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); }
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); }
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(); }
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); }
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); }
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); }
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); }
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(); }
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); }
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); }
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()); }