| @@ -2,7 +2,6 @@ | |||
| #include "ui/Quantity.hpp" | |||
| #include "engine/Module.hpp" | |||
| #include "engine/Param.hpp" | |||
| #include "engine/ParamInfo.hpp" | |||
| namespace rack { | |||
| @@ -14,7 +13,6 @@ struct ParamQuantity : Quantity { | |||
| int paramId = 0; | |||
| Param *getParam(); | |||
| ParamInfo *getParamInfo(); | |||
| /** Request to the engine to smoothly set the value */ | |||
| void setSmoothValue(float smoothValue); | |||
| float getSmoothValue(); | |||
| @@ -5,7 +5,6 @@ | |||
| #include "engine/Input.hpp" | |||
| #include "engine/Output.hpp" | |||
| #include "engine/Light.hpp" | |||
| #include "engine/ParamInfo.hpp" | |||
| #include <vector> | |||
| #include <jansson.h> | |||
| @@ -19,7 +18,6 @@ struct Module { | |||
| std::vector<Input> inputs; | |||
| std::vector<Output> outputs; | |||
| std::vector<Light> lights; | |||
| std::vector<ParamInfo> paramInfos; | |||
| /** For power meter */ | |||
| float cpuTime = 0.f; | |||
| bool bypass = false; | |||
| @@ -6,19 +6,55 @@ | |||
| namespace rack { | |||
| struct ParamQuantity; | |||
| struct ParamQuantityFactory { | |||
| virtual ~ParamQuantityFactory() {} | |||
| virtual ParamQuantity *create() = 0; | |||
| }; | |||
| struct Param { | |||
| float value = 0.f; | |||
| float minValue = 0.f; | |||
| float maxValue = 1.f; | |||
| float defaultValue = 0.f; | |||
| void config(float minValue, float maxValue, float defaultValue) { | |||
| std::string label; | |||
| std::string unit; | |||
| /** Set to 0 for linear, nonzero for exponential */ | |||
| float displayBase = 0.f; | |||
| float displayMultiplier = 1.f; | |||
| std::string description; | |||
| ParamQuantityFactory *paramQuantityFactory = NULL; | |||
| ~Param() { | |||
| if (paramQuantityFactory) | |||
| delete paramQuantityFactory; | |||
| } | |||
| template<class TParamQuantity = ParamQuantity> | |||
| void config(float minValue, float maxValue, float defaultValue, std::string label = "", std::string unit = "", float displayBase = 0.f, float displayMultiplier = 1.f) { | |||
| this->value = defaultValue; | |||
| this->minValue = minValue; | |||
| this->maxValue = maxValue; | |||
| this->defaultValue = defaultValue; | |||
| this->label = label; | |||
| this->unit = unit; | |||
| this->displayBase = displayBase; | |||
| this->displayMultiplier = displayMultiplier; | |||
| struct TParamQuantityFactory : ParamQuantityFactory { | |||
| ParamQuantity *create() override {return new TParamQuantity;} | |||
| }; | |||
| if (paramQuantityFactory) | |||
| delete paramQuantityFactory; | |||
| paramQuantityFactory = new TParamQuantityFactory; | |||
| } | |||
| bool isBounded(); | |||
| json_t *toJson(); | |||
| void fromJson(json_t *rootJ); | |||
| void reset(); | |||
| @@ -1,48 +0,0 @@ | |||
| #pragma once | |||
| #include "common.hpp" | |||
| namespace rack { | |||
| struct ParamQuantity; | |||
| struct ParamQuantityFactory { | |||
| virtual ~ParamQuantityFactory() {} | |||
| virtual ParamQuantity *create() = 0; | |||
| }; | |||
| struct ParamInfo { | |||
| std::string label; | |||
| std::string unit; | |||
| /** Set to 0 for linear, nonzero for exponential */ | |||
| float displayBase = 0.f; | |||
| float displayMultiplier = 1.f; | |||
| std::string description; | |||
| ParamQuantityFactory *paramQuantityFactory = NULL; | |||
| ~ParamInfo() { | |||
| if (paramQuantityFactory) | |||
| delete paramQuantityFactory; | |||
| } | |||
| template<class TParamQuantity = ParamQuantity> | |||
| void config(std::string label = "", std::string unit = "", float displayBase = 0.f, float displayMultiplier = 1.f) { | |||
| this->label = label; | |||
| this->unit = unit; | |||
| this->displayBase = displayBase; | |||
| this->displayMultiplier = displayMultiplier; | |||
| struct TParamQuantityFactory : ParamQuantityFactory { | |||
| ParamQuantity *create() override {return new TParamQuantity;} | |||
| }; | |||
| if (paramQuantityFactory) | |||
| delete paramQuantityFactory; | |||
| paramQuantityFactory = new TParamQuantityFactory; | |||
| } | |||
| }; | |||
| } // namespace rack | |||
| @@ -58,7 +58,7 @@ TParamWidget *createParam(math::Vec pos, Module *module, int paramId) { | |||
| TParamWidget *o = new TParamWidget; | |||
| o->box.pos = pos; | |||
| if (module) { | |||
| ParamQuantityFactory *f = module->paramInfos[paramId].paramQuantityFactory; | |||
| ParamQuantityFactory *f = module->params[paramId].paramQuantityFactory; | |||
| if (f) | |||
| o->paramQuantity = f->create(); | |||
| else | |||
| @@ -11,11 +11,6 @@ Param *ParamQuantity::getParam() { | |||
| return &module->params[paramId]; | |||
| } | |||
| ParamInfo *ParamQuantity::getParamInfo() { | |||
| assert(module); | |||
| return &module->paramInfos[paramId]; | |||
| } | |||
| void ParamQuantity::setSmoothValue(float smoothValue) { | |||
| if (!module) | |||
| return; | |||
| @@ -63,34 +58,34 @@ float ParamQuantity::getDefaultValue() { | |||
| float ParamQuantity::getDisplayValue() { | |||
| if (!module) | |||
| return Quantity::getDisplayValue(); | |||
| if (getParamInfo()->displayBase == 0.f) { | |||
| if (getParam()->displayBase == 0.f) { | |||
| // Linear | |||
| return getValue() * getParamInfo()->displayMultiplier; | |||
| return getValue() * getParam()->displayMultiplier; | |||
| } | |||
| else if (getParamInfo()->displayBase == 1.f) { | |||
| else if (getParam()->displayBase == 1.f) { | |||
| // Fixed (special case of exponential) | |||
| return getParamInfo()->displayMultiplier; | |||
| return getParam()->displayMultiplier; | |||
| } | |||
| else { | |||
| // Exponential | |||
| return std::pow(getParamInfo()->displayBase, getValue()) * getParamInfo()->displayMultiplier; | |||
| return std::pow(getParam()->displayBase, getValue()) * getParam()->displayMultiplier; | |||
| } | |||
| } | |||
| void ParamQuantity::setDisplayValue(float displayValue) { | |||
| if (!module) | |||
| return; | |||
| if (getParamInfo()->displayBase == 0.f) { | |||
| if (getParam()->displayBase == 0.f) { | |||
| // Linear | |||
| setValue(displayValue / getParamInfo()->displayMultiplier); | |||
| setValue(displayValue / getParam()->displayMultiplier); | |||
| } | |||
| else if (getParamInfo()->displayBase == 1.f) { | |||
| else if (getParam()->displayBase == 1.f) { | |||
| // Fixed | |||
| setValue(getParamInfo()->displayMultiplier); | |||
| setValue(getParam()->displayMultiplier); | |||
| } | |||
| else { | |||
| // Exponential | |||
| setValue(std::log(displayValue / getParamInfo()->displayMultiplier) / std::log(getParamInfo()->displayBase)); | |||
| setValue(std::log(displayValue / getParam()->displayMultiplier) / std::log(getParam()->displayBase)); | |||
| } | |||
| } | |||
| @@ -109,13 +104,13 @@ int ParamQuantity::getDisplayPrecision() { | |||
| std::string ParamQuantity::getLabel() { | |||
| if (!module) | |||
| return Quantity::getLabel(); | |||
| return getParamInfo()->label; | |||
| return getParam()->label; | |||
| } | |||
| std::string ParamQuantity::getUnit() { | |||
| if (!module) | |||
| return Quantity::getUnit(); | |||
| return getParamInfo()->unit; | |||
| return getParam()->unit; | |||
| } | |||
| @@ -82,7 +82,7 @@ void ParamWidget::step() { | |||
| // Quantity string | |||
| tooltip->text = paramQuantity->getString(); | |||
| // Param description | |||
| std::string description = paramQuantity->getParamInfo()->description; | |||
| std::string description = paramQuantity->getParam()->description; | |||
| if (!description.empty()) | |||
| tooltip->text += "\n" + description; | |||
| } | |||
| @@ -9,14 +9,13 @@ Module::Module() { | |||
| void Module::config(int numParams, int numInputs, int numOutputs, int numLights) { | |||
| params.resize(numParams); | |||
| inputs.resize(numInputs); | |||
| outputs.resize(numOutputs); | |||
| lights.resize(numLights); | |||
| paramInfos.resize(numParams); | |||
| // Create default param labels | |||
| for (int i = 0; i < numParams; i++) { | |||
| paramInfos[i].label = string::f("#%d", i + 1); | |||
| params[i].label = string::f("#%d", i + 1); | |||
| } | |||
| inputs.resize(numInputs); | |||
| outputs.resize(numOutputs); | |||
| lights.resize(numLights); | |||
| } | |||
| json_t *Module::toJson() { | |||
| @@ -6,32 +6,37 @@ | |||
| namespace rack { | |||
| bool Param::isBounded() { | |||
| return std::isfinite(minValue) && std::isfinite(maxValue); | |||
| } | |||
| json_t *Param::toJson() { | |||
| json_t *rootJ = json_object(); | |||
| float v = 0.f; | |||
| // Infinite params should serialize to 0 | |||
| if (std::isfinite(minValue) && std::isfinite(maxValue)) | |||
| v = value; | |||
| json_object_set_new(rootJ, "value", json_real(v)); | |||
| if (isBounded()) { | |||
| json_object_set_new(rootJ, "value", json_real(value)); | |||
| } | |||
| return rootJ; | |||
| } | |||
| void Param::fromJson(json_t *rootJ) { | |||
| json_t *valueJ = json_object_get(rootJ, "value"); | |||
| if (valueJ) | |||
| value = json_number_value(valueJ); | |||
| if (isBounded()) { | |||
| json_t *valueJ = json_object_get(rootJ, "value"); | |||
| if (valueJ) | |||
| value = json_number_value(valueJ); | |||
| } | |||
| } | |||
| void Param::reset() { | |||
| if (std::isfinite(minValue) && std::isfinite(maxValue)) { | |||
| if (isBounded()) { | |||
| value = defaultValue; | |||
| } | |||
| } | |||
| void Param::randomize() { | |||
| if (std::isfinite(minValue) && std::isfinite(maxValue)) { | |||
| if (isBounded()) { | |||
| value = math::rescale(random::uniform(), 0.f, 1.f, minValue, maxValue); | |||
| } | |||
| } | |||