public static void DeleteSpringBonesAndManagers()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("再生モードを止めてください。");
                return;
            }

            if (Selection.gameObjects.Length != 1)
            {
                Debug.LogError("一つだけのルートオブジェクトを選択してください");
                return;
            }

            var rootObject   = Selection.gameObjects.First();
            var queryMessage = "本当にこのオブジェクトとその子供に入っている全ての\n"
                               + "スプリングボーンとスプリングマネージャーを削除しますか?\n\n"
                               + rootObject.name;

            if (EditorUtility.DisplayDialog(
                    "スプリングボーンとマネージャーを削除", queryMessage, "削除", "キャンセル"))
            {
                SpringBoneSetup.DestroySpringManagersAndBones(rootObject);
                AssetDatabase.Refresh();
            }
        }
        public static void AssignSpringBonesRecursively()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("再生モードを止めてください。");
                return;
            }

            if (Selection.gameObjects.Length < 1)
            {
                Debug.LogError("一つ以上のオブジェクトを選択してください。");
                return;
            }

            var springManagers = new HashSet <SpringManager>();

            foreach (var gameObject in Selection.gameObjects)
            {
                SpringBoneSetup.AssignSpringBonesRecursively(gameObject.transform);
                var manager = gameObject.GetComponentInParent <SpringManager>();
                if (manager != null)
                {
                    springManagers.Add(manager);
                }
            }

            foreach (var manager in springManagers)
            {
                SpringBoneSetup.FindAndAssignSpringBones(manager, true);
            }

            AssetDatabase.Refresh();
        }
示例#3
0
        public static void DeleteSpringBonesAndManagers()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("请退出Play模式。");
                return;
            }

            if (Selection.gameObjects.Length != 1)
            {
                Debug.LogError("只可以选择一个Root对象");
                return;
            }

            var rootObject   = Selection.gameObjects.First();
            var queryMessage =
                "确定要把以下对象及其子对象中的\n"
                + "SpringBone与SpringManager都删除吗?\n\n"
                + rootObject.name
            ;

            if (EditorUtility.DisplayDialog(
                    "考虑清楚,真的要删掉嘛", queryMessage, "删除", "取消"))
            {
                SpringBoneSetup.DestroySpringManagersAndBones(rootObject);
                AssetDatabase.Refresh();
            }
        }
示例#4
0
        public static SpringManager PerformSetup
        (
            GameObject rootObject,
            IEnumerable <GameObject> newSpringBones,
            AutoSetupParameters parameters
        )
        {
            SpringBoneSetup.DestroySpringManagersAndBones(rootObject);
            SpringColliderSetup.DestroySpringColliders(rootObject);

            var springBones = new List <SpringBone>();

            foreach (var boneParent in newSpringBones.Where(boneParent => boneParent.transform.childCount > 0))
            {
                springBones.Add(boneParent.AddComponent <SpringBone>());
            }

            var manager = rootObject.AddComponent <SpringManager>();

            SpringBoneSetup.FindAndAssignSpringBones(manager, true);

            if (parameters.createPivots)
            {
                foreach (var springBone in springBones)
                {
                    SpringBoneSetup.CreateSpringPivotNode(springBone);
                }
            }

            return(manager);
        }
            public void BuildObjects(GameObject springBoneRoot, GameObject colliderRoot, IEnumerable <string> requiredBones)
            {
                var managerProperties = PersistentSpringManagerProperties.Create(
                    springBoneRoot.GetComponentInChildren <SpringManager>());

                SpringBoneSetup.DestroySpringManagersAndBones(springBoneRoot);

                if (requiredBones != null)
                {
                    FilterBoneRecordsByRequiredBonesAndCreateUnrecordedBones(springBoneRoot, requiredBones);
                }

                var initialTransforms = GameObjectUtil.BuildNameToComponentMap <Transform>(springBoneRoot, true);

                foreach (var record in pivotRecords)
                {
                    BuildPivotFromSerializer(initialTransforms, record);
                }

                var setupMaps = SpringBoneSetupMaps.Build(springBoneRoot, colliderRoot);

                foreach (var record in springBoneRecords)
                {
                    BuildSpringBoneFromSerializer(setupMaps, record);
                }

                var springManager = springBoneRoot.AddComponent <SpringManager>();

                if (managerProperties != null)
                {
                    managerProperties.ApplyTo(springManager);
                }
                SpringBoneSetup.FindAndAssignSpringBones(springManager);
            }
            private void FilterBoneRecordsByRequiredBonesAndCreateUnrecordedBones
            (
                GameObject springBoneRoot,
                IEnumerable <string> requiredBones
            )
            {
                var boneRecordsToUse = springBoneRecords
                                       .Where(record => requiredBones.Contains(record.baseData.boneName));
                var recordedBoneNames = boneRecordsToUse.Select(record => record.baseData.boneName);

                var bonesWithoutRecords = requiredBones
                                          .Except(recordedBoneNames)
                                          .Select(boneName => GameObjectUtil.FindChildByName(springBoneRoot, boneName))
                                          .Where(item => item != null)
                                          .Select(item => item.gameObject);

                foreach (var bone in bonesWithoutRecords)
                {
                    var springBone = bone.AddComponent <SpringBone>();
                    SpringBoneSetup.CreateSpringPivotNode(springBone);
                }

                // Report the skipped bone records so the user knows
                var skippedBoneRecords = springBoneRecords.Except(boneRecordsToUse);

                foreach (var skippedRecord in skippedBoneRecords)
                {
                    Debug.LogWarning(skippedRecord.baseData.boneName
                                     + "\nボーンリストにないので作成しません");
                }

                springBoneRecords = boneRecordsToUse;
            }
