How about a JMEDesktopGameState

Hi!



I've tried to create a gamestate specifically for rendering a JMEDesktop but with no luck. I hope someone can see what I've done wrong or maybe someone even already have such a gamestate to share  :slight_smile:



public class GUISystem extends BasicGameState{

   private static GUISystem instance;
   
   private JMEDesktop jmeDesktop;
   private Node desktopNode;
   
   private GUISystem()
   {
      super("GUI game state");
      
      DisplaySystem display = DisplaySystem.getDisplaySystem();
      
      rootNode = new Node("Root node for GUI");
      AlphaState as1 = display.getRenderer().createAlphaState();
      as1.setBlendEnabled( true );
      as1.setSrcFunction( AlphaState.SB_SRC_ALPHA );
      as1.setDstFunction( AlphaState.DB_ONE );
      as1.setTestEnabled( true );
      as1.setTestFunction( AlphaState.TF_GREATER );
      rootNode.setRenderState(as1);
      TextureState defaultFontTextureState = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
      defaultFontTextureState.setTexture( TextureManager.loadTexture( SimpleGame.class
         .getClassLoader().getResource("com/jme/app/defaultfont.tga"), Texture.MM_LINEAR,
         Texture.FM_LINEAR ) );
      defaultFontTextureState.setEnabled( true );
      rootNode.setCullMode(Spatial.CULL_NEVER);
      rootNode.setRenderQueueMode(Renderer.QUEUE_ORTHO);
      rootNode.setLightCombineMode(LightState.OFF);
      
      jmeDesktop = new JMEDesktop( "test internalFrame" );
      jmeDesktop.setup( display.getWidth(), display.getHeight(), false, new InputHandler());
      jmeDesktop.setLightCombineMode( LightState.OFF );
      desktopNode = new Node( "desktop node" );
      desktopNode.attachChild( jmeDesktop );
      rootNode.attachChild(desktopNode);
       
      final JDesktopPane desktopPane = jmeDesktop.getJDesktop();
      desktopPane.removeAll();

                createSwingInternalFrame( desktopPane, "Some frame...", 500, 500 );

                desktopPane.repaint();
                desktopPane.revalidate();
   }

