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.io.ByteArrayInputStream;
\r
14 import java.io.ByteArrayOutputStream;
\r
15 import java.net.URL;
\r
16 import java.util.ArrayList;
\r
17 import java.util.Collection;
\r
18 import java.util.List;
\r
20 import javax.vecmath.AxisAngle4d;
\r
21 import javax.vecmath.Point3d;
\r
22 import javax.vecmath.Quat4d;
\r
23 import javax.vecmath.Vector3d;
\r
25 import org.eclipse.core.runtime.FileLocator;
\r
26 import org.eclipse.core.runtime.Path;
\r
27 import org.eclipse.jface.action.IMenuManager;
\r
28 import org.eclipse.jface.action.IToolBarManager;
\r
29 import org.eclipse.swt.SWT;
\r
30 import org.eclipse.swt.events.SelectionAdapter;
\r
31 import org.eclipse.swt.events.SelectionEvent;
\r
32 import org.eclipse.swt.layout.FormAttachment;
\r
33 import org.eclipse.swt.layout.FormData;
\r
34 import org.eclipse.swt.layout.FormLayout;
\r
35 import org.eclipse.swt.layout.GridLayout;
\r
36 import org.eclipse.swt.widgets.Button;
\r
37 import org.eclipse.swt.widgets.Composite;
\r
38 import org.simantics.db.Graph;
\r
39 import org.simantics.db.GraphRequestAdapter;
\r
40 import org.simantics.db.GraphRequestStatus;
\r
41 import org.simantics.db.Resource;
\r
42 import org.simantics.processeditor.Activator;
\r
43 import org.simantics.processeditor.ProcessResource;
\r
44 import org.simantics.processeditor.common.PipeComponentProvider;
\r
45 import org.simantics.processeditor.stubs.DirectedControlPoint;
\r
46 import org.simantics.processeditor.stubs.PipeControlPoint;
\r
47 import org.simantics.proconf.g3d.actions.ContextAction;
\r
48 import org.simantics.proconf.g3d.base.EditorContribution;
\r
49 import org.simantics.proconf.g3d.base.G3DTools;
\r
50 import org.simantics.proconf.g3d.base.MathTools;
\r
51 import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;
\r
52 import org.simantics.proconf.g3d.base.VecmathJmeTools;
\r
53 import org.simantics.proconf.g3d.common.StructuredResourceSelection;
\r
54 import org.simantics.utils.ui.ErrorLogger;
\r
56 import com.jme.renderer.ColorRGBA;
\r
57 import com.jme.scene.Geometry;
\r
58 import com.jme.scene.Node;
\r
59 import com.jme.scene.Spatial;
\r
60 import com.jme.scene.TriMesh;
\r
61 import com.jme.scene.shape.Sphere;
\r
62 import com.jme.scene.state.MaterialState;
\r
63 import com.jme.util.export.Savable;
\r
64 import com.jme.util.export.binary.BinaryImporter;
\r
65 import com.jmex.model.converters.ObjToJme;
\r
68 public class ControlPointContribution implements EditorContribution {
\r
69 private List<ContextAction> actions = new ArrayList<ContextAction>();
\r
70 private ThreeDimensionalEditorBase parent;
\r
71 private Resource componentResource;
\r
72 private Resource controlPointResource;
\r
74 private Composite sideComposite;
\r
76 private double radius = 0.2;
\r
77 private double radius2 = 0.1;
\r
78 private double angle = Math.PI / 4.0;
\r
80 public ControlPointContribution(ThreeDimensionalEditorBase parent) {
\r
81 this.parent = parent;
\r
85 public void createControl(Composite parent) {
\r
86 FormLayout flayout = new FormLayout();
\r
87 parent.setLayout(flayout);
\r
88 sideComposite = new Composite(parent,SWT.BORDER);
\r
89 FormData data = new FormData();
\r
90 data.top = new FormAttachment(0, 0);
\r
91 data.left = new FormAttachment(0, 0);
\r
92 data.right = new FormAttachment(sideComposite, 0, SWT.LEFT);
\r
93 data.bottom = new FormAttachment(100,0);
\r
94 this.parent.getRenderingComposite().setLayoutData(data);
\r
95 GridLayout layout = new GridLayout(1,false);
\r
96 layout.marginHeight = 1;
\r
97 layout.marginWidth = 1;
\r
98 sideComposite.setLayout(layout);
\r
99 data = new FormData();
\r
100 data.top = new FormAttachment(0, 0);
\r
101 data.bottom = new FormAttachment(100,0);
\r
102 data.right = new FormAttachment(100,0);
\r
103 sideComposite.setLayoutData(data);
\r
105 Button showCPButton = new Button(sideComposite,SWT.TOGGLE);
\r
106 showCPButton.setText("Show CtrlPts");
\r
107 showCPButton.addSelectionListener(new SelectionAdapter() {
\r
109 public void widgetSelected(SelectionEvent e) {
\r
110 Button b = (Button)e.widget;
\r
111 showControlPoints(b.getSelection());
\r
115 Button addCPButton = new Button(sideComposite,SWT.PUSH);
\r
116 addCPButton.setText("Add CtrlPt");
\r
117 addCPButton.addSelectionListener(new SelectionAdapter() {
\r
119 public void widgetSelected(SelectionEvent e) {
\r
124 Button removeCPButton = new Button(sideComposite,SWT.PUSH);
\r
125 removeCPButton.setText("Remove CtrlPt");
\r
126 removeCPButton.addSelectionListener(new SelectionAdapter() {
\r
128 public void widgetSelected(SelectionEvent e) {
\r
133 Button showPipesButton = new Button(sideComposite,SWT.TOGGLE);
\r
134 showPipesButton.setText("Pipes");
\r
135 showPipesButton.addSelectionListener(new SelectionAdapter() {
\r
137 public void widgetSelected(SelectionEvent e) {
\r
138 Button b = (Button)e.widget;
\r
139 showPipes(b.getSelection());
\r
147 public void disposeControl() {
\r
148 sideComposite.dispose();
\r
152 public void fillContextMenu(Graph graph, IMenuManager manager,
\r
153 StructuredResourceSelection selection) {
\r
158 public void fillLocalPullDown(IMenuManager manager) {
\r
163 public void fillLocalToolBar(IToolBarManager manager) {
\r
168 public Collection<ContextAction> getActions() {
\r
173 public String getName() {
\r
174 return "Control Points";
\r
177 List<Node> pipes = new ArrayList<Node>();
\r
178 List<Node> controlPoints = new ArrayList<Node>();
\r
180 private void showPipes(boolean show) {
\r
182 if (!pipes.isEmpty()) {
\r
183 for (Node n : pipes) {
\r
184 n.removeFromParent();
\r
189 parent.getSession().asyncRead(new GraphRequestAdapter() {
\r
191 public GraphRequestStatus perform(Graph g) throws Exception {
\r
192 PipeControlPoint pcp = new PipeControlPoint(g,controlPointResource);
\r
193 if (pcp.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {
\r
194 Node n = new Node();
\r
195 TriMesh mesh = new TriMesh();
\r
196 Point3d p1 = new Point3d(-10.0,0.0,0.0);
\r
197 Point3d p2 = new Point3d( 0.0,0.0,0.0);
\r
198 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
199 n.attachChild(mesh);
\r
200 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
203 } else if (pcp.isInstanceOf(ProcessResource.plant3Dresource.DualInlineControlPoint)) {
\r
205 double length = 0.5;
\r
206 Double d = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength);
\r
210 double offset = 0.0;
\r
211 d = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasOffset);
\r
216 if (pcp.isInstanceOf(ProcessResource.plant3Dresource.SizeChangeControlPoint)) {
\r
220 Node n = new Node();
\r
221 TriMesh mesh = new TriMesh();
\r
222 Point3d p1 = new Point3d(-10.0,0.0,0.0);
\r
223 Point3d p2 = new Point3d( -length*0.5,0.0,0.0);
\r
225 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
226 n.attachChild(mesh);
\r
227 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
231 mesh = new TriMesh();
\r
232 p1 = new Point3d(10.0,offset,0.0);
\r
233 p2 = new Point3d(length*0.5,offset,0.0);
\r
235 PipeComponentProvider.createStraightGeometry(p1, p2, r, new Geometry[]{mesh});
\r
236 n.attachChild(mesh);
\r
237 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
240 } else if (pcp.isInstanceOf(ProcessResource.plant3Dresource.InlineControlPoint)) {
\r
241 double length = 0.5;
\r
242 Double d = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength);
\r
246 Node n = new Node();
\r
247 TriMesh mesh = new TriMesh();
\r
248 Point3d p1 = new Point3d(-10.0,0.0,0.0);
\r
249 Point3d p2 = new Point3d( -length*0.5,0.0,0.0);
\r
251 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
252 n.attachChild(mesh);
\r
253 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
257 mesh = new TriMesh();
\r
258 p1 = new Point3d(10.0,0.0,0.0);
\r
259 p2 = new Point3d(length*0.5,0.0,0.0);
\r
261 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
262 n.attachChild(mesh);
\r
263 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
265 } else if (pcp.isInstanceOf(ProcessResource.plant3Dresource.TurnControlPoint)) {
\r
266 double length = 0.5;
\r
267 Double d = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength);
\r
271 Node n = new Node();
\r
272 TriMesh mesh = new TriMesh();
\r
273 Point3d p1 = new Point3d(-10.0,0.0,0.0);
\r
274 Point3d p2 = new Point3d( -length*0.5,0.0,0.0);
\r
276 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
277 n.attachChild(mesh);
\r
278 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
282 mesh = new TriMesh();
\r
283 p1 = new Point3d(10.0,0.0,0.0);
\r
284 p2 = new Point3d(length*0.5,0.0,0.0);
\r
285 Quat4d q = new Quat4d();
\r
286 q.set(new AxisAngle4d(0.0,1.0,0.0,angle));
\r
287 MathTools.rotate(q, p1, p1);
\r
288 MathTools.rotate(q, p2, p2);
\r
290 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
291 n.attachChild(mesh);
\r
292 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
294 } else if (pcp.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint)) {
\r
295 Node n = new Node();
\r
296 TriMesh mesh = new TriMesh();
\r
297 Point3d p1 = new Point3d(10.0,0.0,0.0);
\r
298 Point3d p2 = new Point3d( 0.0,0.0,0.0);
\r
299 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
300 n.attachChild(mesh);
\r
301 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
305 if(!pcp.isInstanceOf(ProcessResource.plant3Dresource.DualInlineControlPoint)) {
\r
306 Collection<PipeControlPoint> subPoints = pcp.getSubPoint();
\r
310 parent.setViewChanged(true);
\r
311 return GraphRequestStatus.transactionComplete();
\r
315 if (!pipes.isEmpty()) {
\r
316 for (Node n : pipes) {
\r
317 n.removeFromParent();
\r
321 parent.setViewChanged(true);
\r
326 private void showControlPoints(boolean show) {
\r
328 if (!controlPoints.isEmpty()) {
\r
329 for (Node n : controlPoints) {
\r
330 n.removeFromParent();
\r
335 parent.getSession().asyncRead(new GraphRequestAdapter() {
\r
337 public GraphRequestStatus perform(Graph g) throws Exception {
\r
339 PipeControlPoint pcp = new PipeControlPoint(g,controlPointResource);
\r
340 Vector3d p = G3DTools.getVector(pcp.getWorldPosition());
\r
341 Node n = new Node();
\r
342 Spatial sphere = new Sphere("",5,8,0.1f);
\r
343 n.attachChild(sphere);
\r
344 n.setLocalTranslation(VecmathJmeTools.get(p));
\r
345 MaterialState ms = parent.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
346 ms.setDiffuse(new ColorRGBA(1.f,0.f,0.f,0.f));
\r
347 sphere.setRenderState(ms);
\r
348 sphere.setName(Long.toString(pcp.getResource().getResourceId()));
\r
349 parent.getRenderingComponent().getNoShadowRoot().attachChild(n);
\r
350 controlPoints.add(n);
\r
351 Collection<PipeControlPoint> subPoints = pcp.getSubPoint();
\r
352 ms = parent.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
353 ms.setDiffuse(new ColorRGBA(0.f,1.f,0.f,0.f));
\r
354 for (PipeControlPoint cp : subPoints) {
\r
355 p = G3DTools.getVector(cp.getWorldPosition());
\r
357 if (cp.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint)) {
\r
358 sphere = getDCPMesh();
\r
359 if (sphere == null)
\r
360 sphere = new Sphere("",5,8,0.1f);
\r
362 sphere = new Sphere("",5,8,0.1f);
\r
364 sphere.setName(Long.toString(cp.getResource().getResourceId()));
\r
365 n.attachChild(sphere);
\r
366 n.setLocalTranslation(VecmathJmeTools.get(p));
\r
367 sphere.setRenderState(ms);
\r
368 parent.getRenderingComponent().getNoShadowRoot().attachChild(n);
\r
369 controlPoints.add(n);
\r
371 parent.setViewChanged(true);
\r
372 return GraphRequestStatus.transactionComplete();
\r
376 if (!controlPoints.isEmpty()) {
\r
377 for (Node n : controlPoints) {
\r
378 n.removeFromParent();
\r
381 parent.setViewChanged(true);
\r
387 public void initialize(Graph graph) {
\r
388 Resource modelResource = parent.getInputResource();
\r
389 Resource inverse = graph.getInverse(ProcessResource.plant3Dresource.HasGraphics);
\r
390 Collection<Resource> equipment = graph.getObjects(modelResource, inverse);
\r
391 if (equipment.size() != 1)
\r
392 throw new RuntimeException("Cannot find component for model " + modelResource);
\r
393 componentResource = equipment.iterator().next();
\r
394 Collection<Resource> pcp = graph.getObjects(componentResource, ProcessResource.plant3Dresource.HasControlPoint);
\r
395 if (pcp.size() != 1)
\r
396 throw new RuntimeException("Cannot find control point for component " + componentResource);
\r
397 controlPointResource = pcp.iterator().next();
\r
401 public void dispose() {
\r
406 public void run() {
\r
410 private void addControlPoint() {
\r
411 parent.getSession().asyncWrite(new GraphRequestAdapter() {
\r
413 public GraphRequestStatus perform(Graph g) throws Exception {
\r
414 DirectedControlPoint dcp = DirectedControlPoint.createDefault(g);
\r
415 PipeControlPoint pcp = new PipeControlPoint(g,controlPointResource);
\r
416 pcp.addStatement(ProcessResource.plant3Dresource.HasSubPoint, dcp);
\r
417 return GraphRequestStatus.transactionComplete();
\r
422 private Spatial getDCPMesh() {
\r
424 ObjToJme converter=new ObjToJme();
\r
425 String file = "data/dcp.obj";
\r
426 URL objFile=FileLocator.find(Activator.getDefault().getBundle(),new Path(file),null);
\r
427 converter.setProperty("mtllib",objFile);
\r
428 ByteArrayOutputStream BO=new ByteArrayOutputStream();
\r
429 //System.out.println("Starting to convert .obj to .jme");
\r
430 converter.convert(objFile.openStream(),BO);
\r
432 Savable s = BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
\r
434 } catch (Exception e) {
\r
435 ErrorLogger.defaultLogError(e);
\r