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.

464 lines
12KB

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