설명 없음
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.

ModelPreviewer.cs 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. namespace UnityEditor.U2D.Aseprite.Common
  4. {
  5. internal class ModelPreviewer : System.IDisposable
  6. {
  7. const float k_TimeControlRectHeight = 20;
  8. readonly PreviewRenderUtility m_RenderUtility;
  9. bool m_Disposed = false;
  10. Rect m_PreviewRect;
  11. Bounds m_RenderableBounds;
  12. Vector2Int m_ActorSize;
  13. TimeControl m_TimeControl;
  14. int m_Fps;
  15. Animator m_Animator;
  16. AnimationClip[] m_Clips;
  17. AnimationClip m_SelectedClip;
  18. List<float> m_FrameTimings;
  19. int m_ClipIndex = 0;
  20. SpriteRenderer[] m_Renderers;
  21. Texture m_Texture;
  22. GameObject m_PreviewObject;
  23. GUIContent[] m_ClipNames;
  24. int[] m_ClipIndices;
  25. public ModelPreviewer(GameObject assetPrefab, AnimationClip[] clips)
  26. {
  27. m_RenderUtility = new PreviewRenderUtility();
  28. m_RenderUtility.camera.fieldOfView = 30f;
  29. m_PreviewObject = m_RenderUtility.InstantiatePrefabInScene(assetPrefab);
  30. m_RenderUtility.AddManagedGameObject(m_PreviewObject);
  31. m_Renderers = m_PreviewObject.GetComponentsInChildren<SpriteRenderer>();
  32. m_RenderableBounds = GetRenderableBounds(m_Renderers);
  33. if (clips != null && clips.Length > 0)
  34. {
  35. SetupAnimation(clips);
  36. SelectClipFromIndex(m_ClipIndex);
  37. }
  38. }
  39. void SetupAnimation(AnimationClip[] clips)
  40. {
  41. m_TimeControl = new TimeControl();
  42. m_Animator = m_PreviewObject.GetComponent<Animator>();
  43. m_Clips = clips;
  44. var clipInfos = m_Animator.GetCurrentAnimatorClipInfo(0);
  45. var defaultClipName = string.Empty;
  46. if (clipInfos.Length > 0)
  47. defaultClipName = clipInfos[0].clip.name;
  48. m_ClipNames = new GUIContent[m_Clips.Length];
  49. m_ClipIndices = new int[m_Clips.Length];
  50. for (var i = 0; i < m_ClipNames.Length; ++i)
  51. {
  52. m_ClipNames[i] = new GUIContent(m_Clips[i].name);
  53. m_ClipIndices[i] = i;
  54. // Set starting clip to default clip.
  55. if (m_Clips[i].name == defaultClipName)
  56. m_ClipIndex = i;
  57. }
  58. }
  59. void SelectClipFromIndex(int index)
  60. {
  61. m_SelectedClip = m_Clips[index];
  62. m_Fps = Mathf.RoundToInt(m_SelectedClip.frameRate);
  63. m_TimeControl.playbackSpeed = 1f / m_SelectedClip.length;
  64. m_TimeControl.currentTime = 0f;
  65. var timeSet = new HashSet<float>();
  66. var curveBindings = AnimationUtility.GetObjectReferenceCurveBindings(m_SelectedClip);
  67. for (var i = 0; i < curveBindings.Length; ++i)
  68. {
  69. var keyFrames = AnimationUtility.GetObjectReferenceCurve(m_SelectedClip, curveBindings[i]);
  70. for (var m = 0; m < keyFrames.Length; ++m)
  71. timeSet.Add(keyFrames[m].time);
  72. }
  73. m_FrameTimings = new List<float>(timeSet.Count);
  74. foreach (var time in timeSet)
  75. m_FrameTimings.Add(time);
  76. m_FrameTimings.Sort();
  77. // Remove the final frame time, as we add it on generation
  78. m_FrameTimings.RemoveAt(m_FrameTimings.Count - 1);
  79. }
  80. public void DrawPreview(Rect r, GUIStyle background)
  81. {
  82. if (!ShaderUtil.hardwareSupportsRectRenderTexture)
  83. return;
  84. var isRepainting = (Event.current.type == EventType.Repaint);
  85. if (isRepainting)
  86. {
  87. if (m_Texture != null)
  88. Object.DestroyImmediate(m_Texture);
  89. m_Texture = null;
  90. m_PreviewRect = r;
  91. m_PreviewObject.transform.position = Vector3.zero;
  92. m_RenderUtility.BeginPreview(r, background);
  93. DoRenderPreview();
  94. m_Texture = m_RenderUtility.EndPreview();
  95. m_TimeControl?.Update();
  96. }
  97. if (m_SelectedClip != null)
  98. UpdateAnimation(isRepainting);
  99. UpdateActorSize();
  100. GUI.DrawTexture(r, m_Texture, ScaleMode.StretchToFill, false);
  101. if (m_SelectedClip != null)
  102. DrawTimeControlGUI(m_PreviewRect);
  103. else
  104. DrawInfoText(m_PreviewRect);
  105. }
  106. void UpdateAnimation(bool isRepainting)
  107. {
  108. if (!isRepainting || m_PreviewObject == null)
  109. return;
  110. m_TimeControl.loop = true;
  111. m_Animator.Play(m_SelectedClip.name, 0, m_TimeControl.normalizedTime);
  112. m_Animator.Update(m_TimeControl.deltaTime);
  113. }
  114. void UpdateActorSize()
  115. {
  116. var ppu = m_Renderers[0].sprite.pixelsPerUnit;
  117. var bounds = GetRenderableBounds(m_Renderers);
  118. m_ActorSize = new Vector2Int()
  119. {
  120. x = Mathf.RoundToInt(bounds.size.x * ppu),
  121. y = Mathf.RoundToInt(bounds.size.y * ppu)
  122. };
  123. }
  124. void DrawTimeControlGUI(Rect rect)
  125. {
  126. const float kSliderWidth = 150f;
  127. const float kSpacing = 4f;
  128. var timeControlRect = rect;
  129. // background
  130. GUI.Box(rect, GUIContent.none, EditorStyles.toolbar);
  131. timeControlRect.height = k_TimeControlRectHeight;
  132. timeControlRect.xMax -= kSliderWidth;
  133. var sliderControlRect = rect;
  134. sliderControlRect.height = k_TimeControlRectHeight;
  135. sliderControlRect.yMin += 1;
  136. sliderControlRect.yMax -= 1;
  137. sliderControlRect.xMin = sliderControlRect.xMax - kSliderWidth + kSpacing;
  138. m_TimeControl.DoTimeControl(timeControlRect);
  139. EditorGUI.BeginChangeCheck();
  140. m_ClipIndex = EditorGUI.IntPopup(sliderControlRect, m_ClipIndex, m_ClipNames, m_ClipIndices);
  141. if (EditorGUI.EndChangeCheck())
  142. {
  143. SelectClipFromIndex(m_ClipIndex);
  144. }
  145. DrawInfoText(rect);
  146. }
  147. void DrawInfoText(Rect rect)
  148. {
  149. rect.y = rect.yMax - 24;
  150. rect.height = 20;
  151. var text = "";
  152. if (m_TimeControl != null)
  153. {
  154. var currentTime = m_TimeControl.normalizedTime * m_SelectedClip.length;
  155. var currentFrame = GetFrameFromTime(currentTime);
  156. text += $"Frame {currentFrame} | ";
  157. }
  158. text += $"{m_ActorSize.x}x{m_ActorSize.y}";
  159. EditorGUI.DropShadowLabel(rect, text);
  160. }
  161. int GetFrameFromTime(float currentTime)
  162. {
  163. var frame = 0;
  164. for (var i = 0; i < m_FrameTimings.Count; ++i)
  165. {
  166. if (currentTime < m_FrameTimings[i])
  167. break;
  168. frame++;
  169. }
  170. // Remove one to get the frame number start from 0
  171. return frame - 1;
  172. }
  173. void DoRenderPreview()
  174. {
  175. var num1 = Mathf.Max(m_RenderableBounds.extents.magnitude, 0.0001f);
  176. var num2 = num1 * 3.8f;
  177. var vector3 = m_RenderableBounds.center - Quaternion.identity * (Vector3.forward * num2);
  178. m_RenderUtility.camera.transform.position = vector3;
  179. m_RenderUtility.camera.nearClipPlane = num2 - num1 * 1.1f;
  180. m_RenderUtility.camera.farClipPlane = num2 + num1 * 5.1f;
  181. m_RenderUtility.lights[0].intensity = 0.7f;
  182. m_RenderUtility.lights[1].intensity = 0.7f;
  183. m_RenderUtility.ambientColor = new Color(0.1f, 0.1f, 0.1f, 0.0f);
  184. m_RenderUtility.Render(true);
  185. }
  186. static Bounds GetRenderableBounds(SpriteRenderer[] renderers)
  187. {
  188. if (renderers.Length == 1)
  189. {
  190. var renderBound = renderers[0].bounds;
  191. var localPos = renderers[0].transform.localPosition;
  192. renderBound.center -= localPos;
  193. return renderBound;
  194. }
  195. var bounds = new Bounds();
  196. foreach (var rendererComponents in renderers)
  197. {
  198. var renderBound = rendererComponents.bounds;
  199. if (bounds.extents == Vector3.zero)
  200. bounds = renderBound;
  201. else if (rendererComponents.enabled)
  202. bounds.Encapsulate(renderBound);
  203. }
  204. return bounds;
  205. }
  206. public void Dispose()
  207. {
  208. if (m_Disposed)
  209. return;
  210. m_RenderUtility.Cleanup();
  211. Object.DestroyImmediate(m_PreviewObject);
  212. m_PreviewObject = null;
  213. m_Disposed = true;
  214. }
  215. }
  216. }