| @@ -10,7 +10,7 @@ OBJCOPY ?= objcopy | |||
| FLAGS += -MMD -MP | |||
| FLAGS += -g | |||
| # 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 | |||
| ifneq ($(ARCH), mac) | |||
| @@ -12,47 +12,18 @@ struct SequentialLayout : virtual Widget { | |||
| HORIZONTAL_ORIENTATION, | |||
| VERTICAL_ORIENTATION, | |||
| }; | |||
| Orientation orientation = HORIZONTAL_ORIENTATION; | |||
| enum Alignment { | |||
| LEFT_ALIGNMENT, | |||
| CENTER_ALIGNMENT, | |||
| RIGHT_ALIGNMENT, | |||
| }; | |||
| Orientation orientation = HORIZONTAL_ORIENTATION; | |||
| Alignment alignment = LEFT_ALIGNMENT; | |||
| /** 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 "helpers.hpp" | |||
| #include "event.hpp" | |||
| #include "ui/Quantity.hpp" | |||
| #include "ui/RadioButton.hpp" | |||
| #include "ui/Label.hpp" | |||
| #include "app/ModuleBrowser.hpp" | |||
| #include "app/Scene.hpp" | |||
| #include "ui/List.hpp" | |||
| #include "ui/TextField.hpp" | |||
| #include "ui/SequentialLayout.hpp" | |||
| #include "widgets/ObstructWidget.hpp" | |||
| #include "widgets/ZoomWidget.hpp" | |||
| #include "plugin.hpp" | |||
| #include "context.hpp" | |||
| #include <set> | |||
| #include <algorithm> | |||
| namespace rack { | |||
| @@ -43,14 +46,17 @@ struct ModuleWidgetWrapper : ObstructWidget { | |||
| struct ModuleBrowser : OpaqueWidget { | |||
| SequentialLayout *moduleLayout; | |||
| ModuleBrowser() { | |||
| math::Vec p; | |||
| moduleLayout = new SequentialLayout; | |||
| moduleLayout->spacing = math::Vec(10, 10); | |||
| addChild(moduleLayout); | |||
| for (Plugin *plugin : plugin::plugins) { | |||
| for (Model *model : plugin->models) { | |||
| ModuleWidgetWrapper *wrapper = new ModuleWidgetWrapper; | |||
| wrapper->box.pos = p; | |||
| wrapper->model = model; | |||
| addChild(wrapper); | |||
| moduleLayout->addChild(wrapper); | |||
| ZoomWidget *zoomWidget = new ZoomWidget; | |||
| zoomWidget->setZoom(0.5); | |||
| @@ -59,7 +65,6 @@ struct ModuleBrowser : OpaqueWidget { | |||
| ModuleWidget *moduleWidget = model->createModuleWidgetNull(); | |||
| zoomWidget->addChild(moduleWidget); | |||
| 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 { | |||
| 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(); | |||
| } | |||
| @@ -543,7 +543,7 @@ Toolbar::Toolbar() { | |||
| SequentialLayout *layout = new SequentialLayout; | |||
| layout->box.pos = math::Vec(margin, margin); | |||
| layout->spacing = 0.0; | |||
| layout->spacing = math::Vec(0, 0); | |||
| addChild(layout); | |||
| FileButton *fileButton = new FileButton; | |||
| @@ -146,7 +146,8 @@ static void Engine_step(Engine *engine) { | |||
| auto stopTime = std::chrono::high_resolution_clock::now(); | |||
| float cpuTime = std::chrono::duration<float>(stopTime - startTime).count() * engine->internal->sampleRate; | |||
| // 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 { | |||
| module->step(); | |||
| @@ -1,5 +1,6 @@ | |||
| #include "ui/MenuItem.hpp" | |||
| 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 | |||