/******************************************************************************* * Copyright (c) 2007- VTT Technical Research Centre of Finland. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.proconf.g3d.actions; import java.awt.event.MouseEvent; import java.math.BigDecimal; import java.util.Collection; import java.util.List; import javax.vecmath.AxisAngle4d; import javax.vecmath.AxisAngle4f; import javax.vecmath.Point3d; import javax.vecmath.Quat4d; import javax.vecmath.Vector3d; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IToolBarManager; import org.simantics.db.Graph; import org.simantics.db.GraphRequest; import org.simantics.db.GraphRequestAdapter; import org.simantics.db.GraphRequestStatus; import org.simantics.db.Resource; import org.simantics.layer0.utils.IEntity; import org.simantics.layer0.utils.EntityFactory; import org.simantics.proconf.g3d.Activator; import org.simantics.proconf.g3d.Resources; import org.simantics.proconf.g3d.base.G3DTools; import org.simantics.proconf.g3d.base.MathTools; import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase; import org.simantics.proconf.g3d.gizmo.TransformGizmo; import org.simantics.proconf.g3d.scenegraph.IGraphicsNode; import org.simantics.proconf.g3d.stubs.Orientation; import org.simantics.proconf.g3d.stubs.Position; public class TranslateAction extends ConstrainedTransformAction { private TransformGizmo gizmo; private double istep = 10.0; private int decimals = 2; private Action csAction; List mos = null; private boolean worldCoord = true; private AxisAngle4d aa; private Quat4d q; public TranslateAction(ThreeDimensionalEditorBase parent) { super(parent); csAction = new Action("World",Action.AS_CHECK_BOX) { public void run() { GraphRequest r = new GraphRequestAdapter() { @Override public GraphRequestStatus perform(Graph g) throws Exception { setWorldCoord(g,!isChecked()); return GraphRequestStatus.transactionComplete(); } }; TranslateAction.this.parent.getSession().asyncRead(r); } }; gizmo = new TransformGizmo(component.getDisplaySystem().getRenderer()); } public void init() { this.setText("Translate"); this.setToolTipText("Translate the object"); this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/translate.png")); } @Override public boolean usable(Graph graph, List resources) { if (resources.size() == 0) return false; for (Resource r : resources) { IEntity t = EntityFactory.create(graph,r); if (t.isInstanceOf(Resources.g3dResource.G3DNode)) { Collection p = t.getRelatedObjects(Resources.g3dResource.HasLocalPosition); if (p == null || p.size() != 1) return false; } } return true; } @Override public void deactivate() { super.deactivate(); parent.setGizmo(null); mos = null; } private void setWorldCoord(Graph graph,boolean b) { if (worldCoord == b) return; worldCoord = b; updateWorldCoord(graph); } private void updateWorldCoord(Graph graph) { if (worldCoord) { csAction.setText("World"); gizmo.setRotation(new AxisAngle4f()); aa = null; q = null; } else { csAction.setText("Local"); Orientation o = mos.get(0).getParent().getG3DNode(graph).getWorldOrientation(); if (o == null) { aa = new AxisAngle4d(); } else { aa = G3DTools.getOrientation(o); } gizmo.setRotation(new AxisAngle4f(aa)); q = new Quat4d(); q.set(aa); } // if (manager != null) // parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() { // public void run() { // manager.update(true); // } // }); this.parent.setViewChanged(true); } public void fillToolBar(IToolBarManager manager) { super.fillToolBar(manager); csAction.setChecked(!worldCoord); manager.add(csAction); } @Override public void activate() { GraphRequest r = new GraphRequestAdapter() { public GraphRequestStatus perform(Graph g) throws Exception { parent.setGizmo(gizmo); updateGizmo(g); component.getNoShadowRoot().attachChild(gizmo.getNode()); String text = ""; mos = parent.getSelectionAdapter().getSelectedObjects(); for (IGraphicsNode mo : mos) { if (worldCoord) text += G3DTools.getVector(mo.getG3DNode(g).getWorldPosition()) + " ";//mo.getWorldPosition() + " "; else text += G3DTools.getVector(mo.getG3DNode(g).getLocalPosition()) + " "; } final String fText = text; parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() { public void run() { setInfoText(fText); } }); Resource r[] = new Resource[mos.size()]; for (int i = 0; i < mos.size(); i++) { r[i] = mos.get(i).getResource(); } TranslateActionConstraints.addConstraints(r, detector); updateWorldCoord(g); return GraphRequestStatus.transactionComplete(); }; }; parent.getSession().asyncRead(r); } Vector3d getTranslate(Graph graph) { return getTranslate(graph,new Vector3d()); } Vector3d getTranslate(Graph graph,Vector3d offset) { Vector3d translate = new Vector3d(); Vector3d o = new Vector3d(); Vector3d d = new Vector3d(); parent.createPickRay(o, d); Vector3d p = G3DTools.getVector(mos.get(0).getG3DNode(graph).getWorldPosition());//gizmo.getPosition(); Vector3d dir = null; switch (gizmo.getSelected()) { case TransformGizmo.XYZ : Vector3d normal = camera.getUnNormalizedHeading(); if(!worldCoord) MathTools.rotate(q, normal, normal); normal.normalize(); double s[] = new double[1]; Vector3d r = new Vector3d(); if (MathTools.intersectStraightPlane(o, d, p, normal, r)) { r.sub(p); translate.x = r.x; translate.y = r.y; translate.z = r.z; } break; case TransformGizmo.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,o, d, i2, i1,s); translate.x = s[0]; break; case TransformGizmo.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,o, d, i2, i1,s); translate.y = s[0]; break; case TransformGizmo.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,o, d, i2, i1,s); translate.z = s[0]; break; case TransformGizmo.XY : normal = new Vector3d(0.0,0.0,1.0); if(!worldCoord) MathTools.rotate(q, normal, normal); r = new Vector3d(); if (MathTools.intersectStraightPlane(o, d, p, normal, r)) { r.sub(p); translate.x = r.x; translate.y = r.y; } break; case TransformGizmo.XZ : normal = new Vector3d(0.0,1.0,0.0); if(!worldCoord) MathTools.rotate(q, normal, normal); r = new Vector3d(); if (MathTools.intersectStraightPlane(o, d, p, normal, r)) { r.sub(p); translate.x = r.x; translate.z = r.z; } break; case TransformGizmo.YZ : normal = new Vector3d(1.0,0.0,0.0); if(!worldCoord) MathTools.rotate(q, normal, normal); r = new Vector3d(); if (MathTools.intersectStraightPlane(o, d, p, normal, r)) { r.sub(p); translate.y = r.y; translate.z = r.z; } break; default : return null; } translate.sub(offset); if (useConstraints && dir != null) { switch (gizmo.getSelected()) { case TransformGizmo.X: case TransformGizmo.Y: case TransformGizmo.Z: Vector3d t = new Vector3d(translate); // TODO : to the test against all translated objects and snap to closest one Point3d pos = G3DTools.getPoint(mos.get(0).getG3DNode(graph).getWorldPosition()); t.add(pos); Point3d snap = detector.getPointSnap2(t, dir); if (snap != null) { // System.out.print("t: " + translate); translate = new Vector3d(snap); translate.sub(pos); // System.out.println(" " + translate); } break; } } return translate; } Vector3d prevTranslate = new Vector3d(); @Override public void doChanges(Graph graph) throws Exception { if (input.mousePressed()) { boolean b = useConstraints; useConstraints = false; prevTranslate = getTranslate(graph); useConstraints = b; } if (input.mouseClicked()) { end(); return; } if (!input.mouseDragged()) { parent.getDefaultAction().update(); return; } detector.clearConstraintHighlights(); parent.setViewChanged(true); Vector3d translate = getTranslate(graph,prevTranslate); if (translate == null) { //cameraRotateAction.update(); parent.getDefaultAction().update(); updateGizmo(graph); return; } //translate.sub(prevTranslate); if ((input.dragModifiers() & MouseEvent.CTRL_MASK) > 0) { String text = ""; for (IGraphicsNode mo : mos) { Point3d p; if (worldCoord) p = G3DTools.getPoint(mo.getG3DNode(graph).getWorldPosition());//mo.getWorldPosition(); else p = G3DTools.getPoint(mo.getG3DNode(graph).getLocalPosition()); p.add(translate); if (gizmo.getSelected() == TransformGizmo.X || gizmo.getSelected() == TransformGizmo.XY || gizmo.getSelected() == TransformGizmo.XZ || gizmo.getSelected() == TransformGizmo.XYZ) { 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(); } if (gizmo.getSelected() == TransformGizmo.Y || gizmo.getSelected() == TransformGizmo.XY || gizmo.getSelected() == TransformGizmo.YZ || gizmo.getSelected() == TransformGizmo.XYZ) { 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(); } if (gizmo.getSelected() == TransformGizmo.Z || gizmo.getSelected() == TransformGizmo.YZ || gizmo.getSelected() == TransformGizmo.XZ || gizmo.getSelected() == TransformGizmo.XYZ) { 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(); } text += p + " "; if (worldCoord) G3DTools.setTuple3(mo.getG3DNode(graph).getWorldPosition(), p); else G3DTools.setTuple3(mo.getG3DNode(graph).getLocalPosition(), p); //mo.setWorldTranslation(p); } if (useConstraints) text+=detector.getSnapString(); setInfoText(text); } else { String text = ""; for (IGraphicsNode mo : mos) { Position pos; if (worldCoord) { pos = mo.getG3DNode(graph).getWorldPosition(); } else { pos = mo.getG3DNode(graph).getLocalPosition(); } Point3d p = G3DTools.getPoint(pos); p.add(translate); text += p; G3DTools.setTuple3(pos, p); } if (useConstraints) text+=detector.getSnapString(); setInfoText(text); // parent.getGraph().commitChanges(CommitMessage.CHANGE_MESSAGE); } updateGizmo(graph); } protected void updateGizmo(Graph graph) { List mos = parent.getSelectionAdapter().getSelectedObjects(); if (mos.size() == 0) { end(); return; } gizmo.update(G3DTools.getVector(mos.get(0).getG3DNode(graph).getWorldPosition()),camera.getCameraPos(),component); } public void setInfoText(String text) { } }