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.

478 lines
10KB

  1. #pragma once
  2. #include <assert.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include <list>
  6. #include <map>
  7. #include <jansson.h>
  8. #include "../ext/nanovg/src/nanovg.h"
  9. #include "../ext/oui/blendish.h"
  10. #include "util.hpp"
  11. namespace rack {
  12. struct Module;
  13. struct Wire;
  14. struct RackWidget;
  15. struct ParamWidget;
  16. struct InputPort;
  17. struct OutputPort;
  18. ////////////////////
  19. // base class and traits
  20. ////////////////////
  21. /** A node in the 2D scene graph */
  22. struct Widget {
  23. /** Stores position and size */
  24. Rect box = Rect(Vec(), Vec(INFINITY, INFINITY));
  25. Widget *parent = NULL;
  26. std::list<Widget*> children;
  27. virtual ~Widget();
  28. Vec getAbsolutePos();
  29. Rect getChildrenBoundingBox();
  30. template <class T>
  31. T *getAncestorOfType() {
  32. if (!parent) return NULL;
  33. T *p = dynamic_cast<T*>(parent);
  34. if (p) return p;
  35. return parent->getAncestorOfType<T>();
  36. }
  37. /** Adds widget to list of children.
  38. Gives ownership of widget to this widget instance.
  39. */
  40. void addChild(Widget *widget);
  41. // Does not delete widget but transfers ownership to caller
  42. // Silenty fails if widget is not a child
  43. void removeChild(Widget *widget);
  44. void clearChildren();
  45. /** Advances the module by one frame */
  46. virtual void step();
  47. /** Draws to NanoVG context */
  48. virtual void draw(NVGcontext *vg);
  49. // Events
  50. /** Called when a mouse button is pressed over this widget
  51. 0 for left, 1 for right, 2 for middle.
  52. Return `this` to accept the event.
  53. Return NULL to reject the event and pass it to the widget behind this one.
  54. */
  55. virtual Widget *onMouseDown(Vec pos, int button);
  56. virtual Widget *onMouseUp(Vec pos, int button);
  57. virtual Widget *onMouseMove(Vec pos, Vec mouseRel);
  58. /** Called when this widget begins responding to `onMouseMove` events */
  59. virtual void onMouseEnter() {}
  60. /** Called when another widget begins responding to `onMouseMove` events */
  61. virtual void onMouseLeave() {}
  62. virtual Widget *onScroll(Vec pos, Vec scrollRel);
  63. /** Called when a widget responds to `onMouseDown` for a left button press */
  64. virtual void onDragStart() {}
  65. /** Called when the left button is released and this widget is being dragged */
  66. virtual void onDragEnd() {}
  67. /** Called when a widget responds to `onMouseMove` and is being dragged */
  68. virtual void onDragMove(Vec mouseRel) {}
  69. /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
  70. virtual void onDragDrop(Widget *origin) {}
  71. virtual void onAction() {}
  72. virtual void onChange() {}
  73. };
  74. /** Widget that does not respond to events */
  75. struct TransparentWidget : virtual Widget {
  76. Widget *onMouseDown(Vec pos, int button) {return NULL;}
  77. Widget *onMouseUp(Vec pos, int button) {return NULL;}
  78. Widget *onMouseMove(Vec pos, Vec mouseRel) {return NULL;}
  79. Widget *onScroll(Vec pos, Vec scrollRel) {return NULL;}
  80. };
  81. /** Widget that itself responds to mouse events */
  82. struct OpaqueWidget : virtual Widget {
  83. Widget *onMouseDown(Vec pos, int button) {
  84. Widget *w = Widget::onMouseDown(pos, button);
  85. if (w) return w;
  86. onMouseDown(button);
  87. return this;
  88. }
  89. Widget *onMouseUp(Vec pos, int button) {
  90. Widget *w = Widget::onMouseUp(pos, button);
  91. if (w) return w;
  92. onMouseUp(button);
  93. return this;
  94. }
  95. Widget *onMouseMove(Vec pos, Vec mouseRel) {
  96. Widget *w = Widget::onMouseMove(pos, mouseRel);
  97. if (w) return w;
  98. onMouseMove(mouseRel);
  99. return this;
  100. }
  101. /** "High level" events called by the above lower level events.
  102. Use these if you don't care about the clicked position.
  103. */
  104. virtual void onMouseDown(int button) {}
  105. virtual void onMouseUp(int button) {}
  106. virtual void onMouseMove(Vec mouseRel) {}
  107. };
  108. struct SpriteWidget : virtual Widget {
  109. Vec spriteOffset;
  110. Vec spriteSize;
  111. std::string spriteFilename;
  112. int index = 0;
  113. void draw(NVGcontext *vg);
  114. };
  115. struct QuantityWidget : virtual Widget {
  116. float value = 0.0;
  117. float minValue = 0.0;
  118. float maxValue = 1.0;
  119. float defaultValue = 0.0;
  120. std::string label;
  121. /** Include a space character if you want a space after the number, e.g. " Hz" */
  122. std::string unit;
  123. /** The digit place to round for displaying values.
  124. A precision of -2 will display as "1.00" for example.
  125. */
  126. int precision = -2;
  127. QuantityWidget();
  128. void setValue(float value);
  129. void setLimits(float minValue, float maxValue);
  130. void setDefaultValue(float defaultValue);
  131. /** Generates the display value */
  132. std::string getText();
  133. };
  134. ////////////////////
  135. // gui elements
  136. ////////////////////
  137. struct Label : Widget {
  138. std::string text;
  139. Label() {
  140. box.size.y = BND_WIDGET_HEIGHT;
  141. }
  142. void draw(NVGcontext *vg);
  143. };
  144. // Deletes itself from parent when clicked
  145. struct MenuOverlay : OpaqueWidget {
  146. void step();
  147. Widget *onScroll(Vec pos, Vec scrollRel) {
  148. return this;
  149. }
  150. void onDragDrop(Widget *origin);
  151. };
  152. struct Menu : OpaqueWidget {
  153. Menu() {
  154. box.size = Vec(0, 0);
  155. }
  156. // Resizes menu and calls addChild()
  157. void pushChild(Widget *child);
  158. void draw(NVGcontext *vg);
  159. };
  160. struct MenuEntry : OpaqueWidget {
  161. std::string text;
  162. MenuEntry() {
  163. box.size = Vec(0, BND_WIDGET_HEIGHT);
  164. }
  165. float computeMinWidth(NVGcontext *vg);
  166. };
  167. struct MenuLabel : MenuEntry {
  168. void draw(NVGcontext *vg);
  169. };
  170. struct MenuItem : MenuEntry {
  171. BNDwidgetState state = BND_DEFAULT;
  172. void draw(NVGcontext *vg);
  173. void onMouseEnter();
  174. void onMouseLeave() ;
  175. void onDragDrop(Widget *origin);
  176. };
  177. struct Button : OpaqueWidget {
  178. std::string text;
  179. BNDwidgetState state = BND_DEFAULT;
  180. Button() {
  181. box.size.y = BND_WIDGET_HEIGHT;
  182. }
  183. void draw(NVGcontext *vg);
  184. void onMouseEnter();
  185. void onMouseLeave();
  186. void onDragStart();
  187. void onDragEnd();
  188. void onDragDrop(Widget *origin);
  189. };
  190. struct ChoiceButton : Button {
  191. void draw(NVGcontext *vg);
  192. };
  193. struct Slider : OpaqueWidget, QuantityWidget {
  194. BNDwidgetState state = BND_DEFAULT;
  195. Slider() {
  196. box.size.y = BND_WIDGET_HEIGHT;
  197. }
  198. void draw(NVGcontext *vg);
  199. void onDragStart();
  200. void onDragMove(Vec mouseRel);
  201. void onDragEnd();
  202. };
  203. struct ScrollBar : OpaqueWidget {
  204. enum { VERTICAL, HORIZONTAL } orientation;
  205. float containerOffset = 0.0;
  206. float containerSize = 0.0;
  207. BNDwidgetState state = BND_DEFAULT;
  208. ScrollBar() {
  209. box.size = Vec(BND_SCROLLBAR_WIDTH, BND_SCROLLBAR_HEIGHT);
  210. }
  211. void draw(NVGcontext *vg);
  212. void move(float delta);
  213. void onDragStart();
  214. void onDragMove(Vec mouseRel);
  215. void onDragEnd();
  216. };
  217. // Handles a container with scrollbars
  218. struct ScrollWidget : OpaqueWidget {
  219. Widget *container;
  220. ScrollBar *hScrollBar;
  221. ScrollBar *vScrollBar;
  222. ScrollWidget();
  223. void step();
  224. void draw(NVGcontext *vg);
  225. Widget *onScroll(Vec pos, Vec scrollRel);
  226. };
  227. struct Tooltip : Widget {
  228. void step();
  229. void draw(NVGcontext *vg);
  230. };
  231. ////////////////////
  232. // module
  233. ////////////////////
  234. // A 1U module should be 15x380. Thus the width of a module should be a factor of 15.
  235. struct Model;
  236. struct ModuleWidget : OpaqueWidget {
  237. Model *model = NULL;
  238. // Eventually this should be replaced with a `moduleId` which will be used for inter-process communication between the gui world and the audio world.
  239. Module *module = NULL;
  240. // int moduleId;
  241. std::vector<InputPort*> inputs;
  242. std::vector<OutputPort*> outputs;
  243. std::vector<ParamWidget*> params;
  244. ModuleWidget(Module *module);
  245. ~ModuleWidget();
  246. // Convenience functions for adding special widgets (calls addChild())
  247. void addInput(InputPort *input);
  248. void addOutput(OutputPort *output);
  249. void addParam(ParamWidget *param);
  250. json_t *toJson();
  251. void fromJson(json_t *root);
  252. void disconnectPorts();
  253. void resetParams();
  254. void cloneParams(ModuleWidget *source);
  255. void draw(NVGcontext *vg);
  256. bool requested = false;
  257. Vec requestedPos;
  258. Vec dragPos;
  259. void onDragStart();
  260. void onDragMove(Vec mouseRel);
  261. void onDragEnd();
  262. void onMouseDown(int button);
  263. };
  264. struct WireWidget : OpaqueWidget {
  265. OutputPort *outputPort = NULL;
  266. InputPort *inputPort = NULL;
  267. Wire *wire = NULL;
  268. NVGcolor color;
  269. WireWidget();
  270. ~WireWidget();
  271. void updateWire();
  272. void draw(NVGcontext *vg);
  273. void drawOutputPlug(NVGcontext *vg);
  274. void drawInputPlug(NVGcontext *vg);
  275. };
  276. struct RackWidget : OpaqueWidget {
  277. // Only put ModuleWidgets in here
  278. Widget *moduleContainer;
  279. // Only put WireWidgets in here
  280. Widget *wireContainer;
  281. WireWidget *activeWire = NULL;
  282. RackWidget();
  283. ~RackWidget();
  284. void clear();
  285. void savePatch(std::string filename);
  286. void loadPatch(std::string filename);
  287. json_t *toJson();
  288. void fromJson(json_t *root);
  289. void repositionModule(ModuleWidget *module);
  290. void step();
  291. void draw(NVGcontext *vg);
  292. void onMouseDown(int button);
  293. };
  294. struct ModulePanel : TransparentWidget {
  295. NVGcolor backgroundColor;
  296. NVGcolor highlightColor;
  297. std::string imageFilename;
  298. void draw(NVGcontext *vg);
  299. };
  300. ////////////////////
  301. // params
  302. ////////////////////
  303. struct Light : TransparentWidget, SpriteWidget {
  304. NVGcolor color;
  305. void draw(NVGcontext *vg);
  306. };
  307. // If you don't add these to your ModuleWidget, it will fall out of the RackWidget
  308. struct Screw : TransparentWidget, SpriteWidget {
  309. Screw();
  310. };
  311. struct ParamWidget : OpaqueWidget, QuantityWidget {
  312. Module *module = NULL;
  313. int paramId;
  314. json_t *toJson();
  315. void fromJson(json_t *root);
  316. void onMouseDown(int button);
  317. void onChange();
  318. };
  319. struct Knob : ParamWidget, SpriteWidget {
  320. int minIndex, maxIndex, spriteCount;
  321. void step();
  322. void onDragStart();
  323. void onDragMove(Vec mouseRel);
  324. void onDragEnd();
  325. };
  326. struct Switch : ParamWidget, SpriteWidget {
  327. };
  328. struct ToggleSwitch : virtual Switch {
  329. void onDragStart() {
  330. index = 1;
  331. }
  332. void onDragEnd() {
  333. index = 0;
  334. }
  335. void onDragDrop(Widget *origin) {
  336. if (origin != this)
  337. return;
  338. // Cycle through modes
  339. // e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3.
  340. float v = value + 1.0;
  341. setValue(v > maxValue ? minValue : v);
  342. }
  343. };
  344. struct MomentarySwitch : virtual Switch {
  345. void onDragStart() {
  346. setValue(maxValue);
  347. index = 1;
  348. }
  349. void onDragEnd() {
  350. setValue(minValue);
  351. index = 0;
  352. }
  353. };
  354. ////////////////////
  355. // ports
  356. ////////////////////
  357. struct Port : OpaqueWidget, SpriteWidget {
  358. Module *module = NULL;
  359. WireWidget *connectedWire = NULL;
  360. Port();
  361. ~Port();
  362. void disconnect();
  363. int type;
  364. void drawGlow(NVGcontext *vg);
  365. void onMouseDown(int button);
  366. void onDragEnd();
  367. };
  368. struct InputPort : Port {
  369. int inputId;
  370. void draw(NVGcontext *vg);
  371. void onDragStart();
  372. void onDragDrop(Widget *origin);
  373. };
  374. struct OutputPort : Port {
  375. int outputId;
  376. void draw(NVGcontext *vg);
  377. void onDragStart();
  378. void onDragDrop(Widget *origin);
  379. };
  380. ////////////////////
  381. // scene
  382. ////////////////////
  383. struct Toolbar : OpaqueWidget {
  384. Slider *wireOpacitySlider;
  385. Slider *wireTensionSlider;
  386. Toolbar();
  387. void draw(NVGcontext *vg);
  388. };
  389. struct Scene : OpaqueWidget {
  390. Toolbar *toolbar;
  391. ScrollWidget *scrollWidget;
  392. Widget *overlay = NULL;
  393. Scene();
  394. void setOverlay(Widget *w);
  395. void step();
  396. };
  397. } // namespace rack