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.

1288 lines
31KB

  1. #pragma once
  2. #include <map>
  3. #include "rack.hpp"
  4. #include "asset.hpp"
  5. #include "widgets.hpp"
  6. #include "LRGestalt.hpp"
  7. #define LCD_FONT_DIG7 "res/digital-7.ttf"
  8. #define LCD_FONTSIZE 11
  9. #define LCD_LETTER_SPACING 0
  10. #define LCD_MARGIN_VERTICAL 1.73
  11. #define LCD_MARGIN_HORIZONTAL 1.07
  12. #define LCD_DEFAULT_COLOR_DARK nvgRGBAf(0.23, 0.6, 0.82, 1.0)
  13. #define LCD_DEFAULT_COLOR_LIGHT nvgRGBAf(0.23, 0.7, 1.0, 1.0)
  14. #define LCD_DEFAULT_COLOR_AGED nvgRGBAf(0.63, 0.1, 0.0, 1.0)
  15. #define LED_DEFAULT_COLOR_DARK nvgRGBAf(0.23, 0.5, 1.0, 1.0)
  16. #define LED_DEFAULT_COLOR_LIGHT nvgRGBAf(1.0, 0.32, 0.12, 1.0)
  17. #define LED_DEFAULT_COLOR_AGED nvgRGBAf(1.0, 1.0, 0.12, 1.0)
  18. /* show values of all knobs */
  19. #define DEBUG_VALUES false
  20. using namespace rack;
  21. using std::vector;
  22. using std::shared_ptr;
  23. using std::string;
  24. using std::map;
  25. #ifdef USE_VST2
  26. #define plugin "LindenbergResearch"
  27. #else
  28. extern Plugin *plugin;
  29. #endif // USE_VST2
  30. namespace lrt {
  31. /* Type definitions for common used data structures */
  32. typedef std::shared_ptr<rack::Font> TrueType;
  33. typedef std::vector<std::string> StringVector;
  34. /**
  35. * @brief Emulation of a LCD monochrome display
  36. */
  37. struct LRLCDWidget : FramebufferWidget, LRGestaltVariant, LRGestaltChangeAction {
  38. enum LCDType {
  39. NUMERIC,
  40. TEXT,
  41. LIST
  42. };
  43. TransformWidget *tw;
  44. SVGWidget *sw;
  45. TrueType ttfLCDDIG7;
  46. LCDType type;
  47. NVGcolor fg;
  48. bool active = true;
  49. float value = 0.0;
  50. unsigned char length = 0;
  51. string format, text;
  52. vector<string> items;
  53. float fontsize;
  54. string s1;
  55. string s2;
  56. /**
  57. * @brief Constructor
  58. */
  59. LRLCDWidget(unsigned char length, string format, LCDType type, float fontsize);
  60. void step() override;
  61. /**
  62. * @brief Draw LCD display
  63. * @param vg
  64. */
  65. void draw(NVGcontext *vg) override;
  66. inline void addItem(string name) {
  67. items.push_back(name);
  68. }
  69. void doResize(Vec v);
  70. void onGestaltChange(LREventGestaltChange &e) override;
  71. virtual void onMouseDown(EventMouseDown &e) override;
  72. };
  73. /**
  74. * @brief Indicator for control voltages on knobs
  75. */
  76. struct LRCVIndicator : TransparentWidget {
  77. static constexpr float OVERFLOW_THRESHOLD = 0.01f;
  78. /** flag to control drawing */
  79. bool active = false;
  80. bool lightMode = false;
  81. /** color of indicator */
  82. NVGcolor normalColor = nvgRGBA(0x00, 0x00, 0x00, 0xBB);
  83. NVGcolor overflowColor = nvgRGBA(0xBB, 0x00, 0x00, 0xBB);
  84. NVGcolor normalColorLight = nvgRGBA(0xDD, 0xDD, 0xDD, 0xBB);
  85. NVGcolor overflowColorLight = nvgRGBA(0xDD, 0x00, 0x00, 0xBB);
  86. /** radius from middle */
  87. float distance;
  88. /** normalized control voltage. must between [0..1] */
  89. float cv = 0.f;
  90. /** indicator distances */
  91. float d1 = 4.f;
  92. float d2 = 0.1f;
  93. /** draw angle */
  94. float angle;
  95. float angle2;
  96. /** middle of parent */
  97. Vec middle;
  98. /**
  99. * @brief Init indicator
  100. * @param distance Radius viewed from the middle
  101. * @param angle Angle of active knob area
  102. */
  103. LRCVIndicator(float distance, float angle);
  104. /**
  105. * @brief Manipulate the indicator symbol
  106. * @param d1 Height of the triangle
  107. * @param d2 Half of the base width
  108. */
  109. void setDistances(float d1, float d2);
  110. /**
  111. * @brief Draw routine for cv indicator
  112. * @param vg
  113. */
  114. void draw(NVGcontext *vg) override;
  115. };
  116. /**
  117. * @brief Standard LR Shadow
  118. */
  119. struct LRShadow : TransparentWidget {
  120. private:
  121. Rect box;
  122. float size = 0.65;
  123. float strength = 1.f;
  124. /** shadow shift */
  125. Vec shadowPos = Vec(3, 5);
  126. public:
  127. LRShadow();
  128. /**
  129. * @brief Set the new offset of the shadow gradient
  130. * @param x
  131. * @param y
  132. */
  133. void setShadowPosition(float x, float y) {
  134. shadowPos = Vec(x, y);
  135. }
  136. void setBox(const Rect &box);
  137. void setSize(float size);
  138. void setStrength(float strength);
  139. /**
  140. * @brief Draw shadow for circular knobs
  141. * @param vg NVGcontext
  142. * @param strength Alpha value of outside gradient
  143. * @param size Outer size
  144. * @param shift XY Offset shift from middle
  145. */
  146. void drawShadow(NVGcontext *vg, float strength, float size);
  147. void draw(NVGcontext *vg) override;
  148. };
  149. /**
  150. * @brief The base of all knobs used in LR panels, includes a indicator
  151. */
  152. struct LRKnob : SVGKnob, LRGestaltVariant, LRGestaltChangeAction {
  153. private:
  154. static constexpr float ANGLE = 0.83f;
  155. /** setup indicator with default values */
  156. LRCVIndicator *indicator;
  157. bool debug = DEBUG_VALUES;
  158. TrueType font;
  159. /** snap mode */
  160. bool snap = false;
  161. /** position to snap */
  162. float snapAt = 0.0f;
  163. /** snap sensitivity */
  164. float snapSens = 0.1;
  165. protected:
  166. /** shader */
  167. LRShadow *shader;
  168. public:
  169. LRKnob();
  170. /**
  171. * @brief Set the value of the indicator
  172. * @param value
  173. */
  174. void setIndicatorValue(float value) {
  175. indicator->cv = value;
  176. dirty = true;
  177. }
  178. /**
  179. * @brief Switch indicator on/off
  180. * @param active
  181. */
  182. void setIndicatorActive(bool active) {
  183. indicator->active = active;
  184. dirty = true;
  185. }
  186. /**
  187. * @brief Get indicator state
  188. * @return
  189. */
  190. bool isIndicatorActive() {
  191. return indicator->active;
  192. }
  193. /**
  194. * @brief Setup distance of indicator from middle
  195. * @param distance
  196. */
  197. void setIndicatorDistance(float distance) {
  198. indicator->distance = distance;
  199. dirty = true;
  200. }
  201. /**
  202. * @brief Setup distance of indicator from middle
  203. * @param distance
  204. */
  205. void setIndicatorShape(float d1, float d2) {
  206. indicator->setDistances(d1, d2);
  207. dirty = true;
  208. }
  209. /**
  210. * @brief Set new colors for the indicator (default red overflow)
  211. * @param normal Normal indicator color
  212. * @param overflow Optional overflow color
  213. */
  214. void setIndicatorColors(NVGcolor normal, NVGcolor overflow = nvgRGBA(0xBB, 0x00, 0x00, 0xBB)) {
  215. indicator->normalColor = normal;
  216. indicator->overflowColor = overflow;
  217. }
  218. /**
  219. * @brief Hook into setSVG() method to setup box dimensions correct for indicator
  220. * @param svg
  221. */
  222. void setSVG(shared_ptr<SVG> svg);
  223. /**
  224. * @brief Creates a new instance of a LRKnob child
  225. * @tparam TParamWidget Subclass of LRKnob
  226. * @param pos Position
  227. * @param module Module pointer
  228. * @param paramId Parameter ID
  229. * @param minValue Min
  230. * @param maxValue Max
  231. * @param defaultValue Default
  232. * @return Pointer to new subclass of LRKnob
  233. */
  234. template<class TParamWidget>
  235. static TParamWidget *create(Vec pos, Module *module, int paramId, float minValue, float maxValue, float
  236. defaultValue) {
  237. auto *param = new TParamWidget();
  238. param->box.pos = pos;
  239. param->module = module;
  240. param->paramId = paramId;
  241. param->setLimits(minValue, maxValue);
  242. param->setDefaultValue(defaultValue);
  243. return param;
  244. }
  245. /**
  246. * @brief Draw knob
  247. * @param vg
  248. */
  249. void draw(NVGcontext *vg) override;
  250. /**
  251. * @brief Setup knob snapping
  252. * @param position
  253. * @param sensitivity
  254. */
  255. void setSnap(float position, float sensitivity);
  256. /**
  257. * @brief Remove knob snaping
  258. */
  259. void unsetSnap();
  260. /**
  261. * @brief Snapping mode for knobs
  262. * @param e
  263. */
  264. void onChange(EventChange &e) override;
  265. void onGestaltChange(LREventGestaltChange &e) override;
  266. };
  267. /**
  268. * @brief Quantize position to odd numbers to simulate a toggle switch
  269. */
  270. struct LRToggleKnob : LRKnob {
  271. LRToggleKnob(float length = 0.5f) {
  272. //TODO: parametrize start and end angle
  273. minAngle = -0.666666f * (float) M_PI;
  274. maxAngle = length * (float) M_PI;
  275. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/ToggleKnob.svg")));
  276. addSVGVariant(LRGestalt::DARK, SVG::load(assetPlugin(plugin, "res/knobs/ToggleKnob.svg")));
  277. addSVGVariant(LRGestalt::LIGHT, SVG::load(assetPlugin(plugin, "res/knobs/AlternateToggleKnobLight.svg")));
  278. addSVGVariant(LRGestalt::AGED, SVG::load(assetPlugin(plugin, "res/knobs/AlternateToggleKnobLight.svg")));
  279. speed = 2.f;
  280. }
  281. void onChange(EventChange &e) override {
  282. value = round(value);
  283. SVGKnob::onChange(e);
  284. }
  285. void onGestaltChange(LREventGestaltChange &e) override {
  286. LRKnob::onGestaltChange(e);
  287. switch (*gestalt) {
  288. case LRGestalt::DARK:
  289. shader->setShadowPosition(3, 4);
  290. shader->setStrength(1.2f);
  291. shader->setSize(0.7f);
  292. break;
  293. case LRGestalt::LIGHT:
  294. shader->setShadowPosition(2, 3);
  295. shader->setStrength(0.5f);
  296. shader->setSize(0.6f);
  297. break;
  298. case LRGestalt::AGED:
  299. shader->setShadowPosition(2, 3);
  300. shader->setStrength(0.5f);
  301. shader->setSize(0.6f);
  302. break;
  303. default:
  304. break;
  305. }
  306. }
  307. };
  308. /**
  309. * @brief Quantize position to odd numbers to simulate a toggle switch
  310. */
  311. struct LRMiddleIncremental : LRKnob {
  312. LRMiddleIncremental(float length = 0.5f) {
  313. minAngle = -length * (float) M_PI;
  314. maxAngle = length * (float) M_PI;
  315. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/AlternateMiddleKnob.svg")));
  316. shader->setShadowPosition(3, 4);
  317. shader->setStrength(1.2f);
  318. shader->setSize(0.7f);
  319. speed = 3.f;
  320. }
  321. void onChange(EventChange &e) override {
  322. value = lround(value);
  323. //value = round(value);
  324. SVGKnob::onChange(e);
  325. }
  326. };
  327. /**
  328. * @brief LR Big Knob
  329. */
  330. struct LRBigKnob : LRKnob {
  331. LRBigKnob() {
  332. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/BigKnob.svg")));
  333. addSVGVariant(LRGestalt::DARK, SVG::load(assetPlugin(plugin, "res/knobs/BigKnob.svg")));
  334. addSVGVariant(LRGestalt::LIGHT, SVG::load(assetPlugin(plugin, "res/knobs/AlternateBigLight.svg")));
  335. addSVGVariant(LRGestalt::AGED, SVG::load(assetPlugin(plugin, "res/knobs/AlternateBigLight.svg")));
  336. }
  337. void onGestaltChange(LREventGestaltChange &e) override {
  338. LRKnob::onGestaltChange(e);
  339. switch (*gestalt) {
  340. case LRGestalt::DARK:
  341. setIndicatorDistance(15);
  342. setIndicatorShape(4.8, 0.12);
  343. shader->setShadowPosition(4, 5);
  344. shader->setStrength(0.8f);
  345. shader->setSize(.65f);
  346. break;
  347. case LRGestalt::LIGHT:
  348. setIndicatorDistance(17);
  349. setIndicatorShape(4.1, 0.08);
  350. shader->setShadowPosition(4, 5);
  351. shader->setStrength(0.5f);
  352. shader->setSize(0.6f);
  353. break;
  354. case LRGestalt::AGED:
  355. setIndicatorDistance(17);
  356. setIndicatorShape(4.1, 0.08);
  357. shader->setShadowPosition(4, 5);
  358. shader->setStrength(0.5f);
  359. shader->setSize(0.6f);
  360. break;
  361. default:
  362. break;
  363. }
  364. }
  365. };
  366. /**
  367. * @brief LR Middle Knob
  368. */
  369. struct LRMiddleKnob : LRKnob {
  370. LRMiddleKnob() {
  371. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/MiddleKnob.svg")));
  372. addSVGVariant(LRGestalt::DARK, SVG::load(assetPlugin(plugin, "res/knobs/MiddleKnob.svg")));
  373. addSVGVariant(LRGestalt::LIGHT, SVG::load(assetPlugin(plugin, "res/knobs/AlternateMiddleLight.svg")));
  374. addSVGVariant(LRGestalt::AGED, SVG::load(assetPlugin(plugin, "res/knobs/AlternateMiddleLight.svg")));
  375. }
  376. void onGestaltChange(LREventGestaltChange &e) override {
  377. LRKnob::onGestaltChange(e);
  378. switch (*gestalt) {
  379. case LRGestalt::DARK:
  380. setIndicatorDistance(13);
  381. setIndicatorShape(5, 0.13);
  382. shader->setShadowPosition(2, 3);
  383. shader->setStrength(0.8f);
  384. shader->setSize(.65f);
  385. break;
  386. case LRGestalt::LIGHT:
  387. setIndicatorDistance(11);
  388. setIndicatorShape(4.3, 0.11);
  389. shader->setShadowPosition(2, 3);
  390. shader->setStrength(0.5f);
  391. shader->setSize(0.6f);
  392. break;
  393. case LRGestalt::AGED:
  394. setIndicatorDistance(11);
  395. setIndicatorShape(4.3, 0.11);
  396. shader->setShadowPosition(2, 3);
  397. shader->setStrength(0.5f);
  398. shader->setSize(0.6f);
  399. break;
  400. default:
  401. break;
  402. }
  403. }
  404. };
  405. /**
  406. * @brief LR Small Knob
  407. */
  408. struct LRSmallKnob : LRKnob {
  409. LRSmallKnob() {
  410. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/SmallKnob.svg")));
  411. addSVGVariant(LRGestalt::DARK, SVG::load(assetPlugin(plugin, "res/knobs/SmallKnob.svg")));
  412. addSVGVariant(LRGestalt::LIGHT, SVG::load(assetPlugin(plugin, "res/knobs/AlternateSmallLight.svg")));
  413. addSVGVariant(LRGestalt::AGED, SVG::load(assetPlugin(plugin, "res/knobs/AlternateSmallLight.svg")));
  414. setSnap(0.0f, 0.02f);
  415. speed = 0.9f;
  416. }
  417. void onGestaltChange(LREventGestaltChange &e) override {
  418. LRKnob::onGestaltChange(e);
  419. switch (*gestalt) {
  420. case LRGestalt::DARK:
  421. setIndicatorDistance(13);
  422. setIndicatorShape(5, 0.13);
  423. shader->setShadowPosition(3, 3);
  424. shader->setStrength(1.f);
  425. shader->setSize(.65f);
  426. break;
  427. case LRGestalt::LIGHT:
  428. shader->setShadowPosition(3, 3);
  429. shader->setShadowPosition(2, 3);
  430. shader->setStrength(0.5f);
  431. shader->setSize(0.7f);
  432. break;
  433. case LRGestalt::AGED:
  434. shader->setShadowPosition(3, 3);
  435. shader->setShadowPosition(2, 3);
  436. shader->setStrength(0.5f);
  437. shader->setSize(0.7f);
  438. break;
  439. default:
  440. break;
  441. }
  442. }
  443. };
  444. /**
  445. * @brief LR Small Knob
  446. */
  447. struct LRSmallToggleKnob : LRKnob {
  448. LRSmallToggleKnob(float length = 0.73) {
  449. //TODO: parametrize start and end angle
  450. minAngle = -length * (float) M_PI;
  451. maxAngle = length * (float) M_PI;
  452. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/AlternateSmallToggleLight.svg")));
  453. addSVGVariant(LRGestalt::DARK, SVG::load(assetPlugin(plugin, "res/knobs/AlternateSmallToggleLight.svg")));
  454. addSVGVariant(LRGestalt::LIGHT, SVG::load(assetPlugin(plugin, "res/knobs/AlternateSmallToggleLight.svg")));
  455. addSVGVariant(LRGestalt::AGED, SVG::load(assetPlugin(plugin, "res/knobs/AlternateSmallToggleLight.svg")));
  456. speed = 3.0;
  457. }
  458. void onChange(EventChange &e) override {
  459. value = round(value);
  460. SVGKnob::onChange(e);
  461. }
  462. void onGestaltChange(LREventGestaltChange &e) override {
  463. LRKnob::onGestaltChange(e);
  464. switch (*gestalt) {
  465. case LRGestalt::DARK:
  466. setIndicatorDistance(13);
  467. setIndicatorShape(5, 0.13);
  468. shader->setShadowPosition(3, 3);
  469. shader->setStrength(1.f);
  470. shader->setSize(.65f);
  471. break;
  472. case LRGestalt::LIGHT:
  473. shader->setShadowPosition(3, 3);
  474. shader->setShadowPosition(2, 3);
  475. shader->setStrength(0.3f);
  476. shader->setSize(0.7f);
  477. break;
  478. case LRGestalt::AGED:
  479. shader->setShadowPosition(3, 3);
  480. shader->setShadowPosition(2, 3);
  481. shader->setStrength(0.5f);
  482. shader->setSize(0.7f);
  483. break;
  484. default:
  485. break;
  486. }
  487. }
  488. };
  489. /**
  490. * @brief LR Alternate Small Knob
  491. */
  492. struct LRAlternateSmallKnob : LRKnob {
  493. LRAlternateSmallKnob() {
  494. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/AlternateSmallKnob.svg")));
  495. shader->setShadowPosition(3, 3);
  496. setSnap(0.0f, 0.02f);
  497. speed = 0.9f;
  498. }
  499. };
  500. /**
  501. * @brief LR Middle Knob
  502. */
  503. struct LRAlternateMiddleKnob : LRKnob {
  504. LRAlternateMiddleKnob() {
  505. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/AlternateMiddleKnob.svg")));
  506. setIndicatorDistance(11);
  507. setIndicatorShape(5.0, 0.14);
  508. shader->setShadowPosition(4, 5);
  509. setSnap(0.0f, 0.12f);
  510. }
  511. };
  512. /**
  513. * @brief LR Big Knob
  514. */
  515. struct LRAlternateBigKnob : LRKnob {
  516. LRAlternateBigKnob() {
  517. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/AlternateBigKnob.svg")));
  518. setIndicatorDistance(15);
  519. setIndicatorShape(4.8, 0.12);
  520. shader->setShadowPosition(5, 6);
  521. }
  522. };
  523. /**
  524. * @brief LR Big Knob
  525. */
  526. struct LRAlternateBigLight : LRKnob {
  527. LRAlternateBigLight() {
  528. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/AlternateBigLight.svg")));
  529. setIndicatorDistance(17);
  530. setIndicatorShape(4.1, 0.08);
  531. shader->setShadowPosition(4, 5);
  532. shader->setStrength(0.5f);
  533. shader->setSize(0.6f);
  534. }
  535. };
  536. /**
  537. * @brief LR Big Knob
  538. */
  539. struct LRAlternateMiddleLight : LRKnob {
  540. LRAlternateMiddleLight() {
  541. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/AlternateMiddleLight.svg")));
  542. setIndicatorDistance(11);
  543. setIndicatorShape(4.3, 0.11);
  544. shader->setShadowPosition(2, 3);
  545. shader->setStrength(0.5f);
  546. shader->setSize(0.6f);
  547. }
  548. };
  549. /**
  550. * @brief LR Small Knob
  551. */
  552. struct LRAlternateSmallLight : LRKnob {
  553. LRAlternateSmallLight() {
  554. setSVG(SVG::load(assetPlugin(plugin, "res/knobs/AlternateSmallLight.svg")));
  555. shader->setShadowPosition(3, 3);
  556. setSnap(0.0f, 0.02f);
  557. shader->setShadowPosition(2, 3);
  558. shader->setStrength(0.5f);
  559. shader->setSize(0.7f);
  560. speed = 0.9f;
  561. }
  562. };
  563. /**
  564. * @brief Alternative IO Port
  565. */
  566. struct LRIOPort : SVGPort {
  567. private:
  568. LRShadow *shader;
  569. public:
  570. LRIOPort() {
  571. background->svg = SVG::load(assetPlugin(plugin, "res/elements/IOPortB.svg"));
  572. background->wrap();
  573. box.size = background->box.size;
  574. shader = new LRShadow();
  575. // addChild(shadow);
  576. /** inherit dimensions */
  577. shader->setBox(box);
  578. shader->setSize(0.50);
  579. shader->setShadowPosition(3, 2);
  580. }
  581. /**
  582. * @brief Hook into draw method
  583. * @param vg
  584. */
  585. void draw(NVGcontext *vg) override {
  586. shader->draw(vg);
  587. SVGPort::draw(vg);
  588. }
  589. };
  590. /**
  591. * @brief Alternative IO Port
  592. */
  593. struct LRIOPortBLight : SVGPort {
  594. private:
  595. LRShadow *shader;
  596. public:
  597. LRIOPortBLight() {
  598. background->svg = SVG::load(assetPlugin(plugin, "res/elements/IOPortBLight.svg"));
  599. background->wrap();
  600. box.size = background->box.size;
  601. shader = new LRShadow();
  602. // addChild(shadow);
  603. /** inherit dimensions */
  604. shader->setBox(box);
  605. shader->setSize(0.55);
  606. shader->setStrength(0.3);
  607. shader->setShadowPosition(1, 2);
  608. }
  609. /**
  610. * @brief Hook into draw method
  611. * @param vg
  612. */
  613. void draw(NVGcontext *vg) override {
  614. shader->draw(vg);
  615. SVGPort::draw(vg);
  616. }
  617. };
  618. /**
  619. * @brief Alternative IO Port
  620. */
  621. struct LRIOPortC : SVGPort {
  622. private:
  623. LRShadow *shader;
  624. public:
  625. LRIOPortC() {
  626. background->svg = SVG::load(assetPlugin(plugin, "res/elements/IOPortC.svg"));
  627. background->wrap();
  628. box.size = background->box.size;
  629. shader = new LRShadow();
  630. // addChild(shader);
  631. /** inherit dimensions */
  632. shader->setBox(box);
  633. shader->setSize(0.50);
  634. shader->setStrength(0.1);
  635. shader->setShadowPosition(3, 4);
  636. }
  637. /**
  638. * @brief Hook into draw method
  639. * @param vg
  640. */
  641. void draw(NVGcontext *vg) override {
  642. shader->draw(vg);
  643. SVGPort::draw(vg);
  644. }
  645. };
  646. /**
  647. * @brief Alternative IO Port
  648. */
  649. struct LRIOPortD : SVGPort, LRGestaltVariant, LRGestaltChangeAction { //TODO: rename after migration
  650. private:
  651. LRShadow *shader;
  652. public:
  653. LRIOPortD() {
  654. shader = new LRShadow();
  655. }
  656. void onGestaltChange(LREventGestaltChange &e) override {
  657. switch (*gestalt) {
  658. case LRGestalt::DARK:
  659. background->svg = getSVGVariant(DARK);
  660. background->wrap();
  661. box.size = background->box.size;
  662. shader->setBox(box);
  663. shader->setSize(0.57);
  664. shader->setStrength(0.3);
  665. shader->setShadowPosition(2, 3);
  666. break;
  667. case LRGestalt::LIGHT:
  668. background->svg = getSVGVariant(LIGHT);
  669. background->wrap();
  670. box.size = background->box.size;
  671. shader->setBox(box);
  672. shader->setSize(0.52);
  673. shader->setStrength(0.5);
  674. shader->setShadowPosition(1, 2);
  675. break;
  676. case LRGestalt::AGED:
  677. background->svg = getSVGVariant(AGED);
  678. background->wrap();
  679. box.size = background->box.size;
  680. shader->setBox(box);
  681. shader->setSize(0.52);
  682. shader->setStrength(0.5);
  683. shader->setShadowPosition(1, 2);
  684. break;
  685. default:
  686. break;
  687. }
  688. dirty = true;
  689. }
  690. /**
  691. * @brief Hook into draw method
  692. * @param vg
  693. */
  694. void draw(NVGcontext *vg) override {
  695. shader->draw(vg);
  696. SVGPort::draw(vg);
  697. }
  698. };
  699. /**
  700. * @brief Audio variant of IO port
  701. */
  702. struct LRIOPortAudio : LRIOPortD {
  703. LRIOPortAudio() : LRIOPortD() {
  704. addSVGVariant(DARK, SVG::load(assetPlugin(plugin, "res/elements/IOPortB.svg")));
  705. addSVGVariant(LIGHT, SVG::load(assetPlugin(plugin, "res/elements/IOPortBLight.svg")));
  706. addSVGVariant(AGED, SVG::load(assetPlugin(plugin, "res/elements/IOPortBLight.svg")));
  707. }
  708. };
  709. /**
  710. * @brief CV variant of IO port
  711. */
  712. struct LRIOPortCV : LRIOPortD {
  713. LRIOPortCV() : LRIOPortD() {
  714. addSVGVariant(DARK, SVG::load(assetPlugin(plugin, "res/elements/IOPortC.svg")));
  715. addSVGVariant(LIGHT, SVG::load(assetPlugin(plugin, "res/elements/IOPortCLight.svg")));
  716. addSVGVariant(AGED, SVG::load(assetPlugin(plugin, "res/elements/IOPortCLight.svg")));
  717. }
  718. };
  719. /**
  720. * @brief Alternative IO Port
  721. */
  722. struct LRIOPortCLight : SVGPort {
  723. private:
  724. LRShadow *shader;
  725. public:
  726. LRIOPortCLight() {
  727. background->svg = SVG::load(assetPlugin(plugin, "res/elements/IOPortCLight.svg"));
  728. background->wrap();
  729. box.size = background->box.size;
  730. shader = new LRShadow();
  731. // addChild(shader);
  732. /** inherit dimensions */
  733. shader->setBox(box);
  734. shader->setSize(0.55);
  735. shader->setStrength(0.3);
  736. shader->setShadowPosition(1, 2);
  737. }
  738. /**
  739. * @brief Hook into draw method
  740. * @param vg
  741. */
  742. void draw(NVGcontext *vg) override {
  743. shader->draw(vg);
  744. SVGPort::draw(vg);
  745. }
  746. };
  747. /**
  748. * @brief Alternative screw head A
  749. */
  750. struct ScrewDarkA : SVGScrew {
  751. ScrewDarkA() {
  752. sw->svg = SVG::load(assetPlugin(plugin, "res/elements/ScrewDark.svg"));
  753. sw->wrap();
  754. box.size = sw->box.size;
  755. }
  756. };
  757. /**
  758. * @brief Alternative screw head A
  759. */
  760. struct ScrewLight : SVGScrew, LRGestaltVariant, LRGestaltChangeAction {
  761. ScrewLight() {
  762. sw->svg = SVG::load(assetPlugin(plugin, "res/elements/ScrewLight.svg"));
  763. sw->wrap();
  764. box.size = sw->box.size;
  765. addSVGVariant(LRGestalt::DARK, SVG::load(assetPlugin(plugin, "res/elements/ScrewDarkC.svg")));
  766. addSVGVariant(LRGestalt::LIGHT, SVG::load(assetPlugin(plugin, "res/elements/ScrewDarkLightC.svg")));
  767. addSVGVariant(LRGestalt::AGED, SVG::load(assetPlugin(plugin, "res/elements/ScrewDarkLightC.svg")));
  768. }
  769. void onGestaltChange(LREventGestaltChange &e) override {
  770. LRGestaltChangeAction::onGestaltChange(e);
  771. sw->svg = getSVGVariant(*gestalt);
  772. dirty = true;
  773. }
  774. };
  775. /**
  776. * @brief Alternative screw head A
  777. */
  778. struct AlternateScrewLight : SVGScrew {
  779. AlternateScrewLight() {
  780. sw->svg = SVG::load(assetPlugin(plugin, "res/elements/AlternateScrewLight.svg"));
  781. sw->wrap();
  782. box.size = sw->box.size;
  783. }
  784. };
  785. /**
  786. * @brief Alternative screw head A
  787. */
  788. struct ScrewDarkB : SVGScrew {
  789. ScrewDarkB() {
  790. sw->svg = SVG::load(assetPlugin(plugin, "res/elements/ScrewDarkB.svg"));
  791. sw->wrap();
  792. box.size = sw->box.size;
  793. }
  794. };
  795. /**
  796. * @brief Custom switch based on original Rack files
  797. */
  798. struct LRSwitch : SVGSwitch, ToggleSwitch {
  799. LRSwitch() {
  800. addFrame(SVG::load(assetPlugin(plugin, "res/elements/Switch0.svg")));
  801. addFrame(SVG::load(assetPlugin(plugin, "res/elements/Switch1.svg")));
  802. }
  803. };
  804. /**
  805. * @brief Standard LED
  806. */
  807. struct LRLight : ModuleLightWidget, LRGestaltChangeAction {
  808. float glowIntensity = 0.25;
  809. LRLight();
  810. void draw(NVGcontext *vg) override;
  811. void setColor(NVGcolor color);
  812. void onGestaltChange(LREventGestaltChange &e) override;
  813. };
  814. /**
  815. * @brief Standard linear gradient widget
  816. */
  817. struct LRGradientWidget : TransparentWidget {
  818. private:
  819. /* gradient vectors */
  820. Vec v1, v2;
  821. /* standard margin */
  822. float margin = 10.f;
  823. /* gradient colors */
  824. NVGcolor innerColor, outerColor;
  825. public:
  826. LRGradientWidget(const Vec &size) {
  827. box.pos = Vec(0, 0);
  828. box.size = size;
  829. }
  830. /**
  831. * @brief Create a new gradient widget
  832. * @param size box size (derived from parent widget)
  833. * @param innerColor The inner color (v1)
  834. * @param outerColor The outher color (v2)
  835. * @param offset The offset of the left-top corner (optional)
  836. */
  837. LRGradientWidget(const Vec &size, const NVGcolor &innerColor, const NVGcolor &outerColor, const Vec &offset = Vec(30, -50)) :
  838. innerColor(innerColor), outerColor(outerColor) {
  839. box.size = size;
  840. box.pos = Vec(0, 0);
  841. /* initialise with standard dimensions */
  842. v1 = offset;
  843. v2 = Vec(v1.x, size.y);
  844. }
  845. void setGradientOffset(const Vec &v1, const Vec &v2) {
  846. LRGradientWidget::v1 = v1;
  847. LRGradientWidget::v2 = v2;
  848. }
  849. const NVGcolor &getInnerColor() const;
  850. void setInnerColor(const NVGcolor &innerColor);
  851. const NVGcolor &getOuterColor() const;
  852. void setOuterColor(const NVGcolor &outerColor);
  853. void draw(NVGcontext *vg) override;
  854. };
  855. /**
  856. * @brief Widget for simulating used look
  857. */
  858. struct LRPatinaWidget : TransparentWidget {
  859. SVGWidget *svg;
  860. float strength = 0.99f;
  861. LRPatinaWidget(const string &filename, const Vec &size);
  862. void draw(NVGcontext *vg) override;
  863. void randomize();
  864. };
  865. /**
  866. * @brief Default panel border
  867. */
  868. struct LRPanelBorder : TransparentWidget {
  869. static constexpr float BORDER_WIDTH = 1.2f;
  870. inline void draw(NVGcontext *vg) override {
  871. NVGcolor borderColorLight = nvgRGBAf(0.9, 0.9, 0.9, 0.1);
  872. NVGcolor borderColorDark = nvgRGBAf(0.1, 0.1, 0.1, 0.5);
  873. nvgBeginPath(vg);
  874. nvgRect(vg, 0, BORDER_WIDTH, 0 + BORDER_WIDTH, box.size.y);
  875. nvgFillColor(vg, borderColorLight);
  876. nvgFill(vg);
  877. nvgBeginPath(vg);
  878. nvgRect(vg, 0, 0, box.size.x, BORDER_WIDTH);
  879. nvgFillColor(vg, borderColorLight);
  880. nvgFill(vg);
  881. nvgBeginPath(vg);
  882. nvgRect(vg, 0, box.size.y - BORDER_WIDTH, box.size.x, box.size.y - BORDER_WIDTH);
  883. nvgFillColor(vg, borderColorDark);
  884. nvgFill(vg);
  885. nvgBeginPath(vg);
  886. nvgRect(vg, box.size.x - BORDER_WIDTH, 0, box.size.x - BORDER_WIDTH, box.size.y);
  887. nvgFillColor(vg, borderColorDark);
  888. nvgFill(vg);
  889. }
  890. };
  891. /**
  892. * @brief Standard LR module Panel
  893. */
  894. struct LRPanel : FramebufferWidget, LRGestaltVariant, LRGestaltChangeAction {
  895. SVGWidget *panelWidget;
  896. map<LRGestalt, LRGradientWidget *> gradients;
  897. LRPatinaWidget *patinaWidgetClassic, *patinaWidgetWhite;
  898. LRPanel();
  899. void setGradientVariant(bool enabled);
  900. void setPatina(bool enabled);
  901. void step() override;
  902. void init();
  903. void onGestaltChange(LREventGestaltChange &e) override;
  904. };
  905. /**
  906. * @brief Passive rotating SVG image
  907. */
  908. struct SVGRotator : FramebufferWidget {
  909. TransformWidget *tw;
  910. SVGWidget *sw;
  911. /** angle to rotate per step */
  912. float angle = 0;
  913. float inc;
  914. float scale;
  915. float transperency;
  916. SVGRotator();
  917. /**
  918. * @brief Factory method
  919. * @param pos Position
  920. * @param svg Pointer to SVG image
  921. * @param angle Increment angle per step
  922. * @param scale Scaling of the SVG / default 100%
  923. * @param transperency Transperancy of the SVG / default 100%
  924. */
  925. SVGRotator static *create(Vec pos, shared_ptr<SVG> svg, float inc, float scale = 1.0f, float transperency = 1.f) {
  926. SVGRotator *rotator = FramebufferWidget::create<SVGRotator>(pos);
  927. rotator->setSVG(svg);
  928. rotator->inc = inc;
  929. rotator->scale = scale;
  930. rotator->transperency = transperency;
  931. return rotator;
  932. }
  933. void draw(NVGcontext *vg) override;
  934. void setSVG(shared_ptr<SVG> svg);
  935. void step() override;
  936. };
  937. struct FontIconWidget : FramebufferWidget {
  938. TrueType iconFont;
  939. float fontSize;
  940. NVGcolor color;
  941. explicit FontIconWidget(float fontSize = 12.f, NVGcolor color = nvgRGBAf(1.f, 1.f, 1.f, 1.f));
  942. void draw(NVGcontext *vg) override;
  943. };
  944. /**
  945. * Utility widget for resize action on modules
  946. */
  947. struct ModuleResizeWidget : Widget {
  948. float minWidth;
  949. bool right = false;
  950. float dragX;
  951. float dragY;
  952. Rect originalBox;
  953. ModuleResizeWidget(float _minWidth) {
  954. box.size = Vec(RACK_GRID_WIDTH * 1, RACK_GRID_HEIGHT);
  955. minWidth = _minWidth;
  956. }
  957. void onMouseDown(EventMouseDown &e) override {
  958. if (e.button == 0) {
  959. e.consumed = true;
  960. e.target = this;
  961. }
  962. }
  963. void onDragStart(EventDragStart &e) override {
  964. dragX = RACK_PLUGIN_UI_RACKWIDGET->lastMousePos.x;
  965. dragY = RACK_PLUGIN_UI_RACKWIDGET->lastMousePos.y;
  966. ModuleWidget *m = getAncestorOfType<ModuleWidget>();
  967. originalBox = m->box;
  968. }
  969. void onDragMove(EventDragMove &e) override {
  970. ModuleWidget *m = getAncestorOfType<ModuleWidget>();
  971. float newDragX = RACK_PLUGIN_UI_RACKWIDGET->lastMousePos.x;
  972. float deltaX = newDragX - dragX;
  973. float newDragY = RACK_PLUGIN_UI_RACKWIDGET->lastMousePos.y;
  974. float deltaY = newDragY - dragY;
  975. Rect newBox = originalBox;
  976. // resize width
  977. if (right) {
  978. newBox.size.x += deltaX;
  979. newBox.size.x = fmaxf(newBox.size.x, minWidth);
  980. newBox.size.x = roundf(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
  981. } else {
  982. newBox.size.x -= deltaX;
  983. newBox.size.x = fmaxf(newBox.size.x, minWidth);
  984. newBox.size.x = roundf(newBox.size.x / RACK_GRID_WIDTH) * RACK_GRID_WIDTH;
  985. newBox.pos.x = originalBox.pos.x + originalBox.size.x - newBox.size.x;
  986. }
  987. // resize height
  988. newBox.size.y += deltaY;
  989. newBox.size.y = fmaxf(newBox.size.y, RACK_GRID_HEIGHT);
  990. newBox.size.y = roundf(newBox.size.y / RACK_GRID_HEIGHT) * RACK_GRID_HEIGHT;
  991. RACK_PLUGIN_UI_RACKWIDGET->requestModuleBox(m, newBox);
  992. }
  993. };
  994. }