DOTweenAnimationInspector.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  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 System.IO;
  6. using DG.DemiEditor;
  7. using DG.DOTweenEditor.Core;
  8. using DG.DOTweenEditor.UI;
  9. using DG.Tweening;
  10. using DG.Tweening.Core;
  11. using UnityEditor;
  12. using UnityEngine;
  13. using DOTweenSettings = DG.Tweening.Core.DOTweenSettings;
  14. #if true // UI_MARKER
  15. using UnityEngine.UI;
  16. #endif
  17. #if true // TEXTMESHPRO_MARKER
  18. using TMPro;
  19. #endif
  20. namespace DG.DOTweenEditor
  21. {
  22. [CustomEditor(typeof(DOTweenAnimation))]
  23. public class DOTweenAnimationInspector : ABSAnimationInspector
  24. {
  25. enum FadeTargetType
  26. {
  27. CanvasGroup,
  28. Image
  29. }
  30. enum ChooseTargetMode
  31. {
  32. None,
  33. BetweenCanvasGroupAndImage
  34. }
  35. static readonly Dictionary<DOTweenAnimation.AnimationType, Type[]> _AnimationTypeToComponent = new Dictionary<DOTweenAnimation.AnimationType, Type[]>() {
  36. { DOTweenAnimation.AnimationType.Move, new[] {
  37. #if true // PHYSICS_MARKER
  38. typeof(Rigidbody),
  39. #endif
  40. #if true // PHYSICS2D_MARKER
  41. typeof(Rigidbody2D),
  42. #endif
  43. #if true // UI_MARKER
  44. typeof(RectTransform),
  45. #endif
  46. typeof(Transform)
  47. }},
  48. { DOTweenAnimation.AnimationType.Rotate, new[] {
  49. #if true // PHYSICS_MARKER
  50. typeof(Rigidbody),
  51. #endif
  52. #if true // PHYSICS2D_MARKER
  53. typeof(Rigidbody2D),
  54. #endif
  55. typeof(Transform)
  56. }},
  57. { DOTweenAnimation.AnimationType.LocalMove, new[] { typeof(Transform) } },
  58. { DOTweenAnimation.AnimationType.LocalRotate, new[] { typeof(Transform) } },
  59. { DOTweenAnimation.AnimationType.Scale, new[] { typeof(Transform) } },
  60. { DOTweenAnimation.AnimationType.Color, new[] {
  61. typeof(Light),
  62. #if true // SPRITE_MARKER
  63. typeof(SpriteRenderer),
  64. #endif
  65. #if true // UI_MARKER
  66. typeof(Image), typeof(Text), typeof(RawImage), typeof(Graphic),
  67. #endif
  68. typeof(Renderer),
  69. }},
  70. { DOTweenAnimation.AnimationType.Fade, new[] {
  71. typeof(Light),
  72. #if true // SPRITE_MARKER
  73. typeof(SpriteRenderer),
  74. #endif
  75. #if true // UI_MARKER
  76. typeof(Image), typeof(Text), typeof(CanvasGroup), typeof(RawImage), typeof(Graphic),
  77. #endif
  78. typeof(Renderer),
  79. }},
  80. #if true // UI_MARKER
  81. { DOTweenAnimation.AnimationType.Text, new[] { typeof(Text) } },
  82. #endif
  83. { DOTweenAnimation.AnimationType.PunchPosition, new[] {
  84. #if true // UI_MARKER
  85. typeof(RectTransform),
  86. #endif
  87. typeof(Transform)
  88. }},
  89. { DOTweenAnimation.AnimationType.PunchRotation, new[] { typeof(Transform) } },
  90. { DOTweenAnimation.AnimationType.PunchScale, new[] { typeof(Transform) } },
  91. { DOTweenAnimation.AnimationType.ShakePosition, new[] {
  92. #if true // UI_MARKER
  93. typeof(RectTransform),
  94. #endif
  95. typeof(Transform)
  96. }},
  97. { DOTweenAnimation.AnimationType.ShakeRotation, new[] { typeof(Transform) } },
  98. { DOTweenAnimation.AnimationType.ShakeScale, new[] { typeof(Transform) } },
  99. { DOTweenAnimation.AnimationType.CameraAspect, new[] { typeof(Camera) } },
  100. { DOTweenAnimation.AnimationType.CameraBackgroundColor, new[] { typeof(Camera) } },
  101. { DOTweenAnimation.AnimationType.CameraFieldOfView, new[] { typeof(Camera) } },
  102. { DOTweenAnimation.AnimationType.CameraOrthoSize, new[] { typeof(Camera) } },
  103. { DOTweenAnimation.AnimationType.CameraPixelRect, new[] { typeof(Camera) } },
  104. { DOTweenAnimation.AnimationType.CameraRect, new[] { typeof(Camera) } },
  105. #if true // UI_MARKER
  106. { DOTweenAnimation.AnimationType.UIWidthHeight, new[] { typeof(RectTransform) } },
  107. { DOTweenAnimation.AnimationType.FillAmount, new[] { typeof(Image) } },
  108. #endif
  109. };
  110. #if false // TK2D_MARKER
  111. static readonly Dictionary<DOTweenAnimation.AnimationType, Type[]> _Tk2dAnimationTypeToComponent = new Dictionary<DOTweenAnimation.AnimationType, Type[]>() {
  112. { DOTweenAnimation.AnimationType.Scale, new[] { typeof(tk2dBaseSprite), typeof(tk2dTextMesh) } },
  113. { DOTweenAnimation.AnimationType.Color, new[] { typeof(tk2dBaseSprite), typeof(tk2dTextMesh) } },
  114. { DOTweenAnimation.AnimationType.Fade, new[] { typeof(tk2dBaseSprite), typeof(tk2dTextMesh) } },
  115. { DOTweenAnimation.AnimationType.Text, new[] { typeof(tk2dTextMesh) } }
  116. };
  117. #endif
  118. #if true // TEXTMESHPRO_MARKER
  119. static readonly Dictionary<DOTweenAnimation.AnimationType, Type[]> _TMPAnimationTypeToComponent = new Dictionary<DOTweenAnimation.AnimationType, Type[]>() {
  120. { DOTweenAnimation.AnimationType.Color, new[] { typeof(TextMeshPro), typeof(TextMeshProUGUI) } },
  121. { DOTweenAnimation.AnimationType.Fade, new[] { typeof(TextMeshPro), typeof(TextMeshProUGUI) } },
  122. { DOTweenAnimation.AnimationType.Text, new[] { typeof(TextMeshPro), typeof(TextMeshProUGUI) } }
  123. };
  124. #endif
  125. static readonly string[] _AnimationType = new[] {
  126. "None",
  127. "Move", "LocalMove",
  128. "Rotate", "LocalRotate",
  129. "Scale",
  130. "Color", "Fade",
  131. #if true // UI_MARKER
  132. "FillAmount",
  133. "Text",
  134. #endif
  135. #if false // TK2D_MARKER
  136. "Text",
  137. #endif
  138. #if true // TEXTMESHPRO_MARKER
  139. "Text",
  140. #endif
  141. #if true // UI_MARKER
  142. "UIWidthHeight",
  143. #endif
  144. "Punch/Position", "Punch/Rotation", "Punch/Scale",
  145. "Shake/Position", "Shake/Rotation", "Shake/Scale",
  146. "Camera/Aspect", "Camera/BackgroundColor", "Camera/FieldOfView", "Camera/OrthoSize", "Camera/PixelRect", "Camera/Rect"
  147. };
  148. static string[] _animationTypeNoSlashes; // _AnimationType list without slashes in values
  149. static string[] _datString; // String representation of DOTweenAnimation enum (here for caching reasons)
  150. DOTweenAnimation _src;
  151. DOTweenSettings _settings;
  152. bool _runtimeEditMode; // If TRUE allows to change and save stuff at runtime
  153. bool _refreshRequired; // If TRUE refreshes components data
  154. int _totComponentsOnSrc; // Used to determine if a Component is added or removed from the source
  155. bool _isLightSrc; // Used to determine if we're tweening a Light, to set the max Fade value to more than 1
  156. #pragma warning disable 414
  157. ChooseTargetMode _chooseTargetMode = ChooseTargetMode.None;
  158. #pragma warning restore 414
  159. static readonly GUIContent _GuiC_selfTarget_true = new GUIContent(
  160. "SELF", "Will animate components on this gameObject"
  161. );
  162. static readonly GUIContent _GuiC_selfTarget_false = new GUIContent(
  163. "OTHER", "Will animate components on the given gameObject instead than on this one"
  164. );
  165. static readonly GUIContent _GuiC_tweenTargetIsTargetGO_true = new GUIContent(
  166. "Use As Tween Target", "Will set the tween target (via SetTarget, used to control a tween directly from a target) to the \"OTHER\" gameObject"
  167. );
  168. static readonly GUIContent _GuiC_tweenTargetIsTargetGO_false = new GUIContent(
  169. "Use As Tween Target", "Will set the tween target (via SetTarget, used to control a tween directly from a target) to the gameObject containing this animation, not the \"OTHER\" one"
  170. );
  171. #region MonoBehaviour Methods
  172. void OnEnable()
  173. {
  174. _src = target as DOTweenAnimation;
  175. _settings = DOTweenUtilityWindow.GetDOTweenSettings();
  176. onStartProperty = base.serializedObject.FindProperty("onStart");
  177. onPlayProperty = base.serializedObject.FindProperty("onPlay");
  178. onUpdateProperty = base.serializedObject.FindProperty("onUpdate");
  179. onStepCompleteProperty = base.serializedObject.FindProperty("onStepComplete");
  180. onCompleteProperty = base.serializedObject.FindProperty("onComplete");
  181. onRewindProperty = base.serializedObject.FindProperty("onRewind");
  182. onTweenCreatedProperty = base.serializedObject.FindProperty("onTweenCreated");
  183. // Convert _AnimationType to _animationTypeNoSlashes
  184. int len = _AnimationType.Length;
  185. _animationTypeNoSlashes = new string[len];
  186. for (int i = 0; i < len; ++i) {
  187. string a = _AnimationType[i];
  188. a = a.Replace("/", "");
  189. _animationTypeNoSlashes[i] = a;
  190. }
  191. }
  192. void OnDisable()
  193. {
  194. DOTweenPreviewManager.StopAllPreviews();
  195. }
  196. override public void OnInspectorGUI()
  197. {
  198. base.OnInspectorGUI();
  199. GUILayout.Space(3);
  200. EditorGUIUtils.SetGUIStyles();
  201. bool playMode = Application.isPlaying;
  202. _runtimeEditMode = _runtimeEditMode && playMode;
  203. GUILayout.BeginHorizontal();
  204. EditorGUIUtils.InspectorLogo();
  205. GUILayout.Label(_src.animationType.ToString() + (string.IsNullOrEmpty(_src.id) ? "" : " [" + _src.id + "]"), EditorGUIUtils.sideLogoIconBoldLabelStyle);
  206. // Up-down buttons
  207. GUILayout.FlexibleSpace();
  208. if (GUILayout.Button("▲", DeGUI.styles.button.toolIco)) UnityEditorInternal.ComponentUtility.MoveComponentUp(_src);
  209. if (GUILayout.Button("▼", DeGUI.styles.button.toolIco)) UnityEditorInternal.ComponentUtility.MoveComponentDown(_src);
  210. GUILayout.EndHorizontal();
  211. if (playMode) {
  212. if (_runtimeEditMode) {
  213. } else {
  214. GUILayout.Space(8);
  215. GUILayout.Label("Animation Editor disabled while in play mode", EditorGUIUtils.wordWrapLabelStyle);
  216. if (!_src.isActive) {
  217. GUILayout.Label("This animation has been toggled as inactive and won't be generated", EditorGUIUtils.wordWrapLabelStyle);
  218. GUI.enabled = false;
  219. }
  220. if (GUILayout.Button(new GUIContent("Activate Edit Mode", "Switches to Runtime Edit Mode, where you can change animations values and restart them"))) {
  221. _runtimeEditMode = true;
  222. }
  223. GUILayout.Label("NOTE: when using DOPlayNext, the sequence is determined by the DOTweenAnimation Components order in the target GameObject's Inspector", EditorGUIUtils.wordWrapLabelStyle);
  224. GUILayout.Space(10);
  225. if (!_runtimeEditMode) return;
  226. }
  227. }
  228. Undo.RecordObject(_src, "DOTween Animation");
  229. Undo.RecordObject(_settings, "DOTween Animation");
  230. // _src.isValid = Validate(); // Moved down
  231. EditorGUIUtility.labelWidth = 110;
  232. if (playMode) {
  233. GUILayout.Space(4);
  234. DeGUILayout.Toolbar("Edit Mode Commands");
  235. DeGUILayout.BeginVBox(DeGUI.styles.box.stickyTop);
  236. GUILayout.BeginHorizontal();
  237. if (GUILayout.Button("TogglePause")) _src.tween.TogglePause();
  238. if (GUILayout.Button("Rewind")) _src.tween.Rewind();
  239. if (GUILayout.Button("Restart")) _src.tween.Restart();
  240. GUILayout.EndHorizontal();
  241. if (GUILayout.Button("Commit changes and restart")) {
  242. _src.tween.Rewind();
  243. _src.tween.Kill();
  244. if (_src.isValid) {
  245. _src.CreateTween();
  246. _src.tween.Play();
  247. }
  248. }
  249. GUILayout.Label("To apply your changes when exiting Play mode, use the Component's upper right menu and choose \"Copy Component\", then \"Paste Component Values\" after exiting Play mode", DeGUI.styles.label.wordwrap);
  250. DeGUILayout.EndVBox();
  251. } else {
  252. GUILayout.BeginHorizontal();
  253. bool hasManager = _src.GetComponent<DOTweenVisualManager>() != null;
  254. EditorGUI.BeginChangeCheck();
  255. _settings.showPreviewPanel = hasManager
  256. ? DeGUILayout.ToggleButton(_settings.showPreviewPanel, "Preview Controls", styles.custom.inlineToggle)
  257. : DeGUILayout.ToggleButton(_settings.showPreviewPanel, "Preview Controls", styles.custom.inlineToggle, GUILayout.Width(120));
  258. if (EditorGUI.EndChangeCheck()) {
  259. EditorUtility.SetDirty(_settings);
  260. DOTweenPreviewManager.StopAllPreviews();
  261. }
  262. if (!hasManager) {
  263. if (GUILayout.Button(new GUIContent("Add Manager", "Adds a manager component which allows you to choose additional options for this gameObject"))) {
  264. _src.gameObject.AddComponent<DOTweenVisualManager>();
  265. }
  266. }
  267. GUILayout.EndHorizontal();
  268. }
  269. // Preview in editor
  270. bool isPreviewing = _settings.showPreviewPanel ? DOTweenPreviewManager.PreviewGUI(_src) : false;
  271. EditorGUI.BeginDisabledGroup(isPreviewing);
  272. // Choose target
  273. GUILayout.BeginHorizontal();
  274. _src.isActive = EditorGUILayout.Toggle(new GUIContent("", "If unchecked, this animation will not be created"), _src.isActive, GUILayout.Width(14));
  275. EditorGUI.BeginChangeCheck();
  276. EditorGUI.BeginChangeCheck();
  277. _src.targetIsSelf = DeGUILayout.ToggleButton(
  278. _src.targetIsSelf, _src.targetIsSelf ? _GuiC_selfTarget_true : _GuiC_selfTarget_false,
  279. new Color(1f, 0.78f, 0f), DeGUI.colors.bg.toggleOn, new Color(0.33f, 0.14f, 0.02f), DeGUI.colors.content.toggleOn,
  280. null, GUILayout.Width(47)
  281. );
  282. bool innerChanged = EditorGUI.EndChangeCheck();
  283. if (innerChanged) {
  284. _src.targetGO = null;
  285. GUI.changed = true;
  286. }
  287. if (_src.targetIsSelf) GUILayout.Label(_GuiC_selfTarget_true.tooltip);
  288. else {
  289. using (new DeGUI.ColorScope(null, null, _src.targetGO == null ? Color.red : Color.white)) {
  290. _src.targetGO = (GameObject)EditorGUILayout.ObjectField(_src.targetGO, typeof(GameObject), true);
  291. }
  292. _src.tweenTargetIsTargetGO = DeGUILayout.ToggleButton(
  293. _src.tweenTargetIsTargetGO, _src.tweenTargetIsTargetGO ? _GuiC_tweenTargetIsTargetGO_true : _GuiC_tweenTargetIsTargetGO_false,
  294. GUILayout.Width(131)
  295. );
  296. }
  297. bool check = EditorGUI.EndChangeCheck();
  298. if (check) _refreshRequired = true;
  299. GUILayout.EndHorizontal();
  300. GameObject targetGO = _src.targetIsSelf ? _src.gameObject : _src.targetGO;
  301. if (targetGO == null) {
  302. // Uses external target gameObject but it's not set
  303. if (_src.targetGO != null || _src.target != null) {
  304. _src.targetGO = null;
  305. _src.target = null;
  306. GUI.changed = true;
  307. }
  308. } else {
  309. GUILayout.BeginHorizontal();
  310. DOTweenAnimation.AnimationType prevAnimType = _src.animationType;
  311. // _src.animationType = (DOTweenAnimation.AnimationType)EditorGUILayout.EnumPopup(_src.animationType, EditorGUIUtils.popupButton);
  312. GUI.enabled = GUI.enabled && _src.isActive;
  313. _src.animationType = AnimationToDOTweenAnimationType(_AnimationType[EditorGUILayout.Popup(DOTweenAnimationTypeToPopupId(_src.animationType), _AnimationType)]);
  314. _src.autoGenerate = DeGUILayout.ToggleButton(_src.autoGenerate, new GUIContent("AutoGenerate", "If selected, the tween will be generated at startup (during Start for RectTransform position tween, Awake for all the others)"));
  315. if (_src.autoGenerate) {
  316. _src.autoPlay = DeGUILayout.ToggleButton(_src.autoPlay, new GUIContent("AutoPlay", "If selected, the tween will play automatically"));
  317. }
  318. _src.autoKill = DeGUILayout.ToggleButton(_src.autoKill, new GUIContent("AutoKill", "If selected, the tween will be killed when it completes, and won't be reusable"));
  319. GUILayout.EndHorizontal();
  320. if (prevAnimType != _src.animationType) {
  321. // Set default optional values based on animation type
  322. _src.endValueTransform = null;
  323. _src.useTargetAsV3 = false;
  324. switch (_src.animationType) {
  325. case DOTweenAnimation.AnimationType.Move:
  326. case DOTweenAnimation.AnimationType.LocalMove:
  327. case DOTweenAnimation.AnimationType.Rotate:
  328. case DOTweenAnimation.AnimationType.LocalRotate:
  329. case DOTweenAnimation.AnimationType.Scale:
  330. _src.endValueV3 = Vector3.zero;
  331. _src.endValueFloat = 0;
  332. _src.optionalBool0 = _src.animationType == DOTweenAnimation.AnimationType.Scale;
  333. break;
  334. case DOTweenAnimation.AnimationType.UIWidthHeight:
  335. _src.endValueV3 = Vector3.zero;
  336. _src.endValueFloat = 0;
  337. _src.optionalBool0 = _src.animationType == DOTweenAnimation.AnimationType.UIWidthHeight;
  338. break;
  339. case DOTweenAnimation.AnimationType.FillAmount:
  340. _src.endValueFloat = 1;
  341. break;
  342. case DOTweenAnimation.AnimationType.Color:
  343. case DOTweenAnimation.AnimationType.Fade:
  344. _isLightSrc = targetGO.GetComponent<Light>() != null;
  345. _src.endValueFloat = 0;
  346. break;
  347. case DOTweenAnimation.AnimationType.Text:
  348. _src.optionalBool0 = true;
  349. break;
  350. case DOTweenAnimation.AnimationType.PunchPosition:
  351. case DOTweenAnimation.AnimationType.PunchRotation:
  352. case DOTweenAnimation.AnimationType.PunchScale:
  353. _src.endValueV3 = _src.animationType == DOTweenAnimation.AnimationType.PunchRotation ? new Vector3(0, 180, 0) : Vector3.one;
  354. _src.optionalFloat0 = 1;
  355. _src.optionalInt0 = 10;
  356. _src.optionalBool0 = false;
  357. break;
  358. case DOTweenAnimation.AnimationType.ShakePosition:
  359. case DOTweenAnimation.AnimationType.ShakeRotation:
  360. case DOTweenAnimation.AnimationType.ShakeScale:
  361. _src.endValueV3 = _src.animationType == DOTweenAnimation.AnimationType.ShakeRotation ? new Vector3(90, 90, 90) : Vector3.one;
  362. _src.optionalInt0 = 10;
  363. _src.optionalFloat0 = 90;
  364. _src.optionalBool0 = false;
  365. _src.optionalBool1 = true;
  366. break;
  367. case DOTweenAnimation.AnimationType.CameraAspect:
  368. case DOTweenAnimation.AnimationType.CameraFieldOfView:
  369. case DOTweenAnimation.AnimationType.CameraOrthoSize:
  370. _src.endValueFloat = 0;
  371. break;
  372. case DOTweenAnimation.AnimationType.CameraPixelRect:
  373. case DOTweenAnimation.AnimationType.CameraRect:
  374. _src.endValueRect = new Rect(0, 0, 0, 0);
  375. break;
  376. }
  377. }
  378. if (_src.animationType == DOTweenAnimation.AnimationType.None) {
  379. _src.isValid = false;
  380. if (GUI.changed) EditorUtility.SetDirty(_src);
  381. return;
  382. }
  383. if (_refreshRequired || prevAnimType != _src.animationType || ComponentsChanged()) {
  384. _refreshRequired = false;
  385. _src.isValid = Validate(targetGO);
  386. // See if we need to choose between multiple targets
  387. #if true // UI_MARKER
  388. if (_src.animationType == DOTweenAnimation.AnimationType.Fade && targetGO.GetComponent<CanvasGroup>() != null && targetGO.GetComponent<Image>() != null) {
  389. _chooseTargetMode = ChooseTargetMode.BetweenCanvasGroupAndImage;
  390. // Reassign target and forcedTargetType if lost
  391. if (_src.forcedTargetType == DOTweenAnimation.TargetType.Unset) _src.forcedTargetType = _src.targetType;
  392. switch (_src.forcedTargetType) {
  393. case DOTweenAnimation.TargetType.CanvasGroup:
  394. _src.target = targetGO.GetComponent<CanvasGroup>();
  395. break;
  396. case DOTweenAnimation.TargetType.Image:
  397. _src.target = targetGO.GetComponent<Image>();
  398. break;
  399. }
  400. } else {
  401. #endif
  402. _chooseTargetMode = ChooseTargetMode.None;
  403. _src.forcedTargetType = DOTweenAnimation.TargetType.Unset;
  404. #if true // UI_MARKER
  405. }
  406. #endif
  407. }
  408. if (!_src.isValid) {
  409. GUI.color = Color.red;
  410. GUILayout.BeginVertical(GUI.skin.box);
  411. GUILayout.Label("No valid Component was found for the selected animation", EditorGUIUtils.wordWrapLabelStyle);
  412. GUILayout.EndVertical();
  413. GUI.color = Color.white;
  414. if (GUI.changed) EditorUtility.SetDirty(_src);
  415. return;
  416. }
  417. #if true // UI_MARKER
  418. // Special cases in which multiple target types could be used (set after validation)
  419. if (_chooseTargetMode == ChooseTargetMode.BetweenCanvasGroupAndImage && _src.forcedTargetType != DOTweenAnimation.TargetType.Unset) {
  420. FadeTargetType fadeTargetType = (FadeTargetType)Enum.Parse(typeof(FadeTargetType), _src.forcedTargetType.ToString());
  421. DOTweenAnimation.TargetType prevTargetType = _src.forcedTargetType;
  422. _src.forcedTargetType = (DOTweenAnimation.TargetType)Enum.Parse(typeof(DOTweenAnimation.TargetType), EditorGUILayout.EnumPopup(_src.animationType + " Target", fadeTargetType).ToString());
  423. if (_src.forcedTargetType != prevTargetType) {
  424. // Target type change > assign correct target
  425. switch (_src.forcedTargetType) {
  426. case DOTweenAnimation.TargetType.CanvasGroup:
  427. _src.target = targetGO.GetComponent<CanvasGroup>();
  428. break;
  429. case DOTweenAnimation.TargetType.Image:
  430. _src.target = targetGO.GetComponent<Image>();
  431. break;
  432. }
  433. }
  434. }
  435. #endif
  436. GUILayout.BeginHorizontal();
  437. _src.duration = EditorGUILayout.FloatField("Duration", _src.duration);
  438. if (_src.duration < 0) _src.duration = 0;
  439. _src.isSpeedBased = DeGUILayout.ToggleButton(_src.isSpeedBased, new GUIContent("SpeedBased", "If selected, the duration will count as units/degree x second"), DeGUI.styles.button.tool, GUILayout.Width(75));
  440. GUILayout.EndHorizontal();
  441. _src.delay = EditorGUILayout.FloatField("Delay", _src.delay);
  442. if (_src.delay < 0) _src.delay = 0;
  443. _src.isIndependentUpdate = EditorGUILayout.Toggle("Ignore TimeScale", _src.isIndependentUpdate);
  444. _src.easeType = EditorGUIUtils.FilteredEasePopup("Ease", _src.easeType);
  445. if (_src.easeType == Ease.INTERNAL_Custom) {
  446. _src.easeCurve = EditorGUILayout.CurveField(" Ease Curve", _src.easeCurve);
  447. }
  448. _src.loops = EditorGUILayout.IntField(new GUIContent("Loops", "Set to -1 for infinite loops"), _src.loops);
  449. if (_src.loops < -1) _src.loops = -1;
  450. if (_src.loops > 1 || _src.loops == -1)
  451. _src.loopType = (LoopType)EditorGUILayout.EnumPopup(" Loop Type", _src.loopType);
  452. _src.id = EditorGUILayout.TextField("ID", _src.id);
  453. bool canBeRelative = true;
  454. // End value and eventual specific options
  455. switch (_src.animationType) {
  456. case DOTweenAnimation.AnimationType.Move:
  457. case DOTweenAnimation.AnimationType.LocalMove:
  458. GUIEndValueV3(targetGO, _src.animationType == DOTweenAnimation.AnimationType.Move);
  459. _src.optionalBool0 = EditorGUILayout.Toggle(" Snapping", _src.optionalBool0);
  460. canBeRelative = !_src.useTargetAsV3;
  461. break;
  462. case DOTweenAnimation.AnimationType.Rotate:
  463. case DOTweenAnimation.AnimationType.LocalRotate:
  464. bool isRigidbody2D = DOTweenModuleUtils.Physics.HasRigidbody2D(_src);
  465. if (isRigidbody2D) GUIEndValueFloat();
  466. else {
  467. GUIEndValueV3(targetGO);
  468. _src.optionalRotationMode = (RotateMode)EditorGUILayout.EnumPopup(" Rotation Mode", _src.optionalRotationMode);
  469. }
  470. break;
  471. case DOTweenAnimation.AnimationType.Scale:
  472. if (_src.optionalBool0) GUIEndValueFloat();
  473. else GUIEndValueV3(targetGO);
  474. _src.optionalBool0 = EditorGUILayout.Toggle("Uniform Scale", _src.optionalBool0);
  475. break;
  476. case DOTweenAnimation.AnimationType.UIWidthHeight:
  477. if (_src.optionalBool0) GUIEndValueFloat();
  478. else GUIEndValueV2();
  479. _src.optionalBool0 = EditorGUILayout.Toggle("Uniform Scale", _src.optionalBool0);
  480. break;
  481. case DOTweenAnimation.AnimationType.FillAmount:
  482. GUIEndValueFloat();
  483. if (_src.endValueFloat < 0) _src.endValueFloat = 0;
  484. if (_src.endValueFloat > 1) _src.endValueFloat = 1;
  485. canBeRelative = false;
  486. break;
  487. case DOTweenAnimation.AnimationType.Color:
  488. GUIEndValueColor();
  489. canBeRelative = false;
  490. break;
  491. case DOTweenAnimation.AnimationType.Fade:
  492. GUIEndValueFloat();
  493. if (_src.endValueFloat < 0) _src.endValueFloat = 0;
  494. if (!_isLightSrc && _src.endValueFloat > 1) _src.endValueFloat = 1;
  495. canBeRelative = false;
  496. break;
  497. case DOTweenAnimation.AnimationType.Text:
  498. GUIEndValueString();
  499. _src.optionalBool0 = EditorGUILayout.Toggle("Rich Text Enabled", _src.optionalBool0);
  500. _src.optionalScrambleMode = (ScrambleMode)EditorGUILayout.EnumPopup("Scramble Mode", _src.optionalScrambleMode);
  501. _src.optionalString = EditorGUILayout.TextField(new GUIContent("Custom Scramble", "Custom characters to use in case of ScrambleMode.Custom"), _src.optionalString);
  502. break;
  503. case DOTweenAnimation.AnimationType.PunchPosition:
  504. case DOTweenAnimation.AnimationType.PunchRotation:
  505. case DOTweenAnimation.AnimationType.PunchScale:
  506. GUIEndValueV3(targetGO);
  507. canBeRelative = false;
  508. _src.optionalInt0 = EditorGUILayout.IntSlider(new GUIContent(" Vibrato", "How much will the punch vibrate"), _src.optionalInt0, 1, 50);
  509. _src.optionalFloat0 = EditorGUILayout.Slider(new GUIContent(" Elasticity", "How much the vector will go beyond the starting position when bouncing backwards"), _src.optionalFloat0, 0, 1);
  510. if (_src.animationType == DOTweenAnimation.AnimationType.PunchPosition) _src.optionalBool0 = EditorGUILayout.Toggle(" Snapping", _src.optionalBool0);
  511. break;
  512. case DOTweenAnimation.AnimationType.ShakePosition:
  513. case DOTweenAnimation.AnimationType.ShakeRotation:
  514. case DOTweenAnimation.AnimationType.ShakeScale:
  515. GUIEndValueV3(targetGO);
  516. canBeRelative = false;
  517. _src.optionalInt0 = EditorGUILayout.IntSlider(new GUIContent(" Vibrato", "How much will the shake vibrate"), _src.optionalInt0, 1, 50);
  518. using (new GUILayout.HorizontalScope()) {
  519. _src.optionalFloat0 = EditorGUILayout.Slider(new GUIContent(" Randomness", "The shake randomness"), _src.optionalFloat0, 0, 90);
  520. _src.optionalShakeRandomnessMode = (ShakeRandomnessMode)EditorGUILayout.EnumPopup(_src.optionalShakeRandomnessMode, GUILayout.Width(70));
  521. }
  522. _src.optionalBool1 = EditorGUILayout.Toggle(new GUIContent(" FadeOut", "If selected the shake will fade out, otherwise it will constantly play with full force"), _src.optionalBool1);
  523. if (_src.animationType == DOTweenAnimation.AnimationType.ShakePosition) _src.optionalBool0 = EditorGUILayout.Toggle(" Snapping", _src.optionalBool0);
  524. break;
  525. case DOTweenAnimation.AnimationType.CameraAspect:
  526. case DOTweenAnimation.AnimationType.CameraFieldOfView:
  527. case DOTweenAnimation.AnimationType.CameraOrthoSize:
  528. GUIEndValueFloat();
  529. canBeRelative = false;
  530. break;
  531. case DOTweenAnimation.AnimationType.CameraBackgroundColor:
  532. GUIEndValueColor();
  533. canBeRelative = false;
  534. break;
  535. case DOTweenAnimation.AnimationType.CameraPixelRect:
  536. case DOTweenAnimation.AnimationType.CameraRect:
  537. GUIEndValueRect();
  538. canBeRelative = false;
  539. break;
  540. }
  541. // Final settings
  542. if (canBeRelative) _src.isRelative = EditorGUILayout.Toggle(" Relative", _src.isRelative);
  543. // Events
  544. AnimationInspectorGUI.AnimationEvents(this, _src);
  545. }
  546. EditorGUI.EndDisabledGroup();
  547. if (GUI.changed) EditorUtility.SetDirty(_src);
  548. }
  549. #endregion
  550. #region Methods
  551. // Returns TRUE if the Component layout on the src gameObject changed (a Component was added or removed)
  552. bool ComponentsChanged()
  553. {
  554. int prevTotComponentsOnSrc = _totComponentsOnSrc;
  555. _totComponentsOnSrc = _src.gameObject.GetComponents<Component>().Length;
  556. return prevTotComponentsOnSrc != _totComponentsOnSrc;
  557. }
  558. // Checks if a Component that can be animated with the given animationType is attached to the src
  559. bool Validate(GameObject targetGO)
  560. {
  561. if (_src.animationType == DOTweenAnimation.AnimationType.None) return false;
  562. Component srcTarget;
  563. // First check for external plugins
  564. #if false // TK2D_MARKER
  565. if (_Tk2dAnimationTypeToComponent.ContainsKey(_src.animationType)) {
  566. foreach (Type t in _Tk2dAnimationTypeToComponent[_src.animationType]) {
  567. srcTarget = targetGO.GetComponent(t);
  568. if (srcTarget != null) {
  569. _src.target = srcTarget;
  570. _src.targetType = DOTweenAnimation.TypeToDOTargetType(t);
  571. return true;
  572. }
  573. }
  574. }
  575. #endif
  576. #if true // TEXTMESHPRO_MARKER
  577. if (_TMPAnimationTypeToComponent.ContainsKey(_src.animationType)) {
  578. foreach (Type t in _TMPAnimationTypeToComponent[_src.animationType]) {
  579. srcTarget = targetGO.GetComponent(t);
  580. if (srcTarget != null) {
  581. _src.target = srcTarget;
  582. _src.targetType = DOTweenAnimation.TypeToDOTargetType(t);
  583. return true;
  584. }
  585. }
  586. }
  587. #endif
  588. // Then check for regular stuff
  589. if (_AnimationTypeToComponent.ContainsKey(_src.animationType)) {
  590. foreach (Type t in _AnimationTypeToComponent[_src.animationType]) {
  591. srcTarget = targetGO.GetComponent(t);
  592. if (srcTarget != null) {
  593. _src.target = srcTarget;
  594. _src.targetType = DOTweenAnimation.TypeToDOTargetType(t);
  595. return true;
  596. }
  597. }
  598. }
  599. return false;
  600. }
  601. DOTweenAnimation.AnimationType AnimationToDOTweenAnimationType(string animation)
  602. {
  603. if (_datString == null) _datString = Enum.GetNames(typeof(DOTweenAnimation.AnimationType));
  604. animation = animation.Replace("/", "");
  605. return (DOTweenAnimation.AnimationType)(Array.IndexOf(_datString, animation));
  606. }
  607. int DOTweenAnimationTypeToPopupId(DOTweenAnimation.AnimationType animation)
  608. {
  609. return Array.IndexOf(_animationTypeNoSlashes, animation.ToString());
  610. }
  611. #endregion
  612. #region GUI Draw Methods
  613. void GUIEndValueFloat()
  614. {
  615. GUILayout.BeginHorizontal();
  616. GUIToFromButton();
  617. _src.endValueFloat = EditorGUILayout.FloatField(_src.endValueFloat);
  618. GUILayout.EndHorizontal();
  619. }
  620. void GUIEndValueColor()
  621. {
  622. GUILayout.BeginHorizontal();
  623. GUIToFromButton();
  624. _src.endValueColor = EditorGUILayout.ColorField(_src.endValueColor);
  625. GUILayout.EndHorizontal();
  626. }
  627. void GUIEndValueV3(GameObject targetGO, bool optionalTransform = false)
  628. {
  629. GUILayout.BeginHorizontal();
  630. GUIToFromButton();
  631. if (_src.useTargetAsV3) {
  632. Transform prevT = _src.endValueTransform;
  633. _src.endValueTransform = EditorGUILayout.ObjectField(_src.endValueTransform, typeof(Transform), true) as Transform;
  634. if (_src.endValueTransform != prevT && _src.endValueTransform != null) {
  635. #if true // UI_MARKER
  636. // Check that it's a Transform for a Transform or a RectTransform for a RectTransform
  637. if (targetGO.GetComponent<RectTransform>() != null) {
  638. if (_src.endValueTransform.GetComponent<RectTransform>() == null) {
  639. EditorUtility.DisplayDialog("DOTween Pro", "For Unity UI elements, the target must also be a UI element", "Ok");
  640. _src.endValueTransform = null;
  641. }
  642. } else if (_src.endValueTransform.GetComponent<RectTransform>() != null) {
  643. EditorUtility.DisplayDialog("DOTween Pro", "You can't use a UI target for a non UI object", "Ok");
  644. _src.endValueTransform = null;
  645. }
  646. #endif
  647. }
  648. } else {
  649. _src.endValueV3 = EditorGUILayout.Vector3Field("", _src.endValueV3, GUILayout.Height(16));
  650. }
  651. if (optionalTransform) {
  652. if (GUILayout.Button(_src.useTargetAsV3 ? "target" : "value", EditorGUIUtils.sideBtStyle, GUILayout.Width(44))) _src.useTargetAsV3 = !_src.useTargetAsV3;
  653. }
  654. GUILayout.EndHorizontal();
  655. #if true // UI_MARKER
  656. if (_src.useTargetAsV3 && _src.endValueTransform != null && _src.target is RectTransform) {
  657. EditorGUILayout.HelpBox("NOTE: when using a UI target, the tween will be created during Start instead of Awake", MessageType.Info);
  658. }
  659. #endif
  660. }
  661. void GUIEndValueV2()
  662. {
  663. GUILayout.BeginHorizontal();
  664. GUIToFromButton();
  665. _src.endValueV2 = EditorGUILayout.Vector2Field("", _src.endValueV2, GUILayout.Height(16));
  666. GUILayout.EndHorizontal();
  667. }
  668. void GUIEndValueString()
  669. {
  670. GUILayout.BeginHorizontal();
  671. GUIToFromButton();
  672. _src.endValueString = EditorGUILayout.TextArea(_src.endValueString, EditorGUIUtils.wordWrapTextArea);
  673. GUILayout.EndHorizontal();
  674. }
  675. void GUIEndValueRect()
  676. {
  677. GUILayout.BeginHorizontal();
  678. GUIToFromButton();
  679. _src.endValueRect = EditorGUILayout.RectField(_src.endValueRect);
  680. GUILayout.EndHorizontal();
  681. }
  682. void GUIToFromButton()
  683. {
  684. if (GUILayout.Button(_src.isFrom ? "FROM" : "TO", EditorGUIUtils.sideBtStyle, GUILayout.Width(90))) _src.isFrom = !_src.isFrom;
  685. GUILayout.Space(16);
  686. }
  687. #endregion
  688. }
  689. // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
  690. // ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████
  691. // █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
  692. [InitializeOnLoad]
  693. static class Initializer
  694. {
  695. static Initializer()
  696. {
  697. DOTweenAnimation.OnReset += OnReset;
  698. }
  699. static void OnReset(DOTweenAnimation src)
  700. {
  701. DOTweenSettings settings = DOTweenUtilityWindow.GetDOTweenSettings();
  702. if (settings == null) return;
  703. Undo.RecordObject(src, "DOTweenAnimation");
  704. src.autoPlay = settings.defaultAutoPlay == AutoPlay.All || settings.defaultAutoPlay == AutoPlay.AutoPlayTweeners;
  705. src.autoKill = settings.defaultAutoKill;
  706. EditorUtility.SetDirty(src);
  707. }
  708. }
  709. }