Applet + JME Desktop

I am trying to make an applet JME cube desktop.

I tried JME Desktop tuturial : great.

I used part of this code in my applet but result is not concluant from now : panes; buttons etc does not appears correctly, + not interraction

render is not like swing (TestJMEDesktop sample).

Is it a way to hide FPS and Trimesh indication at bottom of the page.



My source :


package com.orange.rd.java.monkey.engine;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JEditorPane;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;

import com.jme.bounding.BoundingBox;
import com.jme.input.InputHandler;
import com.jme.input.KeyboardLookHandler;
import com.jme.input.MouseInput;
import com.jme.input.action.InputActionEvent;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.SceneElement;
import com.jme.scene.shape.Box;
import com.jme.scene.state.LightState;
import com.jmex.awt.applet.SimpleJMEApplet;
import com.jmex.awt.swingui.JMEAction;
import com.jmex.awt.swingui.JMEDesktop;

public class Web3DJMEApplet extends SimpleJMEApplet {

/**
*
*/
private static final long serialVersionUID = 9194125664838585328L;

   
    private Node nodeFront = null;
    private JMEDesktop desktopFront = null;

    public void simpleAppletSetup() {
   
    // Background color
    getRenderer().setBackgroundColor(ColorRGBA.blue);
   
    Node rootNode = getRootNode();           
    getLightState().setEnabled(false);
    rootNode.setCullMode( SceneElement.CULL_NEVER );           
       
    // create a node for ortho gui stuff   
        nodeFront = new Node( "gui" );
        nodeFront.setRenderQueueMode( Renderer.QUEUE_ORTHO );                   
       
        // create the desktop Quad
        desktopFront = new JMEDesktop( "desktop", 400, 400, new InputHandler() );
        //final JMEDesktop desktop = new JMEDesktop( "test internalFrame 1" );     
        //InputHandler input = new InputHandler();   
    //Camera camera = getCamera();   
    //KeyboardLookHandler lookHandler = new KeyboardLookHandler(camera, 50, 1 );
        //input.addToAttachedHandlers( lookHandler );               
        //desktop.setup( 20, 20, false, input );       
       
        // and attach it to the gui node
        nodeFront.attachChild( desktopFront );       
        // center it on screen
        desktopFront.getLocalTranslation().set( getWidth() / 2 - 30, getHeight() / 2 + 50, 0 );
   
        // Perform all the swing stuff in the swing thread
        Runnable toRun = new Runnable() {
        public void run() {
        // make it transparent blue
        desktopFront.getJDesktop().setBackground( new Color( 0, 0, 1, 0.2f ) );

                // create a swing button
                final JButton button = new JButton( "click me" );
                // and put it directly on the desktop
                desktopFront.getJDesktop().add( button );
                // desktop has no layout - we layout ourselfes (could assign a layout to desktop here instead)
                button.setLocation( 200, 200 );
                button.setSize( button.getPreferredSize() );
                // add some actions
                // standard swing action:
                button.addActionListener( new ActionListener() {
                    public void actionPerformed( ActionEvent e ) {
                        // this gets executed in swing thread
                        // alter swing components ony in swing thread!
                        button.setLocation( FastMath.rand.nextInt( 400 ), FastMath.rand.nextInt( 300 ) );
                        System.out.println( "clicked!" );
                    }
                } );
                // action that gets executed in the update thread:
                button.addActionListener( new JMEAction( "my action", getInputHandler() ) {
                    public void performAction( InputActionEvent evt ) {
                        // this gets executed in jme thread
                        // do 3d system calls in jme thread only!
                        nodeFront.updateRenderState(); // this call has no effect but should be done in jme thread :)
                    }
                });
        }
        };
 
        if ( SwingUtilities.isEventDispatchThread() )
            toRun.run();
else {
try {
SwingUtilities.invokeAndWait( toRun );
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
     
        // don't cull the gui away
        nodeFront.setCullMode( SceneElement.CULL_NEVER );
        // gui needs no lighting
        nodeFront.setLightCombineMode( LightState.OFF );                 
       
        // Background color
        desktopFront.getJDesktop().setBackground( Color.red );                       
       
        // update the render states (especially the texture state of the deskop!)
        nodeFront.updateRenderState();
        // update the world vectors (needed as we have altered local translation of the desktop and it's
        //  not called in the update loop)
        nodeFront.updateGeometricState( 0, true );
                                       
        // finally show the system mouse cursor to allow the user to click our button
        MouseInput.get().setCursorVisible( true );               
        rootNode.attachChild(nodeFront); 
     
                                   
        createBoxBorder(desktopFront, nodeFront); 
        perspective(desktopFront, nodeFront);
        createSwingStuff(desktopFront, nodeFront);   
        try {
createEditorPane(desktopFront);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
    }
       
   
   
    private void createBoxBorder(JMEDesktop desktop, Node desktopNode) {
        //create a border from boxes around the desktop
    float borderSize = 3/*10*/;
        float halfBorderSize = borderSize / 2;
        int halfDesktopWidth = desktop.getJDesktop().getWidth() / 2;
        int halfDesktopHeight = desktop.getJDesktop().getHeight() / 2;

        Box top = new Box( "top border", new Vector3f(),
                halfDesktopWidth + halfBorderSize,
                halfBorderSize, halfBorderSize );
        top.getLocalTranslation().set( 0, -halfDesktopHeight, 0 );
        top.setModelBound( new BoundingBox() );
        top.updateModelBound();
        desktopNode.attachChild( top );

        Box bottom = new Box( "bottom border", new Vector3f(),
                halfDesktopWidth + halfBorderSize,
                halfBorderSize, halfBorderSize );
        bottom.getLocalTranslation().set( 0, halfDesktopHeight, 0 );
        bottom.setModelBound( new BoundingBox() );
        bottom.updateModelBound();
        desktopNode.attachChild( bottom );

        Box left = new Box( "left border", new Vector3f(),
                halfBorderSize,
                halfDesktopHeight + halfBorderSize,
                halfBorderSize );
        left.getLocalTranslation().set( -halfDesktopWidth, 0, 0 );
        left.setModelBound( new BoundingBox() );
        left.updateModelBound();
        desktopNode.attachChild( left );

        Box right = new Box( "right border", new Vector3f(),
                halfBorderSize,
                halfDesktopHeight + halfBorderSize,
                halfBorderSize );
        right.getLocalTranslation().set( halfDesktopWidth, 0, 0 );
        right.setModelBound( new BoundingBox() );
        right.updateModelBound();
        desktopNode.attachChild( right );
                               
    }
   
    private void perspective(JMEDesktop desktop, Node desktopNode) {
    desktopNode.setLocalScale( 18f / desktop.getJDesktop().getWidth() );
    desktopNode.getLocalTranslation().set( 0, 0, 0 );
    desktopNode.setRenderQueueMode( Renderer.QUEUE_TRANSPARENT );
    desktopNode.setCullMode( SceneElement.CULL_DYNAMIC );
    }
   
   
    protected void createSwingStuff(JMEDesktop desktop, Node desktopNode) {
        final JDesktopPane desktopPane = desktop.getJDesktop();
        desktopPane.removeAll();

        createSwingInternalFrame( desktopPane, "My Frame 1", 10, 150 );
        //createSwingInternalFrame( desktopPane, "My Frame 2", 20, 300 );
        //createSwingInternalFrame( desktopPane, null, 400, 350 );

        final JButton button3 = new JButton( "more stuff" );
        button3.setLocation( 300, 100 );
        button3.setSize( button3.getPreferredSize() );
        button3.setBackground(Color.blue);
        desktopPane.add( button3 );
        button3.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
                //createMoreSwingStuff();
                //button3.setVisible( false );
            }
        } );

      /* final JButton buttonToggleMouse = new JButton( "toggle system/custom cursor" );
        buttonToggleMouse.setLocation( 300, 70 );
        buttonToggleMouse.setSize( buttonToggleMouse.getPreferredSize() );
        desktopPane.add( buttonToggleMouse );
        buttonToggleMouse.addActionListener( new JMEAction( "toggle mouse", input ) {
            public void performAction( InputActionEvent evt ) {
                if ( MouseInput.get().isCursorVisible() ) {
                    // switch to custom mouse

                    // hide system cursor
                    MouseInput.get().setCursorVisible( false );

                    // show custom cursor
                    cursor.setCullMode( SceneElement.CULL_NEVER );
                } else {
                    // switch to system mouse

                    // hide custom cursor
                    cursor.setCullMode( SceneElement.CULL_ALWAYS );

                    // show system cursor
                    MouseInput.get().setCursorVisible( true );
                }
            }
        } );
        buttonToggleMouse.setMnemonic( 'm' );*/

      // final JLabel label = new JLabel( "click scene to steer view (WASD+Arrows)" );
    //    label.setSize( label.getPreferredSize() );
    //    label.setLocation( /*display.getWidth()*/100 - (int) label.getSize().getWidth() - 10, 10 );
    //    desktopPane.add( label );

        //moreStuffCreated = false;

        /*final JButton themeButton = new JButton( "change l&f" );
        themeButton.setLocation( 10, 400 );
        themeButton.setSize( themeButton.getPreferredSize() );
        desktopPane.add( themeButton );
        themeButton.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
                jmeDesktop.getJDesktop().removeAll();
                switchLookAndFeel( theme + 1 );
                createSwingStuff();
            }
        } );*/

        /*JButton fullScreenButton = new JButton( "<html><big>toggle fullscreen</big></html>" );
        fullScreenButton.setSize( fullScreenButton.getPreferredSize() );
        fullScreenButton.setLocation( ( display.getWidth() - fullScreenButton.getWidth() ) / 2,
                display.getHeight() - 40 - fullScreenButton.getHeight() / 2 );
        desktopPane.add( fullScreenButton );
        fullScreenButton.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
                if ( desktopNode.getRenderQueueMode() == Renderer.QUEUE_ORTHO ) {
                    perspective();
                } else {
                    fullScreen();
                }
            }
        } );*/

      /* createRotateButton( desktopPane, 0.25f );
        createRotateButton( desktopPane, -0.25f );
        createRotateButton( desktopPane, 0.15f );
        createRotateButton( desktopPane, -0.15f );
        createRotateButton( desktopPane, 0.45f );
        createRotateButton( desktopPane, -0.45f );*/

      /* try {
createEditorPane();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}*/
               
        desktopPane.repaint();
        desktopPane.revalidate();
    }           
   
