n2xVmMap.cpp (4972B)
1 #include "n2xVmMap.h" 2 3 #include "n2xController.h" 4 #include "n2xEditor.h" 5 6 namespace n2xJucePlugin 7 { 8 constexpr const char* g_postfix = "Sens"; 9 10 class SliderListener : public juce::Slider::Listener 11 { 12 public: 13 SliderListener() = delete; 14 15 SliderListener(const SliderListener&) = delete; 16 SliderListener(SliderListener&&) = default; 17 18 SliderListener& operator=(const SliderListener&) = delete; 19 SliderListener& operator=(SliderListener&&) = default; 20 21 SliderListener(juce::Slider* _slider, const std::function<void(juce::Slider*)>& _onValueChanged) : m_slider(_slider), m_onValueChanged(_onValueChanged) 22 { 23 _slider->addListener(this); 24 } 25 ~SliderListener() override 26 { 27 m_slider->removeListener(this); 28 } 29 void sliderValueChanged(juce::Slider* _slider) override 30 { 31 if (m_onValueChanged) 32 m_onValueChanged(_slider); 33 } 34 private: 35 juce::Slider* m_slider; 36 std::function<void(juce::Slider*)> m_onValueChanged; 37 }; 38 39 VmMap::VmMap(Editor& _editor, pluginLib::ParameterBinding& _binding) 40 : m_editor(_editor) 41 , m_btVmMap(_editor.findComponentT<juce::Button>("VMMAP")) 42 { 43 auto& c = _editor.getN2xController(); 44 45 const auto& descs = c.getParameterDescriptions().getDescriptions(); 46 47 for (const auto& desc : descs) 48 { 49 uint32_t idxBase, idxVm; 50 51 const auto& nameBase = desc.name; 52 const auto& nameVm = desc.name + g_postfix; 53 54 if(c.getParameterDescriptions().getIndexByName(idxBase, nameBase) && 55 c.getParameterDescriptions().getIndexByName(idxVm, nameVm)) 56 { 57 auto* compBase = _editor.findComponentByParamT<juce::Slider>(nameBase); 58 auto* compVm = _editor.findComponentByParamT<juce::Slider>(nameVm); 59 60 // 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 61 _binding.unbind(compVm); 62 63 auto vmParam = std::make_unique<VmParam>(); 64 65 vmParam->paramNameBase = nameBase; 66 vmParam->paramNameVm = nameVm; 67 vmParam->compBase = compBase; 68 vmParam->compVm = compVm; 69 70 vmParam->sliderListenerVm = new SliderListener(compVm, [this, vmParam = vmParam.get()](juce::Slider* _slider) 71 { 72 onVmSliderChanged(*vmParam); 73 }); 74 75 m_vmParams.push_back(std::move(vmParam)); 76 } 77 } 78 79 m_btVmMap->onClick = [this] 80 { 81 toggleVmMap(m_btVmMap->getToggleState()); 82 }; 83 m_onCurrentPartChanged.set(c.onCurrentPartChanged, [this](const uint8_t&/* _part*/) 84 { 85 onCurrentPartChanged(); 86 }); 87 88 bindAll(); 89 } 90 91 void VmMap::setEnabled(bool _enabled) 92 { 93 toggleVmMap(_enabled); 94 } 95 96 VmMap::VmParam::~VmParam() 97 { 98 delete sliderListenerVm; 99 } 100 101 void VmMap::toggleVmMap(const bool _enabled) 102 { 103 if(m_enabled == _enabled) 104 return; 105 106 m_enabled = _enabled; 107 108 for (auto& vmParam : m_vmParams) 109 { 110 vmParam->compVm->setInterceptsMouseClicks(_enabled, _enabled); 111 vmParam->compBase->setInterceptsMouseClicks(!_enabled, !_enabled); 112 vmParam->compVm->setEnabled(_enabled); 113 vmParam->compBase->setEnabled(!_enabled); 114 } 115 116 m_btVmMap->setToggleState(_enabled, juce::dontSendNotification); 117 } 118 119 void VmMap::onCurrentPartChanged() const 120 { 121 bindAll(); 122 } 123 124 void VmMap::bindAll() const 125 { 126 const auto part = m_editor.getN2xController().getCurrentPart(); 127 128 for (auto& vmParamPtr : m_vmParams) 129 { 130 auto& vmParam = *vmParamPtr; 131 132 auto* paramBase = m_editor.getN2xController().getParameter(vmParam.paramNameBase, part); 133 auto* paramVm = m_editor.getN2xController().getParameter(vmParam.paramNameVm, part); 134 135 vmParam.paramBase = paramBase; 136 vmParam.paramVm = paramVm; 137 138 vmParam.parameterListenerBase.set(paramBase, [&vmParam, this](pluginLib::Parameter* _parameter) 139 { 140 onBaseParamChanged(vmParam, _parameter); 141 }); 142 143 vmParam.parameterListenerVm.set(paramVm, [&vmParam, this](pluginLib::Parameter* _parameter) 144 { 145 onVmParamChanged(vmParam, _parameter); 146 }); 147 148 updateVmSlider(vmParam); 149 } 150 } 151 152 void VmMap::onVmSliderChanged(const VmParam& _param) const 153 { 154 if (!_param.paramBase || !_param.paramVm) 155 return; 156 157 int value = juce::roundToInt(_param.compVm->getValue()); 158 value -= _param.paramBase->getUnnormalizedValue(); 159 160 _param.paramVm->setUnnormalizedValue(value, pluginLib::Parameter::Origin::Ui); 161 162 m_editor.getFocusedParameter().updateByComponent(_param.compVm); 163 } 164 165 void VmMap::onBaseParamChanged(const VmParam& _vmParam, pluginLib::Parameter*) 166 { 167 updateVmSlider(_vmParam); 168 } 169 170 void VmMap::onVmParamChanged(const VmParam& _vmParam, pluginLib::Parameter*) 171 { 172 updateVmSlider(_vmParam); 173 } 174 175 void VmMap::updateVmSlider(const VmParam& _vmParam) 176 { 177 const auto& range = _vmParam.compBase->getRange(); 178 _vmParam.compVm->setRange(range.getStart(), range.getEnd()); 179 180 const auto baseValue = _vmParam.paramBase->getUnnormalizedValue(); 181 182 const auto offset = _vmParam.paramVm->getUnnormalizedValue(); 183 184 _vmParam.compVm->setValue(baseValue + offset, juce::dontSendNotification); 185 _vmParam.compVm->setDoubleClickReturnValue(true, baseValue); 186 187 _vmParam.compVm->setAlpha(offset != 0 ? 1.0f : 0.0f); 188 } 189 }