Nifty menu keeps returning first selected element [SOLVED]

I have succeeded in popping up a Nifty menu when the player clicks (RMB) on an element (node) on the screen. The menu shows 2 options: ‘Attack’ and ‘Cancel’. When ‘Attack’ is clicked, the name of the selected element is displayed on the HUD on the main screen of the game (just for testing purposes; it is the idea to have the guns of the ship lock to the selected element later on).



The first time I click (RMB) on an element and pick ‘Attack’, it shows the name of the element in the HUD, just as it should do. When I click again (RMB) and choose ‘Cancel’, the name is removed from the HUD (as it should). But when I click after this on an (random) element, the new element name is not showed on the HUD, but the name of the first selected element keeps being displayed every time I pick ‘Attack’. The ‘Cancel’ button remains doing what it should do: clear the name on the HUD.



Question is: Why is the name not updated to the last selected elements name?



Below parts of the code I use.



This is the XML-file:

[xml]<?xml version=“1.0” encoding=“UTF-8”?>

<nifty xmlns=“http://nifty-gui.sourceforge.net/nifty.xsd

xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance

xsi:schemaLocation=“http://nifty-gui.sourceforge.net/nifty.xsd

http://nifty-gui.sourceforge.net/nifty.xsd”>

<screen id=“actionsmenu” controller=“enemyahead.ActionsMenu”>

<layer id=“menu” backgroundColor="#0000" childLayout=“absolute”>

<panel id=“menu” x="${CALL.setX()}" y="${CALL.setY()}" height=“80” width=“120” backgroundColor="#003f" childLayout=“vertical”>

<panel id=“attack” height=“30” width=“100” align=“center” valign=“center”

backgroundColor="#f60f" childLayout=“center” visibleToMouse=“true”>

<text id=“textAttack” font=“Interface/Arial-20.fnt” color="#000f"

text=“Attack” align=“center” valign=“center” />

<effect>

<onHover name=“pulsate” scaleFactor=“0.008” startColor="#f600" endColor="#ffff" post=“true”/>

</effect>

<interact onClick=“actionAttack()”/>

</panel>

<panel id=“cancel” height=“30” width=“100” align=“center” valign=“center”

backgroundColor="#f60f" childLayout=“center” visibleToMouse=“true”>

<text id=“textCancel” font=“Interface/Arial-20.fnt” color="#000f"

text=“Cancel” align=“center” valign=“center” />

<effect>

<onHover name=“pulsate” scaleFactor=“0.008” startColor="#f600" endColor="#ffff" post=“true”/>

</effect>

<interact onClick=“actionCancel()”/>

</panel>

</panel>

</layer>

</screen>

</nifty>[/xml]



Part of Main:

[java]public class Main extends SimpleApplication implements PhysicsTickListener

{

[…]

// Menu:

Nifty nifty;

ActionsMenu actionsMenu;

[…]

}[/java]



Part of simpleInitApp():

[java]public void simpleInitApp()

{

[…]

// Create the menu:

NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);

nifty = niftyDisplay.getNifty();

guiViewPort.addProcessor(niftyDisplay);

[…]

}[/java]



I check which node has been clicked and pass this to the showDialog function:

[java]// The closest result is the target that the player picked:

Geometry target = results.getClosestCollision().getGeometry();

showDialog(target);[/java]



showDialog function:

[java]public void showDialog(Geometry trgt)

{

nifty.fromXml(“Interface/actionsmenu.xml”, “actionsmenu”, new ActionsMenu(this, trgt, inputManager.getCursorPosition().x, inputManager.getCursorPosition().y));

}[/java]



Class ActionsMenu:

[java]package enemyahead;



import com.jme3.font.BitmapText;

import com.jme3.scene.Geometry;

import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.screen.Screen;

import de.lessvoid.nifty.screen.ScreenController;



public class ActionsMenu implements ScreenController

