{* 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, UGraphicClasses, UTime, USongs, USong, UIni, ULog, UTexture, UMenuText, URecord, UEditorLyrics, UFilesystem, Math, gl, {$IFDEF UseMIDIPort} MidiOut, MidiCons, {$ENDIF} UThemes, UPath; type TVisibleHeaders = record Title: UTF8String; Artist: UTF8String; CoverId: Integer; BackgroundId: Integer; Mp3Id: Integer; GAP: Real; Video: IPath; VideoGAP: real; BPM: array of TBPM; end; 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; PlayVideo: boolean; PlayStopTime: real; LastClick: integer; Click: boolean; CopySrc: integer; {$IFDEF UseMIDIPort} MidiOut: TMidiOutput; {$endif} MidiStart: real; MidiStop: real; MidiTime: real; MidiPos: real; MidiLastNote: integer; TextPosition: integer; TextEditMode: boolean; TitleEditMode: boolean; ArtistEditMode: boolean; BackupEditText: UTF8String; //backup of current text in text-edit-mode CurrentEditText: UTF8String; // current edit text editLenghtText: integer; CurrentSlideId: integer; //title header TitleSlideId: integer; TitleData: integer; TitleVal: array of UTF8String; SlideTitleIndex: integer; // artist header ArtistSlideId: integer; ArtistData: integer; ArtistVal: array of UTF8String; SlideArtistIndex: integer; // mp3 header MP3SlideId: integer; MP3Data: integer; MP3Val: array of UTF8String; SlideMP3Index: integer; // Cover header CoverSlideId: integer; CoverData: integer; CoverVal: array of UTF8String; SlideCoverIndex: integer; // Background header BackgroundSlideId: integer; BackgroundData: integer; BackgroundVal: array of UTF8String; SlideBackgroundIndex: integer; // BPM header BPMSlideId: integer; BPMData: integer; BPMVal: array of UTF8String; SlideBPMIndex: integer; // GAP header GAPSlideId: integer; GAPData: integer; GAPVal: array of UTF8String; SlideGAPIndex: integer; // Start header StartSlideId: integer; StartData: integer; StartVal: array of UTF8String; SlideStartIndex: integer; // Duration header DurationSlideId: integer; DurationData: integer; DurationVal: array of UTF8String; SlideDurationIndex: integer; // Tone header ToneSlideId: integer; ToneData: integer; ToneVal: array of UTF8String; SlideToneIndex: integer; // Text header LyricSlideId: integer; LyricData: integer; LyricVal: array of UTF8String; SlideLyricIndex: integer; // VideoGap header VideoGapSlideId: integer; VideoGapData: integer; VideoGapVal: array of UTF8String; SlideVideoGapIndex: integer; // Volume Slide VolumeAudioSlideId: integer; VolumeMidiSlideId: integer; VolumeClickSlideId: integer; VolumeAudioIndex,VolumeMidiIndex,VolumeClickIndex: integer; //for update slide VolumeAudio: array of UTF8String; VolumeMidi: array of UTF8String; VolumeClick: array of UTF8String; // background image & video preview BackgroundImageId: integer; // currentX, CurrentY CurrentX: integer; CurrentY: integer; Lyric: TEditorLyrics; //undo declaration UndoLines: array of TLines; UndoStateNote: array of integer; //UNDO: note's position CurrentUndoLines: integer; UndoHeader: array of TVisibleHeaders; //video view fCurrentVideo: IVideo; //singtrack CurrentSound: TCaptureBuffer; // Interactive note InteractiveNoteId: array of integer; 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 CopyToUndo; //copy current Lines,mouse position and headers procedure CopyFromUndo; //undo last Lines,mouse position and headers procedure DrawPlayerTrack(X, Y, W: real; Space: integer; CurrentTone: integer; Count: integer; CurrentNote: integer); procedure DrawStatics; procedure DrawInfoBar(x, y, w, h: integer); procedure DrawText(Left, Top, Right: real; NrLines: integer; Space: integer); //video view procedure StartVideoPreview(); procedure StopVideoPreview(); //Note Name Mod function GetNoteName(Note: integer): string; // show transparent background note for intaractions procedure ShowInteractiveBackground; public Tex_PrevBackground: 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 ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; override; function Draw: boolean; override; procedure OnHide; override; end; implementation uses UGraphic, UDraw, UMenuInteract, UNote, USkins, ULanguage, TextGL, UTextEncoding, UUnicodeUtils; 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; i: integer; begin Result := true; if TextEditMode or TitleEditMode or ArtistEditMode 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'); SetLength(UndoLines, 0); //clear undo lines SetLength(UndoStateNote, 0); //clear undo currentnote state SetLength(Undoheader, 0); //clear undo headrers CurrentUndoLines := 0; 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 CopyToUndo; DivideBPM; ShowInteractiveBackground; Exit; end; end; SDLK_M: begin // Multiply lengths by 2 if (SDL_ModState = KMOD_LSHIFT) then begin CopyToUndo; MultiplyBPM; ShowInteractiveBackground; Exit; end; end; SDLK_C: begin // Capitalize letter at the beginning of line if SDL_ModState = 0 then begin CopyToUndo; LyricsCapitalize; Lyric.AddLine(Lines[0].Current); Lyric.Selected := CurrentNote; end; // Correct spaces if SDL_ModState = KMOD_LSHIFT then begin CopyToUndo; LyricsCorrectSpaces; end; // Copy sentence if SDL_ModState = KMOD_LCTRL then MarkSrc; Exit; end; SDLK_V: begin if SDL_ModState = 0 then begin AudioPlayback.Stop; Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1; CurrentNote := 0; AudioPlayback.Position := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start); PlayStopTime := GetTimeFromBeat(Lines[0].Line[Lines[0].High].End_); PlaySentence := true; AudioPlayback.SetVolume(SelectsS[VolumeAudioSlideId].SelectedOption / 100); AudioPlayback.Play; LastClick := -100; PlayVideo := true; StartVideoPreview(); end; // 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 CopyToUndo; CopySentence(CopySrc, Lines[0].Current); end; GoldenRec.KillAll; ShowInteractiveBackground; end; SDLK_T: begin // Fixes timings between sentences CopyToUndo; FixTimings; Exit; end; SDLK_P: begin if SDL_ModState = 0 then begin // Play Sentence Click := true; AudioPlayback.Stop; PlayVideo := false; StopVideoPreview; Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1; CurrentNote := 0; 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.SetVolume(SelectsS[VolumeAudioSlideId].SelectedOption / 100); AudioPlayback.Play; LastClick := -100; end; end else if SDL_ModState = KMOD_LSHIFT then begin Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1; CurrentNote := 0; PlaySentenceMidi := true; PlayVideo := false; StopVideoPreview; 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 Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1; CurrentNote := 0; PlaySentenceMidi := true; PlayVideo := false; StopVideoPreview; 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.SetVolume(SelectsS[VolumeAudioSlideId].SelectedOption / 100); AudioPlayback.Play; LastClick := -100; end; Exit; end; // Golden Note SDLK_G: begin CopyToUndo; 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; GoldenRec.KillAll; Exit; end; // Freestyle Note SDLK_F: begin CopyToUndo; 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; GoldenRec.KillAll; // update lyrics Lyric.AddLine(Lines[0].Current); Lyric.Selected := CurrentNote; Exit; end; SDLK_Z: begin if SDL_ModState = KMOD_LCTRL then begin CopyFromUndo; GoldenRec.KillAll; end; ShowInteractiveBackground; end; end; // check special keys case PressedKey of SDLK_ESCAPE : // SDLK_BACKSPACE : // disable to leave editor by backspace key begin if length(UndoLines) > 0 then ScreenPopupcheck.CheckFadeTo(@ScreenSong,'Do you want leave editor without save ?') else FadeTo(@ScreenSong); end; SDLK_BACKQUOTE: begin // Increase Note Length (same as Alt + Right) CopyToUndo; 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_); GoldenRec.KillAll; ShowInteractiveBackground; end; SDLK_EQUALS: begin // Increase BPM CopyToUndo; 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 CopyToUndo; 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 CopyToUndo; 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); GoldenRec.KillAll; end; if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT + KMOD_LALT then begin CopyToUndo; CopySentences(CopySrc, Lines[0].Current, 4); GoldenRec.KillAll; end; ShowInteractiveBackground; end; SDLK_5: begin if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then begin CopyToUndo; 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); GoldenRec.KillAll; end; if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT + KMOD_LALT then begin CopyToUndo; CopySentences(CopySrc, Lines[0].Current, 5); GoldenRec.KillAll; end; ShowInteractiveBackground; end; SDLK_7: begin if SDL_ModState = 0 then CurrentSong.VideoGAP := (round(CurrentSong.VideoGAP*100) - 1 )/100; if SDL_ModState = KMOD_LSHIFT then CurrentSong.VideoGAP := (round(CurrentSong.VideoGAP*100) - 10 )/100; if SDL_ModState = KMOD_LCTRL then CurrentSong.VideoGAP := (round(CurrentSong.VideoGAP*100) - 100 )/100; end; SDLK_8: begin if SDL_ModState = 0 then CurrentSong.VideoGAP := (round(CurrentSong.VideoGAP*100) + 1 )/100; if SDL_ModState = KMOD_LSHIFT then CurrentSong.VideoGAP := (round(CurrentSong.VideoGAP*100) + 10 )/100; if SDL_ModState = KMOD_LCTRL then CurrentSong.VideoGAP := (round(CurrentSong.VideoGAP*100) + 100 )/100; end; SDLK_9: begin // Decrease GAP CopyToUndo; 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 CopyToUndo; 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 CopyToUndo; if SDL_ModState = 0 then ChangeWholeTone(1); if SDL_ModState = KMOD_LSHIFT then ChangeWholeTone(12); GoldenRec.KillAll; ShowInteractiveBackground; end; SDLK_KP_MINUS: begin // Decrease tone of all notes CopyToUndo; if SDL_ModState = 0 then ChangeWholeTone(-1); if SDL_ModState = KMOD_LSHIFT then ChangeWholeTone(-12); GoldenRec.KillAll; ShowInteractiveBackground; end; SDLK_SLASH: begin CopyToUndo; if SDL_ModState = 0 then begin // Insert start of sentece if CurrentNote > 0 then DivideSentence; GoldenRec.KillAll; end; if SDL_ModState = KMOD_LSHIFT then begin // Join next sentence with current if Lines[0].Current < Lines[0].High then JoinSentence; GoldenRec.KillAll; end; if SDL_ModState = KMOD_LCTRL then begin // divide note DivideNote; Lyric.AddLine(Lines[0].Current); Lyric.Selected := CurrentNote; GoldenRec.KillAll; end; ShowInteractiveBackground; end; SDLK_F4: begin // Enter Text Edit Mode BackupEditText := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text; CurrentEditText := BackupEditText; CurrentSlideId := LyricSlideId; TextPosition := LengthUTF8(BackupEditText); editLenghtText := LengthUTF8(BackupEditText); 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; PlayVideo := false; StopVideoPreview; 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.SetVolume(SelectsS[VolumeAudioSlideId].SelectedOption / 100); 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 if Interaction = TitleSlideId then begin BackupEditText := CurrentSong.Title; CurrentEditText := BackupEditText; editLenghtText := LengthUTF8(BackupEditText); CurrentSlideId := TitleSlideId; TextPosition := LengthUTF8(BackupEditText); TitleEditMode := true; end; if Interaction = ArtistSlideId then begin BackupEditText := CurrentSong.Artist; CurrentEditText := BackupEditText; editLenghtText := LengthUTF8(BackupEditText); CurrentSlideId := ArtistSlideId; TextPosition := LengthUTF8(BackupEditText); ArtistEditMode := true; end; if Interaction = LyricSlideId then begin BackupEditText := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text; CurrentEditText := BackupEditText; editLenghtText := LengthUTF8(BackupEditText); CurrentSlideId := LyricSlideId; TextPosition := LengthUTF8(BackupEditText); TextEditMode := true; end; if high(InteractiveNoteId) >= Lines[0].Line[Lines[0].Current].HighNote then for i := 0 to Lines[0].Line[Lines[0].Current].HighNote do begin if Interaction = InteractiveNoteId[i] then begin Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1; currentnote := i; Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2; Lyric.Selected := CurrentNote; //play curren note 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.SetVolume(SelectsS[VolumeAudioSlideId].SelectedOption / 100); AudioPlayback.Play; end; end; end; SDLK_DELETE: begin if SDL_ModState = KMOD_LCTRL then begin // deletes current note CopyToUndo; DeleteNote; GoldenRec.KillAll; ShowInteractiveBackground; end; end; SDLK_PERIOD: begin // moves text to right in current sentence CopyToUndo; MoveTextToRight; end; SDLK_RIGHT: begin // right CopyToUndo; if SDL_ModState = 0 then begin AudioPlayback.Stop; PlaySentence := false; PlayVideo := false; {$IFDEF UseMIDIPort} MidiOut.PutShort($B1, $7, floor(1.27*SelectsS[VolumeMidiSlideId].SelectedOption)); MidiOut.PutShort($81, 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(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 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; GoldenRec.KillAll; 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_); GoldenRec.KillAll; end; // alt + right if SDL_ModState = KMOD_LALT 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_); GoldenRec.KillAll; end; // alt + ctrl + shift + right = move all from cursor to right if SDL_ModState = KMOD_LALT + KMOD_LCTRL + KMOD_LSHIFT then begin MoveAllToEnd(1); GoldenRec.KillAll; end; ShowInteractiveBackground; end; SDLK_LEFT: begin // left CopyToUndo; if SDL_ModState = 0 then begin AudioPlayback.Stop; PlaySentence := false; PlayVideo := false; {$IFDEF UseMIDIPort} MidiOut.PutShort($B1, $7, floor(1.27*SelectsS[VolumeMidiSlideId].SelectedOption)); MidiOut.PutShort($81, 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(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 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; GoldenRec.KillAll; 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_); GoldenRec.KillAll; end; // alt + left if SDL_ModState = KMOD_LALT 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; GoldenRec.KillAll; end; // alt + ctrl + shift + right = move all from cursor to left if SDL_ModState = KMOD_LALT + KMOD_LCTRL + KMOD_LSHIFT then begin MoveAllToEnd(-1); GoldenRec.KillAll; end; ShowInteractiveBackground; end; SDLK_DOWN: begin // skip to next sentence if SDL_ModState = 0 then begin {$IFDEF UseMIDIPort} MidiOut.PutShort($B1, $7, floor(1.27*SelectsS[VolumeMidiSlideId].SelectedOption)); 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; PlayVideo := false; GoldenRec.KillAll; end; // decrease tone if SDL_ModState = KMOD_LCTRL then begin CopyToUndo; TransposeNote(-1); GoldenRec.KillAll; end; ShowInteractiveBackground; end; SDLK_UP: begin // skip to previous sentence if SDL_ModState = 0 then begin AudioPlayback.Stop; PlayVideo := false; PlaySentence := false; {$IFDEF UseMIDIPort} MidiOut.PutShort(MIDI_NOTEOFF or 1, $7, floor(1.27*SelectsS[VolumeMidiSlideId].SelectedOption)); MidiOut.PutShort($81, 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; GoldenRec.KillAll; end; // increase tone if SDL_ModState = KMOD_LCTRL then begin CopyToUndo; TransposeNote(1); GoldenRec.KillAll; end; ShowInteractiveBackground; 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 CurrentEditText := UTF8Copy(CurrentEditText, 1,TextPosition) + UCS4ToUTF8String(CharCode) + UTF8Copy(CurrentEditText, TextPosition+1, LengthUTF8(CurrentEditText)); inc(editLenghtText); inc(TextPosition); if TextEditMode then begin Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text := CurrentEditText; Lyric.AddLine(Lines[0].Current); Lyric.Selected := CurrentNote; end; Exit; end; // check special keys case PressedKey of SDLK_ESCAPE: begin if TextEditMode then Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text := BackupEditText; if TitleEditMode then begin CurrentSong.Title := BackupEditText; SelectsS[CurrentSlideId].TextOpt[0].Text := BackupEditText; end; if ArtistEditMode then begin CurrentSong.Artist := BackupEditText; SelectsS[CurrentSlideId].TextOpt[0].Text := BackupEditText; end; Lyric.AddLine(Lines[0].Current); Lyric.Selected := CurrentNote; TextEditMode := false; TitleEditMode := false; ArtistEditMode := false; editLenghtText := 0; TextPosition := -1; end; SDLK_F4, SDLK_RETURN: begin // Exit Text Edit Mode CopyToUndo; if TitleEditMode then begin CurrentSong.Title := UTF8Copy(CurrentEditText, 1, TextPosition) + UTF8Copy(CurrentEditText, TextPosition+1, LengthUTF8(CurrentEditText)-TextPosition); SelectsS[CurrentSlideId].TextOpt[0].Text := CurrentEditText; end; if ArtistEditMode then begin CurrentSong.Artist := UTF8Copy(CurrentEditText, 1, TextPosition) + UTF8Copy(CurrentEditText, TextPosition+1, LengthUTF8(CurrentEditText)-TextPosition); SelectsS[CurrentSlideId].TextOpt[0].Text := CurrentEditText; end; if TextEditMode then begin Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text := UTF8Copy(CurrentEditText, 1, TextPosition) + UTF8Copy(CurrentEditText, TextPosition+1, LengthUTF8(CurrentEditText)-TextPosition); SelectsS[CurrentSlideId].TextOpt[0].Text := CurrentEditText; Lyric.AddLine(Lines[0].Current); end; Lyric.Selected := CurrentNote; TitleEditMode := false; TextEditMode := false; ArtistEditMode := false; editLenghtText := 0; TextPosition := -1; CurrentSlideId := -1; end; SDLK_BACKSPACE: begin UTF8Delete(CurrentEditText, TextPosition, 1); dec(TextPosition); if TextEditMode then begin Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text := UTF8Copy(CurrentEditText, 1, TextPosition) + UTF8Copy(CurrentEditText, TextPosition+1, LengthUTF8(CurrentEditText)-TextPosition); Lyric.AddLine(Lines[0].Current); Lyric.Selected := CurrentNote; end; end; SDLK_DELETE: begin UTF8Delete(CurrentEditText, TextPosition+1, 1); end; SDLK_RIGHT: begin // right if SDL_ModState = 0 then begin if (TextPosition >= 0) and (TextPosition < editLenghtText-1) then TextPosition := TextPosition + 1 else TextPosition := 0; end; end; SDLK_LEFT: begin // left if SDL_ModState = 0 then begin if TextPosition > 0 then TextPosition := TextPosition - 1 else TextPosition := editLenghtText-1; end; end; end; //case end; //if (PressedDown) end; function TScreenEditSub.ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; var nBut: integer; Action: TMouseClickAction; begin // transfer mousecords to the 800x600 raster we use to draw X := Round((X / (ScreenW / Screens)) * RenderW); if (X > RenderW) then X := X - RenderW; Y := Round((Y / ScreenH) * RenderH); CurrentX := X; CurrentY := X; Result := true; nBut := InteractAt(X, Y); Action := maNone; if nBut >= 0 then begin //select on mouse-over if nBut <> Interaction then SetInteraction(nBut); end; if (BtnDown) then begin if (MouseButton = SDL_BUTTON_LEFT) then begin //click button or SelectS if (Interactions[nBut].Typ = iSelectS) then begin Action := SelectsS[Interactions[nBut].Num].OnClick(X, Y); end else Action := maReturn; end; end; // changed cover if ((CoverSlideId = Interactions[nBut].Num) and (Action = maLeft) and (SelectsS[Interactions[nBut].Num].SelectedOption > 0)) then begin CopyToUndo; SelectsS[Interactions[nBut].Num].SelectedOption := SelectsS[Interactions[nBut].Num].SelectedOption -1; CurrentSong.Cover := Path(SelectsS[Interactions[nBut].Num].TextOptT[SelectsS[Interactions[nBut].Num].SelectedOption]); end; if ((CoverSlideId = Interactions[nBut].Num) and (Action = maRight) and (SelectsS[Interactions[nBut].Num].SelectedOption < Length(SelectsS[Interactions[nBut].Num].TextOptT)-1)) then begin CopyToUndo; SelectsS[Interactions[nBut].Num].SelectedOption := SelectsS[Interactions[nBut].Num].SelectedOption +1; CurrentSong.Cover := Path(SelectsS[Interactions[nBut].Num].TextOptT[SelectsS[Interactions[nBut].Num].SelectedOption]); end; if ((BackgroundSlideId = Interactions[nBut].Num) and (Action = maLeft) and (SelectsS[Interactions[nBut].Num].SelectedOption > 0)) then begin CopyToUndo; SelectsS[Interactions[nBut].Num].SelectedOption := SelectsS[Interactions[nBut].Num].SelectedOption -1; CurrentSong.Background := Path(SelectsS[Interactions[nBut].Num].TextOptT[SelectsS[Interactions[nBut].Num].SelectedOption]); // change background picture Tex_PrevBackground := Texture.LoadTexture(CurrentSong.Path.Append(CurrentSong.Background)); Texture.AddTexture(Tex_PrevBackground, TEXTURE_TYPE_PLAIN, false); Statics[BackgroundImageId].Texture := Tex_PrevBackground; Statics[BackgroundImageId].Texture.X := theme.EditSub.BackgroundImage.X; Statics[BackgroundImageId].Texture.Y := theme.EditSub.BackgroundImage.Y; Statics[BackgroundImageId].Texture.W := theme.EditSub.BackgroundImage.W; Statics[BackgroundImageId].Texture.H := theme.EditSub.BackgroundImage.H; end; if ((BackgroundSlideId = Interactions[nBut].Num) and (Action = maRight) and (SelectsS[Interactions[nBut].Num].SelectedOption < Length(SelectsS[Interactions[nBut].Num].TextOptT)-1)) then begin CopyToUndo; SelectsS[Interactions[nBut].Num].SelectedOption := SelectsS[Interactions[nBut].Num].SelectedOption +1; CurrentSong.Background := Path(SelectsS[Interactions[nBut].Num].TextOptT[SelectsS[Interactions[nBut].Num].SelectedOption]); // change background picture Tex_PrevBackground := Texture.LoadTexture(CurrentSong.Path.Append(CurrentSong.Background)); Texture.AddTexture(Tex_PrevBackground, TEXTURE_TYPE_PLAIN, false); Statics[BackgroundImageId].Texture := Tex_PrevBackground; Statics[BackgroundImageId].Texture.X := theme.EditSub.BackgroundImage.X; Statics[BackgroundImageId].Texture.Y := theme.EditSub.BackgroundImage.Y; Statics[BackgroundImageId].Texture.W := theme.EditSub.BackgroundImage.W; Statics[BackgroundImageId].Texture.H := theme.EditSub.BackgroundImage.H; end; if ((Mp3SlideId = Interactions[nBut].Num) and (Action = maLeft) and (SelectsS[Interactions[nBut].Num].SelectedOption > 0)) then begin CopyToUndo; SelectsS[Interactions[nBut].Num].SelectedOption := SelectsS[Interactions[nBut].Num].SelectedOption -1; CurrentSong.Mp3 := Path(SelectsS[Interactions[nBut].Num].TextOptT[SelectsS[Interactions[nBut].Num].SelectedOption]); AudioPlayback.Close; AudioPlayback.Open(CurrentSong.Path.Append(CurrentSong.Mp3)); end; if ((Mp3SlideId = Interactions[nBut].Num) and (Action = maRight) and (SelectsS[Interactions[nBut].Num].SelectedOption < Length(SelectsS[Interactions[nBut].Num].TextOptT)-1)) then begin CopyToUndo; SelectsS[Interactions[nBut].Num].SelectedOption := SelectsS[Interactions[nBut].Num].SelectedOption +1; CurrentSong.Mp3 := Path(SelectsS[Interactions[nBut].Num].TextOptT[SelectsS[Interactions[nBut].Num].SelectedOption]); AudioPlayback.Close; AudioPlayback.Open(CurrentSong.Path.Append(CurrentSong.Mp3)); end; if (((VolumeAudioSlideId = Interactions[nBut].Num) or (VolumeMidiSlideId = Interactions[nBut].Num) or (VolumeClickSlideId = Interactions[nBut].Num)) and (Action = maLeft) and (SelectsS[Interactions[nBut].Num].SelectedOption > 0)) then begin SelectsS[Interactions[nBut].Num].SelectedOption := SelectsS[Interactions[nBut].Num].SelectedOption -1; end; if (((VolumeAudioSlideId = Interactions[nBut].Num) or (VolumeMidiSlideId = Interactions[nBut].Num) or (VolumeClickSlideId = Interactions[nBut].Num)) and (Action = maRight) and (SelectsS[Interactions[nBut].Num].SelectedOption < Length(SelectsS[Interactions[nBut].Num].TextOptT)-1)) then begin SelectsS[Interactions[nBut].Num].SelectedOption := SelectsS[Interactions[nBut].Num].SelectedOption +1; end; case Action of maReturn: Result := ParseInput(SDLK_RETURN, 0, true); // maLeft: Result := ParseInput(SDLK_LEFT, 0, true); // maRight: Result := ParseInput(SDLK_RIGHT, 0, true); 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 i,j: integer; begin CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM / 2; for i := 0 to Lines[0].High do begin Lines[0].Line[i].Start := Lines[0].Line[i].Start div 2; Lines[0].Line[i].End_ := Lines[0].Line[i].End_ div 2; for j := 0 to Lines[0].Line[i].HighNote do begin Lines[0].Line[i].Note[j].Start := Lines[0].Line[i].Note[j].Start div 2; Lines[0].Line[i].Note[j].Length := Round(Lines[0].Line[i].Note[j].Length / 2); end; // j end; // i end; procedure TScreenEditSub.MultiplyBPM; var i,j: integer; begin CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM * 2; for i := 0 to Lines[0].High do begin Lines[0].Line[i].Start := Lines[0].Line[i].Start * 2; Lines[0].Line[i].End_ := Lines[0].Line[i].End_ * 2; for j := 0 to Lines[0].Line[i].HighNote do begin Lines[0].Line[i].Note[j].Start := Lines[0].Line[i].Note[j].Start * 2; Lines[0].Line[i].Note[j].Length := Lines[0].Line[i].Note[j].Length * 2; end; // i end; // j end; procedure TScreenEditSub.LyricsCapitalize; var i: integer; //N: integer; // temporary S: UTF8String; 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 i := 0 to Lines[0].High do begin S := UTF8UpperCase(UTF8Copy(Lines[0].Line[i].Note[0].Text, 1, 1)); S := S + UTF8Copy(Lines[0].Line[i].Note[0].Text, 2, Length(Lines[0].Line[i].Note[0].Text)-1); Lines[0].Line[i].Note[0].Text := S; end; // i 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.CopyToUndo; var I,J: integer; begin SetLength(UndoLines, high(UndoLines)+2); CurrentUndoLines := high(UndoLines); SetLength(UndoStateNote, CurrentUndoLines+1); SetLength(UndoHeader, CurrentUndoLines+1); Undoheader[CurrentUndoLines].Title := CurrentSong.Title; Undoheader[CurrentUndoLines].Artist := CurrentSong.Artist; Undoheader[CurrentUndoLines].CoverId := SelectsS[CoverSlideId].SelectedOption; Undoheader[CurrentUndoLines].BackgroundId := SelectsS[BackgroundSlideId].SelectedOption; Undoheader[CurrentUndoLines].Mp3Id := SelectsS[Mp3SlideId].SelectedOption; Undoheader[CurrentUndoLines].GAP := CurrentSong.GAP; Undoheader[CurrentUndoLines].Video := CurrentSong.Video; Undoheader[CurrentUndoLines].VideoGAP := CurrentSong.VideoGAP; SetLength(Undoheader[CurrentUndoLines].BPM, length(CurrentSong.BPM)); for I:=0 to length(CurrentSong.BPM)-1 do begin Undoheader[CurrentUndoLines].BPM[I].BPM := CurrentSong.BPM[I].BPM; Undoheader[CurrentUndoLines].BPM[I].StartBeat := CurrentSong.BPM[I].StartBeat; end; UndoStateNote[CurrentUndoLines] := currentnote; UndoLines[CurrentUndoLines].Current := Lines[0].Current; UndoLines[CurrentUndoLines].High := Lines[0].High; UndoLines[CurrentUndoLines].Number := Lines[0].Number; UndoLines[CurrentUndoLines].Resolution := Lines[0].Resolution; UndoLines[CurrentUndoLines].NotesGAP := Lines[0].NotesGAP; UndoLines[CurrentUndoLines].ScoreValue := Lines[0].ScoreValue; SetLength(UndoLines[CurrentUndoLines].Line, length(Lines[0].Line)); for I:=0 to length(Lines[0].Line)-1 do begin UndoLines[CurrentUndoLines].Line[I].Start := Lines[0].Line[I].Start; UndoLines[CurrentUndoLines].Line[I].Lyric := Lines[0].Line[I].Lyric; UndoLines[CurrentUndoLines].Line[I].End_ := Lines[0].Line[I].End_; UndoLines[CurrentUndoLines].Line[I].BaseNote := Lines[0].Line[I].BaseNote; UndoLines[CurrentUndoLines].Line[I].HighNote := Lines[0].Line[I].HighNote; UndoLines[CurrentUndoLines].Line[I].TotalNotes := Lines[0].Line[I].TotalNotes; UndoLines[CurrentUndoLines].Line[I].LastLine := Lines[0].Line[I].LastLine; SetLength(UndoLines[CurrentUndoLines].Line[I].Note, length(Lines[0].Line[I].Note)); for J:=0 to length(Lines[0].Line[I].Note)-1 do begin UndoLines[CurrentUndoLines].Line[I].Note[J].Color := Lines[0].Line[I].Note[J].Color; UndoLines[CurrentUndoLines].Line[I].Note[J].Start := Lines[0].Line[I].Note[J].Start; UndoLines[CurrentUndoLines].Line[I].Note[J].Length := Lines[0].Line[I].Note[J].Length; UndoLines[CurrentUndoLines].Line[I].Note[J].Tone := Lines[0].Line[I].Note[J].Tone; UndoLines[CurrentUndoLines].Line[I].Note[J].Text := Lines[0].Line[I].Note[J].Text; UndoLines[CurrentUndoLines].Line[I].Note[J].NoteType := Lines[0].Line[I].Note[J].NoteType; end; //for J end; //for I end; procedure TScreenEditSub.CopyFromUndo; var I,J: integer; begin CurrentUndoLines := high(UndoLines); if CurrentUndoLines >= 0 then begin CurrentSong.Title := Undoheader[CurrentUndoLines].Title; CurrentSong.Artist := Undoheader[CurrentUndoLines].Artist; SelectsS[CoverSlideId].SelectedOption := Undoheader[CurrentUndoLines].CoverId; SelectsS[BackgroundSlideId].SelectedOption := Undoheader[CurrentUndoLines].BackgroundId; SelectsS[Mp3SlideId].SelectedOption := Undoheader[CurrentUndoLines].Mp3Id; CurrentSong.GAP := Undoheader[CurrentUndoLines].GAP; CurrentSong.Video := Undoheader[CurrentUndoLines].Video; CurrentSong.VideoGAP := Undoheader[CurrentUndoLines].VideoGAP; currentnote := UndoStateNote[high(UndoStateNote)]; SetLength(CurrentSong.BPM, length(Undoheader[CurrentUndoLines].BPM)); for I:=0 to length(Undoheader[CurrentUndoLines].BPM)-1 do begin CurrentSong.BPM[I].BPM := Undoheader[CurrentUndoLines].BPM[I].BPM; CurrentSong.BPM[I].StartBeat := Undoheader[CurrentUndoLines].BPM[I].StartBeat; end; Lines[0].Current := UndoLines[CurrentUndoLines].Current; Lines[0].High := UndoLines[CurrentUndoLines].High; Lines[0].Number := UndoLines[CurrentUndoLines].Number; Lines[0].Resolution := UndoLines[CurrentUndoLines].Resolution; Lines[0].NotesGAP := UndoLines[CurrentUndoLines].NotesGAP; Lines[0].ScoreValue := UndoLines[CurrentUndoLines].ScoreValue; SetLength(Lines[0].Line, length(UndoLines[CurrentUndoLines].Line)); for I:=0 to length(UndoLines[CurrentUndoLines].Line)-1 do begin Lines[0].Line[I].Start := UndoLines[CurrentUndoLines].Line[I].Start; Lines[0].Line[I].Lyric := UndoLines[CurrentUndoLines].Line[I].Lyric; Lines[0].Line[I].End_ := UndoLines[CurrentUndoLines].Line[I].End_; Lines[0].Line[I].BaseNote := UndoLines[CurrentUndoLines].Line[I].BaseNote; Lines[0].Line[I].HighNote := UndoLines[CurrentUndoLines].Line[I].HighNote; Lines[0].Line[I].TotalNotes := UndoLines[CurrentUndoLines].Line[I].TotalNotes; Lines[0].Line[I].LastLine := UndoLines[CurrentUndoLines].Line[I].LastLine; SetLength(Lines[0].Line[I].Note, length(UndoLines[CurrentUndoLines].Line[I].Note)); for J:=0 to length(UndoLines[CurrentUndoLines].Line[I].Note)-1 do begin Lines[0].Line[I].Note[J].Color := UndoLines[CurrentUndoLines].Line[I].Note[J].Color; Lines[0].Line[I].Note[J].Start := UndoLines[CurrentUndoLines].Line[I].Note[J].Start; Lines[0].Line[I].Note[J].Length := UndoLines[CurrentUndoLines].Line[I].Note[J].Length; Lines[0].Line[I].Note[J].Tone := UndoLines[CurrentUndoLines].Line[I].Note[J].Tone; Lines[0].Line[I].Note[J].Text := UndoLines[CurrentUndoLines].Line[I].Note[J].Text; log.LogError(Lines[0].Line[I].Note[J].Text); Lines[0].Line[I].Note[J].NoteType := UndoLines[CurrentUndoLines].Line[I].Note[J].NoteType; end; //for J end; //for I SetLength(UndoStateNote, high(UndoStateNote)); SetLength(UndoHeader, high(UndoLines)); SetLength(UndoLines, high(UndoLines)); Text[TextDebug].Text := Language.Translate('INFO_UNDO'); // to refresh all headers SelectsS[LyricSlideId].TextOpt[0].Text := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text; SelectsS[ArtistSlideId].TextOpt[0].Text := CurrentSong.Artist; SelectsS[TitleSlideId].TextOpt[0].Text := CurrentSong.Title; Lyric.AddLine(Lines[0].Current); Lyric.Selected := CurrentNote; end; //if CurrentUndoLines end; procedure TScreenEditSub.DrawPlayerTrack(X, Y, W: real; Space: integer; CurrentTone: integer; Count: integer; CurrentNote: integer); var TempR: real; Rec: TRecR; N, scale: integer; // R, G, B, A: real; NotesH2,W1,H1,X1,X2: real; begin glColor3f(1, 1, 1); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); TempR := W / (Lines[0].Line[Lines[0].Current].End_ - Lines[0].Line[Lines[0].Current].Note[0].Start); NotesH2 := int(NotesH * 0.65); W1 := NotesW * 2 + 2; H1 := NotesH * 1.5;// + 3.5; X2 := 40 + 0.5 + 10*ScreenX+Count; X1 := X2-W1-2; Rec.Left := X1; Rec.Right := X2; scale := 0; repeat if (Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone+12*scale > CurrentTone) then dec(scale) else inc(scale); until ( (((Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone + 12*scale) / 12) < 1) and (((Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone + 12*scale) / 12) >= 0)); Rec.Top := 410 - (CurrentTone-12*scale-Lines[0].Line[Lines[0].Current].BaseNote)*Space/2 - H1; Rec.Bottom := Rec.Top + 2 * H1; glColor3f(1, 1, 1); glBindTexture(GL_TEXTURE_2D, Tex_Lyric_Help_Bar.TexNum); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top); glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom); glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom); glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top); glEnd; 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: integer; numLines: 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; procedure TScreenEditSub.DrawText(Left, Top, Right: real; NrLines: integer; Space: integer); var Rec: TRecR; Count: integer; TempR: real; PlayerNumber: integer; GoldenStarPos: real; lTmpA, lTmpB : real; begin if (ScreenSing.settings.NotesVisible and (1 shl NrLines) <> 0) then begin PlayerNumber := NrLines + 1; // Player 1 is 0 glColor3f(1, 1, 1); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); lTmpA := (Right-Left); lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start); if ( lTmpA > 0 ) and ( lTmpB > 0 ) then TempR := lTmpA / lTmpB else TempR := 0; with Lines[NrLines].Line[Lines[NrLines].Current] do begin for Count := 0 to HighNote do begin with Note[Count] do begin // left part Rec.Left := 0; Rec.Right := 0; BaseNote := Lines[0].Line[Lines[NrLines].Current].BaseNote; Rec.Top := Top - (Tone-BaseNote)*Space/2 - NotesH; Rec.Bottom := Rec.Top + 2 * NotesH; // middle part Rec.Left := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX + NotesW; Rec.Right := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - NotesW - 0.5 + 10*ScreenX; glColor4f(0, 0, 0, 1); SetFontStyle (1); SetFontItalic(False); SetFontSize(14); SetFontPos (Rec.Left, Rec.Top); glPrint(Text); end; // with end; // for end; // with glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); end; end; // show transparent background for intaractive note procedure TScreenEditSub.ShowInteractiveBackground; var TempR: real; i: integer; begin for i := 0 to high(InteractiveNoteId) do begin Button[i].SetX(0); Button[i].SetY(0); Button[i].SetW(0); Button[i].SetH(0); end; // adding transparent buttons while (high(InteractiveNoteId) < Lines[0].Line[Lines[0].Current].HighNote) do begin SetLength(InteractiveNoteId, high(InteractiveNoteId)+2); AddButton(0, 0, 0, 0,PATH_NONE); // AddButton(0, 0, 0, 0,Skin.GetTextureFileName('ButtonF')); InteractiveNoteId[high(InteractiveNoteId)] := Length(Interactions)-1; end; TempR := 720 / (Lines[0].Line[Lines[0].Current].End_ - Lines[0].Line[Lines[0].Current].Note[0].Start); for i := 0 to Lines[0].Line[Lines[0].Current].HighNote do begin Button[i].SetX(40 + (Lines[0].Line[Lines[0].Current].Note[i].Start - Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR + 0.5 + 10*ScreenX); Button[i].SetY(410 - (Lines[0].Line[Lines[0].Current].Note[i].Tone - Lines[0].Line[Lines[0].Current].BaseNote)*15/2 - 9); Button[i].SetW((Lines[0].Line[Lines[0].Current].Note[i].Length) * TempR - 0.5 + 10*(ScreenX)); Button[i].SetH(19); end; end; // from revision 2475 procedure TScreenEditSub.StartVideoPreview; var VideoFile: IPath; begin if Assigned(fCurrentVideo) then begin fCurrentVideo.Stop(); fCurrentVideo := nil; end; VideoFile := CurrentSong.Path.Append(CurrentSong.Video); if (CurrentSong.Video.IsSet) and VideoFile.IsFile then begin fCurrentVideo := VideoPlayback.Open(VideoFile); if (fCurrentVideo <> nil) then begin fCurrentVideo.Position := CurrentSong.VideoGAP + AudioPlayback.Position; fCurrentVideo.Play; end; end; end; procedure TScreenEditSub.StopVideoPreview; begin // Stop video preview of previous song if Assigned(fCurrentVideo) then begin fCurrentVideo.Stop(); fCurrentVideo := nil; end; end; constructor TScreenEditSub.Create; begin inherited Create; LoadFromTheme(Theme.EditSub); //video fCurrentVideo := nil; SetLength(Player, 1); SetLength(TitleVal, 0); SetLength(ArtistVal, 0); SetLength(MP3Val, 0); SetLength(CoverVal, 0); SetLength(BackgroundVal, 0); SetLength(BPMVal, 0); SetLength(GAPVal, 0); SetLength(ToneVal, 0); SetLength(DurationVal, 0); SetLength(LyricVal, 0); //volume SetLength(VolumeAudio,0); SetLength(VolumeMidi,0); SetLength(VolumeClick,0); // 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:'); // Title Header TitleSlideId := AddSelectSlide(Theme.EditSub.SlideTitle, Titledata, TitleVal); SelectsS[TitleSlideId].Text.Align := 0; SelectsS[TitleSlideId].Text.X := SelectsS[TitleSlideId].Texture.X + 3; // AddText(30, 90, 0, 24, 0, 0, 0, 'Artist:'); // Artist Header ArtistSlideId := AddSelectSlide(Theme.EditSub.SlideArtist, Artistdata, ArtistVal); SelectsS[ArtistSlideId].Text.Align := 0; SelectsS[ArtistSlideId].Text.X := SelectsS[ArtistSlideId].Texture.X + 3; //AddText(30, 115, 0, 24, 0, 0, 0, 'Mp3:'); // Artist Header MP3SlideId := AddSelectSlide(Theme.EditSub.SlideMP3, MP3data, MP3Val); SelectsS[MP3SlideId].Text.Align := 0; SelectsS[MP3SlideId].Text.X := SelectsS[MP3SlideId].Texture.X + 3; // Cover Header CoverSlideId := AddSelectSlide(Theme.EditSub.SlideCover, Coverdata, CoverVal); SelectsS[CoverSlideId].Text.Align := 0; SelectsS[CoverSlideId].Text.X := SelectsS[CoverSlideId].Texture.X + 3; // Background Header BackgroundSlideId := AddSelectSlide(Theme.EditSub.SlideBackground, Backgrounddata, BackgroundVal); SelectsS[BackgroundSlideId].Text.Align := 0; SelectsS[BackgroundSlideId].Text.X := SelectsS[BackgroundSlideId].Texture.X + 3; // AddText(30, 140, 0, 24, 0, 0, 0, 'BPM:'); // BPM Header BPMSlideId := AddSelectSlide(Theme.EditSub.SlideBPM, BPMdata, BPMVal); SelectsS[BPMSlideId].Text.Align := 0; SelectsS[BPMSlideId].Text.X := SelectsS[BPMSlideId].Texture.X + 3; //AddText(30, 165, 0, 24, 0, 0, 0, 'GAP:'); // GAP Header GAPSlideId := AddSelectSlide(Theme.EditSub.SlideGAP, GAPdata, GAPVal); SelectsS[GAPSlideId].Text.Align := 0; SelectsS[GAPSlideId].Text.X := SelectsS[GAPSlideId].Texture.X + 3; // Start Header StartSlideId := AddSelectSlide(Theme.EditSub.SlideStart, Startdata, StartVal); SelectsS[StartSlideId].Text.Align := 0; SelectsS[StartSlideId].Text.X := SelectsS[StartSlideId].Texture.X + 3; // Duration Header DurationSlideId := AddSelectSlide(Theme.EditSub.SlideDuration, Durationdata, DurationVal); SelectsS[DurationSlideId].Text.Align := 0; SelectsS[DurationSlideId].Text.X := SelectsS[StartSlideId].Texture.X + 3; // Tone Header ToneSlideId := AddSelectSlide(Theme.EditSub.SlideTone, Tonedata, ToneVal); SelectsS[ToneSlideId].Text.Align := 0; SelectsS[ToneSlideId].Text.X := SelectsS[ToneSlideId].Texture.X + 3; // Text Header LyricSlideId := AddSelectSlide(Theme.EditSub.SlideLyric, Lyricdata, LyricVal); SelectsS[LyricSlideId].Text.Align := 0; SelectsS[LyricSlideId].Text.X := SelectsS[LyricSlideId].Texture.X + 3; VolumeAudioSlideId := AddSelectSlide(Theme.EditSub.SelectVolAudio, VolumeAudioIndex, VolumeAudio); VolumeMidiSlideId := AddSelectSlide(Theme.EditSub.SelectVolMidi, VolumeMidiIndex, VolumeMidi); VolumeClickSlideId := AddSelectSlide(Theme.EditSub.SelectVolClick, VolumeClickIndex, VolumeClick); // VideoGap Header VideoGapSlideId := AddSelectSlide(Theme.EditSub.SlideVideoGap, VideoGapdata, VideoGapVal); SelectsS[VideoGapSlideId].Text.Align := 0; SelectsS[VideoGapSlideId].Text.X := SelectsS[VideoGapSlideId].Texture.X + 3; // background image & preview BackgroundImageId := AddStatic(Theme.EditSub.BackgroundImage); // 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; Files: TPathDynArray; i: integer; begin inherited; // reset video playback engine fCurrentVideo := nil; AudioPlayback.Stop; PlaySentence := false; PlaySentenceMidi := false; Text[TextDebug].Text := ''; Log.LogStatus('Initializing', 'TEditScreen.OnShow'); Lyric := TEditorLyrics.Create; ResetSingTemp; GoldenRec.KillAll; // SetLength(UndoSong, 0); SetLength(UndoLines, 0); SetLength(UndoStateNote, 0); SetLength(Undoheader, 0); 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; // Header Title SetLength(TitleVal, 1); TitleVal[0] := CurrentSong.Title; SlideTitleIndex := 1; UpdateSelectSlideOptions(Theme.EditSub.SlideTitle,TitleSlideId,TitleVal,SlideTitleIndex); SelectsS[TitleSlideId].TextOpt[0].Align := 0; SelectsS[TitleSlideId].TextOpt[0].X := SelectsS[TitleSlideId].TextureSBG.X + 5; // Text[TextArtist].Text := CurrentSong.Artist; // Header Artist SetLength(ArtistVal, 1); ArtistVal[0] := CurrentSong.Artist; SlideArtistIndex := 1; UpdateSelectSlideOptions(Theme.EditSub.SlideArtist,ArtistSlideId,ArtistVal,SlideArtistIndex); SelectsS[ArtistSlideId].TextOpt[0].Align := 0; SelectsS[ArtistSlideId].TextOpt[0].X := SelectsS[ArtistSlideId].TextureSBG.X + 5; //Text[TextMp3].Text := CurrentSong.Mp3.ToUTF8; // Header MP3 SetLength(MP3Val, 0); SetLength(Files, 0); SlideMP3Index := -1; Songs.FindFilesByExtension(Path(includeTrailingPathDelimiter(CurrentSong.Path.ToNative)), Path('.mp3'), true, Files); for i:=0 to high(Files) do begin SetLength(MP3Val, high(MP3Val)+2); MP3Val[i] := filesystem.ExtractFileName(files[i]).ToUTF8; if (UTF8CompareText(MP3Val[i],CurrentSong.Mp3.ToUTF8) = 0) then SlideMP3Index := i; end; UpdateSelectSlideOptions(Theme.EditSub.SlideMP3,MP3SlideId,MP3Val,SlideMP3Index); // Header Cover SetLength(Files, 0); SetLength(CoverVal, 0); SlideCoverIndex := -1; Songs.FindFilesByExtension(Path(includeTrailingPathDelimiter(CurrentSong.Path.ToNative)), Path('.jpg'), true, Files); for i:=0 to high(Files) do begin SetLength(CoverVal, high(CoverVal)+2); CoverVal[i] := ExtractFileName(files[i].ToUTF8()); if UTF8CompareText(CoverVal[i], CurrentSong.Cover.ToUTF8) = 0 then SlideCoverIndex := i; end; if high(Files) < 0 then begin SetLength(CoverVal, 1); CoverVal[0] := CurrentSong.Cover.ToUTF8; SlideCoverIndex := 0; end; UpdateSelectSlideOptions(Theme.EditSub.SlideCover,CoverSlideId,CoverVal,SlideCoverIndex); // Header Background SetLength(Files, 0); SetLength(BackgroundVal, 0); SlideBackgroundIndex := -1; Songs.FindFilesByExtension(Path(includeTrailingPathDelimiter(CurrentSong.Path.ToNative)), Path('.jpg'), true, Files); for i:=0 to high(Files) do begin SetLength(BackgroundVal, high(BackgroundVal)+2); BackgroundVal[i] := ExtractFileName(files[i].ToUTF8()); if UTF8CompareText(BackgroundVal[i], CurrentSong.Background.ToUTF8) = 0 then SlideBackgroundIndex := i; end; if high(Files) < 0 then begin SetLength(BackgroundVal, 1); BackgroundVal[0] := CurrentSong.Background.ToUTF8; SlideBackgroundIndex := 0; end; UpdateSelectSlideOptions(Theme.EditSub.SlideBackground,BackgroundSlideId,BackgroundVal,SlideBackgroundIndex); // SelectsS[BackgroundSlideId].TextOpt[0].Align := 0; // Header BPM SetLength(BPMVal, 1); BPMVal[0] := ''; SlideBPMIndex := 1; UpdateSelectSlideOptions(Theme.EditSub.SlideBPM,BPMSlideId,BPMVal,SlideBPMIndex); SelectsS[BPMSlideId].TextOpt[0].Align := 0; SelectsS[BPMSlideId].TextOpt[0].X := SelectsS[BPMSlideId].TextureSBG.X + 5; // Header GAP SetLength(GAPVal, 1); GAPVal[0] := ''; SlideGAPIndex := 1; UpdateSelectSlideOptions(Theme.EditSub.SlideGAP,GAPSlideId,GAPVal,SlideGAPIndex); SelectsS[GAPSlideId].TextOpt[0].Align := 0; SelectsS[GAPSlideId].TextOpt[0].X := SelectsS[GAPSlideId].TextureSBG.X + 5; // Header Start SetLength(StartVal, 1); StartVal[0] := ''; SlideStartIndex := 1; UpdateSelectSlideOptions(Theme.EditSub.SlideStart,StartSlideId,StartVal,SlideStartIndex); SelectsS[StartSlideId].TextOpt[0].Align := 0; SelectsS[StartSlideId].TextOpt[0].X := SelectsS[StartSlideId].TextureSBG.X + 5; // Header Duration SetLength(DurationVal, 1); DurationVal[0] := ''; SlideDurationIndex := 1; UpdateSelectSlideOptions(Theme.EditSub.SlideDuration,DurationSlideId,DurationVal,SlideDurationIndex); SelectsS[DurationSlideId].TextOpt[0].Align := 0; SelectsS[DurationSlideId].TextOpt[0].X := SelectsS[DurationSlideId].TextureSBG.X + 5; // Header Tone SetLength(ToneVal, 1); ToneVal[0] := ''; SlideDurationIndex := 1; UpdateSelectSlideOptions(Theme.EditSub.SlideTone,ToneSlideId,ToneVal,SlideToneIndex); SelectsS[ToneSlideId].TextOpt[0].Align := 0; SelectsS[ToneSlideId].TextOpt[0].X := SelectsS[ToneSlideId].TextureSBG.X + 5; // Header Lyric SetLength(LyricVal, 1); LyricVal[0] := ''; SlideLyricIndex := 1; UpdateSelectSlideOptions(Theme.EditSub.SlideLyric,LyricSlideId,LyricVal,SlideLyricIndex); SelectsS[LyricSlideId].TextOpt[0].Align := 0; SelectsS[LyricSlideId].TextOpt[0].X := SelectsS[LyricSlideId].TextureSBG.X + 5; // Header VideoGap SetLength(VideoGapVal, 1); VideoGapVal[0] := ''; SlideVideoGapIndex := 1; UpdateSelectSlideOptions(Theme.EditSub.SlideVideoGap,VideoGapSlideId,VideoGapVal,SlideVideoGapIndex); SelectsS[VideoGapSlideId].TextOpt[0].Align := 0; SelectsS[VideoGapSlideId].TextOpt[0].X := SelectsS[VideoGapSlideId].TextureSBG.X + 5; // volume slides SetLength(VolumeAudio, 0); SetLength(VolumeMidi, 0); SetLength(VolumeClick, 0); for i:=0 to 100 do begin SetLength(VolumeAudio, high(VolumeAudio)+2); SetLength(VolumeMidi, high(VolumeMidi)+2); SetLength(VolumeClick, high(VolumeClick)+2); VolumeAudio[i] := inttostr(i); VolumeMidi[i] := inttostr(i); VolumeClick[i] := inttostr(i); end; VolumeAudioIndex := 100; VolumeMidiIndex := 100; VolumeClickIndex := 100; UpdateSelectSlideOptions(Theme.EditSub.SelectVolAudio,VolumeAudioSlideId,VolumeAudio,VolumeAudioIndex); UpdateSelectSlideOptions(Theme.EditSub.SelectVolMidi,VolumeMidiSlideId,VolumeMidi,VolumeMidiIndex); UpdateSelectSlideOptions(Theme.EditSub.SelectVolClick,VolumeClickSlideId,VolumeClick,VolumeClickIndex); 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; //show transparent background for notes ShowInteractiveBackground; // user input tracking AudioInput.CaptureStart; end; // background picture try //BgFile := CurrentSong.Path.Append(CurrentSong.Background); Statics[BackgroundImageId].Texture.X := 500; Statics[BackgroundImageId].Texture.Y := 65; Statics[BackgroundImageId].Texture.W := 80; Statics[BackgroundImageId].Texture.H := 0; if (Not (CurrentSong.Background = PATH_NONE) and CurrentSong.Path.Append(CurrentSong.Background).Exists) then begin log.LogError('background:' + CurrentSong.Background.ToUTF8()); Tex_PrevBackground := Texture.LoadTexture(CurrentSong.Path.Append(CurrentSong.Background)); Texture.AddTexture(Tex_PrevBackground, TEXTURE_TYPE_PLAIN, true); Statics[BackgroundImageId].Texture := Tex_PrevBackground; Statics[BackgroundImageId].Texture.X := theme.EditSub.BackgroundImage.X; Statics[BackgroundImageId].Texture.Y := theme.EditSub.BackgroundImage.Y; Statics[BackgroundImageId].Texture.W := theme.EditSub.BackgroundImage.W; Statics[BackgroundImageId].Texture.H := theme.EditSub.BackgroundImage.H; end; except Log.LogError('Background could not be loaded: ' + CurrentSong.Background.ToNative); Tex_PrevBackground.TexNum := 0; end; //Interaction := 0; TextEditMode := false; TitleEditMode := false; ArtistEditMode := false; editLenghtText := 0; TextPosition := -1; end; function TScreenEditSub.Draw: boolean; var i: integer; lastline, note,Count: integer; notechange: boolean; 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($B1, $7, floor(1.27*SelectsS[VolumeMidiSlideId].SelectedOption)); 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 i := 0 to Lines[0].Line[Lines[0].Current].HighNote do if (Lines[0].Line[Lines[0].Current].Note[i].Start = AktBeat) then begin LastClick := AktBeat; {$IFDEF UseMIDIPort} MidiOut.PutShort($B1, $7, floor(1.27*SelectsS[VolumeMidiSlideId].SelectedOption)); if i > 0 then MidiOut.PutShort(MIDI_NOTEOFF or 1, Lines[0].Line[Lines[0].Current].Note[i-1].Tone + 60, 127); MidiOut.PutShort($91, Lines[0].Line[Lines[0].Current].Note[i].Tone + 60, 127); MidiLastNote := i; {$ENDIF} end; end; end; // if PlaySentenceMidi // move "cursor" if (PlaySentence or PlaySentenceMidi or PlayVideo) then //and Not (PlayNote) then begin if (PlaySentence or PlayVideo) then AktBeat := Floor(GetMidBeat(AudioPlayback.Position - (CurrentSong.GAP) / 1000)); if PlaySentenceMidi then AktBeat := Floor(GetMidBeat(MidiPos - CurrentSong.GAP / 1000)); lastline := Lines[0].Current; repeat //find current line if Lines[0].Line[Lines[0].Current].End_ < AktBeat then inc(Lines[0].Current); until ((Length(Lines[0].Line) = Lines[0].Current) or (Lines[0].Line[Lines[0].Current].End_ >= AktBeat)); if Lines[0].Current <> lastline then begin Lines[0].Line[lastline].Note[CurrentNote].Color := 1; Lyric.AddLine(Lines[0].Current); Lyric.Selected := 0; CurrentNote := 0; ShowInteractiveBackground; GoldenRec.KillAll; end; for note := CurrentNote to Length(Lines[0].Line[Lines[0].Current].note) - 1 do begin //note change if Lines[0].Line[Lines[0].Current].Note[note].Start < AktBeat then begin Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 1; CurrentNote := note; Lyric.Selected := CurrentNote; Lines[0].Line[Lines[0].Current].Note[CurrentNote].Color := 2; end; //if end; //for note} end; //end move cursor // mp3 music if (PlaySentence or PlayVideo) then begin // stop the music if (AudioPlayback.Position > PlayStopTime) then begin AudioPlayback.Stop; PlaySentence := false; PlayVideo := false; StopVideoPreview; 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 i := 0 to Lines[0].Line[Lines[0].Current].HighNote do if (Lines[0].Line[Lines[0].Current].Note[i].Start = AktBeat) then begin SoundLib.Click.Volume := SelectsS[VolumeClickSlideId].SelectedOption / 100; 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); BPMVal[0] := FloatToStr(CurrentSong.BPM[0].BPM / 4); SelectsS[BPMSlideId].TextOpt[0].Text := BPMVal[0]; //Text[TextGAP].Text := FloatToStr(CurrentSong.GAP); GAPVal[0] := FloatToStr(CurrentSong.GAP); SelectsS[GAPSlideId].TextOpt[0].Text := GAPVal[0]; //Error reading Variables when no Song is loaded if not (Error or TitleEditMode or TextEditMode) then begin // Note info //Text[TextNStart].Text := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start); StartVal[0] := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start); SelectsS[StartSlideId].TextOpt[0].Text := StartVal[0]; //Text[TextNLength].Text := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length); DurationVal[0] := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length); SelectsS[DurationSlideId].TextOpt[0].Text := DurationVal[0]; //Text[TextNTon].Text := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone) + ' ( ' + GetNoteName(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone) + ' )'; ToneVal[0] := IntToStr(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone) + ' ( ' + GetNoteName(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Tone) + ' )'; SelectsS[ToneSlideId].TextOpt[0].Text := ToneVal[0]; //Text[TextNText].Text := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text; LyricVal[0] := Lines[0].Line[Lines[0].Current].Note[CurrentNote].Text; SelectsS[LyricSlideId].TextOpt[0].Text := LyricVal[0]; VideoGapVal[0] := floattostr(CurrentSong.VideoGAP); SelectsS[VideoGapSlideId].TextOpt[0].Text := VideoGapVal[0]; end; // Text Edit Mode if TextEditMode or TitleEditMode or ArtistEditMode then begin if TextPosition >= 0 then SelectsS[CurrentSlideId].TextOpt[0].Text := UTF8Copy(CurrentEditText, 1, TextPosition) + '|' + UTF8Copy(CurrentEditText, TextPosition+1, LengthUTF8(CurrentEditText)-TextPosition); editLenghtText := LengthUTF8(SelectsS[CurrentSlideId].TextOpt[0].Text); end; // draw static menu DrawBG; 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); DrawText(40, 410, 760, 0, 15); end; CurrentSound := AudioInputProcessor.Sound[0]; CurrentSound.AnalyzeBuffer; if (CurrentSound.ToneString <> '-') then begin Count := trunc((720 / (GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_) - GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start)))*(AudioPlayback.Position-GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start))); DrawPlayerTrack(0, 16, 32, 15, CurrentSound.Tone, Count,CurrentNote); end; GoldenRec.SpawnRec; // draw text Lyric.Draw; //video if Assigned(fCurrentVideo) then begin fCurrentVideo.GetFrame(CurrentSong.VideoGAP + AudioPlayback.Position); fCurrentVideo.SetScreen(1); fCurrentVideo.Alpha := 1; fCurrentVideo.SetScreenPosition(theme.EditSub.BackgroundImage.X, theme.EditSub.BackgroundImage.Y, 1); fCurrentVideo.Width := theme.EditSub.BackgroundImage.W; fCurrentVideo.Height := theme.EditSub.BackgroundImage.H; fCurrentVideo.ReflectionSpacing := 1; fCurrentVideo.AspectCorrection := acoCrop; fCurrentVideo.Draw; end; Result := true; end; procedure TScreenEditSub.OnHide; begin {$IFDEF UseMIDIPort} MidiOut.Close; MidiOut.Free; {$ENDIF} Lyric.Free; //Music.SetVolume(1.0); AudioInput.CaptureStop; 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.