[jME3+Nifty] Scrolling repeated image

Hello!



I’m still learning how to utilize nifty within jME3 and so far I’ve been making some really simple gui’s. One thing I was experimenting for the better part of the morning was trying to get a repeated image texture on a panel to scroll (in any direction!). I haven’t met much success. I’ve been able to create a panel with a repeated texture no problem but I don’t really have a grasp on how to have an effect scroll it. I have a custom effect on it and I know it’s using it I’m just a bit clueless as to how to get this effect. Should it even be an effect?



Eventually, the desired result was for a diagonally slow-scrolling texture on the furthest back layer to scroll under an overlay of panels that are the actual menus. I was also thinking this could be utilized in backgrounds for other things, or even a left-right slow scrolling scenery.



Any “point me in the right direction” help would be appreciated!



~FlaH

Shifting the texture coordinates might help

uhm, just to make sure that I’ve understood you correctly:



a) you’re using imageMode=“repeat:x,y,w,h” with an imageOverlay effect in onActive like the nifty-panel.xml style in the style-grey?

b) you want to scroll that image (the repeated part) probably with shifting texture coordinates as momoko_fan suggested?



When a) irritates you, then I’d like to know how you’re doing it at the moment :slight_smile:



You could do it with shifting texture coordinates in an effect but you need to consider some things:


  1. this effect needs to be executed before the rendering of the panel so that your manipulation of the texture coordinates effects the rendering. You can achieve this with adding a post=“false” to the effect.
  2. you’ll need to directly access OpenGL to shift the coordinates on the texture matrix because the NiftyRenderEngine does currently not allow manipulation of texture coordinates
  3. you probably want to reset your texture manipulation after the panel has been rendered by Nifty. maybe with another effect added to the element that resets the OpenGL state. And you’ll add a post=“true” to this effect.



    There are other solutions possible I think. Maybe the best would be to make something like your own custom imageOverlay effect that renders his own image (and animates the actual image position) and simply rely to childClip=“true” on the element you attach that effect too.



    But maybe I did not understand your question correctly at all :slight_smile: If this is the case please try again. What you’re trying to do sounds interessting and I’d like to help getting this to work :slight_smile:

Hello again!



Alrighty, I’ll try to stop dancing around and focus :stuck_out_tongue: I was racking my brain trying to think of a game menu that used this but nothing sprang to mind.



MAINLY, I was trying to take a tile-able pattern and repeat it across a panel. Then I wanted it to scroll slowly diagonally (or any direction really, I mean how hard could it be after you initially figure it out to get it going the right way ;p). I thought about maybe taking a panel and having the pattern tiled across it and just move the panel itself, but I haven’t tried that.



In the above case, this would be used on the bottom most layer so that the rest of the menus hover above it, preferably with some soft faked shadow or something to give the illusion of depth.



A MORE GENERAL USE would be for something liiiiiike… The animation on the Cave Story fanpage is a good example: http://www.cavestory.org/

Having a panel that continually scrolled across like that could be used for tons of things. Hell, even in-game effects could utilize that with some alpha mapping done right.



Honestly, I’m pretty damn terrible at using Nifty so far so I’m probably tackling something way over my head. I can handle some panels and some buttons but it gets hairy past that I’m afraid ;p



~FlaH

Nifty - at least in its current state - is a bit hairy, I’m afraid :slight_smile:



The standard controls (Buttons, Checkboxes, ListBoxes, Textfields and so on) are being shaved right now for the Nifty 1.3 release so they should be much easier to use and more powerful too. Especially the usage of the controls from Java should be a lot better.



Ok, back to your problem.



Probably the best way would be to simply render your moving texture panel on your own and overlay Nifty above it. This would allow you to use any rendering mechanism possible. Especially when rendering more complex stuff.



It’s possible with standard Nifty too but because we don’t have access to texture coordinates directly with the standard NiftyRenderEngine in the effect we need to workaround rendering the image a bit larger and rely on screenspace clipping.



Here is a Nifty effect that does this:



[java]package de.lessvoid.nifty.examples.helloworld;



import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.effects.EffectImpl;

import de.lessvoid.nifty.effects.EffectProperties;

import de.lessvoid.nifty.effects.Falloff;

import de.lessvoid.nifty.elements.Element;

import de.lessvoid.nifty.render.NiftyImage;

import de.lessvoid.nifty.render.NiftyImageMode;

import de.lessvoid.nifty.render.NiftyRenderEngine;

import de.lessvoid.nifty.tools.TimeProvider;



