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.

467 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 "../lib/nanovg/src/nanovg.h"
  9. #include "../lib/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 a widget responds to `onMouseMove` and is being dragged */
  66. virtual void onDragMove(Vec mouseRel) {}
  67. /** Called when a widget responds to `onMouseUp` for a left button release and a widget is being dragged */
  68. virtual void onDragDrop(Widget *origin) {}
  69. /** Called when the left button is released and this widget is being dragged */
  70. virtual void onDragEnd() {}
  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. void draw(NVGcontext *vg);
  140. };
  141. // Deletes itself from parent when clicked
  142. struct MenuOverlay : OpaqueWidget {
  143. void step();
  144. Widget *onScroll(Vec pos, Vec scrollRel) {
  145. return this;
  146. }
  147. void onDragDrop(Widget *origin);
  148. };
  149. struct Menu : OpaqueWidget {
  150. Menu() {
  151. box.size = Vec(0, 0);
  152. }
  153. // Resizes menu and calls addChild()
  154. void pushChild(Widget *child);
  155. void draw(NVGcontext *vg);
  156. };
  157. struct MenuEntry : OpaqueWidget {
  158. std::string text;
  159. MenuEntry() {
  160. box.size = Vec(0, BND_WIDGET_HEIGHT);
  161. }
  162. float computeMinWidth(NVGcontext *vg);
  163. };
  164. struct MenuLabel : MenuEntry {
  165. void draw(NVGcontext *vg);
  166. };
  167. struct MenuItem : MenuEntry {
  168. BNDwidgetState state = BND_DEFAULT;
  169. void draw(NVGcontext *vg);
  170. void onMouseEnter();
  171. void onMouseLeave() ;
  172. void onDragDrop(Widget *origin);
  173. };
  174. struct Button : OpaqueWidget {
  175. std::string text;
  176. BNDwidgetState state = BND_DEFAULT;
  177. Button();
  178. void draw(NVGcontext *vg);
  179. void onMouseEnter();
  180. void onMouseLeave() ;
  181. void onDragDrop(Widget *origin);
  182. };
  183. struct ChoiceButton : Button {
  184. void draw(NVGcontext *vg);
  185. };
  186. struct Slider : OpaqueWidget, QuantityWidget {
  187. BNDwidgetState state = BND_DEFAULT;
  188. Slider();
  189. void draw(NVGcontext *vg);
  190. void onDragStart();
  191. void onDragMove(Vec mouseRel);
  192. void onDragEnd();
  193. };
  194. struct ScrollBar : OpaqueWidget {
  195. enum { VERTICAL, HORIZONTAL } orientation;
  196. float containerOffset = 0.0;
  197. float containerSize = 0.0;
  198. BNDwidgetState state = BND_DEFAULT;
  199. ScrollBar();
  200. void draw(NVGcontext *vg);
  201. void move(float delta);
  202. void onDragStart();
  203. void onDragMove(Vec mouseRel);
  204. void onDragEnd();
  205. };
  206. // Handles a container with scrollbars
  207. struct ScrollWidget : OpaqueWidget {
  208. Widget *container;
  209. ScrollBar *hScrollBar;
  210. ScrollBar *vScrollBar;
  211. ScrollWidget();
  212. void step();
  213. void draw(NVGcontext *vg);
  214. Widget *onScroll(Vec pos, Vec scrollRel);
  215. };
  216. struct Tooltip : Widget {
  217. void step();
  218. void draw(NVGcontext *vg);
  219. };
  220. ////////////////////
  221. // module
  222. ////////////////////
  223. // A 1U module should be 15x380. Thus the width of a module should be a factor of 15.
  224. struct Model;
  225. struct ModuleWidget : OpaqueWidget {
  226. Model *model = NULL;
  227. // Eventually this should be replaced with a `moduleId` which will be used for inter-process communication between the gui world and the audio world.
  228. Module *module = NULL;
  229. // int moduleId;
  230. std::vector<InputPort*> inputs;
  231. std::vector<OutputPort*> outputs;
  232. std::vector<ParamWidget*> params;
  233. ModuleWidget(Module *module);
  234. ~ModuleWidget();
  235. // Convenience functions for adding special widgets (calls addChild())
  236. void addInput(InputPort *input);
  237. void addOutput(OutputPort *output);
  238. void addParam(ParamWidget *param);
  239. json_t *toJson();
  240. void fromJson(json_t *root);
  241. void disconnectPorts();
  242. void resetParams();
  243. void cloneParams(ModuleWidget *source);
  244. void draw(NVGcontext *vg);
  245. bool requested = false;
  246. Vec requestedPos;
  247. Vec dragPos;
  248. void onDragStart();
  249. void onDragMove(Vec mouseRel);
  250. void onDragEnd();
  251. void onMouseDown(int button);
  252. };
  253. struct WireWidget : OpaqueWidget {
  254. OutputPort *outputPort = NULL;
  255. InputPort *inputPort = NULL;
  256. Wire *wire = NULL;
  257. NVGcolor color;
  258. WireWidget();
  259. ~WireWidget();
  260. void updateWire();
  261. void draw(NVGcontext *vg);
  262. void drawOutputPlug(NVGcontext *vg);
  263. void drawInputPlug(NVGcontext *vg);
  264. };
  265. struct RackWidget : OpaqueWidget {
  266. // Only put ModuleWidgets in here
  267. Widget *moduleContainer;
  268. // Only put WireWidgets in here
  269. Widget *wireContainer;
  270. WireWidget *activeWire = NULL;
  271. RackWidget();
  272. ~RackWidget();
  273. void clear();
  274. void savePatch(std::string filename);
  275. void loadPatch(std::string filename);
  276. json_t *toJson();
  277. void fromJson(json_t *root);
  278. int frame = 0;
  279. void repositionModule(ModuleWidget *module);
  280. void step();
  281. void draw(NVGcontext *vg);
  282. void onMouseDown(int button);
  283. };
  284. struct ModulePanel : TransparentWidget {
  285. std::string imageFilename;
  286. NVGcolor backgroundColor;
  287. void draw(NVGcontext *vg);
  288. };
  289. ////////////////////
  290. // params
  291. ////////////////////
  292. struct Light : TransparentWidget, SpriteWidget {
  293. NVGcolor color;
  294. void draw(NVGcontext *vg);
  295. };
  296. // If you don't add these to your ModuleWidget, it will fall out of the RackWidget
  297. struct Screw : TransparentWidget, SpriteWidget {
  298. Screw();
  299. };
  300. struct ParamWidget : OpaqueWidget, QuantityWidget {
  301. Module *module = NULL;
  302. int paramId;
  303. json_t *toJson();
  304. void fromJson(json_t *root);
  305. void onMouseDown(int button);
  306. void onChange();
  307. };
  308. struct Knob : ParamWidget, SpriteWidget {
  309. int minIndex, maxIndex, spriteCount;
  310. void step();
  311. void onDragStart();
  312. void onDragMove(Vec mouseRel);
  313. void onDragEnd();
  314. };
  315. struct Switch : ParamWidget, SpriteWidget {
  316. };
  317. struct ToggleSwitch : virtual Switch {
  318. void onDragStart() {
  319. index = 1;
  320. }
  321. void onDragEnd() {
  322. index = 0;
  323. }
  324. void onDragDrop(Widget *origin) {
  325. if (origin != this)
  326. return;
  327. // Cycle through modes
  328. // e.g. a range of [0.0, 3.0] would have modes 0, 1, 2, and 3.
  329. float v = value + 1.0;
  330. setValue(v > maxValue ? minValue : v);
  331. }
  332. };
  333. struct MomentarySwitch : virtual Switch {
  334. void onDragStart() {
  335. setValue(maxValue);
  336. index = 1;
  337. }
  338. void onDragEnd() {
  339. setValue(minValue);
  340. index = 0;
  341. }
  342. };
  343. ////////////////////
  344. // ports
  345. ////////////////////
  346. struct Port : OpaqueWidget, SpriteWidget {
  347. Module *module = NULL;
  348. WireWidget *connectedWire = NULL;
  349. Port();
  350. ~Port();
  351. void disconnect();
  352. int type;
  353. void drawGlow(NVGcontext *vg);
  354. void onMouseDown(int button);
  355. void onDragEnd();
  356. };
  357. struct InputPort : Port {
  358. int inputId;
  359. void draw(NVGcontext *vg);
  360. void onDragStart();
  361. void onDragDrop(Widget *origin);
  362. };
  363. struct OutputPort : Port {
  364. int outputId;
  365. void draw(NVGcontext *vg);
  366. void onDragStart();
  367. void onDragDrop(Widget *origin);
  368. };
  369. ////////////////////
  370. // scene
  371. ////////////////////
  372. struct Toolbar : OpaqueWidget {
  373. Slider *wireOpacitySlider;
  374. Slider *wireTensionSlider;
  375. Toolbar();
  376. void draw(NVGcontext *vg);
  377. };
  378. struct Scene : OpaqueWidget {
  379. Toolbar *toolbar;
  380. ScrollWidget *scrollWidget;
  381. Widget *overlay = NULL;
  382. Scene();
  383. void setOverlay(Widget *w);
  384. void step();
  385. };
  386. } // namespace rack