| @@ -10,7 +10,7 @@ OBJCOPY ?= objcopy | |||||
| FLAGS += -MMD -MP | FLAGS += -MMD -MP | ||||
| FLAGS += -g | FLAGS += -g | ||||
| # Optimization | # Optimization | ||||
| FLAGS += -O0 -march=nocona -ffast-math -fno-finite-math-only | |||||
| FLAGS += -O3 -march=nocona -ffast-math -fno-finite-math-only | |||||
| FLAGS += -Wall -Wextra -Wno-unused-parameter | FLAGS += -Wall -Wextra -Wno-unused-parameter | ||||
| ifneq ($(ARCH), mac) | ifneq ($(ARCH), mac) | ||||
| @@ -12,47 +12,18 @@ struct SequentialLayout : virtual Widget { | |||||
| HORIZONTAL_ORIENTATION, | HORIZONTAL_ORIENTATION, | ||||
| VERTICAL_ORIENTATION, | VERTICAL_ORIENTATION, | ||||
| }; | }; | ||||
| Orientation orientation = HORIZONTAL_ORIENTATION; | |||||
| enum Alignment { | enum Alignment { | ||||
| LEFT_ALIGNMENT, | LEFT_ALIGNMENT, | ||||
| CENTER_ALIGNMENT, | CENTER_ALIGNMENT, | ||||
| RIGHT_ALIGNMENT, | RIGHT_ALIGNMENT, | ||||
| }; | }; | ||||
| Orientation orientation = HORIZONTAL_ORIENTATION; | |||||
| Alignment alignment = LEFT_ALIGNMENT; | Alignment alignment = LEFT_ALIGNMENT; | ||||
| /** Space between adjacent elements */ | /** Space between adjacent elements */ | ||||
| float spacing = 0.0; | |||||
| void step() override { | |||||
| Widget::step(); | |||||
| float offset = 0.0; | |||||
| for (Widget *child : children) { | |||||
| if (!child->visible) | |||||
| continue; | |||||
| // Set position | |||||
| (orientation == HORIZONTAL_ORIENTATION ? child->box.pos.x : child->box.pos.y) = offset; | |||||
| // Increment by size | |||||
| offset += (orientation == HORIZONTAL_ORIENTATION ? child->box.size.x : child->box.size.y); | |||||
| offset += spacing; | |||||
| } | |||||
| // We're done if left aligned | |||||
| if (alignment == LEFT_ALIGNMENT) | |||||
| return; | |||||
| // Adjust positions based on width of the layout itself | |||||
| offset -= spacing; | |||||
| if (alignment == RIGHT_ALIGNMENT) | |||||
| offset -= (orientation == HORIZONTAL_ORIENTATION ? box.size.x : box.size.y); | |||||
| else if (alignment == CENTER_ALIGNMENT) | |||||
| offset -= (orientation == HORIZONTAL_ORIENTATION ? box.size.x : box.size.y) / 2.0; | |||||
| for (Widget *child : children) { | |||||
| if (!child->visible) | |||||
| continue; | |||||
| (orientation == HORIZONTAL_ORIENTATION ? child->box.pos.x : child->box.pos.y) += offset; | |||||
| } | |||||
| } | |||||
| math::Vec spacing; | |||||
| void step() override; | |||||
| }; | }; | ||||
| @@ -1,20 +1,23 @@ | |||||
| #include <set> | |||||
| #include <algorithm> | |||||
| #include "app/ModuleBrowser.hpp" | |||||
| // TODO clean up | |||||
| #include "window.hpp" | #include "window.hpp" | ||||
| #include "helpers.hpp" | #include "helpers.hpp" | ||||
| #include "event.hpp" | #include "event.hpp" | ||||
| #include "ui/Quantity.hpp" | #include "ui/Quantity.hpp" | ||||
| #include "ui/RadioButton.hpp" | #include "ui/RadioButton.hpp" | ||||
| #include "ui/Label.hpp" | #include "ui/Label.hpp" | ||||
| #include "app/ModuleBrowser.hpp" | |||||
| #include "app/Scene.hpp" | #include "app/Scene.hpp" | ||||
| #include "ui/List.hpp" | #include "ui/List.hpp" | ||||
| #include "ui/TextField.hpp" | #include "ui/TextField.hpp" | ||||
| #include "ui/SequentialLayout.hpp" | |||||
| #include "widgets/ObstructWidget.hpp" | #include "widgets/ObstructWidget.hpp" | ||||
| #include "widgets/ZoomWidget.hpp" | #include "widgets/ZoomWidget.hpp" | ||||
| #include "plugin.hpp" | #include "plugin.hpp" | ||||
| #include "context.hpp" | #include "context.hpp" | ||||
| #include <set> | |||||
| #include <algorithm> | |||||
| namespace rack { | namespace rack { | ||||
| @@ -43,14 +46,17 @@ struct ModuleWidgetWrapper : ObstructWidget { | |||||
| struct ModuleBrowser : OpaqueWidget { | struct ModuleBrowser : OpaqueWidget { | ||||
| SequentialLayout *moduleLayout; | |||||
| ModuleBrowser() { | ModuleBrowser() { | ||||
| math::Vec p; | |||||
| moduleLayout = new SequentialLayout; | |||||
| moduleLayout->spacing = math::Vec(10, 10); | |||||
| addChild(moduleLayout); | |||||
| for (Plugin *plugin : plugin::plugins) { | for (Plugin *plugin : plugin::plugins) { | ||||
| for (Model *model : plugin->models) { | for (Model *model : plugin->models) { | ||||
| ModuleWidgetWrapper *wrapper = new ModuleWidgetWrapper; | ModuleWidgetWrapper *wrapper = new ModuleWidgetWrapper; | ||||
| wrapper->box.pos = p; | |||||
| wrapper->model = model; | wrapper->model = model; | ||||
| addChild(wrapper); | |||||
| moduleLayout->addChild(wrapper); | |||||
| ZoomWidget *zoomWidget = new ZoomWidget; | ZoomWidget *zoomWidget = new ZoomWidget; | ||||
| zoomWidget->setZoom(0.5); | zoomWidget->setZoom(0.5); | ||||
| @@ -59,7 +65,6 @@ struct ModuleBrowser : OpaqueWidget { | |||||
| ModuleWidget *moduleWidget = model->createModuleWidgetNull(); | ModuleWidget *moduleWidget = model->createModuleWidgetNull(); | ||||
| zoomWidget->addChild(moduleWidget); | zoomWidget->addChild(moduleWidget); | ||||
| wrapper->box.size = moduleWidget->box.size.mult(zoomWidget->zoom); | wrapper->box.size = moduleWidget->box.size.mult(zoomWidget->zoom); | ||||
| p = wrapper->box.getTopRight().plus(math::Vec(20, 0)); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -67,7 +72,8 @@ struct ModuleBrowser : OpaqueWidget { | |||||
| void step() override { | void step() override { | ||||
| assert(parent); | assert(parent); | ||||
| box = parent->box.zeroPos().grow(math::Vec(-100, -100)); | |||||
| box = parent->box.zeroPos().grow(math::Vec(-50, -50)); | |||||
| moduleLayout->box.size = box.size; | |||||
| OpaqueWidget::step(); | OpaqueWidget::step(); | ||||
| } | } | ||||
| @@ -543,7 +543,7 @@ Toolbar::Toolbar() { | |||||
| SequentialLayout *layout = new SequentialLayout; | SequentialLayout *layout = new SequentialLayout; | ||||
| layout->box.pos = math::Vec(margin, margin); | layout->box.pos = math::Vec(margin, margin); | ||||
| layout->spacing = 0.0; | |||||
| layout->spacing = math::Vec(0, 0); | |||||
| addChild(layout); | addChild(layout); | ||||
| FileButton *fileButton = new FileButton; | FileButton *fileButton = new FileButton; | ||||
| @@ -146,7 +146,8 @@ static void Engine_step(Engine *engine) { | |||||
| auto stopTime = std::chrono::high_resolution_clock::now(); | auto stopTime = std::chrono::high_resolution_clock::now(); | ||||
| float cpuTime = std::chrono::duration<float>(stopTime - startTime).count() * engine->internal->sampleRate; | float cpuTime = std::chrono::duration<float>(stopTime - startTime).count() * engine->internal->sampleRate; | ||||
| // Smooth cpu time | // Smooth cpu time | ||||
| module->cpuTime += (cpuTime - module->cpuTime) * engine->internal->sampleTime / 0.5f; | |||||
| float powerLambda = 2.f / 10.f; | |||||
| module->cpuTime += (cpuTime - module->cpuTime) * engine->internal->sampleTime * powerLambda; | |||||
| } | } | ||||
| else { | else { | ||||
| module->step(); | module->step(); | ||||
| @@ -1,5 +1,6 @@ | |||||
| #include "ui/MenuItem.hpp" | #include "ui/MenuItem.hpp" | ||||
| namespace rack { | namespace rack { | ||||
| @@ -0,0 +1,65 @@ | |||||
| #include "ui/SequentialLayout.hpp" | |||||
| #include <vector> | |||||
| namespace rack { | |||||
| #define X(_v) (orientation == HORIZONTAL_ORIENTATION ? (_v).x : (_v).y) | |||||
| #define Y(_v) (orientation == HORIZONTAL_ORIENTATION ? (_v).y : (_v).x) | |||||
| void SequentialLayout::step() { | |||||
| Widget::step(); | |||||
| // Sort widgets into rows (or columns if vertical) | |||||
| std::vector<std::vector<Widget*>> rows; | |||||
| rows.resize(1); | |||||
| float rowWidth = 0.0; | |||||
| for (Widget *child : children) { | |||||
| if (!child->visible) | |||||
| continue; | |||||
| // Should we wrap the widget now? | |||||
| if (!rows.back().empty() && rowWidth + X(child->box.size) >= X(box.size)) { | |||||
| rowWidth = 0.0; | |||||
| rows.resize(rows.size() + 1); | |||||
| } | |||||
| rows.back().push_back(child); | |||||
| rowWidth += X(child->box.size) + X(spacing); | |||||
| } | |||||
| // Position widgets | |||||
| math::Vec p; | |||||
| for (auto &row : rows) { | |||||
| // For center and right alignment, compute offset from the left margin | |||||
| float offset = 0.0; | |||||
| if (alignment != LEFT_ALIGNMENT) { | |||||
| float rowWidth = 0.0; | |||||
| for (Widget *child : row) { | |||||
| rowWidth += X(child->box.size) + X(spacing); | |||||
| } | |||||
| rowWidth -= X(spacing); | |||||
| if (alignment == CENTER_ALIGNMENT) | |||||
| offset = (X(box.size) - rowWidth) / 2; | |||||
| else if (alignment == RIGHT_ALIGNMENT) | |||||
| offset = X(box.size) - rowWidth; | |||||
| } | |||||
| float maxHeight = 0.0; | |||||
| for (Widget *child : row) { | |||||
| child->box.pos = p; | |||||
| X(child->box.pos) += offset; | |||||
| X(p) += X(child->box.size) + X(spacing); | |||||
| if (Y(child->box.size) > maxHeight) | |||||
| maxHeight = Y(child->box.size); | |||||
| } | |||||
| X(p) = 0.0; | |||||
| Y(p) += maxHeight + Y(spacing); | |||||
| } | |||||
| } | |||||
| } // namespace rack | |||||