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.

463 lines
12KB

  1. #pragma once
  2. #include <vector>
  3. #include <jansson.h>
  4. #include "widgets.hpp"
  5. #include "ui.hpp"
  6. static const float SVG_DPI = 75.0;
  7. static const float MM_PER_IN = 25.4;
  8. namespace rack {
  9. inline float in2px(float inches) {
  10. return inches * SVG_DPI;
  11. }
  12. inline math::Vec in2px(math::Vec inches) {
  13. return inches.mult(SVG_DPI);
  14. }
  15. inline float mm2px(float millimeters) {
  16. return millimeters * (SVG_DPI / MM_PER_IN);
  17. }
  18. inline math::Vec mm2px(math::Vec millimeters) {
  19. return millimeters.mult(SVG_DPI / MM_PER_IN);
  20. }
  21. struct Model;
  22. struct Module;
  23. struct Wire;
  24. struct RackWidget;
  25. struct ParamWidget;
  26. struct Port;
  27. struct SVGPanel;
  28. ////////////////////
  29. // module
  30. ////////////////////
  31. // A 1HPx3U module should be 15x380 pixels. Thus the width of a module should be a factor of 15.
  32. static const float RACK_GRID_WIDTH = 15;
  33. static const float RACK_GRID_HEIGHT = 380;
  34. static const math::Vec RACK_GRID_SIZE = math::Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
  35. static const std::string PRESET_FILTERS = "VCV Rack module preset (.vcvm):vcvm";
  36. static const std::string PATCH_FILTERS = "VCV Rack patch (.vcv):vcv";
  37. } // namespace rack
  38. #include "app/ModuleWidget.hpp"
  39. namespace rack {
  40. struct WireWidget : OpaqueWidget {
  41. Port *outputPort = NULL;
  42. Port *inputPort = NULL;
  43. Port *hoveredOutputPort = NULL;
  44. Port *hoveredInputPort = NULL;
  45. Wire *wire = NULL;
  46. NVGcolor color;
  47. WireWidget();
  48. ~WireWidget();
  49. /** Synchronizes the plugged state of the widget to the owned wire */
  50. void updateWire();
  51. math::Vec getOutputPos();
  52. math::Vec getInputPos();
  53. json_t *toJson();
  54. void fromJson(json_t *rootJ);
  55. void draw(NVGcontext *vg) override;
  56. void drawPlugs(NVGcontext *vg);
  57. };
  58. struct WireContainer : TransparentWidget {
  59. WireWidget *activeWire = NULL;
  60. /** Takes ownership of `w` and adds it as a child if it isn't already */
  61. void setActiveWire(WireWidget *w);
  62. /** "Drops" the wire onto the port, making an engine connection if successful */
  63. void commitActiveWire();
  64. void removeTopWire(Port *port);
  65. void removeAllWires(Port *port);
  66. /** Returns the most recently added wire connected to the given Port, i.e. the top of the stack */
  67. WireWidget *getTopWire(Port *port);
  68. void draw(NVGcontext *vg) override;
  69. };
  70. struct RackWidget : OpaqueWidget {
  71. FramebufferWidget *rails;
  72. // Only put ModuleWidgets in here
  73. Widget *moduleContainer;
  74. // Only put WireWidgets in here
  75. WireContainer *wireContainer;
  76. std::string lastPath;
  77. math::Vec lastMousePos;
  78. bool lockModules = false;
  79. RackWidget();
  80. ~RackWidget();
  81. /** Completely clear the rack's modules and wires */
  82. void clear();
  83. /** Clears the rack and loads the template patch */
  84. void reset();
  85. void loadDialog();
  86. void saveDialog();
  87. void saveAsDialog();
  88. /** If `lastPath` is defined, ask the user to reload it */
  89. void revert();
  90. /** Disconnects all wires */
  91. void disconnect();
  92. void save(std::string filename);
  93. void load(std::string filename);
  94. json_t *toJson();
  95. void fromJson(json_t *rootJ);
  96. /** Creates a module and adds it to the rack */
  97. ModuleWidget *moduleFromJson(json_t *moduleJ);
  98. void pastePresetClipboard();
  99. void addModule(ModuleWidget *m);
  100. /** Removes the module and transfers ownership to the caller */
  101. void deleteModule(ModuleWidget *m);
  102. void cloneModule(ModuleWidget *m);
  103. /** Sets a module's box if non-colliding. Returns true if set */
  104. bool requestModuleBox(ModuleWidget *m, math::Rect box);
  105. /** Moves a module to the closest non-colliding position */
  106. bool requestModuleBoxNearest(ModuleWidget *m, math::Rect box);
  107. void step() override;
  108. void draw(NVGcontext *vg) override;
  109. void on(event::Hover &e) override;
  110. void on(event::Button &e) override;
  111. void on(event::Zoom &e) override;
  112. };
  113. struct RackRail : TransparentWidget {
  114. void draw(NVGcontext *vg) override;
  115. };
  116. ////////////////////
  117. // ParamWidgets and other components
  118. ////////////////////
  119. /** A Widget that exists on a Panel and interacts with a Module */
  120. struct Component : OpaqueWidget {
  121. Module *module = NULL;
  122. };
  123. struct CircularShadow : TransparentWidget {
  124. float blurRadius;
  125. float opacity;
  126. CircularShadow();
  127. void draw(NVGcontext *vg) override;
  128. };
  129. /** A Component which has control over a Param (defined in engine.hpp) */
  130. struct ParamWidget : Component, QuantityWidget {
  131. int paramId;
  132. /** Used to momentarily disable value randomization
  133. To permanently disable or change randomization behavior, override the randomize() method instead of changing this.
  134. */
  135. bool randomizable = true;
  136. /** Apply per-sample smoothing in the engine */
  137. bool smooth = false;
  138. json_t *toJson();
  139. void fromJson(json_t *rootJ);
  140. virtual void reset();
  141. virtual void randomize();
  142. void on(event::Button &e) override;
  143. void on(event::Change &e) override;
  144. };
  145. /** Implements vertical dragging behavior for ParamWidgets */
  146. struct Knob : ParamWidget {
  147. /** Snap to nearest integer while dragging */
  148. bool snap = false;
  149. /** Multiplier for mouse movement to adjust knob value */
  150. float speed = 1.0;
  151. float dragValue;
  152. Knob();
  153. void on(event::DragStart &e) override;
  154. void on(event::DragMove &e) override;
  155. void on(event::DragEnd &e) override;
  156. };
  157. /** A knob which rotates an SVG and caches it in a framebuffer */
  158. struct SVGKnob : Knob, FramebufferWidget {
  159. TransformWidget *tw;
  160. SVGWidget *sw;
  161. CircularShadow *shadow;
  162. /** Angles in radians */
  163. float minAngle, maxAngle;
  164. SVGKnob();
  165. void setSVG(std::shared_ptr<SVG> svg);
  166. void step() override;
  167. void on(event::Change &e) override;
  168. };
  169. /** Behaves like a knob but linearly moves an SVGWidget between two points.
  170. Can be used for horizontal or vertical linear faders.
  171. */
  172. struct SVGSlider : Knob, FramebufferWidget {
  173. SVGWidget *background;
  174. SVGWidget *handle;
  175. /** Intermediate positions will be interpolated between these positions */
  176. math::Vec minHandlePos, maxHandlePos;
  177. SVGSlider();
  178. void setSVGs(std::shared_ptr<SVG> backgroundSVG, std::shared_ptr<SVG> handleSVG);
  179. void step() override;
  180. void on(event::Change &e) override;
  181. };
  182. /** A ParamWidget with multiple frames corresponding to its value */
  183. struct SVGSwitch : virtual ParamWidget, FramebufferWidget {
  184. std::vector<std::shared_ptr<SVG>> frames;
  185. SVGWidget *sw;
  186. SVGSwitch();
  187. /** Adds an SVG file to represent the next switch position */
  188. void addFrame(std::shared_ptr<SVG> svg);
  189. void on(event::Change &e) override;
  190. };
  191. /** A switch that cycles through each mechanical position */
  192. struct ToggleSwitch : virtual ParamWidget {
  193. void on(event::DragStart &e) override;
  194. };
  195. /** A switch that is turned on when held and turned off when released.
  196. Consider using SVGButton if the switch simply changes the state of your Module when clicked.
  197. */
  198. struct MomentarySwitch : virtual ParamWidget {
  199. /** Don't randomize state */
  200. void randomize() override {}
  201. void on(event::DragStart &e) override;
  202. void on(event::DragEnd &e) override;
  203. };
  204. /** A Component with a default (up) and active (down) state when clicked.
  205. Does not modify a Param, simply calls onAction() of a subclass.
  206. */
  207. struct SVGButton : Component, FramebufferWidget {
  208. Module *module = NULL;
  209. std::shared_ptr<SVG> defaultSVG;
  210. std::shared_ptr<SVG> activeSVG;
  211. SVGWidget *sw;
  212. SVGButton();
  213. /** If `activeSVG` is NULL, `defaultSVG` is used as the active state instead. */
  214. void setSVGs(std::shared_ptr<SVG> defaultSVG, std::shared_ptr<SVG> activeSVG);
  215. void on(event::DragStart &e) override;
  216. void on(event::DragEnd &e) override;
  217. };
  218. ////////////////////
  219. // IO widgets
  220. ////////////////////
  221. struct LedDisplay : virtual EventWidget {
  222. void draw(NVGcontext *vg) override;
  223. };
  224. struct LedDisplaySeparator : TransparentWidget {
  225. LedDisplaySeparator();
  226. void draw(NVGcontext *vg) override;
  227. };
  228. struct LedDisplayChoice : TransparentWidget {
  229. std::string text;
  230. std::shared_ptr<Font> font;
  231. math::Vec textOffset;
  232. NVGcolor color;
  233. LedDisplayChoice();
  234. void draw(NVGcontext *vg) override;
  235. void on(event::Button &e) override;
  236. };
  237. struct LedDisplayTextField : TextField {
  238. std::shared_ptr<Font> font;
  239. math::Vec textOffset;
  240. NVGcolor color;
  241. LedDisplayTextField();
  242. void draw(NVGcontext *vg) override;
  243. int getTextPosition(math::Vec mousePos) override;
  244. };
  245. struct AudioIO;
  246. struct MidiIO;
  247. struct AudioWidget : LedDisplay {
  248. /** Not owned */
  249. AudioIO *audioIO = NULL;
  250. LedDisplayChoice *driverChoice;
  251. LedDisplaySeparator *driverSeparator;
  252. LedDisplayChoice *deviceChoice;
  253. LedDisplaySeparator *deviceSeparator;
  254. LedDisplayChoice *sampleRateChoice;
  255. LedDisplaySeparator *sampleRateSeparator;
  256. LedDisplayChoice *bufferSizeChoice;
  257. AudioWidget();
  258. void step() override;
  259. };
  260. struct MidiWidget : LedDisplay {
  261. /** Not owned */
  262. MidiIO *midiIO = NULL;
  263. LedDisplayChoice *driverChoice;
  264. LedDisplaySeparator *driverSeparator;
  265. LedDisplayChoice *deviceChoice;
  266. LedDisplaySeparator *deviceSeparator;
  267. LedDisplayChoice *channelChoice;
  268. MidiWidget();
  269. void step() override;
  270. };
  271. ////////////////////
  272. // lights
  273. ////////////////////
  274. struct LightWidget : TransparentWidget {
  275. NVGcolor bgColor = nvgRGBA(0, 0, 0, 0);
  276. NVGcolor color = nvgRGBA(0, 0, 0, 0);
  277. NVGcolor borderColor = nvgRGBA(0, 0, 0, 0);
  278. void draw(NVGcontext *vg) override;
  279. virtual void drawLight(NVGcontext *vg);
  280. virtual void drawHalo(NVGcontext *vg);
  281. };
  282. /** Mixes a list of colors based on a list of brightness values */
  283. struct MultiLightWidget : LightWidget {
  284. /** Colors of each value state */
  285. std::vector<NVGcolor> baseColors;
  286. void addBaseColor(NVGcolor baseColor);
  287. /** Sets the color to a linear combination of the baseColors with the given weights */
  288. void setValues(const std::vector<float> &values);
  289. };
  290. /** A MultiLightWidget that points to a module's Light or a range of lights
  291. Will access firstLightId, firstLightId + 1, etc. for each added color
  292. */
  293. struct ModuleLightWidget : MultiLightWidget {
  294. Module *module = NULL;
  295. int firstLightId;
  296. void step() override;
  297. };
  298. ////////////////////
  299. // ports
  300. ////////////////////
  301. struct Port : Component {
  302. enum PortType {
  303. INPUT,
  304. OUTPUT
  305. };
  306. PortType type = INPUT;
  307. int portId;
  308. MultiLightWidget *plugLight;
  309. Port();
  310. ~Port();
  311. void step() override;
  312. void draw(NVGcontext *vg) override;
  313. void on(event::Button &e) override;
  314. void on(event::DragStart &e) override;
  315. void on(event::DragEnd &e) override;
  316. void on(event::DragDrop &e) override;
  317. void on(event::DragEnter &e) override;
  318. void on(event::DragLeave &e) override;
  319. };
  320. struct SVGPort : Port, FramebufferWidget {
  321. SVGWidget *background;
  322. CircularShadow *shadow;
  323. SVGPort();
  324. void setSVG(std::shared_ptr<SVG> svg);
  325. void draw(NVGcontext *vg) override;
  326. };
  327. /** If you don't add these to your ModuleWidget, they will fall out of the rack... */
  328. struct SVGScrew : FramebufferWidget {
  329. SVGWidget *sw;
  330. SVGScrew();
  331. };
  332. ////////////////////
  333. // scene
  334. ////////////////////
  335. struct Toolbar : OpaqueWidget {
  336. Slider *wireOpacitySlider;
  337. Slider *wireTensionSlider;
  338. Slider *zoomSlider;
  339. RadioButton *cpuUsageButton;
  340. Toolbar();
  341. void draw(NVGcontext *vg) override;
  342. };
  343. struct PluginManagerWidget : virtual EventWidget {
  344. Widget *loginWidget;
  345. Widget *manageWidget;
  346. Widget *downloadWidget;
  347. PluginManagerWidget();
  348. void step() override;
  349. };
  350. struct RackScrollWidget : ScrollWidget {
  351. void step() override;
  352. };
  353. struct RackScene : Scene {
  354. ScrollWidget *scrollWidget;
  355. ZoomWidget *zoomWidget;
  356. RackScene();
  357. void step() override;
  358. void draw(NVGcontext *vg) override;
  359. void on(event::HoverKey &e) override;
  360. void on(event::PathDrop &e) override;
  361. };
  362. ////////////////////
  363. // globals
  364. ////////////////////
  365. extern std::string gApplicationName;
  366. extern std::string gApplicationVersion;
  367. extern std::string gApiHost;
  368. extern std::string gLatestVersion;
  369. extern bool gCheckVersion;
  370. // Easy access to "singleton" widgets
  371. extern RackScene *gRackScene;
  372. extern RackWidget *gRackWidget;
  373. extern Toolbar *gToolbar;
  374. void appInit(bool devMode);
  375. void appDestroy();
  376. void appModuleBrowserCreate();
  377. json_t *appModuleBrowserToJson();
  378. void appModuleBrowserFromJson(json_t *rootJ);
  379. /** Deprecated. Will be removed in v1 */
  380. json_t *colorToJson(NVGcolor color);
  381. /** Deprecated. Will be removed in v1 */
  382. NVGcolor jsonToColor(json_t *colorJ);
  383. } // namespace rack