| @@ -382,8 +382,9 @@ struct Marbles : Module { | |||||
| lights[T_DEJA_VU_LIGHT].setBrightness(t_deja_vu); | lights[T_DEJA_VU_LIGHT].setBrightness(t_deja_vu); | ||||
| lights[X_DEJA_VU_LIGHT].setBrightness(x_deja_vu); | lights[X_DEJA_VU_LIGHT].setBrightness(x_deja_vu); | ||||
| lights[T_MODE_LIGHTS + 0].setBrightness(t_mode == 0 || t_mode == 1); | |||||
| lights[T_MODE_LIGHTS + 1].setBrightness(t_mode == 1 || t_mode == 2); | |||||
| int t_mode3 = t_mode % 3; | |||||
| lights[T_MODE_LIGHTS + 0].setBrightness(t_mode3 == 0 || t_mode3 == 1); | |||||
| lights[T_MODE_LIGHTS + 1].setBrightness(t_mode3 == 1 || t_mode3 == 2); | |||||
| lights[X_MODE_LIGHTS + 0].setBrightness(x_mode == 0 || x_mode == 1); | lights[X_MODE_LIGHTS + 0].setBrightness(x_mode == 0 || x_mode == 1); | ||||
| lights[X_MODE_LIGHTS + 1].setBrightness(x_mode == 1 || x_mode == 2); | lights[X_MODE_LIGHTS + 1].setBrightness(x_mode == 1 || x_mode == 2); | ||||
| @@ -525,6 +526,38 @@ struct CKD6Light : BASE { | |||||
| }; | }; | ||||
| MenuItem* createIndexMenu(int* ptr, std::string name, std::vector<std::string> labels) { | |||||
| struct IndexItem : MenuItem { | |||||
| int* ptr; | |||||
| int index; | |||||
| void onAction(const event::Action& e) override { | |||||
| *ptr = index; | |||||
| } | |||||
| }; | |||||
| struct Item : MenuItem { | |||||
| int* ptr; | |||||
| std::vector<std::string> labels; | |||||
| Menu* createChildMenu() override { | |||||
| Menu* menu = new Menu(); | |||||
| for (int i = 0; i < (int) labels.size(); i++) { | |||||
| IndexItem* item = createMenuItem<IndexItem>(labels[i], CHECKMARK(*ptr == i)); | |||||
| item->ptr = ptr; | |||||
| item->index = i; | |||||
| menu->addChild(item); | |||||
| } | |||||
| return menu; | |||||
| } | |||||
| }; | |||||
| int index = *ptr; | |||||
| std::string label = (0 <= index && index < (int) labels.size()) ? labels[index] : ""; | |||||
| Item* item = createMenuItem<Item>(name, label); | |||||
| item->ptr = ptr; | |||||
| item->labels = labels; | |||||
| return item; | |||||
| } | |||||
| struct MarblesWidget : ModuleWidget { | struct MarblesWidget : ModuleWidget { | ||||
| MarblesWidget(Marbles* module) { | MarblesWidget(Marbles* module) { | ||||
| setModule(module); | setModule(module); | ||||
| @@ -588,94 +621,66 @@ struct MarblesWidget : ModuleWidget { | |||||
| void appendContextMenu(Menu* menu) override { | void appendContextMenu(Menu* menu) override { | ||||
| Marbles* module = dynamic_cast<Marbles*>(this->module); | Marbles* module = dynamic_cast<Marbles*>(this->module); | ||||
| struct ScaleItem : MenuItem { | |||||
| Marbles* module; | |||||
| int scale; | |||||
| void onAction(const event::Action& e) override { | |||||
| module->x_scale = scale; | |||||
| } | |||||
| }; | |||||
| menu->addChild(new MenuSeparator); | menu->addChild(new MenuSeparator); | ||||
| menu->addChild(createMenuLabel("Scales")); | |||||
| const std::string scaleLabels[] = { | |||||
| menu->addChild(createIndexMenu(&module->t_mode, "t mode", { | |||||
| "Complementary Bernoulli", | |||||
| "Clusters", | |||||
| "Drums", | |||||
| "Independent Bernoulli", | |||||
| "Divider", | |||||
| "Three states", | |||||
| "Markov", | |||||
| })); | |||||
| menu->addChild(createIndexMenu(&module->t_range, "t range", { | |||||
| "1/4x", | |||||
| "1x", | |||||
| "4x", | |||||
| })); | |||||
| menu->addChild(createIndexMenu(&module->x_mode, "X mode", { | |||||
| "Identical", | |||||
| "Bump", | |||||
| "Tilt", | |||||
| })); | |||||
| menu->addChild(createIndexMenu(&module->x_range, "X range", { | |||||
| "Narrow", | |||||
| "Positive", | |||||
| "Full", | |||||
| })); | |||||
| menu->addChild(createIndexMenu(&module->x_scale, "Scales", { | |||||
| "Major", | "Major", | ||||
| "Minor", | "Minor", | ||||
| "Pentatonic", | "Pentatonic", | ||||
| "Pelog", | "Pelog", | ||||
| "Raag Bhairav That", | "Raag Bhairav That", | ||||
| "Raag Shri", | "Raag Shri", | ||||
| }; | |||||
| for (int i = 0; i < (int) LENGTHOF(scaleLabels); i++) { | |||||
| ScaleItem* item = createMenuItem<ScaleItem>(scaleLabels[i], CHECKMARK(module->x_scale == i)); | |||||
| item->module = module; | |||||
| item->scale = i; | |||||
| menu->addChild(item); | |||||
| } | |||||
| })); | |||||
| struct XClockSourceInternal : MenuItem { | |||||
| Marbles* module; | |||||
| int source; | |||||
| void onAction(const event::Action& e) override { | |||||
| module->x_clock_source_internal = source; | |||||
| } | |||||
| }; | |||||
| menu->addChild(new MenuSeparator); | |||||
| menu->addChild(createMenuLabel("Internal X clock source")); | |||||
| const std::string sourceLabels[] = { | |||||
| menu->addChild(createIndexMenu(&module->x_clock_source_internal, "Internal X clock source", { | |||||
| "T₁ → X₁, T₂ → X₂, T₃ → X₃", | "T₁ → X₁, T₂ → X₂, T₃ → X₃", | ||||
| "T₁ → X₁, X₂, X₃", | "T₁ → X₁, X₂, X₃", | ||||
| "T₂ → X₁, X₂, X₃", | "T₂ → X₁, X₂, X₃", | ||||
| "T₃ → X₁, X₂, X₃", | "T₃ → X₁, X₂, X₃", | ||||
| }; | |||||
| for (int i = 0; i < (int) LENGTHOF(sourceLabels); i++) { | |||||
| XClockSourceInternal* item = createMenuItem<XClockSourceInternal>(sourceLabels[i], CHECKMARK(module->x_clock_source_internal == i)); | |||||
| item->module = module; | |||||
| item->source = i; | |||||
| menu->addChild(item); | |||||
| } | |||||
| struct YDividerIndexItem : MenuItem { | |||||
| Marbles* module; | |||||
| int index; | |||||
| void onAction(const event::Action& e) override { | |||||
| module->y_divider_index = index; | |||||
| } | |||||
| }; | |||||
| struct YDividerItem : MenuItem { | |||||
| Marbles* module; | |||||
| Menu* createChildMenu() override { | |||||
| Menu* menu = new Menu(); | |||||
| const std::string yDividerRatioLabels[] = { | |||||
| "1/64", | |||||
| "1/48", | |||||
| "1/32", | |||||
| "1/24", | |||||
| "1/16", | |||||
| "1/12", | |||||
| "1/8", | |||||
| "1/6", | |||||
| "1/4", | |||||
| "1/3", | |||||
| "1/2", | |||||
| "1", | |||||
| }; | |||||
| for (int i = 0; i < (int) LENGTHOF(yDividerRatioLabels); i++) { | |||||
| YDividerIndexItem* item = createMenuItem<YDividerIndexItem>(yDividerRatioLabels[i], CHECKMARK(module->y_divider_index == i)); | |||||
| item->module = module; | |||||
| item->index = i; | |||||
| menu->addChild(item); | |||||
| } | |||||
| return menu; | |||||
| } | |||||
| }; | |||||
| menu->addChild(new MenuSeparator); | |||||
| YDividerItem* yDividerItem = createMenuItem<YDividerItem>("Y divider ratio"); | |||||
| yDividerItem->module = module; | |||||
| menu->addChild(yDividerItem); | |||||
| })); | |||||
| menu->addChild(createIndexMenu(&module->y_divider_index, "Y divider ratio", { | |||||
| "1/64", | |||||
| "1/48", | |||||
| "1/32", | |||||
| "1/24", | |||||
| "1/16", | |||||
| "1/12", | |||||
| "1/8", | |||||
| "1/6", | |||||
| "1/4", | |||||
| "1/3", | |||||
| "1/2", | |||||
| "1", | |||||
| })); | |||||
| } | } | ||||
| }; | }; | ||||