[skycastle-commits] SF.net SVN: skycastle: [472] trunk/skycastle/modules/ui/src/main/java/org/ skycastle

  • From: zzorn@xxxxxxxxxxxxxxxxxxxxx
  • To: skycastle-commits@xxxxxxxxxxxxx
  • Date: Sat, 26 Apr 2008 02:07:22 -0700

Revision: 472
          http://skycastle.svn.sourceforge.net/skycastle/?rev=472&view=rev
Author:   zzorn
Date:     2008-04-26 02:07:22 -0700 (Sat, 26 Apr 2008)

Log Message:
-----------
Looked into different ways to combine OpenGL and Swing.  Swing with 3D window, 
and 3D window with Swing.  Got both approaches to work relatively ok, 3D window 
in Swing is slower but allows resizing on the fly.

Added Paths:
-----------
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/Canvas3D.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/FrameListener.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/AbstractDragGesture.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/AbstractNavigationGesture.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/CameraAccessor.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/MoveGesture.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/NavigationGesture.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/PanGesture.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/RotateGesture.java
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/Sketch3DUI.java
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchUi.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/Canvas3D.java
===================================================================
--- trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/Canvas3D.java 
                        (rev 0)
+++ trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/Canvas3D.java 
2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,580 @@
+package org.skycastle.opengl;
+
+import com.jme.renderer.Camera;
+import com.jme.renderer.Renderer;
+import com.jme.scene.Spatial;
+import com.jme.scene.state.CullState;
+import com.jme.system.DisplaySystem;
+import com.jmex.awt.JMECanvas;
+import com.jmex.awt.SimpleCanvasImpl;
+import org.skycastle.opengl.navigationgestures.*;
+import org.skycastle.util.ParameterChecker;
+import org.skycastle.util.cursor.CursorChangerImpl;
+import org.skycastle.util.fpscounter.FpsCounter;
+
+import javax.swing.*;
+import java.awt.Canvas;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A 3D Canvas, showing a 3D object in an AWT Canvas component.
+ * <p/>
+ * Allows registering Gestures, that can be used to navigate the 3D view 
(already has default gestures registered).
+ * <p/>
+ * Also allows adding FrameListeners, that are called after each rendering 
frame in the swing thread.
+ *
+ * @author Hans Haggstrom
+ */
+// IDEA: Also call them (a different method) in the opengl thread, before 
rendering.
+public final class Canvas3D
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final Set<NavigationGesture> myNavigationGestures = new 
HashSet<NavigationGesture>();
+    private final CursorChangerImpl myCursorChanger = new CursorChangerImpl();
+    private final FpsCounter myFpsCounter = new FpsCounter();
+    private final Set<FrameListener> myFrameListeners = new 
HashSet<FrameListener>();
+
+    private final CameraAccessor myCameraAccessor = new CameraAccessor()
+    {
+
+        public Camera getCamera()
+        {
+            return Canvas3D.this.getCamera();
+        }
+
+    };
+
+    private Spatial my3DNode = null;
+    private Component myView3D = null;
+    private Canvas myCanvas = null;
+    private MyCanvasRenderer myCanvasRenderer = null;
+    private float myViewDistance;
+
+    //======================================================================
+    // Private Constants
+
+    private static final int DEFAULT_WIDTH = 800;
+    private static final int DEFAULT_HEIGHT = 600;
+
+    private static final int CANVAS_REPAINT_INTERVAL_MS = 10;
+    private static final int DEFAULT_VIEW_DISTANCE = 100000;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    /**
+     * Creates a new empty 3D canvas.
+     * <p/>
+     * Use set3DNode to set a 3D object to show.
+     */
+    public Canvas3D()
+    {
+        this( null );
+    }
+
+
+    /**
+     * Creates a new 3D canvas, showing the specified 3D node.
+     *
+     * @param a3dNode the 3D node to show on this canvas, or null not to show 
any node.
+     */
+    public Canvas3D( final Spatial a3dNode )
+    {
+        this( a3dNode, DEFAULT_VIEW_DISTANCE );
+    }
+
+
+    public Canvas3D( final Spatial a3DNode, final float viewDistance )
+    {
+        my3DNode = a3DNode;
+
+        setViewDistance( viewDistance );
+
+        // Add default navigation gestures
+        addNavigationGesture( new PanGesture() );
+        addNavigationGesture( new RotateGesture() );
+        addNavigationGesture( new MoveGesture() );
+    }
+
+    //----------------------------------------------------------------------
+    // Other Public Methods
+
+    /**
+     * TODO: CHECK: Are the units meters?
+     *
+     * @return distance in screen units to the far clipping plane - 3D 
geometry beyond this distance is not shown.
+     */
+    public float getViewDistance()
+    {
+        return myViewDistance;
+    }
+
+
+    /**
+     * TODO: CHECK: Are the units meters?
+     *
+     * @param viewDistance distance in screen units to the far clipping plane 
- 3D geometry beyond this distance is not shown.
+     */
+    public void setViewDistance( final float viewDistance )
+    {
+        ParameterChecker.checkPositiveNonZeroNormalNumber( viewDistance, 
"viewDistance" );
+
+        myViewDistance = viewDistance;
+    }
+
+
+    /**
+     * @return the 3D node currently shown, or null if none shown.
+     */
+    public Spatial get3DNode()
+    {
+        return my3DNode;
+    }
+
+
+    /**
+     * @return the camera associated wit this 3D canvas, if it has been 
created, otherwise null.
+     */
+    public Camera getCamera()
+    {
+        if ( myCanvasRenderer != null )
+        {
+            return myCanvasRenderer.getCamera();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    /**
+     * Adds the specified FrameListener.  The listener is called after each 
frame is rendered in the swing thread.
+     *
+     * @param addedFrameListener should not be null or already added.
+     */
+    public void addFrameListener( FrameListener addedFrameListener )
+    {
+        ParameterChecker.checkNotNull( addedFrameListener, 
"addedFrameListener" );
+        ParameterChecker.checkNotAlreadyContained( addedFrameListener,
+                                                   myFrameListeners,
+                                                   "myFrameListeners" );
+
+        myFrameListeners.add( addedFrameListener );
+    }
+
+
+    /**
+     * Removes the specified FrameListener.
+     *
+     * @param removedFrameListener should not be null.
+     *
+     * @return true if the listener was found and removed, false if it was not 
found.
+     */
+    public boolean removeFrameListener( FrameListener removedFrameListener )
+    {
+        ParameterChecker.checkNotNull( removedFrameListener, 
"removedFrameListener" );
+
+        return myFrameListeners.remove( removedFrameListener );
+    }
+
+
+    /**
+     * @return the number of frames rendered per second,
+     *         or a negative value if the canvas has not yet been rendered.
+     */
+    public double getFramesPerSecond()
+    {
+        return myCanvasRenderer.getFramesPerSecond();
+    }
+
+
+    /**
+     * @return number of seconds between the previous frame and the frame 
before that,
+     *         or a negative value if the canvas has not yet been rendered.
+     */
+    public double getSecondsBetweenFrames()
+    {
+        return myCanvasRenderer.getSecondsBetweenFrames();
+    }
+
+
+    /**
+     * @param a3dNode the 3d node to show in this 3D canvas.
+     */
+    public void set3DNode( final Spatial a3dNode )
+    {
+        my3DNode = a3dNode;
+
+        if ( myCanvasRenderer != null )
+        {
+            myCanvasRenderer.setCanvasRootNode( a3dNode );
+        }
+    }
+
+
+    /**
+     * @return an AWT component containing a view of the 3D node.
+     */
+    public Component get3DView()
+    {
+        if ( myView3D == null )
+        {
+            myView3D = createView3D();
+        }
+
+        return myView3D;
+    }
+
+
+    /**
+     * @param addedNavigationGesture some gesture that can be used to control 
the camera.
+     */
+    public void addNavigationGesture( NavigationGesture addedNavigationGesture 
)
+    {
+        ParameterChecker.checkNotNull( addedNavigationGesture, 
"addedNavigationGesture" );
+        ParameterChecker.checkNotAlreadyContained( addedNavigationGesture,
+                                                   myNavigationGestures,
+                                                   "myNavigationGestures" );
+
+        myNavigationGestures.add( addedNavigationGesture );
+
+        registerNavigationGestureListener( addedNavigationGesture );
+    }
+
+
+    /**
+     * @param removedNavigationGesture gesture to remove.
+     */
+    public void removeNavigationGesture( NavigationGesture 
removedNavigationGesture )
+    {
+        ParameterChecker.checkNotNull( removedNavigationGesture, 
"removedNavigationGesture" );
+        ParameterChecker.checkContained( removedNavigationGesture,
+                                         myNavigationGestures,
+                                         "myNavigationGestures" );
+
+        myNavigationGestures.remove( removedNavigationGesture );
+
+        unRegisterNavigationGestureListener( removedNavigationGesture );
+    }
+
+
+    /**
+     * Removes all registered navigation gestures, including the builtin ones.
+     */
+    public void removeAllNavigationGestures()
+    {
+        myNavigationGestures.clear();
+
+        for ( NavigationGesture navigationGesture : myNavigationGestures )
+        {
+            unRegisterNavigationGestureListener( navigationGesture );
+        }
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private void registerNavigationGestureListener( final NavigationGesture 
navigationGesture )
+    {
+        if ( myCanvas != null )
+        {
+            navigationGesture.init( myCanvas, myCursorChanger, 
myCameraAccessor );
+        }
+    }
+
+
+    private void unRegisterNavigationGestureListener( final NavigationGesture 
navigationGesture )
+    {
+        if ( myCanvas != null )
+        {
+            navigationGesture.deInit();
+        }
+    }
+
+
+    private Component createView3D()
+    {
+        final int width = DEFAULT_WIDTH;
+        final int height = DEFAULT_HEIGHT;
+
+        // Create the 3D canvas
+        myCanvas = DisplaySystem.getDisplaySystem( "lwjgl" ).createCanvas( 
width, height );
+        myCanvas.setMinimumSize( new Dimension( 0, 0 ) ); // Make sure it is 
shrinkable
+        myCursorChanger.setComponent( myCanvas );
+        final JMECanvas jmeCanvas = ( (JMECanvas) myCanvas );
+
+        // Set the renderer that renders the canvas contents
+        myCanvasRenderer = new MyCanvasRenderer( width, height, my3DNode, 
myCanvas );
+        jmeCanvas.setImplementor( myCanvasRenderer );
+
+        // Add navigation gesture listeners to the created 3D canvas
+        for ( NavigationGesture navigationGesture : myNavigationGestures )
+        {
+            registerNavigationGestureListener( navigationGesture );
+        }
+
+        // We need to repaint the component to see the updates, so we create a 
repaint calling thread
+        final Thread repaintThread = new Thread( new MyRepainter( myCanvas ) );
+        repaintThread.setDaemon( true ); // Do not keep the JVM alive if only 
the repaint thread is left running
+        repaintThread.start();
+
+        return myCanvas;
+    }
+
+    //======================================================================
+    // Inner Classes
+
+    /**
+     * A thread for repainting a swing canvas regularily to make it update the 
3D view.
+     */
+    private static final class MyRepainter
+            implements Runnable
+    {
+
+        
//======================================================================
+        // Private Fields
+
+        private final Canvas myCanvas;
+
+        
//======================================================================
+        // Public Methods
+
+        
//----------------------------------------------------------------------
+        // Constructors
+
+        public MyRepainter( final Canvas canvas )
+        {
+            myCanvas = canvas;
+        }
+
+        
//----------------------------------------------------------------------
+        // Runnable Implementation
+
+        public void run()
+        {
+            while ( true )
+            {
+                myCanvas.repaint();
+
+                // TODO: Instead of sleeping a fixed amount, we could try to 
sleep some amount to maintain some maximum FPS.
+                try
+                {
+                    Thread.sleep( CANVAS_REPAINT_INTERVAL_MS );
+                }
+                catch ( InterruptedException e )
+                {
+                    // Ignore
+                }
+            }
+        }
+
+    }
+
+    /**
+     * A renderer that renders a 3D object in a 3D Canvas.
+     */
+    private final class MyCanvasRenderer
+            extends SimpleCanvasImpl
+    {
+
+        
//======================================================================
+        // Private Fields
+
+        private final Canvas myCanvas;
+
+        private final Runnable myFrameListenerUpdater = new Runnable()
+        {
+
+            public void run()
+            {
+                final double secondsSinceLastFrame = 
myFpsCounter.getSecondsBetweenFrames();
+                for ( FrameListener frameListener : myFrameListeners )
+                {
+                    frameListener.onFrame( secondsSinceLastFrame );
+                }
+            }
+
+        };
+
+        private Spatial myCanvasRootNode;
+        private boolean myAspectRatioNeedsCorrecting = true;
+
+        
//======================================================================
+        // Private Constants
+
+        private static final float DEFAULT_FIELD_OF_VIEW_DEGREES = 45;
+
+        
//======================================================================
+        // Public Methods
+
+        
//----------------------------------------------------------------------
+        // Constructors
+
+        /**
+         * Creates a new renderer that renders the specified spatial in a 3D 
canvas.
+         *
+         * @param width          initial size of the canvas.  Should be larger 
than 0.
+         * @param height         initial size of the canvas.  Should be larger 
than 0.
+         * @param canvasRootNode the 3D object to render.
+         *                       May be null, in which case nothing is 
rendered (black area)
+         * @param canvas         the canvas we are rendering to.  Needed for 
listening to resize events.
+         */
+        public MyCanvasRenderer( final int width,
+                                 final int height,
+                                 final Spatial canvasRootNode,
+                                 final Canvas canvas )
+        {
+            super( width, height );
+
+            ParameterChecker.checkPositiveNonZeroInteger( width, "width" );
+            ParameterChecker.checkPositiveNonZeroInteger( height, "height" );
+            ParameterChecker.checkNotNull( canvas, "canvas" );
+
+            myCanvasRootNode = canvasRootNode;
+            myCanvas = canvas;
+
+            // When the component is resized, adjust the size of the 3D 
viewport too.
+            myCanvas.addComponentListener( new ComponentAdapter()
+            {
+
+                public void componentResized( ComponentEvent ce )
+                {
+                    resizeCanvas( myCanvas.getWidth(), myCanvas.getHeight() );
+                    myAspectRatioNeedsCorrecting = true;
+                }
+
+            } );
+        }
+
+        
//----------------------------------------------------------------------
+        // Other Public Methods
+
+        /**
+         * @return the number of frames rendered per second,
+         *         or a negative value if the canvas has not yet been rendered.
+         */
+        public double getFramesPerSecond()
+        {
+            return myFpsCounter.getFramesPerSecond();
+        }
+
+
+        /**
+         * @return number of seconds between the previous frame and the frame 
before that,
+         *         or a negative value if the canvas has not yet been rendered.
+         */
+        public double getSecondsBetweenFrames()
+        {
+            return myFpsCounter.getSecondsBetweenFrames();
+        }
+
+
+        /**
+         * @param canvasRootNode the spatial to render with this 
CanvasRenderer.
+         *                       May be null, in which case nothing is 
rendered (black area)
+         */
+        public void setCanvasRootNode( final Spatial canvasRootNode )
+        {
+            if ( rootNode != null && myCanvasRootNode != null )
+            {
+                rootNode.detachChild( myCanvasRootNode );
+            }
+
+            myCanvasRootNode = canvasRootNode;
+
+            if ( rootNode != null && myCanvasRootNode != null )
+            {
+                rootNode.attachChild( myCanvasRootNode );
+            }
+        }
+
+
+        @Override
+        public void simpleSetup()
+        {
+            // Remove the back faces when rendering
+            // REFACTOR: Actually the terrain is backwards at the moment, the 
camera is 'under' it.  Flip it around at some point.
+            final CullState cullState = 
DisplaySystem.getDisplaySystem().getRenderer().createCullState();
+            cullState.setCullMode( CullState.CS_FRONT );
+            rootNode.setRenderState( cullState );
+
+
+            if ( myCanvasRootNode != null )
+            {
+                rootNode.attachChild( myCanvasRootNode );
+            }
+
+            getCamera().setFrustumFar( myViewDistance );
+        }
+
+
+        @Override
+        public void simpleUpdate()
+        {
+            myFpsCounter.onFrame();
+
+            if ( !myFrameListeners.isEmpty() )
+            {
+                SwingUtilities.invokeLater( myFrameListenerUpdater );
+            }
+        }
+
+
+        public void simpleRender()
+        {
+            // Setup aspect ratio for camera on the first frame (the camera is 
not created before the rendering starts)
+            if ( myAspectRatioNeedsCorrecting )
+            {
+                correctCameraAspectRatio();
+
+                myAspectRatioNeedsCorrecting = false;
+            }
+        }
+
+        
//======================================================================
+        // Private Methods
+
+        /**
+         * Sets the aspect ratio of the camera to the aspect ratio of the 
viewport size.
+         */
+        private void correctCameraAspectRatio()
+        {
+            final Renderer renderer = getRenderer();
+
+            if ( renderer != null )
+            {
+                // Get size on screen
+                final float height = renderer.getHeight();
+                final float width = renderer.getWidth();
+
+                // Calculate aspect ratio
+                float aspectRatio = 1;
+                if ( height > 0 )
+                {
+                    aspectRatio = width / height;
+                }
+
+                // Set aspect ratio and field of view to camera
+                final Camera camera = getCamera();
+                camera.setFrustumPerspective( DEFAULT_FIELD_OF_VIEW_DEGREES,
+                                              aspectRatio,
+                                              camera.getFrustumNear(),
+                                              camera.getFrustumFar() );
+            }
+        }
+
+    }
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/FrameListener.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/FrameListener.java
                            (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/FrameListener.java
    2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,20 @@
+package org.skycastle.opengl;
+
+
+/**
+ * A listener that is called for each frame that is rendered.
+ * The listener is called in the swing thread, so it can update the swing UI.
+ *
+ * @author Hans Haggstrom
+ */
+public interface FrameListener
+{
+
+    /**
+     * Called each frame, in the swing thread context.
+     *
+     * @param secondsSinceLastFrame number of seconds since the last frame, or 
a negative value if this is the first frame.
+     */
+    void onFrame( double secondsSinceLastFrame );
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/AbstractDragGesture.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/AbstractDragGesture.java
                           (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/AbstractDragGesture.java
   2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,115 @@
+package org.skycastle.opengl.navigationgestures;
+
+import com.jme.renderer.Camera;
+
+import java.awt.event.MouseEvent;
+
+/**
+ * Common functionality for gestures that involve listening to drags.
+ *
+ * @author Hans H�ggstr�m
+ */
+public abstract class AbstractDragGesture
+        extends AbstractNavigationGesture
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final int myButtonDownMask;
+    private final int myButton;
+
+    private int myOldX = 0;
+    private int myOldY = 0;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // MouseListener Implementation
+
+    @Override
+    public void mousePressed( final MouseEvent e )
+    {
+        if ( isMouseButtonPressed( e, myButtonDownMask ) )
+        {
+            myOldX = e.getX();
+            myOldY = e.getY();
+
+            getCursorChanger().setCursor( this, null );
+        }
+    }
+
+
+    @Override
+    public void mouseReleased( final MouseEvent e )
+    {
+        if ( e.getButton() == myButton )
+        {
+            getCursorChanger().resetCursor( this );
+        }
+    }
+
+    //----------------------------------------------------------------------
+    // MouseMotionListener Implementation
+
+    @Override
+    public void mouseDragged( final MouseEvent e )
+    {
+        if ( isMouseButtonPressed( e, myButtonDownMask ) )
+        {
+            final Camera camera = getCamera();
+            if ( camera != null )
+            {
+                // Calculate mouse movement
+                final int currentX = e.getX();
+                final int currentY = e.getY();
+                final int deltaXInt = currentX - myOldX;
+                final int deltaYInt = currentY - myOldY;
+
+                if ( deltaXInt != 0 || deltaYInt != 0 )
+                {
+                    final float deltaX = deltaXInt * getSensitivity();
+                    final float deltaY = deltaYInt * getSensitivity();
+
+                    // Do the drag bussiness logic
+                    applyDragGesture( camera, deltaX, deltaY );
+
+                    // Reset mouse position
+                    setMousePos( myOldX, myOldY );
+                }
+            }
+        }
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    //----------------------------------------------------------------------
+    // Protected Constructors
+
+    /**
+     * @param sensitivity    a sensitivity value for this gesture.
+     * @param button         button whose drags we should listen to.
+     * @param buttonDownMask the down mask for the button whose drags we 
should listen to.
+     */
+    protected AbstractDragGesture( final float sensitivity, final int button, 
final int buttonDownMask )
+    {
+        super( sensitivity );
+        myButton = button;
+        myButtonDownMask = buttonDownMask;
+    }
+
+    //----------------------------------------------------------------------
+    // Abstract Protected Methods
+
+    /**
+     * Called from the drag handling code.
+     *
+     * @param camera a reference to the camera
+     * @param deltaX the sensitivity scaled movement along the x axis of the 
mouse since the last call or the start of the gesture.
+     * @param deltaY the sensitivity scaled movement along the y axis of the 
mouse since the last call or the start of the gesture.
+     */
+    protected abstract void applyDragGesture( Camera camera, float deltaX, 
float deltaY );
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/AbstractNavigationGesture.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/AbstractNavigationGesture.java
                             (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/AbstractNavigationGesture.java
     2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,224 @@
+package org.skycastle.opengl.navigationgestures;
+
+import com.jme.math.Vector3f;
+import com.jme.renderer.Camera;
+import org.skycastle.util.cursor.CursorChanger;
+
+import javax.swing.event.MouseInputAdapter;
+import java.awt.AWTException;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+
+
+/**
+ * Contains common functionality for navigationGestureListeners.
+ *
+ * @author Hans H�ggstr�m
+ */
+public abstract class AbstractNavigationGesture
+        extends MouseInputAdapter
+        implements NavigationGesture
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final float mySensitivity;
+
+    private CameraAccessor myCameraAccessor = null;
+    private CursorChanger myCursorChanger = null;
+    private Robot myRobot = null;
+    private Component myComponent = null;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // MouseWheelListener Implementation
+
+    public void mouseWheelMoved( final MouseWheelEvent e )
+    {
+        // Override if needed
+    }
+
+    //----------------------------------------------------------------------
+    // NavigationGesture Implementation
+
+    public void init( final Component component,
+                      final CursorChanger cursorChanger,
+                      final CameraAccessor cameraAccessor )
+    {
+        setComponent( component );
+        setCursorChanger( cursorChanger );
+        setCameraAccessor( cameraAccessor );
+    }
+
+
+    public void deInit()
+    {
+        setComponent( null );
+        setCursorChanger( null );
+        setCameraAccessor( null );
+    }
+
+    //----------------------------------------------------------------------
+    // Other Public Methods
+
+    /**
+     * @return a scaling factor to apply to the gesture.
+     */
+    public final float getSensitivity()
+    {
+        return mySensitivity;
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    //----------------------------------------------------------------------
+    // Protected Constructors
+
+    protected AbstractNavigationGesture( final float sensitivity )
+    {
+        try
+        {
+            myRobot = new Robot();
+        }
+        catch ( AWTException e )
+        {
+            e.printStackTrace();
+        }
+
+        mySensitivity = sensitivity;
+    }
+
+    /**
+     * Moves the mouse position to the specified canvas coordinates
+     */
+    protected final void setMousePos( int x, int y )
+    {
+        final Point locationOnScreen = myComponent.getLocationOnScreen();
+        myRobot.mouseMove( locationOnScreen.x + x, locationOnScreen.y + y );
+    }
+
+
+    /**
+     * @return an interface that can be used to change the mouse cursor on the 
3D canvas we are rendering to (or hide it).
+     */
+    protected final CursorChanger getCursorChanger()
+    {
+        return myCursorChanger;
+    }
+
+
+    private void setCursorChanger( final CursorChanger cursorChanger )
+    {
+        if ( cursorChanger == null && myCursorChanger != null )
+        {
+            myCursorChanger.resetCursor( this );
+        }
+
+        myCursorChanger = cursorChanger;
+    }
+
+
+    /**
+     * @return the camera that has been assigned to this navigation gesture 
listener, or null if no camera has yet been assigned.
+     */
+    protected final Camera getCamera()
+    {
+        if ( myCameraAccessor != null )
+        {
+            return myCameraAccessor.getCamera();
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    /**
+     * @return a multiplication factor calculated from the altitude, used to 
adjust the move and pan operations.
+     */
+    protected final float getAltitudeFactor()
+    {
+        final Camera camera = getCamera();
+        if ( camera != null )
+        {
+            final float altitude = getAltitudeAt( camera.getLocation() );
+
+            // Less movement lower, more higher.  Use a non linear function 
(square root) of the altitude.
+            return (float) ( 0.4 * Math.sqrt( Math.abs( altitude ) ) + 0.01f );
+        }
+        else
+        {
+            return 1;
+        }
+    }
+
+
+    protected boolean isMouseButtonPressed( final MouseEvent e, final int 
buttonDownMask )
+    {
+        return ( e.getModifiersEx() & buttonDownMask ) != 0;
+    }
+
+    //======================================================================
+    // Private Methods
+
+    /**
+     * REFACTOR: Move to some terrain or map class and make public.
+     *
+     * @param location A location to calculate the altitude of.
+     *
+     * @return the altitude of the specified location above the ground.  The 
accuracy can be calculated relative to the altitude,
+     *         if the location is closer to the ground, higher accuracy is 
used than if it is further from the ground.
+     */
+    private float getAltitudeAt( final Vector3f location )
+    {
+        return location.z - getTerrainHeightAt( location );
+    }
+
+
+    /**
+     * REFACTOR: Move to some terrain or map class and make public.
+     *
+     * @param location some location in the world.  Usually only the x and y 
values are used, z is ignored.
+     *                 The z value can be used to determine the accuracy to 
calculate the terrain height at.  If the location is far above (or below) the 
ground,
+     *                 less accuracy is needed, while if it is close to the 
ground, greater accuracy is needed.
+     *
+     * @return the terrain height at the specified location.
+     */
+    private float getTerrainHeightAt( final Vector3f location )
+    {
+        // TODO: Get terrain height at the specified location
+        return (float) 0;
+    }
+
+
+    private void setComponent( final Component component )
+    {
+        if ( myComponent != null )
+        {
+            myComponent.removeMouseMotionListener( this );
+            myComponent.removeMouseListener( this );
+            myComponent.removeMouseWheelListener( this );
+        }
+
+        myComponent = component;
+
+        component.addMouseMotionListener( this );
+        component.addMouseListener( this );
+        component.addMouseWheelListener( this );
+    }
+
+
+    private void setCameraAccessor( final CameraAccessor cameraAccessor )
+    {
+        myCameraAccessor = cameraAccessor;
+    }
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/CameraAccessor.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/CameraAccessor.java
                                (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/CameraAccessor.java
        2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,18 @@
+package org.skycastle.opengl.navigationgestures;
+
+import com.jme.renderer.Camera;
+
+/**
+ * An interface that allows accessing the camera for a 3D view.
+ *
+ * @author Hans H�ggstr�m
+ */
+public interface CameraAccessor
+{
+
+    /**
+     * @return the camera for a 3D view.  Can be modified by calling camera 
modifying methods.
+     */
+    Camera getCamera();
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/MoveGesture.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/MoveGesture.java
                           (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/MoveGesture.java
   2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,54 @@
+package org.skycastle.opengl.navigationgestures;
+
+import com.jme.renderer.Camera;
+
+import java.awt.event.MouseWheelEvent;
+
+/**
+ * A gesture for moving forward or back.
+ * <p/>
+ * Move camera with W,S,A,D or arrow keys or scroll wheel (forward and back 
and strafes to the sides,
+ * acceleration is enabled (and a bit of inertia too for effect)).
+ * With scroll wheel, a few scrolls gives a small thrust, many scrolls leaves 
the thrust on.
+ * Scroll back to turn the thrust off again (and to thrust backwards).
+ * <p/>
+ * Also scale move amount by altitude.
+ *
+ * @author Hans H�ggstr�m
+ */
+public final class MoveGesture
+        extends AbstractNavigationGesture
+{
+
+    //======================================================================
+    // Private Constants
+
+    private static final float DEFAULT_MOVE_SENSITIVITY = 10.0f;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    public MoveGesture()
+    {
+        super( DEFAULT_MOVE_SENSITIVITY );
+    }
+
+    //----------------------------------------------------------------------
+    // MouseWheelListener Implementation
+
+    public void mouseWheelMoved( final MouseWheelEvent e )
+    {
+        final Camera camera = getCamera();
+
+        final float movementAmount = -e.getWheelRotation() * getSensitivity() 
* getAltitudeFactor();
+
+        // TODO: Implement inertia, acceleration, locked movement, and 
keyboard input
+
+        camera.getLocation().scaleAdd( movementAmount, camera.getDirection(), 
camera.getLocation() );
+        camera.onFrameChange();
+    }
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/NavigationGesture.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/NavigationGesture.java
                             (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/NavigationGesture.java
     2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,37 @@
+package org.skycastle.opengl.navigationgestures;
+
+
+import org.skycastle.util.cursor.CursorChanger;
+
+import javax.swing.event.MouseInputListener;
+import java.awt.Component;
+import java.awt.event.MouseWheelListener;
+
+/**
+ * An interface for handling navigation gestures done to the 3D view.
+ *
+ * @author Hans H�ggstr�m
+ */
+public interface NavigationGesture
+        extends MouseInputListener, MouseWheelListener
+{
+
+    /**
+     * Initializes the navigation gesture.
+     *
+     * @param component      the component that the gesture should listen to.  
Can be asked e.g. the size and position.
+     *                       Might also be used to add rubber band graphics or 
similar on top of the component
+     * @param cursorChanger  an interface that can be used to change the mouse 
cursor on the 3D canvas rendered to.
+     * @param cameraAccessor Can be asked for the camera that the navigation 
gesture listener should modify when gestures happen.
+     */
+    void init( Component component,
+               CursorChanger cursorChanger,
+               CameraAccessor cameraAccessor );
+
+    /**
+     * De-initializes the navigation gesture.  The navigation gesture should 
stop listening to the component, and should
+     * remove its cursor settings.
+     */
+    void deInit();
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/PanGesture.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/PanGesture.java
                            (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/PanGesture.java
    2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,59 @@
+package org.skycastle.opengl.navigationgestures;
+
+import com.jme.math.Vector3f;
+import com.jme.renderer.Camera;
+
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+
+/**
+ * Implements a panning gesture for the 3D renderer.
+ * <p/>
+ * Pan / move across map with left mouse button drag (will actually move 
camera along the left/right,
+ * up/down axes of the camera). (A single left mouse button click will select 
/ click on an item on map).
+ * The drag has some inertia, so a quick drag will move the camera faster than 
a slow one.
+ * The camera is kept above the ground level at all times though.
+ * <p/>
+ * Also scale pan amount by altitude.
+ *
+ * @author Hans H�ggstr�m
+ */
+public final class PanGesture
+        extends AbstractDragGesture
+{
+
+    //======================================================================
+    // Private Constants
+
+    private static final float DEFAULT_PAN_SENSITIVITY = 0.1f;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    public PanGesture()
+    {
+        super( DEFAULT_PAN_SENSITIVITY, MouseEvent.BUTTON3, 
InputEvent.BUTTON3_DOWN_MASK );
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    protected void applyDragGesture( final Camera camera, final float deltaX, 
final float deltaY )
+    {
+        final float altitudeFactor = getAltitudeFactor();
+
+        // TODO: Add inertia and acceleration
+        // TODO: Add ground collision detection and keep the camera above 
ground.
+
+        final Vector3f newLocation = new Vector3f( camera.getLocation() );
+
+        newLocation.scaleAdd( -deltaX * altitudeFactor, camera.getLeft(), 
newLocation );
+        newLocation.scaleAdd( -deltaY * altitudeFactor, camera.getUp(), 
newLocation );
+
+        camera.setLocation( newLocation );
+    }
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/RotateGesture.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/RotateGesture.java
                         (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/navigationgestures/RotateGesture.java
 2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,70 @@
+package org.skycastle.opengl.navigationgestures;
+
+import com.jme.math.Quaternion;
+import com.jme.math.Vector3f;
+import com.jme.renderer.Camera;
+
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+
+/**
+ * Turn camera using right mouse button drag (change yaw and pitch, pitch 
locked to avoid rolling to back,
+ * there could be a maximum angle to avoid getting lost looking at the sky) 
(cursor disappears while mouse pressed,
+ * relative movement is measured. Similar to first person view games). (A 
right mouse button click without drag will
+ * typically show a context menu for the feature under the mouse).
+ *
+ * @author Hans H�ggstr�m
+ */
+public final class RotateGesture
+        extends AbstractDragGesture
+{
+
+    //======================================================================
+    // Private Fields
+
+    private Quaternion myRotation = new Quaternion( 0, 0, 0, 1 );
+    private Quaternion myDirection = new Quaternion( 0, 0, 0, 1 );
+
+    //======================================================================
+    // Private Constants
+
+    private static final Vector3f Z_AXIS = new Vector3f( 0, 0, 1 );
+    private static final float DEFAULT_ROTATION_SENSITIVITY = 0.01f;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    public RotateGesture()
+    {
+        super( DEFAULT_ROTATION_SENSITIVITY, MouseEvent.BUTTON1, 
InputEvent.BUTTON1_DOWN_MASK );
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    protected void applyDragGesture( final Camera camera, final float deltaX, 
final float deltaY )
+    {
+        // Get quaternion from camera
+        final Vector3f left = camera.getLeft();
+        final Vector3f up = camera.getUp();
+        final Vector3f forward = camera.getDirection();
+        myDirection.fromAxes( left, up, forward );
+
+        // TODO: Block rotation so that it is not possible to turn upside down
+
+        // Apply rotation to around current position
+        myRotation.fromAngleNormalAxis( deltaY, left );
+        myRotation.mult( myDirection, myDirection );
+        myRotation.fromAngleNormalAxis( -deltaX, Z_AXIS );
+        myRotation.mult( myDirection, myDirection );
+
+        // Apply new direction to camera
+        camera.setAxes( myDirection );
+
+        // TODO: Stabilize the left, up, and forward vectors so that they stay 
orthogonal despite rotation rounding errors.
+    }
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/Sketch3DUI.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/Sketch3DUI.java   
                            (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/Sketch3DUI.java   
    2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,279 @@
+package org.skycastle.sketch;
+
+import com.jme.app.SimpleGame;
+import com.jme.bounding.BoundingBox;
+import com.jme.image.Texture;
+import com.jme.input.*;
+import com.jme.math.Vector3f;
+import com.jme.renderer.ColorRGBA;
+import com.jme.renderer.Renderer;
+import com.jme.scene.Controller;
+import com.jme.scene.Node;
+import com.jme.scene.SceneElement;
+import com.jme.scene.shape.Box;
+import com.jme.scene.state.LightState;
+import com.jme.scene.state.TextureState;
+import com.jme.util.TextureManager;
+import com.jmex.awt.swingui.JMEDesktop;
+
+import javax.swing.*;
+import javax.swing.plaf.basic.BasicInternalFrameUI;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Container;
+import java.beans.PropertyVetoException;
+import java.util.logging.Logger;
+
+/**
+ * OpenGL main loop for the sketch program.
+ *
+ * @author Hans Haggstrom
+ */
+@SuppressWarnings( { "MagicNumber" } )
+public class Sketch3DUI
+        extends SimpleGame
+{
+
+    //======================================================================
+    // Private Fields
+
+    /**
+     * Keyboard look input handler.
+     */
+    private KeyboardLookHandler lookHandler = null;
+
+    /**
+     * Scene node for the GUI.
+     */
+    private Node guiNode = null;
+
+    /**
+     * JME desktop on which the GUI will be shown.
+     */
+    private JMEDesktop desktop = null;
+
+    //======================================================================
+    // Non-Private Fields
+
+    /**
+     * The color to be used as background color for the desktop. This is 
completely transparent right now.
+     */
+    protected static final Color DESKTOP_BACKGROUND_COLOR = new Color( 0.5f, 
0.5f, 0.5f, 0.0f );
+
+    //======================================================================
+    // Private Constants
+
+    private static final Logger LOGGER = Logger.getLogger( 
Sketch3DUI.class.getName() );
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Other Public Methods
+
+    /**
+     * Set up key bindings.
+     */
+    public void initKeyBindings()
+    {
+        /* Remove some keybindings established by BaseSimpleGame, since they
+           are needed for chatting.
+           TODO: Find a more elegant solution. Maybe bind/rebind depending on
+                 focus, or handling these during update.
+                 Eventually, we may also need to implement our own base game
+                 class.
+         */
+        KeyBindingManager.getKeyBindingManager().remove( "toggle_pause" );
+        KeyBindingManager.getKeyBindingManager().remove( "step" );
+        KeyBindingManager.getKeyBindingManager().remove( "toggle_wire" );
+        KeyBindingManager.getKeyBindingManager().remove( "toggle_lights" );
+        KeyBindingManager.getKeyBindingManager().remove( "toggle_bounds" );
+        KeyBindingManager.getKeyBindingManager().remove( "toggle_normals" );
+        KeyBindingManager.getKeyBindingManager().remove( "camera_out" );
+        KeyBindingManager.getKeyBindingManager().remove( "mem_report" );
+
+        // Bind the BaseSimpleGame functions to other keys.
+        KeyBindingManager.getKeyBindingManager().set( "toggle_pause", 
KeyInput.KEY_F4 );
+        KeyBindingManager.getKeyBindingManager().set( "step", KeyInput.KEY_F5 
);
+        KeyBindingManager.getKeyBindingManager().set( "toggle_wire", 
KeyInput.KEY_F6 );
+        KeyBindingManager.getKeyBindingManager().set( "toggle_lights", 
KeyInput.KEY_F7 );
+        KeyBindingManager.getKeyBindingManager().set( "toggle_bounds", 
KeyInput.KEY_F8 );
+        KeyBindingManager.getKeyBindingManager().set( "toggle_normals", 
KeyInput.KEY_F9 );
+        KeyBindingManager.getKeyBindingManager().set( "camera_out", 
KeyInput.KEY_F10 );
+        KeyBindingManager.getKeyBindingManager().set( "mem_report", 
KeyInput.KEY_F11 );
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    /**
+     * Create the UI. Create the elements of the Swing UI.
+     */
+    protected void initUI()
+    {
+        /// JME part of the GUI creation.
+        guiNode = new Node( "gui" );
+        guiNode.setRenderQueueMode( Renderer.QUEUE_ORTHO );
+
+        desktop = new JMEDesktop(
+                "desktop",
+                display.getWidth(),
+                display.getHeight(),
+                input
+        );
+        guiNode.attachChild( desktop );
+        desktop.getLocalTranslation().set(
+                display.getWidth() / 2.0f,
+                display.getHeight() / 2.0f, 0
+        );
+
+        // AWT/Swing part of the GUI creation.
+        desktop.getJDesktop().setBackground( DESKTOP_BACKGROUND_COLOR );
+
+
+        JInternalFrame toolFrame = new JInternalFrame();
+//        toolFrame.setLocation( 10, 10 );
+//        toolFrame.setResizable( true );
+
+        toolFrame.setOpaque( false );
+        Container contentPane = toolFrame.getContentPane();
+        contentPane.setLayout( new BorderLayout() );
+        contentPane.setBackground( new Color( 0, 0, 0, 0 ) );
+
+        contentPane.add( new JLabel( "foo" ), BorderLayout.EAST );
+        contentPane.add( createNorthPanel(), BorderLayout.NORTH );
+
+        toolFrame.setBorder( BorderFactory.createEmptyBorder() );
+        toolFrame.setTitle( null );
+
+        toolFrame.setVisible( true );
+        toolFrame.pack();
+
+        final BasicInternalFrameUI basicInternalFrameUI = 
(BasicInternalFrameUI) toolFrame.getUI();
+        basicInternalFrameUI.setNorthPane( null );
+
+        desktop.getJDesktop().add( toolFrame );
+
+/*
+        toolFrame.putClientProperty(  );
+
+        a) internalFrame.putClientProperty("JInternalFrame.isPalette", 
Boolean.TRUE);
+*/
+
+/*
+        final JLabel jLabel = new JLabel( "fooo" );
+
+        jLabel.setForeground( Color.WHITE );
+        jDesktopPane.setLayout( new BorderLayout() );
+        jDesktopPane.add( jLabel, BorderLayout.CENTER );
+*/
+        try
+        {
+            toolFrame.setMaximum( true );
+        }
+        catch ( PropertyVetoException e )
+        {
+            e.printStackTrace();
+        }
+    }
+
+    private JComponent createNorthPanel()
+    {
+        SketchUi sketchUi = new SketchUi();
+        return sketchUi.createToolbar();
+    }
+
+
+    /**
+     * Create the 3D scene. In this case, this is just the rotating box.
+     */
+    protected void create3DScene()
+    {
+        final Vector3f axis = new Vector3f( 1, 1, 0.5f ).normalizeLocal();
+        final Box box = new Box( "Box",
+                                 new Vector3f( -5, -5, -5 ),
+                                 new Vector3f( 5, 5, 5 ) );
+
+        box.setModelBound( new BoundingBox() );
+        box.updateModelBound();
+        box.setLocalTranslation( new Vector3f( 0, 0, -10 ) );
+        box.setLightCombineMode( LightState.OFF );
+
+        TextureState ts = display.getRenderer().createTextureState();
+        ts.setEnabled( true );
+        ts.setTexture( TextureManager.loadTexture(
+                Sketch3DUI.class.getClassLoader().getResource(
+                        "org/skycastle/client/data/skycastle.png" ),
+                Texture.MM_LINEAR,
+                Texture.FM_LINEAR )
+        );
+        box.setRenderState( ts );
+        box.addController(
+                // Controller which rotates the box.
+                new Controller()
+                {
+
+                    private static final long serialVersionUID = 1L;
+
+                    @Override
+                    public void update( float time )
+                    {
+                        box.getLocalRotation().fromAngleNormalAxis(
+                                timer.getTimeInSeconds(), axis );
+                    }
+
+                }
+        );
+
+        rootNode.attachChild( box );
+    }
+
+
+    /**
+     * Initialize game. Overridden from SimpleGame.
+     */
+    @Override
+    protected void simpleInitGame()
+    {
+        display.setTitle( "Skycastle 3D Client" );
+        display.getRenderer().setBackgroundColor( ColorRGBA.black );
+
+        // Set up the keyboard look handler.
+        input = new InputHandler();
+        lookHandler = new KeyboardLookHandler( cam, 50, 1 );
+        input.addToAttachedHandlers( lookHandler );
+        // Some changes to the BaseSimpleGame keyboard bindings.
+        initKeyBindings();
+
+        // Set up GUI, static 3D scene and chat client.
+        initUI();
+        create3DScene();
+
+        // Always show the the GUI.
+        guiNode.setCullMode( SceneElement.CULL_NEVER );
+        guiNode.setLightCombineMode( LightState.OFF );
+        guiNode.updateRenderState();
+        guiNode.updateGeometricState( 0, true );
+        MouseInput.get().setCursorVisible( true );
+    }
+
+
+    /**
+     * Update hook. Overridden from SimpleGame.
+     */
+    @Override
+    protected void simpleUpdate()
+    {
+    }
+
+
+    /**
+     * Render hook. Overridden from SimpleGame.
+     */
+    @Override
+    protected void simpleRender()
+    {
+        display.getRenderer().draw( guiNode );
+    }
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchUi.java
===================================================================
--- trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchUi.java 
                        (rev 0)
+++ trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchUi.java 
2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,60 @@
+package org.skycastle.sketch;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+
+/**
+ * @author Hans Haggstrom
+ */
+public class SketchUi
+{
+
+    public JToolBar createToolbar()
+    {
+        final JToolBar toolBar = new JToolBar();
+        toolBar.add( new JButton( new AbstractAction( "Quit" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+                System.exit( 0 );
+            }
+
+        } ) );
+        toolBar.add( new JButton( new AbstractAction( "New Page" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+            }
+
+        } ) );
+        toolBar.add( new JButton( new AbstractAction( "Zoom Out" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+            }
+
+        } ) );
+        toolBar.add( new JButton( new AbstractAction( "Zoom In" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+            }
+
+        } ) );
+        toolBar.add( new JButton( new AbstractAction( "Zoom to show all" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+            }
+
+        } ) );
+
+        toolBar.setVisible( true );
+        return toolBar;
+    }
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java
                          (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java
  2008-04-26 09:07:22 UTC (rev 472)
@@ -0,0 +1,124 @@
+package org.skycastle.sketch;
+
+import com.jme.bounding.BoundingBox;
+import com.jme.math.Vector3f;
+import com.jme.scene.Controller;
+import com.jme.scene.Spatial;
+import com.jme.scene.shape.Box;
+import com.jme.scene.state.LightState;
+import org.skycastle.opengl.Canvas3D;
+import org.skycastle.util.simpleui.SimpleFrame;
+
+import javax.swing.*;
+import java.awt.BorderLayout;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A simple sketch program, supporting a pen tablet as input, and running in 
opengl.
+ *
+ * @author Hans Haggstrom
+ */
+public class SkycastleSketch
+{
+
+    //======================================================================
+    // Private Fields
+
+    private static float myBoxRotationCounter = 0;
+
+    //======================================================================
+    // Private Constants
+
+    private static final Logger LOGGER = Logger.getLogger( 
SkycastleSketch.class.getName() );
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Main Method
+
+    /**
+     * Start everything.
+     */
+    public static void main( String[] args )
+    {
+        LOGGER.log( Level.INFO, "Skycastle Sketch starting up." );
+
+        // Do not show logging output below the WARNING level (JME outputs a 
lot of debugging info at INFO level).
+        // This way the console output is a bit more relevant.
+        LOGGER.setLevel( Level.WARNING );
+
+
+        Canvas3D canvas3D = new Canvas3D();
+
+        SketchUi sketchUi = new SketchUi();
+
+        JPanel panel = new JPanel( new BorderLayout() );
+        panel.add( canvas3D.get3DView(), BorderLayout.CENTER );
+        panel.add( sketchUi.createToolbar(), BorderLayout.NORTH );
+
+        new SimpleFrame( panel );
+
+        canvas3D.set3DNode( create3DScene() );
+
+/*
+        Sketch3DUI sketch3DUI = new Sketch3DUI();
+        sketch3DUI.start();
+*/
+    }
+
+    //======================================================================
+    // Private Methods
+
+    /**
+     * Create the 3D scene. In this case, this is just the rotating box.
+     */
+    private static Spatial create3DScene()
+    {
+        final Vector3f axis = new Vector3f( 1, 1, 0.5f ).normalizeLocal();
+        final Box box = new Box( "Box",
+                                 new Vector3f( 5, 5, 5 ),
+                                 new Vector3f( -5, -5, -5 ) );
+
+        box.setModelBound( new BoundingBox() );
+        box.updateModelBound();
+        box.setLocalTranslation( new Vector3f( 0, 0, -10 ) );
+        box.setLightCombineMode( LightState.OFF );
+
+        box.setRandomColors();
+
+/*
+        TextureState ts = 
DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
+        ts.setEnabled( true );
+        ts.setTexture( TextureManager.loadTexture(
+                Sketch3DUI.class.getClassLoader().getResource(
+                        "org/skycastle/client/data/skycastle.png" ),
+                Texture.MM_LINEAR,
+                Texture.FM_LINEAR )
+        );
+        box.setRenderState( ts );
+*/
+
+        box.addController(
+                // Controller which rotates the box.
+                new Controller()
+                {
+
+                    private static final long serialVersionUID = 1L;
+
+                    @Override
+                    public void update( float time )
+                    {
+                        myBoxRotationCounter += time;
+                        box.getLocalRotation().fromAngleNormalAxis(
+                                myBoxRotationCounter, axis );
+                    }
+
+                }
+        );
+
+        return box;
+    }
+
+}


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

Other related posts:

  • » [skycastle-commits] SF.net SVN: skycastle: [472] trunk/skycastle/modules/ui/src/main/java/org/ skycastle