Skip to content

Commit 5c54cb3

Browse files
committed
editor save error button: fix scaling, allow saving anyways, go to error, and fix
interaction with Alt+V on macOS
1 parent 7a4f57a commit 5c54cb3

4 files changed

Lines changed: 394 additions & 92 deletions

File tree

-332 Bytes
Loading
-332 Bytes
Loading

src/screens/UScreenEditSub.pas

Lines changed: 176 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,11 @@ TScreenEditSub = class(TMenu)
359359

360360
// medley
361361
MedleyNotes: TMedleyNotes;
362+
PendingSaveRelative: boolean;
363+
TimingErrorTrack: Integer;
364+
TimingErrorLine: Integer;
365+
TimingErrorBeat: Integer;
366+
TimingErrorValid: boolean;
362367

363368
procedure ChangeBPM(newBPM: real);
364369
procedure ResetBeatTracking;
@@ -435,6 +440,9 @@ TScreenEditSub = class(TMenu)
435440
function DuetMoveLine: boolean;
436441
procedure CopyLine(SrcTrack, SrcLine, DstTrack, DstLine: Integer);
437442
function CheckTimingSyntaxErrors(out ErrorMessages: UTF8String): boolean;
443+
procedure GoToLineAndBeat(const TrackIndex, LineIndex, Beat: Integer);
444+
procedure GoToFirstTimingError;
445+
function SaveSongToFile(const SaveRelative: boolean): boolean;
438446
procedure Refresh;
439447
procedure CopyToUndo; //copy current lines, mouse position and headers
440448
procedure CopyFromUndo; //undo last lines, mouse position and headers
@@ -520,6 +528,20 @@ procedure OnSaveEncodingError(Value: boolean; Data: Pointer);
520528
ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
521529
end;
522530

531+
procedure OnSaveTimingErrorChoice(Value: integer; Data: Pointer);
532+
var
533+
EditScreen: TScreenEditSub;
534+
begin
535+
if Data = nil then
536+
Exit;
537+
538+
EditScreen := TScreenEditSub(Data);
539+
case Value of
540+
0: EditScreen.SaveSongToFile(EditScreen.PendingSaveRelative);
541+
1: EditScreen.GoToFirstTimingError;
542+
end;
543+
end;
544+
523545
procedure OnExit(Value: boolean; Data: Pointer);
524546
begin
525547
Display.CheckOK := Value;
@@ -640,81 +662,26 @@ function TScreenEditSub.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; Pre
640662
// SDLK_S: HandleSaveSong
641663
procedure TScreenEditSub.HandleSaveSong(SDL_ModState: word);
642664
var
643-
SResult: TSaveSongResult;
644665
TimingErrors: UTF8String;
666+
SaveRelative: boolean;
645667
begin
646-
// run timing checks before saving and abort on serious problems
668+
SaveRelative := (SDL_ModState = KMOD_LSHIFT);
669+
PendingSaveRelative := SaveRelative;
670+
647671
if CheckTimingSyntaxErrors(TimingErrors) then
648672
begin
649673
if TimingErrors <> '' then
650-
ScreenPopupError.ShowPopup(TimingErrors);
674+
ScreenPopupError.ShowPopup(
675+
TimingErrors,
676+
['Save anyways', 'Go to Error', 'Cancel'],
677+
OnSaveTimingErrorChoice,
678+
Self,
679+
1,
680+
2);
651681
Exit;
652682
end;
653683

