gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

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 }