示例#7
0
        public static void UpdateSpringManagerFromBoneList(SpringManager springManager)
        {
            var rootObject            = springManager.gameObject;
            var designatedSpringBones = GetBonesDesignatedForDynamics(rootObject);
            var currentSpringBones    = rootObject.GetComponentsInChildren <SpringBone>(true);

            var skinBones            = GameObjectExtensions.GameObjectUtil.GetAllBones(rootObject);
            var springBonesToDestroy = currentSpringBones
                                       .Where(bone => !designatedSpringBones.Contains(bone.gameObject));

            foreach (var boneToDestroy in springBonesToDestroy)
            {
                var pivot = boneToDestroy.pivotNode;
                if (pivot != null &&
                    SpringBoneSetup.IsPivotProbablySafeToDestroy(pivot, skinBones))
                {
                    SpringBoneSetup.DestroyUnityObject(pivot.gameObject);
                }
                SpringBoneSetup.DestroyUnityObject(boneToDestroy);
            }

            var objectsToAddBonesTo = designatedSpringBones
                                      .Where(bone => bone.GetComponent <SpringBone>() == null);

            foreach (var newBoneOwner in objectsToAddBonesTo)
            {
                var newSpringBone = newBoneOwner.AddComponent <SpringBone>();
                SpringBoneSetup.CreateSpringPivotNode(newSpringBone);
            }
            SpringBoneSetup.FindAndAssignSpringBones(springManager, true);
        }
示例#8
0
        private static void AutoLoadDynamics()
        {
            var springManagers = GameObjectUtil.FindComponentsOfType <SpringManager>();

            foreach (var springManager in springManagers)
            {
                var name = springManager.name;
                SpringBoneSetup.AutoLoad(springManager);
                System.IO.File.Delete(SpringBoneSetup.GetAutoSavePath(name));
            }
        }
示例#9
0
        private static void RemoveDuplicateComponents <T>() where T : Component
        {
            // Delete all components of the same type after the first
            var duplicateObjects = GameObjectExtensions.GameObjectUtil.FindComponentsOfType <Transform>()
                                   .Where(item => item.GetComponents <T>().Length > 1);

            if (duplicateObjects.Any())
            {
                Undo.RecordObjects(duplicateObjects.ToArray(), "Remove duplicate components");
                foreach (var transform in duplicateObjects)
                {
                    var components = transform.GetComponents <T>();
                    for (int componentIndex = 1; componentIndex < components.Length; componentIndex++)
                    {
                        SpringBoneSetup.DestroyUnityObject(components[componentIndex]);
                    }
                }
            }
        }
示例#10
0
        public static void CreatePivotForSpringBones()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("再生モードを止めてください。");
                return;
            }

            if (Selection.gameObjects.Length < 1)
            {
                Debug.LogError("一つ以上のオブジェクトを選択してください。");
                return;
            }

            var selectedSpringBones = Selection.gameObjects
                                      .Select(gameObject => gameObject.GetComponent <SpringBone>())
                                      .Where(bone => bone != null);

            foreach (var springBone in selectedSpringBones)
            {
                SpringBoneSetup.CreateSpringPivotNode(springBone);
            }
        }