654-
// handle medley tags first
655-
if CurrentSong.isDuet then
656-
begin
657-
CurrentSong.Medley.Source := msNone;
658-
end
659-
else if (MedleyNotes.isStart and MedleyNotes.isEnd and MedleyNotes.isCustom) and
660-
(MedleyNotes.start.line < MedleyNotes.end_.line) and
661-
(Length(CurrentSong.Tracks[CurrentTrack].Lines)> MedleyNotes.end_.line) and
662-
(Length(CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.end_.line].Notes) > MedleyNotes.end_.note) and
663-
(Length(CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.start.line].Notes) > MedleyNotes.start.note) then
664-
begin
665-
CurrentSong.Medley.Source := msTag;
666-
CurrentSong.Medley.StartBeat := CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.start.line].Notes[MedleyNotes.start.note].StartBeat;
667-
CurrentSong.Medley.EndBeat := CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.end_.line].Notes[MedleyNotes.end_.note].StartBeat +
668-
CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.end_.line].Notes[MedleyNotes.end_.note].Duration;
669-
CurrentSong.Medley.FadeIn_time := DEFAULT_FADE_IN_TIME;
670-
CurrentSong.Medley.FadeOut_time := DEFAULT_FADE_OUT_TIME;
671-
end
672-
else if MedleyNotes.isCustom then
673-
begin
674-
CurrentSong.Medley.Source := msNone;
675-
CurrentSong.Medley.StartBeat := 0;
676-
CurrentSong.Medley.EndBeat := 0;
677-
end;
678-
679-
// Save Song (SHIFT = relative)
680-
if SDL_ModState = KMOD_LSHIFT then
681-
begin
682-
if (CurrentSong.isDuet) then
683-
begin
684-
ScreenPopupError.ShowPopup(Language.Translate('EDIT_INFO_DUET_RELATIVE_UNSUPPORTED'));
685-
Exit;
686-
end;
687-
688-
if (CurrentSong.Medley.Source = msTag) then
689-
begin
690-
ScreenPopupError.ShowPopup(Language.Translate('EDIT_INFO_MEDLEY_RELATIVE_UNSUPPORTED') + ' ' + Language.Translate('EDIT_INFO_MEDLEY_DELETED'));
691-
end;
692-
693-
CurrentSong.Medley.Source := msNone;
694-
CurrentSong.Relative := true;
695-
SResult := SaveSong(CurrentSong, CurrentSong.Tracks, CurrentSong.Path.Append(CurrentSong.FileName), CurrentSong.Relative); //save with relative timings
696-
end else
697-
begin
698-
CurrentSong.Relative := false;
699-
SResult := SaveSong(CurrentSong, CurrentSong.Tracks, CurrentSong.Path.Append(CurrentSong.FileName), CurrentSong.Relative); // save with absolute timings
700-
end;
701-
702-
if (SResult = ssrOK) then // saving was successful
703-
begin
704-
Text[TextInfo].Text := Language.Translate('INFO_FILE_SAVED');
705-
SetLength(UndoLines, 0, High(CurrentSong.Tracks)); //clear undo lines
706-
SetLength(UndoStateNote, 0, Length(CurrentSong.Tracks)); //clear undo CurrentNote[CurrentTrack] state
707-
SetLength(Undoheader, 0); //clear undo headers
708-
CurrentUndoLines := 0;
709-
//if not CheckSong then
710-
// ScreenPopupError.ShowPopup(Language.Translate(''));
711-
712-
//CatSongs.Song[SongIndex] := CurrentSong;
713-
end
714-
else // saving was unsuccessful
715-
begin
716-
ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
717-
end;
684+
SaveSongToFile(SaveRelative);
718685
end;
719686

720687

@@ -1131,7 +1098,11 @@ procedure TScreenEditSub.HandleVideo(SDL_ModState: word);
11311098
end;
11321099
if (SDL_ModState = KMOD_LALT) then
11331100
begin
1101+
{$IFDEF UseMIDIPort}
11341102
PlaySentenceMidi := true;
1103+
{$ELSE}
1104+
PlaySentenceMidi := false;
1105+
{$ENDIF}
11351106
ConfigureMidiPlayback(AudioPlayback.Position, PlayStopTime);
11361107
end;
11371108
PlaySentence := true;
@@ -1925,7 +1896,11 @@ procedure TScreenEditSub.ToggleTextEditMode(SDL_ModState: word);
19251896
begin
19261897
CurrentSong.Tracks[CurrentTrack].Lines[CurrentSong.Tracks[CurrentTrack].CurrentLine].Notes[CurrentNote[CurrentTrack]].Color := 1;
19271898
CurrentNote[CurrentTrack] := 0;
1899+
{$IFDEF UseMIDIPort}
19281900
PlaySentenceMidi := true;
1901+
{$ELSE}
1902+
PlaySentenceMidi := false;
1903+
{$ENDIF}
19291904
PlayVideo := false;
19301905
StopVideoPreview;
19311906
LastClick := -100;
@@ -1946,7 +1921,11 @@ procedure TScreenEditSub.ToggleTextEditMode(SDL_ModState: word);
19461921
begin
19471922
CurrentSong.Tracks[CurrentTrack].Lines[CurrentSong.Tracks[CurrentTrack].CurrentLine].Notes[CurrentNote[CurrentTrack]].Color := 1;
19481923
CurrentNote[CurrentTrack] := 0;
1924+
{$IFDEF UseMIDIPort}
19491925
PlaySentenceMidi := true;
1926+
{$ELSE}
1927+
PlaySentenceMidi := false;
1928+
{$ENDIF}
19501929
PlayVideo := false;
19511930
StopVideoPreview;
19521931
PlaySentence := true;
@@ -4997,12 +4976,27 @@ function TScreenEditSub.CheckTimingSyntaxErrors(out ErrorMessages: UTF8String):
49974976
procedure AppendMsg(const Msg: UTF8String);
49984977
begin
49994978
if Messages <> '' then
5000-
Messages := Messages + ' ' + Msg
4979+
Messages := Messages + '\n' + Msg
50014980
else
50024981
Messages := Msg;
50034982
end;
4983+
4984+
procedure RememberFirstError(const TrackIndex, LineIndex, Beat: Integer);
4985+
begin
4986+
if TimingErrorValid then
4987+
Exit;
4988+
4989+
TimingErrorValid := true;
4990+
TimingErrorTrack := TrackIndex;
4991+
TimingErrorLine := LineIndex;
4992+
TimingErrorBeat := Beat;
4993+
end;
50044994
begin
50054995
Messages := '';
4996+
TimingErrorValid := false;
4997+
TimingErrorTrack := 0;
4998+
TimingErrorLine := 0;
4999+
TimingErrorBeat := 0;
50065000

50075001
for TrackIndex := 0 to High(CurrentSong.Tracks) do
50085002
begin
@@ -5033,6 +5027,7 @@ function TScreenEditSub.CheckTimingSyntaxErrors(out ErrorMessages: UTF8String):
50335027
// any later note starting before previous note ended is an overlap
50345028
if NoteStart < PrevNoteEnd then
50355029
begin
5030+
RememberFirstError(TrackIndex, LineIndex, NoteStart);
50365031
AppendMsg(Format(Language.Translate('EDIT_INFO_TIMING_NOTE_OVERLAP'),
50375032
[TrackIndex + 1, LineIndex + 1, NoteIndex + 1,
50385033
NoteStart, NoteEnd - 1, PrevNoteEnd - 1]));
@@ -5052,6 +5047,7 @@ function TScreenEditSub.CheckTimingSyntaxErrors(out ErrorMessages: UTF8String):
50525047
// forbidden: NoteStart < LineEndBeat < NoteEnd
50535048
if (NoteStart < LineEndBeat) and (LineEndBeat < NoteEnd) then
50545049
begin
5050+
RememberFirstError(TrackIndex, LineIndex, LineEndBeat);
50555051
AppendMsg(Format(Language.Translate('EDIT_INFO_TIMING_LINEBREAK_OVERLAP'),
50565052
[TrackIndex + 1, LineIndex + 1, LineEndBeat,
50575053
NoteIndex + 1, NoteStart, NoteEnd - 1]));
@@ -5082,6 +5078,7 @@ function TScreenEditSub.CheckTimingSyntaxErrors(out ErrorMessages: UTF8String):
50825078

