Browse Source

Merge branch 'master' of https://github.com/VCVRack/Rack into 2017-10-bontric-midiCC-fix

tags/v0.5.0
ben 7 years ago
parent
commit
786ee4cdc0
25 changed files with 115 additions and 62 deletions
  1. +1
    -0
      .gitignore
  2. +2
    -0
      include/app.hpp
  3. +2
    -1
      include/engine.hpp
  4. +21
    -2
      include/math.hpp
  5. +11
    -1
      include/widgets.hpp
  6. +3
    -1
      src/app.cpp
  7. +0
    -3
      src/app/RackScene.cpp
  8. +1
    -1
      src/app/RackScrollWidget.cpp
  9. +1
    -0
      src/app/RackWidget.cpp
  10. +8
    -0
      src/app/SVGPanel.cpp
  11. +10
    -4
      src/app/Toolbar.cpp
  12. +4
    -8
      src/app/WireWidget.cpp
  13. +3
    -3
      src/core/AudioInterface.cpp
  14. +1
    -1
      src/core/MidiClockToCV.cpp
  15. +2
    -2
      src/core/MidiIO.cpp
  16. +1
    -1
      src/core/QuadMidiToCV.cpp
  17. +2
    -2
      src/engine.cpp
  18. +9
    -5
      src/gui.cpp
  19. +5
    -3
      src/settings.cpp
  20. +2
    -6
      src/widgets/FramebufferWidget.cpp
  21. +1
    -0
      src/widgets/SVGWidget.cpp
  22. +2
    -0
      src/widgets/Slider.cpp
  23. +1
    -1
      src/widgets/Tooltip.cpp
  24. +17
    -17
      src/widgets/Widget.cpp
  25. +5
    -0
      src/widgets/ZoomWidget.cpp

+ 1
- 0
.gitignore View File

@@ -8,3 +8,4 @@
*.vcv *.vcv
/patches /patches
/design /design
.DS_Store

+ 2
- 0
include/app.hpp View File

@@ -155,6 +155,7 @@ struct Panel : TransparentWidget {
}; };


struct SVGPanel : FramebufferWidget { struct SVGPanel : FramebufferWidget {
void step() override;
void setBackground(std::shared_ptr<SVG> svg); void setBackground(std::shared_ptr<SVG> svg);
}; };


@@ -354,6 +355,7 @@ extern std::string gApplicationVersion;
extern std::string gApiHost; extern std::string gApiHost;


// Easy access to "singleton" widgets // Easy access to "singleton" widgets
extern RackScene *gRackScene;
extern RackWidget *gRackWidget; extern RackWidget *gRackWidget;
extern Toolbar *gToolbar; extern Toolbar *gToolbar;




+ 2
- 1
include/engine.hpp View File

@@ -30,8 +30,9 @@ struct Output {
}; };


struct Light { struct Light {
/** The square of the brightness value */
float value = 0.0; float value = 0.0;
void setSmooth(float v);
void setBrightnessSmooth(float brightness);
}; };






+ 21
- 2
include/math.hpp View File

@@ -2,7 +2,7 @@


#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
#include <cmath>




namespace rack { namespace rack {
@@ -61,6 +61,10 @@ inline float eucmodf(float a, float base) {
return mod < 0.0 ? mod + base : mod; return mod < 0.0 ? mod + base : mod;
} }


inline float nearf(float a, float b, float epsilon = 1e-6) {
return fabsf(a - b) <= epsilon;
}

/** Limits a value between a minimum and maximum /** Limits a value between a minimum and maximum
If min > max, the limits are switched If min > max, the limits are switched
*/ */
@@ -204,7 +208,7 @@ struct Vec {
return x == 0.0 && y == 0.0; return x == 0.0 && y == 0.0;
} }
bool isFinite() { bool isFinite() {
return isfinite(x) && isfinite(y);
return std::isfinite(x) && std::isfinite(y);
} }
Vec clamp(Rect bound); Vec clamp(Rect bound);
}; };
@@ -267,6 +271,21 @@ struct Rect {
r.pos.y = clampf(pos.y, bound.pos.y, bound.pos.y + bound.size.y - size.y); r.pos.y = clampf(pos.y, bound.pos.y, bound.pos.y + bound.size.y - size.y);
return r; return r;
} }
/** Expands this Rect to contain `other` */
Rect expand(Rect other) {
Rect r;
r.pos.x = fminf(pos.x, other.pos.x);
r.pos.y = fminf(pos.y, other.pos.y);
r.size.x = fmaxf(pos.x + size.x, other.pos.x + other.size.x) - r.pos.x;
r.size.y = fmaxf(pos.y + size.y, other.pos.y + other.size.y) - r.pos.y;
return r;
}
/** Returns a Rect with its position set to zero */
Rect zeroPos() {
Rect r;
r.size = size;
return r;
}
}; };






