Hi
Is there any fancy way to bind a button to toggle a menu? So that a menu is both activated and deactivated by same button ?
This is my implementation of an ingame menu:
[java]/*
- To change this template, choose Tools | Templates
- and open the template in the editor.
*/
package alpineterra.appstates;
import alpineterra.AlpineTerraStyles;
import alpineterra.Main;
import com.jme3.app.Application;
import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioNode;
import com.jme3.audio.AudioSource;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Command;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.event.BaseAppState;
import com.simsilica.lemur.style.ElementId;
/**
*
-
@author asf
*/
public class InGameMenuState extends BaseAppState{private Container menu;
private AudioNode selectUp;
private AudioNode selectDown;
private AudioNode selectNeutral;private AudioNode music;
public InGameMenuState() {
}@Override
protected void initialize( Application app ) {
menu = new Container(new SpringGridLayout(), new ElementId(AlpineTerraStyles.MENU_ID), “retro”);
menu.addChild(new Label(“Alpine Terra”, new ElementId(AlpineTerraStyles.MENU_TITLE_ID), “retro”));Button multipliers = menu.addChild(new Button("Multipliers", "retro")); multipliers.addClickCommands(new Multipliers()); multipliers.addCommands(Button.ButtonAction.HighlightOn, new Highlight()); Button exitToMainMenu = menu.addChild(new Button("Exit to main menu", "retro")); exitToMainMenu.addClickCommands(new ExitToMainMenu()); exitToMainMenu.addCommands(Button.ButtonAction.HighlightOn, new Highlight()); Button returnToGame = menu.addChild(new Button("Return to game", "retro")); returnToGame.addClickCommands(new ReturnToGame()); returnToGame.addCommands(Button.ButtonAction.HighlightOn, new Highlight()); Camera cam = app.getCamera(); float menuScale = cam.getHeight()/720f; Vector3f pref = menu.getPreferredSize(); menu.setLocalTranslation(cam.getWidth() * 0.5f - pref.x * 0.5f * menuScale, cam.getHeight() * 0.75f + pref.y * 0.5f * menuScale, 10); menu.setLocalScale(menuScale); AssetManager assets = app.getAssetManager(); selectUp = new AudioNode(assets, "Sounds/select-up.ogg", false); selectUp.setReverbEnabled(false); selectUp.setPositional(false); selectDown = new AudioNode(assets, "Sounds/select-down.ogg", false); selectDown.setReverbEnabled(false); selectDown.setPositional(false); selectNeutral = new AudioNode(assets, "Sounds/select-neutral.ogg", false); selectNeutral.setReverbEnabled(false); selectNeutral.setPositional(false);
}
@Override
protected void cleanup(Application app) {
menu.removeFromParent();
}protected void startMusic() {
if( music == null || music.getStatus() == AudioSource.Status.Stopped ) {
AssetManager assets = getApplication().getAssetManager();
music = new AudioNode(assets, “Sounds/panic-menu-theme.ogg”, true);
music.setReverbEnabled(false);
music.setPositional(false);
music.play();
}
}protected void stopMusic() {
if( music != null ) {
music.stop();
music = null;
}
}@Override
public void update( float tpf ) {
startMusic();
}@Override
protected void enable() {
Main main = (Main)getApplication();
main.getGuiNode().attachChild(menu);
getStateManager().getState(GamePlayState.class).setPaused(true);
startMusic();
}@Override
protected void disable() {
menu.removeFromParent();
stopMusic();
}private class Multipliers implements Command<Button> {
@Override
public void execute( Button source ) {
selectUp.playInstance();
//getStateManager().attach(new MultiPlayerState());
getStateManager().getState(GameControlState.class).setEnabled(true);
setEnabled(false);
}
}private class ExitToMainMenu implements Command<Button> {
@Override
public void execute( Button source ) {
selectDown.playInstance();
if (getStateManager().getState(GamePlayState.class) != null) {
getStateManager().getState(GamePlayState.class).setEnabled(false);
}
if (getStateManager().getState(MainMenuState.class) != null) {
getStateManager().getState(MainMenuState.class).setEnabled(true);
}
setEnabled(false);
}
}private class ReturnToGame implements Command<Button> {
@Override
public void execute( Button source ) {
selectDown.playInstance();
getStateManager().getState(GamePlayState.class).setPaused(false);
setEnabled(false);
}
}private class Highlight implements Command<Button> {
@Override
public void execute( Button source ) {
selectNeutral.playInstance();
}
}
}
[/java]
Return to game does what I want, basically. But I want the button that activated this menu, to also deactivate it (if it is activated and vice versa)
This is my GameControlState that activates the menu:
[java]package alpineterra.appstates;
import alpineterra.GameFunctions;
import com.jme3.app.Application;
import com.jme3.audio.AudioNode;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.simsilica.es.EntityData;
import com.simsilica.es.EntityId;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.event.BaseAppState;
import com.simsilica.lemur.input.AnalogFunctionListener;
import com.simsilica.lemur.input.FunctionId;
import com.simsilica.lemur.input.InputMapper;
import com.simsilica.lemur.input.InputState;
import com.simsilica.lemur.input.StateFunctionListener;
/**
-
Maps player input into game control.
-
@author Asser Fahrenholz
*/
public class GameControlState extends BaseAppState
implements AnalogFunctionListener, StateFunctionListener {private long lastFrame;
private AudioNode shoot;
private AudioNode thrust;Application app;
public GameControlState( ) {
}@Override
protected void initialize( Application app ) {
this.app = app;
InputMapper inputMapper = GuiGlobals.getInstance().getInputMapper();
inputMapper.addStateListener(this,
GameFunctions.F_PAUSE);shoot = new AudioNode(app.getAssetManager(), "Sounds/shoot.ogg", false); shoot.setReverbEnabled(false); thrust = new AudioNode(app.getAssetManager(), "Sounds/thrust.ogg", false); thrust.setReverbEnabled(false); thrust.setLooping(true);
}
@Override
protected void cleanup( Application app ) {
InputMapper inputMapper = GuiGlobals.getInstance().getInputMapper();
inputMapper.removeStateListener(this,
GameFunctions.F_PAUSE);
}@Override
protected void enable() {
lastFrame = System.nanoTime();InputMapper inputMapper = GuiGlobals.getInstance().getInputMapper(); inputMapper.activateGroup(GameFunctions.GAMEGROUP);
}
@Override
protected void disable() {
InputMapper inputMapper = GuiGlobals.getInstance().getInputMapper();
inputMapper.deactivateGroup(GameFunctions.GAMEGROUP);
}
/*
public void valueActive( FunctionId func, double value, double tpf ) {
if( func == ShipFunctions.F_TURN ) {Velocity vel = ed.getComponent(ship, Velocity.class); float rotate = (float)(value * rotateSpeed); ed.setComponent(ship, new Velocity(vel.getLinear(), new Vector3f(0,0,rotate))); } else if( func == ShipFunctions.F_THRUST ) { Position pos = ed.getComponent(ship, Position.class); accel.set(0,(float)(speed * value),0); pos.getFacing().multLocal(accel); lastThrustTime += tpf; if( value != 0 && lastThrustTime >= thrustInterval ) { lastThrustTime = 0; // Create a thrust entity EntityId thrust = ed.createEntity(); Vector3f thrustVel = accel.mult(-1); Vector3f thrustPos = pos.getLocation().add(thrustVel.normalize().multLocal(0.1f)); ed.setComponents(thrust, new Position(thrustPos, new Quaternion()), new Velocity(thrustVel), new ModelType(PanicModelFactory.MODEL_THRUST), new Decay(1000)); } else if( value == 0 ) { lastThrustTime = thrustInterval; } }
}
*/
@Override
public void valueChanged( FunctionId func, InputState value, double tpf ) {
if( func == GameFunctions.F_PAUSE && value == InputState.Positive ) {
//Pause game
app.getStateManager().getState(GamePlayState.class).setPaused(true);
//app.getStateManager().getState(null)
//Show in game menu
if(app.getStateManager().getState(InGameMenuState.class) == null){
app.getStateManager().attach(new InGameMenuState());
}
else{
app.getStateManager().getState(InGameMenuState.class).setEnabled(true);
}
//Disable this state
this.setEnabled(false);
}
}@Override
public void update( float tpf ) {// Use our own tpf calculation in case frame rate is // running away making this tpf unstable long time = System.nanoTime(); long delta = time - lastFrame; lastFrame = time; if( delta == 0 ) { return; // no update to perform }
}
@Override
public void valueActive(FunctionId func, double value, double tpf) {
throw new UnsupportedOperationException(“Not supported yet.”); //To change body of generated methods, choose Tools | Templates.
}
}
[/java]