BsGUICurves.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsEditorPrerequisites.h"
  5. #include "GUI/BsGUIElement.h"
  6. #include "GUI/BsGUITimeline.h"
  7. #include "GUI/BsGUIGraphTicks.h"
  8. #include "2D/BsImageSprite.h"
  9. #include "Animation/BsAnimationUtility.h"
  10. namespace bs
  11. {
  12. /** @addtogroup GUI-Editor
  13. * @{
  14. */
  15. /** Controls which elements should a GUICurves object draw. */
  16. enum class BS_SCRIPT_EXPORT(m:GUIEditor,n:CurveDrawOptions,api:bed) CurveDrawOption
  17. {
  18. /** Draws markers at specific time intervals. */
  19. DrawMarkers = 1 << 0,
  20. /** Draws elements representing individual keyframes. */
  21. DrawKeyframes = 1 << 1,
  22. /** Draws curves and the area between them. Only relevant if only two curves are provided for drawing. */
  23. DrawRange = 1 << 2
  24. };
  25. typedef Flags<CurveDrawOption> CurveDrawOptions;
  26. BS_FLAGS_OPERATORS(CurveDrawOption)
  27. /** Curve and a color to draw it in. */
  28. struct BS_SCRIPT_EXPORT(pl:true,m:GUIEditor,api:bed) CurveDrawInfo
  29. {
  30. CurveDrawInfo() = default;
  31. CurveDrawInfo(const TAnimationCurve<float>& curve, Color color)
  32. :curve(curve), color(color)
  33. { }
  34. TAnimationCurve<float> curve;
  35. Color color;
  36. bool operator== (const CurveDrawInfo& rhs) const { return curve == rhs.curve && color == rhs.color; }
  37. bool operator!= (const CurveDrawInfo& rhs) const { return !operator==(rhs); }
  38. };
  39. /** GUI element that displays one or multiple curves. */
  40. class BS_ED_EXPORT BS_SCRIPT_EXPORT(m:GUIEditor,api:bed) GUICurves : public GUITimeline
  41. {
  42. public:
  43. /** Returns type name of the GUI element used for finding GUI element styles. */
  44. static const String& getGUITypeName();
  45. /**
  46. * Creates a new GUI element.
  47. *
  48. * @param[in] styleName Optional style to use for the element. Style will be retrieved from GUISkin of the
  49. * GUIWidget the element is used on. If not specified default style is used.
  50. */
  51. BS_SCRIPT_EXPORT(ec:GUICurves)
  52. static GUICurves* create(const String& styleName = StringUtil::BLANK);
  53. /**
  54. * Creates a new GUI element.
  55. *
  56. * @param[in] drawOptions Options that control which additional elements to draw.
  57. * @param[in] styleName Optional style to use for the element. Style will be retrieved from GUISkin of the
  58. * GUIWidget the element is used on. If not specified default style is used.
  59. */
  60. BS_SCRIPT_EXPORT(ec:GUICurves)
  61. static GUICurves* create(CurveDrawOptions drawOptions, const String& styleName = StringUtil::BLANK);
  62. /**
  63. * Creates a new GUI element.
  64. *
  65. * @param[in] options Options that allow you to control how is the element positioned and sized. This will
  66. * override any similar options set by style.
  67. * @param[in] styleName Optional style to use for the element. Style will be retrieved from GUISkin of the
  68. * GUIWidget the element is used on. If not specified default style is used.
  69. */
  70. static GUICurves* create(const GUIOptions& options, const String& styleName = StringUtil::BLANK);
  71. /**
  72. * Creates a new GUI element.
  73. *
  74. * @param[in] drawOptions Options that control which additional elements to draw.
  75. * @param[in] options Options that allow you to control how is the element positioned and sized. This will
  76. * override any similar options set by style.
  77. * @param[in] styleName Optional style to use for the element. Style will be retrieved from GUISkin of the
  78. * GUIWidget the element is used on. If not specified default style is used.
  79. */
  80. static GUICurves* create(CurveDrawOptions drawOptions, const GUIOptions& options,
  81. const String& styleName = StringUtil::BLANK);
  82. /** Animation curves to display. */
  83. BS_SCRIPT_EXPORT(pr:setter,n:Curves)
  84. void setCurves(const Vector<CurveDrawInfo>& curves);
  85. /** @copydoc setCurves */
  86. BS_SCRIPT_EXPORT(pr:getter,n:Curves)
  87. const Vector<CurveDrawInfo>& getCurves() const { return mCurves; }
  88. /**
  89. * Changes the visible range that the GUI element displays.
  90. *
  91. * @param[in] xRange Range of the horizontal area. Displayed area will range from [0, xRange].
  92. * @param[in] yRange Range of the vertical area. Displayed area will range from [-yRange * 0.5, yRange * 0.5]
  93. */
  94. BS_SCRIPT_EXPORT()
  95. void setRange(float xRange, float yRange);
  96. /**
  97. * Returns the offset at which the displayed timeline values start at.
  98. *
  99. * @param[in] offset Value to start the timeline values at, where x = time, y = value.
  100. */
  101. BS_SCRIPT_EXPORT()
  102. void setOffset(const Vector2& offset);
  103. /** Centers and zooms the view to fully display the provided set of curves. */
  104. BS_SCRIPT_EXPORT()
  105. void centerAndZoom();
  106. /**
  107. * Converts pixel coordinates into coordinates in curve space.
  108. *
  109. * @param[in] pixelCoords Coordinates relative to this GUI element, in pixels.
  110. * @param[out] curveCoords Curve coordinates within the range as specified by setRange(). Only valid when
  111. * function returns true.
  112. * @param[in] padding Determines should coordinates over the area reserved for padding be registered.
  113. * @return True if the coordinates are within the curve area, false otherwise.
  114. */
  115. BS_SCRIPT_EXPORT()
  116. bool pixelToCurveSpace(const Vector2I& pixelCoords, Vector2& curveCoords, bool padding = false) const;
  117. /**
  118. * Converts coordinate in curve space (time, value) into pixel coordinates relative to this element's origin.
  119. *
  120. * @param[in] curveCoords Time and value of the location to convert.
  121. * @return Coordinates relative to this element's origin, in pixels.
  122. */
  123. BS_SCRIPT_EXPORT()
  124. Vector2I curveToPixelSpace(const Vector2& curveCoords) const;
  125. /**
  126. * Attempts to find a curve under the provided coordinates.
  127. *
  128. * @param[in] pixelCoords Coordinates relative to this GUI element in pixels.
  129. * @return Index of the curve, or -1 if none found.
  130. */
  131. BS_SCRIPT_EXPORT()
  132. UINT32 findCurve(const Vector2I& pixelCoords);
  133. /**
  134. * Attempts to find a keyframe under the provided coordinates.
  135. *
  136. * @param[in] pixelCoords Coordinates relative to this GUI element in pixels.
  137. * @param[out] keyframe Output object containing keyframe index and index of the curve it belongs to. Only
  138. * valid if method returns true.
  139. * @return True if there is a keyframe under the coordinates, false otherwise.
  140. */
  141. BS_SCRIPT_EXPORT()
  142. bool findKeyFrame(const Vector2I& pixelCoords, KeyframeRef& keyframe);
  143. /**
  144. * Attempts to find a a tangent handle under the provided coordinates.
  145. *
  146. * @param[in] pixelCoords Coordinates relative to this GUI element in pixels.
  147. * @param[in] tangent Output object containing keyframe information and tangent type. Only valid if method
  148. * returns true.
  149. * @return True if there is a tangent handle under the coordinates, false otherwise.
  150. */
  151. BS_SCRIPT_EXPORT()
  152. bool findTangent(const Vector2I& pixelCoords, TangentRef& tangent);
  153. /**
  154. * Marks the specified key-frame as selected, changing the way it is displayed.
  155. *
  156. * @param[in] keyframeRef Keyframe reference containing the curve and keyframe index.
  157. * @param[in] tangentMode Type of tangent to display on the selected keyframe.
  158. * @param[in] selected True to select it, false to deselect it.
  159. */
  160. BS_SCRIPT_EXPORT()
  161. void selectKeyframe(const KeyframeRef& keyframeRef, const TangentMode& tangentMode, bool selected);
  162. /** Clears any key-frames that were marked as selected. */
  163. BS_SCRIPT_EXPORT()
  164. void clearSelectedKeyframes();
  165. BS_SCRIPT_EXPORT(in:true)
  166. Event<void()> onClicked; /**< Triggered when the user clicks on the GUI element. */
  167. protected:
  168. GUICurves(CurveDrawOptions drawOptions, const String& styleName, const GUIDimensions& dimensions);
  169. ~GUICurves() override = default;
  170. /**
  171. * Converts a keyframe tangent (slope) value into a 2D normal vector.
  172. *
  173. * @param[in] tangent Keyframe tangent (slope).
  174. * @return Normalized 2D vector pointing in the direction of the tangent.
  175. */
  176. Vector2 tangentToNormal(float tangent) const;
  177. /**
  178. * Returns the position of the tangent, in element's pixel space.
  179. *
  180. * @param[in] keyFrame Keyframe that the tangent belongs to.
  181. * @param[in] type Which tangent to retrieve the position for.
  182. * @return Position of the tangent, relative to the this GUI element's origin, in pixels.
  183. */
  184. Vector2I getTangentPosition(const TKeyframe<float>& keyFrame, TangentType type) const;
  185. /**
  186. * Checks if the tangent should be displayed, depending on the active tangent mode.
  187. *
  188. * @param[in] mode Tangent mode for the keyframe.
  189. * @param[in] type Which tangent to check for.
  190. * @return True if the tangent should be displayed.
  191. */
  192. bool isTangentDisplayed(TangentMode mode, TangentType type) const;
  193. /**
  194. * Checks is the provided key-frame currently marked as selected.
  195. *
  196. * @param[in] curveIdx Index of the curve the keyframe is on.
  197. * @param[in] keyIdx Index of the keyframe.
  198. * @return True if selected, false otherwise.
  199. */
  200. bool isSelected(int curveIdx, int keyIdx) const;
  201. /**
  202. * Draws a vertical frame marker on the curve area.
  203. *
  204. * @param[in] t Time at which to draw the marker.
  205. * @param[in] color Color with which to draw the marker.
  206. * @param[in] onTop Determines should the marker be drawn above or below the curve.
  207. */
  208. void drawFrameMarker(float t, Color color, bool onTop);
  209. /** Draws a horizontal line representing the line at y = 0. */
  210. void drawCenterLine();
  211. /**
  212. * Draws a diamond shape of the specified size at the coordinates.
  213. *
  214. * @param[in] center Position at which to place the diamond's center, in pixel coordinates.
  215. * @param[in] size Determines number of pixels to extend the diamond in each direction.
  216. * @param[in] innerColor Color of the diamond's background.
  217. * @param[in] outerColor Color of the diamond's outline.
  218. */
  219. void drawDiamond(Vector2I center, int size, Color innerColor, Color outerColor);
  220. /**
  221. * Draws a keyframe a the specified time and value.
  222. *
  223. * @param[in] t Time to draw the keyframe at.
  224. * @param[in] y Y value to draw the keyframe at.
  225. * @param[in] selected Determines should the keyframe be drawing using the selected color scheme, or normally.
  226. */
  227. void drawKeyframe(float t, float y, bool selected);
  228. /**
  229. * Draws zero, one or two tangents for the specified keyframe. Whether tangents are drawn depends on the provided
  230. * mode.
  231. *
  232. * @param[in] keyFrame Keyframe to draw the tangents for.
  233. * @param[in] tangentMode Type of tangents in the keyframe.
  234. */
  235. void drawTangents(const TKeyframe<float>& keyFrame, TangentMode tangentMode);
  236. /**
  237. * Draws the curve using the provided color.
  238. *
  239. * @param[in] curve Curve to draw within the currently set range.
  240. * @param[in] color Color to draw the curve with.
  241. */
  242. void drawCurve(const TAnimationCurve<float>& curve, const Color& color);
  243. /*
  244. * Draws the area between two curves using the provided color.
  245. *
  246. * @param[in] curves Curves to draw within the currently set range.
  247. * @param[in] color Color to draw the area with.
  248. */
  249. void drawCurveRange(const Vector<TAnimationCurve<float>>& curves, Color color);
  250. /** @copydoc GUIElement::updateRenderElementsInternal */
  251. void updateRenderElementsInternal() override;
  252. /** @copydoc GUIElement::_mouseEvent() */
  253. bool _mouseEvent(const GUIMouseEvent& ev) override;
  254. private:
  255. /** Information about a currently selected keyframe. */
  256. struct SelectedKeyframe
  257. {
  258. SelectedKeyframe(KeyframeRef keyframeRef, TangentMode tangentMode)
  259. :keyframeRef(keyframeRef), tangentMode(tangentMode)
  260. { }
  261. KeyframeRef keyframeRef;
  262. TangentMode tangentMode;
  263. };
  264. Vector<CurveDrawInfo> mCurves;
  265. Vector<SelectedKeyframe> mSelectedKeyframes;
  266. float mYRange = 20.0f;
  267. float mYOffset = 0.0f;
  268. CurveDrawOptions mDrawOptions;
  269. GUIGraphTicks mTickHandler;
  270. };
  271. /** @} */
  272. }