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.

314 lines
9.5KB

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