]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/TranslateAction.java
32274f037864573f1afaef25cf33211133aad318
[simantics/3d.git] / org.simantics.g3d.vtk / src / org / simantics / g3d / vtk / swt / TranslateAction.java
1 /*******************************************************************************
2  * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.g3d.vtk.swt;
13
14 import java.awt.event.KeyEvent;
15 import java.awt.event.MouseEvent;
16 import java.math.BigDecimal;
17
18 import javax.vecmath.AxisAngle4d;
19 import javax.vecmath.Point3d;
20 import javax.vecmath.Quat4d;
21 import javax.vecmath.Vector3d;
22
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.graphics.Cursor;
25 import org.eclipse.swt.widgets.Display;
26 import org.simantics.g3d.math.MathTools;
27 import org.simantics.g3d.math.Ray;
28 import org.simantics.g3d.scenegraph.IG3DNode;
29 import org.simantics.g3d.scenegraph.structural.IStructuralNode;
30 import org.simantics.g3d.vtk.Activator;
31 import org.simantics.g3d.vtk.common.VTKNodeMap;
32 import org.simantics.g3d.vtk.gizmo.TranslateAxisGizmo;
33 import org.simantics.g3d.vtk.utils.vtkUtil;
34 import org.simantics.utils.threads.AWTThread;
35 import org.simantics.utils.threads.ThreadUtils;
36
37 import vtk.vtkProp;
38
39 public class TranslateAction extends vtkSwtAction{
40         
41         public static final int X = 0;
42     public static final int Y = 1;
43     public static final int Z = 2;
44     public static final int XY = 3;
45     public static final int XZ = 4;
46     public static final int YZ = 5;
47     public static final int P = 6;
48
49         private VTKNodeMap nodeMap;
50         //private TranslateGizmo  gizmo = new TranslateGizmo();
51         private TranslateAxisGizmo gizmo = new TranslateAxisGizmo();
52         protected IG3DNode node;
53         
54         
55         
56         private Cursor activeCursor;// = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
57         private Cursor dragCursor;// = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
58         
59         public void setNode(IG3DNode node) {
60                 this.node = node;
61                 if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot()) {
62                         setEnabled(false);
63                 } else {
64                         setEnabled(true);
65                 }
66         }
67         
68         public IG3DNode getNode() {
69                 return node;
70         }
71         
72         public TranslateAction(InteractiveVtkComposite panel, VTKNodeMap nodeMap) {
73                 super(panel);
74                 setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_out.png"));
75                 setText("Translate");
76                 this.nodeMap = nodeMap;
77                 
78                 activeCursor = Display.getCurrent().getSystemCursor(SWT.CURSOR_HAND);
79         dragCursor = Display.getCurrent().getSystemCursor(SWT.CURSOR_SIZEALL);
80         }
81         
82         public void attach() {
83                 if (node == null)
84                         return;
85                 
86                 super.attach();
87                 ThreadUtils.asyncExec(panel.getThreadQueue(), new Runnable() {
88                         public void run() {
89                                 attachUI();
90                                 update();
91                         }
92                 });
93                 
94                 
95                 
96         }
97         
98         public void deattach() {
99                 
100                 node = null;
101                 nodeMap.commit();
102                 deattachUI();
103                 super.deattach();
104                 panel.refresh();
105         }
106         
107         private void attachUI() {
108                 panel.getComponent().setCursor(activeCursor);
109                 gizmo.attach(panel);
110         }
111         
112         private void deattachUI() {
113                 panel.getComponent().setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_ARROW));
114                 gizmo.deattach();
115         }
116         
117         @Override
118         public boolean keyPressed(KeyEvent e) {
119                 if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
120                         panel.useDefaultAction();
121                 if (valid)
122                         return true;
123                 if (e.getKeyCode() == KeyEvent.VK_X) {
124                         if (index != X)
125                                 index = X;
126                         else
127                                 index = P;
128                 }
129                 if (e.getKeyCode() == KeyEvent.VK_Y) {
130                         if (index != Y)
131                                 index = Y;
132                         else
133                                 index = P;
134                 }
135                 if (e.getKeyCode() == KeyEvent.VK_Z) {
136                         if (index != Z)
137                                 index = Z;
138                         else
139                                 index = P;
140                 }
141                 if (e.getKeyCode() == KeyEvent.VK_G) {
142                         worldCoord = !worldCoord;
143                 }
144                 gizmo.setType(index);
145                 
146                 update();
147                 //panel.repaint();
148                 return true;
149         }
150         
151
152         
153         @Override
154         public boolean mouseClicked(MouseEvent e) {
155                 if (e.getClickCount() > 1) {
156                         if (isOverNode(e)) {
157                                 return true;
158                         } else {
159                                 panel.useDefaultAction();
160                         }
161                         //if(!gizmo.isPartOf(actor))
162                         //      panel.useDefaultAction();
163                         return true;
164                 }
165                 return false;
166         }
167         
168         private boolean isOverNode(MouseEvent e) {
169                 vtkProp picked[] = panel.pick(e.getX(), e.getY());
170                 if (picked !=null) {
171                         for (int i = 0; i < picked.length; i++) {
172                                 if (node.equals(nodeMap.getNode(picked[i])))
173                                         return true;
174                         }
175                 }
176                 return false;
177         }
178         
179         
180         int index = P;
181         protected boolean valid = false;
182         private boolean worldCoord = true;
183         private AxisAngle4d aa = null;
184         private Quat4d q = null;
185         
186         
187         public void setWorldCoord(boolean b) {
188                 if (worldCoord == b)
189                         return;
190                 worldCoord = b;
191                 update();
192                                         
193         }
194         
195         
196         protected void update() {
197                 if (node == null)
198                         return;
199                 if (worldCoord) {
200                         gizmo.setRotation(new AxisAngle4d());
201                         aa = null;
202                         q = null;
203                 } else {
204                         aa = new AxisAngle4d();
205                         aa.set(((IG3DNode)node.getParent()).getWorldOrientation());
206                         gizmo.setRotation(aa);
207                         q = new Quat4d();
208                         MathTools.getQuat(aa, q);
209                 }
210                 
211                 Vector3d nodePos = node.getWorldPosition();
212                 //System.out.println(nodePos);
213                 gizmo.setPosition(nodePos);
214
215                 
216                 Point3d camPos = new Point3d(panel.getRenderer().GetActiveCamera().GetPosition());
217                 Vector3d p = new Vector3d(nodePos);
218                 p.sub(camPos);
219                 
220                 if (q != null) {
221                         Quat4d qi = new Quat4d(q);
222                         qi.inverse();
223                         MathTools.rotate(q, p, p);
224                 }
225                 if (panel.getRenderer().GetActiveCamera().GetParallelProjection() == 0) {
226                         double distance = p.length();
227                         p.negate();
228             double fov = panel.getRenderer().GetActiveCamera().GetViewAngle();
229             float s = (float) (Math.sin(fov) * distance * 0.1); 
230
231             Vector3d scale = new Vector3d(1., 1., 1.);
232             
233 //            if (p.x > 0.f)
234 //                scale.x = -1.;
235 //            if (p.y > 0.f)
236 //                scale.y = -1.;
237 //            if (p.z > 0.f)
238 //                scale.z = -1.;
239             scale.scale(s);
240             gizmo.setScale(scale);
241                         
242                 } else {
243                         Vector3d scale = new Vector3d(1.f, 1.f, 1.f);
244             double s = panel.getRenderer().GetActiveCamera().GetParallelScale() / 5.;
245 //            if (p.x > 0.f)
246 //                scale.x = -1.;
247 //            if (p.y > 0.f)
248 //                scale.y = -1.;
249 //            if (p.z > 0.f)
250 //                scale.z = -1.;
251             scale.scale(s);
252             gizmo.setScale(scale);
253                 }
254                 
255                 //panel.Render();
256                 panel.refresh();
257         }
258         
259         protected Vector3d prevTranslate = null;
260         
261         @Override
262         public boolean mousePressed(MouseEvent e) {
263                 if (e.getButton() == MouseEvent.BUTTON1) {
264
265                         if (isOverNode(e)) {
266                                 prevTranslate = getTranslate(e.getX(), e.getY());
267                                 valid = true;
268                                 panel.getComponent().setCursor(dragCursor);
269                         } else {
270                                 valid = false;
271                                 getDefaultAction().mousePressed(e);
272                                 panel.getComponent().setCursor(activeCursor);
273                         }
274                 } else {
275                         getDefaultAction().mousePressed(e);
276                 }
277                 return true;
278                 //index = gizmo.getTranslateAxis(actor);
279                 //if (index == -1) {
280                 //  valid = false;
281                 //      panel.getDefaultAction().mousePressed(e);
282                 //      return;
283                 //}
284                 //valid = true; 
285                 //prevTranslate = getTranslate(e.getX(), e.getY());
286                 //System.out.println("start translate " + prevTranslate);
287         }
288         
289         
290         
291         @Override
292         public boolean mouseReleased(MouseEvent e) {
293                 if (e.getButton() == MouseEvent.BUTTON1) {
294                         valid = false;
295                         prevTranslate = null;
296                         panel.getComponent().setCursor(activeCursor);
297                 } else {
298                         getDefaultAction().mouseReleased(e);
299                 }
300                 return true;
301         }
302         
303         @Override
304         public boolean mouseDragged(MouseEvent e) {
305                 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0 && valid) { 
306                         
307                         Vector3d translate = getTranslate(e.getX(), e.getY(), prevTranslate);
308                         //System.out.println("translate " + translate);
309                         if (translate == null)
310                                 return true;
311                         boolean step = ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0);
312                         if (worldCoord) {
313                                 Vector3d pos = new Vector3d(node.getWorldPosition());
314                                 pos.add(translate);
315                                 pos = constaints(pos, step);
316                                 setWorldPos(pos);
317                         } else {
318                                 Vector3d pos = new Vector3d(node.getPosition());
319                                 pos.add(translate);
320                                 pos = constaints(pos, step);
321                                 setPos(pos);
322                         }
323                         //mapping.rangeModified(node);
324                         
325                         //nodeMap.modified(node);
326                         update();
327                 } else {
328                         getDefaultAction().mouseDragged(e);
329                         update();
330                 }
331                 return true;
332         }
333         
334         protected void setPos(Vector3d pos) {
335                 node.setPosition(pos);
336         }
337         
338         protected void setWorldPos(Vector3d pos) {
339                 node.setWorldPosition(pos);
340         }
341         
342          private double istep = 10.0;
343          private int decimals = 2;
344         
345         protected Vector3d constaints(Vector3d p, boolean step) {
346                 if(!step)
347                         return p;
348                 switch (index) {
349                 case X:
350                          p.x = Math.round(istep * p.x) / istep;
351              BigDecimal bx = new BigDecimal(p.x);
352              bx.setScale(decimals, BigDecimal.ROUND_HALF_UP);
353              p.x = bx.doubleValue();
354                         break;
355                 case Y:
356                          p.y = Math.round(istep * p.y) / istep;
357              BigDecimal by = new BigDecimal(p.y);
358              by.setScale(decimals, BigDecimal.ROUND_HALF_UP);
359              p.y = by.doubleValue();
360                         break;
361                         
362                 case Z:
363                          p.z = Math.round(istep * p.z) / istep;
364              BigDecimal bz = new BigDecimal(p.z);
365              bz.setScale(decimals, BigDecimal.ROUND_HALF_UP);
366              p.z = bz.doubleValue();
367                         break;
368                 }
369                 return p;
370         }
371         
372         @Override
373         public boolean mouseMoved(MouseEvent e) {
374                 getDefaultAction().mouseMoved(e);
375                 return true;
376         }
377         
378         protected Vector3d getTranslate(double x, double y) {
379                 return getTranslate(x, y, new Vector3d());
380         }
381         
382         protected Vector3d getTranslate(double x, double y, Vector3d offset) {
383                 Vector3d translate = new Vector3d();
384                 
385                 Ray ray = vtkUtil.createMouseRay(panel.getRenderer(),x, y);
386                 
387                 Vector3d p = node.getWorldPosition();
388                 Vector3d dir = null;
389                 
390                 switch (index) {
391                 case P:
392                         Vector3d normal = new Vector3d(panel.getRenderer().GetActiveCamera().GetDirectionOfProjection());
393                         if (!worldCoord) {
394                                 MathTools.rotate(q, normal, normal);
395                         }
396                         normal.normalize();
397                         double s[] = new double[1];
398             Vector3d r = new Vector3d();
399             if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
400                 r.sub(p);
401                 translate.x = r.x;
402                 translate.y = r.y;
403                 translate.z = r.z;
404             }
405             break;
406
407                  case X :
408                     dir = new Vector3d(1.0,0.0,0.0);
409                     if(!worldCoord)
410                         MathTools.rotate(q, dir, dir);
411                     Vector3d i1 = new Vector3d();
412                     Vector3d i2 = new Vector3d();
413                     s = new double[2];
414                     MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
415                     translate.x = s[0];
416                     
417                     break;
418                 case Y :
419                     dir = new Vector3d(0.0,1.0,0.0);
420                     if(!worldCoord)
421                         MathTools.rotate(q, dir, dir);
422                     i1 = new Vector3d();
423                     i2 = new Vector3d();
424                     s = new double[2];
425                     MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
426                     translate.y = s[0];
427                     break;
428                 case Z :
429                     dir = new Vector3d(0.0,0.0,1.0);
430                     if(!worldCoord)
431                         MathTools.rotate(q, dir, dir);
432                     i1 = new Vector3d();
433                     i2 = new Vector3d();
434                     s = new double[2];
435                     MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
436                     translate.z = s[0];
437                     break;
438                 case XY :
439                     normal = new Vector3d(0.0,0.0,1.0);
440                     if(!worldCoord)
441                         MathTools.rotate(q, normal, normal);
442                     r = new Vector3d();
443                     if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
444                         r.sub(p);
445                         translate.x = r.x;
446                         translate.y = r.y;
447                     }
448                     break;
449                 case XZ :
450                     normal = new Vector3d(0.0,1.0,0.0);
451                     if(!worldCoord)
452                         MathTools.rotate(q, normal, normal);
453                     r = new Vector3d();
454                     if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
455                         r.sub(p);
456                         translate.x = r.x;
457                         translate.z = r.z;
458                     }
459                     break;
460                 case YZ :
461                     normal = new Vector3d(1.0,0.0,0.0);
462                     if(!worldCoord)
463                         MathTools.rotate(q, normal, normal);
464                     r = new Vector3d();
465                     if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
466                         r.sub(p);
467                         translate.y = r.y;
468                         translate.z = r.z;
469                     }
470                     break;
471                 default :
472                     
473                     return null;
474                 }
475                 translate.sub(offset);
476                 return translate;
477         }
478         
479 }