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.

302 lines
8.7KB

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