Need to destroy JmeContext display mode

Hi there, so i have made a vehicle selector stage as a SimpleApplication game , when i enter the game after choosing my spaceship , everything goes normal & fine , then i exit the game & re-enter the vehicle selector stage (which is a JFrame having a canvas holding the stage) it opens its context on the last game configuration that i have already exited , keeping the display width & height configs of the stage :

Vehicle Selector Stage code :


package Store;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.BaseAppState;
import com.jme3.bullet.BulletAppState;
import com.jme3.input.ChaseCamera;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.LightScatteringFilter;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;

/**
 *
 * @author twisted
 */
public class VehicleSelectorStage extends SimpleApplication {
    private BulletAppState bulletAppState;
    private Node vehicle;
    private String selectedSpaceShip;
    
    /**
     * create a new Instance of stage view
     * @param selectedSpaceShip default spaceship
     */
    public VehicleSelectorStage(String selectedSpaceShip){
        this.selectedSpaceShip=selectedSpaceShip;
    }
    
    
    /**
     * change the vehicle view on the stage
     * @param selectedSpaceShip vehicle directory
     */
    public void changeVehicle(String selectedSpaceShip) {
      try{
           Thread.sleep(150);
           vehicle=(Node) rootNode.getChild("Vehicle");
           vehicle.detachAllChildren();
           vehicle.attachChild(assetManager.loadModel(selectedSpaceShip).scale(1.5f));
           /**
            * add Light to the node
            */
            DirectionalLight metallicLight = new DirectionalLight();
            metallicLight.setDirection(rootNode.getChild("stage").getLocalTranslation().negate());
            metallicLight.setColor(ColorRGBA.Blue);
            vehicle.addLight(metallicLight); 
      }catch(InterruptedException e){
          System.err.println(e.getMessage());
      }
    }
    @Override
    public void simpleInitApp() {
        /**
         * Attach physcis state
         */
        bulletAppState=new BulletAppState();
        stateManager.attach(bulletAppState);
        bulletAppState.setDebugEnabled(false);
        /**
         * Light up the world
         */
        rootNode.addLight(new AmbientLight(ColorRGBA.White));  

        /**
         * load the stage scene & the stage Vehicles
         */
        rootNode.attachChild(assetManager.loadModel("Scenes/Vehicle Selector Stage/VehicleSelectorStage.j3o"));
        vehicle=(Node) rootNode.getChild("Vehicle");
        vehicle.detachAllChildren();
        vehicle.attachChild(assetManager.loadModel(selectedSpaceShip).scale(1.5f));
        /**
         * Setting up the camera
         */
        ChaseCamera vehicleStageCamera=new ChaseCamera(cam, vehicle);
        vehicleStageCamera.setDefaultDistance(-20);
        vehicleStageCamera.setChasingSensitivity(0.05f);
        vehicleStageCamera.setSmoothMotion(true);
        
        vehicleStageCamera.registerWithInput(inputManager);
        vehicleStageCamera.setToggleRotationTrigger(new MouseButtonTrigger(MouseInput.AXIS_X));        
        /**
         * Set-up Stage Effects(FIlter effect)
         */
      
        FilterPostProcessor stagefilter=new FilterPostProcessor(assetManager);
        LightScatteringFilter stagelight = new LightScatteringFilter(rootNode.getChild("stage").getLocalTranslation());
        stagelight.setLightDensity(10f);
        stagefilter.addFilter(stagelight);
        viewPort.addProcessor(stagefilter); 
        
        DirectionalLight stageDirectLight = new DirectionalLight();
        stageDirectLight.setDirection(rootNode.getChild("stage").getLocalTranslation().negate());
        stageDirectLight.setColor(ColorRGBA.Blue);
        rootNode.addLight(stageDirectLight); 

            
        DirectionalLight metallicLight = new DirectionalLight();
        metallicLight.setDirection(rootNode.getChild("stage").getLocalTranslation().negate());
        metallicLight.setColor(ColorRGBA.Blue);
        vehicle.addLight(metallicLight); 

    } 
    
}

