okay, i managed to create the 'demo' code:
package src;
import java.util.logging.Level;
import com.jme.app.AbstractGame;
import com.jme.app.BaseGame;
import com.jme.app.GameState;
import com.jme.app.GameStateManager;
import com.jme.app.StandardGameState;
import com.jme.input.InputHandler;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.renderer.ColorRGBA;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.LoggingSystem;
import com.jme.util.Timer;
public class ProblemDemo extends BaseGame{
public static String STATE_NAME_1 = "STATE1";
public static String STATE_NAME_2 = "STATE2";
/**
* InputManager for default state (BLUE one)
* @author FreakyB
*
*/
public class State1InputHandler extends InputHandler {
public State1InputHandler() {
setKeyBindings();
}
private void setKeyBindings() {
KeyBindingManager.getKeyBindingManager().set("exit", KeyInput.KEY_ESCAPE);
addAction( new ExitAction(), "exit", false );
KeyBindingManager.getKeyBindingManager().set("showRedState", KeyInput.KEY_M);
addAction( new showRedStateAction(), "showRedState", false );
}
private class ExitAction extends InputAction {
public void performAction( InputActionEvent evt ) {
System.exit(0);
}
}
private class showRedStateAction extends InputAction {
public void performAction(InputActionEvent evt) {
GameStateManager.getInstance().deactivateChildNamed(STATE_NAME_1);
GameStateManager.getInstance().activateChildNamed(STATE_NAME_2);
}
}
}
/**
* InputManager for default state (RED one)
* @author FreakyB
*
*/
public class State2InputHandler extends InputHandler {
public State2InputHandler() {
setKeyBindings();
}
private void setKeyBindings() {
KeyBindingManager.getKeyBindingManager().set("LeaveState", KeyInput.KEY_ESCAPE);
addAction( new LeaveState(), "LeaveState", false );
}
private class LeaveState extends InputAction {
public void performAction( InputActionEvent evt) {
GameStateManager.getInstance().deactivateChildNamed(STATE_NAME_2);
GameStateManager.getInstance().activateChildNamed(STATE_NAME_1);
}
}
}
/**
* Default state - BLUE one
* @author FreakyB
*
*/
public class State1 extends StandardGameState {
private InputHandler mInputHandler = null;
public State1() {
super(STATE_NAME_1);
mInputHandler = new State1InputHandler();
}
protected void onActivate() {
// enable camera
super.onActivate();
DisplaySystem.getDisplaySystem().getRenderer().setBackgroundColor(ColorRGBA.blue);
mInputHandler.setEnabled(true);
}
protected void onDeactivate() {
mInputHandler.setEnabled(false);
}
protected void stateUpdate(float tpf) {
mInputHandler.update(tpf);
}
}
/**
* Default state - RED one
* @author FreakyB
*
*/
public class State2 extends StandardGameState {
private InputHandler mInputHandler = null;
public State2() {
super(STATE_NAME_2);
mInputHandler = new State2InputHandler();
}
protected void onActivate() {
// enable camera
super.onActivate();
DisplaySystem.getDisplaySystem().getRenderer().setBackgroundColor(ColorRGBA.red);
mInputHandler.setEnabled(true);
}
protected void onDeactivate() {
mInputHandler.setEnabled(false);
}
protected void stateUpdate(float tpf) {
mInputHandler.update(tpf);
}
}
// MAIN CLASS
private Timer mTimer = null;
private float mTPF = .0f;
protected final void update(float interpolation) {
// Recalculate the framerate.
mTimer.update();
mTPF = mTimer.getTimePerFrame();
// Update the current game state.
GameStateManager.getInstance().update(mTPF);
}
/**
* This is called every frame in BaseGame.start(), after update()
*
* @param interpolation unused in this implementation
* @see AbstractGame#render(float interpolation)
*/
protected final void render(float interpolation) {
// Clears the previously rendered information.
display.getRenderer().clearBuffers();
// Render the current game state.
GameStateManager.getInstance().render(mTPF);
}
/**
* Creates display, sets up camera, and binds keys. Called in BaseGame.start() directly after
* the dialog box.
*
* @see AbstractGame#initSystem()
*/
protected final void initSystem() {
try {
/** Get a DisplaySystem acording to the renderer selected in the startup box. */
display = DisplaySystem.getDisplaySystem(properties.getRenderer());
/** Create a window with the startup box's information. */
display.createWindow(
properties.getWidth(),
properties.getHeight(),
properties.getDepth(),
properties.getFreq(),
properties.getFullscreen());
/** Create a camera specific to the DisplaySystem that works with
* the display's width and height*/
}
catch (JmeException e) {
/** If the displaysystem can't be initialized correctly, exit instantly. */
e.printStackTrace();
System.exit(1);
}
/** Get a high resolution timer for FPS updates. */
mTimer = Timer.getTimer();
}
/**
* Called in BaseGame.start() after initSystem().
*
* @see AbstractGame#initGame()
*/
protected final void initGame() {
// Creates the GameStateManager. Only needs to be called once.
GameStateManager.create();
// Adds a new GameState to the GameStateManager. In order for it to get
// processed (rendered and updated) it needs to get activated.
//GameState menu = new MenuState("menu");
///menu.setActive(true);
//GameStateManager.getInstance().attachChild(menu);
GameState state1BLUE = new State1();
GameState state2RED = new State2();
GameStateManager.getInstance().attachChild(state1BLUE);
GameStateManager.getInstance().attachChild(state2RED);
state1BLUE.setActive(true);
}
/**
* Empty.
*
* @see AbstractGame#reinit()
*/
protected void reinit() {
}
/**
* Cleans up the keyboard and game state system.
*
* @see AbstractGame#cleanup()
*/
protected void cleanup() {
LoggingSystem.getLogger().log(Level.INFO, "Cleaning up resources.");
// Performs cleanup on all loaded game states.
GameStateManager.getInstance().cleanup();
}
public static void main(String[] args) {
ProblemDemo app = new ProblemDemo();
app.start();
}
}
so nothing more than 2 states with their own input manager.
start the program and you'll see the BLUE-state, press the (almost famous ;)) M-button, and the RED-state appearce, press ESCAPE, the blue state shows back, and now the problem hits...
push the M-button again but the RED state won't show up...
as mentioned before, the problem is here:
in CommandTrigger:
public void performAction( InputActionEvent event ) {
if ( name == null ||
KeyBindingManager.getKeyBindingManager().isValidCommand( name, allowRepeats ) ) {
super.performAction( event );
activate();
}
}
in ActionTrigger:
public void performAction( InputActionEvent event ) {
final int count = getActionInvocationCount();
for ( int i=0; i < count; i++ ) {
putTriggerInfo( event, i );
action.performAction( event );
}
if ( !allowRepeats ) {
deactivate();
}
}
the workflow:
CommandTrigger::performAction()
--> ActionTrigger::performAction()
--> action.performAction()
So, this does:
GameStateManager.getInstance().deactivateChildNamed(STATE_NAME_1);
GameStateManager.getInstance().activateChildNamed(STATE_NAME_2);
which means that for state 1, the input manager is disabled by the onDeactivate() method
--> deActivate()
--> ActionTrigger::activate()
and here is the problem:
if ( !active && inputHandler.isEnabled() ) ....
the inputhandler isn't enabled anymore, cause it's been disabled in the GameState::onDeactivate() method....
I hope I made myself a little more clear now ;)
any idea how to solve it?
thanks!
FreakyB