1 /*******************************************************************************
\r
2 * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package org.simantics.proconf.g3d.actions;
\r
13 import java.awt.event.MouseEvent;
\r
14 import java.math.BigDecimal;
\r
15 import java.util.Collection;
\r
16 import java.util.List;
\r
18 import javax.vecmath.AxisAngle4d;
\r
19 import javax.vecmath.AxisAngle4f;
\r
20 import javax.vecmath.Point3d;
\r
21 import javax.vecmath.Quat4d;
\r
22 import javax.vecmath.Vector3d;
\r
24 import org.eclipse.jface.action.Action;
\r
25 import org.eclipse.jface.action.IToolBarManager;
\r
26 import org.simantics.db.Graph;
\r
27 import org.simantics.db.GraphRequest;
\r
28 import org.simantics.db.GraphRequestAdapter;
\r
29 import org.simantics.db.GraphRequestStatus;
\r
30 import org.simantics.db.Resource;
\r
31 import org.simantics.layer0.utils.IEntity;
\r
32 import org.simantics.layer0.utils.EntityFactory;
\r
33 import org.simantics.proconf.g3d.Activator;
\r
34 import org.simantics.proconf.g3d.Resources;
\r
35 import org.simantics.proconf.g3d.base.G3DTools;
\r
36 import org.simantics.proconf.g3d.base.MathTools;
\r
37 import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;
\r
38 import org.simantics.proconf.g3d.gizmo.TransformGizmo;
\r
39 import org.simantics.proconf.g3d.scenegraph.IGraphicsNode;
\r
40 import org.simantics.proconf.g3d.stubs.Orientation;
\r
41 import org.simantics.proconf.g3d.stubs.Position;
\r
44 public class TranslateAction extends ConstrainedTransformAction {
\r
47 private TransformGizmo gizmo;
\r
49 private double istep = 10.0;
\r
50 private int decimals = 2;
\r
53 private Action csAction;
\r
54 List<IGraphicsNode> mos = null;
\r
56 private boolean worldCoord = true;
\r
59 private AxisAngle4d aa;
\r
62 public TranslateAction(ThreeDimensionalEditorBase parent) {
\r
65 csAction = new Action("World",Action.AS_CHECK_BOX) {
\r
67 GraphRequest r = new GraphRequestAdapter() {
\r
69 public GraphRequestStatus perform(Graph g) throws Exception {
\r
70 setWorldCoord(g,!isChecked());
\r
71 return GraphRequestStatus.transactionComplete();
\r
74 TranslateAction.this.parent.getSession().asyncRead(r);
\r
78 gizmo = new TransformGizmo(component.getDisplaySystem().getRenderer());
\r
81 public void init() {
\r
82 this.setText("Translate");
\r
83 this.setToolTipText("Translate the object");
\r
84 this.setImageDescriptor(Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/translate.png"));
\r
88 public boolean usable(Graph graph, List<Resource> resources) {
\r
89 if (resources.size() == 0)
\r
91 for (Resource r : resources) {
\r
92 IEntity t = EntityFactory.create(graph,r);
\r
93 if (t.isInstanceOf(Resources.g3dResource.G3DNode)) {
\r
94 Collection<IEntity> p = t.getRelatedObjects(Resources.g3dResource.HasLocalPosition);
\r
95 if (p == null || p.size() != 1)
\r
105 public void deactivate() {
\r
106 super.deactivate();
\r
107 parent.setGizmo(null);
\r
111 private void setWorldCoord(Graph graph,boolean b) {
\r
112 if (worldCoord == b)
\r
115 updateWorldCoord(graph);
\r
118 private void updateWorldCoord(Graph graph) {
\r
120 csAction.setText("World");
\r
121 gizmo.setRotation(new AxisAngle4f());
\r
125 csAction.setText("Local");
\r
126 Orientation o = mos.get(0).getParent().getG3DNode(graph).getWorldOrientation();
\r
128 aa = new AxisAngle4d();
\r
130 aa = G3DTools.getOrientation(o);
\r
133 gizmo.setRotation(new AxisAngle4f(aa));
\r
137 // if (manager != null)
\r
138 // parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() {
\r
139 // public void run() {
\r
140 // manager.update(true);
\r
144 this.parent.setViewChanged(true);
\r
147 public void fillToolBar(IToolBarManager manager) {
\r
148 super.fillToolBar(manager);
\r
149 csAction.setChecked(!worldCoord);
\r
150 manager.add(csAction);
\r
154 public void activate() {
\r
155 GraphRequest r = new GraphRequestAdapter() {
\r
156 public GraphRequestStatus perform(Graph g) throws Exception {
\r
157 parent.setGizmo(gizmo);
\r
161 component.getNoShadowRoot().attachChild(gizmo.getNode());
\r
164 mos = parent.getSelectionAdapter().getSelectedObjects();
\r
165 for (IGraphicsNode mo : mos) {
\r
167 text += G3DTools.getVector(mo.getG3DNode(g).getWorldPosition()) + " ";//mo.getWorldPosition() + " ";
\r
169 text += G3DTools.getVector(mo.getG3DNode(g).getLocalPosition()) + " ";
\r
171 final String fText = text;
\r
172 parent.getRenderingComposite().getDisplay().asyncExec(new Runnable() {
\r
173 public void run() {
\r
174 setInfoText(fText);
\r
178 Resource r[] = new Resource[mos.size()];
\r
179 for (int i = 0; i < mos.size(); i++) {
\r
180 r[i] = mos.get(i).getResource();
\r
183 TranslateActionConstraints.addConstraints(r, detector);
\r
184 updateWorldCoord(g);
\r
185 return GraphRequestStatus.transactionComplete();
\r
189 parent.getSession().asyncRead(r);
\r
193 Vector3d getTranslate(Graph graph) {
\r
194 return getTranslate(graph,new Vector3d());
\r
197 Vector3d getTranslate(Graph graph,Vector3d offset) {
\r
198 Vector3d translate = new Vector3d();
\r
199 Vector3d o = new Vector3d();
\r
200 Vector3d d = new Vector3d();
\r
201 parent.createPickRay(o, d);
\r
202 Vector3d p = G3DTools.getVector(mos.get(0).getG3DNode(graph).getWorldPosition());//gizmo.getPosition();
\r
203 Vector3d dir = null;
\r
204 switch (gizmo.getSelected()) {
\r
205 case TransformGizmo.XYZ :
\r
206 Vector3d normal = camera.getUnNormalizedHeading();
\r
208 MathTools.rotate(q, normal, normal);
\r
209 normal.normalize();
\r
210 double s[] = new double[1];
\r
211 Vector3d r = new Vector3d();
\r
212 if (MathTools.intersectStraightPlane(o, d, p, normal, r)) {
\r
219 case TransformGizmo.X :
\r
220 dir = new Vector3d(1.0,0.0,0.0);
\r
222 MathTools.rotate(q, dir, dir);
\r
223 Vector3d i1 = new Vector3d();
\r
224 Vector3d i2 = new Vector3d();
\r
226 MathTools.intersectStraightStraight( p, dir,o, d, i2, i1,s);
\r
227 translate.x = s[0];
\r
230 case TransformGizmo.Y :
\r
231 dir = new Vector3d(0.0,1.0,0.0);
\r
233 MathTools.rotate(q, dir, dir);
\r
234 i1 = new Vector3d();
\r
235 i2 = new Vector3d();
\r
237 MathTools.intersectStraightStraight( p, dir,o, d, i2, i1,s);
\r
238 translate.y = s[0];
\r
240 case TransformGizmo.Z :
\r
241 dir = new Vector3d(0.0,0.0,1.0);
\r
243 MathTools.rotate(q, dir, dir);
\r
244 i1 = new Vector3d();
\r
245 i2 = new Vector3d();
\r
247 MathTools.intersectStraightStraight( p, dir,o, d, i2, i1,s);
\r
248 translate.z = s[0];
\r
250 case TransformGizmo.XY :
\r
251 normal = new Vector3d(0.0,0.0,1.0);
\r
253 MathTools.rotate(q, normal, normal);
\r
254 r = new Vector3d();
\r
255 if (MathTools.intersectStraightPlane(o, d, p, normal, r)) {
\r
261 case TransformGizmo.XZ :
\r
262 normal = new Vector3d(0.0,1.0,0.0);
\r
264 MathTools.rotate(q, normal, normal);
\r
265 r = new Vector3d();
\r
266 if (MathTools.intersectStraightPlane(o, d, p, normal, r)) {
\r
272 case TransformGizmo.YZ :
\r
273 normal = new Vector3d(1.0,0.0,0.0);
\r
275 MathTools.rotate(q, normal, normal);
\r
276 r = new Vector3d();
\r
277 if (MathTools.intersectStraightPlane(o, d, p, normal, r)) {
\r
287 translate.sub(offset);
\r
289 if (useConstraints && dir != null) {
\r
290 switch (gizmo.getSelected()) {
\r
291 case TransformGizmo.X:
\r
292 case TransformGizmo.Y:
\r
293 case TransformGizmo.Z:
\r
294 Vector3d t = new Vector3d(translate);
\r
295 // TODO : to the test against all translated objects and snap to closest one
\r
296 Point3d pos = G3DTools.getPoint(mos.get(0).getG3DNode(graph).getWorldPosition());
\r
298 Point3d snap = detector.getPointSnap2(t, dir);
\r
299 if (snap != null) {
\r
300 // System.out.print("t: " + translate);
\r
301 translate = new Vector3d(snap);
\r
302 translate.sub(pos);
\r
303 // System.out.println(" " + translate);
\r
312 Vector3d prevTranslate = new Vector3d();
\r
315 public void doChanges(Graph graph) throws Exception {
\r
316 if (input.mousePressed()) {
\r
317 boolean b = useConstraints;
\r
318 useConstraints = false;
\r
319 prevTranslate = getTranslate(graph);
\r
320 useConstraints = b;
\r
322 if (input.mouseClicked()) {
\r
326 if (!input.mouseDragged()) {
\r
327 parent.getDefaultAction().update();
\r
330 detector.clearConstraintHighlights();
\r
331 parent.setViewChanged(true);
\r
335 Vector3d translate = getTranslate(graph,prevTranslate);
\r
337 if (translate == null) {
\r
338 //cameraRotateAction.update();
\r
339 parent.getDefaultAction().update();
\r
340 updateGizmo(graph);
\r
343 //translate.sub(prevTranslate);
\r
345 if ((input.dragModifiers() & MouseEvent.CTRL_MASK) > 0) {
\r
347 for (IGraphicsNode mo : mos) {
\r
351 p = G3DTools.getPoint(mo.getG3DNode(graph).getWorldPosition());//mo.getWorldPosition();
\r
353 p = G3DTools.getPoint(mo.getG3DNode(graph).getLocalPosition());
\r
355 if (gizmo.getSelected() == TransformGizmo.X || gizmo.getSelected() == TransformGizmo.XY || gizmo.getSelected() == TransformGizmo.XZ || gizmo.getSelected() == TransformGizmo.XYZ) {
\r
356 p.x = Math.round(istep * p.x) / istep;
\r
357 BigDecimal bx = new BigDecimal(p.x);
\r
358 bx.setScale(decimals, BigDecimal.ROUND_HALF_UP);
\r
359 p.x = bx.doubleValue();
\r
361 if (gizmo.getSelected() == TransformGizmo.Y || gizmo.getSelected() == TransformGizmo.XY || gizmo.getSelected() == TransformGizmo.YZ || gizmo.getSelected() == TransformGizmo.XYZ) {
\r
362 p.y = Math.round(istep * p.y) / istep;
\r
363 BigDecimal by = new BigDecimal(p.y);
\r
364 by.setScale(decimals, BigDecimal.ROUND_HALF_UP);
\r
365 p.y = by.doubleValue();
\r
367 if (gizmo.getSelected() == TransformGizmo.Z || gizmo.getSelected() == TransformGizmo.YZ || gizmo.getSelected() == TransformGizmo.XZ || gizmo.getSelected() == TransformGizmo.XYZ) {
\r
368 p.z = Math.round(istep * p.z) / istep;
\r
369 BigDecimal bz = new BigDecimal(p.z);
\r
370 bz.setScale(decimals, BigDecimal.ROUND_HALF_UP);
\r
371 p.z = bz.doubleValue();
\r
375 G3DTools.setTuple3(mo.getG3DNode(graph).getWorldPosition(), p);
\r
377 G3DTools.setTuple3(mo.getG3DNode(graph).getLocalPosition(), p);
\r
378 //mo.setWorldTranslation(p);
\r
381 if (useConstraints)
\r
382 text+=detector.getSnapString();
\r
387 for (IGraphicsNode mo : mos) {
\r
390 pos = mo.getG3DNode(graph).getWorldPosition();
\r
392 pos = mo.getG3DNode(graph).getLocalPosition();
\r
394 Point3d p = G3DTools.getPoint(pos);
\r
397 G3DTools.setTuple3(pos, p);
\r
399 if (useConstraints)
\r
400 text+=detector.getSnapString();
\r
402 // parent.getGraph().commitChanges(CommitMessage.CHANGE_MESSAGE);
\r
404 updateGizmo(graph);
\r
408 protected void updateGizmo(Graph graph) {
\r
409 List<IGraphicsNode> mos = parent.getSelectionAdapter().getSelectedObjects();
\r
410 if (mos.size() == 0) {
\r
414 gizmo.update(G3DTools.getVector(mos.get(0).getG3DNode(graph).getWorldPosition()),camera.getCameraPos(),component);
\r
418 public void setInfoText(String text) {
\r