|
@@ -15,20 +15,27 @@ import { ScaleGizmo } from "./scaleGizmo";
|
|
import { BoundingBoxGizmo } from "./boundingBoxGizmo";
|
|
import { BoundingBoxGizmo } from "./boundingBoxGizmo";
|
|
|
|
|
|
/**
|
|
/**
|
|
- * Helps setup gizmo's in the scene to rotate/scale/position meshes
|
|
|
|
|
|
+ * Helps setup gizmo's in the scene to rotate/scale/position nodes
|
|
*/
|
|
*/
|
|
export class GizmoManager implements IDisposable {
|
|
export class GizmoManager implements IDisposable {
|
|
/**
|
|
/**
|
|
* Gizmo's created by the gizmo manager, gizmo will be null until gizmo has been enabled for the first time
|
|
* Gizmo's created by the gizmo manager, gizmo will be null until gizmo has been enabled for the first time
|
|
*/
|
|
*/
|
|
public gizmos: { positionGizmo: Nullable<PositionGizmo>, rotationGizmo: Nullable<RotationGizmo>, scaleGizmo: Nullable<ScaleGizmo>, boundingBoxGizmo: Nullable<BoundingBoxGizmo> };
|
|
public gizmos: { positionGizmo: Nullable<PositionGizmo>, rotationGizmo: Nullable<RotationGizmo>, scaleGizmo: Nullable<ScaleGizmo>, boundingBoxGizmo: Nullable<BoundingBoxGizmo> };
|
|
|
|
+
|
|
/** When true, the gizmo will be detached from the current object when a pointer down occurs with an empty picked mesh */
|
|
/** When true, the gizmo will be detached from the current object when a pointer down occurs with an empty picked mesh */
|
|
public clearGizmoOnEmptyPointerEvent = false;
|
|
public clearGizmoOnEmptyPointerEvent = false;
|
|
|
|
+
|
|
/** Fires an event when the manager is attached to a mesh */
|
|
/** Fires an event when the manager is attached to a mesh */
|
|
public onAttachedToMeshObservable = new Observable<Nullable<AbstractMesh>>();
|
|
public onAttachedToMeshObservable = new Observable<Nullable<AbstractMesh>>();
|
|
|
|
+
|
|
|
|
+ /** Fires an event when the manager is attached to a node */
|
|
|
|
+ public onAttachedToNodeObservable = new Observable<Nullable<Node>>();
|
|
|
|
+
|
|
private _gizmosEnabled = { positionGizmo: false, rotationGizmo: false, scaleGizmo: false, boundingBoxGizmo: false };
|
|
private _gizmosEnabled = { positionGizmo: false, rotationGizmo: false, scaleGizmo: false, boundingBoxGizmo: false };
|
|
private _pointerObserver: Nullable<Observer<PointerInfo>> = null;
|
|
private _pointerObserver: Nullable<Observer<PointerInfo>> = null;
|
|
private _attachedMesh: Nullable<AbstractMesh> = null;
|
|
private _attachedMesh: Nullable<AbstractMesh> = null;
|
|
|
|
+ private _attachedNode: Nullable<Node> = null;
|
|
private _boundingBoxColor = Color3.FromHexString("#0984e3");
|
|
private _boundingBoxColor = Color3.FromHexString("#0984e3");
|
|
private _defaultUtilityLayer: UtilityLayerRenderer;
|
|
private _defaultUtilityLayer: UtilityLayerRenderer;
|
|
private _defaultKeepDepthUtilityLayer: UtilityLayerRenderer;
|
|
private _defaultKeepDepthUtilityLayer: UtilityLayerRenderer;
|
|
@@ -42,7 +49,11 @@ export class GizmoManager implements IDisposable {
|
|
*/
|
|
*/
|
|
public attachableMeshes: Nullable<Array<AbstractMesh>> = null;
|
|
public attachableMeshes: Nullable<Array<AbstractMesh>> = null;
|
|
/**
|
|
/**
|
|
- * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh. (Default: true)
|
|
|
|
|
|
+ * Array of nodes which will have the gizmo attached when a pointer selected them. If null, all nodes are attachable. (Default: null)
|
|
|
|
+ */
|
|
|
|
+ public attachableNodes: Nullable<Array<Node>> = null;
|
|
|
|
+ /**
|
|
|
|
+ * If pointer events should perform attaching/detaching a gizmo, if false this can be done manually via attachToMesh/attachToNode. (Default: true)
|
|
*/
|
|
*/
|
|
public usePointerToAttachGizmos = true;
|
|
public usePointerToAttachGizmos = true;
|
|
|
|
|
|
@@ -124,7 +135,11 @@ export class GizmoManager implements IDisposable {
|
|
if (this._attachedMesh) {
|
|
if (this._attachedMesh) {
|
|
this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
|
|
this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
|
|
}
|
|
}
|
|
|
|
+ if (this._attachedNode) {
|
|
|
|
+ this._attachedNode.removeBehavior(this.boundingBoxDragBehavior);
|
|
|
|
+ }
|
|
this._attachedMesh = mesh;
|
|
this._attachedMesh = mesh;
|
|
|
|
+ this._attachedNode = null;
|
|
for (var key in this.gizmos) {
|
|
for (var key in this.gizmos) {
|
|
var gizmo = <Nullable<Gizmo>>((<any>this.gizmos)[key]);
|
|
var gizmo = <Nullable<Gizmo>>((<any>this.gizmos)[key]);
|
|
if (gizmo && (<any>this._gizmosEnabled)[key]) {
|
|
if (gizmo && (<any>this._gizmosEnabled)[key]) {
|
|
@@ -138,6 +153,31 @@ export class GizmoManager implements IDisposable {
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
|
|
+ * Attaches a set of gizmos to the specified node
|
|
|
|
+ * @param node The node the gizmo's should be attached to
|
|
|
|
+ */
|
|
|
|
+ public attachToNode(node: Nullable<Node>) {
|
|
|
|
+ if (this._attachedMesh) {
|
|
|
|
+ this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
|
|
|
|
+ }
|
|
|
|
+ if (this._attachedNode) {
|
|
|
|
+ this._attachedNode.removeBehavior(this.boundingBoxDragBehavior);
|
|
|
|
+ }
|
|
|
|
+ this._attachedMesh = null;
|
|
|
|
+ this._attachedNode = node;
|
|
|
|
+ for (var key in this.gizmos) {
|
|
|
|
+ var gizmo = <Nullable<Gizmo>>((<any>this.gizmos)[key]);
|
|
|
|
+ if (gizmo && (<any>this._gizmosEnabled)[key]) {
|
|
|
|
+ gizmo.attachedNode = node;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (this.boundingBoxGizmoEnabled && this._attachedNode) {
|
|
|
|
+ this._attachedNode.addBehavior(this.boundingBoxDragBehavior);
|
|
|
|
+ }
|
|
|
|
+ this.onAttachedToNodeObservable.notifyObservers(node);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
* If the position gizmo is enabled
|
|
* If the position gizmo is enabled
|
|
*/
|
|
*/
|
|
public set positionGizmoEnabled(value: boolean) {
|
|
public set positionGizmoEnabled(value: boolean) {
|
|
@@ -145,9 +185,13 @@ export class GizmoManager implements IDisposable {
|
|
if (!this.gizmos.positionGizmo) {
|
|
if (!this.gizmos.positionGizmo) {
|
|
this.gizmos.positionGizmo = new PositionGizmo(this._defaultUtilityLayer, this._thickness);
|
|
this.gizmos.positionGizmo = new PositionGizmo(this._defaultUtilityLayer, this._thickness);
|
|
}
|
|
}
|
|
- this.gizmos.positionGizmo.attachedMesh = this._attachedMesh;
|
|
|
|
|
|
+ if (this._attachedNode) {
|
|
|
|
+ this.gizmos.positionGizmo.attachedNode = this._attachedNode;
|
|
|
|
+ } else {
|
|
|
|
+ this.gizmos.positionGizmo.attachedMesh = this._attachedMesh;
|
|
|
|
+ }
|
|
} else if (this.gizmos.positionGizmo) {
|
|
} else if (this.gizmos.positionGizmo) {
|
|
- this.gizmos.positionGizmo.attachedMesh = null;
|
|
|
|
|
|
+ this.gizmos.positionGizmo.attachedNode = null;
|
|
}
|
|
}
|
|
this._gizmosEnabled.positionGizmo = value;
|
|
this._gizmosEnabled.positionGizmo = value;
|
|
}
|
|
}
|
|
@@ -162,9 +206,13 @@ export class GizmoManager implements IDisposable {
|
|
if (!this.gizmos.rotationGizmo) {
|
|
if (!this.gizmos.rotationGizmo) {
|
|
this.gizmos.rotationGizmo = new RotationGizmo(this._defaultUtilityLayer, 32, false, this._thickness);
|
|
this.gizmos.rotationGizmo = new RotationGizmo(this._defaultUtilityLayer, 32, false, this._thickness);
|
|
}
|
|
}
|
|
- this.gizmos.rotationGizmo.attachedMesh = this._attachedMesh;
|
|
|
|
|
|
+ if (this._attachedNode) {
|
|
|
|
+ this.gizmos.rotationGizmo.attachedNode = this._attachedNode;
|
|
|
|
+ } else {
|
|
|
|
+ this.gizmos.rotationGizmo.attachedMesh = this._attachedMesh;
|
|
|
|
+ }
|
|
} else if (this.gizmos.rotationGizmo) {
|
|
} else if (this.gizmos.rotationGizmo) {
|
|
- this.gizmos.rotationGizmo.attachedMesh = null;
|
|
|
|
|
|
+ this.gizmos.rotationGizmo.attachedNode = null;
|
|
}
|
|
}
|
|
this._gizmosEnabled.rotationGizmo = value;
|
|
this._gizmosEnabled.rotationGizmo = value;
|
|
}
|
|
}
|
|
@@ -177,9 +225,13 @@ export class GizmoManager implements IDisposable {
|
|
public set scaleGizmoEnabled(value: boolean) {
|
|
public set scaleGizmoEnabled(value: boolean) {
|
|
if (value) {
|
|
if (value) {
|
|
this.gizmos.scaleGizmo = this.gizmos.scaleGizmo || new ScaleGizmo(this._defaultUtilityLayer, this._thickness);
|
|
this.gizmos.scaleGizmo = this.gizmos.scaleGizmo || new ScaleGizmo(this._defaultUtilityLayer, this._thickness);
|
|
- this.gizmos.scaleGizmo.attachedMesh = this._attachedMesh;
|
|
|
|
|
|
+ if (this._attachedNode) {
|
|
|
|
+ this.gizmos.scaleGizmo.attachedNode = this._attachedNode;
|
|
|
|
+ } else {
|
|
|
|
+ this.gizmos.scaleGizmo.attachedMesh = this._attachedMesh;
|
|
|
|
+ }
|
|
} else if (this.gizmos.scaleGizmo) {
|
|
} else if (this.gizmos.scaleGizmo) {
|
|
- this.gizmos.scaleGizmo.attachedMesh = null;
|
|
|
|
|
|
+ this.gizmos.scaleGizmo.attachedNode = null;
|
|
}
|
|
}
|
|
this._gizmosEnabled.scaleGizmo = value;
|
|
this._gizmosEnabled.scaleGizmo = value;
|
|
}
|
|
}
|
|
@@ -192,16 +244,26 @@ export class GizmoManager implements IDisposable {
|
|
public set boundingBoxGizmoEnabled(value: boolean) {
|
|
public set boundingBoxGizmoEnabled(value: boolean) {
|
|
if (value) {
|
|
if (value) {
|
|
this.gizmos.boundingBoxGizmo = this.gizmos.boundingBoxGizmo || new BoundingBoxGizmo(this._boundingBoxColor, this._defaultKeepDepthUtilityLayer);
|
|
this.gizmos.boundingBoxGizmo = this.gizmos.boundingBoxGizmo || new BoundingBoxGizmo(this._boundingBoxColor, this._defaultKeepDepthUtilityLayer);
|
|
- this.gizmos.boundingBoxGizmo.attachedMesh = this._attachedMesh;
|
|
|
|
|
|
+ if (this._attachedMesh) {
|
|
|
|
+ this.gizmos.boundingBoxGizmo.attachedMesh = this._attachedMesh;
|
|
|
|
+ } else {
|
|
|
|
+ this.gizmos.boundingBoxGizmo.attachedNode = this._attachedNode;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (this._attachedMesh) {
|
|
if (this._attachedMesh) {
|
|
this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
|
|
this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
|
|
this._attachedMesh.addBehavior(this.boundingBoxDragBehavior);
|
|
this._attachedMesh.addBehavior(this.boundingBoxDragBehavior);
|
|
|
|
+ } else if (this._attachedNode) {
|
|
|
|
+ this._attachedNode.removeBehavior(this.boundingBoxDragBehavior);
|
|
|
|
+ this._attachedNode.addBehavior(this.boundingBoxDragBehavior);
|
|
}
|
|
}
|
|
} else if (this.gizmos.boundingBoxGizmo) {
|
|
} else if (this.gizmos.boundingBoxGizmo) {
|
|
if (this._attachedMesh) {
|
|
if (this._attachedMesh) {
|
|
this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
|
|
this._attachedMesh.removeBehavior(this.boundingBoxDragBehavior);
|
|
|
|
+ } else if (this._attachedNode) {
|
|
|
|
+ this._attachedNode.removeBehavior(this.boundingBoxDragBehavior);
|
|
}
|
|
}
|
|
- this.gizmos.boundingBoxGizmo.attachedMesh = null;
|
|
|
|
|
|
+ this.gizmos.boundingBoxGizmo.attachedNode = null;
|
|
}
|
|
}
|
|
this._gizmosEnabled.boundingBoxGizmo = value;
|
|
this._gizmosEnabled.boundingBoxGizmo = value;
|
|
}
|
|
}
|