X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=org.simantics.g3d.vtk%2Fsrc%2Forg%2Fsimantics%2Fg3d%2Fvtk%2Faction%2FTranslateAction.java;fp=org.simantics.g3d.vtk%2Fsrc%2Forg%2Fsimantics%2Fg3d%2Fvtk%2Faction%2FTranslateAction.java;h=785e549d81e07feee2e48d5564ccf5f77a2c4676;hb=87b3241ec277ba3d8e414b26186a032c9cdcaeed;hp=0000000000000000000000000000000000000000;hpb=1f0bcd66274375f2278d2e6c486cb28257a5f7b2;p=simantics%2F3d.git diff --git a/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/action/TranslateAction.java b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/action/TranslateAction.java new file mode 100644 index 00000000..785e549d --- /dev/null +++ b/org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/action/TranslateAction.java @@ -0,0 +1,475 @@ +package org.simantics.g3d.vtk.action; + +import java.awt.Cursor; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.math.BigDecimal; + +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Point3d; +import javax.vecmath.Quat4d; +import javax.vecmath.Vector3d; + +import org.simantics.g3d.math.MathTools; +import org.simantics.g3d.math.Ray; +import org.simantics.g3d.scenegraph.IG3DNode; +import org.simantics.g3d.scenegraph.structural.IStructuralNode; +import org.simantics.g3d.vtk.Activator; +import org.simantics.g3d.vtk.common.InteractiveVtkPanel; +import org.simantics.g3d.vtk.common.VTKNodeMap; +import org.simantics.g3d.vtk.gizmo.TranslateAxisGizmo; +import org.simantics.g3d.vtk.utils.vtkUtil; +import org.simantics.utils.threads.AWTThread; +import org.simantics.utils.threads.ThreadUtils; + +import vtk.vtkProp; + +public class TranslateAction extends vtkAction{ + + public static final int X = 0; + public static final int Y = 1; + public static final int Z = 2; + public static final int XY = 3; + public static final int XZ = 4; + public static final int YZ = 5; + public static final int P = 6; + + private VTKNodeMap nodeMap; + //private TranslateGizmo gizmo = new TranslateGizmo(); + private TranslateAxisGizmo gizmo = new TranslateAxisGizmo(); + private IG3DNode node; + + + + private Cursor activeCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + private Cursor dragCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); + + public void setNode(IG3DNode node) { + this.node = node; + if ((node instanceof IStructuralNode) && ((IStructuralNode)node).isPartOfInstantiatedModel() && !((IStructuralNode)node).isInstantiatedModelRoot()) { + setEnabled(false); + } else { + setEnabled(true); + } + } + + public IG3DNode getNode() { + return node; + } + + public TranslateAction(InteractiveVtkPanel panel, VTKNodeMap nodeMap) { + super(panel); + setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_out.png")); + setText("Translate"); + this.nodeMap = nodeMap; + } + + public void attach() { + if (node == null) + return; + + super.attach(); + ThreadUtils.asyncExec(AWTThread.getThreadAccess(), new Runnable() { + public void run() { + attachUI(); + update(); + } + }); + + + + } + + public void deattach() { + + node = null; + nodeMap.commit(); + deattachUI(); + super.deattach(); + panel.repaint(); + } + + private void attachUI() { + panel.setCursor(activeCursor); + gizmo.attach(panel.GetRenderer()); + } + + private void deattachUI() { + panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + gizmo.deattach(); + } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) + panel.useDefaultAction(); + if (valid) + return; + if (e.getKeyCode() == KeyEvent.VK_X) { + if (index != X) + index = X; + else + index = P; + } + if (e.getKeyCode() == KeyEvent.VK_Y) { + if (index != Y) + index = Y; + else + index = P; + } + if (e.getKeyCode() == KeyEvent.VK_Z) { + if (index != Z) + index = Z; + else + index = P; + } + if (e.getKeyCode() == KeyEvent.VK_G) { + worldCoord = !worldCoord; + } + gizmo.setType(index); + + update(); + //panel.repaint(); + } + + @Override + public void keyReleased(KeyEvent e) { + + } + + @Override + public void keyTyped(KeyEvent e) { + + } + + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() > 1) { + if (isOverNode(e)) { + return; + } else { + panel.useDefaultAction(); + } + //if(!gizmo.isPartOf(actor)) + // panel.useDefaultAction(); + + } + } + + private boolean isOverNode(MouseEvent e) { + vtkProp picked[] = panel.pick(e.getX(), e.getY()); + if (picked !=null) { + for (int i = 0; i < picked.length; i++) { + if (node.equals(nodeMap.getNode(picked[i]))) + return true; + } + } + return false; + } + + @Override + public void mouseEntered(MouseEvent e) { + + } + + @Override + public void mouseExited(MouseEvent e) { + + } + + int index = P; + boolean valid = false; + private boolean worldCoord = true; + private AxisAngle4d aa = null; + private Quat4d q = null; + + + public void setWorldCoord(boolean b) { + if (worldCoord == b) + return; + worldCoord = b; + update(); + + } + + + private void update() { + if (node == null) + return; + if (worldCoord) { + gizmo.setRotation(new AxisAngle4d()); + aa = null; + q = null; + } else { + aa = new AxisAngle4d(); + aa.set(((IG3DNode)node.getParent()).getWorldOrientation()); + gizmo.setRotation(aa); + q = new Quat4d(); + MathTools.getQuat(aa, q); + } + + Vector3d nodePos = node.getWorldPosition(); + //System.out.println(nodePos); + gizmo.setPosition(nodePos); + + + Point3d camPos = new Point3d(panel.GetRenderer().GetActiveCamera().GetPosition()); + Vector3d p = new Vector3d(nodePos); + p.sub(camPos); + + if (q != null) { + Quat4d qi = new Quat4d(q); + qi.inverse(); + MathTools.rotate(q, p, p); + } + if (panel.GetRenderer().GetActiveCamera().GetParallelProjection() == 0) { + double distance = p.length(); + p.negate(); + double fov = panel.GetRenderer().GetActiveCamera().GetViewAngle(); + float s = (float) (Math.sin(fov) * distance * 0.1); + + Vector3d scale = new Vector3d(1., 1., 1.); + +// if (p.x > 0.f) +// scale.x = -1.; +// if (p.y > 0.f) +// scale.y = -1.; +// if (p.z > 0.f) +// scale.z = -1.; + scale.scale(s); + gizmo.setScale(scale); + + } else { + Vector3d scale = new Vector3d(1.f, 1.f, 1.f); + double s = panel.GetRenderer().GetActiveCamera().GetParallelScale() / 5.; +// if (p.x > 0.f) +// scale.x = -1.; +// if (p.y > 0.f) +// scale.y = -1.; +// if (p.z > 0.f) +// scale.z = -1.; + scale.scale(s); + gizmo.setScale(scale); + } + + //panel.Render(); + panel.repaint(); + } + + Vector3d prevTranslate = null; + + @Override + public void mousePressed(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1) { + + if (isOverNode(e)) { + prevTranslate = getTranslate(e.getX(), e.getY()); + valid = true; + panel.setCursor(dragCursor); + } else { + valid = false; + panel.getDefaultAction().mousePressed(e); + panel.setCursor(activeCursor); + } + } else { + panel.getDefaultAction().mousePressed(e); + } + //index = gizmo.getTranslateAxis(actor); + //if (index == -1) { + // valid = false; + // panel.getDefaultAction().mousePressed(e); + // return; + //} + //valid = true; + //prevTranslate = getTranslate(e.getX(), e.getY()); + //System.out.println("start translate " + prevTranslate); + } + + + + @Override + public void mouseReleased(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1) { + valid = false; + prevTranslate = null; + panel.setCursor(activeCursor); + } else { + panel.getDefaultAction().mouseReleased(e); + } + } + + @Override + public void mouseDragged(MouseEvent e) { + if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) > 0 && valid) { + + Vector3d translate = getTranslate(e.getX(), e.getY(), prevTranslate); + //System.out.println("translate " + translate); + if (translate == null) + return; + boolean step = ((e.getModifiers() & MouseEvent.CTRL_MASK) > 0); + if (worldCoord) { + Vector3d pos = new Vector3d(node.getWorldPosition()); + pos.add(translate); + pos = constaints(pos, step); + setWorldPos(pos); + } else { + Vector3d pos = new Vector3d(node.getPosition()); + pos.add(translate); + pos = constaints(pos, step); + setPos(pos); + } + //mapping.rangeModified(node); + + //nodeMap.modified(node); + update(); + } else { + panel.getDefaultAction().mouseDragged(e); + update(); + } + } + + protected void setPos(Vector3d pos) { + node.setPosition(pos); + } + + protected void setWorldPos(Vector3d pos) { + node.setWorldPosition(pos); + } + + private double istep = 10.0; + private int decimals = 2; + + private Vector3d constaints(Vector3d p, boolean step) { + if(!step) + return p; + switch (index) { + case X: + p.x = Math.round(istep * p.x) / istep; + BigDecimal bx = new BigDecimal(p.x); + bx.setScale(decimals, BigDecimal.ROUND_HALF_UP); + p.x = bx.doubleValue(); + break; + case Y: + p.y = Math.round(istep * p.y) / istep; + BigDecimal by = new BigDecimal(p.y); + by.setScale(decimals, BigDecimal.ROUND_HALF_UP); + p.y = by.doubleValue(); + break; + + case Z: + p.z = Math.round(istep * p.z) / istep; + BigDecimal bz = new BigDecimal(p.z); + bz.setScale(decimals, BigDecimal.ROUND_HALF_UP); + p.z = bz.doubleValue(); + break; + } + return p; + } + + @Override + public void mouseMoved(MouseEvent e) { + panel.getDefaultAction().mouseMoved(e); + } + + Vector3d getTranslate(double x, double y) { + return getTranslate(x, y, new Vector3d()); + } + + Vector3d getTranslate(double x, double y, Vector3d offset) { + Vector3d translate = new Vector3d(); + + Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(),x, y); + + Vector3d p = node.getWorldPosition(); + Vector3d dir = null; + + switch (index) { + case P: + Vector3d normal = new Vector3d(panel.GetRenderer().GetActiveCamera().GetDirectionOfProjection()); + if (!worldCoord) { + MathTools.rotate(q, normal, normal); + } + normal.normalize(); + double s[] = new double[1]; + Vector3d r = new Vector3d(); + if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) { + r.sub(p); + translate.x = r.x; + translate.y = r.y; + translate.z = r.z; + } + break; + + case X : + dir = new Vector3d(1.0,0.0,0.0); + if(!worldCoord) + MathTools.rotate(q, dir, dir); + Vector3d i1 = new Vector3d(); + Vector3d i2 = new Vector3d(); + s = new double[2]; + MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s); + translate.x = s[0]; + + break; + case Y : + dir = new Vector3d(0.0,1.0,0.0); + if(!worldCoord) + MathTools.rotate(q, dir, dir); + i1 = new Vector3d(); + i2 = new Vector3d(); + s = new double[2]; + MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s); + translate.y = s[0]; + break; + case Z : + dir = new Vector3d(0.0,0.0,1.0); + if(!worldCoord) + MathTools.rotate(q, dir, dir); + i1 = new Vector3d(); + i2 = new Vector3d(); + s = new double[2]; + MathTools.intersectStraightStraight( p, dir,ray.pos, ray.dir, i2, i1,s); + translate.z = s[0]; + break; + case XY : + normal = new Vector3d(0.0,0.0,1.0); + if(!worldCoord) + MathTools.rotate(q, normal, normal); + r = new Vector3d(); + if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) { + r.sub(p); + translate.x = r.x; + translate.y = r.y; + } + break; + case XZ : + normal = new Vector3d(0.0,1.0,0.0); + if(!worldCoord) + MathTools.rotate(q, normal, normal); + r = new Vector3d(); + if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) { + r.sub(p); + translate.x = r.x; + translate.z = r.z; + } + break; + case YZ : + normal = new Vector3d(1.0,0.0,0.0); + if(!worldCoord) + MathTools.rotate(q, normal, normal); + r = new Vector3d(); + if (MathTools.intersectStraightPlane(ray.pos, ray.dir, p, normal, r)) { + r.sub(p); + translate.y = r.y; + translate.z = r.z; + } + break; + default : + + return null; + } + translate.sub(offset); + return translate; + } + +}