1 package org.simantics.g3d.csg.editor;
\r
3 import java.awt.Component;
\r
4 import java.util.ArrayList;
\r
5 import java.util.Collection;
\r
6 import java.util.HashSet;
\r
7 import java.util.List;
\r
8 import java.util.Set;
\r
10 import org.eclipse.jface.action.IMenuListener;
\r
11 import org.eclipse.jface.action.IMenuManager;
\r
12 import org.eclipse.jface.action.MenuManager;
\r
13 import org.eclipse.jface.viewers.ISelectionChangedListener;
\r
14 import org.eclipse.jface.viewers.SelectionChangedEvent;
\r
15 import org.eclipse.swt.SWT;
\r
16 import org.eclipse.swt.events.DisposeEvent;
\r
17 import org.eclipse.swt.events.DisposeListener;
\r
18 import org.eclipse.swt.layout.FillLayout;
\r
19 import org.eclipse.swt.widgets.Composite;
\r
20 import org.eclipse.swt.widgets.Display;
\r
21 import org.eclipse.swt.widgets.Menu;
\r
22 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
\r
23 import org.simantics.db.ReadGraph;
\r
24 import org.simantics.db.Resource;
\r
25 import org.simantics.db.common.request.ReadRequest;
\r
26 import org.simantics.db.exception.DatabaseException;
\r
27 import org.simantics.g3d.csg.actions.AddBooleanOpAction2;
\r
28 import org.simantics.g3d.csg.actions.AddPrimitiveAction2;
\r
29 import org.simantics.g3d.csg.actions.SplitBooleanOpAction2;
\r
30 import org.simantics.g3d.csg.scenegraph2.BarrelNode;
\r
31 import org.simantics.g3d.csg.scenegraph2.BoxNode;
\r
32 import org.simantics.g3d.csg.scenegraph2.CSGparentNode;
\r
33 import org.simantics.g3d.csg.scenegraph2.CSGrootNode;
\r
34 import org.simantics.g3d.csg.scenegraph2.ConeNode;
\r
35 import org.simantics.g3d.csg.scenegraph2.CylinderNode;
\r
36 import org.simantics.g3d.csg.scenegraph2.DifferenceNode;
\r
37 import org.simantics.g3d.csg.scenegraph2.EllipticCylinderNode;
\r
38 import org.simantics.g3d.csg.scenegraph2.ICSGnode;
\r
39 import org.simantics.g3d.csg.scenegraph2.IntersectionNode;
\r
40 import org.simantics.g3d.csg.scenegraph2.RectangularSolidNode;
\r
41 import org.simantics.g3d.csg.scenegraph2.RegularPrismNode;
\r
42 import org.simantics.g3d.csg.scenegraph2.SchemaBuilder;
\r
43 import org.simantics.g3d.csg.scenegraph2.SphereNode;
\r
44 import org.simantics.g3d.csg.scenegraph2.TorusNode;
\r
45 import org.simantics.g3d.csg.scenegraph2.UnionNode;
\r
46 import org.simantics.g3d.scenegraph.IG3DNode;
\r
47 import org.simantics.g3d.scenegraph.NodeMap;
\r
48 import org.simantics.g3d.scenegraph.base.INode;
\r
49 import org.simantics.g3d.vtk.action.RemoveAction;
\r
50 import org.simantics.g3d.vtk.action.RotateAction;
\r
51 import org.simantics.g3d.vtk.action.TranslateAction;
\r
52 import org.simantics.g3d.vtk.action.vtkCameraAndSelectorAction;
\r
53 import org.simantics.g3d.vtk.common.HoverHighlighter;
\r
54 import org.simantics.g3d.vtk.common.InteractiveVtkPanel;
\r
55 import org.simantics.g3d.vtk.common.NodeSelectionProvider2;
\r
56 import org.simantics.g3d.vtk.common.SelectionHighlighter;
\r
57 import org.simantics.g3d.vtk.common.VTKContentOutlinePage;
\r
58 import org.simantics.g3d.vtk.shape.vtkShape;
\r
59 import org.simantics.g3d.vtk.utils.vtkPanelUtil;
\r
60 import org.simantics.objmap.graph.IMapping;
\r
61 import org.simantics.objmap.graph.Mappings;
\r
62 import org.simantics.objmap.graph.schema.IMappingSchema;
\r
63 import org.simantics.selectionview.StandardPropertyPage;
\r
64 import org.simantics.ui.workbench.IPropertyPage;
\r
65 import org.simantics.ui.workbench.IResourceEditorInput;
\r
66 import org.simantics.ui.workbench.ResourceEditorPart;
\r
67 import org.simantics.utils.threads.AWTThread;
\r
68 import org.simantics.utils.threads.ThreadUtils;
\r
69 import org.simantics.utils.ui.ExceptionUtils;
\r
70 import org.simantics.utils.ui.SWTAWTComponent;
\r
72 import vtk.vtkActor;
\r
73 import vtk.vtkCameraPass;
\r
74 import vtk.vtkDefaultPass;
\r
75 import vtk.vtkLightsPass;
\r
76 import vtk.vtkRenderPassCollection;
\r
77 import vtk.vtkRenderer;
\r
78 import vtk.vtkSequencePass;
\r
80 public class CSGEditor2 extends ResourceEditorPart {
\r
81 private Composite parent;
\r
82 private Resource input;
\r
83 private InteractiveVtkPanel panel;
\r
84 private SWTAWTComponent component;
\r
86 private CSGrootNode rootNode;
\r
87 private IMapping<Resource,Object> mapping;
\r
89 private NodeSelectionProvider2<Resource,Object> selectionProvider;
\r
91 private vtkCameraAndSelectorAction cameraAction;
\r
92 private TranslateAction translateAction;
\r
93 private RotateAction rotateAction;
\r
94 private RemoveAction removeAction;
\r
96 //private ScenegraphOutlinePage outlinePage;
\r
98 private CSGNodeMap nodeMap;
\r
103 public void createPartControl(Composite parent) {
\r
104 this.parent = parent;
\r
105 parent.setLayout (new FillLayout ());
\r
106 component = new SWTAWTComponent(parent,SWT.NONE) {
\r
109 protected Component createSwingComponent() {
\r
110 if (panel == null) {
\r
111 panel = new InteractiveVtkPanel();
\r
112 vtkPanelUtil.registerPanel(panel);
\r
119 IResourceEditorInput rei = (IResourceEditorInput)getEditorInput();
\r
120 input = rei.getResource();
\r
123 //IActionBars actionBars = getEditorSite().getActionBars();
\r
127 component.syncPopulate();
\r
129 panel.addMouseListener(new java.awt.event.MouseAdapter() {
\r
131 public void mouseClicked(final java.awt.event.MouseEvent e) {
\r
132 if (e.getButton() == java.awt.event.MouseEvent.BUTTON3) {
\r
133 Display.getDefault().asyncExec(new Runnable() {
\r
134 public void run() {
\r
135 contextMenu.setLocation(e.getXOnScreen(), e.getYOnScreen());
\r
136 contextMenu.setVisible(true);
\r
144 cameraAction = new vtkCameraAndSelectorAction(panel);
\r
145 panel.setDefaultAction(cameraAction);
\r
146 panel.useDefaultAction();
\r
149 getSession().syncRequest(new ReadRequest() {
\r
151 @SuppressWarnings({ "rawtypes", "unchecked" })
\r
153 public void run(ReadGraph graph) throws DatabaseException {
\r
154 IMappingSchema schema = SchemaBuilder.getSchema(graph);
\r
155 mapping = Mappings.createWithListening(schema);
\r
156 rootNode = (CSGrootNode)mapping.map(graph, input);
\r
157 nodeMap = new CSGNodeMap(getSession(), mapping, panel,(CSGrootNode)rootNode);
\r
161 if (rootNode == null)
\r
162 throw new RuntimeException("Scenegraph loading failed.");
\r
165 selectionProvider = new NodeSelectionProvider2<Resource,Object>(this,mapping,nodeMap);
\r
167 cameraAction.addSelectionChangedListener(selectionProvider);
\r
169 cameraAction.addHoverChangedListener(new HoverHighlighter(panel,nodeMap));
\r
170 selectionProvider.addSelectionChangedListener(new SelectionHighlighter(panel,nodeMap));
\r
172 getSite().setSelectionProvider(selectionProvider);
\r
173 getSite().getPage().addPostSelectionListener(selectionProvider);
\r
175 //outlinePage = new ScenegraphOutlinePage(rootNode);
\r
178 parent.addDisposeListener(new DisposeListener() {
\r
181 public void widgetDisposed(DisposeEvent e) {
\r
182 getSite().getPage().removePostSelectionListener(selectionProvider);
\r
183 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
\r
186 public void run() {
\r
188 vtkPanelUtil.unregisterPanel(panel);
\r
193 component.dispose();
\r
198 } catch (DatabaseException e1) {
\r
199 ExceptionUtils.logAndShowError("Cannot open CSG editor",e1);
\r
203 translateAction = new TranslateAction(panel,nodeMap);
\r
204 rotateAction = new RotateAction(panel,nodeMap);
\r
205 removeAction = new RemoveAction(nodeMap) {
\r
206 public void setNode(IG3DNode node) {
\r
207 super.setNode(node);
\r
208 if (node.getParent() instanceof CSGparentNode)
\r
220 public void populate() {
\r
221 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
\r
224 public void run() {
\r
225 nodeMap.populate();
\r
234 public void setFocus() {
\r
235 component.setFocus();
\r
238 private void createScene() {
\r
239 vtkRenderer ren1 = panel.GetRenderer();
\r
241 boolean multiPass = false;
\r
244 vtkLightsPass lightsPass = new vtkLightsPass();
\r
245 vtkDefaultPass defaultPass = new vtkDefaultPass();
\r
248 vtkRenderPassCollection passes = new vtkRenderPassCollection();
\r
249 passes.AddItem(lightsPass);
\r
250 passes.AddItem(defaultPass);
\r
252 vtkSequencePass seq = new vtkSequencePass();
\r
253 seq.SetPasses(passes);
\r
257 vtkCameraPass cameraPass = new vtkCameraPass();
\r
258 cameraPass.SetDelegatePass(seq);
\r
260 ren1.SetPass(cameraPass);
\r
263 // ren1.GetRenderWindow().LineSmoothingOn();
\r
264 // ren1.GetRenderWindow().PointSmoothingOn();
\r
265 // ren1.GetRenderWindow().PolygonSmoothingOn();
\r
266 // ren1.GetRenderWindow().SetMultiSamples(2);
\r
270 ren1.SetBackground2(1,1,1); // background color white
\r
271 ren1.SetBackground(0.9,0.9,0.9);
\r
272 ren1.SetGradientBackground(true);
\r
274 // vtkActor grid = vtkShape.createGridActor(8,1.0,1|2|4);
\r
275 vtkActor grid = vtkShape.createGridActor(8,1.0, 2 );
\r
276 grid.SetPickable(0);
\r
277 ren1.AddActor(grid);
\r
278 panel.addDeletable(grid);
\r
284 protected Menu contextMenu;
\r
286 protected void hookContextMenu() {
\r
287 MenuManager menuMgr = new MenuManager("#PopupMenu");
\r
288 menuMgr.setRemoveAllWhenShown(true);
\r
289 menuMgr.addMenuListener(new IMenuListener() {
\r
290 public void menuAboutToShow(IMenuManager manager) {
\r
291 final IMenuManager m = manager;
\r
292 List<IG3DNode> selected = selectionProvider.getSelectedNodes();
\r
293 if (selected.size() == 0) {
\r
294 m.add(new AddPrimitiveAction2(rootNode, BarrelNode.class));
\r
295 m.add(new AddPrimitiveAction2(rootNode, BoxNode.class));
\r
296 m.add(new AddPrimitiveAction2(rootNode, ConeNode.class));
\r
297 m.add(new AddPrimitiveAction2(rootNode, CylinderNode.class));
\r
298 m.add(new AddPrimitiveAction2(rootNode, EllipticCylinderNode.class));
\r
299 m.add(new AddPrimitiveAction2(rootNode, RectangularSolidNode.class));
\r
300 m.add(new AddPrimitiveAction2(rootNode, RegularPrismNode.class));
\r
301 m.add(new AddPrimitiveAction2(rootNode, SphereNode.class));
\r
302 m.add(new AddPrimitiveAction2(rootNode, TorusNode.class));
\r
303 } else if (selected.size() == 1) {
\r
304 m.add(translateAction);
\r
305 m.add(rotateAction);
\r
306 m.add(removeAction);
\r
307 ICSGnode node = (ICSGnode)selected.get(0);
\r
308 translateAction.setNode(node);
\r
309 rotateAction.setNode(node);
\r
310 removeAction.setNode(node);
\r
311 if (node instanceof CSGparentNode) {
\r
312 m.add(new SplitBooleanOpAction2(rootNode,(CSGparentNode)node));
\r
314 } else if (selected.size() == 2) {
\r
315 if (selected.get(0).getParent().equals(rootNode) && selected.get(1).getParent().equals(rootNode)) {
\r
316 Collection<ICSGnode> nodes = new ArrayList<ICSGnode>();
\r
317 for (IG3DNode n : selected)
\r
318 nodes.add((ICSGnode)n);
\r
319 m.add(new AddBooleanOpAction2(rootNode, DifferenceNode.class, nodes));
\r
320 m.add(new AddBooleanOpAction2(rootNode, IntersectionNode.class, nodes));
\r
321 m.add(new AddBooleanOpAction2(rootNode, UnionNode.class, nodes));
\r
325 // SimanticsUI.getSession().syncRequest(new ReadRequest() {
\r
328 // public void run(ReadGraph graph) throws DatabaseException {
\r
329 // Layer0 l0 = Layer0.getInstance(graph);
\r
330 // CSG csg = CSG.getInstance(graph);
\r
331 // Resource ontology = graph.getResource("http://www.simantics.org/CSG-0.1");
\r
333 // if (selectionProvider.getSelectedResources().size() == 0) {
\r
334 // List<NamedResource> primitives = new ArrayList<NamedResource>();
\r
335 // for (Resource r : graph.getObjects(ontology, l0.ConsistsOf)) {
\r
336 // if (graph.isInheritedFrom(r, csg.Primitive) && !r.equals(csg.Primitive)) {
\r
337 // primitives.add(new NamedResource((String)graph.getRelatedValue(r, l0.HasName), r));
\r
341 // Collections.sort(primitives);
\r
342 // for (NamedResource n : primitives) {
\r
343 // m.add(new AddPrimitiveAction(graph, n.getResource(),input));
\r
346 // if (selectionProvider.getSelectedResources().size() == 2) {
\r
347 // List<NamedResource> booleanOps = new ArrayList<NamedResource>();
\r
348 // for (Resource r : graph.getObjects(ontology, l0.ConsistsOf)) {
\r
349 // if (graph.isInheritedFrom(r, csg.BooleanOperation) && !r.equals(csg.BooleanOperation)) {
\r
350 // booleanOps.add(new NamedResource((String)graph.getRelatedValue(r, l0.HasName), r));
\r
354 // Collections.sort(booleanOps);
\r
355 // for (NamedResource n : booleanOps) {
\r
356 // m.add(new AddBooleanOpAction(graph, n.getResource(), input, selectionProvider.getSelectedResources()));
\r
359 // if (selectionProvider.getSelectedResources().size() == 1) {
\r
360 // m.add(translateAction);
\r
361 // m.add(rotateAction);
\r
362 // m.add(removeAction);
\r
363 // Resource selected = selectionProvider.getSelectedResources().get(0);
\r
364 // translateAction.setNode((IG3DNode2)mapping.get(selected));
\r
365 // rotateAction.setNode((IG3DNode2)mapping.get(selected));
\r
366 // removeAction.setNode((IG3DNode2)mapping.get(selected));
\r
367 // if (graph.isInstanceOf(selected, csg.BooleanOperation)) {
\r
368 // m.add(new SplitBooleanOpAction(input,selected));
\r
376 // } catch (DatabaseException e) {
\r
377 // // TODO Auto-generated catch block
\r
378 // e.printStackTrace();
\r
384 contextMenu = menuMgr.createContextMenu(parent);
\r
387 private IContentOutlinePage createOutline() {
\r
388 if (rootNode == null || selectionProvider == null)
\r
390 IContentOutlinePage outlinePage = new VTKContentOutlinePage<Resource,Object>(rootNode, selectionProvider);
\r
391 outlinePage.addSelectionChangedListener(new ISelectionChangedListener() {
\r
394 public void selectionChanged(SelectionChangedEvent event) {
\r
395 selectionProvider.selectionChanged(event);
\r
398 return outlinePage;
\r
401 @SuppressWarnings("rawtypes")
\r
403 public Object getAdapter(Class adapter) {
\r
404 if (IPropertyPage.class.equals(adapter))
\r
405 return new StandardPropertyPage(getSite(),getPropertyContexts());
\r
406 if (IContentOutlinePage.class.equals(adapter)) {
\r
407 return createOutline();
\r
409 if (NodeMap.class.equals(adapter)) {
\r
412 if (INode.class.equals(adapter)) {
\r
415 if (IMapping.class.equals(adapter)) {
\r
418 if (InteractiveVtkPanel.class.equals(adapter)) {
\r
421 return super.getAdapter(adapter);
\r
424 public Set<String> getPropertyContexts() {
\r
425 Set<String> result = new HashSet<String>();
\r
426 result.add("http://www.simantics.org/Project-1.0/ProjectBrowseContext");
\r