Browse Source

Fix event drag handling, fix ParamQuantity and tweak its API

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
960ac66b73
26 changed files with 198 additions and 155 deletions
  1. +3
    -26
      include/app/Knob.hpp
  2. +1
    -1
      include/app/LedDisplay.hpp
  3. +14
    -64
      include/app/ParamQuantity.hpp
  4. +4
    -8
      include/app/ParamWidget.hpp
  5. +1
    -1
      include/app/PluginManagerWidget.hpp
  6. +11
    -5
      include/helpers.hpp
  7. +1
    -1
      include/ui/Label.hpp
  8. +1
    -1
      include/ui/ProgressBar.hpp
  9. +2
    -0
      include/ui/Quantity.hpp
  10. +1
    -1
      include/ui/SequentialLayout.hpp
  11. +1
    -1
      include/ui/Tooltip.hpp
  12. +1
    -1
      include/widgets/FramebufferWidget.hpp
  13. +1
    -1
      include/widgets/OpaqueWidget.hpp
  14. +1
    -1
      include/widgets/SVGWidget.hpp
  15. +1
    -1
      include/widgets/TransformWidget.hpp
  16. +1
    -1
      include/widgets/TransparentWidget.hpp
  17. +1
    -7
      include/widgets/Widget.hpp
  18. +15
    -22
      include/widgets/ZoomWidget.hpp
  19. +39
    -0
      src/app/Knob.cpp
  20. +1
    -0
      src/app/ModuleBrowser.cpp
  21. +1
    -0
      src/app/ModuleWidget.cpp
  22. +74
    -0
      src/app/ParamQuantity.cpp
  23. +1
    -0
      src/app/RackWidget.cpp
  24. +3
    -3
      src/app/SVGKnob.cpp
  25. +9
    -9
      src/event.cpp
  26. +9
    -0
      src/widgets/Widget.cpp

+ 3
- 26
include/app/Knob.hpp View File

@@ -15,32 +15,9 @@ struct Knob : ParamWidget {
/** Multiplier for mouse movement to adjust knob value */ /** Multiplier for mouse movement to adjust knob value */
float speed = 1.0; float speed = 1.0;


void onDragStart(event::DragStart &e) override {
context()->window->cursorLock();
}

void onDragEnd(event::DragEnd &e) override {
context()->window->cursorUnlock();
}

void onDragMove(event::DragMove &e) override {
if (quantity) {
float range;
if (quantity->isBounded()) {
range = quantity->getRange();
}
else {
// Continuous encoders scale as if their limits are +/-1
range = 2.f;
}
float delta = KNOB_SENSITIVITY * -e.mouseDelta.y * speed * range;

// Drag slower if Mod is held
if (context()->window->isModPressed())
delta /= 16.f;
quantity->moveValue(delta);
}
}
void onDragStart(event::DragStart &e) override;
void onDragEnd(event::DragEnd &e) override;
void onDragMove(event::DragMove &e) override;
}; };






+ 1
- 1
include/app/LedDisplay.hpp View File

