DOTweenPreviewManager.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Author: Daniele Giardini - http://www.demigiant.com
  2. // Created: 2015/03/12 16:03
  3. using System;
  4. using System.Collections.Generic;
  5. using DG.DemiEditor;
  6. using DG.DemiLib;
  7. using DG.Tweening;
  8. using DG.Tweening.Core;
  9. using UnityEditor;
  10. using UnityEditorInternal;
  11. using UnityEngine;
  12. using Object = UnityEngine.Object;
  13. namespace DG.DOTweenEditor
  14. {
  15. public static class DOTweenPreviewManager
  16. {
  17. static bool _previewOnlyIfSetToAutoPlay = true;
  18. static readonly Dictionary<DOTweenAnimation,TweenInfo> _AnimationToTween = new Dictionary<DOTweenAnimation,TweenInfo>();
  19. static readonly List<DOTweenAnimation> _TmpKeys = new List<DOTweenAnimation>();
  20. #region Public Methods & GUI
  21. /// <summary>
  22. /// Returns TRUE if its actually previewing animations
  23. /// </summary>
  24. public static bool PreviewGUI(DOTweenAnimation src)
  25. {
  26. if (EditorApplication.isPlaying) return false;
  27. Styles.Init();
  28. bool isPreviewing = _AnimationToTween.Count > 0;
  29. bool isPreviewingThis = isPreviewing && _AnimationToTween.ContainsKey(src);
  30. // Preview in editor
  31. GUI.backgroundColor = isPreviewing
  32. ? new DeSkinColor(new Color(0.49f, 0.8f, 0.86f), new Color(0.15f, 0.26f, 0.35f))
  33. : new DeSkinColor(Color.white, new Color(0.13f, 0.13f, 0.13f));
  34. GUILayout.BeginVertical(Styles.previewBox);
  35. DeGUI.ResetGUIColors();
  36. GUILayout.BeginHorizontal();
  37. GUILayout.Label("Preview Mode - Experimental", Styles.previewLabel);
  38. _previewOnlyIfSetToAutoPlay = DeGUILayout.ToggleButton(
  39. _previewOnlyIfSetToAutoPlay,
  40. new GUIContent("AutoPlay only", "If toggled only previews animations that have AutoPlay turned ON"),
  41. Styles.btOption
  42. );
  43. GUILayout.EndHorizontal();
  44. GUILayout.Space(1);
  45. // Preview - Play
  46. GUILayout.BeginHorizontal();
  47. EditorGUI.BeginDisabledGroup(
  48. isPreviewingThis || src.animationType == DOTweenAnimation.AnimationType.None
  49. || !src.isActive || _previewOnlyIfSetToAutoPlay && !src.autoPlay
  50. );
  51. if (GUILayout.Button("► Play", Styles.btPreview)) {
  52. if (!isPreviewing) StartupGlobalPreview();
  53. AddAnimationToGlobalPreview(src);
  54. }
  55. EditorGUI.EndDisabledGroup();
  56. EditorGUI.BeginDisabledGroup(isPreviewing);
  57. if (GUILayout.Button("► Play All <i>on GameObject</i>", Styles.btPreview)) {
  58. if (!isPreviewing) StartupGlobalPreview();
  59. DOTweenAnimation[] anims = src.gameObject.GetComponents<DOTweenAnimation>();
  60. foreach (DOTweenAnimation anim in anims) AddAnimationToGlobalPreview(anim);
  61. }
  62. if (GUILayout.Button("► Play All <i>in Scene</i>", Styles.btPreview)) {
  63. if (!isPreviewing) StartupGlobalPreview();
  64. // DOTweenAnimation[] anims = Object.FindObjectsOfType<DOTweenAnimation>(); // OBSOLETE
  65. DOTweenAnimation[] anims = DeEditorCompatibilityUtils.FindObjectsOfType<DOTweenAnimation>();
  66. foreach (DOTweenAnimation anim in anims) AddAnimationToGlobalPreview(anim);
  67. }
  68. EditorGUI.EndDisabledGroup();
  69. GUILayout.EndHorizontal();
  70. // Preview - Stop
  71. GUILayout.BeginHorizontal();
  72. EditorGUI.BeginDisabledGroup(!isPreviewingThis);
  73. if (GUILayout.Button("■ Stop", Styles.btPreview)) {
  74. if (_AnimationToTween.ContainsKey(src)) StopPreview(_AnimationToTween[src].tween);
  75. }
  76. EditorGUI.EndDisabledGroup();
  77. EditorGUI.BeginDisabledGroup(!isPreviewing);
  78. if (GUILayout.Button("■ Stop All <i>on GameObject</i>", Styles.btPreview)) {
  79. StopPreview(src.gameObject);
  80. }
  81. if (GUILayout.Button("■ Stop All <i>in Scene</i>", Styles.btPreview)) {
  82. StopAllPreviews();
  83. }
  84. EditorGUI.EndDisabledGroup();
  85. GUILayout.EndHorizontal();
  86. if (isPreviewing) {
  87. int playingTweens = 0;
  88. int completedTweens = 0;
  89. int pausedTweens = 0;
  90. foreach (KeyValuePair<DOTweenAnimation, TweenInfo> kvp in _AnimationToTween) {
  91. Tween t = kvp.Value.tween;
  92. if (t.IsPlaying()) playingTweens++;
  93. else if (t.IsComplete()) completedTweens++;
  94. else pausedTweens++;
  95. }
  96. GUILayout.Label("Playing Tweens: " + playingTweens, Styles.previewStatusLabel);
  97. GUILayout.Label("Completed Tweens: " + completedTweens, Styles.previewStatusLabel);
  98. // GUILayout.Label("Paused Tweens: " + playingTweens);
  99. }
  100. GUILayout.EndVertical();
  101. return isPreviewing;
  102. }
  103. #if !(UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5)
  104. public static void StopAllPreviews(PlayModeStateChange state)
  105. {
  106. StopAllPreviews();
  107. }
  108. #endif
  109. public static void StopAllPreviews()
  110. {
  111. _TmpKeys.Clear();
  112. foreach (KeyValuePair<DOTweenAnimation,TweenInfo> kvp in _AnimationToTween) {
  113. _TmpKeys.Add(kvp.Key);
  114. }
  115. StopPreview(_TmpKeys);
  116. _TmpKeys.Clear();
  117. _AnimationToTween.Clear();
  118. DOTweenEditorPreview.Stop();
  119. #if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5
  120. UnityEditor.EditorApplication.playmodeStateChanged -= StopAllPreviews;
  121. #else
  122. UnityEditor.EditorApplication.playModeStateChanged -= StopAllPreviews;
  123. #endif
  124. // EditorApplication.playmodeStateChanged -= StopAllPreviews;
  125. InternalEditorUtility.RepaintAllViews();
  126. }
  127. #endregion
  128. #region Methods
  129. static void StartupGlobalPreview()
  130. {
  131. DOTweenEditorPreview.Start();
  132. #if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5
  133. UnityEditor.EditorApplication.playmodeStateChanged += StopAllPreviews;
  134. #else
  135. UnityEditor.EditorApplication.playModeStateChanged += StopAllPreviews;
  136. #endif
  137. // EditorApplication.playmodeStateChanged += StopAllPreviews;
  138. }
  139. static void AddAnimationToGlobalPreview(DOTweenAnimation src)
  140. {
  141. if (!src.isActive) return; // Ignore sources whose tweens have been set to inactive
  142. if (_previewOnlyIfSetToAutoPlay && !src.autoPlay) return;
  143. Tween t = src.CreateEditorPreview();
  144. if (t == null) return;
  145. _AnimationToTween.Add(src, new TweenInfo(src, t, src.isFrom));
  146. // Tween setup
  147. DOTweenEditorPreview.PrepareTweenForPreview(t);
  148. }
  149. static void StopPreview(GameObject go)
  150. {
  151. _TmpKeys.Clear();
  152. foreach (KeyValuePair<DOTweenAnimation,TweenInfo> kvp in _AnimationToTween) {
  153. if (kvp.Key.gameObject != go) continue;
  154. _TmpKeys.Add(kvp.Key);
  155. }
  156. StopPreview(_TmpKeys);
  157. _TmpKeys.Clear();
  158. if (_AnimationToTween.Count == 0) StopAllPreviews();
  159. else InternalEditorUtility.RepaintAllViews();
  160. }
  161. static void StopPreview(Tween t)
  162. {
  163. TweenInfo tInfo = null;
  164. foreach (KeyValuePair<DOTweenAnimation,TweenInfo> kvp in _AnimationToTween) {
  165. if (kvp.Value.tween != t) continue;
  166. tInfo = kvp.Value;
  167. _AnimationToTween.Remove(kvp.Key);
  168. break;
  169. }
  170. if (tInfo == null) {
  171. Debug.LogWarning("DOTween Preview ► Couldn't find tween to stop");
  172. return;
  173. }
  174. if (tInfo.isFrom) {
  175. int totLoops = tInfo.tween.Loops();
  176. if (totLoops < 0 || totLoops > 1) {
  177. tInfo.tween.Goto(tInfo.tween.Duration(false));
  178. } else tInfo.tween.Complete();
  179. } else tInfo.tween.Rewind();
  180. tInfo.tween.Kill();
  181. EditorUtility.SetDirty(tInfo.animation); // Refresh views
  182. if (_AnimationToTween.Count == 0) StopAllPreviews();
  183. else InternalEditorUtility.RepaintAllViews();
  184. }
  185. // Stops while iterating inversely, which deals better with tweens that overwrite each other
  186. static void StopPreview(List<DOTweenAnimation> keys)
  187. {
  188. for (int i = keys.Count - 1; i > -1; --i) {
  189. DOTweenAnimation anim = keys[i];
  190. TweenInfo tInfo = _AnimationToTween[anim];
  191. if (tInfo.isFrom) {
  192. int totLoops = tInfo.tween.Loops();
  193. if (totLoops < 0 || totLoops > 1) {
  194. tInfo.tween.Goto(tInfo.tween.Duration(false));
  195. } else tInfo.tween.Complete();
  196. } else tInfo.tween.Rewind();
  197. tInfo.tween.Kill();
  198. EditorUtility.SetDirty(anim); // Refresh views
  199. _AnimationToTween.Remove(anim);
  200. }
  201. }
  202. #endregion
  203. // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
  204. // ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████
  205. // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
  206. class TweenInfo
  207. {
  208. public DOTweenAnimation animation;
  209. public Tween tween;
  210. public bool isFrom;
  211. public TweenInfo(DOTweenAnimation animation, Tween tween, bool isFrom)
  212. {
  213. this.animation = animation;
  214. this.tween = tween;
  215. this.isFrom = isFrom;
  216. }
  217. }
  218. static class Styles
  219. {
  220. static bool _initialized;
  221. public static GUIStyle previewBox, previewLabel, btOption, btPreview, previewStatusLabel;
  222. public static void Init()
  223. {
  224. if (_initialized) return;
  225. _initialized = true;
  226. previewBox = new GUIStyle(GUI.skin.box).Clone().Padding(1, 1, 0, 3)
  227. .Background(DeStylePalette.squareBorderCurved_darkBorders).Border(7, 7, 7, 7);
  228. previewLabel = new GUIStyle(GUI.skin.label).Clone(10, FontStyle.Bold).Padding(1, 0, 3, 0).Margin(3, 6, 0, 0).StretchWidth(false);
  229. btOption = DeGUI.styles.button.bBlankBorderCompact.MarginBottom(2).MarginRight(4);
  230. btPreview = EditorStyles.miniButton.Clone(Format.RichText);
  231. previewStatusLabel = EditorStyles.miniLabel.Clone().Padding(4, 0, 0, 0).Margin(0);
  232. }
  233. }
  234. }
  235. }