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);
}
}