VCV Rack API v2
Loading...
Searching...
No Matches
helpers.hpp
Go to the documentation of this file.
1#pragma once
2#include <plugin/Model.hpp>
3#include <ui/MenuOverlay.hpp>
4#include <ui/MenuItem.hpp>
5#include <ui/MenuLabel.hpp>
6#include <ui/Menu.hpp>
7#include <app/PortWidget.hpp>
8#include <app/ParamWidget.hpp>
10#include <app/Scene.hpp>
11#include <app/SvgPanel.hpp>
12#include <engine/Module.hpp>
14#include <context.hpp>
15
16#include <functional>
17
18
19namespace rack {
20
21
23template <class TModule, class TModuleWidget>
24plugin::Model* createModel(std::string slug) {
25 struct TModel : plugin::Model {
26 engine::Module* createModule() override {
27 engine::Module* m = new TModule;
28 m->model = this;
29 return m;
30 }
31 app::ModuleWidget* createModuleWidget(engine::Module* m) override {
32 TModule* tm = NULL;
33 if (m) {
34 assert(m->model == this);
35 tm = dynamic_cast<TModule*>(m);
36 }
37 app::ModuleWidget* mw = new TModuleWidget(tm);
38 assert(mw->module == m);
39 mw->setModel(this);
40 return mw;
41 }
42 };
43
44 plugin::Model* o = new TModel;
45 o->slug = slug;
46 return o;
47}
48
49
51template <class TWidget>
52TWidget* createWidget(math::Vec pos) {
53 TWidget* o = new TWidget;
54 o->box.pos = pos;
55 return o;
56}
57
58
60template <class TWidget>
62 TWidget* o = createWidget<TWidget>(pos);
63 o->box.pos = o->box.pos.minus(o->box.size.div(2));
64 return o;
65}
66
67
69template <class TPanel = app::SvgPanel>
70TPanel* createPanel(std::string svgPath) {
71 TPanel* panel = new TPanel;
72 panel->setBackground(window::Svg::load(svgPath));
73 return panel;
74}
75
76
78template <class TPanel = app::ThemedSvgPanel>
79TPanel* createPanel(std::string lightSvgPath, std::string darkSvgPath) {
80 TPanel* panel = new TPanel;
81 panel->setBackground(window::Svg::load(lightSvgPath), window::Svg::load(darkSvgPath));
82 return panel;
83}
84
85
86template <class TParamWidget>
87TParamWidget* createParam(math::Vec pos, engine::Module* module, int paramId) {
88 TParamWidget* o = new TParamWidget;
89 o->box.pos = pos;
90 o->app::ParamWidget::module = module;
91 o->app::ParamWidget::paramId = paramId;
92 o->initParamQuantity();
93 return o;
94}
95
96
97template <class TParamWidget>
98TParamWidget* createParamCentered(math::Vec pos, engine::Module* module, int paramId) {
99 TParamWidget* o = createParam<TParamWidget>(pos, module, paramId);
100 o->box.pos = o->box.pos.minus(o->box.size.div(2));
101 return o;
102}
103
104
105template <class TPortWidget>
106TPortWidget* createInput(math::Vec pos, engine::Module* module, int inputId) {
107 TPortWidget* o = new TPortWidget;
108 o->box.pos = pos;
109 o->app::PortWidget::module = module;
110 o->app::PortWidget::type = engine::Port::INPUT;
111 o->app::PortWidget::portId = inputId;
112 return o;
113}
114
115
116template <class TPortWidget>
117TPortWidget* createInputCentered(math::Vec pos, engine::Module* module, int inputId) {
118 TPortWidget* o = createInput<TPortWidget>(pos, module, inputId);
119 o->box.pos = o->box.pos.minus(o->box.size.div(2));
120 return o;
121}
122
123
124template <class TPortWidget>
125TPortWidget* createOutput(math::Vec pos, engine::Module* module, int outputId) {
126 TPortWidget* o = new TPortWidget;
127 o->box.pos = pos;
128 o->app::PortWidget::module = module;
129 o->app::PortWidget::type = engine::Port::OUTPUT;
130 o->app::PortWidget::portId = outputId;
131 return o;
132}
133
134
135template <class TPortWidget>
136TPortWidget* createOutputCentered(math::Vec pos, engine::Module* module, int outputId) {
137 TPortWidget* o = createOutput<TPortWidget>(pos, module, outputId);
138 o->box.pos = o->box.pos.minus(o->box.size.div(2));
139 return o;
140}
141
142
143template <class TModuleLightWidget>
144TModuleLightWidget* createLight(math::Vec pos, engine::Module* module, int firstLightId) {
145 TModuleLightWidget* o = new TModuleLightWidget;
146 o->box.pos = pos;
147 o->app::ModuleLightWidget::module = module;
148 o->app::ModuleLightWidget::firstLightId = firstLightId;
149 return o;
150}
151
152
153template <class TModuleLightWidget>
154TModuleLightWidget* createLightCentered(math::Vec pos, engine::Module* module, int firstLightId) {
155 TModuleLightWidget* o = createLight<TModuleLightWidget>(pos, module, firstLightId);
156 o->box.pos = o->box.pos.minus(o->box.size.div(2));
157 return o;
158}
159
160
164template <class TParamWidget>
165TParamWidget* createLightParam(math::Vec pos, engine::Module* module, int paramId, int firstLightId) {
166 TParamWidget* o = createParam<TParamWidget>(pos, module, paramId);
167 o->getLight()->module = module;
168 o->getLight()->firstLightId = firstLightId;
169 return o;
170}
171
172
173template <class TParamWidget>
174TParamWidget* createLightParamCentered(math::Vec pos, engine::Module* module, int paramId, int firstLightId) {
175 TParamWidget* o = createLightParam<TParamWidget>(pos, module, paramId, firstLightId);
176 o->box.pos = o->box.pos.minus(o->box.size.div(2));
177 return o;
178}
179
180
181template <class TMenu = ui::Menu>
182TMenu* createMenu() {
183 TMenu* menu = new TMenu;
184 menu->box.pos = APP->scene->mousePos;
185
186 ui::MenuOverlay* menuOverlay = new ui::MenuOverlay;
187 menuOverlay->addChild(menu);
188
189 APP->scene->addChild(menuOverlay);
190 return menu;
191}
192
193
194template <class TMenuLabel = ui::MenuLabel>
195TMenuLabel* createMenuLabel(std::string text) {
196 TMenuLabel* label = new TMenuLabel;
197 label->text = text;
198 return label;
199}
200
201
202template <class TMenuItem = ui::MenuItem>
203TMenuItem* createMenuItem(std::string text, std::string rightText = "") {
204 TMenuItem* item = new TMenuItem;
205 item->text = text;
206 item->rightText = rightText;
207 return item;
208}
209
210
220template <class TMenuItem = ui::MenuItem>
221TMenuItem* createMenuItem(std::string text, std::string rightText, std::function<void()> action, bool disabled = false, bool alwaysConsume = false) {
222 struct Item : TMenuItem {
223 std::function<void()> action;
224 bool alwaysConsume;
225
226 void onAction(const event::Action& e) override {
227 action();
228 if (alwaysConsume)
229 e.consume(this);
230 }
231 };
232
233 Item* item = createMenuItem<Item>(text, rightText);
234 item->action = action;
235 item->disabled = disabled;
236 item->alwaysConsume = alwaysConsume;
237 return item;
238}
239
240
253template <class TMenuItem = ui::MenuItem>
254ui::MenuItem* createCheckMenuItem(std::string text, std::string rightText, std::function<bool()> checked, std::function<void()> action, bool disabled = false, bool alwaysConsume = false) {
255 struct Item : TMenuItem {
256 std::string rightTextPrefix;
257 std::function<bool()> checked;
258 std::function<void()> action;
259 bool alwaysConsume;
260
261 void step() override {
262 this->rightText = rightTextPrefix;
263 if (checked()) {
264 if (!rightTextPrefix.empty())
265 this->rightText += " ";
266 this->rightText += CHECKMARK_STRING;
267 }
268 TMenuItem::step();
269 }
270 void onAction(const event::Action& e) override {
271 action();
272 if (alwaysConsume)
273 e.consume(this);
274 }
275 };
276
277 Item* item = createMenuItem<Item>(text);
278 item->rightTextPrefix = rightText;
279 item->checked = checked;
280 item->action = action;
281 item->disabled = disabled;
282 item->alwaysConsume = alwaysConsume;
283 return item;
284}
285
286
299template <class TMenuItem = ui::MenuItem>
300ui::MenuItem* createBoolMenuItem(std::string text, std::string rightText, std::function<bool()> getter, std::function<void(bool state)> setter, bool disabled = false, bool alwaysConsume = false) {
301 struct Item : TMenuItem {
302 std::string rightTextPrefix;
303 std::function<bool()> getter;
304 std::function<void(size_t)> setter;
305 bool alwaysConsume;
306
307 void step() override {
308 this->rightText = rightTextPrefix;
309 if (getter()) {
310 if (!rightTextPrefix.empty())
311 this->rightText += " ";
312 this->rightText += CHECKMARK_STRING;
313 }
314 TMenuItem::step();
315 }
316 void onAction(const event::Action& e) override {
317 setter(!getter());
318 if (alwaysConsume)
319 e.consume(this);
320 }
321 };
322
323 Item* item = createMenuItem<Item>(text);
324 item->rightTextPrefix = rightText;
325 item->getter = getter;
326 item->setter = setter;
327 item->disabled = disabled;
328 item->alwaysConsume = alwaysConsume;
329 return item;
330}
331
332
338template <typename T>
339ui::MenuItem* createBoolPtrMenuItem(std::string text, std::string rightText, T* ptr) {
340 return createBoolMenuItem(text, rightText,
341 [=]() {
342 return ptr ? *ptr : false;
343 },
344 [=](T val) {
345 if (ptr)
346 *ptr = val;
347 }
348 );
349}
350
351
362template <class TMenuItem = ui::MenuItem>
363ui::MenuItem* createSubmenuItem(std::string text, std::string rightText, std::function<void(ui::Menu* menu)> createMenu, bool disabled = false) {
364 struct Item : TMenuItem {
365 std::function<void(ui::Menu* menu)> createMenu;
366
367 ui::Menu* createChildMenu() override {
368 ui::Menu* menu = new ui::Menu;
369 createMenu(menu);
370 return menu;
371 }
372 };
373
374 Item* item = createMenuItem<Item>(text, rightText + (rightText.empty() ? "" : " ") + RIGHT_ARROW);
375 item->createMenu = createMenu;
376 item->disabled = disabled;
377 return item;
378}
379
380
394template <class TMenuItem = ui::MenuItem>
395ui::MenuItem* createIndexSubmenuItem(std::string text, std::vector<std::string> labels, std::function<size_t()> getter, std::function<void(size_t val)> setter, bool disabled = false, bool alwaysConsume = false) {
396 struct IndexItem : ui::MenuItem {
397 std::function<size_t()> getter;
398 std::function<void(size_t)> setter;
399 size_t index;
400 bool alwaysConsume;
401
402 void step() override {
403 size_t currIndex = getter();
404 this->rightText = CHECKMARK(currIndex == index);
405 MenuItem::step();
406 }
407 void onAction(const event::Action& e) override {
408 setter(index);
409 if (alwaysConsume)
410 e.consume(this);
411 }
412 };
413
414 struct Item : TMenuItem {
415 std::function<size_t()> getter;
416 std::function<void(size_t)> setter;
417 std::vector<std::string> labels;
418 bool alwaysConsume;
419
420 void step() override {
421 size_t currIndex = getter();
422 std::string label = (currIndex < labels.size()) ? labels[currIndex] : "";
423 this->rightText = label + " " + RIGHT_ARROW;
424 TMenuItem::step();
425 }
426 ui::Menu* createChildMenu() override {
427 ui::Menu* menu = new ui::Menu;
428 for (size_t i = 0; i < labels.size(); i++) {
429 IndexItem* item = createMenuItem<IndexItem>(labels[i]);
430 item->getter = getter;
431 item->setter = setter;
432 item->index = i;
433 item->alwaysConsume = alwaysConsume;
434 menu->addChild(item);
435 }
436 return menu;
437 }
438 };
439
440 Item* item = createMenuItem<Item>(text);
441 item->getter = getter;
442 item->setter = setter;
443 item->labels = labels;
444 item->disabled = disabled;
445 item->alwaysConsume = alwaysConsume;
446 return item;
447}
448
449
458template <typename T>
459ui::MenuItem* createIndexPtrSubmenuItem(std::string text, std::vector<std::string> labels, T* ptr) {
460 return createIndexSubmenuItem(text, labels,
461 [=]() {
462 return ptr ? *ptr : 0;
463 },
464 [=](size_t index) {
465 if (ptr)
466 *ptr = T(index);
467 }
468 );
469}
470
471
472} // namespace rack
#define APP
Accesses the global Context pointer.
Definition context.hpp:71
Root namespace for the Rack API.
Definition AudioDisplay.hpp:9
TMenu * createMenu()
Definition helpers.hpp:182
ui::MenuItem * createCheckMenuItem(std::string text, std::string rightText, std::function< bool()> checked, std::function< void()> action, bool disabled=false, bool alwaysConsume=false)
Creates a MenuItem with a check mark set by a lambda function.
Definition helpers.hpp:254
TParamWidget * createParam(math::Vec pos, engine::Module *module, int paramId)
Definition helpers.hpp:87
TMenuLabel * createMenuLabel(std::string text)
Definition helpers.hpp:195
TPortWidget * createOutputCentered(math::Vec pos, engine::Module *module, int outputId)
Definition helpers.hpp:136
TWidget * createWidget(math::Vec pos)
Creates a Widget subclass with its top-left at a position.
Definition helpers.hpp:52
TModuleLightWidget * createLight(math::Vec pos, engine::Module *module, int firstLightId)
Definition helpers.hpp:144
TParamWidget * createLightParamCentered(math::Vec pos, engine::Module *module, int paramId, int firstLightId)
Definition helpers.hpp:174
ui::MenuItem * createIndexSubmenuItem(std::string text, std::vector< std::string > labels, std::function< size_t()> getter, std::function< void(size_t val)> setter, bool disabled=false, bool alwaysConsume=false)
Creates a MenuItem that when hovered, opens a submenu with several MenuItems indexed by an integer.
Definition helpers.hpp:395
ui::MenuItem * createBoolPtrMenuItem(std::string text, std::string rightText, T *ptr)
Easy wrapper for createBoolMenuItem() to modify a bool pointer.
Definition helpers.hpp:339
TMenuItem * createMenuItem(std::string text, std::string rightText="")
Definition helpers.hpp:203
ui::MenuItem * createBoolMenuItem(std::string text, std::string rightText, std::function< bool()> getter, std::function< void(bool state)> setter, bool disabled=false, bool alwaysConsume=false)
Creates a MenuItem that controls a boolean value with a check mark.
Definition helpers.hpp:300
TWidget * createWidgetCentered(math::Vec pos)
Creates a Widget subclass with its center at a position.
Definition helpers.hpp:61
TPortWidget * createOutput(math::Vec pos, engine::Module *module, int outputId)
Definition helpers.hpp:125
ui::MenuItem * createIndexPtrSubmenuItem(std::string text, std::vector< std::string > labels, T *ptr)
Easy wrapper for createIndexSubmenuItem() that controls an integer index at a pointer address.
Definition helpers.hpp:459
plugin::Model * createModel(std::string slug)
Returns a Model that constructs a Module and ModuleWidget subclass.
Definition helpers.hpp:24
TParamWidget * createLightParam(math::Vec pos, engine::Module *module, int paramId, int firstLightId)
Creates a param with a light and calls setFirstLightId() on it.
Definition helpers.hpp:165
TParamWidget * createParamCentered(math::Vec pos, engine::Module *module, int paramId)
Definition helpers.hpp:98
TPanel * createPanel(std::string svgPath)
Creates an SvgPanel and loads the SVG from the given path.
Definition helpers.hpp:70
TModuleLightWidget * createLightCentered(math::Vec pos, engine::Module *module, int firstLightId)
Definition helpers.hpp:154
TPortWidget * createInput(math::Vec pos, engine::Module *module, int inputId)
Definition helpers.hpp:106
ui::MenuItem * createSubmenuItem(std::string text, std::string rightText, std::function< void(ui::Menu *menu)> createMenu, bool disabled=false)
Creates a MenuItem that opens a submenu.
Definition helpers.hpp:363
TPortWidget * createInputCentered(math::Vec pos, engine::Module *module, int inputId)
Definition helpers.hpp:117
Manages an engine::Module in the rack.
Definition ModuleWidget.hpp:17
engine::Module * module
Owned.
Definition ModuleWidget.hpp:24
void setModel(plugin::Model *model)
DSP processor instance for your module.
Definition Module.hpp:29
Light & getLight(int index)
Definition Module.hpp:290
plugin::Model * model
Not owned.
Definition Module.hpp:34
@ OUTPUT
Definition Port.hpp:39
@ INPUT
Definition Port.hpp:38
2-dimensional vector of floats, representing a point on the plane for graphics.
Definition math.hpp:189
Type information for a module.
Definition Model.hpp:34
std::string slug
Must be unique.
Definition Model.hpp:40
Definition MenuItem.hpp:12
Deletes itself from parent when clicked.
Definition MenuOverlay.hpp:11
Definition Menu.hpp:11
void consume(Widget *w) const
Sets the target Widget and stops propagating.
Definition event.hpp:85
Occurs after a certain action is triggered on a Widget.
Definition Widget.hpp:445
void addChild(Widget *child)
Adds widget to the top of the children.
static std::shared_ptr< Svg > load(const std::string &filename)
Loads Svg from a cache.
#define CHECKMARK_STRING
Useful for menu items with a "true" boolean state.
Definition common.hpp:9
#define RIGHT_ARROW
Useful for menu items that open a sub-menu.
Definition common.hpp:13
#define CHECKMARK(_cond)
Definition common.hpp:10