]> gerrit.simantics Code Review - simantics/3d.git/commitdiff
latest release (0.41), third attempt
authorluukkainen <luukkainen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 29 Sep 2008 11:10:35 +0000 (11:10 +0000)
committerluukkainen <luukkainen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Mon, 29 Sep 2008 11:10:35 +0000 (11:10 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/3d/trunk@6847 ac1ea38d-2e2b-0410-8846-a27921b304fc

147 files changed:
org.simantics.proconf.g3d/.classpath [new file with mode: 0644]
org.simantics.proconf.g3d/.project [new file with mode: 0644]
org.simantics.proconf.g3d/META-INF/MANIFEST.MF [new file with mode: 0644]
org.simantics.proconf.g3d/build.properties [new file with mode: 0644]
org.simantics.proconf.g3d/data/defaultfont.tga [new file with mode: 0644]
org.simantics.proconf.g3d/icons/batch.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/batch.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/delete.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/delete.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/eye.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/eye.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/ff.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/ff.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/geometry.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/geometry.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/node.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/node.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/play.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/play.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/rotate.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/rotate.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/rw.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/rw.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_eject.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_eject_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_end.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_end_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_equalizer.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_equalizer_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_fastforward.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_fastforward_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_pause.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_pause_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_play.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_play_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_repeat.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_repeat_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_rewind.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_rewind_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_start.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_start_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_stop.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/control_stop_blue.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/lock.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/silk/lock_open.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/stop.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/stop.svg [new file with mode: 0644]
org.simantics.proconf.g3d/icons/translate.png [new file with mode: 0644]
org.simantics.proconf.g3d/icons/translate.svg [new file with mode: 0644]
org.simantics.proconf.g3d/logging.properties [new file with mode: 0644]
org.simantics.proconf.g3d/plugin.xml [new file with mode: 0644]
org.simantics.proconf.g3d/schema/geometry.exsd [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/Activator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/Resources.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/CameraAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ConstrainedTransformAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ContextAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ContextActionFactory.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ContextActionRegistry.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/FocusAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/InteractiveAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ReadAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ReadInteractiveAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/RemoveAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/RotateAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/TranslateAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/TranslateActionConstraints.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/WriteAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/WriteInteractiveAction.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AbstractScalarInterpolator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/Animatable.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/Animation.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AnimationController.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AnimationSystem.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AnimationSystemListener.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ChanneledColorInterpolator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ChanneledPositionInterpolator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ConstantInterpolator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/Interpolator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ResourceAnimationController.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ScalarInterpolator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ScaledResourceAnimationController.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/SlerpInterpolator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/TCBInterpolator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/TestAnimationController.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ui/AnimationControlCreator.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/AppearanceTools.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/Constraint.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ConstraintDetector.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/EditorContribution.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/G3DAPI.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/G3DTools.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/GeometryProvider.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/GeometryProviderRegistry.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/JmeRenderingComponent.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/MathTools.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ScenegraphAdapter.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ScenegraphAdapterImpl.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/SelectionAdapter.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorBase.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorPart.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorProvider.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/TransformationTools.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/VecmathJmeTools.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/VisualizationScheduler.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/JmeComposite.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/JmeSinglePassRenderingComponent.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/OrbitalCamera.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/PropertyTester2.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/StructuredResourceSelection.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/dialogs/JMEDialog.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/dnd/DropListener.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/dnd/ShapeDropTarget.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/AbstractGizmo.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/Gizmo.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/MultiSelectionGizmo.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/RotateGizmo.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/TransformGizmo.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/TransformInlineGizmo.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/input/AWTInputProvider.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/input/InputProvider.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/input/SWTInputProvider.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/preferences/G3DPreferencesPage.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/preferences/PreferenceConstants.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/preferences/PreferenceInitializer.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/AbstractGraphicsNode.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/IGeometryNode.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/IGraphicsNode.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ISelectableNode.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ModelNode.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/NonTransformableNode.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ParameterizedModelNode.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/RootGraphicsNode.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ShapeNode.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/AxesShape.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/FloorShape.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/GridShape.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/Quad.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/OEPathSelectionListener.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/OESelectionListener.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/PropertyTree.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/ScenegraphLockTraverser.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/AppearanceEditor.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/ScenegraphViewPart.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/SinglePageResourceEditor.java [new file with mode: 0644]
org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/SinglePageResourceView.java [new file with mode: 0644]

diff --git a/org.simantics.proconf.g3d/.classpath b/org.simantics.proconf.g3d/.classpath
new file mode 100644 (file)
index 0000000..2e6482e
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry excluding="fi/vtt/simantics/g3d/views/AppearanceEditor.java" kind="src" path="src"/>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/org.simantics.proconf.g3d/.project b/org.simantics.proconf.g3d/.project
new file mode 100644 (file)
index 0000000..a27da2f
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>org.simantics.proconf.g3d</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/org.simantics.proconf.g3d/META-INF/MANIFEST.MF b/org.simantics.proconf.g3d/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..ae81bc8
--- /dev/null
@@ -0,0 +1,43 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: G3D Plug-in
+Bundle-SymbolicName: org.simantics.proconf.g3d;singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Activator: org.simantics.proconf.g3d.Activator
+Bundle-Vendor: VTT
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.simantics.g2d.stubs,
+ javax.vecmath,
+ com.jme.eclipse,
+ org.simantics.proconf.image,
+ org.eclipse.ui.views,
+ org.simantics.db,
+ org.simantics.layer0.stubs,
+ org.simantics.layer0.utils,
+ org.simantics.image.stubs,
+ org.simantics.utils,
+ org.simantics.utils.datastructures,
+ org.simantics.utils.ui,
+ org.simantics.proconf.ui,
+ org.simantics.equation,
+ org.simantics.proconf.browsing,
+ org.eclipse.ui.forms,
+ org.eclipse.core.expressions,
+ org.simantics.animation
+Eclipse-LazyStart: true
+Export-Package: org.simantics.proconf.g3d.actions,
+ org.simantics.proconf.g3d.animation,
+ org.simantics.proconf.g3d.animation.ui,
+ org.simantics.proconf.g3d.base,
+ org.simantics.proconf.g3d.common,
+ org.simantics.proconf.g3d.dialogs,
+ org.simantics.proconf.g3d.dnd,
+ org.simantics.proconf.g3d.gizmo,
+ org.simantics.proconf.g3d.input,
+ org.simantics.proconf.g3d.preferences,
+ org.simantics.proconf.g3d.scenegraph,
+ org.simantics.proconf.g3d.shapes,
+ org.simantics.proconf.g3d.stubs,
+ org.simantics.proconf.g3d.tools,
+ org.simantics.proconf.g3d.views
diff --git a/org.simantics.proconf.g3d/build.properties b/org.simantics.proconf.g3d/build.properties
new file mode 100644 (file)
index 0000000..6f20375
--- /dev/null
@@ -0,0 +1,5 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .,\\r
+               plugin.xml\r
diff --git a/org.simantics.proconf.g3d/data/defaultfont.tga b/org.simantics.proconf.g3d/data/defaultfont.tga
new file mode 100644 (file)
index 0000000..e215541
Binary files /dev/null and b/org.simantics.proconf.g3d/data/defaultfont.tga differ
diff --git a/org.simantics.proconf.g3d/icons/batch.png b/org.simantics.proconf.g3d/icons/batch.png
new file mode 100644 (file)
index 0000000..424fd1b
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/batch.png differ
diff --git a/org.simantics.proconf.g3d/icons/batch.svg b/org.simantics.proconf.g3d/icons/batch.svg
new file mode 100644 (file)
index 0000000..23ba494
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
+<svg\r
+   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
+   xmlns:cc="http://web.resource.org/cc/"\r
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+   xmlns:svg="http://www.w3.org/2000/svg"\r
+   xmlns="http://www.w3.org/2000/svg"\r
+   xmlns:xlink="http://www.w3.org/1999/xlink"\r
+   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"\r
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
+   width="744.09448819"\r
+   height="1052.3622047"\r
+   id="svg2"\r
+   sodipodi:version="0.32"\r
+   inkscape:version="0.43"\r
+   sodipodi:docbase="D:\workspace\fi.vtt.proconf.webmon.visualizations.binary\icons"\r
+   sodipodi:docname="binary.svg"\r
+   inkscape:export-filename="D:\binary.png"\r
+   inkscape:export-xdpi="14.400002"\r
+   inkscape:export-ydpi="14.400002">\r
+  <defs\r
+     id="defs4">\r
+    <linearGradient\r
+       id="linearGradient1308">\r
+      <stop\r
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"\r
+         offset="0.00000000"\r
+         id="stop1310" />\r
+      <stop\r
+         style="stop-color:#5764ff;stop-opacity:1.0000000;"\r
+         offset="1.0000000"\r
+         id="stop1312" />\r
+    </linearGradient>\r
+    <radialGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#linearGradient1308"\r
+       id="radialGradient1316"\r
+       cx="105.42004"\r
+       cy="96.950104"\r
+       fx="105.42004"\r
+       fy="96.950104"\r
+       r="50.500000"\r
+       gradientUnits="userSpaceOnUse"\r
+       gradientTransform="matrix(0.892809,1.055631,-0.763525,0.645779,74.50455,-84.48377)" />\r
+  </defs>\r
+  <sodipodi:namedview\r
+     id="base"\r
+     pagecolor="#ffffff"\r
+     bordercolor="#666666"\r
+     borderopacity="1.0"\r
+     inkscape:pageopacity="0.0"\r
+     inkscape:pageshadow="2"\r
+     inkscape:zoom="7.2970297"\r
+     inkscape:cx="107.14286"\r
+     inkscape:cy="947.14286"\r
+     inkscape:document-units="px"\r
+     inkscape:current-layer="layer1"\r
+     inkscape:window-width="1280"\r
+     inkscape:window-height="904"\r
+     inkscape:window-x="149"\r
+     inkscape:window-y="34" />\r
+  <metadata\r
+     id="metadata7">\r
+    <rdf:RDF>\r
+      <cc:Work\r
+         rdf:about="">\r
+        <dc:format>image/svg+xml</dc:format>\r
+        <dc:type\r
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
+      </cc:Work>\r
+    </rdf:RDF>\r
+  </metadata>\r
+  <g\r
+     inkscape:label="Layer 1"\r
+     inkscape:groupmode="layer"\r
+     id="layer1">\r
+    <path\r
+       sodipodi:type="arc"\r
+       style="fill:url(#radialGradient1316);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"\r
+       id="path1306"\r
+       sodipodi:cx="107.14286"\r
+       sodipodi:cy="105.21932"\r
+       sodipodi:rx="50.000000"\r
+       sodipodi:ry="50.000000"\r
+       d="M 157.14286 105.21932 A 50.000000 50.000000 0 1 1  57.142860,105.21932 A 50.000000 50.000000 0 1 1  157.14286 105.21932 z" />\r
+    <text\r
+       xml:space="preserve"\r
+       style="font-size:93.40623474px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"\r
+       x="71.08165"\r
+       y="144.76363"\r
+       id="text1318"\r
+       sodipodi:linespacing="125%"\r
+       transform="scale(1.0468,0.955293)"><tspan\r
+         sodipodi:role="line"\r
+         id="tspan1311"\r
+         x="71.08165"\r
+         y="144.76363">B</tspan></text>\r
+  </g>\r
+</svg>\r
diff --git a/org.simantics.proconf.g3d/icons/delete.png b/org.simantics.proconf.g3d/icons/delete.png
new file mode 100644 (file)
index 0000000..31f061a
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/delete.png differ
diff --git a/org.simantics.proconf.g3d/icons/delete.svg b/org.simantics.proconf.g3d/icons/delete.svg
new file mode 100644 (file)
index 0000000..888616f
--- /dev/null
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="100"
+   height="100"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.44"
+   version="1.0"
+   sodipodi:docname="delete.svg"
+   sodipodi:docbase="D:\dev\icons"
+   inkscape:export-filename="D:\dev\icons\Nozzle.png"
+   inkscape:export-xdpi="14.4"
+   inkscape:export-ydpi="14.4">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3686">
+      <stop
+         style="stop-color:red;stop-opacity:0;"
+         offset="0"
+         id="stop3688" />
+      <stop
+         style="stop-color:red;stop-opacity:1;"
+         offset="1"
+         id="stop3690" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3133">
+      <stop
+         style="stop-color:#4c4c4c;stop-opacity:1;"
+         offset="0"
+         id="stop3135" />
+      <stop
+         id="stop3141"
+         offset="0.5"
+         style="stop-color:#cbcbcb;stop-opacity:1;" />
+      <stop
+         style="stop-color:#4c4c4c;stop-opacity:1;"
+         offset="1"
+         id="stop3137" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3686"
+       id="radialGradient3692"
+       cx="50"
+       cy="50"
+       fx="50"
+       fy="50"
+       r="52"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.707107,-0.707107,0.707107,0.707107,-20.71068,50)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="7.72"
+     inkscape:cx="50"
+     inkscape:cy="55.181347"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     width="100px"
+     height="100px"
+     inkscape:window-width="1280"
+     inkscape:window-height="968"
+     inkscape:window-x="-4"
+     inkscape:window-y="-4" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:url(#radialGradient3692);fill-opacity:1;stroke:red;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 7.5735931,21.715729 L 35.857864,50 L 7.5735931,78.284271 L 21.715729,92.426407 L 50,64.142136 L 78.284271,92.426407 L 92.426407,78.284271 L 64.142136,50 L 92.426407,21.715729 L 78.284271,7.5735931 L 50,35.857864 L 21.715729,7.5735931 L 7.5735931,21.715729 z "
+       id="rect2796" />
+  </g>
+</svg>
diff --git a/org.simantics.proconf.g3d/icons/eye.png b/org.simantics.proconf.g3d/icons/eye.png
new file mode 100644 (file)
index 0000000..0e78cfd
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/eye.png differ
diff --git a/org.simantics.proconf.g3d/icons/eye.svg b/org.simantics.proconf.g3d/icons/eye.svg
new file mode 100644 (file)
index 0000000..cfb5620
--- /dev/null
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="100"
+   height="100"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.44"
+   version="1.0"
+   sodipodi:docname="eye.svg"
+   sodipodi:docbase="D:\dev\icons"
+   inkscape:export-filename="D:\dev\icons\eye.png"
+   inkscape:export-xdpi="14.4"
+   inkscape:export-ydpi="14.4">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient4583">
+      <stop
+         style="stop-color:#0049ff;stop-opacity:1;"
+         offset="0"
+         id="stop4585" />
+      <stop
+         style="stop-color:#00b3b3;stop-opacity:1;"
+         offset="1"
+         id="stop4587" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3686">
+      <stop
+         style="stop-color:red;stop-opacity:0;"
+         offset="0"
+         id="stop3688" />
+      <stop
+         style="stop-color:red;stop-opacity:1;"
+         offset="1"
+         id="stop3690" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3133">
+      <stop
+         style="stop-color:#4c4c4c;stop-opacity:1;"
+         offset="0"
+         id="stop3135" />
+      <stop
+         id="stop3141"
+         offset="0.5"
+         style="stop-color:#cbcbcb;stop-opacity:1;" />
+      <stop
+         style="stop-color:#4c4c4c;stop-opacity:1;"
+         offset="1"
+         id="stop3137" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="10"
+     inkscape:cx="50"
+     inkscape:cy="59.95985"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     width="100px"
+     height="100px"
+     inkscape:window-width="1280"
+     inkscape:window-height="968"
+     inkscape:window-x="-4"
+     inkscape:window-y="-4" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:8;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="M 10,50 C 35.054042,24.945958 64.998554,24.998554 90,50 C 65.010416,74.989584 35.029348,75.029348 10,50 z "
+       id="path3694"
+       sodipodi:nodetypes="ccc" />
+    <path
+       sodipodi:type="arc"
+       style="fill:#009bff;fill-opacity:1;stroke:#009aff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path3696"
+       sodipodi:cx="50"
+       sodipodi:cy="50"
+       sodipodi:rx="15"
+       sodipodi:ry="15"
+       d="M 65 50 A 15 15 0 1 1  35,50 A 15 15 0 1 1  65 50 z" />
+    <path
+       sodipodi:type="arc"
+       style="fill:black;fill-opacity:1;stroke:black;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="path5476"
+       sodipodi:cx="50"
+       sodipodi:cy="50"
+       sodipodi:rx="4"
+       sodipodi:ry="4"
+       d="M 54 50 A 4 4 0 1 1  46,50 A 4 4 0 1 1  54 50 z" />
+  </g>
+</svg>
diff --git a/org.simantics.proconf.g3d/icons/ff.png b/org.simantics.proconf.g3d/icons/ff.png
new file mode 100644 (file)
index 0000000..9fb120a
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/ff.png differ
diff --git a/org.simantics.proconf.g3d/icons/ff.svg b/org.simantics.proconf.g3d/icons/ff.svg
new file mode 100644 (file)
index 0000000..5d9ddc9
--- /dev/null
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
+<svg\r
+   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
+   xmlns:cc="http://web.resource.org/cc/"\r
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+   xmlns:svg="http://www.w3.org/2000/svg"\r
+   xmlns="http://www.w3.org/2000/svg"\r
+   xmlns:xlink="http://www.w3.org/1999/xlink"\r
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
+   width="100"\r
+   height="100"\r
+   id="svg2"\r
+   sodipodi:version="0.32"\r
+   inkscape:version="0.44"\r
+   version="1.0"\r
+   sodipodi:docname="ff.svg"\r
+   sodipodi:docbase="D:\dev\icons"\r
+   inkscape:export-filename="D:\dev\icons\ff.png"\r
+   inkscape:export-xdpi="14.4"\r
+   inkscape:export-ydpi="14.4">\r
+  <defs\r
+     id="defs4">\r
+    <linearGradient\r
+       id="linearGradient6310">\r
+      <stop\r
+         style="stop-color:white;stop-opacity:1;"\r
+         offset="0"\r
+         id="stop6312" />\r
+      <stop\r
+         style="stop-color:blue;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop6314" />\r
+    </linearGradient>\r
+    <linearGradient\r
+       id="linearGradient3686">\r
+      <stop\r
+         style="stop-color:red;stop-opacity:0;"\r
+         offset="0"\r
+         id="stop3688" />\r
+      <stop\r
+         style="stop-color:red;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop3690" />\r
+    </linearGradient>\r
+    <linearGradient\r
+       id="linearGradient3133">\r
+      <stop\r
+         style="stop-color:#4c4c4c;stop-opacity:1;"\r
+         offset="0"\r
+         id="stop3135" />\r
+      <stop\r
+         id="stop3141"\r
+         offset="0.5"\r
+         style="stop-color:#cbcbcb;stop-opacity:1;" />\r
+      <stop\r
+         style="stop-color:#4c4c4c;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop3137" />\r
+    </linearGradient>\r
+    <radialGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#linearGradient6310"\r
+       id="radialGradient6316"\r
+       cx="63.25"\r
+       cy="49.999989"\r
+       fx="63.25"\r
+       fy="49.999989"\r
+       r="20.5"\r
+       gradientTransform="matrix(0.768293,5.919238e-8,-1.428134e-7,1.853659,14.65549,-42.68293)"\r
+       gradientUnits="userSpaceOnUse" />\r
+    <radialGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#linearGradient6310"\r
+       id="radialGradient6318"\r
+       cx="29"\r
+       cy="49.999989"\r
+       fx="29"\r
+       fy="49.999989"\r
+       r="20.5"\r
+       gradientTransform="matrix(0.780488,9.067778e-7,-2.068587e-6,1.780488,6.365957,-39.02442)"\r
+       gradientUnits="userSpaceOnUse" />\r
+  </defs>\r
+  <sodipodi:namedview\r
+     id="base"\r
+     pagecolor="#ffffff"\r
+     bordercolor="#666666"\r
+     borderopacity="1.0"\r
+     gridtolerance="10000"\r
+     guidetolerance="10"\r
+     objecttolerance="10"\r
+     inkscape:pageopacity="0.0"\r
+     inkscape:pageshadow="2"\r
+     inkscape:zoom="4"\r
+     inkscape:cx="50"\r
+     inkscape:cy="40"\r
+     inkscape:document-units="px"\r
+     inkscape:current-layer="layer1"\r
+     width="100px"\r
+     height="100px"\r
+     inkscape:window-width="1280"\r
+     inkscape:window-height="968"\r
+     inkscape:window-x="-4"\r
+     inkscape:window-y="-4" />\r
+  <metadata\r
+     id="metadata7">\r
+    <rdf:RDF>\r
+      <cc:Work\r
+         rdf:about="">\r
+        <dc:format>image/svg+xml</dc:format>\r
+        <dc:type\r
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
+      </cc:Work>\r
+    </rdf:RDF>\r
+  </metadata>\r
+  <g\r
+     inkscape:label="Layer 1"\r
+     inkscape:groupmode="layer"\r
+     id="layer1">\r
+    <path\r
+       style="fill:url(#radialGradient6316);fill-opacity:1.0;fill-rule:evenodd;stroke:blue;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"\r
+       d="M 85,50 L 50,15 L 50,85 L 85,50 z "\r
+       id="path4536" />\r
+    <path\r
+       style="fill:url(#radialGradient6318);fill-opacity:1.0;fill-rule:evenodd;stroke:blue;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"\r
+       d="M 15.5,85 L 15,15 L 50,50 L 15.5,85 z "\r
+       id="path4538" />\r
+  </g>\r
+</svg>\r
diff --git a/org.simantics.proconf.g3d/icons/geometry.png b/org.simantics.proconf.g3d/icons/geometry.png
new file mode 100644 (file)
index 0000000..b06b553
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/geometry.png differ
diff --git a/org.simantics.proconf.g3d/icons/geometry.svg b/org.simantics.proconf.g3d/icons/geometry.svg
new file mode 100644 (file)
index 0000000..e0e8ab7
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.44"
+   sodipodi:docbase="D:\dev\icons\jme"
+   sodipodi:docname="geometry.svg"
+   inkscape:export-filename="D:\dev\icons\jme\geometry.png"
+   inkscape:export-xdpi="14.400002"
+   inkscape:export-ydpi="14.400002">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient1308">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="0.00000000"
+         id="stop1310" />
+      <stop
+         style="stop-color:#00d51d;stop-opacity:1;"
+         offset="1"
+         id="stop1312" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient1308"
+       id="radialGradient1316"
+       cx="105.42004"
+       cy="96.950104"
+       fx="105.42004"
+       fy="96.950104"
+       r="50.500000"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.892809,1.055631,-0.763525,0.645779,74.50455,-84.48377)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="7.2970297"
+     inkscape:cx="107.14286"
+     inkscape:cy="947.14286"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="1280"
+     inkscape:window-height="904"
+     inkscape:window-x="149"
+     inkscape:window-y="34" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       sodipodi:type="arc"
+       style="fill:url(#radialGradient1316);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+       id="path1306"
+       sodipodi:cx="107.14286"
+       sodipodi:cy="105.21932"
+       sodipodi:rx="50.000000"
+       sodipodi:ry="50.000000"
+       d="M 157.14286 105.21932 A 50.000000 50.000000 0 1 1  57.142860,105.21932 A 50.000000 50.000000 0 1 1  157.14286 105.21932 z" />
+    <text
+       xml:space="preserve"
+       style="font-size:93.40626526px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
+       x="65.321404"
+       y="144.90714"
+       id="text1318"
+       sodipodi:linespacing="125%"
+       transform="scale(1.0468,0.955293)"><tspan
+         sodipodi:role="line"
+         id="tspan1876"
+         x="65.321404"
+         y="144.90714">G</tspan></text>
+  </g>
+</svg>
diff --git a/org.simantics.proconf.g3d/icons/node.png b/org.simantics.proconf.g3d/icons/node.png
new file mode 100644 (file)
index 0000000..a2cb4c4
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/node.png differ
diff --git a/org.simantics.proconf.g3d/icons/node.svg b/org.simantics.proconf.g3d/icons/node.svg
new file mode 100644 (file)
index 0000000..8fe1dd3
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.44"
+   sodipodi:docbase="D:\dev\icons\jme"
+   sodipodi:docname="node.svg"
+   inkscape:export-filename="D:\dev\icons\jme\node.png"
+   inkscape:export-xdpi="14.400002"
+   inkscape:export-ydpi="14.400002">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient1308">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="0.00000000"
+         id="stop1310" />
+      <stop
+         style="stop-color:red;stop-opacity:1;"
+         offset="1"
+         id="stop1312" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient1308"
+       id="radialGradient1316"
+       cx="105.42004"
+       cy="96.950104"
+       fx="105.42004"
+       fy="96.950104"
+       r="50.500000"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.892809,1.055631,-0.763525,0.645779,74.50455,-84.48377)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="7.2970297"
+     inkscape:cx="107.14286"
+     inkscape:cy="947.14286"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="1280"
+     inkscape:window-height="904"
+     inkscape:window-x="149"
+     inkscape:window-y="34" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       sodipodi:type="arc"
+       style="fill:url(#radialGradient1316);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+       id="path1306"
+       sodipodi:cx="107.14286"
+       sodipodi:cy="105.21932"
+       sodipodi:rx="50.000000"
+       sodipodi:ry="50.000000"
+       d="M 157.14286 105.21932 A 50.000000 50.000000 0 1 1  57.142860,105.21932 A 50.000000 50.000000 0 1 1  157.14286 105.21932 z" />
+    <text
+       xml:space="preserve"
+       style="font-size:93.40623199;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Arial"
+       x="71.08165"
+       y="144.76363"
+       id="text1318"
+       sodipodi:linespacing="125%"
+       transform="scale(1.0468,0.955293)"><tspan
+         sodipodi:role="line"
+         id="tspan1876"
+         x="71.08165"
+         y="144.76363">N</tspan></text>
+  </g>
+</svg>
diff --git a/org.simantics.proconf.g3d/icons/play.png b/org.simantics.proconf.g3d/icons/play.png
new file mode 100644 (file)
index 0000000..10f00bb
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/play.png differ
diff --git a/org.simantics.proconf.g3d/icons/play.svg b/org.simantics.proconf.g3d/icons/play.svg
new file mode 100644 (file)
index 0000000..dafc820
--- /dev/null
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
+<svg\r
+   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
+   xmlns:cc="http://web.resource.org/cc/"\r
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+   xmlns:svg="http://www.w3.org/2000/svg"\r
+   xmlns="http://www.w3.org/2000/svg"\r
+   xmlns:xlink="http://www.w3.org/1999/xlink"\r
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
+   width="100"\r
+   height="100"\r
+   id="svg2"\r
+   sodipodi:version="0.32"\r
+   inkscape:version="0.44"\r
+   version="1.0"\r
+   inkscape:export-filename="D:\dev\icons\play.png"\r
+   inkscape:export-xdpi="14"\r
+   inkscape:export-ydpi="14"\r
+   sodipodi:docname="play.svg"\r
+   sodipodi:docbase="D:\dev\icons">\r
+  <defs\r
+     id="defs4">\r
+    <linearGradient\r
+       id="linearGradient2184">\r
+      <stop\r
+         style="stop-color:white;stop-opacity:1;"\r
+         offset="0"\r
+         id="stop2186" />\r
+      <stop\r
+         style="stop-color:#2aae3a;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop2188" />\r
+    </linearGradient>\r
+    <linearGradient\r
+       id="linearGradient3146">\r
+      <stop\r
+         style="stop-color:#0000ff;stop-opacity:1;"\r
+         offset="0"\r
+         id="stop3148" />\r
+      <stop\r
+         id="stop3156"\r
+         offset="0.5"\r
+         style="stop-color:#006eff;stop-opacity:1;" />\r
+      <stop\r
+         style="stop-color:#00ffff;stop-opacity:1;"\r
+         offset="0.75"\r
+         id="stop3158" />\r
+      <stop\r
+         style="stop-color:#0079ff;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop3150" />\r
+    </linearGradient>\r
+    <linearGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#linearGradient2184"\r
+       id="linearGradient2190"\r
+       x1="8.00577"\r
+       y1="50.15"\r
+       x2="92.29423"\r
+       y2="50.15"\r
+       gradientUnits="userSpaceOnUse" />\r
+    <radialGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#linearGradient2184"\r
+       id="radialGradient2795"\r
+       cx="50"\r
+       cy="50"\r
+       fx="50"\r
+       fy="50"\r
+       r="40.5"\r
+       gradientUnits="userSpaceOnUse" />\r
+    <radialGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#linearGradient2184"\r
+       id="radialGradient5460"\r
+       cx="41.099998"\r
+       cy="49.999992"\r
+       fx="41.099998"\r
+       fy="49.999992"\r
+       r="30.5"\r
+       gradientTransform="matrix(0.724585,-2.263036e-7,3.286836e-7,1.055743,11.31954,-2.78713)"\r
+       gradientUnits="userSpaceOnUse" />\r
+  </defs>\r
+  <sodipodi:namedview\r
+     id="base"\r
+     pagecolor="#ffffff"\r
+     bordercolor="#666666"\r
+     borderopacity="1.0"\r
+     gridtolerance="10000"\r
+     guidetolerance="10"\r
+     objecttolerance="10"\r
+     inkscape:pageopacity="0.0"\r
+     inkscape:pageshadow="2"\r
+     inkscape:zoom="10"\r
+     inkscape:cx="50"\r
+     inkscape:cy="58.310406"\r
+     inkscape:document-units="px"\r
+     inkscape:current-layer="layer1"\r
+     width="100px"\r
+     height="100px"\r
+     inkscape:window-width="1272"\r
+     inkscape:window-height="960"\r
+     inkscape:window-x="0"\r
+     inkscape:window-y="0" />\r
+  <metadata\r
+     id="metadata7">\r
+    <rdf:RDF>\r
+      <cc:Work\r
+         rdf:about="">\r
+        <dc:format>image/svg+xml</dc:format>\r
+        <dc:type\r
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
+      </cc:Work>\r
+    </rdf:RDF>\r
+  </metadata>\r
+  <g\r
+     inkscape:label="Layer 1"\r
+     inkscape:groupmode="layer"\r
+     id="layer1">\r
+    <path\r
+       style="fill:url(#radialGradient5460);fill-opacity:1.0;fill-rule:evenodd;stroke:#009c00;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"\r
+       d="M 80,50 L 20,10 L 20,90 L 80,50 z "\r
+       id="path4567" />\r
+  </g>\r
+</svg>\r
diff --git a/org.simantics.proconf.g3d/icons/rotate.png b/org.simantics.proconf.g3d/icons/rotate.png
new file mode 100644 (file)
index 0000000..bcc829f
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/rotate.png differ
diff --git a/org.simantics.proconf.g3d/icons/rotate.svg b/org.simantics.proconf.g3d/icons/rotate.svg
new file mode 100644 (file)
index 0000000..1b8d04b
--- /dev/null
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="100"
+   height="100"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.43"
+   version="1.0"
+   inkscape:export-filename="C:\Documents and Settings\Make\Desktop\rotate.png"
+   inkscape:export-xdpi="14"
+   inkscape:export-ydpi="14"
+   sodipodi:docname="rotate.svg"
+   sodipodi:docbase="C:\Documents and Settings\Make\Desktop">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient2184">
+      <stop
+         style="stop-color:#2aae3a;stop-opacity:1;"
+         offset="0"
+         id="stop2186" />
+      <stop
+         style="stop-color:#2aae3a;stop-opacity:0;"
+         offset="1"
+         id="stop2188" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3146">
+      <stop
+         style="stop-color:#0000ff;stop-opacity:1;"
+         offset="0"
+         id="stop3148" />
+      <stop
+         id="stop3156"
+         offset="0.5"
+         style="stop-color:#006eff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#00ffff;stop-opacity:1;"
+         offset="0.75"
+         id="stop3158" />
+      <stop
+         style="stop-color:#0079ff;stop-opacity:1;"
+         offset="1"
+         id="stop3150" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2184"
+       id="linearGradient2190"
+       x1="8.00577"
+       y1="50.15"
+       x2="92.29423"
+       y2="50.15"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="10"
+     inkscape:cx="50"
+     inkscape:cy="52.718966"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     width="100px"
+     height="100px"
+     inkscape:window-width="1680"
+     inkscape:window-height="994"
+     inkscape:window-x="1280"
+     inkscape:window-y="22" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:url(#linearGradient2190);fill-opacity:1.0;fill-rule:nonzero;stroke:#009c00;stroke-width:4;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 50.15,10.00577 C 27.990385,10.00577 10.00577,27.990385 10.00577,50.15 C 10.00577,72.309615 27.990385,90.29423 50.15,90.29423 C 61.229808,90.29423 71.260847,85.793059 78.526954,78.526954 L 64.351021,64.351021 C 60.717969,67.984074 55.689904,70.222115 50.15,70.222115 C 39.070192,70.222115 30.077885,61.229808 30.077885,50.15 C 30.077885,39.070192 39.070192,30.077885 50.15,30.077885 C 55.689904,30.077885 60.717969,32.315926 64.351021,35.948979 L 50.15,50.15 L 90.29423,50.15 L 90.29423,10.00577 L 78.526954,21.773046 C 71.260847,14.506941 61.229808,10.00577 50.15,10.00577 z "
+       id="path2162"
+       inkscape:export-xdpi="14"
+       inkscape:export-ydpi="14" />
+  </g>
+</svg>
diff --git a/org.simantics.proconf.g3d/icons/rw.png b/org.simantics.proconf.g3d/icons/rw.png
new file mode 100644 (file)
index 0000000..ccc1ce6
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/rw.png differ
diff --git a/org.simantics.proconf.g3d/icons/rw.svg b/org.simantics.proconf.g3d/icons/rw.svg
new file mode 100644 (file)
index 0000000..dc4aed2
--- /dev/null
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
+<svg\r
+   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
+   xmlns:cc="http://web.resource.org/cc/"\r
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+   xmlns:svg="http://www.w3.org/2000/svg"\r
+   xmlns="http://www.w3.org/2000/svg"\r
+   xmlns:xlink="http://www.w3.org/1999/xlink"\r
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
+   width="100"\r
+   height="100"\r
+   id="svg2"\r
+   sodipodi:version="0.32"\r
+   inkscape:version="0.44"\r
+   version="1.0"\r
+   sodipodi:docname="rw.svg"\r
+   sodipodi:docbase="D:\dev\icons"\r
+   inkscape:export-filename="D:\dev\icons\rw.png"\r
+   inkscape:export-xdpi="14.4"\r
+   inkscape:export-ydpi="14.4">\r
+  <defs\r
+     id="defs4">\r
+    <linearGradient\r
+       id="linearGradient6310">\r
+      <stop\r
+         style="stop-color:white;stop-opacity:1;"\r
+         offset="0"\r
+         id="stop6312" />\r
+      <stop\r
+         style="stop-color:blue;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop6314" />\r
+    </linearGradient>\r
+    <linearGradient\r
+       id="linearGradient3686">\r
+      <stop\r
+         style="stop-color:red;stop-opacity:0;"\r
+         offset="0"\r
+         id="stop3688" />\r
+      <stop\r
+         style="stop-color:red;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop3690" />\r
+    </linearGradient>\r
+    <linearGradient\r
+       id="linearGradient3133">\r
+      <stop\r
+         style="stop-color:#4c4c4c;stop-opacity:1;"\r
+         offset="0"\r
+         id="stop3135" />\r
+      <stop\r
+         id="stop3141"\r
+         offset="0.5"\r
+         style="stop-color:#cbcbcb;stop-opacity:1;" />\r
+      <stop\r
+         style="stop-color:#4c4c4c;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop3137" />\r
+    </linearGradient>\r
+    <radialGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#linearGradient6310"\r
+       id="radialGradient6316"\r
+       cx="63.25"\r
+       cy="49.999989"\r
+       fx="63.25"\r
+       fy="49.999989"\r
+       r="20.5"\r
+       gradientTransform="matrix(-0.768293,-5.919238e-8,1.428134e-7,-1.853659,85.34451,142.6829)"\r
+       gradientUnits="userSpaceOnUse" />\r
+    <radialGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#linearGradient6310"\r
+       id="radialGradient6318"\r
+       cx="29"\r
+       cy="49.999989"\r
+       fx="29"\r
+       fy="49.999989"\r
+       r="20.5"\r
+       gradientTransform="matrix(-0.780488,-9.067778e-7,2.068587e-6,-1.780488,93.63404,139.0244)"\r
+       gradientUnits="userSpaceOnUse" />\r
+  </defs>\r
+  <sodipodi:namedview\r
+     id="base"\r
+     pagecolor="#ffffff"\r
+     bordercolor="#666666"\r
+     borderopacity="1.0"\r
+     gridtolerance="10000"\r
+     guidetolerance="10"\r
+     objecttolerance="10"\r
+     inkscape:pageopacity="0.0"\r
+     inkscape:pageshadow="2"\r
+     inkscape:zoom="4"\r
+     inkscape:cx="50"\r
+     inkscape:cy="40"\r
+     inkscape:document-units="px"\r
+     inkscape:current-layer="layer1"\r
+     width="100px"\r
+     height="100px"\r
+     inkscape:window-width="1280"\r
+     inkscape:window-height="968"\r
+     inkscape:window-x="-4"\r
+     inkscape:window-y="-4" />\r
+  <metadata\r
+     id="metadata7">\r
+    <rdf:RDF>\r
+      <cc:Work\r
+         rdf:about="">\r
+        <dc:format>image/svg+xml</dc:format>\r
+        <dc:type\r
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
+      </cc:Work>\r
+    </rdf:RDF>\r
+  </metadata>\r
+  <g\r
+     inkscape:label="Layer 1"\r
+     inkscape:groupmode="layer"\r
+     id="layer1">\r
+    <path\r
+       style="fill:url(#radialGradient6316);fill-opacity:1;fill-rule:evenodd;stroke:blue;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"\r
+       d="M 15,50 L 50,85 L 50,15 L 15,50 z "\r
+       id="path4536" />\r
+    <path\r
+       style="fill:url(#radialGradient6318);fill-opacity:1;fill-rule:evenodd;stroke:blue;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"\r
+       d="M 84.5,15 L 85,85 L 50,50 L 84.5,15 z "\r
+       id="path4538" />\r
+  </g>\r
+</svg>\r
diff --git a/org.simantics.proconf.g3d/icons/silk/control_eject.png b/org.simantics.proconf.g3d/icons/silk/control_eject.png
new file mode 100644 (file)
index 0000000..924d817
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_eject.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_eject_blue.png b/org.simantics.proconf.g3d/icons/silk/control_eject_blue.png
new file mode 100644 (file)
index 0000000..2bd4963
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_eject_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_end.png b/org.simantics.proconf.g3d/icons/silk/control_end.png
new file mode 100644 (file)
index 0000000..036e04d
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_end.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_end_blue.png b/org.simantics.proconf.g3d/icons/silk/control_end_blue.png
new file mode 100644 (file)
index 0000000..7207935
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_end_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_equalizer.png b/org.simantics.proconf.g3d/icons/silk/control_equalizer.png
new file mode 100644 (file)
index 0000000..4606087
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_equalizer.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_equalizer_blue.png b/org.simantics.proconf.g3d/icons/silk/control_equalizer_blue.png
new file mode 100644 (file)
index 0000000..1b2e6a3
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_equalizer_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_fastforward.png b/org.simantics.proconf.g3d/icons/silk/control_fastforward.png
new file mode 100644 (file)
index 0000000..31f7fd3
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_fastforward.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_fastforward_blue.png b/org.simantics.proconf.g3d/icons/silk/control_fastforward_blue.png
new file mode 100644 (file)
index 0000000..4a2f9d4
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_fastforward_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_pause.png b/org.simantics.proconf.g3d/icons/silk/control_pause.png
new file mode 100644 (file)
index 0000000..2d9ce9c
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_pause.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_pause_blue.png b/org.simantics.proconf.g3d/icons/silk/control_pause_blue.png
new file mode 100644 (file)
index 0000000..ec61099
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_pause_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_play.png b/org.simantics.proconf.g3d/icons/silk/control_play.png
new file mode 100644 (file)
index 0000000..0846555
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_play.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_play_blue.png b/org.simantics.proconf.g3d/icons/silk/control_play_blue.png
new file mode 100644 (file)
index 0000000..f8c8ec6
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_play_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_repeat.png b/org.simantics.proconf.g3d/icons/silk/control_repeat.png
new file mode 100644 (file)
index 0000000..1c4f57a
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_repeat.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_repeat_blue.png b/org.simantics.proconf.g3d/icons/silk/control_repeat_blue.png
new file mode 100644 (file)
index 0000000..406ec33
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_repeat_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_rewind.png b/org.simantics.proconf.g3d/icons/silk/control_rewind.png
new file mode 100644 (file)
index 0000000..c029447
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_rewind.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_rewind_blue.png b/org.simantics.proconf.g3d/icons/silk/control_rewind_blue.png
new file mode 100644 (file)
index 0000000..15d1584
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_rewind_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_start.png b/org.simantics.proconf.g3d/icons/silk/control_start.png
new file mode 100644 (file)
index 0000000..7dd1c07
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_start.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_start_blue.png b/org.simantics.proconf.g3d/icons/silk/control_start_blue.png
new file mode 100644 (file)
index 0000000..6f11fcb
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_start_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_stop.png b/org.simantics.proconf.g3d/icons/silk/control_stop.png
new file mode 100644 (file)
index 0000000..893bb60
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_stop.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/control_stop_blue.png b/org.simantics.proconf.g3d/icons/silk/control_stop_blue.png
new file mode 100644 (file)
index 0000000..e6f75d2
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/control_stop_blue.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/lock.png b/org.simantics.proconf.g3d/icons/silk/lock.png
new file mode 100644 (file)
index 0000000..2ebc4f6
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/lock.png differ
diff --git a/org.simantics.proconf.g3d/icons/silk/lock_open.png b/org.simantics.proconf.g3d/icons/silk/lock_open.png
new file mode 100644 (file)
index 0000000..a471765
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/silk/lock_open.png differ
diff --git a/org.simantics.proconf.g3d/icons/stop.png b/org.simantics.proconf.g3d/icons/stop.png
new file mode 100644 (file)
index 0000000..ef86eb5
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/stop.png differ
diff --git a/org.simantics.proconf.g3d/icons/stop.svg b/org.simantics.proconf.g3d/icons/stop.svg
new file mode 100644 (file)
index 0000000..58381c7
--- /dev/null
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>\r
+<!-- Created with Inkscape (http://www.inkscape.org/) -->\r
+<svg\r
+   xmlns:dc="http://purl.org/dc/elements/1.1/"\r
+   xmlns:cc="http://web.resource.org/cc/"\r
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\r
+   xmlns:svg="http://www.w3.org/2000/svg"\r
+   xmlns="http://www.w3.org/2000/svg"\r
+   xmlns:xlink="http://www.w3.org/1999/xlink"\r
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"\r
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\r
+   width="100"\r
+   height="100"\r
+   id="svg2"\r
+   sodipodi:version="0.32"\r
+   inkscape:version="0.44"\r
+   version="1.0"\r
+   sodipodi:docname="stop.svg"\r
+   sodipodi:docbase="D:\dev\icons"\r
+   inkscape:export-filename="D:\dev\icons\stop.png"\r
+   inkscape:export-xdpi="14.4"\r
+   inkscape:export-ydpi="14.4">\r
+  <defs\r
+     id="defs4">\r
+    <linearGradient\r
+       id="linearGradient3686">\r
+      <stop\r
+         style="stop-color:white;stop-opacity:1;"\r
+         offset="0"\r
+         id="stop3688" />\r
+      <stop\r
+         style="stop-color:red;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop3690" />\r
+    </linearGradient>\r
+    <linearGradient\r
+       id="linearGradient3133">\r
+      <stop\r
+         style="stop-color:#4c4c4c;stop-opacity:1;"\r
+         offset="0"\r
+         id="stop3135" />\r
+      <stop\r
+         id="stop3141"\r
+         offset="0.5"\r
+         style="stop-color:#cbcbcb;stop-opacity:1;" />\r
+      <stop\r
+         style="stop-color:#4c4c4c;stop-opacity:1;"\r
+         offset="1"\r
+         id="stop3137" />\r
+    </linearGradient>\r
+    <radialGradient\r
+       inkscape:collect="always"\r
+       xlink:href="#linearGradient3686"\r
+       id="radialGradient3657"\r
+       cx="50"\r
+       cy="50"\r
+       fx="50"\r
+       fy="50"\r
+       r="42"\r
+       gradientUnits="userSpaceOnUse"\r
+       gradientTransform="matrix(1.366955,0,0,1.366953,-18.34766,-18.34764)" />\r
+  </defs>\r
+  <sodipodi:namedview\r
+     id="base"\r
+     pagecolor="#ffffff"\r
+     bordercolor="#666666"\r
+     borderopacity="1.0"\r
+     gridtolerance="10000"\r
+     guidetolerance="10"\r
+     objecttolerance="10"\r
+     inkscape:pageopacity="0.0"\r
+     inkscape:pageshadow="2"\r
+     inkscape:zoom="7.72"\r
+     inkscape:cx="50"\r
+     inkscape:cy="50"\r
+     inkscape:document-units="px"\r
+     inkscape:current-layer="layer1"\r
+     width="100px"\r
+     height="100px"\r
+     inkscape:window-width="1280"\r
+     inkscape:window-height="968"\r
+     inkscape:window-x="-4"\r
+     inkscape:window-y="-4" />\r
+  <metadata\r
+     id="metadata7">\r
+    <rdf:RDF>\r
+      <cc:Work\r
+         rdf:about="">\r
+        <dc:format>image/svg+xml</dc:format>\r
+        <dc:type\r
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />\r
+      </cc:Work>\r
+    </rdf:RDF>\r
+  </metadata>\r
+  <g\r
+     inkscape:label="Layer 1"\r
+     inkscape:groupmode="layer"\r
+     id="layer1">\r
+    <path\r
+       style="fill:url(#radialGradient3657);fill-opacity:1;fill-rule:evenodd;stroke:red;stroke-width:6;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"\r
+       d="M 17.619764,17.619763 L 17.619764,82.380236 L 82.380236,82.380236 L 82.380236,17.619763 L 17.619764,17.619763 z "\r
+       id="path1878" />\r
+  </g>\r
+</svg>\r
diff --git a/org.simantics.proconf.g3d/icons/translate.png b/org.simantics.proconf.g3d/icons/translate.png
new file mode 100644 (file)
index 0000000..21f5284
Binary files /dev/null and b/org.simantics.proconf.g3d/icons/translate.png differ
diff --git a/org.simantics.proconf.g3d/icons/translate.svg b/org.simantics.proconf.g3d/icons/translate.svg
new file mode 100644 (file)
index 0000000..b600c2f
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="100"
+   height="100"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.44"
+   version="1.0"
+   inkscape:export-filename="C:\Documents and Settings\Make\Desktop\rotate.png"
+   inkscape:export-xdpi="14"
+   inkscape:export-ydpi="14"
+   sodipodi:docname="translate.svg"
+   sodipodi:docbase="D:\dev\icons">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient2184">
+      <stop
+         style="stop-color:#2aae3a;stop-opacity:1;"
+         offset="0"
+         id="stop2186" />
+      <stop
+         style="stop-color:#2aae3a;stop-opacity:0;"
+         offset="1"
+         id="stop2188" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3146">
+      <stop
+         style="stop-color:#0000ff;stop-opacity:1;"
+         offset="0"
+         id="stop3148" />
+      <stop
+         id="stop3156"
+         offset="0.5"
+         style="stop-color:#006eff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#00ffff;stop-opacity:1;"
+         offset="0.75"
+         id="stop3158" />
+      <stop
+         style="stop-color:#0079ff;stop-opacity:1;"
+         offset="1"
+         id="stop3150" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2184"
+       id="linearGradient2190"
+       x1="8.00577"
+       y1="50.15"
+       x2="92.29423"
+       y2="50.15"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2184"
+       id="radialGradient4579"
+       cx="50"
+       cy="50"
+       fx="50"
+       fy="50"
+       r="52"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.809436,0,0,0.809436,9.463433,9.592966)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="7.72"
+     inkscape:cx="50"
+     inkscape:cy="39.637306"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     width="100px"
+     height="100px"
+     inkscape:window-width="1280"
+     inkscape:window-height="968"
+     inkscape:window-x="-4"
+     inkscape:window-y="-4" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:url(#radialGradient4579);fill-opacity:1;fill-rule:evenodd;stroke:#009c00;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 49.935233,9.5929652 L 33.746512,25.781686 L 41.840873,25.781686 L 41.840873,41.970406 L 25.652153,41.970406 L 25.652153,33.876046 L 9.4634316,50.064767 L 25.652153,66.253488 L 25.652153,58.159127 L 41.840873,58.159127 L 41.840873,74.347847 L 33.746512,74.347847 L 49.935233,90.536568 L 66.123954,74.347847 L 58.029594,74.347847 L 58.029594,58.159127 L 74.218314,58.159127 L 74.218314,66.253488 L 90.407036,50.064767 L 74.218314,33.876046 L 74.218314,41.970406 L 58.029594,41.970406 L 58.029594,25.781686 L 66.123954,25.781686 L 49.935233,9.5929652 z "
+       id="path1879" />
+  </g>
+</svg>
diff --git a/org.simantics.proconf.g3d/logging.properties b/org.simantics.proconf.g3d/logging.properties
new file mode 100644 (file)
index 0000000..d8ec9e4
--- /dev/null
@@ -0,0 +1,54 @@
+############################################################\r
+#      Default Logging Configuration File\r
+#\r
+# You can use a different file by specifying a filename\r
+# with the java.util.logging.config.file system property.  \r
+# For example java -Djava.util.logging.config.file=myfile\r
+############################################################\r
+\r
+############################################################\r
+#      Global properties\r
+############################################################\r
+\r
+# "handlers" specifies a comma separated list of log Handler \r
+# classes.  These handlers will be installed during VM startup.\r
+# Note that these classes must be on the system classpath.\r
+# By default we only configure a ConsoleHandler, which will only\r
+# show messages at the INFO and above levels.\r
+handlers= java.util.logging.ConsoleHandler\r
+\r
+# To also add the FileHandler, use the following line instead.\r
+#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler\r
+\r
+# Default global logging level.\r
+# This specifies which kinds of events are logged across\r
+# all loggers.  For any given facility this global level\r
+# can be overriden by a facility specific level\r
+# Note that the ConsoleHandler also has a separate level\r
+# setting to limit messages printed to the console.\r
+.level= OFF\r
+\r
+############################################################\r
+# Handler specific properties.\r
+# Describes specific configuration info for Handlers.\r
+############################################################\r
+\r
+# default file output is in user's home directory.\r
+java.util.logging.FileHandler.pattern = %h/java%u.log\r
+java.util.logging.FileHandler.limit = 50000\r
+java.util.logging.FileHandler.count = 1\r
+java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter\r
+\r
+# Limit the message that are printed on the console to INFO and above.\r
+java.util.logging.ConsoleHandler.level = OFF\r
+java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter\r
+\r
+\r
+############################################################\r
+# Facility specific properties.\r
+# Provides extra control for each logger.\r
+############################################################\r
+\r
+# For example, set the com.xyz.foo logger to only log SEVERE\r
+# messages:\r
+# com.xyz.foo.level = SEVERE\r
diff --git a/org.simantics.proconf.g3d/plugin.xml b/org.simantics.proconf.g3d/plugin.xml
new file mode 100644 (file)
index 0000000..fc55861
--- /dev/null
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<?eclipse version="3.2"?>\r
+<plugin>\r
+   <extension-point id="geometry" name="Geometry" schema="schema/geometry.exsd"/>\r
+   <extension\r
+         point="org.eclipse.ui.preferencePages">\r
+      <page\r
+            category="org.simantics.proconf.preferences"\r
+            class="org.simantics.proconf.g3d.preferences.G3DPreferencesPage"\r
+            id="fi.vtt.simantics.g3d.page1"\r
+            name="3D Preferences">\r
+      </page>\r
+   </extension>\r
+   <extension\r
+         point="org.eclipse.core.runtime.preferences">\r
+      <initializer\r
+            class="org.simantics.proconf.g3d.preferences.PreferenceInitializer">\r
+      </initializer>\r
+   </extension>\r
+   <extension\r
+         point="org.eclipse.ui.views">\r
+      <view\r
+            allowMultiple="false"\r
+            class="org.simantics.proconf.g3d.views.ScenegraphViewPart"\r
+            icon="icons/geometry.png"\r
+            id="org.simantics.g3d.views.scenegraph"\r
+            name="Scene-graph">\r
+      </view>\r
+      <view\r
+            allowMultiple="false"\r
+            class="org.simantics.proconf.g3d.views.AppearanceEditor"\r
+            icon="icons/geometry.png"\r
+            id="org.simantics.proconf.g3d.view1"\r
+            name="Appearance Editor">\r
+      </view>\r
+   </extension>\r
+   <extension\r
+         point="org.eclipse.core.expressions.propertyTesters">\r
+      <propertyTester\r
+            class="org.simantics.proconf.g3d.common.PropertyTester2"\r
+            id="org.simantics.proconf.editorToolTester"\r
+            namespace="org.simantics.proconf"\r
+            properties="editorTool"\r
+            type="org.eclipse.jface.viewers.IStructuredSelection">\r
+      </propertyTester>\r
+   </extension>\r
+</plugin>\r
diff --git a/org.simantics.proconf.g3d/schema/geometry.exsd b/org.simantics.proconf.g3d/schema/geometry.exsd
new file mode 100644 (file)
index 0000000..f6af128
--- /dev/null
@@ -0,0 +1,112 @@
+<?xml version='1.0' encoding='UTF-8'?>\r
+<!-- Schema file written by PDE -->\r
+<schema targetNamespace="org.simantics.proconf.g3d">\r
+<annotation>\r
+      <appInfo>\r
+         <meta.schema plugin="org.simantics.proconf.g3d" id="geometry" name="Geometry"/>\r
+      </appInfo>\r
+      <documentation>\r
+         [Enter description of this extension point.]\r
+      </documentation>\r
+   </annotation>\r
+\r
+   <element name="extension">\r
+      <complexType>\r
+         <sequence>\r
+            <element ref="Geometry" minOccurs="0" maxOccurs="unbounded"/>\r
+         </sequence>\r
+         <attribute name="point" type="string" use="required">\r
+            <annotation>\r
+               <documentation>\r
+                  \r
+               </documentation>\r
+            </annotation>\r
+         </attribute>\r
+         <attribute name="id" type="string">\r
+            <annotation>\r
+               <documentation>\r
+                  \r
+               </documentation>\r
+            </annotation>\r
+         </attribute>\r
+         <attribute name="name" type="string">\r
+            <annotation>\r
+               <documentation>\r
+                  \r
+               </documentation>\r
+               <appInfo>\r
+                  <meta.attribute translatable="true"/>\r
+               </appInfo>\r
+            </annotation>\r
+         </attribute>\r
+      </complexType>\r
+   </element>\r
+\r
+   <element name="Geometry">\r
+      <complexType>\r
+         <attribute name="id" type="string" use="required">\r
+            <annotation>\r
+               <documentation>\r
+                  \r
+               </documentation>\r
+            </annotation>\r
+         </attribute>\r
+         <attribute name="class" type="string" use="required">\r
+            <annotation>\r
+               <documentation>\r
+                  \r
+               </documentation>\r
+               <appInfo>\r
+                  <meta.attribute kind="java" basedOn=":fi.vtt.simantics.g3d.base.GeometryProvider"/>\r
+               </appInfo>\r
+            </annotation>\r
+         </attribute>\r
+      </complexType>\r
+   </element>\r
+\r
+   <annotation>\r
+      <appInfo>\r
+         <meta.section type="since"/>\r
+      </appInfo>\r
+      <documentation>\r
+         [Enter the first release in which this extension point appears.]\r
+      </documentation>\r
+   </annotation>\r
+\r
+   <annotation>\r
+      <appInfo>\r
+         <meta.section type="examples"/>\r
+      </appInfo>\r
+      <documentation>\r
+         [Enter extension point usage example here.]\r
+      </documentation>\r
+   </annotation>\r
+\r
+   <annotation>\r
+      <appInfo>\r
+         <meta.section type="apiInfo"/>\r
+      </appInfo>\r
+      <documentation>\r
+         [Enter API information here.]\r
+      </documentation>\r
+   </annotation>\r
+\r
+   <annotation>\r
+      <appInfo>\r
+         <meta.section type="implementation"/>\r
+      </appInfo>\r
+      <documentation>\r
+         [Enter information about supplied implementation of this extension point.]\r
+      </documentation>\r
+   </annotation>\r
+\r
+   <annotation>\r
+      <appInfo>\r
+         <meta.section type="copyright"/>\r
+      </appInfo>\r
+      <documentation>\r
+         \r
+      </documentation>\r
+   </annotation>\r
+\r
+</schema>\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/Activator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/Activator.java
new file mode 100644 (file)
index 0000000..38b8b6f
--- /dev/null
@@ -0,0 +1,94 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d;\r
+\r
+import org.eclipse.ui.plugin.AbstractUIPlugin;\r
+import org.osgi.framework.BundleContext;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.management.ISessionContextChangedListener;\r
+import org.simantics.db.management.SessionContextChangedEvent;\r
+import org.simantics.proconf.ui.ProConfUI;\r
+\r
+/**\r
+ * The activator class controls the plug-in life cycle\r
+ */\r
+public class Activator extends AbstractUIPlugin {\r
+\r
+       // The plug-in ID\r
+       public static final String PLUGIN_ID = "org.simantics.proconf.g3d";\r
+\r
+       // The shared instance\r
+       private static Activator plugin;\r
+       \r
+       /**\r
+        * The constructor\r
+        */\r
+       public Activator() {\r
+       }\r
+\r
+       /*\r
+        * (non-Javadoc)\r
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)\r
+        */\r
+       public void start(BundleContext context) throws Exception {\r
+               super.start(context);\r
+               plugin = this;\r
+               ProConfUI.getSessionContextProvider().addContextChangedListener(new ISessionContextChangedListener() {\r
+                       @Override\r
+                       public void sessionContextChanged(SessionContextChangedEvent event) {\r
+                               ISessionContext ctx = event.getNewValue();\r
+                               if (ctx != null) {\r
+                                       ctx.getSession().asyncRead(new GraphRequestAdapter() {\r
+                                               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                                                       Resources.initialize(g);\r
+                                                       return GraphRequestStatus.transactionComplete();\r
+                                               };\r
+                                       });\r
+                               } else {\r
+                                       Resources.deinitialize();\r
+                               }\r
+                       }\r
+               });\r
+               try {\r
+                       ProConfUI.getSession().asyncRead(new GraphRequestAdapter() {\r
+                               @Override\r
+                               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                                       Resources.initialize(g);\r
+                                       return GraphRequestStatus.transactionComplete();\r
+                               }\r
+                       });\r
+               } catch (Exception e) {\r
+                       \r
+               }\r
+       }\r
+\r
+       /*\r
+        * (non-Javadoc)\r
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)\r
+        */\r
+       public void stop(BundleContext context) throws Exception {\r
+               plugin = null;\r
+               super.stop(context);\r
+       }\r
+\r
+       /**\r
+        * Returns the shared instance\r
+        *\r
+        * @return the shared instance\r
+        */\r
+       public static Activator getDefault() {\r
+               return plugin;\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/Resources.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/Resources.java
new file mode 100644 (file)
index 0000000..f0cacb4
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.equation.stubs.EquationResource;\r
+import org.simantics.g2d.stubs.anim.AnimationResource;\r
+import org.simantics.animation.curve.CurveBuilder;\r
+import org.simantics.animation.curve.CurveBuilderImpl;\r
+import org.simantics.proconf.g3d.base.G3DTools;\r
+import org.simantics.proconf.g3d.stubs.G3DResource;\r
+\r
+public class Resources {\r
+       public static AnimationResource animationResource;\r
+       public static G3DResource g3dResource;\r
+       public static CurveBuilder curveBuilder;\r
+       public static EquationResource equationResource;\r
+       \r
+       public static void initialize(Graph g) {\r
+               animationResource = AnimationResource.getInstance(g);\r
+               g3dResource = G3DResource.getInstance(g);\r
+               curveBuilder = new CurveBuilderImpl(Resources.animationResource);\r
+               equationResource = EquationResource.getInstance(g);\r
+               G3DTools.initialize();\r
+       }\r
+       \r
+       public static void deinitialize() {\r
+               animationResource = null;\r
+               g3dResource = null;\r
+               curveBuilder = null;\r
+               equationResource = null;\r
+               G3DTools.deinitialize();\r
+       }\r
+       \r
+       \r
+       \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/CameraAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/CameraAction.java
new file mode 100644 (file)
index 0000000..2f61904
--- /dev/null
@@ -0,0 +1,134 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseEvent;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.base.JmeRenderingComponent;\r
+import org.simantics.proconf.g3d.base.MathTools;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.common.OrbitalCamera;\r
+\r
+\r
+\r
+public class CameraAction extends InteractiveAction{\r
+       \r
+       private JmeRenderingComponent component;\r
+       private OrbitalCamera camera;\r
+       \r
+    public CameraAction(ThreeDimensionalEditorBase parent) {\r
+        super(parent);\r
+        component = parent.getRenderingComponent();\r
+        camera = parent.getCamera();\r
+    }\r
+    \r
+    @Override\r
+    public void activate() {\r
+\r
+    }\r
+\r
+    @Override\r
+    public void deactivate() {\r
+\r
+    }\r
+    \r
+    @Override\r
+  public boolean usable(Graph graph,List<Resource> resources) {\r
+      return true;\r
+  }\r
+\r
+    Vector3d prevIntersectPoint = new Vector3d();\r
+    @Override\r
+    public void update() {\r
+        double scale = 1.0;\r
+        if (input.keyDown(KeyEvent.VK_CONTROL))\r
+            scale = -1.0;\r
+        if (input.keyPressed(KeyEvent.VK_NUMPAD5)) {\r
+            if (component.getProjectionPolicy() == JmeRenderingComponent.PERSPECTIVE_PROJECTION)\r
+                component.setProjectionPolicy(JmeRenderingComponent.PARALLEL_PROJECTION);\r
+            else\r
+                component.setProjectionPolicy(JmeRenderingComponent.PERSPECTIVE_PROJECTION);\r
+            parent.setViewChanged(true);\r
+        }\r
+        if (input.keyPressed(KeyEvent.VK_NUMPAD7)) {\r
+            camera.setCameraPosRelativeToTarget(new Vector3d(camera.getDistanceToTarget() * scale, 0, 0));\r
+            parent.setViewChanged(true);\r
+        }\r
+        if (input.keyPressed(KeyEvent.VK_NUMPAD1)) {\r
+            camera.setCameraPosRelativeToTarget(new Vector3d(0, 0, camera.getDistanceToTarget() * scale));\r
+            parent.setViewChanged(true);\r
+        }\r
+        if (input.keyPressed(KeyEvent.VK_NUMPAD9)) {\r
+            camera.setCameraPosRelativeToTarget(new Vector3d(0, camera.getDistanceToTarget() * scale, 0));\r
+            parent.setViewChanged(true);\r
+        }\r
+\r
+        if (input.mousePressed() && ((input.pressModifiers() & MouseEvent.BUTTON1_MASK) > 0)) {\r
+            Vector3d o = new Vector3d();\r
+            Vector3d d = new Vector3d();\r
+            parent.createPickRay(o, d);\r
+            Vector3d point = new Vector3d(camera.getTarget());\r
+            Vector3d normal = camera.getUnNormalizedHeading();\r
+            normal.normalize();\r
+            MathTools.intersectStraightPlane(o, d, point, normal, prevIntersectPoint);\r
+        }\r
+        if (!input.mouseDragged())\r
+            return;\r
+        parent.setViewChanged(true);\r
+        Vector3d msTmp = new Vector3d();\r
+        msTmp.x = (input.prevMouseX() - input.mouseX()) / 100f;\r
+        msTmp.y = (input.prevMouseY() - input.mouseY()) / 100f;\r
+\r
+        if ((input.dragModifiers() & MouseEvent.BUTTON1_MASK) > 0) {\r
+            if ((input.dragModifiers() & MouseEvent.CTRL_MASK) > 0) {\r
+                Vector3d o = new Vector3d();\r
+                Vector3d d = new Vector3d();\r
+                parent.createPickRay(o, d);\r
+                Vector3d point = new Vector3d(camera.getTarget());\r
+                Vector3d normal = camera.getUnNormalizedHeading();\r
+                normal.normalize();\r
+                Vector3d intersectPoint = new Vector3d();\r
+                if (MathTools.intersectStraightPlane(o, d, point, normal, intersectPoint)) {\r
+                    Vector3d delta = new Vector3d(intersectPoint);\r
+                    delta.sub(prevIntersectPoint);\r
+                    prevIntersectPoint = intersectPoint;\r
+                    delta.negate();\r
+                    camera.translate(delta);\r
+                    prevIntersectPoint.add(delta);\r
+                } else {\r
+                    camera.moveRight((float) msTmp.x);\r
+                    camera.moveUp(-(float) msTmp.y);\r
+                }\r
+            } else {\r
+                camera.rotateRight((float) msTmp.x);\r
+                camera.rotateUp((float) msTmp.y);\r
+            }\r
+        } else if ((input.dragModifiers() & MouseEvent.BUTTON2_MASK) > 0) {\r
+            // System.out.println("zoom");\r
+            if (component.getProjectionPolicy() == JmeRenderingComponent.PERSPECTIVE_PROJECTION) {\r
+                camera.moveScaledToTarget((float) msTmp.y * 0.5f);\r
+            } else {\r
+                component.setScreenScale(component.getScreenScale() - (float) msTmp.y * 0.5f * component.getScreenScale());\r
+            }\r
+        }\r
+//        } else {\r
+//            System.out.println("cameraAction!");\r
+//            System.out.println(input);\r
+//        } \r
+       \r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ConstrainedTransformAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ConstrainedTransformAction.java
new file mode 100644 (file)
index 0000000..1cd0b59
--- /dev/null
@@ -0,0 +1,74 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.base.ConstraintDetector;\r
+import org.simantics.proconf.g3d.base.JmeRenderingComponent;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.common.OrbitalCamera;\r
+\r
+\r
+public abstract class ConstrainedTransformAction extends WriteInteractiveAction {\r
+       private static final ImageDescriptor LOCK_ICON = Activator.imageDescriptorFromPlugin("org.simantic.proconf.g3d", "icons/silk/lock.png");\r
+       private static final ImageDescriptor LOCK_OPEN_ICON = Activator.imageDescriptorFromPlugin("org.simantic.proconf.g3d", "icons/silk/lock_open.png");\r
+       \r
+       protected JmeRenderingComponent component;\r
+       protected OrbitalCamera camera;\r
+       \r
+    protected boolean useConstraints = false;\r
+    protected ConstraintDetector detector;\r
+    \r
+    protected Action useConstraintsAction;\r
+    \r
+    //protected IToolBarManager manager;\r
+    \r
+       public ConstrainedTransformAction(ThreeDimensionalEditorBase editor) {\r
+               super(editor, true);\r
+               component = parent.getRenderingComponent();\r
+               camera = parent.getCamera();\r
+               detector = new ConstraintDetector(parent);\r
+               useConstraintsAction = new Action("Constraints", Action.AS_CHECK_BOX) {\r
+                       public void run() {\r
+                               useConstraints = this.isChecked();\r
+                       }\r
+\r
+                       public void setChecked(boolean b) {\r
+                               super.setChecked(b);\r
+                               if (b) {\r
+                                       setImageDescriptor(LOCK_ICON);\r
+                               } else {\r
+                                       setImageDescriptor(LOCK_OPEN_ICON);\r
+                               }\r
+                       }\r
+               };\r
+               useConstraintsAction.setImageDescriptor(LOCK_OPEN_ICON);\r
+\r
+       }\r
+       \r
+       @Override\r
+       public void deactivate() {\r
+               detector.clearConstraintHighlights();\r
+       }\r
+       \r
+       @Override\r
+       public void fillToolBar(IToolBarManager manager) {\r
+                //this.manager = manager;\r
+                useConstraintsAction.setChecked(useConstraints);\r
+                manager.add(useConstraintsAction);\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ContextAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ContextAction.java
new file mode 100644 (file)
index 0000000..c86858d
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+\r
+\r
+/**\r
+ * Context / selection dependent action\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public abstract class ContextAction extends Action {\r
+    protected ThreeDimensionalEditorBase parent;\r
+\r
+    public ContextAction(ThreeDimensionalEditorBase parent) {\r
+        this.parent = parent;\r
+        init();\r
+    }\r
+    \r
+    /**\r
+     * Initialization\r
+     */\r
+    public void init(){};\r
\r
+    /**\r
+     * Runs the action\r
+     */\r
+    public abstract void run();\r
+    \r
+    /**\r
+     * Used to check if action is usable for given resources\r
+     * @param resources\r
+     * @return\r
+     */\r
+    public abstract boolean usable(Graph graph, List<Resource> resources);\r
+    \r
+    \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ContextActionFactory.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ContextActionFactory.java
new file mode 100644 (file)
index 0000000..ce6638a
--- /dev/null
@@ -0,0 +1,20 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+\r
+\r
+public interface ContextActionFactory {\r
+       \r
+       \r
+       public ContextAction createAction(ThreeDimensionalEditorBase editor);\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ContextActionRegistry.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ContextActionRegistry.java
new file mode 100644 (file)
index 0000000..bb8ffbc
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.utils.ui.plugin.Extension;\r
+import org.simantics.utils.ui.plugin.ExtensionLoader;\r
+\r
+\r
+\r
+public class ContextActionRegistry {\r
+       /*\r
+    private static ContextActionRegistry instance;\r
+    public final static String ELEMENT_NAME = "ContextAction";\r
+    public final static String NAME_SPACE = "org.simantics.proconf.g3d";\r
+    public final static String EP_NAME = "contextaction";\r
+    \r
+    private ExtensionLoader<ContextActionFactory> loader;\r
+    \r
+    private ContextActionRegistry() {\r
+        loader = new ExtensionLoader<ContextActionFactory>(ELEMENT_NAME, NAME_SPACE, EP_NAME);\r
+    }\r
+    \r
+    public static ContextActionRegistry getInstance() {\r
+        if (instance==null) instance = new ContextActionRegistry();\r
+        return instance;\r
+    }\r
+\r
+    public Extension<ContextActionFactory>[] getExtensions() {\r
+        return loader.getExtensions();\r
+    }\r
+\r
+    \r
+    public static ContextActionFactory[] getActions(String editorID) {\r
+       List<ContextActionFactory> list = new ArrayList<ContextActionFactory>();\r
+       for (Extension<ContextActionFactory> e : getInstance().getExtensions()) {\r
+               if(e.getStringField("editorid").compareTo(editorID) == 0) {\r
+                       list.add(e.getInstance());\r
+               }\r
+       }\r
+       return list.toArray(new ContextActionFactory[0]);\r
+    }\r
+    */\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/FocusAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/FocusAction.java
new file mode 100644 (file)
index 0000000..7893f23
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.base.G3DTools;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.common.OrbitalCamera;\r
+import org.simantics.proconf.g3d.stubs.Tuple3;\r
+\r
+public class FocusAction extends ContextAction{\r
+\r
+       private OrbitalCamera camera;\r
+       \r
+    Vector3d focusPoint = null;\r
+    \r
+    public FocusAction(ThreeDimensionalEditorBase parent) {\r
+        super(parent);\r
+        camera = parent.getCamera();\r
+    }\r
+    \r
+    public void init() {\r
+        this.setText("Focus");\r
+        this.setToolTipText("Focus");\r
+        this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/eye.png"));\r
+    }\r
+    \r
+\r
+    \r
+    @Override\r
+  public boolean usable(Graph graph,List<Resource> resources) {\r
+      if (resources.size() != 1)\r
+          return false;\r
+      IEntity t = EntityFactory.create(graph, resources.get(0));\r
+      \r
+      if (t.isInstanceOf(Resources.g3dResource.G3DNode)) {\r
+          Collection<IEntity> p = t.getRelatedObjects(Resources.g3dResource.HasWorldPosition);\r
+          if (p == null || p.size() != 1)\r
+              return false;\r
+          else \r
+              //focusPoint = new Vector3d(G3DTools.getPoint(new Position(graph,p.iterator().next().getResource())));\r
+              focusPoint = new Vector3d(G3DTools.getPoint(new Tuple3(graph,p.iterator().next().getResource())));\r
+      }\r
+      return true;\r
+  }\r
+    \r
+    public void run() {\r
+        camera.setTarget(focusPoint);\r
+        parent.setViewChanged(true);\r
+    }\r
+\r
+   \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/InteractiveAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/InteractiveAction.java
new file mode 100644 (file)
index 0000000..a797434
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.input.InputProvider;\r
+\r
+\r
+\r
+/**\r
+ * Context / selection dependent action that requires user's interaction\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public abstract class InteractiveAction extends ContextAction {\r
+    protected InputProvider input;\r
+    \r
+    public InteractiveAction(ThreeDimensionalEditorBase parent) {\r
+        super(parent);\r
+        input = parent.getInputProvider();\r
+    }\r
+    \r
+    public abstract void update() ;\r
+\r
+    /**\r
+     * Activates the action\r
+     */\r
+    public abstract void activate();\r
+\r
+    /**\r
+     * Deactivates / ends the action\r
+     */\r
+    public abstract void deactivate();\r
+    \r
+    /**\r
+     * Activates the action in the viewer. Normally there's no need to override this method.\r
+     */\r
+    public final void run() {\r
+        parent.setCurrentAction(this);\r
+    }\r
+    \r
+    /**\r
+     * This method is used to end the action, call this from <code>update()</code>.\r
+     *\r
+     */\r
+    public void end() {\r
+        parent.setCurrentAction(parent.getDefaultAction());\r
+    }\r
+    \r
+    public void fillToolBar(IToolBarManager manager) {\r
+        \r
+    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ReadAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ReadAction.java
new file mode 100644 (file)
index 0000000..36fcc4b
--- /dev/null
@@ -0,0 +1,52 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequest;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Session;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+\r
+public abstract class ReadAction extends ContextAction {\r
+       boolean sync;\r
+       public ReadAction(ThreeDimensionalEditorBase parent, boolean sync) {\r
+               super(parent);\r
+               this.sync = sync;\r
+       }\r
+\r
+       @Override\r
+       public final void run() {\r
+               Session session = parent.getSession();\r
+               if(!canActivate()) {\r
+                       return;\r
+               }\r
+               GraphRequest r = new GraphRequestAdapter() {\r
+                       @Override\r
+                       public GraphRequestStatus perform(Graph g) throws Exception {\r
+                               doChanges(g);\r
+                               return GraphRequestStatus.transactionComplete();\r
+                       }\r
+               };\r
+               if (sync) {\r
+                       session.syncRead(r);\r
+               } else {\r
+                       session.asyncRead(r);\r
+               } \r
+       }\r
+       \r
+       public abstract void doChanges(Graph graph) throws Exception;\r
+\r
+       public boolean canActivate() {\r
+               return true;\r
+       }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ReadInteractiveAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/ReadInteractiveAction.java
new file mode 100644 (file)
index 0000000..9bd972c
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequest;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Session;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+\r
+public abstract class ReadInteractiveAction extends InteractiveAction {\r
+       boolean sync;\r
+       \r
+       public ReadInteractiveAction(ThreeDimensionalEditorBase parent, boolean sync) {\r
+               super(parent);\r
+               this.sync = sync;\r
+       }\r
+       \r
+       @Override\r
+       public final void update(){\r
+               Session session = parent.getSession();\r
+               GraphRequest r = new GraphRequestAdapter() {\r
+                       @Override\r
+                       public GraphRequestStatus perform(Graph g) throws Exception {\r
+                               doChanges(g);\r
+                               return GraphRequestStatus.transactionComplete();\r
+                       }\r
+               };\r
+               if (sync) {\r
+                       session.syncRead(r);\r
+               } else {\r
+                       session.asyncRead(r);\r
+               } \r
+       }\r
+\r
+       \r
+       public abstract void doChanges(Graph graph) throws Exception;\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/RemoveAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/RemoveAction.java
new file mode 100644 (file)
index 0000000..ac9bdfa
--- /dev/null
@@ -0,0 +1,56 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import java.util.List;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
+\r
+public class RemoveAction extends WriteAction {\r
+    \r
+    public RemoveAction(ThreeDimensionalEditorBase parent) {\r
+        super(parent,false);\r
+    }\r
+    \r
+    public void init() {\r
+        setText("Remove");\r
+        setToolTipText("Remove the object");\r
+        this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/delete.png"));\r
+    }\r
+    public GraphRequestStatus doChanges(Graph graph) {\r
+        StructuredResourceSelection sel = parent.getSelectionAdapter().getCurrentSelection();\r
+        List<Resource> res = sel.getSelectionList();\r
+        for (Resource r : res) {\r
+                IEntity t = EntityFactory.create(graph, r);\r
+                if (t.isInstanceOf(Resources.g3dResource.G3DNode)) {\r
+                    IEntity parentNode = t.getSingleRelatedObject(Resources.g3dResource.HasParent);\r
+                    parentNode.removeStatement(Resources.g3dResource.HasChild, t);\r
+                }\r
+\r
+            }\r
+        return GraphRequestStatus.transactionComplete();\r
+     \r
+    }\r
+    \r
+    @Override\r
+    public boolean usable(Graph graph,List<Resource> resources) {\r
+        return resources.size() > 0;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/RotateAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/RotateAction.java
new file mode 100644 (file)
index 0000000..fe6fc71
--- /dev/null
@@ -0,0 +1,453 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.MouseEvent;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.AxisAngle4f;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequest;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.base.G3DTools;\r
+import org.simantics.proconf.g3d.base.JmeRenderingComponent;\r
+import org.simantics.proconf.g3d.base.MathTools;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.base.VecmathJmeTools;\r
+import org.simantics.proconf.g3d.common.OrbitalCamera;\r
+import org.simantics.proconf.g3d.gizmo.RotateGizmo;\r
+import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+\r
+public class RotateAction extends WriteInteractiveAction {\r
+       \r
+       private JmeRenderingComponent component;\r
+       \r
+    private RotateGizmo gizmo;\r
+\r
+    private OrbitalCamera camera;\r
+    \r
+    private Map<IGraphicsNode, AxisAngle4d > rotations = new HashMap<IGraphicsNode, AxisAngle4d>();\r
+    \r
+    private int steps; \r
+    private double angles[];\r
+    \r
+    private Action csAction;\r
+    private boolean worldCoord = true;\r
+    private IToolBarManager manager;\r
+    \r
+    private List<IGraphicsNode> mos;\r
+    AxisAngle4d aa;\r
+    Quat4d q;\r
+    \r
+    public RotateAction(ThreeDimensionalEditorBase parent) {\r
+        super(parent,true);\r
+        component = parent.getRenderingComponent();\r
+        camera = parent.getCamera();\r
+        gizmo = new RotateGizmo(component.getDisplaySystem().getRenderer());\r
+        csAction = new Action("World",Action.AS_CHECK_BOX) {\r
+               public void run() {\r
+                       GraphRequest r = new GraphRequestAdapter() {\r
+                               @Override\r
+                               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                                       setWorldCoord(g,!isChecked());\r
+                                       return GraphRequestStatus.transactionComplete();\r
+                               }\r
+                       };\r
+                       RotateAction.this.parent.getSession().asyncRead(r);\r
+                       \r
+               }\r
+        };\r
+    }\r
+    \r
+    public void init() {\r
+        this.setText("Rotate");\r
+        this.setToolTipText("Rotate the object");\r
+        this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/rotate.png"));\r
+        steps = 36;\r
+        angles = new double[steps+1];\r
+        for (int i = 0; i < angles.length; i++) {\r
+            angles[i] = - Math.PI + (Math.PI * i * 2.0 / steps);\r
+        }\r
+    }\r
+    \r
+    @Override\r
+    public boolean usable(Graph graph, List<Resource> resources) {\r
+        if (resources.size() == 0)\r
+            return false;\r
+        for (Resource r : resources) {\r
+               IEntity t = EntityFactory.create(graph,r);\r
+            if (t.isInstanceOf(Resources.g3dResource.G3DNode)) {\r
+                Collection<IEntity> p = t.getRelatedObjects(Resources.g3dResource.HasLocalOrientation);\r
+                if (p == null || p.size() != 1)\r
+                    return false;\r
+            }\r
+               \r
+        }\r
+        return true;\r
+        \r
+    }\r
+    \r
+    @Override\r
+    public void deactivate() {\r
+       inputType = InputType.NONE;\r
+        parent.setGizmo(null);\r
+        mos = null;\r
+\r
+    }\r
+    \r
+    public void fillToolBar(IToolBarManager manager) {\r
+       super.fillToolBar(manager);\r
+       this.manager = manager;\r
+        csAction.setChecked(!worldCoord);\r
+        manager.add(csAction);\r
+        \r
+    }\r
+    \r
+    private void setWorldCoord(Graph graph,boolean b) {\r
+       if (worldCoord == b)\r
+               return;\r
+       worldCoord = b;\r
+       updateWorldCoord(graph);\r
+    }\r
+    \r
+    private void updateWorldCoord(Graph graph) {\r
+       if (worldCoord) {\r
+                       csAction.setText("World");\r
+                       gizmo.setRotation(new AxisAngle4f());\r
+                       aa = null;\r
+                       q = null;\r
+       } else {\r
+                       csAction.setText("Local");\r
+                       aa = G3DTools.getOrientation(mos.get(0).getParent().getG3DNode(graph).getWorldOrientation());\r
+                       if (aa == null)\r
+                               aa = new AxisAngle4d();\r
+                       gizmo.setRotation(new AxisAngle4f(aa));\r
+                       q = new Quat4d();\r
+               q.set(aa);\r
+       }\r
+       if (manager != null)\r
+               manager.update(true);\r
+       this.parent.setViewChanged(true);\r
+    }\r
+    \r
+    @Override\r
+    public void activate() {\r
+       \r
+       Session session = parent.getSession();\r
+       \r
+       GraphRequest r = new GraphRequestAdapter() {\r
+               @Override\r
+               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                       parent.setGizmo(gizmo);\r
+               \r
+               component.getNoShadowRoot().attachChild(gizmo.getNode());\r
+               updateGizmo();\r
+\r
+               String text = "";\r
+               mos = parent.getSelectionAdapter().getSelectedObjects();\r
+               rotations = new HashMap<IGraphicsNode, AxisAngle4d>();\r
+               for (IGraphicsNode mo : mos) {\r
+                       G3DNode n = mo.getG3DNode(g);\r
+                   rotations.put(mo,G3DTools.getOrientation(n.getLocalOrientation()));\r
+                   text += G3DTools.getOrientation(n.getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(g).getLocalOrientation())) + " ";\r
+               }\r
+               setInfoText(text);\r
+               parent.setViewChanged(true);\r
+               inputType = InputType.NONE;\r
+               return GraphRequestStatus.transactionComplete();\r
+               }\r
+       };\r
+       \r
+       session.syncRead(r);\r
+       \r
+        \r
+    }\r
+    \r
+    \r
+    private Vector3d getRotationAxis() {\r
+        switch (gizmo.getSelected()) {\r
+        case RotateGizmo.X:\r
+            return new Vector3d(1.0,0.0,0.0);\r
+        case RotateGizmo.Y:\r
+            return new Vector3d(0.0,1.0,0.0);\r
+        case RotateGizmo.Z:\r
+            return new Vector3d(0.0,0.0,1.0);\r
+        case RotateGizmo.XYZ:\r
+            Vector3d axis = camera.getUnNormalizedHeading();\r
+            axis.normalize();\r
+            return axis;\r
+        default:\r
+            return null;\r
+        }\r
+    }\r
+    private double prevS = 0.0;\r
+    \r
+    private Vector3d i = new Vector3d();\r
+    private Vector3d j = new Vector3d();\r
+    private double prevAngle = 0;\r
+\r
+    enum InputType{INTERSECT,NONINTERSECT,KEY,NONE};\r
+    InputType inputType;\r
+    private boolean useStep = false;\r
+    \r
+    @Override\r
+    public void doChanges(Graph graph) throws Exception {\r
+       \r
+        if (input.mousePressed()) {\r
+            Vector3d axis = getRotationAxis();\r
+            if (axis != null) {\r
+               if (!worldCoord) {\r
+                       MathTools.rotate(q, axis, axis);\r
+               }\r
+                Vector3d o = new Vector3d();\r
+                Vector3d d = new Vector3d();\r
+                parent.createPickRay(o, d);\r
+                Vector3d p = gizmo.getPosition();\r
+                double s[] = new double[2];\r
+                Vector3d i2 = new Vector3d();\r
+                if ((input.pressModifiers() & MouseEvent.CTRL_MASK) > 0) {\r
+                    useStep = true;\r
+                } else {\r
+                    useStep = false;\r
+                }\r
+                if (MathTools.intersectStraightPlane(o, d, p, axis, i2, s) && Math.abs(d.dot(axis)) > 0.2)\r
+                       inputType = InputType.INTERSECT;\r
+                else\r
+                       inputType = InputType.NONINTERSECT;\r
+                       \r
+                \r
+                if (inputType == InputType.INTERSECT) {\r
+                    // picking ray and plane defined by gizmo's center point and\r
+                    // rotation axis can intersect\r
+                    // vector from center point to intersection point\r
+                    i2.sub(p);\r
+                    // creating vectors i and j that are lying on the plane and\r
+                    // are perpendicular\r
+                    // vectors are used to calculate polar coordinate for\r
+                    // intersection point\r
+                    j.set(i2);\r
+                    i.cross(j, axis);\r
+                    double angleI = i2.angle(i);\r
+                    double angleJ = i2.angle(j);\r
+                    prevAngle = Math.atan2(Math.cos(angleJ), Math.cos(angleI));\r
+                } else {\r
+                    // picking ray and plane defined by gizmo's center point and\r
+                    // rotation axis are parallel,\r
+                    // so we'll use cross product of rotation axis and picking\r
+                    // ray to detect amount of rotation\r
+                    i.cross(d, axis);\r
+                    MathTools.intersectStraightStraight(o, d, p, i, new Vector3d(), new Vector3d(), s);\r
+                    prevS = s[1];\r
+                }\r
+            }\r
+           \r
+            \r
+        }\r
+        if (input.mouseClicked()) {\r
+            end();\r
+            return;\r
+        }\r
+        Vector3d axis = null;\r
+        if (input.keyPressed(KeyEvent.VK_LEFT)) {\r
+               inputType = InputType.KEY;\r
+               axis = new Vector3d(0.0,1.0,0.0);\r
+        } else if (input.keyPressed(KeyEvent.VK_RIGHT)) {\r
+               inputType = InputType.KEY;\r
+               axis = new Vector3d(0.0,-1.0,0.0);\r
+        } else if (input.keyPressed(KeyEvent.VK_UP)) {\r
+               inputType = InputType.KEY;\r
+               axis = new Vector3d(1.0,0.0,0.0);\r
+        } else if (input.keyPressed(KeyEvent.VK_DOWN)) {\r
+               inputType = InputType.KEY;\r
+               axis = new Vector3d(-1.0,0.0,0.0);\r
+        } else if (!input.mouseDragged()) {\r
+            parent.getDefaultAction().update();\r
+            return;\r
+        }\r
+        parent.setViewChanged(true);\r
+        \r
+        \r
+        updateGizmo();\r
+        List<IGraphicsNode> mos = parent.getSelectionAdapter().getSelectedObjects();\r
+        if (inputType != InputType.KEY)\r
+               axis = getRotationAxis();\r
+        if (axis == null) {\r
+            parent.getDefaultAction().update();\r
+            return;   \r
+        }\r
+        Vector3d taxis = null;\r
+        if (!worldCoord) {\r
+               taxis = new Vector3d(axis);\r
+               MathTools.rotate(q, axis, axis);\r
+       }\r
+        String text = "";\r
+        if (inputType == InputType.INTERSECT) {\r
+            Vector3d o = new Vector3d();\r
+            Vector3d d = new Vector3d();\r
+            parent.createPickRay(o, d);\r
+            Vector3d p = gizmo.getPosition();\r
+            double s[] = new double[2];\r
+            Vector3d i2 = new Vector3d();\r
+            MathTools.intersectStraightPlane(o, d, p, axis, i2, s);\r
+            i2.sub(p);\r
+            double angleI = i2.angle(i);\r
+            double angleJ = i2.angle(j);\r
+            double angle = Math.atan2(Math.cos(angleJ), Math.cos(angleI));\r
+            if(!worldCoord)\r
+               axis = taxis;\r
+            if (false && useStep) {\r
+                for (IGraphicsNode mo : mos) {\r
+                    G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), rotations.get(mo));\r
+                    // FIXME : commit\r
+                    G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,angle-prevAngle));\r
+                    //mo.setRotation(rotations.get(mo));\r
+                    //mo.modifyWorldRotation(axis, angle - prevAngle);\r
+                    AxisAngle4d aa = G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation());\r
+                    rotations.put(mo, aa);\r
+                    prevAngle = angle;\r
+                    Vector3d euler = MathTools.getEuler(aa);\r
+                    euler.x = roundAngle(euler.x);\r
+                    euler.y = roundAngle(euler.y);\r
+                    euler.z = roundAngle(euler.z);\r
+                    aa = MathTools.getFromEuler2(euler);\r
+                    G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), aa);\r
+                    //mo.setRotation(aa);\r
+                    Vector3d e = MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()));\r
+                    e.scale(180.0/Math.PI);\r
+                    text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + e + " ";\r
+                }\r
+            } else  {\r
+                for (IGraphicsNode mo : mos) {\r
+                    if (worldCoord)\r
+                               G3DTools.multiplyOrientation\r
+                               (mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,angle-prevAngle));\r
+                       else\r
+                               G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,angle-prevAngle));\r
+                       text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation())) + " ";\r
+                }\r
+                prevAngle = angle;\r
+            }\r
+            \r
+        } else if (inputType == InputType.NONINTERSECT){\r
+            Vector3d o = new Vector3d();\r
+            Vector3d d = new Vector3d();\r
+            parent.createPickRay(o, d);\r
+            Vector3d p = gizmo.getPosition();\r
+            double s[] = new double[2];\r
+            MathTools.intersectStraightStraight(o, d, p, i, new Vector3d(), new Vector3d(), s);\r
+            if(!worldCoord)\r
+               axis = taxis;\r
+            if (false && useStep) {\r
+                for (IGraphicsNode mo : mos) {\r
+                    G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), rotations.get(mo));\r
+                    G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
+                    //mo.setRotation(rotations.get(mo));\r
+                    //mo.modifyWorldRotation(axis, s[1] - prevS);\r
+                    AxisAngle4d aa = G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation());\r
+                    rotations.put(mo, aa);\r
+                    Vector3d euler = MathTools.getEuler(aa);\r
+                    euler.x = roundAngle(euler.x);\r
+                    euler.y = roundAngle(euler.y);\r
+                    euler.z = roundAngle(euler.z);\r
+                    aa = MathTools.getFromEuler2(euler);\r
+                    prevS = s[1];\r
+                    G3DTools.setOrientation(mo.getG3DNode(graph).getLocalOrientation(), aa);\r
+                    //mo.setRotation(aa);\r
+                    Vector3d e = MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()));\r
+                    e.scale(180.0/Math.PI);\r
+                    text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + e + " ";\r
+                }\r
+            } else {\r
+                for (IGraphicsNode mo : mos) {\r
+                       if (worldCoord)\r
+                               G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
+                       else\r
+                               G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,s[1] - prevS));\r
+                    text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation())) + " ";\r
+                }\r
+                prevS = s[1];\r
+                \r
+            }\r
+           \r
+        } else {\r
+               for (IGraphicsNode mo : mos) {\r
+               if (worldCoord)\r
+                       G3DTools.multiplyOrientation(mo.getG3DNode(graph).getWorldOrientation(), new AxisAngle4d(axis,Math.PI * 0.5));\r
+               else\r
+                       G3DTools.multiplyOrientation(mo.getG3DNode(graph).getLocalOrientation(), new AxisAngle4d(axis,Math.PI * 0.5));\r
+                text += G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation()) + " " + MathTools.getEuler(G3DTools.getOrientation(mo.getG3DNode(graph).getLocalOrientation())) + " ";\r
+            }\r
+        }\r
+        setInfoText(text);\r
\r
+    }\r
+    /*\r
+    private double roundAngle(double current, double modify) {\r
+        double angle = roundAngle(current+modify);\r
+        if (Double.isNaN(angle)) {\r
+            angle = current+modify;\r
+        }\r
+        //System.out.println(angle + " " + (current+modify));\r
+        return angle;\r
+    }\r
+    */\r
+    \r
+    private double roundAngle(double angle) {\r
+        while (angle < - Math.PI)\r
+            angle += Math.PI*2.0;\r
+        while (angle > Math.PI)\r
+            angle -= Math.PI*2.0;\r
+        \r
+        \r
+        int index = 0;\r
+        while (angle > angles[index])\r
+            index++;\r
+        if (index == 0) {\r
+            angle = angles[0];\r
+        } else {\r
+            double d = angle - angles[index - 1];\r
+            double d2 = angles[index] - angle;\r
+            if (d < d2)\r
+                angle = angles[index - 1];\r
+            else\r
+                angle = angles[index];\r
+        }\r
+        return angle;\r
+    }\r
+    \r
+    private void updateGizmo() {\r
+        List<IGraphicsNode> mos = parent.getSelectionAdapter().getSelectedObjects();\r
+        //gizmo.update(XithTools.getPosition(mos.get(0).getGroup()),camera.getCameraPos(),component);\r
+        gizmo.update(VecmathJmeTools.getD(mos.get(0).getGroup().getWorldTranslation()),camera.getCameraPos(),component);\r
+    }\r
+    \r
+    public void setInfoText(String text) {\r
+       \r
+    }\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/TranslateAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/TranslateAction.java
new file mode 100644 (file)
index 0000000..d4630a1
--- /dev/null
@@ -0,0 +1,422 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import java.awt.event.MouseEvent;\r
+import java.math.BigDecimal;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.AxisAngle4f;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequest;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.base.G3DTools;\r
+import org.simantics.proconf.g3d.base.MathTools;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.gizmo.TransformGizmo;\r
+import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
+import org.simantics.proconf.g3d.stubs.Orientation;\r
+import org.simantics.proconf.g3d.stubs.Position;\r
+\r
+\r
+public class TranslateAction extends ConstrainedTransformAction {\r
+       \r
+       \r
+    private TransformGizmo gizmo;\r
+    \r
+    private double istep = 10.0;\r
+    private int decimals = 2;\r
+    \r
+    \r
+    private Action csAction;\r
+    List<IGraphicsNode> mos = null;\r
+    \r
+    private boolean worldCoord = true;\r
+    \r
+    \r
+    private AxisAngle4d aa;\r
+    private Quat4d q;\r
+    \r
+    public TranslateAction(ThreeDimensionalEditorBase parent) {\r
+        super(parent);\r
+        \r
+        csAction = new Action("World",Action.AS_CHECK_BOX) {\r
+               public void run() {\r
+                       GraphRequest r = new GraphRequestAdapter() {\r
+                               @Override\r
+                               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                                       setWorldCoord(g,!isChecked());\r
+                                       return GraphRequestStatus.transactionComplete();\r
+                               }\r
+                       };\r
+                       TranslateAction.this.parent.getSession().asyncRead(r);\r
+                       \r
+               }\r
+        };\r
+        gizmo = new TransformGizmo(component.getDisplaySystem().getRenderer());\r
+    }\r
+    \r
+    public void init() {\r
+        this.setText("Translate");\r
+        this.setToolTipText("Translate the object");\r
+        this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/translate.png"));\r
+    }\r
+    \r
+    @Override\r
+    public boolean usable(Graph graph, List<Resource> resources) {\r
+        if (resources.size() == 0)\r
+            return false;\r
+        for (Resource r : resources) {\r
+               IEntity t = EntityFactory.create(graph,r);\r
+            if (t.isInstanceOf(Resources.g3dResource.G3DNode)) {\r
+                Collection<IEntity> p = t.getRelatedObjects(Resources.g3dResource.HasLocalPosition);\r
+                if (p == null || p.size() != 1)\r
+                    return false;\r
+            }\r
+               \r
+        }\r
+        return true;\r
+        \r
+    }\r
+    \r
+    @Override\r
+    public void deactivate() {\r
+       super.deactivate();\r
+        parent.setGizmo(null);\r
+        mos = null;\r
+    }\r
+    \r
+    private void setWorldCoord(Graph graph,boolean b) {\r
+       if (worldCoord == b)\r
+               return;\r
+       worldCoord = b;\r
+       updateWorldCoord(graph);\r
+    }\r
+    \r
+    private void updateWorldCoord(Graph graph) {\r
+       if (worldCoord) {\r
+                       csAction.setText("World");\r
+                       gizmo.setRotation(new AxisAngle4f());\r
+                       aa = null;\r
+                       q = null;\r
+       } else {\r
+                       csAction.setText("Local");\r
+                       Orientation o = mos.get(0).getParent().getG3DNode(graph).getWorldOrientation();\r
+                       if (o == null) {\r
+                               aa = new AxisAngle4d();\r
+                       } else {\r
+                               aa = G3DTools.getOrientation(o);\r
+                       }\r
+                               \r
+                       gizmo.setRotation(new AxisAngle4f(aa));\r
+                       q = new Quat4d();\r
+                       q.set(aa);\r
+       }\r
+//     if (manager != null)\r
+//             parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() {\r
+//                     public void run() {\r
+//                             manager.update(true);\r
+//                     }\r
+//             });\r
+               \r
+       this.parent.setViewChanged(true);\r
+    }\r
+    \r
+    public void fillToolBar(IToolBarManager manager) {\r
+       super.fillToolBar(manager);\r
+        csAction.setChecked(!worldCoord);\r
+        manager.add(csAction);\r
+    }\r
+\r
+    @Override\r
+    public void activate() {\r
+       GraphRequest r = new GraphRequestAdapter() {\r
+               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                       parent.setGizmo(gizmo);\r
+\r
+               updateGizmo(g);\r
+\r
+               component.getNoShadowRoot().attachChild(gizmo.getNode());\r
+               \r
+               String text = "";\r
+               mos = parent.getSelectionAdapter().getSelectedObjects();\r
+               for (IGraphicsNode mo : mos) {\r
+                       if (worldCoord)\r
+                               text += G3DTools.getVector(mo.getG3DNode(g).getWorldPosition()) + " ";//mo.getWorldPosition() + " ";\r
+                       else\r
+                               text += G3DTools.getVector(mo.getG3DNode(g).getLocalPosition()) + " ";\r
+               }\r
+               final String fText = text;\r
+               parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() {\r
+                       public void run() {\r
+                               setInfoText(fText);    \r
+                       }\r
+               });\r
+               \r
+               Resource r[] = new Resource[mos.size()];\r
+               for (int i = 0; i < mos.size(); i++) {\r
+                   r[i] = mos.get(i).getResource();\r
+               }\r
+               \r
+               TranslateActionConstraints.addConstraints(r, detector);   \r
+               updateWorldCoord(g);\r
+               return GraphRequestStatus.transactionComplete();\r
+               };\r
+         \r
+       };\r
+       parent.getSession().asyncRead(r);\r
+        \r
+    }\r
+    \r
+    Vector3d getTranslate(Graph graph) {\r
+        return getTranslate(graph,new Vector3d());\r
+    }\r
+    \r
+    Vector3d getTranslate(Graph graph,Vector3d offset) {\r
+        Vector3d translate = new Vector3d();\r
+        Vector3d o = new Vector3d();\r
+        Vector3d d = new Vector3d();\r
+        parent.createPickRay(o, d);\r
+        Vector3d p = G3DTools.getVector(mos.get(0).getG3DNode(graph).getWorldPosition());//gizmo.getPosition();\r
+        Vector3d dir = null;\r
+        switch (gizmo.getSelected()) {\r
+        case TransformGizmo.XYZ :\r
+            Vector3d normal = camera.getUnNormalizedHeading();\r
+            if(!worldCoord)\r
+               MathTools.rotate(q, normal, normal);\r
+            normal.normalize();\r
+            double s[] = new double[1];\r
+            Vector3d r = new Vector3d();\r
+            if (MathTools.intersectStraightPlane(o, d, p, normal, r)) {\r
+                r.sub(p);\r
+                translate.x = r.x;\r
+                translate.y = r.y;\r
+                translate.z = r.z;\r
+            }\r
+            break;\r
+        case TransformGizmo.X :\r
+            dir = new Vector3d(1.0,0.0,0.0);\r
+            if(!worldCoord)\r
+               MathTools.rotate(q, dir, dir);\r
+            Vector3d i1 = new Vector3d();\r
+            Vector3d i2 = new Vector3d();\r
+            s = new double[2];\r
+            MathTools.intersectStraightStraight( p, dir,o, d, i2, i1,s);\r
+            translate.x = s[0];\r
+            \r
+            break;\r
+        case TransformGizmo.Y :\r
+            dir = new Vector3d(0.0,1.0,0.0);\r
+            if(!worldCoord)\r
+               MathTools.rotate(q, dir, dir);\r
+            i1 = new Vector3d();\r
+            i2 = new Vector3d();\r
+            s = new double[2];\r
+            MathTools.intersectStraightStraight( p, dir,o, d, i2, i1,s);\r
+            translate.y = s[0];\r
+            break;\r
+        case TransformGizmo.Z :\r
+            dir = new Vector3d(0.0,0.0,1.0);\r
+            if(!worldCoord)\r
+               MathTools.rotate(q, dir, dir);\r
+            i1 = new Vector3d();\r
+            i2 = new Vector3d();\r
+            s = new double[2];\r
+            MathTools.intersectStraightStraight( p, dir,o, d, i2, i1,s);\r
+            translate.z = s[0];\r
+            break;\r
+        case TransformGizmo.XY :\r
+            normal = new Vector3d(0.0,0.0,1.0);\r
+            if(!worldCoord)\r
+               MathTools.rotate(q, normal, normal);\r
+            r = new Vector3d();\r
+            if (MathTools.intersectStraightPlane(o, d, p, normal, r)) {\r
+                r.sub(p);\r
+                translate.x = r.x;\r
+                translate.y = r.y;\r
+            }\r
+            break;\r
+        case TransformGizmo.XZ :\r
+            normal = new Vector3d(0.0,1.0,0.0);\r
+            if(!worldCoord)\r
+               MathTools.rotate(q, normal, normal);\r
+            r = new Vector3d();\r
+            if (MathTools.intersectStraightPlane(o, d, p, normal, r)) {\r
+                r.sub(p);\r
+                translate.x = r.x;\r
+                translate.z = r.z;\r
+            }\r
+            break;\r
+        case TransformGizmo.YZ :\r
+            normal = new Vector3d(1.0,0.0,0.0);\r
+            if(!worldCoord)\r
+               MathTools.rotate(q, normal, normal);\r
+            r = new Vector3d();\r
+            if (MathTools.intersectStraightPlane(o, d, p, normal, r)) {\r
+                r.sub(p);\r
+                translate.y = r.y;\r
+                translate.z = r.z;\r
+            }\r
+            break;\r
+        default :\r
+            \r
+            return null;\r
+        }\r
+        translate.sub(offset);\r
+        \r
+        if (useConstraints && dir != null) {\r
+            switch (gizmo.getSelected()) {\r
+            case TransformGizmo.X:\r
+            case TransformGizmo.Y:\r
+            case TransformGizmo.Z:\r
+                Vector3d t = new Vector3d(translate);\r
+                // TODO : to the test against all translated objects and snap to closest one\r
+                Point3d pos = G3DTools.getPoint(mos.get(0).getG3DNode(graph).getWorldPosition());\r
+                t.add(pos);\r
+                Point3d snap = detector.getPointSnap2(t, dir);\r
+                if (snap != null) {\r
+                   // System.out.print("t: " + translate);\r
+                    translate = new Vector3d(snap);\r
+                    translate.sub(pos);\r
+                   // System.out.println(" " + translate);\r
+                }\r
+                break;\r
+                \r
+            }\r
+        }\r
+        return translate;\r
+    }\r
+    \r
+    Vector3d prevTranslate = new Vector3d();\r
+    \r
+    @Override\r
+    public void doChanges(Graph graph) throws Exception {\r
+        if (input.mousePressed()) {\r
+            boolean b = useConstraints;\r
+            useConstraints = false;\r
+            prevTranslate = getTranslate(graph);\r
+            useConstraints = b;\r
+        }\r
+        if (input.mouseClicked()) {\r
+            end();\r
+            return;\r
+        }\r
+        if (!input.mouseDragged()) {\r
+            parent.getDefaultAction().update();\r
+            return;\r
+        }   \r
+        detector.clearConstraintHighlights();\r
+        parent.setViewChanged(true);\r
+        \r
+        \r
+        \r
+        Vector3d translate = getTranslate(graph,prevTranslate);\r
+       \r
+        if (translate == null) {\r
+            //cameraRotateAction.update();\r
+            parent.getDefaultAction().update();\r
+            updateGizmo(graph);\r
+            return;\r
+        }\r
+        //translate.sub(prevTranslate);\r
+       \r
+        if ((input.dragModifiers() & MouseEvent.CTRL_MASK) > 0) {\r
+            String text = "";\r
+            for (IGraphicsNode mo : mos) {\r
+                \r
+                Point3d p;\r
+                if (worldCoord)\r
+                       p = G3DTools.getPoint(mo.getG3DNode(graph).getWorldPosition());//mo.getWorldPosition();\r
+                else\r
+                       p = G3DTools.getPoint(mo.getG3DNode(graph).getLocalPosition());\r
+                p.add(translate);\r
+                if (gizmo.getSelected() == TransformGizmo.X || gizmo.getSelected() == TransformGizmo.XY || gizmo.getSelected() == TransformGizmo.XZ || gizmo.getSelected() == TransformGizmo.XYZ) {\r
+                    p.x = Math.round(istep * p.x) / istep;\r
+                    BigDecimal bx = new BigDecimal(p.x);\r
+                    bx.setScale(decimals, BigDecimal.ROUND_HALF_UP);\r
+                    p.x = bx.doubleValue();\r
+                }\r
+                if (gizmo.getSelected() == TransformGizmo.Y || gizmo.getSelected() == TransformGizmo.XY || gizmo.getSelected() == TransformGizmo.YZ || gizmo.getSelected() == TransformGizmo.XYZ) {\r
+                    p.y = Math.round(istep * p.y) / istep;\r
+                    BigDecimal by = new BigDecimal(p.y);\r
+                    by.setScale(decimals, BigDecimal.ROUND_HALF_UP);\r
+                    p.y = by.doubleValue();\r
+                }\r
+                if (gizmo.getSelected() == TransformGizmo.Z || gizmo.getSelected() == TransformGizmo.YZ || gizmo.getSelected() == TransformGizmo.XZ || gizmo.getSelected() == TransformGizmo.XYZ) {      \r
+                    p.z = Math.round(istep * p.z) / istep;\r
+                    BigDecimal bz = new BigDecimal(p.z);\r
+                    bz.setScale(decimals, BigDecimal.ROUND_HALF_UP);\r
+                    p.z = bz.doubleValue();\r
+                }\r
+                text += p + " ";\r
+                if (worldCoord)\r
+                       G3DTools.setTuple3(mo.getG3DNode(graph).getWorldPosition(), p); \r
+                else\r
+                       G3DTools.setTuple3(mo.getG3DNode(graph).getLocalPosition(), p);\r
+                //mo.setWorldTranslation(p);\r
+                \r
+            }\r
+            if (useConstraints)\r
+                text+=detector.getSnapString();\r
+            setInfoText(text);\r
+            \r
+        } else {\r
+            String text = "";\r
+            for (IGraphicsNode mo : mos) {\r
+               Position pos;\r
+               if (worldCoord) {\r
+                       pos = mo.getG3DNode(graph).getWorldPosition();  \r
+               } else {\r
+                       pos = mo.getG3DNode(graph).getLocalPosition();\r
+               }\r
+               Point3d p = G3DTools.getPoint(pos);\r
+                       p.add(translate);\r
+                       text += p;\r
+                       G3DTools.setTuple3(pos, p);\r
+            }\r
+            if (useConstraints)\r
+                text+=detector.getSnapString();\r
+            setInfoText(text);\r
+           // parent.getGraph().commitChanges(CommitMessage.CHANGE_MESSAGE);\r
+        }\r
+        updateGizmo(graph);\r
+\r
+    }\r
+    \r
+    protected void updateGizmo(Graph graph) {\r
+        List<IGraphicsNode> mos = parent.getSelectionAdapter().getSelectedObjects();\r
+        if (mos.size() == 0) {\r
+               end();\r
+               return;\r
+        }\r
+        gizmo.update(G3DTools.getVector(mos.get(0).getG3DNode(graph).getWorldPosition()),camera.getCameraPos(),component);\r
+        \r
+   }\r
+    \r
+    public void setInfoText(String text) {\r
+       \r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/TranslateActionConstraints.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/TranslateActionConstraints.java
new file mode 100644 (file)
index 0000000..c1a7236
--- /dev/null
@@ -0,0 +1,147 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.base.ConstraintDetector;\r
+\r
+\r
+/**\r
+ * Temporary class to handle "Automatic" constraints for translation\r
+ * TODO : create extension point / extension that can provide constraints\r
+ * TODO : how to override previously added constraints ?\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class TranslateActionConstraints {\r
+    \r
+    \r
+    public static void addConstraints(Resource translated[], ConstraintDetector detector) {\r
+        detector.clearConstraints();\r
+        // these must be provided through extension point !\r
+//        if (isElbow(translated)) {\r
+//            addElbowConstraints(translated, detector);\r
+//        } else if (isPipeControlPoint(translated)) {\r
+//            addPipeControlPointConstraints(translated, detector);\r
+//        } else if (isEndComponent(translated)) {\r
+//             addEndComponentConstraints(translated, detector);\r
+//        }\r
+        \r
+        \r
+    }\r
+    \r
+    /*\r
+     * These methods must be inserted into extension\r
+     */\r
+    \r
+//    private static boolean isElbow(Resource translated[]) {\r
+//        for (Resource r : translated) {\r
+//            if (!r.isInstanceOf(GlobalIdMap.get(PSK3DModelingOntologyMapping.ELBOW))) {\r
+//                return false;\r
+//            }\r
+//        }\r
+//        return true;\r
+//    }\r
+//    \r
+//    private static boolean isEndComponent(Resource translated[]) {\r
+//        for (Resource r : translated) {\r
+//            if (!r.isInstanceOf(GlobalIdMap.get(PSK3DModelingOntologyMapping.END_COMPONENT))) {\r
+//                return false;\r
+//            }\r
+//        }\r
+//        return true;\r
+//    }\r
+//    \r
+//    private static boolean isPipeControlPoint(Resource translated[]) {\r
+//        for (Resource r : translated) {\r
+//            if (!r.isInstanceOf(GlobalIdMap.get(PSK3DModelingOntologyMapping.PIPE_CONTROL_POINT))) {\r
+//                return false;\r
+//            }\r
+//        }\r
+//        return true;\r
+//    }\r
+//    \r
+//    private static void addElbowConstraints(Resource translated[], ConstraintDetector detector) {\r
+//        Set<Resource> res = new HashSet<Resource>();\r
+//        // add all controlpoints connected to every elbow's controlpoint\r
+//        for (Resource r : translated) {\r
+//            Elbow elbow = ElbowFactory.create(r);\r
+//            PipeControlPoint p = elbow.getHasControlPoint();\r
+//            PipeControlPoint next = PipingTools.findNextEnd(p);\r
+//            PipeControlPoint previous = PipingTools.findPreviousEnd(p);\r
+//            if (next != null)\r
+//                res.add(next.getResource());\r
+//            if (previous != null)\r
+//                res.add(previous.getResource());\r
+//            \r
+//        }\r
+//        // remove all controlpoints that are elbows' controlpoints\r
+//        for (Resource r : translated) {\r
+//            Elbow elbow = ElbowFactory.create(r);\r
+//            res.remove(elbow.getHasControlPoint().getResource());\r
+//        }\r
+//        for (Resource r : res) {\r
+//            PipeControlPoint p = PipeControlPointFactory.create(r);\r
+//            detector.addContraintPoint(GraphicsNodeTools.getPoint(p.getLocalPosition()));\r
+//        }\r
+//    }\r
+//    \r
+//    private static void addEndComponentConstraints(Resource translated[], ConstraintDetector detector) {\r
+//        Set<Resource> res = new HashSet<Resource>();\r
+//        // add all controlpoints connected to every elbow's controlpoint\r
+//        for (Resource r : translated) {\r
+//            EndComponent elbow = EndComponentFactory.create(r);\r
+//            PipeControlPoint p = elbow.getHasControlPoint();\r
+//            PipeControlPoint next = PipingTools.findNextEnd(p);\r
+//            PipeControlPoint previous = PipingTools.findPreviousEnd(p);\r
+//            if (next != null)\r
+//                res.add(next.getResource());\r
+//            if (previous != null)\r
+//                res.add(previous.getResource());\r
+//            \r
+//        }\r
+//        // remove all controlpoints that are elbows' controlpoints\r
+//        for (Resource r : translated) {\r
+//             EndComponent elbow = EndComponentFactory.create(r);\r
+//            res.remove(elbow.getHasControlPoint().getResource());\r
+//        }\r
+//        for (Resource r : res) {\r
+//            PipeControlPoint p = PipeControlPointFactory.create(r);\r
+//            detector.addContraintPoint(GraphicsNodeTools.getPoint(p.getLocalPosition()));\r
+//        }\r
+//    }\r
+//    \r
+//    \r
+//    private static void addPipeControlPointConstraints(Resource translated[], ConstraintDetector detector) {\r
+//        Set<Resource> res = new HashSet<Resource>();\r
+//        // add all controlpoints connected to every elbow's controlpoint\r
+//        for (Resource r : translated) {\r
+//            PipeControlPoint p = PipeControlPointFactory.create(r);\r
+//            PipeControlPoint next = PipingTools.findNextEnd(p);\r
+//            PipeControlPoint previous = PipingTools.findPreviousEnd(p);\r
+//            if (next != null)\r
+//                res.add(next.getResource());\r
+//            if (previous != null)\r
+//                res.add(previous.getResource());\r
+//            \r
+//        }\r
+//        // remove all controlpoints that are elbows' controlpoints\r
+//        for (Resource r : translated) {\r
+//            res.remove(r);\r
+//        }\r
+//        for (Resource r : res) {\r
+//            PipeControlPoint p = PipeControlPointFactory.create(r);\r
+//            detector.addContraintPoint(GraphicsNodeTools.getPoint(p.getLocalPosition()));\r
+//        }\r
+//    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/WriteAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/WriteAction.java
new file mode 100644 (file)
index 0000000..58aa02a
--- /dev/null
@@ -0,0 +1,61 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequest;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Session;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+\r
+public abstract class WriteAction extends ContextAction {\r
+       boolean sync;\r
+       public WriteAction(ThreeDimensionalEditorBase parent, boolean sync) {\r
+               super(parent);\r
+               this.sync = sync;\r
+       }\r
+\r
+       @Override\r
+       public final void run() {\r
+               Session session = parent.getSession();\r
+               if(!canActivate()) {\r
+                       return;\r
+               }\r
+               GraphRequest r = new GraphRequestAdapter() {\r
+                       @Override\r
+                       public GraphRequestStatus perform(Graph g) throws Exception {\r
+                               return doChanges(g);\r
+                       }\r
+                       \r
+                       @Override\r
+                       public void requestCompleted(GraphRequestStatus status) {\r
+                               afterChanges(status);\r
+                       }\r
+               };\r
+               if (sync) {\r
+                       session.syncWrite(r);\r
+               } else {\r
+                       session.asyncWrite(r);\r
+               } \r
+       }\r
+       \r
+       public abstract GraphRequestStatus doChanges(Graph graph) throws Exception;\r
+       \r
+       public void afterChanges(GraphRequestStatus status) {\r
+               \r
+       }\r
+       \r
+       public boolean canActivate() {\r
+               return true;\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/WriteInteractiveAction.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/actions/WriteInteractiveAction.java
new file mode 100644 (file)
index 0000000..1208b75
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.actions;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequest;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Session;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+\r
+\r
+public abstract class WriteInteractiveAction extends InteractiveAction {\r
+       boolean sync;\r
+       \r
+       public WriteInteractiveAction(ThreeDimensionalEditorBase parent, boolean sync) {\r
+               super(parent);\r
+               this.sync = sync;\r
+       }\r
+       \r
+       @Override\r
+       public final void update(){\r
+               Session session = parent.getSession();\r
+               GraphRequest r = new GraphRequestAdapter() {\r
+                       @Override\r
+                       public GraphRequestStatus perform(Graph g) throws Exception {\r
+                               doChanges(g);\r
+                               return GraphRequestStatus.transactionComplete();\r
+                       }\r
+               };\r
+               if (sync) {\r
+                       session.syncWrite(r);\r
+               } else {\r
+                       session.asyncWrite(r);\r
+               } \r
+       }\r
+\r
+       \r
+       public abstract void doChanges(Graph graph) throws Exception;\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AbstractScalarInterpolator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AbstractScalarInterpolator.java
new file mode 100644 (file)
index 0000000..5777f8e
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+public abstract class AbstractScalarInterpolator implements ScalarInterpolator {\r
+    public void interpolate(double delta) {\r
+        throw new UnsupportedOperationException("");\r
+        \r
+    }\r
+    \r
+    public void setTarget(Object target) {\r
+        throw new UnsupportedOperationException("");\r
+        \r
+    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/Animatable.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/Animatable.java
new file mode 100644 (file)
index 0000000..435cb0d
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+\r
+\r
+/**\r
+ * \r
+ * TODO : multiple animations\r
+ * TODO : remove setRandomAnimation\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public interface Animatable {\r
+    \r
+    /**\r
+     * Sets used animation\r
+     * @param animation\r
+     */\r
+    public boolean setAnimation(Graph graph, Resource animation);\r
+    \r
+    /**\r
+     * Updates animation\r
+     * @param delta\r
+     */\r
+    public void animate(double delta, double frameTime);\r
+    \r
+    /**\r
+     * Sets random animation\r
+     * (Testing purposes)\r
+     */\r
+    public boolean setRandomAnimation(Graph graph);\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/Animation.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/Animation.java
new file mode 100644 (file)
index 0000000..9dd7f5e
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+public class Animation {\r
+    private List<Interpolator> interpolators = new ArrayList<Interpolator>();\r
+\r
+\r
+    public void addInterpolator(Interpolator i) {\r
+        interpolators.add(i);\r
+    }\r
+    \r
+    public void removeInterpolator(Interpolator i) {\r
+        interpolators.remove(i);\r
+    }\r
+    \r
+    public void interpolate(double delta) {\r
+        for (Interpolator i : interpolators) {\r
+            i.interpolate(delta);\r
+        }\r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AnimationController.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AnimationController.java
new file mode 100644 (file)
index 0000000..809ec60
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import org.simantics.db.Graph;\r
+\r
+\r
+public interface AnimationController {\r
+       \r
+       public void updateAnimation(Graph graph, double frameTime);\r
+       public void setAnimatable(Animatable animatable);\r
+       public void addAnimatable(Animatable animatable);\r
+       public void dispose();\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AnimationSystem.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AnimationSystem.java
new file mode 100644 (file)
index 0000000..8085405
--- /dev/null
@@ -0,0 +1,94 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.proconf.g3d.base.ScenegraphAdapter;\r
+\r
+\r
+public class AnimationSystem {\r
+       private ScenegraphAdapter adapter;\r
+       private List<AnimationController> animationControllers = new ArrayList<AnimationController>();\r
+    \r
+       private List<AnimationSystemListener> listeners = new ArrayList<AnimationSystemListener>();\r
+       \r
+       private boolean pause = false;\r
+       \r
+       public AnimationSystem(ScenegraphAdapter adapter) {\r
+               if (adapter == null)\r
+                       throw new IllegalArgumentException("ScenegraphAdapter must not be null");\r
+               this.adapter = adapter;\r
+       }\r
+       \r
+       public void add(AnimationController controller) {\r
+               animationControllers.add(controller);\r
+               for (AnimationSystemListener l : listeners)\r
+               l.animationAdded(this, controller);\r
+       }\r
+       \r
+       public void addListener(AnimationSystemListener l) {\r
+               listeners.add(l);\r
+       }\r
+       \r
+       public void removeListener(AnimationSystemListener l) {\r
+               listeners.remove(l);\r
+       }\r
+       \r
+       public boolean isRunning() {\r
+               return animationControllers.size() > 0;\r
+       }\r
+       \r
+       public void pause() {\r
+               if (pause)\r
+                       return;\r
+               pause = true;\r
+               for (AnimationSystemListener l : listeners)\r
+               l.animationPaused(this);\r
+       }\r
+       \r
+       public void play() {\r
+               if(!pause)\r
+                       return;\r
+               pause = false;\r
+               for (AnimationSystemListener l : listeners)\r
+               l.animationPlay(this);\r
+       }\r
+       \r
+       public void stop() {\r
+               for (AnimationController c : animationControllers)\r
+               c.dispose();\r
+       animationControllers.clear();\r
+       for (AnimationSystemListener l : listeners)\r
+               l.animationStopped(this);\r
+       }\r
+       \r
+       public boolean isPause() {\r
+               return pause;\r
+       }\r
+       \r
+       public void run(Graph graph, double frameTime) {\r
+               if (pause)\r
+                       return;\r
+                if (animationControllers.size() > 0) {\r
+               for (AnimationController c : animationControllers)\r
+                               c.updateAnimation(graph, frameTime);\r
+                       adapter.setChanged(true);\r
+            }\r
+       }\r
+       \r
+       public List<AnimationController> getAnimationControllers() {\r
+               return animationControllers;\r
+       }\r
+       \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AnimationSystemListener.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/AnimationSystemListener.java
new file mode 100644 (file)
index 0000000..f45c3b4
--- /dev/null
@@ -0,0 +1,18 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+public interface AnimationSystemListener {\r
+       public void animationStopped(AnimationSystem animationSystem);\r
+       public void animationPaused(AnimationSystem animationSystem);\r
+       public void animationPlay(AnimationSystem animationSystem);\r
+       public void animationAdded(AnimationSystem animationSystem, AnimationController animationController);\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ChanneledColorInterpolator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ChanneledColorInterpolator.java
new file mode 100644 (file)
index 0000000..5a80e83
--- /dev/null
@@ -0,0 +1,68 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.scene.state.MaterialState;\r
+\r
+public class ChanneledColorInterpolator implements Interpolator {\r
+    private ScalarInterpolator rInterpolator;\r
+    private ScalarInterpolator gInterpolator;\r
+    private ScalarInterpolator bInterpolator;\r
+    \r
+    //Material m = null;\r
+    MaterialState m = null;\r
+    int type = 1;\r
+    \r
+    public static final int AMBIENT = 0;\r
+    public static final int DIFFUSE = 1;\r
+    public static final int SPECULAR = 2;\r
+    public static final int EMISSIVE = 3;\r
+    \r
+    \r
+    public ChanneledColorInterpolator(ScalarInterpolator rInterpolator, ScalarInterpolator gInterpolator, ScalarInterpolator bInterpolator) {\r
+        this.rInterpolator = rInterpolator;\r
+        this.gInterpolator = gInterpolator;\r
+        this.bInterpolator = bInterpolator;\r
+    }\r
+    \r
+    public void interpolate(double delta) {\r
+        double r = rInterpolator.evaluate(delta);\r
+        double g = gInterpolator.evaluate(delta);\r
+        double b = bInterpolator.evaluate(delta);\r
+\r
+        ColorRGBA c = new ColorRGBA((float)r, (float)g, (float)b,0.f);\r
+        switch (type) {\r
+        case AMBIENT : \r
+            m.setAmbient(c);\r
+            break;\r
+        case DIFFUSE:\r
+            m.setDiffuse(c);\r
+            break;\r
+        case SPECULAR:\r
+            m.setSpecular(c);\r
+            break;\r
+        case EMISSIVE:\r
+            m.setEmissive(c);\r
+            break;\r
+        }\r
+    }\r
+    \r
+    public void setTarget(Object target) {\r
+       // m = (Material)target;\r
+        m = (MaterialState)target;\r
+    }\r
+    \r
+    public void setType(int type) {\r
+        this.type = type;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ChanneledPositionInterpolator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ChanneledPositionInterpolator.java
new file mode 100644 (file)
index 0000000..5b6aeb6
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+\r
+import com.jme.math.Vector3f;\r
+import com.jme.scene.Node;\r
+\r
+\r
+public class ChanneledPositionInterpolator implements Interpolator {\r
+    private ScalarInterpolator xInterpolator;\r
+    private ScalarInterpolator yInterpolator;\r
+    private ScalarInterpolator zInterpolator;\r
+\r
+    Node node;\r
+    \r
+    public ChanneledPositionInterpolator(ScalarInterpolator xInterpolator, ScalarInterpolator yInterpolator, ScalarInterpolator zInterpolator) {\r
+        this.xInterpolator = xInterpolator;\r
+        this.yInterpolator = yInterpolator;\r
+        this.zInterpolator = zInterpolator;\r
+    }\r
+    \r
+    public void interpolate(double delta) {\r
+        double x = xInterpolator.evaluate(delta);\r
+        double y = yInterpolator.evaluate(delta);\r
+        double z = zInterpolator.evaluate(delta);\r
+\r
+        node.setLocalTranslation(new Vector3f((float)x,(float)y,(float)z));\r
+    }\r
+    \r
+    public void setTarget(Object target) {\r
+       node = (Node)target;\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ConstantInterpolator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ConstantInterpolator.java
new file mode 100644 (file)
index 0000000..5e273d1
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+public class ConstantInterpolator extends AbstractScalarInterpolator{\r
+    double constant;\r
+    \r
+    \r
+    public ConstantInterpolator(double constant) {\r
+        this.constant = constant;\r
+    }\r
+    \r
+    public double evaluate(double delta) {\r
+        return constant;\r
+    }\r
+    \r
+    \r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/Interpolator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/Interpolator.java
new file mode 100644 (file)
index 0000000..630434f
--- /dev/null
@@ -0,0 +1,18 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+public interface Interpolator {\r
+    \r
+    public void interpolate(double delta);\r
+    public void setTarget(Object target);\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ResourceAnimationController.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ResourceAnimationController.java
new file mode 100644 (file)
index 0000000..d359c34
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+\r
+public class ResourceAnimationController implements AnimationController {\r
+       List<Animatable> animatables = new ArrayList<Animatable>();\r
+    \r
+       Resource source;\r
+       \r
+    public ResourceAnimationController(Resource source) {\r
+       this.source = source;\r
+    }\r
+    \r
+       public void addAnimatable(Animatable animatable) {\r
+               animatables.add(animatable);\r
+               \r
+       }\r
+       \r
+       public void setAnimatable(Animatable animatable) {\r
+               animatables.clear();\r
+               animatables.add(animatable);\r
+               \r
+       }\r
+       \r
+       protected double getValue(Graph graph) {\r
+               //return PropertyUtils.getScalarDoubleValue(source);\r
+               return graph.getScalarDouble(source);\r
+               //source.getDoubleValue();\r
+       }\r
+       \r
+       public void updateAnimation(Graph graph, double frameTime) {\r
+               double d = getValue(graph);\r
+               d = d - Math.floor(d);\r
+        if (d > 1.0) {\r
+            d = 1.0;\r
+        } else if (d < 0.0) {\r
+            d = 0.0;\r
+        }\r
+        for (Animatable a : animatables)\r
+            a.animate(d,frameTime);\r
+       }\r
+       \r
+       public void dispose() {\r
+               \r
+       }\r
+       \r
+       \r
+       \r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ScalarInterpolator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ScalarInterpolator.java
new file mode 100644 (file)
index 0000000..afe7597
--- /dev/null
@@ -0,0 +1,17 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+public interface ScalarInterpolator extends Interpolator{\r
+\r
+    public double evaluate(double delta);\r
+    \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ScaledResourceAnimationController.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ScaledResourceAnimationController.java
new file mode 100644 (file)
index 0000000..c356269
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+\r
+public class ScaledResourceAnimationController extends ResourceAnimationController {\r
+       double min;\r
+       double max;\r
+       double irange;\r
+       \r
+       public ScaledResourceAnimationController(Resource source, double min, double max) {\r
+               super(source);\r
+               this.max = max;\r
+               this.min = min;\r
+               this.irange = 1.0/(max - min);\r
+       }\r
+\r
+       \r
+       @Override\r
+       public void updateAnimation(Graph graph, double frameTime) {\r
+               double d = (getValue(graph) - min) * irange;\r
+        if (d > 1.0) {\r
+            d = 1.0;\r
+        } else if (d < 0.0) {\r
+            d = 0.0;\r
+        }\r
+        for (Animatable a : animatables)\r
+            a.animate(d,frameTime);\r
+       }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/SlerpInterpolator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/SlerpInterpolator.java
new file mode 100644 (file)
index 0000000..33e565c
--- /dev/null
@@ -0,0 +1,47 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import javax.vecmath.Quat4d;\r
+\r
+import org.simantics.proconf.g3d.base.VecmathJmeTools;\r
+\r
+\r
+import com.jme.scene.Node;\r
+\r
+import org.simantics.animation.curve.SlerpCurve;\r
+\r
+\r
+public class SlerpInterpolator implements Interpolator{\r
+    private SlerpCurve curve;\r
+    \r
+    //private TransformGroup group;\r
+    //private Transform3D transform;\r
+    private Node node = null;\r
+    \r
+    public SlerpInterpolator(SlerpCurve curve) {\r
+        this.curve = curve;\r
+        //transform = new Transform3D();\r
+    }\r
+    \r
+    public void interpolate(double delta) {\r
+       Quat4d q = curve.evaluate(delta);\r
+       //transform.set(new Quat4f(q));\r
+       //group.setTransform(transform);\r
+       node.setLocalRotation(VecmathJmeTools.get(q));\r
+    }\r
+    \r
+    public void setTarget(Object target) {\r
+        //group = (TransformGroup)target;\r
+       node = (Node)target;\r
+    }\r
+    \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/TCBInterpolator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/TCBInterpolator.java
new file mode 100644 (file)
index 0000000..063b0a6
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import org.simantics.animation.curve.TCBCurve;\r
+\r
+\r
+public class TCBInterpolator extends AbstractScalarInterpolator{\r
+    TCBCurve curve;\r
+    \r
+    public TCBInterpolator(TCBCurve curve) {\r
+        this.curve = curve;\r
+    }\r
+\r
+    public double evaluate(double delta) {\r
+        return curve.evaluate(delta);\r
+    \r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/TestAnimationController.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/TestAnimationController.java
new file mode 100644 (file)
index 0000000..ec40dea
--- /dev/null
@@ -0,0 +1,55 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Graph;\r
+\r
+public class TestAnimationController implements AnimationController {\r
+       List<Animatable> animatables = new ArrayList<Animatable>();\r
+       \r
+       private double d = 0.0;\r
+    private double delta = 0.01;\r
+    \r
+       public void addAnimatable(Animatable animatable) {\r
+               animatables.add(animatable);\r
+               \r
+       }\r
+       \r
+       public void setAnimatable(Animatable animatable) {\r
+               animatables.clear();\r
+               animatables.add(animatable);\r
+               \r
+       }\r
+       \r
+       public void updateAnimation(Graph graph, double frameTime) {\r
+               d += delta;\r
+        if (d > 1.0) {\r
+            d = 1.0;\r
+            delta = -delta;\r
+        } else if (d < 0.0) {\r
+            delta = -delta;\r
+            d = 0.0;\r
+        }\r
+        for (Animatable a : animatables)\r
+            a.animate(d,frameTime);\r
+       }\r
+       \r
+       public void dispose() {\r
+               \r
+       }\r
+       \r
+       \r
+       \r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ui/AnimationControlCreator.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/animation/ui/AnimationControlCreator.java
new file mode 100644 (file)
index 0000000..b433d22
--- /dev/null
@@ -0,0 +1,139 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.animation.ui;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.animation.AnimationController;\r
+import org.simantics.proconf.g3d.animation.AnimationSystem;\r
+import org.simantics.proconf.g3d.animation.AnimationSystemListener;\r
+\r
+\r
+\r
+public class AnimationControlCreator {\r
+       \r
+       private AnimationSystem animationSystem;\r
+       \r
+       public AnimationControlCreator(AnimationSystem animationSystem) {\r
+               if (animationSystem == null)\r
+                       throw new IllegalArgumentException("AnimationSystem must not be null");\r
+               this.animationSystem = animationSystem;\r
+       }\r
+       \r
+       public Action createStopAction() {\r
+               return new StopAction();\r
+       }\r
+       \r
+       public Action createPauseAction() {\r
+               return new PauseAction();\r
+       }\r
+       \r
+       public Action createPlayAction() {\r
+               return new PlayAction();\r
+       }\r
+       \r
+       private class StopAction extends Action implements AnimationSystemListener {\r
+               \r
+               public StopAction() {\r
+                       super();\r
+                       this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/silk/control_stop_blue.png"));\r
+                       this.setDisabledImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/silk/control_stop.png"));\r
+                       animationSystem.addListener(this);\r
+                       if (!animationSystem.isRunning())\r
+                               this.setEnabled(false);\r
+               }\r
+               \r
+               public void run() {\r
+                       animationSystem.stop();\r
+               }\r
+               \r
+               public void animationAdded(AnimationSystem animationSystem, AnimationController animationController) {\r
+                       this.setEnabled(true);\r
+               }\r
+               \r
+               public void animationPaused(AnimationSystem animationSystem) {\r
+                       this.setEnabled(true);\r
+               }\r
+               \r
+               public void animationPlay(AnimationSystem animationSystem) {\r
+                       this.setEnabled(true);\r
+               }\r
+               \r
+               public void animationStopped(AnimationSystem animationSystem) {\r
+                       this.setEnabled(false);\r
+               }\r
+       }\r
+       \r
+       private class PlayAction extends Action implements AnimationSystemListener {\r
+               \r
+               public PlayAction() {\r
+                       super();\r
+                       this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/silk/control_play_blue.png"));\r
+                       this.setDisabledImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/silk/control_play.png"));\r
+                       animationSystem.addListener(this);\r
+                       if (!animationSystem.isPause() || !animationSystem.isRunning())\r
+                               this.setEnabled(false);\r
+               }\r
+               \r
+               public void run() {\r
+                       animationSystem.play();\r
+               }\r
+               \r
+               public void animationAdded(AnimationSystem animationSystem, AnimationController animationController) {\r
+                       this.setEnabled(animationSystem.isPause());\r
+               }\r
+               \r
+               public void animationPaused(AnimationSystem animationSystem) {\r
+                       this.setEnabled(true);\r
+               }\r
+               \r
+               public void animationPlay(AnimationSystem animationSystem) {\r
+                       this.setEnabled(false);\r
+               }\r
+               \r
+               public void animationStopped(AnimationSystem animationSystem) {\r
+                       this.setEnabled(false);\r
+               }\r
+       }\r
+       \r
+       private class PauseAction extends Action implements AnimationSystemListener {\r
+               \r
+               public PauseAction() {\r
+                       super();\r
+                       this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/silk/control_pause_blue.png"));\r
+                       this.setDisabledImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/silk/control_pause.png"));\r
+                       animationSystem.addListener(this);\r
+                       if (animationSystem.isPause() || !animationSystem.isRunning())\r
+                               this.setEnabled(false);\r
+               }\r
+               \r
+               public void run() {\r
+                       animationSystem.pause();\r
+               }\r
+               \r
+               public void animationAdded(AnimationSystem animationSystem, AnimationController animationController) {\r
+                       this.setEnabled(!animationSystem.isPause());\r
+               }\r
+               \r
+               public void animationPaused(AnimationSystem animationSystem) {\r
+                       this.setEnabled(false);\r
+               }\r
+               \r
+               public void animationPlay(AnimationSystem animationSystem) {\r
+                       this.setEnabled(true);\r
+               }\r
+               \r
+               public void animationStopped(AnimationSystem animationSystem) {\r
+                       this.setEnabled(false);\r
+               }\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/AppearanceTools.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/AppearanceTools.java
new file mode 100644 (file)
index 0000000..5cc4304
--- /dev/null
@@ -0,0 +1,454 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.eclipse.swt.graphics.Device;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.StubLinkedList;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.stubs.Appearance;\r
+import org.simantics.proconf.g3d.stubs.Color;\r
+import org.simantics.proconf.g3d.stubs.G3DResource;\r
+import org.simantics.proconf.g3d.stubs.ImageTexture;\r
+import org.simantics.proconf.g3d.stubs.Material;\r
+import org.simantics.proconf.g3d.stubs.MultiTexture;\r
+import org.simantics.proconf.g3d.stubs.MultiTextureMode;\r
+import org.simantics.proconf.g3d.stubs.Shader;\r
+import org.simantics.proconf.g3d.stubs.Texture;\r
+import org.simantics.utils.ErrorLogger;\r
+\r
+import com.jme.image.Image;\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.Geometry;\r
+import com.jme.scene.state.AlphaState;\r
+import com.jme.scene.state.FragmentProgramState;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.scene.state.RenderState;\r
+import com.jme.scene.state.TextureState;\r
+import com.jme.scene.state.VertexProgramState;\r
+\r
+\r
+public class AppearanceTools {\r
+       \r
+       \r
+    \r
+    \r
+    public static void setColor(Color color, org.eclipse.swt.graphics.Color c) {\r
+        color.setRed(new double[]{(double)c.getRed() / 255.0});\r
+        color.setGreen(new double[]{(double)c.getGreen() / 255.0});\r
+        color.setBlue(new double[]{(double)c.getBlue() / 255.0});\r
+    }\r
+    \r
+    public static org.eclipse.swt.graphics.Color getColor(Color color, Device device) {\r
+        org.eclipse.swt.graphics.Color c = new org.eclipse.swt.graphics.Color(device, (int)(color.getRed()[0] * 255.0), (int)(color.getGreen()[0] * 255.0),(int)(color.getBlue()[0] * 255.0));\r
+        return c;\r
+    }\r
+    \r
+    /**\r
+     * Returns collection of renderstates that represent the given appearance.\r
+     * Note : if collection contains an alphastate, node must be inserted to transparent rendering queue.!\r
+     * @param appearance\r
+     * @param renderer\r
+     * @return\r
+     */\r
+    public static Collection<RenderState> getAppearance(Appearance appearance, Renderer renderer) {\r
+        Material m = appearance.getMaterial();\r
+        List <RenderState> states = new ArrayList<RenderState>();\r
+        if (m != null) {\r
+          states.addAll(getMaterial(m, renderer));\r
+        }\r
+        Texture t = appearance.getTexture();\r
+        if (t != null) {\r
+            if (t.isInstanceOf(Resources.g3dResource.ImageTexture)) {\r
+                states.addAll(getPatternTexture(t, renderer));\r
+            } else if (t.isInstanceOf(Resources.g3dResource.Texture3D)) {\r
+                ErrorLogger.getDefault().logWarning("JME doesn't support volume textures!", null);\r
+            } else if (t.isInstanceOf(Resources.g3dResource.MultiTexture)) {\r
+                states.addAll(getMultiTexture(t, renderer));\r
+            } else if (t.isInstanceOf(Resources.g3dResource.CubeMapTexture)) {\r
+               ErrorLogger.getDefault().logWarning("JME doesn't support cubemap textures!", null);    \r
+            } else {\r
+                throw new UnsupportedOperationException("Unsupported texture");\r
+            }\r
+        }\r
+        Shader s =  appearance.getShader();\r
+        if (s != null) {\r
+            states.addAll(getShader(s, renderer));\r
+        }\r
+        return states;\r
+        \r
+    }\r
+    \r
+    private static ColorRGBA getJMEColor(Color color) {\r
+       return new ColorRGBA((float)color.getRed()[0],(float)color.getGreen()[0],(float)color.getBlue()[0],0.f);\r
+    }\r
+    \r
+    private static ColorRGBA getJMEColor(Color color, float alpha) {\r
+       return new ColorRGBA((float)color.getRed()[0],(float)color.getGreen()[0],(float)color.getBlue()[0],alpha);\r
+    }\r
+    \r
+    private static Collection<RenderState> getMaterial(Material m , Renderer renderer) {\r
+       float alpha = 0.f;\r
+       MaterialState ms = renderer.createMaterialState();\r
+       List<RenderState> states = new ArrayList<RenderState>();\r
+       if (m.getTransparency()[0] > 0.0) {\r
+               AlphaState as = renderer.createAlphaState();\r
+               as.setBlendEnabled(true);\r
+               as.setSrcFunction(AlphaState.DB_SRC_ALPHA);\r
+               as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);\r
+               states.add(as);\r
+               alpha = 1.f - (float)m.getTransparency()[0];\r
+               //node.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+               ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK);\r
+        } else {\r
+               //node.setRenderQueueMode(Renderer.QUEUE_OPAQUE);\r
+        }\r
+       \r
+       ms.setEmissive(getJMEColor(m.getEmissiveColor()));\r
+        ms.setSpecular(getJMEColor(m.getSpecularColor()));\r
+        ms.setAmbient(getJMEColor(m.getAmbientColor()));\r
+        ms.setDiffuse(getJMEColor(m.getDiffuseColor(),alpha));\r
+        ms.setShininess((float) m.getShininess()[0]); \r
+        //node.setRenderState(ms);\r
+        states.add(ms);\r
+        return states; \r
+    }\r
+    \r
+    private static Collection<RenderState> getShader(Shader s , Renderer renderer) {\r
+       List<RenderState> states = new ArrayList<RenderState>();\r
+        VertexProgramState vs = renderer.createVertexProgramState();\r
+        vs.load(s.getVertexShader()[0]);\r
+        FragmentProgramState fs = renderer.createFragmentProgramState();\r
+        fs.load(s.getFragmentShader()[0]);\r
+        states.add(vs);\r
+        states.add(fs);\r
+        return states;\r
+    }\r
+    \r
+    private static Collection<RenderState> getPatternTexture(Texture t, Renderer renderer) {\r
+\r
+               List<RenderState> states = new ArrayList<RenderState>();\r
+               com.jme.image.Texture texture = ResourceTextureCache.getInstance().loadTexture(t.getGraph(), t.getResource());\r
+               if (texture == null)\r
+                       return states;\r
+               TextureState state = renderer.createTextureState();\r
+               state.setTexture(texture);\r
+               state.setEnabled(true);\r
+               states.add(state);\r
+               return states;\r
+       \r
+    }\r
+    \r
+    private static Image getPatternTexture(ImageTexture t) {\r
+       return ResourceTextureCache.getInstance().loadImage(t.getGraph(), t.getResource());\r
+    }\r
+    \r
+    \r
+    \r
+    \r
+    \r
+    private static Collection<RenderState> getMultiTexture(Texture t,  Renderer renderer) {\r
+       List<RenderState> states = new ArrayList<RenderState>();\r
+       TextureState state = renderer.createTextureState();\r
+        MultiTexture t3 = new MultiTexture(t); \r
+        Collection<IEntity> mtList = t3.getRelatedObjects(Resources.g3dResource.HasMultiTextureElementList);\r
+        assert (mtList.size() == 1); //this is required in the ontology!\r
+        StubLinkedList<IEntity> list = new StubLinkedList<IEntity>(mtList.iterator().next());\r
+        \r
+        for (int i = 0; i < list.size(); i++) {\r
+               IEntity ie = list.get(i);\r
+               //MultiTextureElement e = new MultiTextureElement(ie);\r
+               Texture tex = new Texture(ie); //e.getTexture();\r
+               MultiTextureMode mode = tex.getTextureMode();//e.getTextureMode();\r
+               com.jme.image.Texture texture = new com.jme.image.Texture();\r
+            texture.setFilter(com.jme.image.Texture.FM_LINEAR);\r
+            texture.setMipmapState(com.jme.image.Texture.MM_LINEAR_LINEAR);\r
+            texture.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T);\r
+            if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_add)) {\r
+               texture.setApply(com.jme.image.Texture.AM_ADD);\r
+            } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_modulate)) {\r
+               texture.setApply(com.jme.image.Texture.AM_MODULATE);\r
+            } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_decal)) {\r
+               texture.setApply(com.jme.image.Texture.AM_DECAL);\r
+            } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_blend)) {\r
+               texture.setApply(com.jme.image.Texture.AM_BLEND);\r
+            } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_replace)) {\r
+               texture.setApply(com.jme.image.Texture.AM_REPLACE);\r
+            } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_combine)) {\r
+               texture.setApply(com.jme.image.Texture.AM_COMBINE);\r
+                //CombineMode cm = e.getCombineMode();\r
+                //CombineSource cs = e.getCombineSource();\r
+               StubLinkedList<IEntity> combine = new StubLinkedList<IEntity>(tex.getCombineDefinition());\r
+                setCombineAttributes(texture, combine);\r
+                  \r
+                  \r
+                  \r
+                  //att.setBlendColor(blendColor)\r
+                  //att.setTexBlendColor(texBlendColor)\r
+                  //att.setTextureBlendColor(color)\r
+                  //att.setTextureTransform(transform)\r
+             } else {\r
+                  throw new UnsupportedOperationException("Texture mode not supported");\r
+             }\r
+              \r
+              \r
+              if (tex.isInstanceOf(Resources.g3dResource.MultiTexture)) {\r
+                  ErrorLogger.defaultLogError("MultiTexture contains another MultiTexture which is not allowed", null);\r
+                  continue;\r
+              } else if (tex.isInstanceOf(Resources.g3dResource.ImageTexture)) {\r
+                  Image image = getPatternTexture(new ImageTexture(tex));\r
+                  if (image != null)\r
+                       texture.setImage(image);\r
+  \r
+              } else if (tex.isInstanceOf(Resources.g3dResource.Texture3D)) {\r
+               ErrorLogger.getDefault().logWarning("JME doesn't support volume textures!", null);\r
+  \r
+              } else if (tex.isInstanceOf(Resources.g3dResource.CubeMapTexture)) {\r
+               ErrorLogger.getDefault().logWarning("JME doesn't support cubemap textures!", null);    \r
+  \r
+              } else {\r
+                  throw new UnsupportedOperationException("Unsupported texture");\r
+              }\r
+\r
+              state.setTexture(texture, i);\r
+          }\r
+        states.add(state);\r
+        return states;\r
+               \r
+        //MultiTextureElementList texturesList = t3.getMultiTextureElementList();\r
+        //List<MultiTextureElement> textures = texturesList.toStandAloneList();\r
+        //ArrayList<TextureUnitState> states = new ArrayList<TextureUnitState>();\r
+       // for (MultiTextureElement e : textures) {\r
+       //     Texture tex = e.getTexture();\r
+           \r
+            //int index = e.getMultiTextureIndexValue();\r
+            //String mode = e.getMultiTextureModeValue();\r
+            \r
+       //     com.jme.image.Texture texture = new com.jme.image.Texture();\r
+       //     texture.setFilter(com.jme.image.Texture.FM_LINEAR);\r
+       //     texture.setMipmapState(com.jme.image.Texture.MM_LINEAR_LINEAR);\r
+       //     texture.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T);\r
+//            if (mode.startsWith(TEXTURE_MODE_MODULATE)) {\r
+//             texture.setApply(com.jme.image.Texture.AM_MODULATE);\r
+//            } else if (mode.startsWith(TEXTURE_MODE_DECAL)) {\r
+//             texture.setCombineFuncRGB(com.jme.image.Texture.AM_DECAL);\r
+//            } else if (mode.startsWith(TEXTURE_MODE_BLEND)) {\r
+//             texture.setCombineFuncRGB(com.jme.image.Texture.AM_MODULATE);\r
+//            } else if (mode.startsWith(TEXTURE_MODE_REPLACE)) {\r
+//             texture.setCombineFuncRGB(com.jme.image.Texture.AM_REPLACE);\r
+//            } else if (mode.startsWith(TEXTURE_MODE_COMBINE)) {\r
+//             texture.setCombineFuncRGB(com.jme.image.Texture.AM_COMBINE);\r
+//                \r
+//                mode = mode.substring(TEXTURE_MODE_COMBINE.length()+1); \r
+//                setCombineAttributes(texture, mode);\r
+                \r
+                \r
+                \r
+                //att.setBlendColor(blendColor)\r
+                //att.setTexBlendColor(texBlendColor)\r
+                //att.setTextureBlendColor(color)\r
+                //att.setTextureTransform(transform)\r
+//            } else {\r
+//                throw new UnsupportedOperationException("Texture mode not supported");\r
+//            }\r
+//            \r
+//            \r
+//            if (tex.isInstanceOf(Resources.g3dResource.MultiTexture)) {\r
+//                ErrorLogger.defaultLogError("MultiTexture contains another MultiTexture which is not allowed", null);\r
+//                continue;\r
+//            } else if (tex.isInstanceOf(Resources.g3dResource.ImageTexture)) {\r
+//                Image image = getPatternTexture(ImageTextureFactory.create(tex));\r
+//                if (image != null)\r
+//                     texture.setImage(image);\r
+//\r
+//            } else if (tex.isInstanceOf(Resources.g3dResource.Texture3D)) {\r
+//             ErrorLogger.getDefault().logWarning("JME doesn't support volume textures!", null);\r
+//\r
+//            } else if (tex.isInstanceOf(Resources.g3dResource.CubeMapTexture)) {\r
+//             ErrorLogger.getDefault().logWarning("JME doesn't support cubemap textures!", null);    \r
+//\r
+//            } else {\r
+//                throw new UnsupportedOperationException("Unsupported texture");\r
+//            }\r
+            \r
+            //FIXME !\r
+            //state.setTexture(texture, index);\r
+      //  }\r
+      //  node.setRenderState(state);\r
+       \r
+        \r
+\r
+    }\r
+    \r
+    \r
+    private static void setCombineAttributes(com.jme.image.Texture texture, StubLinkedList<IEntity> definition) {\r
+       // TODO : rgb and alpha scale\r
+        Iterator<IEntity> it = definition.iterator();\r
+        IEntity mode = it.next();\r
+        if (mode.getResource().equals(Resources.g3dResource.CombineMode_add)) {\r
+            texture.setCombineFuncRGB(com.jme.image.Texture.ACF_ADD);\r
+        } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_addsigned)) {\r
+            texture.setCombineFuncRGB(com.jme.image.Texture.ACF_ADD_SIGNED);\r
+        } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_dot3)) {\r
+            texture.setCombineFuncRGB(com.jme.image.Texture.ACF_DOT3_RGB);\r
+        } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_interpolate)) {\r
+            texture.setCombineFuncRGB(com.jme.image.Texture.ACF_INTERPOLATE);\r
+        } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_modulate)) {\r
+            texture.setCombineFuncRGB(com.jme.image.Texture.ACF_MODULATE);\r
+        } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_replace)) {\r
+            texture.setCombineFuncRGB(com.jme.image.Texture.ACF_REPLACE);\r
+        } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_subtract)) {\r
+            texture.setCombineFuncRGB(com.jme.image.Texture.ACF_SUBTRACT);\r
+        } else {\r
+            throw new UnsupportedOperationException("Unsupported combine mode");\r
+        }\r
+        mode = it.next();\r
+        int i = 0;\r
+        for (i = 0; i < 3; i++) {\r
+               int m;\r
+            if (mode.getResource().equals(Resources.g3dResource.CombineSource_constantcolor)) {\r
+                m = com.jme.image.Texture.ACS_CONSTANT;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_objectcolor)) {\r
+                m = com.jme.image.Texture.ACS_PRIMARY_COLOR;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_previousstate)) {\r
+                m = com.jme.image.Texture.ACS_TEXTURE;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texturecolor)) {\r
+                m = com.jme.image.Texture.ACS_TEXTURE;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texture0)) {\r
+                m = com.jme.image.Texture.ACS_TEXTURE;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texture1)) {\r
+                m = com.jme.image.Texture.ACS_TEXTURE;\r
+            } else {\r
+                break;\r
+                //throw new UnsupportedOperationException("Texture combine source not supported");\r
+            }\r
+            mode = it.next();\r
+            switch (i) {\r
+               case 0:\r
+                       texture.setCombineSrc0RGB(m);\r
+                       break;\r
+               case 1:\r
+                       texture.setCombineSrc1RGB(m);\r
+                       break;\r
+               case 2:\r
+                       texture.setCombineSrc2RGB(m);\r
+                       break;\r
+                       \r
+            }\r
+        }\r
+        if (i > 0) {\r
+            for (i = 0; i < 3; i++) {\r
+               int m;\r
+                if (mode.getResource().equals(Resources.g3dResource.CombineFunction_srccolor)) {\r
+                    m = com.jme.image.Texture.ACO_SRC_COLOR;\r
+                } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_srcalpha)) {\r
+                    m = com.jme.image.Texture.ACO_SRC_ALPHA;\r
+                } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_oneminussrccolor)) {\r
+                    m = com.jme.image.Texture.ACO_ONE_MINUS_SRC_COLOR;\r
+                } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_oneminussrcalpha)) {\r
+                    m = com.jme.image.Texture.ACO_ONE_MINUS_SRC_ALPHA;\r
+                } else {\r
+                    break;\r
+                }\r
+                mode = it.next();\r
+                switch (i) {\r
+               case 0:\r
+                       texture.setCombineOp0RGB(m);\r
+                       break;\r
+               case 1:\r
+                       texture.setCombineOp1RGB(m);\r
+                       break;\r
+               case 2:\r
+                       texture.setCombineOp2RGB(m);\r
+                       break;\r
+                       \r
+                }\r
+            }\r
+        }\r
+        \r
+        for (i = 0; i < 3; i++) {\r
+               int m;\r
+               if (mode.getResource().equals(Resources.g3dResource.CombineSource_constantcolor)) {\r
+                m = com.jme.image.Texture.ACS_CONSTANT;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_objectcolor)) {\r
+                m = com.jme.image.Texture.ACS_PRIMARY_COLOR;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_previousstate)) {\r
+                m = com.jme.image.Texture.ACS_TEXTURE;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texturecolor)) {\r
+                m = com.jme.image.Texture.ACS_TEXTURE;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texture0)) {\r
+                m = com.jme.image.Texture.ACS_TEXTURE;\r
+            } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texture1)) {\r
+                m = com.jme.image.Texture.ACS_TEXTURE;\r
+            } else {\r
+                break;\r
+                //throw new UnsupportedOperationException("Texture combine source not supported");\r
+            }\r
+            mode = it.next();\r
+            switch (i) {\r
+               case 0:\r
+                       texture.setCombineSrc0Alpha(m);\r
+                       break;\r
+               case 1:\r
+                       texture.setCombineSrc1Alpha(m);\r
+                       break;\r
+               case 2:\r
+                       texture.setCombineSrc2Alpha(m);\r
+                       break;\r
+                       \r
+            }\r
+        }\r
+        if (i > 0) {\r
+            for (i = 0; i < 3; i++) {\r
+               int m;\r
+               if (mode.getResource().equals(Resources.g3dResource.CombineFunction_srccolor)) {\r
+                    m = com.jme.image.Texture.ACO_SRC_COLOR;\r
+                } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_srcalpha)) {\r
+                    m = com.jme.image.Texture.ACO_SRC_ALPHA;\r
+                } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_oneminussrccolor)) {\r
+                    m = com.jme.image.Texture.ACO_ONE_MINUS_SRC_COLOR;\r
+                } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_oneminussrcalpha)) {\r
+                    m = com.jme.image.Texture.ACO_ONE_MINUS_SRC_ALPHA;\r
+                } else {\r
+                    break;\r
+                }\r
+                mode = it.next();\r
+                switch (i) {\r
+               case 0:\r
+                       texture.setCombineOp0Alpha(m);\r
+                       break;\r
+               case 1:\r
+                       texture.setCombineOp1Alpha(m);\r
+                       break;\r
+               case 2:\r
+                       texture.setCombineOp2Alpha(m);\r
+                       break;\r
+                       \r
+                }\r
+            }\r
+        }\r
+    }\r
+    \r
+    public static void copyMaterial(Geometry from, Geometry to) {\r
+       for (int i = RenderState.RS_ALPHA; i < RenderState.RS_MAX_STATE; i++) {\r
+               RenderState rs = from.getRenderState(i);\r
+               if (rs != null)\r
+                       to.setRenderState(rs);\r
+       }\r
+       \r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/Constraint.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/Constraint.java
new file mode 100644 (file)
index 0000000..9d48d3e
--- /dev/null
@@ -0,0 +1,19 @@
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+public class Constraint {\r
+       \r
+       public Constraint() {\r
+               points = new ArrayList<Point3d>();\r
+               dirs = new ArrayList<Vector3d>();\r
+       }\r
+       \r
+       public List<Point3d> points;\r
+       public List<Vector3d> dirs;\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ConstraintDetector.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ConstraintDetector.java
new file mode 100644 (file)
index 0000000..3a18c27
--- /dev/null
@@ -0,0 +1,442 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestWithResult;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.adaption.AdaptionException;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.utils.ErrorLogger;\r
+\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.scene.Geometry;\r
+import com.jme.scene.Line;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.util.geom.BufferUtils;\r
+\r
+public class ConstraintDetector {\r
+    \r
+    private static final int X = 0;\r
+    private static final int Y = 1;\r
+    private static final int Z = 2;\r
+    \r
+    \r
+    private ThreeDimensionalEditorBase editor;\r
+    //private G3DNode constraintReference = null;\r
+    private Resource constraintReference = null;\r
+    private ArrayList<Point3d> constraintPoints = new ArrayList<Point3d>();\r
+    private ArrayList<Vector3d> constraintDirections = new ArrayList<Vector3d>();\r
+    private MaterialState ms;\r
+    \r
+    private ColorRGBA xColor = new ColorRGBA(1.f,0.f,0.f,1.f);\r
+    private ColorRGBA yColor = new ColorRGBA(0.f,1.f,0.f,1.f);\r
+    private ColorRGBA zColor = new ColorRGBA(0.f,0.f,1.f,1.f);\r
+    \r
+    \r
+    public ConstraintDetector(ThreeDimensionalEditorBase editor) {\r
+        this.editor = editor;\r
+        ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+        ms.setEmissive(new ColorRGBA(1.f,1.f,1.f,1.f));\r
+        ms.setColorMaterial(MaterialState.CM_EMISSIVE);\r
+    }\r
+    \r
+\r
+    public void clearConstraints() {\r
+        //System.out.println("ConstraintDetector.clearConstraints()");\r
+        constraintPoints.clear();\r
+        constraintDirections.clear();\r
+    }\r
+    \r
+    private void updateConstraints() {\r
+        clearConstraints();\r
+        if (constraintReference == null)\r
+            return;\r
+        GraphRequestWithResult<Constraint>  request = new GraphRequestWithResult<Constraint>() {\r
+               @Override\r
+               public Constraint performWithResult(Graph g) throws Exception {\r
+                       try {\r
+                               return g.adapt(constraintReference, Resources.g3dResource.HasConstraints);\r
+                       } catch (AdaptionException e) {\r
+                               ErrorLogger.defaultLogWarning("Cannot add constraint", e);\r
+                               return null;\r
+                       }\r
+               }\r
+        };\r
+        editor.getSession().syncRead(request);\r
+        Constraint c = request.getResult();\r
+        if (c == null)\r
+               return;\r
+        constraintPoints.addAll(c.points);\r
+        constraintDirections.addAll(c.dirs);\r
+    }\r
+    \r
+    \r
+    public ArrayList<Point3d> getConstraintPoints() {\r
+        return constraintPoints;\r
+    }\r
+    \r
+    public ArrayList<Vector3d> getConstraintDirections() {\r
+        return constraintDirections;\r
+    }\r
+\r
+    public void updateConstraintReference() {\r
+   \r
+            Resource interactive = null;\r
+            if (editor.getSelectionAdapter().getHighlightSelection().size() > 0) {\r
+                interactive = editor.getSelectionAdapter().getInteractiveSelectedObjects().iterator().next().getResource();\r
+                if (constraintReference == null) {\r
+                    constraintReference = interactive;\r
+                    updateConstraints();\r
+                } else if (!constraintReference.getResource().equals(interactive.getResource())) {\r
+                    constraintReference = interactive;\r
+                    updateConstraints();\r
+                }\r
+            } else {\r
+                constraintReference = null;\r
+                updateConstraints();\r
+            }\r
+\r
+    }\r
+    \r
+    public void addContraintPoint(Point3d p) {\r
+        //System.out.println("ConstraintDetector.addConstraintPoint() " + p);\r
+        constraintPoints.add(p);\r
+    }\r
+    \r
+    public void addContraintDirection(Vector3d v) {\r
+        //System.out.println("ConstraintDetector.addConstraintDirection() " + v);\r
+        constraintDirections.add(v);\r
+    }\r
+    \r
+    private double snapAngle = 0.1;\r
+    private String snapString = "";\r
+\r
+    private ArrayList<Geometry> constraintHighlights = new ArrayList<Geometry>();\r
+    \r
+    public Point3d getSnappedPoint(Vector3d pickPoint, Vector3d pickDir, Vector3d requestedPoint) {\r
+        \r
+        \r
+        Vector3d snappedPoint = new Vector3d();\r
+        Vector3d t = new Vector3d();\r
+        Point3d currentPoint = null;\r
+        // TODO : snap to closest angle\r
+        for (Vector3d constraintDir : constraintDirections) {\r
+            \r
+            MathTools.intersectStraightStraight(pickPoint,pickDir, requestedPoint, constraintDir, t, snappedPoint);\r
+            t.sub(snappedPoint);\r
+            if (t.lengthSquared() < snapAngle) {\r
+                \r
+                snapString += "Angle snap ";\r
+                currentPoint = new Point3d(snappedPoint);\r
+                break;\r
+            }\r
+        }\r
+        if (currentPoint != null) {\r
+            Vector3d dir = new Vector3d(currentPoint);\r
+            dir.sub(requestedPoint);\r
+            Point3d p = getPointSnap(requestedPoint, dir);\r
+            if (p != null)\r
+                currentPoint = p;\r
+        } else {\r
+               List<Double> distances = new ArrayList<Double>();\r
+               List<Point3d> snapPoints = new ArrayList<Point3d>();\r
+               List<String> snapStrings = new ArrayList<String>();\r
+               List<ColorRGBA> snapColors = new ArrayList<ColorRGBA>();\r
+            for (Point3d constraintPoint : constraintPoints) {\r
+               distances.clear();\r
+               snapPoints.clear();\r
+               snapStrings.clear();\r
+                MathTools.intersectStraightStraight(new Vector3d(constraintPoint), new Vector3d(1.0, 0.0, 0.0),\r
+                        pickPoint, pickDir, snappedPoint, t);\r
+                t.sub(snappedPoint);\r
+                double distance = t.lengthSquared();\r
+                if (distance < snapAngle) {\r
+                       distances.add(distance);\r
+                       snapPoints.add(new Point3d(snappedPoint));\r
+                       snapStrings.add("Point x-snap ");\r
+                       snapColors.add(xColor);\r
+                }\r
+                MathTools.intersectStraightStraight(new Vector3d(constraintPoint), new Vector3d(0.0, 1.0, 0.0),\r
+                        pickPoint, pickDir, snappedPoint, t);\r
+                t.sub(snappedPoint);\r
+                distance = t.lengthSquared();\r
+                if (distance < snapAngle) {\r
+                       distances.add(distance);\r
+                       snapPoints.add(new Point3d(snappedPoint));\r
+                       snapStrings.add("Point y-snap ");\r
+                       snapColors.add(yColor);\r
+                }\r
+                MathTools.intersectStraightStraight(new Vector3d(constraintPoint), new Vector3d(0.0, 0.0, 1.0),\r
+                        pickPoint, pickDir, snappedPoint, t);\r
+                t.sub(snappedPoint);\r
+                distance = t.lengthSquared();\r
+                if (distance < snapAngle) {\r
+                       distances.add(distance);\r
+                       snapPoints.add(new Point3d(snappedPoint));\r
+                       snapStrings.add("Point z-snap ");\r
+                       snapColors.add(zColor);\r
+                    \r
+                }\r
+                if (distances.size() > 0) {\r
+                    if (distances.size() > 1) {\r
+                        // more than one axes snape\r
+                       Vector3d ref = MathTools.closestPointOnStraight(constraintPoint, new Point3d(pickPoint), pickDir);\r
+                       ref.sub(constraintPoint);\r
+                       distance = ref.lengthSquared();\r
+                       if (distance < snapAngle) {\r
+                               // we are close enought to point, so we'll just snap there\r
+                               currentPoint = new Point3d(constraintPoint);\r
+                               snapString += "Point snap ";\r
+                       } else {\r
+                               // select the closest of axes snap to\r
+                               int min = 0;\r
+                               for (int i = 1; i < distances.size(); i++) {\r
+                                       if (distances.get(i) < distances.get(min))\r
+                                               min = i;\r
+                               }\r
+                               currentPoint = snapPoints.get(min);\r
+                               addConstrainLineHighlight(currentPoint, constraintPoint,snapColors.get(min));\r
+                               snapString += snapStrings.get(min);\r
+                       }\r
+                    } else {\r
+                       // only one of the axes snaps\r
+                       currentPoint = snapPoints.get(0);\r
+                       addConstrainLineHighlight(currentPoint, constraintPoint,snapColors.get(0));\r
+                       snapString += snapStrings.get(0);\r
+                    }\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+        return currentPoint;\r
+\r
+    }\r
+    \r
+    public void clearConstraintHighlights() {\r
+        snapString = "";\r
+\r
+        for (Geometry s : constraintHighlights)\r
+            s.removeFromParent();\r
+        \r
+        constraintHighlights.clear();\r
+    }\r
+    \r
+    private void addConstrainLineHighlight(Point3d p1, Point3d p2, ColorRGBA color) {\r
+\r
+       float coord[] = new float[6];\r
+       ColorRGBA colors[] = new ColorRGBA[2];\r
+       colors[0] = color;\r
+       colors[1] = color;\r
+       coord[0] = (float)p1.x;\r
+       coord[1] = (float)p1.y;\r
+       coord[2] = (float)p1.z;\r
+       coord[3] = (float)p2.x;\r
+       coord[4] = (float)p2.y;\r
+       coord[5] = (float)p2.z;\r
+       Line shape = new Line("",BufferUtils.createFloatBuffer(coord),null,BufferUtils.createFloatBuffer(colors),null);\r
+       editor.getRenderingComponent().getNoShadowRoot().attachChild(shape);\r
+       shape.setRenderState(ms);\r
+       constraintHighlights.add(shape);\r
+    }\r
+    \r
+    private void addConstrainPlaneHighlight(Point3d p1, Point3d p2, int axis) {\r
+\r
+       float coord[] = new float[9];\r
+       ColorRGBA colors[] = new ColorRGBA[3];\r
+       coord[0] = (float)p1.x;\r
+       coord[1] = (float)p1.y;\r
+       coord[2] = (float)p1.z;\r
+       switch (axis) {\r
+       case X:\r
+               coord[3] = (float)p1.x;\r
+               coord[4] = (float)p1.y;\r
+               coord[5] = (float)p2.z;\r
+               colors[0] = colors[1] = colors[2] = xColor;\r
+               break;\r
+       case Y:\r
+               coord[3] = (float)p1.x;\r
+               coord[4] = (float)p1.y;\r
+               coord[5] = (float)p2.z;\r
+               colors[0] = colors[1] = colors[2] = yColor;\r
+               break;\r
+       case Z:\r
+               coord[3] = (float)p1.x;\r
+               coord[4] = (float)p2.y;\r
+               coord[5] = (float)p2.z;\r
+               colors[0] = colors[1] = colors[2] = zColor;\r
+               break;\r
+       \r
+       }\r
+       coord[6] = (float)p2.x;\r
+       coord[7] = (float)p2.y;\r
+       coord[8] = (float)p2.z;\r
+       Line shape = new Line("",BufferUtils.createFloatBuffer(coord),null,BufferUtils.createFloatBuffer(colors),null);\r
+       shape.setMode(Line.CONNECTED);\r
+       editor.getRenderingComponent().getNoShadowRoot().attachChild(shape);\r
+       shape.setRenderState(ms);\r
+        constraintHighlights.add(shape);\r
+    }\r
+    \r
+    /**\r
+     * Snaps position to axis-aligned planes defined by constraint points\r
+     * Form of position is p+v, meaning that the position that is snapped is requestedPoint + requestedDir\r
+     * @param requestedPoint one part of the position to be snapped\r
+     * @param requestedDir second part of the position to be snapped and direction that the position is allowed to move\r
+     * @return\r
+     */\r
+    public Point3d getPointSnap(Vector3d requestedPoint, Vector3d requestedDir) {\r
+        \r
+        Vector3d snappedPoint = new Vector3d();\r
+        Point3d currentPoint = null;\r
+        double u[] = new double[1];\r
+        List<Point3d> p1s = new ArrayList<Point3d>();\r
+        List<Point3d> p2s = new ArrayList<Point3d>();\r
+        List<Integer> axes = new ArrayList<Integer>();\r
+        \r
+        for (Point3d constraintPoint : constraintPoints) {\r
+            boolean snap = false;\r
+            \r
+            if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), getAxialVector(X), snappedPoint,u) && Math.abs(1.0 - u[0]) < snapAngle) {\r
+                currentPoint = new Point3d(snappedPoint);\r
+                //snapString += "Point/Plane x-snap ";\r
+                snap = true;\r
+                //addConstrainPlaneHighlight(constraintPoint, currentPoint,X);\r
+                p1s.add(constraintPoint);\r
+                p2s.add(currentPoint);\r
+                axes.add(X);\r
+            }\r
+            \r
+            if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), getAxialVector(Y), snappedPoint,u) && Math.abs(1.0 - u[0]) < snapAngle) {\r
+                currentPoint = new Point3d(snappedPoint);\r
+                //snapString += "Point/Plane y-snap ";\r
+                snap = true;\r
+                //addConstrainPlaneHighlight(constraintPoint, currentPoint,Y);\r
+                p1s.add(constraintPoint);\r
+                p2s.add(currentPoint);\r
+                axes.add(Y);\r
+            }\r
+            \r
+            if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), getAxialVector(Z), snappedPoint,u) && Math.abs(1.0 - u[0]) < snapAngle) {\r
+                currentPoint = new Point3d(snappedPoint);\r
+                //snapString += "Point/Plane z-snap ";\r
+                snap = true;\r
+                //addConstrainPlaneHighlight(constraintPoint, currentPoint,Z);\r
+                p1s.add(constraintPoint);\r
+                p2s.add(currentPoint);\r
+                axes.add(Z);\r
+            }\r
+            if (snap)\r
+                break;\r
+        }\r
+        if (p1s.size() == 0)\r
+               return null;\r
+        if (p1s.size() == 1) {\r
+               snapString += "Point/Plane ";\r
+               switch (axes.get(0)) {\r
+               case X:\r
+                       snapString += "x";\r
+                       break;\r
+               case Y:\r
+                       snapString += "y";\r
+                       break;\r
+               case Z:\r
+                       snapString += "z";\r
+                       break;\r
+               }\r
+               snapString += "-snap ";\r
+               addConstrainPlaneHighlight(p1s.get(0), p2s.get(0),axes.get(0));\r
+               return currentPoint;\r
+        } else if (p1s.size() == 3){\r
+               // all axial planes are intersecting, snapping point must be the constraint point\r
+               // all constraint points are the same, so just pick the first in the list\r
+               snapString += "Point/Point ";\r
+               return p1s.get(0);\r
+        } else {\r
+               Vector3d dir = new Vector3d();\r
+               dir.cross(getAxialVector(axes.get(0)), getAxialVector(axes.get(1)));\r
+               currentPoint = new Point3d(MathTools.closestPointOnStraight(currentPoint, p1s.get(0), dir));\r
+               addConstrainLineHighlight(p1s.get(0), currentPoint, xColor);\r
+               snapString += "Point/Line ";\r
+               return currentPoint;\r
+        }\r
+        \r
+    }\r
+    \r
+    private Vector3d getAxialVector(int axis) {\r
+       switch (axis) {\r
+       case X:\r
+               return new Vector3d(1.0,0.0,0.0);\r
+       case Y:\r
+               return new Vector3d(0.0,1.0,0.0);\r
+       case Z:\r
+               return new Vector3d(0.0,0.0,1.0);\r
+       }\r
+       throw new RuntimeException("Unknown axis " + axis);     \r
+    }\r
+    \r
+    /**\r
+     * Snaps the position to axis-aligned planes defined by constraint points\r
+     * @param requestedPoint point that is snapped\r
+     * @param requestedDir direction that point is allowed to move\r
+     * @return\r
+     */\r
+    \r
+    public Point3d getPointSnap2(Vector3d requestedPoint, Vector3d requestedDir) {\r
+        \r
+        Vector3d snappedPoint = new Vector3d();\r
+        Point3d currentPoint = null;\r
+        double u[] = new double[1];\r
+        //System.out.println(requestedPoint + "  " + requestedDir);\r
+        for (Point3d constraintPoint : constraintPoints) {\r
+            boolean snap = false;\r
+            //System.out.print(constraintPoint + " ");\r
+            if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), new Vector3d(1.0,0.0,0.0), snappedPoint,u) && Math.abs(u[0]) < snapAngle) {\r
+                currentPoint = new Point3d(snappedPoint);\r
+                snapString += "Point/Plane x-snap ";\r
+                snap = true;\r
+                addConstrainPlaneHighlight(constraintPoint, currentPoint,X);\r
+                //System.out.print(" x " + u[0]);\r
+            }\r
+            \r
+            if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), new Vector3d(0.0,1.0,0.0), snappedPoint,u) && Math.abs(u[0]) < snapAngle) {\r
+                currentPoint = new Point3d(snappedPoint);\r
+                snapString += "Point/Plane y-snap ";\r
+                snap = true;\r
+                addConstrainPlaneHighlight(constraintPoint, currentPoint,Y);\r
+                //System.out.print(" y " + u[0]);\r
+            }\r
+           \r
+            \r
+            if (MathTools.intersectStraightPlane(requestedPoint, requestedDir, new Vector3d(constraintPoint), new Vector3d(0.0,0.0,1.0), snappedPoint,u) && Math.abs(u[0]) < snapAngle) {\r
+                currentPoint = new Point3d(snappedPoint);\r
+                snapString += "Point/Plane z-snap ";\r
+                snap = true;\r
+                addConstrainPlaneHighlight(constraintPoint, currentPoint,Z);\r
+                //System.out.print(" z " + u[0]);\r
+            }\r
+            //System.out.println();\r
+            if (snap)\r
+                break;\r
+        }\r
+        return currentPoint;\r
+    }\r
+    \r
+    public String getSnapString() {\r
+        return snapString;\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/EditorContribution.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/EditorContribution.java
new file mode 100644 (file)
index 0000000..0cca6ec
--- /dev/null
@@ -0,0 +1,70 @@
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.Collection;\r
+\r
+import org.eclipse.jface.action.IMenuManager;\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.db.Graph;\r
+import org.simantics.proconf.g3d.actions.ContextAction;\r
+import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
+\r
+public interface EditorContribution {\r
+       \r
+       public String getName();\r
+       \r
+       /**\r
+        * Initializes the contribution\r
+        * @param graph\r
+        */\r
+       void initialize(Graph graph);\r
+       \r
+       \r
+       /**\r
+        * Allows contribution to modify current ui.\r
+        * @param parent\r
+        */\r
+       void createControl(Composite parent);\r
+       \r
+       /**\r
+        * Removes all changes created by createControl\r
+        */\r
+       void disposeControl();\r
+       \r
+       /**\r
+        * Fills context menu\r
+        * @param graph\r
+        * @param manager\r
+        */\r
+       void fillContextMenu(Graph graph, IMenuManager manager, StructuredResourceSelection selection);\r
+       \r
+       /**\r
+        * Fills toolbar\r
+        * \r
+        * @param manager\r
+        */\r
+       void fillLocalToolBar(IToolBarManager manager);\r
+       \r
+       /**\r
+        * Fills menumanager\r
+        * \r
+        * \r
+        * @param manager\r
+        */\r
+       void fillLocalPullDown(IMenuManager manager);\r
+\r
+       \r
+       /**\r
+        * Returns context dependent actions\r
+        * @return\r
+        */\r
+       Collection<ContextAction> getActions();\r
+       \r
+       /**\r
+        * \r
+        */\r
+       void run();\r
+       \r
+       void dispose();\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/G3DAPI.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/G3DAPI.java
new file mode 100644 (file)
index 0000000..3bec68d
--- /dev/null
@@ -0,0 +1,94 @@
+package org.simantics.proconf.g3d.base;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Tuple3d;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.proconf.g3d.Resources;\r
+\r
+/**\r
+ * Set of methods that make scene-graph handling easier.\r
+ * \r
+ * \r
+ * @author Marko Luukkainen <Marko.Luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class G3DAPI {\r
+\r
+       \r
+       public static void setWorldPosition(IEntity node, Tuple3d position) {\r
+               G3DTools.setTuple3(node.getSingleRelatedObject(Resources.g3dResource.HasWorldPosition), position);\r
+               //G3DTools.transformationUpdate(node.getGraph(), node.getResource());\r
+               G3DTools.propagateWorldTransformChange(node.getSingleRelatedObject(Resources.g3dResource.HasParent), node);\r
+       }\r
+       \r
+       public static void setLocalPosition(IEntity node, Tuple3d position) {\r
+               G3DTools.setTuple3(node.getSingleRelatedObject(Resources.g3dResource.HasLocalPosition), position);\r
+               //G3DTools.transformationUpdate(node.getGraph(), node.getResource());\r
+               G3DTools.propagateLocalTransformChange(node.getSingleRelatedObject(Resources.g3dResource.HasParent), node);\r
+               \r
+       }\r
+       \r
+       public static void setWorldOrientation(IEntity node, AxisAngle4d orientation) {\r
+               G3DTools.setOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasWorldOrientation), orientation);\r
+               //G3DTools.transformationUpdate(node.getGraph(), node.getResource());\r
+               G3DTools.propagateWorldTransformChange(node.getSingleRelatedObject(Resources.g3dResource.HasParent), node);\r
+               \r
+       }\r
+       \r
+       public static void setLocalOrientation(IEntity node, AxisAngle4d orientation) {\r
+               G3DTools.setOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation), orientation);\r
+               //G3DTools.transformationUpdate(node.getGraph(), node.getResource());\r
+               G3DTools.propagateLocalTransformChange(node.getSingleRelatedObject(Resources.g3dResource.HasParent), node);\r
+               \r
+               \r
+       }\r
+       \r
+       public static void setWorldTransformation(IEntity node, Tuple3d position, AxisAngle4d orientation) {\r
+               G3DTools.setTuple3(node.getSingleRelatedObject(Resources.g3dResource.HasWorldPosition), position);\r
+               G3DTools.setOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasWorldOrientation), orientation);\r
+               //G3DTools.transformationUpdate(node.getGraph(), node.getResource());\r
+               G3DTools.propagateWorldTransformChange(node.getSingleRelatedObject(Resources.g3dResource.HasParent), node);\r
+               \r
+       }\r
+       \r
+       public static void setLocalTransformation(IEntity node, Tuple3d position, AxisAngle4d orientation) {\r
+               G3DTools.setTuple3(node.getSingleRelatedObject(Resources.g3dResource.HasLocalPosition), position);\r
+               G3DTools.setOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation), orientation);\r
+               //G3DTools.transformationUpdate(node.getGraph(), node.getResource());\r
+               G3DTools.propagateLocalTransformChange(node.getSingleRelatedObject(Resources.g3dResource.HasParent), node);\r
+       }\r
+       \r
+       public static void addNodeWorld(IEntity parent, IEntity node) {\r
+               parent.addStatement(Resources.g3dResource.HasChild, node);\r
+               G3DTools.propagateWorldTransformChange(parent,node);\r
+       }\r
+       \r
+       public static void addNodeLocal(IEntity parent, IEntity node) {\r
+               parent.addStatement(Resources.g3dResource.HasChild, node);\r
+               G3DTools.propagateLocalTransformChange(parent,node);\r
+       }\r
+       \r
+       public static void addNodeWorld(IEntity parent, Resource relation, IEntity node) {\r
+               assert(parent.getGraph().isSubrelationOf(relation, Resources.g3dResource.HasChild));\r
+               parent.addStatement(relation, node);\r
+               G3DTools.propagateWorldTransformChange(parent,node);\r
+       }\r
+       \r
+       public static void addNodeLocal(IEntity parent, Resource relation, IEntity node) {\r
+               assert(parent.getGraph().isSubrelationOf(relation, Resources.g3dResource.HasChild));\r
+               parent.addStatement(relation, node);\r
+               G3DTools.propagateLocalTransformChange(parent,node);\r
+       }\r
+       \r
+       public static void removeNode(IEntity node) {\r
+               node.removeRelatedStatements(Resources.g3dResource.HasParent);\r
+       }\r
+       \r
+       public static void moveNode(IEntity node, IEntity newParent) {\r
+               node.removeRelatedStatements(Resources.g3dResource.HasParent);\r
+               newParent.addStatement(Resources.g3dResource.HasChild, node);\r
+               G3DTools.propagateWorldTransformChange(newParent,node);\r
+       }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/G3DTools.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/G3DTools.java
new file mode 100644 (file)
index 0000000..0b08880
--- /dev/null
@@ -0,0 +1,399 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.Collection;\r
+import java.util.Set;\r
+import java.util.Stack;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.AxisAngle4f;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Point3f;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Tuple3d;\r
+import javax.vecmath.Tuple3f;\r
+import javax.vecmath.Vector3d;\r
+import javax.vecmath.Vector3f;\r
+\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.Statement;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.layer0.utils.viewpoints.State;\r
+import org.simantics.layer0.utils.viewpoints.TraversalDecision;\r
+import org.simantics.layer0.utils.viewpoints.TraversalResult;\r
+import org.simantics.layer0.utils.viewpoints.TraversalRule;\r
+import org.simantics.layer0.utils.viewpoints.TraversalUtils;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+import org.simantics.proconf.g3d.stubs.Orientation;\r
+import org.simantics.proconf.g3d.stubs.Position;\r
+\r
+/**\r
+ * Basic ThreeDimensionalModelingOntology tools\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class G3DTools {\r
+       \r
+       private static boolean DEBUG = false;\r
+       \r
+       private static TransformationTools tt;\r
+\r
+       public static void initialize() {\r
+               tt = new TransformationTools(Resources.g3dResource.HasChild, Resources.g3dResource.HasParent);\r
+       }\r
+       \r
+       public static void deinitialize() {\r
+               tt = null;\r
+       }\r
+       \r
+       public static Point3d getPoint(IEntity p) {\r
+        return new Point3d(p.getSingleRelatedScalarDouble(Resources.g3dResource.HasX),\r
+                                          p.getSingleRelatedScalarDouble(Resources.g3dResource.HasY),\r
+                                          p.getSingleRelatedScalarDouble(Resources.g3dResource.HasZ));\r
+    }\r
+    \r
+    public static Point3f getPointFloat(IEntity p) {\r
+        return new Point3f((float)p.getSingleRelatedScalarDouble(Resources.g3dResource.HasX),\r
+                                          (float)p.getSingleRelatedScalarDouble(Resources.g3dResource.HasY),\r
+                                          (float)p.getSingleRelatedScalarDouble(Resources.g3dResource.HasZ));\r
+    }\r
+    \r
+    \r
+    public static Vector3d getVector(IEntity p) {\r
+        return new Vector3d(p.getSingleRelatedScalarDouble(Resources.g3dResource.HasX),\r
+                                                       p.getSingleRelatedScalarDouble(Resources.g3dResource.HasY),\r
+                                                       p.getSingleRelatedScalarDouble(Resources.g3dResource.HasZ));\r
+    }\r
+    \r
+    public static Vector3f getVectorFloat(IEntity p) {\r
+        return new Vector3f((float)p.getSingleRelatedScalarDouble(Resources.g3dResource.HasX),\r
+                                                       (float)p.getSingleRelatedScalarDouble(Resources.g3dResource.HasY),\r
+                                                       (float)p.getSingleRelatedScalarDouble(Resources.g3dResource.HasZ));\r
+    }\r
+\r
+    \r
+    public static void setTuple3(IEntity d, Tuple3d translation) {\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasX, translation.x);\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasY, translation.y);\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasZ, translation.z);    \r
+    }\r
+    \r
+    public static void setTuple3(IEntity d, Tuple3f translation) {\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasX, translation.x);\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasY, translation.y);\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasZ, translation.z);    \r
+    }\r
+\r
+    public static void setTuple3(IEntity d, double x, double y, double z) {\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasX, x);\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasY, y);\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasZ, z);    \r
+    }\r
+    \r
+    public static void addTuple3(IEntity d, Tuple3d translation) {\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasX, translation.x + d.getSingleRelatedScalarDouble(Resources.g3dResource.HasX));\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasY, translation.y + d.getSingleRelatedScalarDouble(Resources.g3dResource.HasY));\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasZ, translation.z + d.getSingleRelatedScalarDouble(Resources.g3dResource.HasZ));\r
+    }\r
+    \r
+    public static void addTuple3(IEntity d, Tuple3f translation) {\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasX, translation.x + d.getSingleRelatedScalarDouble(Resources.g3dResource.HasX));\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasY, translation.y + d.getSingleRelatedScalarDouble(Resources.g3dResource.HasY));\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasZ, translation.z + d.getSingleRelatedScalarDouble(Resources.g3dResource.HasZ));\r
+    }\r
+\r
+    public static void addTuple3(IEntity d, double x, double y, double z) {\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasX, x + d.getSingleRelatedScalarDouble(Resources.g3dResource.HasX));\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasY, y + d.getSingleRelatedScalarDouble(Resources.g3dResource.HasY));\r
+       d.setRelatedScalarDouble(Resources.g3dResource.HasZ, z + d.getSingleRelatedScalarDouble(Resources.g3dResource.HasZ));    \r
+    }\r
+    \r
+    public static AxisAngle4d getOrientation(IEntity r) {\r
+        return new AxisAngle4d(r.getSingleRelatedScalarDouble(Resources.g3dResource.HasX),\r
+                                                  r.getSingleRelatedScalarDouble(Resources.g3dResource.HasY),\r
+                                                  r.getSingleRelatedScalarDouble(Resources.g3dResource.HasZ),\r
+                                                  r.getSingleRelatedScalarDouble(Resources.g3dResource.HasAngle));\r
+    }\r
+    \r
+    public static AxisAngle4f getOrientationFloat(IEntity r) {\r
+        return new AxisAngle4f((float)r.getSingleRelatedScalarDouble(Resources.g3dResource.HasX),\r
+                                          (float)r.getSingleRelatedScalarDouble(Resources.g3dResource.HasY),\r
+                                          (float)r.getSingleRelatedScalarDouble(Resources.g3dResource.HasZ),\r
+                                          (float)r.getSingleRelatedScalarDouble(Resources.g3dResource.HasAngle));\r
+    }\r
+\r
+    public static void setOrientation(IEntity r, AxisAngle4d aa) {\r
+       r.setRelatedScalarDouble(Resources.g3dResource.HasX, aa.x);\r
+       r.setRelatedScalarDouble(Resources.g3dResource.HasY, aa.y);\r
+       r.setRelatedScalarDouble(Resources.g3dResource.HasZ, aa.z);\r
+       r.setRelatedScalarDouble(Resources.g3dResource.HasAngle, aa.angle);\r
+    }\r
+    \r
+    \r
+    public static void multiplyOrientation(IEntity r, AxisAngle4d rot) {\r
+               AxisAngle4d current = getOrientation(r);\r
+               Quat4d q1 = new Quat4d();\r
+               q1.set(current);\r
+               Quat4d q2 = new Quat4d();\r
+               // q2.set(rot);\r
+               q2.set(rot);\r
+               q2.mul(q1);\r
+               rot.set(q2);\r
+               setOrientation(r, rot);\r
+       }\r
+    \r
+    \r
+    public static AxisAngle4d getWorldFromLocal(IEntity node, AxisAngle4d localRot) {\r
+       return tt.getWorldFromLocal(node, localRot);\r
+    }\r
+    \r
+    public static Point3d getWorldFromLocal(IEntity node, Point3d localRot) {\r
+       return tt.getWorldFromLocal(node, localRot);\r
+    }\r
+    \r
+    public static AxisAngle4d getLocalFromWorld(IEntity node, AxisAngle4d localRot) {\r
+       return tt.getLocalFromWorld(node, localRot);\r
+    }\r
+    \r
+    public static Point3d getLocalFromWorld(IEntity node, Point3d localRot) {\r
+       return tt.getLocalFromWorld(node, localRot);\r
+    }\r
+    \r
+    public static void propagateLocalTransformChange(IEntity node, IEntity child) {\r
+       tt.propagateLocalTransformChange(node, child);\r
+    }\r
+    \r
+    public static void propagateWorldTransformChange(IEntity node, IEntity child) {\r
+       tt.propagateWorldTransformChange(node, child);\r
+    }\r
+    \r
+    public static void transformationUpdate(Graph graph, Resource resource) {\r
+       tt.transformationUpdate(graph, resource);\r
+    }\r
+    \r
+    public static void resetTransformation(IEntity shape) {\r
+               Graph graph = shape.getGraph();\r
+               if (shape.getAtMostOneRelatedObject(Resources.g3dResource.HasLocalPosition) == null) {\r
+\r
+                       // LocalPosition p = LocalPosition.createDefault(graph);\r
+                       Position p = Position.createDefault(graph);\r
+                       shape.addStatement(Resources.g3dResource.HasLocalPosition, p);\r
+                       // WorldPosition p2 = WorldPosition.createDefault(graph);\r
+                       Position p2 = Position.createDefault(graph);\r
+                       shape.addStatement(Resources.g3dResource.HasWorldPosition, p2);\r
+                       p.setX(new double[] { 0.0 });\r
+                       p.setY(new double[] { 0.0 });\r
+                       p.setZ(new double[] { 0.0 });\r
+\r
+                       p2.setX(new double[] { 0.0 });\r
+                       p2.setY(new double[] { 0.0 });\r
+                       p2.setZ(new double[] { 0.0 });\r
+\r
+               } else {\r
+                       G3DTools.setTuple3(shape.getSingleRelatedObject(Resources.g3dResource.HasLocalPosition), 0.0, 0.0, 0.0);\r
+                       G3DTools.setTuple3(shape.getSingleRelatedObject(Resources.g3dResource.HasWorldPosition), 0.0, 0.0, 0.0);\r
+               }\r
+               if (shape.getAtMostOneRelatedObject(Resources.g3dResource.HasLocalOrientation) == null) {\r
+\r
+                       // LocalOrientation r = LocalOrientationFactory.create(graph);\r
+                       Orientation r = Orientation.createDefault(graph);\r
+                       shape.addStatement(Resources.g3dResource.HasLocalOrientation, r);\r
+                       // WorldOrientation r2 = WorldOrientationFactory.create(graph);\r
+                       Orientation r2 = Orientation.createDefault(graph);\r
+                       shape.addStatement(Resources.g3dResource.HasWorldOrientation, r2);\r
+                       r.setAngle(new double[] { 0.0 });\r
+                       r.setX(new double[] { 1.0 });\r
+                       r.setY(new double[] { 0.0 });\r
+                       r.setZ(new double[] { 0.0 });\r
+                       r2.setAngle(new double[] { 0.0 });\r
+                       r2.setX(new double[] { 1.0 });\r
+                       r2.setY(new double[] { 0.0 });\r
+                       r2.setZ(new double[] { 0.0 });\r
+\r
+               } else {\r
+                       G3DTools.setOrientation(shape.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation),\r
+                                       new AxisAngle4d(0.0, 1.0, 0.0, 0.0));\r
+                       G3DTools.setOrientation(shape.getSingleRelatedObject(Resources.g3dResource.HasWorldOrientation),\r
+                                       new AxisAngle4d(0.0, 1.0, 0.0, 0.0));\r
+               }\r
+       }\r
+    \r
+    \r
+    public static G3DNode getModelFromResource(Graph graph,Resource resource) {\r
+       G3DNode node = new G3DNode(graph, resource);\r
+       while (true) {\r
+               G3DNode parent = node.getParent();\r
+               if (parent == null)\r
+                       break;\r
+               node = parent;\r
+       }\r
+        return node;\r
+    }\r
+    \r
+    /**\r
+     * Checks if instance has a certain property instance\r
+     * @param instance\r
+     * @param propertyInstance\r
+     * @return\r
+     */\r
+    public static boolean hasProperty(Graph graph,Resource instance, Resource propertyInstance) {\r
+        Builtins builtins = graph.getBuiltins();\r
+       Stack<IEntity> props = new Stack<IEntity>();\r
+        IEntity IEntity = EntityFactory.create(graph, instance);\r
+        Collection<IEntity> res = IEntity.getRelatedObjects(builtins.HasProperty);\r
+        for (IEntity t : res)\r
+               props.add(t);\r
+        \r
+        while (!props.isEmpty()) {\r
+            IEntity property = props.pop();\r
+            if (property.getResource().equals(propertyInstance)) {\r
+                return true;\r
+            }\r
+            res = property.getRelatedObjects(builtins.HasProperty);\r
+            for (IEntity r : res) {\r
+                props.add(r);\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+    \r
+    /**\r
+     * Checks if one of shapes subshapes has a certain property\r
+     * @param instance shape instance\r
+     * @param propertyInstance instance of a property\r
+     * @return\r
+     * \r
+     */\r
+    public static boolean hasSubProperty(Graph graph,Resource instance, Resource propertyInstance) {\r
+        Builtins builtins = graph.getBuiltins();\r
+        Stack<IEntity> instances = new Stack<IEntity>();\r
+\r
+         //Resource res[] = instance.getRelatedResources(Builtins.HasProperty);\r
+        IEntity entity = EntityFactory.create(graph, instance);\r
+        Collection<IEntity> res;\r
+//         res = entity.getRelatedObjects(Resources.g3dResource.HasChild);\r
+//         for (IEntity t : res) {\r
+//              Collection<IEntity> sub = t.getRelatedObjects(Resources.g3dResource.HasGeometryDefinition);\r
+//              if (sub.size() > 0)\r
+//                     instances.addAll(sub);\r
+//         }\r
+        {\r
+                Collection<IEntity> sub = entity.getRelatedObjects(Resources.g3dResource.HasGeometryDefinition);\r
+                if (sub.size() > 0)\r
+               instances.addAll(sub);\r
+        }\r
+         while (!instances.isEmpty()) {\r
+            IEntity i = instances.pop();\r
+            Stack<IEntity> props = new Stack<IEntity>();\r
+            res = i.getRelatedObjects(builtins.HasProperty);\r
+            for (IEntity r : res) {\r
+                props.add(r);\r
+            }\r
+            while (!props.isEmpty()) {\r
+                IEntity property = props.pop();\r
+                if (property.equals(propertyInstance)) {\r
+                    return true;\r
+                }\r
+                res = property.getRelatedObjects(builtins.HasProperty);\r
+                for (IEntity r : res) {\r
+                    props.add(r);\r
+                }\r
+            }\r
+            res = i.getRelatedObjects(Resources.g3dResource.HasGeometryDefinition);\r
+            for (IEntity r : res) {\r
+               // TODO : unnecessary check\r
+               Collection<IEntity> sub = r.getRelatedObjects(Resources.g3dResource.GeometryDefinitionOf);\r
+                       if (sub.size() > 0)\r
+                       instances.add(r);\r
+            }\r
+            \r
+        }\r
+         return false;\r
+     }\r
+    \r
+    \r
+    \r
+    \r
+    \r
+    \r
+    /**\r
+     * Loads positions of control point to rule cache\r
+     * \r
+     * @param root resource of the modeled plant\r
+     */\r
+    public static void reloadCache(Graph graph, Resource root) {\r
+//        TraverseHandler handler = new TraverseHandler() {\r
+//            public boolean addToResult(Resource r) {\r
+//                if (r.isInstanceOf(GlobalIdMap.get(ThreeDimensionalModelingOntologyMapping.GRAPHICS_NODE)))\r
+//                    return true;\r
+//                return false;\r
+//            }\r
+//            \r
+//            public TraverseRelation[] traverseFromResource(Resource resource) {\r
+//                return new TraverseRelation[] { new TraverseRelation(\r
+//                        ThreeDimensionalModelingOntologyMapping.HAS_SUBNODES,\r
+//                        TraverseDirection.OUTBOUND)};\r
+//            }\r
+//            \r
+//            \r
+//        };\r
+       \r
+       IEntity IEntity = EntityFactory.create(graph, root);\r
+       State s = new State() {};\r
+       TraversalResult res = TraversalUtils.traverse(new TraversalRule (){\r
+               \r
+               \r
+               @Override\r
+               public boolean areAllStatesRelevant() {\r
+                       return true;\r
+               }\r
+               \r
+               @Override\r
+               public TraversalDecision makeTraversalDecision(State state,\r
+                               Statement statement) {\r
+                       if (statement.getPredicate().isInstanceOf(Resources.g3dResource.HasChild))\r
+                               return TraversalDecision.continueTraversal(state);\r
+                       else\r
+                               return TraversalDecision.stopTraversal;\r
+               }\r
+               \r
+               @Override\r
+               public Collection<State> relevantStates() {\r
+                       return null;\r
+               }\r
+               }, IEntity,s\r
+               );\r
+       \r
+    \r
+       Set<Resource> cps = res.get(s);\r
+        \r
+        //Collection<Resource> cps = TraverseUtils.traverseGraph(root, handler);\r
+        for (Resource r : cps) {\r
+            G3DNode cp = new G3DNode(graph,r);\r
+            if (cp.getLocalPosition() != null)\r
+                tt.storeProperty(cp.getLocalPosition().getResource(),G3DTools.getPoint(cp.getLocalPosition()));\r
+            if (cp.getWorldPosition() != null)\r
+                tt.storeProperty(cp.getWorldPosition().getResource(),G3DTools.getPoint(cp.getWorldPosition()));\r
+            if (cp.getLocalOrientation() != null)\r
+                tt.storeProperty(cp.getLocalOrientation().getResource(),G3DTools.getOrientation(cp.getLocalOrientation()));\r
+            if (cp.getWorldOrientation() != null)\r
+                tt.storeProperty(cp.getWorldOrientation().getResource(),G3DTools.getOrientation(cp.getWorldOrientation()));\r
+            \r
+        }\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/GeometryProvider.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/GeometryProvider.java
new file mode 100644 (file)
index 0000000..8ebb506
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import org.simantics.layer0.utils.IEntity;\r
+\r
+\r
+/**\r
+ * Interface for geometryProviders\r
+ * \r
+ * TODO : instead of using Geometry array, create class that is passed through\r
+ * TODO : Current animation system links resources; what about code generated meshes ?\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public interface GeometryProvider {\r
+    \r
+       /**\r
+        * Used to check if GeometryProvider can generate mesh\r
+        * @param instance\r
+        * @return\r
+        */\r
+    public boolean canHandle(IEntity instance);\r
+       \r
+    /**\r
+     * Generates mesh\r
+     * @param instance\r
+     * @param transform\r
+     * @return\r
+     */\r
+    public com.jme.scene.Geometry[] getGeometryFromResource(IEntity instance, boolean transform);\r
+    \r
+    /**\r
+     * Updates mesh\r
+     * @param instance\r
+     * @param transform\r
+     * @param geometry\r
+     * @return\r
+     */\r
+    public boolean reconstructGeometry(IEntity instance, boolean transform, com.jme.scene.Geometry[] geometry);\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/GeometryProviderRegistry.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/GeometryProviderRegistry.java
new file mode 100644 (file)
index 0000000..fa92b87
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.utils.ui.plugin.Extension;\r
+import org.simantics.utils.ui.plugin.ExtensionLoader;\r
+\r
+import com.jme.scene.Geometry;\r
+\r
+public class GeometryProviderRegistry {\r
+    private static GeometryProviderRegistry instance;\r
+    public final static String ELEMENT_NAME = "Geometry";\r
+    public final static String NAME_SPACE = "org.simantics.proconf.g3d";\r
+    public final static String EP_NAME = "geometry";\r
+    \r
+    private ExtensionLoader<GeometryProvider> loader;\r
+    private Map<Resource,GeometryProvider> providers;\r
+    \r
+    private GeometryProviderRegistry() {\r
+        loader = new ExtensionLoader<GeometryProvider>(ELEMENT_NAME, NAME_SPACE, EP_NAME);\r
+        providers = new HashMap<Resource,GeometryProvider>();\r
+    }\r
+    \r
+    public static GeometryProviderRegistry getInstance() {\r
+        if (instance==null) instance = new GeometryProviderRegistry();\r
+        return instance;\r
+    }\r
+\r
+    public Extension<GeometryProvider>[] getExtensions() {\r
+        return loader.getExtensions();\r
+    }\r
+    \r
+    private Map<Resource,GeometryProvider> getProviderMap() {\r
+        return providers;\r
+    }\r
+    \r
+    public static Geometry[] getGeometry(IEntity thing, boolean transform) {\r
+        GeometryProvider provider = getGeometryProvider(thing);\r
+        return provider.getGeometryFromResource(thing, transform);\r
+    }\r
+    \r
+    public static GeometryProvider getGeometryProvider(IEntity thing) {\r
+       Collection<IEntity> types = thing.getRelatedObjects(thing.getGraph().getBuiltins().InstanceOf);\r
+        \r
+       //Resource types[] = OntologyUtils.getTypes(resource);\r
+       for (IEntity t : types) {\r
+               GeometryProvider provider = getInstance().getProviderMap().get(t.getResource());\r
+               if (provider == null) {\r
+                for (Extension<GeometryProvider> e : getInstance().getExtensions()) {\r
+                    if (e.getInstance().canHandle(thing)) {\r
+                        getInstance().getProviderMap().put(t.getResource(), e.getInstance());\r
+                        return e.getInstance();\r
+                    }\r
+                }\r
+                \r
+            } else {\r
+               return provider;\r
+            }\r
+       }\r
+       \r
+       throw new UnsupportedOperationException("Cannot handle resource " + thing);\r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/JmeRenderingComponent.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/JmeRenderingComponent.java
new file mode 100644 (file)
index 0000000..4e4905d
--- /dev/null
@@ -0,0 +1,93 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import com.jme.renderer.Camera;\r
+import com.jme.scene.Node;\r
+import com.jme.system.DisplaySystem;\r
+\r
+\r
+\r
+\r
+/**\r
+ * Rendering component\r
+ * Allows to change underlying rendering so that\r
+ * additional information can be presented to the user\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public abstract class JmeRenderingComponent {\r
+    public static final int PARALLEL_PROJECTION = 0;\r
+    public static final int PERSPECTIVE_PROJECTION = 1;\r
+    \r
+    /**\r
+     * Returns root node for nodes that cast and receive shadows.\r
+     * @return\r
+     */\r
+       public abstract Node getShadowRoot();\r
+       \r
+       /**\r
+     * Returns root node for nodes that do not cast shadows.\r
+     * @return\r
+     */\r
+       public abstract Node getNoCastRoot();\r
+       \r
+       /**\r
+        * Returns root node of the scenegraph\r
+        * @return\r
+        */\r
+       public abstract Node getRoot();\r
+       \r
+       /**\r
+        * Returns root node of orthogonal nodes (nodes that always face the camera)\r
+        * @return\r
+        */\r
+       public abstract Node getOrthoNode();\r
+       \r
+       /**\r
+        * Returns root node for nodes that do not cast or receive shadows.\r
+        * @return\r
+        */\r
+       public abstract Node getNoShadowRoot();\r
+       \r
+       public abstract void init(DisplaySystem displaySystem);\r
+       \r
+       /**\r
+        * Sets projection policy.\r
+        * FIXME : this was for Xith compatibility!\r
+        * @param policy\r
+        */\r
+       public abstract void setProjectionPolicy(int policy);\r
+    public abstract int getProjectionPolicy();\r
+    \r
+    public abstract float getScreenScale();\r
+    public abstract void setScreenScale(float screenScale);\r
+    public abstract float getFieldOfView();\r
+    public abstract void dispose();\r
+    \r
+    /**\r
+     * Update flag (Return true if view needs to be rendered)\r
+     * @return\r
+     */\r
+    public boolean update() {return false;}\r
+    public abstract Camera getCamera();\r
+    \r
+    public abstract void render();\r
+    public abstract void resize(int width, int height);\r
+    public abstract DisplaySystem getDisplaySystem();\r
+    \r
+    /**\r
+     * TODO : this is for debugging purposes and will be removed.\r
+     * @param text\r
+     */\r
+    public abstract void setDebugText(String text);\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/MathTools.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/MathTools.java
new file mode 100644 (file)
index 0000000..2a89a4a
--- /dev/null
@@ -0,0 +1,395 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Matrix3d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Tuple3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import com.jme.math.Vector2f;\r
+\r
+/**\r
+ * Some useful geometry related math functions. Beware, methods may modify their input parameters!\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class MathTools {\r
+    \r
+    static double EPS = 0.001;\r
+    \r
+    public static Vector3d closestPointOnEdge(Vector3d point, Vector3d edgePoint1, Vector3d edgePoint2) {\r
+        point.sub(edgePoint1);\r
+        Vector3d v = new Vector3d(edgePoint2);\r
+        v.sub(edgePoint1);\r
+        double t = v.dot(point);\r
+        t /= v.lengthSquared();\r
+        if (t <= 0.0f)\r
+          return edgePoint1;\r
+        if (t >= 1.0f)\r
+          return edgePoint2;\r
+        v.scale(t);\r
+        v.add(edgePoint1);\r
+        return v;   \r
+    }\r
+    \r
+    public static Vector3d closestPointOnStraight(Point3d point, Point3d straightPoint, Vector3d straightDir) {\r
+        Vector3d v = new Vector3d(point);\r
+        v.sub(straightPoint);\r
+        double t = straightDir.dot(v);\r
+        t /= straightDir.lengthSquared();\r
+        v.set(straightDir);\r
+        v.scale(t);\r
+        v.add(straightPoint);\r
+        return v;   \r
+    }\r
+    \r
+    public static Vector3d closestPointOnStraight(Point3d point, Point3d straightPoint, Vector3d straightDir, double u[]) {\r
+        Vector3d v = new Vector3d(point);\r
+        v.sub(straightPoint);\r
+        u[0] = straightDir.dot(v);\r
+        u[0] /= straightDir.lengthSquared();\r
+        v.set(straightDir);\r
+        v.scale(u[0]);\r
+        v.add(straightPoint);\r
+        return v;   \r
+    }\r
+    \r
+    public static double distanceFromPlane(Vector3d point, Vector3d planeNormal, Tuple3d planePoint) {\r
+        point.sub(planePoint);\r
+        \r
+        return planeNormal.dot(point);\r
+    }\r
+      \r
+    public static double distanceFromPlane(Vector3d point, Vector3d planeNormal, float d) {\r
+        return (planeNormal.dot(point) + d);\r
+    }\r
+    \r
+    public static boolean intersectStraightPlane(Tuple3d linePoint, Vector3d lineDir, Tuple3d planePoint, Vector3d planeNormal, Tuple3d intersectPoint) {\r
+        intersectPoint.set(planePoint);\r
+        intersectPoint.sub(linePoint);\r
+        double u = planeNormal.dot(new Vector3d(intersectPoint));\r
+        double v = planeNormal.dot(lineDir);\r
+        if (Math.abs(v) < EPS)\r
+            return false;\r
+        u /= v;\r
+        intersectPoint.set(lineDir);\r
+        intersectPoint.scale(u);\r
+        intersectPoint.add(linePoint);\r
+        return true;\r
+    }\r
+    \r
+    public static boolean intersectStraightPlane(Tuple3d linePoint, Vector3d lineDir, Tuple3d planePoint, Vector3d planeNormal, Vector3d intersectPoint, double[] u) {\r
+        intersectPoint.set(planePoint);\r
+        intersectPoint.sub(linePoint);\r
+        u[0] = planeNormal.dot(intersectPoint);\r
+        double v = planeNormal.dot(lineDir);\r
+        if (Math.abs(v) < EPS)\r
+            return false;\r
+        u[0] /= v;\r
+        intersectPoint.set(lineDir);\r
+        intersectPoint.scale(u[0]);\r
+        intersectPoint.add(linePoint);\r
+        return true;\r
+    }\r
+    \r
+    public static boolean intersectLineLine(Vector3d p1,Vector3d p2,Vector3d p3,Vector3d p4,Vector3d pa,Vector3d pb) {\r
+            Vector3d p13 = new Vector3d();\r
+            Vector3d p43 = new Vector3d();\r
+            Vector3d p21 = new Vector3d();\r
+            double d1343,d4321,d1321,d4343,d2121;\r
+            double numer,denom;\r
+            p13.sub(p1, p3);\r
+            p43.sub(p4,p3);\r
+            if (Math.abs(p43.x)  < EPS && Math.abs(p43.y)  < EPS && Math.abs(p43.z)  < EPS)\r
+               return false;\r
+            p21.sub(p2,p1);\r
+            if (Math.abs(p21.x)  < EPS && Math.abs(p21.y)  < EPS && Math.abs(p21.z)  < EPS)\r
+               return false;\r
+\r
+            d1343 = p13.dot(p43);\r
+            d4321 = p43.dot(p21);\r
+            d1321 = p13.dot(p21);\r
+            d4343 = p43.lengthSquared();\r
+            d2121 = p21.lengthSquared();\r
+\r
+            denom = d2121 * d4343 - d4321 * d4321;\r
+            if (Math.abs(denom) < EPS)\r
+               return false;\r
+            numer = d1343 * d4321 - d1321 * d4343;\r
+\r
+            double mua = numer / denom;\r
+            double mub = (d1343 + d4321 * mua) / d4343;\r
\r
+            pa.x = p1.x + mua * p21.x;\r
+            pa.y = p1.y + mua * p21.y;\r
+            pa.z = p1.z + mua * p21.z;\r
+            pb.x = p3.x + mub * p43.x;\r
+            pb.y = p3.y + mub * p43.y;\r
+            pb.z = p3.z + mub * p43.z;\r
+\r
+            return true;\r
+    }\r
+    \r
+    public static boolean intersectStraightStraight(Vector3d p1,Vector3d p21,Vector3d p3,Vector3d p43,Tuple3d pa,Tuple3d pb) {\r
+        Vector3d p13 = new Vector3d();\r
+\r
+        double d1343,d4321,d1321,d4343,d2121;\r
+        double numer,denom;\r
+        \r
+        p13.sub(p1, p3);\r
+        if (Math.abs(p43.x)  < EPS && Math.abs(p43.y)  < EPS && Math.abs(p43.z)  < EPS)\r
+           return false;\r
+        if (Math.abs(p21.x)  < EPS && Math.abs(p21.y)  < EPS && Math.abs(p21.z)  < EPS)\r
+           return false;\r
+\r
+        d1343 = p13.dot(p43);\r
+        d4321 = p43.dot(p21);\r
+        d1321 = p13.dot(p21);\r
+        d4343 = p43.lengthSquared();\r
+        d2121 = p21.lengthSquared();\r
+\r
+        denom = d2121 * d4343 - d4321 * d4321;\r
+        if (Math.abs(denom) < EPS)\r
+           return false;\r
+        numer = d1343 * d4321 - d1321 * d4343;\r
+\r
+        double mua = numer / denom;\r
+        double mub = (d1343 + d4321 * mua) / d4343;\r
+\r
+        pa.x = p1.x + mua * p21.x;\r
+        pa.y = p1.y + mua * p21.y;\r
+        pa.z = p1.z + mua * p21.z;\r
+        pb.x = p3.x + mub * p43.x;\r
+        pb.y = p3.y + mub * p43.y;\r
+        pb.z = p3.z + mub * p43.z;\r
+\r
+        return true;\r
+   }\r
+    \r
+    /**\r
+     * Calculate the line segment PaPb that is the shortest route between\r
+     *  two lines P1P2 and P3P4. Calculate also the values of mua and mub where\r
+     *  Pa = P1 + mua (P2 - P1)\r
+     *  Pb = P3 + mub (P4 - P3)\r
+     * @param p1\r
+     * @param p21\r
+     * @param p3\r
+     * @param p43\r
+     * @param pa\r
+     * @param pb\r
+     * @param mu\r
+     * @return\r
+     */\r
+    public static boolean intersectStraightStraight(Tuple3d p1,Vector3d p21,Tuple3d p3,Vector3d p43,Tuple3d pa,Tuple3d pb, double mu[]) {\r
+        Vector3d p13 = new Vector3d();\r
+\r
+        double d1343,d4321,d1321,d4343,d2121;\r
+        double numer,denom;\r
+        double EPS = 0.001;\r
+        p13.sub(p1, p3);\r
+        if (Math.abs(p43.x)  < EPS && Math.abs(p43.y)  < EPS && Math.abs(p43.z)  < EPS)\r
+           return false;\r
+        if (Math.abs(p21.x)  < EPS && Math.abs(p21.y)  < EPS && Math.abs(p21.z)  < EPS)\r
+           return false;\r
+\r
+        d1343 = p13.dot(p43);\r
+        d4321 = p43.dot(p21);\r
+        d1321 = p13.dot(p21);\r
+        d4343 = p43.lengthSquared();\r
+        d2121 = p21.lengthSquared();\r
+\r
+        denom = d2121 * d4343 - d4321 * d4321;\r
+        if (Math.abs(denom) < EPS)\r
+           return false;\r
+        numer = d1343 * d4321 - d1321 * d4343;\r
+\r
+        mu[0] = numer / denom;\r
+        mu[1] = (d1343 + d4321 * mu[0]) / d4343;\r
+\r
+        pa.x = p1.x + mu[0] * p21.x;\r
+        pa.y = p1.y + mu[0] * p21.y;\r
+        pa.z = p1.z + mu[0] * p21.z;\r
+        pb.x = p3.x + mu[1] * p43.x;\r
+        pb.y = p3.y + mu[1] * p43.y;\r
+        pb.z = p3.z + mu[1] * p43.z;\r
+\r
+        return true;\r
+   }\r
+   \r
+   public static AxisAngle4d getFromEuler2(Vector3d euler) {\r
+       AxisAngle4d aa = new AxisAngle4d();\r
+       aa.angle = euler.length();\r
+       Vector3d normal = new Vector3d(euler);\r
+       if (aa.angle > EPS) {\r
+           normal.normalize();\r
+           aa.x = normal.x;\r
+           aa.y = normal.y;\r
+           aa.z = normal.z;\r
+       } else {\r
+           aa.x = 1.0;\r
+           aa.y = 0.0;\r
+           aa.z = 0.0;\r
+       }\r
+       \r
+       return aa;\r
+   }\r
+   \r
+   public static Vector3d getEuler(AxisAngle4d aa) {\r
+       Vector3d euler = new Vector3d(aa.x,aa.y,aa.z);\r
+       euler.scale(aa.angle);\r
+       return euler;\r
+   }\r
+   \r
+   public static void rotate(Quat4d q, Tuple3d in, Tuple3d out) {\r
+       // p' = q * p * q'\r
+       double tw =           - q.x*in.x - q.y*in.y - q.z*in.z;\r
+       double tx =  q.w*in.x            + q.y*in.z - q.z*in.y;\r
+       double ty =  q.w*in.y - q.x*in.z            + q.z*in.x;\r
+       double tz =  q.w*in.z + q.x*in.y - q.y*in.x           ;\r
+       \r
+       //temp * q' -> x = -x, y = -y z = -z\r
+       //out.w = tw*q.w + tx*q.x + ty*q.y + tz*q.z;\r
+       out.x =  -tw*q.x + tx*q.w - ty*q.z + tz*q.y;\r
+       out.y =  -tw*q.y + tx*q.z + ty*q.w - tz*q.x;\r
+       out.z =  -tw*q.z - tx*q.y + ty*q.x + tz*q.w;  \r
+   }\r
+   \r
+   public static void getMatrix(Quat4d quat, Matrix3d m) {\r
+                  m.m00 = 1.0f - 2.0 * (quat.y * quat.y + quat.z * quat.z);\r
+                  m.m01 = 2.0 * (quat.x * quat.y + quat.w * quat.z);\r
+                  m.m02 = 2.0 * (quat.x * quat.z - quat.w * quat.y);\r
+                  m.m10 = 2.0 * (quat.x * quat.y - quat.w * quat.z);\r
+                  m.m11 = 1.0 - 2.0f * (quat.x * quat.x + quat.z * quat.z);\r
+                  m.m12 = 2.0 * (quat.y * quat.z + quat.w * quat.x);\r
+                  m.m20 = 2.0 * (quat.x * quat.z + quat.w * quat.y);\r
+                  m.m21 = 2.0 * (quat.y * quat.z - quat.w * quat.x);\r
+                  m.m22 = 1.0 - 2.0f * (quat.x * quat.x + quat.y * quat.y);\r
+\r
+   }\r
+   \r
+   public static void getQuat(Matrix3d mat, Quat4d quat) {\r
+          double tr = mat.m00 + mat.m11 + mat.m22;\r
+               if (tr > 0.0) {\r
+                       double s = Math.sqrt(tr + 1.0);\r
+                       quat.w = 0.5 * s;\r
+                       s = 0.5 / s;\r
+                       quat.x = (mat.m21 - mat.m12) * s;\r
+                       quat.y = (mat.m02 - mat.m20) * s;\r
+                       quat.z = (mat.m10 - mat.m01) * s;\r
+               } else {\r
+                       int i = 0, j, k;\r
+                       if (mat.m11 > mat.m00)\r
+                               i = 1;\r
+                       if (mat.m22 > mat.getElement(i, i))\r
+                               i = 2;\r
+                       int nxt[] = { 1, 2, 0 };\r
+\r
+                       j = nxt[i];\r
+                       k = nxt[j];\r
+\r
+                       double s = Math\r
+                                       .sqrt((mat.getElement(i, i) - (mat.getElement(j, j) + mat\r
+                                                       .getElement(k, k))) + 1.0);\r
+\r
+                       double q[] = new double[3];\r
+                       q[i] = s * 0.5;\r
+\r
+                       if (Math.abs(s) > 0.001)\r
+                               s = 0.5 / s;\r
+\r
+                       quat.w = (mat.getElement(k, j) - mat.getElement(j, k)) * s;\r
+                       q[j] = (mat.getElement(j, i) + mat.getElement(i, j)) * s;\r
+                       q[k] = (mat.getElement(k, i) + mat.getElement(i, k)) * s;\r
+\r
+                       quat.x = q[0];\r
+                       quat.y = q[1];\r
+                       quat.z = q[2];\r
+               }\r
+       }\r
+   \r
+   \r
+       /*\r
+        * Cohen-Sutherland\r
+        */\r
+       \r
+       private static final int IN = 0;\r
+       private static final int LEFT = 1;\r
+       private static final int RIGHT = 2;\r
+       private static final int BOTTOM = 4;\r
+       private static final int TOP = 8;\r
+       \r
+       \r
+       private static int bitcode(Vector2f p1, Vector2f min, Vector2f max) {\r
+               int code = IN;\r
+               if (p1.x < min.x)\r
+                       code |= LEFT;\r
+               else if (p1.x > max.x)\r
+                       code |= RIGHT;\r
+               if (p1.y < min.y)\r
+                       code |= BOTTOM;\r
+               else if (p1.y > max.y)\r
+                       code |= TOP;\r
+               return code;\r
+       }\r
+       \r
+       public static boolean clipLineRectangle(Vector2f p1,Vector2f p2, Vector2f min, Vector2f max, Vector2f r1, Vector2f r2) {\r
+               while (true) {\r
+                       int o1 = bitcode(p1, min, max);\r
+                       int o2 = bitcode(p2, min, max);\r
+                       int and = o1 & o2;\r
+                       int or = o1 | o2;\r
+                       if (and != IN) {\r
+                               return false;\r
+                       }\r
+                       if (or == IN) {\r
+                               r1.set(p1);\r
+                               r2.set(p2);\r
+                               return true;\r
+                       }\r
+                       if (o1 == IN) {\r
+                               Vector2f t = p1;\r
+                               p1 = p2;\r
+                               p2 = t;\r
+                               int t2 = o1;\r
+                               o1 = o2;\r
+                               o2 = t2;\r
+                       }\r
+                       if ((o1 & TOP) != IN) {\r
+                               float t = (max.y - p1.y) / (p2.y - p1.y);\r
+                               p1.x += t * (p2.x - p1.x);\r
+                               p1.y = max.y;\r
+                       } else if ((o1 & BOTTOM) != IN) {\r
+                               float t = (min.y - p1.y) / (p2.y - p1.y);\r
+                               p1.x += t * (p2.x - p1.x);\r
+                               p1.y = min.y;\r
+                       } else if ((o1 & LEFT) != IN) {\r
+                               float t = (min.x - p1.x) / (p2.x - p1.x);\r
+                               p1.y += t * (p2.y - p1.y);\r
+                               p1.x = min.x;\r
+                       } else if ((o1 & RIGHT) != IN) {\r
+                               float t = (max.x - p1.x) / (p2.x - p1.x);\r
+                               p1.y += t * (p2.y - p1.y);\r
+                               p1.x = max.x;\r
+                       } else {\r
+                               throw new RuntimeException("Error in clipping code");\r
+                       }\r
+               }\r
+               \r
+       }\r
+       \r
+       public static double square(double d) {\r
+               return d * d;\r
+       }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java
new file mode 100644 (file)
index 0000000..bbba901
--- /dev/null
@@ -0,0 +1,220 @@
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.nio.ByteBuffer;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.swt.graphics.ImageData;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.stubs.ImageTexture;\r
+import org.simantics.proconf.g3d.stubs.TextureCoordinateGenerator;\r
+import org.simantics.proconf.image.interfaces.IImage;\r
+import org.simantics.proconf.image.interfaces.IImageFactory;\r
+import org.simantics.utils.ErrorLogger;\r
+import org.simantics.utils.ui.gfx.ImageUtils;\r
+import org.simantics.utils.ui.gfx.PixelDimension;\r
+\r
+import com.jme.image.Image;\r
+import com.jme.image.Texture;\r
+import com.jme.util.TextureManager;\r
+\r
+/**\r
+ * Caches resource based textures.\r
+ * TODO : use queries to update textures, now textures are read once and cannot be updated\r
+ * TODO : either use shared context or use separate cache for each editor\r
+ * TODO : ShapeNode implementation won't use release texture yet\r
+ * TODO : Texture is released when reference count goes to zero; we probably want to wait for a while before texture is released because it might be used again.\r
+ * \r
+ * @author Marko Luukkainen <Marko.Luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class ResourceTextureCache {\r
+       \r
+       public static PixelDimension DEFAULT_SIZE = new PixelDimension(128,128);\r
+       \r
+       private static ResourceTextureCache instance = new ResourceTextureCache();\r
+       \r
+       private Map<Resource,Image> images = new HashMap<Resource, Image>();\r
+       private Map<Resource,Integer> imageReferences = new HashMap<Resource, Integer>();\r
+       \r
+       private Map<Resource,Texture> textures = new HashMap<Resource, Texture>();\r
+       private Map<Resource,Integer> textureReferences = new HashMap<Resource, Integer>();\r
+       \r
+       \r
+       private ResourceTextureCache() {\r
+               \r
+       }\r
+       \r
+       public Texture loadTexture(Graph g, Resource res) {\r
+               Texture t = textures.get(res);\r
+               if (t == null) {\r
+                       ImageTexture it = new ImageTexture(g,res);\r
+                       org.simantics.image.stubs.Image pattern = it.getImage();\r
+                       Image image = loadImage(g, pattern.getResource());\r
+//                     image.getData().rewind();\r
+//                     while (image.getData().hasRemaining())\r
+//                             image.getData().put((byte)(Math.random()*256.0 - 127.0));\r
+                       if (image == null) {\r
+                               return null;\r
+                       }\r
+                       t = new Texture();\r
+                       t.setImage(image);\r
+                       \r
+                       //t = TextureManager.loadTexture(image, Texture.MM_LINEAR, Texture.FM_LINEAR);\r
+//                     t.setImageLocation(res.toString());\r
+//                     URL url = FileLocator.find(com.jme.eclipse.Activator.getDefault().getBundle(),new Path("data/texture/clouds.png"),null);\r
+//             t = TextureManager.loadTexture(url, Texture.MM_LINEAR, Texture.FM_LINEAR);\r
+               \r
+                       t.setFilter(com.jme.image.Texture.FM_LINEAR);\r
+               t.setMipmapState(com.jme.image.Texture.MM_LINEAR);\r
+               t.setApply(Texture.AM_COMBINE);\r
+               t.setCombineFuncRGB(Texture.ACF_MODULATE);\r
+               t.setCombineScaleRGB(2.f);\r
+\r
+               //t.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T);\r
+                       \r
+                       TextureCoordinateGenerator gen = it.getTextureCoordinateGenerator();\r
+                       setTextureCoordGenerator(gen, t);\r
+                       textures.put(res, t);\r
+               }\r
+               addTextureReference(res);\r
+               return t;\r
+       }\r
+       \r
+       public void releaseTexture(Graph g, Resource res) {\r
+               Integer i = textureReferences.get(res);\r
+               if (i != null) {\r
+                       i = i - 1;\r
+                       if (i == 0) {\r
+                               Texture t = textures.get(res);\r
+                               ImageTexture it = new ImageTexture(g,res);\r
+                               org.simantics.image.stubs.Image pattern = it.getImage();\r
+                               releaseImage(pattern.getResource());\r
+                               t.setImage(null);\r
+                               textureReferences.remove(res);\r
+                               //FIXME : release the texture\r
+                       } else {\r
+                               textureReferences.put(res, i);\r
+                       }\r
+                       \r
+               } else {\r
+                       throw new RuntimeException("Cannot released texture that does not exist " + res);\r
+               }\r
+       }\r
+       \r
+       public Image loadImage(Graph g, Resource res) {\r
+               Image image = images.get(res);\r
+               if (image == null) {\r
+                       org.simantics.image.stubs.Image pattern = new org.simantics.image.stubs.Image(g,res);\r
+                       IImageFactory f = org.simantics.proconf.image.ImageUtils.getImageFactoryForResource(g,pattern.getResource());\r
+               try {\r
+                       IImage p = f.createImageForResource(g,pattern.getResource());\r
+               PixelDimension pd = p.getDimensions().getPixelDimension();\r
+               if (pd==null) pd = DEFAULT_SIZE;\r
+                       ImageData data = p.rasterize(pd.getWidth(), pd.getHeight());\r
+                       image = getImage(data);\r
+                       images.put(res, image);\r
+                       \r
+               } catch (Exception e) {\r
+                       ErrorLogger.defaultLogError("Cannor create pattern texture for resource " + pattern, e);\r
+                       return null;\r
+               }\r
+               }\r
+               addImageReference(res);\r
+               return image;\r
+               \r
+       }\r
+       \r
+       private void addTextureReference(Resource res) {\r
+               Integer i = textureReferences.get(res);\r
+               if (i != null) {\r
+                       imageReferences.put(res, i + 1);\r
+               } else {\r
+                       imageReferences.put(res, 1);\r
+               }\r
+       }\r
+       \r
+       private void addImageReference(Resource res) {\r
+               Integer i = imageReferences.get(res);\r
+               if (i != null) {\r
+                       imageReferences.put(res, i + 1);\r
+               } else {\r
+                       imageReferences.put(res, 1);\r
+               }\r
+       }\r
+       \r
+       public void releaseImage(Resource res) {\r
+               Integer i = imageReferences.get(res);\r
+               if (i != null) {\r
+                       i = i - 1;\r
+                       if (i == 0) {\r
+                               Image image = images.get(res);\r
+                               image.getData().clear();\r
+                               image.setData(null);\r
+                               images.remove(res);\r
+                               imageReferences.remove(res);\r
+                       } else {\r
+                               imageReferences.put(res, i);\r
+                       }\r
+               } else {\r
+                       throw new RuntimeException("Cannot release image that does not exist.");\r
+               }\r
+       }\r
+       \r
+       public static ResourceTextureCache getInstance() {\r
+               return instance;\r
+       }\r
+       \r
+       private static Image getImage(ImageData imageData) {\r
+       int width = imageData.width;\r
+       int height = imageData.height;\r
+       int type = 0;\r
+       \r
+       int components = 3;\r
+       \r
+       type = Image.RGB888;\r
+       if (imageData.alphaData != null) {\r
+               type = Image.RGBA8888;\r
+               components = 4;\r
+       }\r
+       \r
+       ByteBuffer buf = ByteBuffer.allocateDirect(components * width * height);\r
+       ImageUtils.convertToRGBA(imageData, buf);       \r
+       return new Image(type,width,height,buf);\r
+    }\r
+       \r
+       \r
+       public static void setTextureCoordGenerator(TextureCoordinateGenerator gen, com.jme.image.Texture texture) {\r
+        if (gen == null)\r
+            return ;\r
+\r
+        //g3dResource.\r
+        if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_sphere))\r
+               texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_SPHERE);\r
+        else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_eyelinear))\r
+               texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_EYE_LINEAR);\r
+        else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_objectlinear))\r
+               texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_OBJECT_LINEAR);\r
+        else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_normal))\r
+               ErrorLogger.getDefault().logWarning("JME doesn't support normal texture coordinate generation", null);\r
+        else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_reflection))\r
+               ErrorLogger.getDefault().logWarning("JME doesn't support reflection texture coordinate generation", null);\r
+        else\r
+               ErrorLogger.getDefault().logWarning("Unsupported TexGen type " + gen.getName(), null);\r
+    }\r
+       \r
+       public void clear() {\r
+               for (Image i : images.values())\r
+                       i.setData(null);\r
+               for (Texture t : textures.values())\r
+                       t.setImage(null);\r
+               imageReferences.clear();\r
+               textureReferences.clear();\r
+               images.clear();\r
+               textures.clear();\r
+       \r
+       }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ScenegraphAdapter.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ScenegraphAdapter.java
new file mode 100644 (file)
index 0000000..e2d0287
--- /dev/null
@@ -0,0 +1,122 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.proconf.g3d.scenegraph.IGeometryNode;\r
+import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+\r
+import com.jme.scene.Node;\r
+\r
+public interface ScenegraphAdapter {\r
+\r
+       /**\r
+        * Disposes the adapter\r
+        */\r
+       public void dispose();\r
+\r
+       /**\r
+        * Returns scene-graph node of the resource\r
+        * @param resource\r
+        * @return\r
+        */\r
+       public IGraphicsNode getNode(Resource resource);\r
+\r
+       /**\r
+        * Returns scene-graph node of the resource\r
+        * @param thing\r
+        * @return\r
+        */\r
+       public IGraphicsNode getNode(IEntity thing);\r
+\r
+       /**\r
+        * Returns node (resource) for the uid.\r
+        * @param uid\r
+        * @return the node (resource)\r
+        */\r
+       public Resource getNodeResource(String uid);\r
+\r
+       /**\r
+        * @return all nodes in the scene-graph\r
+        */\r
+       public Collection<IGraphicsNode> getNodes();\r
+\r
+       /**\r
+        * Returns uid of the node.\r
+        * @param nodeResource\r
+        * @return\r
+        */\r
+       public String getNodeUID(Resource nodeResource);\r
+\r
+       public JmeRenderingComponent getRenderingComponent();\r
+\r
+       public Node getRoot();\r
+\r
+       public IGraphicsNode getRootNode();\r
+\r
+       public Resource getRootResource();\r
+\r
+       /**\r
+        * Returns true if the scene-graph contains the node\r
+        * @param resource\r
+        * @return\r
+        */\r
+       public boolean hasNode(Resource resource);\r
+\r
+       /**\r
+        * Checks if the view has been changed (and needs redrawing).\r
+        * @return\r
+        */\r
+       public boolean isChanged();\r
+\r
+       /**\r
+        * Checks if any geometries needs updating\r
+        * @return \r
+        */\r
+       public boolean needsUpdateGeometry();\r
+\r
+       /**\r
+        * \r
+        * @param changed\r
+        */\r
+       public void setChanged(boolean changed);\r
+\r
+       /**\r
+        * Sets the root node of the scene-graph\r
+        * @param rootNode\r
+        */\r
+       public void setRootNode(G3DNode rootNode);\r
+\r
+       /**\r
+        * Updates requested geometries.\r
+        * \r
+        * @param graph\r
+        */\r
+       public void updateGeometry(Graph graph);\r
+\r
+       /**\r
+        * Updates node's geometry\r
+        * @param node\r
+        */\r
+       public void updateGeometry(IGeometryNode node);\r
+       \r
+       /**\r
+        * Updates node's geometry\r
+        * @param nodeResource\r
+        */\r
+       public void updateGeometry(Resource nodeResource);\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ScenegraphAdapterImpl.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ScenegraphAdapterImpl.java
new file mode 100644 (file)
index 0000000..43a53a2
--- /dev/null
@@ -0,0 +1,828 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Queue;\r
+import java.util.Set;\r
+import java.util.Stack;\r
+import java.util.concurrent.ConcurrentLinkedQueue;\r
+\r
+import org.simantics.db.AbstractQuery;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.queries.IGraphQuery;\r
+import org.simantics.db.queries.IQuery;\r
+import org.simantics.db.queries.IQueryListener;\r
+import org.simantics.db.utils.transaction.MergingTransactionRunner;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.Property;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.scenegraph.IGeometryNode;\r
+import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
+import org.simantics.proconf.g3d.scenegraph.RootGraphicsNode;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+import org.simantics.utils.ErrorLogger;\r
+import org.simantics.utils.datastructures.BijectionMap;\r
+\r
+import com.jme.scene.Node;\r
+\r
+\r
+/**\r
+ * Scene-graph adapter :\r
+ * 1. Adapts graph change events into changes in actual scene-graph nodes.\r
+ * 2. Handles instantiating and disposing of Scene-graph nodes.\r
+ * 3.  \r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public abstract class ScenegraphAdapterImpl implements ScenegraphAdapter {\r
+       \r
+       protected static boolean DEBUG = false;\r
+       \r
+       private RootGraphicsNode root;\r
+       private HashMap<Resource,ScenegraphQuery> scenegraphQueries = new HashMap<Resource, ScenegraphQuery>();\r
+    private HashMap<Resource,NodePropertyQuery> propertyQueries = new HashMap<Resource, NodePropertyQuery>();\r
+    private HashMap<Resource,NodeTransformationQuery> transformationQueries = new HashMap<Resource, NodeTransformationQuery>();\r
+       private HashMap<Resource, IGraphicsNode> abstractGraphicsNodes = new HashMap<Resource, IGraphicsNode>();\r
+    protected Queue<IGeometryNode> geometryUpdates = new ConcurrentLinkedQueue<IGeometryNode>();\r
+       \r
+    private BijectionMap<Resource, String> nameMap = new BijectionMap<Resource, String>();\r
+    \r
+    protected JmeRenderingComponent component;\r
+    \r
+    protected boolean viewChanged = false;\r
+    \r
+    protected Session session;\r
+    \r
+    private MergingTransactionRunner transactionRunner;\r
+    \r
+    public ScenegraphAdapterImpl(Session session, JmeRenderingComponent component) {\r
+       this.component = component;\r
+       this.session = session;\r
+       transactionRunner = new MergingTransactionRunner(session,true);\r
+    }\r
+    \r
+    \r
+    @Override\r
+    public JmeRenderingComponent getRenderingComponent() {\r
+       return component;\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#setRootNode(fi.vtt.simantics.g3d.stubs.G3DNode)\r
+        */\r
+    public void setRootNode(G3DNode rootNode) {\r
+       addSubnodeListener(rootNode);\r
+        root = new RootGraphicsNode(component,rootNode.getResource());\r
+        abstractGraphicsNodes.put(rootNode.getResource(),root);\r
+        G3DTools.reloadCache(rootNode.getGraph(),root.getResource());\r
+        addRootPropertyListener(rootNode.getGraph());\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#needsUpdateGeometry()\r
+        */\r
+    public boolean needsUpdateGeometry() {\r
+       return geometryUpdates.size() > 0;\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#updateGeometry(fi.vtt.simantics.g3d.scenegraph.IGeometryNode)\r
+        */\r
+    public void updateGeometry(IGeometryNode node) {\r
+       geometryUpdates.add(node);\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#updateGeometry(fi.vtt.simantics.db.connection.Resource)\r
+        */\r
+    public void updateGeometry(Resource nodeResource) {\r
+       geometryUpdates.add((IGeometryNode)abstractGraphicsNodes.get(nodeResource));\r
+    }\r
+    \r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#updateGeometry(fi.vtt.simantics.db.connection.Graph)\r
+        */\r
+    public synchronized void updateGeometry(Graph graph) {\r
+       if (geometryUpdates.size() > 0) {\r
+                       for (IGeometryNode n : geometryUpdates) {\r
+                               try {\r
+                                       n.updateGeometry(graph);\r
+                                       if (DEBUG) System.out.println("ScenegraphAdapterImpl: geometryUpdated " + n.getResource());\r
+                               } catch (Exception e) {\r
+                                       ErrorLogger.defaultLogError("Failed to update geometry of node" + n.getResource(), e);\r
+                               }\r
+                       }\r
+                       geometryUpdates.clear();\r
+                       viewChanged = true;\r
+                       //if (DEBUG) System.out.println("ScenegraphAdapterImpl: geometryUpdated");\r
+               }\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNodes()\r
+        */\r
+    public Collection<IGraphicsNode> getNodes() {\r
+        return abstractGraphicsNodes.values();\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNode(fi.vtt.simantics.db.connection.Resource)\r
+        */\r
+    public IGraphicsNode getNode(Resource resource) {\r
+        return abstractGraphicsNodes.get(resource);\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getRootNode()\r
+        */\r
+    public IGraphicsNode getRootNode() {\r
+       return getNode(getRootResource());\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNode(fi.vtt.simantics.layer0.utils.IEntity)\r
+        */\r
+    public IGraphicsNode getNode(IEntity IEntity) {\r
+       return abstractGraphicsNodes.get(IEntity.getResource());\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNodeResource(java.lang.String)\r
+        */\r
+    public Resource getNodeResource(String uid) {\r
+       return nameMap.getLeft(uid);\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getNodeUID(fi.vtt.simantics.db.connection.Resource)\r
+        */\r
+    public String getNodeUID(Resource nodeResource) {\r
+       String name = nameMap.getRight(nodeResource);\r
+       if (name == null) {\r
+               //name = UUID.randomUUID().toString();\r
+               name = Long.toString(nodeResource.getResourceId());\r
+               nameMap.map(nodeResource, name);\r
+       }\r
+       return name;\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#hasNode(fi.vtt.simantics.db.connection.Resource)\r
+        */\r
+    public boolean hasNode(Resource resource) {\r
+        return abstractGraphicsNodes.containsKey(resource);\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getRootResource()\r
+        */\r
+    public Resource getRootResource() {\r
+       if (root == null)\r
+               return null;\r
+        return root.getResource();\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#getRoot()\r
+        */\r
+    public Node getRoot() {\r
+       return root.getGroup();\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#dispose()\r
+        */\r
+    public void dispose() {\r
+       Set<Resource> shapes = new HashSet<Resource>(abstractGraphicsNodes.keySet());\r
+        for (Resource r : shapes) {\r
+            removeNode(r);\r
+        }\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#isChanged()\r
+        */\r
+    public boolean isChanged() {\r
+       return viewChanged;\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+        * @see fi.vtt.simantics.g3d.scenegraph.IScenegraphAdapter#setChanged(boolean)\r
+        */\r
+    public void setChanged(boolean changed) {\r
+       viewChanged = changed;\r
+    }\r
+    \r
+    \r
+    /**\r
+     * Instantiates Listener that listens hierarchy changes in the node (subnode\r
+     * added and/or removed)\r
+     * \r
+     * @param node\r
+     * @return\r
+     */\r
+    protected abstract ScenegraphQuery newSubnodeListener(G3DNode node);\r
+    \r
+    protected void addSubnodeListener(G3DNode node) {\r
+       if (DEBUG) System.out.println("ScenegraphAdapter.addSubnodeListener( " + node.getResource() + " )");\r
+       ScenegraphQuery q = newSubnodeListener(node);\r
+       node.getGraph().performQuery(q);\r
+        scenegraphQueries.put(node.getResource(), q);\r
+    }\r
+    \r
+    /**\r
+     * Returns propertyQuery for a single scene-graph node.\r
+     * @param node\r
+     * @return\r
+     */\r
+    protected abstract NodePropertyQuery newPropertyListener(G3DNode node);\r
+    \r
+    /**\r
+     * Returns transformationQuery for a single scene-graph node\r
+     * @param root\r
+     * @return\r
+     */\r
+    protected abstract NodeTransformationQuery newTransformationListener(G3DNode root);\r
+    \r
+    /**\r
+     * Returns propertyQuery for the root node.\r
+     * May return null if root node has no interesting properties.\r
+     * \r
+     * Potentially root node could contain lighting settings, and so on...\r
+     * \r
+     * @param root\r
+     * @return\r
+     */\r
+    protected abstract NodePropertyQuery newRootPropertyListener(G3DNode root);\r
+    \r
+    protected void addPropertyListener(G3DNode node) {\r
+       if (DEBUG) System.out.println("ScenegraphAdapter.addPropertyListener( " + node.getResource() + " )");\r
+       NodePropertyQuery q = newPropertyListener(node);\r
+       node.getGraph().performQuery(q);\r
+       propertyQueries.put(node.getResource(),q);\r
+    }\r
+    \r
+    \r
+    protected void addTransformationListener(G3DNode node) {\r
+       if (DEBUG) System.out.println("ScenegraphAdapter.addPropertyListener( " + node.getResource() + " )");\r
+       NodeTransformationQuery q = newTransformationListener(node);\r
+       node.getGraph().performQuery(q);\r
+       transformationQueries.put(node.getResource(),q);\r
+    }\r
+    \r
+    protected void addRootPropertyListener(Graph g) {\r
+       G3DNode node = root.getG3DNode(g);\r
+       if (DEBUG) System.out.println("ScenegraphAdapter.addRootPropertyListener( " + node.getResource() + " )");       \r
+       NodePropertyQuery q = newRootPropertyListener(node);\r
+       if (q == null)\r
+               return;\r
+       node.getGraph().performQuery(q);\r
+       propertyQueries.put(node.getResource(),q);\r
+    }\r
+    \r
+    /**\r
+     * Instantiates a new scene-graph node\r
+     * \r
+     * @param parent the parent of the new node.\r
+     * @param node the new node.\r
+     * @return\r
+     */\r
+    protected abstract IGraphicsNode instantiateNode(IGraphicsNode parent, G3DNode node);\r
+    \r
+\r
+    /**\r
+     * Adds node into scene-graph\r
+     * @param parent the parent of the node\r
+     * @param r resource of the node\r
+     * @return created scene-graph node\r
+     */\r
+    protected IGraphicsNode addNode(IEntity parent, IEntity r) {\r
+        if (!r.isInstanceOf(Resources.g3dResource.G3DNode)) {\r
+            ErrorLogger.defaultLogError("Trying to add node into scenegraph that is not instance of graphicsnode " + r,new Exception("ASSERT!"));\r
+            return null;\r
+        }\r
+        if (parent.equals(r)) {\r
+               if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") adding node to itself?!");\r
+            ErrorLogger.defaultLogError("Adding scnegraphnode " + r.getResource().getResourceId() + " to itself!", new Exception("ASSERT!"));\r
+            return abstractGraphicsNodes.get(r);\r
+        }\r
+        \r
+        if (abstractGraphicsNodes.containsKey(r)) {\r
+               \r
+            IGraphicsNode inView = abstractGraphicsNodes.get(r);\r
+            if (inView.getParent() == null) {\r
+                //if graphicsNode has no parent it must be the root node\r
+                ErrorLogger.defaultLogError("Trying to add rootnode into scenegraph " + r, null);\r
+                return null;\r
+            }\r
+            if (parent.equals(inView.getParent().getResource())) {\r
+               if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") already in view");\r
+                return inView;\r
+            } else {\r
+               if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") already in view, but has different parent, current parent is ("+inView.getParent().getResource()+") and node is added to  ("+parent+") -> removing from old parent and inserting to new");\r
+                removeNode(inView.getParent().getResource(),r.getResource());\r
+            }\r
+        }\r
+        \r
+        G3DNode node = new G3DNode(r);\r
+\r
+        IGraphicsNode mo;\r
+        IGraphicsNode parentNode = abstractGraphicsNodes.get(parent);\r
+        if (parentNode == null) {\r
+               if (DEBUG) System.out.println("No graphicsnode for (" + parent.getResource().getResourceId() + ")");\r
+            return null;\r
+        } else {\r
+            mo = instantiateNode(parentNode, node);\r
+            if (mo == null) {\r
+                ErrorLogger.defaultLogError("Could not instantiate scenegraph node for " + r.getResource().getResourceId(), null);\r
+                return null;\r
+            }\r
+            if (DEBUG) System.out.println("ThreeDimensionalEditorBase.addNodeP(" + r.getResource().getResourceId() + ") added to parent (" + parent.getResource().getResourceId() + ") " + mo.getClass());\r
+        }\r
+        addSubnodeListener(node);\r
+        addPropertyListener(node);\r
+        addTransformationListener(node);\r
+\r
+        abstractGraphicsNodes.put(r.getResource(), mo);\r
+\r
+        \r
+        \r
+        // FIXME : this is a hack to fix transformations of instantiated nodes\r
+//             if (graph.getCurrentTransaction() != null) {\r
+//                     try {\r
+//                             G3DTools.propagateWorldTransformChange(parentNode\r
+//                                             .getG3DNode());\r
+//                             graph.commitChanges(CommitMessage.CHANGE_MESSAGE);\r
+//                             // G3DNodeTools.transformationUpdate(graph, r.getId());\r
+//                     } catch (Exception e) {\r
+//                             ErrorLogger.defaultLogError(e);\r
+//                     }\r
+//             }\r
+\r
+        \r
+        return mo;\r
+    }\r
+\r
+    /**\r
+        * This is used only when view is disposed!\r
+        * \r
+        * @param r\r
+        */\r
+    private void removeNode(Resource r) {\r
+       NodeTransformationQuery tq = transformationQueries.get(r);\r
+        //StructuralChangeMonitor monitor = monitors.getLeft(r);\r
+        if (tq == null) {\r
+               if (abstractGraphicsNodes.containsKey(r)) {\r
+                // root node has no monitor (no transformation to monitor)\r
+                //System.out.println("ThreeDimensionalEditorBase.removeNode(" + r + ") node has no monitor, but has node in scenegraph");  \r
+                abstractGraphicsNodes.remove(r);\r
+                if(scenegraphQueries.get(r) != null) {\r
+                       scenegraphQueries.get(r).dispose();\r
+                       scenegraphQueries.remove(r);\r
+                }\r
+            } else {\r
+                //System.out.println("ThreeDimensionalEditorBase.removeNode(" + r + ") not in view");\r
+            }\r
+               return;\r
+        }\r
+        // remove listeners\r
+        propertyQueries.remove(r).dispose();     \r
+        transformationQueries.remove(r).dispose();\r
+        scenegraphQueries.get(r);\r
+        scenegraphQueries.remove(r).dispose();\r
+        // remove children\r
+        IGraphicsNode node = abstractGraphicsNodes.get(r);\r
+        ArrayList<IGraphicsNode> children = new ArrayList<IGraphicsNode>(node.getChildren());\r
+        for (IGraphicsNode n : children) {\r
+            removeNode(n.getResource());\r
+        }\r
+        // remove the node\r
+        if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNode(" + r + ") removed");\r
+        \r
+        node.dispose();\r
+        abstractGraphicsNodes.remove(r);\r
+\r
+    }\r
+    \r
+    /**\r
+     * Removes a scene-graph node.\r
+     * @param parent the parent of the node\r
+     * @param r the node.\r
+     */\r
+    protected void removeNode(Resource parent,Resource r) {\r
+       NodePropertyQuery q = propertyQueries.get(r);\r
+        if (q == null) {\r
+            assert(!abstractGraphicsNodes.containsKey(r));\r
+            if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNodeP(" + r + ") not in view");\r
+            return;\r
+        }\r
+        \r
+        IGraphicsNode node = abstractGraphicsNodes.get(r);\r
+        Resource rParent = node.getParent().getResource();\r
+        if (!rParent.equals(parent)) {\r
+            // this event may happen, depending of the order of events in transaction\r
+               if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNodeP(" + r + ") trying to remove from wrong parent current ("+rParent+") remove parentnode null("+parent+")");    \r
+            return;\r
+        }\r
+        // removing listeners\r
+        propertyQueries.remove(r).dispose();\r
+        transformationQueries.remove(r).dispose();\r
+        scenegraphQueries.remove(r).dispose();\r
+        // remove node's children\r
+        ArrayList<IGraphicsNode> children = new ArrayList<IGraphicsNode>(node.getChildren());\r
+        for (IGraphicsNode n : children) {\r
+            removeNode(r,n.getResource());\r
+        }       \r
+        if (DEBUG) System.out.println("ThreeDimensionalEditorBase.removeNodeP(" + r + ") from ("+parent+")");    \r
+        // remove the node\r
+        \r
+        abstractGraphicsNodes.remove(r);\r
+        if (geometryUpdates.contains(node)) {\r
+               geometryUpdates.remove(node);\r
+        }\r
+        node.dispose();\r
+    }\r
+\r
+    \r
+    /**\r
+     * Query that tracks changes in resources.\r
+     * \r
+     * @author Marko Luukkainen\r
+     *\r
+     */\r
+    public abstract class NodeQuery extends AbstractQuery<Object>{\r
+        protected Resource nodeResource;\r
+        private boolean disposed = false;\r
+        private IQueryListener listener;\r
+        //private OverridingTransactionRunner runner;\r
+        \r
+       \r
+       public NodeQuery(Resource r) {\r
+               this.nodeResource = r;\r
+               //runner = new OverridingTransactionRunner(session,true);\r
+               \r
+       }\r
+       \r
+       protected abstract Object compute2(Graph graph);\r
+       \r
+       @Override\r
+        public Object performQuery(Graph graph) {\r
+               if (disposed) return null;\r
+               return compute2(graph);\r
+        }\r
+       \r
+       /**\r
+        *  \r
+        * @param oldResult result of the query before the change.\r
+        * @param newResult result of the query after the change.\r
+        */\r
+       public abstract boolean updated(Graph graph, Object oldResult, Object newResult);\r
+       \r
+       @Override\r
+       public int getType() {\r
+               return IQuery.SCHEDULED_UPDATE;\r
+       }\r
+       \r
+       @Override\r
+       public void resultChangedRaw(final Object oldResult, final Object newResult) {\r
+               if (disposed)\r
+                       throw new RuntimeException("Updating disposed query"); //return;\r
+               transactionRunner.run(new GraphRequestAdapter() {\r
+               //session.asyncWrite(new GraphRequestAdapter() {\r
+                       @Override\r
+                       public GraphRequestStatus perform(Graph g) throws Exception {\r
+                               if (!disposed) {\r
+                                       if (oldResult == IQueryListener.NO_VALUE)\r
+                                               updated(g, null, newResult);\r
+                                       else\r
+                                               updated(g, oldResult, newResult);\r
+                               } \r
+                               return GraphRequestStatus.transactionComplete();\r
+                       }\r
+               });\r
+\r
+       }\r
+       \r
+       \r
+       @Override\r
+       public boolean equalsQuery(IGraphQuery<Object> other) {\r
+               return nodeResource.equals(((NodeQuery)other).nodeResource);\r
+       }\r
+       \r
+        @Override\r
+        final public int hash() {\r
+            return nodeResource.hashCode();\r
+        }\r
+       \r
+       \r
+       /**\r
+        * Disposes the query\r
+        */\r
+       public void dispose() {\r
+               disposed = true;\r
+               if (DEBUG) System.out.println("NodeQuery " +  nodeResource +  " disposed()" + " " + this.getClass());\r
+       }\r
+       \r
+       //public abstract NodeQuery instantiateQuery(Resource node);\r
+       //public abstract void attach();\r
+       \r
+        @Override\r
+        public boolean isDisposed() {\r
+            return disposed;\r
+        }\r
+        \r
+        @Override\r
+        public IQueryListener getListener() {\r
+               if (listener == null) {\r
+                       listener = new IQueryListener() {\r
+                               @Override\r
+                               public boolean isDisposed() {\r
+                                       return NodeQuery.this.disposed;\r
+                               }\r
+                               \r
+                               @Override\r
+                               public void resultChangedRaw(Object oldResult, Object newResult) {\r
+                                       NodeQuery.this.resultChangedRaw(oldResult, newResult);\r
+                               }\r
+                       };\r
+               }\r
+               return listener;\r
+        }\r
+       \r
+    }\r
+    \r
+    /**\r
+     * \r
+     * Query that tracks changes in scene-graph structure (parent/child relationships).\r
+     * \r
+     * @author Marko Luukkainen\r
+     *\r
+     */\r
+    public abstract class ScenegraphQuery extends NodeQuery {\r
+       \r
+       List<Resource> added = new ArrayList<Resource>();\r
+       List<Resource> removed = new ArrayList<Resource>();\r
+       \r
+       private boolean initialized;\r
+       \r
+       public ScenegraphQuery(Resource nodeResource) {\r
+                       super(nodeResource);\r
+                       initialized = false;\r
+                       if(DEBUG)System.out.println("ScenegraphQuery created for " + nodeResource);\r
+               }\r
+       \r
+       @Override\r
+       public List<Resource> compute2(Graph g) {\r
+               IEntity node = EntityFactory.create(g,nodeResource);\r
+               Collection<IEntity> children = node.getRelatedObjects(Resources.g3dResource.HasChild);\r
+               List<Resource> list = new ArrayList<Resource>();\r
+               for (IEntity n: children)\r
+                       list.add(n.getResource());\r
+               if (DEBUG) System.out.println("ScenegraphQuery " + nodeResource +   " has " + list.size() + " children");\r
+               return list;\r
+       }\r
+       \r
+       @SuppressWarnings("unchecked")\r
+               @Override\r
+       public boolean updated(Graph graph, Object oldResult, Object newResult) {\r
+               List<Resource> oldChildren;\r
+               if (oldResult != null)\r
+                       oldChildren = (List<Resource>)oldResult;\r
+               else\r
+                       oldChildren = new ArrayList<Resource>();\r
+               List<Resource> newChildren      = (List<Resource>)newResult;\r
+               \r
+               if (DEBUG) System.out.println("ScenegraphQuery " + nodeResource +  " updated: had " + oldChildren.size() + " children, but now has " + newChildren.size() + " children");\r
+               added.clear();\r
+               removed.clear();\r
+               if (initialized) {\r
+                               for (Resource r : oldChildren)\r
+                                       if (!newChildren.contains(r))\r
+                                               removed.add(r);\r
+                               for (Resource r : newChildren)\r
+                                       if (!oldChildren.contains(r))\r
+                                               added.add(r);\r
+                               for (Resource r : removed) {\r
+                                       if (DEBUG)\r
+                                               System.out.println("ScenegraphQuery " + nodeResource\r
+                                                               + " removed " + r);\r
+                                       removeNode(nodeResource, r);\r
+                               }\r
+                               if (added.size() > 0) {\r
+                                       G3DNode parent = new G3DNode(graph, nodeResource);\r
+                                       /*\r
+                                        * try {\r
+                                        * \r
+                                        * G3DTools.propagateTransformChange(parent); } catch\r
+                                        * (Exception e) { ErrorLogger.defaultLogError(e); }\r
+                                        */\r
+                                       for (Resource r : added) {\r
+                                               IEntity e = EntityFactory.create(graph, r);\r
+                                               G3DTools.propagateLocalTransformChange(parent, e);\r
+                                               IGraphicsNode n = addNode(parent, e);\r
+                                               shapeAdded(graph, n);\r
+                                       }\r
+                               }\r
+                               return (added.size() > 0 || removed.size() > 0);\r
+               } else {\r
+                       // when query is run for the first time, we can assume that transformations are correct.\r
+                       initialized = true;\r
+                       for (Resource r : newChildren)\r
+                               added.add(r);\r
+                       if (added.size() > 0) {\r
+                                       G3DNode parent = new G3DNode(graph, nodeResource);\r
+                                       for (Resource r : added) {\r
+                                               IEntity e = EntityFactory.create(graph, r);\r
+                                               IGraphicsNode n = addNode(parent, e);\r
+                                               shapeAdded(graph, n);\r
+                                       }\r
+                                       return true;\r
+                               }\r
+                       return false;\r
+               }\r
+               \r
+       }\r
+       \r
+       \r
+       /**\r
+        * This method is run after a node is added to scene-graph.\r
+        * \r
+        * @param graph Graph of the current transaction.\r
+        * @param node the newly added scene-graph node\r
+        */\r
+       public abstract void shapeAdded(Graph graph,IGraphicsNode node);\r
+       \r
+//     @Override\r
+//     public void attach() {\r
+//             scenegraphQueries.put(nodeResource, this);\r
+//     }\r
+       \r
+       \r
+    }\r
+    \r
+    /**\r
+     * Tracks changes in scene-graph nodes' properties\r
+     * \r
+     * @author Marko Luukkainen\r
+     *\r
+     */\r
+    public abstract class NodePropertyQuery extends NodeQuery {\r
\r
+        private boolean initialized;\r
+        \r
+       public NodePropertyQuery(Resource nodeResource) {\r
+               super(nodeResource);\r
+               initialized = false;\r
+               if(DEBUG)System.out.println("NodePropertyQuery created for " + nodeResource);\r
+       }\r
+       \r
+       @Override\r
+       public List<Object> compute2(Graph g) {\r
+               IEntity t = EntityFactory.create(g,nodeResource);\r
+               \r
+               Collection<Property> properties = t.getRelatedProperties(Resources.g3dResource.HasNonTransformation);\r
+               List<Object> propertyValues = new ArrayList<Object>();\r
+               p(properties,propertyValues);\r
+\r
+               return propertyValues;\r
+       }\r
+       \r
+       private void p(Collection<Property> properties, List<Object> propertyValues) {\r
+               for (Property p : properties) {\r
+                       Collection<Property> subProperties = p.getRelatedProperties(p.getGraph().getBuiltins().HasProperty);\r
+                       if (subProperties.size() != 0) {\r
+                               p(subProperties,propertyValues);\r
+                       } \r
+                       if (p.hasValue()){\r
+                               propertyValues.add(p.getValue());\r
+                       }\r
+               }\r
+       }\r
+       \r
+       @Override\r
+       public boolean updated(Graph graph, Object oldResult, Object newResult) {\r
+               if (initialized) {\r
+                       if (DEBUG) System.out.println("NodePropertyQuery changed " + nodeResource + " " + abstractGraphicsNodes.size());\r
+               IGraphicsNode mo = abstractGraphicsNodes.get(nodeResource);\r
+               if (mo == null) {\r
+                       if (DEBUG) System.out.println("NodePropertyQuery invalid change " + nodeResource + " " + abstractGraphicsNodes.size());\r
+                       ErrorLogger.defaultLogError("Got update from resource " + nodeResource + " but its not part of the scenegraph", null);\r
+                       dispose();\r
+                       return false;\r
+               }\r
+               shapeUpdated(graph,mo);\r
+               return true;\r
+               } else {\r
+                       initialized = true;\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       \r
+       /**\r
+        * This method is run when a scene-graph node is changed.\r
+        * \r
+        * @param shape the changed node\r
+        */\r
+       public abstract void shapeUpdated(Graph graph,IGraphicsNode shape);\r
+       \r
+//     @Override\r
+//     public void attach() {\r
+//             propertyQueries.put(nodeResource, this);\r
+//     }\r
+       \r
+    }\r
+    \r
+    public abstract class NodeTransformationQuery extends NodeQuery {\r
+       \r
+       private boolean initialized;\r
+       \r
+       public NodeTransformationQuery(Resource nodeResource) {\r
+               super(nodeResource);\r
+               initialized = false;\r
+               if(DEBUG)System.out.println("NodeTransformationQuery created for " + nodeResource);\r
+       }\r
+       \r
+       @Override\r
+       public List<Object> compute2(Graph g) {\r
+               IEntity t = EntityFactory.create(g,nodeResource);\r
+               \r
+               Collection<Property> properties = t.getRelatedProperties(Resources.g3dResource.HasTransformation);\r
+               \r
+               List<Object> propertyValues = new ArrayList<Object>();\r
+               p(properties,propertyValues);\r
+               return propertyValues;\r
+\r
+       }\r
+       \r
+       private void p(Collection<Property> properties, List<Object> propertyValues) {\r
+               for (Property p : properties) {\r
+                       Collection<Property> subProperties = p.getRelatedProperties(p.getGraph().getBuiltins().HasProperty);\r
+                       if (subProperties.size() != 0) {\r
+                               p(subProperties,propertyValues);\r
+                       } \r
+                       if (p.hasValue()){\r
+                               propertyValues.add(p.getValue());\r
+                       }\r
+               }\r
+       }\r
+       \r
+       @Override\r
+       public boolean updated(Graph graph,Object oldResult, Object newResult) {\r
+               if (initialized) {\r
+                       if (DEBUG) System.out.println("NodeTransformationQuery changed " + nodeResource + " " + abstractGraphicsNodes.size());\r
+\r
+                       G3DTools.transformationUpdate(graph, nodeResource);\r
+\r
+                       IGraphicsNode mo = abstractGraphicsNodes.get(nodeResource);\r
+               if (mo == null) {\r
+                       if (DEBUG) System.out.println("NodeTransformationQuery invalid change " + nodeResource + " " + abstractGraphicsNodes.size());\r
+                       ErrorLogger.defaultLogError("Got update from resource " + nodeResource + " but its not part of the scenegraph", null);\r
+                       dispose();\r
+                       return false;\r
+               }\r
+               shapeUpdated(graph,mo);\r
+               return true;\r
+               } else {\r
+                       initialized = true;\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       \r
+       /**\r
+        * This method is run when a scene-graph node is changed.\r
+        * \r
+        * @param shape the changed node\r
+        */\r
+       public abstract void shapeUpdated(Graph graph,IGraphicsNode shape);\r
+       \r
+//     @Override\r
+//     public void attach() {\r
+//             transformationQueries.put(nodeResource, this);\r
+//     }\r
+       \r
+    }\r
+    \r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/SelectionAdapter.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/SelectionAdapter.java
new file mode 100644 (file)
index 0000000..22b6bc6
--- /dev/null
@@ -0,0 +1,445 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.ISelectionProvider;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
+import org.simantics.proconf.g3d.gizmo.Gizmo;\r
+import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
+import org.simantics.proconf.ui.utils.ResourceAdaptionUtils;\r
+\r
+import com.jme.intersection.PickData;\r
+import com.jme.intersection.PickResults;\r
+import com.jme.intersection.TrianglePickResults;\r
+import com.jme.math.Ray;\r
+\r
+import org.simantics.db.Resource;\r
+\r
+/**\r
+ * Manages highlighting and selecting of objects.\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public abstract class SelectionAdapter implements ISelectionProvider{\r
+       \r
+       protected ScenegraphAdapter adapter;\r
+       \r
+       private Gizmo currentGizmo = null;\r
+       \r
+       public SelectionAdapter(ScenegraphAdapter adapter) {\r
+               this.adapter = adapter;\r
+       }\r
+       \r
+    public enum SelectionType {\r
+        SET, MODIFY\r
+    };\r
+\r
+    protected SelectionType mouseClickType = SelectionType.SET;\r
+    \r
+    public SelectionType getSelectionType() {\r
+       return mouseClickType;\r
+    }\r
+    \r
+    public void setSelectionType(SelectionType type) {\r
+       mouseClickType = type;\r
+    }\r
+    \r
+    public void setCurrentGizmo(Gizmo gizmo) {\r
+       currentGizmo = gizmo;\r
+    }\r
+    \r
+    /**\r
+     * Lists all selected objects\r
+     * <p>\r
+     * Selection may contain objects that are not in this view: those are NOT\r
+     * returned\r
+     * </p>\r
+     * \r
+     * @return\r
+     */\r
+    public List<IGraphicsNode> getSelectedObjects() {\r
+        return getSelectedObjects(selection);\r
+    }\r
+    \r
+    /**\r
+     * Lists all highlighted objects.\r
+     * <p>\r
+     * Typically there may be only one highlighted object.\r
+     * </p>\r
+     * @return\r
+     */\r
+    public List<IGraphicsNode> getHighlightedObjects() {\r
+        return getSelectedObjects(interactiveSelection);\r
+    }\r
+\r
+    /**\r
+     * Lists all selected objects\r
+     * <p>\r
+     * Selection may contain objects that are not in this view: those are NOT\r
+     * returned\r
+     * </p>\r
+     * \r
+     * @return\r
+     */\r
+    public List<IGraphicsNode> getInteractiveSelectedObjects() {\r
+        return getSelectedObjects(interactiveSelection);\r
+    }\r
+\r
+    /**\r
+     * Lists all selected objects\r
+     * <p>\r
+     * Selection may contain objects that are not in this view: those are NOT\r
+     * returned\r
+     * </p>\r
+     * \r
+     * @return\r
+     */\r
+    protected List<IGraphicsNode> getSelectedObjects(StructuredResourceSelection selection) {\r
+        List<IGraphicsNode> l = new ArrayList<IGraphicsNode>();\r
+        Iterator<Resource> i = selection.iterator();\r
+        while (i.hasNext()) {\r
+            Resource s = i.next();\r
+            IGraphicsNode shape = adapter.getNode(s);\r
+            if (shape != null)\r
+                l.add(shape);\r
+\r
+        }\r
+        return l;\r
+    }\r
+\r
+    /**\r
+     * Return selected objects\r
+     * <p>\r
+     * May contain objects that are NOT in this view\r
+     * </p>\r
+     * \r
+     * @return\r
+     */\r
+    public List<Resource> getSelectedResources() {\r
+        List<Resource> l = new ArrayList<Resource>();\r
+        Iterator<Resource> i = selection.iterator();\r
+        while (i.hasNext()) {\r
+            Resource s = (Resource) i.next();\r
+            l.add(s);\r
+\r
+        }\r
+        return l;\r
+    }\r
+    \r
+    private ArrayList<PickData> processed = new ArrayList<PickData>();\r
+    \r
+    private class ExtTrianglePickResults extends TrianglePickResults {\r
+       public ExtTrianglePickResults() {\r
+               this.setCheckDistance(true);\r
+        }\r
+       \r
+       public void processPick() {\r
+                       processed.clear();\r
+                       if (getNumber() > 0) {\r
+                               for (int j = 0; j < getNumber(); j++) {\r
+                                       PickData pData = getPickData(j);\r
+                                       ArrayList<Integer> tris = pData.getTargetTris();\r
+                                       if (tris != null && tris.size() > 0) {\r
+                                               processed.add(pData);\r
+                                       }\r
+                               }\r
+                               \r
+                       }\r
+                       \r
+               }\r
+    }\r
+    \r
+    private PickResults result = new ExtTrianglePickResults();\r
+\r
+       \r
+       private void pickPrefix(String prefix) {\r
+\r
+               ArrayList<PickData> r= new ArrayList<PickData>();\r
+               for (int i = 0; i < processed.size(); i++) {\r
+                       PickData pData = processed.get(i);\r
+                       if (pData.getTargetMesh().getParentGeom().getName().startsWith(prefix))\r
+                               r.add(pData);\r
+               }\r
+               processed = r;\r
+       }\r
+       \r
+       /**\r
+        * Updates highlighted objects according to mouse position.\r
+        * \r
+        * @param mouseRay\r
+        */\r
+       public void updateHighlights(Ray mouseRay) {\r
+               result.clear();\r
+               adapter.getRenderingComponent().getRoot().calculatePick(mouseRay, result);\r
+               if (currentGizmo != null) {\r
+                       pickPrefix(currentGizmo.getPickPrefix());\r
+               }\r
+               doHighlightPick(processed);\r
+       }\r
+       \r
+       /**\r
+        * Picks highlighted objects\r
+        */\r
+       public void pickHighlighted() {\r
+               doPick(processed);\r
+       }\r
+       \r
+    /**\r
+     * Processes pick.\r
+     * @param result\r
+     */\r
+    protected void doPick(ArrayList<PickData> result) {\r
+        if (result != null) {\r
+\r
+               if (result.size() == 0) {\r
+                       if (mouseClickType != SelectionType.MODIFY)\r
+                    updateSelection(new StructuredResourceSelection());\r
+                       return;\r
+               }\r
+               \r
+               String nodeName = result.get(0).getTargetMesh().getParentGeom().getName();\r
+\r
+            StructuredResourceSelection s = new StructuredResourceSelection();\r
+            \r
+            Resource selectedResource = adapter.getNodeResource(nodeName);\r
+            if (adapter.getNode(selectedResource) == null) {\r
+                updateSelection(new StructuredResourceSelection());\r
+                return;\r
+                //throw new RuntimeException("Picked resource that has no node ?!");\r
+            }\r
+            if (mouseClickType == SelectionType.MODIFY) {\r
+                ArrayList<Resource> selected = new ArrayList<Resource>(getSelectedResources());\r
+                if (selected.contains(selectedResource))\r
+                    selected.remove(selectedResource);\r
+                else\r
+                    selected.add(selectedResource);\r
+                for (Resource r : selected)\r
+                    s.add(r);\r
+\r
+            } else {\r
+                s.add(selectedResource);\r
+            }\r
+\r
+            updateSelection(s);\r
+        } else {\r
+            // System.out.println("Picked nothing");\r
+            if (mouseClickType != SelectionType.MODIFY)\r
+                updateSelection(new StructuredResourceSelection());\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Processes highlight pick\r
+     * @param result\r
+     */\r
+    protected void doHighlightPick(ArrayList<PickData> result) {\r
+        if (result != null) {\r
+\r
+               if (result.size() == 0) {\r
+                       updateGizmo(null);\r
+                //System.out.println("IPicked nothing");\r
+                updateHighlightSelection(new StructuredResourceSelection());\r
+                       return;\r
+               }\r
+               \r
+               String nodeName = result.get(0).getTargetMesh().getParentGeom().getName();\r
+        \r
+            updateGizmo(null);\r
+            \r
+            // System.out.println("hits: " + result);\r
+            StructuredResourceSelection s = new StructuredResourceSelection();\r
+                      \r
+            Resource selectedResource = adapter.getNodeResource(nodeName);\r
+            \r
+            if (selectedResource == null) {\r
+               if (currentGizmo != null && nodeName.startsWith(currentGizmo.getPickPrefix())) {\r
+                    updateGizmo(nodeName);\r
+                } \r
+               return;\r
+            }\r
+            \r
+            if (adapter.getNode(selectedResource) != null)\r
+                s.add(selectedResource);\r
+\r
+            updateHighlightSelection(s);\r
+        } else {\r
+            updateGizmo(null);\r
+            // System.out.println("IPicked nothing");\r
+            updateHighlightSelection(new StructuredResourceSelection());\r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Updates gizmo according to picked object\r
+     * @param pickName\r
+     */\r
+    private void updateGizmo(String pickName) {\r
+        if (currentGizmo != null) {\r
+            currentGizmo.setSelected(pickName);\r
+            if (currentGizmo.isChanged()) {\r
+               adapter.setChanged(true);\r
+                currentGizmo.setChanged(false);\r
+            }\r
+        }\r
+    }\r
+    \r
+    \r
+    /**\r
+     * Contains selection\r
+     */\r
+    protected StructuredResourceSelection selection = new StructuredResourceSelection();\r
+\r
+    protected StructuredResourceSelection interactiveSelection = new StructuredResourceSelection();\r
+    \r
+    public StructuredResourceSelection getCurrentSelection() {\r
+        return selection;\r
+    }\r
+\r
+    public void setCurrentSelection(StructuredResourceSelection s) {\r
+        selection = s;\r
+    }\r
+\r
+    public StructuredResourceSelection getHighlightSelection() {\r
+        return interactiveSelection;\r
+    }\r
+\r
+    protected void setHighlightSelection(StructuredResourceSelection s) {\r
+        interactiveSelection = s;\r
+    }\r
+    \r
+    private ArrayList<ISelectionChangedListener> selectionChangedListeners = new ArrayList<ISelectionChangedListener>();\r
+\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)\r
+     */\r
+    public void addSelectionChangedListener(ISelectionChangedListener listener) {\r
+        selectionChangedListeners.add(listener);\r
+\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()\r
+     */\r
+    public ISelection getSelection() {\r
+        return selection;\r
+    }\r
+\r
+    \r
+    \r
+    public static StructuredResourceSelection transformSelection(ISelection sel) {\r
+       if (sel instanceof StructuredResourceSelection)\r
+               return (StructuredResourceSelection)sel;\r
+       StructuredResourceSelection res = new StructuredResourceSelection();\r
+       Resource resources[] = ResourceAdaptionUtils.toResources(sel);\r
+       for (Resource r : resources)\r
+               res.add(r);\r
+       return res;\r
+    }\r
+    \r
+\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)\r
+     */\r
+    public void removeSelectionChangedListener(ISelectionChangedListener listener) {\r
+        selectionChangedListeners.remove(listener);\r
+\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)\r
+     */\r
+    public void setSelection(ISelection selection) {\r
+        // System.out.println();\r
+        StructuredResourceSelection s = filterSelection(selection);\r
+        if (this.selection.equals(s))\r
+            return;\r
+        this.selection = s;\r
+        adapter.setChanged(true);\r
+        setEditorSelection();\r
+\r
+    }\r
+\r
+    /**\r
+     * Filters selection given with setSelection(ISelection selection) This\r
+     * allows impemented editors to modify selection before it's applied into\r
+     * this editor\r
+     * \r
+     * @param s\r
+     * @return the filtered selection\r
+     */\r
+    protected abstract StructuredResourceSelection filterSelection(ISelection s);\r
+\r
+    /**\r
+     * Updates visual part of selection event. Use getCurrentSelection() to get\r
+     * the selection\r
+     */\r
+    public abstract void setEditorSelection();\r
+\r
+    /**\r
+     * Updates visual part of selection event. Use getInteractiveSelection() to\r
+     * get the selection\r
+     */\r
+    protected abstract void setEditorHighlightSelection();\r
+\r
+    /**\r
+     * Editor's internal selection update<br>\r
+     * Sends events to other editors and views about changed selection\r
+     * \r
+     * @param selection\r
+     * @return\r
+     */\r
+    public boolean updateSelection(StructuredResourceSelection s) {\r
+        if (this.selection.equals(s))\r
+            return false;\r
+\r
+        this.selection = s;\r
+        adapter.setChanged(true);\r
+        fireSelectionChangedEvent();\r
+        setEditorSelection();\r
+        return true;\r
+    }\r
+\r
+    protected boolean updateHighlightSelection(StructuredResourceSelection s) {\r
+        if (interactiveSelection.equals(s))\r
+            return false;\r
+        this.interactiveSelection = s;\r
+        adapter.setChanged(true);\r
+        setEditorHighlightSelection();\r
+        return true;\r
+    }\r
+\r
+    /**\r
+     * Fires selection changed events.\r
+     */\r
+    protected void fireSelectionChangedEvent() {\r
+        SelectionChangedEvent e = new SelectionChangedEvent(this, this.selection);\r
+        for (ISelectionChangedListener l : selectionChangedListeners)\r
+            l.selectionChanged(e);\r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorBase.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorBase.java
new file mode 100644 (file)
index 0000000..0a04a22
--- /dev/null
@@ -0,0 +1,741 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.awt.event.MouseEvent;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Stack;\r
+\r
+import javax.vecmath.Tuple3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.IContributionItem;\r
+import org.eclipse.jface.action.IMenuListener;\r
+import org.eclipse.jface.action.IMenuManager;\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.eclipse.jface.action.MenuManager;\r
+import org.eclipse.jface.action.Separator;\r
+import org.eclipse.jface.dialogs.MessageDialog;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.swt.events.PaintEvent;\r
+import org.eclipse.swt.events.PaintListener;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Menu;\r
+import org.eclipse.ui.IActionBars;\r
+import org.eclipse.ui.IEditorActionBarContributor;\r
+import org.eclipse.ui.ISharedImages;\r
+import org.eclipse.ui.IWorkbenchActionConstants;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.eclipse.ui.commands.ICommandService;\r
+import org.eclipse.ui.internal.WorkbenchWindow;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.events.GraphChangeEvent;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.actions.CameraAction;\r
+import org.simantics.proconf.g3d.actions.ContextAction;\r
+import org.simantics.proconf.g3d.actions.InteractiveAction;\r
+import org.simantics.proconf.g3d.base.SelectionAdapter.SelectionType;\r
+import org.simantics.proconf.g3d.common.JmeComposite;\r
+import org.simantics.proconf.g3d.common.JmeSinglePassRenderingComponent;\r
+import org.simantics.proconf.g3d.common.OrbitalCamera;\r
+import org.simantics.proconf.g3d.dialogs.JMEDialog;\r
+import org.simantics.proconf.g3d.dnd.ShapeDropTarget;\r
+import org.simantics.proconf.g3d.gizmo.Gizmo;\r
+import org.simantics.proconf.g3d.input.InputProvider;\r
+import org.simantics.proconf.g3d.input.SWTInputProvider;\r
+import org.simantics.proconf.g3d.scenegraph.IGeometryNode;\r
+import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
+import org.simantics.proconf.g3d.tools.ScenegraphLockTraverser;\r
+import org.simantics.utils.ErrorLogger;\r
+import org.simantics.utils.ui.jface.MenuTools;\r
+\r
+import com.jme.math.Ray;\r
+import com.jme.math.Vector2f;\r
+import com.jme.math.Vector3f;\r
+import com.jme.renderer.ColorRGBA;\r
+\r
+\r
+public abstract class ThreeDimensionalEditorBase implements  Runnable {\r
+\r
+       private Resource inputResource;\r
+       \r
+       private List<EditorContribution> editorContributions = new ArrayList<EditorContribution>();\r
+       \r
+       private EditorContribution currentEditorContribution;\r
+       \r
+    protected List<ContextAction> actions = new ArrayList<ContextAction>();\r
+    \r
+    private List<Action> contributionSelectionActions = new ArrayList<Action>();\r
+      \r
+    protected Composite parent;\r
+    \r
+    protected ISessionContext sessionContext;\r
+    \r
+    protected Session session;\r
+    \r
+    protected ScenegraphAdapter adapter;\r
+    \r
+    protected SelectionAdapter selectionAdapter;\r
+    \r
+    protected Action refreshAction;\r
+    \r
+    protected Action configureJMEAction;\r
+    \r
+    private Action lockScenegraphAction;\r
+\r
+    protected Menu contextMenu;\r
+\r
+    private JmeComposite renderingComposite = null;  \r
+\r
+    protected OrbitalCamera camera = new OrbitalCamera();\r
+\r
+    protected boolean viewChanged = true;\r
+\r
+    private InteractiveAction currentAction = null;\r
+    \r
+    private Gizmo currentGizmo = null;\r
+    \r
+    private InteractiveAction cameraAction = null;\r
+    \r
+    private JmeRenderingComponent component = null;\r
+    \r
+    protected InputProvider input = null;\r
+    \r
+    protected ShapeDropTarget dropTarget;\r
+\r
+//    protected IEditorActionBarContributor actionBarContributor;\r
+    protected IActionBars actionBars;\r
+    protected IToolBarManager toolBarManager;\r
+    protected IMenuManager menuManager;\r
+    \r
+    public ThreeDimensionalEditorBase(ISessionContext session) {\r
+       this.sessionContext = session;\r
+       this.session = session.getSession();\r
+       component = new JmeSinglePassRenderingComponent();\r
+    }\r
+\r
+    public ThreeDimensionalEditorBase(ISessionContext session, JmeRenderingComponent component) {\r
+       this.sessionContext = session;\r
+       this.session = session.getSession();\r
+       this.component = component;\r
+    }\r
+    \r
+//    public void setActionBarContributor(IEditorActionBarContributor contributor) {\r
+//     actionBarContributor = contributor;\r
+//    }\r
+    \r
+    public void setActionBars(IActionBars actionBars) {\r
+       this.actionBars = actionBars;\r
+       this.menuManager = actionBars.getMenuManager();\r
+       this.toolBarManager = actionBars.getToolBarManager();\r
+    }\r
+    \r
+   \r
+    \r
+    \r
+    public ISessionContext getSessionContext() {\r
+       return sessionContext;\r
+    }\r
+    \r
+    public Session getSession() {\r
+       return session;\r
+    }\r
+    \r
+    /**\r
+     * Creates basic UI for ThreeDimenionalEditors.\r
+     * Note : inputResource has not been set at this point.\r
+     * \r
+     * @param graph\r
+     * @param parent\r
+     */\r
+    public void createControl(Graph graph, Composite parent) {\r
+       this.parent = parent;\r
+       renderingComposite = new JmeComposite(parent,component);\r
+       // add listeners to force repaint on size changes\r
+        renderingComposite.getCanvas().addPaintListener(new PaintListener() {\r
+               public void paintControl(PaintEvent e) {\r
+                       viewChanged = true;     \r
+               }\r
+        });\r
+\r
+        \r
+        input = new SWTInputProvider();\r
+        \r
+        renderingComposite.initGL();\r
+        camera.setCamera(component.getCamera());\r
+        camera.updateCamera();  \r
+        makeActions(graph);\r
+        hookContextMenu();\r
+\r
+        // provide selection events for properies view\r
+        this.adapter = createScenegraphAdapter();\r
+        this.selectionAdapter = createSelectionAdapter();\r
+        \r
+        this.selectionAdapter.addSelectionChangedListener(new ISelectionChangedListener() {\r
+               public void selectionChanged(SelectionChangedEvent event) {\r
+                       setCurrentAction(getDefaultAction());   \r
+               }\r
+        });\r
+        hookDragAndDrop();      \r
+        hookInput();\r
+        VisualizationScheduler.getInstance().addVisualization(this);\r
+        \r
+        if (editorContributions.size() > 0) {\r
+            // setActiveEditorContribution(editorContributions.get(0));\r
+           // } else if (editorContributions.size() > 1) {\r
+               // create actions for selecting contribution\r
+               for (EditorContribution ec : editorContributions) {\r
+                       final EditorContribution e = ec;\r
+                       Action a = new Action(e.getName(),Action.AS_RADIO_BUTTON) {\r
+                               @Override\r
+                               public void run() {\r
+                                       \r
+                                       setActiveEditorContribution(e);\r
+                               }\r
+                       };\r
+                       contributionSelectionActions.add(a);\r
+                       \r
+               }\r
+         }\r
+       \r
+    }\r
+    \r
+    public void addEditorContribution(EditorContribution e) {\r
+       if (parent != null)\r
+               throw new RuntimeException("Editor contributions must be added before editor is created.");\r
+       editorContributions.add(e);\r
+    }\r
+    \r
+    private void initializeEditorContributions(Graph graph) {\r
+        for (EditorContribution e : editorContributions) {\r
+               e.initialize(graph);\r
+         }\r
+        if (editorContributions.size() > 0)\r
+                parent.getDisplay().asyncExec(new Runnable() {\r
+                        @Override\r
+                       public void run() {\r
+                                setActiveEditorContribution(editorContributions.get(0));\r
+                       }\r
+                });     \r
+    }\r
+    \r
+    \r
+    private void hookInput() {\r
+        renderingComposite.getCanvas().addKeyListener((SWTInputProvider) input);\r
+        renderingComposite.getCanvas().addMouseListener((SWTInputProvider) input);\r
+        renderingComposite.getCanvas().addMouseMoveListener((SWTInputProvider) input);\r
+        renderingComposite.getCanvas().addMouseTrackListener((SWTInputProvider) input);\r
+        renderingComposite.getCanvas().addFocusListener((SWTInputProvider) input);\r
+    }\r
+    \r
+    protected abstract ScenegraphAdapter createScenegraphAdapter();\r
+    protected abstract SelectionAdapter createSelectionAdapter();\r
+\r
+    \r
+    public JmeComposite getRenderingComposite() {\r
+        return renderingComposite;\r
+   }\r
+    \r
+    public JmeRenderingComponent getRenderingComponent() {\r
+      return component;\r
+    }\r
+\r
+    public ScenegraphAdapter getScenegraphAdapter() {\r
+       return adapter;\r
+    }\r
+    \r
+    public SelectionAdapter getSelectionAdapter() {\r
+       return selectionAdapter;\r
+    }\r
+\r
+    public OrbitalCamera getCamera() {\r
+        return camera;\r
+    }\r
+    \r
+    public void setViewChanged(boolean b) {\r
+        viewChanged = b;\r
+    }\r
+\r
+    protected void hookContextMenu() {\r
+        MenuManager menuMgr = new MenuManager("#PopupMenu");\r
+        menuMgr.setRemoveAllWhenShown(true);\r
+        menuMgr.addMenuListener(new IMenuListener() {\r
+            public void menuAboutToShow(IMenuManager manager) {\r
+               final IMenuManager m = manager;\r
+               GraphRequestAdapter r = new GraphRequestAdapter() {\r
+                       @Override\r
+                       public GraphRequestStatus perform(Graph g) throws Exception {\r
+                               ThreeDimensionalEditorBase.this.fillContextMenu(g,m);\r
+                               return GraphRequestStatus.transactionComplete();\r
+                       }\r
+               };\r
+               \r
+               session.syncRead(r);\r
+                \r
+            }\r
+        });\r
+\r
+        contextMenu = menuMgr.createContextMenu(renderingComposite);\r
+    }\r
+\r
+    \r
+\r
+    protected void fillContextMenu(Graph graph,IMenuManager manager) {\r
+        manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));\r
+        \r
+        List<Resource> selected = selectionAdapter.getSelectedResources();\r
+        for (ContextAction action : actions) {\r
+            if(action.usable(graph,selected)) {\r
+                manager.add(action);\r
+            }\r
+        }\r
+        if (currentEditorContribution != null) {\r
+               currentEditorContribution.fillContextMenu(graph, manager, selectionAdapter.getCurrentSelection());\r
+               for (ContextAction action : currentEditorContribution.getActions()) {\r
+                       if(action.usable(graph,selected)) {\r
+                               manager.add(action);\r
+                }\r
+            }\r
+        }\r
+\r
+    }\r
+\r
+    protected void fillLocalToolBar() {\r
+\r
+       if (currentEditorContribution != null)\r
+               currentEditorContribution.fillLocalToolBar(toolBarManager);\r
+    }\r
+    \r
+    protected void fillLocalPullDown() {\r
+       for (Action a : contributionSelectionActions) {\r
+               IMenuManager menu = MenuTools.getOrCreate(getMenuID(),"View", menuManager);\r
+               menu.add(a);\r
+       }\r
+       MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(refreshAction);\r
+       if (configureJMEAction != null) {\r
+               MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(configureJMEAction);\r
+       }\r
+\r
+       MenuTools.getOrCreate(getMenuID(),"Advanced", menuManager).add(lockScenegraphAction);\r
+       if (currentEditorContribution != null)\r
+               currentEditorContribution.fillLocalPullDown(menuManager);\r
+    }\r
+    \r
+    public String getMenuID() {\r
+       return Long.toString(getInputResource().getResourceId());\r
+    }\r
+\r
+    protected void makeActions(Graph graph) {\r
+        \r
+        refreshAction = new Action() {\r
+\r
+            public void run() {\r
+               GraphRequestAdapter r = new GraphRequestAdapter() {\r
+                       public GraphRequestStatus perform(Graph g) throws Exception {\r
+//                              Stack<IGraphicsNode> stack = new Stack<IGraphicsNode>();\r
+//                         stack.push(adapter.getNode(adapter.getRootResource()));\r
+//                         while(!stack.isEmpty()) {\r
+//                             IGraphicsNode node = stack.pop();\r
+//                             stack.addAll(node.getChildren());\r
+//                             if (node instanceof IGeometryNode) {\r
+//                                 ((IGeometryNode)node).updateGeometry(g);\r
+//                             }\r
+//                         }\r
+                                for (IGraphicsNode node : adapter.getNodes())\r
+                                        if (node instanceof IGeometryNode)\r
+                                                ((IGeometryNode)node).updateGeometry(g);\r
+                         viewChanged = true;\r
+                         return GraphRequestStatus.transactionComplete();\r
+                       };\r
+               };\r
+               session.asyncRead(r);\r
+               \r
+            }\r
+        };\r
+        refreshAction.setText("Refresh");\r
+        refreshAction.setToolTipText("Refreshes the visualization");\r
+        refreshAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(\r
+                ISharedImages.IMG_TOOL_UP));\r
+        if (getRenderingComponent() instanceof JmeSinglePassRenderingComponent) {\r
+               configureJMEAction = new Action() {\r
+                       public void run() {\r
+                               JmeSinglePassRenderingComponent c = (JmeSinglePassRenderingComponent)getRenderingComponent();\r
+                               JMEDialog dialog = new JMEDialog(ThreeDimensionalEditorBase.this.parent.getShell());\r
+                               c.getDisplaySystem().setCurrent();\r
+                               dialog.setBounds(c.isShowBounds());\r
+                               dialog.setNormals(c.isShowNormals());\r
+                               dialog.setWireframe(c.isShowWireframe());\r
+                               ColorRGBA col = c.getDisplaySystem().getRenderer().getBackgroundColor();\r
+                               dialog.setFloatColor(new float[]{col.r,col.g,col.b});\r
+                               if (dialog.open() == JMEDialog.CANCEL)\r
+                                       return;\r
+                               c.setShowBounds(dialog.isBounds());\r
+                               c.setShowNormals(dialog.isNormals());\r
+                               c.setShowWireframe(dialog.isWireframe());\r
+                               if (dialog.getFloatColor() != null) {\r
+                                       c.getDisplaySystem().setCurrent();\r
+                                       c.getDisplaySystem().getRenderer().setBackgroundColor(new ColorRGBA(dialog.getFloatColor()[0],dialog.getFloatColor()[1],dialog.getFloatColor()[2],0.f));\r
+                               }\r
+                       }\r
+               };\r
+               configureJMEAction.setText("Configure JME");\r
+               configureJMEAction.setImageDescriptor(Activator.imageDescriptorFromPlugin("fi.vtt.proconf.ode", "icons/silk/wrench.png"));\r
+        }\r
+        \r
+        lockScenegraphAction = new Action("Lock scenegraph",Action.AS_CHECK_BOX) {\r
+               public void run() {\r
+                       new ScenegraphLockTraverser(adapter.getRoot(),this.isChecked());\r
+               }\r
+        };\r
+        \r
+        cameraAction = new CameraAction(this); \r
+        currentAction = cameraAction;\r
+        \r
+        \r
+    }\r
+    \r
+    public InteractiveAction getDefaultAction() {\r
+        return cameraAction;\r
+    }\r
+    \r
+    public void createPickRay(Vector3d o, Vector3d d) {\r
+       Ray r = createPickRay();\r
+       o.x = r.origin.x;\r
+       o.y = r.origin.y;\r
+       o.z = r.origin.z;\r
+       d.x = r.direction.x;\r
+       d.y = r.direction.y;\r
+       d.z = r.direction.z;\r
+       d.normalize();\r
+    }\r
+    \r
+    public Ray createPickRay() {\r
+       Vector2f screenPos = new Vector2f();\r
+               screenPos.set(input.mouseX(),renderingComposite.getBounds().height - input.mouseY());\r
+               \r
+               \r
+               Ray mouseRay;\r
+               if (component.getCamera().isParallelProjection()) {\r
+                       Vector3f worldCoords = renderingComposite.getDisplaySystem().getWorldCoordinates(screenPos, 0.0f);\r
+                       mouseRay = new Ray(worldCoords,\r
+                               component.getCamera().getDirection());\r
+               } else {\r
+                       Vector3f worldCoords = renderingComposite.getDisplaySystem().getWorldCoordinates(screenPos, 1.0f);\r
+                       mouseRay = new Ray(component.getCamera().getLocation(), worldCoords\r
+                                       .subtractLocal(component.getCamera().getLocation()));\r
+               }\r
+               return mouseRay;\r
+    }\r
+    \r
+    public Vector2f getScreenCoord(Tuple3d worldCoord) {\r
+       Vector3f v = renderingComposite.getDisplaySystem().getScreenCoordinates(VecmathJmeTools.get(worldCoord));\r
+       return new Vector2f(v.x,v.y);\r
+    }\r
+    \r
+    \r
+    public InputProvider getInputProvider() {\r
+        return input;\r
+    }\r
+\r
+    /**\r
+     * Changes current action \r
+     * \r
+     * @param type\r
+     */\r
+    public void setCurrentAction(InteractiveAction action) {\r
+       if (currentAction == action)\r
+               return;\r
+       if (toolBarManager != null) {\r
+               toolBarManager.removeAll();\r
+               fillLocalToolBar();\r
+       }\r
+        if (currentAction != null)\r
+            currentAction.deactivate();\r
+        currentAction = action;\r
+        if (currentAction != null) {\r
+            currentAction.activate();\r
+            if (toolBarManager != null) {\r
+               currentAction.fillToolBar(toolBarManager);\r
+            }\r
+        }\r
+        \r
+        updateBars();\r
+    }\r
+    \r
+    public InteractiveAction getCurrentAction() {\r
+       return currentAction;\r
+    }\r
+    \r
+    public void setActiveEditorContribution(EditorContribution contribution) {\r
+       if (currentEditorContribution == contribution)\r
+               return;\r
+       if (currentAction != getDefaultAction())\r
+               return;\r
+       if (currentEditorContribution != null)\r
+               currentEditorContribution.disposeControl();\r
+       currentEditorContribution = contribution;\r
+       int index = editorContributions.indexOf(contribution);\r
+       for (int i = 0; i < contributionSelectionActions.size(); i++) {\r
+               if (i != index)\r
+                       contributionSelectionActions.get(i).setChecked(false);\r
+               else\r
+                       contributionSelectionActions.get(i).setChecked(true);\r
+       }\r
+       if (currentEditorContribution != null)\r
+               currentEditorContribution.createControl(parent);\r
+       \r
+       actionBars.clearGlobalActionHandlers();\r
+       \r
+       parent.layout(true, true);\r
+       if (toolBarManager != null) {\r
+               toolBarManager.removeAll();\r
+               fillLocalToolBar();\r
+       }\r
+       if (menuManager != null) {              \r
+               menuManager.removeAll();\r
+               fillLocalPullDown();\r
+       }\r
+       \r
+       updateBars();\r
+    }\r
+    \r
+    protected void updateBars() {\r
+       // TODO : actionBars.updateActionBars does not update toolbar, updating toolBar directly layouts code \r
+       //        generated widgets top of contributed (extension) widgets. Only way to achieve proper update\r
+       //        is to use WorkbenchWindow.getCoolBarManager.update(true)\r
+        actionBars.updateActionBars();\r
+//     if (toolBarManager != null) {\r
+//             toolBarManager.update(true);\r
+//     }\r
+       WorkbenchWindow w = (WorkbenchWindow)PlatformUI.getWorkbench().getActiveWorkbenchWindow();\r
+        w.getCoolBarManager().update(true);\r
+    }\r
+    \r
+    public void setGizmo(Gizmo gizmo) {\r
+        if (currentGizmo != null) {\r
+               currentGizmo.getNode().removeFromParent();\r
+        }\r
+        currentGizmo = gizmo;\r
+        selectionAdapter.setCurrentGizmo(gizmo);\r
+        viewChanged = true;\r
+    }\r
+    \r
+//    public void setInfoText(String text) {\r
+//        if (useInfoComposite) {\r
+//            infoText.setText(text);\r
+//        }\r
+//    }\r
+\r
+    public void showMessage(String message) {\r
+        MessageDialog.openInformation(parent.getShell(), "Shape Editor", //$NON-NLS-1$\r
+                message);\r
+    }\r
+\r
+\r
+    /**\r
+     * Passing the focus request to the viewer's control.\r
+     */\r
+    public void setFocus() {\r
+       renderingComposite.getCanvas().setFocus();\r
+    }\r
+\r
+    public void dispose() {\r
+       //System.out.println("ThreeDimensionalEditorBase.dispose()");\r
+        VisualizationScheduler.getInstance().removeVisualization(this);\r
+\r
+        if (currentAction != null)\r
+            currentAction.deactivate();\r
+\r
+        for (EditorContribution e : editorContributions)\r
+               e.dispose();\r
+        \r
+        renderingComposite.dispose();\r
+\r
+        // copy of the set is needed to avoid ConcurrentModificationException\r
+        adapter.dispose();\r
+        component.dispose();\r
+    }\r
+\r
+    public final void reload(Graph g, Resource res) {\r
+       inputResource = res;\r
+        reloadFrom(EntityFactory.create(g, res));\r
+        // at this point we can initialize editor contributions, which may require inputResource\r
+        initializeEditorContributions(g);\r
+    }\r
+\r
+    public Resource getInputResource() {\r
+       return inputResource;\r
+    }\r
+    \r
+    public void update(GraphChangeEvent event) {\r
+//        System.out.println("Transaction " + this + " : " + event.getTransactionId() + " Arg1: " + event.getArg1()\r
+//                + " arg2: " + event.getArg2() + " sender: " + event.getSender() + " source: " + event.getSource());\r
+        \r
+//        if (event.added.size() > 0) {\r
+//            System.out.println("Added:");\r
+//            for (Triplet t : event.added)\r
+//                System.out.println(t);\r
+//        }\r
+//        if (event.changed.size() > 0) {\r
+//            System.out.println("Changed:");\r
+//            for (Triplet t : event.changed)\r
+//                System.out.println(t);\r
+//        }\r
+//        if (event.removed.size() > 0) {\r
+//            System.out.println("Removed:");\r
+//            for (Triplet t : event.removed)\r
+//                System.out.println(t);\r
+//        }\r
+\r
+    }\r
+\r
+    \r
+\r
+    /**\r
+     * Loads the initial scene: all further updates to the view are done by\r
+     * listening changes in the shapes and int the shape group\r
+     * \r
+     * @param resource\r
+     */\r
+    protected abstract void reloadFrom(IEntity thing);\r
+\r
+\r
+       protected void viewUpdated() {\r
+\r
+       }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see java.lang.Runnable#run()\r
+     */\r
+    public void run() {\r
+       if (currentEditorContribution != null)\r
+               currentEditorContribution.run();\r
+       if (parent.isDisposed() || !parent.isVisible())\r
+                       return;\r
+       //renderingComposite.getDisplaySystem().setCurrent();\r
+               input.update();\r
+               if (input.mouseClicked()) {\r
+                       int downMask = MouseEvent.CTRL_DOWN_MASK;\r
+\r
+                       if ((input.clickModifiers() & downMask) > 0) {\r
+                               selectionAdapter.setSelectionType(SelectionType.MODIFY);\r
+                       } else {\r
+                               selectionAdapter.setSelectionType(SelectionType.SET);\r
+                       }\r
+               }\r
+               if (input.mouseMoved()) {\r
+                       Ray mouseRay = createPickRay();\r
+                       selectionAdapter.updateHighlights(mouseRay);\r
+               }\r
+               if (currentAction == cameraAction && input.mouseClicked()) {\r
+                       selectionAdapter.pickHighlighted();\r
+               }\r
+               if (currentAction == cameraAction && input.mousePressed()\r
+                               && (input.pressModifiers() & MouseEvent.BUTTON3_MASK) > 0) {\r
+                       Point p = renderingComposite.toDisplay(input.mouseX(), input\r
+                                       .mouseY());\r
+                       contextMenu.setLocation(p.x, p.y);\r
+                       contextMenu.setVisible(true);\r
+               }\r
+\r
+               if (currentAction != null)\r
+                       try {\r
+                               currentAction.update();\r
+                       } catch (Exception e) {\r
+                               ErrorLogger.defaultLogError("Action error!", e);\r
+                               setCurrentAction(getDefaultAction());\r
+                       }\r
+\r
+               if (component.update())\r
+                       viewChanged = true;\r
+                   \r
+               if (!geometryUpdateRequestAdapter.isRunning() && adapter.needsUpdateGeometry()) {\r
+                       session.asyncRead(geometryUpdateRequestAdapter);        \r
+               }\r
+               \r
+               viewChanged |= adapter.isChanged();\r
+                if (viewChanged) {\r
+                       viewChanged = false;\r
+                       adapter.setChanged(false);\r
+                       camera.updateCamera();\r
+                       viewUpdated();\r
+                       component.render();\r
+               }\r
+       }\r
+    // TODO : there is some sort of synchronization bug in rendering:\r
+    //        part of the rendered objects are rendered with different camera transformation than others.\r
+    //        re-rendering the scene hides the worst problems.\r
+    //        Using shadows is the reason: shadowed objects are rendered with different transformation than non-shadowed.\r
+    //private boolean lastChanged = false;\r
+    \r
+    private GeometryUpdateRequestAdapter geometryUpdateRequestAdapter = new GeometryUpdateRequestAdapter();\r
+       \r
+    private class GeometryUpdateRequestAdapter extends GraphRequestAdapter {\r
+       private boolean running;\r
+       @Override\r
+               public GraphRequestStatus perform(Graph g) throws Exception {\r
+               running = true;\r
+                       adapter.updateGeometry(g);\r
+                       return GraphRequestStatus.transactionComplete();\r
+               }\r
+               @Override\r
+               public void requestCompleted(GraphRequestStatus status) {\r
+                       running = false;\r
+                       adapter.setChanged(true);\r
+               }\r
+               \r
+               public boolean isRunning() {\r
+                       return running;\r
+               }\r
+    }\r
+\r
+   \r
+    \r
+    protected void hookDragAndDrop() {\r
+       dropTarget = new ShapeDropTarget(this);\r
+    }\r
+\r
+    /**\r
+     * Receives selection changes\r
+     * \r
+     * @param part\r
+     * @param selection\r
+     */\r
+    protected abstract void pageSelectionChanged(IWorkbenchPart part, ISelection selection);\r
+\r
+    /**\r
+     * EditorPart or ViewPart uses this method to forward getAdapter(Class)\r
+     * @see org.eclipse.ui.part.WorkbenchPart.getAdapter(Class adapter)\r
+     * @param adapter\r
+     * @return\r
+     */\r
+    public Object getAdapter(Class adapter) {\r
+       return null;\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorPart.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorPart.java
new file mode 100644 (file)
index 0000000..4ad22bd
--- /dev/null
@@ -0,0 +1,205 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import org.eclipse.jface.action.IStatusLineManager;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.ui.IActionBars;\r
+import org.eclipse.ui.IPartListener;\r
+import org.eclipse.ui.ISelectionListener;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.events.GraphChangeEvent;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.proconf.ui.workbench.ResourceEditorPart;\r
+import org.simantics.utils.ErrorLogger;\r
+\r
+\r
+public abstract class ThreeDimensionalEditorPart extends ResourceEditorPart implements ThreeDimensionalEditorProvider{\r
+       \r
+       protected Composite parent;\r
+       \r
+       protected ThreeDimensionalEditorBase editor;\r
+\r
+    protected ISelectionListener pageSelectionListener;\r
+\r
+       protected abstract ThreeDimensionalEditorBase createEditor(ISessionContext session);\r
+       \r
+       /**\r
+     * This is a callback that will allow us to create the viewer and it.\r
+     */\r
+    @Override\r
+    public void createPartControl(Composite p) {\r
+       this.parent = p;\r
+        try {\r
+               editor = createEditor(getSessionContext());\r
+               \r
+            // add partlistener that loads the scene-graph when the view has been created\r
+            this.getEditorSite().getPage().addPartListener(new IPartListener() {\r
+               \r
+               boolean opened = false;\r
+               boolean activated = false;\r
+               \r
+                public void partOpened(IWorkbenchPart part) {\r
+                    if (part.equals(ThreeDimensionalEditorPart.this.getEditorSite().getPart())) {\r
+                        opened = true;\r
+                    }\r
+                }\r
+                \r
+                public void partActivated(IWorkbenchPart part) {\r
+                       if (part.equals(ThreeDimensionalEditorPart.this.getEditorSite().getPart())) {\r
+                        if (opened & !activated) {\r
+                               activated = true;\r
+                               load();\r
+                        }\r
+                       }\r
+                }\r
+                \r
+                public void partBroughtToTop(IWorkbenchPart part) {}\r
+                \r
+                public void partClosed(IWorkbenchPart part) {}\r
+                \r
+                public void partDeactivated(IWorkbenchPart part) {}\r
+                \r
+                private void load() {\r
+                       //System.out.println("ThreeDimensionalEditorPart.reload()");\r
+                    Session ses = ThreeDimensionalEditorPart.this.getSession();\r
+                    GraphRequestAdapter r = new GraphRequestAdapter() {\r
+                       @Override\r
+                       public GraphRequestStatus perform(Graph g)\r
+                                       throws Exception {\r
+                                reload(g);\r
+                               return GraphRequestStatus.transactionComplete();\r
+                       }\r
+                    };\r
+                    ses.asyncRead(r);\r
+                }\r
+            });\r
+\r
+            IActionBars actionBar = getEditorSite().getActionBars();\r
+//            editor.setActionBarContributor(getEditorSite().getActionBarContributor());\r
+            editor.setActionBars(actionBar);\r
+            getSession().syncRead(new GraphRequestAdapter() {\r
+               @Override\r
+               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                       editor.createControl(g,parent);\r
+                       return GraphRequestStatus.transactionComplete();\r
+               }\r
+            });\r
+            \r
+            contributeStatusBar(actionBar.getStatusLineManager());\r
+            hookPageSelection(); \r
+            getSite().setSelectionProvider(editor.selectionAdapter);\r
+            \r
+\r
+\r
+        } catch (Exception e) {\r
+            Display d = getSite().getShell().getDisplay();\r
+            d.asyncExec(new Runnable() {\r
+                public void run() {\r
+                    getSite().getPage().closeEditor(ThreeDimensionalEditorPart.this,false);\r
+                }\r
+            });\r
+\r
+            ErrorLogger logger = ErrorLogger.getDefault();\r
+            logger.logError("Shape editor failed to open, see exception for details", e);\r
+        }\r
+\r
+    }\r
+    \r
+\r
+    protected void contributeStatusBar(IStatusLineManager manager) {\r
+    }\r
+    \r
+    \r
+       @Override\r
+       public void reload(Graph g) {\r
+               Resource inputResource = getInputResource();\r
+               if (inputResource != null) {\r
+                       editor.reload(g,inputResource);\r
+               } else {\r
+                       \r
+                        Display d = getSite().getShell().getDisplay();\r
+                   d.asyncExec(new Runnable() {\r
+                       public void run() {\r
+                               editor.showMessage("Failed to load model.");\r
+                           getSite().getPage().closeEditor(ThreeDimensionalEditorPart.this,false);\r
+                       }\r
+                   });\r
+               }\r
+       }\r
+       \r
+       @Override\r
+       public void update(GraphChangeEvent e) {\r
+               editor.update(e);\r
+       }\r
+       \r
+       @Override\r
+       public void setFocus() {\r
+               editor.setFocus();\r
+       }\r
+       \r
+        /**\r
+     * Hooks selection listening\r
+     */\r
+    private void hookPageSelection() {\r
+        pageSelectionListener = new ISelectionListener() {\r
+            public void selectionChanged(IWorkbenchPart part, ISelection selection) {\r
+                if (part == ThreeDimensionalEditorPart.this)\r
+                    return;\r
+                pageSelectionChanged(part, selection);\r
+            }\r
+        };\r
+        getSite().getPage().addPostSelectionListener(pageSelectionListener);\r
+        ISelection sel = getSite().getPage().getSelection();\r
+        IWorkbenchPart wb = getSite().getPage().getActivePart();\r
+        pageSelectionChanged(wb, sel);\r
+    }\r
+    \r
+    /**\r
+     * Receives selection changes\r
+     * \r
+     * @param part\r
+     * @param selection\r
+     */\r
+    protected void pageSelectionChanged(IWorkbenchPart part, ISelection selection) {\r
+       editor.pageSelectionChanged(part, selection);\r
+    }\r
+    \r
+    public void dispose() {\r
+       if (pageSelectionListener != null)\r
+            getSite().getPage().removePostSelectionListener(pageSelectionListener);\r
+        editor.dispose();\r
+       super.dispose();\r
+    }\r
+    \r
+    public ThreeDimensionalEditorBase getEditor() {\r
+       return editor;\r
+    }\r
+    \r
+    @Override\r
+    public Object getAdapter(Class adapter) {\r
+       Object o = super.getAdapter(adapter);\r
+       if (o == null) {\r
+               o = editor.getAdapter(adapter);\r
+       }\r
+       return o;\r
+    }\r
+\r
+\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorProvider.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ThreeDimensionalEditorProvider.java
new file mode 100644 (file)
index 0000000..df2d14d
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+/**\r
+ * Interface which selectionProviders containing ThreeDimensionalEditorPart\r
+ * must implement. \r
+ * \r
+ * This enables usage of ThreeDimensionalEditorPart in views, editors, dialogs, and so on.\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public interface ThreeDimensionalEditorProvider {\r
+\r
+       public ThreeDimensionalEditorBase getEditor();\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/TransformationTools.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/TransformationTools.java
new file mode 100644 (file)
index 0000000..9ca2754
--- /dev/null
@@ -0,0 +1,520 @@
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.Collection;\r
+import java.util.HashMap;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Point3d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Tuple3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.stubs.Orientation;\r
+import org.simantics.proconf.g3d.stubs.Position;\r
+\r
+public class TransformationTools {\r
+       \r
+       private static boolean DEBUG = false;\r
+       \r
+       private Resource childRelation;\r
+       private Resource parentRelation;\r
+       \r
+       public TransformationTools(Resource childRelation, Resource parentRelation) {\r
+               this.childRelation = childRelation;\r
+               this.parentRelation = parentRelation;\r
+       }\r
+       \r
+       public IEntity getParent(IEntity node) {\r
+               return node.getAtMostOneRelatedObject(parentRelation);\r
+       }\r
+       \r
+       public Point3d getLocalFromWorld(IEntity node, Point3d worldCoord) {\r
+       IEntity parent = getParent(node);\r
+        if (parent == null) {// this is a rootnode ( has no transformation) \r
+               return worldCoord;\r
+        }\r
+\r
+        Point3d local = getLocalFromWorld2(parent,worldCoord);\r
+        return local;\r
+    }\r
+    \r
+    \r
+    private Point3d getLocalFromWorld2(IEntity node, Point3d worldCoord) {\r
+       IEntity parent = getParent(node);\r
+        if (parent == null) {// this is a root node ( has no transformation) \r
+               return worldCoord;\r
+        }\r
+\r
+        Point3d local = getLocalFromWorld2(parent,worldCoord);\r
+        if (node.hasStatement(Resources.g3dResource.HasLocalPosition))\r
+            local.sub(G3DTools.getPoint(node.getSingleRelatedObject(Resources.g3dResource.HasLocalPosition)));\r
+        if (node.hasStatement(Resources.g3dResource.HasLocalOrientation)) {\r
+            Quat4d q = new Quat4d();\r
+            q.set(G3DTools.getOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation)));\r
+            q.inverse();\r
+            MathTools.rotate(q, local, local);\r
+        }\r
+        return local;\r
+    }\r
+    \r
+    public Point3d getWorldFromLocal(IEntity node,Point3d localCoord) {\r
+       IEntity parent = getParent(node);\r
+        if (parent == null) // this is a rootnode ( has no transformation)\r
+            return localCoord;\r
+        return getWorldFromLocal2(parent, localCoord);\r
+    }\r
+    \r
+    private Point3d getWorldFromLocal2(IEntity node,Point3d localCoord) {\r
+       \r
+        if (node.hasStatement(Resources.g3dResource.HasLocalOrientation)) {\r
+            Quat4d q = new Quat4d();\r
+            q.set(G3DTools.getOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation)));\r
+            MathTools.rotate(q, localCoord, localCoord);\r
+        }\r
+        if (node.hasStatement(Resources.g3dResource.HasLocalPosition))\r
+            localCoord.add(G3DTools.getPoint(node.getSingleRelatedObject(Resources.g3dResource.HasLocalPosition)));\r
+        \r
+        IEntity parent = getParent(node);\r
+        if (parent == null) // this is a rootnode ( has no transformation)\r
+            return localCoord;\r
+        \r
+        return getWorldFromLocal2(parent,localCoord);\r
+    }\r
+    \r
+    \r
+    public AxisAngle4d getLocalFromWorld(IEntity node, AxisAngle4d worldRot) {\r
+       IEntity parent = getParent(node);\r
+       if (parent == null) // this is a rootnode ( has no transformation)\r
+            return worldRot;\r
+\r
+        AxisAngle4d local = getLocalFromWorld2(parent,worldRot);\r
+\r
+        return local;\r
+    }\r
+    \r
+    private AxisAngle4d getLocalFromWorld2(IEntity node, AxisAngle4d worldRot) {\r
+       IEntity parent = getParent(node);\r
+        if (parent == null) // this is a rootnode ( has no transformation)\r
+            return worldRot;\r
+        AxisAngle4d local  = getLocalFromWorld2(parent,worldRot);\r
+        \r
+        if (node.hasStatement(Resources.g3dResource.HasLocalOrientation)) {\r
+            Quat4d q = new Quat4d();\r
+            q.set(G3DTools.getOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation)));\r
+            q.inverse();\r
+            Quat4d q2 = new Quat4d();\r
+            q2.set(local);\r
+            q.mul(q2);\r
+            local.set(q);\r
+        }\r
+\r
+        return local;\r
+    }\r
+    \r
+    public AxisAngle4d getWorldFromLocal(IEntity node,AxisAngle4d localRot) {\r
+       IEntity parent = getParent(node);\r
+       if (parent == null)\r
+               return localRot;\r
+\r
+        return getWorldFromLocal2(parent,localRot);\r
+    }\r
+    \r
+    private AxisAngle4d getWorldFromLocal2(IEntity node,AxisAngle4d localRot) {\r
+       \r
+        //System.out.print("wtl " + node.getResource() + " " + localCoord);\r
+        if (node.hasStatement(Resources.g3dResource.HasLocalOrientation)) {\r
+            Quat4d q = new Quat4d();\r
+            q.set(G3DTools.getOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation)));\r
+            Quat4d q2 = new Quat4d();\r
+            q2.set(localRot);\r
+            q.mul(q2);\r
+            localRot.set(q);\r
+        }\r
+        \r
+        IEntity parent = getParent(node);\r
+        if (parent == null) // this is a rootnode ( has no transformation)\r
+            return localRot;\r
+        \r
+        //System.out.println(" " + localCoord);\r
+        return getWorldFromLocal2(parent,localRot);\r
+    }\r
+    \r
+    public Point3d getLocalFromWorldR(IEntity node, Point3d worldCoord) {\r
+       \r
+        Point3d local = getLocalFromWorldR(null,worldCoord);\r
+        if (node.hasStatement(Resources.g3dResource.HasLocalOrientation)) {\r
+            Quat4d q = new Quat4d();\r
+            q.set(G3DTools.getOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation)));\r
+            q.inverse();\r
+            MathTools.rotate(q, local, local);\r
+        }\r
+        \r
+        IEntity parent = getParent(node);\r
+        if (parent == null) // this is a rootnode ( has no transformation)\r
+            return worldCoord;\r
+        \r
+        return local;\r
+    }\r
+    \r
+    public Point3d getWorldFromLocalR(IEntity node,Point3d localCoord) {\r
+       \r
+        if (node.hasStatement(Resources.g3dResource.HasLocalOrientation)) {\r
+            Quat4d q = new Quat4d();\r
+            q.set(G3DTools.getOrientation(node.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation)));\r
+            MathTools.rotate(q, localCoord, localCoord);\r
+        } \r
+        \r
+        IEntity parent = getParent(node);\r
+        if (parent == null) // this is a rootnode ( has no transformation)\r
+            return localCoord;\r
+        \r
+        return getWorldFromLocalR(parent,localCoord);\r
+    }\r
+    \r
+    /**\r
+     * Updates transformations of all children of given node\r
+     * @param node\r
+     */\r
+    public void propagateTransformChange(IEntity node) {\r
+        Collection<IEntity> children = node.getRelatedObjects(childRelation);\r
+       IEntity wp = node.getAtMostOneRelatedObject(Resources.g3dResource.HasWorldPosition);\r
+        IEntity wr = node.getAtMostOneRelatedObject(Resources.g3dResource.HasWorldOrientation);\r
+        Quat4d rot = new Quat4d();\r
+        if (wr != null)\r
+            rot.set(G3DTools.getOrientation(wr));\r
+        else\r
+            rot.w = 1.0;\r
+        Point3d pos = new Point3d();\r
+        if (wp != null)\r
+            pos = G3DTools.getPoint(wp);\r
+        if (DEBUG) {\r
+               if (wr != null)\r
+                       System.out.println("propagate transform " + node.getResource() + " " + pos + " " + G3DTools.getOrientation(wr));\r
+               else\r
+                       System.out.println("propagate transform " + node.getResource() + " " + pos);\r
+        }\r
+        for (IEntity n : children) {\r
+            IEntity lPos = n.getAtMostOneRelatedObject(Resources.g3dResource.HasLocalPosition);\r
+            IEntity lRot = n.getAtMostOneRelatedObject(Resources.g3dResource.HasLocalOrientation);\r
+            if (DEBUG) System.out.print(n);\r
+            if (lRot != null) {\r
+               AxisAngle4d la = G3DTools.getOrientation(lRot);\r
+                AxisAngle4d wa = getWorldFromLocal(n, la);\r
+                IEntity wo = n.getSingleRelatedObject(Resources.g3dResource.HasWorldOrientation);\r
+                G3DTools.setOrientation(wo,wa);\r
+                storeProperty(wo.getResource(), wa);\r
+            }\r
+            if (lPos != null) {\r
+                Point3d lp = G3DTools.getPoint(lPos);\r
+                if (DEBUG) System.out.println(lp);\r
+                MathTools.rotate(rot, lp, lp);\r
+                lp.add(pos);\r
+                IEntity nwp = n.getSingleRelatedObject(Resources.g3dResource.HasWorldPosition);\r
+                G3DTools.setTuple3(nwp, lp);\r
+                if (DEBUG) System.out.print(" " + lp);\r
+                storeProperty(nwp.getResource(), lp);\r
+            }\r
+            if (DEBUG) System.out.println();\r
+            propagateTransformChange(n);\r
+            \r
+        }\r
+    }\r
+    \r
+    /**\r
+     * Updates transformation of one child node without changing its local transformation.\r
+     * @param parent\r
+     * @param node\r
+     */\r
+    public void propagateLocalTransformChange(IEntity parent, IEntity node) {\r
+        //Collection<IEntity> children = parent.getRelatedObjects(childRelation);\r
+       IEntity parentWP = parent.getAtMostOneRelatedObject(Resources.g3dResource.HasWorldPosition);\r
+        IEntity parentWR = parent.getAtMostOneRelatedObject(Resources.g3dResource.HasWorldOrientation);\r
+        Quat4d parentWRot = new Quat4d();\r
+        if (parentWR != null) {\r
+            parentWRot.set(G3DTools.getOrientation(parentWR));\r
+           \r
+        } else\r
+            parentWRot.w = 1.0;\r
+        Point3d parentWPos = new Point3d();\r
+        if (parentWP != null) {\r
+            parentWPos = G3DTools.getPoint(parentWP);\r
+        }\r
+        if (DEBUG) {\r
+               if (parentWR != null)\r
+                       System.out.println("propagate transform " + parent.getResource() + " " + parentWPos + " " + G3DTools.getOrientation(parentWR));\r
+               else\r
+                       System.out.println("propagate transform " + parent.getResource() + " " + parentWPos);\r
+        }\r
+        //for (IEntity n : children) {\r
+        //     if (!n.equals(node))\r
+        //             continue;\r
+            IEntity lPos = node.getAtMostOneRelatedObject(Resources.g3dResource.HasLocalPosition);\r
+            IEntity lRot = node.getAtMostOneRelatedObject(Resources.g3dResource.HasLocalOrientation);\r
+            if (DEBUG) System.out.print(node);\r
+            if (lRot != null) {\r
+               AxisAngle4d aa = G3DTools.getOrientation(lRot);\r
+               storeProperty(lRot.getResource(), aa);\r
+                AxisAngle4d la = getWorldFromLocal(node, aa);\r
+                IEntity wo = node.getSingleRelatedObject(Resources.g3dResource.HasWorldOrientation);\r
+                G3DTools.setOrientation(wo,la);\r
+                storeProperty(wo.getResource(), la);\r
+            }\r
+            if (lPos != null) {\r
+                Point3d lp = G3DTools.getPoint(lPos);\r
+                storeProperty(lPos.getResource(), lp);\r
+                MathTools.rotate(parentWRot, lp, lp);\r
+                lp.add(parentWPos);\r
+                IEntity nwp = node.getSingleRelatedObject(Resources.g3dResource.HasWorldPosition);\r
+                G3DTools.setTuple3(nwp, lp);\r
+                storeProperty(nwp.getResource(), lp);\r
+            }\r
+            if (DEBUG) System.out.println();\r
+            propagateTransformChange(node);\r
+            \r
+        }\r
+//    }\r
+    \r
+    public static void resetTransformation(IEntity shape) {\r
+               Graph graph = shape.getGraph();\r
+               if (shape.getAtMostOneRelatedObject(Resources.g3dResource.HasLocalPosition) == null) {\r
+\r
+                       // LocalPosition p = LocalPosition.createDefault(graph);\r
+                       Position p = Position.createDefault(graph);\r
+                       shape.addStatement(Resources.g3dResource.HasLocalPosition, p);\r
+                       // WorldPosition p2 = WorldPosition.createDefault(graph);\r
+                       Position p2 = Position.createDefault(graph);\r
+                       shape.addStatement(Resources.g3dResource.HasWorldPosition, p2);\r
+                       p.setX(new double[] { 0.0 });\r
+                       p.setY(new double[] { 0.0 });\r
+                       p.setZ(new double[] { 0.0 });\r
+\r
+                       p2.setX(new double[] { 0.0 });\r
+                       p2.setY(new double[] { 0.0 });\r
+                       p2.setZ(new double[] { 0.0 });\r
+\r
+               } else {\r
+                       G3DTools.setTuple3(shape.getSingleRelatedObject(Resources.g3dResource.HasLocalPosition), 0.0, 0.0, 0.0);\r
+                       G3DTools.setTuple3(shape.getSingleRelatedObject(Resources.g3dResource.HasWorldPosition), 0.0, 0.0, 0.0);\r
+               }\r
+               if (shape.getAtMostOneRelatedObject(Resources.g3dResource.HasLocalOrientation) == null) {\r
+\r
+                       // LocalOrientation r = LocalOrientationFactory.create(graph);\r
+                       Orientation r = Orientation.createDefault(graph);\r
+                       shape.addStatement(Resources.g3dResource.HasLocalOrientation, r);\r
+                       // WorldOrientation r2 = WorldOrientationFactory.create(graph);\r
+                       Orientation r2 = Orientation.createDefault(graph);\r
+                       shape.addStatement(Resources.g3dResource.HasWorldOrientation, r2);\r
+                       r.setAngle(new double[] { 0.0 });\r
+                       r.setX(new double[] { 1.0 });\r
+                       r.setY(new double[] { 0.0 });\r
+                       r.setZ(new double[] { 0.0 });\r
+                       r2.setAngle(new double[] { 0.0 });\r
+                       r2.setX(new double[] { 1.0 });\r
+                       r2.setY(new double[] { 0.0 });\r
+                       r2.setZ(new double[] { 0.0 });\r
+\r
+               } else {\r
+                       G3DTools.setOrientation(shape.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation),\r
+                                       new AxisAngle4d(0.0, 1.0, 0.0, 0.0));\r
+                       G3DTools.setOrientation(shape.getSingleRelatedObject(Resources.g3dResource.HasWorldOrientation),\r
+                                       new AxisAngle4d(0.0, 1.0, 0.0, 0.0));\r
+               }\r
+       }\r
+    \r
+    /**\r
+     * Updates transformation of one child node without changing its world transformation.\r
+     * @param parent\r
+     * @param node\r
+     */\r
+    public void propagateWorldTransformChange(IEntity parent, IEntity node) {\r
+        //Collection<IEntity> children = parent.getRelatedObjects(childRelation);\r
+       IEntity parentWP = parent.getAtMostOneRelatedObject(Resources.g3dResource.HasWorldPosition);\r
+        IEntity parentWR = parent.getAtMostOneRelatedObject(Resources.g3dResource.HasWorldOrientation);\r
+        Quat4d parentWQuat = new Quat4d();\r
+        if (parentWR != null) {\r
+            parentWQuat.set(G3DTools.getOrientation(parentWR));\r
+        }\r
+        else\r
+            parentWQuat.w = 1.0;\r
+        Point3d parentWPos = new Point3d();\r
+        if (parentWP != null) {\r
+            parentWPos = G3DTools.getPoint(parentWP);\r
+        }\r
+        if (DEBUG){\r
+               if (parentWR != null) \r
+                   System.out.println("propagate transform " + parent.getResource() + " " + parentWPos + " " + G3DTools.getOrientation(parentWR));\r
+               else\r
+                       System.out.println("propagate transform " + parent.getResource() + " " + parentWPos);\r
+        }\r
+        //for (IEntity n : children) {\r
+      //       if (!n.equals(node))\r
+      //               continue;\r
+            IEntity wPos = node.getAtMostOneRelatedObject(Resources.g3dResource.HasWorldPosition);\r
+            IEntity wRot = node.getAtMostOneRelatedObject(Resources.g3dResource.HasWorldOrientation);\r
+            \r
+            if (DEBUG) System.out.print(node);\r
+            if (wRot != null) {\r
+               AxisAngle4d aa = G3DTools.getOrientation(wRot);\r
+               storeProperty(wRot.getResource(), aa);\r
+                AxisAngle4d la = getLocalFromWorld(node, aa);\r
+                IEntity lRot = node.getSingleRelatedObject(Resources.g3dResource.HasLocalOrientation);\r
+                G3DTools.setOrientation(lRot,la);\r
+                storeProperty(lRot.getResource(), la);\r
+            }\r
+            if (wPos != null) {\r
+                Point3d lp = G3DTools.getPoint(wPos);\r
+                storeProperty(wPos.getResource(), lp);\r
+                lp.sub(parentWPos);\r
+                parentWQuat.inverse();     \r
+                MathTools.rotate(parentWQuat, lp, lp);\r
+                IEntity lPos = node.getSingleRelatedObject(Resources.g3dResource.HasLocalPosition);\r
+                G3DTools.setTuple3(lPos, lp);\r
+                storeProperty(lPos.getResource(), lp);\r
+            }\r
+            if (DEBUG) System.out.println();\r
+            propagateTransformChange(node);\r
+            \r
+ //       }\r
+    }\r
+        \r
+    public boolean transformationUpdate(Graph graph, Resource resource) {\r
+       \r
+       //resources.startTransaction("transformationUpdate");\r
+       IEntity entity = EntityFactory.create(graph,resource);\r
+       return transformationUpdate(entity);\r
+    }\r
+    \r
+    public boolean transformationUpdate(IEntity node) {\r
+       if (DEBUG) System.out.println("Node transformation update " + node.getResource());\r
+       IEntity worldPos = node.getSingleRelatedObject(Resources.g3dResource.HasWorldPosition);\r
+       IEntity localPos = node.getSingleRelatedObject(Resources.g3dResource.HasLocalPosition);\r
+       IEntity worldOr = node.getAtMostOneRelatedObject(Resources.g3dResource.HasWorldOrientation);\r
+       IEntity localOr = node.getAtMostOneRelatedObject(Resources.g3dResource.HasLocalOrientation);\r
+       \r
+       Tuple3d worldP =G3DTools.getPoint(worldPos);\r
+       Tuple3d localP = G3DTools.getPoint(localPos);\r
+\r
+       AxisAngle4d worldR = null;\r
+       AxisAngle4d localR = null;\r
+       if (worldOr != null) {\r
+               worldR = G3DTools.getOrientation(worldOr);\r
+               localR = G3DTools.getOrientation(localOr);\r
+       }\r
+       \r
+       boolean changed = false;\r
+       if (localP != null && worldP != null) {\r
+               Tuple3d cachedWorldP = (Tuple3d)getProperty(worldPos.getResource());\r
+               Tuple3d cachedLocalP = (Tuple3d)getProperty(localPos.getResource());\r
+               boolean changedLocalP = false;\r
+               boolean changedWorldP = false;\r
+               if (cachedLocalP == null)\r
+                       changedLocalP = true;\r
+               else if (changed(cachedLocalP,localP))\r
+                       changedLocalP = true;\r
+\r
+               if (cachedWorldP == null) {\r
+                       changedWorldP = true;\r
+               } else if (changed(cachedWorldP,worldP)){\r
+                       changedWorldP = true;\r
+               }\r
+               if (changedLocalP) {\r
+                       storeProperty(localPos.getResource(), localP);\r
+                       Tuple3d p = getWorldFromLocal(node, new Point3d(localP));\r
+                       storeProperty(worldPos.getResource(), p);\r
+                       G3DTools.setTuple3(worldPos, p);\r
+                       if (DEBUG) System.out.println("Node changed local: wp " + worldP + " lp " + p + " old " + cachedLocalP);\r
+                       changed = true;\r
+               } else if (changedWorldP) {\r
+                       storeProperty(worldPos.getResource(), worldP);\r
+                       Tuple3d p = getLocalFromWorld(node, new Point3d(worldP));\r
+                       G3DTools.setTuple3(localPos, p);\r
+                       storeProperty(localPos.getResource(), p);\r
+                       if (DEBUG) System.out.println("Node changed world: wp " + worldP + " lp " + p + " old " + cachedWorldP);\r
+                       changed = true;\r
+               }\r
+       }\r
+\r
+       if (localR != null || worldR != null) {\r
+               AxisAngle4d cachedWorldR = (AxisAngle4d)getProperty(worldOr.getResource());\r
+               AxisAngle4d cachedLocalR = (AxisAngle4d)getProperty(localOr.getResource());\r
+               boolean changedLocalR = false;\r
+               boolean changedWorldR = false;\r
+\r
+               if (cachedLocalR == null)\r
+                       changedLocalR = true;\r
+               else if (changed(cachedLocalR,localR))\r
+                       changedLocalR = true;\r
+\r
+               if (cachedWorldR == null) {\r
+                       changedWorldR = true;\r
+               } else if (changed(cachedWorldR,worldR)){\r
+                       changedWorldR = true;\r
+               }\r
+\r
+               if (changedLocalR) {\r
+                       storeProperty(localOr.getResource(), localR);\r
+                       AxisAngle4d p = getWorldFromLocal(node, new AxisAngle4d(localR));\r
+                       G3DTools.setOrientation(worldOr, p);\r
+                       storeProperty(worldOr.getResource(), p);\r
+                       if (DEBUG) System.out.println("Node changed localR: wr " + p + " lr " + localR + " old " + cachedLocalR);\r
+                       changed = true;\r
+               } else if (changedWorldR) {\r
+                       storeProperty(worldOr.getResource(), worldR);\r
+                       AxisAngle4d p = getLocalFromWorld(node, new AxisAngle4d(worldR));\r
+                       G3DTools.setOrientation(localOr, p);\r
+                       storeProperty(localOr.getResource(), p);\r
+                       if (DEBUG) System.out.println("Node changed worldR: wr " + worldR + " lr " + p + " old " + cachedWorldR);\r
+                       changed = true;\r
+               } \r
+       }\r
+\r
+       if (changed)\r
+               propagateTransformChange(node);\r
+       else if (DEBUG)\r
+               System.out.println("No Node transformation change detected " + node.getResource());\r
+       return changed;\r
+    }\r
+    \r
+    public static boolean changed(Tuple3d v1, Tuple3d v2) {\r
+        Vector3d t = new Vector3d(v1);\r
+        t.sub(v2);\r
+        return t.lengthSquared() > 0.00001;\r
+    }\r
+    \r
+    public static boolean changed (double d1 , double d2) {\r
+       return (Math.abs(d1 - d2) > 0.00001 );\r
+               \r
+    }\r
+    \r
+    public static boolean changed(AxisAngle4d aa1, AxisAngle4d aa2) {\r
+        if (Math.abs(aa1.angle - aa2.angle) > 0.00001)\r
+            return true;\r
+        Vector3d t1 = new Vector3d(aa1.x-aa2.x,aa1.y-aa2.y,aa1.z-aa2.z);\r
+        if (t1.lengthSquared() > 0.00001) {\r
+               if (Math.abs(aa1.angle) < 0.0001)\r
+                       return false;\r
+               return true;\r
+        }\r
+        return false;\r
+    }\r
+\r
+    \r
+    private HashMap<Object, Object> properties = new HashMap<Object, Object>();\r
+    \r
+    public Object getProperty(Object key) {\r
+        return properties.get(key);\r
+    }\r
+    \r
+    public void storeProperty(Object key, Object value) {\r
+        properties.put(key, value);\r
+    }\r
+    \r
+    \r
+    \r
+    \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/VecmathJmeTools.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/VecmathJmeTools.java
new file mode 100644 (file)
index 0000000..21cfcff
--- /dev/null
@@ -0,0 +1,78 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import javax.vecmath.Color4f;\r
+\r
+import com.jme.renderer.ColorRGBA;\r
+\r
+public class VecmathJmeTools {\r
+       \r
+       public static javax.vecmath.Vector3f get(com.jme.math.Vector3f v) {\r
+               return new javax.vecmath.Vector3f(v.x,v.y,v.z);\r
+       }\r
+       \r
+       public static javax.vecmath.Vector3d getD(com.jme.math.Vector3f v) {\r
+               return new javax.vecmath.Vector3d(v.x,v.y,v.z);\r
+       }\r
+       \r
+       public static com.jme.math.Vector3f get(javax.vecmath.Tuple3f v) {\r
+               return new com.jme.math.Vector3f(v.x,v.y,v.z);\r
+       }\r
+       \r
+       public static com.jme.math.Vector3f get(javax.vecmath.Tuple3d v) {\r
+               return new com.jme.math.Vector3f((float)v.x,(float)v.y,(float)v.z);\r
+       }\r
+       \r
+       public static com.jme.math.Matrix3f get(javax.vecmath.Matrix3d m) {\r
+               return new com.jme.math.Matrix3f((float)m.m00,(float)m.m01,(float)m.m02,(float)m.m10,(float)m.m11,(float)m.m12,(float)m.m20,(float)m.m21,(float)m.m22);\r
+       }\r
+       \r
+       public static javax.vecmath.Quat4f get(com.jme.math.Quaternion v) {\r
+               return new javax.vecmath.Quat4f(v.x,v.y,v.z,v.w);\r
+       }\r
+       \r
+       public static javax.vecmath.Quat4d getD(com.jme.math.Quaternion v) {\r
+               return new javax.vecmath.Quat4d(v.x,v.y,v.z,v.w);\r
+       }\r
+       \r
+       \r
+       public static com.jme.math.Quaternion get(javax.vecmath.Quat4f v) {\r
+               return new com.jme.math.Quaternion(v.x,v.y,v.z,v.w);\r
+       }\r
+       \r
+       public static com.jme.math.Quaternion get(javax.vecmath.Quat4d v) {\r
+               return new com.jme.math.Quaternion((float)v.x,(float)v.y,(float)v.z,(float)v.w);\r
+       }\r
+       \r
+       public static com.jme.math.Quaternion get(javax.vecmath.AxisAngle4f aa) {\r
+               javax.vecmath.Quat4f v = new javax.vecmath.Quat4f();\r
+               v.set(aa);\r
+               return new com.jme.math.Quaternion(v.x,v.y,v.z,v.w);\r
+               \r
+       }\r
+       \r
+       public static com.jme.math.Quaternion get(javax.vecmath.AxisAngle4d aa) {\r
+               javax.vecmath.Quat4f v = new javax.vecmath.Quat4f();\r
+               v.set(aa);\r
+               return new com.jme.math.Quaternion(v.x,v.y,v.z,v.w);\r
+               \r
+       }\r
+       \r
+       public static ColorRGBA get(Color4f c) {\r
+               return new ColorRGBA(c.x,c.y,c.z,c.w);\r
+       }\r
+       \r
+       public static Color4f get(ColorRGBA c) {\r
+               return new Color4f(c.r,c.g,c.b,c.a);\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/VisualizationScheduler.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/VisualizationScheduler.java
new file mode 100644 (file)
index 0000000..e7011eb
--- /dev/null
@@ -0,0 +1,199 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.simantics.utils.ErrorLogger;\r
+\r
+\r
+/**\r
+ * TODO : This is a copy-paste from old proconf.utils plug-ing:\r
+ *             : PreferencePage is not ported,\r
+ *             : Using Webmon ?\r
+ * \r
+ * \r
+ * VisualizationScheduler is singleton class that schedules\r
+ * visualization redraws. \r
+ * \r
+ * Scheduler has three behaviour patters: \r
+ * \r
+ * ONCE : Redraws all visualizations one by one and then sleeps for\r
+ *        a while so that visualizations won't use all available cpu-time.\r
+ *    \r
+ * ALWAYS : Redraws one visualization and sleeps before updating next\r
+ *          visualization.\r
+ *    \r
+ * OFF : uses asyncExec busy-loop (doesn't block eclipse, but other applications may suffer) \r
+ * \r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class VisualizationScheduler implements Runnable{\r
+    private static VisualizationScheduler instance;\r
+    private Display display;\r
+    private ArrayList<Runnable> visualizations;\r
+    private boolean isDisposed = false;\r
+    private boolean stateFlag = false;\r
+    private static int sleepTime = 40;\r
+    private int index = 0;\r
+    \r
+    public enum SleepType{ONCE,ALWAYS,OFF};\r
+    \r
+    private static SleepType sleepType = SleepType.ONCE;\r
+    \r
+    private VisualizationScheduler() {\r
+        visualizations = new ArrayList<Runnable>();\r
+        display = PlatformUI.getWorkbench().getDisplay();\r
+        //sleepTime = UtilsPlugin.getDefault().getPreferenceStore().getInt(PreferenceConstants.SLEEP_TIME);\r
+        //sleepType = SleepType.valueOf(UtilsPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.SLEEP_TYPE));\r
+        run();\r
+    }\r
+\r
+    /**\r
+     * Scheduler's run loop<br>\r
+     * <br>\r
+     * Loop contains two stages:<br>\r
+     * In the first stage scheduler runs asyncExec for each visualization\r
+     * and after that it runs itself with asyncExec.<br>\r
+     * In the second stage scheduler runs itself with timerExec which allows OS to run it's own code.\r
+     */\r
+    public void run() {\r
+        if (!isDisposed && !display.isDisposed() && !PlatformUI.getWorkbench().isClosing()) {\r
+            switch(sleepType) {\r
+            case ALWAYS:\r
+               stateFlag = !stateFlag;\r
+                               if (stateFlag) {\r
+                                       if (visualizations.size() > 0) {\r
+                                               if (index >= visualizations.size())\r
+                                                       index = 0;\r
+                                               Runnable scene = visualizations.get(index);\r
+                                               try {\r
+                                                       display.asyncExec(scene);\r
+                                               } catch (Exception e) {\r
+                                                       ErrorLogger.defaultLogWarning("Scheduler exception", e);\r
+                                               }\r
+                                               index++;\r
+                                       }\r
+                                       display.asyncExec(this);\r
+                               } else {\r
+                                       display.timerExec(sleepTime, this);\r
+                               }\r
+               break;\r
+            case ONCE: \r
+               stateFlag = !stateFlag;\r
+               if (stateFlag) {\r
+                       for (Runnable scene : visualizations) {\r
+                       try {\r
+                               display.asyncExec(scene);\r
+                       } catch (Exception e) {\r
+                               ErrorLogger.defaultLogWarning("Scheduler exception",e);\r
+                       }\r
+                       }\r
+                       display.asyncExec(this);\r
+               } else {\r
+                       display.timerExec(sleepTime,this);\r
+               }\r
+               break;\r
+            case OFF: \r
+               for (Runnable scene : visualizations) {\r
+                       try {\r
+                       display.asyncExec(scene);\r
+                       } catch (Exception e) {\r
+                               ErrorLogger.defaultLogWarning("Scheduler exception",e);\r
+                       }\r
+               }\r
+               display.asyncExec(this);\r
+               break;\r
+            }\r
+        }      \r
+    }\r
+    \r
+    /**\r
+     * Adds visualization into scheduler\r
+     * @param scene\r
+     */\r
+    public void addVisualization(Runnable scene) {\r
+        visualizations.add(scene);\r
+    }\r
+    \r
+    /**\r
+     * Removes visualization from scheduler\r
+     * @param scene\r
+     */\r
+    public void removeVisualization(Runnable scene) {\r
+        visualizations.remove(scene);\r
+    }\r
+    \r
+    /**\r
+     * disposes scheduler.\r
+     *\r
+     */\r
+    public void dispose() {\r
+        isDisposed = true;\r
+    } \r
+    \r
+    /**\r
+     * @return scheduler's instance\r
+     */\r
+    public static VisualizationScheduler getInstance() {\r
+        if (instance == null)\r
+            instance = new VisualizationScheduler();\r
+        \r
+        return instance;\r
+    }\r
+\r
+    /**\r
+     * @return the sleep time of the scheduler\r
+     */\r
+    public int getSleepTime() {\r
+        return sleepTime;\r
+    }\r
+\r
+    /**\r
+     * <p>\r
+     * Sets scheduler's sleep time. Larger sleep time gives more\r
+     * cpu time to other applications, but makes visualizations less\r
+     * responsive.\r
+     * </p>\r
+     *  \r
+     * @param sleepTime\r
+     */\r
+    public static void setSleepTime(int time) {\r
+        sleepTime = time;\r
+    }\r
+\r
+//     public boolean isSleepAlways() {\r
+//             return sleepAlways;\r
+//     }\r
+\r
+       /**\r
+        * if this flag is set scheludler gives time to other aplications\r
+        * between each visualization update. Otherwise all visualizations are updated in row and\r
+        * then priority is given to other applications.\r
+        * @param sleepAlways\r
+        */\r
+//     public static void setSleepAlways(boolean sleep) {\r
+//             sleepAlways = sleep;\r
+//     }  \r
+    \r
+    public static SleepType getSleepType() {\r
+       return sleepType;\r
+    }\r
+    \r
+    public static void setSleepType(SleepType s) {\r
+       sleepType = s;\r
+    }\r
+    \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/JmeComposite.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/JmeComposite.java
new file mode 100644 (file)
index 0000000..5cff3ff
--- /dev/null
@@ -0,0 +1,112 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.common;\r
+\r
+\r
+import java.util.logging.LogManager;\r
+\r
+import org.eclipse.core.runtime.Path;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.ControlAdapter;\r
+import org.eclipse.swt.events.ControlEvent;\r
+import org.eclipse.swt.graphics.Rectangle;\r
+import org.eclipse.swt.layout.FillLayout;\r
+import org.eclipse.swt.opengl.GLCanvas;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.proconf.g3d.base.JmeRenderingComponent;\r
+import org.simantics.proconf.g3d.base.ResourceTextureCache;\r
+import org.simantics.utils.ErrorLogger;\r
+\r
+import com.jme.renderer.Renderer;\r
+import com.jme.renderer.lwjgl.LWJGLRenderer;\r
+import com.jme.scene.Node;\r
+import com.jme.system.DisplaySystem;\r
+import com.jme.system.swt.SWTDisplaySystem;\r
+import com.jme.util.TextureManager;\r
+\r
+\r
+public class JmeComposite extends Composite {\r
+       protected Node rootNode = new Node("root");\r
+       private SWTDisplaySystem displaySystem;\r
+       protected GLCanvas renderingCanvas;\r
+       private JmeRenderingComponent component;\r
+       \r
+       public JmeComposite(Composite parent, JmeRenderingComponent component) {\r
+               super(parent,SWT.NONE);\r
+               if (component == null)\r
+                       throw new NullPointerException("Rendering component must not be null.");\r
+               disableLog();\r
+               //LoggingSystem.getLogger().setLevel(Level.OFF);\r
+               this.component = component;\r
+               this.setLayout(new FillLayout());\r
+               displaySystem = (SWTDisplaySystem)DisplaySystem.getDisplaySystem("SWT");\r
+               renderingCanvas = displaySystem.createCanvas(640, 480, this);\r
+        renderingCanvas.addControlListener(new ControlAdapter() {\r
+            public void controlResized(ControlEvent e) {\r
+                resize();\r
+            }\r
+        });\r
+        \r
+        \r
+       }\r
+       \r
+       private void disableLog() {\r
+               //URL url = FileLocator.find(org.simantics.proconf.g3d.Activator.getDefault().getBundle(),new Path("logging.properties"),null);\r
+               \r
+               try {\r
+                       LogManager.getLogManager().readConfiguration(org.simantics.proconf.g3d.Activator.getDefault().openStream(new Path("logging.properties")));\r
+               } catch (Exception e) {\r
+                       ErrorLogger.defaultLogError(e);\r
+               }\r
+       }\r
+       \r
+       public void resize() {\r
+               displaySystem.setCurrent();\r
+        LWJGLRenderer renderer = (LWJGLRenderer) displaySystem.getRenderer();\r
+        if (renderer!= null) { \r
+            Rectangle r = new Rectangle(renderingCanvas.getClientArea().x,renderingCanvas.getClientArea().y, renderingCanvas.getClientArea().width, renderingCanvas.getClientArea().height );\r
+            if (r.width > 0 && r.height > 0)\r
+            renderer.reinit(r.width, r.height);\r
+            component.resize(r.width, r.height);\r
+        }\r
+    }\r
+       \r
+       public GLCanvas getCanvas() { \r
+        return renderingCanvas;\r
+    }\r
+       \r
+       public Renderer getRenderer() {\r
+               return displaySystem.getRenderer();\r
+       }\r
+       \r
+       public void initGL() {\r
+               component.init(displaySystem);\r
+       }\r
+       \r
+       public void dispose() {\r
+               LWJGLRenderer renderer = (LWJGLRenderer) displaySystem.getRenderer();\r
+               renderer.clearVBOCache();\r
+               renderer.clearQueue();\r
+               renderer.clearStatistics();\r
+               renderingCanvas.dispose();\r
+               if (displaySystem.destroy()) {\r
+                       \r
+                       TextureManager.doTextureCleanup();\r
+                       TextureManager.clearCache();\r
+                       ResourceTextureCache.getInstance().clear();\r
+               }\r
+               super.dispose();\r
+       }\r
+       \r
+       public DisplaySystem getDisplaySystem() {\r
+               return displaySystem;\r
+       }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/JmeSinglePassRenderingComponent.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/JmeSinglePassRenderingComponent.java
new file mode 100644 (file)
index 0000000..fb9aff6
--- /dev/null
@@ -0,0 +1,411 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.common;\r
+\r
+import java.net.URL;\r
+\r
+import org.eclipse.core.runtime.FileLocator;\r
+import org.eclipse.core.runtime.Path;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.base.JmeRenderingComponent;\r
+import org.simantics.proconf.g3d.preferences.PreferenceConstants;\r
+\r
+import com.jme.image.Texture;\r
+import com.jme.light.DirectionalLight;\r
+import com.jme.math.Vector3f;\r
+import com.jme.renderer.Camera;\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.renderer.pass.BasicPassManager;\r
+import com.jme.renderer.pass.RenderPass;\r
+import com.jme.renderer.pass.ShadowedRenderPass;\r
+import com.jme.renderer.swt.SWTRenderer;\r
+import com.jme.scene.Node;\r
+import com.jme.scene.Spatial;\r
+import com.jme.scene.Text;\r
+import com.jme.scene.state.AlphaState;\r
+import com.jme.scene.state.LightState;\r
+import com.jme.scene.state.TextureState;\r
+import com.jme.scene.state.WireframeState;\r
+import com.jme.scene.state.ZBufferState;\r
+import com.jme.system.DisplaySystem;\r
+import com.jme.util.TextureManager;\r
+import com.jme.util.Timer;\r
+import com.jme.util.geom.Debugger;\r
+import com.jmex.effects.glsl.BloomRenderPass;\r
+import com.jmex.effects.glsl.SketchRenderPass;\r
+\r
+\r
+public class JmeSinglePassRenderingComponent extends JmeRenderingComponent {\r
+       protected DisplaySystem displaySystem;\r
+       protected Timer timer;\r
+       protected Node rootNode = new Node("Root");\r
+       protected Node shadowRootNode = new Node("Shadow");\r
+       protected Node noCastShadowRootNode = new Node("No Cast Shadow");\r
+       protected Node noShadowRootNode = new Node("No Shadow");\r
+       protected Camera cam;\r
+       protected float near = .1f;\r
+       protected float far = 3000f;\r
+       protected float fov = 55f;\r
+    \r
+       protected int projectionPolicy;\r
+    \r
+    /** The root node of our text. */\r
+       protected Node orthoNode = new Node("ortho");\r
+\r
+    /** Displays all the lovely information at the bottom. */\r
+    protected Text fps;\r
+    protected Text debug;\r
+    protected String debugText  = "";\r
+    public static String fontLocation = "data/defaultfont.tga";//AppProperties.PATH_DEFAULT_FONT;\r
+    \r
+    \r
+    protected BasicPassManager pManager = new BasicPassManager();\r
+    \r
+    private boolean showBounds = false;\r
+    private boolean showNormals = false;\r
+    private WireframeState ws = null;\r
+    \r
+    private boolean projectionUpdated = false;\r
+    \r
+       public JmeSinglePassRenderingComponent() {\r
+               \r
+       }\r
+       \r
+       public void init(DisplaySystem displaySystem) {\r
+               this.displaySystem = displaySystem;\r
+               cam = displaySystem.getRenderer().createCamera(\r
+                displaySystem.getRenderer().getWidth(), displaySystem.getRenderer().getHeight());\r
+               displaySystem.getRenderer().setBackgroundColor(new ColorRGBA(0.2f,0.2f,0.2f,0.f));//(0.357F, 0.647F, 0.890F, 1.0F));\r
+        displaySystem.getRenderer().getQueue().setTwoPassTransparency(true);\r
+               cam.setFrustumPerspective(fov,\r
+                (float) displaySystem.getRenderer().getWidth()/\r
+                (float) displaySystem.getRenderer().getHeight(),near, far);\r
+        projectionPolicy = PERSPECTIVE_PROJECTION;\r
+        Vector3f loc = new Vector3f(0.0f, 0.0f, 10.0f);\r
+        Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);\r
+        Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);\r
+        Vector3f dir = new Vector3f(0.0f, 0f, -1.0f);\r
+        /** Move our camera to a correct place and orientation. */\r
+        cam.setFrame(loc, left, up, dir);\r
+        /** Signal that we've changed our camera's location/frustum. */\r
+        cam.update();\r
+        displaySystem.getRenderer().setCamera(cam);\r
+        timer = Timer.getTimer();\r
+        displaySystem.setTitle("ShapeEditor");\r
+        displaySystem.getRenderer().enableStatistics(true);\r
+        \r
+        initRoot();\r
+       }\r
+       \r
+       protected Texture loadFontTexture() {\r
+               URL url = FileLocator.find(org.simantics.proconf.g3d.Activator.getDefault().getBundle(),new Path(fontLocation),null);\r
+        return TextureManager.loadTexture(url, Texture.MM_LINEAR,\r
+                Texture.FM_LINEAR);\r
+       }\r
+       \r
+       protected void initRoot() {\r
+               ZBufferState buf = displaySystem.getRenderer().createZBufferState();\r
+        buf.setEnabled(true);\r
+        buf.setFunction(ZBufferState.CF_LEQUAL);\r
+        //buf.setWritable(false);\r
+        rootNode.setRenderState(buf);   \r
+        rootNode.attachChild(noShadowRootNode);\r
+        rootNode.attachChild(noCastShadowRootNode);\r
+        rootNode.attachChild(shadowRootNode);\r
+        noShadowRootNode.setCullMode(Spatial.CULL_NEVER);\r
+        \r
+        //PointLight light = new PointLight();\r
+        DirectionalLight light = new DirectionalLight();\r
+        light.setDiffuse( new ColorRGBA( 0.75f, 0.75f, 0.75f, 0.75f ) );\r
+        light.setAmbient( new ColorRGBA( 0.5f, 0.5f, 0.5f, 0.5f ) );\r
+        //light.setLocation( new Vector3f( 100, 100, 100 ) );\r
+        light.setDirection(new Vector3f( -100, -150, -100 ));\r
+        light.setEnabled( true );\r
+        light.setShadowCaster(true);\r
+        \r
+        LightState lightState = displaySystem.getRenderer().createLightState();\r
+        lightState.setEnabled( true );\r
+        lightState.attach( light );\r
+        lightState.setSeparateSpecular(true);\r
+        lightState.setTwoSidedLighting(false);\r
+        rootNode.setRenderState( lightState );\r
+        \r
+        ws = displaySystem.getRenderer().createWireframeState();\r
+        ws.setEnabled(false);\r
+        rootNode.setRenderState(ws);\r
+        \r
+        AlphaState as1 = displaySystem.getRenderer().createAlphaState();\r
+        as1.setBlendEnabled(true);\r
+        as1.setSrcFunction(AlphaState.SB_SRC_ALPHA);\r
+        as1.setDstFunction(AlphaState.DB_ONE);\r
+        as1.setTestEnabled(true);\r
+        as1.setTestFunction(AlphaState.TF_GREATER);\r
+        as1.setEnabled(true);\r
+        \r
+        TextureState font = displaySystem.getRenderer().createTextureState();\r
+        /** The texture is loaded from fontLocation */\r
+        font.setTexture(loadFontTexture());\r
+\r
+        font.setEnabled(true);\r
+\r
+        // Then our font Text object.\r
+        /** This is what will actually have the text at the bottom. */\r
+        fps = new Text("FPS label", "");\r
+        fps.setCullMode(Spatial.CULL_NEVER);\r
+        fps.setTextureCombineMode(TextureState.REPLACE);\r
+        \r
+        debug = new Text("Debug", "Debug");\r
+        debug.setCullMode(Spatial.CULL_NEVER);\r
+        debug.setTextureCombineMode(TextureState.REPLACE);\r
+        debug.setLocalTranslation(new Vector3f(1.f,10.f,0.f));\r
+\r
+        // Finally, a stand alone node (not attached to root on purpose)\r
+        Node fpsNode = new Node("FPS node");\r
+        fpsNode.attachChild(fps);\r
+        fpsNode.attachChild(debug);\r
+        fpsNode.setRenderState(font);\r
+        fpsNode.setRenderState(as1);\r
+        fpsNode.setCullMode(Spatial.CULL_NEVER);\r
+        orthoNode.attachChild(fpsNode);\r
+        \r
+        rootNode.updateGeometricState(0.0f, true);\r
+        rootNode.updateRenderState();\r
+        \r
+        orthoNode.updateGeometricState(0.0f, true);\r
+        orthoNode.updateRenderState();\r
+        if (Activator.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.SHADOWS)) {\r
+               ShadowedRenderPass shadowRootPass = new ShadowedRenderPass();\r
+               shadowRootPass.add(shadowRootNode);\r
+               shadowRootPass.add(noCastShadowRootNode);\r
+               shadowRootPass.addOccluder(shadowRootNode);\r
+               pManager.add(shadowRootPass);\r
+               //rootPass.setRenderShadows(false);\r
+               shadowRootPass.setShadowColor(new ColorRGBA(0.1f,0.1f,0.1f,0.9f));\r
+               shadowRootPass.setLightingMethod(ShadowedRenderPass.MODULATIVE);\r
+               RenderPass rootPass = new RenderPass();\r
+               rootPass.add(noShadowRootNode);\r
+               pManager.add(rootPass);\r
+        } else {\r
+               RenderPass rootPass = new RenderPass();\r
+               rootPass.add(rootNode);\r
+               pManager.add(rootPass);\r
+        }\r
+               \r
+               String postProcess = Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.POST_PROCESS);\r
+               if (postProcess.startsWith("bloom")) {\r
+                       BloomRenderPass bloomRenderPass = new BloomRenderPass(cam, 4);\r
+                       if (bloomRenderPass.isSupported()) {\r
+                               bloomRenderPass.add(rootNode);\r
+                               bloomRenderPass.setUseCurrentScene(false);\r
+                               pManager.add(bloomRenderPass);\r
+                       }\r
+               } else if (postProcess.startsWith("sketch")) {\r
+                       SketchRenderPass sketchRenderPass = new SketchRenderPass(cam, 4);\r
+                       if (sketchRenderPass.isSupported()) {\r
+                               sketchRenderPass.add(rootNode);\r
+                               pManager.add(sketchRenderPass);\r
+                       }\r
+               }\r
+\r
+               \r
+               RenderPass fpsPass = new RenderPass();\r
+               fpsPass.add(orthoNode);\r
+               pManager.add(fpsPass);\r
+       }\r
+       \r
+       public void render() {\r
+               displaySystem.setCurrent();\r
+                /** Recalculate the framerate. */\r
+        timer.update();\r
+        \r
+          /** Update tpf to time per frame according to the Timer. */\r
+        float tpf = timer.getTimePerFrame();\r
+        /** Send the fps to our fps bar at the bottom. */\r
+        fps.print("FPS: " + (int) timer.getFrameRate() + " - "\r
+                + displaySystem.getRenderer().getStatistics());\r
+        /**\r
+         * Update the physics for this world.\r
+         */\r
+        debug.print(debugText);\r
+\r
+        /** Update controllers/render states/transforms/bounds for rootNode. */\r
+        rootNode.updateGeometricState(tpf, true);\r
+        rootNode.updateRenderState();\r
+       \r
+        orthoNode.updateGeometricState(tpf, true);\r
+        orthoNode.updateRenderState();\r
+        \r
+        displaySystem.getRenderer().clearStatistics();\r
+        /** Clears the previously rendered information. */\r
+        displaySystem.getRenderer().clearBuffers();\r
+\r
+        pManager.updatePasses(tpf);\r
+        \r
+        pManager.renderPasses(displaySystem.getRenderer());\r
+        if ( showBounds ) {\r
+            Debugger.drawBounds( shadowRootNode, displaySystem.getRenderer(), true );\r
+        }\r
+\r
+        if ( showNormals ) {\r
+            Debugger.drawNormals( shadowRootNode, displaySystem.getRenderer());\r
+        }\r
+        displaySystem.getRenderer().displayBackBuffer();\r
+        \r
+        \r
+        \r
+        //swap buffers\r
+        ((SWTRenderer)displaySystem.getRenderer()).swap();\r
+       }\r
+       \r
+       @Override\r
+       public void resize(int width, int height) {\r
+               updateProjection();\r
+       }\r
+       \r
+       @Override\r
+       public Node getShadowRoot() {\r
+               return shadowRootNode;\r
+       }\r
+       \r
+       @Override\r
+       public Node getNoCastRoot() {\r
+               return noCastShadowRootNode;\r
+       }\r
+       \r
+       @Override\r
+       public Node getRoot() {\r
+               return rootNode;\r
+       }\r
+       \r
+       @Override\r
+       public Node getOrthoNode() {\r
+               return orthoNode;\r
+       }\r
+       \r
+       @Override\r
+       public Node getNoShadowRoot() {\r
+               return noShadowRootNode;\r
+       }\r
+       \r
+//     public void setRootNode(Node node) {\r
+//             rootNode = node;\r
+//             initRoot();\r
+//     }\r
+       \r
+       @Override\r
+       public int getProjectionPolicy() {\r
+               return projectionPolicy;\r
+       }\r
+       \r
+       @Override\r
+       public void setProjectionPolicy(int policy) {\r
+               if (policy != projectionPolicy) {\r
+                       projectionPolicy = policy;\r
+                       updateProjection();\r
+               }\r
+       }\r
+       \r
+       private void updateProjection() {\r
+               switch (projectionPolicy) {\r
+               case PERSPECTIVE_PROJECTION:\r
+                       cam.setParallelProjection(false);\r
+                       cam.setFrustumPerspective(fov,\r
+                       (float) displaySystem.getRenderer().getWidth() /\r
+                       (float) displaySystem.getRenderer().getHeight(),near, far);\r
+                       break;\r
+                       \r
+               case PARALLEL_PROJECTION:\r
+                       cam.setParallelProjection(true);\r
+                       break;\r
+               }\r
+               cam.update();\r
+               projectionUpdated = true;\r
+       }\r
+       \r
+       @Override\r
+       public float getScreenScale() {\r
+               //System.out.println(cam.getFrustumLeft() + " " + cam.getFrustumRight() + " " + cam.getFrustumBottom() + " " + cam.getFrustumTop()+ " " + cam.getFrustumNear() + " " + cam.getFrustumFar());\r
+               return Math.abs(cam.getFrustumTop());\r
+       }\r
+       \r
+       @Override\r
+       public void setScreenScale(float screenScale) {\r
+               float aspect = (float) displaySystem.getRenderer().getWidth() /\r
+        (float) displaySystem.getRenderer().getHeight();\r
+               cam.setFrustum(-screenScale*8.f, cam.getFrustumFar(), -screenScale*aspect, screenScale*aspect, -screenScale, screenScale);\r
+       }\r
+       \r
+       @Override\r
+       public float getFieldOfView() {\r
+               return fov;\r
+       }\r
+       \r
+       @Override\r
+       public void dispose() {\r
+               pManager.cleanUp();\r
+               rootNode.dispose();\r
+               rootNode = null;\r
+               noShadowRootNode = null;\r
+               noCastShadowRootNode = null;\r
+               orthoNode = null;\r
+               shadowRootNode = null;\r
+       }\r
+       \r
+       @Override\r
+       public boolean update() {\r
+               if (!projectionUpdated) {\r
+                       return false;\r
+               }\r
+               projectionUpdated = false;\r
+               return true;\r
+       }\r
+       \r
+       @Override\r
+       public Camera getCamera() {\r
+               return cam;\r
+       }\r
+       \r
+       @Override\r
+       public DisplaySystem getDisplaySystem() {\r
+               return displaySystem;\r
+       }\r
+       \r
+       public void setDebugText(String text) {\r
+               this.debugText = text;\r
+               //System.out.println("JmeSinglePass.setDebugText() " + text);\r
+       }\r
+       \r
+       public void setShowNormals(boolean b) {\r
+               showNormals = b;\r
+       }\r
+       \r
+       public void setShowBounds(boolean b) {\r
+               showBounds = b;\r
+       }\r
+       \r
+       public void setShowWireframe(boolean b) {\r
+               ws.setEnabled(b);\r
+       }\r
+       \r
+       public boolean isShowNormals() {\r
+               return showNormals;\r
+       }\r
+       \r
+       public boolean isShowBounds() {\r
+               return showBounds;\r
+       }\r
+       \r
+       public boolean isShowWireframe() {\r
+               return ws.isEnabled();\r
+       }\r
+       \r
+       \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/OrbitalCamera.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/OrbitalCamera.java
new file mode 100644 (file)
index 0000000..4b0aa6f
--- /dev/null
@@ -0,0 +1,205 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.common;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Matrix3d;\r
+import javax.vecmath.Vector3d;\r
+\r
+import org.simantics.proconf.g3d.base.VecmathJmeTools;\r
+\r
+import com.jme.renderer.Camera;\r
+\r
+\r
+/**\r
+ * Orbital camera\r
+ * <p>\r
+ * Modified version of fi.vtt.proconf.webmon.graphics3d.utils.OrbitalCamera<br>\r
+ *  Using floats instead of double<br>\r
+ * </p>\r
+ * \r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class OrbitalCamera {\r
+    \r
+    private Vector3d up = new Vector3d(0.0,1.0,0.0);\r
+    private static Vector3d up2 = new Vector3d(0.0,0.0,-1.0);\r
+    private static double minDistance = 0.5;\r
+    private Vector3d target = new Vector3d();\r
+    private Vector3d cameraPos = new Vector3d(10.0,0.0,0.0);\r
+    \r
+    \r
+    public void translate(Vector3d v) {\r
+        target.add(v);\r
+        cameraPos.add(v);\r
+    }\r
+    \r
+    public void rotateAroundTarget(Vector3d axis, double angle) {\r
+        Vector3d temp = new Vector3d(cameraPos);\r
+        temp.sub(target);\r
+        Matrix3d rotation = new Matrix3d();\r
+        rotation.set(new AxisAngle4d(axis,angle));\r
+        rotation.transform(temp);\r
+        temp.add(target);\r
+        cameraPos.set(temp);      \r
+    }\r
+    \r
+    public Vector3d getUnNormalizedHeading() {\r
+        Vector3d heading = new Vector3d(target);\r
+        heading.sub(cameraPos);\r
+        return heading;\r
+    }\r
+    \r
+    public Vector3d getUnNormalizedRight() {\r
+        Vector3d heading = getUnNormalizedHeading();\r
+        Vector3d right = new Vector3d();\r
+        right.cross(heading,up);\r
+        if (right.lengthSquared() < 0.01)\r
+            right.cross(heading,up2);\r
+        return right;\r
+    }\r
+    \r
+    public double getDistanceToTarget() {\r
+        Vector3d t = new Vector3d(target);\r
+        t.sub(cameraPos);\r
+        return t.length();\r
+    }\r
+    \r
+    public void moveToTarget(double distance) {\r
+        Vector3d heading = getUnNormalizedHeading();\r
+        double length = heading.length();\r
+        if (length + distance < minDistance) {\r
+            // cannot move closer\r
+            return;\r
+        }\r
+        heading.scale(distance / length); //normalizing and scaling by distance\r
+        cameraPos.add(heading);\r
+    }\r
+    \r
+    public void moveScaledToTarget(double s) {\r
+        Vector3d heading = getUnNormalizedHeading();\r
+        double currentLength = heading.length();\r
+        double length = currentLength * (1.0 - s);// heading.length();\r
+        if (length < minDistance) {\r
+           s = -minDistance / currentLength + 1.0;\r
+        }\r
+        heading.scale(s);\r
+         //normalizing and scaling by distance\r
+        cameraPos.add(heading);\r
+    }\r
+    \r
+    public void rotateUp(double angle) {\r
+        Vector3d right = getUnNormalizedRight();\r
+        double length = right.length();\r
+        // TODO : better handling of singular cases\r
+        if (length > 0.01)\r
+            right.scale(1.0/length);\r
+        else \r
+            right.set(-1.0,0.0,0.0);\r
+        rotateAroundTarget(right,angle);\r
+    }\r
+    \r
+    public void rotateRight(double angle) {\r
+        rotateAroundTarget(up,angle);\r
+    }\r
+    \r
+    public void moveRight(double length) {\r
+        Vector3d right = getUnNormalizedRight();\r
+        right.normalize();\r
+        right.scale(length);\r
+        translate(right);\r
+    }\r
+    \r
+    public void moveUp(double length) {\r
+        Vector3d u = new Vector3d(up);\r
+        u.scale(length);\r
+        translate(u);\r
+    }\r
+    \r
+    public void moveFront(double length) {\r
+        Vector3d right = getUnNormalizedRight();\r
+        Vector3d front = new Vector3d();\r
+        front.cross(up,right);\r
+        front.normalize();\r
+        front.scale(length);\r
+        translate(front);\r
+    }\r
+    \r
+    public void updateCamera() {\r
+       Vector3d t = new Vector3d(cameraPos);\r
+       t.sub(target);\r
+       t.normalize();\r
+       cam.setLocation(VecmathJmeTools.get(cameraPos));\r
+       \r
+       if (Math.abs(t.dot(up)) > 0.99) {\r
+               cam.lookAt(VecmathJmeTools.get(target), VecmathJmeTools.get(up2));      \r
+       } else {\r
+               cam.lookAt(VecmathJmeTools.get(target), VecmathJmeTools.get(up));\r
+       }\r
+       cam.update();\r
+       cam.apply();\r
+       \r
+    }\r
+\r
+    /**\r
+     * @return Returns the cameraPos.\r
+     */\r
+    public Vector3d getCameraPos() {\r
+        return cameraPos;\r
+    }\r
+\r
+    /**\r
+     * @param cameraPos The cameraPos to set.\r
+     */\r
+    public void setCameraPos(Vector3d cameraPos) {\r
+        this.cameraPos = cameraPos;\r
+    }\r
+\r
+    /**\r
+     * @return Returns the target.\r
+     */\r
+    public Vector3d getTarget() {\r
+        return target;\r
+    }\r
+\r
+    /**\r
+     * @param target The target to set.\r
+     */\r
+    public void setTarget(Vector3d target) {\r
+        this.target = target;\r
+    }\r
+    \r
+    public void setCameraPosRelativeToTarget(Vector3d targetToCam) {\r
+        targetToCam.add(target);\r
+        setCameraPos(targetToCam);\r
+    }\r
+    \r
+    public void setUp(Vector3d v) {\r
+        up.set(v);\r
+    }\r
+    \r
+    public Vector3d getUp() {\r
+        return up;\r
+    }\r
+    \r
+    public void setDefaultUp() {\r
+        up.set(0.0,1.0,0.0);\r
+    }\r
+    \r
+    private Camera cam;\r
+    \r
+    public void setCamera(Camera cam) {\r
+       this.cam = cam;\r
+    }\r
+    \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/PropertyTester2.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/PropertyTester2.java
new file mode 100644 (file)
index 0000000..0f57f7a
--- /dev/null
@@ -0,0 +1,18 @@
+package org.simantics.proconf.g3d.common;\r
+\r
+import org.eclipse.core.expressions.PropertyTester;\r
+\r
+public class PropertyTester2 extends PropertyTester {\r
+\r
+       public PropertyTester2() {\r
+               // TODO Auto-generated constructor stub\r
+       }\r
+\r
+       @Override\r
+       public boolean test(Object receiver, String property, Object[] args,\r
+                       Object expectedValue) {\r
+               // TODO Auto-generated method stub\r
+               return false;\r
+       }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/StructuredResourceSelection.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/StructuredResourceSelection.java
new file mode 100644 (file)
index 0000000..a13062a
--- /dev/null
@@ -0,0 +1,173 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.common;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.simantics.db.Resource;\r
+\r
+\r
+/**\r
+ * StructuredSelection that contains ResourceSelections\r
+ * \r
+ * @author Marko Luukkainen\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class StructuredResourceSelection implements IStructuredSelection {\r
+    \r
+    public static final StructuredResourceSelection EMPTY = new StructuredResourceSelection() {\r
+        // Create an empty fixed size List to ensure the list is not modified.\r
+        private List<Resource> empty = Arrays.asList(); \r
+        \r
+        public void add(Resource rs) {\r
+            throw new UnsupportedOperationException("BUG: attempted to modify StructuredResourceSelection.EMPTY");\r
+        }\r
+        public List<Resource> getSelectionList() {\r
+            return empty;\r
+        }\r
+    };\r
+\r
+    private List<Resource> selections;\r
+    \r
+    /**\r
+     * Creates a new selection that doesn't contain any items\r
+     */\r
+    public StructuredResourceSelection() {\r
+    }\r
+\r
+    public StructuredResourceSelection(Resource rs) {\r
+        getSelectionList().add(rs);\r
+    }\r
+\r
+    public StructuredResourceSelection(Resource... rss) {\r
+        List<Resource> s = getSelectionList();\r
+        for (Resource rs : rss)\r
+            s.add(rs);\r
+    }\r
+\r
+    public void add(Resource rs) {\r
+        getSelectionList().add(rs);\r
+    }\r
+\r
+    public List<Resource> getSelectionList() {\r
+        if (selections == null) {\r
+            selections = new ArrayList<Resource>();\r
+        }\r
+        return selections;\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.ISelection#isEmpty()\r
+     */\r
+    public boolean isEmpty() {\r
+        return selections == null || selections.isEmpty();\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.IStructuredSelection#getFirstElement()\r
+     */\r
+    public Object getFirstElement() {\r
+        if (!isEmpty())\r
+            return selections.get(0);\r
+        return null;\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.IStructuredSelection#iterator()\r
+     */\r
+    public Iterator<Resource> iterator() {\r
+        return getSelectionList().iterator();\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.IStructuredSelection#size()\r
+     */\r
+    public int size() {\r
+        return selections == null ? 0 : selections.size();\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.IStructuredSelection#toArray()\r
+     */\r
+    public Object[] toArray() {\r
+        return selections == null ? new Object[0] : selections.toArray();\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.jface.viewers.IStructuredSelection#toList()\r
+     */\r
+    public List<Resource> toList() {\r
+        return selections == null ? Arrays.asList(new Resource[0]) : selections;\r
+    }\r
+\r
+    /**\r
+     * Returns whether this structured selection is equal to the given object.\r
+     * Two structured selections are equal iff they contain the same elements\r
+     * in the same order.\r
+     *\r
+     * @param o the other object\r
+     * @return <code>true</code> if they are equal, and <code>false</code> otherwise\r
+     */\r
+    public boolean equals(Object o) {\r
+        if (this == o) {\r
+            return true;\r
+        }\r
+        // null and other classes\r
+        if (!(o instanceof StructuredResourceSelection)) {\r
+            return false;\r
+        }\r
+        StructuredResourceSelection other = (StructuredResourceSelection) o;\r
+\r
+        // either or both empty?\r
+        if (isEmpty()) {\r
+            return other.isEmpty();\r
+        }\r
+        if (other.isEmpty()) {\r
+            return false;\r
+        }\r
+\r
+        // check size\r
+        if (size() != other.size())\r
+            return false;\r
+        \r
+        // element comparison\r
+        Iterator<Resource> it = iterator();\r
+        Iterator<Resource> otherIt = other.iterator();\r
+        while (it.hasNext()) {\r
+            if (!it.next().equals(otherIt.next()))\r
+                return false;\r
+        }\r
+        \r
+        return true;\r
+    }\r
+    \r
+    @Override\r
+    public String toString() {\r
+       return Arrays.toString(getSelectionList().toArray());\r
+    }\r
+    \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/dialogs/JMEDialog.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/dialogs/JMEDialog.java
new file mode 100644 (file)
index 0000000..9e2950d
--- /dev/null
@@ -0,0 +1,174 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.dialogs;\r
+\r
+import org.eclipse.jface.dialogs.Dialog;\r
+import org.eclipse.jface.dialogs.IDialogConstants;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.MouseAdapter;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.RGB;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.ColorDialog;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Shell;\r
+\r
+public class JMEDialog extends Dialog {\r
+       private boolean bounds;\r
+       private boolean normals;\r
+       private boolean wireframe;\r
+       private float[] floatColor = null;\r
+       private Button boundsButton;\r
+       private Button normalsButton;\r
+       private Button wireframeButton;\r
+       private Composite colorComposite;\r
+       private Color color = null;\r
+       \r
+       public JMEDialog(Shell parentShell) {\r
+               super(parentShell);\r
+       }\r
+\r
+       \r
+       @Override\r
+       protected void configureShell(Shell newShell) {\r
+               super.configureShell(newShell);\r
+               newShell.setText("Configure new pipeline");\r
+       }\r
+       \r
+       @Override\r
+       protected Control createDialogArea(Composite parent) {\r
+               Composite composite = (Composite) super.createDialogArea(parent);\r
+               Label label = new Label(composite, SWT.WRAP);\r
+        label.setText("JME Configuration");\r
+        GridData data = new GridData(GridData.GRAB_HORIZONTAL\r
+                | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL\r
+                | GridData.VERTICAL_ALIGN_CENTER);\r
+               \r
+        data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);\r
+        boundsButton = new Button(composite,SWT.CHECK);\r
+        boundsButton.setText("Show bounds");\r
+        boundsButton.addSelectionListener(new SelectionAdapter() {\r
+               @Override\r
+               public void widgetSelected(SelectionEvent e) {\r
+                       bounds = boundsButton.getSelection();\r
+               }\r
+        });\r
+        boundsButton.setSelection(bounds);\r
+        normalsButton = new Button(composite,SWT.CHECK);\r
+        normalsButton.setText("Show normals");\r
+        normalsButton.addSelectionListener(new SelectionAdapter() {\r
+               @Override\r
+               public void widgetSelected(SelectionEvent e) {\r
+                       normals = normalsButton.getSelection();\r
+               }\r
+        });\r
+        normalsButton.setSelection(normals);\r
+        wireframeButton = new Button(composite,SWT.CHECK);\r
+        wireframeButton.setText("Show wireframe");\r
+        wireframeButton.addSelectionListener(new SelectionAdapter() {\r
+               @Override\r
+               public void widgetSelected(SelectionEvent e) {\r
+                       wireframe = wireframeButton.getSelection();\r
+               }\r
+        });\r
+        wireframeButton.setSelection(wireframe);\r
+        \r
+        colorComposite = new Composite(composite,SWT.BORDER);\r
+        colorComposite.addMouseListener(new MouseAdapter() {\r
+               @Override\r
+               public void mouseUp(MouseEvent e) {\r
+                       ColorDialog dialog = new ColorDialog(JMEDialog.this.getShell());\r
+                       RGB rgb = dialog.open();\r
+                       if (rgb != null) {\r
+                               if (color != null)\r
+                                       color.dispose();\r
+                               color = new Color(JMEDialog.this.getShell().getDisplay(),rgb);\r
+                               colorComposite.setBackground(color);\r
+                               floatColor = new float[]{rgb.red/255.f,rgb.green/255.f,rgb.blue/255.f};\r
+                       }\r
+               }\r
+        });\r
+               updateColor();\r
+               \r
+               return composite;\r
+       }\r
+       \r
+       @Override\r
+       public int open() {\r
+               return super.open();\r
+       }\r
+\r
+\r
+       public boolean isBounds() {\r
+               return bounds;\r
+       }\r
+\r
+\r
+       public void setBounds(boolean bounds) {\r
+               this.bounds = bounds;\r
+       }\r
+\r
+\r
+       public boolean isNormals() {\r
+               return normals;\r
+       }\r
+\r
+\r
+       public void setNormals(boolean normals) {\r
+               this.normals = normals;\r
+       }\r
+\r
+\r
+       public boolean isWireframe() {\r
+               return wireframe;\r
+       }\r
+\r
+\r
+       public void setWireframe(boolean wireframe) {\r
+               this.wireframe = wireframe;\r
+       }\r
+       \r
+       \r
+       public float[] getFloatColor() {\r
+               return floatColor;\r
+       }\r
+\r
+       public void setFloatColor(float[] c) {\r
+               this.floatColor = c;\r
+               if (floatColor == null)\r
+                       return;\r
+               \r
+               updateColor();\r
+       }\r
+       \r
+       private void updateColor() {\r
+               if (colorComposite == null)\r
+                       return;\r
+               if (color != null)\r
+                       color.dispose();\r
+               RGB rgb = new RGB((int)(floatColor[0]*255.f),(int)(floatColor[1]*255.f),(int)(floatColor[2]*255.f));\r
+               color = new Color(JMEDialog.this.getShell().getDisplay(),rgb);\r
+               colorComposite.setBackground(color);\r
+       }\r
+\r
+       \r
+\r
+\r
+       \r
+       \r
+       \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/dnd/DropListener.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/dnd/DropListener.java
new file mode 100644 (file)
index 0000000..70e9610
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.dnd;\r
+\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
+\r
+\r
+\r
+public interface DropListener {\r
+       \r
+       boolean acceptDrop(StructuredResourceSelection s, Resource res[]);\r
+       void doDrop(StructuredResourceSelection s, Resource res[]);\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/dnd/ShapeDropTarget.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/dnd/ShapeDropTarget.java
new file mode 100644 (file)
index 0000000..fe832e6
--- /dev/null
@@ -0,0 +1,124 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.dnd;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.eclipse.swt.dnd.DND;\r
+import org.eclipse.swt.dnd.DropTarget;\r
+import org.eclipse.swt.dnd.DropTargetEvent;\r
+import org.eclipse.swt.dnd.DropTargetListener;\r
+import org.eclipse.swt.dnd.TextTransfer;\r
+import org.eclipse.swt.dnd.Transfer;\r
+import org.eclipse.swt.dnd.TransferData;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
+import org.simantics.proconf.ui.dnd.ResourceReferenceTransfer;\r
+\r
+public class ShapeDropTarget implements DropTargetListener{\r
+       ThreeDimensionalEditorBase editor;\r
+       List<DropListener> listeners;\r
+       final Control control;\r
+    private DropTarget target; \r
+    \r
+       public ShapeDropTarget(ThreeDimensionalEditorBase editor) {\r
+               this.editor = editor;\r
+               listeners = new ArrayList<DropListener>();\r
+               this.control = editor.getRenderingComposite();\r
+        \r
+        target = new DropTarget(control, DND.DROP_LINK);\r
+        target.setTransfer(new Transfer[] { ResourceReferenceTransfer.getInstance() });\r
+        target.addDropListener(this);  \r
+       }\r
+       \r
+       public void addDropListener(DropListener listener) {\r
+               listeners.add(listener);\r
+       }\r
+       \r
+       public void removeDropListener(DropListener listener) {\r
+               listeners.remove(listener);\r
+       }\r
+       \r
+       @Override\r
+       public void dragEnter(DropTargetEvent event) {\r
+               event.detail = DND.DROP_LINK;\r
+               dragOver(event);\r
+       }\r
+       \r
+       public void dragOperationChanged(DropTargetEvent event) {\r
+    }\r
+       \r
+       public void dropAccept(DropTargetEvent event) {\r
+    }\r
+       \r
+       public void dragLeave(DropTargetEvent event) {\r
+    }\r
+\r
+       \r
+       @Override\r
+       public void dragOver(DropTargetEvent event) {\r
+               // FIXME : a hack to get the actual data (probably works only in Windows)\r
+               TransferData data = event.currentDataType;\r
+               if(!TextTransfer.getInstance().isSupportedType(data))\r
+                       return;\r
+               Object o = TextTransfer.getInstance().nativeToJava(data);\r
+               \r
+               Point p = getLocalCoords(event);\r
+               editor.getInputProvider().setMouseMoved(true);\r
+               editor.getInputProvider().setMouseX(p.x);\r
+               editor.getInputProvider().setMouseY(p.y);\r
+               editor.run();\r
+               StructuredResourceSelection sel = editor.getSelectionAdapter().getHighlightSelection();\r
+               \r
+               event.data = o;\r
+               Resource ids[] = parseEventData(event);\r
+               for (DropListener l : listeners) {\r
+                       if(l.acceptDrop(sel, ids)) {\r
+                               event.detail = DND.DROP_LINK;\r
+                               return;\r
+                       }\r
+               }\r
+               event.detail = DND.DROP_NONE;           \r
+       }\r
+       \r
+       @Override\r
+       public void drop(DropTargetEvent event) {\r
+               StructuredResourceSelection sel = editor.getSelectionAdapter().getHighlightSelection();\r
+               Resource ids[] = parseEventData(event);\r
+               for (DropListener l : listeners) {\r
+                       if(l.acceptDrop(sel, ids)) {\r
+                               l.doDrop(sel, ids);\r
+                               return;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       protected Point getLocalCoords(DropTargetEvent event) {\r
+               return editor.getRenderingComposite().toControl(event.x, event.y);\r
+       }\r
+       \r
+       public void dispose()\r
+    {\r
+        target.removeDropListener(this);\r
+        target = null;\r
+    }\r
+       \r
+       private Resource[] parseEventData(DropTargetEvent event) {\r
+        if (ResourceReferenceTransfer.getInstance().isSupportedType(event.currentDataType) && (event.data instanceof Resource[])) {\r
+            return (Resource[]) event.data;\r
+        }\r
+        return null;\r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/AbstractGizmo.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/AbstractGizmo.java
new file mode 100644 (file)
index 0000000..e6f7b61
--- /dev/null
@@ -0,0 +1,198 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.gizmo;\r
+\r
+import javax.vecmath.AxisAngle4f;\r
+import javax.vecmath.Color4f;\r
+import javax.vecmath.Quat4f;\r
+import javax.vecmath.Tuple3d;\r
+import javax.vecmath.Tuple3f;\r
+import javax.vecmath.Vector3d;\r
+import javax.vecmath.Vector3f;\r
+\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.base.JmeRenderingComponent;\r
+import org.simantics.proconf.g3d.base.VecmathJmeTools;\r
+import org.simantics.proconf.g3d.preferences.PreferenceConstants;\r
+\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.Node;\r
+\r
+\r
+public abstract class AbstractGizmo implements Gizmo{\r
+    \r
+       private Node position;\r
+       private Node rotate;\r
+       private Node scale;\r
+       \r
+    private boolean changed = false;\r
+    \r
+    private double userScale = 1.0;\r
+    \r
+    public AbstractGizmo() {\r
+        createGroups();\r
+    }\r
+    \r
+    public void setChanged(boolean b) {\r
+        changed = b;\r
+    }\r
+    \r
+    public boolean isChanged() {\r
+        return changed;\r
+    }\r
+    \r
+    public double getUserScale() {\r
+       return Activator.getDefault().getPreferenceStore().getDouble(PreferenceConstants.GIZMO_SCALE);\r
+    }\r
+    \r
+    \r
+    public void setScale(float scale) {\r
+        this.scale.setLocalScale(scale);\r
+    }\r
+    \r
+    public void setScale(Vector3f scale) {\r
+        this.scale.setLocalScale(VecmathJmeTools.get(scale));\r
+    }\r
+    \r
+    public Vector3d getPosition() {\r
+       return VecmathJmeTools.getD(position.getWorldTranslation());\r
+    }\r
+    \r
+    public Vector3f getPositionFloat() {\r
+        return VecmathJmeTools.get(position.getWorldTranslation());\r
+    }\r
+    \r
+    public void setPosition(Tuple3d position) {\r
+        this.position.setLocalTranslation(VecmathJmeTools.get(position));\r
+    }\r
+    \r
+    public void setPosition(Vector3f position) {\r
+       this.position.setLocalTranslation(VecmathJmeTools.get(position));\r
+    }\r
+    \r
+    public void setRotation(Quat4f q) {\r
+       rotate.setLocalRotation(VecmathJmeTools.get(q));\r
+    }\r
+    \r
+    public void setRotation(AxisAngle4f q) {\r
+        rotate.setLocalRotation(VecmathJmeTools.get(q));\r
+    }\r
+    \r
+    public Node getNode() {\r
+       userScale = getUserScale();\r
+       return position;\r
+    }\r
+    \r
+    protected Node getGizmoNode() {\r
+       return scale;\r
+    }\r
+    \r
+    private void createGroups() {\r
+\r
+       position = new Node();\r
+       rotate = new Node();\r
+       scale = new Node();\r
+       position.attachChild(rotate);\r
+       rotate.attachChild(scale);\r
+       position.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+    }\r
+\r
+    public void update(Tuple3d position, Tuple3d cameraPosition, JmeRenderingComponent component) {\r
+        setPosition(position);\r
+        com.jme.math.Vector3f p = VecmathJmeTools.get(position);\r
+        p.subtractLocal(VecmathJmeTools.get(cameraPosition));\r
+        rotate.getLocalRotation().inverse().multLocal(p);\r
+        if (component.getProjectionPolicy() == JmeRenderingComponent.PERSPECTIVE_PROJECTION) {\r
+\r
+            double distance = p.length();\r
+            // (bug caused in Xith->JME translation ?)\r
+            p.negateLocal();\r
+            double fov = component.getFieldOfView();\r
+            float s = (float) (Math.sin(fov) * distance * 0.1); // scaling factor was 0.2 with Xith\r
+            s *= (float)userScale;\r
+            Vector3f scale = new Vector3f(1.f, 1.f, 1.f);\r
+            \r
+            if (p.x > 0.f)\r
+                scale.x = -1.f;\r
+            if (p.y > 0.f)\r
+                scale.y = -1.f;\r
+            if (p.z > 0.f)\r
+                scale.z = -1.f;\r
+            scale.scale(s);\r
+            setScale(scale);\r
+        } else {\r
+            Vector3f scale = new Vector3f(1.f, 1.f, 1.f);\r
+            float s = component.getScreenScale() / 5.f;\r
+            s *= (float)userScale;\r
+            if (p.x > 0.f)\r
+                scale.x = -1.f;\r
+            if (p.y > 0.f)\r
+                scale.y = -1.f;\r
+            if (p.z > 0.f)\r
+                scale.z = -1.f;\r
+            scale.scale(s);\r
+            setScale(scale);\r
+\r
+        }\r
+    }\r
+\r
+    public void update(Tuple3d cameraPosition, JmeRenderingComponent component) {\r
+\r
+       com.jme.math.Vector3f p = VecmathJmeTools.get(getPosition());\r
+        p.subtractLocal(VecmathJmeTools.get(cameraPosition));\r
+        rotate.getLocalRotation().inverse().multLocal(p);\r
+        if (component.getProjectionPolicy() == JmeRenderingComponent.PERSPECTIVE_PROJECTION) {\r
+\r
+            double distance = p.length();\r
+            double fov = component.getFieldOfView();\r
+            float s = (float)(Math.sin(fov) * distance * 0.1); // scaling factor was 0.2 with Xith\r
+            s *= (float)userScale;\r
+            Vector3f scale = new Vector3f(1.f,1.f,1.f);\r
+            if (p.x > 0.f)\r
+                scale.x = -1.f;\r
+            if (p.y > 0.f)\r
+                scale.y = -1.f;\r
+            if (p.z > 0.f)\r
+                scale.z = -1.f;\r
+            scale.scale(s);\r
+            setScale(scale);\r
+        } else {\r
+            \r
+            Vector3f scale = new Vector3f(1.f,1.f,1.f);\r
+            float s = component.getScreenScale()/5.f;\r
+            s *= (float)userScale;\r
+            if (p.x > 0.f)\r
+                scale.x = -1.f;\r
+            if (p.y > 0.f)\r
+                scale.y = -1.f;\r
+            if (p.z > 0.f)\r
+                scale.z = -1.f;\r
+            scale.scale(s);\r
+            setScale(scale);\r
+            \r
+        }\r
+    }\r
+    \r
+    protected void setCoordinate(float array[], int index, Tuple3f c) {\r
+       index *= 3;\r
+       array[index++] = c.x;\r
+       array[index++] = c.y;\r
+       array[index] = c.z;\r
+    }\r
+    \r
+    protected void setColor(float array[], int index, Color4f c) {\r
+       index *= 4;\r
+       array[index++] = c.x;\r
+       array[index++] = c.y;\r
+       array[index++] = c.z;\r
+       array[index] = c.w;\r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/Gizmo.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/Gizmo.java
new file mode 100644 (file)
index 0000000..0e791ca
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.gizmo;\r
+\r
+import com.jme.scene.Node;\r
+\r
+/**\r
+ * Interface for gizmos, interactive components in the scene-graph.\r
+ * \r
+ * @author Marko Luukkainen <Marko.Luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public interface Gizmo {\r
+\r
+       /**\r
+        * Must return unique identifier for this gizmo\r
+        * @return\r
+        */\r
+    public abstract String getPickPrefix();\r
+\r
+    /**\r
+     * Sets selected component (where mouse is hovering) by using its name.\r
+     * Name includes pick prefix\r
+     * @param name\r
+     */\r
+    public abstract void setSelected(String name);\r
+\r
+    /**\r
+     * Returns root-node of the gizmo. It is used for inserting the gizmo into scenegraph.\r
+     * @return\r
+     */\r
+    public abstract Node getNode();\r
+    \r
+    /**\r
+     * Returns true if gizmo needs to be redrawn.\r
+     * @return\r
+     */\r
+    public boolean isChanged();\r
+    \r
+    public void setChanged(boolean b);\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/MultiSelectionGizmo.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/MultiSelectionGizmo.java
new file mode 100644 (file)
index 0000000..b73b886
--- /dev/null
@@ -0,0 +1,110 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.gizmo;\r
+\r
+import java.nio.FloatBuffer;\r
+\r
+import javax.vecmath.Color4f;\r
+\r
+import org.simantics.proconf.g3d.base.VecmathJmeTools;\r
+\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.scene.TriMesh;\r
+import com.jme.util.geom.BufferUtils;\r
+\r
+\r
+\r
+public abstract class MultiSelectionGizmo extends AbstractGizmo {\r
+    \r
+    public static final int UNSELECTED = 0;\r
+    public static final int SELECTED = 1;\r
+\r
+       private TriMesh geoms[] = new TriMesh[4];\r
+       private ColorRGBA colors[][] = new ColorRGBA[4][2];\r
+   \r
+\r
+    private boolean selected[];\r
+    \r
+    \r
+    private int selectedIndex = -1;\r
+    \r
+    \r
+    public MultiSelectionGizmo() {\r
+        super();\r
+\r
+        colors = new ColorRGBA[getCount()][2];\r
+        geoms = new TriMesh[getCount()];\r
+        selected = new boolean[getCount()];\r
+        for (int i = 0; i < selected.length; i++) {\r
+            selected[i] = false;\r
+        }\r
+    }\r
+    \r
+    protected abstract int getCount();\r
+    protected abstract int getIndexForName(String name);\r
+    \r
+    public int getSelected() {\r
+        return selectedIndex;\r
+    }\r
+    \r
+    private void updateColor(int index, int selected) {\r
+\r
+       FloatBuffer buff = geoms[index].getColorBuffer(0);\r
+       for (int i = 0; i < geoms[index].getBatch(0).getVertexCount(); i++) {\r
+               BufferUtils.setInBuffer(colors[index][selected], buff, i);\r
+        }\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+     * @see fi.vtt.proconf.shapeeditor.common.Gizmo#changeSelected(java.lang.String)\r
+     */\r
+    public void setSelected(String name) {\r
+        \r
+        if (name == null) {\r
+            for (int j = 0; j < getCount(); j++) {\r
+                if (selected[j]) {\r
+                    selected[j] = false;\r
+                    updateColor(j,UNSELECTED);\r
+                    setChanged(true);\r
+                }\r
+            }\r
+            selectedIndex = -1;\r
+            return;\r
+        }\r
+        int index = getIndexForName(name);\r
+        if (index == -1)\r
+            return;\r
+        selectedIndex = index;\r
+        if (!selected[index]) {\r
+            selected[index] = true;\r
+            updateColor(index,SELECTED);\r
+            setChanged(true);\r
+        }\r
+        for (int j = 0; j < getCount(); j++) {\r
+            if (j != index) {\r
+                if (selected[j]) {\r
+                    selected[j] = false;\r
+                    updateColor(j,UNSELECTED);\r
+                    setChanged(true);\r
+                }\r
+            }\r
+        } \r
+    }\r
+    \r
+    \r
+    protected void setGeometry(int index, TriMesh geom) {\r
+        geoms[index] = geom;\r
+    }\r
+    \r
+    protected void setColor(int index, int selected, Color4f color) {\r
+        colors[index][selected] = VecmathJmeTools.get(color);\r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/RotateGizmo.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/RotateGizmo.java
new file mode 100644 (file)
index 0000000..dcf18d5
--- /dev/null
@@ -0,0 +1,308 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.gizmo;\r
+\r
+import javax.vecmath.Color4f;\r
+import javax.vecmath.Point3f;\r
+\r
+import com.jme.bounding.BoundingBox;\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.TriMesh;\r
+import com.jme.scene.state.AlphaState;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.scene.state.ZBufferState;\r
+import com.jme.util.geom.BufferUtils;\r
+\r
+\r
+\r
+public class RotateGizmo extends MultiSelectionGizmo {\r
+\r
+    \r
+    public static String PICK_NAME = "rotate";\r
+    public static String X_NAME = "rx";\r
+    public static String Y_NAME = "ry";\r
+    public static String Z_NAME = "rz";\r
+    public static String XYZ_NAME = "ra";\r
+    \r
+    public static final int X = 0;\r
+    public static final int Y = 1;\r
+    public static final int Z = 2;\r
+    public static final int XYZ = 3;\r
+    \r
+\r
+    \r
+    \r
+    /* (non-Javadoc)\r
+     * @see fi.vtt.proconf.shapeeditor.common.Gizmo#getPickPrefix()\r
+     */\r
+    public String getPickPrefix() {\r
+        return PICK_NAME;\r
+    }\r
+    \r
+    public int getIndexForName(String name) {\r
+        if (!name.startsWith(PICK_NAME)) {\r
+            return -1;\r
+        }\r
+        name = name.substring(PICK_NAME.length());\r
+        if (name.startsWith(X_NAME))\r
+            return X;\r
+        if (name.startsWith(Y_NAME))\r
+            return Y;\r
+        if (name.startsWith(Z_NAME))\r
+            return Z;\r
+        if (name.startsWith(XYZ_NAME))\r
+            return XYZ;\r
+        return -1;\r
+    }\r
+    \r
+\r
+    @Override\r
+    public int getCount() {\r
+        return 4;\r
+    }\r
+\r
+    public RotateGizmo(Renderer renderer) {\r
+       super();\r
+       float radius = 2.f;\r
+       float radius2 = 1.8f;\r
+        int div = 9;\r
+        \r
+        float x[] = new float[div+1];\r
+        float y[] = new float[div+1];\r
+        float x2[] = new float[div+1];\r
+        float y2[] = new float[div+1];\r
+        x[0] = radius;\r
+        y[0] = 0.f;\r
+        x[div] = 0.f;\r
+        y[div] = radius;\r
+        x2[0] = radius2;\r
+        y2[0] = 0.f;\r
+        x2[div] = 0.f;\r
+        y2[div] = radius2;\r
+        \r
+        for (int i = 1; i < div; i++) {\r
+            float angle = (float)i/(float)div;\r
+            angle *= Math.PI * 0.5f;\r
+            float c = (float)Math.cos(angle);\r
+            float s = (float)Math.sin(angle);\r
+            x[i] = radius * c;\r
+            y[i] = radius * s;\r
+            x2[i] = radius2 * c;\r
+            y2[i] = radius2 * s;\r
+\r
+        }\r
+         \r
+        Color4f colorx = new Color4f(0.5f,0.f,0.f,0.5f);\r
+        Color4f colory = new Color4f(0.f,0.5f,0.f,0.5f);\r
+        Color4f colorz = new Color4f(0.f,0.f,0.5f,0.5f);\r
+        Color4f scolorx = new Color4f(1.f,0.f,0.f,0.7f);\r
+        Color4f scolory = new Color4f(0.f,1.f,0.f,0.7f);\r
+        Color4f scolorz = new Color4f(0.f,0.f,1.f,0.7f);\r
+\r
+        \r
+        Color4f colorxyz = new Color4f();\r
+        colorxyz.x = colorx.x + colory.x + colorz.x;\r
+        colorxyz.y = colorx.y + colory.y + colorz.y;\r
+        colorxyz.z = colorx.z +colory.z + colorz.z;\r
+        colorxyz.w = 0.5f;\r
+        \r
+        Color4f scolorxyz = new Color4f();\r
+        scolorxyz.x = scolorx.x + scolory.x + scolorz.x;\r
+        scolorxyz.y = scolorx.y + scolory.y + scolorz.y;\r
+        scolorxyz.z = scolorx.z + scolory.z + scolorz.z;\r
+        scolorxyz.w = 0.5f;\r
+        \r
+        int  numVertices = div*2;\r
+        float coordinates[] = new float[numVertices*3 + numVertices*3];\r
+        float cols[] = new float[numVertices*4*2];\r
+        int[] indices = new int[numVertices*3-6+numVertices*3 - 12];\r
+        for (int i = 0; i < div; i++) {\r
+            if (i == 0) {\r
+                indices[0] = 0;\r
+                indices[1] = 1;\r
+                indices[2] = 2;\r
+                continue;\r
+            }\r
+            int vIndex = i * 2 - 1;\r
+            int index = i * 6 - 3;\r
+            if (i == div - 1) {\r
+                indices[index] = vIndex;\r
+                indices[index+1] = vIndex+1;\r
+                indices[index+2] = vIndex+2;\r
+               \r
+            } else {\r
+                indices[index] = vIndex;\r
+                indices[index+1] = vIndex+1;\r
+                indices[index+2] = vIndex+2;\r
+                indices[index+3] = vIndex+1;\r
+                indices[index+4] = vIndex+3;\r
+                indices[index+5] = vIndex+2;\r
+            }\r
+        }\r
+        \r
+        for (int i = div+1; i < div * 2 - 1; i++) {\r
+            int vIndex = i * 2 - 1;\r
+            int index = i * 6 - 12;\r
+\r
+                indices[index] = vIndex;\r
+                indices[index+1] = vIndex+1;\r
+                indices[index+2] = vIndex+2;\r
+                indices[index+3] = vIndex+1;\r
+                indices[index+4] = vIndex+3;\r
+                indices[index+5] = vIndex+2;\r
+        }\r
+        \r
+        for (int i = 0; i < numVertices*2; i++)\r
+          setColor(cols,i, colorx);\r
+        \r
+        setCoordinate(coordinates,0, new Point3f(0.f, x[0], 0.f));\r
+        for (int i = 1; i < div; i++) {\r
+            int index = i * 2 - 1;\r
+            setCoordinate(coordinates,index,new Point3f(0.f,x[i],y[i]));\r
+            setCoordinate(coordinates,index+1,new Point3f(y[1],x[i],y[i]));  \r
+        }\r
+        setCoordinate(coordinates,numVertices - 1, new Point3f(0.f, 0.f, y[div]));\r
+        \r
+        setCoordinate(coordinates,numVertices, new Point3f(0.f, x2[0], 0.f));\r
+        for (int i = 1; i < div; i++) {\r
+            int index = (div+i) * 2 - 1;\r
+            setCoordinate(coordinates,index,new Point3f(y[1],x[i],y[i]));\r
+            setCoordinate(coordinates,index+1,new Point3f(y2[1],x2[i],y2[i]));  \r
+        }\r
+        setCoordinate(coordinates,numVertices*2 - 1, new Point3f(0.f, 0.f, y2[div]));\r
+       \r
+        TriMesh linex = new TriMesh(PICK_NAME+X_NAME,BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        \r
+        for (int i = 0; i < numVertices*2; i++)\r
+          setColor(cols,i, colory);\r
+        \r
+        setCoordinate(coordinates,0, new Point3f(x[0], 0.f, 0.f));\r
+        for (int i = 1; i < div; i++) {\r
+            int index = i * 2 - 1;\r
+            setCoordinate(coordinates,index,new Point3f(x[i],0.f,y[i]));\r
+            setCoordinate(coordinates,index+1,new Point3f(x[i],y[1],y[i]));  \r
+        }\r
+        setCoordinate(coordinates,numVertices - 1, new Point3f(0.f, 0.f, y[div]));\r
+        \r
+        setCoordinate(coordinates,numVertices, new Point3f(x2[0], 0.f, 0.f));\r
+        for (int i = 1; i < div; i++) {\r
+            int index = (div+i) * 2 - 1;\r
+            setCoordinate(coordinates,index,new Point3f(x[i],y[1],y[i]));\r
+            setCoordinate(coordinates,index+1,new Point3f(x2[i],y2[1],y2[i]));  \r
+        }\r
+        setCoordinate(coordinates,numVertices*2 - 1, new Point3f(0.f, 0.f, y2[div]));\r
+\r
+        TriMesh liney = new TriMesh(PICK_NAME+Y_NAME,BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        \r
+        for (int i = 0; i < numVertices*2; i++)\r
+          setColor(cols,i, colorz);\r
+        \r
+        setCoordinate(coordinates,0, new Point3f(0.f, x[0], 0.f));\r
+        for (int i = 1; i < div; i++) {\r
+            int index = i * 2 - 1;\r
+            setCoordinate(coordinates,index,new Point3f(y[i],x[i],0.f));\r
+            setCoordinate(coordinates,index+1,new Point3f(y[i],x[i],y[1]));  \r
+        }\r
+        setCoordinate(coordinates,numVertices - 1, new Point3f(y[div],0.f, 0.f));\r
+\r
+        setCoordinate(coordinates,numVertices, new Point3f(0.f, x2[0], 0.f));\r
+        for (int i = 1; i < div; i++) {\r
+            int index = (div+i) * 2 - 1;\r
+            setCoordinate(coordinates,index,new Point3f(y[i],x[i],y[1]));\r
+            setCoordinate(coordinates,index+1,new Point3f(y2[i],x2[i],y2[1]));  \r
+        }\r
+        setCoordinate(coordinates,numVertices*2 - 1, new Point3f(y2[div],0.f, 0.f));\r
+\r
+        TriMesh linez = new TriMesh(PICK_NAME+Z_NAME,BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        \r
+        numVertices = (div-2)*3+1;\r
+        coordinates = new float[numVertices*3];\r
+        cols = new float[numVertices*4];\r
+        indices = new int[(div-2)*3*3];\r
+        \r
+        for (int i = 0; i < numVertices; i++)\r
+            setColor(cols,i, colorxyz);\r
+        float center = radius * 0.5f;//(float)Math.cos(Math.PI*0.25);\r
+        setCoordinate(coordinates,0,new Point3f(center,center,center));\r
+        for (int i = 1; i < div; i++) {\r
+            int index = i;\r
+            setCoordinate(coordinates,index,new Point3f(y2[1],x2[i],y2[i]));\r
+        }\r
+        for (int i = 1; i < div; i++) {\r
+            int index = i + div-1 - 1;\r
+            setCoordinate(coordinates,index,new Point3f(y2[i],y2[1],x2[i]));\r
+        }\r
+        for (int i = 1; i < div-1; i++) {\r
+            int index = i + 2*(div-1) -2;\r
+            setCoordinate(coordinates,index,new Point3f(x2[i],y2[i],y2[1]));\r
+        }\r
+        for (int i = 0; i < (div-2)*3; i++) {\r
+            int index = i*3;\r
+            int iindex = i+1;\r
+            indices[index] = 0;\r
+            indices[index+1] = iindex;\r
+            indices[index+2] = iindex+1;\r
+            if (iindex == (numVertices -1))\r
+                indices[index+2] = 1;\r
+            \r
+        }\r
+\r
+        TriMesh trianglexyz = new TriMesh(PICK_NAME+XYZ_NAME,BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        \r
+        getGizmoNode().attachChild(linex);\r
+        getGizmoNode().attachChild(liney);\r
+        getGizmoNode().attachChild(linez);\r
+        getGizmoNode().attachChild(trianglexyz);\r
+        getGizmoNode().setModelBound(new BoundingBox());\r
+        getGizmoNode().updateModelBound();\r
+        \r
+        linex.getBatch(0).setCastsShadows(false);\r
+        liney.getBatch(0).setCastsShadows(false);\r
+        linez.getBatch(0).setCastsShadows(false);\r
+        trianglexyz.getBatch(0).setCastsShadows(false);\r
+        \r
+        setGeometry(0,linex);\r
+        setGeometry(1,liney);\r
+        setGeometry(2,linez);\r
+        setGeometry(3,trianglexyz);\r
+             \r
+        setColor(0,0,colorx);\r
+        setColor(0,1,scolorx);\r
+        setColor(1,0,colory);\r
+        setColor(1,1,scolory);\r
+        setColor(2,0,colorz);\r
+        setColor(2,1,scolorz);\r
+        setColor(3,0,colorxyz);\r
+        setColor(3,1,scolorxyz);\r
+        \r
+        AlphaState as = renderer.createAlphaState();\r
+        as.setBlendEnabled(true);\r
+        as.setSrcFunction(AlphaState.DB_SRC_ALPHA);\r
+        as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);\r
+        as.setEnabled(true);\r
+        getGizmoNode().setRenderState(as);\r
+        MaterialState ms = renderer.createMaterialState();\r
+        ms.setColorMaterial(MaterialState.CM_AMBIENT_AND_DIFFUSE);\r
+        ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK);\r
+        getGizmoNode().setRenderState(ms);\r
+        ZBufferState zs = renderer.createZBufferState();\r
+        zs.setFunction(ZBufferState.CF_ALWAYS);\r
+        zs.setEnabled(true);\r
+        getGizmoNode().setRenderState(zs);\r
+        \r
+        \r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/TransformGizmo.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/TransformGizmo.java
new file mode 100644 (file)
index 0000000..b0e6df4
--- /dev/null
@@ -0,0 +1,316 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.gizmo;\r
+\r
+import javax.vecmath.Color4f;\r
+import javax.vecmath.Point3f;\r
+\r
+import com.jme.bounding.BoundingBox;\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.TriMesh;\r
+import com.jme.scene.state.AlphaState;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.scene.state.ZBufferState;\r
+import com.jme.util.geom.BufferUtils;\r
+\r
+\r
+public class TransformGizmo extends MultiSelectionGizmo {\r
+\r
+    \r
+    public static String PICK_NAME = "translate";\r
+    public static String X_NAME = "ax";\r
+    public static String Y_NAME = "ay";\r
+    public static String Z_NAME = "az";\r
+    public static String XZ_NAME = "xz";\r
+    public static String XY_NAME = "xy";\r
+    public static String YZ_NAME = "yz";\r
+    public static String XYZ_NAME = "aa";\r
+    \r
+    public static final int X = 0;\r
+    public static final int Y = 1;\r
+    public static final int Z = 2;\r
+    public static final int XY = 3;\r
+    public static final int XZ = 4;\r
+    public static final int YZ = 5;\r
+    public static final int XYZ = 6;\r
+\r
+    \r
+    \r
+    /* (non-Javadoc)\r
+     * @see fi.vtt.proconf.shapeeditor.common.Gizmo#getPickPrefix()\r
+     */\r
+    public String getPickPrefix() {\r
+        return PICK_NAME;\r
+    }\r
+    \r
+    public int getIndexForName(String name) {\r
+        if (!name.startsWith(PICK_NAME)) {\r
+            return -1;\r
+        }\r
+        name = name.substring(PICK_NAME.length());\r
+        if (name.startsWith(X_NAME))\r
+            return X;\r
+        if (name.startsWith(Y_NAME))\r
+            return Y;\r
+        if (name.startsWith(Z_NAME))\r
+            return Z;\r
+        if (name.startsWith(XY_NAME))\r
+            return XY;\r
+        if (name.startsWith(XZ_NAME))\r
+            return XZ;\r
+        if (name.startsWith(YZ_NAME))\r
+            return YZ;\r
+        if (name.startsWith(XYZ_NAME))\r
+            return XYZ;\r
+        return -1;\r
+    }\r
+    \r
+    @Override\r
+    public int getCount() {\r
+        return 7;\r
+    }\r
+\r
+    \r
+    /*\r
+     public TransformGizmo() {\r
+     */\r
+    public TransformGizmo(Renderer renderer) {\r
+        super();\r
+        float size = 2.f;\r
+        float sizeD2 = 1.f;\r
+        float offset = 0.2f;\r
+        \r
+        Color4f colorx = new Color4f(0.5f,0.f,0.f,0.5f);\r
+        Color4f colory = new Color4f(0.f,0.5f,0.f,0.5f);\r
+        Color4f colorz = new Color4f(0.f,0.f,0.5f,0.5f);\r
+        Color4f scolorx = new Color4f(1.f,0.f,0.f,0.7f);\r
+        Color4f scolory = new Color4f(0.f,1.f,0.f,0.7f);\r
+        Color4f scolorz = new Color4f(0.f,0.f,1.f,0.7f);\r
+        \r
+        Color4f colorxy = new Color4f();\r
+        colorxy.x = colorx.x + colory.x;\r
+        colorxy.y = colorx.y + colory.y;\r
+        colorxy.z = colorx.z + colory.z;\r
+        colorxy.w = 0.5f;\r
+        \r
+        Color4f colorxz = new Color4f();\r
+        colorxz.x = colorx.x + colorz.x;\r
+        colorxz.y = colorx.y + colorz.y;\r
+        colorxz.z = colorx.z + colorz.z;\r
+        colorxz.w = 0.5f;\r
+        \r
+        Color4f coloryz = new Color4f();\r
+        coloryz.x = colory.x + colorz.x;\r
+        coloryz.y = colory.y + colorz.y;\r
+        coloryz.z = colory.z + colorz.z;\r
+        coloryz.w = 0.5f;\r
+        \r
+        Color4f colorxyz = new Color4f();\r
+        colorxyz.x = colorx.x + colory.x + colorz.x;\r
+        colorxyz.y = colorx.y + colory.y + colorz.y;\r
+        colorxyz.z = colorx.z +colory.z + colorz.z;\r
+        colorxyz.w = 0.5f;\r
+        \r
+        Color4f scolorxy = new Color4f();\r
+        scolorxy.x = scolory.x + scolorx.x;\r
+        scolorxy.y = scolory.y + scolorx.y;\r
+        scolorxy.z = scolory.z + scolorx.z;\r
+        scolorxy.w = 0.5f;\r
+        \r
+        Color4f scolorxz = new Color4f();\r
+        scolorxz.x = scolorx.x + scolorz.x;\r
+        scolorxz.y = scolorx.y + scolorz.y;\r
+        scolorxz.z = scolorx.z + scolorz.z;\r
+        scolorxz.w = 0.5f;\r
+        \r
+        Color4f scoloryz = new Color4f();\r
+        scoloryz.x = scolory.x + scolorz.x;\r
+        scoloryz.y = scolory.y + scolorz.y;\r
+        scoloryz.z = scolory.z + scolorz.z;\r
+        scoloryz.w = 0.5f;\r
+        \r
+        Color4f scolorxyz = new Color4f();\r
+        scolorxyz.x = scolorx.x + scolory.x + scolorz.x;\r
+        scolorxyz.y = scolorx.y + scolory.y + scolorz.y;\r
+        scolorxyz.z = scolorx.z + scolory.z + scolorz.z;\r
+        scolorxyz.w = 0.5f;\r
+        \r
+        \r
+        float coordinates[] = new float[6*3];\r
+        float cols[] = new float[6*4];\r
+        int[] indices = new int[]{0,1,3,\r
+                                  1,2,3,\r
+                                  0,3,5,\r
+                                  3,4,5};\r
+        for (int i = 0; i < 6; i++)\r
+          setColor(cols,i, colorx);\r
+\r
+        setCoordinate(coordinates,0, new Point3f(size, 0.f, 0.f));\r
+        setCoordinate(coordinates,1, new Point3f(size - offset, offset, 0.f));\r
+        setCoordinate(coordinates,2, new Point3f(sizeD2 - offset, offset, 0.f));\r
+        setCoordinate(coordinates,3, new Point3f(sizeD2, 0.f, 0.f));\r
+        setCoordinate(coordinates,4, new Point3f(sizeD2 - offset, 0.f, offset));\r
+        setCoordinate(coordinates,5, new Point3f(size - offset, 0.f, offset));\r
+\r
+        TriMesh linex = new TriMesh("",BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        for (int i = 0; i < 6; i++)\r
+          setColor(cols,i, colory);\r
+\r
+        setCoordinate(coordinates,0, new Point3f(0.f, size, 0.f));\r
+        setCoordinate(coordinates,1, new Point3f(offset, size - offset, 0.f));\r
+        setCoordinate(coordinates,2, new Point3f(offset, sizeD2 - offset, 0.f));\r
+        setCoordinate(coordinates,3, new Point3f(0.f, sizeD2, 0.f));\r
+        setCoordinate(coordinates,4, new Point3f(0.f, sizeD2 - offset, offset));\r
+        setCoordinate(coordinates,5, new Point3f(0.f, size - offset, offset));\r
+\r
+        TriMesh liney = new TriMesh("",BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        for (int i = 0; i < 6; i++)\r
+          setColor(cols,i, colorz);\r
+\r
+        setCoordinate(coordinates,0, new Point3f(0.f, 0.f,size));\r
+        setCoordinate(coordinates,1, new Point3f(offset, 0.f, size - offset));\r
+        setCoordinate(coordinates,2, new Point3f(offset, 0.f, sizeD2 - offset));\r
+        setCoordinate(coordinates,3, new Point3f(0.f, 0.f, sizeD2));\r
+        setCoordinate(coordinates,4, new Point3f(0.f, offset, sizeD2 - offset));\r
+        setCoordinate(coordinates,5, new Point3f(0.f, offset, size - offset));\r
+\r
+        TriMesh linez = new TriMesh("",BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        // TODO : picking did not work properly without chancing indices; this must be investigated \r
+        indices = new int[]{2,1,3,0,1,3};//{0,1,3,1,2,3};\r
+        coordinates = new float[4*3];\r
+        cols = new float[4*4];\r
+        \r
+        for (int i = 0; i < 4; i++)\r
+           setColor(cols,i, colorxz);\r
+        setCoordinate(coordinates,0, new Point3f(offset, 0.f, size-offset));\r
+        setCoordinate(coordinates,1, new Point3f(offset, 0.f, sizeD2 - offset));\r
+        setCoordinate(coordinates,2, new Point3f(sizeD2 - offset, 0.f, offset));\r
+        setCoordinate(coordinates,3, new Point3f(size-offset, 0.f, offset));\r
+\r
+        TriMesh trianglexz = new TriMesh("",BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        for (int i = 0; i < 4; i++)\r
+            setColor(cols,i, colorxy);\r
+        setCoordinate(coordinates,0, new Point3f(offset, size-offset, 0.f));\r
+        setCoordinate(coordinates,1, new Point3f(offset, sizeD2 - offset, 0.f));\r
+        setCoordinate(coordinates,2, new Point3f(sizeD2 - offset, offset, 0.f));\r
+        setCoordinate(coordinates,3, new Point3f(size-offset, offset, 0.f));\r
+\r
+        TriMesh trianglexy = new TriMesh("",BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        for (int i = 0; i < 4; i++)\r
+            setColor(cols,i, coloryz);\r
+        setCoordinate(coordinates,0, new Point3f( 0.f,offset, size-offset));\r
+        setCoordinate(coordinates,1, new Point3f( 0.f,offset, sizeD2 - offset));\r
+        setCoordinate(coordinates,2, new Point3f( 0.f,sizeD2 - offset, offset));\r
+        setCoordinate(coordinates,3, new Point3f( 0.f,size-offset, offset));\r
+\r
+        TriMesh triangleyz = new TriMesh("",BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        indices = new int[]{0,1,2,\r
+                            0,2,3,\r
+                            0,3,4,\r
+                            0,4,5,\r
+                            0,5,6,\r
+                            0,6,7,\r
+                            0,7,8,\r
+                            0,8,9,\r
+                            0,9,1};\r
+        coordinates = new float[10*3];\r
+        cols = new float[10*4];\r
+        \r
+        for (int i = 0; i < 10; i++)\r
+            setColor(cols,i, colorxyz);\r
+        setCoordinate(coordinates,0, new Point3f(0.f, 0.f, 0.f));\r
+        setCoordinate(coordinates,1, new Point3f(sizeD2, 0.f, 0.f));\r
+        setCoordinate(coordinates,2, new Point3f(sizeD2 - offset, offset, 0.f));\r
+        setCoordinate(coordinates,3, new Point3f(offset, sizeD2 - offset, 0.f));\r
+        setCoordinate(coordinates,4, new Point3f(0.f, sizeD2, 0.f));\r
+        setCoordinate(coordinates,5, new Point3f(0.f, sizeD2 - offset, offset));\r
+        setCoordinate(coordinates,6, new Point3f(0.f, offset, sizeD2-offset));\r
+        setCoordinate(coordinates,7, new Point3f(0.f, 0.f, sizeD2));\r
+        setCoordinate(coordinates,8, new Point3f(offset, 0.f, sizeD2-offset));\r
+        setCoordinate(coordinates,9, new Point3f(sizeD2-offset, 0.f, offset));\r
+        \r
+        TriMesh trianglexyz = new TriMesh("",BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        linex.setName(PICK_NAME+X_NAME);\r
+        liney.setName(PICK_NAME+Y_NAME);\r
+        linez.setName(PICK_NAME+Z_NAME);\r
+        trianglexy.setName(PICK_NAME+XY_NAME);\r
+        trianglexz.setName(PICK_NAME+XZ_NAME);\r
+        triangleyz.setName(PICK_NAME+YZ_NAME);\r
+        trianglexyz.setName(PICK_NAME+XYZ_NAME);\r
+        \r
+        linex.getBatch(0).setCastsShadows(false);\r
+        liney.getBatch(0).setCastsShadows(false);\r
+        linez.getBatch(0).setCastsShadows(false);\r
+        trianglexy.getBatch(0).setCastsShadows(false);\r
+        trianglexz.getBatch(0).setCastsShadows(false);\r
+        triangleyz.getBatch(0).setCastsShadows(false);\r
+        trianglexyz.getBatch(0).setCastsShadows(false);\r
+\r
+        getGizmoNode().attachChild(linex);\r
+        getGizmoNode().attachChild(liney);\r
+        getGizmoNode().attachChild(linez);\r
+        getGizmoNode().attachChild(trianglexy);\r
+        getGizmoNode().attachChild(trianglexz);\r
+        getGizmoNode().attachChild(triangleyz);\r
+        getGizmoNode().attachChild(trianglexyz);\r
+        getGizmoNode().setModelBound(new BoundingBox());\r
+        getGizmoNode().updateModelBound();\r
+\r
+        setGeometry(0,linex);\r
+        setGeometry(1,liney);\r
+        setGeometry(2,linez);\r
+        setGeometry(3,trianglexy);\r
+        setGeometry(4,trianglexz);\r
+        setGeometry(5,triangleyz);\r
+        setGeometry(6,trianglexyz);\r
+       \r
+        \r
+        setColor(0,0,colorx);\r
+        setColor(0,1,scolorx);\r
+        setColor(1,0,colory);\r
+        setColor(1,1,scolory);\r
+        setColor(2,0,colorz);\r
+        setColor(2,1,scolorz);\r
+        setColor(3,0,colorxy);\r
+        setColor(3,1,scolorxy);\r
+        setColor(4,0,colorxz);\r
+        setColor(4,1,scolorxz);\r
+        setColor(5,0,coloryz);\r
+        setColor(5,1,scoloryz);\r
+        setColor(6,0,colorxyz);\r
+        setColor(6,1,scolorxyz);\r
+        \r
+\r
+        AlphaState as = renderer.createAlphaState();   \r
+        as.setBlendEnabled(true);\r
+        as.setSrcFunction(AlphaState.DB_SRC_ALPHA);\r
+        as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);\r
+        as.setEnabled(true);\r
+        getGizmoNode().setRenderState(as);\r
+        MaterialState ms = renderer.createMaterialState();\r
+        ms.setColorMaterial(MaterialState.CM_AMBIENT_AND_DIFFUSE);\r
+        ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK);\r
+        getGizmoNode().setRenderState(ms);\r
+        ZBufferState zs = renderer.createZBufferState();\r
+        zs.setFunction(ZBufferState.CF_ALWAYS);\r
+        zs.setEnabled(true);\r
+        zs.setWritable(false);\r
+        getGizmoNode().setRenderState(zs);\r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/TransformInlineGizmo.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/gizmo/TransformInlineGizmo.java
new file mode 100644 (file)
index 0000000..23ba6e0
--- /dev/null
@@ -0,0 +1,215 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.gizmo;\r
+\r
+import java.nio.FloatBuffer;\r
+\r
+import javax.vecmath.Color4f;\r
+import javax.vecmath.Point3f;\r
+import javax.vecmath.Vector3f;\r
+\r
+import org.simantics.proconf.g3d.base.VecmathJmeTools;\r
+\r
+import com.jme.bounding.BoundingBox;\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.TriMesh;\r
+import com.jme.scene.state.AlphaState;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.scene.state.ZBufferState;\r
+import com.jme.util.geom.BufferUtils;\r
+\r
+\r
+public class TransformInlineGizmo extends AbstractGizmo {\r
+\r
+       TriMesh geom = new TriMesh();\r
+       ColorRGBA colors[] = new ColorRGBA[2];\r
+   \r
+    \r
+    public static String PICK_NAME = "translate";\r
+    public static String X_NAME = "ax";\r
+    \r
+    public static final int X = 0;\r
+    \r
+    public static final int SELECTED = 1;\r
+    public static final int UNSELECTED = 0;\r
+      \r
+    private boolean selected = false;\r
+    \r
+    \r
+    /* (non-Javadoc)\r
+     * @see fi.vtt.proconf.shapeeditor.common.Gizmo#getPickPrefix()\r
+     */\r
+    public String getPickPrefix() {\r
+        return PICK_NAME;\r
+    }\r
+    \r
+    public int getIndexForName(String name) {\r
+        if (!name.startsWith(PICK_NAME)) {\r
+            return -1;\r
+        }\r
+        name = name.substring(PICK_NAME.length());\r
+        if (name.startsWith(X_NAME))\r
+            return X;\r
+        return -1;\r
+    }\r
+    \r
+    private void updateColor(int sel) {\r
+       FloatBuffer buff = geom.getColorBuffer(0);\r
+       for (int i = 0; i < geom.getBatch(0).getVertexCount(); i++) {\r
+               BufferUtils.setInBuffer(colors[sel], buff, i);\r
+        }\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+     * @see fi.vtt.proconf.shapeeditor.common.Gizmo#changeSelected(java.lang.String)\r
+     */\r
+    public void setSelected(String name) {\r
+        \r
+        if (name == null) {\r
+               setChanged(true);\r
+            updateColor(UNSELECTED);\r
+            selected = false;\r
+            return;\r
+        }\r
+        int index = getIndexForName(name);\r
+        if (index == -1) {\r
+            selected = false;\r
+            return;\r
+        }\r
+\r
+        selected = true;\r
+        updateColor(SELECTED);\r
+        setChanged(true);\r
+        \r
+    }\r
+    \r
+    @Override\r
+    public void setScale(Vector3f scale) {\r
+       /**\r
+        * A bug in JME (?)\r
+        * Negative scaling breaks picking (ray hits the bounding box, but ray doesn't intersect any triangles) \r
+        */\r
+       scale.x = Math.abs(scale.x);\r
+       scale.y = Math.abs(scale.y);\r
+       scale.z = Math.abs(scale.z);\r
+       \r
+       super.setScale(scale);\r
+    }\r
+    \r
+    \r
+    /*\r
+     public TransformInlineGizmo(){\r
+     */\r
+    public TransformInlineGizmo(Renderer renderer) {\r
+       super();\r
+        float size = 2.f;\r
+        float sizeD2 = 1.f;\r
+        float offset = 0.07f;\r
+        \r
+        Color4f colorx = new Color4f(0.5f,0.f,0.f,0.5f);\r
+        Color4f scolorx = new Color4f(1.f,0.f,0.f,0.7f);\r
+        \r
+\r
+        float coordinates[] = new float[18*3];\r
+        float cols[] = new float[18*4];\r
+        int[] indices = new int[]{0,2,1,\r
+                                  0,3,2,\r
+                                  0,4,3,\r
+                                  0,1,4,\r
+                                  1,2,6,\r
+                                  1,6,5,\r
+                                  2,3,7,\r
+                                  2,7,6,\r
+                                  3,4,8,\r
+                                  3,8,7,\r
+                                  4,1,5,\r
+                                  4,5,8,\r
+                                  5,6,7,\r
+                                  5,7,8,\r
+                                  \r
+                                  9,11,10,\r
+                                  9,12,11,\r
+                                  9,13,12,\r
+                                  9,10,13,\r
+                                  10,11,15,\r
+                                  10,15,14,\r
+                                  11,12,16,\r
+                                  11,16,15,\r
+                                  12,13,17,\r
+                                  12,17,16,\r
+                                  13,10,14,\r
+                                  13,14,17,\r
+                                  14,15,16,\r
+                                  14,16,17\r
+                                  \r
+                                                         };\r
+        for (int i = 0; i < 18; i++)\r
+          setColor(cols,i, colorx);\r
+\r
+        setCoordinate(coordinates,0, new Point3f(size, 0.f, 0.f));\r
+        setCoordinate(coordinates,1, new Point3f(size - offset*2, offset, offset));\r
+        setCoordinate(coordinates,2, new Point3f(size - offset*2, offset, -offset));\r
+        setCoordinate(coordinates,3, new Point3f(size - offset*2, -offset, -offset));\r
+        setCoordinate(coordinates,4, new Point3f(size - offset*2, -offset, offset));\r
+        setCoordinate(coordinates,5, new Point3f(sizeD2, offset, offset));\r
+        setCoordinate(coordinates,6, new Point3f(sizeD2, offset, -offset));\r
+        setCoordinate(coordinates,7, new Point3f(sizeD2, -offset, -offset));\r
+        setCoordinate(coordinates,8, new Point3f(sizeD2, -offset, offset));\r
+        \r
+        setCoordinate(coordinates,9, new Point3f(-size, 0.f, 0.f));\r
+        setCoordinate(coordinates,10, new Point3f(-size + offset*2, offset, offset));\r
+        setCoordinate(coordinates,11, new Point3f(-size + offset*2, offset, -offset));\r
+        setCoordinate(coordinates,12, new Point3f(-size + offset*2, -offset, -offset));\r
+        setCoordinate(coordinates,13, new Point3f(-size + offset*2, -offset, offset));\r
+        setCoordinate(coordinates,14, new Point3f(-sizeD2, offset, offset));\r
+        setCoordinate(coordinates,15, new Point3f(-sizeD2, offset, -offset));\r
+        setCoordinate(coordinates,16, new Point3f(-sizeD2, -offset, -offset));\r
+        setCoordinate(coordinates,17, new Point3f(-sizeD2, -offset, offset));\r
+\r
+        TriMesh linex = new TriMesh(PICK_NAME+X_NAME,BufferUtils.createFloatBuffer(coordinates),null,BufferUtils.createFloatBuffer(cols),null,BufferUtils.createIntBuffer(indices));\r
+        \r
+        getGizmoNode().attachChild(linex);\r
+        getGizmoNode().setModelBound(new BoundingBox());\r
+        getGizmoNode().updateModelBound();\r
+\r
+        geom = linex;\r
+        geom.getBatch(0).setCastsShadows(false);\r
+\r
+        colors[0] = VecmathJmeTools.get(colorx);\r
+        colors[1] = VecmathJmeTools.get(scolorx);\r
+        \r
+        AlphaState as = renderer.createAlphaState();\r
+        as.setBlendEnabled(true);\r
+        as.setSrcFunction(AlphaState.DB_SRC_ALPHA);\r
+        as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);\r
+        as.setEnabled(true);\r
+        getGizmoNode().setRenderState(as);\r
+        MaterialState ms = renderer.createMaterialState();\r
+        ms.setColorMaterial(MaterialState.CM_AMBIENT_AND_DIFFUSE);\r
+        ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK);\r
+        getGizmoNode().setRenderState(ms);\r
+        ZBufferState zs = renderer.createZBufferState();\r
+        zs.setFunction(ZBufferState.CF_ALWAYS);\r
+        zs.setEnabled(true);\r
+        getGizmoNode().setRenderState(zs);\r
+        \r
+    }\r
+    \r
+\r
+    public boolean isSelected() {\r
+        return selected;\r
+    }\r
+\r
+    public void setSelected(boolean selected) {\r
+        this.selected = selected;\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/input/AWTInputProvider.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/input/AWTInputProvider.java
new file mode 100644 (file)
index 0000000..ec15239
--- /dev/null
@@ -0,0 +1,309 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.input;\r
+\r
+import java.awt.event.KeyEvent;\r
+import java.awt.event.KeyListener;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.event.MouseListener;\r
+import java.awt.event.MouseMotionListener;\r
+\r
+public class AWTInputProvider implements KeyListener, MouseListener, MouseMotionListener , InputProvider{\r
+    \r
+    private boolean keyPressed[] = new boolean[1024];\r
+    private boolean keyTemp[] = new boolean[1024];\r
+    private boolean keyDown[] = new boolean[1024];\r
+    private boolean keyUp[] = new boolean[1024];\r
+    \r
+    private int awtMouseX = 0;\r
+    private int awtMouseY = 0;\r
+    private boolean awtPressed = false;\r
+    private boolean awtDragged = false;\r
+    private boolean awtReleased = false;\r
+    private boolean awtMouseClicked = false;\r
+    private boolean awtMouseMoved = false;\r
+    \r
+    private int awtPressModifiers = 0;\r
+    private int awtDragModifiers = 0;\r
+    private int awtClickModifiers = 0;\r
+    private int awtMoveModifiers = 0;\r
+    private int awtClickButton = 0;\r
+     \r
+    private int mouseX = 0;\r
+    private int mouseY = 0;\r
+    \r
+    private int prevMouseX = 0;\r
+    private int prevMouseY = 0;\r
+    \r
+    private boolean mousePressed = false;\r
+    private boolean mouseDragged = false;\r
+    private boolean mouseReleased = false;\r
+    private boolean mouseClicked = false;\r
+    private boolean mouseMoved = false;\r
+    \r
+    private int pressModifiers = 0;\r
+    private int clickModifiers = 0;\r
+    private int dragModifiers = 0;\r
+    private int clickButton = 0;\r
+    private int moveModifiers = 0;\r
+    \r
+    public AWTInputProvider() {\r
+        for (int i = 0; i < keyDown.length; i++) {\r
+            keyDown[i] = false;\r
+            keyTemp[i] = false;\r
+            keyPressed[i] = false;  \r
+            keyUp[i] = false;\r
+        }\r
+    }\r
+    \r
+    public boolean keyPressed(int i) {\r
+        return keyPressed[i];\r
+    }\r
+    \r
+    public boolean keyDown(int i) {\r
+        return keyDown[i];\r
+    }\r
+    \r
+    public boolean keyUp(int i) {\r
+       return keyUp[i];\r
+    }\r
+    \r
+    public int mouseX() {\r
+        return mouseX;\r
+    }\r
+    \r
+    public int mouseY() {\r
+        return mouseY;\r
+    }\r
+    \r
+    public int prevMouseX() {\r
+        return prevMouseX;\r
+    }\r
+    \r
+    public int prevMouseY() {\r
+        return prevMouseY;\r
+    }\r
+    \r
+    public boolean mousePressed() {\r
+        return mousePressed;\r
+    }\r
+    \r
+    public boolean mouseMoved() {\r
+        return mouseMoved;\r
+    }\r
+    \r
+    public boolean mouseReleased() {\r
+        return mouseReleased;\r
+    }\r
+    \r
+    public boolean mouseClicked() {\r
+        return mouseClicked;\r
+    }\r
+    \r
+    public boolean mouseDragged() {\r
+        return mouseDragged;\r
+    }\r
+    \r
+    public int pressModifiers() {\r
+        return pressModifiers;\r
+    }\r
+    \r
+    public int clickModifiers() {\r
+        return clickModifiers;\r
+    }\r
+    \r
+    public int dragModifiers() {\r
+        return dragModifiers;\r
+    }\r
+    \r
+    public int moveModifiers() {\r
+        return moveModifiers;\r
+    }\r
+    \r
+    public int clickButton() {\r
+        return clickButton;\r
+    }\r
+    \r
+    \r
+    public void update() {\r
+        prevMouseX = mouseX;\r
+        prevMouseY = mouseY;\r
+        mouseX = awtMouseX;\r
+        mouseY = awtMouseY;\r
+        //System.out.println(mouseX + " " + mouseY);\r
+        mousePressed = awtPressed;\r
+        awtPressed = false;\r
+        mouseReleased = awtReleased;\r
+        awtReleased = false;\r
+        mouseMoved = awtMouseMoved;\r
+        awtMouseMoved = false;\r
+        mouseDragged = awtDragged;\r
+        awtDragged = false;\r
+        mouseClicked = awtMouseClicked;\r
+        awtMouseClicked = false;\r
+        pressModifiers = awtPressModifiers;\r
+       // awtPressModifiers = 0;\r
+        clickModifiers = awtClickModifiers;\r
+        //awtClickModifiers = 0;\r
+        dragModifiers = awtDragModifiers;\r
+       // awtDragModifiers = 0;\r
+        moveModifiers = awtMoveModifiers;\r
+        //awtMoveModifiers = 0;\r
+        clickButton = awtClickButton;\r
+        awtClickButton = 0;\r
+        for (int i = 0; i < keyDown.length; i++) {\r
+            if (keyDown[i] && !keyTemp[i]) {\r
+              keyTemp[i] = true;\r
+              keyPressed[i] = true;\r
+            }\r
+            else if (keyDown[i] && keyTemp[i]) {\r
+             keyPressed[i] = false;\r
+            }\r
+            else if (!keyDown[i] && keyTemp[i]) {\r
+               keyUp[i] = true;\r
+               keyTemp[i] = false;\r
+                keyPressed[i] = false;\r
+            }\r
+            else if (!keyDown[i]) {\r
+              keyTemp[i] = false;\r
+              keyPressed[i] = false;\r
+              keyUp[i] = false;\r
+            }\r
+          }\r
+    \r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+     * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)\r
+     */\r
+    public void mouseDragged(MouseEvent e) {\r
+        awtMouseX = e.getX();\r
+        awtMouseY = e.getY();\r
+        awtDragged = true;\r
+        awtDragModifiers = e.getModifiers() | e.getButton();\r
+    }\r
\r
+    /* (non-Javadoc)\r
+     * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)\r
+     */\r
+    public void mouseReleased(MouseEvent e) {\r
+        awtReleased = true;\r
+        //ms.set(msTmp);\r
+\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)\r
+     */\r
+    public void mouseClicked(MouseEvent e) {\r
+\r
+        awtMouseX = e.getX();\r
+        awtMouseY = e.getY();\r
+        e.getButton();\r
+        \r
+        awtClickModifiers  = e.getModifiersEx();\r
+        awtClickButton = e.getButton();\r
+        awtMouseClicked = true;\r
+\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)\r
+     */\r
+    public void mouseEntered(MouseEvent arg0) {\r
+\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)\r
+     */\r
+    public void mouseExited(MouseEvent arg0) {\r
+\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)\r
+     */\r
+    public void mouseMoved(MouseEvent arg0) {\r
+\r
+        awtMouseMoved = true;\r
+        awtMouseX = arg0.getX();\r
+        awtMouseY = arg0.getY();\r
+        awtMoveModifiers  = arg0.getModifiersEx();\r
+\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+     * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)\r
+     */\r
+    public void keyPressed(KeyEvent arg0) {\r
+           keyDown[arg0.getKeyCode()] = true;\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+     * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)\r
+     */\r
+    public void keyReleased(KeyEvent arg0) {\r
+           keyDown[arg0.getKeyCode()] = false;\r
+    }\r
+    \r
\r
+    /* (non-Javadoc)\r
+     * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent)\r
+     */\r
+    public void keyTyped(KeyEvent e) {\r
+\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)\r
+     */\r
+    public void mousePressed(MouseEvent e) {\r
+        awtMouseX = e.getX();\r
+        awtMouseY = e.getY();\r
+        awtPressed = true;\r
+        awtPressModifiers = e.getModifiers() | e.getButton();\r
+    }\r
+    \r
+    public void setMouseMoved(boolean b) {\r
+\r
+    }\r
+    \r
+    public void setMouseX(int x) {\r
+\r
+    }\r
+    \r
+    public void setMouseY(int y) {\r
+\r
+    }\r
+    \r
+    public String toString() {\r
+        String s = "";\r
+        s += "(" + mouseX + "," + mouseY + ")\n";\r
+        s += "Pressed " + mousePressed + "\n";\r
+        s += "Released " + mouseReleased + "\n";\r
+        s += "Moved " + mouseMoved + "\n";\r
+        s += "Dragged " + mouseDragged + "\n";\r
+        s += "Clicked " + mouseClicked + "\n";\r
+        s += "DragModifiers " + dragModifiers + "\n";\r
+        s += "ClickModifiers " + clickModifiers + "\n";\r
+        s += "PressModifiers " + pressModifiers + "\n";\r
+        return s;\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/input/InputProvider.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/input/InputProvider.java
new file mode 100644 (file)
index 0000000..1f1f56b
--- /dev/null
@@ -0,0 +1,72 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.input;\r
+\r
+\r
+/**\r
+ * InputProvider is used to listen inputs from AWT-thread, \r
+ * and then input actions can be polled from the provider.\r
+ * \r
+ * TODO : use methods instead of public members\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public interface InputProvider {\r
+    \r
+    \r
+    \r
+    public boolean keyPressed(int i);\r
+    \r
+    public boolean keyDown(int i);\r
+    \r
+    public boolean keyUp(int i);\r
+    \r
+    public int mouseX();\r
+    \r
+    public int mouseY();\r
+    \r
+    public int prevMouseX();\r
+    \r
+    public int prevMouseY();\r
+    \r
+    public boolean mousePressed();\r
+    \r
+    public boolean mouseMoved();\r
+    \r
+    public boolean mouseReleased();\r
+    \r
+    public boolean mouseClicked();\r
+    \r
+    public boolean mouseDragged();\r
+    \r
+    public int pressModifiers();\r
+    \r
+    public int clickModifiers();\r
+    \r
+    public int dragModifiers();\r
+    \r
+    public int moveModifiers();\r
+    \r
+    public int clickButton();\r
+    \r
+    \r
+    public void update();\r
+    \r
+    // FIXME : when dnd is used, mouse inputs won't get passed\r
+    \r
+    public void setMouseX(int x);\r
+    public void setMouseY(int y);\r
+    public void setMouseMoved(boolean b);\r
+    \r
+    \r
+   \r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/input/SWTInputProvider.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/input/SWTInputProvider.java
new file mode 100644 (file)
index 0000000..a21d3b7
--- /dev/null
@@ -0,0 +1,511 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.input;\r
+\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.FocusEvent;\r
+import org.eclipse.swt.events.FocusListener;\r
+import org.eclipse.swt.events.KeyEvent;\r
+import org.eclipse.swt.events.KeyListener;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.events.MouseListener;\r
+import org.eclipse.swt.events.MouseMoveListener;\r
+import org.eclipse.swt.events.MouseTrackListener;\r
+\r
+public class SWTInputProvider implements KeyListener, MouseListener, MouseMoveListener, MouseTrackListener, InputProvider, FocusListener {\r
+    \r
+    private static final int PRESS_TIME = 200;\r
+    \r
+    private boolean keyPressed[] = new boolean[1024];\r
+    private boolean keyTemp[] = new boolean[1024];\r
+    private boolean keyDown[] = new boolean[1024];\r
+    private boolean keyUp[] = new boolean[1024];\r
+    \r
+    private int awtMouseX = 0;\r
+    private int awtMouseY = 0;\r
+    private boolean awtPressed = false;\r
+    private boolean awtDragged = false;\r
+    private boolean awtReleased = false;\r
+    private boolean awtMouseClicked = false;\r
+    private boolean awtMouseMoved = false;\r
+    \r
+    private boolean swtMouse1Down = false;\r
+    private boolean swtMouse2Down = false;\r
+    private boolean swtMouse3Down = false;\r
+    \r
+    long mouse1DownTime = 0;\r
+    long mouse2DownTime = 0;\r
+    long mouse3DownTime = 0;\r
+    \r
+    private int awtPressModifiers = 0;\r
+    private int awtDragModifiers = 0;\r
+    private int awtClickModifiers = 0;\r
+    private int awtMoveModifiers = 0;\r
+    private int awtClickButton = 0;\r
+     \r
+    private int mouseX = 0;\r
+    private int mouseY = 0;\r
+    \r
+    private int prevMouseX = 0;\r
+    private int prevMouseY = 0;\r
+    \r
+    private boolean mousePressed = false;\r
+    private boolean mouseDragged = false;\r
+    private boolean mouseReleased = false;\r
+    private boolean mouseClicked = false;\r
+    private boolean mouseMoved = false;\r
+    \r
+    private int pressModifiers = 0;\r
+    private int clickModifiers = 0;\r
+    private int dragModifiers = 0;\r
+    private int clickButton = 0;\r
+    private int moveModifiers = 0;\r
+    \r
+    public SWTInputProvider() {\r
+        reset();\r
+    }\r
+    \r
+    private void reset() {\r
+       for (int i = 0; i < keyDown.length; i++) {\r
+            keyDown[i] = false;\r
+            keyTemp[i] = false;\r
+            keyPressed[i] = false; \r
+            keyUp[i] = false;\r
+        }\r
+        mousePressed = false;\r
+        mouseDragged = false;\r
+        mouseReleased = false;\r
+        mouseClicked = false;\r
+        mouseMoved = false;\r
+        \r
+        pressModifiers = 0;\r
+        clickModifiers = 0;\r
+        dragModifiers = 0;\r
+        clickButton = 0;\r
+        moveModifiers = 0;\r
+    }\r
+    \r
+    public boolean keyPressed(int i) {\r
+        return keyPressed[i];\r
+    }\r
+    \r
+    public boolean keyDown(int i) {\r
+        return keyDown[i];\r
+    }\r
+    \r
+    public boolean keyUp(int i) {\r
+       return keyUp[i];\r
+    }\r
+    \r
+    public int mouseX() {\r
+        return mouseX;\r
+    }\r
+    \r
+    public int mouseY() {\r
+        return mouseY;\r
+    }\r
+    \r
+    public int prevMouseX() {\r
+        return prevMouseX;\r
+    }\r
+    \r
+    public int prevMouseY() {\r
+        return prevMouseY;\r
+    }\r
+    \r
+    public boolean mousePressed() {\r
+        return mousePressed;\r
+    }\r
+    \r
+    public boolean mouseMoved() {\r
+        return mouseMoved;\r
+    }\r
+    \r
+    public boolean mouseReleased() {\r
+        return mouseReleased;\r
+    }\r
+    \r
+    public boolean mouseClicked() {\r
+        return mouseClicked;\r
+    }\r
+    \r
+    public boolean mouseDragged() {\r
+        return mouseDragged;\r
+    }\r
+    \r
+    public int pressModifiers() {\r
+        return pressModifiers;\r
+    }\r
+    \r
+    public int clickModifiers() {\r
+        return clickModifiers;\r
+    }\r
+    \r
+    public int dragModifiers() {\r
+        return dragModifiers;\r
+    }\r
+    \r
+    public int moveModifiers() {\r
+        return moveModifiers;\r
+    }\r
+    \r
+    public int clickButton() {\r
+        return clickButton;\r
+    }\r
+    \r
+    \r
+    public void update() {\r
+        prevMouseX = mouseX;\r
+        prevMouseY = mouseY;\r
+        mouseX = awtMouseX;\r
+        mouseY = awtMouseY;\r
+        //System.out.println(mouseX + " " + mouseY);\r
+        mousePressed = awtPressed;\r
+        awtPressed = false;\r
+        mouseReleased = awtReleased;\r
+        awtReleased = false;\r
+        mouseMoved = awtMouseMoved;\r
+        awtMouseMoved = false;\r
+        mouseDragged = awtDragged;\r
+        awtDragged = false;\r
+        mouseClicked = awtMouseClicked;\r
+        awtMouseClicked = false;\r
+        pressModifiers = awtPressModifiers;\r
+       // awtPressModifiers = 0;\r
+        clickModifiers = awtClickModifiers;\r
+        //awtClickModifiers = 0;\r
+        dragModifiers = awtDragModifiers;\r
+       // awtDragModifiers = 0;\r
+        moveModifiers = awtMoveModifiers;\r
+        //awtMoveModifiers = 0;\r
+        clickButton = awtClickButton;\r
+        awtClickButton = 0;\r
+        for (int i = 0; i < keyDown.length; i++) {\r
+            if (keyDown[i] && !keyTemp[i]) {\r
+              keyTemp[i] = true;\r
+              keyPressed[i] = true;\r
+            }\r
+            else if (keyDown[i] && keyTemp[i]) {\r
+             keyPressed[i] = false;\r
+            }\r
+            else if (!keyDown[i] && keyTemp[i]) {\r
+               keyUp[i] = true;\r
+               keyTemp[i] = false;\r
+                keyPressed[i] = false;\r
+            }\r
+            else if (!keyDown[i]) {\r
+              keyTemp[i] = false;\r
+              keyPressed[i] = false;\r
+              keyUp[i] = false;\r
+            }\r
+          }\r
+    \r
+    }\r
+    \r
\r
+\r
+\r
+    private int getAWTKeyCode(int swtKeyCode) {\r
+        if(swtKeyCode > keyDown.length) {\r
+            int keyCode = 0;\r
+            switch (swtKeyCode) {\r
+            case SWT.CTRL:\r
+                keyCode = java.awt.event.KeyEvent.VK_CONTROL;\r
+                break;\r
+            case SWT.ALT:\r
+                keyCode = java.awt.event.KeyEvent.VK_ALT;\r
+                break;\r
+            \r
+            case SWT.SHIFT:\r
+                keyCode = java.awt.event.KeyEvent.VK_SHIFT;\r
+                break;\r
+            case SWT.ARROW_LEFT:\r
+                keyCode = java.awt.event.KeyEvent.VK_LEFT;\r
+                break;\r
+            case SWT.ARROW_RIGHT:\r
+                keyCode = java.awt.event.KeyEvent.VK_RIGHT;\r
+                break;\r
+            case SWT.ARROW_UP:\r
+                keyCode = java.awt.event.KeyEvent.VK_UP;\r
+                break;\r
+            case SWT.ARROW_DOWN:\r
+                keyCode = java.awt.event.KeyEvent.VK_DOWN;\r
+                break;\r
+            case SWT.KEYPAD_0:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD0;\r
+                break;\r
+            case SWT.KEYPAD_1:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD1;\r
+                break;\r
+            case SWT.KEYPAD_2:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD2;\r
+                break;\r
+            case SWT.KEYPAD_3:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD3;\r
+                break;\r
+            case SWT.KEYPAD_4:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD4;\r
+                break;\r
+            case SWT.KEYPAD_5:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD5;\r
+                break;\r
+            case SWT.KEYPAD_6:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD6;\r
+                break;\r
+            case SWT.KEYPAD_7:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD7;\r
+                break;\r
+            case SWT.KEYPAD_8:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD8;\r
+                break;\r
+            case SWT.KEYPAD_9:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUMPAD9;\r
+                break;\r
+            case SWT.KEYPAD_CR:\r
+                keyCode = java.awt.event.KeyEvent.VK_ENTER;\r
+                break;\r
+            case SWT.NUM_LOCK:\r
+                keyCode = java.awt.event.KeyEvent.VK_NUM_LOCK;\r
+                break;\r
+            case SWT.SCROLL_LOCK:\r
+                keyCode = java.awt.event.KeyEvent.VK_SCROLL_LOCK;\r
+                break;\r
+            case SWT.CAPS_LOCK:\r
+                keyCode = java.awt.event.KeyEvent.VK_CAPS_LOCK;\r
+                break;\r
+            case SWT.INSERT:\r
+                keyCode = java.awt.event.KeyEvent.VK_INSERT;\r
+                break;\r
+            case SWT.HOME:\r
+                keyCode = java.awt.event.KeyEvent.VK_HOME;\r
+                break;\r
+            case SWT.END:\r
+                keyCode = java.awt.event.KeyEvent.VK_END;\r
+                break;\r
+            case SWT.PAGE_UP:\r
+                keyCode = java.awt.event.KeyEvent.VK_PAGE_UP;\r
+                break;\r
+            case SWT.PAGE_DOWN:\r
+                keyCode = java.awt.event.KeyEvent.VK_PAGE_DOWN;\r
+                break;\r
+            case SWT.PAUSE:\r
+                keyCode = java.awt.event.KeyEvent.VK_PAUSE;   \r
+                break;\r
+            case SWT.BREAK:\r
+                keyCode = java.awt.event.KeyEvent.VK_PAUSE;   \r
+                break;\r
+            case SWT.PRINT_SCREEN:\r
+                keyCode = java.awt.event.KeyEvent.VK_PRINTSCREEN;   \r
+                break;   \r
+            case SWT.HELP:\r
+                keyCode = java.awt.event.KeyEvent.VK_HELP;\r
+                break;\r
+            default :\r
+                keyCode = 0;\r
+               break;\r
+            }\r
+            \r
+            return keyCode;\r
+        } else if (swtKeyCode == 8) {\r
+               return java.awt.event.KeyEvent.VK_BACK_SPACE;\r
+        }\r
+        else if (swtKeyCode >= 97 )\r
+               return swtKeyCode - 32;\r
+        else\r
+               return swtKeyCode;\r
+    }\r
+\r
+    \r
+    /* (non-Javadoc)\r
+     * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent)\r
+     */\r
+    public void keyPressed(KeyEvent arg0) {\r
+       //System.out.println("KeyPressed " + arg0.character + " " + arg0.keyCode + " " + getAWTKeyCode(arg0.keyCode));\r
+           keyDown[getAWTKeyCode(arg0.keyCode)] = true;\r
+    }\r
+    \r
+    /* (non-Javadoc)\r
+     * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent)\r
+     */\r
+    public void keyReleased(KeyEvent arg0) {\r
+       //System.out.println("KeyReleased " + arg0.character + " " + arg0.keyCode + " " + getAWTKeyCode(arg0.keyCode));\r
+        \r
+           keyDown[getAWTKeyCode(arg0.keyCode)] = false;\r
+    }\r
+\r
+    public void mouseMove(MouseEvent e) {\r
+        awtMouseX = e.x;\r
+        awtMouseY = e.y;      \r
+        if (swtMouse1Down || swtMouse2Down || swtMouse3Down) {\r
+               // comparing times so that drag event won't be send at the time when mouse button was pressed\r
+               long time = e.time & 0xFFFFFFFFL;\r
+               boolean drag = false;\r
+               if (swtMouse1Down) {\r
+                       drag = time > mouse1DownTime;\r
+               } else if (swtMouse2Down) {\r
+                       drag = time > mouse2DownTime;\r
+               } else {\r
+                       drag = time > mouse3DownTime;\r
+               }\r
+               if (drag)  {\r
+                       awtDragged = true;\r
+                       awtDragModifiers = createButtonMask(e);\r
+               }\r
+        } else {\r
+            awtMoveModifiers = createButtonMask(e);\r
+            awtMouseMoved = true;\r
+        }\r
+    }\r
+\r
+    public void mouseDoubleClick(MouseEvent e) {\r
+        /*\r
+        awtMouseClicked = true;\r
+        awtClickModifiers = createButtonMask(e);\r
+        switch (e.button) {\r
+            case 1:\r
+                awtClickButton = java.awt.event.MouseEvent.BUTTON1;\r
+                break;\r
+            case 2:\r
+                awtClickButton = java.awt.event.MouseEvent.BUTTON2;\r
+                break;\r
+            case 3:\r
+                awtClickButton = java.awt.event.MouseEvent.BUTTON3;\r
+                break;\r
+                \r
+        }\r
+        */\r
+    }\r
+    \r
+    private int createButtonMask(MouseEvent e) {\r
+        int mask = 0;\r
+        if (swtMouse1Down)\r
+            mask |= java.awt.event.MouseEvent.BUTTON1_DOWN_MASK | java.awt.event.MouseEvent.BUTTON1_MASK;\r
+        if (swtMouse2Down)\r
+            mask |= java.awt.event.MouseEvent.BUTTON2_DOWN_MASK | java.awt.event.MouseEvent.BUTTON2_MASK;\r
+        if (swtMouse3Down)\r
+            mask |= java.awt.event.MouseEvent.BUTTON3_DOWN_MASK | java.awt.event.MouseEvent.BUTTON3_MASK;\r
+        if ((e.stateMask & SWT.CTRL) > 0) \r
+              mask |= java.awt.event.MouseEvent.CTRL_DOWN_MASK | java.awt.event.MouseEvent.CTRL_MASK;\r
+        if ((e.stateMask & SWT.CTRL) > 0)  \r
+              mask |= java.awt.event.MouseEvent.ALT_DOWN_MASK | java.awt.event.MouseEvent.ALT_MASK;\r
+        \r
+        \r
+        return mask;\r
+    }\r
+\r
+    public void mouseDown(MouseEvent e) {\r
+        switch (e.button) {\r
+            case 1:\r
+                swtMouse1Down = true;\r
+                mouse1DownTime = e.time & 0xFFFFFFFFL;\r
+                break;\r
+            case 2:\r
+                swtMouse2Down = true;\r
+                mouse2DownTime = e.time & 0xFFFFFFFFL;\r
+                break;\r
+            case 3:\r
+                swtMouse3Down = true;\r
+                mouse3DownTime = e.time & 0xFFFFFFFFL;\r
+        };\r
+        \r
+        awtPressed = true;\r
+        awtPressModifiers = createButtonMask(e);\r
+    }\r
+\r
+    public void mouseUp(MouseEvent e) {\r
+        long mouseUpTime = e.time & 0xFFFFFFFFL;\r
+        long delta = 1000;\r
+        switch (e.button) {\r
+        case 1:\r
+            swtMouse1Down = false;\r
+            delta = mouseUpTime - mouse1DownTime;\r
+            break;\r
+        case 2:\r
+            swtMouse2Down = false;\r
+            delta = mouseUpTime - mouse2DownTime;\r
+            break;\r
+        case 3:\r
+            swtMouse3Down = false;\r
+            delta = mouseUpTime - mouse3DownTime;\r
+        };\r
+        awtReleased = true;\r
+        \r
+        if (delta < PRESS_TIME) {\r
+            awtMouseClicked = true;\r
+            awtClickModifiers = createButtonMask(e);\r
+            switch (e.button) {\r
+                case 1:\r
+                    awtClickButton = java.awt.event.MouseEvent.BUTTON1;\r
+                    break;\r
+                case 2:\r
+                    awtClickButton = java.awt.event.MouseEvent.BUTTON2;\r
+                    break;\r
+                case 3:\r
+                    awtClickButton = java.awt.event.MouseEvent.BUTTON3;\r
+                    break;\r
+                    \r
+            }\r
+        }\r
+    }\r
+    \r
+    \r
+    public void mouseEnter(MouseEvent e) {\r
+        \r
+    }\r
+    \r
+    public void mouseExit(MouseEvent e) {\r
+        awtReleased = false;\r
+        awtPressed = false;\r
+        swtMouse1Down = false;\r
+        swtMouse2Down = false;\r
+        swtMouse3Down = false;\r
+        \r
+        \r
+    }\r
+    \r
+    public void focusGained(FocusEvent e) {\r
+\r
+    }\r
+    \r
+    public void focusLost(FocusEvent e) {\r
+       reset();\r
+    }\r
+    \r
+    public void mouseHover(MouseEvent e) {\r
+\r
+    }\r
+    \r
+    public void setMouseMoved(boolean b) {\r
+       awtMouseMoved = b;\r
+    }\r
+    \r
+    public void setMouseX(int x) {\r
+       awtMouseX = x;\r
+    }\r
+    \r
+    public void setMouseY(int y) {\r
+       awtMouseY = y;\r
+    }\r
+\r
+    public String toString() {\r
+        String s = "";\r
+        s += "(" + mouseX + "," + mouseY + ")\n";\r
+        s += "Pressed " + mousePressed + "\n";\r
+        s += "Released " + mouseReleased + "\n";\r
+        s += "Moved " + mouseMoved + "\n";\r
+        s += "Dragged " + mouseDragged + "\n";\r
+        s += "Clicked " + mouseClicked + "\n";\r
+        s += "DragModifiers " + dragModifiers + "\n";\r
+        s += "ClickModifiers " + clickModifiers + "\n";\r
+        s += "PressModifiers " + pressModifiers + "\n";\r
+        return s;\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/preferences/G3DPreferencesPage.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/preferences/G3DPreferencesPage.java
new file mode 100644 (file)
index 0000000..98230eb
--- /dev/null
@@ -0,0 +1,121 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.preferences;
+
+import org.eclipse.jface.preference.*;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.IWorkbench;
+import org.simantics.proconf.g3d.Activator;
+
+
+/**
+ * This class represents a preference page that
+ * is contributed to the Preferences dialog. By 
+ * subclassing <samp>FieldEditorPreferencePage</samp>, we
+ * can use the field support built into JFace that allows
+ * us to create a page that is small and knows how to 
+ * save, restore and apply itself.
+ * <p>
+ * This page is used to modify preferences only. They
+ * are stored in the preference store that belongs to
+ * the main plug-in class. That way, preferences can
+ * be accessed directly via the preference store.
+ */
+
+public class G3DPreferencesPage
+       extends FieldEditorPreferencePage
+       implements IWorkbenchPreferencePage {
+
+       public G3DPreferencesPage() {
+               super(GRID);
+               setPreferenceStore(Activator.getDefault().getPreferenceStore());
+               setDescription("A demonstration of a preference page implementation");
+       }
+       
+       /**
+        * Creates the field editors. Field editors are abstractions of
+        * the common GUI blocks needed to manipulate various types
+        * of preferences. Each field editor knows how to save and
+        * restore itself.
+        */
+       public void createFieldEditors() {
+//             addField(new DirectoryFieldEditor(PreferenceConstants.P_PATH, 
+//                             "&Directory preference:", getFieldEditorParent()));
+//             addField(
+//                     new BooleanFieldEditor(
+//                             PreferenceConstants.P_BOOLEAN,
+//                             "&An example of a boolean preference",
+//                             getFieldEditorParent()));
+//
+//             addField(new RadioGroupFieldEditor(
+//                             PreferenceConstants.P_CHOICE,
+//                     "An example of a multiple-choice preference",
+//                     1,
+//                     new String[][] { { "&Choice 1", "choice1" }, {
+//                             "C&hoice 2", "choice2" }
+//             }, getFieldEditorParent()));
+//             addField(
+//                     new StringFieldEditor(PreferenceConstants.P_STRING, "A &text preference:", getFieldEditorParent()));
+               addField(new BooleanFieldEditor(PreferenceConstants.SHADOWS,"Use Shadows",getFieldEditorParent()));
+               addField(new RadioGroupFieldEditor(PreferenceConstants.POST_PROCESS, "Post Processing", 1,
+                               new String[][] { { "None", "none" }, 
+                                                                { "Sketch", "sketch" },
+                                                                { "Bloom", "bloom" }}, 
+                                                                getFieldEditorParent()));
+               addField(new ScaleFieldEditor(PreferenceConstants.GIZMO_SCALE,"Gizmo scale",getFieldEditorParent(),5,100,1,10) {
+                       private double oldValue;
+                       
+                       @Override
+                       protected void doStore() {
+                               getPreferenceStore()
+                .setValue(getPreferenceName(), scale.getSelection()*0.1);
+                       }
+                       
+                       @Override
+                       protected void doLoadDefault() {
+                               if (scale != null) {
+                           double value = getPreferenceStore().getDefaultDouble(getPreferenceName());
+                           scale.setSelection((int)(value*10.0));
+                       }
+                       valueChanged();
+                       }
+                       
+                       @Override
+                       protected void doLoad() {
+                               if (scale != null) {
+                                       double value = getPreferenceStore().getDouble(getPreferenceName());
+                           scale.setSelection((int)(value*10.0));
+                           oldValue = value;
+                       };
+                       }
+                       
+                       @Override
+                       protected void valueChanged() {
+                       setPresentsDefaultValue(false);
+
+                       double newValue = scale.getSelection()*0.1;
+                       if (newValue != oldValue) {
+                           fireStateChanged(IS_VALID, false, true);
+                           fireValueChanged(VALUE, new Double(oldValue),
+                                   new Double(newValue));
+                           oldValue = newValue;
+                       }
+                   }
+               });
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+        */
+       public void init(IWorkbench workbench) {
+       }
+       
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/preferences/PreferenceConstants.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/preferences/PreferenceConstants.java
new file mode 100644 (file)
index 0000000..c0163e7
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.preferences;
+
+/**
+ * Constant definitions for plug-in preferences
+ */
+public class PreferenceConstants {
+
+       public static final String POST_PROCESS = "postProcess";
+       public static final String SHADOWS = "shadows";
+       public static final String GIZMO_SCALE = "gizmoScale";
+       
+}
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/preferences/PreferenceInitializer.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/preferences/PreferenceInitializer.java
new file mode 100644 (file)
index 0000000..5a40d2f
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.simantics.proconf.g3d.Activator;
+
+
+/**
+ * Class used to initialize default preference values.
+ */
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+        */
+       public void initializeDefaultPreferences() {
+               IPreferenceStore store = Activator.getDefault()
+                               .getPreferenceStore();
+//             store.setDefault(PreferenceConstants.P_BOOLEAN, true);
+//             store.setDefault(PreferenceConstants.P_CHOICE, "choice2");
+//             store.setDefault(PreferenceConstants.P_STRING,"Default value");
+               store.setDefault(PreferenceConstants.POST_PROCESS, "none");
+               store.setDefault(PreferenceConstants.SHADOWS, true);
+               store.setDefault(PreferenceConstants.GIZMO_SCALE, 1.0);
+       }
+
+}
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/AbstractGraphicsNode.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/AbstractGraphicsNode.java
new file mode 100644 (file)
index 0000000..d1dde38
--- /dev/null
@@ -0,0 +1,200 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.AxisAngle4f;\r
+import javax.vecmath.Matrix3d;\r
+import javax.vecmath.Quat4d;\r
+import javax.vecmath.Vector3f;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.base.G3DTools;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.base.VecmathJmeTools;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+\r
+import com.jme.scene.Node;\r
+\r
+\r
+public abstract class AbstractGraphicsNode implements ISelectableNode {\r
+\r
+       protected ThreeDimensionalEditorBase editor;\r
+       \r
+    protected IGraphicsNode parent = null;\r
+\r
+    protected Resource shapeResource = null;\r
+  \r
+    protected boolean selected;\r
+\r
+    protected Node parentGroup = null;\r
+    protected Node transform = null;\r
+   // protected Node center = null;\r
+    \r
+    protected String id;\r
\r
+    private ArrayList<IGraphicsNode> children = new ArrayList<IGraphicsNode>();\r
+\r
+    public AbstractGraphicsNode(ThreeDimensionalEditorBase editor, IGraphicsNode parent, Graph graph, Resource shapeResource) {\r
+        assert (parent != null);\r
+        this.editor = editor;\r
+        this.parent = parent;\r
+        this.parentGroup = parent.getGroup();\r
+        this.shapeResource = shapeResource;\r
+        this.id = editor.getScenegraphAdapter().getNodeUID(shapeResource);\r
+        createGroups();\r
+        updateTransform(graph);\r
+        parent.addChild(this);\r
+    }\r
+    \r
+    @Override\r
+    public String getID() {\r
+       return id;\r
+    }\r
+    \r
+    public void setID(String id) {\r
+       this.id = id;\r
+    }\r
+\r
+    \r
+    /* (non-Javadoc)\r
+     * @see fi.vtt.proconf.shapeeditor.geometry.IGraphicsNode#getParent()\r
+     */\r
+    public IGraphicsNode getParent() {\r
+        return parent;\r
+    }\r
+    \r
+    public Collection<IGraphicsNode> getChildren() {\r
+        return children;\r
+    }\r
+\r
+    private void createGroups() {\r
+       transform = new Node(); // TODO : uid\r
+       parentGroup.attachChild(transform);\r
+    }\r
+    \r
+    public void addChild(IGraphicsNode node) {\r
+        children.add(node);\r
+    }\r
+    \r
+    public void removeChild(IGraphicsNode node) {\r
+        children.remove(node);\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see fi.vtt.proconf.shapeeditor.geometry.IGraphicsNode#getGroup()\r
+     */\r
+    public Node getGroup() {\r
+       //return center;\r
+       \r
+       return transform;\r
+    }\r
+\r
+    /**\r
+     * Updates rotation and translation of the shape without recalculating\r
+     * geometry\r
+     */\r
+    public void updateTransform(Graph graph) {\r
+       G3DNode shape = getG3DNode(graph);\r
+       if (shape.getLocalPosition() != null)\r
+            transform.setLocalTranslation(VecmathJmeTools.get(G3DTools.getVectorFloat(shape.getLocalPosition())));\r
+        if (shape.getLocalOrientation() != null) \r
+            transform.setLocalRotation(VecmathJmeTools.get(G3DTools.getOrientationFloat(shape.getLocalOrientation())));\r
+//        if (GraphicsNodeTools.hasCenter(shape)) {\r
+//             center.setLocalTranslation(VecmathJmeTools.get(GraphicsNodeTools.getCenterFloat(shape)));\r
+//        }\r
+        // FIXME : typically transforms are updated once per frame (root as initiator) but with threaded access transformation may be read wrong.\r
+        transform.updateWorldVectors();\r
+        editor.getScenegraphAdapter().setChanged(true);\r
+    }\r
+\r
+\r
+    \r
+    protected void update(Matrix3d aa) {\r
+        transform.setLocalRotation(VecmathJmeTools.get(aa));\r
+    }\r
+    protected void update(AxisAngle4f aa) {\r
+        transform.setLocalRotation(VecmathJmeTools.get(aa));\r
+    }\r
+    \r
+    protected void update(AxisAngle4d aa) {\r
+        transform.setLocalRotation(VecmathJmeTools.get(aa));\r
+    }\r
+    \r
+    protected void update(Quat4d q) {\r
+        transform.setLocalRotation(VecmathJmeTools.get(q));\r
+    }\r
+    \r
+    protected void update(Vector3f v) {\r
+        transform.setLocalTranslation(VecmathJmeTools.get(v));\r
+    }\r
+\r
+\r
+    public void setSelected(boolean selected) {\r
+        if (this.selected == selected)\r
+            return;\r
+        this.selected = selected;\r
+    }\r
+\r
+    public boolean isSelected() {\r
+        return selected;\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see fi.vtt.proconf.shapeeditor.geometry.IGraphicsNode#getResource()\r
+     */\r
+    public Resource getResource() {\r
+        return shapeResource;\r
+    }\r
+\r
+    public G3DNode getG3DNode(Graph graph) {\r
+        return new G3DNode(graph,shapeResource);\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see fi.vtt.proconf.shapeeditor.geometry.IGraphicsNode#dispose()\r
+     */\r
+    public void dispose() {\r
+//        if (children.size() != 0) {\r
+//            System.out.print(getResource() + " contains children: ");\r
+//            ArrayList<IGraphicsNode> c = new ArrayList<IGraphicsNode>(children);\r
+//            for (IGraphicsNode n : c) {\r
+//              System.out.print(n.getResource() + " ");\r
+//            }\r
+//            System.out.println();\r
+//            return;\r
+//        }\r
+        assert (children.size() == 0);\r
+\r
+        transform.removeFromParent();\r
+        transform.dispose();\r
+        if (parent != null)\r
+            parent.removeChild(this);\r
+    }\r
+    \r
+    \r
+    public abstract void setPickable(boolean pickable);\r
+    \r
+    public String toString() {\r
+        return  this.getClass().toString();\r
+    }\r
+    \r
+    @Override\r
+    public int hashCode() {\r
+       return shapeResource.hashCode();\r
+    }\r
+\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/IGeometryNode.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/IGeometryNode.java
new file mode 100644 (file)
index 0000000..94d3dae
--- /dev/null
@@ -0,0 +1,19 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import org.simantics.db.Graph;\r
+\r
+public interface IGeometryNode extends IGraphicsNode{\r
+       \r
+       public void updateGeometry(Graph graph);\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/IGraphicsNode.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/IGraphicsNode.java
new file mode 100644 (file)
index 0000000..a72aa5f
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+\r
+import com.jme.scene.Node;\r
+\r
+public interface IGraphicsNode {\r
+\r
+    public IGraphicsNode getParent();\r
+\r
+    public Node getGroup();\r
+\r
+    public Resource getResource();\r
+\r
+    /**\r
+     * Disposes the node. Disposing of node that has children is not allowed.\r
+     */\r
+    public void dispose();\r
+\r
+    public void updateTransform(Graph graph);\r
+    \r
+    public G3DNode getG3DNode(Graph graph);\r
+    \r
+    public void addChild(IGraphicsNode node);\r
+    public void removeChild(IGraphicsNode node);\r
+    public Collection<IGraphicsNode> getChildren();\r
+\r
+    \r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ISelectableNode.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ISelectableNode.java
new file mode 100644 (file)
index 0000000..4abd1b3
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+public interface ISelectableNode extends IGraphicsNode{\r
+    public void setVisible(boolean visible);\r
+    public boolean isVisible();\r
+    public void setSelected(boolean selected);\r
+    public boolean isSelected();\r
+    public void setHighlighted(boolean higlighted);\r
+    public boolean isHighlighted();\r
+    public void setPickable(boolean pickable);\r
+    public String getID();\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ModelNode.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ModelNode.java
new file mode 100644 (file)
index 0000000..40e845a
--- /dev/null
@@ -0,0 +1,195 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.animation.Animatable;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.stubs.G3DModel;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+import org.simantics.utils.ErrorLogger;\r
+\r
+public class ModelNode extends AbstractGraphicsNode implements Animatable, IGeometryNode{\r
+       protected List<ShapeNode> shapes = new ArrayList<ShapeNode>();\r
+    private boolean highlighted;\r
+   \r
+    protected Resource modelResource;\r
+    \r
+    private boolean geometryCreated = false;\r
+    \r
+    public ModelNode(ThreeDimensionalEditorBase editor,IGraphicsNode parent, Graph graph, Resource shapeResource) {\r
+       super(editor,parent, graph, shapeResource);\r
+       \r
+    }\r
+    \r
+    protected void createGeometry(Graph graph) {\r
+       \r
+       if (modelResource != null) {\r
+               G3DModel model = getG3DModel(graph);\r
+            Collection<G3DNode> nodes = model.getChild();\r
+            if (nodes.size() == 0) {\r
+                ErrorLogger.defaultLogError("ModelNode " + model.getResource() + " has no shapes", null);\r
+                return;\r
+            }\r
+            for (G3DNode node: nodes) {\r
+                ShapeNode shape = new ShapeNode(editor,this,graph,node.getResource());\r
+                shapes.add(shape);\r
+\r
+                shape.setID(getID());\r
+                shape.setVisible(true);\r
+                shape.updateGeometry(graph);\r
+                createRecursive(graph,shape);\r
+            } \r
+            geometryCreated = true;\r
+        }\r
+    }\r
+    \r
+    private void createRecursive(Graph graph,IGraphicsNode parentNode) {\r
+       Collection<G3DNode> nodes = parentNode.getG3DNode(graph).getChild();\r
+        for (G3DNode node: nodes) {\r
+                if (node.getRelatedObjects(Resources.g3dResource.GeometryDefinitionOf).size() == 0) {\r
+                        ShapeNode shape = new ShapeNode(editor,parentNode,graph,node.getResource());\r
+                        shapes.add(shape);\r
+\r
+                        shape.setID(getID());\r
+                        shape.setVisible(true);\r
+                        shape.updateGeometry(graph);\r
+                        createRecursive(graph,shape);\r
+                }\r
+         } \r
+    }\r
+    \r
+    public void updateGeometry(Graph graph) {\r
+       if (!geometryCreated) {\r
+               createGeometry(graph);\r
+               return;\r
+       }\r
+       updateTransform(graph);\r
+//     for (IGraphicsNode node : getChildren()) {\r
+//                     ((IGeometryNode)node).updateGeometry();\r
+//             }\r
+       for (ShapeNode node : shapes)\r
+            node.updateGeometry(graph);\r
+    }\r
+    \r
+    public boolean isVisible() {\r
+        for (IGraphicsNode n : getChildren())\r
+                       if (n instanceof ISelectableNode)\r
+               if (!((ISelectableNode)n).isVisible())\r
+                       return false;\r
+       return true;\r
+   }\r
+    \r
+    public void setVisible(boolean visible) {\r
+        for (IGraphicsNode node : getChildren()) {\r
+               if (node instanceof ISelectableNode)\r
+                       ((ISelectableNode)node).setVisible(visible);\r
+        }\r
+    }\r
+    \r
+    @Override\r
+    public void dispose() {\r
+        // shapes must be removed reverse order (leafs first)\r
+       for (int i = shapes.size() - 1; i >= 0; i--) {\r
+               shapes.get(i).dispose();\r
+       }\r
+        super.dispose();\r
+    }\r
+    \r
+    \r
+    @Override\r
+    public void setPickable(boolean pickable) {\r
+        for(ShapeNode n : shapes) {\r
+            n.setPickable(pickable);\r
+        }\r
+    }\r
+    \r
+    public boolean isHighlighted() {\r
+        return highlighted;\r
+    }\r
+    \r
+    public void setHighlighted(boolean selected) {\r
+        if (this.highlighted == selected)\r
+            return;\r
+        this.highlighted = selected;\r
+        for (ShapeNode n : shapes)\r
+            n.setHighlighted(selected);\r
+        \r
+    }\r
+    \r
+    @Override\r
+    public void setSelected(boolean selected) {\r
+        if (this.selected == selected)\r
+            return;\r
+        this.selected = selected;\r
+        for (ShapeNode n : shapes)\r
+            n.setSelected(selected);\r
+    }\r
+    \r
+    public void animate(double delta, double frameTime) {\r
+        for (ShapeNode n : shapes)\r
+            n.animate(delta,frameTime);\r
+    }\r
+    \r
+    public G3DModel getG3DModel(Graph graph) {\r
+       return new G3DModel(graph, modelResource);\r
+    }\r
+    \r
+    public boolean setAnimation(Graph graph, Resource animation) {\r
+        if (modelResource == null) {\r
+            ErrorLogger.getDefault().logWarning("Cannot set animation for " + shapeResource + " since it has no graphics", null);\r
+            return false;    \r
+        }\r
+        Collection<Resource> animations = graph.getObjects(modelResource, Resources.animationResource.HasAnimation);\r
+        if (!animations.contains(animation)) {\r
+            ErrorLogger.getDefault().logWarning("Cannot set animation for " + shapeResource + " since it doesn't have requested animation " + animation.getResource(), null);\r
+            return false;\r
+        }\r
+  \r
+        boolean set = false;\r
+        for (ShapeNode n : shapes) {\r
+            if (n.setAnimation(graph,animation))\r
+                set = true;\r
+        }\r
+        return set;\r
+    }\r
+    \r
+    public boolean setRandomAnimation(Graph graph) {\r
+        if (modelResource == null) {\r
+            ErrorLogger.getDefault().logWarning("Cannot set animation for " + shapeResource + " since it has no graphics", null);\r
+            return false;    \r
+        }\r
+        G3DModel model = getG3DModel(graph);\r
+        Collection<org.simantics.g2d.stubs.anim.Animation> animations = model.getAnimation();\r
+        int num = animations.size();\r
+        if (num == 0) {\r
+            ErrorLogger.getDefault().logWarning("Cannot set animation for " + shapeResource + " since it has no animations", null);\r
+            return false;            \r
+        }\r
+        int random = (int)Math.round(Math.random() * (num-1));\r
+        Iterator<org.simantics.g2d.stubs.anim.Animation> i = animations.iterator();\r
+        while(random > 0) {\r
+            i.next();\r
+            random--;\r
+        }\r
+        return setAnimation(graph,i.next().getResource());\r
+        \r
+    }\r
+    \r
+    \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/NonTransformableNode.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/NonTransformableNode.java
new file mode 100644 (file)
index 0000000..2c02097
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+\r
+import com.jme.scene.Node;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+\r
+public abstract class NonTransformableNode implements IGraphicsNode {\r
+\r
+    private IGraphicsNode parent;\r
+    private ArrayList<IGraphicsNode> children = new ArrayList<IGraphicsNode>();\r
+    protected Node parentGroup = null;\r
+    protected Resource nodeResource;\r
+\r
+    public NonTransformableNode(IGraphicsNode parent, Resource nodeResource) {\r
+       this.parent = parent;\r
+        this.nodeResource = nodeResource;\r
+        parentGroup = parent.getGroup();\r
+        parent.addChild(this);\r
+    }\r
+\r
+    public void addChild(IGraphicsNode node) {\r
+        children.add(node);\r
+        \r
+    }\r
+    \r
+    public Collection<IGraphicsNode> getChildren() {\r
+        return children;\r
+    }\r
+    \r
+    public void removeChild(IGraphicsNode node) {\r
+        children.remove(node);\r
+        \r
+    }\r
+\r
+    public void dispose() {\r
+        assert(children.size() == 0);\r
+        if (parent != null)\r
+            parent.removeChild(this);       \r
+    }\r
+\r
+    public G3DNode getG3DNode(Graph graph) {\r
+        return new G3DNode(graph, nodeResource);\r
+    }\r
+    \r
+    public Node getGroup() {\r
+       return parentGroup;\r
+    }\r
+\r
+\r
+    public IGraphicsNode getParent() {\r
+        return parent;\r
+    }\r
+\r
+\r
+    public Resource getResource() {\r
+        return nodeResource;\r
+    }\r
+\r
+    public void updateTransform(Graph graph) {\r
+        \r
+    }\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ParameterizedModelNode.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ParameterizedModelNode.java
new file mode 100644 (file)
index 0000000..511a2fa
--- /dev/null
@@ -0,0 +1,188 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.ContextGraph;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.equation.solver.Solver;\r
+import org.simantics.g2d.stubs.anim.Animation;\r
+import org.simantics.layer0.utils.Property;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.layer0.utils.Statement;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.stubs.G3DModel;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+import org.simantics.utils.ErrorLogger;\r
+\r
+/**\r
+ * IGraphicsNode for parameterized models. Implementation assumes that G3DNode itself does not contain\r
+ * graphical representation but has link to it. \r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class ParameterizedModelNode extends ModelNode {\r
+       \r
+       /**\r
+        * @param editor\r
+        * @param parent\r
+        * @param graph\r
+        * @param resource this node (G3DNode).\r
+        * @param nodeToModelRelation relation from this node to the model, or from type of this node to the model.\r
+        * @param modelToParametersRelation relation from the model to its sizing parameters\r
+        */\r
+       public ParameterizedModelNode(ThreeDimensionalEditorBase editor, IGraphicsNode parent, Graph graph, Resource resource, Resource nodeToModelRelation) {\r
+               super(editor,parent,graph,resource);\r
+               G3DNode shape = getG3DNode(graph);\r
+               List<IEntity> models = new ArrayList<IEntity>();\r
+               models.addAll(shape.getRelatedObjects(nodeToModelRelation));\r
+               if (models.size() == 0) {\r
+                       Collection<IEntity> types = shape.getTypes();\r
+                       for (IEntity type : types) {\r
+                               models.addAll(type.getRelatedObjects(nodeToModelRelation));\r
+                       }\r
+               }\r
+               if (models.size() != 1)\r
+                       throw new IllegalArgumentException("Cannot find proper model: found " + models.size() + " models.");\r
+               \r
+               this.modelResource = models.iterator().next().getResource();\r
+       }\r
+       \r
+       @Override\r
+       protected void createGeometry(Graph graph) {\r
+               super.createGeometry(createParameterization(graph));\r
+       }\r
+       \r
+       @Override\r
+       public void updateGeometry(Graph graph) {               \r
+               super.updateGeometry(createParameterization(graph));\r
+       }\r
+       \r
+       private void updateSizeParameters(ContextGraph graph, Solver solver) {\r
+               Builtins builtins = graph.getBuiltins();\r
+\r
+               \r
+               G3DNode node = getG3DNode(graph);\r
+               //Collection<Property> nodeProperties = node.getRelatedProperties(builtins.HasProperty);\r
+               Collection<Statement> nodeProperties = node.getRelatedStatements(builtins.HasProperty);\r
+               G3DModel model = getG3DModel(graph);\r
+               Collection<Property> modelProperties = model.getRelatedProperties(Resources.g3dResource.HasSizingParameter);\r
+               \r
+               // there are no relations between then nodes properties and the model's sizing parameters\r
+               // link between them is done by matching names\r
+               for (Property m : modelProperties) {\r
+                       boolean set = false;\r
+                       //if(m.canBeSet(builtins.HasName)) {\r
+\r
+                               String modelPropertyname = m.getAtMostOneRelatedProperty(builtins.HasName).getScalarString();\r
+                               for (Statement n : nodeProperties) {\r
+                                       String relationName = n.getPredicate().getName();\r
+                                       if (relationName.startsWith("Has "))\r
+                                               relationName = relationName.substring(4);\r
+                                       if (relationName.equalsIgnoreCase(modelPropertyname)) {\r
+                                               // found a match\r
+                                               // set property's value for Solver\r
+                                               solver.setValue(m.getResource(), graph.getValueAsObject(n.getObject().getResource()));\r
+                                               set = true;\r
+                                               break;\r
+                                       }\r
+                                       \r
+                               }\r
+                               if (!set) {\r
+                                       ErrorLogger.defaultLogError("Cannot map property " + modelPropertyname, null);\r
+                               }\r
+                       //}\r
+                       \r
+               }\r
+               \r
+               for (Property p : modelProperties) {\r
+                       IEntity t = EntityFactory.create(graph, p.getResource());\r
+                       Collection<IEntity> exp = t.getRelatedObjects(Resources.equationResource.HasTarget);\r
+                       if (exp.size() > 0) { \r
+                               Iterator<IEntity> i = exp.iterator();\r
+                               while(i.hasNext())\r
+                                       solver.evaluate(i.next());\r
+                       } else\r
+                               ErrorLogger.defaultLogError("Model property " + p + " is not bound to a expression",null);\r
+               }\r
+               solver.pushToGraph(graph);\r
+               Collection<Animation> animations = model.getAnimation();\r
+        for (Animation animation : animations) {\r
+               Collection<org.simantics.g2d.stubs.anim.Interpolator> interpolators = animation.getInterpolator();\r
+               for (org.simantics.g2d.stubs.anim.Interpolator interpolator : interpolators) {\r
+                       IEntity target = interpolator.getTarget();\r
+                       // check all model properties\r
+                       for (Property p : modelProperties) {\r
+                               IEntity t = EntityFactory.create(graph,p.getResource());\r
+                               // get parameterization equations\r
+                               Collection<IEntity> equations = t.getRelatedObjects(Resources.equationResource.HasTarget);\r
+                               // get parameterized values\r
+                               Collection<IEntity> parameterTargets = new ArrayList<IEntity>();\r
+                               for (IEntity eq : equations) {\r
+                                       Collection<IEntity> tgts = eq.getRelatedObjects(Resources.equationResource.HasTarget);\r
+                                       assert(tgts.size() == 1);\r
+                                       parameterTargets.add(tgts.iterator().next());\r
+                               }\r
+                               // do matching between interpolator targets and parameterized values\r
+                               // TODO : old system did not have inverse relations but current system does.\r
+                               //                it is possible to take interpolation target and find if it is connected to an equation\r
+                               //                this would make code much faster (no more stupid loops over everything)\r
+                               for (IEntity d : parameterTargets) {\r
+                                       if (d.getResource().equals(target.getResource())) {\r
+                                               // get default value for sizing property\r
+                                               Collection<IEntity> prop = t.getRelatedObjects(Resources.g3dResource.HasDefaultDoubleValue);\r
+                                               if (prop.size() == 1) {\r
+                                                       Resources.curveBuilder.parameterize(interpolator, prop.iterator().next().toProperty().getDoubleArray(), p.getDoubleArray());\r
+                                       } else {\r
+                                               ErrorLogger.defaultLogError("Cannot parameterize interpolator " + interpolator.getResource() + " of animation " + animation.getResource() + " since parameter " + p.getResource() + " has no default value", null);\r
+                                       }\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+        }\r
+       \r
+       }\r
+       \r
+       protected Graph createParameterization(Graph graph) {\r
+               // create ContextGraph if needed\r
+               ContextGraph g;\r
+               if (!(graph instanceof ContextGraph))\r
+                       g = new ContextGraph(graph);\r
+               else\r
+                       g = (ContextGraph)graph;\r
+               // set the context\r
+               g.setContext(this.shapeResource);\r
+               // create solver and calculate parameterized values\r
+               Solver solver = new Solver();\r
+               updateSizeParameters(g, solver);\r
+               // push parameterized values to context\r
+               solver.pushToGraph(g);\r
+               // return graph with parameterized values\r
+               return g;\r
+       }\r
+       \r
+       @Override\r
+       public boolean setAnimation(Graph graph, Resource animation) {          \r
+               return super.setAnimation(createParameterization(graph), animation);\r
+       }\r
+       \r
+       \r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/RootGraphicsNode.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/RootGraphicsNode.java
new file mode 100644 (file)
index 0000000..9937f4c
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.base.JmeRenderingComponent;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+\r
+import com.jme.scene.Node;\r
+\r
+public class RootGraphicsNode implements IGraphicsNode {\r
+\r
+       JmeRenderingComponent component;\r
+    Resource rootNode;\r
+    private ArrayList<IGraphicsNode> children = new ArrayList<IGraphicsNode>();\r
+\r
+    \r
+    public RootGraphicsNode(JmeRenderingComponent component, Resource rootNode) {\r
+        this.component = component;\r
+        this.rootNode = rootNode;\r
+    }\r
+    \r
+    public void addChild(IGraphicsNode node) {\r
+        children.add(node);\r
+    }\r
+    \r
+    public void removeChild(IGraphicsNode node) {\r
+        children.remove(node);\r
+    }\r
+    \r
+    public Collection<IGraphicsNode> getChildren() {\r
+        return children;\r
+    }\r
+\r
+    public void dispose() {\r
+        //throw new RuntimeException("Root cannot be disposed");\r
+    }\r
+\r
+    public Node getGroup() {\r
+       return component.getShadowRoot();\r
+    }\r
+\r
+    public IGraphicsNode getParent() {\r
+        return null;\r
+    }\r
+\r
+    public Resource getResource() {\r
+        return rootNode;\r
+    }\r
+\r
+    public void updateTransform(Graph graph) {\r
+\r
+    }\r
+    \r
+    public String toString() {\r
+        return this.getClass().toString();\r
+    }\r
+\r
+    public G3DNode getG3DNode(Graph graph) {\r
+        return new G3DNode(graph, rootNode);\r
+    }\r
+    \r
+\r
+\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ShapeNode.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/scenegraph/ShapeNode.java
new file mode 100644 (file)
index 0000000..7c89be4
--- /dev/null
@@ -0,0 +1,719 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Quat4d;\r
+\r
+import org.simantics.g2d.stubs.anim.Interpolator;\r
+import org.simantics.animation.curve.SlerpCurve;\r
+import org.simantics.animation.curve.TCBCurve;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.animation.Animatable;\r
+import org.simantics.proconf.g3d.animation.Animation;\r
+import org.simantics.proconf.g3d.animation.ChanneledColorInterpolator;\r
+import org.simantics.proconf.g3d.animation.ChanneledPositionInterpolator;\r
+import org.simantics.proconf.g3d.animation.ConstantInterpolator;\r
+import org.simantics.proconf.g3d.animation.ScalarInterpolator;\r
+import org.simantics.proconf.g3d.animation.SlerpInterpolator;\r
+import org.simantics.proconf.g3d.animation.TCBInterpolator;\r
+import org.simantics.proconf.g3d.base.AppearanceTools;\r
+import org.simantics.proconf.g3d.base.G3DTools;\r
+import org.simantics.proconf.g3d.base.GeometryProvider;\r
+import org.simantics.proconf.g3d.base.GeometryProviderRegistry;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.stubs.Appearance;\r
+import org.simantics.proconf.g3d.stubs.Color;\r
+import org.simantics.proconf.g3d.stubs.G3DModel;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+import org.simantics.proconf.g3d.stubs.Orientation;\r
+import org.simantics.utils.ErrorLogger;\r
+\r
+import com.jme.bounding.BoundingBox;\r
+import com.jme.bounding.CollisionTreeManager;\r
+import com.jme.intersection.PickResults;\r
+import com.jme.math.Ray;\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.Geometry;\r
+import com.jme.scene.Node;\r
+import com.jme.scene.SharedMesh;\r
+import com.jme.scene.TriMesh;\r
+import com.jme.scene.state.AlphaState;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.scene.state.RenderState;\r
+import com.jme.scene.state.WireframeState;\r
+import com.jme.scene.state.ZBufferState;\r
+\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.ContextGraph;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+\r
+public class ShapeNode extends AbstractGraphicsNode implements Animatable, IGeometryNode{\r
+\r
+    public static final int NORMAL = 0;\r
+    public static final int TRANSPARENT = 1;\r
+    public static final int SELECTED_EDGE = 2;\r
+    public static final int HIGHLIGHTED_EDGE = 3;\r
+    \r
+    private boolean highlighted = false;\r
+\r
+    protected Geometry mesh = null;\r
+    protected Geometry lines = null;\r
+    protected Geometry[] geometry = null;\r
+\r
+    private boolean visible[] = new boolean[4];\r
+    \r
+    private Node body;\r
+    private Node transparent;\r
+    private Node edge;\r
+\r
+    private MaterialState selectedEdgeState;\r
+    private MaterialState highlightedEdgeState;\r
+    \r
+    private Collection<RenderState> renderStates;\r
+    private boolean isTransparent;\r
+    \r
+\r
+    public ShapeNode(ThreeDimensionalEditorBase editor,IGraphicsNode parent, Graph graph, Resource shapeResource) {\r
+        super(editor,parent, graph, shapeResource);\r
+        for (int i = 0; i < visible.length; i++)\r
+            visible[i] = false;\r
+        \r
+        body = new Node();\r
+\r
+        body.setName(id); \r
+        \r
+        \r
+        transparent = new Node() {\r
+               private static final long serialVersionUID = 1L;\r
+               @Override\r
+               public void calculatePick(Ray ray, PickResults results) {\r
+               \r
+               }\r
+        };\r
+        \r
+       // transparent.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+        \r
+        edge = new Node(){\r
+               private static final long serialVersionUID = 1L;\r
+               @Override\r
+               public void calculatePick(Ray ray, PickResults results) {\r
+               \r
+               }\r
+        };\r
+        transparent.setIsCollidable(false);\r
+        edge.setIsCollidable(false);\r
+        \r
+        MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+        ms.setDiffuse(new ColorRGBA(0.0f, 0.75f, 0.0f,0.3f));\r
+        ms.setEmissive(new ColorRGBA(0f, 0f, 0f,0.3f));\r
+        ms.setSpecular(new ColorRGBA(0.5f, 0.5f, 0.5f,0.3f));\r
+        ms.setAmbient(new ColorRGBA(0.0f, 0.75f, 0.0f,0.3f));\r
+        ms.setShininess(128.f);\r
+        ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK);\r
+        transparent.setRenderState(ms);\r
+        \r
+        AlphaState as = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState();\r
+        as.setBlendEnabled(true);\r
+        as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);\r
+        as.setSrcFunction(AlphaState.DB_SRC_ALPHA);\r
+        transparent.setRenderState(as);\r
+        \r
+        ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+        ms.setDiffuse(new ColorRGBA(1.f, 1.f, 1.f, 1.f));\r
+        ms.setEmissive(new ColorRGBA(1.f, 1.f, 1.f, 1.f));\r
+        ms.setSpecular(new ColorRGBA(1.f, 1.f, 1.f, 1.f));\r
+        ms.setAmbient(new ColorRGBA(1.f, 1.f, 1.f, 1.f));\r
+        ms.setShininess(128.f);\r
+        selectedEdgeState = ms;\r
+        \r
+        ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+        ms.setDiffuse(new ColorRGBA(1.f, 0.f, 1.f, 1.f));\r
+        ms.setEmissive(new ColorRGBA(1.f, 0.f, 1.f, 1.f));\r
+        ms.setSpecular(new ColorRGBA(1.f, 0.f, 1.f, 1.f));\r
+        ms.setAmbient(new ColorRGBA(1.f, 0.f, 1.f, 1.f));\r
+        ms.setShininess(128.f);\r
+        \r
+        highlightedEdgeState = ms;\r
+\r
+        \r
+    }\r
+\r
+\r
+    /**\r
+     * This method is used to get implementation specific geometry.\r
+     * Arrays first element is a mesh, second contains edges.\r
+     * @return\r
+     */\r
+    public Geometry[] getGeometry(Graph graph, boolean update) {\r
+       G3DNode shape = getG3DNode(graph);\r
+       final GeometryProvider provider = GeometryProviderRegistry.getGeometryProvider(shape);\r
+       if (!update) {\r
+               return provider.getGeometryFromResource(shape, false);\r
+       } else {\r
+               if (geometry == null) {\r
+                               geometry = provider.getGeometryFromResource(shape, false);\r
+                       } else {\r
+                               provider.reconstructGeometry(shape, false, geometry);\r
+                       }\r
+               return geometry;\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Updates shapes and it's ancestors geometry\r
+     */\r
+    public void updateGeometry(Graph graph) {\r
+        updateTransform(graph);\r
+       // cleanAnimation();\r
+        //System.out.println("ShapeNode.updateGeometry() " + name);\r
+        if (geometry == null) {\r
+               Geometry g[] = getGeometry(graph,true);\r
+               if (g != null) {\r
+                               mesh = g[0];\r
+                               //TODO : uid\r
+                               mesh.setName(id); \r
+                               mesh.setModelBound(new BoundingBox());\r
+                               if (g.length > 1) {\r
+                                       lines = g[1];\r
+                               } else {\r
+                                       lines = null;\r
+                               }\r
+                               body.attachChild(mesh);\r
+                               transparent.detachAllChildren();\r
+                               SharedMesh m = new SharedMesh("",(TriMesh)mesh);\r
+                               m.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+                               m.getBatch(0).setCastsShadows(false);\r
+                               transparent.attachChild(m);\r
+                               \r
+                               \r
+                               if (lines == null) {\r
+                                       WireframeState ws = editor.getRenderingComponent().getDisplaySystem().getRenderer().createWireframeState();\r
+                                       edge.attachChild(new SharedMesh("",(TriMesh)mesh));\r
+                                       edge.setRenderState(ws);\r
+                               } else {\r
+                                       ZBufferState zs = editor.getRenderingComponent().getDisplaySystem().getRenderer().createZBufferState();\r
+                           zs.setFunction(ZBufferState.CF_ALWAYS);\r
+                           AlphaState as = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState();\r
+                           as.setBlendEnabled(true);\r
+                           as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);\r
+                           as.setSrcFunction(AlphaState.DB_SRC_ALPHA);\r
+                           lines.setRenderState(zs);\r
+                           lines.setRenderState(as);\r
+                           lines.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+                           edge.attachChild(lines);\r
+                               }\r
+\r
+               }\r
+        }\r
+        if (geometry != null) {\r
+               getGeometry(graph,true);\r
+\r
+            \r
+            G3DNode shape = getG3DNode(graph);\r
+            if (renderStates == null)\r
+               updateAppearance(shape);\r
+\r
+            if (isVisible()) {\r
+               getGroup().attachChild(body);\r
+            } else {\r
+               body.removeFromParent();\r
+            }\r
+            if (isTransparentVisible()) {\r
+               getGroup().attachChild(transparent);\r
+               //setVisible(TRANSPARENT, true);\r
+            } else {\r
+               transparent.removeFromParent();\r
+            }\r
+\r
+            if (isSelectedVisible() || isHighlightedVisible()) {\r
+               getGroup().attachChild(edge);\r
+               //setVisible(SELECTED_EDGE, true);\r
+            } else {\r
+               edge.removeFromParent();\r
+               //setVisible(SELECTED_EDGE,false);\r
+            }\r
+            \r
+            \r
+            mesh.updateModelBound();\r
+            CollisionTreeManager.getInstance().updateCollisionTree(mesh);\r
+            //mesh.updateCollisionTree();\r
+  \r
+        }\r
+    }\r
+    \r
+    protected void updateAppearance(IEntity shape) {\r
+       Collection<IEntity> appearanceResource;\r
+        if ((appearanceResource = shape.getRelatedObjects(Resources.g3dResource.HasAppearance)) != null && appearanceResource.size() > 0) {\r
+            renderStates = AppearanceTools.getAppearance(new Appearance(shape.getGraph(),appearanceResource.iterator().next().getResource()), editor.getRenderingComponent().getDisplaySystem().getRenderer());\r
+        } else {\r
+               renderStates = getMaterial();\r
+        }\r
+        \r
+        isTransparent = false;\r
+        for (RenderState s : renderStates) {\r
+               if (s instanceof AlphaState)\r
+                       isTransparent = true;\r
+        }\r
+        setAppearance();\r
+    }\r
+    \r
+    protected void setAppearance() {\r
+       if (mesh ==  null || renderStates == null) {\r
+               return;\r
+       }\r
+               for (RenderState s : renderStates)\r
+                       mesh.setRenderState(s);\r
+               if (isTransparent)\r
+                       mesh.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+               else\r
+                       mesh.setRenderQueueMode(Renderer.QUEUE_OPAQUE);\r
+    }\r
+\r
+    public void setSelected(boolean selected) {\r
+        if (this.selected == selected)\r
+            return;\r
+        this.selected = selected;\r
+        if (selected) {\r
+\r
+            setSelectedVisible(true);\r
+            setTransparentVisible(true);\r
+        } else {\r
+            setSelectedVisible(false);\r
+            setTransparentVisible(false);\r
+        }\r
+    }\r
+\r
+    public boolean isSelected() {\r
+        return selected;\r
+    }\r
+    \r
+    \r
+\r
+    public boolean isHighlighted() {\r
+        return highlighted;\r
+    }\r
+\r
+    public void setHighlighted(boolean highlighted) {\r
+        if (this.highlighted == highlighted)\r
+            return;\r
+        this.highlighted = highlighted;\r
+        if (highlighted) {\r
+            setHighlightedVisible(true);\r
+        } else {\r
+            setHighlightedVisible(false);\r
+        }\r
+    }\r
+    \r
+    public boolean isVisible(int shape) {\r
+        return visible[shape];\r
+    }\r
+    \r
+    public void setVisible(int shape, boolean visible) {\r
+        if (this.visible[shape] == visible)\r
+            return;   \r
+        this.visible[shape] = visible;\r
+        if (mesh == null) {\r
+               return;\r
+        }\r
+        if (this.visible[NORMAL]){\r
+               getGroup().attachChild(body);\r
+        } else {\r
+               body.removeFromParent();\r
+        }\r
+        if (this.visible[TRANSPARENT]) {\r
+               getGroup().attachChild(transparent);\r
+        } else {\r
+               transparent.removeFromParent();\r
+        }\r
+        if (this.visible[SELECTED_EDGE] || this.visible[HIGHLIGHTED_EDGE]) {\r
+               if (this.visible[HIGHLIGHTED_EDGE])\r
+                       edge.setRenderState(highlightedEdgeState);\r
+               else\r
+                       edge.setRenderState(selectedEdgeState);\r
+               getGroup().attachChild(edge);\r
+               edge.updateRenderState();\r
+        } else {\r
+               edge.removeFromParent();\r
+        } \r
+    }\r
+\r
+    public boolean isVisible() {\r
+        return isVisible(NORMAL);\r
+    }\r
+\r
+    public void setVisible(boolean visible) {\r
+        setVisible(NORMAL, visible);\r
+    }\r
+\r
+    public boolean isSelectedVisible() {\r
+        return isVisible(SELECTED_EDGE);\r
+    }\r
+\r
+    public void setSelectedVisible(boolean visible) {\r
+        setVisible(SELECTED_EDGE, visible);\r
+    }\r
+\r
+    public boolean isHighlightedVisible() {\r
+        return isVisible(HIGHLIGHTED_EDGE);\r
+    }\r
+\r
+    public void setHighlightedVisible(boolean visible) {\r
+        setVisible(HIGHLIGHTED_EDGE, visible);\r
+        \r
+    }\r
+\r
+    \r
+\r
+    public boolean isTransparentVisible() {\r
+        return isVisible(TRANSPARENT);\r
+    }\r
+\r
+    public void setTransparentVisible(boolean visible) {\r
+        setVisible(TRANSPARENT, visible);\r
+    }\r
+\r
+    public void setPickable(boolean pickable) {\r
+       body.setIsCollidable(pickable);\r
+    }\r
+    \r
+    public Collection<RenderState> getMaterial() {\r
+       List<RenderState> states = new ArrayList<RenderState>();\r
+       MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+       ms.setEmissive(new ColorRGBA(0.f,0.f,0.f,0.f));\r
+       ms.setSpecular(new ColorRGBA(1.f,1.f,1.f,1.f));\r
+       ms.setDiffuse(new ColorRGBA(0.75f,0.f,0.f,0.f));\r
+       ms.setAmbient(new ColorRGBA(0.75f,0.f,0.f,0.f));\r
+       ms.setEnabled(true);\r
+       ms.setShininess(128.f);\r
+       states.add(ms);\r
+\r
+       return states;  \r
+    }\r
+    \r
+    private Animation animation;\r
+    private static int preCalcSteps = 9;\r
+    private Geometry[] preCalc = null;\r
+    private int currentPreCalc = 0;\r
+    \r
+    public void animate(double delta,double frameTime) {\r
+        if (animation != null)\r
+            animation.interpolate(delta);\r
+        if (preCalc != null) {\r
+            int newPreCalc = (int)Math.round(delta*(preCalc.length-1));\r
+            if (currentPreCalc != newPreCalc) {\r
+\r
+               preCalc[currentPreCalc].removeFromParent();\r
+                currentPreCalc = newPreCalc;\r
+                \r
+                body.attachChild(preCalc[currentPreCalc]);\r
+            }\r
+        }\r
+    }\r
+    \r
+    private void cleanAnimation() {\r
+       this.animation = null;\r
+       if (preCalc != null) {\r
+               for (Geometry g : preCalc) {\r
+                       if (g != null) {\r
+                               g.removeFromParent();\r
+                               g.clearBuffers();\r
+                       }\r
+               }\r
+               preCalc = null;\r
+       }\r
+    }\r
+\r
+    /**\r
+     * Sets shape's animation\r
+     * TODO : multiple animations at the same time! (must check common animatable properties)\r
+     * TODO : initial values (material, ..) (requires changes in the ontology)\r
+     * TODO : messy code, refactor!\r
+     * TODO : calculate number of required pre-calculated geometries \r
+     * @param animation\r
+     */\r
+    public boolean setAnimation(Graph g, Resource res) {\r
+       ContextGraph graph;\r
+       if (g instanceof ContextGraph) {\r
+               graph = (ContextGraph)g;\r
+       } else {\r
+               graph = new ContextGraph(g);\r
+               graph.setContext(shapeResource);\r
+       }\r
+       cleanAnimation();\r
+       if (res == null) {\r
+               if (isVisible())\r
+                       body.attachChild(mesh);\r
+            return false;\r
+        }\r
+       org.simantics.g2d.stubs.anim.Animation animation = new org.simantics.g2d.stubs.anim.Animation(graph,res);\r
+       G3DNode shape = getG3DNode(graph);\r
+        G3DNode modelResource = G3DTools.getModelFromResource(graph,shape.getResource());\r
+        assert (modelResource != null);\r
+        G3DModel model = new G3DModel(graph,modelResource.getResource());\r
+        Collection<org.simantics.g2d.stubs.anim.Animation> animations = model.getAnimation();\r
+        boolean found = false;\r
+        for (org.simantics.g2d.stubs.anim.Animation a : animations) {\r
+            if (a.getResource().equals(animation.getResource())) {\r
+                found = true;\r
+                break;\r
+            }\r
+        }\r
+        if (!found) {\r
+            ErrorLogger.getDefault().logWarning("Shape " + shape.getResource() + " cannot handle animation " + animation.getResource() + " because it isn't model's animation", null);\r
+            return false;\r
+        }\r
+        Collection<org.simantics.g2d.stubs.anim.Interpolator> interpolators = animation.getInterpolator();\r
+        List<org.simantics.g2d.stubs.anim.Interpolator> handled = new ArrayList<org.simantics.g2d.stubs.anim.Interpolator>();\r
+        List<org.simantics.g2d.stubs.anim.Interpolator> precalculated = new ArrayList<org.simantics.g2d.stubs.anim.Interpolator>();\r
+        for (org.simantics.g2d.stubs.anim.Interpolator i : interpolators) {\r
+            IEntity target = i.getTarget();\r
+            if (G3DTools.hasProperty(graph,shape.getResource(),target.getResource()))\r
+                handled.add(i);\r
+            else if (G3DTools.hasSubProperty(graph,shape.getResource(),target.getResource())) {\r
+                precalculated.add(i);\r
+            }\r
+        }\r
+        if (handled.size() == 0 && precalculated.size() == 0) {\r
+            ErrorLogger.getDefault().logWarning("Shape " + shape.getResource() + " cannot handle animation " + animation.getResource() + " since it doesn't change any of shape's properties", null);\r
+            return false;\r
+        }\r
+        \r
+        \r
+        this.animation = new Animation();\r
+        \r
+        org.simantics.g2d.stubs.anim.Interpolator[] pos = new org.simantics.g2d.stubs.anim.Interpolator[3];\r
+        org.simantics.g2d.stubs.anim.Interpolator[] ambient = new org.simantics.g2d.stubs.anim.Interpolator[3];\r
+        org.simantics.g2d.stubs.anim.Interpolator[] diffuse = new org.simantics.g2d.stubs.anim.Interpolator[3];\r
+        org.simantics.g2d.stubs.anim.Interpolator[] specular = new org.simantics.g2d.stubs.anim.Interpolator[3];\r
+        org.simantics.g2d.stubs.anim.Interpolator[] emissive = new org.simantics.g2d.stubs.anim.Interpolator[3];\r
+\r
+        Builtins builtins = graph.getBuiltins();\r
+\r
+        \r
+        for (org.simantics.g2d.stubs.anim.Interpolator i : handled) {\r
+            IEntity target = i.getTarget();\r
+            //if (target.isInstanceOf(Resources.g3dResource.LocalOrientation)) {\r
+            if (target.isInstanceOf(Resources.g3dResource.Orientation) && target.getRelatedObjects(Resources.g3dResource.LocalOrientationOf).size() == 1) {\r
+                SlerpInterpolator si = new SlerpInterpolator((SlerpCurve)Resources.curveBuilder.loadInterpolator(i));\r
+                si.setTarget(transform);\r
+                this.animation.addInterpolator(si);\r
+            } else if (target.isInstanceOf(builtins.Double)) {\r
+               Resource targetResource = target.getResource();\r
+               Collection<IEntity> p = target.getRelatedObjects(builtins.PropertyOf);\r
+                if (p.size() == 1) {\r
+                    IEntity parent = p.iterator().next();\r
+                    //if (parent.isInstanceOf(Resources.g3dResource.LocalPosition)) {\r
+                    if (parent.isInstanceOf(Resources.g3dResource.Position) && parent.getRelatedObjects(Resources.g3dResource.LocalPositionOf).size() == 1) {\r
+                        if (parent.getSingleRelatedObject(Resources.g3dResource.HasX).getResource().equals(targetResource)) {\r
+                             pos[0] = i;\r
+                        } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasY).getResource().equals(targetResource)) {\r
+                            pos[1] = i;\r
+                        } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasZ).getResource().equals(targetResource)) {\r
+                            pos[2] = i;\r
+                        } else {\r
+                            ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Position ?)" + target.getResource(),  null);\r
+                        }\r
+                    } else if (parent.isInstanceOf(Resources.g3dResource.Color)) {\r
+                        org.simantics.g2d.stubs.anim.Interpolator[] color = null;\r
+                        if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.AmbientColorOf).size() > 0) {\r
+                                color = ambient;\r
+                        } else if (parent.isInstanceOf(Resources.g3dResource.Color)&& parent.getRelatedObjects(Resources.g3dResource.DiffuseColorOf).size() > 0) {\r
+                                color = diffuse;\r
+                        } else if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.SpecularColorOf).size() > 0) {\r
+                                color = specular;\r
+                        } else if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.EmissiveColorOf).size() > 0) {\r
+                                color = emissive;\r
+                        } else {\r
+                            ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Color)" + target.getResource() + " unknown color type",  null);\r
+                        }\r
+                        if (color != null) {\r
+                            if (parent.getSingleRelatedObject(Resources.g3dResource.HasRed).getResource().equals(targetResource)) {\r
+                                color[0] = i;\r
+                            } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasGreen).getResource().equals(targetResource)) {\r
+                                color[1] = i;\r
+                            } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasBlue).getResource().equals(targetResource)) {\r
+                                color[2] = i;\r
+                            } else {\r
+                                ErrorLogger.getDefault().logWarning(\r
+                                        "Cannot map animation interpolator " + i.getResource()\r
+                                                + " to target (Color ?)" + target.getResource(), null);\r
+                            }\r
+                        }\r
+                    } else if (parent.isInstanceOf(Resources.g3dResource.Material)) {\r
+                       // TODO : transparency or shininess     \r
+                    } else {\r
+                        ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target" + target.getResource() + " adding it to precalculated interpolators",  null);\r
+                        precalculated.add(i);\r
+                    }\r
+                } else {\r
+                    if (p.size() == 0) {\r
+                        ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Double)" + target.getResource() + " since it is not a part of a property",  null);\r
+                    } else {\r
+                        ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Double)" + target.getResource() + " since it acts as a property to more than one entity",  null);  \r
+                    }\r
+                }\r
+            } else {\r
+                ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target" + target.getResource(),  null);\r
+            }\r
+        }\r
+        \r
+        if (pos[0] != null || pos[1] != null || pos[2] != null) {\r
+            ScalarInterpolator xIp;\r
+            ScalarInterpolator yIp;\r
+            ScalarInterpolator zIp;\r
+            if (pos[0] != null) {\r
+                xIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[0]));\r
+            } else {\r
+                xIp = new ConstantInterpolator(shape.getLocalPosition().getX()[0]);\r
+            }\r
+            if (pos[1] != null) {\r
+                yIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[1]));\r
+            } else {\r
+                yIp = new ConstantInterpolator(shape.getLocalPosition().getY()[0]);\r
+            }\r
+            if (pos[2] != null) {\r
+                zIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[2]));\r
+            } else {\r
+                zIp = new ConstantInterpolator(shape.getLocalPosition().getZ()[0]);\r
+            }\r
+            ChanneledPositionInterpolator ip = new ChanneledPositionInterpolator(xIp,yIp,zIp);\r
+            ip.setTarget(transform);\r
+            this.animation.addInterpolator(ip);\r
+        \r
+        }  \r
+        addColorInterpolator(shape, ambient, ChanneledColorInterpolator.AMBIENT);\r
+        addColorInterpolator(shape, diffuse, ChanneledColorInterpolator.DIFFUSE);\r
+        addColorInterpolator(shape, emissive, ChanneledColorInterpolator.EMISSIVE);\r
+        addColorInterpolator(shape, specular, ChanneledColorInterpolator.SPECULAR);\r
+        \r
+        if (precalculated.size() == 0) {\r
+            preCalc = null;\r
+        } else {\r
+                preCalc = new Geometry[preCalcSteps+1];\r
+                for (int i = 0; i <= preCalcSteps; i++) {\r
+                    double delta = ((double)i / (double)preCalcSteps);\r
+                    // TODO : copy-paste from CSGAnimatorView\r
+                    // FIXME : does not update transformations (since ContextGraph does not support queries for context dependent values)\r
+                    for (Interpolator ip : precalculated) {\r
+                        if (ip.isInstanceOf(Resources.animationResource.ScalarInterpolator)) {\r
+                            // TODO : creating curve each time when time is set is slow.\r
+                            // Curve should be cached\r
+                            TCBCurve c = (TCBCurve)Resources.curveBuilder.loadInterpolator(ip);\r
+                            double out = c.evaluate(delta);\r
+                            //Double d = DoubleFactory.create(ip.getTarget());\r
+                            //d.setValue(new double[]{out});\r
+                            IEntity d = ip.getTarget();\r
+                            d.toProperty().setDoubleArray(new double[]{out});\r
+                        } else if (ip.isInstanceOf(Resources.animationResource.SlerpInterpolator)) {\r
+                            // TODO : creating curve each time when time is set is slow.\r
+                            // Curve should be cached\r
+                            SlerpCurve c = (SlerpCurve)Resources.curveBuilder.loadInterpolator(ip);\r
+                            Quat4d out = c.evaluate(delta);\r
+                            Orientation r = new Orientation(ip.getTarget());\r
+                            AxisAngle4d aa = new AxisAngle4d();\r
+                            aa.set(out);\r
+                            G3DTools.setOrientation(r, aa);\r
+                        }\r
+                    }\r
+                    preCalc[i] = getGeometry(graph,false)[0];\r
+                    preCalc[i].setIsCollidable(false);\r
+                    AppearanceTools.copyMaterial(mesh, preCalc[i]);\r
+                }\r
+                \r
+                // We'll have to remove original (non-animated) shape from the node\r
+                mesh.removeFromParent();\r
+                body.attachChild(preCalc[0]);\r
+           \r
+        }\r
+        return true;\r
+    }\r
+    \r
+    private void addColorInterpolator(G3DNode shape, org.simantics.g2d.stubs.anim.Interpolator[] color, int type) {\r
+        if (color[0] != null || color[1] != null || color[2] != null) {\r
+            ScalarInterpolator xIp;\r
+            ScalarInterpolator yIp;\r
+            ScalarInterpolator zIp;\r
+            Color col = null;\r
+            Collection<IEntity> appearanceResource = shape.getRelatedObjects(Resources.g3dResource.HasAppearance);\r
+            if (appearanceResource.size() == 0) {\r
+                ErrorLogger.getDefault().logWarning("Cannot create interpolator for color because shape " + shape.getResource() + " has no appearance", null);\r
+            }\r
+            Appearance a = new Appearance(shape.getGraph(),appearanceResource.iterator().next().getResource());\r
+            switch (type) {\r
+                case ChanneledColorInterpolator.AMBIENT:\r
+                    col = a.getMaterial().getAmbientColor();\r
+                    break;\r
+                case ChanneledColorInterpolator.DIFFUSE:\r
+                    col = a.getMaterial().getDiffuseColor();\r
+                    break;\r
+                case ChanneledColorInterpolator.EMISSIVE:\r
+                    col = a.getMaterial().getEmissiveColor();\r
+                    break;\r
+                case ChanneledColorInterpolator.SPECULAR:\r
+                    col = a.getMaterial().getSpecularColor();\r
+                    break;\r
+                default:\r
+                    ErrorLogger.defaultLogError("Unknown color type", null);\r
+                    return;\r
+            }\r
+\r
+            if (color[0] != null) {\r
+                xIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[0]));//CurveUtils.loadCurve(color[0].getResource()));\r
+            } else {\r
+                xIp = new ConstantInterpolator(col.getRed()[0]);\r
+            }\r
+            if (color[1] != null) {\r
+                yIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[1]));//CurveUtils.loadCurve(color[1].getResource()));\r
+            } else {\r
+                yIp = new ConstantInterpolator(col.getGreen()[0]);\r
+            }\r
+            if (color[1] != null) {\r
+                zIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[2]));//CurveUtils.loadCurve(color[2].getResource()));\r
+            } else {\r
+                zIp = new ConstantInterpolator(col.getBlue()[0]);\r
+            }\r
+            ChanneledColorInterpolator ip = new ChanneledColorInterpolator(xIp,yIp,zIp);\r
+            ip.setType(type);\r
+            ip.setTarget(mesh.getRenderState(RenderState.RS_MATERIAL));\r
+            this.animation.addInterpolator(ip);\r
+        } \r
+    }\r
+    \r
+    public boolean setRandomAnimation(Graph graph) {\r
+        return false;\r
+    }\r
+    \r
+    public void dispose() {\r
+//     mesh.clearBuffers();\r
+//     mesh.clearBatches();\r
+//     lines.clearBuffers();\r
+//     lines.clearBatches();\r
+       if (mesh != null) {\r
+               mesh.removeFromParent();\r
+               mesh.dispose();\r
+               mesh = null;\r
+       }\r
+       if (lines != null) {\r
+               lines.removeFromParent();\r
+               lines.dispose();\r
+               lines = null;\r
+       }\r
+       super.dispose();\r
+    }\r
+}
\ No newline at end of file
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/AxesShape.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/AxesShape.java
new file mode 100644 (file)
index 0000000..461087c
--- /dev/null
@@ -0,0 +1,51 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.shapes;\r
+\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.Geometry;\r
+import com.jme.scene.Line;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.util.geom.BufferUtils;\r
+\r
+public class AxesShape {\r
+    \r
+\r
+       public static Geometry getShape(Renderer renderer) {\r
+        float[] coords = new float[]{0.f,0.f,0.f,\r
+                          1.f,0.f,0.f,\r
+                          0.f,0.f,0.f,\r
+                          0.f,1.f,0.f,\r
+                          0.f,0.f,0.f,\r
+                          0.f,0.f,1.f};\r
+        float colors[] = new float[]{1.f,0.f,0.f,0.f,\r
+                          1.f,0.f,0.f,0.f,\r
+                          0.f,1.f,0.f,0.f,\r
+                          0.f,1.f,0.f,0.f,\r
+                          0.f,0.f,1.f,0.f,\r
+                          0.f,0.f,1.f,0.f};\r
+        \r
+\r
+        Line shape = new Line("",BufferUtils.createFloatBuffer(coords),null,BufferUtils.createFloatBuffer(colors),null);\r
+        shape.setMode(Line.SEGMENTS);\r
+        shape.setIsCollidable(false);\r
+        shape.setLineWidth(3.f);\r
+        MaterialState ms = renderer.createMaterialState();\r
+        ms.setColorMaterial(MaterialState.CM_EMISSIVE);\r
+        ms.setEmissive(new ColorRGBA(1.f,1.f,1.f,1.f));\r
+        shape.setRenderState(ms);\r
+        \r
+        return shape;\r
+       \r
+    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/FloorShape.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/FloorShape.java
new file mode 100644 (file)
index 0000000..cd289ad
--- /dev/null
@@ -0,0 +1,91 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.shapes;\r
+\r
+import java.net.URL;\r
+\r
+import org.eclipse.core.runtime.FileLocator;\r
+import org.eclipse.core.runtime.Path;\r
+\r
+import com.jme.image.Texture;\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.Geometry;\r
+import com.jme.scene.TriMesh;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.scene.state.TextureState;\r
+import com.jme.util.TextureManager;\r
+import com.jme.util.geom.BufferUtils;\r
+\r
+public class FloorShape {\r
+       \r
+       private static String textureLocation = "src/jmetest/data/texture/Detail.jpg";\r
+\r
+       public static Geometry getShape(Renderer renderer, float size, float texScale) {\r
+\r
+               float coords[] = new float[3 * 4];\r
+               float normals[] = new float[3 * 4];\r
+               float texcoords[] = new float[2 * 4];\r
+               int indices[] = new int[] { 0, 2, 1, 1, 2, 3 };\r
+               coords[0] = -size;\r
+               coords[1] = 0.f;\r
+               coords[2] = -size;\r
+               coords[3] = size;\r
+               coords[4] = 0.f;\r
+               coords[5] = -size;\r
+               coords[6] = -size;\r
+               coords[7] = 0.f;\r
+               coords[8] = size;\r
+               coords[9] = size;\r
+               coords[10] = 0.f;\r
+               coords[11] = size;\r
+               texcoords[0] = -size*texScale;\r
+               texcoords[1] = -size*texScale;\r
+               texcoords[2] = size*texScale;\r
+               texcoords[3] = -size*texScale;\r
+               texcoords[4] = -size*texScale;\r
+               texcoords[5] = size*texScale;\r
+               texcoords[6] = size*texScale;\r
+               texcoords[7] = size*texScale;\r
+               normals[0] = 0.f;\r
+               normals[1] = 1.f;\r
+               normals[2] = 0.f;\r
+               normals[3] = 0.f;\r
+               normals[4] = 1.f;\r
+               normals[5] = 0.f;\r
+               normals[6] = 0.f;\r
+               normals[7] = 1.0f;\r
+               normals[8] = 0.f;\r
+               normals[9] = 0.f;\r
+               normals[10] = 1.f;\r
+               normals[11] = 0.f;\r
+      \r
+        TriMesh shape = new TriMesh("",BufferUtils.createFloatBuffer(coords),BufferUtils.createFloatBuffer(normals),null,BufferUtils.createFloatBuffer(texcoords),BufferUtils.createIntBuffer(indices));\r
+        MaterialState ms = renderer.createMaterialState();\r
+        ms.setEmissive(new ColorRGBA(0.5f,0.5f,0.5f,0.f));\r
+        ms.setDiffuse(new ColorRGBA(1.f,1.f,1.f,0.f));\r
+        ms.setShininess(128.f);\r
+        shape.setRenderState(ms);\r
+        shape.setCullMode(Geometry.CULL_NEVER);\r
+\r
+        TextureState ts = renderer.createTextureState();\r
+        URL url = FileLocator.find(com.jme.eclipse.Activator.getDefault().getBundle(),new Path(textureLocation),null);\r
+        Texture tex = TextureManager.loadTexture(url, Texture.MM_LINEAR_LINEAR,\r
+                Texture.FM_LINEAR);\r
+        tex.setWrap(Texture.WM_WRAP_S_WRAP_T);\r
+        ts.setTexture(tex);\r
+        shape.setRenderState(ts);\r
+        shape.lockShadows();\r
+        return shape;\r
+       \r
+    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/GridShape.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/GridShape.java
new file mode 100644 (file)
index 0000000..284b357
--- /dev/null
@@ -0,0 +1,57 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.shapes;\r
+\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.Geometry;\r
+import com.jme.scene.Line;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.util.geom.BufferUtils;\r
+\r
+public class GridShape {\r
+    \r
\r
+       public static Geometry getShape(Renderer renderer, int lineCount, float delta) {\r
+           \r
+        float[] coords = new float[lineCount*lineCount*2*3];\r
+        float size = delta * lineCount;\r
+        float halfSize = size * 0.5f;\r
+        \r
+        for (int i = 0 ; i <= lineCount; i++) {\r
+            int index = i*3*2;\r
+            coords[index++] = -halfSize + i * delta;\r
+            coords[index++] = 0.f;\r
+            coords[index++] = -halfSize;\r
+            coords[index++] = -halfSize + i * delta;\r
+            coords[index++] = 0.f;\r
+            coords[index++] = +halfSize;\r
+        }\r
+        for (int i = 0 ; i <= lineCount; i++) {\r
+            int index = (i + lineCount + 1)*3*2;\r
+            coords[index++] = -halfSize;\r
+            coords[index++] = 0.f;\r
+            coords[index++] = -halfSize + i * delta;\r
+            coords[index++] = +halfSize;\r
+            coords[index++] = 0.f;\r
+            coords[index++] = -halfSize + i * delta;\r
+        }\r
+\r
+        Line shape = new Line("",BufferUtils.createFloatBuffer(coords),null,null,null);\r
+        MaterialState ms = renderer.createMaterialState();\r
+        ms.setEmissive(new ColorRGBA(1.f,1.f,1.f,0.f));\r
+        shape.setRenderState(ms);\r
+        shape.setCullMode(Geometry.CULL_NEVER);\r
+        return shape;\r
+       \r
+    }\r
+\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/Quad.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/shapes/Quad.java
new file mode 100644 (file)
index 0000000..cab5e37
--- /dev/null
@@ -0,0 +1,130 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.shapes;\r
+\r
+import java.nio.FloatBuffer;\r
+\r
+import com.jme.math.Vector3f;\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.scene.TriMesh;\r
+import com.jme.scene.batch.TriangleBatch;\r
+import com.jme.util.geom.BufferUtils;\r
+\r
+public class Quad extends TriMesh {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+    public Quad() {\r
+        \r
+    }\r
+    \r
+       /**\r
+        * Constructor creates a new <code>Quad</code> object. That data for the\r
+        * <code>Quad</code> is not set until a call to <code>initialize</code>\r
+        * is made.\r
+        * \r
+        * @param name\r
+        *            the name of this <code>Quad</code>.\r
+        */\r
+       public Quad(String name) {\r
+               super(name);\r
+       }\r
+\r
+       /**\r
+        * Constructor creates a new <code>Quade</code> object with the provided\r
+        * width and height.\r
+        * \r
+        * @param name\r
+        *            the name of the <code>Quad</code>.\r
+        * @param width\r
+        *            the width of the <code>Quad</code>.\r
+        * @param height\r
+        *            the height of the <code>Quad</code>.\r
+        */\r
+       public Quad(String name, float width, float height) {\r
+               super(name);\r
+               initialize(width, height);\r
+       }\r
+\r
+       /**\r
+        * <code>resize</code> changes the width and height of the given quad by\r
+        * altering its vertices.\r
+        * \r
+        * @param width\r
+        *            the new width of the <code>Quad</code>.\r
+        * @param height\r
+        *            the new height of the <code>Quad</code>.\r
+        */\r
+       public void resize(float width, float height) {\r
+        TriangleBatch batch = getBatch(0);\r
+               batch.getVertexBuffer().clear();\r
+               batch.getVertexBuffer().put(-width / 2f).put(height / 2f).put(0);\r
+               batch.getVertexBuffer().put(-width / 2f).put(-height / 2f).put(0);\r
+               batch.getVertexBuffer().put(width / 2f).put(-height / 2f).put(0);\r
+               batch.getVertexBuffer().put(width / 2f).put(height / 2f).put(0);\r
+       }\r
+\r
+       /**\r
+        * \r
+        * <code>initialize</code> builds the data for the <code>Quad</code>\r
+        * object.\r
+        * \r
+        * \r
+        * @param width\r
+        *            the width of the <code>Quad</code>.\r
+        * @param height\r
+        *            the height of the <code>Quad</code>.\r
+        */\r
+       public void initialize(float width, float height) {\r
+        TriangleBatch batch = getBatch(0);\r
+               batch.setVertexCount(4);\r
+               batch.setVertexBuffer(BufferUtils.createVector3Buffer(batch.getVertexCount()));\r
+               batch.setNormalBuffer(BufferUtils.createVector3Buffer(batch.getVertexCount()));\r
+        FloatBuffer tbuf = BufferUtils.createVector2Buffer(batch.getVertexCount());\r
+        setTextureBuffer(0,tbuf);\r
+           batch.setTriangleQuantity(2);\r
+           batch.setIndexBuffer(BufferUtils.createIntBuffer(batch.getTriangleCount() * 3));\r
+\r
+               batch.getVertexBuffer().put(-width / 2f).put(height / 2f).put(0);\r
+               batch.getVertexBuffer().put(-width / 2f).put(-height / 2f).put(0);\r
+               batch.getVertexBuffer().put(width / 2f).put(-height / 2f).put(0);\r
+               batch.getVertexBuffer().put(width / 2f).put(height / 2f).put(0);\r
+\r
+               batch.getNormalBuffer().put(0).put(0).put(1);\r
+               batch.getNormalBuffer().put(0).put(0).put(1);\r
+               batch.getNormalBuffer().put(0).put(0).put(1);\r
+               batch.getNormalBuffer().put(0).put(0).put(1);\r
+\r
+        \r
+               tbuf.put(0).put(0);\r
+        tbuf.put(0).put(1);\r
+        tbuf.put(1).put(1);\r
+        tbuf.put(1).put(0);\r
+\r
+           setDefaultColor(ColorRGBA.white);\r
+\r
+           batch.getIndexBuffer().put(0);\r
+           batch.getIndexBuffer().put(1);\r
+           batch.getIndexBuffer().put(2);\r
+           batch.getIndexBuffer().put(0);\r
+           batch.getIndexBuffer().put(2);\r
+           batch.getIndexBuffer().put(3);\r
+       }\r
+\r
+       /**\r
+        * <code>getCenter</code> returns the center of the <code>Quad</code>.\r
+        * \r
+        * @return Vector3f the center of the <code>Quad</code>.\r
+        */\r
+       public Vector3f getCenter() {\r
+               return worldTranslation;\r
+       }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/OEPathSelectionListener.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/OEPathSelectionListener.java
new file mode 100644 (file)
index 0000000..1af0908
--- /dev/null
@@ -0,0 +1,46 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.tools;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.simantics.layer0.utils.viewpoints.TraversalPath;\r
+import org.simantics.proconf.browsing.MutableCachedGraphTreeNode;\r
+\r
+/**\r
+ * SelectionListener for OntologyExplorer\r
+ * \r
+ * Returns Selection as TraversalPath\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public abstract class OEPathSelectionListener implements ISelectionChangedListener{\r
+       @SuppressWarnings("unchecked")\r
+       public void selectionChanged(SelectionChangedEvent event) {\r
+               IStructuredSelection s = (IStructuredSelection)event.getSelection();\r
+               List<TraversalPath> paths = new ArrayList<TraversalPath>();\r
+               Iterator<MutableCachedGraphTreeNode> i = s.iterator();\r
+               while(i.hasNext()) {\r
+                       MutableCachedGraphTreeNode node = i.next();\r
+                       TraversalPath path = (TraversalPath)node.getObject();\r
+                       paths.add(path);\r
+               }       \r
+               pathSelectionUpdated(paths);\r
+       }\r
+       \r
+       protected abstract void pathSelectionUpdated(List<TraversalPath> paths);\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/OESelectionListener.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/OESelectionListener.java
new file mode 100644 (file)
index 0000000..54e4619
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.tools;\r
+\r
+import java.util.Iterator;\r
+\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.browsing.providers.TreeObject;\r
+import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
+\r
+/**\r
+ * SelectionListener for OntologyExplorer\r
+ * \r
+ * Returns selection as StrcturedResourceSelection\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public abstract class OESelectionListener implements ISelectionChangedListener { \r
+       @SuppressWarnings("unchecked")\r
+       public void selectionChanged(SelectionChangedEvent event) {\r
+               IStructuredSelection s = (IStructuredSelection)event.getSelection();\r
+               StructuredResourceSelection sel = new StructuredResourceSelection();\r
+               Iterator<TreeObject> i = s.iterator();\r
+               while(i.hasNext()) {\r
+                       TreeObject node = i.next();\r
+                       sel.add((Resource)node.getAdapter(Resource.class));\r
+               }\r
+               resourceSelectionUpdated(sel);\r
+       }\r
+       \r
+       protected abstract void resourceSelectionUpdated(StructuredResourceSelection selection);\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/PropertyTree.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/PropertyTree.java
new file mode 100644 (file)
index 0000000..ea7f62d
--- /dev/null
@@ -0,0 +1,313 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.tools;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Tree;\r
+import org.eclipse.swt.widgets.TreeItem;\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.layer0.utils.EntityFactory;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.ResourceDebugUtils;\r
+import org.simantics.layer0.utils.Statement;\r
+import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
+\r
+/**\r
+ * PropertyTree finds common properties for set of objects, and\r
+ * then based on user's selection returns all property instances.\r
+ * \r
+ * @author Marko Luukkainen\r
+ *\r
+ */\r
+public class PropertyTree {\r
+    private Tree tree;\r
+    private Session session;\r
+    \r
+    \r
+    public PropertyTree(Tree tree, Session session) {\r
+        this.tree = tree;\r
+        this.session = session;\r
+    }\r
+    \r
+    public void setProperties(List<Resource> selectedInstances) {\r
+        tree.removeAll();\r
+        addProperties(null,selectedInstances);\r
+        tree.redraw();\r
+    }\r
+    \r
+    public void setProperties(StructuredResourceSelection selection) {\r
+        ArrayList<Resource> selectedInstances = new ArrayList<Resource>();\r
+        for (Resource r : selection.getSelectionList()) {\r
+            if (!contains(selectedInstances,r)) {\r
+               selectedInstances.add(r);\r
+                \r
+                //System.out.println("Added " + name.getName());\r
+            } else {\r
+               \r
+               // System.out.println("Discarded " + name.getName());\r
+            }\r
+        }\r
+        setProperties(selectedInstances);\r
+    }\r
+    \r
+    public Tree getTree() {\r
+        return tree;\r
+    }\r
+\r
+    private void addProperties(final TreeItem parent, final List<Resource> selectedInstances) {\r
+       session.asyncRead(new GraphRequestAdapter() {\r
+               @Override\r
+               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                       Builtins builtins = g.getBuiltins();\r
+                       ArrayList<Resource> relationTypes = new ArrayList<Resource>();\r
+               for (Resource resource : selectedInstances) {\r
+                   IEntity thing = EntityFactory.create(g, resource);\r
+                   \r
+                   Collection<Statement> properties = thing.getRelatedStatements(builtins.HasProperty);\r
+                  // RelationSet properties = resource.getRelatedResourcesWithRelationIds(GlobalIdMap.get(Builtins.HasProperty));\r
+                   \r
+                   for (Statement r : properties) {\r
+                       // Statement contains relation from instance to property(instance)\r
+                       // Find the property's type(s)\r
+                       // TODO : seems to be bad way of finding type\r
+                       Collection<IEntity> types = r.getObject().getRelatedObjects(builtins.InstanceOf);\r
+                       if (types.size() != 1)\r
+                               throw new UnsupportedOperationException("Cannot support multi-instances");\r
+                       IEntity type = types.iterator().next();\r
+                       if (!contains(relationTypes, r.getPredicate().getResource())) {\r
+                           \r
+                           if (type.isInheritedFrom(builtins.Double)) {\r
+                               \r
+                               relationTypes.add(r.getPredicate().getResource());\r
+                              \r
+                               //System.out.println("Added " + name.getName() + " " + type.getId() + " " + r.getRelationId() + " " + relationType.getId());\r
+                               final String name = getNameForThing(r.getPredicate());//getNameForThing(thing);\r
+                               final Object treeData = r.getPredicate().getResource();\r
+                               Display.getDefault().asyncExec(new Runnable() {\r
+                               //parent.getDisplay().asyncExec(new Runnable() {\r
+                                       TreeItem item = null;\r
+                                       @Override\r
+                                       public void run() {\r
+                                               if (parent != null)\r
+                                           item = new TreeItem(parent,SWT.NONE);\r
+                                       else\r
+                                           item = new TreeItem(tree,SWT.NONE);\r
+                                       item.setData(treeData);\r
+                                       item.setText(name);\r
+                                               \r
+                                       }\r
+                               });\r
+                               \r
+                           } else {\r
+                               //Resource pproperties[] = r.getRelatedResources(GlobalIdMap.get(Builtins.PropertyRelationType));\r
+                                   //Resource pproperties[] = resource.get(r.getObjectId()).getRelatedResources(GlobalIdMap.get(Builtins.HasProperty));\r
+                                   Collection<IEntity> pproperties = r.getObject().getRelatedObjects(builtins.HasProperty);\r
+                               if (pproperties.size() > 0) {\r
+                                       final ArrayList<Resource> list = new ArrayList<Resource>();\r
+                                       list.add(r.getObject().getResource());\r
+                                      \r
+                                       final String name = getNameForThing(r.getPredicate());//getNameForThing(thing);\r
+                                       final Object treeData = r.getPredicate().getResource();\r
+                                       relationTypes.add(r.getPredicate().getResource());\r
+                                       Display.getDefault().asyncExec(new Runnable() {\r
+                                       //parent.getDisplay().asyncExec(new Runnable() {\r
+                                               @Override\r
+                                               public void run() {\r
+                                                       TreeItem item = null;\r
+                                                                               if (parent != null)\r
+                                                                                       item = new TreeItem(parent, SWT.NONE);\r
+                                                                               else\r
+                                                                                       item = new TreeItem(tree, SWT.NONE);\r
+                                                                               item.setText(name);\r
+                                                                               item.setData(treeData);\r
+                                                                               addProperties(item,list);\r
+                                               }\r
+                                       });\r
+                                   }\r
+                           }\r
+                       } \r
+                   }\r
+               }\r
+                       return GraphRequestStatus.transactionComplete();\r
+               }\r
+       });\r
+        \r
+    }\r
+    \r
+    private String getNameForThing(IEntity thing) {\r
+       return ResourceDebugUtils.getReadableNameForEntity(thing);\r
+        /*\r
+        String tName = thing.getName();\r
+         if (tName == null) {\r
+               Collection<Thing> ptypes = thing.getTypes();\r
+               for (Thing pt : ptypes) {\r
+                       tName = pt.getName();\r
+                       if (tName != null)\r
+                               break;\r
+               }\r
+         }\r
+         if (tName == null)\r
+                return "Error / no name for " + thing;\r
+         return tName;\r
+         */\r
+    }\r
+    \r
+    private boolean contains(java.util.List<Resource> list, Resource value) {\r
+        for (int i = 0; i < list.size(); i++) {\r
+            if (list.get(i).equals(value))\r
+                return true;\r
+        }\r
+        return false;\r
+    }\r
+    \r
+    /**\r
+     * Returns all properties (instances) contained in the list depending on selection in the tree and \r
+     * TODO : currently can be run only in UI -thread with transaction.\r
+     * \r
+     * @param graph\r
+     * @param shapes\r
+     * @return\r
+     */\r
+    public List<Resource> findLeafPropertyInstances(Graph graph,List<Resource> shapes) {\r
+        TreeItem[] selectedProperties = tree.getSelection();\r
+        List<Resource> props = new ArrayList<Resource>();\r
+        for (TreeItem propertyItem : selectedProperties) {\r
+            \r
+            TreeItem t = propertyItem;\r
+            boolean c = false;\r
+            // if list contains treeNode's parent, node's property is already mapped / will be mapped later\r
+            while (t.getParentItem() != null) {\r
+                if (contains(selectedProperties, t.getParentItem())) {\r
+                    c = true;\r
+                    break;\r
+                }\r
+                t = t.getParentItem();\r
+\r
+            }\r
+            if (!c) {\r
+               props.addAll(findLeafProperties(graph,shapes, propertyItem));\r
+            }\r
+        }\r
+        return props;\r
+    }\r
+    \r
+    public List<Resource> findPropertyInstances(Graph graph,List<Resource> shapes) {\r
+        TreeItem[] selectedProperties = tree.getSelection();\r
+        List<Resource> props = new ArrayList<Resource>();\r
+        for (TreeItem propertyItem : selectedProperties) {\r
+            \r
+            TreeItem t = propertyItem;\r
+            boolean c = false;\r
+            // if list contains treeNode's parent, node's property is already mapped / will be mapped later\r
+            while (t.getParentItem() != null) {\r
+                if (contains(selectedProperties, t.getParentItem())) {\r
+                    c = true;\r
+                    break;\r
+                }\r
+                t = t.getParentItem();\r
+\r
+            }\r
+            if (!c) {\r
+               props.addAll(findProperties(graph,shapes, propertyItem));\r
+            }\r
+        }\r
+        return props;\r
+    }\r
+    \r
+    private List<Resource> findProperties(Graph graph,java.util.List<Resource> shapes, TreeItem propertyItem) {\r
+        ArrayList<Resource> propertyChain = new ArrayList<Resource>();\r
+        TreeItem t = propertyItem;\r
+        while (t != null) {\r
+            propertyChain.add((Resource) t.getData());\r
+            t = t.getParentItem();\r
+        }\r
+        \r
+        return findProperties(graph,shapes,propertyChain);\r
+       \r
+    }\r
+    \r
+    private List<Resource> findLeafProperties(Graph graph,java.util.List<Resource> shapes, TreeItem propertyItem) {\r
+        ArrayList<Resource> propertyChain = new ArrayList<Resource>();\r
+        TreeItem t = propertyItem;\r
+        while (t != null) {\r
+            propertyChain.add((Resource)t.getData());\r
+            t = t.getParentItem();\r
+        }\r
+        // now propertyChain contains property hierarchy from leaf to root\r
+        //Long typeID = (Long) propertyItem.getData();\r
+        if (propertyItem.getItemCount() == 0) { \r
+            return findProperties(graph,shapes,propertyChain);\r
+        } else {\r
+            List<Resource> props = new ArrayList<Resource>();\r
+            //Long typeID = (Long) propertyItem.getData();\r
+            TreeItem children[] = propertyItem.getItems();\r
+            //ArrayList<Resource> props = getPropertiesForType(shapes, typeID);\r
+            for (TreeItem i : children)\r
+                //mapProperty(parameter,props, i);\r
+                props.addAll(findLeafProperties(graph,shapes, i));\r
+            return props;\r
+        }\r
+    }\r
+    \r
+    private List<Resource> findProperties(Graph graph, java.util.List<Resource> shapes, ArrayList<Resource> propertyChain) {\r
+        ArrayList<Resource> res = new ArrayList<Resource>(shapes);\r
+        // propertyChain contains hierarhy of properties form leaf to root :\r
+        // we'll find root property from shapes and then iterate each property instance\r
+        // until we'll fin all requested properties (first element in property chain)\r
+        \r
+//        System.out.print("instances ");\r
+//        for (Resource r : res) {\r
+//            System.out.print(r + " ");\r
+//        }\r
+//        System.out.println();\r
+        \r
+        while (propertyChain.size() > 0) {\r
+            res = getPropertiesForType(graph, res, propertyChain.get(propertyChain.size() - 1));\r
+//            System.out.print(propertyChain.get(propertyChain.size() - 1) +" instances ");\r
+//            for (Resource r : res) {\r
+//                System.out.print(r + " ");\r
+//            }\r
+//            System.out.println();\r
+            propertyChain.remove(propertyChain.size() - 1);\r
+        }\r
+        // now res contains all instances of requested property\r
+        return res;\r
+    }\r
+    \r
+    private ArrayList<Resource> getPropertiesForType(Graph graph,java.util.List<Resource> instances, Resource typeID) {\r
+        ArrayList<Resource> properties = new ArrayList<Resource>();\r
+        for (Resource instance : instances) {\r
+               IEntity t = EntityFactory.create(graph,instance);\r
+               Collection<IEntity> props = t.getRelatedObjects(typeID);\r
+            for (IEntity p : props)\r
+                properties.add(p.getResource());\r
+                \r
+        }\r
+        return properties;\r
+    }\r
+    \r
+    private boolean contains(TreeItem items[], TreeItem item) {\r
+        for (TreeItem i : items)\r
+            if (i.equals(item))\r
+                return true;\r
+        return false;\r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/ScenegraphLockTraverser.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/tools/ScenegraphLockTraverser.java
new file mode 100644 (file)
index 0000000..c3bf357
--- /dev/null
@@ -0,0 +1,32 @@
+package org.simantics.proconf.g3d.tools;\r
+\r
+import java.util.ArrayList;\r
+\r
+import com.jme.scene.Node;\r
+import com.jme.scene.Spatial;\r
+\r
+public class ScenegraphLockTraverser {\r
+       Node root;\r
+       boolean lock;\r
+       public ScenegraphLockTraverser(Node root, boolean lock) {\r
+               this.root = root;\r
+               this.lock = lock;\r
+               lock(root);\r
+       }\r
+       \r
+       private void lock(Spatial spatial) {\r
+               if (lock)\r
+                       spatial.lock();\r
+               else\r
+                       spatial.unlock();\r
+               if (spatial instanceof Node) {\r
+                       Node node = (Node)spatial;\r
+                       ArrayList<Spatial> children = node.getChildren();\r
+               for (Spatial s : children) {\r
+                       s.lock();\r
+                       lock(s);\r
+               }\r
+               }\r
+               \r
+       }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/AppearanceEditor.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/AppearanceEditor.java
new file mode 100644 (file)
index 0000000..6917078
--- /dev/null
@@ -0,0 +1,1146 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.views;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Iterator;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.MouseAdapter;\r
+import org.eclipse.swt.events.MouseEvent;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.RGB;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.ColorDialog;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Slider;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+import org.simantics.layer0.utils.StubLinkedList;\r
+import org.simantics.layer0.utils.internal.Entity;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.base.AppearanceTools;\r
+import org.simantics.proconf.g3d.stubs.Appearance;\r
+import org.simantics.proconf.g3d.stubs.ImageTexture;\r
+import org.simantics.proconf.g3d.stubs.Material;\r
+import org.simantics.proconf.g3d.stubs.MultiTexture;\r
+import org.simantics.proconf.g3d.stubs.Shader;\r
+import org.simantics.proconf.g3d.stubs.Texture;\r
+import org.simantics.proconf.g3d.stubs.TextureCoordinateGenerator;\r
+import org.simantics.proconf.image.ImageUtils;\r
+import org.simantics.proconf.image.interfaces.IImage;\r
+import org.simantics.proconf.image.interfaces.IImageFactory;\r
+import org.simantics.proconf.image.ui.ImageComposite;\r
+import org.simantics.proconf.ui.utils.ResourceAdaptionUtils;\r
+import org.simantics.utils.ErrorLogger;\r
+\r
+\r
+public class AppearanceEditor extends SinglePageResourceView{\r
+\r
+    //Appearance appearance;\r
+       Resource shapeResource;\r
+       Resource appearanceResource;\r
+       \r
+       private enum EditorState{NONE,NO_SHAPE,NO_APPEARANCE, APPEARANCE};\r
+       EditorState state = EditorState.NONE;\r
+       \r
+    Button materialButton;\r
+    \r
+    Composite ambientComposite;\r
+    Composite diffuseComposite;\r
+    Composite specularComposite;\r
+    Composite emissiveComposite;\r
+    Slider specularSlider;\r
+    Slider transparencySlider;\r
+    \r
+    \r
+    Composite textureParent;\r
+    \r
+    Button textureButton;\r
+    Button addTextureButton;\r
+    \r
+    \r
+    //Image image = null;\r
+    \r
+    boolean updating = false;\r
+    \r
+    private ArrayList<TextureComposite> textureComposites = new ArrayList<TextureComposite>();\r
+    \r
+    Button shaderButton;\r
+    Text fragmentShaderText; \r
+    Text vertexShaderText; \r
+    \r
+    Button apply3Button;\r
+    Button apply2Button;\r
+    Button applyButton;\r
+    \r
+    public AppearanceEditor() {\r
+       super();\r
+        //super(Activator.PLUGIN_ID);\r
+       \r
+    }\r
+    \r
+    @Override\r
+    public void createPartControl(Composite parent) {\r
+       super.createPartControl(parent);\r
+       createWidgets();\r
+    }\r
+\r
+    @Override\r
+    protected String getFormText() {\r
+        return "Appearance Editor";\r
+    }\r
+\r
+//    @Override\r
+//    protected void beforeCreateWidgets() {\r
+//        if (!(getInputResource().isInstanceOf(GlobalIdMap.get(ThreeDimensionalModelingOntologyMapping.APPEARANCE))))\r
+//            throw new RuntimeException("Trying to open resource that is not appearance");\r
+//        appearance = AppearanceFactory.create(getInputResource());\r
+//    }\r
+    \r
+    \r
+\r
+    @Override\r
+    protected void createWidgets() {\r
+       \r
+       if (shapeResource == null) {\r
+               if (state != EditorState.NO_SHAPE) {\r
+                       clearForm();\r
+                       state = EditorState.NO_SHAPE;\r
+                       toolkit.createLabel(getBody(), "No shape selected");\r
+                       getActiveForm().layout(true, true);\r
+               }\r
+       } else if (appearanceResource == null){\r
+               if (state != EditorState.NO_APPEARANCE) {\r
+                       clearForm();\r
+                       state = EditorState.NO_APPEARANCE;\r
+                       toolkit.createLabel(getBody(), "Selected shape does not have material definition.");\r
+                       Button b = toolkit.createButton(getBody(), "Create Appearance", SWT.PUSH);\r
+                       b.addSelectionListener(new SelectionAdapter() {\r
+                               @Override\r
+                               public void widgetSelected(SelectionEvent e) {\r
+                                       getSession().asyncWrite(new GraphRequestAdapter() {\r
+                                               @Override\r
+                                               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                                                       Appearance appearance = Appearance.createDefault(g);\r
+                                                       appearanceResource = appearance.getResource();\r
+                                                       g.addStatement(shapeResource, Resources.g3dResource.HasAppearance, appearanceResource);\r
+                                                       return GraphRequestStatus.transactionComplete();\r
+                                               }\r
+                                               \r
+                                               @Override\r
+                                               public void requestCompleted( GraphRequestStatus status) {\r
+                                                       reloadInUIThread();\r
+                                               }\r
+                                       });\r
+\r
+                               }\r
+                       });\r
+                       getActiveForm().layout(true, true);\r
+               }\r
+       } else {\r
+               if (state != EditorState.APPEARANCE) {\r
+                       clearForm();\r
+                       state = EditorState.APPEARANCE;\r
+                       createMaterialGroup(newGridSection(2, 2, false, false, "Material", "Material properties"));\r
+                       createTextureGroup(newGridSection(1, 1, false, false, "Texture", "Texture properties"));\r
+                       createShaderGroup(newGridSection(2, 2, false, false, "Shader", "Shader properties"));\r
+                       getActiveForm().layout(true, true);\r
+               }\r
+               \r
+       }\r
+    }\r
+    \r
+    @Override\r
+    public void clearForm() {\r
+       super.clearForm();\r
+       textureComposites.clear();\r
+    }\r
+    \r
+    @Override\r
+    protected void pageSelectionChanged(IWorkbenchPart part, ISelection selection) {\r
+       Resource res[] = ResourceAdaptionUtils.toResources(selection);\r
+       if (res.length == 0) {\r
+               shapeResource = null;\r
+               appearanceResource = null;\r
+               reload();\r
+               return;\r
+       }\r
+       final Resource sel = res[0];\r
+       if (sel.equals(shapeResource))\r
+                       return;\r
+       //System.out.println("AppearanceEditor.pageSelectionChanged");\r
+       getSession().asyncRead(new GraphRequestAdapter() {\r
+               @Override\r
+               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                       \r
+                       shapeResource = null;\r
+                       appearanceResource = null;\r
+                       // selected object must be a shape\r
+                       if (!g.isInstanceOf(sel, Resources.g3dResource.Shape)) {\r
+                               return GraphRequestStatus.transactionCancel();\r
+                       }\r
+                       // the shape must not be ah geometry definition\r
+                       if (g.getObjects(sel, Resources.g3dResource.GeometryDefinitionOf).size() > 0)\r
+                               return GraphRequestStatus.transactionCancel();\r
+                       \r
+                       shapeResource = sel;\r
+                       Collection<Resource> res = g.getObjects(shapeResource, Resources.g3dResource.HasAppearance);\r
+                       if (res.size() == 1)\r
+                               appearanceResource = res.iterator().next();\r
+                       return GraphRequestStatus.transactionComplete();\r
+               }\r
+               \r
+               @Override\r
+               public void requestCompleted(GraphRequestStatus status) {\r
+                       reloadInUIThread();\r
+               }\r
+       });\r
+    }\r
+    \r
+    public void reloadInUIThread() {\r
+       parent.getDisplay().asyncExec(new Runnable() {\r
+                       @Override\r
+                       public void run() {\r
+                               reload();\r
+                       }\r
+               });\r
+    }\r
+    \r
+    public void reload() {\r
+        if (updating)\r
+             return;\r
+       createWidgets();\r
+       if (state == EditorState.APPEARANCE) {\r
+               getSession().asyncRead(new GraphRequestAdapter() {\r
+                       @Override\r
+                       public GraphRequestStatus perform(Graph g) throws Exception {\r
+                               reload(g);\r
+                               return GraphRequestStatus.transactionComplete();\r
+                       }\r
+               });\r
+       }\r
+    }\r
+\r
+    @Override\r
+    public void reload(Graph g) {\r
+        if (updating)\r
+            return;\r
+        if (state != EditorState.APPEARANCE) {\r
+               return;\r
+        }\r
+        Appearance appearance = new Appearance(g,appearanceResource);\r
+        Material m = appearance.getMaterial();\r
+        Texture t = appearance.getTexture();\r
+        Shader s = appearance.getShader();\r
+        loadMaterial(m);\r
+        loadTexture(t);\r
+        loadShader(s);\r
+\r
+\r
+    }\r
+    \r
+    private void loadMaterial(Material m) {\r
+       final boolean hasMaterial;\r
+       final Color ambient;\r
+       final Color diffuse;\r
+       final Color specular;\r
+       final Color emissive;\r
+       final int shininess;\r
+       final int transparency;\r
+       if (m == null) {\r
+               hasMaterial = false;\r
+               ambient = null;\r
+               diffuse = null;\r
+               specular = null;\r
+               emissive = null;\r
+               shininess = 0;\r
+               transparency = 0;\r
+       } else {\r
+               hasMaterial = true;\r
+               ambient = AppearanceTools.getColor(m.getAmbientColor(), this.getBody().getDisplay());\r
+               diffuse = AppearanceTools.getColor(m.getDiffuseColor(), this.getBody().getDisplay());\r
+               specular = AppearanceTools.getColor(m.getSpecularColor(), this.getBody().getDisplay());\r
+               emissive = AppearanceTools.getColor(m.getEmissiveColor(), this.getBody().getDisplay());\r
+               shininess = (int)m.getShininess()[0];\r
+               transparency = (int)(m.getTransparency()[0]*100.0);\r
+       }\r
+       parent.getDisplay().asyncExec(new Runnable() {\r
+               @Override\r
+               public void run() {\r
+                       boolean t = hasMaterial;\r
+                   materialButton.setSelection(t);\r
+                   ambientComposite.setEnabled(t);\r
+                   diffuseComposite.setEnabled(t);\r
+                   specularComposite.setEnabled(t);\r
+                   emissiveComposite.setEnabled(t);\r
+                   specularSlider.setEnabled(t);\r
+                   transparencySlider.setEnabled(t);\r
+                       if (hasMaterial) {\r
+                   ambientComposite.setBackground(ambient);\r
+                   diffuseComposite.setBackground(diffuse);\r
+                   specularComposite.setBackground(specular);\r
+                   emissiveComposite.setBackground(emissive);\r
+                   specularSlider.setSelection(shininess);\r
+                   transparencySlider.setSelection(transparency);\r
+               } else {\r
+                       Color c = parent.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY);\r
+                       ambientComposite.setBackground(c);\r
+                   diffuseComposite.setBackground(c);\r
+                   specularComposite.setBackground(c);\r
+                   emissiveComposite.setBackground(c);\r
+               }\r
+                       \r
+               };\r
+       });\r
+        \r
+    }\r
+    \r
+    private void loadTexture(Texture t) {\r
+       //System.out.println("AppearanceEditor.loadTexture");\r
+        if (t == null) {\r
+               parent.getDisplay().asyncExec(new Runnable() {\r
+                       @Override\r
+                       public void run() {\r
+                               textureButton.setSelection(false);\r
+                       }\r
+               });\r
+            \r
+            return;\r
+        }\r
+        parent.getDisplay().asyncExec(new Runnable() {\r
+               @Override\r
+               public void run() {\r
+                       textureButton.setSelection(true);\r
+               }\r
+        });\r
+        \r
+        if (t.isInstanceOf(Resources.g3dResource.ImageTexture)) {\r
+            //final ImageTexture t2 = new ImageTexture(t);\r
+               final Resource t2 = t.getResource();\r
+               parent.getDisplay().asyncExec(new Runnable() {\r
+                       @Override\r
+                       public void run() {\r
+                               while (textureComposites.size() > 1) {\r
+                           textureComposites.remove(textureComposites.size()-1).dispose();\r
+                       }\r
+                       if (textureComposites.size() == 0) {\r
+                           textureComposites.add(new TextureComposite(textureParent,SWT.NONE));\r
+                       }\r
+                       getSession().asyncWrite(new GraphRequestAdapter() {\r
+                               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                                       try {\r
+                                   textureComposites.get(0).update(new ImageTexture(g,t2));\r
+                               } catch (Exception e) {\r
+                                   ErrorLogger.defaultLogError(e);\r
+                               }\r
+                               return GraphRequestStatus.transactionComplete();\r
+                               };\r
+                   \r
+                       });\r
+                       }\r
+               });\r
+            \r
+            \r
+        } else if (t.isInstanceOf(Resources.g3dResource.MultiTexture)) {\r
+            \r
+            MultiTexture mt = new MultiTexture(t);\r
+            StubLinkedList<IEntity> elements = new StubLinkedList<IEntity>(mt.getMultiTextureElementList());\r
+            final Resource listResource = mt.getMultiTextureElementList().getResource();\r
+            final int count = elements.size();\r
+            parent.getDisplay().asyncExec(new Runnable() {\r
+               @Override\r
+               public void run() {\r
+                       while (textureComposites.size() > count) {\r
+                        textureComposites.get(textureComposites.size()-1).dispose();\r
+                        textureComposites.remove(textureComposites.size()-1);\r
+                    }\r
+                    while (textureComposites.size() < count) {\r
+                        textureComposites.add(new TextureComposite(textureParent,SWT.NONE));\r
+                    }\r
+                       getSession().asyncWrite(new GraphRequestAdapter() {\r
+                               @Override\r
+                               public GraphRequestStatus perform(Graph g)\r
+                                               throws Exception {\r
+                                       StubLinkedList<IEntity> elements = new StubLinkedList<IEntity>(new Entity(g,listResource));\r
+                                       Iterator<IEntity> i = elements.iterator();\r
+                           int index = 0;\r
+                           while (i.hasNext()) {\r
+                               //MultiTextureElement e = new MultiTextureElement(i.next());\r
+                               //int index = e.getMultiTextureIndexValue();\r
+                               Texture tex = new Texture(i.next());//e.getTexture();\r
+                               if (tex.isInstanceOf(Resources.g3dResource.ImageTexture)) {\r
+                                   ImageTexture t2 = new ImageTexture(tex);\r
+                                   try {\r
+                                       textureComposites.get(index).update(t2);\r
+                                   } catch (Exception err) {\r
+                                       ErrorLogger.defaultLogError(err);\r
+                                   }\r
+                               }\r
+                               index++;\r
+                           }\r
+                                       return null;\r
+                               }\r
+                       });\r
+               }\r
+            });\r
+            \r
+            \r
+            \r
+        }\r
+    }\r
+    \r
+    private void loadShader(Shader s) {\r
+       final boolean hasShader = (s != null);\r
+       final String vertexShader;\r
+       final String fragmentShader;\r
+       if (hasShader) {\r
+               vertexShader = s.getVertexShader()[0];\r
+               fragmentShader = s.getFragmentShader()[0];\r
+       } else {\r
+               vertexShader = null;\r
+               fragmentShader = null;\r
+       }\r
+       parent.getDisplay().asyncExec(new Runnable() {\r
+               @Override\r
+               public void run() {\r
+                       if (!hasShader) {\r
+                   shaderButton.setSelection(false);\r
+               } else {\r
+                   shaderButton.setSelection(true);\r
+                   vertexShaderText.setText(vertexShader);\r
+                   fragmentShaderText.setText(fragmentShader);\r
+               }\r
+                       \r
+               }\r
+       });\r
+        \r
+    }\r
+    \r
+    private void createMaterialGroup(Composite parent) {\r
+        toolkit.paintBordersFor(parent);\r
+        toolkit.setBorderStyle(SWT.BORDER);\r
+        \r
+        materialButton = toolkit.createButton(parent, "Has Material", SWT.CHECK);\r
+        materialButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+               boolean t = materialButton.getSelection();\r
+                   ambientComposite.setEnabled(t);\r
+                   diffuseComposite.setEnabled(t);\r
+                   specularComposite.setEnabled(t);\r
+                   emissiveComposite.setEnabled(t);\r
+                   specularSlider.setEnabled(t);\r
+                   transparencySlider.setEnabled(t);\r
+                \r
+            }\r
+        });\r
+        GridData data = new GridData(GridData.FILL, GridData.FILL, false, false,2,1);\r
+        materialButton.setLayoutData(data);\r
+     \r
+        data = new GridData(GridData.FILL, GridData.FILL, false, false,1,1);\r
+        data.widthHint = 100;\r
+        data.heightHint = 20;\r
+\r
+        toolkit.createLabel(parent, "Ambient");\r
+        ambientComposite = toolkit.createComposite(parent, SWT.BORDER);\r
+        ambientComposite.setLayoutData(data);\r
+        ambientComposite.addMouseListener(new MouseAdapter() {\r
+           @Override\r
+            public void mouseUp(MouseEvent e) {\r
+                ColorDialog dialog = new ColorDialog(AppearanceEditor.this.getBody().getShell());\r
+                RGB rgb = dialog.open();\r
+                if (rgb != null) {\r
+                    ambientComposite.setBackground(new Color(AppearanceEditor.this.getBody().getDisplay(),rgb));\r
+                    \r
+                }\r
+           } \r
+        });\r
+\r
+        toolkit.createLabel(parent, "Diffuse");\r
+        diffuseComposite = toolkit.createComposite(parent, SWT.BORDER);\r
+        diffuseComposite.setLayoutData(data);\r
+        diffuseComposite.addMouseListener(new MouseAdapter() {\r
+            @Override\r
+             public void mouseUp(MouseEvent e) {\r
+                 ColorDialog dialog = new ColorDialog(AppearanceEditor.this.getBody().getShell());\r
+                 RGB rgb = dialog.open();\r
+                 if (rgb != null) {\r
+                     diffuseComposite.setBackground(new Color(AppearanceEditor.this.getBody().getDisplay(),rgb));\r
+                     \r
+                 }\r
+            } \r
+         });\r
+        toolkit.createLabel(parent, "Specular");\r
+        specularComposite = toolkit.createComposite(parent, SWT.BORDER);\r
+        specularComposite.setLayoutData(data);\r
+        specularComposite.addMouseListener(new MouseAdapter() {\r
+            @Override\r
+             public void mouseUp(MouseEvent e) {\r
+                 ColorDialog dialog = new ColorDialog(AppearanceEditor.this.getBody().getShell());\r
+                 \r
+                 RGB rgb = dialog.open();\r
+                 if (rgb != null) {\r
+                     specularComposite.setBackground(new Color(AppearanceEditor.this.getBody().getDisplay(),rgb));\r
+                     \r
+                 }\r
+            } \r
+         });\r
+        toolkit.createLabel(parent, "Emissive");\r
+        emissiveComposite = toolkit.createComposite(parent, SWT.BORDER);\r
+        emissiveComposite.setLayoutData(data);\r
+        emissiveComposite.addMouseListener(new MouseAdapter() {\r
+            @Override\r
+             public void mouseUp(MouseEvent e) {\r
+                 ColorDialog dialog = new ColorDialog(AppearanceEditor.this.getBody().getShell());\r
+                 RGB rgb = dialog.open();\r
+                 if (rgb != null) {\r
+                     emissiveComposite.setBackground(new Color(AppearanceEditor.this.getBody().getDisplay(),rgb));\r
+                     \r
+                 }\r
+            } \r
+         });\r
+        toolkit.createLabel(parent, "Shininess");\r
+        specularSlider = new Slider(parent,SWT.NONE);\r
+        specularSlider.setValues(20, 0, 255, 1, 1, 10);\r
+        toolkit.adapt(specularSlider, true, true);\r
+        toolkit.createLabel(parent, "Transparency");\r
+        transparencySlider = new Slider(parent,SWT.NONE);\r
+        transparencySlider.setValues(0, 0, 100, 1, 1, 10);\r
+        toolkit.adapt(transparencySlider, true, true);\r
+        apply2Button = toolkit.createButton(parent, "Apply", SWT.PUSH);\r
+        apply2Button.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                convertMaterial();\r
+            }\r
+        });\r
+        \r
+    }\r
+    \r
+    private void createTextureGroup(Composite parent) {\r
+        textureParent = parent;\r
+        toolkit.paintBordersFor(parent);\r
+        toolkit.setBorderStyle(SWT.BORDER);\r
+        \r
+        textureButton = toolkit.createButton(parent, "Has Texture", SWT.CHECK);\r
+        textureButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                //loadImageButton.setEnabled(textureButton.getSelection());\r
+                //imageComposite.setEnabled(textureButton.getSelection());\r
+                //textureButton.setEnabled(textureButton.getSelection());\r
+                \r
+            }\r
+        });\r
+        \r
+        \r
+        \r
+        textureButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                //loadImageButton.setEnabled(textureButton.getSelection());\r
+                //imageComposite.setEnabled(textureButton.getSelection());\r
+                //textureButton.setEnabled(textureButton.getSelection());\r
+                \r
+            }\r
+        });\r
+        addTextureButton = toolkit.createButton(parent, "Add Texture", SWT.PUSH);\r
+        addTextureButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                textureComposites.add(new TextureComposite(textureParent,SWT.NONE));\r
+            }\r
+        });\r
+        applyButton = toolkit.createButton(parent, "Apply", SWT.PUSH);\r
+        applyButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                convertImage();\r
+            }\r
+        });\r
+        \r
+    }\r
+    \r
+    private void createShaderGroup(Composite parent) {\r
+        toolkit.paintBordersFor(parent);\r
+        toolkit.setBorderStyle(SWT.BORDER);\r
+        GridData data = new GridData(SWT.FILL,SWT.FILL,true,true,2,1);\r
+        shaderButton = toolkit.createButton(parent, "Has Shader", SWT.CHECK);\r
+        shaderButton.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+               \r
+                \r
+            }\r
+        });\r
+        shaderButton.setLayoutData(data);\r
+        data = new GridData(SWT.FILL,SWT.FILL,true,true,1,1);\r
+        data.widthHint = 400;\r
+        data.heightHint = 200;\r
+        toolkit.createLabel(parent, "Vertex Shader");\r
+        vertexShaderText = toolkit.createText(parent,"", SWT.MULTI);\r
+        vertexShaderText.setLayoutData(data);\r
+        toolkit.createLabel(parent, "Fragment Shader");\r
+        fragmentShaderText = toolkit.createText(parent,"", SWT.MULTI);\r
+        fragmentShaderText.setLayoutData(data);\r
+        apply3Button = toolkit.createButton(parent, "Apply", SWT.PUSH);\r
+        apply3Button.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                convertShader();\r
+            }\r
+        });\r
+    }\r
+    \r
+    \r
+    \r
+    private void convertShader() {\r
+        updating = true;\r
+        final boolean hasShader = shaderButton.getSelection();\r
+        final String vertexShader = vertexShaderText.getText();\r
+        final String fragmentShader = fragmentShaderText.getText();\r
+        getSession().asyncWrite(new GraphRequestAdapter() {\r
+               @Override\r
+               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                       Appearance appearance = new Appearance(g,appearanceResource);\r
+                       if (hasShader) {\r
+                    Shader s = appearance.getShader();\r
+                    if (s == null) {\r
+                        s = Shader.createDefault(g);\r
+                        appearance.setShader(s);\r
+\r
+                    }\r
+                    s.setVertexShader(vertexShader);\r
+                    s.setFragmentShader(fragmentShader);\r
+                } else {\r
+                    appearance.setShader(null);\r
+                }\r
+                       \r
+                       updating = false;\r
+                       return GraphRequestStatus.transactionComplete();\r
+               }\r
+        });\r
+        \r
+        \r
+    }\r
+    \r
+    private void convertMaterial() {\r
+        updating = true;\r
+        \r
+        final boolean hasMaterial = materialButton.getSelection();\r
+        final Color ambientColor = ambientComposite.getBackground();\r
+        final Color diffuseColor = diffuseComposite.getBackground();\r
+        final Color specularColor = specularComposite.getBackground();\r
+        final Color emissiveColor = emissiveComposite.getBackground();\r
+        final double shininess = (double)specularSlider.getSelection();\r
+        final double transparency = (double)transparencySlider.getSelection()/ 100.0;\r
+        \r
+        getSession().asyncWrite(new GraphRequestAdapter() {\r
+               @Override\r
+               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                       Appearance appearance = new Appearance(g,appearanceResource);\r
+                       if (hasMaterial) {\r
+                    Material m = appearance.getMaterial();\r
+                    if (m == null) {\r
+                        m = Material.createDefault(g);\r
+                    }\r
+                    org.simantics.proconf.g3d.stubs.Color aColor = m.getAmbientColor();\r
+                    org.simantics.proconf.g3d.stubs.Color dColor = m.getDiffuseColor();\r
+                    org.simantics.proconf.g3d.stubs.Color sColor = m.getSpecularColor();\r
+                    org.simantics.proconf.g3d.stubs.Color eColor = m.getEmissiveColor();\r
+                    AppearanceTools.setColor(aColor,ambientColor);\r
+                    AppearanceTools.setColor(dColor,diffuseColor);\r
+                    AppearanceTools.setColor(sColor, specularColor);\r
+                    AppearanceTools.setColor(eColor, emissiveColor);\r
+                    m.setShininess(shininess);\r
+                    m.setTransparency(transparency);\r
+                    appearance.setMaterial(m);\r
+                } else {\r
+                       appearance.removeRelatedStatements(Resources.g3dResource.HasMaterial);\r
+                }\r
+                       \r
+                       updating = false;\r
+                       return GraphRequestStatus.transactionComplete();\r
+               }\r
+        });\r
+        \r
+    }\r
+    \r
+    private void convertImage() {\r
+        updating = true;\r
+        getSession().syncWrite(new GraphRequestAdapter() {\r
+               @Override\r
+               public GraphRequestStatus perform(Graph g) throws Exception {\r
+                       Appearance appearance = new Appearance(g,appearanceResource);\r
+                       Texture t = appearance.getTexture();\r
+                if (textureComposites.size() == 1) {\r
+                    ImageTexture t2 = null;\r
+                    if (t != null && t.isInstanceOf(Resources.g3dResource.ImageTexture)) {\r
+                        t2 = new ImageTexture(t);\r
+                    } else {\r
+                        t2 = ImageTexture.createDefault(g);\r
+                        appearance.setTexture(t2);\r
+                    }\r
+                    final Resource mode = textureComposites.get(0).getModeType();\r
+                               \r
+\r
+                    if (mode != null)\r
+                        t2.setTextureMode(mode);\r
+                    textureComposites.get(0).getTexture(t2);\r
+                    \r
+                } else if (textureComposites.size() > 1) {\r
+                    MultiTexture mt = null;\r
+                    if (t != null\r
+                            && t.isInstanceOf(Resources.g3dResource.MultiTexture)) {\r
+                        mt = new MultiTexture(t);\r
+                    } else {\r
+                        mt = MultiTexture.createDefault(g);\r
+                        appearance.setTexture(mt);\r
+                    }\r
+                    StubLinkedList<IEntity> elements = new StubLinkedList<IEntity>(mt.getMultiTextureElementList());\r
+                    //PropertyTypeSet<MultiTextureElement> elements = mt.getMultiTextureElementSet();\r
+                    Iterator<IEntity> it = elements.iterator();\r
+                    for (int i = 0; i < textureComposites.size(); i++) {\r
+                        TextureComposite tc = textureComposites.get(i);\r
+                        \r
+                        ImageTexture tex = null;\r
+                        if (it.hasNext())\r
+                               tex = new ImageTexture(it.next());\r
+                        else {\r
+                               tex = ImageTexture.createDefault(g);\r
+                               elements.add(i,tex);\r
+                        }\r
+                        Resource mode = tc.getModeType();\r
+                        if (mode == null)\r
+                            tex.setTextureMode(Resources.g3dResource.CombineMode_modulate);\r
+                        else\r
+                            tex.setTextureMode(mode);\r
+                        \r
+                        textureComposites.get(i).getTexture(tex);\r
+                        \r
+                    }\r
+                } else {\r
+                    appearance.setTexture(null);\r
+                }\r
+          \r
+                updating = false;\r
+                       return GraphRequestStatus.transactionComplete();\r
+               }\r
+        });\r
+     \r
+            \r
+           \r
+        \r
+    }\r
+\r
+    private class TextureComposite extends Composite {\r
+        private Button textureGeneratorButton;\r
+        private Button sphereMapButton;\r
+        private Button eyeLinearButton;\r
+        private Button objectLinearButton;\r
+        private Button normalMapButton;\r
+        private Button reflectionMapButton;\r
+        \r
+        private Button modulateButton;\r
+        private Button replaceButton;\r
+        private Button decalButton;\r
+        private Button blendButton;\r
+        \r
+        \r
+        \r
+        private Button loadImageButton;\r
+        private ImageComposite imageComposite;\r
+        private Button removeButton;\r
+        \r
+        \r
+        public TextureComposite(Composite parent, int style) {\r
+            super(parent,style);\r
+            GridLayout layout = new GridLayout(2,false);\r
+            this.setLayout(layout);\r
+            \r
+            loadImageButton = toolkit.createButton(this, "Load Texture", SWT.PUSH);\r
+            loadImageButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+\r
+                       IImage[] images = ImageUtils.loadImagesDialog(getSite().getShell(), false, ImageUtils.getImageFactories());\r
+                       if (images == null)\r
+                               return;\r
+                       IImage image = images[0];\r
+                       setImage(image);\r
+\r
+                }\r
+            });\r
+            GridData data = new GridData(SWT.LEFT,SWT.FILL,false,false,2,1);\r
+            \r
+            loadImageButton.setLayoutData(data);\r
+            data = new GridData(SWT.FILL,SWT.FILL,true,true,2,1);\r
+            imageComposite = new ImageComposite(this,SWT.BORDER);\r
+            imageComposite.setLayoutData(data);\r
+            \r
+            Composite texGenComposite = toolkit.createComposite(this, SWT.BORDER);\r
+            layout = new GridLayout(1,false);\r
+            texGenComposite.setLayout(layout);\r
+            data = new GridData(SWT.FILL,SWT.FILL,true,true,1,1);\r
+            data.heightHint = 140;\r
+            texGenComposite.setLayoutData(data);\r
+            textureGeneratorButton = toolkit.createButton(texGenComposite, "Has Texture Coordinate Generator", SWT.CHECK);\r
+            textureGeneratorButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    sphereMapButton.setEnabled(textureGeneratorButton.getSelection());\r
+                    eyeLinearButton.setEnabled(textureGeneratorButton.getSelection());\r
+                    objectLinearButton.setEnabled(textureGeneratorButton.getSelection());\r
+                    normalMapButton.setEnabled(textureGeneratorButton.getSelection());\r
+                    reflectionMapButton.setEnabled(textureGeneratorButton.getSelection());\r
+                    \r
+                }\r
+            });\r
+            \r
+            sphereMapButton = toolkit.createButton(texGenComposite, "Shpere Map", SWT.RADIO);\r
+            sphereMapButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    if (!sphereMapButton.getSelection()) {\r
+                        sphereMapButton.setSelection(true);\r
+                    } else {\r
+                        eyeLinearButton.setSelection(false);\r
+                        objectLinearButton.setSelection(false);\r
+                        normalMapButton.setSelection(false);\r
+                        reflectionMapButton.setSelection(false);\r
+                    }\r
+                }\r
+            });\r
+            eyeLinearButton = toolkit.createButton(texGenComposite, "Eye Linear", SWT.RADIO);\r
+            eyeLinearButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    if (!eyeLinearButton.getSelection()) {\r
+                        eyeLinearButton.setSelection(true);\r
+                    } else {\r
+                        sphereMapButton.setSelection(false);\r
+                        objectLinearButton.setSelection(false);\r
+                        normalMapButton.setSelection(false);\r
+                        reflectionMapButton.setSelection(false);\r
+                    }\r
+                }\r
+            });\r
+            objectLinearButton = toolkit.createButton(texGenComposite, "Object Linear", SWT.RADIO);\r
+            objectLinearButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    if (!objectLinearButton.getSelection()) {\r
+                        objectLinearButton.setSelection(true);\r
+                    } else {\r
+                        eyeLinearButton.setSelection(false);\r
+                        sphereMapButton.setSelection(false);\r
+                        normalMapButton.setSelection(false);\r
+                        reflectionMapButton.setSelection(false);\r
+                    }\r
+                }\r
+            });\r
+            normalMapButton = toolkit.createButton(texGenComposite, "Normal Map", SWT.RADIO);\r
+            normalMapButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    if (!normalMapButton.getSelection()) {\r
+                        normalMapButton.setSelection(true);\r
+                    } else {\r
+                        eyeLinearButton.setSelection(false);\r
+                        objectLinearButton.setSelection(false);\r
+                        sphereMapButton.setSelection(false);\r
+                        reflectionMapButton.setSelection(false);\r
+                    }\r
+                }\r
+            });\r
+            reflectionMapButton = toolkit.createButton(texGenComposite, "Reflection Map", SWT.RADIO);\r
+            reflectionMapButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                    if (!reflectionMapButton.getSelection()) {\r
+                        reflectionMapButton.setSelection(true);\r
+                    } else {\r
+                        eyeLinearButton.setSelection(false);\r
+                        objectLinearButton.setSelection(false);\r
+                        normalMapButton.setSelection(false);\r
+                        sphereMapButton.setSelection(false);\r
+                    }\r
+                }\r
+            });\r
+            \r
+            Composite texModeComposite = toolkit.createComposite(this, SWT.BORDER);\r
+            texModeComposite.setLayout(layout);\r
+            texModeComposite.setLayoutData(data);\r
+            modulateButton = toolkit.createButton(texModeComposite, "Modulate", SWT.RADIO);\r
+            modulateButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                        modulateButton.setSelection(true);\r
+                        replaceButton.setSelection(false);\r
+                        blendButton.setSelection(false);\r
+                        decalButton.setSelection(false);\r
+\r
+                }\r
+            });\r
+            blendButton = toolkit.createButton(texModeComposite, "Blend", SWT.RADIO);\r
+            blendButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                        modulateButton.setSelection(false);\r
+                        replaceButton.setSelection(false);\r
+                        blendButton.setSelection(true);\r
+                        decalButton.setSelection(false);\r
+\r
+                }\r
+            });\r
+            replaceButton = toolkit.createButton(texModeComposite, "Replace", SWT.RADIO);\r
+            replaceButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                        modulateButton.setSelection(false);\r
+                        replaceButton.setSelection(true);\r
+                        blendButton.setSelection(false);\r
+                        decalButton.setSelection(false);\r
+\r
+                }\r
+            });\r
+            decalButton = toolkit.createButton(texModeComposite, "Decal", SWT.RADIO);\r
+            decalButton.addSelectionListener(new SelectionAdapter() {\r
+                public void widgetSelected(SelectionEvent e) {\r
+                        modulateButton.setSelection(false);\r
+                        replaceButton.setSelection(false);\r
+                        blendButton.setSelection(false);\r
+                        decalButton.setSelection(true);\r
+\r
+                }\r
+            });\r
+            \r
+            removeButton = toolkit.createButton(this, "Remove texture", SWT.PUSH);\r
+            parent.getParent().getParent().layout(true, true);\r
+        }\r
+        \r
+        public void setImage(IImage image) {\r
+            imageComposite.setImage(image);\r
+        }\r
+        \r
+        public IImage getImage() {\r
+            return imageComposite.getImage();\r
+        }\r
+        \r
+        public void update(ImageTexture t2) throws Exception {\r
+               Graph graph = t2.getGraph();\r
+            org.simantics.image.stubs.Image i = t2.getImage();\r
+            IImageFactory f = ImageUtils.getImageFactoryForResource(graph,i.getResource());\r
+            final IImage p = f.createImageForResource(graph,i.getResource());\r
+//            PixelDimension pd = p.getDimensions().getPixelDimension();\r
+//            if (pd==null) pd = AppearanceTools.DEFAULT_SIZE;\r
+//             final ImageData id = p.rasterize(pd.getWidth(), pd.getHeight());\r
+            \r
+            parent.getDisplay().asyncExec(new Runnable() {\r
+               @Override\r
+               public void run() {\r
+                       //Image im = new Image(AppearanceEditor.this.getBody().getDisplay(),id);\r
+                       //imageComposite.setImage(im);\r
+                    //showImage();\r
+                       setImage(p);\r
+\r
+               }\r
+            });\r
+            \r
+            TextureCoordinateGenerator gen = t2.getTextureCoordinateGenerator();\r
+            final boolean tg;\r
+            final boolean sm;\r
+            final boolean el;\r
+            final boolean ol;\r
+            final boolean nm;\r
+            final boolean rm;\r
+            if (gen == null) {\r
+               tg = false;\r
+               sm = false;\r
+               el = false;\r
+               ol = false;\r
+               nm = false;\r
+               rm = false;\r
+            } else {\r
+                //type = gen.getTextureCoordinateGeneratorTypeValue();\r
+                //textureGeneratorButton.setSelection(true);\r
+                tg = true;\r
+                if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_sphere)) {\r
+                       sm = true;\r
+                       el = false;\r
+                       ol = false;\r
+                       nm = false;\r
+                       rm = false;\r
+                } else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_eyelinear)) {\r
+                       sm = false;\r
+                       el = true;\r
+                       ol = false;\r
+                       nm = false;\r
+                       rm = false;\r
+                } else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_objectlinear)) {\r
+                       sm = false;\r
+                       el = false;\r
+                       ol = true;\r
+                       nm = false;\r
+                       rm = false;\r
+                } else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_normal)) {\r
+                       sm = false;\r
+                       el = false;\r
+                       ol = false;\r
+                       nm = true;\r
+                       rm = false;\r
+                } else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_reflection)) {\r
+                       sm = false;\r
+                       el = false;\r
+                       ol = false;\r
+                       nm = false;\r
+                       rm = true;\r
+                } else {\r
+                       sm = false;\r
+                       el = false;\r
+                       ol = false;\r
+                       nm = false;\r
+                       rm = false;\r
+                }\r
+                \r
+            }\r
+            \r
+            parent.getDisplay().asyncExec(new Runnable() {\r
+                       @Override\r
+                       public void run() {\r
+                               textureGeneratorButton.setSelection(tg);\r
+                               sphereMapButton.setSelection(sm);\r
+                               eyeLinearButton.setSelection(el);\r
+                               objectLinearButton.setSelection(ol);\r
+                               normalMapButton.setSelection(nm);\r
+                               reflectionMapButton.setSelection(rm);\r
+                               sphereMapButton.setEnabled(textureGeneratorButton.getSelection());\r
+                    eyeLinearButton.setEnabled(textureGeneratorButton.getSelection());\r
+                    objectLinearButton.setEnabled(textureGeneratorButton.getSelection());\r
+                    normalMapButton.setEnabled(textureGeneratorButton.getSelection());\r
+                    reflectionMapButton.setEnabled(textureGeneratorButton.getSelection());\r
+                               \r
+                       }\r
+               });\r
+        }\r
+        \r
+        \r
+        public Resource getGenType() {\r
+            if (sphereMapButton.getSelection())\r
+                return Resources.g3dResource.TextureCoordinateGenerator_sphere;\r
+            else if (eyeLinearButton.getSelection())\r
+               return Resources.g3dResource.TextureCoordinateGenerator_eyelinear;\r
+            else if (objectLinearButton.getSelection())\r
+               return Resources.g3dResource.TextureCoordinateGenerator_objectlinear;\r
+            else if (normalMapButton.getSelection())\r
+               return Resources.g3dResource.TextureCoordinateGenerator_normal;\r
+            else if (reflectionMapButton.getSelection())\r
+               return Resources.g3dResource.TextureCoordinateGenerator_reflection;\r
+            return null;\r
+        }\r
+        \r
+        public Resource getModeType() {\r
+            if (modulateButton.getSelection())\r
+                return Resources.g3dResource.MultiTextureMode_modulate;\r
+            else if (replaceButton.getSelection())\r
+               return Resources.g3dResource.MultiTextureMode_replace;\r
+            else if (blendButton.getSelection())\r
+               return Resources.g3dResource.MultiTextureMode_blend;\r
+            else if (decalButton.getSelection())\r
+               return Resources.g3dResource.MultiTextureMode_decal;\r
+\r
+            return null;\r
+        }\r
+        \r
+        public void getTexture(ImageTexture t2) throws Exception{\r
+               Graph g = t2.getGraph();\r
+               IImage image = getImage();\r
+               if (image != null) {\r
+                       Resource res = image.instantiateAsResource(g);\r
+                       t2.setImage(res);\r
+               }\r
+               final Resource t2res = t2.getResource();\r
+\r
+                       if (textureGeneratorButton.getSelection()) {\r
+                               final Resource type;\r
+                               if (sphereMapButton.getSelection())\r
+                                       type = Resources.g3dResource.TextureCoordinateGenerator_sphere;\r
+                               else if (eyeLinearButton.getSelection())\r
+                                       type = Resources.g3dResource.TextureCoordinateGenerator_eyelinear;\r
+                               else if (objectLinearButton.getSelection())\r
+                                       type = Resources.g3dResource.TextureCoordinateGenerator_objectlinear;\r
+                               else if (normalMapButton.getSelection())\r
+                                       type = Resources.g3dResource.TextureCoordinateGenerator_normal;\r
+                               else if (reflectionMapButton.getSelection())\r
+                                       type = Resources.g3dResource.TextureCoordinateGenerator_reflection;\r
+                               else\r
+                                       type = null;\r
+                               if (type != null) {\r
+                                       getSession().asyncWrite(new GraphRequestAdapter() {\r
+                                               @Override\r
+                                               public GraphRequestStatus perform(Graph g)\r
+                                                               throws Exception {\r
+                                                       ImageTexture t2 = new ImageTexture(g, t2res);\r
+                                                       t2.setTextureCoordinateGenerator(type);\r
+                                                       return GraphRequestStatus.transactionComplete();\r
+                                               }\r
+                                       });\r
+\r
+                               }\r
+\r
+                       }\r
+        }\r
+        \r
+        /*\r
+                * public void getTexture(ImageTexture t2) { if\r
+                * (imageComposite.getImage() != null) { ImageData data =\r
+                * imageComposite.getImage().getImageData(); if (!data.palette.isDirect) {\r
+                * throw new RuntimeException("Not direct"); } int bytes = 0; String\r
+                * type = ""; if (data.depth != 32 && data.depth != 24) { throw new\r
+                * UnsupportedOperationException("Cannot handle bitdepth " +\r
+                * data.depth); } if (data.depth == 32) { bytes = 4; type = "RGBA"; }\r
+                * else if (data.depth == 24) { bytes = 3; type = "RGB"; } String size =\r
+                * data.width + " " + data.height; byte texturedata[] = new\r
+                * byte[data.width * data.height * bytes]; for (int y = 0; y <\r
+                * data.height; y++) { for (int x = 0; x < data.width; x++) { int index =\r
+                * (y * data.width + x) * bytes;\r
+                * \r
+                * texturedata[index] = data.data[index]; texturedata[index + 1] =\r
+                * data.data[index + 1]; texturedata[index + 2] = data.data[index + 2];\r
+                * if (bytes == 4) texturedata[index + 3] = data.data[index + 3];\r
+                *  } } String base64 = new\r
+                * sun.misc.BASE64Encoder().encode(texturedata); // if\r
+                * (coreTC.getCurrentTransaction() == null)\r
+                * \r
+                * \r
+                * \r
+                * fi.vtt.proconf.threedimensionalmodeling.stub.v1_0.Image i =\r
+                * t2.getImage(); if (i == null) { i = ImageFactory.instantiate(graph);\r
+                * graph.commitChanges(this); t2.setImage(i); }\r
+                * i.setImageDataValue(base64); i.setImageTypeValue(type);\r
+                * i.setImageSizeValue(size); graph.commitChanges(this); if\r
+                * (textureGeneratorButton.getSelection()) { type = null; if\r
+                * (sphereMapButton.getSelection()) type =\r
+                * AppearanceTools.TEXTURE_COORD_GEN_SPHERE; else if\r
+                * (eyeLinearButton.getSelection()) type =\r
+                * AppearanceTools.TEXTURE_COORD_GEN_EYE_LINEAR; else if\r
+                * (objectLinearButton.getSelection()) type =\r
+                * AppearanceTools.TEXTURE_COORD_GEN_OBJECT_LINEAR; else if\r
+                * (normalMapButton.getSelection()) type =\r
+                * AppearanceTools.TEXTURE_COORD_GEN_NORMAL; else if\r
+                * (reflectionMapButton.getSelection()) type =\r
+                * AppearanceTools.TEXTURE_COORD_GEN_REFLECTION; else type = null; if\r
+                * (type != null) { TextureCoordinateGenerator gen =\r
+                * t2.getTextureCoordinateGenerator(); if (gen == null) { gen =\r
+                * TextureCoordinateGeneratorFactory.instantiate(graph);\r
+                * graph.commitChanges(this); t2.setTextureCoordinateGenerator(gen); }\r
+                * gen.setTextureCoordinateGeneratorTypeValue(type);\r
+                * graph.commitChanges(this); }\r
+                *  } else { //t2.setTextureCoordinateGenerator(null);\r
+                * graph.commitChanges(this); }\r
+                *  } }\r
+                */\r
+    }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/ScenegraphViewPart.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/ScenegraphViewPart.java
new file mode 100644 (file)
index 0000000..ee3f127
--- /dev/null
@@ -0,0 +1,610 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.views;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import org.eclipse.core.runtime.IAdaptable;\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.IMenuManager;\r
+import org.eclipse.jface.action.IToolBarManager;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.jface.viewers.ITreeContentProvider;\r
+import org.eclipse.jface.viewers.LabelProvider;\r
+import org.eclipse.jface.viewers.TreeViewer;\r
+import org.eclipse.jface.viewers.Viewer;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.ui.IActionBars;\r
+import org.eclipse.ui.IPartListener;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.IWorkbenchWindow;\r
+import org.eclipse.ui.PlatformUI;\r
+import org.eclipse.ui.part.ViewPart;\r
+import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor;\r
+import org.eclipse.ui.views.properties.IPropertyDescriptor;\r
+import org.eclipse.ui.views.properties.IPropertySource;\r
+import org.eclipse.ui.views.properties.TextPropertyDescriptor;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorPart;\r
+import org.simantics.proconf.g3d.scenegraph.IGeometryNode;\r
+import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
+import org.simantics.proconf.g3d.scenegraph.ISelectableNode;\r
+import org.simantics.utils.ui.gfx.ImageCache;\r
+\r
+import com.jme.scene.Geometry;\r
+import com.jme.scene.Node;\r
+import com.jme.scene.SceneElement;\r
+import com.jme.scene.Spatial;\r
+import com.jme.scene.batch.GeomBatch;\r
+\r
+public class ScenegraphViewPart extends ViewPart{\r
+       \r
+       private static final ImageDescriptor GEOMETRY_IMAGE = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/geometry.png");\r
+       private static final ImageDescriptor BATCH_IMAGE = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/batch.png");\r
+       private static final ImageDescriptor NODE_IMAGE = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/node.png");\r
+               \r
+       \r
+       TreeViewer viewer;\r
+       \r
+       IPartListener listener;\r
+       \r
+       Action showJMEAction;\r
+       \r
+       @Override\r
+       public void createPartControl(Composite parent) {\r
+\r
+               viewer = new TreeViewer(parent, SWT.SINGLE | SWT.H_SCROLL| SWT.V_SCROLL);\r
+               viewer.setContentProvider(new GNScenegraphContentProvider());\r
+               viewer.setLabelProvider(new GNScenegraphLabelProvider());\r
+               getSite().setSelectionProvider(viewer);\r
+               \r
+               makeActions();\r
+               \r
+               IActionBars actionBar = getViewSite().getActionBars();\r
+               contributeToActionBars(actionBar);\r
+               \r
+               listener = new IPartListener() {\r
+                       @Override\r
+                       public void partActivated(IWorkbenchPart part) {\r
+                               if (part instanceof ThreeDimensionalEditorPart) {\r
+                                       ThreeDimensionalEditorPart p = (ThreeDimensionalEditorPart)part;\r
+                                       Object newInput = p.getEditor();\r
+                                       if (viewer.getInput() != newInput)\r
+                                               viewer.setInput(newInput);\r
+                               } else {\r
+                                       //viewer.setInput(null);\r
+                               }\r
+                               \r
+                       }\r
+                       \r
+                       @Override\r
+                       public void partBroughtToTop(IWorkbenchPart part) {\r
+\r
+                       }\r
+                       \r
+                       @Override\r
+                       public void partClosed(IWorkbenchPart part) {\r
+\r
+                       }\r
+                       \r
+                       @Override\r
+                       public void partDeactivated(IWorkbenchPart part) {\r
+\r
+                       }\r
+                       \r
+                       @Override\r
+                       public void partOpened(IWorkbenchPart part) {\r
+\r
+                       }\r
+               };\r
+               for (IWorkbenchWindow w : PlatformUI.getWorkbench().getWorkbenchWindows()) {\r
+                       w.getPartService().addPartListener(listener);\r
+                               \r
+               }\r
+               \r
+       }\r
+       \r
+       protected void makeActions() {\r
+               showJMEAction = new Action("jME",Action.AS_CHECK_BOX) {\r
+                       @Override\r
+                       public void run() {\r
+                               Object input = viewer.getInput();\r
+                               viewer.setInput(null);\r
+                               if (this.isChecked()) {\r
+                                       viewer.setContentProvider(new JMEScenegraphContentProvider());\r
+                                       viewer.setLabelProvider(new JMEScenegraphLabelProvider());\r
+                               } else {\r
+                                       viewer.setContentProvider(new GNScenegraphContentProvider());\r
+                                       viewer.setLabelProvider(new GNScenegraphLabelProvider());\r
+                               }\r
+                               viewer.setInput(input);\r
+                       }\r
+               };\r
+       }\r
+       \r
+       protected void contributeToActionBars(IActionBars bars) {\r
+               fillLocalToolBar(bars.getToolBarManager());\r
+               fillLocalPullDown(bars.getMenuManager());\r
+               bars.updateActionBars();\r
+       }\r
+\r
+       protected void fillLocalToolBar(IToolBarManager manager) {\r
+               manager.add(showJMEAction);\r
+       }\r
+\r
+       protected void fillLocalPullDown(IMenuManager manager) {\r
+\r
+       }\r
+       \r
+       @Override\r
+       public void setFocus() {\r
+               viewer.getControl().setFocus();\r
+       }\r
+       \r
+       public void dispose() {\r
+               for (IWorkbenchWindow w : PlatformUI.getWorkbench().getWorkbenchWindows()) {\r
+                       w.getPartService().removePartListener(listener);\r
+                               \r
+               }\r
+               super.dispose();\r
+       }\r
+       \r
+\r
+       private class JMEScenegraphContentProvider implements ITreeContentProvider {\r
+               @Override\r
+               public Object[] getChildren(Object parentElement) {\r
+                       if (parentElement instanceof JMEAdaptable)\r
+                               parentElement = ((JMEAdaptable)parentElement).getElement();\r
+                       \r
+                       if (parentElement instanceof Node) {\r
+                               Node n = (Node)parentElement;\r
+                               Object o[] = new Object[n.getChildren().size()];\r
+                               for (int i = 0; i < n.getChildren().size(); i++) {\r
+                                       o[i] = new JMEAdaptable(n.getChild(i));\r
+                               }\r
+                               return o;\r
+                       }\r
+                       if (parentElement instanceof Geometry) {\r
+                               Geometry g = (Geometry)parentElement;\r
+                               Object o[] = new Object[g.getBatchCount()];\r
+                               for (int i = 0 ; i < g.getBatchCount(); i++)\r
+                                       o[i] = new JMEAdaptable(g.getBatch(i));\r
+                               return o;\r
+                       }\r
+                       return null;\r
+               }\r
+               \r
+               @Override\r
+               public Object[] getElements(Object inputElement) {\r
+                       if (inputElement instanceof ThreeDimensionalEditorBase) {\r
+                               SceneElement root = ((ThreeDimensionalEditorBase)inputElement).getRenderingComponent().getRoot();\r
+                               if (root != null)\r
+                                       return new Object[]{new JMEAdaptable(root)};\r
+                       }\r
+                       return new Object[0];\r
+               }\r
+               \r
+               @Override\r
+               public Object getParent(Object element) {\r
+                       SceneElement e;\r
+                       if (element instanceof JMEAdaptable)\r
+                               e = ((JMEAdaptable)element).getElement();\r
+                       else\r
+                               e = (SceneElement)element;\r
+                       if (e instanceof Spatial) {\r
+                               Spatial s = (Spatial)e;\r
+                               return s.getParent();\r
+                       } \r
+                       if (e instanceof GeomBatch) {\r
+                               GeomBatch g = (GeomBatch)e;\r
+                               return g.getParentGeom();\r
+                       }\r
+                       return null;\r
+               }\r
+               \r
+               @Override\r
+               public boolean hasChildren(Object element) {\r
+                       if (element instanceof JMEAdaptable)\r
+                               element = ((JMEAdaptable)element).getElement();\r
+                       if (element instanceof Node) {\r
+                               Node n = (Node)element;\r
+                               if (n.getChildren() == null)\r
+                                       return false;\r
+                               return n.getChildren().size() > 0;\r
+                       }\r
+                       if (element instanceof Geometry) {\r
+                               Geometry g = (Geometry)element;\r
+                               return g.getBatchCount() > 0;\r
+                       }\r
+                       return false;\r
+               }\r
+               \r
+               @Override\r
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
+                       \r
+               }\r
+               \r
+               @Override\r
+               public void dispose() {\r
+                       \r
+               }\r
+       }\r
+       \r
+       private class JMEScenegraphLabelProvider extends LabelProvider {\r
+               @Override\r
+               public String getText(Object element) {\r
+                       if (element == null)\r
+                               return null;\r
+                       if (element instanceof JMEAdaptable)\r
+                               element = ((JMEAdaptable)element).getElement();\r
+                       SceneElement e = (SceneElement)element;\r
+                       return e.getName() + " : " + e.getClass();\r
+               }\r
+               \r
+               @Override\r
+               public Image getImage(Object element) {\r
+                       if (element == null)\r
+                               return null;\r
+                       if (element instanceof JMEAdaptable)\r
+                               element = ((JMEAdaptable)element).getElement();\r
+                       ImageDescriptor desc = null;\r
+                       if (element instanceof GeomBatch)\r
+                               desc = BATCH_IMAGE;\r
+                       else if (element instanceof Geometry)\r
+                               desc = GEOMETRY_IMAGE;\r
+                       else if (element instanceof Node)\r
+                               desc = NODE_IMAGE;\r
+                       else \r
+                               return null;\r
+                       return ImageCache.getInstance().getImage(desc);\r
+               }\r
+       }\r
+       \r
+       private class GNScenegraphContentProvider implements ITreeContentProvider {\r
+               @Override\r
+               public Object[] getChildren(Object parentElement) {\r
+                       if (parentElement instanceof GNAdaptable)\r
+                               parentElement = ((GNAdaptable)parentElement).getNode();\r
+                       IGraphicsNode node = (IGraphicsNode)parentElement;\r
+                       Object children[] = new Object[node.getChildren().size()];\r
+                       Iterator<IGraphicsNode> it = node.getChildren().iterator();\r
+                       for (int i = 0; i < node.getChildren().size(); i++) {\r
+                               children[i] = new GNAdaptable(it.next());\r
+                       }\r
+                       return children;\r
+               }\r
+               \r
+               @Override\r
+               public Object[] getElements(Object inputElement) {\r
+                       if (inputElement instanceof ThreeDimensionalEditorBase) {\r
+                               IGraphicsNode root = ((ThreeDimensionalEditorBase)inputElement).getScenegraphAdapter().getRootNode();\r
+                               if (root != null)\r
+                                       return new Object[]{new GNAdaptable(root)};\r
+                       }\r
+                       return new Object[0];\r
+               }\r
+               \r
+               @Override\r
+               public Object getParent(Object element) {\r
+                       if (element instanceof GNAdaptable)\r
+                               element = ((GNAdaptable)element).getNode();\r
+                       IGraphicsNode node = (IGraphicsNode)element;\r
+                       return node.getParent();\r
+               }\r
+               \r
+               @Override\r
+               public boolean hasChildren(Object element) {\r
+                       if (element instanceof GNAdaptable)\r
+                               element = ((GNAdaptable)element).getNode();\r
+                       IGraphicsNode node = (IGraphicsNode)element;\r
+                       return node.getChildren().size() > 0;\r
+               }\r
+               \r
+               @Override\r
+               public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
+                       \r
+               }\r
+               \r
+               @Override\r
+               public void dispose() {\r
+                       \r
+               }\r
+       }\r
+       \r
+       private class GNScenegraphLabelProvider extends LabelProvider {\r
+               @Override\r
+               public String getText(Object element) {\r
+                       if (element instanceof GNAdaptable)\r
+                               element = ((GNAdaptable)element).getNode();\r
+                       IGraphicsNode node = (IGraphicsNode)element;\r
+                       return node.getGroup().getName() + " : " + node.getClass();\r
+               }\r
+               \r
+               @Override\r
+               public Image getImage(Object element) {\r
+                       ImageDescriptor desc = NODE_IMAGE;\r
+//                     if (element instanceof GeomBatch)\r
+//                             desc = BATCH_IMAGE;\r
+//                     else if (element instanceof Geometry)\r
+//                             desc = GEOMETRY_IMAGE;\r
+//                     else if (element instanceof Node)\r
+//                             desc = NODE_IMAGE;\r
+//                     else \r
+//                             return null;\r
+                       return ImageCache.getInstance().getImage(desc);\r
+               }\r
+       }\r
+       \r
+       private class JMEAdaptable implements IAdaptable {\r
+               SceneElement element;\r
+                               \r
+               public JMEAdaptable(SceneElement element) {\r
+                       assert (element != null);\r
+                       this.element = element;\r
+               }\r
+               \r
+               @SuppressWarnings("unchecked")\r
+               @Override\r
+               public Object getAdapter(Class adapter) {\r
+               if (adapter == IPropertySource.class) {\r
+                   return new JMEProperties(element);\r
+               }\r
+               return null;\r
+               }\r
+               \r
+               public SceneElement getElement() {\r
+                       return element;\r
+               }\r
+       }\r
+       \r
+       private class GNAdaptable implements IAdaptable {\r
+               IGraphicsNode node;\r
+                               \r
+               public GNAdaptable(IGraphicsNode node) {\r
+                       assert (node != null);\r
+                       this.node = node;\r
+               }\r
+               \r
+               @SuppressWarnings("unchecked")\r
+               @Override\r
+               public Object getAdapter(Class adapter) {\r
+               if (adapter == IPropertySource.class) {\r
+                   return new GNProperties(node);\r
+               }\r
+               return null;\r
+               }\r
+               \r
+               public IGraphicsNode getNode() {\r
+                       return node;\r
+               }\r
+       }\r
+       \r
+       private static final String NAME = "name";\r
+       private static final String CULL_MODE = "cullmode";\r
+       private static final String CULL_MODES[] = {"Inherit","Dynamic","Always","Never"};\r
+       private static final String LIGHT_MODE = "lightmode";\r
+       private static final String LIGHT_MODES[] = {"Off","Combine First","Combine Closest","Combine Recent Enabled","Inherit","Replace"};\r
+       private static final String LOCAL_CULL_MODE = "localcullmode";\r
+       private static final String LOCAL_LIGHT_MODE = "locallightmode";\r
+       private static final String LOCAL_NORMALS_MODE = "localnormalsmode";\r
+       private static final String LOCAL_RENDER_QUEUE_MODE ="localrenderqueuemode";\r
+       private static final String LOCAL_TEXTURE_COMBINE_MODE = "localtexturecombinemode";\r
+       private static final String LOCKS = "locks";\r
+       private static final String NORMALS_MODE = "normalsmode";\r
+       private static final String NORMALS_MODES[] = {"Inherit","Use Provided","Normalize Provided","Normalize if scaled","Off"};\r
+       private static final String RENDER_QUEUE_MODE = "renderqueuemode";\r
+       private static final String RENDER_QUEUE_MODES[] = {"Inherit","Skip","Opaque","Transparent","Ortho"};\r
+       private static final String TEXTURE_COMBINE_MODE = "texturecombinemode";\r
+       private static final String TEXTURE_COMBINE_MODES[] = {"Off","First","Closest","Recent enabled","Inherit","Replace"};\r
+       \r
+       private static final String BOOLEAN_VALUES[] = {"False","True"};\r
+       \r
+       private class JMEProperties implements IPropertySource {        \r
+               \r
+               SceneElement element;\r
+               \r
+               public JMEProperties(SceneElement element) {\r
+                       this.element = element;\r
+               }\r
+               \r
+               @Override\r
+               public Object getEditableValue() {\r
+                       return this;\r
+               }\r
+               \r
+               @Override\r
+               public IPropertyDescriptor[] getPropertyDescriptors() {\r
+                       List<IPropertyDescriptor> desc = new ArrayList<IPropertyDescriptor>();\r
+                       desc.add(new TextPropertyDescriptor(NAME,"Name"));\r
+                       desc.add(new ComboBoxPropertyDescriptor(CULL_MODE,"Cull Mode",CULL_MODES));\r
+                       desc.add(new ComboBoxPropertyDescriptor(LIGHT_MODE,"Light Combine Mode",LIGHT_MODES));\r
+                       desc.add(new ComboBoxPropertyDescriptor(LOCAL_CULL_MODE,"Local Cull Mode",CULL_MODES));\r
+                       desc.add(new ComboBoxPropertyDescriptor(LOCAL_LIGHT_MODE,"Local Light Combine Mode",LIGHT_MODES));\r
+                       desc.add(new ComboBoxPropertyDescriptor(LOCAL_NORMALS_MODE,"Local Normals Mode",NORMALS_MODES));\r
+                       desc.add(new ComboBoxPropertyDescriptor(LOCAL_RENDER_QUEUE_MODE,"Local Render Queue Mode",RENDER_QUEUE_MODES));\r
+                       desc.add(new ComboBoxPropertyDescriptor(LOCAL_TEXTURE_COMBINE_MODE,"Local Texture Combine Mode",TEXTURE_COMBINE_MODES));\r
+                       desc.add(new TextPropertyDescriptor(LOCKS,"Locks"));\r
+                       desc.add(new ComboBoxPropertyDescriptor(NORMALS_MODE,"Normals Mode",NORMALS_MODES));\r
+                       desc.add(new ComboBoxPropertyDescriptor(RENDER_QUEUE_MODE,"Render Queue Mode",RENDER_QUEUE_MODES));\r
+                       desc.add(new ComboBoxPropertyDescriptor(TEXTURE_COMBINE_MODE,"Texture Combine Mode",TEXTURE_COMBINE_MODES));\r
+                       return desc.toArray(new IPropertyDescriptor[desc.size()]);\r
+\r
+               }\r
+               \r
+               @Override\r
+               public Object getPropertyValue(Object id) {\r
+                       if (id == NAME) {\r
+                               return element.getName();\r
+                       } else if (id == CULL_MODE) {\r
+                               return element.getCullMode();\r
+                       } else if (id == LIGHT_MODE) {\r
+                               return element.getLightCombineMode();\r
+                       } else if (id == LOCAL_CULL_MODE) {\r
+                               return element.getLocalCullMode();\r
+                       } else if (id == LOCAL_LIGHT_MODE) {\r
+                               return element.getLocalLightCombineMode();\r
+                       } else if (id == LOCAL_NORMALS_MODE) {\r
+                               return element.getLocalNormalsMode();\r
+                       } else if (id == LOCAL_RENDER_QUEUE_MODE) {\r
+                               return element.getLocalRenderQueueMode();\r
+                       } else if (id == LOCAL_TEXTURE_COMBINE_MODE) {\r
+                               return element.getLocalTextureCombineMode();\r
+                       } else if (id == LOCKS) {\r
+                               return element.getLocks();\r
+                       } else if (id == NORMALS_MODE) {\r
+                               return element.getNormalsMode();\r
+                       } else if (id == RENDER_QUEUE_MODE) {\r
+                               return element.getRenderQueueMode();\r
+                       } else if (id == TEXTURE_COMBINE_MODE) {\r
+                               return element.getTextureCombineMode();\r
+                       }\r
+                       \r
+//                     element.getZOrder();\r
+//                     element.isCollidable();\r
+\r
+                       return null;\r
+               }\r
+               \r
+               @Override\r
+               public boolean isPropertySet(Object id) {\r
+                       return false;\r
+               }\r
+               \r
+               @Override\r
+               public void resetPropertyValue(Object id) {\r
+                       \r
+               }\r
+               \r
+               @Override\r
+               public void setPropertyValue(Object id, Object value) {\r
+                       if (id == NAME) {\r
+                               element.setName((String)value);\r
+                       } else if (id == CULL_MODE) {\r
+                               element.setCullMode((Integer)value);\r
+                       } else if (id == LIGHT_MODE) {\r
+                               element.setLightCombineMode((Integer)value);\r
+                       } else if (id == LOCAL_CULL_MODE) {\r
+                               \r
+                       } else if (id == LOCAL_LIGHT_MODE) {\r
+                               \r
+                       } else if (id == LOCAL_NORMALS_MODE) {\r
+                               \r
+                       } else if (id == LOCAL_RENDER_QUEUE_MODE) {\r
+                               \r
+                       } else if (id == LOCAL_TEXTURE_COMBINE_MODE) {\r
+                               \r
+                       } else if (id == LOCKS) {\r
+                               element.setLocks((Integer)value);\r
+                       } else if (id == NORMALS_MODE) {\r
+                               element.setNormalsMode((Integer)value);\r
+                       } else if (id == RENDER_QUEUE_MODE) {\r
+                               element.setRenderQueueMode((Integer)value);\r
+                       } else if (id == TEXTURE_COMBINE_MODE) {\r
+                               element.setTextureCombineMode((Integer)value);\r
+                       }\r
+                       \r
+               }\r
+\r
+       }\r
+       \r
+       private static final String SELECTED = "selected";\r
+       private static final String HIGHLIGHTED = "highlighted";\r
+       private static final String VISIBLE = "visible";\r
+       \r
+       private class GNProperties implements IPropertySource {\r
+               IGraphicsNode node;\r
+               \r
+               public GNProperties(IGraphicsNode node) {\r
+                       this.node = node;\r
+               }\r
+               \r
+               \r
+               @Override\r
+               public Object getEditableValue() {\r
+                       return this;\r
+               }\r
+               \r
+               @Override\r
+               public IPropertyDescriptor[] getPropertyDescriptors() {\r
+                       List<IPropertyDescriptor> desc = new ArrayList<IPropertyDescriptor>();\r
+                       if (node instanceof ISelectableNode) {\r
+                               //ISelectableNode n = (ISelectableNode)node;\r
+                               \r
+                               desc.add(new ComboBoxPropertyDescriptor(SELECTED,"Selected",BOOLEAN_VALUES));\r
+                               desc.add(new ComboBoxPropertyDescriptor(HIGHLIGHTED,"Highlighted",BOOLEAN_VALUES));\r
+                               desc.add(new ComboBoxPropertyDescriptor(VISIBLE,"Visible",BOOLEAN_VALUES));\r
+                               \r
+                       }\r
+                       return desc.toArray(new IPropertyDescriptor[desc.size()]);\r
+               }\r
+               \r
+               @Override\r
+               public Object getPropertyValue(Object id) {\r
+                       if (node instanceof ISelectableNode) {\r
+                               ISelectableNode n = (ISelectableNode)node;\r
+                               if (id == SELECTED) {\r
+                                       if (n.isSelected())\r
+                                               return 1;\r
+                                       return 0;\r
+                               } else if (id == HIGHLIGHTED) {\r
+                                       if (n.isHighlighted())\r
+                                               return 1;\r
+                                       return 0;\r
+                               } else if (id == VISIBLE) {\r
+                                       if (n.isVisible())\r
+                                               return 1;\r
+                                       return 0;\r
+                               }\r
+                       }\r
+                       if (node instanceof IGeometryNode) {\r
+                               //IGeometryNode n = (IGeometryNode)node;\r
+                       }\r
+\r
+                       return null;\r
+               }\r
+               \r
+               @Override\r
+               public boolean isPropertySet(Object id) {\r
+                       return false;\r
+               }\r
+               \r
+               @Override\r
+               public void resetPropertyValue(Object id) {\r
+\r
+               }\r
+               \r
+               @Override\r
+               public void setPropertyValue(Object id, Object value) {\r
+                       if (node instanceof ISelectableNode) {\r
+                               ISelectableNode n = (ISelectableNode)node;\r
+                               boolean b = ((Integer)value) == 1;\r
+                               if (id == SELECTED) {\r
+                                       n.setSelected(b);\r
+                               } else if (id == HIGHLIGHTED) {\r
+                                       n.setHighlighted(b);\r
+                               } else if (id == VISIBLE) {\r
+                                       n.setVisible(b);\r
+                               }\r
+                       }\r
+                       \r
+               }\r
+\r
+               \r
+       }\r
+       \r
+}\r
+       \r
+\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/SinglePageResourceEditor.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/SinglePageResourceEditor.java
new file mode 100644 (file)
index 0000000..1caba9d
--- /dev/null
@@ -0,0 +1,233 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.views;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.ui.IPartListener;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.forms.events.ExpansionAdapter;\r
+import org.eclipse.ui.forms.events.ExpansionEvent;\r
+import org.eclipse.ui.forms.widgets.FormToolkit;\r
+import org.eclipse.ui.forms.widgets.ScrolledForm;\r
+import org.eclipse.ui.forms.widgets.Section;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.GraphRequestAdapter;\r
+import org.simantics.db.GraphRequestStatus;\r
+import org.simantics.db.Session;\r
+import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
+import org.simantics.proconf.ui.workbench.ResourceEditorPart;\r
+import org.simantics.utils.ErrorLogger;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
+import org.simantics.utils.ui.jface.BaseSelectionProvider;\r
+\r
+\r
+\r
+public abstract class SinglePageResourceEditor extends ResourceEditorPart {\r
+       private ScrolledForm form;\r
+       private BaseSelectionProvider defaultInputSelectionProvider = new BaseSelectionProvider();\r
+       protected FormToolkit toolkit;\r
+       \r
+       @Override\r
+       public void createPartControl(Composite parent) {\r
+               this.getEditorSite().getPage().addPartListener(new IPartListener() {\r
+               \r
+               boolean opened = false;\r
+               boolean activated = false;\r
+               \r
+            public void partOpened(IWorkbenchPart part) {\r
+                if (part.equals(SinglePageResourceEditor.this.getEditorSite().getPart())) {\r
+                    opened = true;\r
+                }\r
+            }\r
+            \r
+            public void partActivated(IWorkbenchPart part) {\r
+               if (part.equals(SinglePageResourceEditor.this.getEditorSite().getPart())) {\r
+                    if (opened & !activated) {\r
+                       activated = true;\r
+                       load();\r
+                    }\r
+               }\r
+            }\r
+            \r
+            public void partBroughtToTop(IWorkbenchPart part) {}\r
+            \r
+            public void partClosed(IWorkbenchPart part) {}\r
+            \r
+            public void partDeactivated(IWorkbenchPart part) {}\r
+            \r
+            private void load() {\r
+               Session ses = SinglePageResourceEditor.this.getSession();\r
+                GraphRequestAdapter r = new GraphRequestAdapter() {\r
+                       @Override\r
+                       public GraphRequestStatus perform(Graph g)\r
+                                       throws Exception {\r
+                                reload(g);\r
+                               return GraphRequestStatus.transactionComplete();\r
+                       }\r
+                };\r
+                ses.asyncRead(r);\r
+            }\r
+        });\r
+               try {\r
+                       toolkit = new FormToolkit(parent.getDisplay());\r
+                       form = getToolkit().createScrolledForm(parent);\r
+\r
+                       GridLayout layout = new GridLayout(2, false);\r
+                       form.getBody().setLayout(layout);\r
+                       form.getBody().setLayoutData(\r
+                                       new GridData(GridData.FILL, GridData.FILL, true, true));\r
+\r
+                       // By default make this ViewPart use a default ISelectionProvider\r
+                       // that will offer the viewparts input resource as its selection.\r
+                       // The Resource is wrapped into a ResourceSelection object.\r
+                       // Any widgets created in createWidgets may override the default\r
+                       // selection provider.\r
+                       getEditorSite().setSelectionProvider(defaultInputSelectionProvider);\r
+\r
+                       beforeCreateWidgets();\r
+                       createWidgets();\r
+\r
+                       //reload();\r
+\r
+                       form.setText(getFormText());\r
+\r
+                       // Finally Set the default selection which will have an effect only\r
+                       // if nothing in createWidgets has overridden the default selection\r
+                       // provider.\r
+                       ISelection s = ISelectionUtils\r
+                                       .createSelection(new StructuredResourceSelection(\r
+                                                       getInputResource()));\r
+                       defaultInputSelectionProvider.setSelection(s);\r
+\r
+               } catch (Exception e) {\r
+                       Display d = getSite().getShell().getDisplay();\r
+                       d.asyncExec(new Runnable() {\r
+                               public void run() {\r
+                                       getSite().getPage().closeEditor(\r
+                                                       SinglePageResourceEditor.this, false);\r
+                               }\r
+                       });\r
+\r
+                       ErrorLogger.defaultLogError("Single-page type editor failed to open, see exception for details",e);\r
+               }\r
+       }\r
+\r
+       public ScrolledForm getActiveForm() {\r
+               return form;\r
+       }\r
+\r
+       protected Composite getBody() {\r
+               return form.getBody();\r
+       }\r
+\r
+       public Composite newGridSection(int formColumns, int childColumns,\r
+                       boolean equalWidth, boolean grabVertical, String text,\r
+                       String description) {\r
+               return newGridSection(getBody(), formColumns, childColumns, equalWidth,\r
+                               grabVertical, text, description);\r
+       }\r
+\r
+       public Composite newGridSection(Composite parent, int formColumns,\r
+                       int childColumns, boolean equalWidth, boolean grabVertical,\r
+                       String text, String description) {\r
+               FormToolkit toolkit = getToolkit();\r
+\r
+               Section section = toolkit.createSection(parent, Section.DESCRIPTION\r
+                               | Section.TWISTIE | Section.TITLE_BAR | Section.EXPANDED);\r
+               section.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,\r
+                               grabVertical, formColumns, 1));\r
+               section.addExpansionListener(new ExpansionAdapter() {\r
+                       public void expansionStateChanged(ExpansionEvent e) {\r
+                               //System.out.println("SinglePageTypeEditor: expansionStateChanged " + e);\r
+                               //reflow(true);\r
+                       }\r
+               });\r
+               section.setText(text);\r
+               section.setDescription(description);\r
+               Composite sectionClient = toolkit.createComposite(section);\r
+               sectionClient.setLayout(new GridLayout(childColumns, equalWidth));\r
+               sectionClient.setLayoutData(new GridData());\r
+               section.setClient(sectionClient);\r
+               return sectionClient;\r
+       }\r
+\r
+       \r
+\r
+       //----------------------------------------------------------------------\r
+       // Getters\r
+\r
+       public FormToolkit getToolkit() {\r
+               return toolkit;\r
+       }\r
+\r
+       //----------------------------------------------------------------------\r
+       // Event utilities\r
+\r
+       public void reflow(boolean flushCache) {\r
+               //System.out.println("FormTypeEditorBase.reflow(" + flushCache + ")");\r
+               getActiveForm().reflow(flushCache);\r
+       }\r
+\r
+       @Override\r
+       public void dispose() {\r
+               if (toolkit != null) {\r
+                       toolkit.dispose();\r
+               }\r
+               super.dispose();\r
+       }\r
+\r
+       @Override\r
+       public void setFocus() {\r
+               //System.out.println("FormTypeEditorBase.setFocus(): Input = " + getInput());\r
+               ScrolledForm form = getActiveForm();\r
+               if (form != null) {\r
+                       form.setFocus();\r
+               }\r
+       }\r
+\r
+       protected abstract String getFormText();\r
+\r
+       /**\r
+        * Returns null by default which makes {@link #updateTitle()} not set the\r
+        * part name programmatically, i.e. the plugin-defined view name will stay.\r
+        * \r
+        * @return\r
+        */\r
+       protected String getTitleText() {\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * Return null by default which makes {@link #updateTitle()} clear the\r
+        * tooltip.\r
+        * \r
+        * @return\r
+        */\r
+       protected String getTitleTooltip() {\r
+               return null;\r
+       }\r
+\r
+       /**\r
+        * A method for performing initializations just before UI initialization.\r
+        */\r
+       protected void beforeCreateWidgets() {\r
+       }\r
+\r
+       /**\r
+        * A method for initializing the UI of the view.\r
+        */\r
+       protected void createWidgets() {\r
+       }\r
+}\r
diff --git a/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/SinglePageResourceView.java b/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/views/SinglePageResourceView.java
new file mode 100644 (file)
index 0000000..d1d3dfd
--- /dev/null
@@ -0,0 +1,155 @@
+package org.simantics.proconf.g3d.views;\r
+\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.ui.ISelectionListener;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.forms.events.ExpansionAdapter;\r
+import org.eclipse.ui.forms.events.ExpansionEvent;\r
+import org.eclipse.ui.forms.widgets.FormToolkit;\r
+import org.eclipse.ui.forms.widgets.ScrolledForm;\r
+import org.eclipse.ui.forms.widgets.Section;\r
+import org.simantics.proconf.ui.workbench.GraphAccessViewPart;\r
+import org.simantics.utils.ui.jface.BaseSelectionProvider;\r
+\r
+public abstract class SinglePageResourceView extends GraphAccessViewPart{\r
+       protected Composite parent;\r
+       private ScrolledForm form;\r
+       private BaseSelectionProvider defaultInputSelectionProvider = new BaseSelectionProvider();\r
+       protected FormToolkit toolkit;\r
+       protected ISelectionListener pageSelectionListener;\r
+       \r
+       @Override\r
+       public void createPartControl(Composite parent) {\r
+               super.createPartControl(parent);\r
+               this.parent = parent;\r
+\r
+               toolkit = new FormToolkit(parent.getDisplay());\r
+               form = getToolkit().createScrolledForm(parent);\r
+\r
+               GridLayout layout = new GridLayout(2, false);\r
+               form.getBody().setLayout(layout);\r
+               form.getBody().setLayoutData(\r
+                               new GridData(GridData.FILL, GridData.FILL, true, true));\r
+\r
+               getViewSite().setSelectionProvider(defaultInputSelectionProvider);\r
+\r
+               // createWidgets();\r
+\r
+               form.setText(getFormText());\r
+\r
+               hookPageSelection();\r
+\r
+       }\r
+       \r
+       \r
+    /**\r
+     * Receives selection changes\r
+     * \r
+     * @param part\r
+     * @param selection\r
+     */\r
+    protected void pageSelectionChanged(IWorkbenchPart part, ISelection selection) {\r
+       \r
+    }\r
+       \r
+       \r
+       \r
+       \r
+       \r
+       protected abstract String getFormText();\r
+       \r
+       protected abstract void createWidgets();\r
+       \r
+       @Override\r
+       public void setFocus() {\r
+               //System.out.println("FormTypeEditorBase.setFocus(): Input = " + getInput());\r
+               ScrolledForm form = getActiveForm();\r
+               if (form != null) {\r
+                       form.setFocus();\r
+               }\r
+       }\r
+       \r
+       public FormToolkit getToolkit() {\r
+               return toolkit;\r
+       }\r
+       \r
+       public ScrolledForm getActiveForm() {\r
+               return form;\r
+       }\r
+       \r
+       public void clearForm() {\r
+               for (Control c : form.getBody().getChildren())\r
+                       c.dispose();\r
+               \r
+       }\r
+       \r
+       protected Composite getBody() {\r
+        return form.getBody();\r
+    }\r
+       \r
+       public Composite newGridSection(\r
+            int formColumns,\r
+            int childColumns,\r
+            boolean equalWidth,\r
+            boolean grabVertical,\r
+            String text,\r
+            String description) \r
+    {\r
+        return newGridSection(getBody(), formColumns, childColumns, equalWidth, grabVertical, text, description);\r
+    }\r
+\r
+    public Composite newGridSection(\r
+            Composite parent,\r
+            int formColumns,\r
+            int childColumns,\r
+            boolean equalWidth,\r
+            boolean grabVertical,\r
+            String text,\r
+            String description)\r
+    {\r
+        FormToolkit toolkit = getToolkit();\r
+        \r
+        Section section = toolkit.createSection(parent,\r
+                Section.DESCRIPTION | Section.TWISTIE | Section.TITLE_BAR | Section.EXPANDED);\r
+        section.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, grabVertical, formColumns, 1));\r
+        section.addExpansionListener(new ExpansionAdapter() {\r
+            public void expansionStateChanged(ExpansionEvent e) {\r
+                //System.out.println("SinglePageTypeEditor: expansionStateChanged " + e);\r
+                //reflow(true);\r
+            }\r
+        });\r
+        section.setText(text);\r
+        section.setDescription(description);\r
+        Composite sectionClient = toolkit.createComposite(section);\r
+        sectionClient.setLayout(new GridLayout(childColumns, equalWidth));\r
+        sectionClient.setLayoutData(new GridData());\r
+        section.setClient(sectionClient);\r
+        return sectionClient;\r
+    }\r
+    \r
+    public void dispose() {\r
+       if (pageSelectionListener != null)\r
+            getSite().getPage().removePostSelectionListener(pageSelectionListener);\r
+    \r
+       super.dispose();\r
+    }\r
+    \r
+    private void hookPageSelection() {\r
+        pageSelectionListener = new ISelectionListener() {\r
+            public void selectionChanged(IWorkbenchPart part, ISelection selection) {\r
+                if (part == SinglePageResourceView.this)\r
+                    return;\r
+                pageSelectionChanged(part, selection);\r
+            }\r
+        };\r
+        getSite().getPage().addPostSelectionListener(pageSelectionListener);\r
+        ISelection sel = getSite().getPage().getSelection();\r
+        IWorkbenchPart wb = getSite().getPage().getActivePart();\r
+        pageSelectionChanged(wb, sel);\r
+    }\r
+    \r
+}\r