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.

211 lines
5.5KB

  1. //***********************************************************************************************
  2. //Geodesics: A modular collection for VCV Rack by Pierre Collard and Marc Boulé
  3. //
  4. //Based on code from Valley Rack Free by Dale Johnson
  5. //See ./LICENSE.txt for all licenses
  6. //***********************************************************************************************
  7. #include "GeoWidgets.hpp"
  8. namespace rack_plugin_Geodesics {
  9. // Dynamic SVGPanel
  10. void PanelBorderWidget::draw(NVGcontext *vg) { // carbon copy from SVGPanel.cpp
  11. NVGcolor borderColor = nvgRGBAf(0.5, 0.5, 0.5, 0.5);
  12. nvgBeginPath(vg);
  13. nvgRect(vg, 0.5, 0.5, box.size.x - 1.0, box.size.y - 1.0);// full rect of module (including expansion area if a module has one)
  14. nvgStrokeColor(vg, borderColor);
  15. nvgStrokeWidth(vg, 1.0);
  16. nvgStroke(vg);
  17. if (expWidth != nullptr && *expWidth != nullptr) {// add expansion division when pannel uses expansion area
  18. int expW = **expWidth;
  19. nvgBeginPath(vg);
  20. nvgMoveTo(vg, box.size.x - expW, 1);
  21. nvgLineTo(vg, box.size.x - expW, box.size.y - 1.0);
  22. nvgStrokeWidth(vg, 2.0);
  23. nvgStroke(vg);
  24. }
  25. }
  26. DynamicSVGPanel::DynamicSVGPanel() {
  27. mode = nullptr;
  28. oldMode = -1;
  29. expWidth = nullptr;
  30. visiblePanel = new SVGWidget();
  31. addChild(visiblePanel);
  32. border = new PanelBorderWidget();
  33. border->expWidth = &expWidth;
  34. addChild(border);
  35. }
  36. void DynamicSVGPanel::addPanel(std::shared_ptr<SVG> svg) {
  37. panels.push_back(svg);
  38. if(!visiblePanel->svg) {
  39. visiblePanel->setSVG(svg);
  40. box.size = visiblePanel->box.size.div(RACK_GRID_SIZE).round().mult(RACK_GRID_SIZE);
  41. border->box.size = box.size;
  42. }
  43. }
  44. void DynamicSVGPanel::step() { // all code except middle if() from SVGPanel::step() in SVGPanel.cpp
  45. if (isNear(rack::global_ui->window.gPixelRatio, 1.0)) {
  46. // Small details draw poorly at low DPI, so oversample when drawing to the framebuffer
  47. oversample = 2.f;
  48. }
  49. if(mode != nullptr && *mode != oldMode) {
  50. if ((unsigned)(*mode) < panels.size()) {
  51. visiblePanel->setSVG(panels[*mode]);
  52. dirty = true;
  53. }
  54. oldMode = *mode;
  55. }
  56. FramebufferWidget::step();
  57. }
  58. // Dynamic SVGPort
  59. DynamicSVGPort::DynamicSVGPort() {
  60. mode = nullptr;
  61. oldMode = -1;
  62. //SVGPort constructor automatically called
  63. }
  64. void DynamicSVGPort::addFrame(std::shared_ptr<SVG> svg) {
  65. frames.push_back(svg);
  66. if(!background->svg)
  67. SVGPort::setSVG(svg);
  68. }
  69. void DynamicSVGPort::step() {
  70. if (isNear(rack::global_ui->window.gPixelRatio, 1.0)) {
  71. // Small details draw poorly at low DPI, so oversample when drawing to the framebuffer
  72. oversample = 2.f;
  73. }
  74. if(mode != nullptr && *mode != oldMode) {
  75. if ((unsigned)(*mode) < frames.size()) {
  76. background->setSVG(frames[*mode]);
  77. dirty = true;
  78. }
  79. oldMode = *mode;
  80. }
  81. Port::step();
  82. }
  83. // Dynamic SVGSwitch
  84. DynamicSVGSwitch::DynamicSVGSwitch() {
  85. mode = nullptr;
  86. oldMode = -1;
  87. //SVGSwitch constructor automatically called
  88. }
  89. void DynamicSVGSwitch::addFrameAll(std::shared_ptr<SVG> svg) {
  90. framesAll.push_back(svg);
  91. if (framesAll.size() == 2) {
  92. addFrame(framesAll[0]);
  93. addFrame(framesAll[1]);
  94. }
  95. }
  96. void DynamicSVGSwitch::step() {
  97. if (isNear(rack::global_ui->window.gPixelRatio, 1.0)) {
  98. // Small details draw poorly at low DPI, so oversample when drawing to the framebuffer
  99. oversample = 2.f;
  100. }
  101. if(mode != nullptr && *mode != oldMode) {
  102. if ((unsigned)(*mode) * 2 + 1 < framesAll.size()) {
  103. if ((*mode) == 0) {
  104. frames[0]=framesAll[0];
  105. frames[1]=framesAll[1];
  106. }
  107. else {
  108. frames[0]=framesAll[2];
  109. frames[1]=framesAll[3];
  110. }
  111. onChange(*(new EventChange()));// required because of the way SVGSwitch changes images, we only change the frames above.
  112. //dirty = true;// dirty is not sufficient when changing via frames assignments above (i.e. onChange() is required)
  113. }
  114. oldMode = *mode;
  115. }
  116. }
  117. // Dynamic SVGKnob
  118. DynamicSVGKnob::DynamicSVGKnob() {
  119. //SVGKnob constructor automatically called first
  120. mode = nullptr;
  121. oldMode = -1;
  122. effect = nullptr;
  123. orientationAngle = 0.0f;
  124. }
  125. void DynamicSVGKnob::addFrameAll(std::shared_ptr<SVG> svg) {
  126. framesAll.push_back(svg);
  127. if (framesAll.size() == 1) {
  128. setSVG(svg);
  129. }
  130. }
  131. void DynamicSVGKnob::addEffect(std::shared_ptr<SVG> svg) {
  132. effect = new SVGWidget();
  133. effect->setSVG(svg);
  134. addChild(effect);
  135. }
  136. void DynamicSVGKnob::step() {
  137. if (isNear(rack::global_ui->window.gPixelRatio, 1.0)) {
  138. // Small details draw poorly at low DPI, so oversample when drawing to the framebuffer
  139. oversample = 2.f;
  140. }
  141. if(mode != nullptr && *mode != oldMode) {
  142. if ((unsigned)(*mode) < framesAll.size()) {
  143. if ((*mode) == 0) {
  144. setSVG(framesAll[0]);
  145. if (effect != nullptr)
  146. effect->visible = false;
  147. }
  148. else {
  149. setSVG(framesAll[1]);
  150. if (effect != nullptr)
  151. effect->visible = true;
  152. }
  153. dirty = true;
  154. }
  155. oldMode = *mode;
  156. }
  157. //SVGKnob::step();
  158. // do code here because handle orientationAngle
  159. // Re-transform TransformWidget if dirty
  160. if (dirty) {
  161. float angle;
  162. if (isfinite(minValue) && isfinite(maxValue)) {
  163. angle = rescale(value, minValue, maxValue, minAngle, maxAngle);
  164. }
  165. else {
  166. angle = rescale(value, -1.0, 1.0, minAngle, maxAngle);
  167. angle = fmodf(angle, 2*M_PI);
  168. }
  169. angle += orientationAngle;
  170. tw->identity();
  171. // Rotate SVG
  172. Vec center = sw->box.getCenter();
  173. tw->translate(center);
  174. tw->rotate(angle);
  175. tw->translate(center.neg());
  176. }
  177. FramebufferWidget::step();
  178. }
  179. } // namespace rack_plugin_Geodesics