+ 11
- 1
include/widgets.hpp View File

@@ -56,8 +56,13 @@ struct Widget {


virtual ~Widget(); virtual ~Widget();


Vec getAbsolutePos();
Rect getChildrenBoundingBox(); Rect getChildrenBoundingBox();
/** Returns `v` transformed into the coordinate system of `relative` */
virtual Vec getRelativeOffset(Vec v, Widget *relative);
/** Returns `v` transformed into world coordinates */
Vec getAbsoluteOffset(Vec v) {
return getRelativeOffset(v, NULL);
}
/** Returns a subset of the given Rect bounded by the box of this widget and all ancestors */ /** Returns a subset of the given Rect bounded by the box of this widget and all ancestors */
virtual Rect getViewport(Rect r); virtual Rect getViewport(Rect r);


@@ -149,6 +154,7 @@ struct TransformWidget : Widget {


struct ZoomWidget : Widget { struct ZoomWidget : Widget {
float zoom = 1.0; float zoom = 1.0;
Vec getRelativeOffset(Vec v, Widget *relative) override;
Rect getViewport(Rect r) override; Rect getViewport(Rect r) override;
void setZoom(float zoom); void setZoom(float zoom);
void draw(NVGcontext *vg) override; void draw(NVGcontext *vg) override;
@@ -230,6 +236,10 @@ Events are not passed to the underlying scene.
struct FramebufferWidget : virtual Widget { 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
This prevents cutting the rendered SVG off on the box edges.
*/
float oversample;
/** The root object in the framebuffer scene /** The root object in the framebuffer scene
The FramebufferWidget owns the pointer The FramebufferWidget owns the pointer
*/ */


+ 3
- 1
src/app.cpp View File

@@ -14,10 +14,12 @@ std::string gApiHost = "http://api.vcvrack.com";


RackWidget *gRackWidget = NULL; RackWidget *gRackWidget = NULL;
Toolbar *gToolbar = NULL; Toolbar *gToolbar = NULL;
RackScene *gRackScene = NULL;




void sceneInit() { void sceneInit() {
gScene = new RackScene();
gRackScene = new RackScene();
gScene = gRackScene;
} }


void sceneDestroy() { void sceneDestroy() {


+ 0
- 3
src/app/RackScene.cpp View File

@@ -62,9 +62,6 @@ void RackScene::step() {
.plus(Vec(500, 500)) .plus(Vec(500, 500))
.div(zoomWidget->zoom); .div(zoomWidget->zoom);


// Set zoom from the toolbar's zoom slider
zoomWidget->setZoom(gToolbar->zoomSlider->value / 100.0);

Scene::step(); Scene::step();


zoomWidget->box.size = gRackWidget->box.size.mult(zoomWidget->zoom); zoomWidget->box.size = gRackWidget->box.size.mult(zoomWidget->zoom);


+ 1
- 1
src/app/RackScrollWidget.cpp View File

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




void RackScrollWidget::step() { void RackScrollWidget::step() {
Vec pos = gMousePos.minus(getAbsolutePos());
Vec pos = gRackWidget->lastMousePos;
// Scroll rack if dragging cable near the edge of the screen // Scroll rack if dragging cable near the edge of the screen
if (gRackWidget->wireContainer->activeWire) { if (gRackWidget->wireContainer->activeWire) {
float margin = 20.0; float margin = 20.0;


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

@@ -17,6 +17,7 @@ namespace rack {
RackWidget::RackWidget() { RackWidget::RackWidget() {
rails = new FramebufferWidget(); rails = new FramebufferWidget();
rails->box.size = Vec(); rails->box.size = Vec();
rails->oversample = 1.0;
{ {
RackRail *rail = new RackRail(); RackRail *rail = new RackRail();
rail->box.size = Vec(); rail->box.size = Vec();


+ 8
- 0
src/app/SVGPanel.cpp View File

@@ -1,4 +1,5 @@
#include "app.hpp" #include "app.hpp"
#include "gui.hpp"




namespace rack { namespace rack {
@@ -16,6 +17,13 @@ struct PanelBorder : TransparentWidget {
}; };




void SVGPanel::step() {
if (nearf(gPixelRatio, 1.0)) {
oversample = 2.0;
}
FramebufferWidget::step();
}

void SVGPanel::setBackground(std::shared_ptr<SVG> svg) { void SVGPanel::setBackground(std::shared_ptr<SVG> svg) {
clearChildren(); clearChildren();




+ 10
- 4
src/app/Toolbar.cpp View File

@@ -39,7 +39,7 @@ struct QuitItem : MenuItem {
struct FileChoice : ChoiceButton { struct FileChoice : ChoiceButton {
void onAction() override { void onAction() override {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y));
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y));
menu->box.size.x = box.size.x; menu->box.size.x = box.size.x;


{ {
@@ -70,7 +70,7 @@ struct SampleRateItem : MenuItem {
struct SampleRateChoice : ChoiceButton { struct SampleRateChoice : ChoiceButton {
void onAction() override { void onAction() override {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y));
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y));
menu->box.size.x = box.size.x; menu->box.size.x = box.size.x;


PauseItem *pauseItem = new PauseItem(); PauseItem *pauseItem = new PauseItem();
@@ -148,12 +148,18 @@ Toolbar::Toolbar() {


xPos += margin; xPos += margin;
{ {
zoomSlider = new Slider();
struct ZoomSlider : Slider {
void onAction() override {
Slider::onAction();
gRackScene->zoomWidget->setZoom(value / 100.0);
}
};
zoomSlider = new ZoomSlider();
zoomSlider->box.pos = Vec(xPos, margin); zoomSlider->box.pos = Vec(xPos, margin);
zoomSlider->box.size.x = 150; zoomSlider->box.size.x = 150;
zoomSlider->label = "Zoom"; zoomSlider->label = "Zoom";
zoomSlider->unit = "%"; zoomSlider->unit = "%";
zoomSlider->setLimits(33.33, 200.0);
zoomSlider->setLimits(25.0, 200.0);
zoomSlider->setDefaultValue(100.0); zoomSlider->setDefaultValue(100.0);
addChild(zoomSlider); addChild(zoomSlider);
xPos += zoomSlider->box.size.x; xPos += zoomSlider->box.size.x;


+ 4
- 8
src/app/WireWidget.cpp View File

@@ -124,31 +124,27 @@ void WireWidget::updateWire() {
} }


Vec WireWidget::getOutputPos() { Vec WireWidget::getOutputPos() {
Vec pos;
if (outputPort) { if (outputPort) {
pos = Rect(outputPort->getAbsolutePos(), outputPort->box.size).getCenter();
return outputPort->getRelativeOffset(outputPort->box.zeroPos().getCenter(), gRackWidget);
} }
else if (hoveredOutputPort) { else if (hoveredOutputPort) {
pos = Rect(hoveredOutputPort->getAbsolutePos(), hoveredOutputPort->box.size).getCenter();
return hoveredOutputPort->getRelativeOffset(hoveredOutputPort->box.zeroPos().getCenter(), gRackWidget);
} }
else { else {
return gRackWidget->lastMousePos; return gRackWidget->lastMousePos;
} }
return pos.minus(getAbsolutePos().minus(box.pos));
} }


Vec WireWidget::getInputPos() { Vec WireWidget::getInputPos() {
Vec pos;
if (inputPort) { if (inputPort) {
pos = Rect(inputPort->getAbsolutePos(), inputPort->box.size).getCenter();
return inputPort->getRelativeOffset(inputPort->box.zeroPos().getCenter(), gRackWidget);
} }
else if (hoveredInputPort) { else if (hoveredInputPort) {
pos = Rect(hoveredInputPort->getAbsolutePos(), hoveredInputPort->box.size).getCenter();
return hoveredInputPort->getRelativeOffset(hoveredInputPort->box.zeroPos().getCenter(), gRackWidget);
} }
else { else {
return gRackWidget->lastMousePos; return gRackWidget->lastMousePos;
} }
return pos.minus(getAbsolutePos().minus(box.pos));
} }


void WireWidget::draw(NVGcontext *vg) { void WireWidget::draw(NVGcontext *vg) {


+ 3
- 3
src/core/AudioInterface.cpp View File

@@ -335,7 +335,7 @@ struct AudioChoice : ChoiceButton {
AudioInterface *audioInterface; AudioInterface *audioInterface;
void onAction() override { void onAction() override {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y));
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x; menu->box.size.x = box.size.x;


int deviceCount = audioInterface->getDeviceCount(); int deviceCount = audioInterface->getDeviceCount();
@@ -373,7 +373,7 @@ struct SampleRateChoice : ChoiceButton {
AudioInterface *audioInterface; AudioInterface *audioInterface;
void onAction() override { void onAction() override {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y));
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x; menu->box.size.x = box.size.x;


const float sampleRates[6] = {44100, 48000, 88200, 96000, 176400, 192000}; const float sampleRates[6] = {44100, 48000, 88200, 96000, 176400, 192000};
@@ -404,7 +404,7 @@ struct BlockSizeChoice : ChoiceButton {
AudioInterface *audioInterface; AudioInterface *audioInterface;
void onAction() override { void onAction() override {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y));
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x; menu->box.size.x = box.size.x;


const int blockSizes[] = {64, 128, 256, 512, 1024, 2048, 4096}; const int blockSizes[] = {64, 128, 256, 512, 1024, 2048, 4096};


+ 1
- 1
src/core/MidiClockToCV.cpp View File

@@ -205,7 +205,7 @@ struct ClockRatioChoice : ChoiceButton {


void onAction() { void onAction() {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y));
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x; menu->box.size.x = box.size.x;


for (unsigned long ratio = 0; ratio < ratioNames.size(); ratio++) { for (unsigned long ratio = 0; ratio < ratioNames.size(); ratio++) {


+ 2
- 2
src/core/MidiIO.cpp View File

@@ -181,7 +181,7 @@ void MidiItem::onAction() {


void MidiChoice::onAction() { void MidiChoice::onAction() {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y));
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x; menu->box.size.x = box.size.x;


{ {
@@ -216,7 +216,7 @@ void ChannelItem::onAction() {


void ChannelChoice::onAction() { void ChannelChoice::onAction() {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y));
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x; menu->box.size.x = box.size.x;


{ {


+ 1
- 1
src/core/QuadMidiToCV.cpp View File

@@ -256,7 +256,7 @@ struct ModeChoice : ChoiceButton {


void onAction() { void onAction() {
Menu *menu = gScene->createMenu(); Menu *menu = gScene->createMenu();
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y));
menu->box.pos = getAbsoluteOffset(Vec(0, box.size.y)).round();
menu->box.size.x = box.size.x; menu->box.size.x = box.size.x;


for (unsigned long i = 0; i < modeNames.size(); i++) { for (unsigned long i = 0; i < modeNames.size(); i++) {


+ 2
- 2
src/engine.cpp View File

@@ -33,8 +33,8 @@ static int smoothParamId;
static float smoothValue; static float smoothValue;




void Light::setSmooth(float v) {
value += (v - value) / sampleRate * 60.0;
void Light::setBrightnessSmooth(float brightness) {
value += (powf(brightness, 2) - value) / sampleRate * 60.0;
} }






+ 9
- 5
src/gui.cpp View File

@@ -218,9 +218,6 @@ void errorCallback(int error, const char *description) {
void renderGui() { void renderGui() {
int width, height; int width, height;
glfwGetFramebufferSize(gWindow, &width, &height); glfwGetFramebufferSize(gWindow, &width, &height);
int windowWidth, windowHeight;
glfwGetWindowSize(gWindow, &windowWidth, &windowHeight);
gPixelRatio = (float)width / windowWidth;


// Update and render // Update and render
nvgBeginFrame(gVg, width, height, gPixelRatio); nvgBeginFrame(gVg, width, height, gPixelRatio);
@@ -257,7 +254,7 @@ void guiInit() {
glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE); glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
gWindow = glfwCreateWindow(640, 480, "", NULL, NULL); gWindow = glfwCreateWindow(640, 480, "", NULL, NULL);
if (!gWindow) { if (!gWindow) {
osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Cannot open window with OpenGL 2.0 renderer. Does your graphics card support OpenGL 2.0 or greater? If so, are the latest drivers installed?");
osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Cannot open window with OpenGL 2.0 renderer. Does your graphics card support OpenGL 2.0 or greater? If so, make sure you have the latest graphics drivers installed.");
exit(1); exit(1);
} }


@@ -277,7 +274,7 @@ void guiInit() {
glewExperimental = GL_TRUE; glewExperimental = GL_TRUE;
err = glewInit(); err = glewInit();
if (err != GLEW_OK) { if (err != GLEW_OK) {
osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Could not initialize GLEW. Does your graphics card support OpenGL 2.0 or greater? If so, are the latest drivers installed?");
osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Could not initialize GLEW. Does your graphics card support OpenGL 2.0 or greater? If so, make sure you have the latest graphics drivers installed.");
exit(1); exit(1);
} }


@@ -341,6 +338,13 @@ void guiRun() {
} }
glfwSetWindowTitle(gWindow, title.c_str()); glfwSetWindowTitle(gWindow, title.c_str());


// Get framebuffer size
int width, height;
glfwGetFramebufferSize(gWindow, &width, &height);
int windowWidth, windowHeight;
glfwGetWindowSize(gWindow, &windowWidth, &windowHeight);
gPixelRatio = (float)width / windowWidth;

// Step scene // Step scene
gScene->step(); gScene->step();




+ 5
- 3
src/settings.cpp View File

@@ -28,7 +28,7 @@ static json_t *settingsToJson() {
json_object_set_new(rootJ, "wireTension", tensionJ); json_object_set_new(rootJ, "wireTension", tensionJ);


// zoom // zoom
float zoom = gToolbar->zoomSlider->value;
float zoom = gRackScene->zoomWidget->zoom;
json_t *zoomJ = json_real(zoom); json_t *zoomJ = json_real(zoom);
json_object_set_new(rootJ, "zoom", zoomJ); json_object_set_new(rootJ, "zoom", zoomJ);


@@ -69,8 +69,10 @@ static void settingsFromJson(json_t *rootJ) {


// zoom // zoom
json_t *zoomJ = json_object_get(rootJ, "zoom"); json_t *zoomJ = json_object_get(rootJ, "zoom");
if (zoomJ)
gToolbar->zoomSlider->value = json_number_value(zoomJ);
if (zoomJ) {
gRackScene->zoomWidget->setZoom(clampf(json_number_value(zoomJ), 0.25, 4.0));
gToolbar->zoomSlider->setValue(json_number_value(zoomJ) * 100.0);
}


// allowCursorLock // allowCursorLock
json_t *allowCursorLockJ = json_object_get(rootJ, "allowCursorLock"); json_t *allowCursorLockJ = json_object_get(rootJ, "allowCursorLock");


+ 2
- 6
src/widgets/FramebufferWidget.cpp View File

@@ -9,12 +9,6 @@
namespace rack { namespace rack {




/** A margin in pixels around the children in the framebuffer
This prevents cutting the rendered SVG off on the box edges.
*/
static const float oversample = 2.0;


struct FramebufferWidget::Internal { struct FramebufferWidget::Internal {
NVGLUframebuffer *fb = NULL; NVGLUframebuffer *fb = NULL;
Rect box; Rect box;
@@ -31,6 +25,7 @@ struct FramebufferWidget::Internal {




FramebufferWidget::FramebufferWidget() { FramebufferWidget::FramebufferWidget() {
oversample = 1.0;
internal = new Internal(); internal = new Internal();
} }


@@ -65,6 +60,7 @@ void FramebufferWidget::draw(NVGcontext *vg) {
if (fbSize.x <= 0.0 || fbSize.y <= 0.0) if (fbSize.x <= 0.0 || fbSize.y <= 0.0)
return; return;


// printf("rendering framebuffer %f %f\n", fbSize.x, fbSize.y);
// Delete old one first to free up GPU memory // Delete old one first to free up GPU memory
internal->setFramebuffer(NULL); internal->setFramebuffer(NULL);
// Create a framebuffer from the main nanovg context. We will draw to this in the secondary nanovg context. // Create a framebuffer from the main nanovg context. We will draw to this in the secondary nanovg context.


+ 1
- 0
src/widgets/SVGWidget.cpp View File

@@ -201,6 +201,7 @@ void SVGWidget::wrap() {


void SVGWidget::draw(NVGcontext *vg) { void SVGWidget::draw(NVGcontext *vg) {
if (svg && svg->handle) { if (svg && svg->handle) {
// printf("drawing svg %f %f\n", box.size.x, box.size.y);
drawSVG(vg, svg->handle); drawSVG(vg, svg->handle);
} }
} }


+ 2
- 0
src/widgets/Slider.cpp View File

@@ -23,11 +23,13 @@ void Slider::onDragMove(Vec mouseRel) {
void Slider::onDragEnd() { void Slider::onDragEnd() {
state = BND_DEFAULT; state = BND_DEFAULT;
guiCursorUnlock(); guiCursorUnlock();
onAction();
} }


void Slider::onMouseDownOpaque(int button) { void Slider::onMouseDownOpaque(int button) {
if (button == 1) { if (button == 1) {
setValue(defaultValue); setValue(defaultValue);
onAction();
} }
} }




+ 1
- 1
src/widgets/Tooltip.cpp View File

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


void Tooltip::step() { void Tooltip::step() {
// Follow the mouse // Follow the mouse
box.pos = gMousePos.minus(parent->getAbsolutePos());
box.pos = gMousePos;


// Wrap size to contents // Wrap size to contents
// box.size = getChildrenBoundingBox().getBottomRight(); // box.size = getChildrenBoundingBox().getBottomRight();


+ 17
- 17
src/widgets/Widget.cpp View File

@@ -16,28 +16,28 @@ Widget::~Widget() {
clearChildren(); clearChildren();
} }


Vec Widget::getAbsolutePos() {
// Recursively compute position offset from parents
if (!parent) {
return box.pos;
}
else {
return box.pos.plus(parent->getAbsolutePos());
Rect Widget::getChildrenBoundingBox() {
Rect bound;
for (Widget *child : children) {
if (child == children.front()) {
bound = child->box;
}
else {
bound = bound.expand(child->box);
}
} }
return bound;
} }


Rect Widget::getChildrenBoundingBox() {
if (children.empty()) {
return Rect();
Vec Widget::getRelativeOffset(Vec v, Widget *relative) {
if (this == relative) {
return v;
} }

Vec topLeft = Vec(INFINITY, INFINITY);
Vec bottomRight = Vec(-INFINITY, -INFINITY);
for (Widget *child : children) {
topLeft = topLeft.min(child->box.pos);
bottomRight = bottomRight.max(child->box.getBottomRight());
v = v.plus(box.pos);
if (parent) {
v = parent->getRelativeOffset(v, relative);
} }
return Rect(topLeft, bottomRight.minus(topLeft));
return v;
} }


Rect Widget::getViewport(Rect r) { Rect Widget::getViewport(Rect r) {


+ 5
- 0
src/widgets/ZoomWidget.cpp View File

@@ -3,6 +3,11 @@


namespace rack { namespace rack {



Vec ZoomWidget::getRelativeOffset(Vec v, Widget *relative) {
return Widget::getRelativeOffset(v.mult(zoom), relative);
}

Rect ZoomWidget::getViewport(Rect r) { Rect ZoomWidget::getViewport(Rect r) {
r.pos = r.pos.mult(zoom); r.pos = r.pos.mult(zoom);
r.size = r.size.mult(zoom); r.size = r.size.mult(zoom);


Loading…
Cancel
Save