5 using System.Collections.Generic;
15 [Header(
"Flattening")]
17 [Tooltip(
"Choose this option if Rig is to be applied to a 2D object.")]
20 [Header(
"Customization Settings")]
22 private Material scaleHandleMaterial;
25 private Material rotateHandleMaterial;
28 private Material interactingMaterial;
32 private float scaleRate = 1.0f;
35 private float appBarHoverOffsetZ = 0.05f;
38 [Tooltip(
"This is the maximum scale that one grab can accomplish.")]
39 private float maxScale = 2.0f;
48 private bool rotateAroundPivot =
false;
50 [Header(
"Preset Components")]
52 [Tooltip(
"To visualize the object bounding box, drop the MixedRealityToolkit/UX/Prefabs/BoundingBoxes/BoundingBoxBasic.prefab here.")]
56 [Tooltip(
"AppBar prefab.")]
57 private AppBar appBarPrefab = null;
61 private GameObject objectToBound;
63 private AppBar appBarInstance;
65 private GameObject[] rotateHandles;
67 private GameObject[] cornerHandles;
69 private List<Vector3> handleCentroids;
71 private GameObject transformRig;
77 private bool showRig =
false;
79 private Vector3 scaleHandleSize =
new Vector3(0.04f, 0.04f, 0.04f);
81 private Vector3 rotateHandleSize =
new Vector3(0.04f, 0.04f, 0.04f);
83 private bool destroying =
false;
89 return boundingBoxPrefab;
94 boundingBoxPrefab = value;
98 public Material ScaleHandleMaterial
102 return scaleHandleMaterial;
107 scaleHandleMaterial = value;
111 public Material RotateHandleMaterial
115 return rotateHandleMaterial;
120 rotateHandleMaterial = value;
124 public Material InteractingMaterial
128 return interactingMaterial;
133 interactingMaterial = value;
153 for (
int i = 0; i < rotateHandles.Length; ++i)
155 rotateHandles[i].SetActive(rotateHandles[i].gameObject == handle);
157 for (
int i = 0; i < cornerHandles.Length; ++i)
159 cornerHandles[i].SetActive(cornerHandles[i].gameObject == handle);
164 for (
int i = 0; i < rotateHandles.Length; ++i)
166 rotateHandles[i].SetActive(
true);
168 for (
int i = 0; i < cornerHandles.Length; ++i)
170 cornerHandles[i].SetActive(
true);
178 objectToBound = this.gameObject;
180 boxInstance = Instantiate(BoundingBoxPrefab) as
BoundingBox;
181 boxInstance.
Target = objectToBound;
186 appBarInstance = Instantiate(appBarPrefab) as
AppBar;
193 private void Update()
195 if (destroying ==
false && ShowRig)
197 UpdateBoundsPoints();
202 private void OnDestroy()
209 private void UpdateBoundsPoints()
211 handleCentroids = GetBounds();
214 private void CreateHandles()
217 UpdateCornerHandles();
218 UpdateRotateHandles();
223 private void UpdateCornerHandles()
225 if (handleCentroids != null)
230 if (cornerHandles == null)
232 cornerHandles =
new GameObject[handleCentroids.Count];
234 for (
int i = 0; i < cornerHandles.Length; ++i)
236 cornerHandles[i] = GameObject.CreatePrimitive(PrimitiveType.Cube);
237 cornerHandles[i].GetComponent<Renderer>().material = scaleHandleMaterial;
238 cornerHandles[i].transform.localScale = scaleHandleSize;
239 cornerHandles[i].name =
"Corner " + i.ToString();
241 rigScaleGizmoHandles[i].
Rig =
this;
242 rigScaleGizmoHandles[i].
ScaleRate = scaleRate;
243 rigScaleGizmoHandles[i].
MaxScale = maxScale;
250 for (
int i = 0; i < cornerHandles.Length; ++i)
252 cornerHandles[i].transform.position = handleCentroids[i];
253 cornerHandles[i].transform.localRotation = objectToBound.transform.rotation;
257 private void UpdateRotateHandles()
259 if (handleCentroids != null)
264 if (rotateHandles == null)
266 rotateHandles =
new GameObject[12];
268 for (
int i = 0; i < rotateHandles.Length; ++i)
270 rotateHandles[i] = GameObject.CreatePrimitive(PrimitiveType.Sphere);
271 rotateHandles[i].GetComponent<Renderer>().material = rotateHandleMaterial;
272 rotateHandles[i].transform.localScale = rotateHandleSize;
273 rotateHandles[i].name =
"Middle " + i.ToString();
276 rigRotateGizmoHandles[i].
Rig =
this;
317 rotateHandles[0].transform.localPosition = (handleCentroids[2] + handleCentroids[0]) * 0.5f;
318 rotateHandles[1].transform.localPosition = (handleCentroids[3] + handleCentroids[1]) * 0.5f;
319 rotateHandles[2].transform.localPosition = (handleCentroids[6] + handleCentroids[4]) * 0.5f;
320 rotateHandles[3].transform.localPosition = (handleCentroids[7] + handleCentroids[5]) * 0.5f;
321 rotateHandles[4].transform.localPosition = (handleCentroids[0] + handleCentroids[1]) * 0.5f;
322 rotateHandles[5].transform.localPosition = (handleCentroids[2] + handleCentroids[3]) * 0.5f;
323 rotateHandles[6].transform.localPosition = (handleCentroids[4] + handleCentroids[5]) * 0.5f;
324 rotateHandles[7].transform.localPosition = (handleCentroids[6] + handleCentroids[7]) * 0.5f;
325 rotateHandles[8].transform.localPosition = (handleCentroids[0] + handleCentroids[4]) * 0.5f;
326 rotateHandles[9].transform.localPosition = (handleCentroids[1] + handleCentroids[5]) * 0.5f;
327 rotateHandles[10].transform.localPosition = (handleCentroids[2] + handleCentroids[6]) * 0.5f;
328 rotateHandles[11].transform.localPosition = (handleCentroids[3] + handleCentroids[7]) * 0.5f;
331 private void ParentHandles()
333 transformRig.transform.position = boxInstance.transform.position;
334 transformRig.transform.rotation = boxInstance.transform.rotation;
336 Vector3 invScale = objectToBound.transform.localScale;
338 transformRig.transform.localScale =
new Vector3(0.5f / invScale.x, 0.5f / invScale.y, 0.5f / invScale.z);
339 transformRig.transform.parent = objectToBound.transform;
342 private void UpdateHandles()
344 UpdateCornerHandles();
345 UpdateRotateHandles();
348 private void ClearCornerHandles()
350 if (cornerHandles != null)
352 for (
int i = 0; i < cornerHandles.Length; ++i)
354 GameObject.Destroy(cornerHandles[i]);
356 cornerHandles = null;
357 handleCentroids = null;
360 cornerHandles = null;
361 handleCentroids = null;
364 private void ClearRotateHandles()
366 if (rotateHandles != null && rotateHandles.Length > 0 && rotateHandles[0] != null)
368 for (
int i = 0; i < rotateHandles.Length; ++i)
370 if (rotateHandles[i] != null)
372 Destroy(rotateHandles[i]);
373 rotateHandles[i] = null;
378 rotateHandles = null;
381 private void ClearHandles()
383 ClearCornerHandles();
384 ClearRotateHandles();
387 private GameObject BuildRig()
389 Vector3 scale = objectToBound.transform.localScale;
391 GameObject rig =
new GameObject();
393 rig.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
394 rig.transform.localScale =
new Vector3(1.0f / scale.x, 1.0f / scale.y, 1.0f / scale.z);
396 GameObject upperLeftFront =
new GameObject();
397 upperLeftFront.name =
"upperleftfront";
398 upperLeftFront.transform.SetPositionAndRotation(
new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity);
399 upperLeftFront.transform.localScale =
new Vector3(1, 1, 1);
400 upperLeftFront.transform.parent = rig.transform;
402 GameObject upperLeftBack =
new GameObject();
403 upperLeftBack.name =
"upperleftback";
404 upperLeftBack.transform.SetPositionAndRotation(
new Vector3(0.5f, 0.5f, -0.5f), Quaternion.identity);
405 upperLeftBack.transform.localScale =
new Vector3(1, 1, 1);
406 upperLeftBack.transform.parent = rig.transform;
408 GameObject lowerLeftFront =
new GameObject();
409 lowerLeftFront.name =
"lowerleftfront";
410 lowerLeftFront.transform.SetPositionAndRotation(
new Vector3(0.5f, -0.5f, 0.5f), Quaternion.identity);
411 lowerLeftFront.transform.localScale =
new Vector3(1, 1, 1);
412 lowerLeftFront.transform.parent = rig.transform;
414 GameObject lowerLeftBack =
new GameObject();
415 lowerLeftBack.name =
"lowerleftback";
416 lowerLeftBack.transform.SetPositionAndRotation(
new Vector3(0.5f, -0.5f, -0.5f), Quaternion.identity);
417 lowerLeftBack.transform.localScale =
new Vector3(1, 1, 1);
418 lowerLeftBack.transform.parent = rig.transform;
420 GameObject upperRightFront =
new GameObject();
421 upperRightFront.name =
"upperrightfront";
422 upperRightFront.transform.SetPositionAndRotation(
new Vector3(-0.5f, 0.5f, 0.5f), Quaternion.identity);
423 upperRightFront.transform.localScale =
new Vector3(1, 1, 1);
424 upperRightFront.transform.parent = rig.transform;
426 GameObject upperRightBack =
new GameObject();
427 upperRightBack.name =
"upperrightback";
428 upperRightBack.transform.SetPositionAndRotation(
new Vector3(-0.5f, 0.5f, -0.5f), Quaternion.identity);
429 upperRightBack.transform.localScale =
new Vector3(1, 1, 1);
430 upperRightBack.transform.parent = rig.transform;
432 GameObject lowerRightFront =
new GameObject();
433 lowerRightFront.name =
"lowerrightfront";
434 lowerRightFront.transform.SetPositionAndRotation(
new Vector3(-0.5f, -0.5f, 0.5f), Quaternion.identity);
435 lowerRightFront.transform.localScale =
new Vector3(1, 1, 1);
436 lowerRightFront.transform.parent = rig.transform;
438 GameObject lowerRightBack =
new GameObject();
439 lowerRightBack.name =
"lowerrightback";
440 lowerRightBack.transform.SetPositionAndRotation(
new Vector3(-0.5f, -0.5f, -0.5f), Quaternion.identity);
441 lowerRightBack.transform.localScale =
new Vector3(1, 1, 1);
442 lowerRightBack.transform.parent = rig.transform;
457 if (destroying ==
false)
461 UpdateBoundsPoints();
465 if (boxInstance != null)
470 if (cornerHandles != null && rotateHandles != null)
472 foreach (GameObject handle
in cornerHandles)
474 handle.SetActive(value);
476 foreach (GameObject handle
in rotateHandles)
478 handle.SetActive(value);
489 if (objectToBound != null)
491 List<Vector3> bounds =
new List<Vector3>();
492 LayerMask mask =
new LayerMask();
494 GameObject clone = GameObject.Instantiate(boxInstance.gameObject);
495 clone.transform.localRotation = Quaternion.identity;
496 clone.transform.position = Vector3.zero;
499 GameObject.Destroy(clone);
500 #if UNITY_2017_1_OR_NEWER 501 Matrix4x4 m = Matrix4x4.Rotate(objectToBound.transform.rotation);
502 for (
int i = 0; i < bounds.Count; ++i)
504 bounds[i] = m.MultiplyPoint(bounds[i]);
507 #endif // UNITY_2017_1_OR_NEWER 516 int index = handleCentroids.Count - 8;
517 float width = (handleCentroids[index + 0] - handleCentroids[index + 4]).magnitude;
518 float height = (handleCentroids[index + 0] - handleCentroids[index + 2]).magnitude;
519 float depth = (handleCentroids[index + 0] - handleCentroids[index + 1]).magnitude;
521 if (width < height && width < depth)
525 else if (height < width && height < depth)
529 else if (depth < height && depth < width)