Skip to content

Commit

Permalink
More Undo/Redo capabilities
Browse files Browse the repository at this point in the history
Addresses surge-synthesizer#694

- Step Sequencer undo
  • Loading branch information
baconpaul committed Apr 7, 2022
1 parent b42d366 commit 78a6bce
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 21 deletions.
7 changes: 7 additions & 0 deletions src/surge-xt/gui/SurgeGUIEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2174,6 +2174,12 @@ void SurgeGUIEditor::setParamFromUndo(int paramId, pdata val)
synth->refresh_editor = true;
}

void SurgeGUIEditor::setStepSequencerFromUndo(int scene, int lfoid, const StepSequencerStorage &val)
{
synth->storage.getPatch().stepsequences[scene][lfoid] = val;
synth->refresh_editor = true;
}

void SurgeGUIEditor::pushParamToUndoRedo(int paramId, Surge::GUI::UndoManager::Target which)
{
auto p = synth->storage.getPatch().param_ptr[paramId];
Expand Down Expand Up @@ -5315,6 +5321,7 @@ SurgeGUIEditor::layoutComponentForSkin(std::shared_ptr<Surge::GUI::Skin::Control
lfoDisplay->setLFOStorage(&synth->storage.getPatch().scene[current_scene].lfo[lfo_id]);
lfoDisplay->setModSource((modsources)p->ctrlgroup_entry);
lfoDisplay->setLFOID(lfo_id);
lfoDisplay->setScene(current_scene);

auto msi = 0;
if (gui_modsrc[p->ctrlgroup_entry])
Expand Down
1 change: 1 addition & 0 deletions src/surge-xt/gui/SurgeGUIEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ class SurgeGUIEditor : public Surge::GUI::IComponentTagValue::Listener,
void setModulationFromUndo(int paramId, modsources ms, int scene, int idx, float val);
void pushModulationToUndoRedo(int paramId, modsources ms, int scene, int idx,
Surge::GUI::UndoManager::Target which);
void setStepSequencerFromUndo(int scene, int lfoid, const StepSequencerStorage &val);

private:
juce::Rectangle<int> positionForModulationGrid(modsources entry);
Expand Down
43 changes: 41 additions & 2 deletions src/surge-xt/gui/UndoManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,16 @@ struct UndoManagerImpl
int type;
std::vector<std::pair<int, pdata>> paramIdValues;
};
struct UndoStep
{
int scene;
int lfoid;
StepSequencerStorage storageCopy;
};

// If you add a new type here add it both to aboutTheSameThing, toString, and
// to undo.
typedef std::variant<UndoParam, UndoModulation, UndoOscillator, UndoFX> UndoAction;
typedef std::variant<UndoParam, UndoModulation, UndoOscillator, UndoFX, UndoStep> UndoAction;
struct UndoRecord
{
UndoAction action;
Expand All @@ -88,7 +94,11 @@ struct UndoManagerImpl
return (pa->paramId == pb->paramId) && (pa->scene == pb->scene) && (pa->ms == pb->ms) &&
(pa->index == pb->index);
}

if (auto pa = std::get_if<UndoStep>(&a))
{
auto pb = std::get_if<UndoStep>(&b);
return (pa->lfoid == pb->lfoid) && (pa->scene == pb->scene);
}
return false;
}

Expand All @@ -113,6 +123,10 @@ struct UndoManagerImpl
{
return fmt::format("FX[slot={},type={}]", pa->fxslot, pa->type);
}
if (auto pa = std::get_if<UndoStep>(&a))
{
return fmt::format("Step[scene={},lfoid={}]", pa->scene, pa->lfoid);
}
return "UNK";
}

Expand Down Expand Up @@ -217,6 +231,19 @@ struct UndoManagerImpl
pushRedo(r);
}

void pushStepSequencer(int scene, int lfoid, const StepSequencerStorage &pushValue,
UndoManager::Target to = UndoManager::UNDO)
{
auto r = UndoStep();
r.scene = scene;
r.lfoid = lfoid;
r.storageCopy = pushValue;
if (to == UndoManager::UNDO)
pushUndo(r);
else
pushRedo(r);
}

bool undoRedoImpl(UndoManager::Target which)
{
auto *currStack = &undoStack;
Expand Down Expand Up @@ -284,6 +311,13 @@ struct UndoManagerImpl
}
return true;
}
if (auto p = std::get_if<UndoStep>(&q))
{
pushStepSequencer(p->scene, p->lfoid,
editor->getPatch().stepsequences[p->scene][p->lfoid], opposite);
editor->setStepSequencerFromUndo(p->scene, p->lfoid, p->storageCopy);
return true;
}

return false;
}
Expand Down Expand Up @@ -339,6 +373,11 @@ void UndoManager::dumpStack() { impl->dumpStack(); }

