| @@ -14,7 +14,10 @@ namespace engine { | |||||
| struct Module; | struct Module; | ||||
| /** A Quantity that wraps an engine::Param. */ | |||||
| /** A Quantity that wraps an engine::Param. | |||||
| If `smoothEnabled` is true, all methods access/modify the target value of the Engine's smoothing algorithm for a Param instead of the value directly. | |||||
| */ | |||||
| struct ParamQuantity : Quantity { | struct ParamQuantity : Quantity { | ||||
| Module* module = NULL; | Module* module = NULL; | ||||
| int paramId = -1; | int paramId = -1; | ||||
| @@ -64,11 +67,26 @@ struct ParamQuantity : Quantity { | |||||
| bool snapEnabled = false; | bool snapEnabled = false; | ||||
| Param* getParam(); | Param* getParam(); | ||||
| /** If smoothEnabled is true, requests to the engine to smoothly move to a target value each sample. */ | |||||
| void setSmoothValue(float value); | |||||
| float getSmoothValue(); | |||||
| /** Deprecated. Use setValue() instead. */ | |||||
| DEPRECATED void setSmoothValue(float value); | |||||
| /** Deprecated. Use getValue() instead. */ | |||||
| DEPRECATED float getSmoothValue(); | |||||
| void setDirectValue(float value); | |||||
| float getDirectValue(); | |||||
| /** Sets the Param's smoothing target value, or direct value if smoothing is disabled. | |||||
| Before Rack 2.3.0, this always set the Param's value directly. | |||||
| For this behavior, use `setDirectValue()` instead. | |||||
| */ | |||||
| void setValue(float value) override; | void setValue(float value) override; | ||||
| /** Gets the Param's smoothing target value, or direct value if smoothing is disabled. | |||||
| Before Rack 2.3.0, this always got the Param's value directly. | |||||
| For this behavior, use `getDirectValue()` instead. | |||||
| */ | |||||
| float getValue() override; | float getValue() override; | ||||
| float getMinValue() override; | float getMinValue() override; | ||||
| float getMaxValue() override; | float getMaxValue() override; | ||||
| @@ -72,7 +72,7 @@ void Knob::onDragStart(const DragStartEvent& e) { | |||||
| engine::ParamQuantity* pq = getParamQuantity(); | engine::ParamQuantity* pq = getParamQuantity(); | ||||
| if (pq) { | if (pq) { | ||||
| internal->oldValue = pq->getSmoothValue(); | |||||
| internal->oldValue = pq->getValue(); | |||||
| internal->snapDelta = 0.f; | internal->snapDelta = 0.f; | ||||
| } | } | ||||
| @@ -103,7 +103,7 @@ void Knob::onDragEnd(const DragEndEvent& e) { | |||||
| engine::ParamQuantity* pq = getParamQuantity(); | engine::ParamQuantity* pq = getParamQuantity(); | ||||
| if (pq) { | if (pq) { | ||||
| float newValue = pq->getSmoothValue(); | |||||
| float newValue = pq->getValue(); | |||||
| if (!std::isnan(internal->oldValue) && internal->oldValue != newValue) { | if (!std::isnan(internal->oldValue) && internal->oldValue != newValue) { | ||||
| // Push ParamChange history action | // Push ParamChange history action | ||||
| history::ParamChange* h = new history::ParamChange; | history::ParamChange* h = new history::ParamChange; | ||||
| @@ -150,7 +150,7 @@ void Knob::onDragMove(const DragMoveEvent& e) { | |||||
| engine::ParamQuantity* pq = getParamQuantity(); | engine::ParamQuantity* pq = getParamQuantity(); | ||||
| if (pq) { | if (pq) { | ||||
| float value = pq->getSmoothValue(); | |||||
| float value = pq->getValue(); | |||||
| // Ratio between parameter value scale / (angle range / 2*pi) | // Ratio between parameter value scale / (angle range / 2*pi) | ||||
| float rangeRatio; | float rangeRatio; | ||||
| @@ -224,7 +224,7 @@ void Knob::onDragMove(const DragMoveEvent& e) { | |||||
| } | } | ||||
| // Set value | // Set value | ||||
| pq->setSmoothValue(value); | |||||
| pq->setValue(value); | |||||
| } | } | ||||
| internal->distDragged += e.mouseDelta.norm(); | internal->distDragged += e.mouseDelta.norm(); | ||||
| @@ -254,7 +254,7 @@ void Knob::onHoverScroll(const HoverScrollEvent& e) { | |||||
| if (!pq) | if (!pq) | ||||
| return; | return; | ||||
| float value = pq->getSmoothValue(); | |||||
| float value = pq->getValue(); | |||||
| // Set old value if unset | // Set old value if unset | ||||
| if (std::isnan(internal->oldValue)) { | if (std::isnan(internal->oldValue)) { | ||||
| internal->oldValue = value; | internal->oldValue = value; | ||||
| @@ -284,7 +284,7 @@ void Knob::onHoverScroll(const HoverScrollEvent& e) { | |||||
| } | } | ||||
| value += delta; | value += delta; | ||||
| pq->setSmoothValue(value); | |||||
| pq->setValue(value); | |||||
| e.consume(this); | e.consume(this); | ||||
| } | } | ||||
| @@ -298,7 +298,7 @@ void Knob::onLeave(const LeaveEvent& e) { | |||||
| engine::ParamQuantity* pq = getParamQuantity(); | engine::ParamQuantity* pq = getParamQuantity(); | ||||
| if (pq) { | if (pq) { | ||||
| float newValue = pq->getSmoothValue(); | |||||
| float newValue = pq->getValue(); | |||||
| if (!std::isnan(internal->oldValue) && internal->oldValue != newValue) { | if (!std::isnan(internal->oldValue) && internal->oldValue != newValue) { | ||||
| // Push ParamChange history action | // Push ParamChange history action | ||||
| history::ParamChange* h = new history::ParamChange; | history::ParamChange* h = new history::ParamChange; | ||||
| @@ -172,7 +172,7 @@ void ParamWidget::destroyTooltip() { | |||||
| void ParamWidget::step() { | void ParamWidget::step() { | ||||
| engine::ParamQuantity* pq = getParamQuantity(); | engine::ParamQuantity* pq = getParamQuantity(); | ||||
| if (pq) { | if (pq) { | ||||
| float value = pq->getSmoothValue(); | |||||
| float value = pq->getValue(); | |||||
| // Dispatch change event when the ParamQuantity value changes | // Dispatch change event when the ParamQuantity value changes | ||||
| if (value != internal->lastValue) { | if (value != internal->lastValue) { | ||||
| ChangeEvent eChange; | ChangeEvent eChange; | ||||
| @@ -35,7 +35,7 @@ void SvgKnob::onChange(const ChangeEvent& e) { | |||||
| // Re-transform the widget::TransformWidget | // Re-transform the widget::TransformWidget | ||||
| engine::ParamQuantity* pq = getParamQuantity(); | engine::ParamQuantity* pq = getParamQuantity(); | ||||
| if (pq) { | if (pq) { | ||||
| float value = pq->getSmoothValue(); | |||||
| float value = pq->getValue(); | |||||
| float angle; | float angle; | ||||
| if (!pq->isBounded()) { | if (!pq->isBounded()) { | ||||
| // Number of rotations equals value for unbounded range | // Number of rotations equals value for unbounded range | ||||
| @@ -57,7 +57,7 @@ void SvgSlider::onChange(const ChangeEvent& e) { | |||||
| float v = 1.f; | float v = 1.f; | ||||
| engine::ParamQuantity* pq = getParamQuantity(); | engine::ParamQuantity* pq = getParamQuantity(); | ||||
| if (pq) { | if (pq) { | ||||
| v = math::rescale(pq->getSmoothValue(), pq->getMinValue(), pq->getMaxValue(), 0.f, 1.f); | |||||
| v = pq->getScaledValue(); | |||||
| } | } | ||||
| // Interpolate handle position | // Interpolate handle position | ||||
| @@ -1060,19 +1060,19 @@ void Engine::setParamValue(Module* module, int paramId, float value) { | |||||
| internal->smoothModule = NULL; | internal->smoothModule = NULL; | ||||
| internal->smoothParamId = 0; | internal->smoothParamId = 0; | ||||
| } | } | ||||
| module->params[paramId].value = value; | |||||
| module->params[paramId].setValue(value); | |||||
| } | } | ||||
| float Engine::getParamValue(Module* module, int paramId) { | float Engine::getParamValue(Module* module, int paramId) { | ||||
| return module->params[paramId].value; | |||||
| return module->params[paramId].getValue(); | |||||
| } | } | ||||
| void Engine::setParamSmoothValue(Module* module, int paramId, float value) { | void Engine::setParamSmoothValue(Module* module, int paramId, float value) { | ||||
| // If another param is being smoothed, jump value | // If another param is being smoothed, jump value | ||||
| if (internal->smoothModule && !(internal->smoothModule == module && internal->smoothParamId == paramId)) { | if (internal->smoothModule && !(internal->smoothModule == module && internal->smoothParamId == paramId)) { | ||||
| internal->smoothModule->params[internal->smoothParamId].value = internal->smoothValue; | |||||
| internal->smoothModule->params[internal->smoothParamId].setValue(internal->smoothValue); | |||||
| } | } | ||||
| internal->smoothParamId = paramId; | internal->smoothParamId = paramId; | ||||
| internal->smoothValue = value; | internal->smoothValue = value; | ||||
| @@ -1084,7 +1084,7 @@ void Engine::setParamSmoothValue(Module* module, int paramId, float value) { | |||||
| float Engine::getParamSmoothValue(Module* module, int paramId) { | float Engine::getParamSmoothValue(Module* module, int paramId) { | ||||
| if (internal->smoothModule == module && internal->smoothParamId == paramId) | if (internal->smoothModule == module && internal->smoothParamId == paramId) | ||||
| return internal->smoothValue; | return internal->smoothValue; | ||||
| return module->params[paramId].value; | |||||
| return module->params[paramId].getValue(); | |||||
| } | } | ||||
| @@ -250,7 +250,7 @@ void Module::paramsFromJson(json_t* rootJ) { | |||||
| json_t* valueJ = json_object_get(paramJ, "value"); | json_t* valueJ = json_object_get(paramJ, "value"); | ||||
| if (valueJ) | if (valueJ) | ||||
| pq->setValue(json_number_value(valueJ)); | |||||
| pq->setDirectValue(json_number_value(valueJ)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -19,24 +19,26 @@ engine::Param* ParamQuantity::getParam() { | |||||
| } | } | ||||
| void ParamQuantity::setSmoothValue(float value) { | void ParamQuantity::setSmoothValue(float value) { | ||||
| setValue(value); | |||||
| } | |||||
| float ParamQuantity::getSmoothValue() { | |||||
| return getValue(); | |||||
| } | |||||
| void ParamQuantity::setDirectValue(float value) { | |||||
| if (!module) | if (!module) | ||||
| return; | return; | ||||
| value = math::clampSafe(value, getMinValue(), getMaxValue()); | value = math::clampSafe(value, getMinValue(), getMaxValue()); | ||||
| if (snapEnabled) | if (snapEnabled) | ||||
| value = std::round(value); | value = std::round(value); | ||||
| if (smoothEnabled) | |||||
| APP->engine->setParamSmoothValue(module, paramId, value); | |||||
| else | |||||
| APP->engine->setParamValue(module, paramId, value); | |||||
| APP->engine->setParamValue(module, paramId, value); | |||||
| } | } | ||||
| float ParamQuantity::getSmoothValue() { | |||||
| float ParamQuantity::getDirectValue() { | |||||
| if (!module) | if (!module) | ||||
| return 0.f; | return 0.f; | ||||
| if (smoothEnabled) | |||||
| return APP->engine->getParamSmoothValue(module, paramId); | |||||
| else | |||||
| return APP->engine->getParamValue(module, paramId); | |||||
| return APP->engine->getParamValue(module, paramId); | |||||
| } | } | ||||
| void ParamQuantity::setValue(float value) { | void ParamQuantity::setValue(float value) { | ||||
| @@ -45,13 +47,19 @@ void ParamQuantity::setValue(float value) { | |||||
| value = math::clampSafe(value, getMinValue(), getMaxValue()); | value = math::clampSafe(value, getMinValue(), getMaxValue()); | ||||
| if (snapEnabled) | if (snapEnabled) | ||||
| value = std::round(value); | value = std::round(value); | ||||
| APP->engine->setParamValue(module, paramId, value); | |||||
| if (smoothEnabled) | |||||
| APP->engine->setParamSmoothValue(module, paramId, value); | |||||
| else | |||||
| APP->engine->setParamValue(module, paramId, value); | |||||
| } | } | ||||
| float ParamQuantity::getValue() { | float ParamQuantity::getValue() { | ||||
| if (!module) | if (!module) | ||||
| return 0.f; | return 0.f; | ||||
| return APP->engine->getParamValue(module, paramId); | |||||
| if (smoothEnabled) | |||||
| return APP->engine->getParamSmoothValue(module, paramId); | |||||
| else | |||||
| return APP->engine->getParamValue(module, paramId); | |||||
| } | } | ||||
| float ParamQuantity::getMinValue() { | float ParamQuantity::getMinValue() { | ||||
| @@ -67,8 +75,7 @@ float ParamQuantity::getDefaultValue() { | |||||
| } | } | ||||
| float ParamQuantity::getDisplayValue() { | float ParamQuantity::getDisplayValue() { | ||||
| // We don't want the text to be smoothed (animated), so get the smooth target value. | |||||
| float v = getSmoothValue(); | |||||
| float v = getValue(); | |||||
| if (displayBase == 0.f) { | if (displayBase == 0.f) { | ||||
| // Linear | // Linear | ||||
| // v is unchanged | // v is unchanged | ||||