1 /*******************************************************************************
\r
2 * Copyright (c) 2007- VTT Technical Research Centre of Finland.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package org.simantics.processeditor.tools;
\r
13 import java.util.ArrayList;
\r
14 import java.util.Collection;
\r
15 import java.util.Iterator;
\r
16 import java.util.List;
\r
18 import org.eclipse.jface.action.Action;
\r
19 import org.eclipse.jface.action.IMenuManager;
\r
20 import org.eclipse.jface.action.IToolBarManager;
\r
21 import org.eclipse.jface.dialogs.MessageDialog;
\r
22 import org.eclipse.swt.SWT;
\r
23 import org.eclipse.swt.layout.FormAttachment;
\r
24 import org.eclipse.swt.layout.FormData;
\r
25 import org.eclipse.swt.layout.FormLayout;
\r
26 import org.eclipse.swt.layout.GridData;
\r
27 import org.eclipse.swt.layout.GridLayout;
\r
28 import org.eclipse.swt.widgets.Composite;
\r
29 import org.eclipse.swt.widgets.Text;
\r
30 import org.simantics.db.Graph;
\r
31 import org.simantics.db.GraphRequestStatus;
\r
32 import org.simantics.db.Resource;
\r
33 import org.simantics.layer0.utils.EntityFactory;
\r
34 import org.simantics.layer0.utils.IEntity;
\r
35 import org.simantics.processeditor.Activator;
\r
36 import org.simantics.processeditor.ProcessResource;
\r
37 import org.simantics.processeditor.actions.InsertComponentAction;
\r
38 import org.simantics.processeditor.actions.InsertEquipmentAction;
\r
39 import org.simantics.processeditor.actions.InsertNozzleAction;
\r
40 import org.simantics.processeditor.actions.ReversePipelineAction;
\r
41 import org.simantics.processeditor.actions.RoutePipeAction;
\r
42 import org.simantics.processeditor.actions.TranslateElbowAction;
\r
43 import org.simantics.processeditor.actions.TranslateInlineComponentAction;
\r
44 import org.simantics.processeditor.actions.TranslateStraightAction;
\r
45 import org.simantics.processeditor.common.ControlPointTools;
\r
46 import org.simantics.processeditor.stubs.InlineComponent;
\r
47 import org.simantics.processeditor.stubs.PipeControlPoint;
\r
48 import org.simantics.proconf.g3d.actions.ContextAction;
\r
49 import org.simantics.proconf.g3d.actions.FocusAction;
\r
50 import org.simantics.proconf.g3d.actions.RemoveAction;
\r
51 import org.simantics.proconf.g3d.actions.RotateAction;
\r
52 import org.simantics.proconf.g3d.actions.TranslateAction;
\r
53 import org.simantics.proconf.g3d.base.EditorContribution;
\r
54 import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;
\r
55 import org.simantics.proconf.g3d.common.StructuredResourceSelection;
\r
56 import org.simantics.utils.ui.jface.MenuTools;
\r
58 import com.jme.intersection.CollisionData;
\r
59 import com.jme.intersection.CollisionResults;
\r
60 import com.jme.intersection.TriangleCollisionResults;
\r
61 import com.jme.scene.Geometry;
\r
62 import com.jme.scene.Node;
\r
63 import com.jme.scene.Spatial;
\r
66 public class PlantEditContribution implements EditorContribution {
\r
67 private List<ContextAction> actions = new ArrayList<ContextAction>();
\r
68 private ThreeDimensionalEditorBase parent;
\r
69 private Composite infoComposite;
\r
70 private Text infoText;
\r
72 private Action checkInterferencesAction = null;
\r
74 public PlantEditContribution(ThreeDimensionalEditorBase parent) {
\r
75 this.parent = parent;
\r
79 public void createControl(Composite parent) {
\r
80 FormLayout flayout = new FormLayout();
\r
81 parent.setLayout(flayout);
\r
82 infoComposite = new Composite(parent, SWT.BORDER);
\r
83 FormData data = new FormData();
\r
84 data.top = new FormAttachment(0, 0);
\r
85 data.left = new FormAttachment(0, 0);
\r
86 data.right = new FormAttachment(100, 0);
\r
87 data.bottom = new FormAttachment(infoComposite, 0, SWT.TOP);
\r
88 this.parent.getRenderingComposite().setLayoutData(data);
\r
89 data = new FormData();
\r
90 data.left = new FormAttachment(0, 0);
\r
91 data.right = new FormAttachment(100, 0);
\r
92 data.bottom = new FormAttachment(100, 0);
\r
94 infoComposite.setLayoutData(data);
\r
95 GridLayout layout = new GridLayout(1,false);
\r
96 layout.marginWidth = 1;
\r
97 layout.marginHeight = 1;
\r
98 infoComposite.setLayout(layout);
\r
99 infoText = new Text(infoComposite, SWT.NONE);
\r
100 GridData gdata = new GridData();
\r
101 gdata.grabExcessHorizontalSpace = true;
\r
102 gdata.horizontalAlignment = SWT.FILL;
\r
103 infoText.setLayoutData(gdata);
\r
108 public void disposeControl() {
\r
109 infoComposite.dispose();
\r
114 public void dispose() {
\r
121 public void fillContextMenu(Graph graph, IMenuManager manager,
\r
122 StructuredResourceSelection selection) {
\r
127 public void fillLocalPullDown(IMenuManager manager) {
\r
128 MenuTools.getOrCreate(parent.getMenuID(),"Advanced", manager).add(checkInterferencesAction);
\r
133 public void fillLocalToolBar(IToolBarManager manager) {
\r
138 public Collection<ContextAction> getActions() {
\r
143 public String getName() {
\r
144 return "Plant Editing";
\r
148 public void initialize(Graph graph) {
\r
149 actions.add(new TranslateAction(parent){
\r
151 public boolean usable(Graph graph,List<Resource> resources) {
\r
152 if (super.usable(graph, resources)) {
\r
153 for (Resource r : resources) {
\r
154 // FIXME : use new ontology :
\r
155 // 1. lose ends works like end components (just what this code does, but type checks are not correct)
\r
156 // 2. connected components are moved inline. (TranslateInlineAction)
\r
157 IEntity t = EntityFactory.create(graph, r);
\r
158 if (t.isInstanceOf(ProcessResource.plant3Dresource.InlineComponent)) {
\r
159 InlineComponent component = new InlineComponent(t);
\r
160 PipeControlPoint pcp = component.getControlPoint();
\r
161 if (pcp.getNext() != null && pcp.getPrevious() != null)
\r
171 public void setInfoText(String text) {
\r
172 infoText.setText(text);
\r
175 actions.add(new TranslateInlineComponentAction(parent) {
\r
177 public void setInfoText(String text) {
\r
178 infoText.setText(text);
\r
181 actions.add(new TranslateStraightAction(parent) {
\r
183 public void setInfoText(String text) {
\r
184 infoText.setText(text);
\r
187 actions.add(new TranslateElbowAction(parent) {
\r
189 public void setInfoText(String text) {
\r
190 infoText.setText(text);
\r
193 actions.add(new RotateAction(parent){
\r
195 public boolean usable(Graph graph,List<Resource> resources) {
\r
196 if (super.usable(graph,resources)) {
\r
197 for (Resource r : resources) {
\r
198 IEntity t = EntityFactory.create(graph,r);
\r
199 // FIXME : use new ontology
\r
200 // TODO : create rotate action that can rotate inline components
\r
201 // TODO : ontology change: pipes and similar components cannot be rotated, since there is no point to do that.
\r
202 if (t.isInstanceOf(ProcessResource.plant3Dresource.InlineComponent)) {
\r
213 public void setInfoText(String text) {
\r
214 infoText.setText(text);
\r
217 actions.add(new RemoveAction(parent) {
\r
219 public GraphRequestStatus doChanges(Graph graph) {
\r
220 Iterator<Resource> i = parent.getSelectionAdapter().getCurrentSelection().iterator();
\r
221 while (i.hasNext()) {
\r
222 Resource s = i.next();
\r
223 IEntity r = EntityFactory.create(graph, s);
\r
224 if (r.isInstanceOf(ProcessResource.g3dResource.G3DNode)) {
\r
225 Collection<IEntity> parentNode= r.getRelatedObjects(ProcessResource.g3dResource.HasParent);
\r
226 if (parentNode.size() == 1) {
\r
227 Collection<IEntity> rs = r.getRelatedObjects(ProcessResource.plant3Dresource.HasControlPoint);
\r
228 for (IEntity cp : rs) {
\r
229 ControlPointTools.removeControlPoint(new PipeControlPoint(cp));
\r
231 r.removeRelatedStatements(ProcessResource.g3dResource.HasParent);
\r
233 if (parentNode.size() == 0) {
\r
234 parent.showMessage("Object has no parent, don't know what to do!");
\r
236 parent.showMessage("Object has more than one parent, don't know what to do!");
\r
242 //parent.getSelectionAdapter().setSelection(new StructuredResourceSelection());
\r
243 return GraphRequestStatus.transactionComplete();
\r
246 actions.add(new FocusAction(parent));
\r
247 actions.add(new RoutePipeAction(parent){
\r
249 public void setInfoText(String text) {
\r
250 infoText.setText(text);
\r
253 actions.add(new InsertComponentAction(parent));
\r
254 actions.add(new InsertEquipmentAction(parent));
\r
255 actions.add(new InsertNozzleAction(parent));
\r
256 actions.add(new ReversePipelineAction(parent));
\r
258 checkInterferencesAction = new Action() {
\r
259 public void run() {
\r
260 CollisionResults results = new TriangleCollisionResults();
\r
261 //getRenderingComponent().getNormalRoot().calculateCollisions(getRenderingComponent().getNormalRoot(), results);
\r
262 collide(parent.getRenderingComponent().getShadowRoot(),parent.getRenderingComponent().getShadowRoot(),results);
\r
263 results = filterResults(results);
\r
264 for (int i = 0; i < results.getNumber(); i++) {
\r
265 CollisionData data = results.getCollisionData(i);
\r
266 Geometry s = data.getSourceMesh();
\r
267 Geometry t = data.getTargetMesh();
\r
268 MessageDialog dialog = new MessageDialog(parent.getRenderingComposite().getShell(),"Interference " + i + " / " + results.getNumber(), null, "Interference between " + s + " and " + t,MessageDialog.WARNING,new String[]{"Next","Cancel"},0);
\r
270 Resource sid = parent.getScenegraphAdapter().getNodeResource(s.getName());
\r
271 Resource tid = parent.getScenegraphAdapter().getNodeResource(t.getName());
\r
273 StructuredResourceSelection sel = new StructuredResourceSelection();
\r
280 parent.getSelectionAdapter().setSelection(sel);
\r
281 } catch(NumberFormatException e) {
\r
284 if (dialog.open() == 1)
\r
289 private void collide(Spatial s, Spatial p, CollisionResults r) {
\r
290 s.calculateCollisions(p, r);
\r
291 if (s instanceof Node) {
\r
293 for (Spatial t : n.getChildren())
\r
298 private CollisionResults filterResults(CollisionResults results) {
\r
299 CollisionResults r = new TriangleCollisionResults();
\r
300 for (int i = 0; i < results.getNumber(); i++) {
\r
301 CollisionData d = results.getCollisionData(i);
\r
302 if (d.getSourceMesh() == d.getTargetMesh())
\r
304 boolean found = false;
\r
305 for (int j = 0; j < r.getNumber(); j++) {
\r
306 CollisionData d2 = r.getCollisionData(j);
\r
307 if (d2.getSourceMesh() == d.getSourceMesh() &&
\r
308 d2.getTargetMesh() == d.getTargetMesh()) {
\r
312 if (d2.getSourceMesh() == d.getTargetMesh() &&
\r
313 d2.getTargetMesh() == d.getSourceMesh()) {
\r
319 if (d.getSourceTris().size() == 0)
\r
321 if (d.getTargetTris().size() == 0)
\r
323 r.addCollisionData(d);
\r
330 checkInterferencesAction.setText("Interferences");
\r
331 checkInterferencesAction.setImageDescriptor(Activator.imageDescriptorFromPlugin("fi.vtt.proconf.ode", "icons/silk/delete.png"));
\r
336 public void run() {
\r