@@ -8,7 +8,7 @@
namespace rack { namespace rack {




struct LedDisplay : VirtualWidget {
struct LedDisplay : virtual Widget {
void draw(NVGcontext *vg) override; void draw(NVGcontext *vg) override;
}; };




+ 14
- 64
include/app/ParamQuantity.hpp View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "ui/Quantity.hpp" #include "ui/Quantity.hpp"
#include "engine/Module.hpp" #include "engine/Module.hpp"
#include "engine/Param.hpp"




namespace rack { namespace rack {
@@ -16,70 +17,19 @@ struct ParamQuantity : Quantity {
bool snap = false; bool snap = false;
float snapValue = 0.f; float snapValue = 0.f;


Param *getParam() {
assert(module);
return &module->params[paramId];
}

void commitSnap() {
// TODO
}

void setValue(float value) override {
// TODO Smooth
// TODO Snap
getParam()->value = value;
}

float getValue() override {
return getParam()->value;
}

float getMinValue() override {
return getParam()->minValue;
}

float getMaxValue() override {
return getParam()->maxValue;
}

float getDefaultValue() override {
return getParam()->defaultValue;
}

float getDisplayValue() override {
if (getParam()->displayBase == 0.f) {
// Linear
return getParam()->value * getParam()->displayMultiplier;
}
else {
// Exponential
return std::pow(getParam()->displayBase, getParam()->value) * getParam()->displayMultiplier;
}
}

void setDisplayValue(float displayValue) override {
if (getParam()->displayBase == 0.f) {
// Linear
getParam()->value = displayValue / getParam()->displayMultiplier;
}
else {
// Exponential
getParam()->value = std::log(displayValue / getParam()->displayMultiplier) / std::log(getParam()->displayBase);
}
}

int getDisplayPrecision() override {
return getParam()->displayPrecision;
}

std::string getLabel() override {
return getParam()->label;
}

std::string getUnit() override {
return getParam()->unit;
}
Param *getParam();
void commitSnap();

void setValue(float value) override;
float getValue() override;
float getMinValue() override;
float getMaxValue() override;
float getDefaultValue() override;
float getDisplayValue() override;
void setDisplayValue(float displayValue) override ;
int getDisplayPrecision() override;
std::string getLabel() override;
std::string getUnit() override;
}; };






+ 4
- 8
include/app/ParamWidget.hpp View File

@@ -1,22 +1,18 @@
#pragma once #pragma once
#include "app/common.hpp" #include "app/common.hpp"
#include "widgets/OpaqueWidget.hpp" #include "widgets/OpaqueWidget.hpp"
#include "app/ParamQuantity.hpp"
#include "ui/Quantity.hpp"




namespace rack { namespace rack {




/** Controls a ParamQuantity */
struct ParamWidget : OpaqueWidget { struct ParamWidget : OpaqueWidget {
ParamQuantity *quantity;

ParamWidget() {
quantity = new ParamQuantity;
}
Quantity *quantity = NULL;


~ParamWidget() { ~ParamWidget() {
delete quantity;
if (quantity)
delete quantity;
} }


/** For legacy patch loading */ /** For legacy patch loading */


+ 1
- 1
include/app/PluginManagerWidget.hpp View File

@@ -6,7 +6,7 @@
namespace rack { namespace rack {




struct PluginManagerWidget : VirtualWidget {
struct PluginManagerWidget : virtual Widget {
Widget *loginWidget; Widget *loginWidget;
Widget *manageWidget; Widget *manageWidget;
Widget *downloadWidget; Widget *downloadWidget;


+ 11
- 5
include/helpers.hpp View File

@@ -1,11 +1,13 @@
#include "plugin/Model.hpp" #include "plugin/Model.hpp"
#include "event.hpp"
#include "ui/MenuLabel.hpp" #include "ui/MenuLabel.hpp"
#include "ui/MenuItem.hpp" #include "ui/MenuItem.hpp"
#include "ui/Menu.hpp" #include "ui/Menu.hpp"
#include "app/Port.hpp" #include "app/Port.hpp"
#include "app/ParamQuantity.hpp"
#include "app/ParamWidget.hpp"
#include "engine/Module.hpp" #include "engine/Module.hpp"
#include "context.hpp" #include "context.hpp"
#include "window.hpp"




namespace rack { namespace rack {
@@ -54,8 +56,10 @@ template <class TParamWidget>
TParamWidget *createParam(math::Vec pos, Module *module, int paramId) { TParamWidget *createParam(math::Vec pos, Module *module, int paramId) {
TParamWidget *o = new TParamWidget; TParamWidget *o = new TParamWidget;
o->box.pos = pos; o->box.pos = pos;
o->quantity->module = module;
o->quantity->paramId = paramId;
ParamQuantity *q = new ParamQuantity;
q->module = module;
q->paramId = paramId;
o->quantity = q;
return o; return o;
} }


@@ -63,8 +67,10 @@ template <class TParamWidget>
TParamWidget *createParamCentered(math::Vec pos, Module *module, int paramId) { TParamWidget *createParamCentered(math::Vec pos, Module *module, int paramId) {
TParamWidget *o = new TParamWidget; TParamWidget *o = new TParamWidget;
o->box.pos = pos.minus(o->box.size.div(2)); o->box.pos = pos.minus(o->box.size.div(2));
o->quantity->module = module;
o->quantity->paramId = paramId;
ParamQuantity *q = new ParamQuantity;
q->module = module;
q->paramId = paramId;
o->quantity = q;
return o; return o;
} }




+ 1
- 1
include/ui/Label.hpp View File

@@ -6,7 +6,7 @@
namespace rack { namespace rack {




struct Label : VirtualWidget {
struct Label : virtual Widget {
std::string text; std::string text;
float fontSize; float fontSize;
NVGcolor color; NVGcolor color;


+ 1
- 1
include/ui/ProgressBar.hpp View File

@@ -5,7 +5,7 @@
namespace rack { namespace rack {




struct ProgressBar : VirtualWidget {
struct ProgressBar : virtual Widget {
Quantity *quantity = NULL; Quantity *quantity = NULL;


ProgressBar() { ProgressBar() {


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

@@ -1,4 +1,6 @@
#pragma once #pragma once
#include "ui/common.hpp"
#include "math.hpp"
#include "string.hpp" #include "string.hpp"






+ 1
- 1
include/ui/SequentialLayout.hpp View File

@@ -7,7 +7,7 @@ namespace rack {




/** Positions children in a row/column based on their widths/heights */ /** Positions children in a row/column based on their widths/heights */
struct SequentialLayout : VirtualWidget {
struct SequentialLayout : virtual Widget {
enum Orientation { enum Orientation {
HORIZONTAL_ORIENTATION, HORIZONTAL_ORIENTATION,
VERTICAL_ORIENTATION, VERTICAL_ORIENTATION,


+ 1
- 1
include/ui/Tooltip.hpp View File

@@ -6,7 +6,7 @@
namespace rack { namespace rack {




struct Tooltip : VirtualWidget {
struct Tooltip : virtual Widget {
std::string text; std::string text;


void draw(NVGcontext *vg) override { void draw(NVGcontext *vg) override {


+ 1
- 1
include/widgets/FramebufferWidget.hpp View File

@@ -9,7 +9,7 @@ namespace rack {
When `dirty` is true, its children will be re-rendered on the next call to step() override. When `dirty` is true, its children will be re-rendered on the next call to step() override.
Events are not passed to the underlying scene. Events are not passed to the underlying scene.
*/ */
struct FramebufferWidget : VirtualWidget {
struct FramebufferWidget : virtual Widget {
/** Set this to true to re-render the children to the framebuffer the next time it is drawn */ /** Set this to true to re-render the children to the framebuffer the next time it is drawn */
bool dirty = true; bool dirty = true;
/** A margin in pixels around the children in the framebuffer /** A margin in pixels around the children in the framebuffer


+ 1
- 1
include/widgets/OpaqueWidget.hpp View File

@@ -9,7 +9,7 @@ namespace rack {
You can of course override the events. You can of course override the events.
You may also call OpaqueWidget::on*() from the overridden method to continue recursing/consuming the event. You may also call OpaqueWidget::on*() from the overridden method to continue recursing/consuming the event.
*/ */
struct OpaqueWidget : VirtualWidget {
struct OpaqueWidget : virtual Widget {
void onHover(event::Hover &e) override { void onHover(event::Hover &e) override {
Widget::onHover(e); Widget::onHover(e);
if (!e.target) if (!e.target)


+ 1
- 1
include/widgets/SVGWidget.hpp View File

@@ -7,7 +7,7 @@ namespace rack {




/** Draws an SVG */ /** Draws an SVG */
struct SVGWidget : VirtualWidget {
struct SVGWidget : virtual Widget {
std::shared_ptr<SVG> svg; std::shared_ptr<SVG> svg;


/** Sets the box size to the svg image size */ /** Sets the box size to the svg image size */


+ 1
- 1
include/widgets/TransformWidget.hpp View File

@@ -6,7 +6,7 @@ namespace rack {




/** Transforms appearance only, not positions of events */ /** Transforms appearance only, not positions of events */
struct TransformWidget : VirtualWidget {
struct TransformWidget : virtual Widget {
/** The transformation matrix */ /** The transformation matrix */
float transform[6]; float transform[6];




+ 1
- 1
include/widgets/TransparentWidget.hpp View File

@@ -6,7 +6,7 @@ namespace rack {




/** Widget that does not respond to events and does not pass events to children */ /** Widget that does not respond to events and does not pass events to children */
struct TransparentWidget : VirtualWidget {
struct TransparentWidget : virtual Widget {
/** Override behavior to do nothing instead. */ /** Override behavior to do nothing instead. */
void onHover(event::Hover &e) override {} void onHover(event::Hover &e) override {}
void onButton(event::Button &e) override {} void onButton(event::Button &e) override {}


+ 1
- 7
include/widgets/Widget.hpp View File

@@ -12,7 +12,7 @@ namespace rack {


/** A node in the 2D scene graph /** A node in the 2D scene graph
It is recommended to inherit virtually from Widget instead of directly. It is recommended to inherit virtually from Widget instead of directly.
e.g. `struct MyWidget : VirtualWidget {}`
e.g. `struct MyWidget : virtual Widget {}`
*/ */
struct Widget { struct Widget {
/** Stores position and size */ /** Stores position and size */
@@ -125,10 +125,4 @@ struct Widget {
}; };




/** Inherit from this class instead of inheriting from Widget directly.
Allows multiple inheritance in the class hierarchy.
*/
struct VirtualWidget : virtual Widget {};


} // namespace rack } // namespace rack

+ 15
- 22
include/widgets/ZoomWidget.hpp View File

@@ -5,7 +5,7 @@
namespace rack { namespace rack {




struct ZoomWidget : VirtualWidget {
struct ZoomWidget : virtual Widget {
float zoom = 1.f; float zoom = 1.f;


math::Vec getRelativeOffset(math::Vec v, Widget *relative) override { math::Vec getRelativeOffset(math::Vec v, Widget *relative) override {
@@ -36,39 +36,32 @@ struct ZoomWidget : VirtualWidget {
} }


void onHover(event::Hover &e) override { void onHover(event::Hover &e) override {
event::Hover e2 = e;
e2.pos = e.pos.div(zoom);
Widget::onHover(e2);
e.pos = e.pos.div(zoom);
Widget::onHover(e);
} }
void onButton(event::Button &e) override { void onButton(event::Button &e) override {
event::Button e2 = e;
e2.pos = e.pos.div(zoom);
Widget::onButton(e2);
e.pos = e.pos.div(zoom);
Widget::onButton(e);
} }
void onHoverKey(event::HoverKey &e) override { void onHoverKey(event::HoverKey &e) override {
event::HoverKey e2 = e;
e2.pos = e.pos.div(zoom);
Widget::onHoverKey(e2);
e.pos = e.pos.div(zoom);
Widget::onHoverKey(e);
} }
void onHoverText(event::HoverText &e) override { void onHoverText(event::HoverText &e) override {
event::HoverText e2 = e;
e2.pos = e.pos.div(zoom);
Widget::onHoverText(e2);
e.pos = e.pos.div(zoom);
Widget::onHoverText(e);
} }
void onHoverScroll(event::HoverScroll &e) override { void onHoverScroll(event::HoverScroll &e) override {
event::HoverScroll e2 = e;
e2.pos = e.pos.div(zoom);
Widget::onHoverScroll(e2);
e.pos = e.pos.div(zoom);
Widget::onHoverScroll(e);
} }
void onDragHover(event::DragHover &e) override { void onDragHover(event::DragHover &e) override {
event::DragHover e2 = e;
e2.pos = e.pos.div(zoom);
Widget::onDragHover(e2);
e.pos = e.pos.div(zoom);
Widget::onDragHover(e);
} }
void onPathDrop(event::PathDrop &e) override { void onPathDrop(event::PathDrop &e) override {
event::PathDrop e2 = e;
e2.pos = e.pos.div(zoom);
Widget::onPathDrop(e2);
e.pos = e.pos.div(zoom);
Widget::onPathDrop(e);
} }
}; };




+ 39
- 0
src/app/Knob.cpp View File

@@ -0,0 +1,39 @@
#include "app/Knob.hpp"


namespace rack {


void Knob::onDragStart(event::DragStart &e) {
context()->window->cursorLock();
e.target = this;
}

void Knob::onDragEnd(event::DragEnd &e) {
context()->window->cursorUnlock();
}

void Knob::onDragMove(event::DragMove &e) {
if (quantity) {
float range;
if (quantity->isBounded()) {
range = quantity->getRange();
}
else {
// Continuous encoders scale as if their limits are +/-1
range = 2.f;
}
float delta = KNOB_SENSITIVITY * -e.mouseDelta.y * speed * range;

// Drag slower if Mod is held
if (context()->window->isModPressed())
delta /= 16.f;
quantity->moveValue(delta);

event::Change eChange;
onChange(eChange);
}
}


} // namespace rack

+ 1
- 0
src/app/ModuleBrowser.cpp View File

@@ -12,6 +12,7 @@
#include "ui/TextField.hpp" #include "ui/TextField.hpp"
#include "plugin.hpp" #include "plugin.hpp"
#include "context.hpp" #include "context.hpp"
#include "logger.hpp"




static const float itemMargin = 2.0; static const float itemMargin = 2.0;


+ 1
- 0
src/app/ModuleWidget.cpp View File

@@ -365,6 +365,7 @@ void ModuleWidget::onHoverKey(event::HoverKey &e) {


void ModuleWidget::onDragStart(event::DragStart &e) { void ModuleWidget::onDragStart(event::DragStart &e) {
dragPos = context()->scene->rackWidget->lastMousePos.minus(box.pos); dragPos = context()->scene->rackWidget->lastMousePos.minus(box.pos);
e.target = this;
} }


void ModuleWidget::onDragEnd(event::DragEnd &e) { void ModuleWidget::onDragEnd(event::DragEnd &e) {


+ 74
- 0
src/app/ParamQuantity.cpp View File

@@ -0,0 +1,74 @@
#include "app/ParamQuantity.hpp"


namespace rack {


Param *ParamQuantity::getParam() {
assert(module);
return &module->params[paramId];
}

void ParamQuantity::commitSnap() {
// TODO
}

void ParamQuantity::setValue(float value) {
value = math::clamp(value, getMinValue(), getMaxValue());
// TODO Smooth
// TODO Snap
getParam()->value = value;
}

float ParamQuantity::getValue() {
return getParam()->value;
}

float ParamQuantity::getMinValue() {
return getParam()->minValue;
}

float ParamQuantity::getMaxValue() {
return getParam()->maxValue;
}

float ParamQuantity::getDefaultValue() {
return getParam()->defaultValue;
}

float ParamQuantity::getDisplayValue() {
if (getParam()->displayBase == 0.f) {
// Linear
return getParam()->value * getParam()->displayMultiplier;
}
else {
// Exponential
return std::pow(getParam()->displayBase, getParam()->value) * getParam()->displayMultiplier;
}
}

void ParamQuantity::setDisplayValue(float displayValue) {
if (getParam()->displayBase == 0.f) {
// Linear
getParam()->value = displayValue / getParam()->displayMultiplier;
}
else {
// Exponential
getParam()->value = std::log(displayValue / getParam()->displayMultiplier) / std::log(getParam()->displayBase);
}
}

int ParamQuantity::getDisplayPrecision() {
return getParam()->displayPrecision;
}

std::string ParamQuantity::getLabel() {
return getParam()->label;
}

std::string ParamQuantity::getUnit() {
return getParam()->unit;
}


} // namespace rack

+ 1
- 0
src/app/RackWidget.cpp View File

@@ -511,6 +511,7 @@ void RackWidget::onHover(event::Hover &e) {
} }


void RackWidget::onButton(event::Button &e) { void RackWidget::onButton(event::Button &e) {
DEBUG("what");
OpaqueWidget::onButton(e); OpaqueWidget::onButton(e);
if (e.target == this) { if (e.target == this) {
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) {


+ 3
- 3
src/app/SVGKnob.cpp View File

@@ -30,11 +30,11 @@ void SVGKnob::step() {
if (dirty && quantity) { if (dirty && quantity) {
float angle; float angle;
if (quantity->isBounded()) { if (quantity->isBounded()) {
angle = math::rescale(quantity->getValue(), -1.f, 1.f, minAngle, maxAngle);
angle = math::rescale(quantity->getScaledValue(), 0.f, 1.f, minAngle, maxAngle);
angle = std::fmod(angle, 2*M_PI); angle = std::fmod(angle, 2*M_PI);
} }
else { else {
angle = math::rescale(quantity->getScaledValue(), 0.f, 1.f, minAngle, maxAngle);
angle = math::rescale(quantity->getValue(), 0.f, 1.f, minAngle, maxAngle);
} }
tw->identity(); tw->identity();
// Rotate SVG // Rotate SVG
@@ -48,7 +48,7 @@ void SVGKnob::step() {


void SVGKnob::onChange(event::Change &e) { void SVGKnob::onChange(event::Change &e) {
dirty = true; dirty = true;
ParamWidget::onChange(e);
Knob::onChange(e);
} }






+ 9
- 9
src/event.cpp View File

@@ -22,7 +22,7 @@ void Context::handleButton(math::Vec pos, int button, int action, int mods) {
// event::DragStart // event::DragStart
event::DragStart eDragStart; event::DragStart eDragStart;
clickedWidget->onDragStart(eDragStart); clickedWidget->onDragStart(eDragStart);
draggedWidget = clickedWidget;
draggedWidget = eDragStart.target;
} }


if (action == GLFW_RELEASE && draggedWidget) { if (action == GLFW_RELEASE && draggedWidget) {
@@ -63,14 +63,14 @@ void Context::handleButton(math::Vec pos, int button, int action, int mods) {
} }
} }


if (button == GLFW_MOUSE_BUTTON_MIDDLE) {
if (action == GLFW_PRESS) {
scrollWidget = clickedWidget;
}
if (action == GLFW_RELEASE) {
scrollWidget = NULL;
}
}
// if (button == GLFW_MOUSE_BUTTON_MIDDLE) {
// if (action == GLFW_PRESS) {
// scrollWidget = clickedWidget;
// }
// if (action == GLFW_RELEASE) {
// scrollWidget = NULL;
// }
// }
} }






+ 9
- 0
src/widgets/Widget.cpp View File

@@ -99,6 +99,15 @@ void Widget::draw(NVGcontext *vg) {
nvgSave(vg); nvgSave(vg);
nvgTranslate(vg, child->box.pos.x, child->box.pos.y); nvgTranslate(vg, child->box.pos.x, child->box.pos.y);
child->draw(vg); child->draw(vg);

// Draw red hitboxes
// if (context()->event->hoveredWidget == child) {
// nvgBeginPath(vg);
// nvgRect(vg, 0, 0, child->box.size.x, child->box.size.y);
// nvgFillColor(vg, nvgRGBAf(1, 0, 0, 0.5));
// nvgFill(vg);
// }

nvgRestore(vg); nvgRestore(vg);
} }
} }


Loading…
Cancel
Save