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