--- /dev/null
+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