JMECanvas and JME 2.0

I am having difficulty with porting my app to JME 2.0,



As a test I used the basic JMESwingTest (with the relevant JME 2 changes) using JME 2.0 and I am getting an error. Can i get confirmation that JMECanvas works in 2.0, or a simple HelloWorld example for JME2 in a Swing environment?


Jan 9, 2009 10:58:19 PM com.jme.input.joystick.DummyJoystickInput <init>
INFO: Joystick support is disabled
Jan 9, 2009 10:58:19 PM com.jme.system.lwjgl.LWJGLDisplaySystem <init>
INFO: LWJGL Display System created.
Exception in thread "main" com.jme.system.JmeException: Unregistered canvas type: AWT
at com.jme.system.DisplaySystem.makeCanvasConstructor(DisplaySystem.java:506)
at com.jme.system.lwjgl.LWJGLDisplaySystem.createCanvas(LWJGLDisplaySystem.java:206)
at com.jme.system.lwjgl.LWJGLDisplaySystem.createCanvas(LWJGLDisplaySystem.java:189)
at canvastest.JMESwingTest$SwingFrame.init(JMESwingTest.java:183)
at canvastest.JMESwingTest$SwingFrame.<init>(JMESwingTest.java:152)
at canvastest.JMESwingTest.<init>(JMESwingTest.java:106)
at canvastest.JMESwingTest.main(JMESwingTest.java:121)



The code I used to generate this error:


package canvastest;
/*
 * Copyright (c) 2003-2006 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.concurrent.Callable;
import java.util.logging.Logger;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.UIManager;

import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.InputHandler;
import com.jme.input.KeyInput;
import com.jme.input.action.InputAction;
import com.jme.input.action.InputActionEvent;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Renderer;
import com.jme.scene.shape.Box;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.GameTaskQueueManager;
import com.jme.util.TextureManager;
import com.jmex.awt.JMECanvas;
import com.jmex.awt.JMECanvasImplementor;
import com.jmex.awt.SimpleCanvasImpl;
import com.jmex.awt.input.AWTMouseInput;

/**
 * <code>JMESwingTest</code> is a test demoing the JMEComponent and
 * HeadlessDelegate integration classes allowing jME generated graphics to be
 * displayed in a AWT/Swing interface.
 *
 * Note the Repaint thread and how you grab a canvas and add an implementor to it.
 *
 * @author Joshua Slack
 * @version $Id: JMESwingTest.java,v 1.17 2007/08/03 00:06:43 nca Exp $
 */

public class JMESwingTest {
    private static final Logger logger = Logger.getLogger(JMESwingTest.class
            .getName());

    int width = 640, height = 480;

    // Swing frame
    private SwingFrame frame;

    public JMESwingTest()
    {
       String s = System.getProperty("user.dir");
       
       System.out.println("lib path " + s);
        frame = new SwingFrame();
        // center the frame
        frame.setLocationRelativeTo(null);
        // show frame
        frame.setVisible(true);
    }

    /**
     * Main Entry point...
     *
     * @param args
     *            String[]
     */
    public static void main(String[] args)
    {
        new JMESwingTest();
    }

    // **************** SWING FRAME ****************

    // Our custom Swing frame... Nothing really special here.
    class SwingFrame extends JFrame {
        private static final long serialVersionUID = 1L;

