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