@@ -20,9 +20,9 @@ ifdef ARCH_LIN | |||||
SOURCES += dep/osdialog/osdialog_gtk2.c | SOURCES += dep/osdialog/osdialog_gtk2.c | ||||
build/dep/osdialog/osdialog_gtk2.c.o: FLAGS += $(shell pkg-config --cflags gtk+-2.0) | build/dep/osdialog/osdialog_gtk2.c.o: FLAGS += $(shell pkg-config --cflags gtk+-2.0) | ||||
LDFLAGS += -rdynamic \ | |||||
LDFLAGS += -rdynamic -Wl,--whole-archive \ | |||||
dep/lib/libGLEW.a dep/lib/libglfw3.a dep/lib/libjansson.a dep/lib/libcurl.a dep/lib/libssl.a dep/lib/libcrypto.a dep/lib/libzip.a dep/lib/libz.a dep/lib/libspeexdsp.a dep/lib/libsamplerate.a dep/lib/librtmidi.a dep/lib/librtaudio.a \ | dep/lib/libGLEW.a dep/lib/libglfw3.a dep/lib/libjansson.a dep/lib/libcurl.a dep/lib/libssl.a dep/lib/libcrypto.a dep/lib/libzip.a dep/lib/libz.a dep/lib/libspeexdsp.a dep/lib/libsamplerate.a dep/lib/librtmidi.a dep/lib/librtaudio.a \ | ||||
-lpthread -lGL -ldl -lX11 -lasound -ljack \ | |||||
-Wl,--no-whole-archive -lpthread -lGL -ldl -lX11 -lasound -ljack \ | |||||
$(shell pkg-config --libs gtk+-2.0) | $(shell pkg-config --libs gtk+-2.0) | ||||
TARGET := Rack | TARGET := Rack | ||||
endif | endif | ||||
@@ -12,21 +12,24 @@ namespace app { | |||||
struct Knob : ParamWidget { | struct Knob : ParamWidget { | ||||
/** Multiplier for mouse movement to adjust knob value */ | /** Multiplier for mouse movement to adjust knob value */ | ||||
float speed = 1.0; | float speed = 1.0; | ||||
float oldValue = 0.f; | |||||
/** Drag horizontally instead of vertically. */ | |||||
bool horizontal = false; | |||||
/** Enables per-sample value smoothing while dragging. */ | |||||
bool smooth = true; | bool smooth = true; | ||||
/** Enable snapping at integer values */ | |||||
/** DEPRECATED. Use `ParamQuantity::snapEnabled`. */ | |||||
bool snap = false; | bool snap = false; | ||||
float snapValue = NAN; | |||||
/** Drag horizontally instead of vertically */ | |||||
bool horizontal = false; | |||||
/** Value of the knob before dragging. */ | |||||
float oldValue = 0.f; | |||||
/** Fractional value between the param's value and the dragged knob position. */ | |||||
float snapDelta = 0.f; | |||||
void init() override; | |||||
void onHover(const event::Hover& e) override; | void onHover(const event::Hover& e) override; | ||||
void onButton(const event::Button& e) override; | void onButton(const event::Button& e) override; | ||||
void onDragStart(const event::DragStart& e) override; | void onDragStart(const event::DragStart& e) override; | ||||
void onDragEnd(const event::DragEnd& e) override; | void onDragEnd(const event::DragEnd& e) override; | ||||
void onDragMove(const event::DragMove& e) override; | void onDragMove(const event::DragMove& e) override; | ||||
void reset() override; | |||||
void randomize() override; | |||||
}; | }; | ||||
@@ -13,9 +13,11 @@ namespace app { | |||||
/** Manages an engine::Param on a ModuleWidget. */ | /** Manages an engine::Param on a ModuleWidget. */ | ||||
struct ParamWidget : widget::OpaqueWidget { | struct ParamWidget : widget::OpaqueWidget { | ||||
engine::ParamQuantity* paramQuantity = NULL; | engine::ParamQuantity* paramQuantity = NULL; | ||||
float dirtyValue = NAN; | |||||
ui::Tooltip* tooltip = NULL; | ui::Tooltip* tooltip = NULL; | ||||
/** For triggering the Change event. `*/ | |||||
float lastValue = NAN; | |||||
virtual void init() {} | |||||
void step() override; | void step() override; | ||||
void draw(const DrawArgs& args) override; | void draw(const DrawArgs& args) override; | ||||
@@ -26,8 +28,6 @@ struct ParamWidget : widget::OpaqueWidget { | |||||
void createContextMenu(); | void createContextMenu(); | ||||
void resetAction(); | void resetAction(); | ||||
virtual void reset() {} | |||||
virtual void randomize() {} | |||||
}; | }; | ||||
@@ -19,12 +19,11 @@ struct Switch : ParamWidget { | |||||
bool momentaryPressed = false; | bool momentaryPressed = false; | ||||
bool momentaryReleased = false; | bool momentaryReleased = false; | ||||
void init() override; | |||||
void step() override; | void step() override; | ||||
void onDoubleClick(const event::DoubleClick& e) override; | void onDoubleClick(const event::DoubleClick& e) override; | ||||
void onDragStart(const event::DragStart& e) override; | void onDragStart(const event::DragStart& e) override; | ||||
void onDragEnd(const event::DragEnd& e) override; | void onDragEnd(const event::DragEnd& e) override; | ||||
void reset() override; | |||||
void randomize() override; | |||||
}; | }; | ||||
@@ -65,7 +65,9 @@ struct Engine { | |||||
// Params | // Params | ||||
void setParam(Module* module, int paramId, float value); | void setParam(Module* module, int paramId, float value); | ||||
float getParam(Module* module, int paramId); | float getParam(Module* module, int paramId); | ||||
/** Requests the parameter to smoothly change toward `value`. */ | |||||
void setSmoothParam(Module* module, int paramId, float value); | void setSmoothParam(Module* module, int paramId, float value); | ||||
/** Returns the target value before smoothing. */ | |||||
float getSmoothParam(Module* module, int paramId); | float getSmoothParam(Module* module, int paramId); | ||||
// ParamHandles | // ParamHandles | ||||
@@ -38,13 +38,16 @@ struct ParamQuantity : Quantity { | |||||
int displayPrecision = 5; | int displayPrecision = 5; | ||||
/** An optional one-sentence description of the parameter. */ | /** An optional one-sentence description of the parameter. */ | ||||
std::string description; | std::string description; | ||||
/** Enables parameter resetting when the module is reset. | |||||
/** Enables parameter resetting when the module or parameter itself is reset. | |||||
*/ | */ | ||||
bool resetEnabled = true; | bool resetEnabled = true; | ||||
/** Enables parameter randomization when the module is randomized. | /** Enables parameter randomization when the module is randomized. | ||||
Unbounded (infinite) parameters are not randomizable, regardless of this setting. | Unbounded (infinite) parameters are not randomizable, regardless of this setting. | ||||
*/ | */ | ||||
bool randomizeEnabled = true; | bool randomizeEnabled = true; | ||||
/** Rounds values to the nearest integer. */ | |||||
bool snapEnabled = false; | |||||
Param* getParam(); | Param* getParam(); | ||||
/** Request to the engine to smoothly set the value */ | /** Request to the engine to smoothly set the value */ | ||||
@@ -62,6 +62,7 @@ TParamWidget* createParam(math::Vec pos, engine::Module* module, int paramId) { | |||||
if (module) { | if (module) { | ||||
o->paramQuantity = module->paramQuantities[paramId]; | o->paramQuantity = module->paramQuantities[paramId]; | ||||
} | } | ||||
o->init(); | |||||
return o; | return o; | ||||
} | } | ||||
@@ -56,10 +56,12 @@ void CableWidget::setCable(engine::Cable* cable) { | |||||
app::ModuleWidget* outputModule = APP->scene->rack->getModule(cable->outputModule->id); | app::ModuleWidget* outputModule = APP->scene->rack->getModule(cable->outputModule->id); | ||||
assert(outputModule); | assert(outputModule); | ||||
outputPort = outputModule->getOutput(cable->outputId); | outputPort = outputModule->getOutput(cable->outputId); | ||||
assert(outputPort); | |||||
app::ModuleWidget* inputModule = APP->scene->rack->getModule(cable->inputModule->id); | app::ModuleWidget* inputModule = APP->scene->rack->getModule(cable->inputModule->id); | ||||
assert(inputModule); | assert(inputModule); | ||||
inputPort = inputModule->getInput(cable->inputId); | inputPort = inputModule->getInput(cable->inputId); | ||||
assert(inputPort); | |||||
} | } | ||||
else { | else { | ||||
outputPort = NULL; | outputPort = NULL; | ||||
@@ -12,6 +12,14 @@ namespace app { | |||||
static const float KNOB_SENSITIVITY = 0.0015f; | static const float KNOB_SENSITIVITY = 0.0015f; | ||||
void Knob::init() { | |||||
ParamWidget::init(); | |||||
if (paramQuantity) { | |||||
if (snap) | |||||
paramQuantity->snapEnabled = true; | |||||
} | |||||
} | |||||
void Knob::onHover(const event::Hover& e) { | void Knob::onHover(const event::Hover& e) { | ||||
math::Vec c = box.size.div(2); | math::Vec c = box.size.div(2); | ||||
float dist = e.pos.minus(c).norm(); | float dist = e.pos.minus(c).norm(); | ||||
@@ -34,9 +42,7 @@ void Knob::onDragStart(const event::DragStart& e) { | |||||
if (paramQuantity) { | if (paramQuantity) { | ||||
oldValue = paramQuantity->getSmoothValue(); | oldValue = paramQuantity->getSmoothValue(); | ||||
if (snap) { | |||||
snapValue = paramQuantity->getValue(); | |||||
} | |||||
snapDelta = 0.f; | |||||
} | } | ||||
APP->window->cursorLock(); | APP->window->cursorLock(); | ||||
@@ -81,22 +87,25 @@ void Knob::onDragMove(const event::DragMove& e) { | |||||
delta *= speed; | delta *= speed; | ||||
delta *= range; | delta *= range; | ||||
// Drag slower if mod is held | |||||
// Drag slower if Mod is held | |||||
int mods = APP->window->getMods(); | int mods = APP->window->getMods(); | ||||
if ((mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | if ((mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | ||||
delta /= 16.f; | delta /= 16.f; | ||||
} | } | ||||
// Drag even slower if mod+shift is held | |||||
// Drag even slower if Mod-Shift is held | |||||
if ((mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | if ((mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | ||||
delta /= 256.f; | delta /= 256.f; | ||||
} | } | ||||
if (snap) { | |||||
snapValue += delta; | |||||
snapValue = math::clamp(snapValue, paramQuantity->getMinValue(), paramQuantity->getMaxValue()); | |||||
paramQuantity->setValue(std::round(snapValue)); | |||||
if (paramQuantity->snapEnabled) { | |||||
// Replace delta with an accumulated delta since the last integer knob. | |||||
snapDelta += delta; | |||||
delta = std::trunc(snapDelta); | |||||
snapDelta -= delta; | |||||
} | } | ||||
else if (smooth) { | |||||
// Set value | |||||
if (smooth) { | |||||
paramQuantity->setSmoothValue(paramQuantity->getSmoothValue() + delta); | paramQuantity->setSmoothValue(paramQuantity->getSmoothValue() + delta); | ||||
} | } | ||||
else { | else { | ||||
@@ -107,23 +116,6 @@ void Knob::onDragMove(const event::DragMove& e) { | |||||
ParamWidget::onDragMove(e); | ParamWidget::onDragMove(e); | ||||
} | } | ||||
void Knob::reset() { | |||||
if (paramQuantity && paramQuantity->isBounded()) { | |||||
paramQuantity->reset(); | |||||
oldValue = snapValue = paramQuantity->getValue(); | |||||
} | |||||
} | |||||
void Knob::randomize() { | |||||
if (paramQuantity && paramQuantity->isBounded()) { | |||||
float value = math::rescale(random::uniform(), 0.f, 1.f, paramQuantity->getMinValue(), paramQuantity->getMaxValue()); | |||||
if (snap) | |||||
value = std::round(value); | |||||
paramQuantity->setValue(value); | |||||
oldValue = snapValue = paramQuantity->getValue(); | |||||
} | |||||
} | |||||
} // namespace app | } // namespace app | ||||
} // namespace rack | } // namespace rack |
@@ -668,9 +668,6 @@ void ModuleWidget::resetAction() { | |||||
h->moduleId = module->id; | h->moduleId = module->id; | ||||
h->oldModuleJ = toJson(); | h->oldModuleJ = toJson(); | ||||
for (ParamWidget* param : params) { | |||||
param->reset(); | |||||
} | |||||
APP->engine->resetModule(module); | APP->engine->resetModule(module); | ||||
h->newModuleJ = toJson(); | h->newModuleJ = toJson(); | ||||
@@ -686,9 +683,6 @@ void ModuleWidget::randomizeAction() { | |||||
h->moduleId = module->id; | h->moduleId = module->id; | ||||
h->oldModuleJ = toJson(); | h->oldModuleJ = toJson(); | ||||
for (ParamWidget* param : params) { | |||||
param->randomize(); | |||||
} | |||||
APP->engine->randomizeModule(module); | APP->engine->randomizeModule(module); | ||||
h->newModuleJ = toJson(); | h->newModuleJ = toJson(); | ||||
@@ -754,12 +748,13 @@ void ModuleWidget::cloneAction() { | |||||
void ModuleWidget::disableAction() { | void ModuleWidget::disableAction() { | ||||
assert(module); | assert(module); | ||||
APP->engine->disableModule(module, !module->disabled); | |||||
// history::ModuleDisable | // history::ModuleDisable | ||||
history::ModuleDisable* h = new history::ModuleDisable; | history::ModuleDisable* h = new history::ModuleDisable; | ||||
h->moduleId = module->id; | h->moduleId = module->id; | ||||
h->disabled = !module->disabled; | |||||
h->disabled = module->disabled; | |||||
APP->history->push(h); | APP->history->push(h); | ||||
h->redo(); | |||||
} | } | ||||
void ModuleWidget::removeAction() { | void ModuleWidget::removeAction() { | ||||
@@ -113,12 +113,12 @@ struct ParamUnmapItem : ui::MenuItem { | |||||
void ParamWidget::step() { | void ParamWidget::step() { | ||||
if (paramQuantity) { | if (paramQuantity) { | ||||
float value = paramQuantity->getValue(); | |||||
float value = paramQuantity->getSmoothValue(); | |||||
// Trigger change event when paramQuantity value changes | // Trigger change event when paramQuantity value changes | ||||
if (value != dirtyValue) { | |||||
dirtyValue = value; | |||||
if (value != lastValue) { | |||||
event::Change eChange; | event::Change eChange; | ||||
onChange(eChange); | onChange(eChange); | ||||
lastValue = value; | |||||
} | } | ||||
} | } | ||||
@@ -218,11 +218,9 @@ void ParamWidget::createContextMenu() { | |||||
} | } | ||||
void ParamWidget::resetAction() { | void ParamWidget::resetAction() { | ||||
if (paramQuantity && paramQuantity->isBounded()) { | |||||
if (paramQuantity && paramQuantity->resetEnabled) { | |||||
float oldValue = paramQuantity->getValue(); | float oldValue = paramQuantity->getValue(); | ||||
reset(); | |||||
// Here's another way of doing it, but either works. | |||||
// paramQuantity->getParam()->reset(); | |||||
paramQuantity->reset(); | |||||
float newValue = paramQuantity->getValue(); | float newValue = paramQuantity->getValue(); | ||||
if (oldValue != newValue) { | if (oldValue != newValue) { | ||||
@@ -573,7 +573,10 @@ void RackWidget::clearCablesAction() { | |||||
complexAction->push(h); | complexAction->push(h); | ||||
} | } | ||||
APP->history->push(complexAction); | |||||
if (!complexAction->isEmpty()) | |||||
APP->history->push(complexAction); | |||||
else | |||||
delete complexAction; | |||||
clearCables(); | clearCables(); | ||||
} | } | ||||
@@ -34,12 +34,14 @@ void SvgKnob::setSvg(std::shared_ptr<Svg> svg) { | |||||
void SvgKnob::onChange(const event::Change& e) { | void SvgKnob::onChange(const event::Change& e) { | ||||
// Re-transform the widget::TransformWidget | // Re-transform the widget::TransformWidget | ||||
if (paramQuantity) { | if (paramQuantity) { | ||||
float value = paramQuantity->getScaledValue(); | |||||
float angle; | float angle; | ||||
if (paramQuantity->isBounded()) { | if (paramQuantity->isBounded()) { | ||||
angle = math::rescale(paramQuantity->getScaledValue(), 0.f, 1.f, minAngle, maxAngle); | |||||
angle = math::rescale(value, 0.f, 1.f, minAngle, maxAngle); | |||||
} | } | ||||
else { | else { | ||||
angle = math::rescale(paramQuantity->getValue(), -1.f, 1.f, minAngle, maxAngle); | |||||
// Center unbounded knobs | |||||
angle = math::rescale(value, -1.f, 1.f, minAngle, maxAngle); | |||||
} | } | ||||
angle = std::fmod(angle, 2 * M_PI); | angle = std::fmod(angle, 2 * M_PI); | ||||
tw->identity(); | tw->identity(); | ||||
@@ -9,6 +9,17 @@ namespace rack { | |||||
namespace app { | namespace app { | ||||
void Switch::init() { | |||||
ParamWidget::init(); | |||||
if (paramQuantity) { | |||||
paramQuantity->snapEnabled = true; | |||||
if (momentary) { | |||||
paramQuantity->resetEnabled = false; | |||||
paramQuantity->randomizeEnabled = false; | |||||
} | |||||
} | |||||
} | |||||
void Switch::step() { | void Switch::step() { | ||||
if (momentaryPressed) { | if (momentaryPressed) { | ||||
momentaryPressed = false; | momentaryPressed = false; | ||||
@@ -75,19 +86,6 @@ void Switch::onDragEnd(const event::DragEnd& e) { | |||||
} | } | ||||
} | } | ||||
void Switch::reset() { | |||||
if (paramQuantity && !momentary) { | |||||
paramQuantity->reset(); | |||||
} | |||||
} | |||||
void Switch::randomize() { | |||||
if (paramQuantity && !momentary) { | |||||
float value = paramQuantity->getMinValue() + std::floor(random::uniform() * (paramQuantity->getRange() + 1)); | |||||
paramQuantity->setValue(value); | |||||
} | |||||
} | |||||
} // namespace app | } // namespace app | ||||
} // namespace rack | } // namespace rack |
@@ -539,7 +539,7 @@ void Engine::addModule(Module* module) { | |||||
if (paramHandle->moduleId == module->id) | if (paramHandle->moduleId == module->id) | ||||
paramHandle->module = module; | paramHandle->module = module; | ||||
} | } | ||||
DEBUG("Added module %d to engine", module->id); | |||||
// DEBUG("Added module %d to engine", module->id); | |||||
} | } | ||||
@@ -582,7 +582,7 @@ void Engine::removeModule(Module* module) { | |||||
internal->primaryModule = NULL; | internal->primaryModule = NULL; | ||||
// Remove module | // Remove module | ||||
internal->modules.erase(it); | internal->modules.erase(it); | ||||
DEBUG("Removed module %d to engine", module->id); | |||||
// DEBUG("Removed module %d to engine", module->id); | |||||
} | } | ||||
@@ -736,7 +736,7 @@ void Engine::addCable(Cable* cable) { | |||||
e.portId = cable->outputId; | e.portId = cable->outputId; | ||||
cable->outputModule->onPortChange(e); | cable->outputModule->onPortChange(e); | ||||
} | } | ||||
DEBUG("Added cable %d to engine", cable->id); | |||||
// DEBUG("Added cable %d to engine", cable->id); | |||||
} | } | ||||
@@ -772,7 +772,7 @@ void Engine::removeCable(Cable* cable) { | |||||
e.portId = cable->outputId; | e.portId = cable->outputId; | ||||
cable->outputModule->onPortChange(e); | cable->outputModule->onPortChange(e); | ||||
} | } | ||||
DEBUG("Removed cable %d to engine", cable->id); | |||||
// DEBUG("Removed cable %d to engine", cable->id); | |||||
} | } | ||||
@@ -979,7 +979,6 @@ void Engine::fromJson(json_t* rootJ) { | |||||
Cable* cable = new Cable; | Cable* cable = new Cable; | ||||
try { | try { | ||||
cable->fromJson(cableJ); | cable->fromJson(cableJ); | ||||
// DEBUG("%p %d %p %d", cable->inputModule, cable->inputId, cable->) | |||||
addCable(cable); | addCable(cable); | ||||
} | } | ||||
catch (Exception& e) { | catch (Exception& e) { | ||||
@@ -180,11 +180,10 @@ void Module::fromJson(json_t* rootJ) { | |||||
void Module::onReset(const ResetEvent& e) { | void Module::onReset(const ResetEvent& e) { | ||||
// Reset all parameters | // Reset all parameters | ||||
assert(params.size() == paramQuantities.size()); | |||||
for (int i = 0; i < (int) params.size(); i++) { | |||||
if (!paramQuantities[i]->resetEnabled) | |||||
for (ParamQuantity* pq : paramQuantities) { | |||||
if (!pq->resetEnabled) | |||||
continue; | continue; | ||||
paramQuantities[i]->reset(); | |||||
pq->reset(); | |||||
} | } | ||||
// Call deprecated event | // Call deprecated event | ||||
onReset(); | onReset(); | ||||
@@ -193,11 +192,10 @@ void Module::onReset(const ResetEvent& e) { | |||||
void Module::onRandomize(const RandomizeEvent& e) { | void Module::onRandomize(const RandomizeEvent& e) { | ||||
// Randomize all parameters | // Randomize all parameters | ||||
assert(params.size() == paramQuantities.size()); | |||||
for (int i = 0; i < (int) params.size(); i++) { | |||||
if (!paramQuantities[i]->randomizeEnabled) | |||||
for (ParamQuantity* pq : paramQuantities) { | |||||
if (!pq->randomizeEnabled) | |||||
continue; | continue; | ||||
paramQuantities[i]->randomize(); | |||||
pq->randomize(); | |||||
} | } | ||||
// Call deprecated event | // Call deprecated event | ||||
onRandomize(); | onRandomize(); | ||||
@@ -17,6 +17,8 @@ void ParamQuantity::setSmoothValue(float smoothValue) { | |||||
if (!module) | if (!module) | ||||
return; | return; | ||||
smoothValue = math::clampSafe(smoothValue, getMinValue(), getMaxValue()); | smoothValue = math::clampSafe(smoothValue, getMinValue(), getMaxValue()); | ||||
if (snapEnabled) | |||||
smoothValue = std::round(smoothValue); | |||||
APP->engine->setSmoothParam(module, paramId, smoothValue); | APP->engine->setSmoothParam(module, paramId, smoothValue); | ||||
} | } | ||||
@@ -30,6 +32,8 @@ void ParamQuantity::setValue(float value) { | |||||
if (!module) | if (!module) | ||||
return; | return; | ||||
value = math::clampSafe(value, getMinValue(), getMaxValue()); | value = math::clampSafe(value, getMinValue(), getMaxValue()); | ||||
if (snapEnabled) | |||||
value = std::round(value); | |||||
APP->engine->setParam(module, paramId, value); | APP->engine->setParam(module, paramId, value); | ||||
} | } | ||||
@@ -54,11 +54,8 @@ void ModuleAdd::setModule(app::ModuleWidget* mw) { | |||||
void ModuleAdd::undo() { | void ModuleAdd::undo() { | ||||
app::ModuleWidget* mw = APP->scene->rack->getModule(moduleId); | app::ModuleWidget* mw = APP->scene->rack->getModule(moduleId); | ||||
assert(mw); | assert(mw); | ||||
engine::Module* module = mw->module; | |||||
APP->scene->rack->removeModule(mw); | APP->scene->rack->removeModule(mw); | ||||
delete mw; | delete mw; | ||||
APP->engine->removeModule(module); | |||||
delete module; | |||||
} | } | ||||
void ModuleAdd::redo() { | void ModuleAdd::redo() { | ||||
@@ -66,6 +63,7 @@ void ModuleAdd::redo() { | |||||
module->id = moduleId; | module->id = moduleId; | ||||
module->fromJson(moduleJ); | module->fromJson(moduleJ); | ||||
APP->engine->addModule(module); | APP->engine->addModule(module); | ||||
app::ModuleWidget* mw = model->createModuleWidget(module); | app::ModuleWidget* mw = model->createModuleWidget(module); | ||||
mw->box.pos = pos; | mw->box.pos = pos; | ||||
APP->scene->rack->addModule(mw); | APP->scene->rack->addModule(mw); | ||||
@@ -130,6 +128,7 @@ void ParamChange::redo() { | |||||
void CableAdd::setCable(app::CableWidget* cw) { | void CableAdd::setCable(app::CableWidget* cw) { | ||||
assert(cw); | |||||
assert(cw->cable); | assert(cw->cable); | ||||
assert(cw->cable->id >= 0); | assert(cw->cable->id >= 0); | ||||
cableId = cw->cable->id; | cableId = cw->cable->id; | ||||
@@ -147,11 +146,6 @@ void CableAdd::undo() { | |||||
assert(cw); | assert(cw); | ||||
APP->scene->rack->removeCable(cw); | APP->scene->rack->removeCable(cw); | ||||
delete cw; | delete cw; | ||||
engine::Cable* cable = APP->engine->getCable(cableId); | |||||
assert(cable); | |||||
APP->engine->removeCable(cable); | |||||
delete cable; | |||||
} | } | ||||
void CableAdd::redo() { | void CableAdd::redo() { | ||||