public static void PromptToUpdateSpringBonesFromList()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("再生中に更新できません");
                return;
            }

            var selectedSpringManagers = Selection.gameObjects
                                         .Select(gameObject => gameObject.GetComponent <SpringManager>())
                                         .Where(manager => manager != null)
                                         .ToArray();

            if (!selectedSpringManagers.Any())
            {
                selectedSpringManagers = GameObjectUtil.FindComponentsOfType <SpringManager>().ToArray();
            }

            if (selectedSpringManagers.Count() != 1)
            {
                Debug.LogError("一つだけのSpringManagerを選択してください");
                return;
            }

            var springManager = selectedSpringManagers.First();
            var queryMessage  = "ボーンリストから揺れものボーンを更新しますか?\n\n"
                                + "リストにないSpringBone情報は削除され、\n"
                                + "モデルにないSpringBone情報は追加されます。\n\n"
                                + "SpringManager: " + springManager.name;

            if (EditorUtility.DisplayDialog("ボーンリストから更新", queryMessage, "更新", "キャンセル"))
            {
                AutoSpringBoneSetup.UpdateSpringManagerFromBoneList(springManager);
            }
        }
示例#2
0
        public static void PromptToUpdateSpringBonesFromList()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("Play过程中无法更新");
                return;
            }

            var selectedSpringManagers = Selection.gameObjects
                                         .Select(gameObject => gameObject.GetComponent <SpringManager>())
                                         .Where(manager => manager != null)
                                         .ToArray();

            if (!selectedSpringManagers.Any())
            {
                selectedSpringManagers = GameObjectUtil.FindComponentsOfType <SpringManager>().ToArray();
            }

            if (selectedSpringManagers.Count() != 1)
            {
                Debug.LogError("只可以选择一个SpringManager");
                return;
            }

            var springManager = selectedSpringManagers.First();
            var queryMessage  = "要根据所选Manager的列表更新SpringBone?\n\n"
                                + "不在列表中的SpringBone信息会被删除、\n"
                                + "列表中存在,但是模型上没有的SpringBone将被添加。\n\n"
                                + "SpringManager: " + springManager.name;

            if (EditorUtility.DisplayDialog("从所选Manager的列表更新", queryMessage, "更新", "取消"))
            {
                AutoSpringBoneSetup.UpdateSpringManagerFromBoneList(springManager);
            }
        }
示例#3
0
        private static SpringManagerBoneGroup[] FindSpringBonesUsingCollider <T>
        (
            Object[] components,
            System.Func <SpringBone, IEnumerable <T>, bool> containmentCheck
        ) where T : class
        {
            var colliders = components
                            .Select(component => component as T)
                            .Where(component => component != null)
                            .ToArray();

            var allSpringBones      = GameObjectUtil.FindComponentsOfType <SpringBone>();
            var matchingSpringBones = allSpringBones
                                      .Where(springBone => containmentCheck(springBone, colliders))
                                      .Distinct()
                                      .ToArray();

            System.Array.Sort(matchingSpringBones, (a, b) => string.Compare(a.name, b.name));

            // Now arrange by manager
            var allManagers = GameObjectUtil.FindComponentsOfType <SpringManager>().ToArray();

            System.Array.Sort(allManagers, (a, b) => string.Compare(a.name, b.name));
            var boneGroups = new List <SpringManagerBoneGroup>();

            foreach (var manager in allManagers)
            {
                var bonesForManager = matchingSpringBones
                                      .Where(bone => manager.springBones.Contains(bone))
                                      .ToArray();
                if (bonesForManager.Any())
                {
                    boneGroups.Add(new SpringManagerBoneGroup
                    {
                        manager        = manager,
                        bones          = bonesForManager,
                        boneCountLabel = string.Format("Bones: {0}", bonesForManager.Length)
                    });
                }
            }

            // Now find the bones with no manager
            var bonesWithNoManager = matchingSpringBones
                                     .Where(bone => !allManagers.Any(manager => manager.springBones.Contains(bone)))
                                     .ToArray();

            if (bonesWithNoManager.Any())
            {
                boneGroups.Add(new SpringManagerBoneGroup
                {
                    manager        = null,
                    bones          = bonesWithNoManager,
                    boneCountLabel = string.Format("Bones: {0}", bonesWithNoManager.Length)
                });
            }

            return(boneGroups.ToArray());
        }