    private void createSwingInternalFrame( final JDesktopPane desktopPane, final String title, int x, int y ) {
        final JInternalFrame internalFrame = new JInternalFrame( title );
        if ( title == null ) {
            internalFrame.putClientProperty( "JInternalFrame.isPalette", Boolean.TRUE );
        }
        internalFrame.setLocation( x, y );
        internalFrame.setResizable( true );

        internalFrame.getContentPane().setLayout( new FlowLayout() );
        JButton button1 = new JButton( "button in " + title );
        button1.setMnemonic( 'u' );
        internalFrame.getContentPane().add( button1 );
        internalFrame.getContentPane().add( new JButton( "<html><i>test</i> <big>2</big></html>" ) );
        internalFrame.setVisible( true );
        internalFrame.pack();
        button1.addActionListener( new ActionListener() {
            public void actionPerformed( ActionEvent e ) {
                //showDialog();
            }
        } );

        final JTextField textField = new JTextField( "type in here" );
        internalFrame.getContentPane().add( textField );
        internalFrame.pack();
        desktopPane.add( internalFrame );
    }
   
    private void createEditorPane(JMEDesktop jmeDesktop) throws IOException {
        JInternalFrame internalFrame = new JInternalFrame( "html test" );
        final JEditorPane editor = new JEditorPane("http://www.motogp.com/fr/motogp/" );
        editor.addHyperlinkListener( new HyperlinkListener() {
            public void hyperlinkUpdate( HyperlinkEvent e ) {
                if ( e.getEventType().equals( HyperlinkEvent.EventType.ACTIVATED ) ) {
                    if ( !Color.green.equals( editor.getBackground() ) ) {
                        editor.setBackground( Color.GREEN );
                    } else {
                        editor.setBackground( Color.WHITE );
                    }
                }
            }
        } );
        editor.setEditable( false );                     
        internalFrame.setLocation( 10, 10 );
        internalFrame.setSize(  editor.getPreferredSize() );
        internalFrame.getContentPane().add( editor, BorderLayout.CENTER );
        internalFrame.setVisible( true );
        jmeDesktop.getJDesktop().add( internalFrame );
    }
   

}

