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.swt;
14 import java.awt.event.KeyEvent;
15 import java.awt.event.MouseEvent;
16 import java.math.BigDecimal;
18 import javax.vecmath.AxisAngle4d;
19 import javax.vecmath.Point3d;
20 import javax.vecmath.Quat4d;
21 import javax.vecmath.Vector3d;
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;
39 public class TranslateAction extends vtkSwtAction{
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;
49 private VTKNodeMap nodeMap;
50 //private TranslateGizmo gizmo = new TranslateGizmo();
51 private TranslateAxisGizmo gizmo = new TranslateAxisGizmo();
52 protected IG3DNode node;
56 private Cursor activeCursor;// = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
57 private Cursor dragCursor;// = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
59 public void setNode(IG3DNode node) {
61 if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot()) {
68 public IG3DNode getNode() {
72 public TranslateAction(InteractiveVtkComposite panel, VTKNodeMap nodeMap) {
74 setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_out.png"));
76 this.nodeMap = nodeMap;
78 activeCursor = Display.getCurrent().getSystemCursor(SWT.CURSOR_HAND);
79 dragCursor = Display.getCurrent().getSystemCursor(SWT.CURSOR_SIZEALL);
82 public void attach() {
87 ThreadUtils.asyncExec(panel.getThreadQueue(), new Runnable() {
98 public void deattach() {
107 private void attachUI() {
108 panel.getComponent().setCursor(activeCursor);
112 private void deattachUI() {
113 panel.getComponent().setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_ARROW));
118 public boolean keyPressed(KeyEvent e) {
119 if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
120 panel.useDefaultAction();
123 if (e.getKeyCode() == KeyEvent.VK_X) {
129 if (e.getKeyCode() == KeyEvent.VK_Y) {
135 if (e.getKeyCode() == KeyEvent.VK_Z) {
141 if (e.getKeyCode() == KeyEvent.VK_G) {
142 worldCoord = !worldCoord;
144 gizmo.setType(index);
154 public boolean mouseClicked(MouseEvent e) {
155 if (e.getClickCount() > 1) {
159 panel.useDefaultAction();
161 //if(!gizmo.isPartOf(actor))
162 // panel.useDefaultAction();
168 private boolean isOverNode(MouseEvent e) {
169 vtkProp picked[] = panel.pick(e.getX(), e.getY());
171 for (int i = 0; i < picked.length; i++) {
172 if (node.equals(nodeMap.getNode(picked[i])))
181 protected boolean valid = false;
182 private boolean worldCoord = true;
183 private AxisAngle4d aa = null;
184 private Quat4d q = null;
187 public void setWorldCoord(boolean b) {
196 protected void update() {
200 gizmo.setRotation(new AxisAngle4d());
204 aa = new AxisAngle4d();
205 aa.set(((IG3DNode)node.getParent()).getWorldOrientation());
206 gizmo.setRotation(aa);
208 MathTools.getQuat(aa, q);
211 Vector3d nodePos = node.getWorldPosition();
212 //System.out.println(nodePos);
213 gizmo.setPosition(nodePos);
216 Point3d camPos = new Point3d(panel.getRenderer().GetActiveCamera().GetPosition());
217 Vector3d p = new Vector3d(nodePos);
221 Quat4d qi = new Quat4d(q);
223 MathTools.rotate(q, p, p);
225 if (panel.getRenderer().GetActiveCamera().GetParallelProjection() == 0) {
226 double distance = p.length();
228 double fov = panel.getRenderer().GetActiveCamera().GetViewAngle();
229 float s = (float) (Math.sin(fov) * distance * 0.1);
231 Vector3d scale = new Vector3d(1., 1., 1.);
240 gizmo.setScale(scale);
243 Vector3d scale = new Vector3d(1.f, 1.f, 1.f);
244 double s = panel.getRenderer().GetActiveCamera().GetParallelScale() / 5.;
252 gizmo.setScale(scale);
259 protected Vector3d prevTranslate = null;
262 public boolean mousePressed(MouseEvent e) {
263 if (e.getButton() == MouseEvent.BUTTON1) {
266 prevTranslate = getTranslate(e.getX(), e.getY());
268 panel.getComponent().setCursor(dragCursor);
271 getDefaultAction().mousePressed(e);
272 panel.getComponent().setCursor(activeCursor);
275 getDefaultAction().mousePressed(e);
278 //index = gizmo.getTranslateAxis(actor);
281 // panel.getDefaultAction().mousePressed(e);
285 //prevTranslate = getTranslate(e.getX(), e.getY());
286 //System.out.println("start translate " + prevTranslate);
292 public boolean mouseReleased(MouseEvent e) {
293 if (e.getButton() == MouseEvent.BUTTON1) {
295 prevTranslate = null;
296 panel.getComponent().setCursor(activeCursor);
298 getDefaultAction().mouseReleased(e);
304 public boolean mouseDragged(MouseEvent e) {
305 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0 && valid) {
307 Vector3d translate = getTranslate(e.getX(), e.getY(), prevTranslate);
308 //System.out.println("translate " + translate);
309 if (translate == null)
311 boolean step = ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0);
313 Vector3d pos = new Vector3d(node.getWorldPosition());
315 pos = constaints(pos, step);
318 Vector3d pos = new Vector3d(node.getPosition());
320 pos = constaints(pos, step);
323 //mapping.rangeModified(node);
325 //nodeMap.modified(node);
328 getDefaultAction().mouseDragged(e);
334 protected void setPos(Vector3d pos) {
335 node.setPosition(pos);
338 protected void setWorldPos(Vector3d pos) {
339 node.setWorldPosition(pos);
342 private double istep = 10.0;
343 private int decimals = 2;
345 protected Vector3d constaints(Vector3d p, boolean step) {
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();
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();
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();
373 public boolean mouseMoved(MouseEvent e) {
374 getDefaultAction().mouseMoved(e);
378 protected Vector3d getTranslate(double x, double y) {
379 return getTranslate(x, y, new Vector3d());
382 protected Vector3d getTranslate(double x, double y, Vector3d offset) {
383 Vector3d translate = new Vector3d();
385 Ray ray = vtkUtil.createMouseRay(panel.getRenderer(),x, y);
387 Vector3d p = node.getWorldPosition();
392 Vector3d normal = new Vector3d(panel.getRenderer().GetActiveCamera().GetDirectionOfProjection());
394 MathTools.rotate(q, normal, normal);
397 double s[] = new double[1];
398 Vector3d r = new Vector3d();
399 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
408 dir = new Vector3d(1.0,0.0,0.0);
410 MathTools.rotate(q, dir, dir);
411 Vector3d i1 = new Vector3d();
412 Vector3d i2 = new Vector3d();
414 MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
419 dir = new Vector3d(0.0,1.0,0.0);
421 MathTools.rotate(q, dir, dir);
425 MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
429 dir = new Vector3d(0.0,0.0,1.0);
431 MathTools.rotate(q, dir, dir);
435 MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s);
439 normal = new Vector3d(0.0,0.0,1.0);
441 MathTools.rotate(q, normal, normal);
443 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
450 normal = new Vector3d(0.0,1.0,0.0);
452 MathTools.rotate(q, normal, normal);
454 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
461 normal = new Vector3d(1.0,0.0,0.0);
463 MathTools.rotate(q, normal, normal);
465 if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) {
475 translate.sub(offset);