-/*******************************************************************************\r
- * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.proconf.g3d.shapeeditor.tools;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.TreeMap;\r
-import java.util.Map.Entry;\r
-\r
-import javax.vecmath.AxisAngle4d;\r
-import javax.vecmath.Point3d;\r
-\r
-import org.eclipse.jface.action.Action;\r
-import org.eclipse.jface.action.IMenuManager;\r
-import org.eclipse.jface.action.IToolBarManager;\r
-import org.eclipse.jface.action.MenuManager;\r
-import org.eclipse.jface.resource.ImageDescriptor;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.layout.FormAttachment;\r
-import org.eclipse.swt.layout.FormData;\r
-import org.eclipse.swt.layout.FormLayout;\r
-import org.eclipse.swt.layout.GridData;\r
-import org.eclipse.swt.layout.GridLayout;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Text;\r
-import org.eclipse.ui.ISharedImages;\r
-import org.eclipse.ui.PlatformUI;\r
-import org.simantics.db.Graph;\r
-import org.simantics.db.GraphRequestAdapter;\r
-import org.simantics.db.GraphRequestStatus;\r
-import org.simantics.db.Resource;\r
-import org.simantics.layer0.stubs.Property;\r
-import org.simantics.layer0.utils.EntityFactory;\r
-import org.simantics.layer0.utils.IEntity;\r
-import org.simantics.layer0.utils.instantiation.Instance;\r
-import org.simantics.layer0.utils.instantiation.InstanceFactory;\r
-import org.simantics.proconf.g3d.actions.ContextAction;\r
-import org.simantics.proconf.g3d.actions.FocusAction;\r
-import org.simantics.proconf.g3d.actions.RemoveAction;\r
-import org.simantics.proconf.g3d.actions.RotateAction;\r
-import org.simantics.proconf.g3d.actions.TranslateAction;\r
-import org.simantics.proconf.g3d.actions.WriteAction;\r
-import org.simantics.proconf.g3d.base.EditorContribution;\r
-import org.simantics.proconf.g3d.base.G3DAPI;\r
-import org.simantics.proconf.g3d.base.G3DTools;\r
-import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
-import org.simantics.proconf.g3d.common.StructuredResourceSelection;\r
-import org.simantics.proconf.g3d.csg.stubs.BooleanOperation;\r
-import org.simantics.proconf.g3d.csg.stubs.CSGModel;\r
-import org.simantics.proconf.g3d.csg.stubs.CSGShape;\r
-import org.simantics.proconf.g3d.csg.stubs.Difference;\r
-import org.simantics.proconf.g3d.csg.stubs.Intersection;\r
-import org.simantics.proconf.g3d.csg.stubs.Primitive;\r
-import org.simantics.proconf.g3d.csg.stubs.Union;\r
-import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;\r
-import org.simantics.proconf.g3d.shapeeditor.Activator;\r
-import org.simantics.proconf.g3d.shapeeditor.ShapeEditorResources;\r
-import org.simantics.proconf.g3d.shapeeditor.views.ShapeEditorBase;\r
-import org.simantics.proconf.g3d.stubs.G3DNode;\r
-import org.simantics.proconf.g3d.stubs.Shape;\r
-import org.simantics.utils.ui.ErrorLogger;\r
-\r
-public class CSGModellingContribution implements EditorContribution {\r
- \r
- private static ImageDescriptor INTERSECTION_IMAGE = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID,"icons/intersection.png");\r
- private static ImageDescriptor UNION_IMAGE = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/union.png");\r
- private static ImageDescriptor DIFFERENCE_IMAGE = Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID,"icons/difference.png");\r
-\r
- private ShapeEditorBase parent;\r
- \r
- private List<ContextAction> actions = new ArrayList<ContextAction>();\r
- \r
- private List<Action> addActions = new ArrayList<Action>();\r
- private ContextAction unionAction;\r
- private ContextAction differenceAction;\r
- private ContextAction intersectionAction;\r
- private ContextAction splitAction;\r
- private ContextAction linkAction;\r
- private ContextAction unlinkAction;\r
- private ContextAction translateAction;\r
- private ContextAction rotateAction;\r
- private ContextAction removeAction;\r
- \r
- private Composite infoComposite;\r
- private Text infoText;\r
- \r
- \r
- public CSGModellingContribution(ThreeDimensionalEditorBase parent) {\r
- this.parent = (ShapeEditorBase)parent; \r
- }\r
- \r
- @Override\r
- public String getName() {\r
- return "Shape Editing";\r
- }\r
- \r
- @Override\r
- public void initialize(Graph graph) {\r
- makeActions(graph);\r
- }\r
- \r
- @Override\r
- public void createControl(Composite parent) {\r
- FormLayout flayout = new FormLayout();\r
- parent.setLayout(flayout);\r
- infoComposite = new Composite(parent, SWT.BORDER);\r
- FormData data = new FormData();\r
- data.top = new FormAttachment(0, 0);\r
- data.left = new FormAttachment(0, 0);\r
- data.right = new FormAttachment(100, 0);\r
- data.bottom = new FormAttachment(infoComposite, 0, SWT.TOP);\r
- this.parent.getRenderingComposite().setLayoutData(data);\r
- data = new FormData();\r
- data.left = new FormAttachment(0, 0);\r
- data.right = new FormAttachment(100, 0);\r
- data.bottom = new FormAttachment(100, 0);\r
- data.height = 18;\r
- infoComposite.setLayoutData(data);\r
- GridLayout layout = new GridLayout(1,false);\r
- layout.marginWidth = 1;\r
- layout.marginHeight = 1;\r
- infoComposite.setLayout(layout);\r
- infoText = new Text(infoComposite, SWT.NONE);\r
- GridData gdata = new GridData();\r
- gdata.grabExcessHorizontalSpace = true;\r
- gdata.horizontalAlignment = SWT.FILL;\r
- infoText.setLayoutData(gdata);\r
- }\r
- \r
- @Override\r
- public void disposeControl() {\r
- infoComposite.dispose();\r
- }\r
- \r
- @Override\r
- public void fillContextMenu(Graph graph, IMenuManager manager, StructuredResourceSelection selection) {\r
-\r
- if (selection.isEmpty()) {\r
- MenuManager addMenu = new MenuManager("Add", "add");\r
- addMenu.setRemoveAllWhenShown(false);\r
- for (Action a : addActions) {\r
- addMenu.add(a);\r
- }\r
- manager.add(addMenu);\r
- }\r
-\r
- }\r
- \r
- protected void makeActions(Graph graph) {\r
- actions.add(translateAction = new TranslateAction(parent) {\r
- @Override\r
- public void setInfoText(String text) {\r
- infoText.setText(text);\r
- }\r
- });\r
- actions.add(rotateAction = new RotateAction(parent){\r
- @Override\r
- public void setInfoText(String text) {\r
- infoText.setText(text);\r
- }\r
- });\r
- actions.add(removeAction = new RemoveAction(parent));\r
- actions.add(new FocusAction(parent));\r
-\r
- \r
- IEntity primitive = EntityFactory.create(graph,ShapeEditorResources.csgResource.Primitive);\r
- \r
- Collection<IEntity> primitives = primitive.getRelatedObjects(graph.getBuiltins().SupertypeOf);\r
-\r
- TreeMap<String, Resource> sorter = new TreeMap<String, Resource>();\r
- for (IEntity p : primitives) {\r
- String key = p.getName();\r
- if (key.equals(""))\r
- key = "ERROR (" + p.getURI() + ")";\r
- sorter.put(key, p.getResource());\r
- }\r
-\r
- for (Entry<String, Resource> e : sorter.entrySet()) {\r
- final String name = e.getKey();\r
- final Resource r = e.getValue();\r
- Action a = new Action() {\r
- Resource res;\r
- public void run() {\r
- parent.getSession().asyncWrite(new GraphRequestAdapter() {\r
- @Override\r
- public GraphRequestStatus perform(Graph g) throws Exception {\r
-\r
- Instance ins = InstanceFactory.getInstanceOfType(g,r);\r
- Resource instance = ins.instantiate(g);\r
- Shape shape = new Shape(g,instance);\r
- res = shape.getResource();\r
- resetShape(shape);\r
- CSGModel model = new CSGModel(g,parent.getModelResource());\r
- model.addStatement(ShapeEditorResources.g3dResource.HasChild, shape.getResource());\r
- return GraphRequestStatus.transactionComplete();\r
- }\r
- \r
- @Override\r
- public void handleException(Throwable e) {\r
- super.handleException(e);\r
- ErrorLogger.defaultLogError("Adding " + name + " failed.", e);\r
- }\r
- \r
- @Override\r
- public void requestCompleted(GraphRequestStatus status) {\r
- parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){\r
- public void run() {\r
- parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(res));\r
- }\r
- });\r
- }\r
- });\r
- }\r
- };\r
- a.setText(name);\r
- a.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK));\r
- addActions.add(a);\r
-\r
- }\r
-\r
- unionAction = new WriteAction(parent,false) {\r
-\r
- Resource r;\r
- @Override\r
- public boolean usable(Graph graph,List<Resource> resources) {\r
- if (resources.size() >= 2)\r
- return true;\r
- return false;\r
- }\r
-\r
- public GraphRequestStatus doChanges(Graph graph) {\r
- List<IGraphicsNode> list = parent.getSelectionAdapter().getSelectedObjects();\r
- if (list.size() < 2) {\r
- showMessage("Union works between two objects");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- Resource r1 = list.get(0).getResource();\r
- CSGShape shape1 = new CSGShape(graph,r1);\r
-\r
- G3DNode parent = shape1.getParent();\r
- if (parent == null) {\r
- showMessage("Primary shape has no parent, don't know what to do");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- BooleanOperation op = Union.createDefault(graph).toBooleanOperation(); //FIXME : stubcast\r
- r = op.getResource();\r
- if (createBooleanOp(op, parent, shape1, list))\r
- return GraphRequestStatus.transactionComplete();\r
- else\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- \r
- @Override\r
- public void afterChanges(GraphRequestStatus status) {\r
- parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){\r
- public void run() {\r
- parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r));\r
- }\r
- });\r
- }\r
- };\r
- unionAction.setText("Union");\r
- unionAction.setToolTipText("Union");\r
- unionAction.setImageDescriptor(UNION_IMAGE);\r
-\r
- differenceAction = new WriteAction(parent,false) {\r
-\r
- Resource r;\r
- @Override\r
- public boolean usable(Graph graph,List<Resource> resources) {\r
- if (resources.size() >= 2)\r
- return true;\r
- return false;\r
- }\r
-\r
- public GraphRequestStatus doChanges(Graph graph) {\r
- List<IGraphicsNode> list = parent.getSelectionAdapter().getSelectedObjects();\r
- if (list.size() < 2) {\r
- showMessage("Difference works between two objects");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- CSGShape shape1 = new CSGShape(graph,list.get(0).getResource());\r
- G3DNode parent = shape1.getParent();\r
- if (parent == null) {\r
- showMessage("Primary shape has no parent, don't know what to do");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- BooleanOperation op = Difference.createDefault(graph).toBooleanOperation(); //FIXME : stubcast\r
- r = op.getResource();\r
- if (createBooleanOp(op, parent, shape1, list))\r
- return GraphRequestStatus.transactionComplete();\r
- else\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- \r
- @Override\r
- public void afterChanges(GraphRequestStatus status) {\r
- parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){\r
- public void run() {\r
- parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r));\r
- }\r
- });\r
- }\r
- };\r
- differenceAction.setText("Difference");\r
- differenceAction.setToolTipText("Difference");\r
- differenceAction.setImageDescriptor(DIFFERENCE_IMAGE);\r
-\r
- intersectionAction = new WriteAction(parent,false) {\r
- Resource r;\r
- @Override\r
- public boolean usable(Graph graph,List<Resource> resources) {\r
- if (resources.size() >= 2)\r
- return true;\r
- return false;\r
- }\r
-\r
- public GraphRequestStatus doChanges(Graph graph) {\r
- List<IGraphicsNode> list = parent.getSelectionAdapter()\r
- .getSelectedObjects();\r
- if (list.size() < 2) {\r
- showMessage("Intersection works between two objects");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- CSGShape shape1 = new CSGShape(graph,list.get(0).getResource());\r
- G3DNode parent = shape1.getParent();\r
- if (parent == null) {\r
- showMessage("Primary shape has no parent, don't know what to do");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- BooleanOperation op = Intersection.createDefault(graph).toBooleanOperation(); //FIXME : stubcast\r
- r = op.getResource();\r
- if (createBooleanOp(op, parent, shape1, list))\r
- return GraphRequestStatus.transactionComplete();\r
- else\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- \r
- @Override\r
- public void afterChanges(GraphRequestStatus status) {\r
- parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){\r
- public void run() {\r
- parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r));\r
- }\r
- });\r
- \r
- }\r
- };\r
- intersectionAction.setText("Intersection");\r
- intersectionAction.setToolTipText("Intersection");\r
- intersectionAction.setImageDescriptor(INTERSECTION_IMAGE);\r
-\r
- splitAction = new WriteAction(parent,false) {\r
-\r
- @Override\r
- public boolean usable(Graph graph,List<Resource> resources) {\r
- if (resources.size() == 1) {\r
- Resource r = resources.iterator().next();\r
- IEntity t = EntityFactory.create(graph,r);\r
- if (t.isInstanceOf(ShapeEditorResources.csgResource.BooleanOperation)) {\r
- return true;\r
- }\r
- }\r
-\r
- return false;\r
- }\r
- \r
- \r
- \r
- public GraphRequestStatus doChanges(Graph graph) {\r
- List<IGraphicsNode> list = parent.getSelectionAdapter().getSelectedObjects();\r
- if (list.size() != 1) {\r
- showMessage("Split requires one object");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- Resource deletedResource = list.get(0).getResource();\r
- IEntity deletedEntity = EntityFactory.create(graph,deletedResource);\r
- if (!deletedEntity.isInstanceOf(ShapeEditorResources.csgResource.BooleanOperation)) {\r
- showMessage("Split requires boolean operation");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- Collection<IEntity> parents = deletedEntity.getRelatedObjects(ShapeEditorResources.g3dResource.HasParent);\r
- if (parents.size() != 1) {\r
- showMessage("Shape has " + parents.size()\r
- + " parents, don't know what to do");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- IEntity parent = parents.iterator().next();\r
- // find all shapes and their positions and orientations relative to world coordinates\r
- BooleanOperation op = new BooleanOperation(deletedEntity);\r
- CSGShape shape1 = op.getMainShape();\r
- Point3d shape1WorldPos = G3DTools.getPoint(shape1.getWorldPosition());\r
- AxisAngle4d shape1WorldRot = G3DTools.getOrientation(shape1.getWorldOrientation());\r
- //System.out.println(shape1WorldPos + " " + shape1WorldRot);\r
- Collection<CSGShape> shape2s = op.getSecondaryShape();\r
-\r
- ArrayList<Point3d> shape2WorldPos = new ArrayList<Point3d>();\r
- ArrayList<AxisAngle4d> shape2WorldRot = new ArrayList<AxisAngle4d>();\r
- for (CSGShape shape : shape2s) {\r
- Point3d pos = G3DTools.getPoint(shape.getWorldPosition());\r
- AxisAngle4d rot = G3DTools.getOrientation(shape.getWorldOrientation());\r
- shape2WorldPos.add(pos);\r
- shape2WorldRot.add(rot);\r
- //System.out.println(pos + " " + rot);\r
- }\r
-\r
- // removed boolean operation is either connected to model or another boolean operation.\r
- CSGModel m = new CSGModel(graph,CSGModellingContribution.this.parent.getModelResource());\r
- if (parent.getResource().equals(CSGModellingContribution.this.parent.getModelResource())) {\r
- // if deleted boolean operation is connected to the model,\r
- // all its children are added to the model\r
-\r
- m.removeStatement(ShapeEditorResources.g3dResource.HasChild, op);\r
- m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape1);\r
- for (CSGShape shape2 : shape2s) {\r
- m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape2);\r
- }\r
-\r
- } else {\r
- // deleted boolean operation is connected to another boolean\r
- // operation\r
- // if the deleted boolean operation is primary child, we'll\r
- // must replace it with deleted boolean operations\r
- // primary child\r
- if (!parent.isInstanceOf(ShapeEditorResources.csgResource.BooleanOperation)) {\r
- ErrorLogger.defaultLogError("Parent shape is not a boolean operation nor model ?!", null);\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- BooleanOperation parentOp = new BooleanOperation(parent);\r
- // we'll have to list all secondary shapes in parent boolean\r
- // op so that we can find the correct relatio\r
- Collection<IEntity> parentShape2s = parentOp.getRelatedObjects(ShapeEditorResources.csgResource.HasSecondaryShape);\r
-\r
- if (parentOp.getMainShape().getResource().equals(deletedResource)) {\r
- // split boolean operation is the primary child in the\r
- // parent boolean operation\r
- parent.removeStatement(ShapeEditorResources.csgResource.HasMainShape,deletedResource);\r
- // graph.commitChanges(ShapeEditorView.this);\r
- parent.addStatement(ShapeEditorResources.csgResource.HasMainShape, shape1);\r
- // graph.commitChanges(ShapeEditorView.this);\r
- for (CSGShape shape2 : shape2s) {\r
- m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape2);\r
- }\r
- } else if (contains(parentShape2s, deletedResource)) {\r
- // split boolean operation is one of the secondary\r
- // shapes in the parent boolean operation\r
- parent.removeStatement(ShapeEditorResources.csgResource.HasSecondaryShape,deletedResource);\r
- // graph.commitChanges(ShapeEditorView.this);\r
- parent.addStatement(ShapeEditorResources.csgResource.HasSecondaryShape,shape1);\r
- // graph.commitChanges(ShapeEditorView.this);\r
-\r
- // model.getConsistOfShapeSet().add(shape2);\r
- for (CSGShape shape2 : shape2s) {\r
- m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape2);\r
- }\r
- } else {\r
- ErrorLogger.defaultLogError("Parent shape is not a boolean operation nor model ?!", null);\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- }\r
- deletedEntity.removeStatement(ShapeEditorResources.csgResource.HasMainShape, shape1);\r
- for (CSGShape shape2 : shape2s)\r
- deletedEntity.removeStatement(ShapeEditorResources.csgResource.HasSecondaryShape, shape2);\r
- //graph.commit();\r
- //System.out.println("Setting original transformations");\r
- //G3DTools.setTuple3(shape1.getWorldPosition(), shape1WorldPos);\r
- //G3DTools.setOrientation(shape1.getWorldOrientation(), shape1WorldRot);\r
- G3DAPI.setWorldTransformation(shape1, shape1WorldPos,shape1WorldRot);\r
- \r
- int i = 0;\r
- for (CSGShape shape : shape2s) {\r
- G3DAPI.setWorldTransformation(shape, shape2WorldPos.get(i),shape2WorldRot.get(i));\r
- //G3DTools.setTuple3(shape.getWorldPosition(), shape2WorldPos.get(i));\r
- //G3DTools.setOrientation(shape.getWorldOrientation(),shape2WorldRot.get(i));\r
- i++;\r
- }\r
- return GraphRequestStatus.transactionComplete();\r
-\r
- }\r
- };\r
- splitAction.setText("Split");\r
- splitAction.setToolTipText("Split");\r
- splitAction.setImageDescriptor(PlatformUI.getWorkbench()\r
- .getSharedImages().getImageDescriptor(\r
- ISharedImages.IMG_OBJS_INFO_TSK));\r
-\r
- linkAction = new WriteAction(parent,false) {\r
- Resource r;\r
- @Override\r
- public boolean usable(Graph graph,List<Resource> resources) {\r
- if (resources.size() == 2) {\r
- Iterator<Resource> i = resources.iterator();\r
- Shape s1 = new Shape(graph,i.next());\r
- Shape s2 = new Shape(graph,i.next());\r
- if (s1.getRelatedObjects(ShapeEditorResources.g3dResource.GeometryDefinitionOf).size() == 0 &&\r
- s2.getRelatedObjects(ShapeEditorResources.g3dResource.GeometryDefinitionOf).size() == 0)\r
- return true;\r
-\r
- }\r
- return false;\r
- }\r
-\r
- public GraphRequestStatus doChanges(Graph graph) {\r
- List<IGraphicsNode> list = parent.getSelectionAdapter().getSelectedObjects();\r
- if (list.size() != 2) {\r
- showMessage("Link works between two objects");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- Resource r1 = list.get(0).getResource();\r
- Resource r2 = list.get(1).getResource();\r
-\r
- CSGShape shape1 = new CSGShape(graph,r1);\r
- CSGShape shape2 = new CSGShape(graph,r2);\r
- \r
- Point3d p = G3DTools.getPoint(shape2.getWorldPosition());\r
- AxisAngle4d aa = G3DTools.getOrientation(shape2.getWorldOrientation());\r
- //System.out.println(p + " " + aa);\r
- shape2.removeRelatedStatements(ShapeEditorResources.g3dResource.HasParent);\r
- r = shape2.getResource();\r
- //System.out.println("Link remove commit");\r
- //graph.commitChanges(ShapeEditorView.this);\r
- //shape1.getChild().add(shape2.toG3DNode()); //FIXME : stubcast\r
- shape1.addStatement(ShapeEditorResources.g3dResource.HasChild, shape2);\r
- // FIXME : this is needed\r
- //System.out.println("Link add commit");\r
- //graph.commitChanges(ShapeEditorView.this);\r
- //G3DTools.setTuple3(shape2.getWorldPosition(), p);\r
- //G3DTools.setOrientation(shape2.getWorldOrientation(), aa);\r
- G3DAPI.setWorldTransformation(shape2, p, aa);\r
- return GraphRequestStatus.transactionComplete();\r
- }\r
- \r
- @Override\r
- public void afterChanges(GraphRequestStatus status) {\r
- parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){\r
- public void run() {\r
- parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r));\r
- }\r
- });\r
- }\r
- };\r
- linkAction.setText("Link");\r
- linkAction.setToolTipText("Link");\r
- linkAction.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/link.png"));\r
-\r
- unlinkAction = new WriteAction(parent,false) {\r
- Resource r;\r
- @Override\r
- public boolean usable(Graph graph,List<Resource> resources) {\r
- if (resources.size() == 1) {\r
- Iterator<Resource> i = resources.iterator();\r
- Shape s1 = new Shape(graph,i.next());\r
- return (s1.getRelatedObjects(ShapeEditorResources.g3dResource.GeometryDefinitionOf).size() == 0\r
- && s1.getParent() != null && !s1.getParent()\r
- .getResource().equals(CSGModellingContribution.this.parent.getModelResource()));\r
-\r
- }\r
- return false;\r
- }\r
-\r
- public GraphRequestStatus doChanges(Graph graph) {\r
- List<IGraphicsNode> list = parent.getSelectionAdapter().getSelectedObjects();\r
- if (list.size() != 1) {\r
- showMessage("Unlink works with one object");\r
- return GraphRequestStatus.transactionCancel();\r
- }\r
- Resource r1 = list.get(0).getResource();\r
-\r
- CSGShape shape1 = new CSGShape(graph,r1);\r
- CSGModel m = new CSGModel(graph,CSGModellingContribution.this.parent.getModelResource());\r
- Point3d p = G3DTools.getPoint(shape1.getWorldPosition());\r
- AxisAngle4d aa = G3DTools.getOrientation(shape1.getWorldOrientation());\r
- shape1.removeRelatedStatements(ShapeEditorResources.g3dResource.HasParent);\r
- //graph.commitChanges(ShapeEditorView.this);\r
- m.addStatement(ShapeEditorResources.g3dResource.HasChild, shape1);\r
- // FIXME : this is needed\r
- //graph.commitChanges(ShapeEditorView.this);\r
- //G3DTools.setTuple3(shape1.getWorldPosition(), p);\r
- //G3DTools.setOrientation(shape1.getWorldOrientation(), aa);\r
- G3DAPI.setWorldTransformation(shape1, p, aa);\r
- r = shape1.getResource();\r
- return GraphRequestStatus.transactionComplete();\r
- }\r
- \r
- @Override\r
- public void afterChanges(GraphRequestStatus status) {\r
- parent.getRenderingComposite().getDisplay().asyncExec(new Runnable(){\r
- public void run() {\r
- parent.getSelectionAdapter().updateSelection(new StructuredResourceSelection(r));\r
- }\r
- });\r
- }\r
- };\r
- unlinkAction.setText("Unlink");\r
- unlinkAction.setToolTipText("Unlink");\r
- unlinkAction.setImageDescriptor(Activator.imageDescriptorFromPlugin(\r
- Activator.PLUGIN_ID, "icons/unlink.png"));\r
-\r
- actions.add(unionAction);\r
- actions.add(intersectionAction);\r
- actions.add(differenceAction);\r
- actions.add(splitAction);\r
- actions.add(linkAction);\r
- actions.add(unlinkAction);\r
- }\r
- \r
- boolean contains(ArrayList<Resource> parentShape2sIds, Resource id) {\r
- for (int i = 0; i < parentShape2sIds.size(); i++) {\r
- if (parentShape2sIds.get(i).equals(id))\r
- return true;\r
-\r
- }\r
- return false;\r
- }\r
- \r
- boolean contains(Collection<IEntity> parentShape2sIds, Resource id) {\r
- for (IEntity e : parentShape2sIds) {\r
- if (e.getResource().equals(id))\r
- return true;\r
-\r
- }\r
- return false;\r
- }\r
-\r
- private boolean createBooleanOp(BooleanOperation op, G3DNode parent,\r
- CSGShape shape1, List<IGraphicsNode> list) {\r
-\r
- resetShape(op.toShape()); //FIXME : stubcast\r
- // new boolean operation is added to the first shape's parent\r
- // the parent is the model\r
-\r
- Point3d refPos = G3DTools.getPoint(shape1.getLocalPosition());\r
- G3DTools.setTuple3(op.getLocalPosition(), refPos);\r
- refPos.negate();\r
- G3DTools.addTuple3(shape1.getLocalPosition(), refPos);\r
- op.removeRelatedStatements(ShapeEditorResources.csgResource.HasMainShape);\r
- op.addStatement(ShapeEditorResources.csgResource.HasMainShape, shape1);\r
- \r
- if (!replaceShape(parent, shape1.toShape(), op.toShape())) { //FIXME : stubcast\r
- return false;\r
- }\r
- //model.getConsistOfSet().remove(shape1);\r
- for (int i = 1; i < list.size(); i++) {\r
- CSGShape shape2 = new CSGShape(op.getGraph(),list.get(i).getResource());\r
- G3DTools.addTuple3(shape2.getLocalPosition(), refPos);\r
- G3DNode shape2parent = shape2.getParent();\r
- if (shape2parent != null) {\r
- // we'll must link before removing or shape will be deleted\r
- //op.addStatement(ShapeEditorResources.csgResource.HasSecondaryShape,shape2); \r
- //if (!replaceShape(shape2parent, shape2, null)) {\r
- // op.removeStatement(ShapeEditorResources.csgResource.HasSecondaryShape, shape2);\r
- // // shape couldn't be removed so we'll remove the link\r
- //}\r
- \r
- if (replaceShape(shape2parent, shape2.toShape(), null)) { //FIXME : stubcast\r
- op.addStatement(ShapeEditorResources.csgResource.HasSecondaryShape,shape2);\r
- }\r
- }\r
- }\r
- // Commit is not needed because this is final call in all transactions\r
- //graph.commitChanges(ShapeEditorView.this);\r
- return true;\r
- }\r
-\r
- /**\r
- * Replaces or removes parent from shape\r
- * @param parent parent containing shape\r
- * @param removed the shape\r
- * @param added the replacing shape or null\r
- * @return true if replacing or removing was successful\r
- * @throws TransactionException\r
- */\r
- private boolean replaceShape(G3DNode parent, Shape removed, Shape added) {\r
- assert (parent != null);\r
- assert (removed != null);\r
-\r
- \r
- //CSGModel m = CSGModelFactory.create(parent.getGraph(),model);\r
- if (parent.getResource().equals(this.parent.getModelResource())) {\r
- // parent is model (rootnode). \r
- // shape is connected to it with "Has Child" relation\r
- parent.removeStatement(ShapeEditorResources.g3dResource.HasChild, removed);\r
- if (added != null) {\r
- parent.addStatement(ShapeEditorResources.g3dResource.HasChild, added);\r
- }\r
- } else {\r
- // the first shape's parent is boolean operation\r
- // so we must know if its connected as a primary shape or as a secondary shape\r
- if (!parent.isInstanceOf(ShapeEditorResources.csgResource.BooleanOperation)) {\r
- ErrorLogger.defaultLogError("Parent shape is not a boolean operation nor model ?!",null);\r
- return false;\r
- }\r
- BooleanOperation parentOp = new BooleanOperation(parent);\r
- // listing all secondary shapes in the parent boolean operation\r
- Collection<CSGShape> parentShape2s = parentOp.getSecondaryShape();\r
- ArrayList<Resource> parentShape2sIds = new ArrayList<Resource>();\r
- for (CSGShape shape2 : parentShape2s)\r
- parentShape2sIds.add(shape2.getResource());\r
- if (parentOp.getMainShape().getResource().equals(removed.getResource())) {\r
- if (added == null) {\r
- return false;\r
- }\r
- parent.removeStatement(ShapeEditorResources.csgResource.HasMainShape, removed);\r
- parent.addStatement(ShapeEditorResources.csgResource.HasMainShape, added);\r
- \r
- } else if (contains(parentShape2sIds, removed.getResource())) {\r
-\r
- parent.removeStatement(ShapeEditorResources.csgResource.HasSecondaryShape, removed);\r
- parent.addStatement(ShapeEditorResources.csgResource.HasSecondaryShape, added); \r
- \r
- } else {\r
- ErrorLogger.defaultLogError("Parent shape is not a boolean operation nor model ?!",null);\r
- //coreTC.cancelTransaction();\r
- return false;\r
- }\r
- }\r
- return true;\r
- }\r
-\r
- /**\r
- * Resets shape to identity rotation and zero translation\r
- * \r
- * @param shape\r
- */\r
- private void resetShape(Shape shape) {\r
- G3DTools.resetTransformation(shape);\r
- Graph graph = shape.getGraph();\r
- if (shape.isInstanceOf(ShapeEditorResources.csgResource.Primitive)) {\r
- Primitive prim = new Primitive(shape);\r
- Collection<Property> c = prim.getSizingProperty();\r
- if (c.size() == 0)\r
- ErrorLogger.getDefault().logWarning("Shape does not contain sizing properties.", null);\r
- \r
- for (Property p : c) {\r
- if (p.isInstanceOf(graph.getBuiltins().Double)) {\r
- graph.setScalarDouble(p.getResource(), 1.0);\r
- } else if (p.isInstanceOf(graph.getBuiltins().Integer)) {\r
- graph.setScalarInteger(p.getResource(), 1);\r
- } else {\r
- ErrorLogger.getDefault().logWarning("Cannot handle sizing property " + p.getName() , null);\r
- }\r
- }\r
- }\r
- \r
- }\r
- \r
- protected void showMessage(String s) {\r
- parent.showMessage(s);\r
- }\r
- \r
- @Override\r
- public Collection<ContextAction> getActions() {\r
- return actions;\r
- }\r
- \r
- \r
- @Override\r
- public void fillLocalToolBar(IToolBarManager manager) {\r
-\r
- }\r
- \r
- @Override\r
- public void fillLocalPullDown(IMenuManager manager) {\r
- \r
- }\r
- \r
- @Override\r
- public void dispose() {\r
- \r
- }\r
- \r
- @Override\r
- public void run() {\r
-\r
- }\r
-\r
-}\r