]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.g3d.csg/src/org/simantics/g3d/csg/editor/CSGEditor2.java
3D framework (Simca 2012)
[simantics/3d.git] / org.simantics.g3d.csg / src / org / simantics / g3d / csg / editor / CSGEditor2.java
diff --git a/org.simantics.g3d.csg/src/org/simantics/g3d/csg/editor/CSGEditor2.java b/org.simantics.g3d.csg/src/org/simantics/g3d/csg/editor/CSGEditor2.java
new file mode 100644 (file)
index 0000000..c1f7c51
--- /dev/null
@@ -0,0 +1,429 @@
+package org.simantics.g3d.csg.editor;\r
+\r
+import java.awt.Component;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import org.eclipse.jface.action.IMenuListener;\r
+import org.eclipse.jface.action.IMenuManager;\r
+import org.eclipse.jface.action.MenuManager;\r
+import org.eclipse.jface.viewers.ISelectionChangedListener;\r
+import org.eclipse.jface.viewers.SelectionChangedEvent;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.DisposeEvent;\r
+import org.eclipse.swt.events.DisposeListener;\r
+import org.eclipse.swt.layout.FillLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Menu;\r
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.g3d.csg.actions.AddBooleanOpAction2;\r
+import org.simantics.g3d.csg.actions.AddPrimitiveAction2;\r
+import org.simantics.g3d.csg.actions.SplitBooleanOpAction2;\r
+import org.simantics.g3d.csg.scenegraph2.BarrelNode;\r
+import org.simantics.g3d.csg.scenegraph2.BoxNode;\r
+import org.simantics.g3d.csg.scenegraph2.CSGparentNode;\r
+import org.simantics.g3d.csg.scenegraph2.CSGrootNode;\r
+import org.simantics.g3d.csg.scenegraph2.ConeNode;\r
+import org.simantics.g3d.csg.scenegraph2.CylinderNode;\r
+import org.simantics.g3d.csg.scenegraph2.DifferenceNode;\r
+import org.simantics.g3d.csg.scenegraph2.EllipticCylinderNode;\r
+import org.simantics.g3d.csg.scenegraph2.ICSGnode;\r
+import org.simantics.g3d.csg.scenegraph2.IntersectionNode;\r
+import org.simantics.g3d.csg.scenegraph2.RectangularSolidNode;\r
+import org.simantics.g3d.csg.scenegraph2.RegularPrismNode;\r
+import org.simantics.g3d.csg.scenegraph2.SchemaBuilder;\r
+import org.simantics.g3d.csg.scenegraph2.SphereNode;\r
+import org.simantics.g3d.csg.scenegraph2.TorusNode;\r
+import org.simantics.g3d.csg.scenegraph2.UnionNode;\r
+import org.simantics.g3d.scenegraph.IG3DNode;\r
+import org.simantics.g3d.scenegraph.NodeMap;\r
+import org.simantics.g3d.scenegraph.base.INode;\r
+import org.simantics.g3d.vtk.action.RemoveAction;\r
+import org.simantics.g3d.vtk.action.RotateAction;\r
+import org.simantics.g3d.vtk.action.TranslateAction;\r
+import org.simantics.g3d.vtk.action.vtkCameraAndSelectorAction;\r
+import org.simantics.g3d.vtk.common.HoverHighlighter;\r
+import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
+import org.simantics.g3d.vtk.common.NodeSelectionProvider2;\r
+import org.simantics.g3d.vtk.common.SelectionHighlighter;\r
+import org.simantics.g3d.vtk.common.VTKContentOutlinePage;\r
+import org.simantics.g3d.vtk.shape.vtkShape;\r
+import org.simantics.g3d.vtk.utils.vtkPanelUtil;\r
+import org.simantics.objmap.graph.IMapping;\r
+import org.simantics.objmap.graph.Mappings;\r
+import org.simantics.objmap.graph.schema.IMappingSchema;\r
+import org.simantics.selectionview.StandardPropertyPage;\r
+import org.simantics.ui.workbench.IPropertyPage;\r
+import org.simantics.ui.workbench.IResourceEditorInput;\r
+import org.simantics.ui.workbench.ResourceEditorPart;\r
+import org.simantics.utils.threads.AWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+import org.simantics.utils.ui.SWTAWTComponent;\r
+\r
+import vtk.vtkActor;\r
+import vtk.vtkCameraPass;\r
+import vtk.vtkDefaultPass;\r
+import vtk.vtkLightsPass;\r
+import vtk.vtkRenderPassCollection;\r
+import vtk.vtkRenderer;\r
+import vtk.vtkSequencePass;\r
+\r
+public class CSGEditor2  extends ResourceEditorPart {\r
+       private Composite parent;\r
+       private Resource input;\r
+       private InteractiveVtkPanel panel;\r
+       private SWTAWTComponent component;\r
+       \r
+       private CSGrootNode rootNode;\r
+       private IMapping<Resource,Object> mapping;\r
+       \r
+       private NodeSelectionProvider2<Resource,Object> selectionProvider;\r
+       \r
+       private vtkCameraAndSelectorAction cameraAction;\r
+       private TranslateAction translateAction;\r
+       private RotateAction rotateAction;\r
+       private RemoveAction removeAction;\r
+       \r
+       //private  ScenegraphOutlinePage outlinePage;\r
+       \r
+       private CSGNodeMap nodeMap;\r
+\r
+\r
+\r
+       @Override\r
+       public void createPartControl(Composite parent) {\r
+               this.parent = parent;\r
+               parent.setLayout (new FillLayout ());\r
+               component = new SWTAWTComponent(parent,SWT.NONE) {\r
+                       \r
+                       @Override\r
+                       protected Component createSwingComponent() {\r
+                               if (panel == null) {\r
+                                       panel = new InteractiveVtkPanel();\r
+                                       vtkPanelUtil.registerPanel(panel);\r
+                                       createScene();\r
+                               }\r
+                               return panel;\r
+                       }\r
+               };\r
+\r
+               IResourceEditorInput rei = (IResourceEditorInput)getEditorInput();\r
+               input = rei.getResource();\r
+               \r
+               \r
+               //IActionBars actionBars = getEditorSite().getActionBars();\r
+\r
+               hookContextMenu();\r
+               \r
+               component.syncPopulate();\r
+               \r
+               panel.addMouseListener(new java.awt.event.MouseAdapter() {\r
+                       @Override\r
+                       public void mouseClicked(final java.awt.event.MouseEvent e) {\r
+                               if (e.getButton() == java.awt.event.MouseEvent.BUTTON3) {\r
+                                       Display.getDefault().asyncExec(new Runnable() {\r
+                                               public void run() {\r
+                                                       contextMenu.setLocation(e.getXOnScreen(), e.getYOnScreen());\r
+                                                       contextMenu.setVisible(true);\r
+                                               }\r
+                                       });\r
+                               }\r
+                       }\r
+               });\r
+               \r
+\r
+               cameraAction = new vtkCameraAndSelectorAction(panel);   \r
+               panel.setDefaultAction(cameraAction);\r
+               panel.useDefaultAction();\r
+               \r
+               try {\r
+                       getSession().syncRequest(new ReadRequest() {\r
+                               \r
+                               @SuppressWarnings({ "rawtypes", "unchecked" })\r
+                               @Override\r
+                               public void run(ReadGraph graph) throws DatabaseException {\r
+                                       IMappingSchema schema = SchemaBuilder.getSchema(graph);\r
+                                       mapping = Mappings.createWithListening(schema);\r
+                                       rootNode = (CSGrootNode)mapping.map(graph, input);\r
+                                       nodeMap = new CSGNodeMap(getSession(), mapping, panel,(CSGrootNode)rootNode);\r
+                               }\r
+                       });\r
+                       \r
+                       if (rootNode == null)\r
+                               throw new RuntimeException("Scenegraph loading failed.");\r
+                       populate();\r
+                       \r
+                       selectionProvider = new NodeSelectionProvider2<Resource,Object>(this,mapping,nodeMap);\r
+\r
+                       cameraAction.addSelectionChangedListener(selectionProvider);\r
+\r
+                       cameraAction.addHoverChangedListener(new HoverHighlighter(panel,nodeMap));\r
+                       selectionProvider.addSelectionChangedListener(new SelectionHighlighter(panel,nodeMap));\r
+                       \r
+                       getSite().setSelectionProvider(selectionProvider);\r
+                       getSite().getPage().addPostSelectionListener(selectionProvider);\r
+                       \r
+                       //outlinePage = new ScenegraphOutlinePage(rootNode);\r
+                       \r
+                       \r
+                       parent.addDisposeListener(new DisposeListener() {\r
+                               \r
+                               @Override\r
+                               public void widgetDisposed(DisposeEvent e) {\r
+                                       getSite().getPage().removePostSelectionListener(selectionProvider);\r
+                                       ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+                                               \r
+                                               @Override\r
+                                               public void run() {\r
+                                                       nodeMap.delete();\r
+                                                       vtkPanelUtil.unregisterPanel(panel);\r
+\r
+                                               }\r
+                                       });\r
+                                       mapping.dispose();\r
+                                       component.dispose();\r
+                                       \r
+                                       \r
+                               }\r
+                       });\r
+               } catch (DatabaseException e1) {\r
+                       ExceptionUtils.logAndShowError("Cannot open CSG editor",e1);\r
+                       return;\r
+               }\r
+               \r
+               translateAction = new TranslateAction(panel,nodeMap);\r
+               rotateAction = new RotateAction(panel,nodeMap);\r
+               removeAction = new RemoveAction(nodeMap) {\r
+                       public void setNode(IG3DNode node) {\r
+                               super.setNode(node);\r
+                               if (node.getParent() instanceof CSGparentNode)\r
+                                       setEnabled(false);\r
+                               \r
+                       }\r
+               };\r
+               \r
+               \r
+       }\r
+       \r
+       \r
+\r
+       \r
+       public void populate() {\r
+               ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
+                       \r
+                       @Override\r
+                       public void run() {\r
+                               nodeMap.populate();\r
+                       }\r
+               });\r
+               \r
+       }\r
+       \r
+       \r
+       \r
+       @Override\r
+       public void setFocus() {\r
+               component.setFocus();\r
+       }\r
+       \r
+       private void createScene() {\r
+               vtkRenderer ren1 = panel.GetRenderer();\r
+               \r
+               boolean multiPass = false;\r
+               if (multiPass) {\r
+                       \r
+                       vtkLightsPass lightsPass = new vtkLightsPass();\r
+                       vtkDefaultPass defaultPass = new vtkDefaultPass();\r
+                       \r
+                       \r
+                       vtkRenderPassCollection passes = new vtkRenderPassCollection();\r
+                       passes.AddItem(lightsPass);\r
+                       passes.AddItem(defaultPass);\r
+                       \r
+                       vtkSequencePass seq = new vtkSequencePass();\r
+                       seq.SetPasses(passes);\r
+                       \r
+               \r
+                       \r
+                       vtkCameraPass cameraPass = new vtkCameraPass();\r
+                       cameraPass.SetDelegatePass(seq);\r
+                       \r
+                       ren1.SetPass(cameraPass);\r
+                       \r
+               }\r
+//             ren1.GetRenderWindow().LineSmoothingOn();\r
+//             ren1.GetRenderWindow().PointSmoothingOn();\r
+//             ren1.GetRenderWindow().PolygonSmoothingOn();\r
+//             ren1.GetRenderWindow().SetMultiSamples(2);\r
+\r
+               \r
+\r
+               ren1.SetBackground2(1,1,1); // background color white\r
+               ren1.SetBackground(0.9,0.9,0.9);\r
+               ren1.SetGradientBackground(true);\r
+\r
+          // vtkActor grid = vtkShape.createGridActor(8,1.0,1|2|4);\r
+           vtkActor grid = vtkShape.createGridActor(8,1.0, 2 );\r
+           grid.SetPickable(0);\r
+           ren1.AddActor(grid);\r
+           panel.addDeletable(grid);\r
+           \r
+\r
+               \r
+       }\r
+       \r
+       protected Menu contextMenu;\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
+                       List<IG3DNode> selected = selectionProvider.getSelectedNodes();\r
+                       if (selected.size() == 0) {\r
+                               m.add(new AddPrimitiveAction2(rootNode, BarrelNode.class));\r
+                               m.add(new AddPrimitiveAction2(rootNode, BoxNode.class));\r
+                               m.add(new AddPrimitiveAction2(rootNode, ConeNode.class));\r
+                               m.add(new AddPrimitiveAction2(rootNode, CylinderNode.class));\r
+                               m.add(new AddPrimitiveAction2(rootNode, EllipticCylinderNode.class));\r
+                               m.add(new AddPrimitiveAction2(rootNode, RectangularSolidNode.class));\r
+                               m.add(new AddPrimitiveAction2(rootNode, RegularPrismNode.class));\r
+                               m.add(new AddPrimitiveAction2(rootNode, SphereNode.class));\r
+                               m.add(new AddPrimitiveAction2(rootNode, TorusNode.class));\r
+                       } else if (selected.size() == 1) {\r
+                               m.add(translateAction);\r
+                                       m.add(rotateAction);\r
+                                       m.add(removeAction);\r
+                                       ICSGnode node = (ICSGnode)selected.get(0);\r
+                                       translateAction.setNode(node);\r
+                                       rotateAction.setNode(node);\r
+                                       removeAction.setNode(node);\r
+                                       if (node instanceof CSGparentNode) {\r
+                                               m.add(new SplitBooleanOpAction2(rootNode,(CSGparentNode)node));\r
+                                       }\r
+                       } else if (selected.size() == 2) {\r
+                               if (selected.get(0).getParent().equals(rootNode) && selected.get(1).getParent().equals(rootNode)) {\r
+                                       Collection<ICSGnode> nodes = new ArrayList<ICSGnode>();\r
+                                       for (IG3DNode n : selected)\r
+                                               nodes.add((ICSGnode)n);\r
+                                       m.add(new AddBooleanOpAction2(rootNode, DifferenceNode.class, nodes));\r
+                                       m.add(new AddBooleanOpAction2(rootNode, IntersectionNode.class, nodes));\r
+                                       m.add(new AddBooleanOpAction2(rootNode, UnionNode.class, nodes));\r
+                               }\r
+                       }\r
+//             try {\r
+//                                     SimanticsUI.getSession().syncRequest(new ReadRequest() {\r
+//                                             \r
+//                                             @Override\r
+//                                             public void run(ReadGraph graph) throws DatabaseException {\r
+//                                                     Layer0 l0 = Layer0.getInstance(graph);\r
+//                                                     CSG csg = CSG.getInstance(graph);\r
+//                                                     Resource ontology = graph.getResource("http://www.simantics.org/CSG-0.1");\r
+//                                                     \r
+//                                                     if (selectionProvider.getSelectedResources().size() == 0) {\r
+//                                                             List<NamedResource> primitives = new ArrayList<NamedResource>();\r
+//                                                             for (Resource r : graph.getObjects(ontology, l0.ConsistsOf)) {\r
+//                                                                     if (graph.isInheritedFrom(r, csg.Primitive) && !r.equals(csg.Primitive)) {\r
+//                                                                             primitives.add(new NamedResource((String)graph.getRelatedValue(r, l0.HasName), r));\r
+//                                                                     }\r
+//                                                             }\r
+//                                                             \r
+//                                                             Collections.sort(primitives);\r
+//                                                             for (NamedResource n : primitives) {\r
+//                                                                     m.add(new AddPrimitiveAction(graph, n.getResource(),input));\r
+//                                                             }\r
+//                                                     }\r
+//                                                     if (selectionProvider.getSelectedResources().size() == 2) {\r
+//                                                             List<NamedResource> booleanOps = new ArrayList<NamedResource>();\r
+//                                                             for (Resource r : graph.getObjects(ontology, l0.ConsistsOf)) {\r
+//                                                                     if (graph.isInheritedFrom(r, csg.BooleanOperation) && !r.equals(csg.BooleanOperation)) {\r
+//                                                                             booleanOps.add(new NamedResource((String)graph.getRelatedValue(r, l0.HasName), r));\r
+//                                                                     }\r
+//                                                             }\r
+//                                                             \r
+//                                                             Collections.sort(booleanOps);\r
+//                                                             for (NamedResource n : booleanOps) {\r
+//                                                                     m.add(new AddBooleanOpAction(graph, n.getResource(), input, selectionProvider.getSelectedResources()));\r
+//                                                             }\r
+//                                                     }\r
+//                                                     if (selectionProvider.getSelectedResources().size() == 1) {\r
+//                                                             m.add(translateAction);\r
+//                                                             m.add(rotateAction);\r
+//                                                             m.add(removeAction);\r
+//                                                             Resource selected = selectionProvider.getSelectedResources().get(0);\r
+//                                                             translateAction.setNode((IG3DNode2)mapping.get(selected));\r
+//                                                             rotateAction.setNode((IG3DNode2)mapping.get(selected));\r
+//                                                             removeAction.setNode((IG3DNode2)mapping.get(selected));\r
+//                                                             if (graph.isInstanceOf(selected, csg.BooleanOperation)) {\r
+//                                                                     m.add(new SplitBooleanOpAction(input,selected));\r
+//                                                             }\r
+//                                                             \r
+//                                                             \r
+//                                                     }\r
+//                                                     \r
+//                                             }\r
+//                                     });\r
+//                             } catch (DatabaseException e) {\r
+//                                     // TODO Auto-generated catch block\r
+//                                     e.printStackTrace();\r
+//                             }\r
+                \r
+            }\r
+        });\r
+\r
+        contextMenu = menuMgr.createContextMenu(parent);\r
+    }\r
+       \r
+       private IContentOutlinePage createOutline() {\r
+               if (rootNode == null || selectionProvider == null)\r
+                       return null;\r
+               IContentOutlinePage outlinePage = new VTKContentOutlinePage<Resource,Object>(rootNode, selectionProvider);\r
+               outlinePage.addSelectionChangedListener(new ISelectionChangedListener() {\r
+                       \r
+                       @Override\r
+                       public void selectionChanged(SelectionChangedEvent event) {\r
+                               selectionProvider.selectionChanged(event);\r
+                       }\r
+               });\r
+               return outlinePage;\r
+       }\r
+\r
+       @SuppressWarnings("rawtypes")\r
+       @Override\r
+       public Object getAdapter(Class adapter) {\r
+               if (IPropertyPage.class.equals(adapter))\r
+                       return new StandardPropertyPage(getSite(),getPropertyContexts());\r
+               if (IContentOutlinePage.class.equals(adapter)) {\r
+                       return createOutline();\r
+               }\r
+               if (NodeMap.class.equals(adapter)) {\r
+                       return nodeMap;\r
+               }\r
+               if (INode.class.equals(adapter)) {\r
+                       return rootNode;\r
+               }\r
+               if (IMapping.class.equals(adapter)) {\r
+                       return mapping;\r
+               }\r
+               if (InteractiveVtkPanel.class.equals(adapter)) {\r
+                       return panel;\r
+               }\r
+               return super.getAdapter(adapter);\r
+       }\r
+       \r
+       public Set<String> getPropertyContexts() {\r
+               Set<String> result = new HashSet<String>();\r
+               result.add("http://www.simantics.org/Project-1.0/ProjectBrowseContext");\r
+               return result;\r
+       }\r
+}\r