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

  • From: zzorn@xxxxxxxxxxxxxxxxxxxxx
  • To: skycastle-commits@xxxxxxxxxxxxx
  • Date: Wed, 30 Apr 2008 05:49:31 -0700

Revision: 502
          http://skycastle.svn.sourceforge.net/skycastle/?rev=502&view=rev
Author:   zzorn
Date:     2008-04-30 05:49:30 -0700 (Wed, 30 Apr 2008)

Log Message:
-----------
Preliminary work on a render to texture approach for buffering brush strokes.  
However, looks like my laptop doesn't support render to texture, need to try it 
out on the desktop.

I wonder if there is any way to solve the problem without render to texture?

Modified Paths:
--------------
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/Canvas3D.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/CanvasInitializer.java
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/JmeUtils.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchController.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java

Added Paths:
-----------
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/BufferedScreen.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/DummyBufferedScreen.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchRenderer.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchRoom.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/TextureBufferedScreen.java
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/input/
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/input/InputHandler.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/input/PenInputHandler.java

Removed Paths:
-------------
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/InputHandler.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/PenInputHandler.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/Canvas3D.java
===================================================================
--- trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/Canvas3D.java 
2008-04-29 21:42:09 UTC (rev 501)
+++ trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/Canvas3D.java 
2008-04-30 12:49:30 UTC (rev 502)
@@ -422,13 +422,13 @@
     }
 
 
-    private void runInitializers( final Renderer renderer )
+    private void runInitializers( final DisplaySystem displaySystem )
     {
         myInitialized = true;
 
         for ( final CanvasInitializer initializer : myInitializers )
         {
-            initializer.initialize( this, renderer );
+            initializer.initialize( this, displaySystem );
         }
 
         myInitializers.clear();
@@ -629,7 +629,8 @@
                 SwingUtilities.invokeLater( myFrameListenerUpdater );
             }
 
-            runInitializers( getRenderer() );
+            // TODO: Is this the correct display system?
+            runInitializers( DisplaySystem.getDisplaySystem() );
         }
 
 

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/CanvasInitializer.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/CanvasInitializer.java
        2008-04-29 21:42:09 UTC (rev 501)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/CanvasInitializer.java
        2008-04-30 12:49:30 UTC (rev 502)
@@ -1,6 +1,6 @@
 package org.skycastle.opengl;
 
-import com.jme.renderer.Renderer;
+import com.jme.system.DisplaySystem;
 
 /**
  * Something that gets called when the {@link Canvas3D} is initialized.
@@ -15,8 +15,8 @@
      * <p/>
      * Do not assume that this is called in the swing thread.
      *
-     * @param canvas3D the {@link Canvas3D} that has been initialized.
-     * @param renderer the 3D {@link Renderer} of the canvas.
+     * @param canvas3D      the {@link org.skycastle.opengl.Canvas3D} that has 
been initialized.
+     * @param displaySystem
      */
-    void initialize( final Canvas3D canvas3D, final Renderer renderer );
+    void initialize( final Canvas3D canvas3D, final DisplaySystem 
displaySystem );
 }

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/JmeUtils.java
===================================================================
--- trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/JmeUtils.java 
2008-04-29 21:42:09 UTC (rev 501)
+++ trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/JmeUtils.java 
2008-04-30 12:49:30 UTC (rev 502)
@@ -1,5 +1,7 @@
 package org.skycastle.opengl;
 
+import com.jme.math.Vector3f;
+import com.jme.renderer.Camera;
 import com.jme.renderer.ColorRGBA;
 import com.jme.renderer.Renderer;
 import com.jme.scene.Spatial;
@@ -77,6 +79,30 @@
         spatial.setRenderQueueMode( Renderer.QUEUE_TRANSPARENT );
     }
 
