commit d60227ee878cba8e3d4398c10ffbfe63f209b411
parent a7c089b874a8d0dea67074413e0619e0a41d059c
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Tue, 19 Nov 2024 22:12:36 +0100
rework vm map indicators to be relative to the base parameter value
Diffstat:
5 files changed, 189 insertions(+), 40 deletions(-)
diff --git a/source/jucePluginEditorLib/focusedParameter.cpp b/source/jucePluginEditorLib/focusedParameter.cpp
@@ -83,10 +83,13 @@ namespace jucePluginEditorLib
void FocusedParameter::onMouseEnter(const juce::MouseEvent& _event)
{
- auto* component = _event.eventComponent;
+ updateByComponent(_event.eventComponent);
+ }
- if(component && component->getProperties().contains("parameter"))
- updateControlLabel(component, Priority::High);
+ void FocusedParameter::updateByComponent(juce::Component* _comp)
+ {
+ if(_comp && _comp->getProperties().contains("parameter"))
+ updateControlLabel(_comp, Priority::High);
}
void FocusedParameter::updateParameter(const std::string& _name, const std::string& _value)
diff --git a/source/jucePluginEditorLib/focusedParameter.h b/source/jucePluginEditorLib/focusedParameter.h
@@ -41,6 +41,8 @@ namespace jucePluginEditorLib
void onMouseEnter(const juce::MouseEvent& _event);
+ void updateByComponent(juce::Component* _comp);
+
virtual void updateParameter(const std::string& _name, const std::string& _value);
private:
diff --git a/source/nord/n2x/n2xJucePlugin/n2xEditor.h b/source/nord/n2x/n2xJucePlugin/n2xEditor.h
@@ -59,6 +59,12 @@ namespace n2xJucePlugin
return *m_lcd.get();
}
+ FocusedParameter& getFocusedParameter() const
+ {
+ assert(m_focusedParameter);
+ return *m_focusedParameter;
+ }
+
private:
void mouseEnter(const juce::MouseEvent& _ev) override;
void onBtSave() const;
diff --git a/source/nord/n2x/n2xJucePlugin/n2xVmMap.cpp b/source/nord/n2x/n2xJucePlugin/n2xVmMap.cpp
@@ -6,28 +6,96 @@
namespace n2xJucePlugin
{
constexpr const char* g_postfix = "Sens";
- constexpr float g_enabledAlpha = 0.5f;
+
+ class SliderListener : public juce::Slider::Listener
+ {
+ public:
+ SliderListener() = delete;
+
+ SliderListener(const SliderListener&) = delete;
+ SliderListener(SliderListener&&) = default;
+
+ SliderListener& operator=(const SliderListener&) = delete;
+ SliderListener& operator=(SliderListener&&) = default;
+
+ SliderListener(juce::Slider* _slider, const std::function<void(juce::Slider*)>& _onValueChanged) : m_slider(_slider), m_onValueChanged(_onValueChanged)
+ {
+ _slider->addListener(this);
+ }
+ ~SliderListener() override
+ {
+ m_slider->removeListener(this);
+ }
+ void sliderValueChanged(juce::Slider* _slider) override
+ {
+ if (m_onValueChanged)
+ m_onValueChanged(_slider);
+ }
+ private:
+ juce::Slider* m_slider;
+ std::function<void(juce::Slider*)> m_onValueChanged;
+ };
VmMap::VmMap(Editor& _editor, pluginLib::ParameterBinding& _binding)
: m_editor(_editor)
- , m_binding(_binding)
, m_btVmMap(_editor.findComponentT<juce::Button>("VMMAP"))
{
- const auto& c = _editor.getN2xController();
+ auto& c = _editor.getN2xController();
+
const auto& descs = c.getParameterDescriptions().getDescriptions();
for (const auto& desc : descs)
{
- uint32_t idx;
+ uint32_t idxBase, idxVm;
+
+ const auto& nameBase = desc.name;
+ const auto& nameVm = desc.name + g_postfix;
+
+ if(c.getParameterDescriptions().getIndexByName(idxBase, nameBase) &&
+ c.getParameterDescriptions().getIndexByName(idxVm, nameVm))
+ {
+ auto* compBase = _editor.findComponentByParamT<juce::Slider>(nameBase);
+ auto* compVm = _editor.findComponentByParamT<juce::Slider>(nameVm);
+
+ // we do not want vm params to be bound at all, we do this manually. Remove any binding that might still be present in a skin
+ _binding.unbind(compVm);
+
+ auto vmParam = std::make_unique<VmParam>();
+
+ vmParam->paramNameBase = nameBase;
+ vmParam->paramNameVm = nameVm;
+ vmParam->compBase = compBase;
+ vmParam->compVm = compVm;
- if(c.getParameterDescriptions().getIndexByName(idx, desc.name + g_postfix))
- m_paramNames.insert(desc.name);
+ vmParam->sliderListenerVm = new SliderListener(compVm, [this, vmParam = vmParam.get()](juce::Slider* _slider)
+ {
+ onVmSliderChanged(*vmParam);
+ });
+
+ m_vmParams.push_back(std::move(vmParam));
+ }
}
m_btVmMap->onClick = [this]
{
toggleVmMap(m_btVmMap->getToggleState());
};
+ m_onCurrentPartChanged.set(c.onCurrentPartChanged, [this](const uint8_t&/* _part*/)
+ {
+ onCurrentPartChanged();
+ });
+
+ bindAll();
+ }
+
+ void VmMap::setEnabled(bool _enabled)
+ {
+ toggleVmMap(_enabled);
+ }
+
+ VmMap::VmParam::~VmParam()
+ {
+ delete sliderListenerVm;
}
void VmMap::toggleVmMap(const bool _enabled)
@@ -35,48 +103,83 @@ namespace n2xJucePlugin
if(m_enabled == _enabled)
return;
- const auto wasEnabled = m_enabled;
-
m_enabled = _enabled;
- const auto& controller = m_editor.getN2xController();
+ for (auto& vmParam : m_vmParams)
+ {
+ vmParam->compVm->setInterceptsMouseClicks(_enabled, _enabled);
+ vmParam->compBase->setInterceptsMouseClicks(!_enabled, !_enabled);
+ vmParam->compVm->setEnabled(_enabled);
+ vmParam->compBase->setEnabled(!_enabled);
+ }
+
+ m_btVmMap->setToggleState(_enabled, juce::dontSendNotification);
+ }
+
+ void VmMap::onCurrentPartChanged() const
+ {
+ bindAll();
+ }
+
+ void VmMap::bindAll() const
+ {
+ const auto part = m_editor.getN2xController().getCurrentPart();
- // initial setup, collect all default-bound components. Only executed once and delayed
- // because in our constructor the components might not be bound yet
- if(m_boundComponents.empty())
+ for (auto& vmParamPtr : m_vmParams)
{
- for(const auto& name : m_paramNames)
+ auto& vmParam = *vmParamPtr;
+
+ auto* paramBase = m_editor.getN2xController().getParameter(vmParam.paramNameBase, part);
+ auto* paramVm = m_editor.getN2xController().getParameter(vmParam.paramNameVm, part);
+
+ vmParam.paramBase = paramBase;
+ vmParam.paramVm = paramVm;
+
+ vmParam.parameterListenerBase.set(paramBase, [&vmParam, this](pluginLib::Parameter* _parameter)
{
- const auto paramIdxDefault = controller.getParameterIndexByName(name);
- const auto paramDefault = controller.getParameter(paramIdxDefault);
+ onBaseParamChanged(vmParam, _parameter);
+ });
- auto* comp = m_binding.getBoundComponent(paramDefault);
+ vmParam.parameterListenerVm.set(paramVm, [&vmParam, this](pluginLib::Parameter* _parameter)
+ {
+ onVmParamChanged(vmParam, _parameter);
+ });
- if(comp)
- m_boundComponents.insert({name, comp});
- }
+ updateVmSlider(vmParam);
}
+ }
- for (const auto& paramName : m_paramNames)
- {
- const auto paramIdxDefault = controller.getParameterIndexByName(paramName);
- const auto paramIdxVm = controller.getParameterIndexByName(paramName + g_postfix);
+ void VmMap::onVmSliderChanged(const VmParam& _param) const
+ {
+ if (!_param.paramBase || !_param.paramVm)
+ return;
- auto it = m_boundComponents.find(paramName);
+ int value = juce::roundToInt(_param.compVm->getValue());
+ value -= _param.paramBase->getUnnormalizedValue();
- if(it == m_boundComponents.end())
- continue;
+ _param.paramVm->setUnnormalizedValue(value, pluginLib::Parameter::Origin::Ui);
- auto* comp = it->second;
+ m_editor.getFocusedParameter().updateByComponent(_param.compVm);
+ }
- m_binding.unbind(comp);
- m_boundComponents.erase(it);
+ void VmMap::onBaseParamChanged(const VmParam& _vmParam, pluginLib::Parameter*)
+ {
+ updateVmSlider(_vmParam);
+ }
+
+ void VmMap::onVmParamChanged(const VmParam& _vmParam, pluginLib::Parameter*)
+ {
+ updateVmSlider(_vmParam);
+ }
- m_binding.bind(*comp, _enabled ? paramIdxVm : paramIdxDefault, pluginLib::ParameterBinding::CurrentPart);
+ void VmMap::updateVmSlider(const VmParam& _vmParam)
+ {
+ const auto& range = _vmParam.compBase->getRange();
+ _vmParam.compVm->setRange(range.getStart(), range.getEnd());
- m_boundComponents.insert({paramName, comp});
+ const auto baseValue = _vmParam.paramBase->getUnnormalizedValue();
- comp->setAlpha(_enabled ? g_enabledAlpha : 1.0f);
- }
+ _vmParam.compVm->setValue(baseValue + _vmParam.paramVm->getUnnormalizedValue(), juce::dontSendNotification);
+ _vmParam.compVm->setDoubleClickReturnValue(true, baseValue);
}
}
diff --git a/source/nord/n2x/n2xJucePlugin/n2xVmMap.h b/source/nord/n2x/n2xJucePlugin/n2xVmMap.h
@@ -2,7 +2,10 @@
#include <map>
#include <string>
-#include <set>
+#include <vector>
+
+#include "n2xFocusedParameter.h"
+#include "jucePluginLib/event.h"
namespace pluginLib
{
@@ -11,6 +14,7 @@ namespace pluginLib
namespace juce
{
+ class Slider;
class Component;
class Button;
}
@@ -19,20 +23,51 @@ namespace n2xJucePlugin
{
class Editor;
+ class SliderListener;
+
class VmMap
{
public:
explicit VmMap(Editor& _editor, pluginLib::ParameterBinding& _binding);
+ void setEnabled(bool _enabled);
+
private:
+ struct VmParam
+ {
+ ~VmParam();
+
+ std::string paramNameBase;
+ std::string paramNameVm;
+
+ pluginLib::Parameter* paramBase = nullptr;
+ pluginLib::Parameter* paramVm = nullptr;
+
+ juce::Slider* compBase = nullptr;
+ juce::Slider* compVm = nullptr;
+
+ pluginLib::ParameterListener parameterListenerBase;
+ pluginLib::ParameterListener parameterListenerVm;
+
+ SliderListener* sliderListenerVm = nullptr;
+ };
+
void toggleVmMap(bool _enabled);
+ void onCurrentPartChanged() const;
+ void bindAll() const;
+
+ void onVmSliderChanged(const VmParam& _param) const;
+
+ static void onBaseParamChanged(const VmParam& _vmParam, pluginLib::Parameter* _baseParam);
+ static void onVmParamChanged(const VmParam& _vmParam, pluginLib::Parameter* _baseParam);
+
+ static void updateVmSlider(const VmParam& _vmParam);
Editor& m_editor;
- pluginLib::ParameterBinding& m_binding;
- std::set<std::string> m_paramNames;
- std::map<std::string, juce::Component*> m_boundComponents;
+ std::vector<std::unique_ptr<VmParam>> m_vmParams;
juce::Button* m_btVmMap;
bool m_enabled = false;
+ pluginLib::EventListener<uint8_t> m_onCurrentPartChanged;
};
}