parameterOverlay.cpp (5314B)
1 #include "parameterOverlay.h" 2 #include "parameterOverlays.h" 3 #include "pluginEditor.h" 4 #include "imagePool.h" 5 6 #include "jucePluginLib/parameter.h" 7 #include "juceUiLib/uiObjectStyle.h" 8 9 namespace jucePluginEditorLib 10 { 11 ParameterOverlay::ParameterOverlay(ParameterOverlays& _overlays, juce::Component* _component) : m_overlays(_overlays), m_component(_component) 12 { 13 } 14 15 ParameterOverlay::~ParameterOverlay() 16 { 17 setParameter(nullptr); 18 19 for (const auto* image : m_images) 20 delete image; 21 } 22 23 void ParameterOverlay::onBind(const pluginLib::ParameterBinding::BoundParameter& _parameter) 24 { 25 setParameter(_parameter.parameter); 26 } 27 28 void ParameterOverlay::onUnbind(const pluginLib::ParameterBinding::BoundParameter&) 29 { 30 setParameter(nullptr); 31 } 32 33 ParameterOverlay::OverlayProperties ParameterOverlay::getOverlayProperties() const 34 { 35 OverlayProperties result; 36 37 const auto& editor = m_overlays.getEditor(); 38 39 auto& root = editor.getRootObject(); 40 const auto& props = m_component->getProperties(); 41 42 result.scale = root.getPropertyFloat("overlayScale", 0.2f); 43 result.scale = props.getWithDefault("overlayScale", result.scale); 44 45 std::string color = root.getProperty("overlayColor", "ffffffff"); 46 color = props.getWithDefault("overlayColor", juce::String(color)).toString().toStdString(); 47 genericUI::UiObjectStyle::parseColor(result.color, color); 48 49 result.position.x = root.getPropertyFloat("overlayPosX", 0.0f); 50 result.position.y = root.getPropertyFloat("overlayPosY", 0.0f); 51 52 result.position.x = props.getWithDefault("overlayPosX", result.position.x); 53 result.position.y = props.getWithDefault("overlayPosY", result.position.y); 54 55 return result; 56 } 57 58 void ParameterOverlay::toggleOverlay(ImagePool::Type _type, const bool _enable, float _opacity/* = 1.0f*/) 59 { 60 juce::DrawableImage*& drawableImage = m_images[static_cast<uint32_t>(_type)]; 61 62 if(_enable) 63 { 64 const auto props = getOverlayProperties(); 65 66 auto updatePosition = [&]() 67 { 68 const auto x = static_cast<int>(props.position.x) + m_component->getPosition().x; 69 const auto y = static_cast<int>(props.position.y) + m_component->getPosition().y; 70 const auto w = drawableImage->getWidth(); 71 const auto h = drawableImage->getHeight(); 72 73 drawableImage->setBoundingBox(juce::Rectangle(x - (w>>1), y - (h>>1), w, h).toFloat()); 74 }; 75 76 if(!drawableImage) 77 { 78 auto& editor = m_overlays.getEditor(); 79 80 auto* image = editor.getImagePool().getImage(_type, props.scale); 81 82 if(image) 83 { 84 drawableImage = new juce::DrawableImage(*image); 85 86 // _image->setOverlayColour(props.color); // juce cannot do it, it does not multiply but replaced the color entirely 87 drawableImage->setInterceptsMouseClicks(false, false); 88 drawableImage->setAlwaysOnTop(true); 89 m_component->getParentComponent()->addAndMakeVisible(drawableImage); 90 } 91 } 92 else 93 { 94 drawableImage->setVisible(true); 95 } 96 97 drawableImage->setOpacity(_opacity); 98 99 updatePosition(); 100 } 101 else if(drawableImage) 102 { 103 drawableImage->setVisible(false); 104 } 105 } 106 107 void ParameterOverlay::updateOverlays() 108 { 109 if(m_component->getParentComponent() == nullptr) 110 return; 111 112 const auto isLocked = m_parameter != nullptr && m_parameter->isLocked(); 113 const auto isLinkSource = m_parameter != nullptr && (m_parameter->getLinkState() & pluginLib::Source); 114 const auto isLinkTarget = m_parameter != nullptr && (m_parameter->getLinkState() & pluginLib::Target); 115 116 const auto linkAlpha = isLinkSource ? 1.0f : 0.5f; 117 118 toggleOverlay(ImagePool::Type::Lock, isLocked); 119 toggleOverlay(ImagePool::Type::Link, isLinkSource || isLinkTarget, linkAlpha); 120 121 std::array<juce::DrawableImage*, OverlayCount> visibleOverlays; 122 123 uint32_t count = 0; 124 int totalWidth = 0; 125 126 for (auto* image : m_images) 127 { 128 if(image && image->isVisible()) 129 { 130 visibleOverlays[count++] = image; 131 totalWidth += image->getWidth(); 132 } 133 } 134 135 if(count <= 1) 136 return; 137 138 const auto avgWidth = totalWidth / count; 139 140 int x = -static_cast<int>(totalWidth >> 1) + static_cast<int>(avgWidth >> 1) + static_cast<int>(visibleOverlays[0]->getBoundingBox().topLeft.x); 141 142 for(uint32_t i=0; i<count; ++i) 143 { 144 auto bounds = visibleOverlays[i]->getBoundingBox(); 145 const auto w = bounds.getWidth(); 146 const auto fx = static_cast<float>(x); 147 bounds.topLeft.x = fx; 148 bounds.bottomLeft.x = fx; 149 bounds.topRight.x = fx + w; 150 visibleOverlays[i]->setBoundingBox(bounds); 151 152 x += visibleOverlays[i]->getWidth(); 153 } 154 } 155 156 void ParameterOverlay::setParameter(pluginLib::Parameter* _parameter) 157 { 158 if(m_parameter == _parameter) 159 return; 160 161 if(m_parameter) 162 { 163 m_parameter->onLockedChanged.removeListener(m_parameterLockChangedListener); 164 m_parameter->onLinkStateChanged.removeListener(m_parameterLinkChangedListener); 165 m_parameterLockChangedListener = InvalidListenerId; 166 m_parameterLinkChangedListener = InvalidListenerId; 167 } 168 169 m_parameter = _parameter; 170 171 if(m_parameter) 172 { 173 m_parameterLockChangedListener = m_parameter->onLockedChanged.addListener([this](pluginLib::Parameter*, const bool&) 174 { 175 updateOverlays(); 176 }); 177 m_parameterLinkChangedListener = m_parameter->onLinkStateChanged.addListener([this](pluginLib::Parameter*, const pluginLib::ParameterLinkType&) 178 { 179 updateOverlays(); 180 }); 181 } 182 183 updateOverlays(); 184 } 185 }