Bez popisu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AnimationClipGeneration.cs 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. namespace UnityEditor.U2D.Aseprite
  5. {
  6. internal static class AnimationClipGeneration
  7. {
  8. const string k_RootName = "Root";
  9. public static AnimationClip[] Generate(string assetName,
  10. Sprite[] sprites,
  11. AsepriteFile file,
  12. List<Layer> layers,
  13. List<Frame> frames,
  14. List<Tag> tags,
  15. Dictionary<int, GameObject> layerIdToGameObject)
  16. {
  17. var noOfFrames = file.noOfFrames;
  18. if (tags.Count == 0)
  19. {
  20. var tag = new Tag();
  21. tag.name = assetName + "_Clip";
  22. tag.fromFrame = 0;
  23. tag.toFrame = noOfFrames;
  24. tags.Add(tag);
  25. }
  26. var clips = new AnimationClip[tags.Count];
  27. for (var i = 0; i < tags.Count; ++i)
  28. clips[i] = CreateClip(tags[i], layers, frames, sprites, layerIdToGameObject);
  29. return clips;
  30. }
  31. static AnimationClip CreateClip(Tag tag, List<Layer> layers, List<Frame> frames, Sprite[] sprites, Dictionary<int, GameObject> layerIdToGameObject)
  32. {
  33. var animationClip = new AnimationClip()
  34. {
  35. name = tag.name,
  36. frameRate = 100f
  37. };
  38. var clipSettings = new AnimationClipSettings();
  39. clipSettings.loopTime = tag.isRepeating;
  40. AnimationUtility.SetAnimationClipSettings(animationClip, clipSettings);
  41. for (var i = 0; i < layers.Count; ++i)
  42. {
  43. var layer = layers[i];
  44. if (layer.layerType != LayerTypes.Normal)
  45. continue;
  46. var layerGo = layerIdToGameObject[layer.index];
  47. if (layerGo.GetComponent<SpriteRenderer>() == null)
  48. continue;
  49. var spriteKeyframes = new List<ObjectReferenceKeyframe>();
  50. var cells = layer.cells;
  51. var activeFrames = AddCellsToClip(in cells, in tag, in sprites, in frames, ref spriteKeyframes);
  52. var linkedCells = layer.linkedCells;
  53. activeFrames.UnionWith(AddLinkedCellsToClip(in linkedCells, in cells, in tag, in sprites, in frames, ref spriteKeyframes));
  54. spriteKeyframes.Sort((x, y) => x.time.CompareTo(y.time));
  55. DuplicateLastFrame(ref spriteKeyframes, frames[tag.toFrame - 1]);
  56. var path = GetGameObjectPath(layerGo.transform);
  57. var spriteBinding = EditorCurveBinding.PPtrCurve(path, typeof(SpriteRenderer), "m_Sprite");
  58. AnimationUtility.SetObjectReferenceCurve(animationClip, spriteBinding, spriteKeyframes.ToArray());
  59. AddEnabledKeyframes(layerGo, tag, in frames, in activeFrames, in animationClip);
  60. AddAnimationEvents(in tag, in frames, animationClip);
  61. }
  62. return animationClip;
  63. }
  64. static HashSet<int> AddCellsToClip(in List<Cell> cells, in Tag tag, in Sprite[] sprites, in List<Frame> frames, ref List<ObjectReferenceKeyframe> keyFrames)
  65. {
  66. var activeFrames = new HashSet<int>();
  67. var startTime = GetTimeFromFrame(in frames, tag.fromFrame);
  68. for (var i = 0; i < cells.Count; ++i)
  69. {
  70. var cell = cells[i];
  71. if (cell.frameIndex < tag.fromFrame ||
  72. cell.frameIndex >= tag.toFrame)
  73. continue;
  74. var sprite = Array.Find(sprites, x => x.GetSpriteID() == cell.spriteId);
  75. if (sprite == null)
  76. continue;
  77. var keyframe = new ObjectReferenceKeyframe();
  78. var time = GetTimeFromFrame(in frames, cell.frameIndex);
  79. keyframe.time = time - startTime;
  80. keyframe.value = sprite;
  81. keyFrames.Add(keyframe);
  82. activeFrames.Add(cell.frameIndex);
  83. }
  84. return activeFrames;
  85. }
  86. static HashSet<int> AddLinkedCellsToClip(in List<LinkedCell> linkedCells, in List<Cell> cells, in Tag tag, in Sprite[] sprites, in List<Frame> frames, ref List<ObjectReferenceKeyframe> keyFrames)
  87. {
  88. var activeFrames = new HashSet<int>();
  89. var startTime = GetTimeFromFrame(in frames, tag.fromFrame);
  90. for (var i = 0; i < linkedCells.Count; ++i)
  91. {
  92. var linkedCell = linkedCells[i];
  93. if (linkedCell.frameIndex < tag.fromFrame ||
  94. linkedCell.frameIndex >= tag.toFrame)
  95. continue;
  96. var cellIndex = cells.FindIndex(x => x.frameIndex == linkedCell.linkedToFrame);
  97. if (cellIndex == -1)
  98. continue;
  99. var cell = cells[cellIndex];
  100. var sprite = Array.Find(sprites, x => x.GetSpriteID() == cell.spriteId);
  101. if (sprite == null)
  102. continue;
  103. var keyframe = new ObjectReferenceKeyframe();
  104. var time = GetTimeFromFrame(in frames, linkedCell.frameIndex);
  105. keyframe.time = time - startTime;
  106. keyframe.value = sprite;
  107. keyFrames.Add(keyframe);
  108. activeFrames.Add(linkedCell.frameIndex);
  109. }
  110. return activeFrames;
  111. }
  112. static void DuplicateLastFrame(ref List<ObjectReferenceKeyframe> keyFrames, Frame lastFrame)
  113. {
  114. if (keyFrames.Count == 0)
  115. return;
  116. var lastKeyFrame = keyFrames[^1];
  117. var duplicatedFrame = new ObjectReferenceKeyframe();
  118. duplicatedFrame.time = lastKeyFrame.time + MsToSeconds(lastFrame.duration);
  119. duplicatedFrame.value = lastKeyFrame.value;
  120. keyFrames.Add(duplicatedFrame);
  121. }
  122. static string GetGameObjectPath(Transform transform)
  123. {
  124. var path = transform.name;
  125. if (transform.name == k_RootName)
  126. return "";
  127. if (transform.parent.name == k_RootName)
  128. return path;
  129. var parentPath = GetGameObjectPath(transform.parent) + "/";
  130. path = path.Insert(0, parentPath);
  131. return path;
  132. }
  133. static void AddEnabledKeyframes(GameObject layerGo, Tag tag, in List<Frame> frames, in HashSet<int> activeFrames, in AnimationClip animationClip)
  134. {
  135. if (activeFrames.Count == tag.noOfFrames)
  136. return;
  137. var path = GetGameObjectPath(layerGo.transform);
  138. var enabledBinding = EditorCurveBinding.FloatCurve(path, typeof(SpriteRenderer), "m_Enabled");
  139. var enabledKeyframes = new List<Keyframe>();
  140. var disabledPrevFrame = false;
  141. var startTime = GetTimeFromFrame(in frames, tag.fromFrame);
  142. for (var frameIndex = tag.fromFrame; frameIndex < tag.toFrame; ++frameIndex)
  143. {
  144. var time = GetTimeFromFrame(in frames, frameIndex);
  145. time -= startTime;
  146. if (!activeFrames.Contains(frameIndex) && !disabledPrevFrame)
  147. {
  148. var keyframe = GetBoolKeyFrame(false, time);
  149. enabledKeyframes.Add(keyframe);
  150. disabledPrevFrame = true;
  151. }
  152. else if (activeFrames.Contains(frameIndex) && disabledPrevFrame)
  153. {
  154. var keyframe = GetBoolKeyFrame(true, time);
  155. enabledKeyframes.Add(keyframe);
  156. disabledPrevFrame = false;
  157. }
  158. }
  159. if (enabledKeyframes.Count == 0)
  160. return;
  161. // Make sure there is an enable keyframe on the first frame, if the first frame is active.
  162. if (activeFrames.Contains(tag.fromFrame))
  163. {
  164. var keyframe = GetBoolKeyFrame(true, 0f);
  165. enabledKeyframes.Add(keyframe);
  166. }
  167. var animCurve = new AnimationCurve(enabledKeyframes.ToArray());
  168. AnimationUtility.SetEditorCurve(animationClip, enabledBinding, animCurve);
  169. }
  170. static float GetTimeFromFrame(in List<Frame> frames, int frameIndex)
  171. {
  172. var totalMs = 0;
  173. for (var i = 0; i < frameIndex; ++i)
  174. totalMs += frames[i].duration;
  175. return MsToSeconds(totalMs);
  176. }
  177. static float MsToSeconds(int ms) => ms / 1000f;
  178. static Keyframe GetBoolKeyFrame(bool value, float time)
  179. {
  180. var keyframe = new Keyframe();
  181. keyframe.value = value ? 1f : 0f;
  182. keyframe.time = time;
  183. keyframe.inTangent = float.PositiveInfinity;
  184. keyframe.outTangent = float.PositiveInfinity;
  185. return keyframe;
  186. }
  187. static void AddAnimationEvents(in Tag tag, in List<Frame> frames, AnimationClip animationClip)
  188. {
  189. var events = new List<AnimationEvent>();
  190. var startTime = GetTimeFromFrame(in frames, tag.fromFrame);
  191. for (var frameIndex = tag.fromFrame; frameIndex < tag.toFrame; ++frameIndex)
  192. {
  193. var frame = frames[frameIndex];
  194. if (frame.eventStrings.Length == 0)
  195. continue;
  196. var frameTime = GetTimeFromFrame(frames, frameIndex);
  197. var eventStrings = frame.eventStrings;
  198. for (var m = 0; m < eventStrings.Length; ++m)
  199. {
  200. events.Add(new AnimationEvent()
  201. {
  202. time = frameTime - startTime,
  203. functionName = eventStrings[m]
  204. });
  205. }
  206. }
  207. if (events.Count > 0)
  208. AnimationUtility.SetAnimationEvents(animationClip, events.ToArray());
  209. }
  210. }
  211. }