예제 #1
0
        public static bool AssociateAllBones(this SpriteCache sprite)
        {
            var skinningCache = sprite.skinningCache;

            if (skinningCache.mode == SkinningMode.SpriteSheet)
            {
                return(false);
            }

            var character = skinningCache.character;

            Debug.Assert(character != null);
            Debug.Assert(character.skeleton != null);

            var characterPart = sprite.GetCharacterPart();

            Debug.Assert(characterPart != null);

            var bones = character.skeleton.bones.Where(x => x.isVisible).ToArray();

            characterPart.bones = bones;

            characterPart.sprite.UpdateMesh(bones);

            return(true);
        }
예제 #2
0
        public static bool IsVisible(this SpriteCache sprite)
        {
            var isVisible     = true;
            var characterPart = sprite.GetCharacterPart();

            if (sprite.skinningCache.mode == SkinningMode.Character && characterPart != null)
            {
                isVisible = characterPart.isVisible;
            }

            return(isVisible);
        }
예제 #3
0
        public static void DeassociateUnusedBones(this SpriteCache sprite)
        {
            var skinningCache = sprite.skinningCache;

            Debug.Assert(skinningCache.mode == SkinningMode.Character);

            var characterPart = sprite.GetCharacterPart();

            Debug.Assert(characterPart != null);

            characterPart.DeassociateUnusedBones();
        }
예제 #4
0
        public static BoneCache[] GetBonesFromMode(this SpriteCache sprite)
        {
            var skinningCache = sprite.skinningCache;

            if (skinningCache.mode == SkinningMode.SpriteSheet)
            {
                return(sprite.GetSkeleton().bones);
            }

            var characterPart = sprite.GetCharacterPart();

            Debug.Assert(characterPart != null);
            return(characterPart.bones);
        }
예제 #5
0
        public static Matrix4x4 GetLocalToWorldMatrixFromMode(this SpriteCache sprite)
        {
            var skinningCache = sprite.skinningCache;

            if (skinningCache.mode == SkinningMode.SpriteSheet)
            {
                return(sprite.localToWorldMatrix);
            }

            var characterPart = sprite.GetCharacterPart();

            Debug.Assert(characterPart != null);

            return(characterPart.localToWorldMatrix);
        }
예제 #6
0
        public static void DeassociateAllBones(this SpriteCache sprite)
        {
            var skinningCache = sprite.skinningCache;

            if (skinningCache.mode == SkinningMode.SpriteSheet)
            {
                return;
            }

            var part = sprite.GetCharacterPart();

            if (part.bones.Length == 0)
            {
                return;
            }

            Debug.Assert(part.sprite != null);

            part.bones = new BoneCache[0];
            part.sprite.UpdateMesh(part.bones);

            skinningCache.events.characterPartChanged.Invoke(part);
        }
예제 #7
0
        private void GenerateWeights(SpriteCache sprite)
        {
            Debug.Assert(sprite != null);

            var mesh = sprite.GetMesh();

            Debug.Assert(mesh != null);

            using (new DefaultPoseScope(skinningCache.GetEffectiveSkeleton(sprite)))
            {
                if (NeedsAssociateBones(sprite.GetCharacterPart()))
                {
                    using (new AssociateBonesScope(sprite))
                    {
                        GenerateWeights(mesh);
                    }
                }
                else
                {
                    GenerateWeights(mesh);
                }
            }
        }
        public static bool AssociatePossibleBones(this SpriteCache sprite)
        {
            var skinningCache = sprite.skinningCache;

            if (skinningCache.mode == SkinningMode.SpriteSheet)
            {
                return(false);
            }

            var character = skinningCache.character;

            Debug.Assert(character != null);
            Debug.Assert(character.skeleton != null);

            var characterPart = sprite.GetCharacterPart();

            Debug.Assert(characterPart != null);

            var bones         = character.skeleton.bones.Where(x => x.isVisible).ToArray();
            var possibleBones = new List <BoneCache>();
            // check if any of the bones overlapped
            BoneCache shortestBoneDistance = null;
            var       minDistances         = float.MaxValue;
            var       characterSpriteRect  = new Rect(characterPart.position.x, characterPart.position.y, characterPart.sprite.textureRect.width, characterPart.sprite.textureRect.height);

            foreach (var bone in bones)
            {
                var startPoint = bone.position;
                var endPoint   = bone.endPosition;
                if (IntersectsSegment(characterSpriteRect, startPoint, endPoint))
                {
                    possibleBones.Add(bone);
                }
                if (possibleBones.Count == 0)
                {
                    // compare bone start end with rect's 4 line
                    // compare rect point with bone line
                    var points         = new Vector2[] { startPoint, endPoint };
                    var rectLinePoints = new []
                    {
                        new Vector2Int(0, 1),
                        new Vector2Int(0, 2),
                        new Vector2Int(1, 3),
                        new Vector2Int(2, 3),
                    };
                    var rectPoints = new []
                    {
                        new Vector2(characterSpriteRect.xMin, characterSpriteRect.yMin),
                        new Vector2(characterSpriteRect.xMin, characterSpriteRect.yMax),
                        new Vector2(characterSpriteRect.xMax, characterSpriteRect.yMin),
                        new Vector2(characterSpriteRect.xMax, characterSpriteRect.yMax)
                    };
                    foreach (var point in points)
                    {
                        foreach (var rectLine in rectLinePoints)
                        {
                            var distance = PointToLineSegmentDistance(point, rectPoints[rectLine.x], rectPoints[rectLine.y]);
                            if (distance < minDistances)
                            {
                                minDistances         = distance;
                                shortestBoneDistance = bone;
                            }
                        }
                    }

                    foreach (var rectPoint in rectPoints)
                    {
                        var distance = PointToLineSegmentDistance(rectPoint, startPoint, endPoint);
                        if (distance < minDistances)
                        {
                            minDistances         = distance;
                            shortestBoneDistance = bone;
                        }
                    }
                }
            }
            // if none overlapped, we use the bone that is closest to us
            if (possibleBones.Count == 0 && shortestBoneDistance != null)
            {
                possibleBones.Add(shortestBoneDistance);
            }
            characterPart.bones = possibleBones.ToArray();

            characterPart.sprite.UpdateMesh(possibleBones.ToArray());

            return(true);
        }
