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) { | ||||