1 package org.simantics.g3d.vtk.action;
\r
3 import java.awt.Cursor;
\r
4 import java.awt.event.KeyEvent;
\r
5 import java.awt.event.MouseEvent;
\r
6 import java.math.BigDecimal;
\r
8 import javax.vecmath.AxisAngle4d;
\r
9 import javax.vecmath.Point3d;
\r
10 import javax.vecmath.Quat4d;
\r
11 import javax.vecmath.Vector3d;
\r
13 import org.simantics.g3d.math.MathTools;
\r
14 import org.simantics.g3d.math.Ray;
\r
15 import org.simantics.g3d.scenegraph.IG3DNode;
\r
16 import org.simantics.g3d.scenegraph.structural.IStructuralNode;
\r
17 import org.simantics.g3d.vtk.Activator;
\r
18 import org.simantics.g3d.vtk.common.InteractiveVtkPanel;
\r
19 import org.simantics.g3d.vtk.common.VTKNodeMap;
\r
20 import org.simantics.g3d.vtk.gizmo.TranslateAxisGizmo;
\r
21 import org.simantics.g3d.vtk.utils.vtkUtil;
\r
22 import org.simantics.utils.threads.AWTThread;
\r
23 import org.simantics.utils.threads.ThreadUtils;
\r
27 public class TranslateAction extends vtkAction{
\r
29 public static final int X = 0;
\r
30 public static final int Y = 1;
\r
31 public static final int Z = 2;
\r
32 public static final int XY = 3;
\r
33 public static final int XZ = 4;
\r
34 public static final int YZ = 5;
\r
35 public static final int P = 6;
\r
37 private VTKNodeMap nodeMap;
\r
38 //private TranslateGizmo gizmo = new TranslateGizmo();
\r
39 private TranslateAxisGizmo gizmo = new TranslateAxisGizmo();
\r
40 private IG3DNode node;
\r
44 private Cursor activeCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
\r
45 private Cursor dragCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
\r
47 public void setNode(IG3DNode node) {
\r
49 if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot()) {
\r
56 public IG3DNode getNode() {
\r
60 public TranslateAction(InteractiveVtkPanel panel, VTKNodeMap nodeMap) {
\r
62 setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_out.png"));
\r
63 setText("Translate");
\r
64 this.nodeMap = nodeMap;
\r
67 public void attach() {
\r
72 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
\r
83 public void deattach() {
\r
92 private void attachUI() {
\r
93 panel.setCursor(activeCursor);
\r
94 gizmo.attach(panel.GetRenderer());
\r
97 private void deattachUI() {
\r
98 panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
\r
103 public void keyPressed(KeyEvent e) {
\r
104 if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
\r
105 panel.useDefaultAction();
\r
108 if (e.getKeyCode() == KeyEvent.VK_X) {
\r
114 if (e.getKeyCode() == KeyEvent.VK_Y) {
\r
120 if (e.getKeyCode() == KeyEvent.VK_Z) {
\r
126 if (e.getKeyCode() == KeyEvent.VK_G) {
\r
127 worldCoord = !worldCoord;
\r
129 gizmo.setType(index);
\r
136 public void keyReleased(KeyEvent e) {
\r
141 public void keyTyped(KeyEvent e) {
\r
146 public void mouseClicked(MouseEvent e) {
\r
147 if (e.getClickCount() > 1) {
\r
148 if (isOverNode(e)) {
\r
151 panel.useDefaultAction();
\r
153 //if(!gizmo.isPartOf(actor))
\r
154 // panel.useDefaultAction();
\r
159 private boolean isOverNode(MouseEvent e) {
\r
160 vtkProp picked[] = panel.pick(e.getX(), e.getY());
\r
161 if (picked !=null) {
\r
162 for (int i = 0; i < picked.length; i++) {
\r
163 if (node.equals(nodeMap.getNode(picked[i])))
\r
171 public void mouseEntered(MouseEvent e) {
\r
176 public void mouseExited(MouseEvent e) {
\r
181 boolean valid = false;
\r
182 private boolean worldCoord = true;
\r
183 private AxisAngle4d aa = null;
\r
184 private Quat4d q = null;
\r
187 public void setWorldCoord(boolean b) {
\r
188 if (worldCoord == b)
\r
196 private void update() {
\r
200 gizmo.setRotation(new AxisAngle4d());
\r
204 aa = new AxisAngle4d();
\r
205 aa.set(((IG3DNode)node.getParent()).getWorldOrientation());
\r
206 gizmo.setRotation(aa);
\r
208 MathTools.getQuat(aa, q);
\r
211 Vector3d nodePos = node.getWorldPosition();
\r
212 //System.out.println(nodePos);
\r
213 gizmo.setPosition(nodePos);
\r
216 Point3d camPos = new Point3d(panel.GetRenderer().GetActiveCamera().GetPosition());
\r
217 Vector3d p = new Vector3d(nodePos);
\r
221 Quat4d qi = new Quat4d(q);
\r
223 MathTools.rotate(q, p, p);
\r
225 if (panel.GetRenderer().GetActiveCamera().GetParallelProjection() == 0) {
\r
226 double distance = p.length();
\r
228 double fov = panel.GetRenderer().GetActiveCamera().GetViewAngle();
\r
229 float s = (float) (Math.sin(fov) * distance * 0.1);
\r
231 Vector3d scale = new Vector3d(1., 1., 1.);
\r
240 gizmo.setScale(scale);
\r
243 Vector3d scale = new Vector3d(1.f, 1.f, 1.f);
\r
244 double s = panel.GetRenderer().GetActiveCamera().GetParallelScale() / 5.;
\r
252 gizmo.setScale(scale);
\r
259 Vector3d prevTranslate = null;
\r
262 public void mousePressed(MouseEvent e) {
\r
263 if (e.getButton() == MouseEvent.BUTTON1) {
\r
265 if (isOverNode(e)) {
\r
266 prevTranslate = getTranslate(e.getX(), e.getY());
\r
268 panel.setCursor(dragCursor);
\r
271 panel.getDefaultAction().mousePressed(e);
\r
272 panel.setCursor(activeCursor);
\r
275 panel.getDefaultAction().mousePressed(e);
\r
277 //index = gizmo.getTranslateAxis(actor);
\r
278 //if (index == -1) {
\r
280 // panel.getDefaultAction().mousePressed(e);
\r
284 //prevTranslate = getTranslate(e.getX(), e.getY());
\r
285 //System.out.println("start translate " + prevTranslate);
\r
291 public void mouseReleased(MouseEvent e) {
\r
292 if (e.getButton() == MouseEvent.BUTTON1) {
\r
294 prevTranslate = null;
\r
295 panel.setCursor(activeCursor);
\r
297 panel.getDefaultAction().mouseReleased(e);
\r
302 public void mouseDragged(MouseEvent e) {
\r
303 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0 && valid) {
\r
305 Vector3d translate = getTranslate(e.getX(), e.getY(), prevTranslate);
\r
306 //System.out.println("translate " + translate);
\r
307 if (translate == null)
\r
309 boolean step = ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0);
\r
311 Vector3d pos = new Vector3d(node.getWorldPosition());
\r
312 pos.add(translate);
\r
313 pos = constaints(pos, step);
\r
316 Vector3d pos = new Vector3d(node.getPosition());
\r
317 pos.add(translate);
\r
318 pos = constaints(pos, step);
\r
321 //mapping.rangeModified(node);
\r
323 //nodeMap.modified(node);
\r
326 panel.getDefaultAction().mouseDragged(e);
\r
331 protected void setPos(Vector3d pos) {
\r
332 node.setPosition(pos);
\r
335 protected void setWorldPos(Vector3d pos) {
\r
336 node.setWorldPosition(pos);
\r
339 private double istep = 10.0;
\r
340 private int decimals = 2;
\r
342 private Vector3d constaints(Vector3d p, boolean step) {
\r
347 p.x = Math.round(istep * p.x) / istep;
\r
348 BigDecimal bx = new BigDecimal(p.x);
\r
349 bx.setScale(decimals, BigDecimal.ROUND_HALF_UP);
\r
350 p.x = bx.doubleValue();
\r
353 p.y = Math.round(istep * p.y) / istep;
\r
354 BigDecimal by = new BigDecimal(p.y);
\r
355 by.setScale(decimals, BigDecimal.ROUND_HALF_UP);
\r
356 p.y = by.doubleValue();
\r
360 p.z = Math.round(istep * p.z) / istep;
\r
361 BigDecimal bz = new BigDecimal(p.z);
\r
362 bz.setScale(decimals, BigDecimal.ROUND_HALF_UP);
\r
363 p.z = bz.doubleValue();
\r
370 public void mouseMoved(MouseEvent e) {
\r
371 panel.getDefaultAction().mouseMoved(e);
\r
374 Vector3d getTranslate(double x, double y) {
\r
375 return getTranslate(x, y, new Vector3d());
\r
378 Vector3d getTranslate(double x, double y, Vector3d offset) {
\r
379 Vector3d translate = new Vector3d();
\r
381 Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(),x, y);
\r
383 Vector3d p = node.getWorldPosition();
\r
384 Vector3d dir = null;
\r
388 Vector3d normal = new Vector3d(panel.GetRenderer().GetActiveCamera().GetDirectionOfProjection());
\r
390 MathTools.rotate(q, normal, normal);
\r
392 normal.normalize();
\r
393 double s[] = new double[1];
\r
394 Vector3d r = new Vector3d();
\r
395 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
\r
404 dir = new Vector3d(1.0,0.0,0.0);
\r
406 MathTools.rotate(q, dir, dir);
\r
407 Vector3d i1 = new Vector3d();
\r
408 Vector3d i2 = new Vector3d();
\r
410 MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
\r
411 translate.x = s[0];
\r
415 dir = new Vector3d(0.0,1.0,0.0);
\r
417 MathTools.rotate(q, dir, dir);
\r
418 i1 = new Vector3d();
\r
419 i2 = new Vector3d();
\r
421 MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
\r
422 translate.y = s[0];
\r
425 dir = new Vector3d(0.0,0.0,1.0);
\r
427 MathTools.rotate(q, dir, dir);
\r
428 i1 = new Vector3d();
\r
429 i2 = new Vector3d();
\r
431 MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
\r
432 translate.z = s[0];
\r
435 normal = new Vector3d(0.0,0.0,1.0);
\r
437 MathTools.rotate(q, normal, normal);
\r
438 r = new Vector3d();
\r
439 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
\r
446 normal = new Vector3d(0.0,1.0,0.0);
\r
448 MathTools.rotate(q, normal, normal);
\r
449 r = new Vector3d();
\r
450 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
\r
457 normal = new Vector3d(1.0,0.0,0.0);
\r
459 MathTools.rotate(q, normal, normal);
\r
460 r = new Vector3d();
\r
461 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
\r
471 translate.sub(offset);
\r