[SOLVED] dynamically add overlaying images to a panel

Hi guys, I need your help again :frowning:



What I want:

When things happen to the player, I want little status icons on the screen. Let’s say one for each different effect. They are added/removed dynamically with a set layout. If the first one runs out but the other ones are still active, all of them move one step in a direction according to the layout. Depending on what the effect is, the icon shall have different frames.



What I got:

A panel, the images and frames, and the whole timing setup. Problem: when multiple effects are applied, I don’t get the layout I want. Most likely due to a misunderstanding of how the ImageCreator class works. There are empty spaces in the panel (with the size of one icon), and additional icons are applied after that space.



This is an example of how it should look like at runtime:

[xml]<panel …>

<image filename=“icon1.png” childLayout=“overlay”>

<image filename=“frame1.png”/>

</image>

</image>

<image filename=“icon2.png” childLayout=“overlay”>

<image filename=“frame2.png”/>

</image>

</image>

</panel>[/xml]





And this is how I generate it currently:

[java]Element panel = screen.findElementByName(“effectPanel”);



// create the icon

ImageCreator iconCreator = new ImageCreator();

iconCreator.setFilename(imageIconPath);

iconCreator.setImageMode(“normal”);

iconCreator.setVAlign(“bottom”);

iconCreator.setChildLayout(“overlay”);

iconCreator.setId(“effect X name”);

Element icon = iconCreator.create(nifty, screen, panel);



// create the whole image by adding the frame

ImageCreator imageCreator = new ImageCreator();

imageCreator.setFilename(imageFramePath);

imageCreator.setImageMode(“normal”);

imageCreator.setId(“effect X name”);

Element frame = imageCreator.create(nifty, screen, icon);



panel.add(icon);

panel.add(frame);[/java]



At first I tried to add the frame to the image as a child (icon.add(frame)), but when I do that I get a stack overflow, because of a circular recursion I guess:

[java]java.lang.StackOverflowError

at org.lwjgl.opengl.GL15.glBufferSubData(GL15.java:189)

at com.jme3.renderer.lwjgl.LwjglRenderer.updateBufferData(LwjglRenderer.java:2107)

at com.jme3.renderer.lwjgl.LwjglRenderer.setVertexAttrib(LwjglRenderer.java:2212)

at com.jme3.renderer.lwjgl.LwjglRenderer.setVertexAttrib(LwjglRenderer.java:2247)

at com.jme3.renderer.lwjgl.LwjglRenderer.renderMeshDefault(LwjglRenderer.java:2452)

at com.jme3.renderer.lwjgl.LwjglRenderer.renderMesh(LwjglRenderer.java:2499)

at com.jme3.material.Material.render(Material.java:1103)

at com.jme3.niftygui.RenderDeviceJme.renderImage(RenderDeviceJme.java:298)

at de.lessvoid.nifty.render.ScalingRenderDevice.renderImage(ScalingRenderDevice.java:103)

at de.lessvoid.nifty.render.image.renderstrategy.ResizeStrategy.render(ResizeStrategy.java:24)

at de.lessvoid.nifty.render.image.CompoundImageMode.render(CompoundImageMode.java:28)

at de.lessvoid.nifty.render.NiftyImage.render(NiftyImage.java:53)

at de.lessvoid.nifty.render.NiftyRenderEngineImpl.renderImage(NiftyRenderEngineImpl.java:244)

at de.lessvoid.nifty.elements.render.ImageRenderer.render(ImageRenderer.java:30)

at de.lessvoid.nifty.elements.Element.renderElement(Element.java:627)

at de.lessvoid.nifty.elements.Element.render(Element.java:605)

at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)

at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)

at de.lessvoid.nifty.elements.Element.render(Element.java:606)

at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)

at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)

at de.lessvoid.nifty.elements.Element.render(Element.java:606)

at de.lessvoid.nifty.elements.Element.renderInternalChildElements(Element.java:644)

at de.lessvoid.nifty.elements.Element.renderChildren(Element.java:637)

at de.lessvoid.nifty.elements.Element.render(Element.java:606)



[/java]



Adding the icon frame not to the icon, but to the panel, does show the whole image as I want it, but considering the weird invisible stuff that is added where I see a space, it’s probably wrong. I printed the IDs of all elements, and there were more elements than I expect to be there (at least 3 for every effect icon), and the spaces have the size of an icon, or even multiple ones.



So does someone see my mistake with the ImageCreator?



Also, the icons are not moving down the panel when previous ones are removed, so I guess the layout is not recalculated. Not sure though, could be something with the messed up creation.

Have you tried doing it with builders instead of creators? I’ve never used the creators but I do dynamic layouts with builders all the time and haven’t had any trouble.

Thanks for the hint. I avoided the Builders because of the bad code maintainability whith big inner anonymous classes, but I just noticed that they can be used without them.



I also found out why I get these weird spaces. Apparently I must not add the elements manually, because they are added automatically by the methods .create(…) or .build(…). Which would be a damn nice info for the javadoc (which doesn’t exist).



Anyway, your hint lead to both a workaround and a solution, so thanks for that :).



Code does exactly what I wanted to do now, and looks like this:

[java]

// create the frame

ImageBuilder frame = new ImageBuilder(effectName);

frame.filename(imageFramePath);



// create the icon and add the frame

ImageBuilder image = new ImageBuilder(effectName);

image.filename(imageIconPath);

image.childLayout(ChildLayoutType.Overlay);

image.image(frame);



// build the whole icon and add it to the panel

image.build(nifty, screen, panel);



// no panel.add(image) here, it would do weird stuff

[/java]