1 package org.simantics.processeditor.tools;
\r
3 import java.io.ByteArrayInputStream;
\r
4 import java.io.ByteArrayOutputStream;
\r
6 import java.util.ArrayList;
\r
7 import java.util.Collection;
\r
8 import java.util.List;
\r
10 import javax.vecmath.AxisAngle4d;
\r
11 import javax.vecmath.Point3d;
\r
12 import javax.vecmath.Quat4d;
\r
13 import javax.vecmath.Vector3d;
\r
15 import org.eclipse.core.runtime.FileLocator;
\r
16 import org.eclipse.core.runtime.Path;
\r
17 import org.eclipse.jface.action.IMenuManager;
\r
18 import org.eclipse.jface.action.IToolBarManager;
\r
19 import org.eclipse.swt.SWT;
\r
20 import org.eclipse.swt.events.SelectionAdapter;
\r
21 import org.eclipse.swt.events.SelectionEvent;
\r
22 import org.eclipse.swt.layout.FormAttachment;
\r
23 import org.eclipse.swt.layout.FormData;
\r
24 import org.eclipse.swt.layout.FormLayout;
\r
25 import org.eclipse.swt.layout.GridLayout;
\r
26 import org.eclipse.swt.widgets.Button;
\r
27 import org.eclipse.swt.widgets.Composite;
\r
28 import org.simantics.db.Graph;
\r
29 import org.simantics.db.GraphRequestAdapter;
\r
30 import org.simantics.db.GraphRequestStatus;
\r
31 import org.simantics.db.Resource;
\r
32 import org.simantics.processeditor.Activator;
\r
33 import org.simantics.processeditor.ProcessResource;
\r
34 import org.simantics.processeditor.common.PipeComponentProvider;
\r
35 import org.simantics.processeditor.stubs.DirectedControlPoint;
\r
36 import org.simantics.processeditor.stubs.PipeControlPoint;
\r
37 import org.simantics.proconf.g3d.actions.ContextAction;
\r
38 import org.simantics.proconf.g3d.base.EditorContribution;
\r
39 import org.simantics.proconf.g3d.base.G3DTools;
\r
40 import org.simantics.proconf.g3d.base.MathTools;
\r
41 import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;
\r
42 import org.simantics.proconf.g3d.base.VecmathJmeTools;
\r
43 import org.simantics.proconf.g3d.common.StructuredResourceSelection;
\r
44 import org.simantics.utils.ui.ErrorLogger;
\r
46 import com.jme.renderer.ColorRGBA;
\r
47 import com.jme.scene.Geometry;
\r
48 import com.jme.scene.Node;
\r
49 import com.jme.scene.Spatial;
\r
50 import com.jme.scene.TriMesh;
\r
51 import com.jme.scene.shape.Sphere;
\r
52 import com.jme.scene.state.MaterialState;
\r
53 import com.jme.util.export.Savable;
\r
54 import com.jme.util.export.binary.BinaryImporter;
\r
55 import com.jmex.model.converters.ObjToJme;
\r
58 public class ControlPointContribution implements EditorContribution {
\r
59 private List<ContextAction> actions = new ArrayList<ContextAction>();
\r
60 private ThreeDimensionalEditorBase parent;
\r
61 private Resource componentResource;
\r
62 private Resource controlPointResource;
\r
64 private Composite sideComposite;
\r
66 private double radius = 0.2;
\r
67 private double radius2 = 0.1;
\r
68 private double angle = Math.PI / 4.0;
\r
70 public ControlPointContribution(ThreeDimensionalEditorBase parent) {
\r
71 this.parent = parent;
\r
75 public void createControl(Composite parent) {
\r
76 FormLayout flayout = new FormLayout();
\r
77 parent.setLayout(flayout);
\r
78 sideComposite = new Composite(parent,SWT.BORDER);
\r
79 FormData data = new FormData();
\r
80 data.top = new FormAttachment(0, 0);
\r
81 data.left = new FormAttachment(0, 0);
\r
82 data.right = new FormAttachment(sideComposite, 0, SWT.LEFT);
\r
83 data.bottom = new FormAttachment(100,0);
\r
84 this.parent.getRenderingComposite().setLayoutData(data);
\r
85 GridLayout layout = new GridLayout(1,false);
\r
86 layout.marginHeight = 1;
\r
87 layout.marginWidth = 1;
\r
88 sideComposite.setLayout(layout);
\r
89 data = new FormData();
\r
90 data.top = new FormAttachment(0, 0);
\r
91 data.bottom = new FormAttachment(100,0);
\r
92 data.right = new FormAttachment(100,0);
\r
93 sideComposite.setLayoutData(data);
\r
95 Button showCPButton = new Button(sideComposite,SWT.TOGGLE);
\r
96 showCPButton.setText("Show CtrlPts");
\r
97 showCPButton.addSelectionListener(new SelectionAdapter() {
\r
99 public void widgetSelected(SelectionEvent e) {
\r
100 Button b = (Button)e.widget;
\r
101 showControlPoints(b.getSelection());
\r
105 Button addCPButton = new Button(sideComposite,SWT.PUSH);
\r
106 addCPButton.setText("Add CtrlPt");
\r
107 addCPButton.addSelectionListener(new SelectionAdapter() {
\r
109 public void widgetSelected(SelectionEvent e) {
\r
114 Button removeCPButton = new Button(sideComposite,SWT.PUSH);
\r
115 removeCPButton.setText("Remove CtrlPt");
\r
116 removeCPButton.addSelectionListener(new SelectionAdapter() {
\r
118 public void widgetSelected(SelectionEvent e) {
\r
123 Button showPipesButton = new Button(sideComposite,SWT.TOGGLE);
\r
124 showPipesButton.setText("Pipes");
\r
125 showPipesButton.addSelectionListener(new SelectionAdapter() {
\r
127 public void widgetSelected(SelectionEvent e) {
\r
128 Button b = (Button)e.widget;
\r
129 showPipes(b.getSelection());
\r
137 public void disposeControl() {
\r
138 sideComposite.dispose();
\r
142 public void fillContextMenu(Graph graph, IMenuManager manager,
\r
143 StructuredResourceSelection selection) {
\r
148 public void fillLocalPullDown(IMenuManager manager) {
\r
153 public void fillLocalToolBar(IToolBarManager manager) {
\r
158 public Collection<ContextAction> getActions() {
\r
163 public String getName() {
\r
164 return "Control Points";
\r
167 List<Node> pipes = new ArrayList<Node>();
\r
168 List<Node> controlPoints = new ArrayList<Node>();
\r
170 private void showPipes(boolean show) {
\r
172 if (!pipes.isEmpty()) {
\r
173 for (Node n : pipes) {
\r
174 n.removeFromParent();
\r
179 parent.getSession().asyncRead(new GraphRequestAdapter() {
\r
181 public GraphRequestStatus perform(Graph g) throws Exception {
\r
182 PipeControlPoint pcp = new PipeControlPoint(g,controlPointResource);
\r
183 if (pcp.isInstanceOf(ProcessResource.plant3Dresource.EndComponentControlPoint)) {
\r
184 Node n = new Node();
\r
185 TriMesh mesh = new TriMesh();
\r
186 Point3d p1 = new Point3d(-10.0,0.0,0.0);
\r
187 Point3d p2 = new Point3d( 0.0,0.0,0.0);
\r
188 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
189 n.attachChild(mesh);
\r
190 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
193 } else if (pcp.isInstanceOf(ProcessResource.plant3Dresource.DualInlineControlPoint)) {
\r
195 double length = 0.5;
\r
196 Double d = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength);
\r
200 double offset = 0.0;
\r
201 d = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasOffset);
\r
206 if (pcp.isInstanceOf(ProcessResource.plant3Dresource.SizeChangeControlPoint)) {
\r
210 Node n = new Node();
\r
211 TriMesh mesh = new TriMesh();
\r
212 Point3d p1 = new Point3d(-10.0,0.0,0.0);
\r
213 Point3d p2 = new Point3d( -length*0.5,0.0,0.0);
\r
215 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
216 n.attachChild(mesh);
\r
217 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
221 mesh = new TriMesh();
\r
222 p1 = new Point3d(10.0,offset,0.0);
\r
223 p2 = new Point3d(length*0.5,offset,0.0);
\r
225 PipeComponentProvider.createStraightGeometry(p1, p2, r, new Geometry[]{mesh});
\r
226 n.attachChild(mesh);
\r
227 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
230 } else if (pcp.isInstanceOf(ProcessResource.plant3Dresource.InlineControlPoint)) {
\r
231 double length = 0.5;
\r
232 Double d = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength);
\r
236 Node n = new Node();
\r
237 TriMesh mesh = new TriMesh();
\r
238 Point3d p1 = new Point3d(-10.0,0.0,0.0);
\r
239 Point3d p2 = new Point3d( -length*0.5,0.0,0.0);
\r
241 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
242 n.attachChild(mesh);
\r
243 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
247 mesh = new TriMesh();
\r
248 p1 = new Point3d(10.0,0.0,0.0);
\r
249 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
255 } else if (pcp.isInstanceOf(ProcessResource.plant3Dresource.TurnControlPoint)) {
\r
256 double length = 0.5;
\r
257 Double d = pcp.getAtMostOneRelatedScalarDouble(ProcessResource.plant3Dresource.HasLength);
\r
261 Node n = new Node();
\r
262 TriMesh mesh = new TriMesh();
\r
263 Point3d p1 = new Point3d(-10.0,0.0,0.0);
\r
264 Point3d p2 = new Point3d( -length*0.5,0.0,0.0);
\r
266 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
267 n.attachChild(mesh);
\r
268 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
272 mesh = new TriMesh();
\r
273 p1 = new Point3d(10.0,0.0,0.0);
\r
274 p2 = new Point3d(length*0.5,0.0,0.0);
\r
275 Quat4d q = new Quat4d();
\r
276 q.set(new AxisAngle4d(0.0,1.0,0.0,angle));
\r
277 MathTools.rotate(q, p1, p1);
\r
278 MathTools.rotate(q, p2, p2);
\r
280 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
281 n.attachChild(mesh);
\r
282 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
284 } else if (pcp.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint)) {
\r
285 Node n = new Node();
\r
286 TriMesh mesh = new TriMesh();
\r
287 Point3d p1 = new Point3d(10.0,0.0,0.0);
\r
288 Point3d p2 = new Point3d( 0.0,0.0,0.0);
\r
289 PipeComponentProvider.createStraightGeometry(p1, p2, radius, new Geometry[]{mesh});
\r
290 n.attachChild(mesh);
\r
291 parent.getRenderingComponent().getShadowRoot().attachChild(n);
\r
295 if(!pcp.isInstanceOf(ProcessResource.plant3Dresource.DualInlineControlPoint)) {
\r
296 Collection<PipeControlPoint> subPoints = pcp.getSubPoint();
\r
300 parent.setViewChanged(true);
\r
301 return GraphRequestStatus.transactionComplete();
\r
305 if (!pipes.isEmpty()) {
\r
306 for (Node n : pipes) {
\r
307 n.removeFromParent();
\r
311 parent.setViewChanged(true);
\r
316 private void showControlPoints(boolean show) {
\r
318 if (!controlPoints.isEmpty()) {
\r
319 for (Node n : controlPoints) {
\r
320 n.removeFromParent();
\r
325 parent.getSession().asyncRead(new GraphRequestAdapter() {
\r
327 public GraphRequestStatus perform(Graph g) throws Exception {
\r
329 PipeControlPoint pcp = new PipeControlPoint(g,controlPointResource);
\r
330 Vector3d p = G3DTools.getVector(pcp.getWorldPosition());
\r
331 Node n = new Node();
\r
332 Spatial sphere = new Sphere("",5,8,0.1f);
\r
333 n.attachChild(sphere);
\r
334 n.setLocalTranslation(VecmathJmeTools.get(p));
\r
335 MaterialState ms = parent.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
336 ms.setDiffuse(new ColorRGBA(1.f,0.f,0.f,0.f));
\r
337 sphere.setRenderState(ms);
\r
338 sphere.setName(Long.toString(pcp.getResource().getResourceId()));
\r
339 parent.getRenderingComponent().getNoShadowRoot().attachChild(n);
\r
340 controlPoints.add(n);
\r
341 Collection<PipeControlPoint> subPoints = pcp.getSubPoint();
\r
342 ms = parent.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
343 ms.setDiffuse(new ColorRGBA(0.f,1.f,0.f,0.f));
\r
344 for (PipeControlPoint cp : subPoints) {
\r
345 p = G3DTools.getVector(cp.getWorldPosition());
\r
347 if (cp.isInstanceOf(ProcessResource.plant3Dresource.DirectedControlPoint)) {
\r
348 sphere = getDCPMesh();
\r
349 if (sphere == null)
\r
350 sphere = new Sphere("",5,8,0.1f);
\r
352 sphere = new Sphere("",5,8,0.1f);
\r
354 sphere.setName(Long.toString(cp.getResource().getResourceId()));
\r
355 n.attachChild(sphere);
\r
356 n.setLocalTranslation(VecmathJmeTools.get(p));
\r
357 sphere.setRenderState(ms);
\r
358 parent.getRenderingComponent().getNoShadowRoot().attachChild(n);
\r
359 controlPoints.add(n);
\r
361 parent.setViewChanged(true);
\r
362 return GraphRequestStatus.transactionComplete();
\r
366 if (!controlPoints.isEmpty()) {
\r
367 for (Node n : controlPoints) {
\r
368 n.removeFromParent();
\r
371 parent.setViewChanged(true);
\r
377 public void initialize(Graph graph) {
\r
378 Resource modelResource = parent.getInputResource();
\r
379 Resource inverse = graph.getInverse(ProcessResource.plant3Dresource.HasGraphics);
\r
380 Collection<Resource> equipment = graph.getObjects(modelResource, inverse);
\r
381 if (equipment.size() != 1)
\r
382 throw new RuntimeException("Cannot find component for model " + modelResource);
\r
383 componentResource = equipment.iterator().next();
\r
384 Collection<Resource> pcp = graph.getObjects(componentResource, ProcessResource.plant3Dresource.HasControlPoint);
\r
385 if (pcp.size() != 1)
\r
386 throw new RuntimeException("Cannot find control point for component " + componentResource);
\r
387 controlPointResource = pcp.iterator().next();
\r
391 public void dispose() {
\r
396 public void run() {
\r
400 private void addControlPoint() {
\r
401 parent.getSession().asyncWrite(new GraphRequestAdapter() {
\r
403 public GraphRequestStatus perform(Graph g) throws Exception {
\r
404 DirectedControlPoint dcp = DirectedControlPoint.createDefault(g);
\r
405 PipeControlPoint pcp = new PipeControlPoint(g,controlPointResource);
\r
406 pcp.addStatement(ProcessResource.plant3Dresource.HasSubPoint, dcp);
\r
407 return GraphRequestStatus.transactionComplete();
\r
412 private Spatial getDCPMesh() {
\r
414 ObjToJme converter=new ObjToJme();
\r
415 String file = "data/dcp.obj";
\r
416 URL objFile=FileLocator.find(Activator.getDefault().getBundle(),new Path(file),null);
\r
417 converter.setProperty("mtllib",objFile);
\r
418 ByteArrayOutputStream BO=new ByteArrayOutputStream();
\r
419 //System.out.println("Starting to convert .obj to .jme");
\r
420 converter.convert(objFile.openStream(),BO);
\r
422 Savable s = BinaryImporter.getInstance().load(new ByteArrayInputStream(BO.toByteArray()));
\r
424 } catch (Exception e) {
\r
425 ErrorLogger.defaultLogError(e);
\r