@@ -66,6 +66,7 @@ extern int threadCount; | |||||
extern bool tooltips; | extern bool tooltips; | ||||
extern bool cpuMeter; | extern bool cpuMeter; | ||||
extern bool lockModules; | extern bool lockModules; | ||||
extern bool squeezeModules; | |||||
extern int frameSwapInterval; | extern int frameSwapInterval; | ||||
extern float autosaveInterval; | extern float autosaveInterval; | ||||
extern bool skipLoadOnLaunch; | extern bool skipLoadOnLaunch; | ||||
@@ -467,6 +467,8 @@ struct ViewButton : MenuButton { | |||||
menu->addChild(knobScrollSensitivitySlider); | menu->addChild(knobScrollSensitivitySlider); | ||||
menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules)); | menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules)); | ||||
menu->addChild(createBoolPtrMenuItem("Auto-squeeze modules when dragging", "", &settings::squeezeModules)); | |||||
} | } | ||||
}; | }; | ||||
@@ -478,13 +478,22 @@ void ModuleWidget::onDragMove(const DragMoveEvent& e) { | |||||
math::Vec pos = mousePos; | math::Vec pos = mousePos; | ||||
pos.x -= internal->dragOffset.x; | pos.x -= internal->dragOffset.x; | ||||
pos.y -= RACK_GRID_HEIGHT / 2; | pos.y -= RACK_GRID_HEIGHT / 2; | ||||
if (APP->scene->rack->isSelected(this)) { | if (APP->scene->rack->isSelected(this)) { | ||||
pos = (pos / RACK_GRID_SIZE).round() * RACK_GRID_SIZE; | pos = (pos / RACK_GRID_SIZE).round() * RACK_GRID_SIZE; | ||||
math::Vec delta = pos.minus(box.pos); | math::Vec delta = pos.minus(box.pos); | ||||
APP->scene->rack->setSelectionPosNearest(delta); | APP->scene->rack->setSelectionPosNearest(delta); | ||||
} | } | ||||
else { | else { | ||||
APP->scene->rack->setModulePosForce(this, pos); | |||||
if (settings::squeezeModules) { | |||||
APP->scene->rack->setModulePosSqueeze(this, pos); | |||||
} | |||||
else { | |||||
if ((APP->window->getMods() & RACK_MOD_MASK) == RACK_MOD_CTRL) | |||||
APP->scene->rack->setModulePosForce(this, pos); | |||||
else | |||||
APP->scene->rack->setModulePosNearest(this, pos); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -598,7 +598,12 @@ void RackWidget::addModuleAtMouse(ModuleWidget* mw) { | |||||
assert(mw); | assert(mw); | ||||
// Move module nearest to the mouse position | // Move module nearest to the mouse position | ||||
math::Vec pos = internal->mousePos.minus(mw->box.size.div(2)); | math::Vec pos = internal->mousePos.minus(mw->box.size.div(2)); | ||||
setModulePosSqueeze(mw, pos); | |||||
if (settings::squeezeModules) | |||||
setModulePosSqueeze(mw, pos); | |||||
else | |||||
setModulePosNearest(mw, pos); | |||||
addModule(mw); | addModule(mw); | ||||
} | } | ||||
@@ -666,21 +671,21 @@ bool RackWidget::requestModulePos(ModuleWidget* mw, math::Vec pos) { | |||||
} | } | ||||
static math::Vec eachNearestGridPos(math::Vec pos, std::function<bool(math::Vec pos)> f) { | static math::Vec eachNearestGridPos(math::Vec pos, std::function<bool(math::Vec pos)> f) { | ||||
math::Vec leftPos = pos.div(RACK_GRID_SIZE).floor().mult(RACK_GRID_SIZE); | |||||
math::Vec rightPos = leftPos + math::Vec(RACK_GRID_WIDTH, 0); | |||||
math::Vec leftPos = (pos / RACK_GRID_SIZE).round(); | |||||
math::Vec rightPos = leftPos + math::Vec(1, 0); | |||||
while (true) { | while (true) { | ||||
if (f(leftPos)) | |||||
return leftPos; | |||||
leftPos.x -= RACK_GRID_WIDTH; | |||||
if (f(leftPos * RACK_GRID_SIZE)) | |||||
return leftPos * RACK_GRID_SIZE; | |||||
leftPos.x -= 1; | |||||
if (f(rightPos)) | |||||
return rightPos; | |||||
rightPos.x += RACK_GRID_WIDTH; | |||||
if (f(rightPos * RACK_GRID_SIZE)) | |||||
return rightPos * RACK_GRID_SIZE; | |||||
rightPos.x += 1; | |||||
} | } | ||||
assert(false); | assert(false); | ||||
return leftPos; | |||||
return math::Vec(); | |||||
} | } | ||||
void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) { | void RackWidget::setModulePosNearest(ModuleWidget* mw, math::Vec pos) { | ||||
@@ -40,6 +40,7 @@ int threadCount = 1; | |||||
bool tooltips = true; | bool tooltips = true; | ||||
bool cpuMeter = false; | bool cpuMeter = false; | ||||
bool lockModules = false; | bool lockModules = false; | ||||
bool squeezeModules = true; | |||||
#if defined ARCH_MAC | #if defined ARCH_MAC | ||||
// Most Mac GPUs can't handle rendering the screen every frame, so use ~30 Hz by default. | // Most Mac GPUs can't handle rendering the screen every frame, so use ~30 Hz by default. | ||||
int frameSwapInterval = 2; | int frameSwapInterval = 2; | ||||
@@ -153,6 +154,8 @@ json_t* toJson() { | |||||
json_object_set_new(rootJ, "lockModules", json_boolean(lockModules)); | json_object_set_new(rootJ, "lockModules", json_boolean(lockModules)); | ||||
json_object_set_new(rootJ, "squeezeModules", json_boolean(squeezeModules)); | |||||
json_object_set_new(rootJ, "frameSwapInterval", json_integer(frameSwapInterval)); | json_object_set_new(rootJ, "frameSwapInterval", json_integer(frameSwapInterval)); | ||||
json_object_set_new(rootJ, "autosaveInterval", json_real(autosaveInterval)); | json_object_set_new(rootJ, "autosaveInterval", json_real(autosaveInterval)); | ||||
@@ -338,6 +341,10 @@ void fromJson(json_t* rootJ) { | |||||
if (lockModulesJ) | if (lockModulesJ) | ||||
lockModules = json_boolean_value(lockModulesJ); | lockModules = json_boolean_value(lockModulesJ); | ||||
json_t* squeezeModulesJ = json_object_get(rootJ, "squeezeModules"); | |||||
if (squeezeModulesJ) | |||||
squeezeModules = json_boolean_value(squeezeModulesJ); | |||||
json_t* frameSwapIntervalJ = json_object_get(rootJ, "frameSwapInterval"); | json_t* frameSwapIntervalJ = json_object_get(rootJ, "frameSwapInterval"); | ||||
if (frameSwapIntervalJ) | if (frameSwapIntervalJ) | ||||
frameSwapInterval = json_integer_value(frameSwapIntervalJ); | frameSwapInterval = json_integer_value(frameSwapIntervalJ); | ||||