]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d.csg/src/org/simantics/g3d/csg/editor/CSGEditor2.java
Include CSG modelling with Plant3D
[simantics/3d.git] / org.simantics.g3d.csg / src / org / simantics / g3d / csg / editor / CSGEditor2.java
1 /*******************************************************************************\r
2  * Copyright (c) 2012, 2013 Association for Decentralized Information Management in\r
3  * Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.g3d.csg.editor;\r
13 \r
14 import java.awt.Component;\r
15 import java.util.ArrayList;\r
16 import java.util.Collection;\r
17 import java.util.HashSet;\r
18 import java.util.List;\r
19 import java.util.Set;\r
20 \r
21 import org.eclipse.jface.action.IMenuListener;\r
22 import org.eclipse.jface.action.IMenuManager;\r
23 import org.eclipse.jface.action.MenuManager;\r
24 import org.eclipse.jface.viewers.ISelectionChangedListener;\r
25 import org.eclipse.jface.viewers.SelectionChangedEvent;\r
26 import org.eclipse.swt.SWT;\r
27 import org.eclipse.swt.events.DisposeEvent;\r
28 import org.eclipse.swt.events.DisposeListener;\r
29 import org.eclipse.swt.layout.FillLayout;\r
30 import org.eclipse.swt.widgets.Composite;\r
31 import org.eclipse.swt.widgets.Display;\r
32 import org.eclipse.swt.widgets.Menu;\r
33 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;\r
34 import org.simantics.db.ReadGraph;\r
35 import org.simantics.db.Resource;\r
36 import org.simantics.db.common.request.ReadRequest;\r
37 import org.simantics.db.exception.DatabaseException;\r
38 import org.simantics.g3d.csg.actions.AddBooleanOpAction2;\r
39 import org.simantics.g3d.csg.actions.AddPrimitiveAction2;\r
40 import org.simantics.g3d.csg.actions.SplitBooleanOpAction2;\r
41 import org.simantics.g3d.csg.scenegraph2.BarrelNode;\r
42 import org.simantics.g3d.csg.scenegraph2.BoxNode;\r
43 import org.simantics.g3d.csg.scenegraph2.CSGparentNode;\r
44 import org.simantics.g3d.csg.scenegraph2.CSGrootNode;\r
45 import org.simantics.g3d.csg.scenegraph2.ConeNode;\r
46 import org.simantics.g3d.csg.scenegraph2.CylinderNode;\r
47 import org.simantics.g3d.csg.scenegraph2.DifferenceNode;\r
48 import org.simantics.g3d.csg.scenegraph2.EllipticCylinderNode;\r
49 import org.simantics.g3d.csg.scenegraph2.ICSGnode;\r
50 import org.simantics.g3d.csg.scenegraph2.IntersectionNode;\r
51 import org.simantics.g3d.csg.scenegraph2.RectangularSolidNode;\r
52 import org.simantics.g3d.csg.scenegraph2.RegularPrismNode;\r
53 import org.simantics.g3d.csg.scenegraph2.SchemaBuilder;\r
54 import org.simantics.g3d.csg.scenegraph2.SphereNode;\r
55 import org.simantics.g3d.csg.scenegraph2.TorusNode;\r
56 import org.simantics.g3d.csg.scenegraph2.UnionNode;\r
57 import org.simantics.g3d.scenegraph.IG3DNode;\r
58 import org.simantics.g3d.scenegraph.NodeMap;\r
59 import org.simantics.g3d.scenegraph.base.INode;\r
60 import org.simantics.g3d.vtk.action.RemoveAction;\r
61 import org.simantics.g3d.vtk.action.RotateAction;\r
62 import org.simantics.g3d.vtk.action.TranslateAction;\r
63 import org.simantics.g3d.vtk.action.vtkCameraAndSelectorAction;\r
64 import org.simantics.g3d.vtk.common.HoverHighlighter;\r
65 import org.simantics.g3d.vtk.common.InteractiveVtkPanel;\r
66 import org.simantics.g3d.vtk.common.NodeSelectionProvider2;\r
67 import org.simantics.g3d.vtk.common.SelectionHighlighter;\r
68 import org.simantics.g3d.vtk.common.VTKContentOutlinePage;\r
69 import org.simantics.g3d.vtk.shape.vtkShape;\r
70 import org.simantics.g3d.vtk.utils.vtkPanelUtil;\r
71 import org.simantics.objmap.graph.IMapping;\r
72 import org.simantics.objmap.graph.Mappings;\r
73 import org.simantics.objmap.graph.schema.IMappingSchema;\r
74 import org.simantics.selectionview.StandardPropertyPage;\r
75 import org.simantics.ui.workbench.IPropertyPage;\r
76 import org.simantics.ui.workbench.IResourceEditorInput;\r
77 import org.simantics.ui.workbench.ResourceEditorPart;\r
78 import org.simantics.utils.threads.AWTThread;\r
79 import org.simantics.utils.threads.ThreadUtils;\r
80 import org.simantics.utils.ui.ExceptionUtils;\r
81 import org.simantics.utils.ui.SWTAWTComponent;\r
82 \r
83 import vtk.vtkActor;\r
84 import vtk.vtkCameraPass;\r
85 import vtk.vtkDefaultPass;\r
86 import vtk.vtkLightsPass;\r
87 import vtk.vtkRenderPassCollection;\r
88 import vtk.vtkRenderer;\r
89 import vtk.vtkSequencePass;\r
90 \r
91 public class CSGEditor2  extends ResourceEditorPart {\r
92         private Composite parent;\r
93         private Resource input;\r
94         private InteractiveVtkPanel panel;\r
95         private SWTAWTComponent component;\r
96         \r
97         private CSGrootNode rootNode;\r
98         private IMapping<Resource,Object> mapping;\r
99         \r
100         private NodeSelectionProvider2<Resource,Object> selectionProvider;\r
101         \r
102         private vtkCameraAndSelectorAction cameraAction;\r
103         private TranslateAction translateAction;\r
104         private RotateAction rotateAction;\r
105         private RemoveAction removeAction;\r
106         \r
107         //private  ScenegraphOutlinePage outlinePage;\r
108         \r
109         private CSGNodeMap nodeMap;\r
110 \r
111 \r
112 \r
113         @Override\r
114         public void createPartControl(Composite parent) {\r
115                 this.parent = parent;\r
116                 parent.setLayout (new FillLayout ());\r
117                 component = new SWTAWTComponent(parent,SWT.NONE) {\r
118                         \r
119                         @Override\r
120                         protected Component createSwingComponent() {\r
121                                 if (panel == null) {\r
122                                         panel = new InteractiveVtkPanel();\r
123                                         vtkPanelUtil.registerPanel(panel);\r
124                                         createScene();\r
125                                 }\r
126                                 return panel;\r
127                         }\r
128                 };\r
129 \r
130                 IResourceEditorInput rei = (IResourceEditorInput)getEditorInput();\r
131                 input = rei.getResource();\r
132                 \r
133                 \r
134                 //IActionBars actionBars = getEditorSite().getActionBars();\r
135 \r
136                 hookContextMenu();\r
137                 \r
138                 component.syncPopulate();\r
139                 \r
140                 panel.addMouseListener(new java.awt.event.MouseAdapter() {\r
141                         @Override\r
142                         public void mouseClicked(final java.awt.event.MouseEvent e) {\r
143                                 if (e.getButton() == java.awt.event.MouseEvent.BUTTON3) {\r
144                                         Display.getDefault().asyncExec(new Runnable() {\r
145                                                 public void run() {\r
146                                                         contextMenu.setLocation(e.getXOnScreen(), e.getYOnScreen());\r
147                                                         contextMenu.setVisible(true);\r
148                                                 }\r
149                                         });\r
150                                 }\r
151                         }\r
152                 });\r
153                 \r
154 \r
155                 cameraAction = new vtkCameraAndSelectorAction(panel);   \r
156                 panel.setDefaultAction(cameraAction);\r
157                 panel.useDefaultAction();\r
158                 \r
159                 try {\r
160                         getSession().syncRequest(new ReadRequest() {\r
161                                 \r
162                                 @SuppressWarnings({ "rawtypes", "unchecked" })\r
163                                 @Override\r
164                                 public void run(ReadGraph graph) throws DatabaseException {\r
165                                         IMappingSchema schema = SchemaBuilder.getSchema(graph);\r
166                                         mapping = Mappings.createWithListening(schema);\r
167                                         rootNode = (CSGrootNode)mapping.map(graph, input);\r
168                                         nodeMap = new CSGNodeMap(getSession(), mapping, panel,(CSGrootNode)rootNode);\r
169                                 }\r
170                         });\r
171                         \r
172                         if (rootNode == null)\r
173                                 throw new RuntimeException("Scenegraph loading failed.");\r
174                         populate();\r
175                         \r
176                         selectionProvider = new NodeSelectionProvider2<Resource,Object>(this,mapping,nodeMap);\r
177 \r
178                         cameraAction.addSelectionChangedListener(selectionProvider);\r
179 \r
180                         cameraAction.addHoverChangedListener(new HoverHighlighter(panel,nodeMap));\r
181                         selectionProvider.addSelectionChangedListener(new SelectionHighlighter(panel,nodeMap));\r
182                         \r
183                         getSite().setSelectionProvider(selectionProvider);\r
184                         getSite().getPage().addPostSelectionListener(selectionProvider);\r
185                         \r
186                         //outlinePage = new ScenegraphOutlinePage(rootNode);\r
187                         \r
188                         \r
189                         parent.addDisposeListener(new DisposeListener() {\r
190                                 \r
191                                 @Override\r
192                                 public void widgetDisposed(DisposeEvent e) {\r
193                                         getSite().getPage().removePostSelectionListener(selectionProvider);\r
194                                         ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
195                                                 \r
196                                                 @Override\r
197                                                 public void run() {\r
198                                                         nodeMap.delete();\r
199                                                         vtkPanelUtil.unregisterPanel(panel);\r
200 \r
201                                                 }\r
202                                         });\r
203                                         mapping.dispose();\r
204                                         component.dispose();\r
205                                         \r
206                                         \r
207                                 }\r
208                         });\r
209                 } catch (DatabaseException e1) {\r
210                         ExceptionUtils.logAndShowError("Cannot open CSG editor",e1);\r
211                         return;\r
212                 }\r
213                 \r
214                 translateAction = new TranslateAction(panel,nodeMap);\r
215                 rotateAction = new RotateAction(panel,nodeMap);\r
216                 removeAction = new RemoveAction(nodeMap) {\r
217                         public void setNode(IG3DNode node) {\r
218                                 super.setNode(node);\r
219                                 if (node.getParent() instanceof CSGparentNode)\r
220                                         setEnabled(false);\r
221                                 \r
222                         }\r
223                 };\r
224                 \r
225                 \r
226         }\r
227         \r
228         \r
229 \r
230         \r
231         public void populate() {\r
232                 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {\r
233                         \r
234                         @Override\r
235                         public void run() {\r
236                                 nodeMap.populate();\r
237                         }\r
238                 });\r
239                 \r
240         }\r
241         \r
242         \r
243         \r
244         @Override\r
245         public void setFocus() {\r
246                 component.setFocus();\r
247         }\r
248         \r
249         private void createScene() {\r
250                 vtkRenderer ren1 = panel.GetRenderer();\r
251                 \r
252                 boolean multiPass = false;\r
253                 if (multiPass) {\r
254                         \r
255                         vtkLightsPass lightsPass = new vtkLightsPass();\r
256                         vtkDefaultPass defaultPass = new vtkDefaultPass();\r
257                         \r
258                         \r
259                         vtkRenderPassCollection passes = new vtkRenderPassCollection();\r
260                         passes.AddItem(lightsPass);\r
261                         passes.AddItem(defaultPass);\r
262                         \r
263                         vtkSequencePass seq = new vtkSequencePass();\r
264                         seq.SetPasses(passes);\r
265                         \r
266                 \r
267                         \r
268                         vtkCameraPass cameraPass = new vtkCameraPass();\r
269                         cameraPass.SetDelegatePass(seq);\r
270                         \r
271                         ren1.SetPass(cameraPass);\r
272                         \r
273                 }\r
274 //              ren1.GetRenderWindow().LineSmoothingOn();\r
275 //              ren1.GetRenderWindow().PointSmoothingOn();\r
276 //              ren1.GetRenderWindow().PolygonSmoothingOn();\r
277 //              ren1.GetRenderWindow().SetMultiSamples(2);\r
278 \r
279                 \r
280 \r
281                 ren1.SetBackground2(1,1,1); // background color white\r
282                 ren1.SetBackground(0.9,0.9,0.9);\r
283                 ren1.SetGradientBackground(true);\r
284 \r
285            // vtkActor grid = vtkShape.createGridActor(8,1.0,1|2|4);\r
286             vtkActor grid = vtkShape.createGridActor(8,1.0, 2 );\r
287             grid.SetPickable(0);\r
288             ren1.AddActor(grid);\r
289             panel.addDeletable(grid);\r
290             \r
291 \r
292                 \r
293         }\r
294         \r
295         protected Menu contextMenu;\r
296         \r
297         protected void hookContextMenu() {\r
298         MenuManager menuMgr = new MenuManager("#PopupMenu");\r
299         menuMgr.setRemoveAllWhenShown(true);\r
300         menuMgr.addMenuListener(new IMenuListener() {\r
301             public void menuAboutToShow(IMenuManager manager) {\r
302                 final IMenuManager m = manager;\r
303                         List<IG3DNode> selected = selectionProvider.getSelectedNodes();\r
304                         if (selected.size() == 0) {\r
305                                 m.add(new AddPrimitiveAction2(rootNode, BarrelNode.class));\r
306                                 m.add(new AddPrimitiveAction2(rootNode, BoxNode.class));\r
307                                 m.add(new AddPrimitiveAction2(rootNode, ConeNode.class));\r
308                                 m.add(new AddPrimitiveAction2(rootNode, CylinderNode.class));\r
309                                 m.add(new AddPrimitiveAction2(rootNode, EllipticCylinderNode.class));\r
310                                 m.add(new AddPrimitiveAction2(rootNode, RectangularSolidNode.class));\r
311                                 m.add(new AddPrimitiveAction2(rootNode, RegularPrismNode.class));\r
312                                 m.add(new AddPrimitiveAction2(rootNode, SphereNode.class));\r
313                                 m.add(new AddPrimitiveAction2(rootNode, TorusNode.class));\r
314                         } else if (selected.size() == 1) {\r
315                                 m.add(translateAction);\r
316                                         m.add(rotateAction);\r
317                                         m.add(removeAction);\r
318                                         ICSGnode node = (ICSGnode)selected.get(0);\r
319                                         translateAction.setNode(node);\r
320                                         rotateAction.setNode(node);\r
321                                         removeAction.setNode(node);\r
322                                         if (node instanceof CSGparentNode) {\r
323                                                 m.add(new SplitBooleanOpAction2(rootNode,(CSGparentNode)node));\r
324                                         }\r
325                         } else if (selected.size() == 2) {\r
326                                 if (selected.get(0).getParent().equals(rootNode) && selected.get(1).getParent().equals(rootNode)) {\r
327                                         Collection<ICSGnode> nodes = new ArrayList<ICSGnode>();\r
328                                         for (IG3DNode n : selected)\r
329                                                 nodes.add((ICSGnode)n);\r
330                                         m.add(new AddBooleanOpAction2(rootNode, DifferenceNode.class, nodes));\r
331                                         m.add(new AddBooleanOpAction2(rootNode, IntersectionNode.class, nodes));\r
332                                         m.add(new AddBooleanOpAction2(rootNode, UnionNode.class, nodes));\r
333                                 }\r
334                         }\r
335 //              try {\r
336 //                                      SimanticsUI.getSession().syncRequest(new ReadRequest() {\r
337 //                                              \r
338 //                                              @Override\r
339 //                                              public void run(ReadGraph graph) throws DatabaseException {\r
340 //                                                      Layer0 l0 = Layer0.getInstance(graph);\r
341 //                                                      CSG csg = CSG.getInstance(graph);\r
342 //                                                      Resource ontology = graph.getResource("http://www.simantics.org/CSG-0.1");\r
343 //                                                      \r
344 //                                                      if (selectionProvider.getSelectedResources().size() == 0) {\r
345 //                                                              List<NamedResource> primitives = new ArrayList<NamedResource>();\r
346 //                                                              for (Resource r : graph.getObjects(ontology, l0.ConsistsOf)) {\r
347 //                                                                      if (graph.isInheritedFrom(r, csg.Primitive) && !r.equals(csg.Primitive)) {\r
348 //                                                                              primitives.add(new NamedResource((String)graph.getRelatedValue(r, l0.HasName), r));\r
349 //                                                                      }\r
350 //                                                              }\r
351 //                                                              \r
352 //                                                              Collections.sort(primitives);\r
353 //                                                              for (NamedResource n : primitives) {\r
354 //                                                                      m.add(new AddPrimitiveAction(graph, n.getResource(),input));\r
355 //                                                              }\r
356 //                                                      }\r
357 //                                                      if (selectionProvider.getSelectedResources().size() == 2) {\r
358 //                                                              List<NamedResource> booleanOps = new ArrayList<NamedResource>();\r
359 //                                                              for (Resource r : graph.getObjects(ontology, l0.ConsistsOf)) {\r
360 //                                                                      if (graph.isInheritedFrom(r, csg.BooleanOperation) && !r.equals(csg.BooleanOperation)) {\r
361 //                                                                              booleanOps.add(new NamedResource((String)graph.getRelatedValue(r, l0.HasName), r));\r
362 //                                                                      }\r
363 //                                                              }\r
364 //                                                              \r
365 //                                                              Collections.sort(booleanOps);\r
366 //                                                              for (NamedResource n : booleanOps) {\r
367 //                                                                      m.add(new AddBooleanOpAction(graph, n.getResource(), input, selectionProvider.getSelectedResources()));\r
368 //                                                              }\r
369 //                                                      }\r
370 //                                                      if (selectionProvider.getSelectedResources().size() == 1) {\r
371 //                                                              m.add(translateAction);\r
372 //                                                              m.add(rotateAction);\r
373 //                                                              m.add(removeAction);\r
374 //                                                              Resource selected = selectionProvider.getSelectedResources().get(0);\r
375 //                                                              translateAction.setNode((IG3DNode2)mapping.get(selected));\r
376 //                                                              rotateAction.setNode((IG3DNode2)mapping.get(selected));\r
377 //                                                              removeAction.setNode((IG3DNode2)mapping.get(selected));\r
378 //                                                              if (graph.isInstanceOf(selected, csg.BooleanOperation)) {\r
379 //                                                                      m.add(new SplitBooleanOpAction(input,selected));\r
380 //                                                              }\r
381 //                                                              \r
382 //                                                              \r
383 //                                                      }\r
384 //                                                      \r
385 //                                              }\r
386 //                                      });\r
387 //                              } catch (DatabaseException e) {\r
388 //                                      // TODO Auto-generated catch block\r
389 //                                      e.printStackTrace();\r
390 //                              }\r
391                 \r
392             }\r
393         });\r
394 \r
395         contextMenu = menuMgr.createContextMenu(parent);\r
396     }\r
397         \r
398         private IContentOutlinePage createOutline() {\r
399                 if (rootNode == null || selectionProvider == null)\r
400                         return null;\r
401                 IContentOutlinePage outlinePage = new VTKContentOutlinePage<Resource,Object>(rootNode, selectionProvider);\r
402                 outlinePage.addSelectionChangedListener(new ISelectionChangedListener() {\r
403                         \r
404                         @Override\r
405                         public void selectionChanged(SelectionChangedEvent event) {\r
406                                 selectionProvider.selectionChanged(event);\r
407                         }\r
408                 });\r
409                 return outlinePage;\r
410         }\r
411 \r
412         @SuppressWarnings("rawtypes")\r
413         @Override\r
414         public Object getAdapter(Class adapter) {\r
415                 if (IPropertyPage.class.equals(adapter))\r
416                         return new StandardPropertyPage(getSite(),getPropertyContexts());\r
417                 if (IContentOutlinePage.class.equals(adapter)) {\r
418                         return createOutline();\r
419                 }\r
420                 if (NodeMap.class.equals(adapter)) {\r
421                         return nodeMap;\r
422                 }\r
423                 if (INode.class.equals(adapter)) {\r
424                         return rootNode;\r
425                 }\r
426                 if (IMapping.class.equals(adapter)) {\r
427                         return mapping;\r
428                 }\r
429                 if (InteractiveVtkPanel.class.equals(adapter)) {\r
430                         return panel;\r
431                 }\r
432                 return super.getAdapter(adapter);\r
433         }\r
434         \r
435         public Set<String> getPropertyContexts() {\r
436                 Set<String> result = new HashSet<String>();\r
437                 result.add("http://www.simantics.org/Project-1.0/ProjectBrowseContext");\r
438                 return result;\r
439         }\r
440 }\r