Skip to content

Instantly share code, notes, and snippets.

@dykarohora
Last active July 6, 2017 10:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dykarohora/ea3aa186f751c850a08e75e5da5601bf to your computer and use it in GitHub Desktop.
Save dykarohora/ea3aa186f751c850a08e75e5da5601bf to your computer and use it in GitHub Desktop.
BoundingBox with Gaze interaction
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
//
using HUX.Buttons;
using System.Collections.Generic;
using UnityEngine;
namespace HUX.Interaction {
/// <summary>
/// Draws a bounding box gizmo in the style of the hololens shell
/// </summary>
[ExecuteInEditMode]
public class BoundingBoxGizmoShell : BoundingBoxGizmo {
#region public
/// <summary>
/// Mesh used to draw scale handles
/// </summary>
public Mesh BoxMesh;
/// <summary>
/// Mesh used to draw rotate handles
/// </summary>
public Mesh SphereMesh;
/// <summary>
/// Material used for drawing handles (must have _Color property)
/// </summary>
public Material HandleMaterial;
/// <summary>
/// Color of active handles
/// </summary>
public Color ActiveColor = Color.blue;
/// <summary>
/// Color of inactive handles
/// </summary>
public Color InactiveColor = Color.gray;
/// <summary>
/// Color of the handle being manipulated by player
/// </summary>
public Color TargetColor = Color.red;
public Color FocusColor = Color.green;
#endregion
#region private
[SerializeField]
private Renderer edgeRenderer;
[SerializeField]
private int activeHandleIndex = -1;
[SerializeField]
private int focusHandleIndex = -1;
private Vector3[] handlePositions;
private Material edgeMaterial;
private List<Matrix4x4> cubeHandleMatrixes = new List<Matrix4x4>();
private List<Matrix4x4> sphereHandleMatrixes = new List<Matrix4x4>();
private Bounds localBounds = new Bounds();
private MaterialPropertyBlock propertyBlock;
private int colorID;
#endregion
#region initialization
void OnEnable() {
edgeMaterial = new Material(HandleMaterial);
edgeRenderer.material = edgeMaterial;
HandleMaterial.enableInstancing = true;
propertyBlock = new MaterialPropertyBlock();
colorID = Shader.PropertyToID("_EmissionColor");
}
void OnDisable() {
if (Application.isPlaying) {
GameObject.Destroy(edgeMaterial);
} else {
GameObject.DestroyImmediate(edgeMaterial);
}
}
#endregion
#region handle drawing
protected override void DrawGizmoObjects() {
if (boundingBox.Target == null) {
edgeRenderer.enabled = false;
return;
}
// Reset our scale - only scaleTransform can be changed
transform.localScale = Vector3.one;
// Get the positions of our handles
localBounds.size = scaleTransform.localScale;
localBounds.center = Vector3.zero;
localBounds.GetCornerAndMidPointPositions(transform, ref handlePositions);
cubeHandleMatrixes.Clear();
sphereHandleMatrixes.Clear();
// Pos / rot / scale for our handles
// Scale is based on smallest dimension to ensure handles don't overlap
// Rotation is just the rotation of our gizmo
Vector3 pos = Vector3.zero;
Quaternion rotation = transform.rotation;
Vector3 scale = Vector3.one * Mathf.Min(Mathf.Min(localBounds.size.x, localBounds.size.y), localBounds.size.z);
// Get the index of our active handle so we can draw it with a different material
activeHandleIndex = -1;
focusHandleIndex = -1;
BoundingBoxManipulate manipulate = boundingBox.GetComponent<BoundingBoxManipulate>();
if (manipulate.ActiveHandle != null && manipulate.ActiveHandle.HandleType != BoundingBoxHandle.HandleTypeEnum.Drag) {
activeHandleIndex = (int)manipulate.ActiveHandle.HandleType;
}
if (manipulate.FocusHandle != null) {
focusHandleIndex = (int)manipulate.FocusHandle.HandleType;
}
// If we're not accepting input, just draw the box bounds
if (!manipulate.AcceptInput) {
edgeRenderer.enabled = true;
edgeMaterial.SetColor("_EmissionColor", InactiveColor);
} else {
switch (manipulate.CurrentOperation) {
default:
case BoundingBoxManipulate.OperationEnum.None:
// No visible bounds
// No visible handles
edgeRenderer.enabled = false;
break;
case BoundingBoxManipulate.OperationEnum.Drag:
// Target bounds
// Inactive scale handles
// Inactive rotate handles (based on permitted operations)
edgeRenderer.enabled = true;
edgeMaterial.SetColor("_EmissionColor", manipulate.ManipulatingNow ? TargetColor : ActiveColor);
// Get all our handle positions
GetAllHandleMatrixes(handlePositions, rotation, scale, cubeHandleMatrixes, sphereHandleMatrixes, activeHandleIndex);
// Draw our handles
DrawHandleMeshes(cubeHandleMatrixes, BoxMesh, InactiveColor);
DrawHandleMeshes(sphereHandleMatrixes, SphereMesh, InactiveColor);
break;
case BoundingBoxManipulate.OperationEnum.RotateY:
case BoundingBoxManipulate.OperationEnum.RotateZ:
case BoundingBoxManipulate.OperationEnum.RotateX:
// Visible bounds
// Inactive scale handles
// Active / Target rotate handles (based on permitted operations)
edgeRenderer.enabled = true;
edgeMaterial.SetColor("_EmissionColor", InactiveColor);
// Get all our handle positions
GetAllHandleMatrixes(handlePositions, rotation, scale, cubeHandleMatrixes, sphereHandleMatrixes, activeHandleIndex);
// Draw our handles
DrawHandleMeshes(cubeHandleMatrixes, BoxMesh, InactiveColor);
DrawHandleMeshes(sphereHandleMatrixes, SphereMesh, ActiveColor);
// DrawTargetMesh(activeHandleIndex, SphereMesh, handlePositions, rotation, scale, manipulate.ManipulatingNow ? TargetColor : ActiveColor);
if (manipulate.ManipulatingNow) {
DrawTargetMesh(activeHandleIndex, SphereMesh, handlePositions, rotation, scale, TargetColor);
} else if (activeHandleIndex != focusHandleIndex) {
DrawTargetMesh(activeHandleIndex, SphereMesh, handlePositions, rotation, scale, ActiveColor);
}
break;
case BoundingBoxManipulate.OperationEnum.ScaleUniform:
// Inactive bounds
// Active / Target scale handles
// Inactive rotate handles (based on permitted operations)
edgeRenderer.enabled = true;
edgeMaterial.SetColor("_EmissionColor", InactiveColor);
// Get all our handle positions
GetAllHandleMatrixes(handlePositions, rotation, scale, cubeHandleMatrixes, sphereHandleMatrixes, activeHandleIndex);
// Draw our handles
DrawHandleMeshes(cubeHandleMatrixes, BoxMesh, ActiveColor);
DrawHandleMeshes(sphereHandleMatrixes, SphereMesh, InactiveColor);
// DrawTargetMesh(activeHandleIndex, BoxMesh, handlePositions, rotation, scale, manipulate.ManipulatingNow ? TargetColor : ActiveColor);
if (manipulate.ManipulatingNow) {
DrawTargetMesh(activeHandleIndex, BoxMesh, handlePositions, rotation, scale, TargetColor);
} else if (activeHandleIndex != focusHandleIndex) {
DrawTargetMesh(activeHandleIndex, BoxMesh, handlePositions, rotation, scale, ActiveColor);
}
break;
}
if (!manipulate.ManipulatingNow) {
switch (focusHandleIndex) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
DrawTargetMesh(focusHandleIndex, BoxMesh, handlePositions, rotation, scale, FocusColor);
break;
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
DrawTargetMesh(focusHandleIndex, SphereMesh, handlePositions, rotation, scale, FocusColor);
break;
case 20:
edgeMaterial.SetColor("_EmissionColor", FocusColor);
break;
}
}
}
}
private void DrawTargetMesh(int targetIndex, Mesh mesh, Vector3[] positions, Quaternion rotation, Vector3 scale, Color color) {
if (targetIndex < 0)
return;
propertyBlock.SetColor(colorID, color);
Graphics.DrawMesh(mesh, Matrix4x4.TRS(positions[targetIndex], rotation, scale), HandleMaterial, PhysicsLayer, Camera.current, 0, propertyBlock, UnityEngine.Rendering.ShadowCastingMode.Off, false);
}
private void DrawHandleMeshes(List<Matrix4x4> matrixes, Mesh mesh, Color color) {
propertyBlock.SetColor(colorID, color);
Graphics.DrawMeshInstanced(mesh, 0, HandleMaterial, matrixes, propertyBlock, UnityEngine.Rendering.ShadowCastingMode.Off, false, PhysicsLayer);
}
private void GetAllHandleMatrixes(Vector3[] positions, Quaternion rotation, Vector3 scale, List<Matrix4x4> cubeMatrixes, List<Matrix4x4> sphereMatrixes, int targetIndex) {
BoundingBoxManipulate manipulate = boundingBox.GetComponent<BoundingBoxManipulate>();
// Get all our handle positions for cubes
if ((manipulate.PermittedOperations & BoundingBoxManipulate.OperationEnum.ScaleUniform) == BoundingBoxManipulate.OperationEnum.ScaleUniform) {
for (int i = BoundsExtentions.LBF; i <= BoundsExtentions.RTB; i++) {
if (i == targetIndex)
continue;
cubeMatrixes.Add(Matrix4x4.TRS(handlePositions[i], rotation, scale));
}
}
// Get all our handle positions for rotation
if ((manipulate.PermittedOperations & BoundingBoxManipulate.OperationEnum.RotateX) == BoundingBoxManipulate.OperationEnum.RotateX) {
for (int i = BoundsExtentions.LTF_RTF; i <= BoundsExtentions.RBB_LBB; i++) {
if (i == targetIndex)
continue;
sphereMatrixes.Add(Matrix4x4.TRS(handlePositions[i], rotation, scale));
}
}
if ((manipulate.PermittedOperations & BoundingBoxManipulate.OperationEnum.RotateY) == BoundingBoxManipulate.OperationEnum.RotateY) {
for (int i = BoundsExtentions.LTF_LBF; i <= BoundsExtentions.RTF_RBF; i++) {
if (i == targetIndex)
continue;
sphereMatrixes.Add(Matrix4x4.TRS(handlePositions[i], rotation, scale));
}
}
if ((manipulate.PermittedOperations & BoundingBoxManipulate.OperationEnum.RotateZ) == BoundingBoxManipulate.OperationEnum.RotateZ) {
for (int i = BoundsExtentions.RBF_RBB; i <= BoundsExtentions.LTF_LTB; i++) {
if (i == targetIndex)
continue;
sphereMatrixes.Add(Matrix4x4.TRS(handlePositions[i], rotation, scale));
}
}
}
#endregion
}
}
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
//
using HUX.Buttons;
using HUX.Focus;
using HUX.Receivers;
using System.Collections.Generic;
using UnityEngine;
namespace HUX.Interaction {
/// <summary>
/// Listens to messages from attached BoundingBoxHandle objects and manipulates the target
/// </summary>
public class BoundingBoxManipulate : BoundingBox {
[System.Flags]
public enum OperationEnum {
None = 0,
Drag = 1,
ScaleUniform = 2,
RotateX = 4,
RotateZ = 8,
RotateY = 16,
ScaleX = 32,
ScaleY = 64,
ScaleZ = 128,
}
#region public
/// <summary>
/// Makes bounding box manipulatable by user
/// </summary>
public bool AcceptInput {
get {
return acceptInput;
}
set {
if (value & !acceptInput) {
// Reset to drag operation
CurrentOperation = OperationEnum.Drag;
}
acceptInput = value;
}
}
/// <summary>
/// Which operations this bounding box is allowed to perform
/// </summary>
public OperationEnum PermittedOperations {
get {
return permittedOperations;
}
set {
if (permittedOperations != value) {
permittedOperations = value;
RefreshActiveHandles();
}
}
}
/// <summary>
/// How quickly objects move when being dragged
/// </summary>
public float DragMultiplier = 10f;
/// <summary>
/// How much to scale rotation input
/// </summary>
public float RotateMultiplier = 10f;
/// <summary>
/// How much to scale scale input
/// </summary>
public float ScaleMultiplier = 10f;
/// <summary>
/// The smallest an object can be scaled with one gesture
/// </summary>
public float MinScalePercentage = 0.05f;
/// <summary>
/// The current operation of the bounding box
/// </summary>
public OperationEnum CurrentOperation {
get {
if (target == null || activeHandle == null) {
return OperationEnum.None;
}
return GetBoundingBoxOperationFromHandleType(activeHandle.HandleType);
}
set {
SetHandleByOperation(value);
}
}
/// <summary>
/// Whether the user is manipulating the bb using a handle
/// </summary>
public bool ManipulatingNow {
get {
if (Application.isPlaying) {
return manipulatingNow;
} else {
return true;
}
}
set {
if (value) {
StartManipulating();
} else {
StopManipulating();
}
}
}
/// <summary>
/// The handle being manipulated by the user, if any
/// </summary>
public BoundingBoxHandle ActiveHandle {
get {
return activeHandle;
}
set {
activeHandle = value;
}
}
public BoundingBoxHandle FocusHandle {
get {
return focusHandle;
}
set {
focusHandle = value;
}
}
/// <summary>
/// The target object being manipulated
/// </summary>
public override GameObject Target {
get {
return target;
}
set {
if (target != value) {
// Send a message to the new / old targets
if (value != null) {
value.SendMessage("OnTargetSelected", SendMessageOptions.DontRequireReceiver);
}
if (target != null) {
target.SendMessage("OnTargetDeselected", SendMessageOptions.DontRequireReceiver);
}
target = value;
// Reset active handle to drag
SetHandleByOperation(OperationEnum.Drag);
ManipulatingNow = false;
}
if (target != null) {
CreateTransforms();
// Set our transforms to the target immediately
targetStandIn.position = target.transform.position;
targetStandIn.rotation = target.transform.rotation;
targetStandIn.localScale = target.transform.lossyScale;
RefreshTargetBounds();
} else {
ActiveHandle = null;
}
}
}
/// <summary>
/// Convenience function to help determine what function a handle serves
/// </summary>
/// <param name="handleType"></param>
/// <returns></returns>
public static OperationEnum GetBoundingBoxOperationFromHandleType(BoundingBoxHandle.HandleTypeEnum handleType) {
switch (handleType) {
case BoundingBoxHandle.HandleTypeEnum.Drag:
return OperationEnum.Drag;
//TODO - break this up into axis scales
case BoundingBoxHandle.HandleTypeEnum.Scale_LBF:
case BoundingBoxHandle.HandleTypeEnum.Scale_LBB:
case BoundingBoxHandle.HandleTypeEnum.Scale_LTF:
case BoundingBoxHandle.HandleTypeEnum.Scale_LTB:
case BoundingBoxHandle.HandleTypeEnum.Scale_RBF:
case BoundingBoxHandle.HandleTypeEnum.Scale_RBB:
case BoundingBoxHandle.HandleTypeEnum.Scale_RTF:
case BoundingBoxHandle.HandleTypeEnum.Scale_RTB:
return OperationEnum.ScaleUniform;
case BoundingBoxHandle.HandleTypeEnum.Rotate_LTF_RTF:
case BoundingBoxHandle.HandleTypeEnum.Rotate_LBF_RBF:
case BoundingBoxHandle.HandleTypeEnum.Rotate_RTB_LTB:
case BoundingBoxHandle.HandleTypeEnum.Rotate_RBB_LBB:
return OperationEnum.RotateX;
case BoundingBoxHandle.HandleTypeEnum.Rotate_LTF_LBF:
case BoundingBoxHandle.HandleTypeEnum.Rotate_RTB_RBB:
case BoundingBoxHandle.HandleTypeEnum.Rotate_LTB_LBB:
case BoundingBoxHandle.HandleTypeEnum.Rotate_RTF_RBF:
return OperationEnum.RotateY;
case BoundingBoxHandle.HandleTypeEnum.Rotate_RBF_RBB:
case BoundingBoxHandle.HandleTypeEnum.Rotate_RTF_RTB:
case BoundingBoxHandle.HandleTypeEnum.Rotate_LBF_LBB:
case BoundingBoxHandle.HandleTypeEnum.Rotate_LTF_LTB:
return OperationEnum.RotateZ;
default:
return OperationEnum.None;
}
}
public override void OnEnable() {
base.OnEnable();
manipulatingNow = false;
}
#endregion
#region manipulation events
protected override void OnFocusEnter(GameObject obj, FocusArgs args) {
if (!ManipulatingNow) {
//TODO show handle mesh
TryToSetFocusHandle(obj);
}
base.OnFocusEnter(obj, args);
}
protected override void OnFocusExit(GameObject obj, FocusArgs args) {
if (!ManipulatingNow) {
//TODO hide handle mesh
focusHandle = null;
}
base.OnFocusExit(obj, args);
}
/// <summary>
/// Chooses our manipulation handle so we know how to interpret future input events
/// </summary>
/// <param name="obj"></param>
/// <param name="eventArgs"></param>
protected override void OnManipulationStarted(GameObject obj, InteractionManager.InteractionEventArgs eventArgs) {
base.OnManipulationStarted(obj, eventArgs);
TryToSetHandle(obj, eventArgs.Position, eventArgs.Focuser);
// Compute a vector as a reference for determining the amount of rotation.
// In order to operate with the vertical and horizontal movements of the hand,
// the reference vector is assumed to be the coordinate axis of the BoundingBox projected on the screen
if (CurrentOperation == OperationEnum.RotateX || CurrentOperation == OperationEnum.RotateY || CurrentOperation == OperationEnum.RotateZ) {
Vector3 axisVect = Vector3.ProjectOnPlane(
CurrentOperation == OperationEnum.RotateX ? transform.right :
CurrentOperation == OperationEnum.RotateY ? transform.up :
transform.forward,
Camera.main.transform.forward);
orthogonalVect = Vector3.Cross(Camera.main.transform.forward, axisVect);
orthogonalVect.Normalize();
}
}
protected override void OnManipulationCanceled(GameObject obj, InteractionManager.InteractionEventArgs eventArgs) {
ManipulatingNow = false;
base.OnManipulationCanceled(obj, eventArgs);
}
protected override void OnManipulationCompleted(GameObject obj, InteractionManager.InteractionEventArgs eventArgs) {
ManipulatingNow = false;
base.OnManipulationCompleted(obj, eventArgs);
}
protected override void OnManipulationUpdated(GameObject obj, InteractionManager.InteractionEventArgs eventArgs) {
base.OnManipulationUpdated(obj, eventArgs);
if (!acceptInput)
return;
if (target == null)
return;
if (!manipulatingNow)
return;
Vector3 eventPos = eventArgs.Position;
// Transform the direction if necessary
if (eventArgs.IsPosRelative) {
eventPos = Veil.Instance.HeadTransform.TransformDirection(eventPos);
}
// See how much our position has changed
navigateVelocity = lastNavigatePos - eventPos;
lastNavigatePos = eventPos;
smoothVelocity = Vector3.Lerp(smoothVelocity, navigateVelocity, 0.5f);
}
#endregion
#region private
/// <summary>
/// Override so we're not overwhelmed by button gizmos
/// </summary>
#if UNITY_EDITOR
protected override void OnDrawGizmos() {
// nothing
if (!Application.isPlaying) {
// Do this here to ensure continuous updates in editor
UpdateTargetManipulation();
RefreshTargetBounds();
}
}
#endif
protected override void Update() {
if (!Application.isPlaying)
return;
// Check to see if our hands have exited the screen
// If they have, stop manipulating
if (!Veil.Instance.HandVisible) {
ManipulatingNow = false;
}
UpdateUserManipulation();
UpdateTargetManipulation();
base.Update();
}
/// <summary>
/// Applies changes gathered during manipulation udpate events
/// </summary>
private void UpdateUserManipulation() {
if (ManipulatingNow) {
// Projecting the movement vector of the hand on the reference vector
Vector3 proj = Vector3.Project(smoothVelocity, orthogonalVect);
// Change the transform helper based on the current operation
// We're using some magic numbers in here to keep the multiplier ranges intuitive
switch (CurrentOperation) {
case OperationEnum.Drag:
transformHelper.position -= (smoothVelocity * DragMultiplier);
break;
case OperationEnum.ScaleUniform:
case OperationEnum.ScaleX:
case OperationEnum.ScaleY:
case OperationEnum.ScaleZ:
// Translate velocity direction based on camera
Vector3 orientedVelocity = Camera.main.transform.TransformDirection(smoothVelocity);
// See whether handle is to left or right of gizmo center
Vector3 handleScreenPoint = Camera.main.WorldToScreenPoint(activeHandle.transform.position);
Vector3 gizmoScreenPoint = Camera.main.WorldToScreenPoint(targetBoundsWorldCenter);
float dragAmount = orientedVelocity.x;
if (handleScreenPoint.x > gizmoScreenPoint.x) {
dragAmount = -dragAmount;
}
transformHelper.localScale += Vector3.one * (dragAmount * ScaleMultiplier);
break;
case OperationEnum.RotateX:
// transformHelper.Rotate(-smoothVelocity.y * RotateMultiplier * 360, 0f, 0f, Space.World);
transformHelper.RotateAround(transformHelper.position, transform.right, smoothVelocity.magnitude * Vector3.Dot(proj.normalized, orthogonalVect.normalized) * -360);
break;
case OperationEnum.RotateY:
// transformHelper.Rotate(0f, smoothVelocity.x * RotateMultiplier * 360, 0f, Space.World);
transformHelper.RotateAround(transformHelper.position, transform.up, smoothVelocity.magnitude * Vector3.Dot(proj.normalized, orthogonalVect.normalized) * -360);
break;
case OperationEnum.RotateZ:
// transformHelper.Rotate(0f, 0f, smoothVelocity.x * RotateMultiplier * 360, Space.World);
transformHelper.RotateAround(transformHelper.position, transform.forward, smoothVelocity.magnitude * Vector3.Dot(proj.normalized, orthogonalVect.normalized) * -360);
break;
default:
break;
}
}
}
/// <summary>
/// Alters the target based on changes applied to bounding box
/// </summary>
private void UpdateTargetManipulation() {
// Goes without saying
if (!acceptInput)
return;
// If we don't have a target, nothing to do here
if (target == null)
return;
// If we're NOT actively manipulating the target, nothing to do here
if (!ManipulatingNow)
return;
if (!Application.isPlaying)
return;
CreateTransforms();
// Apply the target stand-in's transform info to the target
Target.transform.position = targetStandIn.position;
Target.transform.rotation = targetStandIn.rotation;
Target.transform.localScale = targetStandIn.lossyScale;
}
/// <summary>
/// Stores target under our transform helper and prepares for manipulation
/// </summary>
private void StartManipulating() {
// Goes without saying
if (!acceptInput)
return;
if (target == null)
return;
if (manipulatingNow)
return;
manipulatingNow = true;
if (!Application.isPlaying)
return;
CreateTransforms();
// Reset the transform helper to 1,1,1 / idenity
transformHelper.localScale = Vector3.one;
transformHelper.rotation = Quaternion.identity;
adjustedScaleTarget = Vector3.one;
smoothVelocity = Vector3.zero;
// Set up our transforms and gestures based on the operation we're performing
OperationEnum operation = GetBoundingBoxOperationFromHandleType(ActiveHandle.HandleType);
switch (operation) {
case OperationEnum.ScaleUniform:
case OperationEnum.ScaleX:
case OperationEnum.ScaleY:
case OperationEnum.ScaleZ:
// If we're scaling, move the transform helper to the position OPPOSITE the scale handle
// That way the object will grow in the right direction
BoundingBoxHandle oppositeHandle = null;
BoundingBoxHandle.HandleTypeEnum oppositeHandleType = BoundingBoxHandle.GetOpposingHandle(ActiveHandle.HandleType);
foreach (GameObject bbhGo in Interactibles) {
BoundingBoxHandle bbh = bbhGo.GetComponent<BoundingBoxHandle>();
if (bbh != null && bbh.HandleType == oppositeHandleType) {
oppositeHandle = bbh;
break;
}
}
if (oppositeHandle == null) {
Debug.LogWarning("Couldn't find opposing handle for type " + ActiveHandle.HandleType);
transformHelper.position = transform.position;
targetStandIn.position = target.transform.position;
} else {
transformHelper.position = oppositeHandle.transform.position;
targetStandIn.position = target.transform.position;
}
break;
case OperationEnum.Drag:
// If we're rotating or moving, move the transform helper to the center of the gizmo
transformHelper.position = transform.position;
targetStandIn.position = target.transform.position;
break;
case OperationEnum.RotateX:
case OperationEnum.RotateY:
case OperationEnum.RotateZ:
default:
// Rotation
// If we're rotating or moving, move the transform helper to the center of the gizmo
transformHelper.position = transform.position;
targetStandIn.position = target.transform.position;
break;
}
scaleOnStartManipulation = targetStandIn.localScale;
if (target != null) {
// Set our transforms to the target immediately
targetStandIn.position = target.transform.position;
targetStandIn.rotation = target.transform.rotation;
targetStandIn.localScale = target.transform.lossyScale;
}
}
private void StopManipulating() {
if (!manipulatingNow)
return;
manipulatingNow = false;
if (focuser != null) {
focuser.ReleaseFocus();
focuser = null;
}
}
private void SetHandleByOperation(OperationEnum operation) {
switch (operation) {
case OperationEnum.None:
ActiveHandle = null;
break;
case OperationEnum.Drag:
foreach (GameObject obj in Interactibles) {
BoundingBoxHandle h = obj.GetComponent<BoundingBoxHandle>();
if (h.HandleType == BoundingBoxHandle.HandleTypeEnum.Drag) {
ActiveHandle = h;
break;
}
}
break;
default:
//TODO link up other operations here
break;
}
}
private void RefreshActiveHandles() {
foreach (GameObject handleGo in Interactibles) {
BoundingBoxHandle handle = handleGo.GetComponent<BoundingBoxHandle>();
OperationEnum handleOperation = GetBoundingBoxOperationFromHandleType(handle.HandleType);
handleGo.SetActive((handleOperation & permittedOperations) != 0);
}
}
private void TryToSetHandle(GameObject obj, Vector3 position, AFocuser newFocuser) {
if (!acceptInput) {
Debug.Log("Not accepting input");
return;
}
BoundingBoxHandle newHandle = obj.GetComponent<BoundingBoxHandle>();
if (newHandle != null) {
activeHandle = newHandle;
lastNavigatePos = position;
ManipulatingNow = true;
focuser = newFocuser;
focuser.LockFocus();
}
}
private void TryToSetFocusHandle(GameObject obj) {
BoundingBoxHandle newHandle = obj.GetComponent<BoundingBoxHandle>();
if (newHandle != null) {
focusHandle = newHandle;
}
}
[SerializeField]
private BoundingBoxHandle activeHandle;
private BoundingBoxHandle focusHandle;
[SerializeField]
private bool acceptInput = true;
[SerializeField]
private bool manipulatingNow = false;
[SerializeField]
private OperationEnum permittedOperations = OperationEnum.Drag | OperationEnum.RotateY | OperationEnum.ScaleUniform;
private Vector3 lastNavigatePos = Vector3.zero;
private Vector3 navigateVelocity = Vector3.zero;
private Vector3 smoothVelocity = Vector3.zero;
private Vector3 adjustedScaleTarget = Vector3.one;
private Vector3 targetPosition = Vector3.zero;
/// <summary>
/// A vector orthogonal to the rotation axis.
/// </summary>
private Vector3 orthogonalVect = Vector3.one;
private Vector3 scaleOnStartManipulation = Vector3.one;
private AFocuser focuser = null;
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment