dragging cables to the edge of the screen, added nonfunctional search box to Add Module menutags/v0.5.0
@@ -164,7 +164,7 @@ struct CircularShadow : TransparentWidget { | |||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
}; | }; | ||||
struct Light : TransparentWidget { | |||||
struct LightWidget : TransparentWidget { | |||||
NVGcolor bgColor = nvgRGBf(0, 0, 0); | NVGcolor bgColor = nvgRGBf(0, 0, 0); | ||||
NVGcolor color = nvgRGBf(1, 1, 1); | NVGcolor color = nvgRGBf(1, 1, 1); | ||||
void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
@@ -327,6 +327,10 @@ struct PluginManagerWidget : Widget { | |||||
void step() override; | void step() override; | ||||
}; | }; | ||||
struct RackScrollWidget : ScrollWidget { | |||||
void step() override; | |||||
}; | |||||
struct RackScene : Scene { | struct RackScene : Scene { | ||||
ScrollWidget *scrollWidget; | ScrollWidget *scrollWidget; | ||||
ZoomWidget *zoomWidget; | ZoomWidget *zoomWidget; | ||||
@@ -432,10 +432,10 @@ struct CL1362Port : SVGPort { | |||||
}; | }; | ||||
//////////////////// | //////////////////// | ||||
// LEDs | |||||
// Lights | |||||
//////////////////// | //////////////////// | ||||
struct ValueLight : Light { | |||||
struct ValueLight : LightWidget { | |||||
float *value = NULL; | float *value = NULL; | ||||
virtual void setValue(float v) {} | virtual void setValue(float v) {} | ||||
void step() override { | void step() override { | ||||
@@ -29,21 +29,28 @@ struct Output { | |||||
bool active = false; | bool active = false; | ||||
}; | }; | ||||
struct Light { | |||||
float value = 0.0; | |||||
void setSmooth(float v); | |||||
}; | |||||
struct Module { | struct Module { | ||||
std::vector<Param> params; | std::vector<Param> params; | ||||
std::vector<Input> inputs; | std::vector<Input> inputs; | ||||
std::vector<Output> outputs; | std::vector<Output> outputs; | ||||
std::vector<Light> lights; | |||||
/** For CPU usage meter */ | /** For CPU usage meter */ | ||||
float cpuTime = 0.0; | float cpuTime = 0.0; | ||||
/** Deprecated, use constructor below this one */ | /** Deprecated, use constructor below this one */ | ||||
Module() {} | Module() {} | ||||
/** Constructs Module with a fixed number of params, inputs, and outputs */ | /** Constructs Module with a fixed number of params, inputs, and outputs */ | ||||
Module(int numParams, int numInputs, int numOutputs) { | |||||
Module(int numParams, int numInputs, int numOutputs, int numLights = 0) { | |||||
params.resize(numParams); | params.resize(numParams); | ||||
inputs.resize(numInputs); | inputs.resize(numInputs); | ||||
outputs.resize(numOutputs); | outputs.resize(numOutputs); | ||||
lights.resize(numLights); | |||||
} | } | ||||
virtual ~Module() {} | virtual ~Module() {} | ||||
@@ -382,7 +382,6 @@ struct ScrollWidget : OpaqueWidget { | |||||
ScrollWidget(); | ScrollWidget(); | ||||
void step() override; | void step() override; | ||||
Widget *onMouseMove(Vec pos, Vec mouseRel) override; | |||||
bool onScrollOpaque(Vec scrollRel) override; | bool onScrollOpaque(Vec scrollRel) override; | ||||
}; | }; | ||||
@@ -4,7 +4,7 @@ | |||||
namespace rack { | namespace rack { | ||||
void Light::draw(NVGcontext *vg) { | |||||
void LightWidget::draw(NVGcontext *vg) { | |||||
float radius = box.size.x / 2.0; | float radius = box.size.x / 2.0; | ||||
float oradius = radius + 20.0; | float oradius = radius + 20.0; | ||||
@@ -28,7 +28,7 @@ static void checkVersion() { | |||||
RackScene::RackScene() { | RackScene::RackScene() { | ||||
scrollWidget = new ScrollWidget(); | |||||
scrollWidget = new RackScrollWidget(); | |||||
{ | { | ||||
zoomWidget = new ZoomWidget(); | zoomWidget = new ZoomWidget(); | ||||
zoomWidget->zoom = 1.0; | zoomWidget->zoom = 1.0; | ||||
@@ -0,0 +1,26 @@ | |||||
#include "app.hpp" | |||||
namespace rack { | |||||
void RackScrollWidget::step() { | |||||
Vec pos = gMousePos.minus(getAbsolutePos()); | |||||
// Scroll rack if dragging cable near the edge of the screen | |||||
if (gRackWidget->wireContainer->activeWire) { | |||||
float margin = 20.0; | |||||
float speed = 15.0; | |||||
if (pos.x <= margin) | |||||
offset.x -= speed; | |||||
if (pos.x >= box.size.x - margin) | |||||
offset.x += speed; | |||||
if (pos.y <= margin) | |||||
offset.y -= speed; | |||||
if (pos.y >= box.size.y - margin) | |||||
offset.y += speed; | |||||
} | |||||
ScrollWidget::step(); | |||||
} | |||||
} // namespace rack |
@@ -396,6 +396,9 @@ struct AddManufacturerMenuItem : MenuItem { | |||||
} | } | ||||
} | } | ||||
if (models.empty()) | |||||
return NULL; | |||||
// Model items | // Model items | ||||
Menu *menu = new Menu(); | Menu *menu = new Menu(); | ||||
for (Model *model : models) { | for (Model *model : models) { | ||||
@@ -455,9 +458,14 @@ void RackWidget::onMouseDownOpaque(int button) { | |||||
Vec modulePos = gMousePos.minus(getAbsolutePos()); | Vec modulePos = gMousePos.minus(getAbsolutePos()); | ||||
Menu *menu = gScene->createMenu(); | Menu *menu = gScene->createMenu(); | ||||
MenuLabel *menuLabel = new MenuLabel(); | |||||
menuLabel->text = "Add module"; | |||||
menu->pushChild(menuLabel); | |||||
menu->pushChild(construct<MenuLabel>(&MenuLabel::text, "Add module")); | |||||
// TODO make functional | |||||
TextField *searchField = construct<TextField>(); | |||||
menu->pushChild(searchField); | |||||
// Focus search field | |||||
gFocusedWidget = searchField; | |||||
// Collect manufacturer names | // Collect manufacturer names | ||||
std::set<std::string> manufacturerNames; | std::set<std::string> manufacturerNames; | ||||
for (Plugin *plugin : gPlugins) { | for (Plugin *plugin : gPlugins) { | ||||
@@ -14,7 +14,7 @@ | |||||
namespace rack { | namespace rack { | ||||
float sampleRate; | |||||
float sampleRate = 0.0; | |||||
bool gPaused = false; | bool gPaused = false; | ||||
@@ -33,11 +33,17 @@ static int smoothParamId; | |||||
static float smoothValue; | static float smoothValue; | ||||
void Light::setSmooth(float v) { | |||||
value += (v - value) / sampleRate * 60.0; | |||||
} | |||||
void Wire::step() { | void Wire::step() { | ||||
float value = outputModule->outputs[outputId].value; | float value = outputModule->outputs[outputId].value; | ||||
inputModule->inputs[inputId].value = value; | inputModule->inputs[inputId].value = value; | ||||
} | } | ||||
void engineInit() { | void engineInit() { | ||||
engineSetSampleRate(44100.0); | engineSetSampleRate(44100.0); | ||||
} | } | ||||
@@ -42,6 +42,8 @@ void Menu::draw(NVGcontext *vg) { | |||||
// Resize the width to the widest child | // Resize the width to the widest child | ||||
for (Widget *child : children) { | for (Widget *child : children) { | ||||
MenuEntry *menuEntry = dynamic_cast<MenuEntry*>(child); | MenuEntry *menuEntry = dynamic_cast<MenuEntry*>(child); | ||||
if (!menuEntry) | |||||
continue; | |||||
float width = menuEntry->computeMinWidth(vg); | float width = menuEntry->computeMinWidth(vg); | ||||
if (width > box.size.x) { | if (width > box.size.x) { | ||||
box.size.x = width; | box.size.x = width; | ||||
@@ -32,26 +32,30 @@ void ScrollWidget::step() { | |||||
// Update the container's positions from the offset | // Update the container's positions from the offset | ||||
container->box.pos = offset.neg().round(); | container->box.pos = offset.neg().round(); | ||||
Widget::step(); | |||||
} | |||||
Widget *ScrollWidget::onMouseMove(Vec pos, Vec mouseRel) { | |||||
// Scroll with arrow keys | |||||
if (!gFocusedWidget) { | if (!gFocusedWidget) { | ||||
const float arrowSpeed = 50.0; | |||||
float arrowSpeed = 30.0; | |||||
if (guiIsShiftPressed() && guiIsModPressed()) | |||||
arrowSpeed /= 16.0; | |||||
else if (guiIsShiftPressed()) | |||||
arrowSpeed *= 4.0; | |||||
else if (guiIsModPressed()) | |||||
arrowSpeed /= 4.0; | |||||
if (glfwGetKey(gWindow, GLFW_KEY_LEFT) == GLFW_PRESS) { | if (glfwGetKey(gWindow, GLFW_KEY_LEFT) == GLFW_PRESS) { | ||||
offset = offset.minus(Vec(1, 0).mult(arrowSpeed)); | |||||
offset.x -= arrowSpeed; | |||||
} | } | ||||
if (glfwGetKey(gWindow, GLFW_KEY_RIGHT) == GLFW_PRESS) { | if (glfwGetKey(gWindow, GLFW_KEY_RIGHT) == GLFW_PRESS) { | ||||
offset = offset.minus(Vec(-1, 0).mult(arrowSpeed)); | |||||
offset.x += arrowSpeed; | |||||
} | } | ||||
if (glfwGetKey(gWindow, GLFW_KEY_UP) == GLFW_PRESS) { | if (glfwGetKey(gWindow, GLFW_KEY_UP) == GLFW_PRESS) { | ||||
offset = offset.minus(Vec(0, 1).mult(arrowSpeed)); | |||||
offset.y -= arrowSpeed; | |||||
} | } | ||||
if (glfwGetKey(gWindow, GLFW_KEY_DOWN) == GLFW_PRESS) { | if (glfwGetKey(gWindow, GLFW_KEY_DOWN) == GLFW_PRESS) { | ||||
offset = offset.minus(Vec(0, -1).mult(arrowSpeed)); | |||||
offset.y += arrowSpeed; | |||||
} | } | ||||
} | } | ||||
return OpaqueWidget::onMouseMove(pos, mouseRel); | |||||
Widget::step(); | |||||
} | } | ||||
bool ScrollWidget::onScrollOpaque(Vec scrollRel) { | bool ScrollWidget::onScrollOpaque(Vec scrollRel) { | ||||
@@ -18,9 +18,6 @@ void TextField::draw(NVGcontext *vg) { | |||||
state = BND_DEFAULT; | 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); | bndTextField(vg, 0.0, 0.0, box.size.x, box.size.y, BND_CORNER_NONE, state, -1, text.c_str(), begin, end); | ||||
if (text.empty() && state != BND_ACTIVE) { | |||||
bndIconLabelCaret(vg, 0.0, 0.0, box.size.x, box.size.y, -1, bndGetTheme()->textFieldTheme.itemColor, 13, placeholder.c_str(), bndGetTheme()->textFieldTheme.itemColor, 0, -1); | |||||
} | |||||
} | } | ||||
Widget *TextField::onMouseDown(Vec pos, int button) { | Widget *TextField::onMouseDown(Vec pos, int button) { | ||||