public class ScrollingPanel implements EffectImpl {

private TimeProvider timeProvider;

private long start;

private float xspeed;

private float yspeed;

private NiftyImage image;

private float xoff;

private float yoff;



public void activate(final Nifty nifty, final Element element, final EffectProperties parameter) {

timeProvider = nifty.getTimeProvider();

start = timeProvider.getMsTime();

xspeed = Float.valueOf(parameter.getProperty(“xspeed”, “1000”));

yspeed = Float.valueOf(parameter.getProperty(“yspeed”, “1000”));

image = nifty.getRenderEngine().createImage(parameter.getProperty(“filename”), false);

String imageMode = parameter.getProperty(“imageMode”, null);

if (imageMode != null) {

image.setImageMode(NiftyImageMode.valueOf(imageMode));

}

xoff = 0;

yoff = 0;

}



public void execute(final Element element, final float normalizedTime, final Falloff falloff, final NiftyRenderEngine r) {

long now = timeProvider.getMsTime();

r.saveState(null);

xoff = ((now - start) % xspeed / xspeed * image.getWidth()) % image.getWidth();

yoff = ((now - start) % yspeed / yspeed * image.getHeight()) % image.getHeight();

r.enableClip(element.getX(), element.getY(), element.getX() + element.getWidth(), element.getY() + element.getHeight());

r.renderImage(

image,

element.getX() + (int)xoff - image.getWidth(),

element.getY() + (int)yoff - image.getHeight(),

element.getWidth() - (int)xoff + image.getWidth(),

element.getHeight() - (int)yoff + image.getHeight());

r.restoreState();

}



public void deactivate() {

image.dispose();

}

}[/java]



And use it like so:



[xml]<registerEffect name=“scrollingPanel” class=“de.lessvoid.nifty.examples.helloworld.ScrollingPanel”/>



<panel height=“25%” width=“35%” align=“center” valign=“center” childLayout=“vertical” visibleToMouse=“true”>

<effect>

<onActive name=“scrollingPanel” filename=“nifty-logo-150x150.png” imageMode=“repeat:0,0,150,150” xspeed=“1000” yspeed=“5000” />

</effect>[/xml]

Okay, after a few derp derp operator error points on my end I got it working with your code. I sorta/kinda understand what’s going on in the effect but I still have some questions:


  1. What is r.saveState(null) and r.restoreState(); doing? I’ve seen this used before in some of your examples I think, but I couldn’t really nail down what was going on there.


  2. Same goes for the clipping. Are we doing this so that it’s not rendering off the screen somewhere (and into infinity) ?


  3. I’m guessing the xspeed and yspeed is the time required to completely scroll across the image once in the respective direction (in ms)?



    Thanks a ton for bashing this out. I can see a ton of great uses for this effect. Any chance of it making into the 1.3 standard effects? :smiley:

    ~FlaH
  1. saveState() and restoreState() make sure that everything we do with the NiftyRenderEngine does not influence any (child) elements rendered after the effect. Calling saveState(null) will save all states which, well, is not really necessary in this case here :slight_smile: Saving the “clip” state would be enough. At its core Nifty keeps track of things like current color, current position (a little bit like OpenGL).



    A better example to explain this would be the TextColor effect. This effect does not save the renderstate and only changes the current color with r.setColor(). Which means that everything rendered after this effect will get the new Color (which is the purpose of this effect after all ;).



    Calling r.saveState() and r.restoreState() is always a good idea if what we do should not influence other elements.


  2. Try to remove the enableClip() line and see what will happen :slight_smile: To get the scrolling image effect we’re actually really changing the position of the image we render and with the clip() we will make sure that no one sees the trick.



    It really would be better to use a texture shifting effect for this but Nifty does not support this.


  3. correct. That’s what I’ve come up with at least. You could modify it to just change the offset by some other algorithm. Sinus or something would be possible too :slight_smile:



    Well, if at least two other people find this useful I’ll add it as standard effect :wink: At the moment I don’t think this is really that useful for a majority of people. As the nifty jar is approaching 400KB already :confused: I’d like to not add too much. And the EffectImpl interface is IMHO simple enough so that you can easily create your own effects. That was the plan after all. To let you create your own instead of modifying the Standard Nifty all the time :slight_smile:
  1. hmmmm. I commented it out using both my 100x100 test image and the nifty-logo-150x150.png and saw no difference 8O



    Though, it’s odd. My 100x100px image scrolls fine doing anything, but the 150x150 logo suffers from some wiggle/jitter in the render and when it hits the last few pixels of offset the image jumps quite violently. Both with and without the enableClip line commented. Only reason I tried the 150x150 logo at all was because I thought maybe you saw something I didn’t! I’m doing everything pretty much the same, running in a jME3 window of 640x480 resolution.



    EDIT: Derp derp, I forgot to change the repeat,0,0,100,100 to repeat,0,0,150,150. So that’s why it was jumping around at the end of the cycle. I still see a bit of wiggling on the large image though. I’m guessing this has something to do with slinging such a large image around? Still don’t see what enableClip is doing though XD



    ~FlaH

Maybe you’re applying the effect to some element that is already clipping and therefore the enableClip() would not be necessary?



In the general case and in my example which uses a plain panel I can see the whole image when I remove the clipEnable() line. You can see the image jump back to the initial position when it scrolls more then image width or image height.



So I don’t know why you cant see it :slight_smile: