diff --git a/BAKKA-Editor/Enums.cs b/BAKKA-Editor/Enums.cs index c0be685..6597b32 100644 --- a/BAKKA-Editor/Enums.cs +++ b/BAKKA-Editor/Enums.cs @@ -63,4 +63,10 @@ namespace BAKKA_Editor Bonus = 1, Flair = 2 } + + internal enum OperationDirection + { + Undo, + Redo + } } diff --git a/BAKKA-Editor/MainForm.cs b/BAKKA-Editor/MainForm.cs index 49beb03..c959620 100644 --- a/BAKKA-Editor/MainForm.cs +++ b/BAKKA-Editor/MainForm.cs @@ -818,13 +818,21 @@ namespace BAKKA_Editor circlePanel.Invalidate(); } - if(currentNoteType == NoteType.HoldJoint || currentNoteType == NoteType.HoldEnd) + if (currentNoteType == NoteType.HoldJoint || currentNoteType == NoteType.HoldEnd) { if (lastNote.BeatInfo.MeasureDecimal >= circleView.CurrentMeasure) insertButton.Enabled = false; else insertButton.Enabled = true; } + else if (currentSong != null && !currentSong.Paused) + { + insertButton.Enabled = false; + } + else + { + insertButton.Enabled = true; + } } private void positionTrackBar_ValueChanged(object sender, EventArgs e) @@ -1164,13 +1172,11 @@ namespace BAKKA_Editor { playButton.Text = "Play (P)"; updateTimer.Enabled = false; - insertButton.Enabled = true; } else { playButton.Text = "Pause (P)"; updateTimer.Enabled = true; - insertButton.Enabled = false; } } } @@ -1348,7 +1354,7 @@ namespace BAKKA_Editor case NoteType.HoldStartBonusFlair: SetSelectedObject(NoteType.HoldJoint); lastNote = tempNote; - disableNonHoldButtons(); + SetNonHoldButtonState(false); break; case NoteType.HoldJoint: case NoteType.HoldEnd: @@ -1357,7 +1363,7 @@ namespace BAKKA_Editor if (endHoldCheck.Checked) { tempNote.NoteType = NoteType.HoldEnd; - enableNonHoldButtons(); + SetNonHoldButtonState(true); holdButtonClicked(); } else @@ -1377,44 +1383,37 @@ namespace BAKKA_Editor } chart.Notes.Add(tempNote); chart.IsSaved = false; - opManager.Push(new InsertNote(chart, tempNote)); + switch (currentNoteType) + { + case NoteType.HoldStartNoBonus: + case NoteType.HoldStartBonusFlair: + case NoteType.HoldJoint: + case NoteType.HoldEnd: + opManager.Push(new InsertHoldNote(chart, tempNote)); + break; + default: + opManager.Push(new InsertNote(chart, tempNote)); + break; + } } } - private void disableNonHoldButtons() + private void SetNonHoldButtonState(bool state) { - tapButton.Enabled = false; - orangeButton.Enabled = false; - greenButton.Enabled = false; - redButton.Enabled = false; - blueButton.Enabled = false; - chainButton.Enabled = false; - endChartButton.Enabled = false; + tapButton.Enabled = state; + orangeButton.Enabled = state; + greenButton.Enabled = state; + redButton.Enabled = state; + blueButton.Enabled = state; + chainButton.Enabled = state; + endChartButton.Enabled = state; - maskButton.Enabled = false; - bpmChangeButton.Enabled = false; - timeSigButton.Enabled = false; - hiSpeedButton.Enabled = false; - stopButton.Enabled = false; - reverseButton.Enabled = false; - } - - private void enableNonHoldButtons() - { - tapButton.Enabled = true; - orangeButton.Enabled = true; - greenButton.Enabled = true; - redButton.Enabled = true; - blueButton.Enabled = true; - chainButton.Enabled = true; - endChartButton.Enabled = true; - - maskButton.Enabled = true; - bpmChangeButton.Enabled = true; - timeSigButton.Enabled = true; - hiSpeedButton.Enabled = true; - stopButton.Enabled = true; - reverseButton.Enabled = true; + maskButton.Enabled = state; + bpmChangeButton.Enabled = state; + timeSigButton.Enabled = state; + hiSpeedButton.Enabled = state; + stopButton.Enabled = state; + reverseButton.Enabled = state; } private void maskButton_Click(object sender, EventArgs e) @@ -1909,7 +1908,9 @@ namespace BAKKA_Editor return; int delIndex = selectedNoteIndex; - opManager.InvokeAndPush(new RemoveNote(chart, chart.Notes[selectedNoteIndex])); + NoteOperation op = chart.Notes[selectedNoteIndex].IsHold ? new RemoveHoldNote(chart, chart.Notes[selectedNoteIndex]) : new RemoveNote(chart, chart.Notes[selectedNoteIndex]); + opManager.InvokeAndPush(op); + UpdateControlsFromOperation(op, OperationDirection.Redo); if (selectedNoteIndex == delIndex) { UpdateNoteLabels(delIndex - 1); @@ -2008,13 +2009,105 @@ namespace BAKKA_Editor private void undoToolStripMenuItem_Click(object sender, EventArgs e) { if (opManager.CanUndo) - opManager.Undo(); + { + var op = opManager.Undo(); + if (op != null) + { + UpdateControlsFromOperation(op, OperationDirection.Undo); + } + } } private void redoToolStripMenuItem_Click(object sender, EventArgs e) { if (opManager.CanRedo) - opManager.Redo(); + { + var op = opManager.Redo(); + if (op != null) + { + UpdateControlsFromOperation(op, OperationDirection.Redo); + } + } + } + + private void UpdateControlsFromOperation(IOperation op, OperationDirection dir) + { + if (dir == OperationDirection.Undo) + { + bool isInsertHold = op.GetType() == typeof(InsertHoldNote); + bool isRemoveHold = op.GetType() == typeof(RemoveHoldNote); + var note = op.GetType().IsSubclassOf(typeof(NoteOperation)) ? (op as NoteOperation).Note : null; + if (note != null) + { + if (note.NoteType == NoteType.HoldStartNoBonus || note.NoteType == NoteType.HoldStartBonusFlair) + { + if (isInsertHold) + { + SetNonHoldButtonState(true); + SetSelectedObject(note.NoteType); + } + if (isRemoveHold) + { + if (note.NextNote == null) + { + SetNonHoldButtonState(true); + SetSelectedObject(note.NoteType); + } + } + } + else if (note.NoteType == NoteType.HoldJoint) + { + if (isInsertHold) + { + lastNote = note.PrevNote; + } + } + else if (note.NoteType == NoteType.HoldEnd) + { + if (isInsertHold) + { + SetNonHoldButtonState(false); + SetSelectedObject(note.NoteType); + lastNote = note.PrevNote; + } + } + updateTime(); + } + } + else + { + bool isInsertHold = op.GetType() == typeof(InsertHoldNote); + bool isRemoveHold = op.GetType() == typeof(RemoveHoldNote); + var note = op.GetType().IsSubclassOf(typeof(NoteOperation)) ? (op as NoteOperation).Note : null; + if (note != null) + { + if (note.NoteType == NoteType.HoldStartNoBonus || note.NoteType == NoteType.HoldStartBonusFlair) + { + if (isInsertHold) + { + SetNonHoldButtonState(true); + SetSelectedObject(NoteType.HoldJoint); + } + } + else if (note.NoteType == NoteType.HoldJoint) + { + if (isInsertHold) + { + lastNote = note; + } + } + else if (note.NoteType == NoteType.HoldEnd) + { + if (isInsertHold) + { + SetNonHoldButtonState(true); + SetSelectedObject(flairRadio.Checked ? NoteType.HoldStartBonusFlair : NoteType.HoldStartNoBonus); + lastNote = note; + } + } + updateTime(); + } + } } diff --git a/BAKKA-Editor/Operations/NoteOperation.cs b/BAKKA-Editor/Operations/NoteOperation.cs index 521364a..271fcf8 100644 --- a/BAKKA-Editor/Operations/NoteOperation.cs +++ b/BAKKA-Editor/Operations/NoteOperation.cs @@ -8,7 +8,7 @@ namespace BAKKA_Editor.Operations { internal abstract class NoteOperation : IOperation { - protected Note Note { get; } + public Note Note { get; } protected Chart Chart { get; } public abstract string Description { get; } @@ -88,4 +88,94 @@ namespace BAKKA_Editor.Operations Base.Size = OldNote.Size; } } + + internal class InsertHoldNote : NoteOperation + { + public override string Description => "Insert hold note"; + private Note prevNote; + + public InsertHoldNote(Chart chart, Note item) : base(chart, item) + { + prevNote = item.PrevNote; + } + + public override void Redo() + { + if (Note.PrevNote != null) + Note.PrevNote.NextNote = Note; + Chart.Notes.Add(Note); + } + + public override void Undo() + { + if (Note.PrevNote != null) + Note.PrevNote.NextNote = null; + Chart.Notes.Remove(Note); + } + } + + internal class RemoveHoldNote : NoteOperation + { + public override string Description => "Remove hold note"; + private Note prevNote; + private NoteType prevNoteType; + private Note nextNote; + private NoteType nextNoteType; + + public RemoveHoldNote(Chart chart, Note item) : base(chart, item) + { + prevNote = item.PrevNote; + if (prevNote != null) + prevNoteType = prevNote.NoteType; + nextNote = item.NextNote; + if (nextNote != null) + nextNoteType = nextNote.NoteType; + } + + public override void Redo() + { + switch (Note.NoteType) + { + case NoteType.HoldStartNoBonus: + case NoteType.HoldStartBonusFlair: + nextNote.PrevNote = null; + nextNote.NoteType = Note.NoteType; + break; + case NoteType.HoldJoint: + prevNote.NextNote = nextNote; + nextNote.PrevNote = prevNote; + break; + case NoteType.HoldEnd: + prevNote.NextNote = null; + prevNote.NoteType = NoteType.HoldEnd; + break; + default: + break; + } + Chart.Notes.Remove(Note); + } + + public override void Undo() + { + switch (Note.NoteType) + { + case NoteType.HoldStartNoBonus: + case NoteType.HoldStartBonusFlair: + nextNote.PrevNote = Note; + nextNote.NoteType = nextNoteType; + break; + case NoteType.HoldJoint: + prevNote.NextNote = Note; + nextNote.PrevNote = Note; + break; + case NoteType.HoldEnd: + prevNote.NextNote = Note; + prevNote.NoteType = prevNoteType; + break; + default: + break; + } + Chart.Notes.Add(Note); + } + } } diff --git a/BAKKA-Editor/Operations/OperationManager.cs b/BAKKA-Editor/Operations/OperationManager.cs index 8be8e14..36c10bb 100644 --- a/BAKKA-Editor/Operations/OperationManager.cs +++ b/BAKKA-Editor/Operations/OperationManager.cs @@ -43,20 +43,23 @@ namespace BAKKA_Editor.Operations Push(op); } - public void Undo() + public IOperation Undo() { IOperation op = UndoStack.Pop(); op.Undo(); + var type = op.GetType(); RedoStack.Push(op); OperationHistoryChanged?.Invoke(this, EventArgs.Empty); + return op; } - public void Redo() + public IOperation Redo() { IOperation op = RedoStack.Pop(); op.Redo(); UndoStack.Push(op); OperationHistoryChanged?.Invoke(this, EventArgs.Empty); + return op; } public void Clear()