예제 #9
0
        public void PasteMesh(SpriteCache sprite, SkinningCopySpriteData skinningSpriteData, bool flipX, bool flipY, float scale, NewBonesStore newBonesStore)
        {
            if (sprite == null)
            {
                return;
            }

            meshTool.SetupSprite(sprite);
            meshTool.mesh.vertices = skinningSpriteData.vertices;
            if (!Mathf.Approximately(scale, 1f) || flipX || flipY)
            {
                var spriteRect = sprite.textureRect;
                foreach (var vertex in meshTool.mesh.vertices)
                {
                    var position = vertex.position;
                    if (!Mathf.Approximately(scale, 1f))
                    {
                        position = position * scale;
                    }
                    if (flipX)
                    {
                        position.x = spriteRect.width - vertex.position.x;
                    }
                    if (flipY)
                    {
                        position.y = spriteRect.height - vertex.position.y;
                    }
                    vertex.position = position;
                }
            }
            meshTool.mesh.indices = skinningSpriteData.indices;
            meshTool.mesh.edges   = skinningSpriteData.edges;

            int[]       copyBoneToNewBones = new int[skinningSpriteData.boneWeightNames.Count];
            BoneCache[] setBones           = null;

            if (newBonesStore != null && newBonesStore.newBones != null)
            {
                // Update bone weights with new bone indices
                var setBonesList = new List <BoneCache>();
                copyBoneToNewBones = new int[skinningSpriteData.boneWeightNames.Count];
                int index = 0;
                for (int i = 0; i < skinningSpriteData.boneWeightNames.Count; ++i)
                {
                    string oldBoneName = skinningSpriteData.boneWeightNames[i];
                    string newBoneName;
                    newBonesStore.newBoneNameDict.TryGetValue(oldBoneName, out newBoneName);
                    var newBone = newBonesStore.newBones.FirstOrDefault(bone => bone.name == newBoneName);
                    copyBoneToNewBones[i] = -1;
                    if (newBone == null)
                    {
                        continue;
                    }

                    for (int j = 0; j < skinningSpriteData.spriteBones.Count; ++j)
                    {
                        if (skinningSpriteData.spriteBones[j].name == oldBoneName)
                        {
                            copyBoneToNewBones[i] = index++;
                            setBonesList.Add(newBone);
                            break;
                        }
                    }
                }
                setBones = setBonesList.ToArray();
            }
            else
            {
                // Attempt to link weights based on existing bone names
                var skeleton       = skinningCache.GetEffectiveSkeleton(sprite);
                var characterBones = new List <BoneCache>();
                for (int i = 0; i < skinningSpriteData.boneWeightNames.Count; ++i)
                {
                    copyBoneToNewBones[i] = -1;
                    var boneName = skinningSpriteData.boneWeightNames[i];
                    for (int j = 0; j < skeleton.bones.Length; ++j)
                    {
                        if (skeleton.bones[j].name == boneName)
                        {
                            copyBoneToNewBones[i] = characterBones.Count;
                            characterBones.Add(skeleton.bones[j]);
                            break;
                        }
                    }
                }
                setBones = characterBones.ToArray();
            }

            // Remap new bone indexes from copied bone indexes
            foreach (var vertex in meshTool.mesh.vertices)
            {
                var editableBoneWeight = vertex.editableBoneWeight;

                for (var i = 0; i < editableBoneWeight.Count; ++i)
                {
                    if (!editableBoneWeight[i].enabled)
                    {
                        continue;
                    }

                    var boneIndex = copyBoneToNewBones[editableBoneWeight[i].boneIndex];
                    if (boneIndex != -1)
                    {
                        editableBoneWeight[i].boneIndex = boneIndex;
                    }
                }
            }

            // Update associated bones for mesh
            meshTool.mesh.SetCompatibleBoneSet(setBones);
            meshTool.mesh.bones = setBones; // Fixes weights for bones that do not exist

            // Update associated bones for character
            if (skinningCache.hasCharacter)
            {
                var characterPart = sprite.GetCharacterPart();
                if (characterPart != null)
                {
                    characterPart.bones = setBones;
                    skinningCache.events.characterPartChanged.Invoke(characterPart);
                }
            }

            meshTool.UpdateMesh();
        }