how i call it inside a JFrame Swing:

/**
     * Load the canvas & the renderer with-in inside
     */
    private void loadVehicleSelectorCanvas() {
        
        spaceShips=new String[]{"Mars HoverTank/MarsHoverTankEdited.j3o","Universe Vehicles/starwarsShip.j3o","Universe Vehicles/spaceShip1.j3o"};
        availableVehicles=new JLabel[]{marsRover,starwars,ship1};
        availableVehicles[shipPage].setForeground(Color.YELLOW);
        
           jmeThread = new Thread(() -> {
            vehicleSelectorStage = new VehicleSelectorStage("Models/"+spaceShips[shipPage]);
            
            AppSettings stageConfig = new AppSettings(true);
            stageConfig.setFullscreen(false);
            stageConfig.setGammaCorrection(true);
            stageConfig.setFrameRate(60);
            
            stageConfig.setFrequency(60);
            stageConfig.setVSync(false);
            stageConfig.setDepthBits(24);
            stageConfig.setSamples(6);
            stageConfig.setResolution(stageHolder.getWidth(), stageHolder.getHeight());
            
            vehicleSelectorStage.setDisplayFps(false);
            vehicleSelectorStage.setDisplayStatView(false);
            vehicleSelectorStage.setShowSettings(false);
            vehicleSelectorStage.setSettings(stageConfig);
            vehicleSelectorStage.setPauseOnLostFocus(false);
            
            vehicleSelectorStage.createCanvas();
            vehicleSelectorStage.startCanvas(true);
            
            JmeCanvasContext stageContext = (JmeCanvasContext)    vehicleSelectorStage.getContext();
            stageContext.restart();
            Canvas stageRenderer = stageContext.getCanvas();
            stageRenderer.invalidate();
            stageRenderer.repaint();
            stageRenderer.setSize(stageConfig.getWidth(), stageConfig.getHeight());
            stageHolder.add(stageRenderer);
        });
        jmeThread.start();
    }

& this is how i exit this stage & start my Game after it passing the vehicle selected as an argument after loading data from sql(options config) :

                        vehicleSelectorStage.stop(false);
                        LOAD_DATA();
                        map = new UniverseMap(devmode,activateEffects,"Models/"+spaceShips[shipPage]);
                        startGame();
/*
this starts the game straight forward & shuts off the vehicle selector stage JFrame
 private void startGame(){
         AppSettings config = new AppSettings(true);
            config.setFrameRate(refreshrate); // set to less than or equal screen refresh rate
            config.setVSync(vsync);   // prevents page tearing
            config.setFrequency(60); // set to screen refresh rate
            config.setResolution(r1, r2);
            config.setDepthBits(colorDepth);
            config.setFullscreen(fullscreen);
            config.setGammaCorrection(gammacorrection);
            config.setSamples(antialiasingValue);    // anti-aliasing
            config.setTitle("J-Pluto Mars Map"); // branding: window name
            try {
                // Branding: window icon
                config.setIcons(new BufferedImage[]{ImageIO.read(new File("assets/Interface/rocket-launch-run-icon.png"))});
            } catch (IOException ex) {
                System.err.println(ex.getMessage());
            }
            // branding: load splashscreen from assets
            //                        cfg.setSettingsDialogImage("Interface/MySplashscreen.png");
            map.setShowSettings(false); // or don't display splashscreen
            map.setSettings(config);
            map.start();
           vehicleSelectorStage.enqueue(()->{
              vehicleSelectorStage.stop();
        });
           dispose();
    }
*/

this image of stage renders when its my first time entering the application :

