Hi all!
I’m trying to develop a game using appStates (one for main menu and other for the game itself). I am able to change between states correctly using keys, but not the events of niftyGUI.
I’ve made a simple test case based upon TestAppStates which I publish the code here. Pease notice that the piece of code used to change states is the same for keyboard input and nifty event (changeState() method). I am using the appTasks because otherwise I was getting a NullPointerException (original code in changeState_OLD() method).
Thank you for your help.
Main class (TestAppStates)
[java]
package mygame;
import com.jme3.app.Application;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.niftygui.NiftyJmeDisplay;
import com.jme3.scene.Spatial;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeContext;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
public class TestAppStates extends Application implements ScreenController, ActionListener{
RootNodeState state1;
RootNodeState state2;
boolean state=false; //false stands for state1
public static void main(String[] args){
TestAppStates app = new TestAppStates();
app.start();
}
@Override
public void start(JmeContext.Type contextType){
AppSettings settings = new AppSettings(true);
settings.setResolution(800, 600);
setSettings(settings);
super.start(contextType);
}
@Override
public void initialize(){
super.initialize();
System.out.println(“Initialize”);
state1 = new RootNodeState();
viewPort.attachScene(state1.getRootNode());
stateManager.attach(state1);
Spatial model1 = assetManager.loadModel(“Models/Teapot/Teapot.obj”);
model1.scale(3);
model1.setLocalTranslation(0, 1, 0);
model1.setMaterial(assetManager.loadMaterial(“Interface/Logo/Logo.j3m”));
state1.getRootNode().attachChild(model1);
state2 = new RootNodeState();
Spatial model2 = assetManager.loadModel(“Models/Teapot/Teapot.obj”);
model2.scale(2);
model2.setLocalTranslation(0, 1, 0);
model2.setMaterial(assetManager.loadMaterial(“Interface/Logo/Logo.j3m”));
state2.getRootNode().attachChild(model2);
NiftyJmeDisplay niftyDisplay = new NiftyJmeDisplay(assetManager,
inputManager,
audioRenderer,
guiViewPort);
niftyDisplay.getNifty().fromXml(“Interface/menu.xml”, “start”);
guiViewPort.addProcessor(niftyDisplay);
setupKeys();
}
@Override
public void update(){
super.update();
// do some animation
float tpf = timer.getTimePerFrame();
stateManager.update(tpf);
stateManager.render(renderManager);
// render the viewports
renderManager.render(tpf);
}
@Override
public void destroy(){
super.destroy();
System.out.println(“Destroy”);
}
//Old method (nifty gives null pointer exception)
public void changeState_OLD()
{
if(state)
{
viewPort.detachScene(state2.getRootNode());
stateManager.detach(state2);
viewPort.attachScene(state1.getRootNode());
stateManager.attach(state1);
state=false;
}
else
{
viewPort.detachScene(state1.getRootNode());
stateManager.detach(state1);
viewPort.attachScene(state2.getRootNode());
stateManager.attach(state2);
state=true;
}
}
public void changeState()
{
System.out.println(“changeState Called”);
if(state)
{
this.enqueue(new ChangeStateTask(state2,state1,viewPort,stateManager));
state=false;
}
else
{
this.enqueue(new ChangeStateTask(state1,state2,viewPort,stateManager));
state=true;
}
}
private void setupKeys() {
inputManager.addMapping(“change”, new KeyTrigger(KeyInput.KEY_C));
inputManager.addListener(this,“change”);
}
public void bind(Nifty nifty, Screen screen) {
}
public void onStartScreen() {
}
public void onEndScreen() {
}
public void onAction(String name, boolean isPressed, float tpf)
{
if (name.equals(“change”)) {
if(isPressed)
{
changeState();
}
}
}
}
[/java]
The Callable object for the task
[java]
/*
- To change this template, choose Tools | Templates
- and open the template in the editor.
*/
package mygame;
import com.jme3.app.state.AppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.renderer.ViewPort;
import java.util.concurrent.Callable;
public class ChangeStateTask implements Callable
{
private RootNodeState oldState;
private RootNodeState newState;
private ViewPort viewPort;
private AppStateManager stateManager;
public ChangeStateTask(RootNodeState oldState, RootNodeState newState, ViewPort view, AppStateManager sm)
{
this.oldState=oldState;
this.newState=newState;
this.viewPort=view;
this.stateManager=sm;
}
public Object call() throws Exception
{
System.out.println("ChangeStateTask called");
viewPort.detachScene(oldState.getRootNode());
stateManager.detach(oldState);
viewPort.attachScene(newState.getRootNode());
stateManager.attach(newState);
return null;
}
}
[/java]
NiftyGUI file (menu.xml)
[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">
<!-- +++++++++++++++++++++++++++++++++++++++ -->
<!-- start screen -->
<!-- +++++++++++++++++++++++++++++++++++++++ -->
<screen id="start" controller="mygame.TestAppStates">
<layer id="layer" childLayout="center">
<panel id="panel" height="25%" width="35%" align="center" valign="center" backgroundColor="#f60f" childLayout="center" visibleToMouse="true">
<interact onClick="changeState()"/>
<effect>
<onStartScreen name="move" mode="in" direction="top" length="300" startDelay="0" inherit="true"/>
<onEndScreen name="move" mode="out" direction="bottom" length="300" startDelay="0" inherit="true"/>
<onHover name="pulsate" scaleFactor="0.008" startColor="#f600" endColor="#ffff" post="true"/>
</effect>
<text id="text" font="aurulent-sans-17.fnt" color="#000f" text="Hello World!" align="center" valign="center" />
</panel>
</layer>
</screen>
</nifty>
[/xml]
PS: forgot to mention, I am using jME3 alpha3 (jMP)