예제 #10
0
        public NewBonesStore PasteSkeletonBones(SpriteCache sprite, List <SpriteBone> spriteBones, bool flipX, bool flipY, float scale = 1.0f)
        {
            NewBonesStore newBonesStore = new NewBonesStore();

            newBonesStore.newBones = skinningCache.CreateBoneCacheFromSpriteBones(spriteBones.ToArray(), scale);
            if (newBonesStore.newBones.Length == 0)
            {
                return(null);
            }

            if (sprite == null || (skinningCache.mode == SkinningMode.SpriteSheet && skinningCache.hasCharacter))
            {
                return(null);
            }

            var spriteRect = sprite.textureRect;
            var skeleton   = skinningCache.GetEffectiveSkeleton(sprite);

            var rectPosition = spriteRect.position;

            if (skinningCache.mode == SkinningMode.Character)
            {
                var characterPart = sprite.GetCharacterPart();
                if (characterPart == null)
                {
                    return(null);
                }
                rectPosition = characterPart.position;
            }

            var newPositions = new Vector3[newBonesStore.newBones.Length];
            var newRotations = new Quaternion[newBonesStore.newBones.Length];

            for (var i = 0; i < newBonesStore.newBones.Length; ++i)
            {
                newPositions[i] = GetFlippedBonePosition(newBonesStore.newBones[i], rectPosition, spriteRect, flipX, flipY);
                newRotations[i] = GetFlippedBoneRotation(newBonesStore.newBones[i], flipX, flipY);
            }
            for (var i = 0; i < newBonesStore.newBones.Length; ++i)
            {
                newBonesStore.newBones[i].position = newPositions[i];
                newBonesStore.newBones[i].rotation = newRotations[i];
            }

            if (skinningCache.mode == SkinningMode.SpriteSheet)
            {
                newBonesStore.MapAllExistingBones();
                skeleton.SetBones(newBonesStore.newBones);
            }
            else
            {
                var existingBoneNames = skeleton.bones.Select(x => x.name).ToList();

                skeleton.AddBones(newBonesStore.newBones);

                var bones = skeleton.bones;

                // Update names of all newly pasted bones
                foreach (var bone in newBonesStore.newBones)
                {
                    if (existingBoneNames.Contains(bone.name))
                    {
                        var oldBoneName = bone.name;
                        bone.name = SkeletonController.AutoBoneName(bone.parentBone, bones);
                        existingBoneNames.Add(bone.name);
                        newBonesStore.newBoneNameDict.Add(oldBoneName, bone.name);
                    }
                    else
                    {
                        newBonesStore.newBoneNameDict.Add(bone.name, bone.name);
                    }
                }

                skeleton.SetDefaultPose();
            }

            skinningCache.events.skeletonTopologyChanged.Invoke(skeleton);
            return(newBonesStore);
        }
