12using System.Collections;
13using System.Collections.Generic;
26 [AddComponentMenu(
"")]
41 #region AttachmentPointBehaviours
98 private bool _attachmentPointsDirty =
false;
104 [SerializeField, Disable]
117 [SerializeField, Disable]
118 private bool _isTracked;
124 public bool isTracked {
get {
return _isTracked; }
set { _isTracked = value; } }
127 initializeAttachmentPointFlagConstants();
131 initializeAttachmentPointFlagConstants();
135 #pragma warning disable 0414
137 private bool _isBeingDestroyed =
false;
139 #pragma warning restore 0414
142 _isBeingDestroyed =
true;
152 switch (singlePoint) {
187 if (_attachmentPointFlagConstants ==
null || _attachmentPointFlagConstants.Length == 0) {
188 initializeAttachmentPointFlagConstants();
192 bool requiresDestructionOrCreation =
false;
193 foreach (var flag
in _attachmentPointFlagConstants) {
198 requiresDestructionOrCreation =
true;
203 if (requiresDestructionOrCreation) {
206 flattenAttachmentTransformHierarchy();
211 if (
points.Contains(flag)) {
212 ensureTransformExists(flag);
215 ensureTransformDoesNotExist(flag);
220 organizeAttachmentTransforms();
223 if (_attachmentPointsDirty) {
225 _attachmentPointsDirty =
false;
232 if (_isBeingDestroyed)
return;
237 if (attachHands !=
null) {
246 private void initializeAttachmentPointFlagConstants() {
248 if (_attachmentPointFlagConstants ==
null || _attachmentPointFlagConstants.Length == 0) {
252 foreach (
int f
in flagConstants) {
257 private void setBehaviourForPoint(
AttachmentPointFlags singlePoint, AttachmentPointBehaviour behaviour) {
258 switch (singlePoint) {
290 EditorUtility.SetDirty(
this);
295 if (!singlePoint.IsSinglePoint()) {
296 Debug.LogError(
"Tried to ensure transform exists for singlePoint, but it contains more than one set flag.");
302 if (pointBehaviour ==
null) {
304 var existingPointBehaviour = this.gameObject.GetComponentsInChildren<AttachmentPointBehaviour>()
306 .FirstOrDefault(p => p.attachmentPoint == singlePoint);
312 Undo.RegisterCreatedObjectUndo(obj,
"Created Object");
313 pointBehaviour = Undo.AddComponent<AttachmentPointBehaviour>(obj);
315 pointBehaviour = obj.AddComponent<AttachmentPointBehaviour>();
319 pointBehaviour = existingPointBehaviour;
323 Undo.RecordObject(pointBehaviour,
"Set Attachment Point");
325 pointBehaviour.attachmentPoint = singlePoint;
326 pointBehaviour.attachmentHand =
this;
327 setBehaviourForPoint(singlePoint, pointBehaviour);
329 SetTransformParent(pointBehaviour.transform,
this.transform);
331 _attachmentPointsDirty =
true;
334 EditorUtility.SetDirty(
this);
339 private static void SetTransformParent(Transform t, Transform parent) {
341 Undo.SetTransformParent(t, parent,
"Set Transform Parent");
348 if (!singlePoint.IsSinglePoint()) {
349 Debug.LogError(
"Tried to ensure transform exists for singlePoint, but it contains more than one set flag");
354 if (pointBehaviour !=
null) {
355 InternalUtility.Destroy(pointBehaviour.gameObject);
356 setBehaviourForPoint(singlePoint,
null);
358 pointBehaviour =
null;
360 _attachmentPointsDirty =
true;
363 EditorUtility.SetDirty(
this);
368 private void flattenAttachmentTransformHierarchy() {
369 foreach (var point
in this.
points) {
370 SetTransformParent(point.transform,
this.transform);
374 private void organizeAttachmentTransforms() {
379 wrist.transform.SetSiblingIndex(siblingIdx++);
384 palm.transform.SetSiblingIndex(siblingIdx++);
387 Transform topLevelTransform;
393 if (topLevelTransform !=
null) {
394 topLevelTransform.SetSiblingIndex(siblingIdx++);
398 topLevelTransform = tryStackTransformHierarchy(
indexKnuckle,
402 if (topLevelTransform !=
null) {
403 topLevelTransform.SetSiblingIndex(siblingIdx++);
407 topLevelTransform = tryStackTransformHierarchy(
middleKnuckle,
411 if (topLevelTransform !=
null) {
412 topLevelTransform.SetSiblingIndex(siblingIdx++);
416 topLevelTransform = tryStackTransformHierarchy(
ringKnuckle,
420 if (topLevelTransform !=
null) {
421 topLevelTransform.SetSiblingIndex(siblingIdx++);
425 topLevelTransform = tryStackTransformHierarchy(
pinkyKnuckle,
429 if (topLevelTransform !=
null) {
430 topLevelTransform.SetSiblingIndex(siblingIdx++);
434 private static Transform[] s_hierarchyTransformsBuffer =
new Transform[4];
440 private Transform tryStackTransformHierarchy(params Transform[] transforms) {
441 for (
int i = 0; i < s_hierarchyTransformsBuffer.Length; i++) {
442 s_hierarchyTransformsBuffer[i] =
null;
445 int hierarchyCount = 0;
447 foreach (var transform
in transforms.Query().Where(t => t !=
null)) {
448 s_hierarchyTransformsBuffer[hierarchyCount++] = transform;
451 for (
int i = hierarchyCount - 1; i > 0; i--) {
452 SetTransformParent(s_hierarchyTransformsBuffer[i], s_hierarchyTransformsBuffer[i - 1]);
455 if (hierarchyCount > 0) {
456 return s_hierarchyTransformsBuffer[0];
462 private static Transform[] s_transformsBuffer =
new Transform[4];
463 private Transform tryStackTransformHierarchy(params MonoBehaviour[] monoBehaviours) {
464 for (
int i = 0; i < s_transformsBuffer.Length; i++) {
465 s_transformsBuffer[i] =
null;
469 foreach (var behaviour
in monoBehaviours.Query().Where(b => b !=
null)) {
470 s_transformsBuffer[tIdx++] = behaviour.transform;
473 return tryStackTransformHierarchy(s_transformsBuffer);
483 private int _flagsCount;
488 if (hand !=
null && hand._attachmentPointFlagConstants !=
null) {
491 _flagsCount = hand._attachmentPointFlagConstants.Length;
503 if (_hand ==
null)
return null;
512 }
while (_curIdx < _flagsCount && _hand.
GetBehaviourForPoint(GetFlagFromFlagIdx(_curIdx)) ==
null);
514 return _curIdx < _flagsCount;
This MonoBehaviour is managed by an AttachmentHands component on a parent MonoBehaviour....
AttachmentPointBehaviour pinkyMiddleJoint
AttachmentPointBehaviour palm
AttachmentPointBehaviour indexMiddleJoint
AttachmentPointBehaviour indexTip
AttachmentPointBehaviour GetBehaviourForPoint(AttachmentPointFlags singlePoint)
Returns the AttachmentPointBehaviour child object of this AttachmentHand given a reference to a singl...
AttachmentPointBehaviour middleKnuckle
bool isTracked
Gets the chirality of this AttachmentHand. This is set automatically by the AttachmentHands parent ob...
AttachmentPointBehaviour middleDistalJoint
AttachmentPointBehaviour thumbDistalJoint
AttachmentPointBehaviour ringMiddleJoint
Action OnAttachmentPointsModified
Called when the AttachmentHand refreshes its AttachmentPointBehaviour transforms. If the user uncheck...
AttachmentPointBehaviour ringTip
AttachmentPointBehaviour indexDistalJoint
AttachmentPointBehaviour thumbProximalJoint
AttachmentPointBehaviour wrist
AttachmentPointBehaviour pinkyDistalJoint
AttachmentPointBehaviour ringKnuckle
AttachmentPointBehaviour pinkyTip
AttachmentPointBehaviour indexKnuckle
AttachmentPointBehaviour pinkyKnuckle
void refreshAttachmentTransforms(AttachmentPointFlags points)
AttachmentPointBehaviour middleTip
void notifyPointBehaviourDeleted(AttachmentPointBehaviour point)
AttachmentPointBehaviour ringDistalJoint
AttachmentPointsEnumerator points
Gets an enumerator that traverses all of the AttachmentPoints beneath this AttachmentHand.
AttachmentPointBehaviour thumbTip
Chirality chirality
Gets the chirality of this AttachmentHand. This is set automatically by the AttachmentHands parent ob...
AttachmentPointBehaviour middleMiddleJoint
Add an GameObject with this script to your scene if you would like to have a Transform hierarchy that...
AttachmentPointFlags attachmentPoints
Simple container class for storing a reference to the attachment point this transform corresponds to ...
AttachmentPointFlags
Flags for attachment points on the hand.
An enumerator that traverses all of the existing AttachmentPointBehaviours beneath an AttachmentHand.
AttachmentPointsEnumerator(AttachmentHand hand)
AttachmentPointBehaviour Current
AttachmentPointsEnumerator GetEnumerator()
A Query object is a type of immutable ordered collection of elements that can be used to perform usef...