GUIAnimEvents.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. using System;
  4. using BansheeEngine;
  5. namespace BansheeEditor
  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. Debug.Log(i + ". " + xPos);
  50. if (relativeCoords.x >= (xPos - EVENT_HALF_WIDTH) && relativeCoords.x <= (xPos + EVENT_HALF_WIDTH))
  51. {
  52. eventIdx = i;
  53. return true;
  54. }
  55. }
  56. eventIdx = -1;
  57. return false;
  58. }
  59. /// <summary>
  60. /// Changes the set of displayed animation events.
  61. /// </summary>
  62. /// <param name="events">Events to display on the timeline.</param>
  63. /// <param name="selected">Array of the same size as the <paramref name="events"/> array, determining which
  64. /// events should be displayed as selected.</param>
  65. public void SetEvents(AnimationEvent[] events, bool[] selected)
  66. {
  67. int numEvents;
  68. if (events != null)
  69. numEvents = events.Length;
  70. else
  71. numEvents = 0;
  72. this.events = new AnimationEvent[numEvents];
  73. if(events != null)
  74. Array.Copy(events, this.events, numEvents);
  75. selectedEvents = new bool[numEvents];
  76. if(selected != null)
  77. Array.Copy(selected, selectedEvents, MathEx.Min(numEvents, selected.Length));
  78. }
  79. /// <summary>
  80. /// Draws a marker for a single event.
  81. /// </summary>
  82. /// <param name="t">Time to draw the marker at.</param>
  83. /// <param name="selected">If true the marker will be drawn as selected.</param>
  84. private void DrawEventMarker(float t, bool selected)
  85. {
  86. int xPos = (int)(((t - rangeOffset) / GetRange()) * drawableWidth) + PADDING;
  87. Vector2I a = new Vector2I(xPos - EVENT_HALF_WIDTH, 0);
  88. Vector2I b = new Vector2I(xPos + EVENT_HALF_WIDTH, 0);
  89. Vector2I c = new Vector2I(xPos + EVENT_HALF_WIDTH, height - 1);
  90. Vector2I d = new Vector2I(xPos - EVENT_HALF_WIDTH, height - 1);
  91. // Draw square shape
  92. Vector2I[] linePoints = { a, b, c, d, a };
  93. Vector2I[] trianglePoints = { b, c, a, d };
  94. Color outerColor = selected ? Color.BansheeOrange : Color.Black;
  95. canvas.DrawTriangleStrip(trianglePoints, Color.White, 101);
  96. canvas.DrawPolyLine(linePoints, outerColor, 100);
  97. }
  98. /// <inheritdoc/>
  99. public override void Rebuild()
  100. {
  101. canvas.Clear();
  102. float range = GetRange();
  103. float lengthPerPixel = rangeLength / drawableWidth;
  104. float eventHalfWidth = lengthPerPixel * EVENT_HALF_WIDTH;
  105. for (int i = 0; i < events.Length; i++)
  106. {
  107. float t = events[i].Time;
  108. float min = t - eventHalfWidth;
  109. float max = t + eventHalfWidth;
  110. if (max < rangeOffset || min > (rangeOffset + range))
  111. continue;
  112. DrawEventMarker(t, selectedEvents[i]);
  113. }
  114. DrawFrameMarker();
  115. }
  116. }
  117. /** @} */
  118. }