|
@@ -4,6 +4,7 @@ module BABYLON {
|
|
|
*/
|
|
|
export class PlaneRotationGizmo extends Gizmo {
|
|
|
private _dragBehavior:PointerDragBehavior;
|
|
|
+ private _pointerObserver:Nullable<Observer<PointerInfo>> = null;
|
|
|
/**
|
|
|
* Creates a PlaneRotationGizmo
|
|
|
* @param gizmoLayer The utility layer the gizmo will be added to
|
|
@@ -12,25 +13,30 @@ module BABYLON {
|
|
|
*/
|
|
|
constructor(gizmoLayer:UtilityLayerRenderer, planeNormal:Vector3, color:Color3){
|
|
|
super(gizmoLayer);
|
|
|
- this.updateGizmoRotationToMatchAttachedMesh=false;
|
|
|
|
|
|
// Create Material
|
|
|
var coloredMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
|
|
|
coloredMaterial.disableLighting = true;
|
|
|
coloredMaterial.emissiveColor = color;
|
|
|
+
|
|
|
+ var hoverMaterial = new BABYLON.StandardMaterial("", gizmoLayer.utilityLayerScene);
|
|
|
+ hoverMaterial.disableLighting = true;
|
|
|
+ hoverMaterial.emissiveColor = color.add(new Color3(0.2,0.2,0.2));
|
|
|
|
|
|
// Build mesh on root node
|
|
|
- var rotationMesh = BABYLON.Mesh.CreateTorus("torus", 3, 0.3, 20, gizmoLayer.utilityLayerScene, false);
|
|
|
- this._rootMesh.addChild(rotationMesh);
|
|
|
-
|
|
|
+ var parentMesh = new BABYLON.AbstractMesh("", gizmoLayer.utilityLayerScene);
|
|
|
+ var rotationMesh = BABYLON.Mesh.CreateTorus("torus", 3, 0.15, 20, gizmoLayer.utilityLayerScene, false);
|
|
|
+
|
|
|
// Position arrow pointing in its drag axis
|
|
|
rotationMesh.scaling.scaleInPlace(0.1);
|
|
|
rotationMesh.material = coloredMaterial;
|
|
|
rotationMesh.rotation.x = Math.PI/2;
|
|
|
- this._rootMesh.lookAt(this._rootMesh.position.subtract(planeNormal));
|
|
|
-
|
|
|
+ parentMesh.addChild(rotationMesh);
|
|
|
+ parentMesh.lookAt(this._rootMesh.position.subtract(planeNormal));
|
|
|
+
|
|
|
+ this._rootMesh.addChild(parentMesh);
|
|
|
// Add drag behavior to handle events when the gizmo is dragged
|
|
|
- this._dragBehavior = new PointerDragBehavior({dragPlaneNormal: new Vector3(0,0,1)});
|
|
|
+ this._dragBehavior = new PointerDragBehavior({dragPlaneNormal: planeNormal});
|
|
|
this._dragBehavior.moveAttached = false;
|
|
|
this._rootMesh.addBehavior(this._dragBehavior);
|
|
|
|
|
@@ -43,6 +49,9 @@ module BABYLON {
|
|
|
lastDragPosition = e.dragPlanePoint;
|
|
|
})
|
|
|
|
|
|
+ var rotationMatrix = new Matrix();
|
|
|
+ var planeNormalTowardsCamera = new Vector3();
|
|
|
+ var localPlaneNormalTowardsCamera = new Vector3();
|
|
|
this._dragBehavior.onDragObservable.add((event)=>{
|
|
|
if(!this.interactionsEnabled){
|
|
|
return;
|
|
@@ -57,28 +66,46 @@ module BABYLON {
|
|
|
var cross = Vector3.Cross(newVector,originalVector);
|
|
|
var dot = Vector3.Dot(newVector,originalVector);
|
|
|
var angle = Math.atan2(cross.length(), dot);
|
|
|
- var up = planeNormal.clone();
|
|
|
+ planeNormalTowardsCamera.copyFrom(planeNormal);
|
|
|
+ localPlaneNormalTowardsCamera.copyFrom(planeNormal);
|
|
|
+ if(this.updateGizmoRotationToMatchAttachedMesh){
|
|
|
+ this.attachedMesh.rotationQuaternion.toRotationMatrix(rotationMatrix);
|
|
|
+ localPlaneNormalTowardsCamera = Vector3.TransformCoordinates(planeNormalTowardsCamera, rotationMatrix);
|
|
|
+ }
|
|
|
// Flip up vector depending on which side the camera is on
|
|
|
if(gizmoLayer.utilityLayerScene.activeCamera){
|
|
|
var camVec = gizmoLayer.utilityLayerScene.activeCamera.position.subtract(this.attachedMesh.position);
|
|
|
- if(Vector3.Dot(camVec, up) > 0){
|
|
|
- up.scaleInPlace(-1);
|
|
|
+ if(Vector3.Dot(camVec, localPlaneNormalTowardsCamera) > 0){
|
|
|
+ planeNormalTowardsCamera.scaleInPlace(-1);
|
|
|
+ localPlaneNormalTowardsCamera.scaleInPlace(-1);
|
|
|
}
|
|
|
}
|
|
|
- var halfCircleSide = Vector3.Dot(up, cross) > 0.0;
|
|
|
+ var halfCircleSide = Vector3.Dot(localPlaneNormalTowardsCamera, cross) > 0.0;
|
|
|
if (halfCircleSide) angle = -angle;
|
|
|
|
|
|
|
|
|
// Convert angle and axis to quaternion (http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm)
|
|
|
var quaternionCoefficient = Math.sin(angle/2)
|
|
|
- var amountToRotate = new BABYLON.Quaternion(up.x*quaternionCoefficient,up.y*quaternionCoefficient,up.z*quaternionCoefficient,Math.cos(angle/2));
|
|
|
+ var amountToRotate = new BABYLON.Quaternion(planeNormalTowardsCamera.x*quaternionCoefficient,planeNormalTowardsCamera.y*quaternionCoefficient,planeNormalTowardsCamera.z*quaternionCoefficient,Math.cos(angle/2));
|
|
|
|
|
|
// Rotate selected mesh quaternion over fixed axis
|
|
|
- amountToRotate.multiplyToRef(this.attachedMesh.rotationQuaternion,this.attachedMesh.rotationQuaternion);
|
|
|
+ this.attachedMesh.rotationQuaternion.multiplyToRef(amountToRotate,this.attachedMesh.rotationQuaternion);
|
|
|
|
|
|
lastDragPosition = event.dragPlanePoint;
|
|
|
}
|
|
|
})
|
|
|
+
|
|
|
+ this._pointerObserver = gizmoLayer.utilityLayerScene.onPointerObservable.add((pointerInfo, eventState)=>{
|
|
|
+ if(pointerInfo.pickInfo && (this._rootMesh.getChildMeshes().indexOf(<Mesh>pointerInfo.pickInfo.pickedMesh) != -1)){
|
|
|
+ this._rootMesh.getChildMeshes().forEach((m)=>{
|
|
|
+ m.material = hoverMaterial;
|
|
|
+ });
|
|
|
+ }else{
|
|
|
+ this._rootMesh.getChildMeshes().forEach((m)=>{
|
|
|
+ m.material = coloredMaterial;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
protected _onInteractionsEnabledChanged(value:boolean){
|
|
@@ -89,6 +116,7 @@ module BABYLON {
|
|
|
* Disposes of the gizmo
|
|
|
*/
|
|
|
public dispose(){
|
|
|
+ this.gizmoLayer.utilityLayerScene.onPointerObservable.remove(this._pointerObserver);
|
|
|
this._dragBehavior.detach();
|
|
|
super.dispose();
|
|
|
}
|