GUIAnimEvents.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. using System;
  4. using bs;
  5. namespace bs.Editor
  6. {
  7. /** @addtogroup AnimationEditor
  8. * @{
  9. */
  10. /// <summary>
  11. /// Renders a list of animation events in a form of a timeline. User can set the range of the times to display,
  12. /// as well as its physical dimensions.
  13. /// </summary>
  14. public class GUIAnimEvents : GUITimelineBase
  15. {
  16. private const int EVENT_HALF_WIDTH = 2;
  17. private AnimationEvent[] events = new AnimationEvent[0];
  18. private bool[] selectedEvents = new bool[0];
  19. /// <summary>
  20. /// Constructs a new events timeline and adds it to the specified layout.
  21. /// </summary>
  22. /// <param name="layout">Layout to add the events GUI to.</param>
  23. /// <param name="width">Width of the GUI element in pixels.</param>
  24. /// <param name="height">Height of the GUI element in pixels.</param>
  25. public GUIAnimEvents(GUILayout layout, int width, int height)
  26. :base(layout, width, height)
  27. { }
  28. /// <summary>
  29. /// Attempts to find an event under the provided coordinates.
  30. /// </summary>
  31. /// <param name="pixelCoords">Coordinates relative to the layout the GUI element is on.</param>
  32. /// <param name="eventIdx">Index of the event that was clicked on. Index references the events array as provided
  33. /// to <see cref="SetEvents"/>. Only valid if method returns true.</param>
  34. /// <returns>True if an event was found under the coordinates, false otherwise.</returns>
  35. public bool FindEvent(Vector2I pixelCoords, out int eventIdx)
  36. {
  37. Rect2I bounds = canvas.Bounds;
  38. if (pixelCoords.x < (bounds.x + PADDING) || pixelCoords.x >= (bounds.x + bounds.width - PADDING) ||
  39. pixelCoords.y < bounds.y || pixelCoords.y >= (bounds.y + bounds.height))
  40. {
  41. eventIdx = -1;
  42. return false;
  43. }
  44. Vector2I relativeCoords = pixelCoords - new Vector2I(bounds.x, bounds.y);
  45. for (int i = 0; i < events.Length; i++)
  46. {
  47. AnimationEvent evnt = events[i];
  48. int xPos = (int)(((evnt.time - rangeOffset) / GetRange()) * drawableWidth) + PADDING;
  49. if (relativeCoords.x >= (xPos - EVENT_HALF_WIDTH) && relativeCoords.x <= (xPos + EVENT_HALF_WIDTH))
  50. {
  51. eventIdx = i;
  52. return true;
  53. }
  54. }
  55. eventIdx = -1;
  56. return false;
  57. }
  58. /// <summary>
  59. /// Changes the set of displayed animation events.
  60. /// </summary>
  61. /// <param name="events">Events to display on the timeline.</param>
  62. /// <param name="selected">Array of the same size as the <paramref name="events"/> array, determining which
  63. /// events should be displayed as selected.</param>
  64. public void SetEvents(AnimationEvent[] events, bool[] selected)
  65. {
  66. int numEvents;
  67. if (events != null)
  68. numEvents = events.Length;
  69. else
  70. numEvents = 0;
  71. this.events = new AnimationEvent[numEvents];
  72. if(events != null)
  73. Array.Copy(events, this.events, numEvents);
  74. selectedEvents = new bool[numEvents];
  75. if(selected != null)
  76. Array.Copy(selected, selectedEvents, MathEx.Min(numEvents, selected.Length));
  77. }
  78. /// <summary>
  79. /// Draws a marker for a single event.
  80. /// </summary>
  81. /// <param name="t">Time to draw the marker at.</param>
  82. /// <param name="selected">If true the marker will be drawn as selected.</param>
  83. private void DrawEventMarker(float t, bool selected)
  84. {
  85. int xPos = (int)(((t - rangeOffset) / GetRange()) * drawableWidth) + PADDING;
  86. Vector2I a = new Vector2I(xPos - EVENT_HALF_WIDTH, 0);
  87. Vector2I b = new Vector2I(xPos + EVENT_HALF_WIDTH, 0);
  88. Vector2I c = new Vector2I(xPos + EVENT_HALF_WIDTH, height - 1);
  89. Vector2I d = new Vector2I(xPos - EVENT_HALF_WIDTH, height - 1);
  90. // Draw square shape
  91. Vector2I[] linePoints = { a, b, c, d, a };
  92. Vector2I[] trianglePoints = { b, c, a, d };
  93. Color outerColor = selected ? Color.BansheeOrange : Color.Black;
  94. canvas.DrawTriangleStrip(trianglePoints, Color.White, 101);
  95. canvas.DrawPolyLine(linePoints, outerColor, 100);
  96. }
  97. /// <inheritdoc/>
  98. public override void Rebuild()
  99. {
  100. canvas.Clear();
  101. float range = GetRange();
  102. float lengthPerPixel = rangeLength / drawableWidth;
  103. float eventHalfWidth = lengthPerPixel * EVENT_HALF_WIDTH;
  104. for (int i = 0; i < events.Length; i++)
  105. {
  106. float t = events[i].time;
  107. float min = t - eventHalfWidth;
  108. float max = t + eventHalfWidth;
  109. if (max < rangeOffset || min > (rangeOffset + range))
  110. continue;
  111. DrawEventMarker(t, selectedEvents[i]);
  112. }
  113. DrawFrameMarker();
  114. }
  115. }
  116. /** @} */
  117. }