Пример #1
0
 private void MarkChildRetain(IBone parent)
 {
     foreach (var bone in m_BoneList.bones)
     {
         if (BoneUtility.IsOffspringOf(bone, parent) || bone == parent)
         {
             bone.markedRetainWorldPosition = true;
         }
     }
 }
Пример #2
0
        public void DeleteBone(IBone bone)
        {
            foreach (var otherBone in m_BoneList.bones)
            {
                if (BoneUtility.IsOffspringOf(otherBone, bone))
                {
                    throw new InvalidOperationException("Cannot delete a parent bone with children. Children should all be removed/transfered first.");
                }
            }

            m_BoneList.bones.Remove((Bone)bone);

            m_OrderDirty = true;
            SetDirty();
            MarkChildRetain(bone);
            UpdateHierarchyFromBone(bone, true);
        }
Пример #3
0
        public void Parent(IBone newChild, IBone parent)
        {
            if (newChild == parent)
            {
                throw new InvalidOperationException("Cannot parent a bone to itself.");
            }
            if (BoneUtility.IsOffspringOf(parent, newChild))
            {
                throw new InvalidOperationException(string.Format("Cannot parent {0} to {1}. This will create a loop.", newChild.name, parent.name));
            }

            MarkChildRetain(newChild);

            ((Bone)newChild).parent = parent;

            m_OrderDirty = true;
            SetDirty();
            UpdateHierarchyFromBone(newChild, true);
        }
Пример #4
0
        private void UpdateHierarchyFromBone(IBone fromBone, bool keepChildPosition)
        {
            if (m_OrderDirty)
            {
                m_OrderDirty = false;
                SortBones();
            }

            foreach (var bone in m_BoneList.bones)
            {
                if (BoneUtility.IsOffspringOf(bone, fromBone) || bone == fromBone)
                {
                    if (bone.markedRetainWorldPosition)
                    {
                        bone.RestoreWorldPosition();
                    }
                    bone.RecalculateMatrix();
                }
            }
        }
        // Click on bone body and tip. Handle parenting state here as well.
        private void HandleSelection()
        {
            // Tip first. If a bone near the tip is clicked later, the bone will be selected instead of tip.
            foreach (var bone in m_Model.bones)
            {
                if (m_View.HandleTipSelect(bone))
                {
                    SelectSingleBone(bone);
                    m_View.Refresh();

                    // Always reset relationship after a new selection.
                    ResetRelationship();

                    m_InfoView.SelectionChanged();

                    break;
                }
            }

            // Bone second. Replace selected tip, if bone is clicked on as well.
            foreach (var bone in m_Model.bones)
            {
                if (m_View.HandleBoneSelect(bone))
                {
                    // During parenting state, a click on a bone will not select the bone, but mark this bone as new parent.
                    if (state.parenting)
                    {
                        foreach (var selectedBone in state.selectedBones)
                        {
                            if (bone == selectedBone)
                            {
                                throw new InvalidOperationException("Cannot parent a bone to itself.");
                            }
                            if (BoneUtility.IsOffspringOf(bone, selectedBone))
                            {
                                throw new InvalidOperationException(string.Format("Cannot parent {0} to {1}. This will create a loop.", bone.name, selectedBone.name));
                            }
                        }

                        RecordUndo(bone, "bone parent");

                        foreach (var selectedBone in state.selectedBones)
                        {
                            m_Model.Parent(selectedBone, bone);
                        }

                        // Exit parenting state.
                        state.parenting = false;

                        m_View.Refresh();
                        break;
                    }
                    else
                    {
                        if (state.multiselecting)
                        {
                            state.selectedBones.Add(bone);
                        }
                        else if (!state.selectedBones.Contains(bone))
                        {
                            SelectSingleBone(bone);
                        }

                        m_View.Refresh();

                        // Always reset relationship after a new selection.
                        ResetRelationship();

                        m_InfoView.SelectionChanged();

                        if (!state.multiselecting)
                        {
                            break;
                        }
                    }
                }
            }
        }
        // Repopulate the relationship hash tables for current selected bones.
        public void ResetRelationship()
        {
            m_ChildrenOfSelected.Clear();
            m_SiblingToMoveTogether.Clear();
            m_UpdateParentTip.Clear();
            m_OffspringOfSelected.Clear();
            m_OffspringOfParent.Clear();

            foreach (var bone in state.selectedBones)
            {
                List <IBone> childrenOfSelected     = new List <IBone>();
                List <IBone> childrenToMoveTogether = new List <IBone>();
                List <IBone> siblingToMoveTogether  = new List <IBone>();
                List <IBone> offspringOfSelected    = new List <IBone>();
                List <IBone> offspringOfParent      = new List <IBone>();

                // Traverse all bones to find relationships.
                foreach (var otherBone in m_Model.bones)
                {
                    // Itself
                    if (otherBone == bone)
                    {
                        if (!bone.isRoot)
                        {
                            // Add itself as offspring of its parent. Made sense, right?
                            offspringOfParent.Add(otherBone);
                        }
                        continue;
                    }

                    // Immediate child.
                    if (otherBone.parent == bone)
                    {
                        childrenOfSelected.Add(otherBone);

                        if (ShouldSnap(bone.position, otherBone.position))
                        {
                            // If close enough, they should move together in normal movement.
                            childrenToMoveTogether.Add(otherBone);
                        }
                    }

                    // Sibling.
                    if (otherBone.parent == bone.parent)
                    {
                        if (ShouldSnap(bone.position, otherBone.position))
                        {
                            // If close enough, they should move together in normal movement.
                            siblingToMoveTogether.Add(otherBone);
                        }
                    }

                    // Child, grandchild, grand(^n)child.
                    if (BoneUtility.IsOffspringOf(otherBone, bone))
                    {
                        offspringOfSelected.Add(otherBone);
                    }

                    // Parent's child, grandchild, grand(^n)child.
                    if (!bone.isRoot && BoneUtility.IsOffspringOf(otherBone, bone.parent))
                    {
                        offspringOfParent.Add(otherBone);
                    }
                }

                // If bone is close to parent's tip, it will update parent's tip position when moved (normal move).
                var updateParentTip = !bone.isRoot && ShouldSnap(bone.position, bone.parent.tip);

                m_OffspringOfSelected.Add(bone, offspringOfSelected);
                m_ChildrenOfSelected.Add(bone, childrenOfSelected);
                m_SiblingToMoveTogether.Add(bone, siblingToMoveTogether);
                m_UpdateParentTip.Add(bone, updateParentTip);
                m_OffspringOfParent.Add(bone, offspringOfParent);
            }

            // When multiple bones are selected, movement handling of offspring is disabled if ancestor is selected (normal move).
            m_ValidToMultipleSelectMove = new List <IBone>();
            foreach (var bone in state.selectedBones)
            {
                var offspringOfOtherSelected = false;
                foreach (var c in m_OffspringOfSelected)
                {
                    if (c.Value.Contains(bone))
                    {
                        offspringOfOtherSelected = true;
                        break;
                    }
                }
                if (!offspringOfOtherSelected)
                {
                    m_ValidToMultipleSelectMove.Add(bone);
                }
            }
        }