i have benn confronted with an odd problem once again.
currently i´m working on a panel, that is shown when an image is clicked and hidden when another one
gets clicked.
it works so far, but my problem is, that the onclick hide or show effect is not only working when the images are clicked, but also, when it is clicked anywhere in the panels, they are in (all the panels, even the parent ones).
i thought that effects are attached to the elements they are belonging to.
[xml]
<layer id="swarm_settings" childLayout="center" >
<panel id="parent" height="100px" width="500px" childLayout="vertical" align="center" valign="bottom" visibleToMouse="true" >
<panel id="top" height="20px" width="50px" childLayout="center" align="center" valign="center" backgroundColor="#0fff" visibleToMouse="true" >
<image id="hide_graphic" align="center" valign="center" filename="Interface/hide.png" >
<effect>
<onClick name="hide" targetElement="swarm_settings" />
</effect>
</image>
</panel>
<panel id="middle" height="50px" width="500px" childLayout="horizontal" align="center" valign="center" backgroundColor="#0505" visibleToMouse="true" >
</panel>
<panel id="bottom" height="30px" width="500px" childLayout="horizontal" align="center" valign="center" backgroundColor="#0606" visibleToMouse="true" >
</panel>
</panel>
</layer>
<layer id="settings" childLayout="center" >
<panel id="swarm" height="30px" width="50px" childLayout="vertical" align="center" valign="bottom" backgroundColor="#00ff" visibleToMouse="true">
<image id="show_grafic" align="center" valign="center" filename="Interface/show.png" >
<effect>
<onClick name="show" targetElement="swarm_settings" />
</effect>
</image>
<text id="text" font="console.fnt" color="#ffff" size="10" text="swarm" align="center" valign="center" />
</panel>
</layer>
[/xml]
is there a workaround?
ok, second aproach.
this time i tried to build a toggle, instead of two switches, that show and hide the panel.
in the xml the onlick events name calls a method in the controller, that returns a string
[xml]
<effect>
<onClick name="${CALL.popup()}" targetElement="swarm_settings" />
</effect>
[/xml]
in the controller the called method returns hide, if the panel is shown and show, if the panel is hidden.
[java]
public int showhideint=1;
public String x;
public String popup(){
if (showhideint==1 ) {
x="hide";
showhideint=0;
}
else {
x="show";
showhideint=1;
}
return x;
}
[/java]
Problem is, no matter how often i click the panel, it always returns hide. i somehow guess, that the
name attribute of the onclick effect is not updated, when its clicked the first time.
help
Well, first of all it might be better to do things like that from java. Using an interact onClick method to call a method on your ScreenController (or some other controller) and then showing/hiding the panels from this Java method might be more straight forward. You don’t want to have too much logic hidden inside of XML
But back to your question:
- You’re right. Effects are attached to single elements. But in your case something interessting is happening: You’ve set all of your panels to visibleToMouse="true. This means that Nifty will detect all of these panels when handling mouse events. If you click on a parent panel of on of your images (with the onClick effect) then Nifty will try to execute the onClick effect for this panel and because effects are always executed top-down this onClick effect will travel down the whole hierarchy until it finds your image with the onClick effect set
This is expected behaviour for all effects btw. If you start a onStartScreen effect for the whole screen but only some of your elements do actually respond to the effect you still want these effects to be affected.
In your case you can either remove the visibleToMouse=“true” from all of the parent panels and only add it the image or add an interact onClick method to the image and handle the show/hide from java.
- That’s right. The ${} syntax will only be translated/resolved/called when the xml is first loaded and not every time the onClick effect is executed.
Again, I’d suggest keeping logic inside of Java and not in XML
thank you very much void!
i figured the visible to mouse thing out a that day and it works like a charm now.
there are only two things left, that bother me at the moment.
you say i should do most things in java, but how? do you mean the javabuilder thing?
- how can i change the show/hide effects default state, so that it is hidden right from the start?
- how can the sound be disabled when there is backgroundmusic or onclick sounds in general playing?
is there a special nifty audionode created at the start?
again, i´m very thankful for you guys taking your time for rookies like me
you say i should do most things in java, but how? do you mean the javabuilder thing?
I was not really thinking about the JavaBuilder (although you could use that as well of course). What I had in mind was using [xml]<interact onClick="someMethod()">[/xml] to execute an eventhandler in Java. When you are in Java you can access Elements from the XML using something like [xml]screen.findElementByName("id-of-element")[/xml] and then modify that Element. For instance it would be possible to execute an Effect for the Element - from Java - or you could modify some Attributes of the Element. Especially if there is some logic being part of the decision what Element you need to modify this would be best handled within Java.
1. how can i change the show/hide effects default state, so that it is hidden right from the start?
visible="false" should do that trick? I think the onHide effect will only execute when you really hide a visible Element. IIRC when an element started hidden the effect is not executed.
2. how can the sound be disabled when there is backgroundmusic or onclick sounds in general playing?
is there a special nifty audionode created at the start?
Well, I'm not sure about the JME implementation but nifty.getSoundSystem() should give you a device independend de.lessvoid.nifty.sound.SoundSystem instance which lets you acces background music or sounds. Not sure what you need that for and if the current methods are suitable for you.
thanks void, i think i got it now. found another way to start with the elements hidden
i had a layer that covered the whole screen (like a startscreen, with logos and stuff) and hid itself onclick.
so i only had to add the hide effect for the following panels. there might be another way using the onstartscreen solution, but hey, your solution starting the panel with visible=“false” is more elegant.
did i miss that in the tutorials/wiki?
well, to the audio problem.
at the moment, i have background music and click sounds registered to nifty.
i would like to have a button in the menu, where i can either enable or disable the (nifty) sounds,
or alter the volume (not really important though).
in jme3 i normally create audionodes, that have soundfiles attached and i can set volume levels for each of these nodes. but as i use niftys sound effects for the gui, i dont have specific audionodes to configure.
how can that be done?
edit:
there is a setSoundVolume and a setMusicVolume method in the SoundSystem class, which i already importet, but i cant get them to work somehow.
I’ve just checked the jme3 implementation and there is a AudioNode created for each Sound that is created from Nifty. You should be able to call SoundHandle.stop() to stop the sound playing and setVolume() to change the volume of the sound … when you first get a SoundHandle for the sound and call the methods there, that is.
The SoundSystem calls just change the values for the next sound to be played and currently don’t change the currently playing sounds If you want to modify them you need to access the individual SoundHandles first.
Can’t remember why tho
Erm, ok, well that sounds good, but could you please give an explicit example?
when i register a sound called named click in the xml, then how could i touch that
in the controller for example?
thanks for being so patient with me
[java]// get the SoundSystem
SoundSystem soundSystem = nifty.getSoundSystem();
// get the SoundHandle for a sound registered in the xml with the name/id “click”
SoundHandle sound = soundSystem.getSound(“click”);
// just stop that sound (see de.lessvoid.nifty.spi.sound.SoundHandle for everything that is possible with the SoundHandle)
sound.stop();[/java]
The same works for music using “soundSystem.getMusic(“musicId”);”
perfect!
thank you so much void!!