+    /**
+     * Copies the position, angle, frustrum, and parallel and plane states 
from the source to the target camera.
+     *
+     * @param sourceCamera camera to copy settings from
+     * @param targetCamera camera whose settings should be changed.
+     */
+    public static void copyCameraSettings( final Camera sourceCamera, final 
Camera targetCamera )
+    {
+        targetCamera.setParallelProjection( 
sourceCamera.isParallelProjection() );
+        targetCamera.setPlaneState( sourceCamera.getPlaneState() );
+
+        targetCamera.setLocation( new Vector3f( sourceCamera.getLocation() ) );
+        targetCamera.setUp( new Vector3f( sourceCamera.getUp() ) );
+        targetCamera.setLeft( new Vector3f( sourceCamera.getLeft() ) );
+        targetCamera.setDirection( new Vector3f( sourceCamera.getDirection() ) 
);
+
+        targetCamera.setFrustumFar( sourceCamera.getFrustumFar() );
+        targetCamera.setFrustumNear( sourceCamera.getFrustumNear() );
+        targetCamera.setFrustumLeft( sourceCamera.getFrustumLeft() );
+        targetCamera.setFrustumRight( sourceCamera.getFrustumRight() );
+        targetCamera.setFrustumTop( sourceCamera.getFrustumTop() );
+        targetCamera.setFrustumBottom( sourceCamera.getFrustumBottom() );
+    }
+
     //======================================================================
     // Private Methods
 

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/BufferedScreen.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/BufferedScreen.java
                           (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/BufferedScreen.java
   2008-04-30 12:49:30 UTC (rev 502)
@@ -0,0 +1,24 @@
+package org.skycastle.sketch;
+
+import com.jme.scene.Spatial;
+import com.jme.system.DisplaySystem;
+import org.skycastle.sketch.model.group.GroupElement;
+
+/**
+ * Holds a screen sized (+margin) texture, that can be used to render {@link 
GroupElement}s to.
+ *
+ * @author Hans Haggstrom
+ */
+public interface BufferedScreen
+{
+    /**
+     * @param spatial a 3D object to render to the buffer.
+     */
+    void renderElement( Spatial spatial );
+
+    /**
+     * @return a 3D object with a view of the buffer.
+     */
+    Spatial get3DView( DisplaySystem displaySystem );
+
+}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/DummyBufferedScreen.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/DummyBufferedScreen.java
                              (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/DummyBufferedScreen.java
      2008-04-30 12:49:30 UTC (rev 502)
@@ -0,0 +1,54 @@
+package org.skycastle.sketch;
+
+import com.jme.scene.Node;
+import com.jme.scene.Spatial;
+import com.jme.system.DisplaySystem;
+
+/**
+ * An implementation of {@link BufferedScreen} that just keeps the rendered 
elements in a {@link com.jme.scene.Node},
+ * instead of rendering them to a buffer.
+ * <p/>
+ * Allows working on the rest of the logic around the rende
+ * ring.
+ *
+ * @author Hans Haggstrom
+ */
+public final class DummyBufferedScreen
+        implements BufferedScreen
+{
+
+    //======================================================================
+    // Private Fields
+
+    private Node myNode = null;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // BufferedScreen Implementation
+
+    public void renderElement( final Spatial spatial )
+    {
+        getOrCreateNode().attachChild( spatial );
+    }
+
+    public Spatial get3DView( DisplaySystem displaySystem )
+    {
+        return getOrCreateNode();
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private Node getOrCreateNode()
+    {
+        if ( myNode == null )
+        {
+            myNode = new Node();
+        }
+
+        return myNode;
+    }
+
+}

Deleted: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/InputHandler.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/InputHandler.java 
    2008-04-29 21:42:09 UTC (rev 501)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/InputHandler.java 
    2008-04-30 12:49:30 UTC (rev 502)
@@ -1,208 +0,0 @@
-package org.skycastle.sketch;
-
-import jpen.PenManager;
-import org.skycastle.sketch.Tools.Tool;
-import org.skycastle.sketch.sample.DataSample;
-import org.skycastle.sketch.sample.SampleListener;
-import org.skycastle.util.ParameterChecker;
-
-import javax.swing.*;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * @author Hans Haggstrom
- */
-public final class InputHandler
-{
-
-    //======================================================================
-    // Private Fields
-
-    private final SketchController mySketchController;
-    private final List<Tool> myTools = new ArrayList<Tool>();
-    private final PenInputHandler myPenInputHandler = new PenInputHandler();
-    private final BlockingQueue<DataSample> myQueuedInput = new 
ArrayBlockingQueue<DataSample>(
-            MAX_INPUT_EVENT_QUEUE );
-
-    /**
-     * Recieves input in the pen input thread, and just queues it in a 
syncronized storage for processing in
-     * the Swing thread.
-     */
-    private final SampleListener myInputReciever = new SampleListener()
-    {
-
-        public void onSample( final DataSample dataSample )
-        {
-            try
-            {
-                myQueuedInput.put( dataSample );
-            }
-            catch ( InterruptedException e )
-            {
-                // Interrupted, just return.  The sample is lost, but it 
doesn't matter that much.
-            }
-        }
-
-
-        public void onSamples( final List<DataSample> dataSamples )
-        {
-            // There's no putAll method, so just put the samples one at a time.
-            for ( final DataSample dataSample : dataSamples )
-            {
-                onSample( dataSample );
-            }
-        }
-
-    };
-
-    //======================================================================
-    // Private Constants
-
-    private static final Logger LOGGER = Logger.getLogger( 
InputHandler.class.getName() );
-    private static final int MAX_INPUT_EVENT_QUEUE = 10000;
-    private static final int MAX_SAMPLES_TO_HANDLE_AT_ONCE = 100;
-
-    //======================================================================
-    // Public Methods
-
-    //----------------------------------------------------------------------
-    // Constructors
-
-    /**
-     * Creates a new {@link org.skycastle.sketch.InputHandler}.
-     */
-    public InputHandler( final PenManager penManager, final SketchController 
sketchController )
-    {
-        mySketchController = sketchController;
-        ParameterChecker.checkNotNull( penManager, "penManager" );
-
-        // Listen to projection changes
-        sketchController.getView().addProjectionChangeListener( 
myPenInputHandler );
-
-        // Convert pen events to DataSamples
-        penManager.pen.addListener( myPenInputHandler );
-
-        // Queue the DataSamples
-        myPenInputHandler.addListener( myInputReciever );
-
-        // Handle DataSamples in the queue with tools that run in the swing 
thread
-        final Thread sampleMover = new Thread( new Runnable()
-        {
-
-            public void run()
-            {
-                final List<DataSample> samples = new ArrayList<DataSample>();
-
-                //noinspection InfiniteLoopStatement
-                while ( true )
-                {
-                    // Get next samples
-                    waitForSamples( samples );
-
-                    // Handle the samples in the Swing thread.  Blocks until 
ready
-                    invokeToolsInSwingThread( samples );
-
-                    // Reuse collection.
-                    samples.clear();
-                }
-            }
-
-        } );
-
-        sampleMover.start();
-    }
-
-    //----------------------------------------------------------------------
-    // Other Public Methods
-
-    /**
-     * Adds the specified Tool.
-     *
-     * @param addedTool should not be null or already added.
-     */
-    public void addTool( final Tool addedTool )
-    {
-        ParameterChecker.checkNotNull( addedTool, "addedTool" );
-        ParameterChecker.checkNotAlreadyContained( addedTool, myTools, 
"myTools" );
-
-        myTools.add( addedTool );
-    }
-
-
-    /**
-     * Removes the specified Tool.
-     *
-     * @param removedTool should not be null, and should be present.
-     */
-    public void removeTool( final Tool removedTool )
-    {
-        ParameterChecker.checkNotNull( removedTool, "removedTool" );
-        ParameterChecker.checkContained( removedTool, myTools, "myTools" );
-
-        myTools.remove( removedTool );
-    }
-
-    //======================================================================
-    // Private Methods
-
-    private void invokeToolsInSwingThread( final List<DataSample> samples )
-    {
-        try
-        {
-            SwingUtilities.invokeAndWait( new Runnable()
-            {
-
-                public void run()
-                {
-                    for ( final DataSample dataSample : samples )
-                    {
-                        // Let each tool handle each sample
-                        for ( final Tool tool : myTools )
-                        {
-                            tool.onEvent( dataSample, mySketchController );
-                        }
-                    }
-                }
-
-            } );
-        }
-        catch ( InterruptedException e )
-        {
-            LOGGER.log( Level.INFO, "Interrupted while handling input events", 
e );
-        }
-        catch ( InvocationTargetException e )
-        {
-            LOGGER.log( Level.WARNING, "Problem when handling input events", e 
);
-        }
-    }
-
-
-    private void waitForSamples( final List<DataSample> samples )
-    {
-        // Wait for first sample
-        DataSample dataSample = null;
-        try
-        {
-            dataSample = myQueuedInput.take();
-        }
-        catch ( InterruptedException e )
-        {
-            // We were interrupted, didn't get anything.
-        }
-
-        if ( dataSample != null )
-        {
-            samples.add( dataSample );
-        }
-
-        // Get the rest of the available samples
-        myQueuedInput.drainTo( samples, MAX_SAMPLES_TO_HANDLE_AT_ONCE );
-    }
-
-}

Deleted: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/PenInputHandler.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/PenInputHandler.java
  2008-04-29 21:42:09 UTC (rev 501)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/PenInputHandler.java
  2008-04-30 12:49:30 UTC (rev 502)
@@ -1,159 +0,0 @@
-package org.skycastle.sketch;
-
-import jpen.*;
-import jpen.event.PenListener;
-import org.skycastle.sketch.sample.AbstractSampleProducer;
-import org.skycastle.sketch.sample.DataSample;
-
-/**
- * Recieves pen events, and turns them into {@link DataSample} based events.
- *
- * @author Hans Haggstrom
- */
-@SuppressWarnings( { "ParameterNameDiffersFromOverriddenParameter" } )
-public final class PenInputHandler
-        extends AbstractSampleProducer
-        implements PenListener, ProjectionChangeListener
-{
-
-    //======================================================================
-    // Private Fields
-
-    private final Object myProjectionLock = new Object();
-
-    private float myXOffs = 0;
-    private float myYOffs = 0;
-    private float myXScale = 1;
-    private float myYScale = 1;
-
-    //======================================================================
-    // Public Methods
-
-    //----------------------------------------------------------------------
-    // Constructors
-
-    /**
-     * Creates a new {@link PenInputHandler}.
-     */
-    public PenInputHandler()
-    {
-    }
-
-    //----------------------------------------------------------------------
-    // ProjectionChangeListener Implementation
-
-
-    public void onProjectionChanged( final float xOffs,
-                                     final float yOffs,
-                                     final float xScale,
-                                     final float yScale )
-    {
-        synchronized ( myProjectionLock )
-        {
-            myXOffs = xOffs;
-            myYOffs = yOffs;
-            myXScale = xScale;
-            myYScale = yScale;
-        }
-    }
-
-    //----------------------------------------------------------------------
-    // PenListener Implementation
-
-    public void penKindEvent( final PKindEvent ev )
-    {
-        // Ignored for now
-    }
-
-
-    public void penLevelEvent( final PLevelEvent event )
-    {
-        final DataSample dataSample = new DataSample();
-
-        dataSample.setVariable( "time", getTimeAsSeconds( event ) );
-
-        for ( final PLevel level : event.levels )
-        {
-            final float value = level.value;
-            switch ( level.getType() )
-            {
-                case X:
-                    synchronized ( myProjectionLock )
-                    {
-                        final float x = value * myXScale + myXOffs;
-                        dataSample.setVariable( "x", x );
-                    }
-                    break;
-                case Y:
-                    synchronized ( myProjectionLock )
-                    {
-                        final float y = value * myYScale + myYOffs;
-                        dataSample.setVariable( "y", y );
-                    }
-                    break;
-                case PRESSURE:
-                    dataSample.setVariable( "pressure", value );
-                    break;
-                case TILT_X:
-                    dataSample.setVariable( "tiltX", value );
-                    break;
-                case TILT_Y:
-                    dataSample.setVariable( "tiltY", value );
-                    break;
-            }
-        }
-
-        sendSample( dataSample );
-    }
-
-
-    @Override
-    public void penButtonEvent( final PButtonEvent event )
-    {
-        final DataSample dataSample = new DataSample();
-
-        dataSample.setVariable( "time", getTimeAsSeconds( event ) );
-
-        final float value = event.button.value ? 1 : 0;
-
-        switch ( event.button.getType() )
-        {
-            case CENTER:
-                dataSample.setVariable( "centerButton", value );
-                break;
-
-            case LEFT:
-                dataSample.setVariable( "leftButton", value );
-                break;
-
-            case RIGHT:
-                dataSample.setVariable( "rightButton", value );
-                break;
-        }
-
-        sendSample( dataSample );
-    }
-
-
-    public void penScrollEvent( final PScrollEvent ev )
-    {
-        // Ignored for now
-    }
-
-
-    public void penTock( final long availableMillis )
-    {
-        // TODO: If this goes towards zero, it means our listeners are taking 
up too much time.
-        // Reduce amount of messages?
-    }
-
-    //======================================================================
-    // Private Methods
-
-    private float getTimeAsSeconds( final PenEvent event )
-    {
-        // Convert timestamp to seconds
-        return ( 1.0f * event.getTime() ) / 1000.0f;
-    }
-
-}

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchController.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchController.java
 2008-04-29 21:42:09 UTC (rev 501)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchController.java
 2008-04-30 12:49:30 UTC (rev 502)
@@ -1,6 +1,7 @@
 package org.skycastle.sketch;
 
 import org.skycastle.sketch.Tools.StrokeTool;
+import org.skycastle.sketch.input.InputHandler;
 import org.skycastle.sketch.model.Sketch;
 import org.skycastle.sketch.model.SketchImpl;
 import org.skycastle.sketch.model.group.Group;

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchRenderer.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchRenderer.java
                           (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchRenderer.java
   2008-04-30 12:49:30 UTC (rev 502)
@@ -0,0 +1,136 @@
+package org.skycastle.sketch;
+
+import com.jme.scene.Spatial;
+import com.jme.system.DisplaySystem;
+import org.skycastle.sketch.model.Sketch;
+import org.skycastle.sketch.model.group.Group;
+import org.skycastle.sketch.model.group.GroupElement;
+import org.skycastle.sketch.model.stroke.Stroke;
+import org.skycastle.sketch.rendering.StrokePartRenderer;
+import org.skycastle.util.listenable.collection.CollectionListener;
+import org.skycastle.util.listenable.collection.ListenableCollection;
+
+/**
+ * Provides a renderer for a {@link Sketch}.
+ *
+ * @author Hans Haggstrom
+ */
+public final class SketchRenderer
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final CollectionListener<GroupElement> mySketchListener = 
createSketchListener();
+    private final BufferedScreen myBufferedScreen = new 
TextureBufferedScreen();
+
+    private Sketch mySketch = null;
+    private Spatial myRenderer = null;
+
+    //======================================================================
+    // Public Methods
+
+    public Sketch getSketch()
+    {
+        return mySketch;
+    }
+
+    public void setSketch( final Sketch sketch )
+    {
+        if ( mySketch != null )
+        {
+            mySketch.getRootGroup().removeGroupListener( mySketchListener );
+        }
+
+        mySketch = sketch;
+
+        if ( mySketch != null )
+        {
+            mySketch.getRootGroup().addGroupListener( mySketchListener );
+        }
+
+        redraw();
+    }
+
+    /**
+     * @return a {@link Spatial} that can be used to render the {@link 
SketchRoom}.
+     */
+    public Spatial getRenderer( DisplaySystem displaySystem )
+    {
+        if ( myRenderer == null )
+        {
+            myRenderer = createRenderer( displaySystem );
+        }
+
+        return myRenderer;
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private CollectionListener<GroupElement> createSketchListener()
+    {
+        //noinspection serial
+        return new CollectionListener<GroupElement>()
+        {
+
+            public void onElementAdded( final 
ListenableCollection<GroupElement> groupElementListenableCollection, final 
GroupElement addedElement )
+            {
+                handleElementAddition( addedElement );
+            }
+
+            public void onElementRemoved( final 
ListenableCollection<GroupElement> groupElementListenableCollection,
+                                          final GroupElement removedElement )
+            {
+                redraw();
+            }
+
+        };
+    }
+
+    private void redraw()
+    {
+        if ( myRenderer != null )
+        {
+            // TODO
+
+        }
+    }
+
+    private Spatial createRenderer( DisplaySystem displaySystem )
+    {
+        return myBufferedScreen.get3DView( displaySystem );
+    }
+
+    private void handleElementAddition( final GroupElement addedElement )
+    {
+        // If the element is still actively changing, show it on top of the bg 
bitmap,
+        // and add a listener that notifies when it is ready
+        // If the element is ready (and when it is noted as ready),
+        // merge it into the bg bitmap
+
+
+        if ( addedElement instanceof Stroke )
+        {
+            // TODO: If the stroke is unfinished, keep it in a separate buffer 
until finisehd
+            // Put that logic in the buffer
+
+            Stroke stroke = (Stroke) addedElement;
+
+            final StrokePartRenderer strokePartRenderer = new 
StrokePartRenderer( 1000 );
+            strokePartRenderer.setStroke( stroke, 0 );
+
+            myBufferedScreen.renderElement( strokePartRenderer );
+        }
+        else if ( addedElement instanceof Group )
+        {
+            Group group = (Group) addedElement;
+
+            for ( GroupElement groupElement : group.getElements() )
+            {
+                handleElementAddition( groupElement );
+            }
+        }
+    }
+
+}

Copied: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchRoom.java 
(from rev 501, 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java)
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchRoom.java   
                            (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchRoom.java   
    2008-04-30 12:49:30 UTC (rev 502)
@@ -0,0 +1,35 @@
+package org.skycastle.sketch;
+
+/**
+ * A simple sketch program, supporting a pen tablet as input, and running in 
opengl.
+ *
+ * @author Hans Haggstrom
+ */
+public final class SketchRoom
+{
+
+    //----------------------------------------------------------------------
+    // Main Method
+
+    /**
+     * Start everything.
+     */
+    public static void main( String[] args )
+    {
+        // TODO: 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.
+
+
+        final SketchController sketchController = new SketchController();
+
+        sketchController.start();
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private SketchRoom()
+    {
+    }
+
+}

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java   
    2008-04-29 21:42:09 UTC (rev 501)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java   
    2008-04-30 12:49:30 UTC (rev 502)
@@ -3,21 +3,14 @@
 import com.jme.math.FastMath;
 import com.jme.math.Vector3f;
 import com.jme.renderer.Camera;
-import com.jme.renderer.Renderer;
-import com.jme.scene.Node;
+import com.jme.system.DisplaySystem;
 import jpen.PenManager;
 import org.skycastle.opengl.Canvas3D;
 import org.skycastle.opengl.CanvasInitializer;
 import org.skycastle.opengl.ResizeHandler;
 import org.skycastle.opengl.navigationgestures.NavigationGesture;
 import org.skycastle.sketch.model.Sketch;
-import org.skycastle.sketch.model.group.Group;
-import org.skycastle.sketch.model.group.GroupElement;
-import org.skycastle.sketch.model.stroke.Stroke;
-import org.skycastle.sketch.rendering.StrokePartRenderer;
 import org.skycastle.util.ParameterChecker;
-import org.skycastle.util.listenable.collection.CollectionListener;
-import org.skycastle.util.listenable.collection.ListenableCollection;
 import org.skycastle.util.simpleui.CloseHandler;
 import org.skycastle.util.simpleui.SimpleFrame;
 
@@ -43,9 +36,11 @@
     //======================================================================
     // Private Fields
 
+    private final SketchRenderer mySketchRenderer = new SketchRenderer();
+
+
     private final Map<String, JMenu> myMenus = new HashMap<String, JMenu>( 10 
);
     private final SimpleFrame myMainFrame;
-    private final Node myRoot3DNode;
     private final PenManager myPenManager;
 
     private final Object myProjectionLock = new Object();
@@ -125,10 +120,16 @@
         myToolBar = new JToolBar();
 
         myCanvas3D.removeAllNavigationGestures();
-        myRoot3DNode = new Node( "SketchView_RootNode" );
-        myCanvas3D.set3DNode( myRoot3DNode );
         myCanvas3D.setBackgroundColor( Color.WHITE );
 
+        myCanvas3D.addInitializer( new CanvasInitializer()
+        {
+            public void initialize( final Canvas3D canvas3D, final 
DisplaySystem displaySystem )
+            {
+                myCanvas3D.set3DNode( mySketchRenderer.getRenderer( 
displaySystem ) );
+            }
+        } );
+
         moveCamera( myCameraX, myCameraY, myViewSizeHorizontally, 
myRotationRadians );
 
         final JPanel panel = new JPanel( new BorderLayout() );
@@ -239,7 +240,7 @@
             myCanvas3D.addInitializer( new CanvasInitializer()
             {
 
-                public void initialize( final Canvas3D canvas3D, final 
Renderer renderer )
+                public void initialize( final Canvas3D canvas3D, final 
DisplaySystem displaySystem )
                 {
                     updateCamera( myCanvas3D, cameraX, cameraY, 
viewSizeHorizontally, rotationRadians );
                 }
@@ -348,32 +349,11 @@
 
         mySketch = sketch;
 
-        reRender( sketch );
+        mySketchRenderer.setSketch( mySketch );
 
-        //noinspection serial
-        sketch.getRootGroup().addGroupListener( new 
CollectionListener<GroupElement>()
-        {
-
-            public void onElementAdded( final 
ListenableCollection<GroupElement> collection,
-                                        final GroupElement addedElement )
-            {
-                // TODO: Instead of this, just modify the 3D object for the 
stroke that was changed,
-                // or add a new one, or remove an removed one.
-                reRender( sketch );
-            }
-
-
-            public void onElementRemoved( final 
ListenableCollection<GroupElement> collection,
-                                          final GroupElement removedElement )
-            {
-                // TODO: Instead of this, just modify the 3D object for the 
stroke that was changed,
-                // or add a new one, or remove an removed one.
-                reRender( sketch );
-            }
-
-        } );
     }
 
+
     /**
      * @param listener a listener that is notified whenever the projection 
changes.
      */
@@ -470,42 +450,6 @@
     }
 
 
-    private void reRender( final Sketch sketch )
-    {
-        // Clean out old nodes (NOTE: detach all is usually a bit buggy / 
weird.. )
-        myRoot3DNode.detachAllChildren();
-
-        renderGroup( sketch.getRootGroup() );
-    }
-
-
-    private void renderGroup( final Group group )
-    {
-        for ( final GroupElement groupElement : group.getElements() )
-        {
-            // TODO: Replace with some more polymorphic way to create nodes..
-
-            if ( groupElement instanceof Stroke )
-            {
-                final Stroke stroke = (Stroke) groupElement;
-
-                final StrokePartRenderer strokePartRenderer = new 
StrokePartRenderer( 1000 );
-                strokePartRenderer.setStroke( stroke, 0 );
-                myRoot3DNode.attachChild( strokePartRenderer );
-
-/*
-
-                myRoot3DNode.attachChild( new StrokeRenderer( stroke ) );
-*/
-            }
-            else if ( groupElement instanceof Group )
-            {
-                renderGroup( (Group) groupElement );
-            }
-        }
-    }
-
-
     private JMenu getOrCreateMenu( final String menuName )
     {
         JMenu menu = myMenus.get( menuName );

Deleted: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java
  2008-04-29 21:42:09 UTC (rev 501)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java
  2008-04-30 12:49:30 UTC (rev 502)
@@ -1,35 +0,0 @@
-package org.skycastle.sketch;
-
-/**
- * A simple sketch program, supporting a pen tablet as input, and running in 
opengl.
- *
- * @author Hans Haggstrom
- */
-public final class SkycastleSketch
-{
-
-    //----------------------------------------------------------------------
-    // Main Method
-
-    /**
-     * Start everything.
-     */
-    public static void main( String[] args )
-    {
-        // TODO: 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.
-
-
-        final SketchController sketchController = new SketchController();
-
-        sketchController.start();
-    }
-
-    //======================================================================
-    // Private Methods
-
-    private SkycastleSketch()
-    {
-    }
-
-}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/TextureBufferedScreen.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/TextureBufferedScreen.java
                            (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/TextureBufferedScreen.java
    2008-04-30 12:49:30 UTC (rev 502)
@@ -0,0 +1,92 @@
+package org.skycastle.sketch;
+
+import com.jme.image.Texture;
+import com.jme.renderer.Camera;
+import com.jme.renderer.ColorRGBA;
+import com.jme.renderer.TextureRenderer;
+import com.jme.scene.Spatial;
+import com.jme.scene.shape.Quad;
+import com.jme.scene.state.TextureState;
+import com.jme.system.DisplaySystem;
+import org.skycastle.opengl.JmeUtils;
+import org.skycastle.util.ParameterChecker;
+
+/**
+ * @author Hans Haggstrom
+ */
+public final class TextureBufferedScreen
+        implements BufferedScreen
+{
+
+    //======================================================================
+    // Private Fields
+
+    private Quad myQuad = null;
+    private TextureRenderer myTextureRenderer = null;
+    private Texture myTexture = null;
+    private DisplaySystem myDisplaySystem = null;
+
+    //======================================================================
+    // Private Constants
+
+    private static final ColorRGBA TRANSPARENT = new ColorRGBA( 1f, 0f, 0f, 
0.5f );
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // BufferedScreen Implementation
+
+    public void renderElement( final Spatial spatial )
+    {
+        if ( myQuad != null )
+        {
+            ParameterChecker.checkNotNull( spatial, "spatial" );
+
+            // Copy camera settings
+            final Camera drawingCamera = 
myDisplaySystem.getRenderer().getCamera();
+            final Camera bufferCamera = myTextureRenderer.getCamera();
+            JmeUtils.copyCameraSettings( drawingCamera, bufferCamera );
+//        textureRenderer.updateCamera() // Doesn't exist?
+
+            // Render texture
+            myTextureRenderer.render( spatial, myTexture );
+        }
+    }
+
+    public Spatial get3DView( DisplaySystem displaySystem )
+    {
+        if ( myQuad == null )
+        {
+            myQuad = createQuad( displaySystem );
+        }
+
+        return myQuad;
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private Quad createQuad( DisplaySystem displaySystem )
+    {
+        ParameterChecker.checkNotNull( displaySystem, "displaySystem" );
+        myDisplaySystem = displaySystem;
+
+        //Create the texture renderer
+        myTextureRenderer = displaySystem.createTextureRenderer( 512, 512, 
TextureRenderer.RENDER_TEXTURE_2D );
+        myTextureRenderer.setBackgroundColor( TRANSPARENT );
+
+        // Create the texture to render to
+        myTexture = new Texture();
+        myTextureRenderer.setupTexture( myTexture );
+
+        // Create a quad to show the texture on
+        final Quad quad = new Quad();
+        TextureState textureState = 
displaySystem.getRenderer().createTextureState();
+        textureState.setTexture( myTexture );
+        quad.setRenderState( textureState );
+
+        return quad;
+    }
+
+}

Copied: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/input/InputHandler.java
 (from rev 501, 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/InputHandler.java)
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/input/InputHandler.java
                               (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/input/InputHandler.java
       2008-04-30 12:49:30 UTC (rev 502)
@@ -0,0 +1,211 @@
+package org.skycastle.sketch.input;
+
+import jpen.PenManager;
+import org.skycastle.sketch.SketchController;
+import org.skycastle.sketch.Tools.Tool;
+import org.skycastle.sketch.sample.DataSample;
+import org.skycastle.sketch.sample.SampleListener;
+import org.skycastle.util.ParameterChecker;
+
+import javax.swing.*;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Recieves inputs from {@link PenInputHandler}, and sends them to registered 
{@link Tool}s in the Swing thread.
+ *
+ * @author Hans Haggstrom
+ */
+public final class InputHandler
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final SketchController mySketchController;
+    private final List<Tool> myTools = new ArrayList<Tool>();
+    private final PenInputHandler myPenInputHandler = new PenInputHandler();
+    private final BlockingQueue<DataSample> myQueuedInput = new 
ArrayBlockingQueue<DataSample>(
+            MAX_INPUT_EVENT_QUEUE );
+
+    /**
+     * Recieves input in the pen input thread, and just queues it in a 
syncronized storage for processing in
+     * the Swing thread.
+     */
+    private final SampleListener myInputReciever = new SampleListener()
+    {
+
+        public void onSample( final DataSample dataSample )
+        {
+            try
+            {
+                myQueuedInput.put( dataSample );
+            }
+            catch ( InterruptedException e )
+            {
+                // Interrupted, just return.  The sample is lost, but it 
doesn't matter that much.
+            }
+        }
+
+
+        public void onSamples( final List<DataSample> dataSamples )
+        {
+            // There's no putAll method, so just put the samples one at a time.
+            for ( final DataSample dataSample : dataSamples )
+            {
+                onSample( dataSample );
+            }
+        }
+
+    };
+
+    //======================================================================
+    // Private Constants
+
+    private static final Logger LOGGER = Logger.getLogger( 
InputHandler.class.getName() );
+    private static final int MAX_INPUT_EVENT_QUEUE = 10000;
+    private static final int MAX_SAMPLES_TO_HANDLE_AT_ONCE = 100;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    /**
+     * Creates a new {@link InputHandler}.
+     */
+    public InputHandler( final PenManager penManager, final SketchController 
sketchController )
+    {
+        mySketchController = sketchController;
+        ParameterChecker.checkNotNull( penManager, "penManager" );
+
+        // Listen to projection changes
+        sketchController.getView().addProjectionChangeListener( 
myPenInputHandler );
+
+        // Convert pen events to DataSamples
+        penManager.pen.addListener( myPenInputHandler );
+
+        // Queue the DataSamples
+        myPenInputHandler.addListener( myInputReciever );
+
+        // Handle DataSamples in the queue with tools that run in the swing 
thread
+        final Thread sampleMover = new Thread( new Runnable()
+        {
+
+            public void run()
+            {
+                final List<DataSample> samples = new ArrayList<DataSample>();
+
+                //noinspection InfiniteLoopStatement
+                while ( true )
+                {
+                    // Get next samples
+                    waitForSamples( samples );
+
+                    // Handle the samples in the Swing thread.  Blocks until 
ready
+                    invokeToolsInSwingThread( samples );
+
+                    // Reuse collection.
+                    samples.clear();
+                }
+            }
+
+        } );
+
+        sampleMover.start();
+    }
+
+    //----------------------------------------------------------------------
+    // Other Public Methods
+
+    /**
+     * Adds the specified Tool.
+     *
+     * @param addedTool should not be null or already added.
+     */
+    public void addTool( final Tool addedTool )
+    {
+        ParameterChecker.checkNotNull( addedTool, "addedTool" );
+        ParameterChecker.checkNotAlreadyContained( addedTool, myTools, 
"myTools" );
+
+        myTools.add( addedTool );
+    }
+
+
+    /**
+     * Removes the specified Tool.
+     *
+     * @param removedTool should not be null, and should be present.
+     */
+    public void removeTool( final Tool removedTool )
+    {
+        ParameterChecker.checkNotNull( removedTool, "removedTool" );
+        ParameterChecker.checkContained( removedTool, myTools, "myTools" );
+
+        myTools.remove( removedTool );
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private void invokeToolsInSwingThread( final List<DataSample> samples )
+    {
+        try
+        {
+            SwingUtilities.invokeAndWait( new Runnable()
+            {
+
+                public void run()
+                {
+                    for ( final DataSample dataSample : samples )
+                    {
+                        // Let each tool handle each sample
+                        for ( final Tool tool : myTools )
+                        {
+                            tool.onEvent( dataSample, mySketchController );
+                        }
+                    }
+                }
+
+            } );
+        }
+        catch ( InterruptedException e )
+        {
+            LOGGER.log( Level.INFO, "Interrupted while handling input events", 
e );
+        }
+        catch ( InvocationTargetException e )
+        {
+            LOGGER.log( Level.WARNING, "Problem when handling input events", e 
);
+        }
+    }
+
+
+    private void waitForSamples( final List<DataSample> samples )
+    {
+        // Wait for first sample
+        DataSample dataSample = null;
+        try
+        {
+            dataSample = myQueuedInput.take();
+        }
+        catch ( InterruptedException e )
+        {
+            // We were interrupted, didn't get anything.
+        }
+
+        if ( dataSample != null )
+        {
+            samples.add( dataSample );
+        }
+
+        // Get the rest of the available samples
+        myQueuedInput.drainTo( samples, MAX_SAMPLES_TO_HANDLE_AT_ONCE );
+    }
+
+}

Copied: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/input/PenInputHandler.java
 (from rev 501, 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/PenInputHandler.java)
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/input/PenInputHandler.java
                            (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/input/PenInputHandler.java
    2008-04-30 12:49:30 UTC (rev 502)
@@ -0,0 +1,160 @@
+package org.skycastle.sketch.input;
+
+import jpen.*;
+import jpen.event.PenListener;
+import org.skycastle.sketch.ProjectionChangeListener;
+import org.skycastle.sketch.sample.AbstractSampleProducer;
+import org.skycastle.sketch.sample.DataSample;
+
+/**
+ * Recieves pen events, and turns them into {@link DataSample} based events.
+ *
+ * @author Hans Haggstrom
+ */
+@SuppressWarnings( { "ParameterNameDiffersFromOverriddenParameter" } )
+public final class PenInputHandler
+        extends AbstractSampleProducer
+        implements PenListener, ProjectionChangeListener
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final Object myProjectionLock = new Object();
+
+    private float myXOffs = 0;
+    private float myYOffs = 0;
+    private float myXScale = 1;
+    private float myYScale = 1;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    /**
+     * Creates a new {@link PenInputHandler}.
+     */
+    public PenInputHandler()
+    {
+    }
+
+    //----------------------------------------------------------------------
+    // ProjectionChangeListener Implementation
+
+
+    public void onProjectionChanged( final float xOffs,
+                                     final float yOffs,
+                                     final float xScale,
+                                     final float yScale )
+    {
+        synchronized ( myProjectionLock )
+        {
+            myXOffs = xOffs;
+            myYOffs = yOffs;
+            myXScale = xScale;
+            myYScale = yScale;
+        }
+    }
+
+    //----------------------------------------------------------------------
+    // PenListener Implementation
+
+    public void penKindEvent( final PKindEvent ev )
+    {
+        // Ignored for now
+    }
+
+
+    public void penLevelEvent( final PLevelEvent event )
+    {
+        final DataSample dataSample = new DataSample();
+
+        dataSample.setVariable( "time", getTimeAsSeconds( event ) );
+
+        for ( final PLevel level : event.levels )
+        {
+            final float value = level.value;
+            switch ( level.getType() )
+            {
+                case X:
+                    synchronized ( myProjectionLock )
+                    {
+                        final float x = value * myXScale + myXOffs;
+                        dataSample.setVariable( "x", x );
+                    }
+                    break;
+                case Y:
+                    synchronized ( myProjectionLock )
+                    {
+                        final float y = value * myYScale + myYOffs;
+                        dataSample.setVariable( "y", y );
+                    }
+                    break;
+                case PRESSURE:
+                    dataSample.setVariable( "pressure", value );
+                    break;
+                case TILT_X:
+                    dataSample.setVariable( "tiltX", value );
+                    break;
+                case TILT_Y:
+                    dataSample.setVariable( "tiltY", value );
+                    break;
+            }
+        }
+
+        sendSample( dataSample );
+    }
+
+
+    @Override
+    public void penButtonEvent( final PButtonEvent event )
+    {
+        final DataSample dataSample = new DataSample();
+
+        dataSample.setVariable( "time", getTimeAsSeconds( event ) );
+
+        final float value = event.button.value ? 1 : 0;
+
+        switch ( event.button.getType() )
+        {
+            case CENTER:
+                dataSample.setVariable( "centerButton", value );
+                break;
+
+            case LEFT:
+                dataSample.setVariable( "leftButton", value );
+                break;
+
+            case RIGHT:
+                dataSample.setVariable( "rightButton", value );
+                break;
+        }
+
+        sendSample( dataSample );
+    }
+
+
+    public void penScrollEvent( final PScrollEvent ev )
+    {
+        // Ignored for now
+    }
+
+
+    public void penTock( final long availableMillis )
+    {
+        // TODO: If this goes towards zero, it means our listeners are taking 
up too much time.
+        // Reduce amount of messages?
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private float getTimeAsSeconds( final PenEvent event )
+    {
+        // Convert timestamp to seconds
+        return ( 1.0f * event.getTime() ) / 1000.0f;
+    }
+
+}


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: [502] trunk/skycastle/modules/ui/src/main/java/org/ skycastle