void UndoManager::resetEditor(SurgeGUIEditor *ed) { impl->editor = ed; }

void UndoManager::pushStepSequencer(int scene, int lfoid, const StepSequencerStorage &pushValue)
{
impl->pushStepSequencer(scene, lfoid, pushValue);
}

} // namespace GUI

} // namespace Surge
2 changes: 2 additions & 0 deletions src/surge-xt/gui/UndoManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

struct SurgeSynthesizer;
struct SurgeGUIEditor;
struct StepSequencerStorage;

namespace Surge
{
Expand All @@ -46,6 +47,7 @@ struct UndoManager
void pushModulationChange(int paramId, modsources modsource, int scene, int index, float val,
Target to = UNDO);
void pushOscillator(int scene, int oscnum);
void pushStepSequencer(int scene, int lfoid, const StepSequencerStorage &pushValue);
void pushFX(int fxslot);
bool undo();
bool redo();
Expand Down
70 changes: 51 additions & 19 deletions src/surge-xt/gui/widgets/LFOAndStepDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,14 @@ LFOAndStepDisplay::LFOAndStepDisplay(SurgeGUIEditor *e) : guiEditor(e)
auto q = std::make_unique<OverlayAsAccessibleSlider<LFOAndStepDisplay>>(this, sn);
q->onGetValue = [this, i](auto *T) { return ss->steps[i]; };
q->onSetValue = [this, i](auto *T, float f) {
auto bscg = BeginStepGuard(this);
ss->steps[i] = f;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
return;
};
q->onJogValue = [this, i](auto *t, int dir, bool isShift, bool isControl) {
auto bscg = BeginStepGuard(this);
int step = i;
if (step >= 0)
{
Expand All @@ -116,19 +118,20 @@ LFOAndStepDisplay::LFOAndStepDisplay(SurgeGUIEditor *e) : guiEditor(e)
else
f = limitpm1(f + delt);
ss->steps[step] = f;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
}
};
q->onMinMaxDef = [this, i](auto *t, int mmd) {
auto bscg = BeginStepGuard(this);
if (mmd == 1)
ss->steps[i] = 1.f;
if (mmd == -1)
ss->steps[i] = isUnipolar() ? 0.f : -1.f;
if (mmd == 0)
ss->steps[i] = 0.f;

storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
};
stepLayer->addChildComponent(*q);
Expand Down Expand Up @@ -227,22 +230,25 @@ LFOAndStepDisplay::LFOAndStepDisplay(SurgeGUIEditor *e) : guiEditor(e)
l0->step = 1;
l0->onGetValue = [this](auto *) { return ss->loop_start; };
l0->onSetValue = [this](auto *, float f) {
auto bscg = BeginStepGuard(this);
ss->loop_start = (int)round(f);
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
};
l0->onJogValue = [this](auto *, int dir, bool, bool) {
auto bscg = BeginStepGuard(this);
auto n = limit_range(ss->loop_start + dir, 0, 15);
ss->loop_start = n;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
};
l0->onMinMaxDef = [this](auto *, int mmd) {
auto bscg = BeginStepGuard(this);
if (mmd == 1)
ss->loop_start = ss->loop_end;
else
ss->loop_start = 0;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
};
loopEndOverlays[0] = std::move(l0);
Expand All @@ -254,22 +260,25 @@ LFOAndStepDisplay::LFOAndStepDisplay(SurgeGUIEditor *e) : guiEditor(e)
l0->step = 1;
l0->onGetValue = [this](auto *) { return ss->loop_end; };
l0->onSetValue = [this](auto *, float f) {
auto bscg = BeginStepGuard(this);
ss->loop_end = (int)round(f);
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
};
l0->onJogValue = [this](auto *, int dir, bool, bool) {
auto bscg = BeginStepGuard(this);
auto n = limit_range(ss->loop_end + dir, 0, 15);
ss->loop_end = n;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
};
l0->onMinMaxDef = [this](auto *, int mmd) {
auto bscg = BeginStepGuard(this);
if (mmd == -1)
ss->loop_end = ss->loop_end;
else
ss->loop_end = 15;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
};
loopEndOverlays[1] = std::move(l0);
Expand Down Expand Up @@ -1469,8 +1478,9 @@ void LFOAndStepDisplay::setStepToDefault(const juce::MouseEvent &event)
{
if (steprect[i].contains(event.position))
{
auto bscg = BeginStepGuard(this);
ss->steps[i] = 0.f;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
}
}
Expand All @@ -1495,6 +1505,7 @@ void LFOAndStepDisplay::setStepValue(const juce::MouseEvent &event)
float rx1 = r.getX() + r.getWidth();
if (event.position.x >= rx0 && event.position.x < rx1)
{
auto bscg = BeginStepGuard(this);
draggedStep = i;

float f;
Expand Down Expand Up @@ -1529,7 +1540,7 @@ void LFOAndStepDisplay::setStepValue(const juce::MouseEvent &event)
}

ss->steps[i] = f;
storage->getPatch().isDirty = true;
stepSeqDirty();

repaint();
}
Expand Down Expand Up @@ -1653,6 +1664,7 @@ void LFOAndStepDisplay::mouseDown(const juce::MouseEvent &event)

