/// <summary> /// Adds a child mount point to the list /// </summary> /// <param name="rChild"></param> public void AddChild(MountPoint rChild) { if (rChild == null) { return; } if (!_AllowChildren) { return; } // If the child already has a parent, we need to clear it and reset if (rChild.ParentMountPoint != null) { rChild.ParentMountPoint.RemoveChild(rChild); } rChild.ParentMountPoint = this; // First, check if it already exists. We don't want to add it twice for (int i = 0; i < ChildMountPoints.Count; i++) { MountPointPtr lChild = ChildMountPoints[i]; if (lChild.Owner == rChild._Owner && lChild.GUID == rChild.GUID) { return; } } // If we got here, we need to add the child MountPointPtr lReference = new MountPointPtr(rChild); ChildMountPoints.Add(lReference); }
/// <summary> /// Grab the closest mount point to any of the mount points in this list. /// </summary> /// <param name="rSourceMountPoints"></param> /// <returns></returns> public static MountPoint GetClosestMountPoint(MountPoints rSourceMountPoints) { MountPoint lMountPoint = null; float lDistance = float.MaxValue; for (int i = 0; i < rSourceMountPoints.Points.Count; i++) { MountPoint lSourceMountPoint = rSourceMountPoints.Points[i]; Vector3 lSourceMountPosition = lSourceMountPoint._Anchor.transform.position; MountPoint lTestMountPoint = GetClosestMountPoint(lSourceMountPosition, null, rSourceMountPoints); if (lTestMountPoint != null) { Vector3 lTestPosition = lTestMountPoint._Anchor.transform.position; float lTestDistance = Vector3.Distance(lSourceMountPosition, lTestPosition); if (lTestDistance < lDistance) { lDistance = lTestDistance; lMountPoint = lTestMountPoint; } } } return(lMountPoint); }
/// <summary> /// Removes a child mount point from the list /// </summary> /// <param name="rChild"></param> public void RemoveChild(MountPoint rChild) { if (rChild == null) { return; } // Remove the child's parent if (rChild.ParentMountPoint == this) { rChild.ParentMountPoint = null; } // Remove the child from the list for (int i = ChildMountPoints.Count - 1; i >= 0; i--) { MountPointPtr lChild = ChildMountPoints[i]; if (lChild.Owner == rChild._Owner && lChild.GUID == rChild.GUID) { // Just in case we find it more than once, clear out the parent again MountPoint lChildMountPoint = lChild.MountPoint; if (lChildMountPoint.ParentMountPoint == this) { lChildMountPoint.ParentMountPoint = null; } // Remove it from the list ChildMountPoints.RemoveAt(i); } } }
/// <summary> /// Connects the child mount point to the parent /// </summary> /// <param name="rParent">Parent mount point we are connecting to</param> /// <param name="rChild">Child mount point being connected</param> /// <returns>Boolean used to determine if the connection was made</returns> public bool ConnectMountPoints(MountPoint rParentPoint) { if (rParentPoint == null) { return false; } if (!rParentPoint.AllowChildren) { return false; } Point.ChildTo(rParentPoint); return true; }
/// <summary> /// Disconnects thechild mount point from the parent /// </summary> /// <param name="rChildPoint"></param> public void DisconnectMountPoints(MountPoint rParent, GameObject rChildObject) { for (int i = rParent.ChildMountPoints.Count - 1; i >= 0; i--) { MountPoint lChildPoint = rParent.ChildMountPoints[i].MountPoint; if (lChildPoint != null && lChildPoint._Owner == rChildObject) { lChildPoint.ChildTo(null); } } }
/// <summary> /// Conntects the child mount point to the parent /// </summary> /// <param name="rParent">String representing the parents mount point name</param> /// <param name="rChildItemPath">Resource path to the object we'll instanciate</param> /// <param name="rChildPointName">String representing the child's mount point name</param> /// <returns>GameObject that is the child that is instanciated</returns> public GameObject ConnectMountPoints(string rParentPoint, string rChildItemPath, string rChildPointName) { if (rChildItemPath.Length == 0) { return(null); } MountPoint lParentMP = GetMountPoint(rParentPoint); if (lParentMP == null) { return(null); } GameObject lChild = (GameObject)Instantiate(Resources.Load(rChildItemPath)); if (lChild == null) { return(null); } lChild.name = "Instanciated" + lChild.GetInstanceID(); MountPoint lChildMP = null; MountPoints lChildMPList = lChild.GetComponent <MountPoints>(); if (lChildMPList != null) { lChildMP = lChildMPList.GetMountPoint(rChildPointName); lChildMP.OwnerResourcePath = rChildItemPath; } else { Mount lChildMount = lChild.GetComponent <Mount>(); if (lChildMount != null) { lChildMP = lChildMount.Point; lChildMP.OwnerResourcePath = rChildItemPath; } } // If there is no mount point, get out if (lChildMP == null) { GameObject.DestroyObject(lChild); return(null); } // Finally, connect the objects ConnectMountPoints(lParentMP, lChildMP); // Return the newly created child return(lChild); }
/// <summary> /// Conntects the child mount point to the parent /// </summary> /// <param name="rParent">String representing the parents mount point name</param> /// <param name="rChild">Child mount point being connected</param> /// <returns>Boolean used to determine if the connection was made</returns> public bool ConnectMountPoints(string rParentPoint, MountPoint rChildPoint) { MountPoint lParentPoint = GetMountPoint(rParentPoint); if (lParentPoint == null) { return(false); } // Find the matching parent and attempt a connect return(ConnectMountPoints(lParentPoint, rChildPoint)); }
/// <summary> /// Disconnects thechild mount point from the parent /// </summary> /// <param name="rChildPoint"></param> public void DisconnectMountPoints(MountPoint rChildPoint) { if (rChildPoint == null) { return; } if (rChildPoint.ParentMountPoint == null) { return; } rChildPoint.ChildTo(null); }
/// <summary> /// Creates a mount point at run-time. This won't persist unless you /// serialize the data yourself during run-time. /// </summary> /// <param name="rName">Name of the mount point</param> /// <param name="rBoneName">Bone name to attach it to or empty string to attach to root</param> /// <param name="rIgnoreParentScale">Determines if we should ignore the parent object's scale value</param> /// <returns></returns> public MountPoint CreateMountPoint(string rName, string rBoneName, bool rIgnoreParentScale) { // Create the mount point MountPoint lPoint = new MountPoint(); lPoint.Owner = gameObject; lPoint.Name = rName; lPoint.BoneName = rBoneName; // Attach it to the right bone Transform lParentTransform = gameObject.transform; lPoint.Anchor = new GameObject(); lPoint.Anchor.name = "MP_" + lPoint.Anchor.GetInstanceID(); if (lPoint.BoneName.Length > 0) { Animator lAnimator = gameObject.GetComponent <Animator>(); if (lAnimator != null) { int lBoneIndex = MountPoints.GetHumanBodyBoneID(lPoint.BoneName); if (lBoneIndex >= 0 && lBoneIndex <= (int)HumanBodyBones.LastBone) { lParentTransform = lAnimator.GetBoneTransform((HumanBodyBones)lBoneIndex); } else { Transform lBoneTransform = MountPoints.FindBone(transform, lPoint.BoneName); if (lBoneTransform != null) { lParentTransform = lBoneTransform; } } } } lPoint.Anchor.transform.position = lParentTransform.position; lPoint.Anchor.transform.rotation = lParentTransform.rotation; lPoint.Anchor.transform.parent = lParentTransform; // Initialize by ignoring the scale lPoint.IgnoreParentScale = rIgnoreParentScale; // Add to the list of mount points Points.Add(lPoint); // Return the point return(lPoint); }
/// <summary> /// Connects the child mount point to the parent /// </summary> /// <param name="rParent">Parent mount point we are connecting to</param> /// <param name="rChild">Child mount point being connected</param> /// <returns>Boolean used to determine if the connection was made</returns> public bool ConnectMountPoints(MountPoint rParentPoint) { if (rParentPoint == null) { return(false); } if (!rParentPoint.AllowChildren) { return(false); } Point.ChildTo(rParentPoint); return(true); }
/// <summary> /// Disconnects the child mount point from the parent /// </summary> /// <param name="rParent">Parent mount point who owns the child</param> /// <param name="rChild">Child mount point to disconnect</param> public void DisconnectMountPoints(MountPoint rParent, MountPoint rChild) { if (rParent == null) { return; } if (rChild == null) { return; } if (rChild.ParentMountPoint == rParent) { rChild.ChildTo(null); } }
/// <summary> /// Grab the closest mount point to this mount /// </summary> /// <param name="rSourceMount"></param> /// <returns></returns> public static MountPoint GetClosestMountPoint(Mount rSourceMount) { MountPoint lMountPoint = null; MountPoint lSourceMountPoint = rSourceMount.Point; Vector3 lSourceMountPosition = lSourceMountPoint._Anchor.transform.position; MountPoint lTestMountPoint = GetClosestMountPoint(lSourceMountPosition, rSourceMount, null); if (lTestMountPoint != null) { lMountPoint = lTestMountPoint; } return(lMountPoint); }
/// <summary> /// Creates a mount point at run-time. This won't persist unless you /// serialize the data yourself during run-time. /// </summary> /// <param name="rName">Name of the mount point</param> /// <param name="rBoneName">Bone name to attach it to or empty string to attach to root</param> /// <param name="rIgnoreParentScale">Determines if we should ignore the parent object's scale value</param> /// <returns></returns> public MountPoint CreateMountPoint(string rName, string rBoneName, bool rIgnoreParentScale) { // Create the mount point Point = new MountPoint(); Point.Owner = gameObject; Point.Name = rName; Point.BoneName = rBoneName; Point.AllowChildren = false; Point.ForceChildOrientation = false; Point.IgnoreParentScale = false; // Attach it to the right bone Transform lParentTransform = gameObject.transform; Point.Anchor = new GameObject(); Point.Anchor.name = "MP_" + Point.Anchor.GetInstanceID(); if (Point.BoneName.Length > 0) { Animator lAnimator = gameObject.GetComponent<Animator>(); if (lAnimator != null) { int lBoneIndex = MountPoints.GetHumanBodyBoneID(Point.BoneName); if (lBoneIndex >= 0 && lBoneIndex <= (int)HumanBodyBones.LastBone) { lParentTransform = lAnimator.GetBoneTransform((HumanBodyBones)lBoneIndex); } else { Transform lBoneTransform = MountPoints.FindBone(transform, Point.BoneName); if (lBoneTransform != null) { lParentTransform = lBoneTransform; } } } } Point.Anchor.transform.position = lParentTransform.position; Point.Anchor.transform.rotation = lParentTransform.rotation; Point.Anchor.transform.parent = lParentTransform; // Initialize by ignoring the scale Point.IgnoreParentScale = rIgnoreParentScale; // Return the point return Point; }
/// <summary> /// Given the position, find the closest mount point. However, we don't want that mount point to be part of the /// current Mount or MountPoints component. /// </summary> /// <param name="rPosition"></param> /// <param name="rSourceMount"></param> /// <param name="rSourceMountPoints"></param> /// <returns></returns> public MountPoint GetClosestMountPoint(Vector3 rPosition) { MountPoint lMountPoint = null; float lDistance = float.MaxValue; for (int i = 0; i < Points.Count; i++) { Vector3 lTestPosition = Points[i]._Anchor.transform.position; float lTestDistance = Vector3.Distance(rPosition, lTestPosition); if (lTestDistance < lDistance) { lDistance = lTestDistance; lMountPoint = Points[i]; } } return(lMountPoint); }
/// <summary> /// Given the position, find the closest mount point. However, we don't want that mount point to be part of the /// current Mount or MountPoints component. /// </summary> /// <param name="rPosition"></param> /// <param name="rSourceMount"></param> /// <param name="rSourceMountPoints"></param> /// <returns></returns> public static MountPoint GetClosestMountPoint(Vector3 rPosition, Mount rSourceMount, MountPoints rSourceMountPoints) { MountPoint lMountPoint = null; float lDistance = float.MaxValue; MountPoints[] lMountPoints = Component.FindObjectsOfType <MountPoints>(); for (int i = 0; i < lMountPoints.Length; i++) { if (lMountPoints[i] == rSourceMountPoints) { continue; } for (int j = 0; j < lMountPoints[i].Points.Count; j++) { Vector3 lTestPosition = lMountPoints[i].Points[j]._Anchor.transform.position; float lTestDistance = Vector3.Distance(rPosition, lTestPosition); if (lTestDistance < lDistance) { lDistance = lTestDistance; lMountPoint = lMountPoints[i].Points[j]; } } } Mount[] lMounts = Component.FindObjectsOfType <Mount>(); for (int i = 0; i < lMounts.Length; i++) { if (lMounts[i] == rSourceMount) { continue; } Vector3 lTestPosition = lMounts[i].Point._Anchor.transform.position; float lTestDistance = Vector3.Distance(rPosition, lTestPosition); if (lTestDistance < lDistance) { lDistance = lTestDistance; lMountPoint = lMounts[i].Point; } } return(lMountPoint); }
/// <summary> /// Conntects the child mount point to the parent /// </summary> /// <param name="rParentPoint">String representing the parents mount point name</param> /// <param name="rChild">GameObject representing the child</param> /// <param name="rChildPointName">String representing the child mount point name</param> /// <returns>Boolean used to determine if the connection was made</returns> public bool ConnectMountPoints(string rParentPoint, GameObject rChild, string rChildPointName) { if (rChild == null) { return(false); } MountPoint lParentMP = GetMountPoint(rParentPoint); if (lParentMP == null) { return(false); } MountPoint lChildMP = null; MountPoints lChildMPList = rChild.GetComponent <MountPoints>(); if (lChildMPList != null) { lChildMP = lChildMPList.GetMountPoint(rChildPointName); } else { Mount lParentMount = rChild.GetComponent <Mount>(); if (lParentMount != null) { lChildMP = lParentMount.Point; } } // If there is no child, get out if (lChildMP == null) { return(false); } // Finally, connect the objects return(ConnectMountPoints(lParentMP, lChildMP)); }
/// <summary> /// Allows us to add to a list /// </summary> /// <param name="rList"></param> private void OnPointListItemAdd(ReorderableList rList) { // Create the mount point and initialize it mSelectedPoint = mTarget.CreateMountPoint("New Mount Point", "", true); // Make it the selected one mPointList.index = mTarget.Points.Count - 1; OnPointListItemSelect(rList); mIsDirty = true; }
/// <summary> /// Removes a child mount point from the list /// </summary> /// <param name="rChild"></param> public void RemoveChild(MountPoint rChild) { if (rChild == null) { return; } // Remove the child's parent if (rChild.ParentMountPoint == this) { rChild.ParentMountPoint = null; } // Remove the child from the list for (int i = ChildMountPoints.Count - 1; i >= 0; i--) { MountPointPtr lChild = ChildMountPoints[i]; if (lChild.Owner == rChild._Owner && lChild.GUID == rChild.GUID) { // Just in case we find it more than once, clear out the parent again MountPoint lChildMountPoint = lChild.MountPoint; if (lChildMountPoint.ParentMountPoint == this) { lChildMountPoint.ParentMountPoint = null; } // Remove it from the list ChildMountPoints.RemoveAt(i); } } }
/// <summary> /// Mount Point constructor /// </summary> /// <param name="rSource">Mount Point to fill the reference with</param> public MountPointPtr(MountPoint rSource) { MountPoint = rSource; }
/// <summary> /// Attaches this mount point's owner to the specified /// parent. Clears the attachment if the parent is null /// </summary> /// <param name="rParent"></param> public void ChildTo(MountPoint rParent) { // If we have an invalid owner, then the owner was // probably deleted and we need to disconnect this object if (_Owner == null) { if (ParentMountPoint != null) { ParentMountPoint.RemoveChild(this); } return; } // Ensure we're not trying to parent to a child for (int i = 0; i < ChildMountPoints.Count; i++) { if (ChildMountPoints[i].MountPoint == rParent) { return; } } // Clear out the parent if (rParent == null) { // Disconnect the mount points if (ParentMountPoint != null) { ParentMountPoint.RemoveChild(this); } // Disconnect the actual parenting _Owner.transform.parent = null; _Owner.transform.localScale = _OriginalScale; } // Assign the parent else if (rParent._Anchor != null) { // Ensure the our orientation is correct if (rParent.ForceChildOrientation) { _Owner.transform.rotation = Quaternion.identity; _Owner.transform.rotation = OrientTo(_Anchor.transform.rotation, rParent._Anchor.transform.rotation, rParent.InvertOrientation); } // Since we changed the orientation of the parent, we // may need to reposition it to the mount point Vector3 lDelta = rParent._Anchor.transform.position - _Anchor.transform.position; _Owner.transform.position += lDelta; // Store our current scale so we can go back to it if needed if (_Owner.transform.parent == null) { _OriginalScale = _Owner.transform.lossyScale; } // Parent and adjust the scale as needed _Owner.transform.parent = rParent._Anchor.transform; // Record this mount point is attached to the parent if (ParentMountPoint != rParent) { rParent.AddChild(this); } } }
/// <summary> /// Manages the connection between two mount points (and thier owners) /// </summary> /// <param name="rChild"></param> /// <param name="rParent"></param> private void ConnectMountPoints(MountPoint rChild, MountPoint rParent) { if (rChild == null) { return; } if (!rChild.IsLocked) { return; } if (rParent != null && !rParent.AllowChildren) { return; } // Parent the two rChild.ChildTo(rParent); // Flag the list as needing updating mIsDirty = true; }
/// <summary> /// Breaks the connection between the child and parent mount points /// </summary> /// <param name="rChild">Child mount point to break</param> private void DisconnectMountPoints(MountPoint rChild, MountPoint rParent) { if (rChild == null) { return; } rChild.ChildTo(null); // Sanity check to ensure the child is removed from the parent if (rParent != null) { rParent.RemoveChild(rChild); } // Flag the list as needing updating mIsDirty = true; }
/// <summary> /// Update the mount point with the new anchor information /// </summary> /// <param name="rMountPoint">Mount point to update</param> private void UpdateMountPointBone(ref MountPoint rMountPoint) { rMountPoint.AnchorTo(rMountPoint.BoneName); // Flag the list as needing updating mIsDirty = true; }
/// <summary> /// Use this function to find the closest snap points and put them together /// </summary> /// <returns>Boolean that determines if a snap point was found</returns> private bool FindSnapPoints() { float lMinDistance = float.MaxValue; MountPoint lChildSnapPoint = null; MountPoint lParentSnapPoint = null; // Cycle through our mount points and compare them to other // object mount points. If we find one close enough, we'll snap for (int i = 0; i < mScenePointPositions.Count; i++) { float lDistance = Vector3.Distance(mTarget.Point.Anchor.transform.position, mScenePointPositions[i]); if (lDistance < MountPoints.EditorSnapDistance && lDistance < lMinDistance) { lMinDistance = lDistance; lChildSnapPoint = mTarget.Point; lParentSnapPoint = mScenePoints[i]; } } // Test if we need to invert the parenting if (lChildSnapPoint != null && lParentSnapPoint != null) { // Flip the snap points if we have a selected point if (mTarget.Point != null && mTarget.Point == lParentSnapPoint) { lParentSnapPoint = lChildSnapPoint; lChildSnapPoint = mTarget.Point; } // Ensure they aren't already parented the other way if (lParentSnapPoint.ParentMountPoint == lChildSnapPoint) { MountPoint lTemp = lParentSnapPoint; lParentSnapPoint = lChildSnapPoint; lChildSnapPoint = lTemp; } // If the parent doesn't allow children, don't snap if (!lParentSnapPoint.AllowChildren) { lParentSnapPoint = null; lChildSnapPoint = null; } } // Set the resulting snap points (if found) mChildSnapPoint = lChildSnapPoint; mParentSnapPoint = lParentSnapPoint; return (mChildSnapPoint != null); }
/// <summary> /// Renders the properties of the motion so they can be changed here /// </summary> /// <param name="rLayerIndex">Layer the motion belongs to</param> /// <param name="rMotionIndex">Motions whose properites are to be listed</param> private bool DrawPointDetailItem(MountPoint rPoint) { bool lIsDirty = false; EditorHelper.DrawSmallTitle(rPoint.Name); EditorGUILayout.BeginHorizontal(); // Friendly name string lNewName = EditorGUILayout.TextField(new GUIContent("Name", "Friendly name of the mount point."), rPoint.Name); if (lNewName != rPoint.Name) { lIsDirty = true; rPoint.Name = lNewName; } GUILayout.Space(5); // Locked EditorGUILayout.LabelField(new GUIContent("Locked", "Determines if the MP can be moved."), GUILayout.Width(43)); bool lNewIsLocked = EditorGUILayout.Toggle(rPoint.IsLocked, GUILayout.Width(16)); if (lNewIsLocked != rPoint.IsLocked) { lIsDirty = true; rPoint.IsLocked = lNewIsLocked; } EditorGUILayout.EndHorizontal(); GUILayout.Space(5); // Bone string lBoneName = rPoint.BoneName; int lOriginalSelectedBoneIndex = GetBoneIndex(lBoneName); int lSelectedBoneIndex = EditorGUILayout.Popup("Bone", lOriginalSelectedBoneIndex, mBoneNames.ToArray()); if (lSelectedBoneIndex != lOriginalSelectedBoneIndex && lSelectedBoneIndex == (mBoneNames.Count - 1)) { lBoneName = ""; } string lNewBoneName = lBoneName; if (lSelectedBoneIndex == (mBoneNames.Count - 1)) { lNewBoneName = EditorGUILayout.TextField(new GUIContent("Bone Name", "Full path and name to the bone the MP should anchor to."), lBoneName); } else { lNewBoneName = mBoneNames[lSelectedBoneIndex]; } bool lIsBoneDirty = false; if (lNewBoneName != lBoneName) { lIsDirty = true; lIsBoneDirty = true; rPoint.BoneName = lNewBoneName; } GUILayout.Space(5); if (rPoint.Anchor != null) { // Position Vector3 lPositionValues = rPoint.Anchor.transform.localPosition; lPositionValues.x = Convert.ToSingle(lPositionValues.x.ToString("0.0000")); lPositionValues.y = Convert.ToSingle(lPositionValues.y.ToString("0.0000")); lPositionValues.z = Convert.ToSingle(lPositionValues.z.ToString("0.0000")); Vector3 lNewPositionValues = EditorGUILayout.Vector3Field(new GUIContent("Position", "Position relative to the transform the MP belongs to."), lPositionValues); if (lNewPositionValues != lPositionValues) { lIsDirty = true; rPoint.Anchor.transform.localPosition = lNewPositionValues; } // Rotation Vector3 lRotationValues = rPoint.Anchor.transform.localRotation.eulerAngles; lRotationValues.x = Convert.ToSingle(lRotationValues.x.ToString("0.0000")); lRotationValues.y = Convert.ToSingle(lRotationValues.y.ToString("0.0000")); lRotationValues.z = Convert.ToSingle(lRotationValues.z.ToString("0.0000")); Vector3 lNewRotationValues = EditorGUILayout.Vector3Field(new GUIContent("Orientation (p, y, r)", "Rotation relative to the transform the MP belongs to."), lRotationValues); if (lNewRotationValues != lRotationValues) { lIsDirty = true; rPoint.Anchor.transform.localRotation = Quaternion.Euler(lNewRotationValues); } } // Render the parent mount point if (rPoint.ParentMountPoint != null) { EditorHelper.DrawLine(); MountPoint lParentPoint = rPoint.ParentMountPoint; EditorGUILayout.BeginHorizontal(); GUILayout.Label("Parent:", GUILayout.Width(45)); GUILayout.Label(lParentPoint.Owner.name + "." + lParentPoint.Name, GUILayout.MinWidth(100)); if (GUILayout.Button(new GUIContent("", "Select parent"), EditorHelper.BlueSelectButton, GUILayout.Width(16), GUILayout.Height(16))) { Selection.activeGameObject = lParentPoint.Owner; } if (GUILayout.Button(new GUIContent("", "Break connection"), EditorHelper.RedXButton, GUILayout.Width(16), GUILayout.Height(16))) { DisconnectMountPoints(rPoint, lParentPoint); } GUILayout.Space(2); EditorGUILayout.EndHorizontal(); GUILayout.Space(5); } if (lIsBoneDirty) { UpdateMountPointBone(ref rPoint); } if (lIsDirty) { LoadOtherMountPoints(); } return lIsDirty; }
/// <summary> /// Renders the properties of the motion so they can be changed here /// </summary> /// <param name="rLayerIndex">Layer the motion belongs to</param> /// <param name="rMotionIndex">Motions whose properites are to be listed</param> private bool DrawPointDetailItem(MountPoint rPoint) { bool lIsDirty = false; EditorHelper.DrawSmallTitle(rPoint.Name); EditorGUILayout.BeginHorizontal(); // Friendly name string lNewName = EditorGUILayout.TextField(new GUIContent("Name", "Friendly name of the mount point."), rPoint.Name); if (lNewName != rPoint.Name) { lIsDirty = true; rPoint.Name = lNewName; } GUILayout.Space(5); // Locked EditorGUILayout.LabelField(new GUIContent("Locked", "Determines if the MP can be moved."), GUILayout.Width(43)); bool lNewIsLocked = EditorGUILayout.Toggle(rPoint.IsLocked, GUILayout.Width(16)); if (lNewIsLocked != rPoint.IsLocked) { lIsDirty = true; rPoint.IsLocked = lNewIsLocked; } EditorGUILayout.EndHorizontal(); GUILayout.Space(5); // Bone string lBoneName = rPoint.BoneName; int lOriginalSelectedBoneIndex = GetBoneIndex(lBoneName); int lSelectedBoneIndex = EditorGUILayout.Popup("Bone", lOriginalSelectedBoneIndex, mBoneNames.ToArray()); if (lSelectedBoneIndex != lOriginalSelectedBoneIndex && lSelectedBoneIndex == (mBoneNames.Count - 1)) { lBoneName = ""; } string lNewBoneName = lBoneName; if (lSelectedBoneIndex == (mBoneNames.Count - 1)) { lNewBoneName = EditorGUILayout.TextField(new GUIContent("Bone Name", "Full path and name to the bone the MP should anchor to."), lBoneName); } else { lNewBoneName = mBoneNames[lSelectedBoneIndex]; } bool lIsBoneDirty = false; if (lNewBoneName != lBoneName) { lIsDirty = true; lIsBoneDirty = true; rPoint.BoneName = lNewBoneName; } GUILayout.Space(5); // Position Vector3 lPositionValues = rPoint.Anchor.transform.localPosition; lPositionValues.x = Convert.ToSingle(lPositionValues.x.ToString("0.0000")); lPositionValues.y = Convert.ToSingle(lPositionValues.y.ToString("0.0000")); lPositionValues.z = Convert.ToSingle(lPositionValues.z.ToString("0.0000")); Vector3 lNewPositionValues = EditorGUILayout.Vector3Field(new GUIContent("Position", "Position relative to the transform the MP belongs to."), lPositionValues); if (lNewPositionValues != lPositionValues) { lIsDirty = true; rPoint.Anchor.transform.localPosition = lNewPositionValues; } // Rotation Vector3 lRotationValues = rPoint.Anchor.transform.localRotation.eulerAngles; lRotationValues.x = Convert.ToSingle(lRotationValues.x.ToString("0.0000")); lRotationValues.y = Convert.ToSingle(lRotationValues.y.ToString("0.0000")); lRotationValues.z = Convert.ToSingle(lRotationValues.z.ToString("0.0000")); Vector3 lNewRotationValues = EditorGUILayout.Vector3Field(new GUIContent("Orientation (p, y, r)", "Rotation relative to the transform the MP belongs to."), lRotationValues); if (lNewRotationValues != lRotationValues) { lIsDirty = true; rPoint.Anchor.transform.localRotation = Quaternion.Euler(lNewRotationValues); } GUILayout.Space(5); // Allow children bool lNewAllowChildren = EditorGUILayout.Toggle(new GUIContent("Allow Children", "Determines if this mount point can have children mounted to it."), rPoint.AllowChildren); if (lNewAllowChildren != rPoint.AllowChildren) { lIsDirty = true; rPoint.AllowChildren = lNewAllowChildren; } // Set child orientation bool lNewForceOrientation = EditorGUILayout.Toggle(new GUIContent("Set Child Orientation", "Determines if this MP will force the child to rotate to match its orientation."), rPoint.ForceChildOrientation); if (lNewForceOrientation != rPoint.ForceChildOrientation) { lIsDirty = true; rPoint.ForceChildOrientation = lNewForceOrientation; } // Ignore parent scale bool lNewIgnoreParentScale = EditorGUILayout.Toggle(new GUIContent("Preserve Child Scale", "Determines if this MP will prevent children from scaling when they connect."), rPoint.IgnoreParentScale); if (lNewIgnoreParentScale != rPoint.IgnoreParentScale) { lIsDirty = true; rPoint.IgnoreParentScale = lNewIgnoreParentScale; } // Render the parent mount point if (rPoint.ParentMountPoint != null) { EditorHelper.DrawLine(); MountPoint lParentPoint = rPoint.ParentMountPoint; EditorGUILayout.BeginHorizontal(); GUILayout.Label("Parent:", GUILayout.Width(45)); GUILayout.Label(lParentPoint.Owner.name + "." + lParentPoint.Name, GUILayout.MinWidth(100)); if (GUILayout.Button(new GUIContent("", "Select parent"), EditorHelper.BlueSelectButton, GUILayout.Width(16), GUILayout.Height(16))) { Selection.activeGameObject = lParentPoint.Owner; } if (GUILayout.Button(new GUIContent("", "Break connection"), EditorHelper.RedXButton, GUILayout.Width(16), GUILayout.Height(16))) { DisconnectMountPoints(rPoint, lParentPoint); } GUILayout.Space(2); EditorGUILayout.EndHorizontal(); } // Render the children mount points if (rPoint.ChildMountPoints.Count > 0) { EditorHelper.DrawLine(); // Show the remaining child points for (int i = 0; i < rPoint.ChildMountPoints.Count; i++) { MountPoint lChildPoint = rPoint.ChildMountPoints[i].MountPoint; if (lChildPoint.Owner == null) { continue; } EditorGUILayout.BeginHorizontal(); GUILayout.Label("Child:", GUILayout.Width(40)); GUILayout.Label(lChildPoint.Owner.name + "." + lChildPoint.Name, GUILayout.MinWidth(100)); if (GUILayout.Button(new GUIContent("", "Select child"), EditorHelper.BlueSelectButton, GUILayout.Width(16), GUILayout.Height(16))) { Selection.activeGameObject = lChildPoint.Owner; } if (GUILayout.Button(new GUIContent("", "Break connection"), EditorHelper.RedXButton, GUILayout.Width(16), GUILayout.Height(16))) { DisconnectMountPoints(lChildPoint, rPoint); } GUILayout.Space(2); EditorGUILayout.EndHorizontal(); } } GUILayout.Space(5); if (lIsBoneDirty) { UpdateMountPointBone(ref rPoint); } if (lIsDirty) { LoadOtherMountPoints(); } return lIsDirty; }
/// <summary> /// Adds a child mount point to the list /// </summary> /// <param name="rChild"></param> public void AddChild(MountPoint rChild) { if (rChild == null) { return; } if (!_AllowChildren) { return; } // If the child already has a parent, we need to clear it and reset if (rChild.ParentMountPoint != null) { rChild.ParentMountPoint.RemoveChild(rChild); } rChild.ParentMountPoint = this; // First, check if it already exists. We don't want to add it twice for (int i = 0; i < ChildMountPoints.Count; i++) { MountPointPtr lChild = ChildMountPoints[i]; if (lChild.Owner == rChild._Owner && lChild.GUID == rChild.GUID) { return; } } // If we got here, we need to add the child MountPointPtr lReference = new MountPointPtr(rChild); ChildMountPoints.Add(lReference); }
/// <summary> /// Disconnects thechild mount point from the parent /// </summary> /// <param name="rChildPoint"></param> public void DisconnectMountPoints(MountPoint rChildPoint) { if (rChildPoint == null) { return; } if (rChildPoint.ParentMountPoint == null) { return; } rChildPoint.ChildTo(null); }
/// <summary> /// Conntects the child mount point to the parent /// </summary> /// <param name="rParent">String representing the parents mount point name</param> /// <param name="rChild">Child mount point being connected</param> /// <returns>Boolean used to determine if the connection was made</returns> public bool ConnectMountPoints(string rParentPoint, MountPoint rChildPoint) { MountPoint lParentPoint = GetMountPoint(rParentPoint); if (lParentPoint == null) { return false; } // Find the matching parent and attempt a connect return ConnectMountPoints(lParentPoint, rChildPoint); }
/// <summary> /// Disconnects the child mount point from the parent /// </summary> /// <param name="rParent">Parent mount point who owns the child</param> /// <param name="rChild">Child mount point to disconnect</param> public void DisconnectMountPoints(MountPoint rParent, MountPoint rChild) { if (rParent == null) { return; } if (rChild == null) { return; } if (rChild.ParentMountPoint == rParent) { rChild.ChildTo(null); } }
/// <summary> /// Allows us process when a list is selected /// </summary> /// <param name="rList"></param> private void OnPointListItemSelect(ReorderableList rList) { mTarget.EditorPointIndex = rList.index; if (mTarget.EditorPointIndex == -1) { mSelectedPoint = null; } else { mSelectedPoint = mTarget.Points[mTarget.EditorPointIndex]; } if (SceneView.sceneViews.Count > 0) { SceneView lSceneView = (SceneView)SceneView.sceneViews[0]; lSceneView.Focus(); } }
/// <summary> /// Mount Point constructor /// </summary> /// <param name="rSource">Mount Point to fill the reference with</param> public MountPointPtr(MountPoint rSource) { MountPoint = rSource; }
/// <summary> /// Attaches this mount point's owner to the specified /// parent. Clears the attachment if the parent is null /// </summary> /// <param name="rParent"></param> public void ChildTo(MountPoint rParent) { // If we have an invalid owner, then the owner was // probably deleted and we need to disconnect this object if (_Owner == null) { if (ParentMountPoint != null) { ParentMountPoint.RemoveChild(this); } return; } // Ensure we're not trying to parent to a child for (int i = 0; i < ChildMountPoints.Count; i++) { if (ChildMountPoints[i].MountPoint == rParent) { return; } } // Clear out the parent if (rParent == null) { // Disconnect the mount points if (ParentMountPoint != null) { ParentMountPoint.RemoveChild(this); } // Disconnect the actual parenting _Owner.transform.parent = null; _Owner.transform.localScale = _OriginalScale; } // Assign the parent else if (rParent._Anchor != null) { // Ensure the our orientation is correct if (rParent.ForceChildOrientation) { _Owner.transform.rotation = Quaternion.identity; _Owner.transform.rotation = OrientTo(_Anchor.transform.rotation, rParent._Anchor.transform.rotation); } // Since we changed the orientation of the parent, we // may need to reposition it to the mount point Vector3 lDelta = rParent._Anchor.transform.position - _Anchor.transform.position; _Owner.transform.position += lDelta; // Store our current scale so we can go back to it if needed if (_Owner.transform.parent == null) { _OriginalScale = _Owner.transform.lossyScale; } // Parent and adjust the scale as needed _Owner.transform.parent = rParent._Anchor.transform; // Record this mount point is attached to the parent if (ParentMountPoint != rParent) { rParent.AddChild(this); } } }