aboutsummaryrefslogtreecommitdiffstats
path: root/src/screens/UScreenEditSub.pas
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/screens/UScreenEditSub.pas1809
1 files changed, 1809 insertions, 0 deletions
diff --git a/src/screens/UScreenEditSub.pas b/src/screens/UScreenEditSub.pas
new file mode 100644
index 00000000..fb3f04ce
--- /dev/null
+++ b/src/screens/UScreenEditSub.pas
@@ -0,0 +1,1809 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UScreenEditSub;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+{$I switches.inc}
+
+uses
+ UMenu,
+ UMusic,
+ SDL,
+ SysUtils,
+ UFiles,
+ UTime,
+ USongs,
+ USong,
+ UIni,
+ ULog,
+ UTexture,
+ UMenuText,
+ UEditorLyrics,
+ Math,
+ gl,
+ {$IFDEF UseMIDIPort}
+ MidiOut,
+ MidiCons,
+ {$ENDIF}
+ UThemes;
+
+type
+ TScreenEditSub = class(TMenu)
+ private
+ AktBeat: integer;
+ //Variable is True if no Song is loaded
+ Error: boolean;
+
+ TextNote: integer;
+ TextSentence: integer;
+ TextTitle: integer;
+ TextArtist: integer;
+ TextMp3: integer;
+ TextBPM: integer;
+ TextGAP: integer;
+ TextDebug: integer;
+ TextNStart: integer;
+ TextNLength: integer;
+ TextNTon: integer;
+ TextNText: integer;
+ CurrentNote: integer;
+ PlaySentence: boolean;
+ PlaySentenceMidi: boolean;
+ PlayStopTime: real;
+ LastClick: integer;
+ Click: boolean;
+ CopySrc: integer;
+
+ {$IFDEF UseMIDIPort}
+ MidiOut: TMidiOutput;
+ {$endif}
+
+ MidiStart: real;
+ MidiStop: real;
+ MidiTime: real;
+ MidiPos: real;
+ MidiLastNote: integer;
+
+ TextEditMode: boolean;
+ editText: UTF8String; //backup of current text in text-edit-mode
+
+ Lyric: TEditorLyrics;
+
+ procedure DivideBPM;
+ procedure MultiplyBPM;
+ procedure LyricsCapitalize;
+ procedure LyricsCorrectSpaces;
+ procedure FixTimings;
+ procedure DivideSentence;
+ procedure JoinSentence;
+ procedure DivideNote;
+ procedure DeleteNote;
+ procedure TransposeNote(Transpose: integer);
+ procedure ChangeWholeTone(Tone: integer);
+ procedure MoveAllToEnd(Move: integer);
+ procedure MoveTextToRight;
+ procedure MarkSrc;
+ procedure PasteText;
+ procedure CopySentence(Src, Dst: integer);
+ procedure CopySentences(Src, Dst, Num: integer);
+ procedure DrawStatics;
+ procedure DrawInfoBar(x, y, w, h: integer);
+ //Note Name Mod
+ function GetNoteName(Note: integer): string;
+ public
+ Tex_Background: TTexture;
+ FadeOut: boolean;
+ constructor Create; override;
+ procedure OnShow; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ function ParseInputEditText(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+ function Draw: boolean; override;
+ procedure OnHide; override;
+ end;
+
+implementation
+
+uses
+ UGraphic,
+ UDraw,
+ UNote,
+ USkins,
+ ULanguage,
+ UTextEncoding,
+ UUnicodeUtils,
+ UPath;
+
+
+procedure OnSaveEncodingError(Value: boolean; Data: Pointer);
+var
+ SResult: TSaveSongResult;
+ FilePath: IPath;
+ Success: boolean;
+begin
+ Success := false;
+ if (Value) then
+ begin
+ CurrentSong.Encoding := encUTF8;
+ FilePath := CurrentSong.Path.Append(CurrentSong.FileName);
+ // create backup file
+ FilePath.CopyFile(Path(FilePath.ToUTF8 + '.ansi.bak'), false);
+ // store in UTF-8 encoding
+ SResult := SaveSong(CurrentSong, Lines[0], FilePath,
+ boolean(Data));
+ Success := (SResult = ssrOK);
+ end;
+
+ if (Success) then
+ ScreenPopupInfo.ShowPopup(Language.Translate('INFO_FILE_SAVED'))
+ else
+ ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
+end;
+
+// Method for input parsing. If false is returned, GetNextWindow
+// should be checked to know the next window to load;
+function TScreenEditSub.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+ SDL_ModState: word;
+ R: real;
+ SResult: TSaveSongResult;
+begin
+ Result := true;
+
+ if TextEditMode then
+ begin
+ Result := ParseInputEditText(PressedKey, CharCode, PressedDown);
+ end
+ else
+ begin
+
+ SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT
+ + KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT + KMOD_RALT {+ KMOD_CAPS});
+
+ if (PressedDown) then // Key Down
+ begin
+ // check normal keys
+ case PressedKey of
+ SDLK_Q:
+ begin
+ Result := false;
+ Exit;
+ end;
+ SDLK_S:
+ begin
+ // Save Song
+ SResult := SaveSong(CurrentSong, Lines[0], CurrentSong.Path.Append(CurrentSong.FileName),
+ (SDL_ModState = KMOD_LSHIFT));
+ if (SResult = ssrOK) then
+ begin
+ //ScreenPopupInfo.ShowPopup(Language.Translate('INFO_FILE_SAVED'));
+ Text[TextDebug].Text := Language.Translate('INFO_FILE_SAVED');
+ end
+ else if (SResult = ssrEncodingError) then
+ begin
+ ScreenPopupCheck.ShowPopup(Language.Translate('ENCODING_ERROR_ASK_FOR_UTF8'), OnSaveEncodingError,
+ Pointer(SDL_ModState = KMOD_LSHIFT), true);
+ end
+ else
+ begin
+ ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
+ end;
+ Exit;
+ end;
+
+ SDLK_R: //reload
+ begin
+ AudioPlayback.Stop;
+ {$IFDEF UseMIDIPort}
+ MidiOut.Close;
+ MidiOut.Free;
+ {$ENDIF}
+ Lyric.Free;
+
+ onShow;
+ Text[TextDebug].Text := 'song reloaded'; //TODO: Language.Translate('SONG_RELOADED');
+ end;
+
+ SDLK_D:
+ begin
+ // Divide lengths by 2
+ if (SDL_ModState = KMOD_LSHIFT) then
+ begin
+ DivideBPM;
+ Exit;
+ end;
+ end;
+ SDLK_M:
+ begin
+ // Multiply lengths by 2
+ if (SDL_ModState = KMOD_LSHIFT) then
+ begin
+ MultiplyBPM;
+ Exit;
+ end;
+ end;
+ SDLK_C:
+ begin
+ // Capitalize letter at the beginning of line
+ if SDL_ModState = 0 then
+ LyricsCapitalize;
+
+ // Correct spaces
+ if SDL_ModState = KMOD_LSHIFT then
+ LyricsCorrectSpaces;
+
+ // Copy sentence
+ if SDL_ModState = KMOD_LCTRL then
+ MarkSrc;
+
+ Exit;
+ end;
+ SDLK_V:
+ begin
+ // Paste text
+ if SDL_ModState = KMOD_LCTRL then
+ begin
+ if Lines[0].Line[Lines[0].Current].HighNote >= Lines[0].Line[CopySrc].HighNote then
+ PasteText
+ else
+ Log.LogStatus('PasteText: invalid range', 'TScreenEditSub.ParseInput');
+ end;
+
+ if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then
+ begin
+ CopySentence(CopySrc, Lines[0].Current);
+ end;
+ end;
+ SDLK_T:
+ begin
+ // Fixes timings between sentences
+ FixTimings;
+ Exit;
+ end;
+ SDLK_P:
+ begin
+ if SDL_ModState = 0 then
+ begin
+ // Play Sentence
+ Click := true;
+ AudioPlayback.Stop;
+ R := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start);
+ if R <= AudioPlayback.Length then
+ begin
+ AudioPlayback.Position := R;
+ PlayStopTime := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_);
+ PlaySentence := true;
+ AudioPlayback.Play;
+ LastClick := -100;
+ end;
+ end
+ else if SDL_ModState = KMOD_LSHIFT then
+ begin
+ PlaySentenceMidi := true;
+
+ MidiTime := USTime.GetTime;
+ MidiStart := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start);
+ MidiStop := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_);
+
+ LastClick := -100;
+ end
+ else if SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL then
+ begin
+ PlaySentenceMidi := true;
+ MidiTime := USTime.GetTime;
+ MidiStart := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start);
+ MidiStop := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_);
+ LastClick := -100;
+
+ PlaySentence := true;
+ Click := true;
+ AudioPlayback.Stop;
+ AudioPlayback.Position := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start)+0{-0.10};
+ PlayStopTime := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_)+0;
+ AudioPlayback.Play;
+ LastClick := -100;
+ end;
+ Exit;
+ end;
+
+ // Golden Note
+ SDLK_G:
+ begin
+ if (Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType = ntGolden) then
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntNormal
+ else
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntGolden;
+
+ Exit;
+ end;
+
+ // Freestyle Note
+ SDLK_F:
+ begin
+ if (Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType = ntFreestyle) then
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntNormal
+ else
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntFreestyle;
+
+ // update lyrics
+ Lyric.AddLine(Lines[0].Current);
+ Lyric.Selected := CurrentNote;
+
+ Exit;
+ end;
+ end;
+
+ // check special keys
+ case PressedKey of
+ SDLK_ESCAPE,
+ SDLK_BACKSPACE :
+ begin
+ FadeTo(@ScreenSong);
+ end;
+
+ SDLK_BACKQUOTE:
+ begin
+ // Increase Note Length (same as Alt + Right)
+ Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+ if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+ Inc(Lines[0].Line[Lines[0].Current].End_);
+ end;
+
+ SDLK_EQUALS:
+ begin
+ // Increase BPM
+ if SDL_ModState = 0 then
+ CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 5) + 1) / 5; // (1/20)
+ if SDL_ModState = KMOD_LSHIFT then
+ CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM + 4; // (1/1)
+ if SDL_ModState = KMOD_LCTRL then
+ CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 25) + 1) / 25; // (1/100)
+ end;
+
+ SDLK_MINUS:
+ begin
+ // Decrease BPM
+ if SDL_ModState = 0 then
+ CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 5) - 1) / 5;
+ if SDL_ModState = KMOD_LSHIFT then
+ CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM - 4;
+ if SDL_ModState = KMOD_LCTRL then
+ CurrentSong.BPM[0].BPM := Round((CurrentSong.BPM[0].BPM * 25) - 1) / 25;
+ end;
+
+ SDLK_4:
+ begin
+ if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then
+ begin
+ CopySentence(CopySrc, Lines[0].Current);
+ CopySentence(CopySrc+1, Lines[0].Current+1);
+ CopySentence(CopySrc+2, Lines[0].Current+2);
+ CopySentence(CopySrc+3, Lines[0].Current+3);
+ end;
+
+ if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT + KMOD_LALT then
+ begin
+ CopySentences(CopySrc, Lines[0].Current, 4);
+ end;
+ end;
+ SDLK_5:
+ begin
+ if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then
+ begin
+ CopySentence(CopySrc, Lines[0].Current);
+ CopySentence(CopySrc+1, Lines[0].Current+1);
+ CopySentence(CopySrc+2, Lines[0].Current+2);
+ CopySentence(CopySrc+3, Lines[0].Current+3);
+ CopySentence(CopySrc+4, Lines[0].Current+4);
+ end;
+
+ if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT + KMOD_LALT then
+ begin
+ CopySentences(CopySrc, Lines[0].Current, 5);
+ end;
+ end;
+
+ SDLK_9:
+ begin
+ // Decrease GAP
+ if SDL_ModState = 0 then
+ CurrentSong.GAP := CurrentSong.GAP - 10;
+ if SDL_ModState = KMOD_LSHIFT then
+ CurrentSong.GAP := CurrentSong.GAP - 1000;
+ end;
+ SDLK_0:
+ begin
+ // Increase GAP
+ if SDL_ModState = 0 then
+ CurrentSong.GAP := CurrentSong.GAP + 10;
+ if SDL_ModState = KMOD_LSHIFT then
+ CurrentSong.GAP := CurrentSong.GAP + 1000;
+ end;
+
+ SDLK_KP_PLUS:
+ begin
+ // Increase tone of all notes
+ if SDL_ModState = 0 then
+ ChangeWholeTone(1);
+ if SDL_ModState = KMOD_LSHIFT then
+ ChangeWholeTone(12);
+ end;
+
+ SDLK_KP_MINUS:
+ begin
+ // Decrease tone of all notes
+ if SDL_ModState = 0 then
+ ChangeWholeTone(-1);
+ if SDL_ModState = KMOD_LSHIFT then
+ ChangeWholeTone(-12);
+ end;
+
+ SDLK_SLASH:
+ begin
+ if SDL_ModState = 0 then
+ begin
+ // Insert start of sentece
+ if CurrentNote > 0 then
+ DivideSentence;
+ end;
+
+ if SDL_ModState = KMOD_LSHIFT then
+ begin
+ // Join next sentence with current
+ if Lines[0].Current < Lines[0].High then
+ JoinSentence;
+ end;
+
+ if SDL_ModState = KMOD_LCTRL then
+ begin
+ // divide note
+ DivideNote;
+ end;
+
+ end;
+
+ SDLK_F4:
+ begin
+ // Enter Text Edit Mode
+ editText := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text;
+ TextEditMode := true;
+ end;
+
+ SDLK_SPACE:
+ begin
+ if (SDL_ModState = 0) or (SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL) then
+ begin
+ // Play Sentence
+ PlaySentenceMidi := false; // stop midi
+ PlaySentence := true;
+ Click := false;
+ AudioPlayback.Stop;
+ AudioPlayback.Position := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+ PlayStopTime := (GetTimeFromBeat(
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start +
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length));
+ AudioPlayback.Play;
+ LastClick := -100;
+ end;
+
+ if (SDL_ModState = KMOD_LSHIFT) or (SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL) then
+ begin
+ // Play Midi
+ PlaySentenceMidi := true;
+
+ MidiTime := USTime.GetTime;
+ MidiStart := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+ MidiStop := GetTimeFromBeat(
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start +
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+
+ LastClick := -100;
+ end;
+ end;
+
+ SDLK_RETURN:
+ begin
+ end;
+
+ SDLK_DELETE:
+ begin
+ if SDL_ModState = KMOD_LCTRL then
+ begin
+ // deletes current note
+ DeleteNote;
+ end;
+ end;
+
+ SDLK_PERIOD:
+ begin
+ // moves text to right in current sentence
+ MoveTextToRight;
+ end;
+
+ SDLK_RIGHT:
+ begin
+ // right
+ if SDL_ModState = 0 then
+ begin
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+ Inc(CurrentNote);
+ if CurrentNote > Lines[0].Line[Lines[0].Current].HighNote then
+ CurrentNote := 0;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+ Lyric.Selected := CurrentNote;
+ end;
+
+ // ctrl + right
+ if (SDL_ModState = KMOD_LCTRL) or (SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT) then
+ begin
+ if Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length > 1 then
+ begin
+ Dec(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+ Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+ if CurrentNote = 0 then
+ begin
+ Inc(Lines[0].Line[Lines[0].Current].Start);
+ end;
+ end;
+ end;
+
+ // shift + right
+ if SDL_ModState = KMOD_LSHIFT then
+ begin
+ Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+ if CurrentNote = 0 then
+ begin
+ Inc(Lines[0].Line[Lines[0].Current].Start);
+ end;
+ if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+ Inc(Lines[0].Line[Lines[0].Current].End_);
+ end;
+
+ // alt + right
+ if (SDL_ModState = KMOD_LALT) or (SDL_ModState = KMOD_LALT + KMOD_LSHIFT) then
+ begin
+ Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+ if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+ Inc(Lines[0].Line[Lines[0].Current].End_);
+ end;
+
+ // alt + ctrl + shift + right = move all from cursor to right
+ if SDL_ModState = KMOD_LALT + KMOD_LCTRL + KMOD_LSHIFT then
+ begin
+ MoveAllToEnd(1);
+ end;
+
+ end;
+
+ SDLK_LEFT:
+ begin
+ // left
+ if SDL_ModState = 0 then
+ begin
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+ Dec(CurrentNote);
+ if CurrentNote = -1 then
+ CurrentNote := Lines[0].Line[Lines[0].Current].HighNote;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+ Lyric.Selected := CurrentNote;
+ end;
+
+ // ctrl + left
+ if (SDL_ModState = KMOD_LCTRL) or (SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT) then
+ begin
+ Dec(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+ Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+ if CurrentNote = 0 then
+ begin
+ Dec(Lines[0].Line[Lines[0].Current].Start);
+ end;
+ end;
+
+ // shift + left
+ if SDL_ModState = KMOD_LSHIFT then
+ begin
+ Dec(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+
+ // resizing sentences
+ if CurrentNote = 0 then
+ begin
+ Dec(Lines[0].Line[Lines[0].Current].Start);
+ end;
+
+ if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+ Dec(Lines[0].Line[Lines[0].Current].End_);
+
+ end;
+
+ // alt + left
+ if (SDL_ModState = KMOD_LALT) or (SDL_ModState = KMOD_LALT + KMOD_LSHIFT) then
+ begin
+ if Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length > 1 then
+ begin
+ Dec(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+ if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
+ Dec(Lines[0].Line[Lines[0].Current].End_);
+ end;
+ end;
+
+ // alt + ctrl + shift + right = move all from cursor to left
+ if SDL_ModState = KMOD_LALT + KMOD_LCTRL + KMOD_LSHIFT then
+ begin
+ MoveAllToEnd(-1);
+ end;
+
+ end;
+
+ SDLK_DOWN:
+ begin
+
+ // skip to next sentence
+ if SDL_ModState = 0 then
+ begin
+ {$IFDEF UseMIDIPort}
+ MidiOut.PutShort(MIDI_NOTEOFF or 1,
+ Lines[0].Line[Lines[0].Current].Note[MidiLastNote].Tone + 60,
+ 127);
+ PlaySentenceMidi := false;
+ {$ENDIF}
+
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+ Inc(Lines[0].Current);
+ CurrentNote := 0;
+ if Lines[0].Current > Lines[0].High then
+ Lines[0].Current := 0;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+
+ Lyric.AddLine(Lines[0].Current);
+ Lyric.Selected := 0;
+ AudioPlayback.Stop;
+ PlaySentence := false;
+ end;
+
+ // decrease tone
+ if SDL_ModState = KMOD_LSHIFT then
+ begin
+ TransposeNote(-1);
+ end;
+
+ end;
+
+ SDLK_UP:
+ begin
+
+ // skip to previous sentence
+ if SDL_ModState = 0 then
+ begin
+ {$IFDEF UseMIDIPort}
+ MidiOut.PutShort(MIDI_NOTEOFF or 1,
+ Lines[0].Line[Lines[0].Current].Note[MidiLastNote].Tone + 60,
+ 127);
+ PlaySentenceMidi := false;
+ {$endif}
+
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+ Dec(Lines[0].Current);
+ CurrentNote := 0;
+ if Lines[0].Current = -1 then
+ Lines[0].Current := Lines[0].High;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+
+ Lyric.AddLine(Lines[0].Current);
+ Lyric.Selected := 0;
+ AudioPlayback.Stop;
+ PlaySentence := false;
+ end;
+
+ // increase tone
+ if SDL_ModState = KMOD_LSHIFT then
+ begin
+ TransposeNote(1);
+ end;
+ end;
+
+ end; // case
+ end;
+ end; // if
+end;
+
+function TScreenEditSub.ParseInputEditText(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+ SDL_ModState: word;
+begin
+ // used when in Text Edit Mode
+ Result := true;
+
+ SDL_ModState := SDL_GetModState and (KMOD_LSHIFT + KMOD_RSHIFT
+ + KMOD_LCTRL + KMOD_RCTRL + KMOD_LALT + KMOD_RALT {+ KMOD_CAPS});
+
+ if (PressedDown) then
+ begin
+ // check normal keys
+ if (IsPrintableChar(CharCode)) then
+ begin
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text :=
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text + UCS4ToUTF8String(CharCode);
+
+ Lyric.AddLine(Lines[0].Current);
+ Lyric.Selected := CurrentNote;
+ Exit;
+ end;
+
+ // check special keys
+ case PressedKey of
+ SDLK_ESCAPE:
+ begin
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text := editText;
+ Lyric.AddLine(Lines[0].Current);
+ Lyric.Selected := CurrentNote;
+ TextEditMode := false;
+ end;
+ SDLK_F4, SDLK_RETURN:
+ begin
+ // Exit Text Edit Mode
+ TextEditMode := false;
+ end;
+ SDLK_BACKSPACE:
+ begin
+ UTF8Delete(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text,
+ LengthUTF8(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text), 1);
+ Lyric.AddLine(Lines[0].Current);
+ Lyric.Selected := CurrentNote;
+ end;
+ SDLK_RIGHT:
+ begin
+ // right
+ if SDL_ModState = 0 then
+ begin
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+ Inc(CurrentNote);
+ if CurrentNote > Lines[0].Line[Lines[0].Current].HighNote then
+ CurrentNote := 0;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+ Lyric.Selected := CurrentNote;
+ editText := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text;
+ end;
+ end;
+ SDLK_LEFT:
+ begin
+ // left
+ if SDL_ModState = 0 then
+ begin
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1;
+ Dec(CurrentNote);
+ if CurrentNote = -1 then
+ CurrentNote := Lines[0].Line[Lines[0].Current].HighNote;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+ Lyric.Selected := CurrentNote;
+ editText := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text;
+ end;
+ end;
+ end;
+ end;
+end;
+
+{
+procedure TScreenEditSub.NewBeat;
+begin
+ // click
+ for Pet := 0 to Lines[0].Line[Lines[0].Current].HighNut do
+ if (Lines[0].Line[Lines[0].Current].Note[Pet].Start = Czas.AktBeat) then
+ Music.PlayClick;
+end;
+}
+
+procedure TScreenEditSub.DivideBPM;
+var
+ C: integer;
+ N: integer;
+
+begin
+ CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM / 2;
+
+ for C := 0 to Lines[0].High do
+ begin
+ Lines[0].Line[C].Start := Lines[0].Line[C].Start div 2;
+ Lines[0].Line[C].End_ := Lines[0].Line[C].End_ div 2;
+ for N := 0 to Lines[0].Line[C].HighNote do
+ begin
+ Lines[0].Line[C].Note[N].Start := Lines[0].Line[C].Note[N].Start div 2;
+ Lines[0].Line[C].Note[N].Length := Round(Lines[0].Line[C].Note[N].Length / 2);
+ end; // N
+ end; // C
+end;
+
+procedure TScreenEditSub.MultiplyBPM;
+var
+ C: integer;
+ N: integer;
+begin
+ CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM * 2;
+ for C := 0 to Lines[0].High do
+ begin
+ Lines[0].Line[C].Start := Lines[0].Line[C].Start * 2;
+ Lines[0].Line[C].End_ := Lines[0].Line[C].End_ * 2;
+ for N := 0 to Lines[0].Line[C].HighNote do
+ begin
+ Lines[0].Line[C].Note[N].Start := Lines[0].Line[C].Note[N].Start * 2;
+ Lines[0].Line[C].Note[N].Length := Lines[0].Line[C].Note[N].Length * 2;
+ end; // N
+ end; // C
+end;
+
+procedure TScreenEditSub.LyricsCapitalize;
+var
+ C: integer;
+ //N: integer; // temporary
+ S: string;
+begin
+ // temporary
+ {
+ for C := 0 to Lines[0].High do
+ for N := 0 to Lines[0].Line[C].HighNut do
+ Lines[0].Line[C].Note[N].Text := UTF8LowerCase(Lines[0].Line[C].Note[N].Text);
+ }
+
+ for C := 0 to Lines[0].High do
+ begin
+ S := AnsiUpperCase(Copy(Lines[0].Line[C].Note[0].Text, 1, 1));
+ S := S + Copy(Lines[0].Line[C].Note[0].Text, 2, Length(Lines[0].Line[C].Note[0].Text)-1);
+ Lines[0].Line[C].Note[0].Text := S;
+ end; // C
+end;
+
+procedure TScreenEditSub.LyricsCorrectSpaces;
+var
+ C: integer;
+ N: integer;
+begin
+ for C := 0 to Lines[0].High do
+ begin
+ // correct starting spaces in the first word
+ while Copy(Lines[0].Line[C].Note[0].Text, 1, 1) = ' ' do
+ Lines[0].Line[C].Note[0].Text := Copy(Lines[0].Line[C].Note[0].Text, 2, 100);
+
+ // move spaces on the start to the end of the previous note
+ for N := 1 to Lines[0].Line[C].HighNote do
+ begin
+ while (Copy(Lines[0].Line[C].Note[N].Text, 1, 1) = ' ') do
+ begin
+ Lines[0].Line[C].Note[N].Text := Copy(Lines[0].Line[C].Note[N].Text, 2, 100);
+ Lines[0].Line[C].Note[N-1].Text := Lines[0].Line[C].Note[N-1].Text + ' ';
+ end;
+ end; // N
+
+ // correct '-' to '- '
+ for N := 0 to Lines[0].Line[C].HighNote do
+ begin
+ if Lines[0].Line[C].Note[N].Text = '-' then
+ Lines[0].Line[C].Note[N].Text := '- ';
+ end; // N
+
+ // add space to the previous note when the current word is '- '
+ for N := 1 to Lines[0].Line[C].HighNote do
+ begin
+ if Lines[0].Line[C].Note[N].Text = '- ' then
+ Lines[0].Line[C].Note[N-1].Text := Lines[0].Line[C].Note[N-1].Text + ' ';
+ end; // N
+
+ // correct too many spaces at the end of note
+ for N := 0 to Lines[0].Line[C].HighNote do
+ begin
+ while Copy(Lines[0].Line[C].Note[N].Text, Length(Lines[0].Line[C].Note[N].Text)-1, 2) = ' ' do
+ Lines[0].Line[C].Note[N].Text := Copy(Lines[0].Line[C].Note[N].Text, 1, Length(Lines[0].Line[C].Note[N].Text)-1);
+ end; // N
+
+ // and correct if there is no space at the end of sentence
+ N := Lines[0].Line[C].HighNote;
+ if Copy(Lines[0].Line[C].Note[N].Text, Length(Lines[0].Line[C].Note[N].Text), 1) <> ' ' then
+ Lines[0].Line[C].Note[N].Text := Lines[0].Line[C].Note[N].Text + ' ';
+
+ end; // C
+end;
+
+procedure TScreenEditSub.FixTimings;
+var
+ C: integer;
+ S: integer;
+ Min: integer;
+ Max: integer;
+begin
+ for C := 1 to Lines[0].High do
+ begin
+ with Lines[0].Line[C-1] do
+ begin
+ Min := Note[HighNote].Start + Note[HighNote].Length;
+ Max := Lines[0].Line[C].Note[0].Start;
+ case (Max - Min) of
+ 0: S := Max;
+ 1: S := Max;
+ 2: S := Max - 1;
+ 3: S := Max - 2;
+ else
+ if ((Max - Min) > 4) then
+ S := Min + 2
+ else
+ S := Max;
+ end; // case
+
+ Lines[0].Line[C].Start := S;
+ end; // with
+ end; // for
+end;
+
+procedure TScreenEditSub.DivideSentence;
+var
+ C: integer;
+ CStart: integer;
+ CNew: integer;
+ CLen: integer;
+ N: integer;
+ NStart: integer;
+ NHigh: integer;
+begin
+ // increase sentence length by 1
+ CLen := Length(Lines[0].Line);
+ SetLength(Lines[0].Line, CLen + 1);
+ Inc(Lines[0].Number);
+ Inc(Lines[0].High);
+
+ // move needed sentences to one forward. newly has the copy of divided sentence
+ CStart := Lines[0].Current;
+ for C := CLen-1 downto CStart do
+ Lines[0].Line[C+1] := Lines[0].Line[C];
+
+ // clear and set new sentence
+ CNew := CStart + 1;
+ NStart := CurrentNote;
+ Lines[0].Line[CNew].Start := Lines[0].Line[CStart].Note[NStart].Start;
+ Lines[0].Line[CNew].Lyric := '';
+ Lines[0].Line[CNew].End_ := 0;
+ Lines[0].Line[CNew].BaseNote := 0;//High(integer); // TODO: High (integer) will causes a memory exception later in this procedure. Weird!
+ Lines[0].Line[CNew].HighNote := -1;
+ SetLength(Lines[0].Line[CNew].Note, 0);
+
+ // move right notes to new sentences
+ NHigh := Lines[0].Line[CStart].HighNote;
+ for N := NStart to NHigh do
+ begin
+ // increase sentence counters
+ with Lines[0].Line[CNew] do
+ begin
+ Inc(HighNote);
+ SetLength(Note, HighNote + 1);
+ Note[HighNote] := Lines[0].Line[CStart].Note[N];
+ End_ := Note[HighNote].Start + Note[HighNote].Length;
+
+ if Note[HighNote].Tone < BaseNote then
+ BaseNote := Note[HighNote].Tone;
+ end;
+ end;
+
+ // clear old notes and set sentence counters
+ Lines[0].Line[CStart].HighNote := NStart - 1;
+ Lines[0].Line[CStart].End_ := Lines[0].Line[CStart].Note[NStart-1].Start +
+ Lines[0].Line[CStart].Note[NStart-1].Length;
+ SetLength(Lines[0].Line[CStart].Note, Lines[0].Line[CStart].HighNote + 1);
+
+ //recalculate BaseNote of the divided Sentence
+ with Lines[0].Line[CStart] do
+ begin
+ BaseNote := High(integer);
+
+ for N := 0 to HighNote do
+ if Note[N].Tone < BaseNote then
+ BaseNote := Note[N].Tone;
+ end;
+
+ Lines[0].Current := Lines[0].Current + 1;
+ CurrentNote := 0;
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+ Lyric.AddLine(Lines[0].Current);
+end;
+
+procedure TScreenEditSub.JoinSentence;
+var
+ C: integer;
+ N: integer;
+ NStart: integer;
+ NDst: integer;
+begin
+ C := Lines[0].Current;
+
+ // set new sentence
+ NStart := Lines[0].Line[C].HighNote + 1;
+ Lines[0].Line[C].HighNote := Lines[0].Line[C].HighNote + Lines[0].Line[C+1].HighNote + 1;
+ SetLength(Lines[0].Line[C].Note, Lines[0].Line[C].HighNote + 1);
+
+ // move right notes to new sentences
+ for N := 0 to Lines[0].Line[C+1].HighNote do
+ begin
+ NDst := NStart + N;
+ Lines[0].Line[C].Note[NDst] := Lines[0].Line[C+1].Note[N];
+ end;
+
+ // increase sentence counters
+ NDst := Lines[0].Line[C].HighNote;
+ Lines[0].Line[C].End_ := Lines[0].Line[C].Note[NDst].Start +
+ Lines[0].Line[C].Note[NDst].Length;
+
+ // move needed sentences to one backward.
+ for C := Lines[0].Current + 1 to Lines[0].High - 1 do
+ Lines[0].Line[C] := Lines[0].Line[C+1];
+
+ // increase sentence length by 1
+ SetLength(Lines[0].Line, Length(Lines[0].Line) - 1);
+ Dec(Lines[0].Number);
+ Dec(Lines[0].High);
+end;
+
+procedure TScreenEditSub.DivideNote;
+var
+ C: integer;
+ N: integer;
+begin
+ C := Lines[0].Current;
+
+ with Lines[0].Line[C] do
+ begin
+ Inc(HighNote);
+ SetLength(Note, HighNote + 1);
+
+ // we copy all notes including selected one
+ for N := HighNote downto CurrentNote+1 do
+ begin
+ Note[N] := Note[N-1];
+ end;
+
+ // Note[Cur] and Note[Cur + 1] is identical at this point
+ // modify first note
+ Note[CurrentNote].Length := Note[CurrentNote+1].Length div 2 + Note[CurrentNote+1].Length mod 2;
+
+ // 2nd note
+ Note[CurrentNote+1].Start := Note[CurrentNote].Start + Note[CurrentNote].Length;
+ Note[CurrentNote+1].Length := Note[CurrentNote + 1].Length div 2;
+
+ Note[CurrentNote+1].Text := '~';
+ Note[CurrentNote+1].Color := 1;
+ end;
+
+ // update lyric display
+ Lyric.AddLine(Lines[0].Current);
+ Lyric.Selected := CurrentNote;
+end;
+
+procedure TScreenEditSub.DeleteNote;
+var
+ C: integer;
+ N: integer;
+begin
+ C := Lines[0].Current;
+
+ //Do Not delete Last Note
+ if (Lines[0].Line[C].HighNote > 0) then
+ begin
+ // we copy all notes from the next to the selected one
+ for N := CurrentNote+1 to Lines[0].Line[C].HighNote do
+ begin
+ Lines[0].Line[C].Note[N-1] := Lines[0].Line[C].Note[N];
+ end;
+
+ Dec(Lines[0].Line[C].HighNote);
+
+ SetLength(Lines[0].Line[C].Note, Lines[0].Line[C].HighNote + 1);
+
+ // last note was deleted
+ if (CurrentNote > Lines[0].Line[C].HighNote) then
+ begin
+ // select new last note
+ CurrentNote := Lines[0].Line[C].HighNote;
+
+ // correct Line ending
+ with Lines[0].Line[C] do
+ End_ := Note[HighNote].Start + Note[HighNote].Length;
+ end;
+
+ Lines[0].Line[C].Note[CurrentNote].Color := 2;
+ end
+ // Last Note of current Sentence Deleted - > Delete Sentence
+ // if there are more than two left
+ else if (Lines[0].High > 1) then
+ begin
+ //Move all Sentences after the current to the Left
+ for N := C+1 to Lines[0].High do
+ Lines[0].Line[N-1] := Lines[0].Line[N];
+
+ //Delete Last Sentence
+ SetLength(Lines[0].Line, Lines[0].High);
+ Lines[0].High := High(Lines[0].Line);
+ Lines[0].Number := Length(Lines[0].Line);
+
+ CurrentNote := 0;
+ if (C > 0) then
+ Lines[0].Current := C - 1
+ else
+ Lines[0].Current := 0;
+
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2;
+ end;
+
+ // update lyric display
+ Lyric.AddLine(Lines[0].Current);
+ Lyric.Selected := CurrentNote;
+end;
+
+procedure TScreenEditSub.TransposeNote(Transpose: integer);
+begin
+ Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone, Transpose);
+end;
+
+procedure TScreenEditSub.ChangeWholeTone(Tone: integer);
+var
+ C: integer;
+ N: integer;
+begin
+ for C := 0 to Lines[0].High do
+ begin
+ Lines[0].Line[C].BaseNote := Lines[0].Line[C].BaseNote + Tone;
+ for N := 0 to Lines[0].Line[C].HighNote do
+ Lines[0].Line[C].Note[N].Tone := Lines[0].Line[C].Note[N].Tone + Tone;
+ end;
+end;
+
+procedure TScreenEditSub.MoveAllToEnd(Move: integer);
+var
+ C: integer;
+ N: integer;
+ NStart: integer;
+begin
+ for C := Lines[0].Current to Lines[0].High do
+ begin
+ NStart := 0;
+ if C = Lines[0].Current then
+ NStart := CurrentNote;
+ for N := NStart to Lines[0].Line[C].HighNote do
+ begin
+ Inc(Lines[0].Line[C].Note[N].Start, Move); // move note start
+
+ if N = 0 then
+ begin // fix beginning
+ Inc(Lines[0].Line[C].Start, Move);
+ end;
+
+ if N = Lines[0].Line[C].HighNote then // fix ending
+ Inc(Lines[0].Line[C].End_, Move);
+
+ end; // for
+ end; // for
+end;
+
+procedure TScreenEditSub.MoveTextToRight;
+var
+ C: integer;
+ N: integer;
+ NHigh: integer;
+begin
+ {
+ C := Lines[0].Current;
+
+ for N := Lines[0].Line[C].HighNut downto 1 do
+ begin
+ Lines[0].Line[C].Note[N].Text := Lines[0].Line[C].Note[N-1].Text;
+ end; // for
+
+ Lines[0].Line[C].Note[0].Text := '- ';
+ }
+
+ C := Lines[0].Current;
+ NHigh := Lines[0].Line[C].HighNote;
+
+ // last word
+ Lines[0].Line[C].Note[NHigh].Text := Lines[0].Line[C].Note[NHigh-1].Text + Lines[0].Line[C].Note[NHigh].Text;
+
+ // other words
+ for N := NHigh - 1 downto CurrentNote + 1 do
+ begin
+ Lines[0].Line[C].Note[N].Text := Lines[0].Line[C].Note[N-1].Text;
+ end; // for
+ Lines[0].Line[C].Note[CurrentNote].Text := '- ';
+end;
+
+procedure TScreenEditSub.MarkSrc;
+begin
+ CopySrc := Lines[0].Current;
+end;
+
+procedure TScreenEditSub.PasteText;
+var
+ C: integer;
+ N: integer;
+begin
+ C := Lines[0].Current;
+
+ for N := 0 to Lines[0].Line[CopySrc].HighNote do
+ Lines[0].Line[C].Note[N].Text := Lines[0].Line[CopySrc].Note[N].Text;
+end;
+
+procedure TScreenEditSub.CopySentence(Src, Dst: integer);
+var
+ N: integer;
+ Time1: integer;
+ Time2: integer;
+ TD: integer;
+begin
+ Time1 := Lines[0].Line[Src].Note[0].Start;
+ Time2 := Lines[0].Line[Dst].Note[0].Start;
+ TD := Time2-Time1;
+
+ SetLength(Lines[0].Line[Dst].Note, Lines[0].Line[Src].HighNote + 1);
+ Lines[0].Line[Dst].HighNote := Lines[0].Line[Src].HighNote;
+ for N := 0 to Lines[0].Line[Src].HighNote do
+ begin
+ Lines[0].Line[Dst].Note[N].Text := Lines[0].Line[Src].Note[N].Text;
+ Lines[0].Line[Dst].Note[N].Length := Lines[0].Line[Src].Note[N].Length;
+ Lines[0].Line[Dst].Note[N].Tone := Lines[0].Line[Src].Note[N].Tone;
+ Lines[0].Line[Dst].Note[N].Start := Lines[0].Line[Src].Note[N].Start + TD;
+ end;
+ N := Lines[0].Line[Src].HighNote;
+ Lines[0].Line[Dst].End_ := Lines[0].Line[Dst].Note[N].Start + Lines[0].Line[Dst].Note[N].Length;
+end;
+
+procedure TScreenEditSub.CopySentences(Src, Dst, Num: integer);
+var
+ C: integer;
+begin
+ // create place for new sentences
+ SetLength(Lines[0].Line, Lines[0].Number + Num - 1);
+
+ // moves sentences next to the destination
+ for C := Lines[0].High downto Dst + 1 do
+ begin
+ Lines[0].Line[C + Num - 1] := Lines[0].Line[C];
+ end;
+
+ // prepares new sentences: sets sentence start and create first note
+ for C := 1 to Num-1 do
+ begin
+ Lines[0].Line[Dst + C].Start := Lines[0].Line[Dst + C - 1].Note[0].Start +
+ (Lines[0].Line[Src + C].Note[0].Start - Lines[0].Line[Src + C - 1].Note[0].Start);
+ SetLength(Lines[0].Line[Dst + C].Note, 1);
+ Lines[0].Line[Dst + C].HighNote := 0;
+ Lines[0].Line[Dst + C].Note[0].Start := Lines[0].Line[Dst + C].Start;
+ Lines[0].Line[Dst + C].Note[0].Length := 1;
+ Lines[0].Line[Dst + C].End_ := Lines[0].Line[Dst + C].Start + 1;
+ end;
+
+ // increase counters
+ Lines[0].Number := Lines[0].Number + Num - 1;
+ Lines[0].High := Lines[0].High + Num - 1;
+
+ for C := 0 to Num-1 do
+ CopySentence(Src + C, Dst + C);
+end;
+
+procedure TScreenEditSub.DrawStatics;
+var
+ x, y, w, h: Integer;
+begin
+ //Theme:
+ //bg
+ glDisable(GL_BLEND);
+
+ x := 0;
+ y := 0;
+ w := 800;
+ h := 600;
+ glColor4f(0.3, 0.5, 0.6, 1);
+ glbegin(gl_quads);
+ glVertex2f(x, y);
+ glVertex2f(x, y+h);
+ glVertex2f(x+w, y+h);
+ glVertex2f(x+w, y);
+ glEnd;
+
+ // Line
+ glColor4f(0.9, 0.9, 0.9, 1);
+ x := 20;
+ y := 5;
+ w := 200;
+ h := 40;
+ glbegin(gl_quads);
+ glVertex2f(x, y);
+ glVertex2f(x, y+h);
+ glVertex2f(x+w, y+h);
+ glVertex2f(x+w, y);
+ glEnd;
+
+ // Note
+ x := 260;
+ y := 5;
+ w := 200;
+ h := 40;
+ glbegin(gl_quads);
+ glVertex2f(x, y);
+ glVertex2f(x, y+h);
+ glVertex2f(x+w, y+h);
+ glVertex2f(x+w, y);
+ glEnd;
+
+ // some borders
+ x := 20;
+ y := 55;
+ w := 760;
+ h := 236;
+ glColor4f(0.9, 0.9, 0.9, 1);
+ glbegin(gl_quads);
+ glVertex2f(x, y);
+ glVertex2f(x, y+h);
+ glVertex2f(x+w, y+h);
+ glVertex2f(x+w, y);
+ glEnd;
+
+ glColor4f(0, 0, 0, 1);
+ glLineWidth(2);
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(x-1, y-1);
+ glVertex2f(x+w+1, y-1);
+ glVertex2f(x+w+1, y+h+1);
+ glVertex2f(x-1, y+h+1);
+ glEnd;
+
+ x := 20;
+ y := 305;
+ w := 760;
+ h := 135;
+ glColor4f(0.9, 0.9, 0.9, 1);
+ glbegin(gl_quads);
+ glVertex2f(x, y);
+ glVertex2f(x, y+h);
+ glVertex2f(x+w, y+h);
+ glVertex2f(x+w, y);
+ glEnd;
+
+ glColor4f(0, 0, 0, 1);
+ glLineWidth(2);
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(x-1, y-1);
+ glVertex2f(x+w+1, y-1);
+ glVertex2f(x+w+1, y+h+1);
+ glVertex2f(x-1, y+h+1);
+ glEnd;
+
+ x := 20;
+ y := 500;
+ w := 760;
+ h := 40;
+ glColor4f(0.9, 0.9, 0.9, 1);
+ glbegin(gl_quads);
+ glVertex2f(x, y);
+ glVertex2f(x, y+h);
+ glVertex2f(x+w, y+h);
+ glVertex2f(x+w, y);
+ glEnd;
+
+ glColor4f(0, 0, 0, 1);
+ glLineWidth(2);
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(x-1, y-1);
+ glVertex2f(x+w+1, y-1);
+ glVertex2f(x+w+1, y+h+1);
+ glVertex2f(x-1, y+h+1);
+ glEnd;
+
+ glLineWidth(1);
+end;
+
+procedure TScreenEditSub.DrawInfoBar(x, y, w, h: integer);
+var
+ start, end_: integer;
+ SongStart, SongEnd: integer;
+ ww: integer;
+
+ pos: real;
+ br: real;
+
+ line, note: integer;
+ numLines, numNotes: integer;
+
+begin
+ numLines := Length(Lines[0].Line);
+
+ if(numLines=0) then
+ Exit;
+
+ SongStart := Lines[0].Line[0].Note[0].Start;
+ SongEnd := Lines[0].Line[numLines-1].End_;
+ ww := SongEnd - SongStart;
+
+ glColor4f(0, 0, 0, 1);
+ glDisable(GL_BLEND);
+ glLineWidth(2);
+ glBegin(GL_LINE_LOOP);
+ glVertex2f(x-1, y-1);
+ glVertex2f(x+w+1, y-1);
+ glVertex2f(x+w+1, y+h+1);
+ glVertex2f(x-1, y+h+1);
+ glEnd;
+
+ glColor4f(0.9, 0.9, 0.9, 1);
+ glbegin(gl_quads);
+ glVertex2f(x, y);
+ glVertex2f(x, y+h);
+ glVertex2f(x+w, y+h);
+ glVertex2f(x+w, y);
+ glEnd;
+
+
+ for line := 0 to numLines - 1 do
+ begin
+ if (line = Lines[0].Current) and not (PlaySentence or PlaySentenceMidi) then
+ glColor4f(0.4, 0.4, 0, 1)
+ else
+ glColor4f(1, 0.6, 0, 1);
+
+
+ start := Lines[0].Line[line].Note[0].Start;
+ end_ := Lines[0].Line[line].Note[Lines[0].Line[line].HighNote].Start+
+ Lines[0].Line[line].Note[Lines[0].Line[line].HighNote].Length;
+
+ pos := (start - SongStart)/ww*w;
+ br := (end_-start)/ww*w;
+
+ glbegin(gl_quads);
+ glVertex2f(x+pos, y);
+ glVertex2f(x+pos, y+h);
+ glVertex2f(x+pos+br, y+h);
+ glVertex2f(x+pos+br, y);
+ glEnd;
+ end;
+
+ if(PlaySentence or PlaySentenceMidi) then
+ begin
+ glColor4f(0, 0, 0, 0.5);
+ pos := 0;
+ br := (AktBeat - SongStart)/ww*w;
+ if (br>w) then
+ br := w;
+ end else
+ begin
+ glColor4f(1, 0, 0, 1);
+ pos := (Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start - SongStart)/ww*w;
+ br := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length/ww*w;
+ if (br<1) then
+ br := 1;
+ end;
+
+ glEnable(GL_BLEND);
+ glbegin(gl_quads);
+ glVertex2f(x+pos, y);
+ glVertex2f(x+pos, y+h);
+ glVertex2f(x+pos+br, y+h);
+ glVertex2f(x+pos+br, y);
+ glEnd;
+ glDisable(GL_BLEND);
+
+ glLineWidth(1);
+end;
+
+constructor TScreenEditSub.Create;
+begin
+ inherited Create;
+ SetLength(Player, 1);
+
+ // line
+ AddText(40, 11, 1, 30, 0, 0, 0, 'Line:');
+ TextSentence := AddText(110, 11, 1, 30, 0, 0, 0, '0 / 0');
+
+
+ // Note
+ AddText(282, 11, 1, 30, 0, 0, 0, 'Note:');
+ TextNote := AddText(360, 11, 1, 30, 0, 0, 0, '0 / 0');
+
+ // file info
+ AddText(30, 65, 0, 24, 0, 0, 0, 'Title:');
+ AddText(30, 90, 0, 24, 0, 0, 0, 'Artist:');
+ AddText(30, 115, 0, 24, 0, 0, 0, 'Mp3:');
+ AddText(30, 140, 0, 24, 0, 0, 0, 'BPM:');
+ AddText(30, 165, 0, 24, 0, 0, 0, 'GAP:');
+
+ TextTitle := AddText(180, 65, 0, 24, 0, 0, 0, 'a');
+ TextArtist := AddText(180, 90, 0, 24, 0, 0, 0, 'b');
+ TextMp3 := AddText(180, 115, 0, 24, 0, 0, 0, 'c');
+ TextBPM := AddText(180, 140, 0, 24, 0, 0, 0, 'd');
+ TextGAP := AddText(180, 165, 0, 24, 0, 0, 0, 'e');
+
+ // note info
+ AddText(30, 190, 0, 24, 0, 0, 0, 'Start:');
+ AddText(30, 215, 0, 24, 0, 0, 0, 'Duration:');
+ AddText(30, 240, 0, 24, 0, 0, 0, 'Tone:');
+ AddText(30, 265, 0, 24, 0, 0, 0, 'Text:'); //AddText(500, 265, 0, 8, 0, 0, 0, 'VideoGap:');
+
+ TextNStart := AddText(180, 190, 0, 24, 0, 0, 0, 'a');
+ TextNLength := AddText(180, 215, 0, 24, 0, 0, 0, 'b');
+ TextNTon := AddText(180, 240, 0, 24, 0, 0, 0, 'c');
+ TextNText := AddText(180, 265, 0, 24, 0, 0, 0, 'd');
+
+ //TextVideoGap := AddText(600, 265, 0, 24, 0, 0, 0, 'e');
+
+ // debug
+ TextDebug := AddText(30, 550, 0, 27, 0, 0, 0, '');
+
+end;
+
+procedure TScreenEditSub.OnShow;
+var
+ FileExt: IPath;
+begin
+ inherited;
+
+ AudioPlayback.Stop;
+ PlaySentence := false;
+ PlaySentenceMidi := false;
+
+ Log.LogStatus('Initializing', 'TEditScreen.OnShow');
+ Lyric := TEditorLyrics.Create;
+
+ ResetSingTemp;
+
+ try
+ //Check if File is XML
+ FileExt := CurrentSong.FileName.GetExtension;
+ if FileExt.ToUTF8 = '.xml' then
+ Error := not CurrentSong.LoadXMLSong()
+ else
+ begin
+ // reread header with custom tags
+ Error := not CurrentSong.Analyse(true);
+ if not Error then
+ Error := not CurrentSong.LoadSong;
+ end;
+ except
+ Error := true;
+ end;
+
+ if Error then
+ begin
+ //Error Loading Song -> Go back to Song Screen and Show some Error Message
+ FadeTo(@ScreenSong);
+ ScreenPopupError.ShowPopup (Language.Translate('ERROR_CORRUPT_SONG'));
+ Exit;
+ end
+ else
+ begin
+ {$IFDEF UseMIDIPort}
+ MidiOut := TMidiOutput.Create(nil);
+ MidiOut.Open;
+ {$ENDIF}
+ Text[TextTitle].Text := CurrentSong.Title;
+ Text[TextArtist].Text := CurrentSong.Artist;
+ Text[TextMp3].Text := CurrentSong.Mp3.ToUTF8;
+
+ Lines[0].Current := 0;
+ CurrentNote := 0;
+ Lines[0].Line[0].Note[0].Color := 2;
+ AudioPlayback.Open(CurrentSong.Path.Append(CurrentSong.Mp3));
+ //Set Down Music Volume for Better hearability of Midi Sounds
+ //Music.SetVolume(0.4);
+
+ Lyric.Clear;
+ Lyric.X := 400;
+ Lyric.Y := 500;
+ Lyric.Align := atCenter;
+ Lyric.Size := 42;
+ Lyric.ColR := 0;
+ Lyric.ColG := 0;
+ Lyric.ColB := 0;
+ Lyric.ColSR := Skin_FontHighlightR;
+ Lyric.ColSG := Skin_FontHighlightG;
+ Lyric.ColSB := Skin_FontHighlightB;
+ Lyric.AddLine(0);
+ Lyric.Selected := 0;
+
+ NotesH := 7;
+ NotesW := 4;
+
+ end;
+
+ //Interaction := 0;
+ TextEditMode := false;
+end;
+
+function TScreenEditSub.Draw: boolean;
+var
+ Pet: integer;
+begin
+
+ glClearColor(1,1,1,1);
+
+ // midi music
+ if PlaySentenceMidi then
+ begin
+ {$IFDEF UseMIDIPort}
+ MidiPos := USTime.GetTime - MidiTime + MidiStart;
+
+ // stop the music
+ if (MidiPos > MidiStop) then
+ begin
+ MidiOut.PutShort(MIDI_NOTEOFF or 1,
+ Lines[0].Line[Lines[0].Current].Note[MidiLastNote].Tone + 60,
+ 127);
+ PlaySentenceMidi := false;
+ end;
+ {$ENDIF}
+
+ // click
+ AktBeat := Floor(GetMidBeat(MidiPos - CurrentSong.GAP / 1000));
+ Text[TextDebug].Text := IntToStr(AktBeat);
+
+ if AktBeat <> LastClick then
+ begin
+ for Pet := 0 to Lines[0].Line[Lines[0].Current].HighNote do
+ if (Lines[0].Line[Lines[0].Current].Note[Pet].Start = AktBeat) then
+ begin
+
+ LastClick := AktBeat;
+ {$IFDEF UseMIDIPort}
+ if Pet > 0 then
+ begin
+ MidiOut.PutShort(MIDI_NOTEOFF or 1,
+ Lines[0].Line[Lines[0].Current].Note[Pet-1].Tone + 60,
+ 127);
+ end;
+ MidiOut.PutShort(MIDI_NOTEON or 1,
+ Lines[0].Line[Lines[0].Current].Note[Pet].Tone + 60,
+ 127);
+ MidiLastNote := Pet;
+ {$ENDIF}
+
+ end;
+ end;
+ end; // if PlaySentenceMidi
+
+ // mp3 music
+ if PlaySentence then
+ begin
+ // stop the music
+ if (AudioPlayback.Position > PlayStopTime) then
+ begin
+ AudioPlayback.Stop;
+ PlaySentence := false;
+ end;
+
+ // click
+ if (Click) and (PlaySentence) then
+ begin
+ //AktBeat := Floor(CurrentSong.BPM[0].BPM * (Music.Position - CurrentSong.GAP / 1000) / 60);
+ AktBeat := Floor(GetMidBeat(AudioPlayback.Position - CurrentSong.GAP / 1000));
+ Text[TextDebug].Text := IntToStr(AktBeat);
+ if AktBeat <> LastClick then
+ begin
+ for Pet := 0 to Lines[0].Line[Lines[0].Current].HighNote do
+ if (Lines[0].Line[Lines[0].Current].Note[Pet].Start = AktBeat) then
+ begin
+ AudioPlayback.PlaySound( SoundLib.Click );
+ LastClick := AktBeat;
+ end;
+ end;
+ end; // click
+ end; // if PlaySentence
+
+
+ Text[TextSentence].Text := IntToStr(Lines[0].Current + 1) + ' / ' + IntToStr(Lines[0].Number);
+ Text[TextNote].Text := IntToStr(CurrentNote + 1) + ' / ' + IntToStr(Lines[0].Line[Lines[0].Current].HighNote + 1);
+
+ // Song info
+ Text[TextBPM].Text := FloatToStr(CurrentSong.BPM[0].BPM / 4);
+ Text[TextGAP].Text := FloatToStr(CurrentSong.GAP);
+
+ //Error reading Variables when no Song is loaded
+ if not Error then
+ begin
+ // Note info
+ Text[TextNStart].Text := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
+ Text[TextNLength].Text := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
+ Text[TextNTon].Text := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone) + ' ( ' + GetNoteName(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone) + ' )';
+ Text[TextNText].Text := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text;
+ end;
+
+ // Text Edit Mode
+ if TextEditMode then
+ Text[TextNText].Text := Text[TextNText].Text + '|';
+
+ // draw static menu
+ DrawStatics;
+ DrawInfoBar(20, 460, 760, 20);
+ //inherited Draw;
+ DrawFG;
+ // draw notes
+ SingDrawNoteLines(20, 305, 780, 15);
+ //Error Drawing when no Song is loaded
+ if not Error then
+ begin
+ SingDrawBeatDelimeters(40, 305, 760, 0);
+ EditDrawLine(40, 410, 760, 0, 15);
+ end;
+
+ // draw text
+ Lyric.Draw;
+
+ Result := true;
+end;
+
+procedure TScreenEditSub.OnHide;
+begin
+ {$IFDEF UseMIDIPort}
+ MidiOut.Close;
+ MidiOut.Free;
+ {$ENDIF}
+ Lyric.Free;
+ //Music.SetVolume(1.0);
+end;
+
+function TScreenEditSub.GetNoteName(Note: integer): string;
+var
+ N1, N2: integer;
+begin
+ if (Note > 0) then
+ begin
+ N1 := Note mod 12;
+ N2 := Note div 12;
+ end
+ else
+ begin
+ N1 := (Note + (-Trunc(Note/12)+1)*12) mod 12;
+ N2 := -1;
+ end;
+
+ case N1 of
+ 0: Result := 'c';
+ 1: Result := 'c#';
+ 2: Result := 'd';
+ 3: Result := 'd#';
+ 4: Result := 'e';
+ 5: Result := 'f';
+ 6: Result := 'f#';
+ 7: Result := 'g';
+ 8: Result := 'g#';
+ 9: Result := 'a';
+ 10: Result := 'b';
+ 11: Result := 'h';
+ end;
+
+ case N2 of
+ 0: Result := UpperCase(Result); //Normal Uppercase Note, 1: Normal lowercase Note
+ 2: Result := Result + ''''; //One Striped
+ 3: Result := Result + ''''''; //Two Striped
+ 4: Result := Result + ''''''''; //etc.
+ 5: Result := Result + '''''''''';
+ 6: Result := Result + '''''''''''';
+ 7: Result := Result + '''''''''''''';
+ end;
+end;
+
+end. \ No newline at end of file