示例#11
0
        public static void AddToOrUpdateSpringManagerInSelection()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("再生モードを止めてください。");
                return;
            }

            if (Selection.gameObjects.Length <= 0)
            {
                Debug.LogError("一つ以上のオブジェクトを選択してください。");
                return;
            }

            foreach (var gameObject in Selection.gameObjects)
            {
                var manager = gameObject.GetComponent <SpringManager>();
                if (manager == null)
                {
                    manager = gameObject.AddComponent <SpringManager>();
                }
                SpringBoneSetup.FindAndAssignSpringBones(manager, true);
            }
        }
示例#12
0
        public static void CleanUpDynamics()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("再生モードを止めてください。");
                return;
            }

            var springManagers = GameObjectExtensions.GameObjectUtil.FindComponentsOfType <SpringManager>();

            if (!springManagers.Any())
            {
                return;
            }

            var queryMessage = "本当にダイナミクスのクリーンナップを行いますか?";

            if (EditorUtility.DisplayDialog("ダイナミクスクリーンナップ", queryMessage, "削除", "キャンセル"))
            {
                RemoveDuplicateComponents <SpringBone>();
                RemoveDuplicateComponents <DynamicsNull>();
                RemoveDuplicateComponents <SpringManager>();

                springManagers = GameObjectExtensions.GameObjectUtil.FindComponentsOfType <SpringManager>();
                foreach (var springManager in springManagers)
                {
                    var springBones = springManager.GetComponentsInChildren <SpringBone>(true);
                    var allBones    = GameObjectExtensions.GameObjectUtil.GetAllBones(springManager.gameObject);

                    var maybeUnusedGameObjects = new HashSet <GameObject>();

                    var unusedSpheres = springManager.GetComponentsInChildren <SpringSphereCollider>(true)
                                        .Where(collider => !springBones.Any(springBone => springBone.sphereColliders.Contains(collider)));
                    foreach (var collider in unusedSpheres)
                    {
                        maybeUnusedGameObjects.Add(collider.gameObject);
                        SpringBoneSetup.DestroyUnityObject(collider);
                    }

                    var unusedCapsules = springManager.GetComponentsInChildren <SpringCapsuleCollider>(true)
                                         .Where(collider => !springBones.Any(springBone => springBone.capsuleColliders.Contains(collider)));
                    foreach (var collider in unusedCapsules)
                    {
                        maybeUnusedGameObjects.Add(collider.gameObject);
                        SpringBoneSetup.DestroyUnityObject(collider);
                    }

                    var unusedPanels = springManager.GetComponentsInChildren <SpringPanelCollider>(true)
                                       .Where(collider => !springBones.Any(springBone => springBone.panelColliders.Contains(collider)));
                    foreach (var collider in unusedPanels)
                    {
                        maybeUnusedGameObjects.Add(collider.gameObject);
                        SpringBoneSetup.DestroyUnityObject(collider);
                    }

                    var gameObjectsToDelete = maybeUnusedGameObjects
                                              .Where(gameObject => !allBones.Contains(gameObject.transform));
                    foreach (var gameObject in gameObjectsToDelete)
                    {
                        if (gameObject.GetComponents <Component>().Length <= 1)
                        {
                            SpringBoneSetup.DestroyUnityObject(gameObject);
                        }
                    }

                    // Next remove all empty entries from SpringBones
                    Undo.RecordObjects(springBones.ToArray(), "SpringBone cleanup");
                    foreach (var springBone in springBones)
                    {
                        springBone.capsuleColliders   = springBone.capsuleColliders.Where(item => item != null).ToArray();
                        springBone.panelColliders     = springBone.panelColliders.Where(item => item != null).ToArray();
                        springBone.sphereColliders    = springBone.sphereColliders.Where(item => item != null).ToArray();
                        springBone.lengthLimitTargets = springBone.lengthLimitTargets.Where(item => item != null).ToArray();
                    }
                }
            }
        }