      private void createSwingInternalFrame( final JDesktopPane desktopPane, final String title, int x, int y ) {
          final Color backGroundColor = new Color(0f,0f,0.5f,0.5f);
          
           final JInternalFrame internalFrame = new JInternalFrame( title );
           if ( title == null ) {
               internalFrame.putClientProperty( "JInternalFrame.isPalette", Boolean.TRUE );
           }
           ((javax.swing.plaf.basic.BasicInternalFrameUI)internalFrame.getUI()).setNorthPane(null);
           internalFrame.setLocation( x, y );
           internalFrame.setBackground(backGroundColor);

           internalFrame.getContentPane().setLayout( new FlowLayout() );
          
           JTextPane text = new JTextPane();
           text.setText("Endnu en test p

Solved the problem. If anyone is interested I will show the code here.

If you've made a JMEDesktopGameState out of it, I'm sure some people would be happy to use that one day to avoid whatever problem you had.

Good then I'll post it. I just have to clean the code a bit first. Stay tuned.

First an abstract JMEDesktopGameState:


package gui;

import javax.swing.JDesktopPane;

import com.jme.app.BasicGameState;
import com.jme.input.AbsoluteMouse;
import com.jme.input.InputHandler;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.state.LightState;
import com.jme.system.DisplaySystem;
import com.jmex.awt.swingui.JMEDesktop;

public abstract class JMEDesktopGameState extends BasicGameState {

   protected JMEDesktop jmeDesktop;

   private Node desktopNode;

   protected InputHandler input;

   protected AbsoluteMouse cursor;

   protected DisplaySystem display;

   public JMEDesktopGameState(InputHandler input) {
      super("GUI game state");

      this.input = input;
      display = DisplaySystem.getDisplaySystem();

      rootNode.setCullMode(Spatial.CULL_NEVER);

      jmeDesktop = new JMEDesktop("JMEDesktop");
      jmeDesktop.setup(display.getWidth(), display.getHeight(), false, input);
      desktopNode = new Node("JMEDesktop node");
      desktopNode.getLocalRotation().set(0, 0, 0, 1);
      desktopNode.getLocalTranslation().set(display.getWidth() / 2,
            display.getHeight() / 2, 0);
      desktopNode.getLocalScale().set(1, 1, 1);
      desktopNode.setRenderQueueMode(Renderer.QUEUE_ORTHO);
      desktopNode.setLightCombineMode(LightState.OFF);
      desktopNode.attachChild(jmeDesktop);
      rootNode.attachChild(desktopNode);

      JDesktopPane desktopPane = jmeDesktop.getJDesktop();
      desktopPane.removeAll();

      initSwing(desktopPane);

      initCursor();

      desktopPane.repaint();
      desktopPane.revalidate();

      rootNode.updateGeometricState(0.0f, true);
      rootNode.updateRenderState();
   }

   protected abstract void initSwing(JDesktopPane desktopPane);

   protected abstract void initCursor();

}


An example of how to derive from JMEDesktopGameState. Note that it's a good thing to implement your derivation as a singleton since your only allowed to have one instance of a JMEDesktop in your game (correct me if I'm wrong)


package gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.net.URL;

import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.plaf.metal.MetalLookAndFeel;

import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.input.AbsoluteMouse;
import com.jme.input.InputHandler;
import com.jme.scene.Spatial;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;

public class GUI extends JMEDesktopGameState {
   
   private static GUI instance;
   
    private GUI(InputHandler input) {
      super(input);
   }

    public static void create(InputHandler input)
    {
       if (instance==null)
          instance = new GUI(input);
    }
   
    public static GUI getInstance(){
       if (instance==null)
          throw new RuntimeException("GUI.create() hasn't been called yet.");
       return instance;
    }
   
   protected void initCursor() {
        cursor = new AbsoluteMouse( "cursor", display.getWidth(), display.getHeight() );

        // Get a picture for my mouse.
        TextureState ts = display.getRenderer().createTextureState();
        URL cursorLoc;
        cursorLoc = JMEDesktopGameState.class.getClassLoader().getResource(
                "jmetest/data/cursor/cursor1.png" );
        Texture t = TextureManager.loadTexture( cursorLoc, Texture.MM_LINEAR,
                Texture.FM_LINEAR, Image.GUESS_FORMAT_NO_S3TC, 1, true );
        ts.setTexture( t );
        cursor.setRenderState( ts );

        // Make the mouse's background blend with what's already there
        AlphaState as = display.getRenderer().createAlphaState();
        as.setBlendEnabled( true );
        as.setSrcFunction( AlphaState.SB_SRC_ALPHA );
        as.setDstFunction( AlphaState.DB_ONE_MINUS_SRC_ALPHA );
        as.setTestEnabled( true );
        as.setTestFunction( AlphaState.TF_GREATER );
        cursor.setRenderState( as );

        // Assign the mouse to an input handler
        cursor.registerWithInputHandler( input );

        rootNode.attachChild( cursor );

        // important for JMEDesktop: use system coordinates
        cursor.setUsingDelta( false );
        cursor.getXUpdateAction().setSpeed( 1 );
        cursor.getYUpdateAction().setSpeed( 1 );

        cursor.setCullMode( Spatial.CULL_NEVER );
    }
   
   protected void initSwing( JDesktopPane desktopPane) {
        
      try {
            UIManager.setLookAndFeel(new MetalLookAndFeel());
            SwingUtilities.updateComponentTreeUI(jmeDesktop.getJDesktop());
        } catch (Exception e) { }
     
       final Color backGroundColor = new Color(0f,0f,0.5f,0.5f);
       
        final JInternalFrame internalFrame = new JInternalFrame("My JInternalFrame");

        ((javax.swing.plaf.basic.BasicInternalFrameUI)internalFrame.getUI()).setNorthPane(null);
        internalFrame.setLocation( 500, 500 );
        internalFrame.setBackground(backGroundColor);

        internalFrame.getContentPane().setLayout( new FlowLayout() );
       
        JTextPane text = new JTextPane();
        text.setText("Look we have a nice GUI here. There's a button to the right with html on it!");
        text.setPreferredSize(new Dimension(400,50));
        text.setBackground(new Color(1f,1f,1f,0f));
        text.setForeground(Color.WHITE);
        text.setHighlighter(null);
        text.setEditable(false);
        internalFrame.getContentPane().add(text);
       
        internalFrame.getContentPane().add( new JButton( "<html> <big>⇒</big></html>" ) );
       
        internalFrame.setVisible( true );
        internalFrame.pack();

        desktopPane.add( internalFrame );
    }
}


Finally a sample extension of BaseGame that allows anyone to easily test the above classes.


import gui.GUI;

import java.util.logging.Level;

import com.jme.app.BaseGame;
import com.jme.app.GameStateManager;
import com.jme.input.FirstPersonHandler;
import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.MouseInput;
import com.jme.input.joystick.JoystickInput;
import com.jme.renderer.Camera;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.LoggingSystem;
import com.jme.util.Timer;

public class GUITest extends BaseGame {
   
   private Timer timer;
   private float tpf;
   private Camera cam;
   private InputHandler input;
   
   protected final void update(float interpolation) {
      timer.update();
      tpf = timer.getTimePerFrame();
      input.update(tpf);
      GameStateManager.getInstance().update(tpf);
   }
   
   protected final void render(float interpolation) {
      display.getRenderer().clearStatistics();
      display.getRenderer().clearBuffers();
      GameStateManager.getInstance().render(tpf);
   }
   
   protected final void initSystem() {
      try {
         display = DisplaySystem.getDisplaySystem(properties.getRenderer());
         display.setMinDepthBits(8);
            display.setMinStencilBits(0);
            display.setMinAlphaBits(0);
            display.setMinSamples(0);
         display.createWindow(
               properties.getWidth(),
               properties.getHeight(),
               properties.getDepth(),
               properties.getFreq(),
               properties.getFullscreen());
         cam = display.getRenderer().createCamera(display.getWidth(),
                    display.getHeight());
         display.getRenderer().setCamera(cam);
      }
      catch (JmeException e) {
         e.printStackTrace();
         System.exit(1);
      }
      timer = Timer.getTimer(properties.getRenderer());
      
   }
   
   protected final void initGame() {      
      display.setTitle("TextDisplay");
      input = new FirstPersonHandler(cam, 50, 1);
      GUI.create(input);
      GameStateManager.create();
      GUI.getInstance().setActive(true);
      GameStateManager.getInstance().attachChild(GUI.getInstance());
   }
   
   protected void reinit() {}
   
   protected void cleanup() {
      LoggingSystem.getLogger().log(Level.INFO, "Cleaning up resources.");
      GameStateManager.getInstance().cleanup();
        KeyInput.destroyIfInitalized();
        MouseInput.destroyIfInitalized();
        JoystickInput.destroyIfInitalized();
   }

   public static void main(String[] args) {
      GUITest app = new GUITest();
      app.setDialogBehaviour(GUITest.ALWAYS_SHOW_PROPS_DIALOG);
      app.start();
   }


   public void exit() {
      finish();
   }

   @Override
   protected void quit() {
      super.quit();
      System.exit(0);
   }
}

Wow, this is the first time I've noticed this thread.  I've just recently created a JMEDesktopState that is now in CVS if you're interested.

Cool. I'll have a look at it and see what things I didn't think of when I made the above code. Then I might migrate to your code in a later project.