Noody knows ???

It is likely that JMEDesktop does not work in applets - I never tried that. Try with a 'normal' jME app first.

I tried simple applet with the sample of tutorial. It’s ok.

I tried JME Desktop sample : it works OK.



But when I try to but them together JMEDesktop is not correctly displayed and panels do not appears correctly.



So it seems that it is not the solution for what I need ; :’(

Cube Applet 3D with Swing contents on the different sides.

I tried again to put the JMDesktop code in an applet. Still the same, no panel is rendered. I only have desktop borders.



Just to be sure, can someone confirm of not if JME Desktop works in applet ??? So I could take a decision for my project.






Maybe it's an applet-swing use issue?  No idea.

Thanks for the answer



I don't know because we cannot add a Simple Game component as an applet component.

JME Applet is also specific so it is difficult to say



So I took all the source code of JME Desktop and readapt it to the JME Applet as I said.



It would be very well if we could run desktop in applet.





There are two things that I have managed to locate that may assist with this problem, as I am hoping to be able to access the JME Desktop within an applet as well.

The root of the matter appears to be a threading problem, but I am not experienced enough in Java AWT/Swing threading to pinpoint what is going on. The chief difference between JME as a standalone Game versus and Applet is that the Applet does EVERYTHING as part of an AWT Event Dispatch Thread. This includes rendering, event processing, etcetera. This is a problem because JME is used to handling rendering in the main thread, and delegating JME Desktop calls to the AWT Event Dispatcher.


First off, JMEDesktop.java uses SwingUtilities.invokeAndWait() to transmit calls from the InputHandler to the JDesktopPane in the JME Desktop. This method throws an exception when called within the dispatch thread, since the dispatch thread is not allowed to wait. I've solved this problem by replacing the lines

SwingUtilities.invokeAndWait( new Runnable() {
    // **** EVENT CODE
} );

with

if(EventQueue.isDispatchThread()) {
    // **** EVENT CODE
} else SwingUtilities.invokeAndWait( new Runnable() {
    // **** EVENT CODE
} );

This way the waiting is ignored.

The second issue, which I have not yet been able to solve is that the JDesktopPane is simply never painted. I've been able to force it to paint by calling paintImmediately(), but this doesn't seem like a good idea for the long run. The JMEDesktop uses a Frame to handle all of its event calls, and it may do this by creating a new event dispatcher thread or using the existing one, but as it stands, it does not appear to be processing ANY events whatsoever.

I call desktop.getJDesktop().repaint(), yet nothing ever happens. So something appears to be stalling or rendering the frame event thread useless. Perhaps one of you jME gurus can expound on this a little bit more.

Hope this helps, though I'm sorry I haven't found a solution yet.
Hopefully there will be one coming.
Cheers!

Yes we can!



See the attached file.

I modified an example of JME.