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.

167 lines
3.6KB

  1. #include <app/ModuleLightWidget.hpp>
  2. #include <app/Scene.hpp>
  3. #include <context.hpp>
  4. #include <settings.hpp>
  5. namespace rack {
  6. namespace app {
  7. struct ModuleLightWidget::Internal {
  8. ui::Tooltip* tooltip = NULL;
  9. };
  10. struct LightTooltip : ui::Tooltip {
  11. ModuleLightWidget* lightWidget;
  12. void step() override {
  13. if (lightWidget->module) {
  14. engine::LightInfo* lightInfo = lightWidget->getLightInfo();
  15. if (!lightInfo)
  16. return;
  17. // Label
  18. std::string name = lightInfo->getName();
  19. text = string::f(string::translate("ModuleLightWidget.light"), name);
  20. // Description
  21. std::string description = lightInfo->getDescription();
  22. if (description != "") {
  23. text += "\n";
  24. text += description;
  25. }
  26. // Brightness for each color
  27. text += "\n";
  28. int numColors = lightWidget->getNumColors();
  29. for (int colorId = 0; colorId < numColors; colorId++) {
  30. if (colorId > 1)
  31. text += " ";
  32. engine::Light* light = lightWidget->getLight(colorId);
  33. float brightness = math::clamp(light->getBrightness(), 0.f, 1.f);
  34. text += string::f("% 3.0f%%", brightness * 100.f);
  35. }
  36. }
  37. Tooltip::step();
  38. // Position at bottom-right of parameter
  39. box.pos = lightWidget->getAbsoluteOffset(lightWidget->box.size).round();
  40. // Fit inside parent (copied from Tooltip.cpp)
  41. assert(parent);
  42. box = box.nudge(parent->box.zeroPos());
  43. }
  44. };
  45. ModuleLightWidget::ModuleLightWidget() {
  46. internal = new Internal;
  47. }
  48. ModuleLightWidget::~ModuleLightWidget() {
  49. destroyTooltip();
  50. delete internal;
  51. }
  52. engine::Light* ModuleLightWidget::getLight(int colorId) {
  53. if (!module)
  54. return NULL;
  55. if (firstLightId < 0)
  56. return NULL;
  57. return &module->lights[firstLightId + colorId];
  58. }
  59. engine::LightInfo* ModuleLightWidget::getLightInfo() {
  60. if (!module)
  61. return NULL;
  62. if (firstLightId < 0)
  63. return NULL;
  64. return module->lightInfos[firstLightId];
  65. }
  66. void ModuleLightWidget::createTooltip() {
  67. if (!settings::tooltips)
  68. return;
  69. if (internal->tooltip)
  70. return;
  71. // If the LightInfo is null, don't show a tooltip
  72. if (!getLightInfo())
  73. return;
  74. LightTooltip* tooltip = new LightTooltip;
  75. tooltip->lightWidget = this;
  76. APP->scene->addChild(tooltip);
  77. internal->tooltip = tooltip;
  78. }
  79. void ModuleLightWidget::destroyTooltip() {
  80. if (!internal->tooltip)
  81. return;
  82. APP->scene->removeChild(internal->tooltip);
  83. delete internal->tooltip;
  84. internal->tooltip = NULL;
  85. }
  86. void ModuleLightWidget::step() {
  87. std::vector<float> brightnesses(baseColors.size());
  88. int lastLightId = firstLightId + (int) baseColors.size();
  89. if (module) {
  90. if (module->isBypassed()) {
  91. // Leave lights off
  92. }
  93. else if (0 <= firstLightId && lastLightId <= (int) module->lights.size()) {
  94. for (size_t i = 0; i < baseColors.size(); i++) {
  95. float b = module->lights[firstLightId + i].getBrightness();
  96. if (!std::isfinite(b))
  97. b = 0.f;
  98. b = math::clamp(b, 0.f, 1.f);
  99. // Because LEDs are nonlinear, this seems to look more natural.
  100. b = std::sqrt(b);
  101. brightnesses[i] = b;
  102. }
  103. }
  104. }
  105. else {
  106. // Turn all lights on
  107. for (size_t i = 0; i < baseColors.size(); i++) {
  108. brightnesses[i] = 1.f;
  109. }
  110. }
  111. setBrightnesses(brightnesses);
  112. MultiLightWidget::step();
  113. }
  114. void ModuleLightWidget::onHover(const HoverEvent& e) {
  115. // Adapted from OpaqueWidget::onHover()
  116. Widget::onHover(e);
  117. // If the LightInfo is null, don't consume Hover event
  118. if (!getLightInfo())
  119. return;
  120. e.stopPropagating();
  121. // Consume if not consumed by child
  122. if (!e.isConsumed())
  123. e.consume(this);
  124. }
  125. void ModuleLightWidget::onEnter(const EnterEvent& e) {
  126. createTooltip();
  127. }
  128. void ModuleLightWidget::onLeave(const LeaveEvent& e) {
  129. destroyTooltip();
  130. }
  131. } // namespace app
  132. } // namespace rack