1 package fi.vtt.simantics.processeditor.tools;
\r
3 import java.util.ArrayList;
\r
4 import java.util.Collection;
\r
5 import java.util.Iterator;
\r
6 import java.util.List;
\r
8 import org.eclipse.jface.action.Action;
\r
9 import org.eclipse.jface.action.IMenuManager;
\r
10 import org.eclipse.jface.action.IToolBarManager;
\r
11 import org.eclipse.jface.dialogs.MessageDialog;
\r
12 import org.eclipse.swt.SWT;
\r
13 import org.eclipse.swt.layout.FormAttachment;
\r
14 import org.eclipse.swt.layout.FormData;
\r
15 import org.eclipse.swt.layout.FormLayout;
\r
16 import org.eclipse.swt.layout.GridData;
\r
17 import org.eclipse.swt.layout.GridLayout;
\r
18 import org.eclipse.swt.widgets.Composite;
\r
19 import org.eclipse.swt.widgets.Text;
\r
20 import org.simantics.db.Graph;
\r
21 import org.simantics.db.GraphRequestStatus;
\r
22 import org.simantics.db.Resource;
\r
23 import org.simantics.layer0.utils.EntityFactory;
\r
24 import org.simantics.layer0.utils.IEntity;
\r
25 import org.simantics.proconf.g3d.actions.ContextAction;
\r
26 import org.simantics.proconf.g3d.actions.FocusAction;
\r
27 import org.simantics.proconf.g3d.actions.RemoveAction;
\r
28 import org.simantics.proconf.g3d.actions.RotateAction;
\r
29 import org.simantics.proconf.g3d.actions.TranslateAction;
\r
30 import org.simantics.proconf.g3d.base.EditorContribution;
\r
31 import org.simantics.proconf.g3d.common.StructuredResourceSelection;
\r
32 import org.simantics.utils.ui.jface.MenuTools;
\r
34 import com.jme.intersection.CollisionData;
\r
35 import com.jme.intersection.CollisionResults;
\r
36 import com.jme.intersection.TriangleCollisionResults;
\r
37 import com.jme.scene.Geometry;
\r
38 import com.jme.scene.Node;
\r
39 import com.jme.scene.Spatial;
\r
41 import fi.vtt.simantics.processeditor.Activator;
\r
42 import fi.vtt.simantics.processeditor.ProcessResource;
\r
43 import fi.vtt.simantics.processeditor.actions.InsertComponentAction;
\r
44 import fi.vtt.simantics.processeditor.actions.InsertEquipmentAction;
\r
45 import fi.vtt.simantics.processeditor.actions.InsertNozzleAction;
\r
46 import fi.vtt.simantics.processeditor.actions.ReversePipelineAction;
\r
47 import fi.vtt.simantics.processeditor.actions.RoutePipeAction;
\r
48 import fi.vtt.simantics.processeditor.actions.TranslateElbowAction;
\r
49 import fi.vtt.simantics.processeditor.actions.TranslateInlineComponentAction;
\r
50 import fi.vtt.simantics.processeditor.actions.TranslateStraightAction;
\r
51 import fi.vtt.simantics.processeditor.common.ControlPointTools;
\r
52 import fi.vtt.simantics.processeditor.stubs.InlineComponent;
\r
53 import fi.vtt.simantics.processeditor.stubs.PipeControlPoint;
\r
54 import fi.vtt.simantics.processeditor.views.ProcessEditor;
\r
56 public class PlantEditContribution implements EditorContribution {
\r
57 private List<ContextAction> actions = new ArrayList<ContextAction>();
\r
58 private ProcessEditor parent;
\r
59 private Composite infoComposite;
\r
60 private Text infoText;
\r
62 private Action checkInterferencesAction = null;
\r
64 public PlantEditContribution(ProcessEditor parent) {
\r
65 this.parent = parent;
\r
69 public void createControl(Composite parent) {
\r
70 FormLayout flayout = new FormLayout();
\r
71 parent.setLayout(flayout);
\r
72 infoComposite = new Composite(parent, SWT.BORDER);
\r
73 FormData data = new FormData();
\r
74 data.top = new FormAttachment(0, 0);
\r
75 data.left = new FormAttachment(0, 0);
\r
76 data.right = new FormAttachment(100, 0);
\r
77 data.bottom = new FormAttachment(infoComposite, 0, SWT.TOP);
\r
78 this.parent.getRenderingComposite().setLayoutData(data);
\r
79 data = new FormData();
\r
80 data.left = new FormAttachment(0, 0);
\r
81 data.right = new FormAttachment(100, 0);
\r
82 data.bottom = new FormAttachment(100, 0);
\r
84 infoComposite.setLayoutData(data);
\r
85 GridLayout layout = new GridLayout(1,false);
\r
86 layout.marginWidth = 1;
\r
87 layout.marginHeight = 1;
\r
88 infoComposite.setLayout(layout);
\r
89 infoText = new Text(infoComposite, SWT.NONE);
\r
90 GridData gdata = new GridData();
\r
91 gdata.grabExcessHorizontalSpace = true;
\r
92 gdata.horizontalAlignment = SWT.FILL;
\r
93 infoText.setLayoutData(gdata);
\r
98 public void disposeControl() {
\r
99 infoComposite.dispose();
\r
104 public void dispose() {
\r
111 public void fillContextMenu(Graph graph, IMenuManager manager,
\r
112 StructuredResourceSelection selection) {
\r
117 public void fillLocalPullDown(IMenuManager manager) {
\r
118 MenuTools.getOrCreate(parent.getMenuID(),"Advanced", manager).add(checkInterferencesAction);
\r
123 public void fillLocalToolBar(IToolBarManager manager) {
\r
128 public Collection<ContextAction> getActions() {
\r
133 public String getName() {
\r
134 return "Plant Editing";
\r
138 public void initialize(Graph graph) {
\r
139 actions.add(new TranslateAction(parent){
\r
141 public boolean usable(Graph graph,List<Resource> resources) {
\r
142 if (super.usable(graph, resources)) {
\r
143 for (Resource r : resources) {
\r
144 // FIXME : use new ontology :
\r
145 // 1. lose ends works like end components (just what this code does, but type checks are not correct)
\r
146 // 2. connected components are moved inline. (TranslateInlineAction)
\r
147 IEntity t = EntityFactory.create(graph, r);
\r
148 if (t.isInstanceOf(ProcessResource.plant3Dresource.InlineComponent)) {
\r
149 InlineComponent component = new InlineComponent(t);
\r
150 PipeControlPoint pcp = component.getControlPoint();
\r
151 if (pcp.getNext() != null && pcp.getPrevious() != null)
\r
161 public void setInfoText(String text) {
\r
162 infoText.setText(text);
\r
165 actions.add(new TranslateInlineComponentAction(parent) {
\r
167 public void setInfoText(String text) {
\r
168 infoText.setText(text);
\r
171 actions.add(new TranslateStraightAction(parent) {
\r
173 public void setInfoText(String text) {
\r
174 infoText.setText(text);
\r
177 actions.add(new TranslateElbowAction(parent) {
\r
179 public void setInfoText(String text) {
\r
180 infoText.setText(text);
\r
183 actions.add(new RotateAction(parent){
\r
185 public boolean usable(Graph graph,List<Resource> resources) {
\r
186 if (super.usable(graph,resources)) {
\r
187 for (Resource r : resources) {
\r
188 IEntity t = EntityFactory.create(graph,r);
\r
189 // FIXME : use new ontology
\r
190 // TODO : create rotate action that can rotate inline components
\r
191 // TODO : ontology change: pipes and similar components cannot be rotated, since there is no point to do that.
\r
192 if (t.isInstanceOf(ProcessResource.plant3Dresource.InlineComponent)) {
\r
203 public void setInfoText(String text) {
\r
204 infoText.setText(text);
\r
207 actions.add(new RemoveAction(parent) {
\r
209 public GraphRequestStatus doChanges(Graph graph) {
\r
210 Iterator<Resource> i = parent.getSelectionAdapter().getCurrentSelection().iterator();
\r
211 while (i.hasNext()) {
\r
212 Resource s = i.next();
\r
213 IEntity r = EntityFactory.create(graph, s);
\r
214 if (r.isInstanceOf(ProcessResource.g3dResource.G3DNode)) {
\r
215 Collection<IEntity> parentNode= r.getRelatedObjects(ProcessResource.g3dResource.HasParent);
\r
216 if (parentNode.size() == 1) {
\r
217 Collection<IEntity> rs = r.getRelatedObjects(ProcessResource.plant3Dresource.HasControlPoint);
\r
218 for (IEntity cp : rs) {
\r
219 ControlPointTools.removeControlPoint(new PipeControlPoint(cp));
\r
221 r.removeRelatedStatements(ProcessResource.g3dResource.HasParent);
\r
223 if (parentNode.size() == 0) {
\r
224 parent.showMessage("Object has no parent, don't know what to do!");
\r
226 parent.showMessage("Object has more than one parent, don't know what to do!");
\r
232 //parent.getSelectionAdapter().setSelection(new StructuredResourceSelection());
\r
233 return GraphRequestStatus.transactionComplete();
\r
236 actions.add(new FocusAction(parent));
\r
237 actions.add(new RoutePipeAction(parent){
\r
239 public void setInfoText(String text) {
\r
240 infoText.setText(text);
\r
243 actions.add(new InsertComponentAction(parent));
\r
244 actions.add(new InsertEquipmentAction(parent));
\r
245 actions.add(new InsertNozzleAction(parent));
\r
246 actions.add(new ReversePipelineAction(parent));
\r
248 checkInterferencesAction = new Action() {
\r
249 public void run() {
\r
250 CollisionResults results = new TriangleCollisionResults();
\r
251 //getRenderingComponent().getNormalRoot().calculateCollisions(getRenderingComponent().getNormalRoot(), results);
\r
252 collide(parent.getRenderingComponent().getShadowRoot(),parent.getRenderingComponent().getShadowRoot(),results);
\r
253 results = filterResults(results);
\r
254 for (int i = 0; i < results.getNumber(); i++) {
\r
255 CollisionData data = results.getCollisionData(i);
\r
256 Geometry s = data.getSourceMesh();
\r
257 Geometry t = data.getTargetMesh();
\r
258 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
260 Resource sid = parent.getScenegraphAdapter().getNodeResource(s.getName());
\r
261 Resource tid = parent.getScenegraphAdapter().getNodeResource(t.getName());
\r
263 StructuredResourceSelection sel = new StructuredResourceSelection();
\r
270 parent.getSelectionAdapter().setSelection(sel);
\r
271 } catch(NumberFormatException e) {
\r
274 if (dialog.open() == 1)
\r
279 private void collide(Spatial s, Spatial p, CollisionResults r) {
\r
280 s.calculateCollisions(p, r);
\r
281 if (s instanceof Node) {
\r
283 for (Spatial t : n.getChildren())
\r
288 private CollisionResults filterResults(CollisionResults results) {
\r
289 CollisionResults r = new TriangleCollisionResults();
\r
290 for (int i = 0; i < results.getNumber(); i++) {
\r
291 CollisionData d = results.getCollisionData(i);
\r
292 if (d.getSourceMesh() == d.getTargetMesh())
\r
294 boolean found = false;
\r
295 for (int j = 0; j < r.getNumber(); j++) {
\r
296 CollisionData d2 = r.getCollisionData(j);
\r
297 if (d2.getSourceMesh() == d.getSourceMesh() &&
\r
298 d2.getTargetMesh() == d.getTargetMesh()) {
\r
302 if (d2.getSourceMesh() == d.getTargetMesh() &&
\r
303 d2.getTargetMesh() == d.getSourceMesh()) {
\r
309 if (d.getSourceTris().size() == 0)
\r
311 if (d.getTargetTris().size() == 0)
\r
313 r.addCollisionData(d);
\r
320 checkInterferencesAction.setText("Interferences");
\r
321 checkInterferencesAction.setImageDescriptor(Activator.imageDescriptorFromPlugin("fi.vtt.proconf.ode", "icons/silk/delete.png"));
\r
326 public void run() {
\r