@@ -1,5 +1,5 @@ | |||||
ARCH ?= lin | ARCH ?= lin | ||||
FLAGS = -g -Wall -O3 -msse -mfpmath=sse -ffast-math \ | |||||
FLAGS = -g -Wall -O3 -msse -mfpmath=sse -ffast-math -fno-finite-math-only \ | |||||
-I./ext -I./include | -I./ext -I./include | ||||
CXXFLAGS = -fno-exceptions | CXXFLAGS = -fno-exceptions | ||||
@@ -36,56 +36,47 @@ struct SynthTechAlco : SpriteKnob { | |||||
} | } | ||||
}; | }; | ||||
struct KnobDavies1900h : SpriteKnob { | |||||
KnobDavies1900h() { | |||||
struct Davies1900hKnob : SVGKnob { | |||||
Davies1900hKnob() { | |||||
box.size = Vec(36, 36); | box.size = Vec(36, 36); | ||||
spriteOffset = Vec(-2, -2); | |||||
spriteSize = Vec(42, 42); | |||||
minIndex = 44; | |||||
maxIndex = -46; | |||||
spriteCount = 120; | |||||
minAngle = -0.75*M_PI; | |||||
maxAngle = 0.75*M_PI; | |||||
} | } | ||||
}; | }; | ||||
struct KnobDavies1900hWhite : KnobDavies1900h { | |||||
KnobDavies1900hWhite() { | |||||
spriteImage = Image::load("res/ComponentLibrary/Davies1900hWhite.png"); | |||||
struct Davies1900hWhiteKnob : Davies1900hKnob { | |||||
Davies1900hWhiteKnob() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Davies1900hWhite.svg")); | |||||
} | } | ||||
}; | }; | ||||
struct KnobDavies1900hBlack : KnobDavies1900h { | |||||
KnobDavies1900hBlack() { | |||||
spriteImage = Image::load("res/ComponentLibrary/Davies1900hBlack.png"); | |||||
struct Davies1900hBlackKnob : Davies1900hKnob { | |||||
Davies1900hBlackKnob() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Davies1900hBlack.svg")); | |||||
} | } | ||||
}; | }; | ||||
struct KnobDavies1900hRed : KnobDavies1900h { | |||||
KnobDavies1900hRed() { | |||||
spriteImage = Image::load("res/ComponentLibrary/Davies1900hRed.png"); | |||||
struct Davies1900hRedKnob : Davies1900hKnob { | |||||
Davies1900hRedKnob() { | |||||
setSVG(SVG::load("res/ComponentLibrary/Davies1900hRed.svg")); | |||||
} | } | ||||
}; | }; | ||||
struct BefacoBigKnob : SpriteKnob { | |||||
struct BefacoBigKnob : SVGKnob { | |||||
BefacoBigKnob() { | BefacoBigKnob() { | ||||
box.size = Vec(75, 75); | box.size = Vec(75, 75); | ||||
spriteOffset = Vec(-2, -2); | |||||
spriteSize = Vec(81, 81); | |||||
minIndex = 44; | |||||
maxIndex = -46; | |||||
spriteCount = 120; | |||||
spriteImage = Image::load("res/ComponentLibrary/BefacoBigKnob.png"); | |||||
minAngle = -0.75*M_PI; | |||||
maxAngle = 0.75*M_PI; | |||||
setSVG(SVG::load("res/ComponentLibrary/BefacoBigKnob.svg")); | |||||
} | } | ||||
}; | }; | ||||
struct BefacoTinyKnob : SpriteKnob { | |||||
struct BefacoTinyKnob : SVGKnob { | |||||
BefacoTinyKnob() { | BefacoTinyKnob() { | ||||
box.size = Vec(26, 26); | box.size = Vec(26, 26); | ||||
spriteOffset = Vec(-2, -2); | |||||
spriteSize = Vec(32, 32); | |||||
minIndex = 44; | |||||
maxIndex = -46; | |||||
spriteCount = 120; | |||||
spriteImage = Image::load("res/ComponentLibrary/BefacoTinyKnob.png"); | |||||
minAngle = -0.75*M_PI; | |||||
maxAngle = 0.75*M_PI; | |||||
setSVG(SVG::load("res/ComponentLibrary/BefacoTinyKnob.svg")); | |||||
} | } | ||||
}; | }; | ||||
@@ -1,8 +1,13 @@ | |||||
#pragma once | #pragma once | ||||
#include "math.hpp" | |||||
#include "util.hpp" | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "engine.hpp" | #include "engine.hpp" | ||||
#include "gui.hpp" | #include "gui.hpp" | ||||
#include "scene.hpp" | |||||
#include "components.hpp" | #include "components.hpp" | ||||
#include "dsp.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -131,6 +131,20 @@ struct SpriteKnob : Knob, SpriteWidget { | |||||
void step(); | void step(); | ||||
}; | }; | ||||
/** A knob which rotates an SVG and caches it in a framebuffer */ | |||||
struct SVGKnob : Knob, FramebufferWidget { | |||||
/** Angles in radians */ | |||||
float minAngle, maxAngle; | |||||
/** Not owned */ | |||||
TransformWidget *tw; | |||||
SVGWidget *sw; | |||||
SVGKnob(); | |||||
void setSVG(std::shared_ptr<SVG> svg); | |||||
void step(); | |||||
void onChange(); | |||||
}; | |||||
struct Switch : ParamWidget, SpriteWidget { | struct Switch : ParamWidget, SpriteWidget { | ||||
}; | }; | ||||
@@ -95,6 +95,10 @@ struct Widget { | |||||
virtual void onMouseEnter() {} | virtual void onMouseEnter() {} | ||||
/** Called when another widget begins responding to `onMouseMove` events */ | /** Called when another widget begins responding to `onMouseMove` events */ | ||||
virtual void onMouseLeave() {} | virtual void onMouseLeave() {} | ||||
virtual void onSelect() {} | |||||
virtual void onDeselect() {} | |||||
virtual void onText(int codepoint) {} | |||||
virtual void onKey(int key) {} | |||||
virtual Widget *onScroll(Vec pos, Vec scrollRel); | virtual Widget *onScroll(Vec pos, Vec scrollRel); | ||||
/** Called when a widget responds to `onMouseDown` for a left button press */ | /** Called when a widget responds to `onMouseDown` for a left button press */ | ||||
@@ -116,7 +120,7 @@ struct TransformWidget : Widget { | |||||
/** The transformation matrix */ | /** The transformation matrix */ | ||||
float transform[6]; | float transform[6]; | ||||
TransformWidget(); | TransformWidget(); | ||||
void reset(); | |||||
void identity(); | |||||
void translate(Vec delta); | void translate(Vec delta); | ||||
void rotate(float angle); | void rotate(float angle); | ||||
void scale(Vec s); | void scale(Vec s); | ||||
@@ -175,8 +179,8 @@ struct SpriteWidget : virtual Widget { | |||||
struct SVGWidget : virtual Widget { | struct SVGWidget : virtual Widget { | ||||
std::shared_ptr<SVG> svg; | std::shared_ptr<SVG> svg; | ||||
/** Sets the box size to the svg page */ | |||||
void step(); | |||||
/** Sets the box size to the svg image size */ | |||||
void wrap(); | |||||
void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
}; | }; | ||||
@@ -185,9 +189,9 @@ When `dirty` is true, `scene` will be re-rendered on the next call to step(). | |||||
Events are not passed to the underlying scene. | Events are not passed to the underlying scene. | ||||
*/ | */ | ||||
struct FramebufferWidget : virtual Widget { | struct FramebufferWidget : virtual Widget { | ||||
/** Set this to true to re-render the scene to the framebuffer in the next step() */ | |||||
bool dirty = true; | bool dirty = true; | ||||
/** The root object in the framebuffer scene | /** The root object in the framebuffer scene | ||||
Its position is ignored for now, fixed at (0, 0) | |||||
The FramebufferWidget owns the pointer | The FramebufferWidget owns the pointer | ||||
*/ | */ | ||||
Widget *scene = NULL; | Widget *scene = NULL; | ||||
@@ -196,6 +200,9 @@ struct FramebufferWidget : virtual Widget { | |||||
FramebufferWidget(); | FramebufferWidget(); | ||||
~FramebufferWidget(); | ~FramebufferWidget(); | ||||
void setScene(Widget *w) { | |||||
scene = w; | |||||
} | |||||
void step(); | void step(); | ||||
void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
}; | }; | ||||
@@ -344,6 +351,25 @@ struct ScrollWidget : OpaqueWidget { | |||||
Widget *onScroll(Vec pos, Vec scrollRel); | Widget *onScroll(Vec pos, Vec scrollRel); | ||||
}; | }; | ||||
struct TextField : OpaqueWidget { | |||||
std::string text; | |||||
int begin = 0; | |||||
int end = 0; | |||||
TextField() { | |||||
box.size.y = BND_WIDGET_HEIGHT; | |||||
} | |||||
void draw(NVGcontext *vg); | |||||
Widget *onMouseDown(Vec pos, int button); | |||||
void onText(int codepoint); | |||||
void onKey(int scancode); | |||||
void onSelect(); | |||||
}; | |||||
struct PasswordField : TextField { | |||||
void draw(NVGcontext *vg); | |||||
}; | |||||
struct Tooltip : Widget { | struct Tooltip : Widget { | ||||
void step(); | void step(); | ||||
void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
@@ -6,8 +6,7 @@ | |||||
#include "gui.hpp" | #include "gui.hpp" | ||||
#include "scene.hpp" | #include "scene.hpp" | ||||
// Include implementations here | |||||
// By the way, please stop packaging your libraries like this. It's best to use a single source file (e.g. foo.c) and a single header (e.g. foo.h) | |||||
// #define NANOVG_GL2_IMPLEMENTATION | |||||
#define NANOVG_GL3_IMPLEMENTATION | #define NANOVG_GL3_IMPLEMENTATION | ||||
#include "../ext/nanovg/src/nanovg_gl.h" | #include "../ext/nanovg/src/nanovg_gl.h" | ||||
#include "../ext/nanovg/src/nanovg_gl_utils.h" | #include "../ext/nanovg/src/nanovg_gl_utils.h" | ||||
@@ -36,13 +35,22 @@ void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { | |||||
if (action == GLFW_PRESS) { | if (action == GLFW_PRESS) { | ||||
// onMouseDown | // onMouseDown | ||||
Widget *w = gScene->onMouseDown(gMousePos, button); | Widget *w = gScene->onMouseDown(gMousePos, button); | ||||
gSelectedWidget = w; | |||||
if (button == GLFW_MOUSE_BUTTON_LEFT) { | if (button == GLFW_MOUSE_BUTTON_LEFT) { | ||||
gDraggedWidget = w; | |||||
if (gDraggedWidget) { | |||||
if (w) { | |||||
// onDragStart | // onDragStart | ||||
gDraggedWidget->onDragStart(); | |||||
w->onDragStart(); | |||||
} | |||||
gDraggedWidget = w; | |||||
if (w != gSelectedWidget) { | |||||
if (gSelectedWidget) { | |||||
w->onDeselect(); | |||||
} | |||||
if (w) { | |||||
w->onSelect(); | |||||
} | |||||
gSelectedWidget = w; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -127,13 +135,16 @@ void scrollCallback(GLFWwindow *window, double x, double y) { | |||||
gScene->onScroll(gMousePos, scrollRel.mult(-95)); | gScene->onScroll(gMousePos, scrollRel.mult(-95)); | ||||
} | } | ||||
void charCallback(GLFWwindow *window, unsigned int value) { | |||||
void charCallback(GLFWwindow *window, unsigned int codepoint) { | |||||
if (gSelectedWidget) { | |||||
gSelectedWidget->onText(codepoint); | |||||
} | |||||
} | } | ||||
static int lastWindowX, lastWindowY, lastWindowWidth, lastWindowHeight; | static int lastWindowX, lastWindowY, lastWindowWidth, lastWindowHeight; | ||||
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { | void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { | ||||
if (action == GLFW_PRESS) { | |||||
if (action == GLFW_PRESS || action == GLFW_REPEAT) { | |||||
if (key == GLFW_KEY_F11 || key == GLFW_KEY_ESCAPE) { | if (key == GLFW_KEY_F11 || key == GLFW_KEY_ESCAPE) { | ||||
// Toggle fullscreen | // Toggle fullscreen | ||||
GLFWmonitor *monitor = glfwGetWindowMonitor(window); | GLFWmonitor *monitor = glfwGetWindowMonitor(window); | ||||
@@ -151,6 +162,11 @@ void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods | |||||
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); | glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); | ||||
} | } | ||||
} | } | ||||
else { | |||||
if (gSelectedWidget) { | |||||
gSelectedWidget->onKey(key); | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -181,6 +197,8 @@ void guiInit() { | |||||
err = glfwInit(); | err = glfwInit(); | ||||
assert(err); | assert(err); | ||||
// glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); | |||||
// glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | |||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | ||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); | ||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); | ||||
@@ -209,6 +227,7 @@ void guiInit() { | |||||
glfwSetWindowSizeLimits(window, 240, 160, GLFW_DONT_CARE, GLFW_DONT_CARE); | glfwSetWindowSizeLimits(window, 240, 160, GLFW_DONT_CARE, GLFW_DONT_CARE); | ||||
// Set up NanoVG | // Set up NanoVG | ||||
// gVg = nvgCreateGL2(NVG_ANTIALIAS); | |||||
gVg = nvgCreateGL3(NVG_ANTIALIAS); | gVg = nvgCreateGL3(NVG_ANTIALIAS); | ||||
assert(gVg); | assert(gVg); | ||||
@@ -220,6 +239,7 @@ void guiInit() { | |||||
void guiDestroy() { | void guiDestroy() { | ||||
defaultFont.reset(); | defaultFont.reset(); | ||||
// nvgDeleteGL2(gVg); | |||||
nvgDeleteGL3(gVg); | nvgDeleteGL3(gVg); | ||||
glfwDestroyWindow(window); | glfwDestroyWindow(window); | ||||
glfwTerminate(); | glfwTerminate(); | ||||
@@ -32,13 +32,16 @@ FramebufferWidget::~FramebufferWidget() { | |||||
delete internal; | delete internal; | ||||
} | } | ||||
/** A margin in pixels around the scene in the framebuffer */ | |||||
/** A margin in pixels around the scene in the framebuffer | |||||
This prevents cutting the rendered SVG off on the box edges. | |||||
*/ | |||||
static const int margin = 1; | static const int margin = 1; | ||||
void FramebufferWidget::step() { | void FramebufferWidget::step() { | ||||
if (!scene) | if (!scene) | ||||
return; | return; | ||||
// Step scene before rendering | |||||
scene->step(); | scene->step(); | ||||
// Render the scene to the framebuffer if dirty | // Render the scene to the framebuffer if dirty | ||||
@@ -73,13 +76,15 @@ void FramebufferWidget::step() { | |||||
void FramebufferWidget::draw(NVGcontext *vg) { | void FramebufferWidget::draw(NVGcontext *vg) { | ||||
if (!internal->fb) | if (!internal->fb) | ||||
return; | return; | ||||
if (!scene) | |||||
return; | |||||
// Draw framebuffer image | // Draw framebuffer image | ||||
int width, height; | int width, height; | ||||
nvgImageSize(vg, internal->fb->image, &width, &height); | nvgImageSize(vg, internal->fb->image, &width, &height); | ||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgRect(vg, -margin, -margin, width, height); | nvgRect(vg, -margin, -margin, width, height); | ||||
NVGpaint paint = nvgImagePattern(vg, -margin, -margin, width, height, 0.0, internal->fb->image, 1.0); | |||||
NVGpaint paint = nvgImagePattern(vg, -margin + scene->box.pos.x, -margin + scene->box.pos.y, width, height, 0.0, internal->fb->image, 1.0); | |||||
nvgFillPaint(vg, paint); | nvgFillPaint(vg, paint); | ||||
nvgFill(vg); | nvgFill(vg); | ||||
} | } | ||||
@@ -8,15 +8,18 @@ void Light::draw(NVGcontext *vg) { | |||||
NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | ||||
float radius = box.size.x / 2.0; | float radius = box.size.x / 2.0; | ||||
// Solid | |||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgCircle(vg, radius, radius, radius); | nvgCircle(vg, radius, radius, radius); | ||||
nvgFillColor(vg, color); | nvgFillColor(vg, color); | ||||
nvgFill(vg); | nvgFill(vg); | ||||
// Border | |||||
nvgStrokeWidth(vg, 1.0); | nvgStrokeWidth(vg, 1.0); | ||||
nvgStrokeColor(vg, colorOutline); | nvgStrokeColor(vg, colorOutline); | ||||
nvgStroke(vg); | nvgStroke(vg); | ||||
// Glow | |||||
nvgGlobalCompositeOperation(vg, NVG_LIGHTER); | nvgGlobalCompositeOperation(vg, NVG_LIGHTER); | ||||
NVGpaint paint; | NVGpaint paint; | ||||
NVGcolor icol = color; | NVGcolor icol = color; | ||||
@@ -23,7 +23,7 @@ void ParamWidget::onChange() { | |||||
if (!module) | if (!module) | ||||
return; | return; | ||||
// moduleWidget->module->params[paramId] = value; | |||||
// module->params[paramId] = value; | |||||
engineSetParamSmooth(module, paramId, value); | engineSetParamSmooth(module, paramId, value); | ||||
} | } | ||||
@@ -0,0 +1,15 @@ | |||||
#include "widgets.hpp" | |||||
namespace rack { | |||||
void PasswordField::draw(NVGcontext *vg) { | |||||
std::string textTmp = text; | |||||
text = std::string(textTmp.size(), '*'); | |||||
TextField::draw(vg); | |||||
text = textTmp; | |||||
} | |||||
} // namespace rack |
@@ -0,0 +1,45 @@ | |||||
#include "scene.hpp" | |||||
namespace rack { | |||||
SVGKnob::SVGKnob() { | |||||
tw = new TransformWidget(); | |||||
setScene(tw); | |||||
sw = new SVGWidget(); | |||||
tw->addChild(sw); | |||||
} | |||||
void SVGKnob::setSVG(std::shared_ptr<SVG> svg) { | |||||
sw->svg = svg; | |||||
sw->wrap(); | |||||
} | |||||
void SVGKnob::step() { | |||||
// Re-transform TransformWidget if dirty | |||||
if (dirty) { | |||||
float angle = mapf(value, minValue, maxValue, minAngle, maxAngle); | |||||
tw->box.size = box.size; | |||||
tw->identity(); | |||||
// Resize SVG | |||||
Vec scale = Vec(box.size.x / sw->box.size.x, box.size.y / sw->box.size.y); | |||||
tw->scale(scale); | |||||
// Rotate SVG | |||||
Vec center = sw->box.getCenter(); | |||||
tw->translate(center); | |||||
tw->rotate(angle); | |||||
tw->translate(center.neg()); | |||||
} | |||||
FramebufferWidget::step(); | |||||
} | |||||
void SVGKnob::onChange() { | |||||
dirty = true; | |||||
ParamWidget::onChange(); | |||||
} | |||||
} // namespace rack |
@@ -79,8 +79,7 @@ static void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||||
} | } | ||||
void SVGWidget::step() { | |||||
// Automatically wrap box size to SVG page size | |||||
void SVGWidget::wrap() { | |||||
if (svg) | if (svg) | ||||
box.size = Vec(svg->handle->width, svg->handle->height); | box.size = Vec(svg->handle->width, svg->handle->height); | ||||
else | else | ||||
@@ -0,0 +1,95 @@ | |||||
#include "widgets.hpp" | |||||
// for gVg | |||||
#include "gui.hpp" | |||||
// for key codes | |||||
#include <GLFW/glfw3.h> | |||||
namespace rack { | |||||
void TextField::draw(NVGcontext *vg) { | |||||
BNDwidgetState state; | |||||
if (this == gSelectedWidget) | |||||
state = BND_ACTIVE; | |||||
else if (this == gHoveredWidget) | |||||
state = BND_HOVER; | |||||
else | |||||
state = BND_DEFAULT; | |||||
bndTextField(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str(), begin, end); | |||||
} | |||||
Widget *TextField::onMouseDown(Vec pos, int button) { | |||||
end = begin = bndTextFieldTextPosition(gVg, 0.0, 0.0, box.size.x, box.size.y, -1, text.c_str(), pos.x, pos.y); | |||||
return OpaqueWidget::onMouseDown(pos, button); | |||||
} | |||||
void TextField::onText(int codepoint) { | |||||
if (begin < end) | |||||
text.erase(begin, end - begin); | |||||
char c = codepoint; | |||||
text.insert(begin, &c, 1); | |||||
begin++; | |||||
end = begin; | |||||
} | |||||
void TextField::onKey(int key) { | |||||
switch (key) { | |||||
case GLFW_KEY_BACKSPACE: | |||||
if (begin < end) { | |||||
text.erase(begin, end - begin); | |||||
} | |||||
else { | |||||
begin--; | |||||
if (begin >= 0) | |||||
text.erase(begin, 1); | |||||
} | |||||
end = begin; | |||||
break; | |||||
case GLFW_KEY_DELETE: | |||||
if (begin < end) { | |||||
text.erase(begin, end - begin); | |||||
} | |||||
else { | |||||
text.erase(begin, 1); | |||||
} | |||||
end = begin; | |||||
break; | |||||
case GLFW_KEY_LEFT: | |||||
if (begin < end) { | |||||
} | |||||
else { | |||||
begin--; | |||||
} | |||||
end = begin; | |||||
break; | |||||
case GLFW_KEY_RIGHT: | |||||
if (begin < end) { | |||||
begin = end; | |||||
} | |||||
else { | |||||
begin++; | |||||
} | |||||
end = begin; | |||||
break; | |||||
case GLFW_KEY_HOME: | |||||
end = begin = 0; | |||||
break; | |||||
case GLFW_KEY_END: | |||||
end = begin = text.size(); | |||||
break; | |||||
} | |||||
begin = mini(maxi(begin, 0), text.size()); | |||||
end = mini(maxi(end, 0), text.size()); | |||||
} | |||||
void TextField::onSelect() { | |||||
begin = 0; | |||||
end = text.size(); | |||||
} | |||||
} // namespace rack |
@@ -75,8 +75,9 @@ struct SampleRateChoice : ChoiceButton { | |||||
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
menu->box.size.x = box.size.x; | menu->box.size.x = box.size.x; | ||||
float sampleRates[6] = {44100, 48000, 88200, 96000, 176400, 192000}; | |||||
for (int i = 0; i < 6; i++) { | |||||
float sampleRates[] = {44100, 48000, 88200, 96000, 176400, 192000}; | |||||
int sampleRatesLen = sizeof(sampleRates) / sizeof(sampleRates[0]); | |||||
for (int i = 0; i < sampleRatesLen; i++) { | |||||
SampleRateItem *item = new SampleRateItem(); | SampleRateItem *item = new SampleRateItem(); | ||||
item->text = stringf("%.0f Hz", sampleRates[i]); | item->text = stringf("%.0f Hz", sampleRates[i]); | ||||
item->sampleRate = sampleRates[i]; | item->sampleRate = sampleRates[i]; | ||||
@@ -15,7 +15,7 @@ void Tooltip::step() { | |||||
void Tooltip::draw(NVGcontext *vg) { | void Tooltip::draw(NVGcontext *vg) { | ||||
bndTooltipBackground(vg, box.pos.x, box.pos.y, box.size.x, box.size.y); | |||||
bndTooltipBackground(vg, 0.0, 0.0, box.size.x, box.size.y); | |||||
Widget::draw(vg); | Widget::draw(vg); | ||||
} | } | ||||
@@ -5,10 +5,10 @@ namespace rack { | |||||
TransformWidget::TransformWidget() { | TransformWidget::TransformWidget() { | ||||
reset(); | |||||
identity(); | |||||
} | } | ||||
void TransformWidget::reset() { | |||||
void TransformWidget::identity() { | |||||
nvgTransformIdentity(transform); | nvgTransformIdentity(transform); | ||||
} | } | ||||
@@ -68,7 +68,7 @@ static void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, NVGcolor color, float t | |||||
} | } | ||||
static NVGcolor wireColors[8] = { | |||||
static const NVGcolor wireColors[8] = { | |||||
nvgRGB(0xc9, 0xb7, 0x0e), // yellow | nvgRGB(0xc9, 0xb7, 0x0e), // yellow | ||||
nvgRGB(0xc9, 0x18, 0x47), // red | nvgRGB(0xc9, 0x18, 0x47), // red | ||||
nvgRGB(0x0c, 0x8e, 0x15), // green | nvgRGB(0x0c, 0x8e, 0x15), // green | ||||
@@ -82,13 +82,8 @@ static int lastWireColorId = -1; | |||||
WireWidget::WireWidget() { | WireWidget::WireWidget() { | ||||
int wireColorId; | |||||
do { | |||||
wireColorId = randomu32() % 8; | |||||
} while (wireColorId == lastWireColorId); | |||||
lastWireColorId = wireColorId; | |||||
color = wireColors[wireColorId]; | |||||
lastWireColorId = (lastWireColorId + 1) % 8; | |||||
color = wireColors[lastWireColorId]; | |||||
} | } | ||||
WireWidget::~WireWidget() { | WireWidget::~WireWidget() { | ||||