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.

213 lines
7.5KB

  1. //**************************************************************************************
  2. //TriggersMKIII module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS
  3. //
  4. //**************************************************************************************
  5. #include "AS.hpp"
  6. #include "window.hpp"
  7. #include "dsp/digital.hpp"
  8. struct TriggersMKIII: Module {
  9. enum ParamIds {
  10. TRIGGER_SWITCH_1,
  11. TRIGGER_SWITCH_2,
  12. NUM_PARAMS
  13. };
  14. enum InputIds {
  15. CV_TRIG_INPUT_1_1,
  16. CV_TRIG_INPUT_1_2,
  17. CV_TRIG_INPUT_2_1,
  18. CV_TRIG_INPUT_2_2,
  19. NUM_INPUTS
  20. };
  21. enum OutputIds {
  22. TRIGGER_OUT1,
  23. TRIGGER_OUT2,
  24. NUM_OUTPUTS
  25. };
  26. enum LightIds {
  27. TRIGGER_LED_1,
  28. TRIGGER_LED_2,
  29. NUM_LIGHTS
  30. };
  31. SchmittTrigger btnTrigger1, btnTrigger2;
  32. SchmittTrigger extTrigger1_1, extTrigger1_2;
  33. SchmittTrigger extTrigger2_1, extTrigger2_2;
  34. TextField* textField1;
  35. TextField* textField2;
  36. const float lightLambda = 0.075f;
  37. float resetLight1 = 0.0f;
  38. float resetLight2 = 0.0f;
  39. int label_num1 = 0;
  40. int label_num2 = 0;
  41. TriggersMKIII() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  42. void step() override;
  43. json_t *toJson()override {
  44. json_t *rootJ = json_object();
  45. // text
  46. json_object_set_new(rootJ, "label1", json_string(textField1->text.c_str()));
  47. json_object_set_new(rootJ, "label2", json_string(textField2->text.c_str()));
  48. return rootJ;
  49. }
  50. void fromJson(json_t *rootJ)override {
  51. json_t *text1J = json_object_get(rootJ, "label1");
  52. if (text1J){
  53. textField1->text = json_string_value(text1J);
  54. }
  55. json_t *text2J = json_object_get(rootJ, "label2");
  56. if (text2J){
  57. textField2->text = json_string_value(text2J);
  58. }
  59. }
  60. };
  61. void TriggersMKIII::step() {
  62. outputs[TRIGGER_OUT1].value = 0.0f;
  63. outputs[TRIGGER_OUT2].value = 0.0f;
  64. //TRIGGER 1
  65. if (btnTrigger1.process(params[TRIGGER_SWITCH_1].value) || extTrigger1_1.process(inputs[CV_TRIG_INPUT_1_1].value) || extTrigger1_2.process(inputs[CV_TRIG_INPUT_1_2].value)) {
  66. resetLight1 = 1.0;
  67. outputs[TRIGGER_OUT1].value = 10.0f;
  68. }else{
  69. outputs[TRIGGER_OUT1].value = 0.0f;
  70. }
  71. resetLight1 -= resetLight1 / lightLambda / engineGetSampleRate();
  72. lights[TRIGGER_LED_1].value = resetLight1;
  73. //TRIGGER 2
  74. //EXTERNAL TRIGGER
  75. if (btnTrigger2.process(params[TRIGGER_SWITCH_2].value) || extTrigger2_1.process(inputs[CV_TRIG_INPUT_2_1].value) || extTrigger2_2.process(inputs[CV_TRIG_INPUT_2_2].value)) {
  76. resetLight2 = 1.0;
  77. outputs[TRIGGER_OUT2].value = 10.0f;
  78. //INTERNAL TRIGGER
  79. }else{
  80. outputs[TRIGGER_OUT2].value = 0.0f;
  81. }
  82. resetLight2 -= resetLight2 / lightLambda / engineGetSampleRate();
  83. lights[TRIGGER_LED_2].value = resetLight2;
  84. }
  85. ////////////////////////////////////
  86. struct CustomLedDisplayTextField : TextField {
  87. std::shared_ptr<Font> font;
  88. Vec textOffset;
  89. NVGcolor color;
  90. CustomLedDisplayTextField(){
  91. font = Font::load(assetPlugin(plugin, "res/saxmono.ttf"));
  92. color = nvgRGB(0xf0, 0x00, 0x00);
  93. textOffset = Vec(5, 0);
  94. };
  95. void draw(NVGcontext *vg) override{
  96. nvgScissor(vg, 0, 0, box.size.x, box.size.y);
  97. // Background
  98. NVGcolor backgroundColor = nvgRGB(0x20, 0x10, 0x10);
  99. NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10);
  100. nvgBeginPath(vg);
  101. nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 4.0);
  102. nvgFillColor(vg, backgroundColor);
  103. nvgFill(vg);
  104. nvgStrokeWidth(vg, 1.5);
  105. nvgStrokeColor(vg, borderColor);
  106. nvgStroke(vg);
  107. nvgFontSize(vg, 20);
  108. // Text
  109. if (font->handle >= 0) {
  110. bndSetFont(font->handle);
  111. NVGcolor highlightColor = nvgRGB(0xf0, 0x00, 0x00);//color;
  112. highlightColor.a = 0.5;
  113. int begin = min(cursor, selection);
  114. int end = (this == RACK_PLUGIN_UI_FOCUSED_WIDGET) ? max(cursor, selection) : -1;
  115. bndIconLabelCaret(vg, textOffset.x, textOffset.y,
  116. box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y,
  117. -1, color, 12, text.c_str(), highlightColor, begin, end);
  118. }
  119. nvgResetScissor(vg);
  120. bndSetFont(rack::global_ui->window.gGuiFont->handle);
  121. }
  122. int getTextPosition(Vec mousePos)override {
  123. bndSetFont(font->handle);
  124. int textPos = bndIconLabelTextPosition(rack::global_ui->window.gVg, textOffset.x, textOffset.y,
  125. box.size.x - 2*textOffset.x, box.size.y - 2*textOffset.y,
  126. -1, 12, text.c_str(), mousePos.x, mousePos.y);
  127. bndSetFont(font->handle);
  128. return textPos;
  129. }
  130. };
  131. ////////////////////////////////////
  132. struct TriggersMKIIIWidget : ModuleWidget {
  133. TextField* textField1;
  134. TextField* textField2;
  135. TriggersMKIIIWidget(TriggersMKIII *module);
  136. };
  137. TriggersMKIIIWidget::TriggersMKIIIWidget(TriggersMKIII *module) : ModuleWidget(module) {
  138. setPanel(SVG::load(assetPlugin(plugin, "res/TriggersMKIII.svg")));
  139. //SCREWS
  140. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, 0)));
  141. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  142. addChild(Widget::create<as_HexScrew>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  143. addChild(Widget::create<as_HexScrew>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  144. static const float led_offset = 3.3;
  145. static const float led_center = 15;
  146. static const float y_offset = 150;
  147. //TRIGGER 1
  148. textField1 = Widget::create<CustomLedDisplayTextField>(Vec(6, 46));
  149. textField1->box.size = Vec(78, 30);
  150. textField1->multiline = false;
  151. addChild(textField1);
  152. module->textField1 = this->textField1;
  153. //SWITCH
  154. addParam(ParamWidget::create<BigLEDBezel>(Vec(led_center, 122), module, TriggersMKIII::TRIGGER_SWITCH_1, 0.0, 1.0, 0.0));
  155. addChild(ModuleLightWidget::create<GiantLight<RedLight>>(Vec(led_center+led_offset, 122+led_offset), module, TriggersMKIII::TRIGGER_LED_1));
  156. //PORTS
  157. addInput(Port::create<as_PJ301MPort>(Vec(8, 90), Port::INPUT, module, TriggersMKIII::CV_TRIG_INPUT_1_1));
  158. addInput(Port::create<as_PJ301MPort>(Vec(33, 90), Port::INPUT, module, TriggersMKIII::CV_TRIG_INPUT_1_2));
  159. addOutput(Port::create<as_PJ301MPort>(Vec(58, 90), Port::OUTPUT, module, TriggersMKIII::TRIGGER_OUT1));
  160. //TRIGGER 2
  161. textField2 = Widget::create<CustomLedDisplayTextField>(Vec(6, 46+y_offset));
  162. textField2->box.size = Vec(78, 30);
  163. textField2->multiline = false;
  164. addChild(textField2);
  165. module->textField2 = this->textField2;
  166. //SWITCH
  167. addParam(ParamWidget::create<BigLEDBezel>(Vec(led_center, 122+y_offset), module, TriggersMKIII::TRIGGER_SWITCH_2, 0.0, 1.0, 0.0));
  168. addChild(ModuleLightWidget::create<GiantLight<RedLight>>(Vec(led_center+led_offset, 122+led_offset+y_offset), module, TriggersMKIII::TRIGGER_LED_2));
  169. //PORTS
  170. addInput(Port::create<as_PJ301MPort>(Vec(8, 90+y_offset), Port::INPUT, module, TriggersMKIII::CV_TRIG_INPUT_2_1));
  171. addInput(Port::create<as_PJ301MPort>(Vec(33, 90+y_offset), Port::INPUT, module, TriggersMKIII::CV_TRIG_INPUT_2_2));
  172. addOutput(Port::create<as_PJ301MPort>(Vec(58, 90+y_offset), Port::OUTPUT, module, TriggersMKIII::TRIGGER_OUT2));
  173. }
  174. RACK_PLUGIN_MODEL_INIT(AS, TriggersMKIII) {
  175. Model *modelTriggersMKIII = Model::create<TriggersMKIII, TriggersMKIIIWidget>("AS", "TriggersMKIII", "Triggers MKIII", SWITCH_TAG, UTILITY_TAG);
  176. return modelTriggersMKIII;
  177. }