示例#13
0
        public static void DeleteAllChildCollidersFromSelection()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("再生モードを止めてください。");
                return;
            }

            if (Selection.gameObjects.Length == 0)
            {
                return;
            }

            var queryMessage = "本当に選択中のオブジェクトの全子供のコライダーを削除しますか?";

            if (!EditorUtility.DisplayDialog("選択コライダーを削除", queryMessage, "削除", "キャンセル"))
            {
                return;
            }

            var charaBones = Selection.gameObjects
                             .SelectMany(gameObject => GameObjectExtensions.GameObjectUtil.GetAllBones(gameObject.transform.root.gameObject))
                             .Distinct();

            var colliderTypes = SpringColliderSetup.GetColliderTypes();
            var deadColliders = new List <Component>();

            foreach (var gameObject in Selection.gameObjects)
            {
                foreach (var type in colliderTypes)
                {
                    deadColliders.AddRange(gameObject.GetComponentsInChildren(type, true));
                }
            }
            deadColliders = deadColliders.Distinct().ToList();

            var probablyDeadGameObjects = deadColliders.Select(collider => collider.gameObject)
                                          .Distinct()
                                          .Where(gameObject => !charaBones.Contains(gameObject.transform) &&
                                                 gameObject.GetComponents <Component>().Count() <= 1 &&
                                                 gameObject.transform.childCount == 0)
                                          .ToArray();

            var springBones = GameObjectExtensions.GameObjectUtil.FindComponentsOfType <SpringBone>();
            var undoObjects = new List <Object>(springBones.Select(item => (Object)item));

            undoObjects.AddRange(deadColliders.Select(item => (Object)item));
            undoObjects.AddRange(probablyDeadGameObjects.Select(item => (Object)item));
            Undo.RecordObjects(undoObjects.ToArray(), "Remove all selected child colliders");

            foreach (var springBone in springBones)
            {
                springBone.sphereColliders  = springBone.sphereColliders.Where(collider => !deadColliders.Contains(collider)).ToArray();
                springBone.capsuleColliders = springBone.capsuleColliders.Where(collider => !deadColliders.Contains(collider)).ToArray();
                springBone.panelColliders   = springBone.panelColliders.Where(collider => !deadColliders.Contains(collider)).ToArray();
            }

            foreach (var deadCollider in deadColliders)
            {
                SpringBoneSetup.DestroyUnityObject(deadCollider);
            }

            foreach (var gameObject in probablyDeadGameObjects)
            {
                SpringBoneSetup.DestroyUnityObject(gameObject);
            }
        }
        private static bool BuildSpringBoneFromSerializer
        (
            SpringBoneSetupMaps setupMaps,
            SpringBoneSerializer serializer
        )
        {
            var       baseData  = serializer.baseData;
            Transform childBone = null;

            if (!setupMaps.allChildren.TryGetValue(baseData.boneName, out childBone))
            {
                Debug.LogError("ボーンが見つかりません: " + baseData.boneName);
                return(false);
            }

            var springBone = childBone.gameObject.AddComponent <SpringBone>();

            springBone.stiffnessForce          = baseData.stiffness;
            springBone.dragForce               = baseData.drag;
            springBone.springForce             = baseData.springForce;
            springBone.windInfluence           = baseData.windInfluence;
            springBone.angularStiffness        = baseData.angularStiffness;
            springBone.yAngleLimits            = BuildAngleLimitsFromSerializer(baseData.yAngleLimits);
            springBone.zAngleLimits            = BuildAngleLimitsFromSerializer(baseData.zAngleLimits);
            springBone.radius                  = baseData.radius;
            springBone.lodLevel                = baseData.lodLevel;
            springBone.lodMode                 = (SpringBone.LODMode)baseData.lodMode;
            springBone.lengthLimitStiffness    = baseData.lengthLimitStiffness;
            springBone.isLengthLimitPercentage = baseData.isLengthLimitPercentage;
            springBone.lengthLimitMode         = (SpringBone.LengthLimitMode)baseData.lengthLimitMode;

            // Pivot node
            var       pivotNodeName = baseData.pivotName;
            Transform pivotNode     = null;

            if (pivotNodeName.Length > 0)
            {
                if (!setupMaps.allChildren.TryGetValue(pivotNodeName, out pivotNode))
                {
                    Debug.LogError("Pivotオブジェクトが見つかりません: " + pivotNodeName);
                    pivotNode = null;
                }
            }
            if (pivotNode == null)
            {
                pivotNode = springBone.transform.parent ?? springBone.transform;
            }
            else
            {
                var skinBones = GameObjectUtil.GetAllBones(springBone.transform.root.gameObject);
                if (pivotNode.GetComponent <SpringBonePivot>() &&
                    SpringBoneSetup.IsPivotProbablySafeToDestroy(pivotNode, skinBones))
                {
                    pivotNode.position = springBone.transform.position;
                }
            }
            springBone.pivotNode = pivotNode;

            springBone.lengthLimitTargets = baseData.lengthLimits
                                            .Where(lengthLimit => setupMaps.allChildren.ContainsKey(lengthLimit.objectName))
                                            .Select(lengthLimit => setupMaps.allChildren[lengthLimit.objectName])
                                            .ToArray();

            springBone.sphereColliders = serializer.colliderNames
                                         .Where(name => setupMaps.sphereColliders.ContainsKey(name))
                                         .Select(name => setupMaps.sphereColliders[name])
                                         .ToArray();

            springBone.capsuleColliders = serializer.colliderNames
                                          .Where(name => setupMaps.capsuleColliders.ContainsKey(name))
                                          .Select(name => setupMaps.capsuleColliders[name])
                                          .ToArray();

            springBone.panelColliders = serializer.colliderNames
                                        .Where(name => setupMaps.panelColliders.ContainsKey(name))
                                        .Select(name => setupMaps.panelColliders[name])
                                        .ToArray();

            return(true);
        }
 private static void UpdateBoneList(SpringManager manager)
 {
     Undo.RecordObject(manager, "SpringBoneリストを更新");
     SpringBoneSetup.FindAndAssignSpringBones(manager, true);
 }
        private void PerformMirror()
        {
            var mirrorItems = boneEntries.Where(
                item => item.sourceBone != null &&
                item.targetBone != null &&
                item.sourceBone != item.targetBone);
            var undoItems = mirrorItems.Select(item => (Component)item.targetBone).ToList();

            var allSkinBones = GameObjectUtil.FindComponentsOfType <SkinnedMeshRenderer>()
                               .SelectMany(renderer => renderer.bones)
                               .Distinct()
                               .ToArray();

            var editablePivots = mirrorItems
                                 .Select(item => item.targetBone.pivotNode)
                                 .Where(pivotNode => pivotNode != null &&
                                        SpringBoneSetup.IsPivotProbablySafeToDestroy(pivotNode, allSkinBones))
                                 .ToArray();

            undoItems.AddRange(editablePivots);
            Undo.RecordObjects(undoItems.ToArray(), "Mirror SpringBones");

            foreach (var mirrorItem in mirrorItems)
            {
                var sourceBone  = mirrorItem.sourceBone;
                var targetBone  = mirrorItem.targetBone;
                var rootManager = targetBone.GetComponentInParent <SpringManager>();
                if (rootManager == null)
                {
                    continue;
                }

                targetBone.stiffnessForce = sourceBone.stiffnessForce;
                targetBone.dragForce      = sourceBone.dragForce;
                targetBone.springForce    = sourceBone.springForce;
                targetBone.windInfluence  = sourceBone.windInfluence;

                if (editablePivots.Contains(targetBone.pivotNode))
                {
                    MirrorPivot(sourceBone, targetBone);
                }

                targetBone.angularStiffness = sourceBone.angularStiffness;
                sourceBone.yAngleLimits.CopyTo(targetBone.yAngleLimits);
                sourceBone.zAngleLimits.CopyTo(targetBone.zAngleLimits);
                targetBone.yAngleLimits.min = -sourceBone.yAngleLimits.max;
                targetBone.yAngleLimits.max = -sourceBone.yAngleLimits.min;

                targetBone.lengthLimitTargets = FindMirroredComponents(
                    rootManager.gameObject, sourceBone.lengthLimitTargets, mirrorAxis)
                                                .Where(item => item != null)
                                                .ToArray();

                targetBone.radius          = sourceBone.radius;
                targetBone.sphereColliders = FindMirroredComponents(
                    rootManager.gameObject, sourceBone.sphereColliders, mirrorAxis)
                                             .Where(item => item != null)
                                             .ToArray();
                targetBone.capsuleColliders = FindMirroredComponents(
                    rootManager.gameObject, sourceBone.capsuleColliders, mirrorAxis)
                                              .Where(item => item != null)
                                              .ToArray();
                targetBone.panelColliders = FindMirroredComponents(
                    rootManager.gameObject, sourceBone.panelColliders, mirrorAxis)
                                            .Where(item => item != null)
                                            .ToArray();
            }
        }
示例#17
0
 private static void UpdateBoneList(SpringManager manager)
 {
     SpringBoneSetup.FindAndAssignSpringBones(manager, true);
 }
示例#18
0
 private void OnDestroy()
 {
     SpringBoneSetup.AutoSave(this);
 }