if (r.contains(event.position))
{
auto bscg = BeginStepGuard(this);
dragMode = TRIGGERS;

uint64_t maski = ss->trigmask & (UINT64_C(1) << i);
Expand Down Expand Up @@ -1697,7 +1709,7 @@ void LFOAndStepDisplay::mouseDown(const juce::MouseEvent &event)
ss->trigmask &= maskOff;
ss->trigmask |= maskOn;

storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();

return;
Expand All @@ -1708,6 +1720,7 @@ void LFOAndStepDisplay::mouseDown(const juce::MouseEvent &event)

void LFOAndStepDisplay::shiftLeft()
{
auto bscg = BeginStepGuard(this);
float t = ss->steps[0];

for (int i = 0; i < (n_stepseqsteps - 1); i++)
Expand All @@ -1724,12 +1737,13 @@ void LFOAndStepDisplay::shiftLeft()
(((ss->trigmask & 0x0000fffe00000000) >> 1) |
(((ss->trigmask & 0x100000000) << 15) & 0xffff00000000));

storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
}

void LFOAndStepDisplay::shiftRight()
{
auto bscg = BeginStepGuard(this);
float t = ss->steps[n_stepseqsteps - 1];

for (int i = (n_stepseqsteps - 2); i >= 0; i--)
Expand All @@ -1746,7 +1760,7 @@ void LFOAndStepDisplay::shiftRight()
(((ss->trigmask & 0x00007fff00000000) << 1) |
(((ss->trigmask & 0x0000800000000000) >> 15) & 0xffff00000000));

storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
}

Expand Down Expand Up @@ -1927,17 +1941,19 @@ void LFOAndStepDisplay::mouseDrag(const juce::MouseEvent &event)
{
if (ss->loop_start != loopStart && loopStart >= 0)
{
auto bscg = BeginStepGuard(this);
ss->loop_start = loopStart;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
}
}
else
{
if (ss->loop_end != loopStart && loopStart >= 0)
{
auto bscg = BeginStepGuard(this);
ss->loop_end = loopStart;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
}
}
Expand Down Expand Up @@ -2046,6 +2062,7 @@ void LFOAndStepDisplay::mouseUp(const juce::MouseEvent &event)

if (s >= 0 && e >= 0 && s != e) // s == e is the abort gesture
{
auto bscg = BeginStepGuard(this);
float fs = (float)(steprect[s].getBottom() - rmStepStart.y) / steprect[s].getHeight();
float fe = (float)(steprect[e].getBottom() - rmStepCurr.y) / steprect[e].getHeight();

Expand All @@ -2067,7 +2084,6 @@ void LFOAndStepDisplay::mouseUp(const juce::MouseEvent &event)
}

ss->steps[s] = fs;
storage->getPatch().isDirty = true;

if (s != e)
{
Expand Down Expand Up @@ -2098,10 +2114,10 @@ void LFOAndStepDisplay::mouseUp(const juce::MouseEvent &event)
}

ss->steps[q] = f;
storage->getPatch().isDirty = true;
}
}

stepSeqDirty();
repaint();
}
}
Expand All @@ -2128,6 +2144,8 @@ void LFOAndStepDisplay::mouseWheelMove(const juce::MouseEvent &event,
return;
}

auto bscg = BeginStepGuard(this);

float delta = wheel.deltaX - (wheel.isReversed ? 1 : -1) * wheel.deltaY;
#if MAC
delta *= 1.3;
Expand Down Expand Up @@ -2159,7 +2177,7 @@ void LFOAndStepDisplay::mouseWheelMove(const juce::MouseEvent &event,
}

ss->steps[i] = v;
storage->getPatch().isDirty = true;
stepSeqDirty();
repaint();
}
}
Expand Down Expand Up @@ -2381,5 +2399,19 @@ bool LFOAndStepDisplay::keyPressed(const juce::KeyPress &key)
return false;
}

void LFOAndStepDisplay::prepareForEdit()
{
jassert(stepDirtyCount == 0);
stepDirtyCount++;
undoStorageCopy = *ss;
}

void LFOAndStepDisplay::stepSeqDirty()
{
jassert(stepDirtyCount == 1);
storage->getPatch().isDirty = true;
guiEditor->undoManager()->pushStepSequencer(scene, lfoid, undoStorageCopy);
}

} // namespace Widgets
} // namespace Surge
Loading

0 comments on commit 78a6bce

Please sign in to comment.