@@ -112,7 +112,6 @@ struct ModuleWidget : widget::OpaqueWidget { | |||||
/** Deletes `this` */ | /** Deletes `this` */ | ||||
void removeAction(); | void removeAction(); | ||||
void createContextMenu(); | void createContextMenu(); | ||||
void createSelectionContextMenu(); | |||||
INTERNAL math::Vec& dragOffset(); | INTERNAL math::Vec& dragOffset(); | ||||
INTERNAL bool& dragEnabled(); | INTERNAL bool& dragEnabled(); | ||||
@@ -4,6 +4,7 @@ | |||||
#include <app/common.hpp> | #include <app/common.hpp> | ||||
#include <widget/OpaqueWidget.hpp> | #include <widget/OpaqueWidget.hpp> | ||||
#include <widget/FramebufferWidget.hpp> | #include <widget/FramebufferWidget.hpp> | ||||
#include <ui/Menu.hpp> | |||||
#include <app/RailWidget.hpp> | #include <app/RailWidget.hpp> | ||||
#include <app/ModuleWidget.hpp> | #include <app/ModuleWidget.hpp> | ||||
#include <app/CableWidget.hpp> | #include <app/CableWidget.hpp> | ||||
@@ -70,6 +71,8 @@ struct RackWidget : widget::OpaqueWidget { | |||||
void updateModuleOldPositions(); | void updateModuleOldPositions(); | ||||
history::ComplexAction* getModuleDragAction(); | history::ComplexAction* getModuleDragAction(); | ||||
// Module selection methods | |||||
void updateModuleSelections(); | void updateModuleSelections(); | ||||
void clearModuleSelections(); | void clearModuleSelections(); | ||||
bool hasSelectedModules(); | bool hasSelectedModules(); | ||||
@@ -82,6 +85,7 @@ struct RackWidget : widget::OpaqueWidget { | |||||
bool areSelectedModulesBypassed(); | bool areSelectedModulesBypassed(); | ||||
void deleteSelectedModulesAction(); | void deleteSelectedModulesAction(); | ||||
bool requestSelectedModulePos(math::Vec delta); | bool requestSelectedModulePos(math::Vec delta); | ||||
void appendSelectionContextMenu(ui::Menu* menu); | |||||
// Cable methods | // Cable methods | ||||
@@ -215,6 +215,11 @@ struct EditButton : MenuButton { | |||||
disconnectCablesItem->text = "Clear cables"; | disconnectCablesItem->text = "Clear cables"; | ||||
menu->addChild(disconnectCablesItem); | menu->addChild(disconnectCablesItem); | ||||
if (APP->scene->rack->hasSelectedModules()) { | |||||
menu->addChild(new ui::MenuSeparator); | |||||
APP->scene->rack->appendSelectionContextMenu(menu); | |||||
} | |||||
menu->addChild(new ui::MenuSeparator); | menu->addChild(new ui::MenuSeparator); | ||||
AllowCursorLockItem* allowCursorLockItem = new AllowCursorLockItem; | AllowCursorLockItem* allowCursorLockItem = new AllowCursorLockItem; | ||||
@@ -389,7 +389,8 @@ void ModuleWidget::onButton(const ButtonEvent& e) { | |||||
// Open context menu on right-click | // Open context menu on right-click | ||||
if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | if (e.action == GLFW_PRESS && e.button == GLFW_MOUSE_BUTTON_RIGHT) { | ||||
if (internal->selected) { | if (internal->selected) { | ||||
createSelectionContextMenu(); | |||||
ui::Menu* menu = createMenu(); | |||||
APP->scene->rack->appendSelectionContextMenu(menu); | |||||
} | } | ||||
else { | else { | ||||
createContextMenu(); | createContextMenu(); | ||||
@@ -1085,47 +1086,6 @@ void ModuleWidget::createContextMenu() { | |||||
appendContextMenu(menu); | appendContextMenu(menu); | ||||
} | } | ||||
void ModuleWidget::createSelectionContextMenu() { | |||||
ui::Menu* menu = createMenu(); | |||||
int n = APP->scene->rack->getNumSelectedModules(); | |||||
menu->addChild(createMenuLabel(string::f("%d selected %s", n, n == 1 ? "module" : "modules"))); | |||||
// Deselect | |||||
menu->addChild(createMenuItem("Deselect", "", [=]() { | |||||
APP->scene->rack->clearModuleSelections(); | |||||
})); | |||||
// Initialize | |||||
menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [=]() { | |||||
APP->scene->rack->resetSelectedModulesAction(); | |||||
})); | |||||
// Randomize | |||||
menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [=]() { | |||||
APP->scene->rack->randomizeSelectedModulesAction(); | |||||
})); | |||||
// Disconnect cables | |||||
menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [=]() { | |||||
APP->scene->rack->disconnectSelectedModulesAction(); | |||||
})); | |||||
// Bypass | |||||
std::string bypassText = RACK_MOD_CTRL_NAME "+E"; | |||||
bool bypassed = APP->scene->rack->areSelectedModulesBypassed(); | |||||
if (bypassed) | |||||
bypassText += " " CHECKMARK_STRING; | |||||
menu->addChild(createMenuItem("Bypass", bypassText, [=]() { | |||||
APP->scene->rack->bypassSelectedModulesAction(!bypassed); | |||||
})); | |||||
// Delete | |||||
menu->addChild(createMenuItem("Delete", "Backspace/Delete", [=]() { | |||||
APP->scene->rack->deleteSelectedModulesAction(); | |||||
})); | |||||
} | |||||
math::Vec& ModuleWidget::dragOffset() { | math::Vec& ModuleWidget::dragOffset() { | ||||
return internal->dragOffset; | return internal->dragOffset; | ||||
} | } | ||||
@@ -15,6 +15,7 @@ | |||||
#include <context.hpp> | #include <context.hpp> | ||||
#include <asset.hpp> | #include <asset.hpp> | ||||
#include <patch.hpp> | #include <patch.hpp> | ||||
#include <helpers.hpp> | |||||
namespace rack { | namespace rack { | ||||
@@ -828,6 +829,45 @@ bool RackWidget::requestSelectedModulePos(math::Vec delta) { | |||||
return true; | return true; | ||||
} | } | ||||
void RackWidget::appendSelectionContextMenu(ui::Menu* menu) { | |||||
int n = getNumSelectedModules(); | |||||
menu->addChild(createMenuLabel(string::f("%d selected %s", n, n == 1 ? "module" : "modules"))); | |||||
// Deselect | |||||
menu->addChild(createMenuItem("Deselect", "", [=]() { | |||||
clearModuleSelections(); | |||||
})); | |||||
// Initialize | |||||
menu->addChild(createMenuItem("Initialize", RACK_MOD_CTRL_NAME "+I", [=]() { | |||||
resetSelectedModulesAction(); | |||||
})); | |||||
// Randomize | |||||
menu->addChild(createMenuItem("Randomize", RACK_MOD_CTRL_NAME "+R", [=]() { | |||||
randomizeSelectedModulesAction(); | |||||
})); | |||||
// Disconnect cables | |||||
menu->addChild(createMenuItem("Disconnect cables", RACK_MOD_CTRL_NAME "+U", [=]() { | |||||
disconnectSelectedModulesAction(); | |||||
})); | |||||
// Bypass | |||||
std::string bypassText = RACK_MOD_CTRL_NAME "+E"; | |||||
bool bypassed = areSelectedModulesBypassed(); | |||||
if (bypassed) | |||||
bypassText += " " CHECKMARK_STRING; | |||||
menu->addChild(createMenuItem("Bypass", bypassText, [=]() { | |||||
bypassSelectedModulesAction(!bypassed); | |||||
})); | |||||
// Delete | |||||
menu->addChild(createMenuItem("Delete", "Backspace/Delete", [=]() { | |||||
deleteSelectedModulesAction(); | |||||
})); | |||||
} | |||||
void RackWidget::clearCables() { | void RackWidget::clearCables() { | ||||
incompleteCable = NULL; | incompleteCable = NULL; | ||||
internal->cableContainer->clearChildren(); | internal->cableContainer->clearChildren(); | ||||