示例#4
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));
            }
        }
        public static void DeleteSelectedBones()
        {
            var springBonesToDelete = GameObjectUtil.FindComponentsOfType <SpringBone>()
                                      .Where(bone => Selection.gameObjects.Contains(bone.gameObject))
                                      .ToArray();
            var springManagersToUpdate = GameObjectUtil.FindComponentsOfType <SpringManager>()
                                         .Where(manager => manager.springBones.Any(bone => springBonesToDelete.Contains(bone)))
                                         .ToArray();

            Undo.RecordObjects(springManagersToUpdate, "Delete selected bones");
            foreach (var boneToDelete in springBonesToDelete)
            {
                Undo.DestroyObjectImmediate(boneToDelete);
            }
            foreach (var manager in springManagersToUpdate)
            {
                manager.FindSpringBones(true);
            }
        }
        private static void RemoveDuplicateComponents <T>() where T : Component
        {
            // Delete all components of the same type after the first
            var duplicateObjects = 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]);
                    }
                }
            }
        }
        private void AcquireSourceBonesOnSideOfAxis(bool getLessThanZero)
        {
            if (boneEntries == null)
            {
                boneEntries = new List <BoneEntry>();
            }

            // Is there a better way of defining this?
            System.Func <SpringBone, bool> boneMatches = item => false;
            if (getLessThanZero)
            {
                switch (mirrorAxis)
                {
                case Axis.X: boneMatches = item => item.transform.position.x < 0f; break;

                case Axis.Y: boneMatches = item => item.transform.position.y < 0f; break;

                case Axis.Z: boneMatches = item => item.transform.position.z < 0f; break;
                }
            }
            else
            {
                switch (mirrorAxis)
                {
                case Axis.X: boneMatches = item => item.transform.position.x > 0f; break;

                case Axis.Y: boneMatches = item => item.transform.position.y > 0f; break;

                case Axis.Z: boneMatches = item => item.transform.position.z > 0f; break;
                }
            }

            var allSpringBones = GameObjectUtil.FindComponentsOfType <SpringBone>();
            var selectedBones  = allSpringBones.Where(boneMatches);
            var newBoneEntries = selectedBones
                                 .Select(bone => new BoneEntry(bone, FindMirroredSpringBone(bone, mirrorAxis)))
                                 .Where(entry => entry.targetBone != null &&
                                        entry.targetBone != entry.sourceBone);

            boneEntries = newBoneEntries.ToList();
        }
        private void InitializeData()
        {
            if (managers != null && managers.Length > 0)
            {
                return;
            }

            managers = targets
                       .Select(target => target as Component)
                       .Where(target => target != null)
                       .Select(target => target.GetComponentInParent <SpringManager>())
                       .Where(manager => manager != null)
                       .Distinct()
                       .ToArray();

            var pivots = targets
                         .Where(target => target is Component)
                         .Select(target => ((Component)target).transform)
                         .ToArray();

            bones = GameObjectUtil.FindComponentsOfType <SpringBone>()
                    .Where(bone => pivots.Contains(bone.pivotNode))
                    .ToArray();
        }
        public static void CleanUpDynamics()
        {
            if (Application.isPlaying)
            {
                Debug.LogError("再生モードを止めてください。");
                return;
            }

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

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

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

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

                springManagers = GameObjectUtil.FindComponentsOfType <SpringManager>();
                foreach (var springManager in springManagers)
                {
                    var springBones = springManager.GetComponentsInChildren <SpringBone>(true);
                    var allBones    = 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();
                    }
                }
            }
        }
        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 => 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 = 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 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();
            }
        }
示例#12
0
 private void Start()
 {
     // Must get the ForceProviders in Start and not Awake or Unity will complain that
     // "the scene is not loaded"
     forceProviders = GameObjectUtil.FindComponentsOfType <ForceProvider>().ToArray();
 }