예제 #11
0
        public SkinningCopyData CopySingle(SpriteCache sprite)
        {
            var skinningCopyData = new SkinningCopyData();

            skinningCopyData.pixelsPerUnit = pixelsPerUnit;

            // Mesh
            var skinningSpriteData = new SkinningCopySpriteData();

            skinningCopyData.copyData.Add(skinningSpriteData);

            CopyMeshFromSpriteCache(sprite, skinningSpriteData);

            // Bones
            var rootBones = new List <BoneCache>();

            if (skinningCache.hasCharacter)
            {
                var characterPart = skinningCache.GetCharacterPart(sprite);
                if (characterPart != null && characterPart.bones != null)
                {
                    var bones = characterPart.bones.FindRoots();
                    foreach (var bone in bones)
                    {
                        rootBones.Add(bone);
                    }
                }
            }
            else
            {
                var skeleton = skinningCache.GetEffectiveSkeleton(sprite);
                if (skeleton != null && skeleton.BoneCount > 0)
                {
                    var bones = skeleton.bones.FindRoots();
                    foreach (var bone in bones)
                    {
                        rootBones.Add(bone);
                    }
                }
            }

            if (rootBones.Count > 0)
            {
                skinningSpriteData.spriteBones = new List <SpriteBone>();
                foreach (var rootBone in rootBones)
                {
                    var rootBoneIndex = skinningSpriteData.spriteBones.Count;
                    GetSpriteBoneDataRecursively(skinningSpriteData.spriteBones, rootBone);
                    if (skinningCache.hasCharacter)
                    {
                        // Offset the bones based on the currently selected Sprite in Character mode
                        var characterPart = sprite.GetCharacterPart();
                        if (characterPart != null)
                        {
                            var offset         = characterPart.position;
                            var rootSpriteBone = skinningSpriteData.spriteBones[rootBoneIndex];
                            rootSpriteBone.position = rootSpriteBone.position - offset;
                            skinningSpriteData.spriteBones[rootBoneIndex] = rootSpriteBone;
                        }
                    }
                }
            }

            return(skinningCopyData);
        }
예제 #12
0
        public void PasteMesh(SpriteCache sprite, SkinningCopySpriteData skinningSpriteData, bool flipX, bool flipY, float scale, BoneCache[] newBones)
        {
            if (sprite == null)
            {
                return;
            }

            meshTool.SetupSprite(sprite);
            meshTool.mesh.vertices = skinningSpriteData.vertices;
            if (!Mathf.Approximately(scale, 1f) || flipX || flipY)
            {
                var spriteRect = sprite.textureRect;
                foreach (var vertex in meshTool.mesh.vertices)
                {
                    var position = vertex.position;
                    if (!Mathf.Approximately(scale, 1f))
                    {
                        position = position * scale;
                    }
                    if (flipX)
                    {
                        position.x = spriteRect.width - vertex.position.x;
                    }
                    if (flipY)
                    {
                        position.y = spriteRect.height - vertex.position.y;
                    }
                    vertex.position = position;
                }
            }
            meshTool.mesh.indices = skinningSpriteData.indices;
            meshTool.mesh.edges   = skinningSpriteData.edges;

            if (newBones != null)
            {
                // Update bone weights with new bone indices
                int[] copyBoneToNewBones = new int[skinningSpriteData.boneWeightNames.Count];
                for (int i = 0; i < skinningSpriteData.boneWeightNames.Count; ++i)
                {
                    copyBoneToNewBones[i] = -1;
                    var boneName = skinningSpriteData.boneWeightNames[i];
                    for (int j = 0; j < skinningSpriteData.spriteBones.Count; ++j)
                    {
                        if (skinningSpriteData.spriteBones[j].name == boneName)
                        {
                            copyBoneToNewBones[i] = j;
                            break;
                        }
                    }
                }

                // Remap new bone indexes from copied bone indexes
                foreach (var vertex in meshTool.mesh.vertices)
                {
                    var editableBoneWeight = vertex.editableBoneWeight;

                    for (var i = 0; i < editableBoneWeight.Count; ++i)
                    {
                        if (!editableBoneWeight[i].enabled)
                        {
                            continue;
                        }

                        var boneIndex = copyBoneToNewBones[editableBoneWeight[i].boneIndex];

                        if (boneIndex != -1)
                        {
                            editableBoneWeight[i].boneIndex = boneIndex;
                        }
                    }
                }

                // Update associated bones for mesh
                meshTool.mesh.SetCompatibleBoneSet(newBones);
                meshTool.mesh.bones = newBones; // Fixes weights for bones that do not exist

                // Update associated bones for character
                if (skinningCache.hasCharacter)
                {
                    var characterPart = sprite.GetCharacterPart();
                    if (characterPart != null)
                    {
                        characterPart.bones = newBones;
                        skinningCache.events.characterPartChanged.Invoke(characterPart);
                    }
                }
            }
            meshTool.UpdateMesh();
        }
 public CharacterPartCache GetSpriteCharacterPart(SpriteCache sprite)
 {
     return(sprite.GetCharacterPart());
 }