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