& this image of stage after i started my Game then i exited it & renter the vehicle store to choose vehicle & start once again , seems that the previous game context didnot shut down properly so its assigned back to JmeContext as the stage uses some of the configs that are settled for the game only ! or maybe that because i am using dispose() on a JFrame !

& of course the canvas the empty in the 2nd time because it starts in the context of the Previous SimpleApplication without creating a new context !

its minimized there : image the J-Pluto item in the panel

1 Like

I think this design is not what you should be doing. If you want a menu or a vehicle selector screen for a game, make it in the game rather than a separate swing frame before you start the game.

3 Likes

Indeed. You are basically asking for trouble.

Also, you should use AppStates rather than exiting and reentering the Game.

1 Like

@Pesegato yes its the best approach concerning code logic , but the same problem exists , so the best solution was to transform my gui to ingame gui , so i will give it another try if i succeeded i will post the code otherwise i will use in-game Lemur GUI

Finally , i made it using Lemur GUI before the game starts :slight_smile:


package Store;

import Mars_Map.VehicleLoader;
import com.jme3.asset.AssetManager;
import com.jme3.input.ChaseCamera;
import com.jme3.input.InputManager;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.post.filters.LightScatteringFilter;
import com.jme3.renderer.Camera;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.control.BillboardControl;
import com.jme3.system.AppSettings;
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.IconComponent;

/**
 *
 * @author twisted
 */
public abstract class VehicleSelectorStage implements ActionListener{

    private Node vehicle;
    private final Node rootNode;
    private AssetManager assetManager;
    public  String selectedSpaceShip;
    public static boolean goButtonPressed;
    private Camera camera;
    private InputManager inputManager;
    private ViewPort viewPort;
    private final String[] availableSpaceShips;
    private int spaceShipIndex=0;
    private DirectionalLight stageDirectLight;
    private DirectionalLight metallicLight;
    private boolean startGame=false;
    private Node guiNode;
    private Label spec;
    private Container container;

    
    public VehicleSelectorStage(String selectedSpaceShip,Node rootNode,String[] availableSpaceShips){
        this.rootNode=rootNode;
        this.selectedSpaceShip=selectedSpaceShip;
        this.availableSpaceShips=availableSpaceShips;
    }

    
    public void setGuiNode(Node guiNode) {
        this.guiNode = guiNode;
    }
    
    
    public abstract void onFinish();

    public void setAssetManager(AssetManager assetManager) {
        this.assetManager = assetManager;
    }

    public AssetManager getAssetManager() {
        return assetManager;
    }

    public void setCamera(Camera camera) {
        this.camera = camera;
    }

    public Camera getCamera() {
        return camera;
    }

    public void setInputManager(InputManager inputManager) {
        this.inputManager = inputManager;
    }

    public InputManager getInputManager() {
        return inputManager;
    }

    public void setViewPort(ViewPort viewPort) {
        this.viewPort = viewPort;
    }

    public ViewPort getViewPort() {
        return viewPort;
    }

    public String getSelectedSpaceShip() {
        return selectedSpaceShip;
    }

    public void setSelectedSpaceShip(String selectedSpaceShip) {
        this.selectedSpaceShip = selectedSpaceShip;
    }

    public void setStartGame(boolean startGame) {
        this.startGame = startGame;
    }

