AnimationWindow.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. using System.Collections.Generic;
  4. using BansheeEngine;
  5. namespace BansheeEditor
  6. {
  7. /** @addtogroup Windows
  8. * @{
  9. */
  10. /// <summary>
  11. /// Displays animation curve editor window.
  12. /// </summary>
  13. internal class AnimationWindow : EditorWindow
  14. {
  15. public struct KeyframeRef
  16. {
  17. public KeyframeRef(int curveIdx, int keyIdx)
  18. {
  19. this.curveIdx = curveIdx;
  20. this.keyIdx = keyIdx;
  21. }
  22. public int curveIdx;
  23. public int keyIdx;
  24. }
  25. private GUIGraphTime timeline;
  26. private GUICurveDrawing curveDrawing;
  27. private GUIGraphValues sidebar;
  28. private GUIFloatField lengthField;
  29. private GUIIntField fpsField;
  30. private GUIFloatField yRangeField;
  31. private GUIButton addKeyframeBtn;
  32. private GUILayout buttonLayout;
  33. private EdAnimationCurve[] curves = new EdAnimationCurve[0];
  34. private int markedFrameIdx;
  35. private List<KeyframeRef> selectedKeyframes = new List<KeyframeRef>();
  36. // Keyframe drag
  37. private bool isMousePressedOverKey;
  38. private KeyFrame[] draggedKeyframes;
  39. private Vector2 dragStart;
  40. /// <summary>
  41. /// Opens the animation window.
  42. /// </summary>
  43. [MenuItem("Windows/Animation", ButtonModifier.CtrlAlt, ButtonCode.A, 6000)]
  44. private static void OpenGameWindow()
  45. {
  46. OpenWindow<AnimationWindow>();
  47. }
  48. /// <inheritdoc/>
  49. protected override LocString GetDisplayName()
  50. {
  51. return new LocEdString("Animation");
  52. }
  53. private void OnInitialize()
  54. {
  55. lengthField = new GUIFloatField(new LocEdString("Length"), 50);
  56. fpsField = new GUIIntField(new LocEdString("FPS"), 50);
  57. yRangeField = new GUIFloatField(new LocEdString("Y range"), 50);
  58. addKeyframeBtn = new GUIButton(new LocEdString("Add keyframe"));
  59. lengthField.Value = 60.0f;
  60. fpsField.Value = 1;
  61. yRangeField.Value = 20.0f;
  62. lengthField.OnChanged += x =>
  63. {
  64. timeline.SetRange(lengthField.Value);
  65. curveDrawing.SetRange(lengthField.Value, yRangeField.Value);
  66. };
  67. fpsField.OnChanged += x =>
  68. {
  69. timeline.SetFPS(x);
  70. curveDrawing.SetFPS(x);
  71. };
  72. yRangeField.OnChanged += x =>
  73. {
  74. curveDrawing.SetRange(lengthField.Value, x);
  75. sidebar.SetRange(x * -0.5f, x * 0.5f);
  76. };
  77. addKeyframeBtn.OnClick += () =>
  78. {
  79. AddKeyframeAtMarker();
  80. };
  81. GUILayout mainLayout = GUI.AddLayoutY();
  82. buttonLayout = mainLayout.AddLayoutX();
  83. buttonLayout.AddSpace(5);
  84. buttonLayout.AddElement(lengthField);
  85. buttonLayout.AddSpace(5);
  86. buttonLayout.AddElement(yRangeField);
  87. buttonLayout.AddSpace(5);
  88. buttonLayout.AddElement(fpsField);
  89. buttonLayout.AddSpace(5);
  90. buttonLayout.AddElement(addKeyframeBtn);
  91. buttonLayout.AddSpace(5);
  92. timeline = new GUIGraphTime(mainLayout, Width, 20);
  93. curves = CreateDummyCurves();
  94. curveDrawing = new GUICurveDrawing(mainLayout, Width, Height - 20, curves);
  95. curveDrawing.SetRange(60.0f, 20.0f);
  96. GUIPanel sidebarPanel = GUI.AddPanel(-10);
  97. sidebarPanel.SetPosition(0, 20 + buttonLayout.Bounds.height);
  98. sidebar = new GUIGraphValues(sidebarPanel, 30, Height - 20 - buttonLayout.Bounds.height);
  99. sidebar.SetRange(-10.0f, 10.0f);
  100. curveDrawing.SetSize(Width, Height - 20 - buttonLayout.Bounds.height);
  101. curveDrawing.Rebuild();
  102. // TODO - Calculate min/max Y and range to set as default
  103. // - Also recalculate whenever curves change and increase as needed
  104. }
  105. private void AddKeyframeAtMarker()
  106. {
  107. ClearSelection();
  108. foreach (var curve in curves)
  109. {
  110. float t = curveDrawing.GetTimeForFrame(markedFrameIdx);
  111. float value = curve.Native.Evaluate(t);
  112. curve.AddKeyframe(t, value);
  113. }
  114. curveDrawing.Rebuild();
  115. }
  116. private void DeleteSelectedKeyframes()
  117. {
  118. // Sort keys from highest to lowest so they can be removed without changing the indices of the keys
  119. // after them
  120. selectedKeyframes.Sort((x, y) =>
  121. {
  122. if (x.curveIdx.Equals(y.curveIdx))
  123. return y.keyIdx.CompareTo(x.keyIdx);
  124. return x.curveIdx.CompareTo(y.curveIdx);
  125. });
  126. foreach (var keyframe in selectedKeyframes)
  127. curves[keyframe.curveIdx].RemoveKeyframe(keyframe.keyIdx);
  128. ClearSelection();
  129. curveDrawing.Rebuild();
  130. }
  131. private EdAnimationCurve[] CreateDummyCurves()
  132. {
  133. EdAnimationCurve[] curves = new EdAnimationCurve[1];
  134. curves[0] = new EdAnimationCurve();
  135. curves[0].AddKeyframe(0.0f, 1.0f);
  136. curves[0].AddKeyframe(10.0f, 5.0f);
  137. curves[0].AddKeyframe(15.0f, -2.0f);
  138. curves[0].AddKeyframe(20.0f, 3.0f, TangentMode.InStep);
  139. return curves;
  140. }
  141. protected override void WindowResized(int width, int height)
  142. {
  143. timeline.SetSize(width, 20);
  144. curveDrawing.SetSize(width, height - 20 - buttonLayout.Bounds.height);
  145. sidebar.SetSize(30, height - 20 - buttonLayout.Bounds.height);
  146. curveDrawing.Rebuild();
  147. }
  148. private void ClearSelection()
  149. {
  150. curveDrawing.ClearSelectedKeyframes();
  151. selectedKeyframes.Clear();
  152. isMousePressedOverKey = false;
  153. }
  154. private void OnEditorUpdate()
  155. {
  156. if (Input.IsPointerButtonDown(PointerButton.Left))
  157. {
  158. Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition);
  159. Vector2 curveCoord;
  160. int curveIdx;
  161. int keyIdx;
  162. if (curveDrawing.GetCoordInfo(windowPos, out curveCoord, out curveIdx, out keyIdx))
  163. {
  164. if (keyIdx == -1)
  165. ClearSelection();
  166. else
  167. {
  168. if (!Input.IsButtonHeld(ButtonCode.LeftShift) && !Input.IsButtonHeld(ButtonCode.RightShift))
  169. ClearSelection();
  170. curveDrawing.SelectKeyframe(curveIdx, keyIdx, true);
  171. int existingIdx = selectedKeyframes.FindIndex(x =>
  172. {
  173. return x.curveIdx == curveIdx && x.keyIdx == keyIdx;
  174. });
  175. if (existingIdx == -1)
  176. selectedKeyframes.Add(new KeyframeRef(curveIdx, keyIdx));
  177. isMousePressedOverKey = true;
  178. dragStart = curveCoord;
  179. }
  180. curveDrawing.Rebuild();
  181. }
  182. }
  183. else if (Input.IsPointerButtonHeld(PointerButton.Left))
  184. {
  185. Vector2I windowPos = ScreenToWindowPos(Input.PointerPosition);
  186. if (isMousePressedOverKey)
  187. {
  188. // TODO - Check if pointer moves some minimal amount
  189. // - If so, start drag. Record all current positions
  190. // - Calculate offset in curve space and apply to all keyframes
  191. }
  192. else
  193. {
  194. int frameIdx = timeline.GetFrame(windowPos);
  195. if (frameIdx != -1)
  196. {
  197. timeline.SetMarkedFrame(frameIdx);
  198. curveDrawing.SetMarkedFrame(frameIdx);
  199. markedFrameIdx = frameIdx;
  200. curveDrawing.Rebuild();
  201. }
  202. }
  203. }
  204. else if (Input.IsPointerButtonUp(PointerButton.Left))
  205. {
  206. isMousePressedOverKey = false;
  207. }
  208. if(Input.IsButtonUp(ButtonCode.Delete))
  209. DeleteSelectedKeyframes();
  210. }
  211. }
  212. /** @} */
  213. }