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.

247 lines
7.1KB

  1. //**************************************************************************************
  2. //TriggersMKII module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS
  3. //
  4. //**************************************************************************************
  5. #include "AS.hpp"
  6. #include "dsp/digital.hpp"
  7. #include <sstream>
  8. #include <iomanip>
  9. //#include <iostream>
  10. //#include <cmath>
  11. struct TriggersMKII: Module {
  12. enum ParamIds {
  13. LABEL_PARAM_1,
  14. LABEL_PARAM_2,
  15. TRIGGER_SWITCH_1,
  16. MOMENTARY_SWITCH_2,
  17. NUM_PARAMS
  18. };
  19. enum InputIds {
  20. CV_TRIG_INPUT_1,
  21. CV_TRIG_INPUT_2,
  22. NUM_INPUTS
  23. };
  24. enum OutputIds {
  25. TRIGGER_OUT1,
  26. MOMENTARY_OUT2,
  27. NUM_OUTPUTS
  28. };
  29. enum LightIds {
  30. RUN_LED,
  31. TRIGGER_LED_1,
  32. MOMENTARY_LED_2,
  33. NUM_LIGHTS
  34. };
  35. SchmittTrigger btnTrigger1;
  36. SchmittTrigger extTrigger1;
  37. SchmittTrigger btnTrigger2;
  38. SchmittTrigger extTrigger2;
  39. const float lightLambda = 0.075f;
  40. float resetLight1 = 0.0f;
  41. float resetLight2 = 0.0f;
  42. int label_num1 = 0;
  43. int label_num2 = 0;
  44. TriggersMKII() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  45. void step() override;
  46. };
  47. void TriggersMKII::step() {
  48. label_num1 = roundf(params[LABEL_PARAM_1].value);
  49. label_num2 = roundf(params[LABEL_PARAM_2].value);
  50. outputs[TRIGGER_OUT1].value = 0.0f;
  51. outputs[MOMENTARY_OUT2].value = 0.0f;
  52. //TRIGGER 1
  53. //EXTERNAL TRIGGER
  54. if (btnTrigger1.process(params[TRIGGER_SWITCH_1].value)) {
  55. resetLight1 = 1.0;
  56. outputs[TRIGGER_OUT1].value = 10.0f;
  57. //INTERNAL TRIGGER
  58. }else if (extTrigger1.process(inputs[CV_TRIG_INPUT_1].value)) {
  59. resetLight1 = 1.0;
  60. outputs[TRIGGER_OUT1].value = 10.0f;
  61. }else{
  62. outputs[TRIGGER_OUT1].value = 0.0f;
  63. }
  64. resetLight1 -= resetLight1 / lightLambda / engineGetSampleRate();
  65. lights[TRIGGER_LED_1].value = resetLight1;
  66. //TRIGGER 2
  67. //EXTERNAL TRIGGER
  68. if (btnTrigger2.process(params[MOMENTARY_SWITCH_2].value)) {
  69. resetLight2 = 1.0;
  70. outputs[MOMENTARY_OUT2].value = 10.0f;
  71. //INTERNAL TRIGGER
  72. }else if (extTrigger2.process(inputs[CV_TRIG_INPUT_2].value)) {
  73. resetLight2 = 1.0;
  74. outputs[MOMENTARY_OUT2].value = 10.0f;
  75. }else{
  76. outputs[MOMENTARY_OUT2].value = 0.0f;
  77. }
  78. resetLight2 -= resetLight2 / lightLambda / engineGetSampleRate();
  79. lights[MOMENTARY_LED_2].value = resetLight2;
  80. }
  81. static const char *label_values[] = {
  82. "------",
  83. " MUTE",
  84. " SOLO",
  85. " RESET",
  86. " DRUMS",
  87. " KICK",
  88. " SNARE",
  89. " HIHAT",
  90. " CLAP",
  91. " PERC",
  92. "BASS 1",
  93. "BASS 2",
  94. " GTR 1",
  95. " GTR 2",
  96. "LEAD 1",
  97. "LEAD 2",
  98. " PAD 1",
  99. " PAD 2",
  100. "CHORDS",
  101. " FX 1",
  102. " FX 2",
  103. " SEQ 1",
  104. " SEQ 2",
  105. " MIX 1",
  106. " MIX 2",
  107. " AUX 1",
  108. " AUX 2",
  109. " ON",
  110. " OFF",
  111. " START",
  112. " STOP",
  113. " PAUSE",
  114. " UP",
  115. " DOWN",
  116. " LEFT",
  117. " RIGHT",
  118. " RUN",
  119. };
  120. ///////////////////////////////////
  121. struct LabelDisplayWidget : TransparentWidget {
  122. int *value;
  123. std::shared_ptr<Font> font;
  124. LabelDisplayWidget() {
  125. font = Font::load(assetPlugin(plugin, "res/saxmono.ttf"));
  126. };
  127. void draw(NVGcontext *vg) override
  128. {
  129. // Background
  130. //NVGcolor backgroundColor = nvgRGB(0x20, 0x20, 0x20);
  131. NVGcolor backgroundColor = nvgRGB(0x20, 0x10, 0x10);
  132. NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10);
  133. nvgBeginPath(vg);
  134. nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 4.0);
  135. nvgFillColor(vg, backgroundColor);
  136. nvgFill(vg);
  137. nvgStrokeWidth(vg, 1.5);
  138. nvgStrokeColor(vg, borderColor);
  139. nvgStroke(vg);
  140. // text
  141. nvgFontSize(vg, 18);
  142. nvgFontFaceId(vg, font->handle);
  143. nvgTextLetterSpacing(vg, 2.0);
  144. std::stringstream to_display;
  145. to_display << std::right << std::setw(5) << *value;
  146. Vec textPos = Vec(4.0f, 16.0f);
  147. NVGcolor textColor = nvgRGB(0xdf, 0xd2, 0x2c);
  148. nvgFillColor(vg, nvgTransRGBA(textColor, 16));
  149. nvgText(vg, textPos.x, textPos.y, "000000", NULL);
  150. textColor = nvgRGB(0xda, 0xe9, 0x29);
  151. nvgFillColor(vg, nvgTransRGBA(textColor, 16));
  152. nvgText(vg, textPos.x, textPos.y, "------", NULL);
  153. textColor = nvgRGB(0xf0, 0x00, 0x00);
  154. nvgFillColor(vg, textColor);
  155. //nvgText(vg, textPos.x, textPos.y, to_display.str().c_str(), NULL);
  156. nvgText(vg, textPos.x, textPos.y, label_values[*value], NULL);
  157. }
  158. };
  159. ////////////////////////////////////
  160. struct TriggersMKIIWidget : ModuleWidget
  161. {
  162. TriggersMKIIWidget(TriggersMKII *module);
  163. };
  164. TriggersMKIIWidget::TriggersMKIIWidget(TriggersMKII *module) : ModuleWidget(module) {
  165. setPanel(SVG::load(assetPlugin(plugin, "res/TriggersMKII.svg")));
  166. //SCREWS
  167. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, 0)));
  168. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  169. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  170. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  171. static const float led_offset = 3.3;
  172. static const float led_center = 15;
  173. static const float y_offset = 150;
  174. //TRIGGER 1
  175. //LABEL DISPLAY
  176. LabelDisplayWidget *display1 = new LabelDisplayWidget();
  177. display1->box.pos = Vec(6,50);
  178. display1->box.size = Vec(78, 20);
  179. display1->value = &module->label_num1;
  180. addChild(display1);
  181. //PARAM
  182. addParam(ParamWidget::create<as_KnobBlack>(Vec(46, 77), module, TriggersMKII::LABEL_PARAM_1, 0.0, 36.0, 0.0));
  183. //SWITCH
  184. addParam(ParamWidget::create<BigLEDBezel>(Vec(led_center, 132), module, TriggersMKII::TRIGGER_SWITCH_1, 0.0, 1.0, 0.0));
  185. addChild(ModuleLightWidget::create<GiantLight<RedLight>>(Vec(led_center+led_offset, 132+led_offset), module, TriggersMKII::TRIGGER_LED_1));
  186. //PORTS
  187. addOutput(Port::create<as_PJ301MPort>(Vec(7, 78), Port::OUTPUT, module, TriggersMKII::TRIGGER_OUT1));
  188. addInput(Port::create<as_PJ301MPort>(Vec(7, 104), Port::INPUT, module, TriggersMKII::CV_TRIG_INPUT_1));
  189. //TRIGGER 2
  190. //LABEL DISPLAY
  191. LabelDisplayWidget *display2 = new LabelDisplayWidget();
  192. display2->box.pos = Vec(6,50+y_offset);
  193. display2->box.size = Vec(78, 20);
  194. display2->value = &module->label_num2;
  195. addChild(display2);
  196. //PARAM
  197. addParam(ParamWidget::create<as_KnobBlack>(Vec(46, 77+y_offset), module, TriggersMKII::LABEL_PARAM_2, 0.0, 36.0, 0.0));
  198. //SWITCH
  199. addParam(ParamWidget::create<BigLEDBezel>(Vec(led_center, 132+y_offset), module, TriggersMKII::MOMENTARY_SWITCH_2, 0.0, 1.0, 0.0));
  200. addChild(ModuleLightWidget::create<GiantLight<RedLight>>(Vec(led_center+led_offset, 132+led_offset+y_offset), module, TriggersMKII::MOMENTARY_LED_2));
  201. //PORTS
  202. addOutput(Port::create<as_PJ301MPort>(Vec(7, 78+y_offset), Port::OUTPUT, module, TriggersMKII::MOMENTARY_OUT2));
  203. addInput(Port::create<as_PJ301MPort>(Vec(7, 104+y_offset), Port::INPUT, module, TriggersMKII::CV_TRIG_INPUT_2));
  204. }
  205. RACK_PLUGIN_MODEL_INIT(AS, TriggersMKII) {
  206. Model *modelTriggersMKII = Model::create<TriggersMKII, TriggersMKIIWidget>("AS", "TriggersMKII", "Triggers MKII", SWITCH_TAG, UTILITY_TAG);
  207. return modelTriggersMKII;
  208. }