        JPanel contentPane;
        JPanel mainPanel = new JPanel();
        Canvas comp = null;
        JButton coolButton = new JButton();
        JButton uncoolButton = new JButton();
        JPanel spPanel = new JPanel();
        JScrollPane scrollPane = new JScrollPane();
        JTree jTree1 = new JTree();
        JCheckBox scaleBox = new JCheckBox("Scale GL Image");
        JPanel colorPanel = new JPanel();
        JLabel colorLabel = new JLabel("BG Color:");
        JMECanvasImplementor impl;

       
        // Construct the frame
        public SwingFrame() {
            addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    dispose();
                }
            });

            init();
            pack();


            // MAKE SURE YOU REPAINT SOMEHOW OR YOU WON'T SEE THE UPDATES...
            new Thread() {
                { setDaemon(true); }
                public void run() {
                    while (true) {
                        comp.repaint();
                        yield();
                    }
                }
            }.start();

           
        }

        // Component initialization
        private void init()
        {
            contentPane = (JPanel) this.getContentPane();
            contentPane.setLayout(new BorderLayout());

            mainPanel.setLayout(new GridBagLayout());

            setTitle("JME - SWING INTEGRATION TEST");

            //


GL STUFF

            // make the canvas:
            comp = (Canvas) DisplaySystem.getDisplaySystem("lwjgl").createCanvas(width, height);
           

            // add a listener... if window is resized, we can do something about it.
            comp.addComponentListener(new ComponentAdapter() {
                public void componentResized(ComponentEvent ce) {
                    doResize();
                }
            });
            KeyInput.setProvider( KeyInput.INPUT_AWT );
            AWTMouseInput.setup( comp, false );

                    // Important!  Here is where we add the guts to the panel:
            impl = new MyImplementor(width, height);
          
            JMECanvas jmeCanvas = ( (JMECanvas) comp );
           
            jmeCanvas.setImplementor(impl);
            jmeCanvas.setUpdateInput( true );

            //
END OF GL STUFF

            coolButton.setText("Cool Button");
            uncoolButton.setText("Uncool Button");

            colorPanel.setBackground(java.awt.Color.black);
            colorPanel.setToolTipText("Click here to change Panel BG color.");
            colorPanel.setBorder(BorderFactory.createRaisedBevelBorder());
            colorPanel.addMouseListener(new java.awt.event.MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    final java.awt.Color color = JColorChooser.showDialog(
                            SwingFrame.this, "Choose new background color:",
                            colorPanel.getBackground());
                    if (color == null)
                        return;
                    colorPanel.setBackground(color);
                    Callable<?> call = new Callable<Object>() {
                        public Object call() throws Exception {
                            comp.setBackground(color);
                            return null;
                        }
                    };
                    GameTaskQueueManager.getManager().render(call);
                }
            });

            scaleBox.setOpaque(false);
            scaleBox.setSelected(true);
            scaleBox.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    if (comp != null)
                        doResize();
                }
            });

            spPanel.setLayout(new BorderLayout());
            contentPane.add(mainPanel, BorderLayout.WEST);
            mainPanel.add(scaleBox,
                    new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
                            GridBagConstraints.CENTER,
                            GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0,
                                    5), 0, 0));
            mainPanel.add(colorLabel,
                    new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
                            GridBagConstraints.CENTER,
                            GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0,
                                    5), 0, 0));
            mainPanel.add(colorPanel, new GridBagConstraints(0, 2, 1, 1, 0.0,
                    0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE,
                    new Insets(5, 5, 0, 5), 25, 25));
            mainPanel.add(coolButton,
                    new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0,
                            GridBagConstraints.CENTER,
                            GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0,
                                    5), 0, 0));
            mainPanel.add(uncoolButton,
                    new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0,
                            GridBagConstraints.CENTER,
                            GridBagConstraints.HORIZONTAL, new Insets(5, 5, 0,
                                    5), 0, 0));
            mainPanel.add(spPanel, new GridBagConstraints(0, 5, 1, 1, 1.0, 1.0,
                    GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                    new Insets(5, 5, 0, 5), 0, 0));
            spPanel.add(scrollPane, BorderLayout.CENTER);
           
            scrollPane.setViewportView(jTree1);
            comp.setBounds(0, 0, width, height);
            contentPane.add(comp, BorderLayout.CENTER);
        }

        protected void doResize() {
            if (scaleBox != null && scaleBox.isSelected()) {
                impl.resizeCanvas(comp.getWidth(), comp.getHeight());
            } else {
                impl.resizeCanvas(width, height);
            }
        }

        // Overridden so we can exit when window is closed
        protected void processWindowEvent(WindowEvent e) {
            super.processWindowEvent(e);
            if (e.getID() == WindowEvent.WINDOW_CLOSING) {
                System.exit(0);
            }
        }
    }

   
    // IMPLEMENTING THE SCENE:
   
    class MyImplementor extends SimpleCanvasImpl {

        private Quaternion rotQuat;
        private float angle = 0;
        private Vector3f axis;
        private Box box;
                long startTime = 0;
                long fps = 0;
        private InputHandler input;

        public MyImplementor(int width, int height)
        {
            super(width, height);
        }

        public void simpleSetup()
        {
           
           

            // Normal Scene setup stuff...
            rotQuat = new Quaternion();
            axis = new Vector3f(1, 1, 0.5f);
            axis.normalizeLocal();

            Vector3f max = new Vector3f(5, 5, 5);
            Vector3f min = new Vector3f(-5, -5, -5);

            box = new Box("Box", min, max);
            box.setModelBound(new BoundingBox());
            box.updateModelBound();
            box.setLocalTranslation(new Vector3f(0, 0, -10));
            box.setRenderQueueMode(Renderer.QUEUE_SKIP);
            rootNode.attachChild(box);

            box.setRandomColors();

            TextureState ts = renderer.createTextureState();
            ts.setEnabled(true);
            ts.setTexture(TextureManager.loadTexture(JMESwingTest.class
                    .getClassLoader().getResource(
                            "jmetest/data/images/Monkey.jpg"),
                            Texture.MinificationFilter.BilinearNearestMipMap,
                            Texture.MagnificationFilter.Bilinear));

            rootNode.setRenderState(ts);
            startTime = System.currentTimeMillis() + 5000;

            input = new InputHandler();
            input.addAction( new InputAction() {
                public void performAction( InputActionEvent evt ) {
                    logger.info( evt.getTriggerName() );
                }
            }, InputHandler.DEVICE_MOUSE, InputHandler.BUTTON_ALL, InputHandler.AXIS_NONE, false );
        }

        public void simpleUpdate() {
            input.update( tpf );

            // Code for rotating the box... no surprises here.
            if (tpf < 1) {
                angle = angle + (tpf * 25);
                if (angle > 360) {
                    angle = 0;
                }
            }
            rotQuat.fromAngleNormalAxis(angle * FastMath.DEG_TO_RAD, axis);
            box.setLocalRotation(rotQuat);
           
                        if (startTime > System.currentTimeMillis()) {
                                fps++;
                        } else {
                                long timeUsed = 5000 + (startTime - System.currentTimeMillis());
                                startTime = System.currentTimeMillis() + 5000;
                                logger.info(fps + " frames in " + (timeUsed / 1000f) + " seconds = "
                                                + (fps / (timeUsed / 1000f))+" FPS (average)");
                                fps = 0;
                        }                              
        }
    }
}



