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.

468 lines
10KB

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