/******************************************************************************* * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. * 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.processeditor.actions; import java.util.List; import javax.vecmath.AxisAngle4f; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import org.eclipse.jface.action.IToolBarManager; import org.simantics.db.Graph; import org.simantics.db.GraphRequestAdapter; import org.simantics.db.GraphRequestStatus; import org.simantics.db.Resource; import org.simantics.layer0.utils.EntityFactory; import org.simantics.layer0.utils.IEntity; import org.simantics.processeditor.Activator; import org.simantics.processeditor.ProcessResource; import org.simantics.processeditor.common.ControlPointTools; import org.simantics.processeditor.common.PipingTools2; import org.simantics.processeditor.stubs.FixedLengthInlineComponent; import org.simantics.processeditor.stubs.PipeControlPoint; import org.simantics.proconf.g3d.actions.ConstrainedTransformAction; import org.simantics.proconf.g3d.actions.TranslateActionConstraints; 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.AbstractGizmo; import org.simantics.proconf.g3d.gizmo.TransformGizmo; import org.simantics.proconf.g3d.gizmo.TransformInlineGizmo; /** * Action that allows translating VariableLengthInlineComontolPoints. * * TODO : Action won't show two gizmos when both ends can be moved * TODO : With loose ends, gizmo is in the middle of component, when it should be positioned on the end of the component * * * @author Marko Luukkainen * */ public class TranslateStraightAction extends ConstrainedTransformAction { private static final int CONNECTED = 0; private static final int LOOSE = 1; private AbstractGizmo gizmo; private TransformGizmo transformGizmo; private TransformInlineGizmo transformInlineGizmo; //private Straight straight; //private PipeControlPoint pcp; private Resource pcpResource; private int type; Vector3d prevTranslate = new Vector3d(); Point3d start; Point3d end; Vector3d dir; double istep = 10.0; int decimals = 2; public TranslateStraightAction(ThreeDimensionalEditorBase parent) { super(parent); transformGizmo = new TransformGizmo(component.getDisplaySystem().getRenderer()); transformInlineGizmo = new TransformInlineGizmo(component.getDisplaySystem().getRenderer()); } public void init() { this.setText("Translate"); this.setToolTipText("Translate one end of a straight"); this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/translate_d.png")); } @Override public boolean usable(Graph graph, List resources) { if (resources.size() != 1) return false; IEntity r = EntityFactory.create(graph,resources.get(0)); if (!r.isInstanceOf(ProcessResource.plant3Dresource.VariableLengthInlineComponent)) { return false; } FixedLengthInlineComponent flic = new FixedLengthInlineComponent(r); PipeControlPoint scp = flic.getControlPoint(); PipeControlPoint start = scp.getPrevious(); PipeControlPoint end = scp.getNext(); if (start == null) { pcpResource = scp.getResource(); type = LOOSE; return true; } if (end == null) { pcpResource = scp.getResource(); type = LOOSE; return true; } if (start.isInstanceOf(ProcessResource.plant3Dresource.BranchEndControlPoint)) { pcpResource = graph.getObjects(start.getResource(), ProcessResource.plant3Dresource.SubPointOf).iterator().next(); type = CONNECTED; return true; } if (end.isInstanceOf(ProcessResource.plant3Dresource.BranchEndControlPoint)) { pcpResource = graph.getObjects(end.getResource(), ProcessResource.plant3Dresource.SubPointOf).iterator().next(); type = CONNECTED; return true; } return false; } @Override public void deactivate() { super.deactivate(); parent.setGizmo(null); } @Override public void activate() { parent.getSession().syncRead(new GraphRequestAdapter() { @Override public GraphRequestStatus perform(Graph g) throws Exception { PipeControlPoint pcp = new PipeControlPoint(g,pcpResource); if (type == CONNECTED) { gizmo = transformInlineGizmo; start = new Point3d(); end = new Point3d(); dir = new Vector3d(); //ControlPointTools.getInlineControlPointEnds(pcp, start, end, dir); ControlPointTools.getInlineMovement(pcp, start, end); //PipingTools2.getInlineComponentEnds(ic, start, end); dir.set(end); dir.sub(start); //System.out.println(start + " " + end + " " + dir); Vector3d front = new Vector3d(1.0,0.0,0.0); Vector3d current = new Vector3d(dir); float angle = (float)current.angle(front); AxisAngle4f aa; if (angle < 0.01 || (Math.PI - angle) < 0.01) { aa = new AxisAngle4f(); } else { current.normalize(); Vector3d right = new Vector3d(); right.cross(front, current); right.normalize(); if (right.lengthSquared() < 0.01) { aa = new AxisAngle4f(); } else { aa = new AxisAngle4f((float) right.x, (float) right.y, (float) right.z, angle); } } transformInlineGizmo.setRotation(aa); } else { gizmo = transformGizmo; } parent.setGizmo(gizmo); component.getNoShadowRoot().attachChild(gizmo.getNode()); updateGizmo(pcp); TranslateActionConstraints.addConstraints(new Resource[]{pcpResource}, detector); parent.setViewChanged(true); return GraphRequestStatus.transactionComplete(); } }); } // FIXME : copy-paste from TranslateInlineAction.getTranslate() Vector3d getTranslate() { Vector3d translate = new Vector3d(); Vector3d o = new Vector3d(); Vector3d d = new Vector3d(); parent.createPickRay(o, d); // Vector3d p = gizmo.getPosition(); if (((TransformInlineGizmo) gizmo).isSelected()) { double s[] = new double[1]; Vector3d i1 = new Vector3d(); Vector3d i2 = new Vector3d(); s = new double[2]; MathTools.intersectStraightStraight(start, dir, o, d, i2, i1, s); translate.set(dir); if (s[0] < 0.0) s[0] = 0.0; else if (s[0] > 1.0) s[0] = 1.0; translate.scale(s[0]); translate.add(start); if (useConstraints) { Vector3d t = new Vector3d(translate); // FIXME : snapped point may be outside of proper range Point3d snap = detector.getPointSnap2(t, dir); if (snap != null) { translate = new Vector3d(snap); } } return translate; } return null; } // FIXME : copy-paste from TranslateAction.getTranslate(Vector3d v) Vector3d getTranslate(PipeControlPoint pcp, Vector3d offset) { Vector3d translate = new Vector3d(); Vector3d o = new Vector3d(); Vector3d d = new Vector3d(); parent.createPickRay(o, d); Vector3d p = ((TransformGizmo)gizmo).getPosition(); Vector3d dir = null; switch (((TransformGizmo)gizmo).getSelected()) { case TransformGizmo.XYZ : Vector3d normal = camera.getUnNormalizedHeading(); 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); 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); 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); 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); s = new double[1]; 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); s = new double[1]; 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); s = new double[1]; 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; } //System.out.println(translate + " " + offset); translate.sub(offset); if (useConstraints) { switch (((TransformGizmo)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(pcp.getLocalPosition()); 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; } } //System.out.println(translate); return translate; } @Override public void doChanges(Graph graph) throws Exception { PipeControlPoint pcp = new PipeControlPoint(graph, pcpResource); if (input.mousePressed()) { if (type == LOOSE) prevTranslate = getTranslate(pcp,new Vector3d()); } if (input.mouseClicked()) { //System.out.println("end"); end(); return; } if (!input.mouseDragged()) { parent.getDefaultAction().update(); return; } detector.clearConstraintHighlights(); parent.setViewChanged(true); Vector3d translate; if (type == CONNECTED) translate = getTranslate(); else translate = getTranslate(pcp,prevTranslate); if (translate == null) { //cameraRotateAction.update(); parent.getDefaultAction().update(); updateGizmo(pcp); return; } String text = ""; if (type == CONNECTED) { G3DTools.setTuple3(pcp.getWorldPosition(), translate); // mo.setLocalTranslation(translate); //text += GraphicsNodeTools.getWorldTranslation(mo.getGraphicsNode()) + " " + translate;// mo.getWorldPosition() if (useConstraints) text+=detector.getSnapString(); } else { G3DTools.addTuple3(pcp.getWorldPosition(), translate); // mo.modifyWorldTranslation(translate); //text += GraphicsNodeTools.getWorldTranslation(mo.getGraphicsNode()) + " ";//mo.getWorldPosition() + " "; if (useConstraints) text+=detector.getSnapString(); } setInfoText(text); updateGizmo(pcp); } protected void updateGizmo(PipeControlPoint pcp) { gizmo.update(G3DTools.getVector(pcp.getWorldPosition()), camera.getCameraPos(), component); } public void setInfoText(String text) { } }