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.

301 lines
8.6KB

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