| /******************************************************************************* |
| * Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| * 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: |
| * Pierre Allard, |
| * Regent L'Archeveque, |
| * Sebastien Gemme - initial API and implementation |
| * |
| * SPDX-License-Identifier: EPL-1.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.apogy.common.topology.ui.jme3.scene_objects; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.Callable; |
| |
| import javax.vecmath.Matrix4d; |
| import javax.vecmath.Vector3d; |
| |
| import org.eclipse.apogy.common.topology.ApogyCommonTopologyPackage; |
| import org.eclipse.apogy.common.topology.Node; |
| import org.eclipse.apogy.common.topology.PositionNode; |
| import org.eclipse.apogy.common.topology.RotationNode; |
| import org.eclipse.apogy.common.topology.TransformNode; |
| import org.eclipse.apogy.common.topology.ui.adapters.TransformNodeSceneObject; |
| import org.eclipse.apogy.common.topology.ui.jme3.JME3RenderEngineDelegate; |
| import org.eclipse.apogy.common.topology.ui.jme3.JME3Utilities; |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.Notifier; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.jme3.asset.AssetManager; |
| import com.jme3.math.Transform; |
| import com.jme3.scene.Geometry; |
| |
| public abstract class AbstractTransformationJME3SceneObject<T extends Node> extends DefaultJME3SceneObject<T> |
| implements TransformNodeSceneObject, Adapter { |
| private static final Logger Logger = LoggerFactory.getLogger(AbstractTransformationJME3SceneObject.class); |
| |
| private float previousAxisLength = 1.0f; |
| private boolean axisVisible = true; |
| |
| private Geometry axisGeometry = null; |
| |
| private final AssetManager assetManager; |
| |
| public AbstractTransformationJME3SceneObject(T topologyNode, JME3RenderEngineDelegate jme3RenderEngineDelegate) { |
| super(topologyNode, jme3RenderEngineDelegate); |
| |
| this.assetManager = this.jme3Application.getAssetManager(); |
| |
| // Register to the node. |
| registerListener(topologyNode); |
| |
| // Creates the 3DAxis. |
| this.axisGeometry = JME3Utilities.createAxis3D(1.0f, this.assetManager); |
| |
| // Attaches the 3DAxis if required. |
| if (this.axisVisible) |
| getAttachmentNode().attachChild(this.axisGeometry); |
| |
| // Updates the transform. |
| requestUpdate(); |
| } |
| |
| @Override |
| public void updateGeometry(float tpf) { |
| Matrix4d transformMatrix = new Matrix4d(); |
| transformMatrix.setIdentity(); |
| |
| if (getTopologyNode() instanceof TransformNode) { |
| TransformNode transformNode = (TransformNode) getTopologyNode(); |
| if (transformNode.asMatrix4d() != null) |
| transformMatrix = transformNode.asMatrix4d(); |
| } else if (getTopologyNode() instanceof PositionNode) { |
| PositionNode positionNode = (PositionNode) getTopologyNode(); |
| if (positionNode.getPosition() != null) { |
| transformMatrix.set(new Vector3d(positionNode.getPosition().asTuple3d())); |
| } |
| } else if (getTopologyNode() instanceof RotationNode) { |
| RotationNode rotationNode = (RotationNode) getTopologyNode(); |
| if (rotationNode.getRotationMatrix() != null) { |
| transformMatrix.set(rotationNode.getRotationMatrix().asMatrix3d()); |
| } |
| } |
| |
| Transform transform = JME3Utilities.createTransform(transformMatrix); |
| getAttachmentNode().setLocalTransform(transform); |
| } |
| |
| @Override |
| public void dispose() { |
| // Removes listener from topology node. |
| if (getTopologyNode() != null) { |
| unRegisterListener(getTopologyNode()); |
| } |
| super.dispose(); |
| } |
| |
| @Override |
| public List<Geometry> getGeometries() { |
| List<Geometry> geometries = new ArrayList<Geometry>(); |
| if (this.axisGeometry != null) |
| geometries.add(this.axisGeometry); |
| return geometries; |
| } |
| |
| @Override |
| public void setAxisVisible(final boolean visible) { |
| Logger.info("Setting axis visible to <" + visible + ">"); |
| this.axisVisible = visible; |
| this.jme3Application.enqueue(new Callable<Object>() { |
| @Override |
| public Object call() throws Exception { |
| if (AbstractTransformationJME3SceneObject.this.axisVisible) { |
| getAttachmentNode().attachChild(AbstractTransformationJME3SceneObject.this.axisGeometry); |
| } else { |
| getAttachmentNode().detachChild(AbstractTransformationJME3SceneObject.this.axisGeometry); |
| } |
| return null; |
| } |
| }); |
| } |
| |
| @Override |
| public void setAxisLength(double length) { |
| Logger.info("Setting axis length to <" + length + ">"); |
| |
| this.jme3Application.enqueue(new Callable<Object>() { |
| @Override |
| public Object call() throws Exception { |
| try { |
| float scale = (float) Math.abs(length) |
| / AbstractTransformationJME3SceneObject.this.previousAxisLength; |
| |
| // Scales existing axis. |
| if (AbstractTransformationJME3SceneObject.this.axisGeometry != null) |
| AbstractTransformationJME3SceneObject.this.axisGeometry.scale(scale); |
| |
| AbstractTransformationJME3SceneObject.this.previousAxisLength = (float) length; |
| } catch (Throwable t) { |
| Logger.error("Failed to setAxisLength(" + length + ")", t); |
| } |
| |
| return null; |
| } |
| }); |
| } |
| |
| @Override |
| public void notifyChanged(Notification notification) { |
| if (notification.getNotifier() instanceof TransformNode) { |
| int featureId = notification.getFeatureID(TransformNode.class); |
| if (featureId == ApogyCommonTopologyPackage.TRANSFORM_NODE__POSITION) { |
| // Unregister from previous position |
| if (notification.getOldValue() instanceof org.eclipse.apogy.common.math.Tuple3d) { |
| org.eclipse.apogy.common.math.Tuple3d oldValue = (org.eclipse.apogy.common.math.Tuple3d) notification |
| .getOldValue(); |
| oldValue.eAdapters().remove(this); |
| } |
| requestUpdate(); |
| |
| // Register to new position. |
| if (notification.getNewValue() instanceof org.eclipse.apogy.common.math.Tuple3d) { |
| org.eclipse.apogy.common.math.Tuple3d newValue = (org.eclipse.apogy.common.math.Tuple3d) notification |
| .getNewValue(); |
| newValue.eAdapters().add(this); |
| } |
| } else if (featureId == ApogyCommonTopologyPackage.TRANSFORM_NODE__ROTATION_MATRIX) { |
| // Unregister from previous matrix |
| if (notification.getOldValue() instanceof org.eclipse.apogy.common.math.Matrix3x3) { |
| org.eclipse.apogy.common.math.Matrix3x3 oldValue = (org.eclipse.apogy.common.math.Matrix3x3) notification |
| .getOldValue(); |
| oldValue.eAdapters().remove(this); |
| } |
| requestUpdate(); |
| |
| // Register to new matrix. |
| if (notification.getNewValue() instanceof org.eclipse.apogy.common.math.Matrix3x3) { |
| org.eclipse.apogy.common.math.Matrix3x3 newValue = (org.eclipse.apogy.common.math.Matrix3x3) notification |
| .getNewValue(); |
| newValue.eAdapters().add(this); |
| } |
| } |
| } else if (notification.getNotifier() instanceof RotationNode) { |
| int featureId = notification.getFeatureID(RotationNode.class); |
| if (featureId == ApogyCommonTopologyPackage.ROTATION_NODE__ROTATION_MATRIX) { |
| // Unregister from previous matrix |
| if (notification.getOldValue() instanceof org.eclipse.apogy.common.math.Matrix3x3) { |
| org.eclipse.apogy.common.math.Matrix3x3 oldValue = (org.eclipse.apogy.common.math.Matrix3x3) notification |
| .getOldValue(); |
| oldValue.eAdapters().remove(this); |
| } |
| requestUpdate(); |
| |
| // Register to new matrix. |
| if (notification.getNewValue() instanceof org.eclipse.apogy.common.math.Matrix3x3) { |
| org.eclipse.apogy.common.math.Matrix3x3 newValue = (org.eclipse.apogy.common.math.Matrix3x3) notification |
| .getNewValue(); |
| newValue.eAdapters().add(this); |
| } |
| } |
| } else if (notification.getNotifier() instanceof PositionNode) { |
| int featureId = notification.getFeatureID(PositionNode.class); |
| if (featureId == ApogyCommonTopologyPackage.POSITION_NODE__POSITION) { |
| // Unregister from previous position |
| if (notification.getOldValue() instanceof org.eclipse.apogy.common.math.Tuple3d) { |
| org.eclipse.apogy.common.math.Tuple3d oldValue = (org.eclipse.apogy.common.math.Tuple3d) notification |
| .getOldValue(); |
| oldValue.eAdapters().remove(this); |
| } |
| requestUpdate(); |
| |
| // Register to new position. |
| if (notification.getNewValue() instanceof org.eclipse.apogy.common.math.Tuple3d) { |
| org.eclipse.apogy.common.math.Tuple3d newValue = (org.eclipse.apogy.common.math.Tuple3d) notification |
| .getNewValue(); |
| newValue.eAdapters().add(this); |
| } |
| } |
| } else if (notification.getNotifier() instanceof org.eclipse.apogy.common.math.Tuple3d) { |
| requestUpdate(); |
| } else if (notification.getNotifier() instanceof org.eclipse.apogy.common.math.Matrix3x3) { |
| requestUpdate(); |
| } |
| } |
| |
| @Override |
| public Notifier getTarget() { |
| return null; |
| } |
| |
| @Override |
| public void setTarget(Notifier newTarget) { |
| } |
| |
| @Override |
| public boolean isAdapterForType(Object type) { |
| return false; |
| } |
| |
| protected void registerListener(T topologyNode) { |
| topologyNode.eAdapters().add(this); |
| if (topologyNode instanceof TransformNode) { |
| TransformNode transformNode = (TransformNode) topologyNode; |
| if (transformNode.getRotationMatrix() != null) |
| transformNode.getRotationMatrix().eAdapters().add(this); |
| if (transformNode.getPosition() != null) |
| transformNode.getPosition().eAdapters().add(this); |
| } else if (topologyNode instanceof RotationNode) { |
| RotationNode rotationNode = (RotationNode) topologyNode; |
| if (rotationNode.getRotationMatrix() != null) |
| rotationNode.getRotationMatrix().eAdapters().add(this); |
| } else if (topologyNode instanceof PositionNode) { |
| PositionNode positionNode = (PositionNode) topologyNode; |
| if (positionNode.getPosition() != null) |
| positionNode.getPosition().eAdapters().add(this); |
| } |
| } |
| |
| protected void unRegisterListener(T topologyNode) { |
| topologyNode.eAdapters().add(this); |
| if (topologyNode instanceof TransformNode) { |
| TransformNode transformNode = (TransformNode) topologyNode; |
| if (transformNode.getRotationMatrix() != null) |
| transformNode.getRotationMatrix().eAdapters().remove(this); |
| if (transformNode.getPosition() != null) |
| transformNode.getPosition().eAdapters().remove(this); |
| } else if (topologyNode instanceof RotationNode) { |
| RotationNode rotationNode = (RotationNode) topologyNode; |
| if (rotationNode.getRotationMatrix() != null) |
| rotationNode.getRotationMatrix().eAdapters().remove(this); |
| } else if (topologyNode instanceof PositionNode) { |
| PositionNode positionNode = (PositionNode) topologyNode; |
| if (positionNode.getPosition() != null) |
| positionNode.getPosition().eAdapters().remove(this); |
| } |
| } |
| } |