#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace rack { template plugin::Model* createModel(const std::string& slug) { struct TModel : plugin::Model { engine::Module* createModule() override { engine::Module* m = new TModule; m->model = this; return m; } app::ModuleWidget* createModuleWidget(engine::Module* m) override { TModule* tm = NULL; if (m) { assert(m->model == this); tm = dynamic_cast(m); } app::ModuleWidget* mw = new TModuleWidget(tm); mw->model = this; return mw; } }; plugin::Model* o = new TModel; o->slug = slug; return o; } template TWidget* createWidget(math::Vec pos) { TWidget* o = new TWidget; o->box.pos = pos; return o; } template TWidget* createWidgetCentered(math::Vec pos) { TWidget* o = createWidget(pos); o->box.pos = o->box.pos.minus(o->box.size.div(2)); return o; } inline app::SvgPanel* createPanel(std::string svgPath) { app::SvgPanel* panel = new app::SvgPanel; std::shared_ptr svg = Svg::load(svgPath); panel->setBackground(svg); return panel; } template TParamWidget* createParam(math::Vec pos, engine::Module* module, int paramId) { TParamWidget* o = new TParamWidget; o->box.pos = pos; o->app::ParamWidget::module = module; o->app::ParamWidget::paramId = paramId; o->initParamQuantity(); return o; } template TParamWidget* createParamCentered(math::Vec pos, engine::Module* module, int paramId) { TParamWidget* o = createParam(pos, module, paramId); o->box.pos = o->box.pos.minus(o->box.size.div(2)); return o; } template TPortWidget* createInput(math::Vec pos, engine::Module* module, int inputId) { TPortWidget* o = new TPortWidget; o->box.pos = pos; o->app::PortWidget::module = module; o->app::PortWidget::type = engine::Port::INPUT; o->app::PortWidget::portId = inputId; return o; } template TPortWidget* createInputCentered(math::Vec pos, engine::Module* module, int inputId) { TPortWidget* o = createInput(pos, module, inputId); o->box.pos = o->box.pos.minus(o->box.size.div(2)); return o; } template TPortWidget* createOutput(math::Vec pos, engine::Module* module, int outputId) { TPortWidget* o = new TPortWidget; o->box.pos = pos; o->app::PortWidget::module = module; o->app::PortWidget::type = engine::Port::OUTPUT; o->app::PortWidget::portId = outputId; return o; } template TPortWidget* createOutputCentered(math::Vec pos, engine::Module* module, int outputId) { TPortWidget* o = createOutput(pos, module, outputId); o->box.pos = o->box.pos.minus(o->box.size.div(2)); return o; } template TModuleLightWidget* createLight(math::Vec pos, engine::Module* module, int firstLightId) { TModuleLightWidget* o = new TModuleLightWidget; o->box.pos = pos; o->app::ModuleLightWidget::module = module; o->app::ModuleLightWidget::firstLightId = firstLightId; return o; } template TModuleLightWidget* createLightCentered(math::Vec pos, engine::Module* module, int firstLightId) { TModuleLightWidget* o = createLight(pos, module, firstLightId); o->box.pos = o->box.pos.minus(o->box.size.div(2)); return o; } /** Creates a param with a light and calls setFirstLightId() on it. */ template TParamWidget* createLightParam(math::Vec pos, engine::Module* module, int paramId, int firstLightId) { TParamWidget* o = createParam(pos, module, paramId); o->setFirstLightId(firstLightId); return o; } template TParamWidget* createLightParamCentered(math::Vec pos, engine::Module* module, int paramId, int firstLightId) { TParamWidget* o = createLightParam(pos, module, paramId, firstLightId); o->box.pos = o->box.pos.minus(o->box.size.div(2)); return o; } template TMenu* createMenu() { TMenu* o = new TMenu; o->box.pos = APP->scene->mousePos; ui::MenuOverlay* menuOverlay = new ui::MenuOverlay; menuOverlay->addChild(o); APP->scene->addChild(menuOverlay); return o; } template TMenuLabel* createMenuLabel(std::string text) { TMenuLabel* o = new TMenuLabel; o->text = text; return o; } template TMenuItem* createMenuItem(std::string text, std::string rightText = "") { TMenuItem* o = new TMenuItem; o->text = text; o->rightText = rightText; return o; } template TMenuItem* createMenuItem(std::string text, std::string rightText, std::function action) { struct Item : TMenuItem { std::function action; void onAction(const event::Action& e) override { action(); } }; Item* item = createMenuItem(text, rightText); item->action = action; return item; } /** Creates a MenuItem with a check mark set by a lambda function. */ inline ui::MenuItem* createCheckMenuItem(std::string text, std::function checked, std::function action) { struct Item : ui::MenuItem { std::function action; void onAction(const event::Action& e) override { action(); } }; Item* item = createMenuItem(text, CHECKMARK(checked())); item->action = action; return item; } /** Creates a MenuItem that controls a boolean value with a check mark. */ inline ui::MenuItem* createBoolMenuItem(std::string text, std::function getter, std::function setter) { struct Item : ui::MenuItem { std::function setter; bool val; void onAction(const event::Action& e) override { setter(val); } }; bool currVal = getter(); Item* item = createMenuItem(text, CHECKMARK(currVal)); item->setter = setter; item->val = !currVal; return item; } /** Easy wrapper for createBoolMenuItem() to modify a bool pointer. */ template ui::MenuItem* createBoolPtrMenuItem(std::string text, T* ptr) { return createBoolMenuItem(text, [=]() {return *ptr;}, [=](T val) {*ptr = val;} ); } /** Creates a MenuItem that when hovered, opens a submenu with several MenuItems indexed by an integer. */ inline ui::MenuItem* createIndexSubmenuItem(std::string text, std::vector labels, std::function getter, std::function setter) { struct IndexItem : ui::MenuItem { std::function setter; size_t index; void onAction(const event::Action& e) override { setter(index); } }; struct Item : ui::MenuItem { std::function getter; std::function setter; std::vector labels; ui::Menu* createChildMenu() override { ui::Menu* menu = new ui::Menu; size_t currIndex = getter(); for (size_t i = 0; i < labels.size(); i++) { IndexItem* item = createMenuItem(labels[i], CHECKMARK(currIndex == i)); item->setter = setter; item->index = i; menu->addChild(item); } return menu; } }; size_t currIndex = getter(); std::string label = (currIndex < labels.size()) ? labels[currIndex] : ""; Item* item = createMenuItem(text, label + " " + RIGHT_ARROW); item->getter = getter; item->setter = setter; item->labels = labels; return item; } /** Easy wrapper for createIndexSubmenuItem() that controls an integer index at a pointer address. */ template ui::MenuItem* createIndexPtrSubmenuItem(std::string text, std::vector labels, T* ptr) { return createIndexSubmenuItem(text, labels, [=]() {return *ptr;}, [=](size_t index) {*ptr = T(index);} ); } } // namespace rack