You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

293 lines
8.3KB

  1. #pragma once
  2. #include <list>
  3. #include <memory>
  4. #include "../ext/nanovg/src/nanovg.h"
  5. #include "../ext/nanosvg/src/nanosvg.h"
  6. #include "util/common.hpp"
  7. #include "events.hpp"
  8. namespace rack {
  9. ////////////////////
  10. // resources
  11. ////////////////////
  12. // Constructing these directly will load from the disk each time. Use the load() functions to load from disk and cache them as long as the shared_ptr is held.
  13. // Implemented in window.cpp
  14. struct Font {
  15. int handle;
  16. Font(const std::string &filename);
  17. ~Font();
  18. static std::shared_ptr<Font> load(const std::string &filename);
  19. };
  20. struct Image {
  21. int handle;
  22. Image(const std::string &filename);
  23. ~Image();
  24. static std::shared_ptr<Image> load(const std::string &filename);
  25. };
  26. struct SVG {
  27. NSVGimage *handle;
  28. SVG(const std::string &filename);
  29. ~SVG();
  30. static std::shared_ptr<SVG> load(const std::string &filename);
  31. };
  32. ////////////////////
  33. // Base widget
  34. ////////////////////
  35. /** A node in the 2D scene graph */
  36. struct Widget {
  37. /** Stores position and size */
  38. Rect box = Rect(Vec(), Vec(INFINITY, INFINITY));
  39. Widget *parent = NULL;
  40. std::list<Widget*> children;
  41. bool visible = true;
  42. virtual ~Widget();
  43. virtual Rect getChildrenBoundingBox();
  44. /** Returns `v` transformed into the coordinate system of `relative` */
  45. virtual Vec getRelativeOffset(Vec v, Widget *relative);
  46. /** Returns `v` transformed into world coordinates */
  47. Vec getAbsoluteOffset(Vec v) {
  48. return getRelativeOffset(v, NULL);
  49. }
  50. /** Returns a subset of the given Rect bounded by the box of this widget and all ancestors */
  51. virtual Rect getViewport(Rect r);
  52. template <class T>
  53. T *getAncestorOfType() {
  54. if (!parent) return NULL;
  55. T *p = dynamic_cast<T*>(parent);
  56. if (p) return p;
  57. return parent->getAncestorOfType<T>();
  58. }
  59. template <class T>
  60. T *getFirstDescendantOfType() {
  61. for (Widget *child : children) {
  62. T *c = dynamic_cast<T*>(child);
  63. if (c) return c;
  64. c = child->getFirstDescendantOfType<T>();
  65. if (c) return c;
  66. }
  67. return NULL;
  68. }
  69. /** Adds widget to list of children.
  70. Gives ownership of widget to this widget instance.
  71. */
  72. void addChild(Widget *widget);
  73. /** Removes widget from list of children if it exists.
  74. Does not delete widget but transfers ownership to caller
  75. Silently fails if widget is not a child
  76. */
  77. void removeChild(Widget *widget);
  78. void clearChildren();
  79. /** Recursively finalizes event start/end pairs as needed */
  80. void finalizeEvents();
  81. /** Advances the module by one frame */
  82. virtual void step();
  83. /** Draws to NanoVG context */
  84. virtual void draw(NVGcontext *vg);
  85. // Events
  86. /** Called when a mouse button is pressed over this widget
  87. 0 for left, 1 for right, 2 for middle.
  88. Return `this` to accept the event.
  89. Return NULL to reject the event and pass it to the widget behind this one.
  90. */
  91. virtual void onMouseDown(EventMouseDown &e);
  92. virtual void onMouseUp(EventMouseUp &e);
  93. /** Called on every frame, even if mouseRel = Vec(0, 0) */
  94. virtual void onMouseMove(EventMouseMove &e);
  95. virtual void onHoverKey(EventHoverKey &e);
  96. /** Called when this widget begins responding to `onMouseMove` events */
  97. virtual void onMouseEnter(EventMouseEnter &e) {}
  98. /** Called when another widget begins responding to `onMouseMove` events */
  99. virtual void onMouseLeave(EventMouseLeave &e) {}
  100. virtual void onFocus(EventFocus &e) {}
  101. virtual void onDefocus(EventDefocus &e) {}
  102. virtual void onText(EventText &e) {}
  103. virtual void onKey(EventKey &e) {}
  104. virtual void onScroll(EventScroll &e);
  105. /** Called when a widget responds to `onMouseDown` for a left button press */
  106. virtual void onDragStart(EventDragStart &e) {}
  107. /** Called when the left button is released and this widget is being dragged */
  108. virtual void onDragEnd(EventDragEnd &e) {}
  109. /** Called when a widget responds to `onMouseMove` and is being dragged */
  110. virtual void onDragMove(EventDragMove &e) {}
  111. /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
  112. virtual void onDragEnter(EventDragEnter &e) {}
  113. virtual void onDragLeave(EventDragEnter &e) {}
  114. virtual void onDragDrop(EventDragDrop &e) {}
  115. virtual void onPathDrop(EventPathDrop &e);
  116. virtual void onAction(EventAction &e) {}
  117. virtual void onChange(EventChange &e) {}
  118. virtual void onZoom(EventZoom &e);
  119. /** Helper function for creating and initializing a Widget with certain arguments (in this case just the position).
  120. In this project, you will find this idiom everywhere, as an easier alternative to constructor arguments, for building a Widget (or a subclass) with a one-liner.
  121. Example:
  122. addChild(Widget::create<SVGWidget>(Vec(0, 0)))
  123. */
  124. template <typename T = Widget>
  125. static T *create(Vec pos) {
  126. T *o = new T();
  127. o->box.pos = pos;
  128. return o;
  129. }
  130. };
  131. struct TransformWidget : Widget {
  132. /** The transformation matrix */
  133. float transform[6];
  134. TransformWidget();
  135. Rect getChildrenBoundingBox() override;
  136. void identity();
  137. void translate(Vec delta);
  138. void rotate(float angle);
  139. void scale(Vec s);
  140. void draw(NVGcontext *vg) override;
  141. };
  142. struct ZoomWidget : Widget {
  143. float zoom = 1.0;
  144. Vec getRelativeOffset(Vec v, Widget *relative) override;
  145. Rect getViewport(Rect r) override;
  146. void setZoom(float zoom);
  147. void draw(NVGcontext *vg) override;
  148. void onMouseDown(EventMouseDown &e) override;
  149. void onMouseUp(EventMouseUp &e) override;
  150. void onMouseMove(EventMouseMove &e) override;
  151. void onHoverKey(EventHoverKey &e) override;
  152. void onScroll(EventScroll &e) override;
  153. void onPathDrop(EventPathDrop &e) override;
  154. };
  155. ////////////////////
  156. // Trait widgets
  157. ////////////////////
  158. /** Widget that does not respond to events */
  159. struct TransparentWidget : virtual Widget {
  160. void onMouseDown(EventMouseDown &e) override {}
  161. void onMouseUp(EventMouseUp &e) override {}
  162. void onMouseMove(EventMouseMove &e) override {}
  163. void onScroll(EventScroll &e) override {}
  164. };
  165. /** Widget that automatically responds to all mouse events but gives a chance for children to respond instead */
  166. struct OpaqueWidget : virtual Widget {
  167. void onMouseDown(EventMouseDown &e) override {
  168. Widget::onMouseDown(e);
  169. if (!e.target)
  170. e.target = this;
  171. e.consumed = true;
  172. }
  173. void onMouseUp(EventMouseUp &e) override {
  174. Widget::onMouseUp(e);
  175. if (!e.target)
  176. e.target = this;
  177. e.consumed = true;
  178. }
  179. void onMouseMove(EventMouseMove &e) override {
  180. Widget::onMouseMove(e);
  181. if (!e.target)
  182. e.target = this;
  183. e.consumed = true;
  184. }
  185. void onScroll(EventScroll &e) override {
  186. Widget::onScroll(e);
  187. e.consumed = true;
  188. }
  189. };
  190. struct SpriteWidget : virtual Widget {
  191. Vec spriteOffset;
  192. Vec spriteSize;
  193. std::shared_ptr<Image> spriteImage;
  194. int index = 0;
  195. void draw(NVGcontext *vg) override;
  196. };
  197. struct SVGWidget : virtual Widget {
  198. std::shared_ptr<SVG> svg;
  199. /** Sets the box size to the svg image size */
  200. void wrap();
  201. /** Sets and wraps the SVG */
  202. void setSVG(std::shared_ptr<SVG> svg);
  203. void draw(NVGcontext *vg) override;
  204. };
  205. /** Caches a widget's draw() result to a framebuffer so it is called less frequently
  206. When `dirty` is true, its children will be re-rendered on the next call to step() override.
  207. Events are not passed to the underlying scene.
  208. */
  209. struct FramebufferWidget : virtual Widget {
  210. /** Set this to true to re-render the children to the framebuffer the next time it is drawn */
  211. bool dirty = true;
  212. /** A margin in pixels around the children in the framebuffer
  213. This prevents cutting the rendered SVG off on the box edges.
  214. */
  215. float oversample;
  216. /** The root object in the framebuffer scene
  217. The FramebufferWidget owns the pointer
  218. */
  219. struct Internal;
  220. Internal *internal;
  221. FramebufferWidget();
  222. ~FramebufferWidget();
  223. void draw(NVGcontext *vg) override;
  224. int getImageHandle();
  225. void onZoom(EventZoom &e) override;
  226. };
  227. struct QuantityWidget : virtual Widget {
  228. float value = 0.0;
  229. float minValue = 0.0;
  230. float maxValue = 1.0;
  231. float defaultValue = 0.0;
  232. std::string label;
  233. /** Include a space character if you want a space after the number, e.g. " Hz" */
  234. std::string unit;
  235. /** The decimal place to round for displaying values.
  236. A precision of 2 will display as "1.00" for example.
  237. */
  238. int precision = 2;
  239. QuantityWidget();
  240. void setValue(float value);
  241. void setLimits(float minValue, float maxValue);
  242. void setDefaultValue(float defaultValue);
  243. /** Generates the display value */
  244. std::string getText();
  245. };
  246. ////////////////////
  247. // globals
  248. ////////////////////
  249. extern Widget *gHoveredWidget;
  250. extern Widget *gDraggedWidget;
  251. extern Widget *gDragHoveredWidget;
  252. extern Widget *gFocusedWidget;
  253. } // namespace rack