50835079
if (NoteStart < LineEndBeat) and (LineEndBeat < NoteEnd) then
50845080
begin
5081+
RememberFirstError(TrackIndex, LineIndex, LineEndBeat);
50855082
AppendMsg(Format(Language.Translate('EDIT_INFO_TIMING_LINEBREAK_OVERLAP'),
50865083
[TrackIndex + 1, LineIndex + 1, LineEndBeat,
50875084
NoteIndex + 1, NoteStart, NoteEnd - 1]));
@@ -5093,7 +5090,7 @@ function TScreenEditSub.CheckTimingSyntaxErrors(out ErrorMessages: UTF8String):
50935090

50945091
if Messages <> '' then
50955092
begin
5096-
ErrorMessages := Language.Translate('EDIT_INFO_SYNTAX_ERRORS_TIMING_HEADER') + ' ' + Messages;
5093+
ErrorMessages := Language.Translate('EDIT_INFO_SYNTAX_ERRORS_TIMING_HEADER') + '\n\n' + Messages;
50975094
Result := true;
50985095
end
50995096
else
@@ -5103,6 +5100,114 @@ function TScreenEditSub.CheckTimingSyntaxErrors(out ErrorMessages: UTF8String):
51035100
end;
51045101
end;
51055102

5103+
procedure TScreenEditSub.GoToLineAndBeat(const TrackIndex, LineIndex, Beat: Integer);
5104+
var
5105+
NoteIndex: Integer;
5106+
begin
5107+
if (TrackIndex < 0) or (TrackIndex > High(CurrentSong.Tracks)) then
5108+
Exit;
5109+
if (LineIndex < 0) or (LineIndex > CurrentSong.Tracks[TrackIndex].High) then
5110+
Exit;
5111+
if CurrentSong.Tracks[TrackIndex].Lines[LineIndex].HighNote < 0 then
5112+
Exit;
5113+
5114+
AudioPlayback.Stop;
5115+
PlaySentence := false;
5116+
PlaySentenceMidi := false;
5117+
PlayOne := false;
5118+
PlayVideo := false;
5119+
StopVideoPreview;
5120+
{$IFDEF UseMIDIPort}
5121+
StopMidi;
5122+
{$ENDIF}
5123+
5124+
CurrentSong.Tracks[CurrentTrack].Lines[CurrentSong.Tracks[CurrentTrack].CurrentLine].Notes[CurrentNote[CurrentTrack]].Color := 1;
5125+
CurrentTrack := TrackIndex;
5126+
CurrentSong.Tracks[CurrentTrack].CurrentLine := LineIndex;
5127+
CurrentNote[CurrentTrack] := 0;
5128+
5129+
for NoteIndex := 0 to CurrentSong.Tracks[CurrentTrack].Lines[LineIndex].HighNote do
5130+
begin
5131+
CurrentNote[CurrentTrack] := NoteIndex;
5132+
if CurrentSong.Tracks[CurrentTrack].Lines[LineIndex].Notes[NoteIndex].EndBeat >= Beat then
5133+
Break;
5134+
end;
5135+
5136+
UpdateLineBaseNote(CurrentTrack, CurrentSong.Tracks[CurrentTrack].CurrentLine);
5137+
CurrentSong.Tracks[CurrentTrack].Lines[CurrentSong.Tracks[CurrentTrack].CurrentLine].Notes[CurrentNote[CurrentTrack]].Color := P1_INVERTED;
5138+
EditorLyrics[CurrentTrack].AddLine(CurrentTrack, CurrentSong.Tracks[CurrentTrack].CurrentLine);
5139+
EditorLyrics[CurrentTrack].Selected := CurrentNote[CurrentTrack];
5140+
ShowInteractiveBackground;
5141+
GoldenRec.KillAll;
5142+
Text[TextInfo].Text := Language.Translate('EDIT_INFO_CURRENT_BEAT') + ' ' + IntToStr(Beat);
5143+
end;
5144+
5145+
procedure TScreenEditSub.GoToFirstTimingError;
5146+
begin
5147+
if TimingErrorValid then
5148+
GoToLineAndBeat(TimingErrorTrack, TimingErrorLine, TimingErrorBeat);
5149+
end;
5150+
5151+
function TScreenEditSub.SaveSongToFile(const SaveRelative: boolean): boolean;
5152+
var
5153+
SResult: TSaveSongResult;
5154+
begin
5155+
if CurrentSong.isDuet then
5156+
begin
5157+
CurrentSong.Medley.Source := msNone;
5158+
end
5159+
else if (MedleyNotes.isStart and MedleyNotes.isEnd and MedleyNotes.isCustom) and
5160+
(MedleyNotes.start.line < MedleyNotes.end_.line) and
5161+
(Length(CurrentSong.Tracks[CurrentTrack].Lines) > MedleyNotes.end_.line) and
5162+
(Length(CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.end_.line].Notes) > MedleyNotes.end_.note) and
5163+
(Length(CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.start.line].Notes) > MedleyNotes.start.note) then
5164+
begin
5165+
CurrentSong.Medley.Source := msTag;
5166+
CurrentSong.Medley.StartBeat := CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.start.line].Notes[MedleyNotes.start.note].StartBeat;
5167+
CurrentSong.Medley.EndBeat := CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.end_.line].Notes[MedleyNotes.end_.note].StartBeat +
5168+
CurrentSong.Tracks[CurrentTrack].Lines[MedleyNotes.end_.line].Notes[MedleyNotes.end_.note].Duration;
5169+
CurrentSong.Medley.FadeIn_time := DEFAULT_FADE_IN_TIME;
5170+
CurrentSong.Medley.FadeOut_time := DEFAULT_FADE_OUT_TIME;
5171+
end
5172+
else if MedleyNotes.isCustom then
5173+
begin
5174+
CurrentSong.Medley.Source := msNone;
5175+
CurrentSong.Medley.StartBeat := 0;
5176+
CurrentSong.Medley.EndBeat := 0;
5177+
end;
5178+
5179+
if SaveRelative then
5180+
begin
5181+
if CurrentSong.isDuet then
5182+
begin
5183+
ScreenPopupError.ShowPopup(Language.Translate('EDIT_INFO_DUET_RELATIVE_UNSUPPORTED'));
5184+
Exit(false);
5185+
end;
5186+
5187+
if CurrentSong.Medley.Source = msTag then
5188+
ScreenPopupError.ShowPopup(Language.Translate('EDIT_INFO_MEDLEY_RELATIVE_UNSUPPORTED') + ' ' + Language.Translate('EDIT_INFO_MEDLEY_DELETED'));
5189+
5190+
CurrentSong.Medley.Source := msNone;
5191+
CurrentSong.Relative := true;
5192+
end
5193+
else
5194+
CurrentSong.Relative := false;
5195+
5196+
SResult := SaveSong(CurrentSong, CurrentSong.Tracks, CurrentSong.Path.Append(CurrentSong.FileName), CurrentSong.Relative);
5197+
Result := (SResult = ssrOK);
5198+
5199+
if Result then
5200+
begin
5201+
Text[TextInfo].Text := Language.Translate('INFO_FILE_SAVED');
5202+
SetLength(UndoLines, 0, High(CurrentSong.Tracks));
5203+
SetLength(UndoStateNote, 0, Length(CurrentSong.Tracks));
5204+
SetLength(Undoheader, 0);
5205+
CurrentUndoLines := 0;
5206+
end;
5207+
if not Result then
5208+
ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
5209+
end;
5210+
51065211
constructor TScreenEditSub.Create;
51075212
begin
51085213
inherited Create;
@@ -5112,6 +5217,8 @@ constructor TScreenEditSub.Create;
51125217
fCurrentVideo := nil;
51135218

51145219
ResetBeatTracking;
5220+
PendingSaveRelative := false;
5221+
TimingErrorValid := false;
51155222

51165223
EditorLyrics[0] := TEditorLyrics.Create;
51175224
EditorLyrics[1] := TEditorLyrics.Create;

0 commit comments

Comments
 (0)