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.

686 lines
21KB

  1. #include "dsp/digital.hpp"
  2. #include "moDllz.hpp"
  3. #include "dsp/filter.hpp"
  4. /*
  5. * XBender
  6. */
  7. namespace rack_plugin_moDllz {
  8. struct XBender : Module {
  9. enum ParamIds {
  10. XBEND_PARAM,
  11. XBENDCVTRIM_PARAM,
  12. XBENDRANGE_PARAM,
  13. BEND_PARAM,
  14. BENDCVTRIM_PARAM,
  15. AXISXFADE_PARAM,
  16. AXISSLEW_PARAM,
  17. AXISTRNSUP_PARAM,
  18. AXISTRNSDWN_PARAM,
  19. AXISSHIFTTRIM_PARAM,
  20. AXISSELECT_PARAM = 10,
  21. AXISSELECTCV_PARAM = 18,
  22. SNAPAXIS_PARAM,
  23. YCENTER_PARAM,
  24. YZOOM_PARAM,
  25. AUTOZOOM_PARAM,
  26. NUM_PARAMS
  27. };
  28. enum InputIds {
  29. IN_INPUT,
  30. XBENDCV_INPUT = 8,
  31. XBENDRANGE_INPUT,
  32. BENDCV_INPUT,
  33. AXISSELECT_INPUT,
  34. AXISEXT_INPUT,
  35. AXISXFADE_INPUT,
  36. AXISSHIFT_INPUT,
  37. AXISSLEW_INPUT,
  38. NUM_INPUTS
  39. };
  40. enum OutputIds {
  41. OUT_OUTPUT,
  42. AXIS_OUTPUT = 8,
  43. NUM_OUTPUTS
  44. };
  45. enum LightIds {
  46. AXIS_LIGHT,
  47. AUTOZOOM_LIGHT = 8,
  48. SNAPAXIS_LIGHT,
  49. NUM_LIGHTS
  50. };
  51. float inAxis = 0.f;
  52. float axisSlew = 0.f;
  53. int axisTransParam = 0;
  54. float finalAxis = 0.f;
  55. float AxisShift = 0.f;
  56. float axisXfade;
  57. float selectedAxisF = 0.f;
  58. int selectedAxisI = 0;
  59. float dZoom = 1.f;
  60. float dCenter = 0.5f;
  61. int frameAutoZoom = 0;
  62. float slewchanged = 0.f;
  63. float XBenderKnobVal = 0.f;
  64. float XBenderKnobCV = 0.f;
  65. float xbend = 0.f;
  66. float testVal = 0.f;
  67. bool newZoom = false;
  68. SchmittTrigger axisTransUpTrigger;
  69. SchmittTrigger axisTransDwnTrigger;
  70. SchmittTrigger axisSelectTrigger[8];
  71. struct ioXBended {
  72. float inx = 0.0f;
  73. float xout = 0.0f;
  74. bool iactive = false;
  75. };
  76. ioXBended ioxbended[8];
  77. SlewLimiter slewlimiter;
  78. XBender() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  79. void step() override;
  80. void onReset() override {
  81. for (int ix = 0; ix < 8 ; ix++){
  82. outputs[OUT_OUTPUT + ix].value = inputs[IN_INPUT + ix].value;
  83. }
  84. }
  85. json_t *toJson() override {
  86. json_t *rootJ = json_object();
  87. json_object_set_new(rootJ, "selectedAxisI", json_integer(selectedAxisI));
  88. json_object_set_new(rootJ, "axisTransParam", json_integer(axisTransParam));
  89. return rootJ;
  90. }
  91. void fromJson(json_t *rootJ) override {
  92. json_t *selectedAxisIJ = json_object_get(rootJ,("selectedAxisI"));
  93. selectedAxisI = json_integer_value(selectedAxisIJ);
  94. json_t *axisTransParamJ = json_object_get(rootJ,("axisTransParam"));
  95. axisTransParam = json_integer_value(axisTransParamJ);
  96. }
  97. };
  98. ///////////////////////////////////////////
  99. ///////////////STEP //////////////////
  100. /////////////////////////////////////////////
  101. void XBender::step() {
  102. if(inputs[AXISSELECT_INPUT].active) {
  103. if (params[SNAPAXIS_PARAM].value > 0.5f){
  104. selectedAxisI = (clamp(static_cast<int>(inputs[AXISSELECT_INPUT].value * 0.7), 0, 7));
  105. selectedAxisF = static_cast<float>(selectedAxisI);
  106. inAxis = inputs[selectedAxisI].value;
  107. } else {
  108. selectedAxisF = clamp(inputs[AXISSELECT_INPUT].value * 0.7, 0.f, 7.f);
  109. selectedAxisI = static_cast<int>(selectedAxisF);
  110. float ax_float = selectedAxisF - static_cast<float>(selectedAxisI);
  111. inAxis = (inputs[selectedAxisI].value * (1.f - ax_float) + (inputs[selectedAxisI + 1].value * ax_float));
  112. }
  113. }else{
  114. inAxis = inputs[selectedAxisI].value;
  115. }
  116. lights[SNAPAXIS_LIGHT].value = (params[SNAPAXIS_PARAM].value > 0.5f)? 1.f : 0.f;
  117. axisXfade = clamp((params[AXISXFADE_PARAM].value + inputs[AXISXFADE_INPUT].value/ 10.f), 0.f, 1.f);
  118. if (inputs[AXISEXT_INPUT].active){
  119. float axisext = inputs[AXISEXT_INPUT].value;
  120. axisSlew = crossfade(axisext, inAxis, axisXfade);
  121. }else axisSlew = inAxis;
  122. float slewsum = clamp((params[AXISSLEW_PARAM].value + inputs[AXISSLEW_INPUT].value * .1f), 0.f , 1.f);
  123. if (slewchanged != slewsum) {
  124. slewchanged = slewsum;
  125. float slewfloat = 1.0f/(5.0f + slewsum * engineGetSampleRate());
  126. slewlimiter.setRiseFall(slewfloat,slewfloat);
  127. }
  128. finalAxis = slewlimiter.process(axisSlew) + (inputs[AXISSHIFT_INPUT].value * params[AXISSHIFTTRIM_PARAM].value);
  129. AxisShift = (static_cast<float>(axisTransParam)/12.f);
  130. finalAxis += clamp(AxisShift, -12.f,12.f);
  131. float range = clamp((params[XBENDRANGE_PARAM].value + inputs[XBENDRANGE_INPUT].value/2.f), 1.f,5.f);
  132. /////////// MOTORIZED KNOB
  133. //float xbend = clamp((params[XBEND_PARAM].value + (inputs[XBENDCV_INPUT].value /5.f) * (params[XBENDCVTRIM_PARAM].value /24.f)),-1.f, 1.f);
  134. XBenderKnobCV = (params[XBENDCVTRIM_PARAM].value / 24.f) * (inputs[XBENDCV_INPUT].value / 5.f);
  135. XBenderKnobVal = params[XBEND_PARAM].value;
  136. xbend = clamp((XBenderKnobVal + XBenderKnobCV),-1.f,1.f);
  137. /////////////////////////
  138. float bend = clamp((params[BEND_PARAM].value + (inputs[BENDCV_INPUT].value /5.f) * (params[BENDCVTRIM_PARAM].value /60.f)),-1.f, 1.f);
  139. for (int i = 0; i < 8; i++){
  140. if (inputs[IN_INPUT + i].active) {
  141. if (axisSelectTrigger[i].process(params[AXISSELECT_PARAM + i].value)) {
  142. selectedAxisI = i;
  143. selectedAxisF = static_cast<float>(i); // float for display
  144. }
  145. ioxbended[i].iactive= true;
  146. lights[AXIS_LIGHT + i].value = (selectedAxisI == i)? 1.f : 0.01f;
  147. ioxbended[i].inx = inputs[IN_INPUT + i].value;
  148. float diff = (finalAxis - ioxbended[i].inx) * xbend * range;
  149. ioxbended[i].xout = clamp((ioxbended[i].inx + diff + bend * 6.f),-12.f,12.f);
  150. outputs[OUT_OUTPUT + i].value = ioxbended[i].xout;
  151. }else{
  152. lights[AXIS_LIGHT + i].value = 0;
  153. ioxbended[i].iactive=false;
  154. }
  155. } //for loop ix
  156. outputs[AXIS_OUTPUT].value = finalAxis;
  157. if (axisTransUpTrigger.process(params[AXISTRNSUP_PARAM].value))
  158. if (axisTransParam < 48) axisTransParam ++;
  159. if (axisTransDwnTrigger.process(params[AXISTRNSDWN_PARAM].value))
  160. if (axisTransParam > -48) axisTransParam --;
  161. bool autoZoom = (params[AUTOZOOM_PARAM].value > 0.f);
  162. if (autoZoom){
  163. frameAutoZoom ++;
  164. if (frameAutoZoom > 128) {
  165. frameAutoZoom = 0;
  166. float autoZoomMin = 12.f , autoZoomMax = -12.f;
  167. int active = 0;
  168. for (int i = 0; i < 8; i++){
  169. if (inputs[IN_INPUT + i].active) {
  170. active ++;
  171. if (ioxbended[i].inx < autoZoomMin)
  172. autoZoomMin = ioxbended[i].inx;
  173. if (ioxbended[i].xout < autoZoomMin)
  174. autoZoomMin = ioxbended[i].xout;
  175. if (ioxbended[i].inx > autoZoomMax)
  176. autoZoomMax = ioxbended[i].inx;
  177. if (ioxbended[i].xout > autoZoomMax)
  178. autoZoomMax = ioxbended[i].xout;
  179. }
  180. }
  181. if (finalAxis < autoZoomMin)
  182. autoZoomMin = finalAxis;
  183. if (finalAxis > autoZoomMax)
  184. autoZoomMax = finalAxis;
  185. float autoZ = 22.f / clamp((autoZoomMax - autoZoomMin),1.f,24.f);
  186. float autoCenter = 10.f * (autoZoomMin + (autoZoomMax - autoZoomMin) / 2.f);
  187. dZoom = clamp(autoZ, 1.f, 15.f);
  188. dCenter = clamp(autoCenter, -120.f, 120.f);
  189. }
  190. lights[AUTOZOOM_LIGHT].value = 10.f;
  191. }
  192. else {
  193. dCenter = params[XBender::YCENTER_PARAM].value;
  194. dZoom = params[XBender::YZOOM_PARAM].value;
  195. lights[AUTOZOOM_LIGHT].value = 0.f;
  196. }
  197. testVal = xbend;
  198. }//closing STEP
  199. ///Bend Realtime Background Display
  200. struct BenderDisplayBackG : TransparentWidget {
  201. BenderDisplayBackG() {
  202. }
  203. float *pyCenter ;
  204. float *pyZoom ;
  205. void draw(NVGcontext* vg)
  206. {
  207. const float dispHeight = 228.f;
  208. const float dispCenter = dispHeight / 2.f;
  209. float yZoom = *pyZoom;
  210. float yCenter = *pyCenter * yZoom + dispCenter;
  211. float keyw = 10.f * yZoom /12.f;
  212. // crop drawing to display
  213. nvgScissor(vg, 0.f, 0.f, 152.f, dispHeight);
  214. nvgBeginPath(vg);
  215. nvgFillColor(vg, nvgRGB(0x2a, 0x2a, 0x2a));
  216. nvgRect(vg, 20.f, yCenter - 120.f * yZoom, 110.f, 20.f * yZoom);
  217. nvgRect(vg, 20.f, yCenter + 100.f * yZoom, 110.f, 20.f * yZoom);
  218. nvgFill(vg);
  219. nvgBeginPath(vg);
  220. if (yZoom > 2.5f) {
  221. nvgFillColor(vg, nvgRGB(0x0, 0x0, 0x0));
  222. nvgRect(vg, 0.f, 0.f, 20.f, dispHeight);
  223. nvgFill(vg);
  224. nvgBeginPath(vg);
  225. nvgFillColor(vg, nvgRGB(0x2f, 0x2f, 0x2f));
  226. } else {
  227. nvgFillColor(vg, nvgRGB(0x1a, 0x1a, 0x1a));
  228. }
  229. nvgRect(vg, 20.f, yCenter - 50.f * yZoom, 110.f, 100.f * yZoom );
  230. nvgFill(vg);
  231. for (int i = 0; i < 11; i++){
  232. if (yZoom < 2.5f){
  233. // 1V lines
  234. nvgBeginPath(vg);
  235. nvgStrokeColor(vg, nvgRGB(0x2d,0x2d,0x2d));
  236. nvgMoveTo(vg, 20.f, yCenter - 10.f * yZoom * i);
  237. nvgLineTo(vg, 130.f,yCenter - 10.f * yZoom * i);
  238. nvgMoveTo(vg, 20.f, yCenter + 10.f * yZoom * i);
  239. nvgLineTo(vg, 130.f,yCenter + 10.f * yZoom * i);
  240. nvgStroke(vg);
  241. }else if (i < 5){
  242. // keyboard
  243. float keyPos = yCenter + 10.f * yZoom * i;
  244. // C's highlight
  245. nvgBeginPath(vg);
  246. nvgFillColor(vg, nvgRGB(0x44, 0x44, 0x44));
  247. nvgRect(vg, 20.f, yCenter - 10.f * yZoom * i - keyw * 0.5f, 110.f, keyw);
  248. nvgFill(vg);
  249. /// over center
  250. nvgBeginPath(vg);
  251. nvgFillColor(vg, nvgRGB(0x0, 0x0, 0x0));
  252. nvgRect(vg, 20.f, keyPos + keyw * 1.5f, 110.f, keyw);
  253. nvgRect(vg, 20.f, keyPos + keyw * 3.5f , 110.f, keyw);
  254. nvgRect(vg, 20.f, keyPos + keyw * 5.5f, 110.f, keyw);
  255. nvgRect(vg, 20.f, keyPos + keyw * 8.5f, 110.f, keyw);
  256. nvgRect(vg, 20.f, keyPos + keyw * 10.5f, 110.f, keyw);
  257. nvgFill(vg);
  258. /// C's highlight
  259. nvgBeginPath(vg);
  260. nvgFillColor(vg, nvgRGB(0x44, 0x44, 0x44));
  261. nvgRect(vg, 20.f, yCenter + 10.f * yZoom * i - keyw * 0.5f, 110.f, keyw);
  262. nvgFill(vg);
  263. /// under center
  264. keyPos = yCenter - 10.f * yZoom * i;
  265. nvgBeginPath(vg);
  266. nvgFillColor(vg, nvgRGB(0x0, 0x0, 0x0));
  267. nvgRect(vg, 20.f, keyPos - keyw * 1.5f, 110.f, keyw);
  268. nvgRect(vg, 20.f, keyPos - keyw * 3.5f , 110.f, keyw);
  269. nvgRect(vg, 20.f, keyPos - keyw * 6.5f, 110.f, keyw);
  270. nvgRect(vg, 20.f, keyPos - keyw * 8.5f, 110.f, keyw);
  271. nvgRect(vg, 20.f, keyPos - keyw * 10.5f, 110.f, keyw);
  272. nvgFill(vg);
  273. }
  274. }
  275. // center 0v...
  276. nvgBeginPath(vg);
  277. if (yZoom < 2.5f){
  278. nvgStrokeColor(vg,nvgRGBA(0x80, 0x00, 0x00 ,0x77));
  279. nvgStrokeWidth(vg,1.f);
  280. nvgMoveTo(vg, 20.f, yCenter);
  281. nvgLineTo(vg, 130.f, yCenter);
  282. nvgStroke(vg);
  283. }//... center C
  284. else {
  285. nvgFillColor(vg, nvgRGBA(0x80, 0x00, 0x00 ,0x77));
  286. nvgRect(vg, 20.f, yCenter - keyw * 0.5f, 110.f, keyw);
  287. nvgFill(vg);
  288. }
  289. }
  290. };
  291. ///Bend Realtime Display
  292. struct BenderDisplay : TransparentWidget {
  293. BenderDisplay() {
  294. }
  295. XBender::ioXBended *ioxB;
  296. float *pAxis = NULL;
  297. float *pyCenter ;
  298. float *pyZoom ;
  299. float *pAxisIx;
  300. float *pAxisXfade;
  301. void draw(NVGcontext* vg)
  302. {
  303. const float dispHeight = 228.f;
  304. const float dispCenter = dispHeight / 2.f;
  305. float yZoom = *pyZoom;
  306. float yCenter = *pyCenter * yZoom + dispCenter;
  307. float AxisIx = *pAxisIx;
  308. float keyw = 10.f * yZoom /12.f;
  309. // crop drawing to display
  310. nvgScissor(vg, 0.f, 0.f, 152.f, dispHeight);
  311. float Axis = *pAxis;
  312. ///// Bend Lines
  313. const float yfirst = 10.5f;
  314. const float ystep = 26.f;
  315. for (int i = 0; i < 8 ; i++){
  316. //nowactive =;
  317. if (ioxB[i].iactive){
  318. float yport = yfirst + i * ystep;
  319. float yi = yZoom * ioxB[i].inx * -10.f + yCenter ;
  320. float yo = yZoom * ioxB[i].xout * -10.f + yCenter ;
  321. nvgBeginPath(vg);
  322. nvgStrokeWidth(vg,1.f);
  323. nvgStrokeColor(vg,nvgRGBA(0xff, 0xff, 0xff,0x80));
  324. nvgMoveTo(vg, 0.f, yport);
  325. nvgLineTo(vg, 20.f, yi);
  326. nvgLineTo(vg, 130.f, yo);
  327. nvgLineTo(vg, 150.f, yport);
  328. nvgStroke(vg);
  329. if (yZoom > 2.5f){
  330. nvgBeginPath(vg);
  331. nvgFillColor(vg, nvgRGBA(0xff, 0xff, 0xff,0x60));
  332. nvgRoundedRect(vg, 15.f, yi - keyw * 0.5f, 10.f, keyw, yZoom / 3.f);
  333. nvgFill(vg);
  334. nvgBeginPath(vg);
  335. nvgRoundedRect(vg, 125.f, yo - keyw * 0.5f, 10.f, keyw, yZoom / 3.f);
  336. nvgFill(vg);
  337. }
  338. }
  339. }
  340. /// Axis Line
  341. NVGcolor extColor = nvgRGBA(0xee, 0xee, 0x00, (1.f - *pAxisXfade) * 0xff);
  342. NVGcolor intColor = nvgRGBA(0xee, 0x00, 0x00, *pAxisXfade * 0xff);
  343. NVGcolor axisColor = nvgRGB(0xee, (1.f - *pAxisXfade) * 0xee, 0x00);
  344. Axis = yZoom * Axis * -10.f + yCenter;
  345. nvgStrokeWidth(vg,1.f);
  346. //ext
  347. nvgBeginPath(vg);
  348. nvgStrokeColor(vg,extColor);
  349. nvgMoveTo(vg, 0.f, 228.f);
  350. nvgLineTo(vg, 20.f, Axis);
  351. nvgStroke(vg);
  352. // int
  353. nvgBeginPath(vg);
  354. nvgStrokeColor(vg,intColor);
  355. nvgMoveTo(vg, 0.f, yfirst + AxisIx * ystep);
  356. nvgLineTo(vg, 20.f, Axis);
  357. nvgStroke(vg);
  358. // axis
  359. nvgBeginPath(vg);
  360. nvgStrokeColor(vg,axisColor);
  361. nvgMoveTo(vg, 20.f, Axis);
  362. nvgLineTo(vg, 130.f, Axis);
  363. nvgLineTo(vg, 150.f, 222.f);
  364. nvgStroke(vg);
  365. }
  366. };
  367. // Transp Display
  368. struct AxisTranspDisplay : TransparentWidget {
  369. AxisTranspDisplay(){
  370. font = Font::load(FONT_FILE);
  371. }
  372. float mdfontSize = 11.f;
  373. std::string s;
  374. std::shared_ptr<Font> font;
  375. int *pAxisTransP = 0;
  376. int AxisTransP = 128;
  377. void draw(NVGcontext* vg) {
  378. if (AxisTransP != *pAxisTransP) {
  379. AxisTransP = *pAxisTransP;
  380. s = std::to_string(*pAxisTransP);
  381. }
  382. nvgFontSize(vg, mdfontSize);
  383. nvgFontFaceId(vg, font->handle);
  384. nvgTextAlign(vg, NVG_ALIGN_CENTER);
  385. nvgFillColor(vg, nvgRGB(0xFF,0xFF,0xFF));
  386. nvgTextBox(vg, 0.f, 14.0f,box.size.x, s.c_str(), NULL);
  387. }
  388. };
  389. struct RangeSelector: moDllzSmSelector{
  390. RangeSelector(){
  391. minAngle = -0.4*M_PI;
  392. maxAngle = 0.4*M_PI;
  393. }
  394. };
  395. struct xbendKnob : SVGKnob {
  396. // XBender *module;
  397. // float *ptoKnobCV = 0;
  398. // float *pxbend = 0;
  399. //
  400. // float toKnobCV = 0.f;
  401. // float KnobVal = 0.f;
  402. xbendKnob() {
  403. minAngle = -0.83*M_PI;
  404. maxAngle = 0.83*M_PI;
  405. setSVG(SVG::load(assetPlugin(plugin, "res/xbendKnob.svg")));
  406. shadow->opacity = 0.f;
  407. }
  408. // void step() {
  409. // if (KnobVal != *pxbend){
  410. // KnobVal = *pxbend;
  411. // toKnobCV = *ptoKnobCV;
  412. // value = KnobVal;
  413. // dirty = true;
  414. // }
  415. // if (dirty) {
  416. // float angle;
  417. // if (isfinite(minValue) && isfinite(maxValue)) {
  418. // angle = rescale(value, minValue, maxValue, minAngle, maxAngle);
  419. // }
  420. // else {
  421. // angle = rescale(value, -1.0, 1.0, minAngle, maxAngle);
  422. // angle = fmodf(angle, 2*M_PI);
  423. // }
  424. // tw->identity();
  425. // // Rotate SVG
  426. // Vec center = sw->box.getCenter();
  427. // tw->translate(center);
  428. // tw->rotate(angle);
  429. // tw->translate(center.neg());
  430. // // Redraw
  431. // module->XBenderKnobVal = value - toKnobCV;
  432. // }
  433. // FramebufferWidget::step();
  434. // }
  435. //
  436. // void onChange(EventChange &e) {
  437. // dirty = true;
  438. // Knob::onChange(e);
  439. // }
  440. // void onMouseUp(EventMouseUp &e){
  441. //
  442. // }
  443. };
  444. struct zTTrim : SVGKnob {
  445. zTTrim() {
  446. minAngle = 0;
  447. maxAngle = 1.75*M_PI;
  448. setSVG(SVG::load(assetPlugin(plugin, "res/zTTrim.svg")));
  449. shadow->opacity = 0.f;
  450. }
  451. };
  452. struct cTTrim : SVGKnob {
  453. cTTrim() {
  454. minAngle = -0.83*M_PI;
  455. maxAngle = 0.83*M_PI;
  456. snap = true;
  457. setSVG(SVG::load(assetPlugin(plugin, "res/cTTrim.svg")));
  458. shadow->opacity = 0.f;
  459. }
  460. };
  461. struct autoZoom : SVGSwitch, ToggleSwitch {
  462. autoZoom() {
  463. addFrame(SVG::load(assetPlugin(plugin, "res/autoButton.svg")));
  464. addFrame(SVG::load(assetPlugin(plugin, "res/autoButton.svg")));
  465. }
  466. };
  467. struct snapAxisButton : SVGSwitch, ToggleSwitch {
  468. snapAxisButton() {
  469. addFrame(SVG::load(assetPlugin(plugin, "res/snapButton.svg")));
  470. addFrame(SVG::load(assetPlugin(plugin, "res/snapButton.svg")));
  471. }
  472. };
  473. struct XBenderWidget : ModuleWidget {
  474. XBenderWidget(XBender *module): ModuleWidget(module){
  475. setPanel(SVG::load(assetPlugin(plugin, "res/XBender.svg")));
  476. float xPos;
  477. float yPos;
  478. float xyStep = 26.f ;
  479. //Screws
  480. addChild(Widget::create<ScrewBlack>(Vec(0, 0)));
  481. addChild(Widget::create<ScrewBlack>(Vec(box.size.x - 15, 0)));
  482. addChild(Widget::create<ScrewBlack>(Vec(0, 365)));
  483. addChild(Widget::create<ScrewBlack>(Vec(box.size.x - 15, 365)));
  484. xPos = 73.f;
  485. yPos = 22.f;
  486. {
  487. BenderDisplayBackG *benderDisplayBG = new BenderDisplayBackG();
  488. benderDisplayBG->box.pos = Vec(xPos, yPos);
  489. benderDisplayBG->box.size = {152.f, 228.f};
  490. benderDisplayBG->pyCenter = &(module->dCenter);
  491. benderDisplayBG->pyZoom = &(module->dZoom);
  492. addChild(benderDisplayBG);
  493. }
  494. {
  495. BenderDisplay *benderDisplay = new BenderDisplay();
  496. benderDisplay->box.pos = Vec(xPos, yPos);
  497. benderDisplay->box.size = {152.f, 228.f};
  498. benderDisplay->ioxB = &(module->ioxbended[0]);
  499. benderDisplay->pAxis = &(module->finalAxis);
  500. benderDisplay->pAxisIx = &(module->selectedAxisF);
  501. benderDisplay->pyCenter = &(module->dCenter);
  502. benderDisplay->pyZoom = &(module->dZoom);
  503. benderDisplay->pAxisXfade = &(module->axisXfade);
  504. addChild(benderDisplay);
  505. }
  506. xPos = 170.f;
  507. yPos = 252.f;
  508. /// View Center Zoom
  509. addParam(ParamWidget::create<cTTrim>(Vec(xPos,yPos), module, XBender::YCENTER_PARAM, -120.f, 120.f, 0.f));
  510. xPos = 203;
  511. addParam(ParamWidget::create<zTTrim>(Vec(xPos,yPos), module, XBender::YZOOM_PARAM, 1.f, 15.f, 1.f));
  512. yPos += 1.5f;
  513. xPos = 125.f;
  514. addParam(ParamWidget::create<autoZoom>(Vec(xPos, yPos ), module, XBender::AUTOZOOM_PARAM, 0.0f, 1.0f, 1.0f));
  515. addChild(ModuleLightWidget::create<TinyLight<RedLight>>(Vec(xPos + 17.f, yPos + 4.f), module, XBender::AUTOZOOM_LIGHT));
  516. /// IN - Axis select - OUTS
  517. xPos = 12.f;
  518. yPos = 22.f;
  519. for (int i = 0; i < 8; i++){
  520. // IN leds OUT
  521. addInput(Port::create<moDllzPort>(Vec(xPos, yPos), Port::INPUT, module, XBender::IN_INPUT + i));
  522. addParam(ParamWidget::create<moDllzRoundButton>(Vec(xPos + 37.f, yPos + 5.f), module, XBender::AXISSELECT_PARAM + i, 0.0f, 1.0f, 0.0f));
  523. addChild(ModuleLightWidget::create<TinyLight<RedLight>>(Vec(xPos + 42.5f, yPos + 10.5f), module, XBender::AXIS_LIGHT + i));
  524. addOutput(Port::create<moDllzPort>(Vec(234.8f, yPos), Port::OUTPUT, module, XBender::OUT_OUTPUT + i));
  525. yPos += xyStep;
  526. }
  527. yPos = 248.f;
  528. //// AXIS out >>>> on the Right
  529. addOutput(Port::create<moDllzPort>(Vec(234.8f, yPos), Port::OUTPUT, module, XBender::AXIS_OUTPUT));
  530. yPos = 249.f;
  531. /// AXIS select in
  532. addInput(Port::create<moDllzPort>(Vec(xPos, yPos), Port::INPUT, module, XBender::AXISSELECT_INPUT));
  533. addParam(ParamWidget::create<snapAxisButton>(Vec(xPos + 22.5f, yPos + 2.f ), module, XBender::SNAPAXIS_PARAM, 0.0f, 1.0f, 0.0f));
  534. addChild(ModuleLightWidget::create<TinyLight<RedLight>>(Vec(xPos + 40.f, yPos + 4.f), module, XBender::SNAPAXIS_LIGHT));
  535. /// AXIS EXT - XFADE
  536. yPos += 25.f;
  537. addInput(Port::create<moDllzPort>(Vec(xPos, yPos), Port::INPUT, module, XBender::AXISXFADE_INPUT));
  538. addParam(ParamWidget::create<moDllzKnob26>(Vec(36.f,280.f), module, XBender::AXISXFADE_PARAM, 0.f, 1.f, 1.f));
  539. yPos += 25.f;
  540. addInput(Port::create<moDllzPort>(Vec(xPos, yPos), Port::INPUT, module, XBender::AXISEXT_INPUT));
  541. /// AXIS Slew
  542. yPos += 25.f;
  543. addInput(Port::create<moDllzPort>(Vec(xPos, yPos), Port::INPUT, module, XBender::AXISSLEW_INPUT));
  544. addParam(ParamWidget::create<moDllzKnob26>(Vec(34.f, 324.f), module, XBender::AXISSLEW_PARAM, 0.f, 1.f, 0.f));
  545. //AXIS Mod Shift
  546. addInput(Port::create<moDllzPort>(Vec(xPos + 53.f,yPos), Port::INPUT, module, XBender::AXISSHIFT_INPUT));
  547. addParam(ParamWidget::create<moDllzKnob26>(Vec(87.f, 324.f), module, XBender::AXISSHIFTTRIM_PARAM, 0.0f, 1.0f, 0.f));
  548. //AXIS Transp
  549. xPos = 73.5f;
  550. yPos = 278.5f;
  551. addParam(ParamWidget::create<moDllzPulseUp>(Vec(xPos + 31.f,yPos - 1.f), module, XBender::AXISTRNSUP_PARAM, 0.0f, 1.0f, 0.0f));
  552. addParam(ParamWidget::create<moDllzPulseDwn>(Vec(xPos + 31.f ,yPos + 10.f), module, XBender::AXISTRNSDWN_PARAM, 0.0f, 1.0f, 0.0f));
  553. {
  554. AxisTranspDisplay *axisTranspDisplay = new AxisTranspDisplay();
  555. axisTranspDisplay->box.pos = Vec(xPos, yPos);
  556. axisTranspDisplay->box.size = {30.f, 20};
  557. axisTranspDisplay->pAxisTransP = &(module->axisTransParam);
  558. addChild(axisTranspDisplay);
  559. }
  560. /// Knobs
  561. //XBEND
  562. xPos = 124.f;
  563. yPos = 272.f;
  564. addParam(ParamWidget::create<xbendKnob>(Vec(xPos, yPos), module, XBender::XBEND_PARAM, -1.f, 1.f, 0.f));
  565. // { xbendKnob *xbendK = new xbendKnob();
  566. // xbendK->box.pos = Vec(xPos, yPos);
  567. // xbendK->box.size = {50.f, 50.f};
  568. // xbendK->minValue = -1.f;
  569. // xbendK->maxValue = 1.f;
  570. // xbendK->defaultValue = 0.f;
  571. // xbendK->module = module;
  572. // xbendK->ptoKnobCV = &(module->XBenderKnobCV);
  573. // xbendK->pxbend = &(module->xbend);
  574. // addChild(xbendK);
  575. // }
  576. xPos = 127.5f;
  577. yPos = 328.f;
  578. addInput(Port::create<moDllzPort>(Vec(xPos,yPos), Port::INPUT, module, XBender::XBENDCV_INPUT));
  579. addParam(ParamWidget::create<TTrimSnap>(Vec(xPos + 26.5f,yPos + 7.f), module, XBender::XBENDCVTRIM_PARAM, 0.f, 24.f, 24.f));
  580. xPos = 127.5f;
  581. yPos = 328.f;
  582. addInput(Port::create<moDllzPort>(Vec(xPos,yPos), Port::INPUT, module, XBender::XBENDCV_INPUT));
  583. addParam(ParamWidget::create<TTrimSnap>(Vec(xPos + 26.5f,yPos + 7.f), module, XBender::XBENDCVTRIM_PARAM, 0.f, 24.f, 24.f));
  584. //XBEND RANGE
  585. xPos = 181.f;
  586. yPos = 288.f;
  587. addParam(ParamWidget::create<RangeSelector>(Vec(xPos, yPos), module, XBender::XBENDRANGE_PARAM, 1.f, 5.f, 1.f));
  588. xPos = 187.5f;
  589. yPos = 328.f;
  590. addInput(Port::create<moDllzPort>(Vec(xPos,yPos), Port::INPUT, module, XBender::XBENDRANGE_INPUT));
  591. //BEND
  592. xPos = 219.f;
  593. yPos = 288.f;
  594. addParam(ParamWidget::create<moDllzKnobM>(Vec(xPos, yPos), module, XBender::BEND_PARAM, -1.f, 1.f, 0.f));
  595. xPos = 218.5f;
  596. yPos = 328.f;
  597. addInput(Port::create<moDllzPort>(Vec(xPos,yPos), Port::INPUT, module, XBender::BENDCV_INPUT));
  598. addParam(ParamWidget::create<TTrimSnap>(Vec(xPos + 26.5f,yPos + 7.f), module, XBender::BENDCVTRIM_PARAM, 0.f, 60.f, 12.f));
  599. // {
  600. // testDisplay *mDisplay = new testDisplay();
  601. // mDisplay->box.pos = Vec(0.0f, 360.0f);
  602. // mDisplay->box.size = {165.0f, 20.0f};
  603. // mDisplay->valP = &(module->testVal);
  604. // addChild(mDisplay);
  605. // }
  606. }
  607. };
  608. // Specify the Module and ModuleWidget subclass, human-readable
  609. // manufacturer name for categorization, module slug (should never
  610. // change), human-readable module name, and any number of tags
  611. // (found in `include/tags.hpp`) separated by commas.
  612. } // namespace rack_plugin_moDllz
  613. using namespace rack_plugin_moDllz;
  614. RACK_PLUGIN_MODEL_INIT(moDllz, XBender) {
  615. Model *modelXBender = Model::create<XBender, XBenderWidget>("moDllz", "XBender", "Poly X Bender",MULTIPLE_TAG ,EFFECT_TAG);
  616. return modelXBender;
  617. }