    public boolean isStartGame() {
        return startGame;
    }
    
    
    
    
    /**
     * change the vehicle view on the stage
     * @param selectedSpaceShip vehicle directory
     */
    public void changeVehicle(String selectedSpaceShip) {
      try{
           Thread.sleep(50);
           vehicle=(Node) rootNode.getChild("Vehicle");
           vehicle.detachAllChildren();
           vehicle.attachChild(assetManager.loadModel(selectedSpaceShip).scale(1.5f));
           /**
            * add Light to the node
            */
            metallicLight = new DirectionalLight();
            metallicLight.setDirection(rootNode.getChild("stage").getLocalTranslation().negate());
            metallicLight.setColor(ColorRGBA.Blue);
            vehicle.addLight(metallicLight);
            setSelectedSpaceShip(selectedSpaceShip);
      }catch(InterruptedException e){
          System.err.println(e.getMessage());
      }
    }
    /**
     * Intialize the stage on the current Scene
     */
    public void intializeSelector() {
        /**
         * Attach physcis state
         */
        /**
         * Light up the world
         */
        rootNode.addLight(new AmbientLight(ColorRGBA.White));  

        /**
         * load the stage scene & the stage Vehicles
         */
        rootNode.attachChild(assetManager.loadModel("Scenes/Vehicle Selector Stage/VehicleSelectorStage.j3o"));
        vehicle=(Node) rootNode.getChild("Vehicle");
        vehicle.detachAllChildren();
        vehicle.attachChild(assetManager.loadModel(selectedSpaceShip).scale(1.5f));
        /**
         * Setting up the camera
         */
        ChaseCamera vehicleStageCamera=new ChaseCamera(camera, vehicle);
        vehicleStageCamera.setDefaultDistance(-30);
        vehicleStageCamera.setChasingSensitivity(0.05f);
        vehicleStageCamera.setSmoothMotion(true);
       
        
        vehicleStageCamera.registerWithInput(inputManager);
        vehicleStageCamera.setToggleRotationTrigger(new MouseButtonTrigger(MouseInput.AXIS_X));        
        /**
         * Set-up Stage Effects(FIlter effect)
         */
      
        FilterPostProcessor stagefilter=new FilterPostProcessor(assetManager);
        LightScatteringFilter stagelight = new LightScatteringFilter(rootNode.getChild("stage").getLocalTranslation());
        stagelight.setLightDensity(10f);
        stagefilter.addFilter(stagelight);
        viewPort.addProcessor(stagefilter); 
        
        stageDirectLight = new DirectionalLight();
        stageDirectLight.setDirection(rootNode.getChild("stage").getLocalTranslation().negate());
        stageDirectLight.setColor(ColorRGBA.Blue);
        rootNode.addLight(stageDirectLight); 
           

            
        metallicLight = new DirectionalLight();
        metallicLight.setDirection(rootNode.getChild("stage").getLocalTranslation().negate());
        metallicLight.setColor(ColorRGBA.Blue);
        vehicle.addLight(metallicLight); 
        

        inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_LEFT));
        inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_RIGHT));
        inputManager.addMapping("Go", new KeyTrigger(KeyInput.KEY_RETURN));
        inputManager.addListener(this, new String[]{"Left","Right","Go"});
        
    }
    /**
     * intialize the gui btn
     */
    public void intializeGUI() {
        
        Button button=new Button("Go");
        button.setIcon(new IconComponent("Interface/rocket-launch-run-icon.png"));
        button.setLocalScale(0.1f, 0.1f, 0.1f);
        ((Node)rootNode.getChild("go")).addControl(new BillboardControl());
        ((Node)rootNode.getChild("go")).attachChild(button);
        button.addClickCommands((Command<Button>) (Button arg0) -> {
            rootNode.detachAllChildren();
            viewPort.clearProcessors();
            rootNode.removeLight(stageDirectLight);
            rootNode.removeLight(metallicLight);
            camera.setRotation(Quaternion.IDENTITY);
            onFinish();
            setStartGame(true);
        });
    }
    /**
     * intialize the spec GUI
     * @param vehicle the current selected vehicle 
     * @param settings the current settings of the launched app/game
     */
    public void intializeVehicleSpec(String vehicle,AppSettings settings){
         
         container=new Container();
         container.setLocalScale(new Vector3f(2f,2f,2f));
         container.setLocalTranslation(new Vector3f(settings.getMinWidth(), settings.getHeight(), 0f));
         spec=new Label(formulatingSpeed(VehicleLoader.MARS_ROVER_SPEED)+
                        "Acceleration : "+"#"+"\n"+
                        "Light Ammo Intensity : "+"#"+"\n"+
                        "Heavy Ammo Intensity : "+"###"+"\n"    );
  
         container.addChild(spec);
         guiNode.attachChild(container);

         
    }
    /**
     * change vehicle spec values
     * @param vehicle 
     */
    private void switchVehicleSpec(String vehicle){
        if(vehicle.contains("Plane")){
            spec.setText(formulatingSpeed(VehicleLoader.J_PLANE_SPEED)+
                         "Acceleration : "+"#"+"\n"+
                         "Light Ammo Intensity : "+"#"+"\n"+
                         "Heavy Ammo Intensity : "+"###"+"\n");
       
        }else if(vehicle.contains("Hover")){
            spec.setText(formulatingSpeed(VehicleLoader.MARS_ROVER_SPEED)+
                         "Acceleration : "+"#"+"\n"+
                         "Light Ammo Intensity : "+"#"+"\n"+
                         "Heavy Ammo Intensity : "+"###"+"\n");
        }
    }
    /**
     * formulate the speed into # with 0.5 as a rate of point increase 
     * @param speed the real speed
     * @return string representation with the formula Speed : ####
     */
    private String formulatingSpeed(float speed){
        String formulatedSpeed="";
        for(float n=0f;n<speed;n+=0.5f){
            formulatedSpeed+="#";
        }
        return "Speed : "+formulatedSpeed+"\n";
    }

    @Override
    public void onAction(String binding, boolean isPressed, float arg2) {
         switch(binding){
            case "Left":
                //--
                int startOffset=0;
                if(spaceShipIndex > startOffset){
                   changeVehicle(availableSpaceShips[--spaceShipIndex]);
                   switchVehicleSpec(availableSpaceShips[spaceShipIndex]);
                }
                break;
            case "Right":
                //++
                int lastIndex=availableSpaceShips.length-1;
                if(spaceShipIndex < lastIndex){
                    changeVehicle(availableSpaceShips[++spaceShipIndex]);
                    switchVehicleSpec(availableSpaceShips[spaceShipIndex]);
                }
                break;
            case "Go":
                rootNode.detachAllChildren();
                viewPort.clearProcessors();
                rootNode.removeLight(stageDirectLight);
                rootNode.removeLight(metallicLight);
                camera.setRotation(Quaternion.IDENTITY);
                onFinish();
                setStartGame(true);
                break;
         
         }   
    }
}

