1 /*******************************************************************************
2 * Copyright (c) 2012, 2013 Association for Decentralized Information Management in
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.g3d.vtk.awt;
14 import java.awt.Cursor;
15 import java.awt.event.KeyEvent;
16 import java.awt.event.MouseEvent;
17 import java.math.BigDecimal;
19 import javax.vecmath.AxisAngle4d;
20 import javax.vecmath.Point3d;
21 import javax.vecmath.Quat4d;
22 import javax.vecmath.Vector3d;
24 import org.simantics.g3d.math.MathTools;
25 import org.simantics.g3d.math.Ray;
26 import org.simantics.g3d.scenegraph.IG3DNode;
27 import org.simantics.g3d.scenegraph.base.INode;
28 import org.simantics.g3d.scenegraph.structural.IStructuralNode;
29 import org.simantics.g3d.vtk.Activator;
30 import org.simantics.g3d.vtk.common.VTKNodeMap;
31 import org.simantics.g3d.vtk.gizmo.TranslateAxisGizmo;
32 import org.simantics.g3d.vtk.utils.vtkUtil;
33 import org.simantics.utils.threads.AWTThread;
34 import org.simantics.utils.threads.ThreadUtils;
38 public class TranslateAction extends vtkAwtAction{
40 public static final int X = 0;
41 public static final int Y = 1;
42 public static final int Z = 2;
43 public static final int XY = 3;
44 public static final int XZ = 4;
45 public static final int YZ = 5;
46 public static final int P = 6;
48 private VTKNodeMap<?, ? extends INode> nodeMap;
49 //private TranslateGizmo gizmo = new TranslateGizmo();
50 private TranslateAxisGizmo gizmo = new TranslateAxisGizmo();
51 protected IG3DNode node;
55 private Cursor activeCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
56 private Cursor dragCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
58 public void setNode(IG3DNode node) {
60 if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot()) {
67 public IG3DNode getNode() {
71 public TranslateAction(InteractiveVtkPanel panel, VTKNodeMap<?, ? extends INode> nodeMap) {
73 setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_out.png"));
75 this.nodeMap = nodeMap;
78 public void attach() {
83 ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() {
94 public void deattach() {
97 nodeMap.commit("Translate");
103 private void attachUI() {
104 panel.setCursor(activeCursor);
108 private void deattachUI() {
109 panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
114 public void keyPressed(KeyEvent e) {
115 if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
116 panel.useDefaultAction();
119 if (e.getKeyCode() == KeyEvent.VK_X) {
125 if (e.getKeyCode() == KeyEvent.VK_Y) {
131 if (e.getKeyCode() == KeyEvent.VK_Z) {
137 if (e.getKeyCode() == KeyEvent.VK_G) {
138 worldCoord = !worldCoord;
140 gizmo.setType(index);
147 public void keyReleased(KeyEvent e) {
152 public void keyTyped(KeyEvent e) {
157 public void mouseClicked(MouseEvent e) {
158 if (e.getClickCount() > 1) {
162 panel.useDefaultAction();
164 //if(!gizmo.isPartOf(actor))
165 // panel.useDefaultAction();
170 private boolean isOverNode(MouseEvent e) {
171 vtkProp picked[] = panel.pick(e.getX(), e.getY());
173 for (int i = 0; i < picked.length; i++) {
174 if (node.equals(nodeMap.getNode(picked[i])))
182 public void mouseEntered(MouseEvent e) {
187 public void mouseExited(MouseEvent e) {
192 protected boolean valid = false;
193 private boolean worldCoord = true;
194 private AxisAngle4d aa = null;
195 private Quat4d q = null;
198 public void setWorldCoord(boolean b) {
207 protected void update() {
211 gizmo.setRotation(new AxisAngle4d());
215 aa = new AxisAngle4d();
216 aa.set(((IG3DNode)node.getParent()).getWorldOrientation());
217 gizmo.setRotation(aa);
219 MathTools.getQuat(aa, q);
222 Vector3d nodePos = node.getWorldPosition();
223 //System.out.println(nodePos);
224 gizmo.setPosition(nodePos);
227 Point3d camPos = new Point3d(panel.GetRenderer().GetActiveCamera().GetPosition());
228 Vector3d p = new Vector3d(nodePos);
232 Quat4d qi = new Quat4d(q);
234 MathTools.rotate(q, p, p);
236 if (panel.GetRenderer().GetActiveCamera().GetParallelProjection() == 0) {
237 double distance = p.length();
239 double fov = panel.GetRenderer().GetActiveCamera().GetViewAngle();
240 float s = (float) (Math.sin(fov) * distance * 0.1);
242 Vector3d scale = new Vector3d(1., 1., 1.);
251 gizmo.setScale(scale);
254 Vector3d scale = new Vector3d(1.f, 1.f, 1.f);
255 double s = panel.GetRenderer().GetActiveCamera().GetParallelScale() / 5.;
263 gizmo.setScale(scale);
270 protected Vector3d prevTranslate = null;
273 public void mousePressed(MouseEvent e) {
274 if (e.getButton() == MouseEvent.BUTTON1) {
277 prevTranslate = getTranslate(e.getX(), e.getY());
279 panel.setCursor(dragCursor);
282 getDefaultAction().mousePressed(e);
283 panel.setCursor(activeCursor);
286 getDefaultAction().mousePressed(e);
288 //index = gizmo.getTranslateAxis(actor);
291 // panel.getDefaultAction().mousePressed(e);
295 //prevTranslate = getTranslate(e.getX(), e.getY());
296 //System.out.println("start translate " + prevTranslate);
302 public void mouseReleased(MouseEvent e) {
303 if (e.getButton() == MouseEvent.BUTTON1) {
305 prevTranslate = null;
306 panel.setCursor(activeCursor);
308 getDefaultAction().mouseReleased(e);
313 public void mouseDragged(MouseEvent e) {
314 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0 && valid) {
316 Vector3d translate = getTranslate(e.getX(), e.getY(), prevTranslate);
317 //System.out.println("translate " + translate);
318 if (translate == null)
320 boolean step = ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0);
322 Vector3d pos = new Vector3d(node.getWorldPosition());
324 pos = constaints(pos, step);
327 Vector3d pos = new Vector3d(node.getPosition());
329 pos = constaints(pos, step);
332 //mapping.rangeModified(node);
334 //nodeMap.modified(node);
337 getDefaultAction().mouseDragged(e);
342 protected void setPos(Vector3d pos) {
343 node.setPosition(pos);
346 protected void setWorldPos(Vector3d pos) {
347 node.setWorldPosition(pos);
350 private double istep = 10.0;
351 private int decimals = 2;
353 protected Vector3d constaints(Vector3d p, boolean step) {
358 p.x = Math.round(istep * p.x) / istep;
359 BigDecimal bx = new BigDecimal(p.x);
360 bx.setScale(decimals, BigDecimal.ROUND_HALF_UP);
361 p.x = bx.doubleValue();
364 p.y = Math.round(istep * p.y) / istep;
365 BigDecimal by = new BigDecimal(p.y);
366 by.setScale(decimals, BigDecimal.ROUND_HALF_UP);
367 p.y = by.doubleValue();
371 p.z = Math.round(istep * p.z) / istep;
372 BigDecimal bz = new BigDecimal(p.z);
373 bz.setScale(decimals, BigDecimal.ROUND_HALF_UP);
374 p.z = bz.doubleValue();
381 public void mouseMoved(MouseEvent e) {
382 getDefaultAction().mouseMoved(e);
385 protected Vector3d getTranslate(double x, double y) {
386 return getTranslate(x, y, new Vector3d());
389 protected Vector3d getTranslate(double x, double y, Vector3d offset) {
390 Vector3d translate = new Vector3d();
392 Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(),x, y);
394 Vector3d p = node.getWorldPosition();
399 Vector3d normal = new Vector3d(panel.GetRenderer().GetActiveCamera().GetDirectionOfProjection());
401 MathTools.rotate(q, normal, normal);
404 double s[] = new double[1];
405 Vector3d r = new Vector3d();
406 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
415 dir = new Vector3d(1.0,0.0,0.0);
417 MathTools.rotate(q, dir, dir);
418 Vector3d i1 = new Vector3d();
419 Vector3d i2 = new Vector3d();
421 MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
426 dir = new Vector3d(0.0,1.0,0.0);
428 MathTools.rotate(q, dir, dir);
432 MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
436 dir = new Vector3d(0.0,0.0,1.0);
438 MathTools.rotate(q, dir, dir);
442 MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
446 normal = new Vector3d(0.0,0.0,1.0);
448 MathTools.rotate(q, normal, normal);
450 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
457 normal = new Vector3d(0.0,1.0,0.0);
459 MathTools.rotate(q, normal, normal);
461 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
468 normal = new Vector3d(1.0,0.0,0.0);
470 MathTools.rotate(q, normal, normal);
472 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
482 translate.sub(offset);