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.

152 lines
3.2KB

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