Register CanvasConstructor type like this


DisplaySystem ds = DisplaySystem.getDisplaySystem(JOGLSystemProvider.SYSTEM_IDENTIFIER);
ds.registerCanvasConstructor("AWT", JOGLAWTCanvasConstructor.class);



You can use
JOGLAWTCanvasConstructor or
LWJGLAWTCanvasConstructor or
LWJGLSWTCanvasConstructor

I want to encourage everyone to look at the test package that comes with jME 2. All of the examples have been updated.


xopherxm said:

As a test I used the basic JMESwingTest (with the relevant JME 2 changes) using JME 2.0 and I am getting an error. Can i get confirmation that JMECanvas works in 2.0, or a simple HelloWorld example for JME2 in a Swing environment?

http://code.google.com/p/jmonkeyengine/source/browse/trunk/src/jmetest/util/JMESwingTest.java

Thanks. I'd like to point out that as of today (1/12/09) the latest JARs available for JME 2.0 do not reflect the latest source code, at least in regards to the LWJGLCanvas class. (LWJGLAWTCanvasConstructor is also missing from the JAR).



I was just using the jars and it complained, when I added the source tot he build path it worked.

xopherxm said:

Thanks. I'd like to point out that as of today (1/12/09) the latest JARs available for JME 2.0 do not reflect the latest source code, at least in regards to the LWJGLCanvas class. (LWJGLAWTCanvasConstructor is also missing from the JAR).

I was just using the jars and it complained, when I added the source tot he build path it worked.

We have not built/released any jars for jME 2.0 yet. Perhaps you are referring to jME 1.0 jars?