& to use it in a SimpleApplication Game context :slight_smile:

 @Override
    public void simpleInitApp() {
        
        GuiGlobals.initialize(this);
        
        // Load the 'glass' style
        BaseStyles.loadGlassStyle();
            
        // Set 'glass' as the default style when not specified
        GuiGlobals.getInstance().getStyles().setDefaultStyle("glass");
        
        VehicleSelectorStage stage=new VehicleSelectorStage("Models/Mars HoverTank/MarsHoverTankEdited.j3o", rootNode,new String[]{"Models/Mars HoverTank/MarsHoverTankEdited.j3o",
                                                                                                              "Models/Mars HoverTank/MarsHoverPlane.j3o"  }) {
            @Override
            public void onFinish() {
                inputManager.clearMappings();
                inputManager.clearRawInputListeners();
                /**
                 * start the map
                 */
                startMap();
               
            }
        };
        /**
         * configure the stage
         */
        stage.setGuiNode(guiNode);
        stage.setAssetManager(assetManager);
        stage.setCamera(cam);
        stage.setInputManager(inputManager);
        stage.setViewPort(viewPort);
        /**
         * start the stage
         */
        stage.intializeSelector();
        /**
         * add the Go Button & set-up Listeners
         */
        stage.intializeGUI();
        /**
         * start the vehicle spec container dialog
         */
        stage.intializeVehicleSpec(stage.getSelectedSpaceShip(),settings);
        
    }

Images :