{

Main myGame;

Geometry myTarget;

int posX;

int posY;



public ActionsMenu(Main mygame, Geometry trgt, float x, float y)

{

myGame = mygame;

myTarget = trgt;

posX = (int)x;

posY = (int)y;



myGame.nifty.gotoScreen(“actionsmenu”);

myGame.nifty.update();

//System.out.println("Target: " + myTarget.getName());

}



public String setX()

{

return Integer.toString(posX);

}



public String setY()

{

return Integer.toString(posY);

}



public void actionAttack()

{

// System.out.println("Target: " + myTarget.getName());

myGame.geoSelectedTarget = myTarget;

myGame.strSelectedTarget = myTarget.getName();

myGame.nifty.exit(); // Close the menu.

}



public void actionCancel()

{

myGame.geoSelectedTarget = null;

myGame.strSelectedTarget = “”;

myGame.nifty.exit(); // Close the menu.

}



public void bind(Nifty nifty, Screen screen)

{

}

public void onStartScreen()

{

}

public void onEndScreen()

{

}

}[/java]



The ’ //System.out.println("Target: " + myTarget.getName());’ in the ‘public ActionsMenu(Main mygame, Geometry trgt, float x, float y)’ returns the correct element every time. Putting this same line in the ‘actionAttack()’ keeps returning the first selected element.



To remove any doubts: The first element selected is not showing the same element every time, so I am able to select other elements.

I guess you will have to re-parse the document, so basically load it again. But I’m not sure.

Dumb question (most likely), but… How would I do that?

Oh I just see you do that probably… The showDialog() is called each time, right? Then I don’t know.

You only need the fromXml line once when you first load the screen. After that goto it using gotoScreen.



Have you looked at nifty popups? They are designed for doing this sort of thing - although I’ve found a few problems with using nifty popups and changing nifty screen at the same time.

Indeed, showDialog() is called each time I right-click on an object.

To dynamically change the text in a text field look at http://freefr.dl.sourceforge.net/project/nifty-gui/nifty-gui/nifty-gui-the-manual-v1.0.pdf



I use something like:

[java] private void setText(String key, String text) {

if (screen == null) {

return;

}

Element e = screen.findElementByName(key);

TextRenderer t = e.getRenderer(TextRenderer.class);

t.setText(text);

}

[/java]

1 Like

I see, but I think this is not what I want… I do not want to change the text in the menu, I just want the right Geometry to be passed to the actionAttack(), so I can use it to track it’s co-ordinates. It works the first time, why not the next?

Don’t call nifty.fromXml() every time you need to show info. Create this class at the beginning, when you load everything and then just make public function to pass new data to it. Also, I find it useful sometimes when I am changing text to just do: e.getParent().layoutElements().

1 Like

Thanks all. I finally got it working (have been on holiday for some weeks).



I had to change some things, but it is working now. First of all, I create the nifty menu in the simpleInitApp():

[java]NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);

nifty = niftyDisplay.getNifty();

nifty.fromXml(“Interface/screen.xml”, “start”, new MenuController(this));

guiViewPort.addProcessor(niftyDisplay);[/java]

(It now shows a start menu when the game is launched).



Then, during gameplay, the ‘popup’ menu is opened as soon as the user clicks a geometry in the scene and with the setConstraint-functions as well as the setText-function, I am now able to dynamically change the position of the popup and set the text in the popup dynamically without problems:



[java]// The closest result is the target that the player picked:

target = results.getClosestCollision().getGeometry();

// Show the actions menu:

nifty.getScreen(“actionsmenu”).findElementByName(“panel_menu_background”).setConstraintX(new SizeValue(Integer.toString((int)click2d.x)));

nifty.getScreen(“actionsmenu”).findElementByName(“panel_menu_background”).setConstraintY(new SizeValue(Integer.toString(screenHeight-(int)click2d.y)));

nifty.getScreen(“actionsmenu”).findElementByName(“selection”).getRenderer(TextRenderer.class).setText(target.getName());

nifty.getScreen(“actionsmenu”).findElementByName(“panel_menu_background”).layoutElements();

nifty.gotoScreen(“actionsmenu”); [/java]



I do not use the build-in popup of nifty (yet), but might dig into it. Only problem I still have is that nifty is throwing a nullPointerException every now and then when the right mouse button is clicked. I have not been able to figure out why (have created another post for that error, so will not debate it here in this post).