Browse Source

Added param value entry. Make ParamQuantity automatically compute its displayPrecision.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
4c23dc9cc0
7 changed files with 81 additions and 39 deletions
  1. +1
    -3
      include/engine/Param.hpp
  2. +3
    -27
      include/ui/MenuOverlay.hpp
  3. +7
    -0
      include/ui/Quantity.hpp
  4. +1
    -0
      include/ui/TextField.hpp
  5. +10
    -6
      src/app/ParamQuantity.cpp
  6. +53
    -1
      src/app/ParamWidget.cpp
  7. +6
    -2
      src/ui/TextField.cpp

+ 1
- 3
include/engine/Param.hpp View File

@@ -16,18 +16,16 @@ struct Param {
/** Set to 0 for linear, nonzero for exponential */
float displayBase = 0.f;
float displayMultiplier = 1.f;
int displayPrecision = 2;
std::string label;
std::string unit;

void setup(float minValue, float maxValue, float defaultValue, std::string label = "", std::string unit = "", int displayPrecision = 2, float displayBase = 0.f, float displayMultiplier = 1.f) {
void setup(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->displayPrecision = displayPrecision;
this->displayBase = displayBase;
this->displayMultiplier = displayMultiplier;
}


+ 3
- 27
include/ui/MenuOverlay.hpp View File

@@ -8,33 +8,9 @@ namespace rack {

/** Deletes itself from parent when clicked */
struct MenuOverlay : OpaqueWidget {
void step() override {
// Adopt parent's size
box.size = parent->box.size;

// Fit all children in the box
for (Widget *child : children) {
child->box = child->box.nudge(box.zeroPos());
}

Widget::step();
}

void onButton(const event::Button &e) override {
OpaqueWidget::onButton(e);

if (e.getConsumed() == this && e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT) {
requestedDelete = true;
}
}

void onHoverKey(const event::HoverKey &e) override {
OpaqueWidget::onHoverKey(e);

if (e.getConsumed() == this && e.action == GLFW_PRESS && e.key == GLFW_KEY_ESCAPE) {
requestedDelete = true;
}
}
void step() override;
void onButton(const event::Button &e) override;
void onHoverKey(const event::HoverKey &e) override;
};




+ 7
- 0
include/ui/Quantity.hpp View File

@@ -50,6 +50,13 @@ struct Quantity {
return string::f("%.*f", getDisplayPrecision(), getDisplayValue());
}

virtual void setDisplayValueString(std::string s) {
float displayValue = 0.f;
int n = std::sscanf(s.c_str(), "%f", &displayValue);
if (n == 1)
setDisplayValue(displayValue);
}

/** The name of the quantity */
virtual std::string getLabel() {return "";}



+ 1
- 0
include/ui/TextField.hpp View File

@@ -32,6 +32,7 @@ struct TextField : OpaqueWidget {

/** Replaces the entire text */
void setText(std::string text);
void selectAll();
virtual int getTextPosition(math::Vec mousePos);
};



+ 10
- 6
src/app/ParamQuantity.cpp View File

@@ -51,7 +51,7 @@ float ParamQuantity::getDisplayValue() {
return Quantity::getDisplayValue();
if (getParam()->displayBase == 0.f) {
// Linear
return getParam()->value * getParam()->displayMultiplier;
return getValue() * getParam()->displayMultiplier;
}
else if (getParam()->displayBase == 1.f) {
// Fixed (special case of exponential)
@@ -59,7 +59,7 @@ float ParamQuantity::getDisplayValue() {
}
else {
// Exponential
return std::pow(getParam()->displayBase, getParam()->value) * getParam()->displayMultiplier;
return std::pow(getParam()->displayBase, getValue()) * getParam()->displayMultiplier;
}
}

@@ -68,22 +68,26 @@ void ParamQuantity::setDisplayValue(float displayValue) {
return;
if (getParam()->displayBase == 0.f) {
// Linear
getParam()->value = displayValue / getParam()->displayMultiplier;
setValue(displayValue / getParam()->displayMultiplier);
}
else if (getParam()->displayBase == 1.f) {
// Fixed
getParam()->value = getParam()->displayMultiplier;
setValue(getParam()->displayMultiplier);
}
else {
// Exponential
getParam()->value = std::log(displayValue / getParam()->displayMultiplier) / std::log(getParam()->displayBase);
setValue(std::log(displayValue / getParam()->displayMultiplier) / std::log(getParam()->displayBase));
}
}

int ParamQuantity::getDisplayPrecision() {
if (!module)
return Quantity::getDisplayPrecision();
return getParam()->displayPrecision;
float displayValue = getDisplayValue();
if (displayValue == 0.f)
return 0;
float log = std::log10(std::abs(getDisplayValue()));
return (int) std::ceil(math::clamp(-log + 3.f, 0.f, 6.f));
}

std::string ParamQuantity::getLabel() {


+ 53
- 1
src/app/ParamWidget.cpp View File

@@ -1,4 +1,6 @@
#include "app/ParamWidget.hpp"
#include "ui/MenuOverlay.hpp"
#include "ui/TextField.hpp"
#include "app/Scene.hpp"
#include "context.hpp"
#include "settings.hpp"
@@ -8,6 +10,43 @@
namespace rack {


struct ParamField : TextField {
ParamWidget *paramWidget;

void step() override {
// Keep selected
context()->event->setSelected(this);
}

void setParamWidget(ParamWidget *paramWidget) {
this->paramWidget = paramWidget;
if (paramWidget->quantity)
text = paramWidget->quantity->getDisplayValueString();
selectAll();
}

void onSelectKey(const event::SelectKey &e) override {
if (e.action == GLFW_PRESS && (e.key == GLFW_KEY_ENTER || e.key == GLFW_KEY_KP_ENTER)) {
if (paramWidget->quantity)
paramWidget->quantity->setDisplayValueString(text);

MenuOverlay *overlay = getAncestorOfType<MenuOverlay>();
overlay->requestedDelete = true;
e.consume(this);
}

if (e.action == GLFW_PRESS && e.key == GLFW_KEY_ESCAPE) {
MenuOverlay *overlay = getAncestorOfType<MenuOverlay>();
overlay->requestedDelete = true;
e.consume(this);
}

if (!e.getConsumed())
TextField::onSelectKey(e);
}
};


ParamWidget::~ParamWidget() {
if (quantity)
delete quantity;
@@ -27,7 +66,7 @@ void ParamWidget::step() {
if (tooltip) {
if (quantity)
tooltip->text = quantity->getString();
tooltip->box.pos = getAbsoluteOffset(box.size);
tooltip->box.pos = getAbsoluteOffset(box.size).round();
}

OpaqueWidget::step();
@@ -50,6 +89,19 @@ void ParamWidget::onButton(const event::Button &e) {
// dynamic_cast<ParamQuantity*>(quantity)->getParam()->reset();
}

// Shift-click to open value entry
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_LEFT && (e.mods & GLFW_MOD_SHIFT) && !(e.mods & GLFW_MOD_CONTROL)) {
// Create ParamField
MenuOverlay *overlay = new MenuOverlay;
context()->scene->addChild(overlay);

ParamField *paramField = new ParamField;
paramField->box.size.x = 100;
paramField->box.pos = getAbsoluteOffset(box.size).round();
paramField->setParamWidget(this);
overlay->addChild(paramField);
}

OpaqueWidget::onButton(e);
}



+ 6
- 2
src/ui/TextField.cpp View File

@@ -155,8 +155,7 @@ void TextField::onSelectKey(const event::SelectKey &e) {
} break;
case GLFW_KEY_A: {
if (context()->window->isModPressed()) {
selection = 0;
cursor = text.size();
selectAll();
}
} break;
case GLFW_KEY_ENTER: {
@@ -198,6 +197,11 @@ void TextField::setText(std::string text) {
onChange(eChange);
}

void TextField::selectAll() {
cursor = text.size();
selection = 0;
}

int TextField::getTextPosition(math::Vec mousePos) {
return bndTextFieldTextPosition(context()->window->vg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str(), mousePos.x, mousePos.y);
}


Loading…
Cancel
Save