unit UScreenEditSub;
interface
uses UMenu, UMusic, SDL, SysUtils, UFiles, UTime, USongs, UIni, ULog, USmpeg, UTexture, UMenuText,
ULyrics, Math, gl, UThemes, MidiOut, UHelp;
type
TMedleyNotes = record
start: TPos;
end_: TPos;
Preview: TPos;
isStart: boolean; //start beat is declared
isEnd: boolean; //end beat is declared
end;
TScreenEditSub = class(TMenu)
const
ID='ID_001'; //for help system
private
//Variable is True if no SOng is loaded
Error: Boolean;
MP3Volume: Integer;
TextNote: integer;
TextSentence: integer;
TextTitle: integer;
TextArtist: integer;
TextMp3: integer;
TextBPM: integer;
TextGAP: integer;
TextDebug: integer;
TextNStart: integer;
TextNDlugosc: integer;
TextNTon: integer;
TextNText: integer;
AktNuta: integer;
PlaySentence: boolean;
PlaySentenceMidi: boolean;
PlayStopTime: real;
LastClick: integer;
Click: boolean;
CopySrc: integer;
MidiOut: TMidiOutput;
MidiStart: real;
MidiStop: real;
MidiTime: real;
MidiPos: real;
MidiLastNote: integer;
TextEditMode: boolean;
MedleyNotes: TMedleyNotes;
editText: string; //backup of current text in text-edit-mode
noteStart: integer; //Start note when playing sentence
LineChanged: boolean;
procedure NewBeat;
procedure CzesciDivide;
procedure CzesciMultiply;
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);
//Note Name Mod
function GetNoteName(Note: Integer): String;
function GetMedleyLength: real; //returns if availible the length of the medley in seconds, else 0
public
Tex_Background: TTexture;
FadeOut: boolean;
Path: string;
FileName: string;
SongIndex: integer; //SongIndex from CatSongs.Song
constructor Create; override;
procedure onShow; override;
function ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean; override;
function ParseInputEditText(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean;
function Draw: boolean; override;
procedure onHide; override;
end;
implementation
uses UGraphic, UDraw, UMain, USkins, ULanguage;
// Method for input parsing. If False is returned, GetNextWindow
// should be checked to know the next window to load;
function TScreenEditSub.ParseInput(PressedKey: Cardinal; ScanCode: byte; PressedDown: Boolean): Boolean;
var
SDL_ModState: Word;
R: real;
SResult: boolean;
begin
Result := true;
Text[TextDebug].Text := '';
if TextEditMode then begin
Result := ParseInputEditText(PressedKey, ScanCode, 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 begin // Key Down
case PressedKey of
SDLK_TAB:
begin
ScreenPopupHelp.ShowPopup();
end;
SDLK_ESCAPE:
begin
FadeTo(@ScreenSong);
end;
SDLK_Q:
begin
Result := false;
end;
SDLK_BACKQUOTE:
begin
// Increase Note Length (same as Alt + Right)
Inc(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc);
if AktNuta = Czesci[0].Czesc[Czesci[0].Akt].HighNut then
Inc(Czesci[0].Czesc[Czesci[0].Akt].Koniec);
end;
SDLK_EQUALS:
begin
// Increase BPM
if SDL_ModState = 0 then
AktSong.BPM[0].BPM := Round((AktSong.BPM[0].BPM * 5) + 1) / 5; // (1/20)
if SDL_ModState = KMOD_LSHIFT then
AktSong.BPM[0].BPM := AktSong.BPM[0].BPM + 4; // (1/1)
if SDL_ModState = KMOD_LCTRL then
AktSong.BPM[0].BPM := Round((AktSong.BPM[0].BPM * 25) + 1) / 25; // (1/100)
end;
SDLK_MINUS:
begin
// Decrease BPM
if SDL_ModState = 0 then
AktSong.BPM[0].BPM := Round((AktSong.BPM[0].BPM * 5) - 1) / 5;
if SDL_ModState = KMOD_LSHIFT then
AktSong.BPM[0].BPM := AktSong.BPM[0].BPM - 4;
if SDL_ModState = KMOD_LCTRL then
AktSong.BPM[0].BPM := Round((AktSong.BPM[0].BPM * 25) - 1) / 25;
end;
SDLK_0:
begin
// Increase GAP
if SDL_ModState = 0 then
AktSong.GAP := AktSong.GAP + 10;
if SDL_ModState = KMOD_LSHIFT then
AktSong.GAP := AktSong.GAP + 1000;
end;
SDLK_9:
begin
// Decrease GAP
if SDL_ModState = 0 then
AktSong.GAP := AktSong.GAP - 10;
if SDL_ModState = KMOD_LSHIFT then
AktSong.GAP := AktSong.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 AktNuta > 0 then
DivideSentence;
end;
if SDL_ModState = KMOD_LSHIFT then begin
// Join next sentence with current
if Czesci[0].Akt < Czesci[0].High then
JoinSentence;
end;
if SDL_ModState = KMOD_LCTRL then begin
// divide note
DivideNote;
end;
end;
SDLK_S:
begin
//Medley MOD:
if (MedleyNotes.isStart and MedleyNotes.isEnd) and
(MedleyNotes.start.line < MedleyNotes.end_.line) then
begin
AktSong.Medley.Source := msTag;
AktSong.Medley.StartBeat:=Czesci[0].Czesc[MedleyNotes.start.line].Nuta[MedleyNotes.start.note].Start;
AktSong.Medley.EndBeat:=Czesci[0].Czesc[MedleyNotes.end_.line].Nuta[MedleyNotes.end_.note].Start +
Czesci[0].Czesc[MedleyNotes.end_.line].Nuta[MedleyNotes.end_.note].Dlugosc;
AktSong.Medley.FadeIn_time := DEFAULT_FADE_IN_TIME;
AktSong.Medley.FadeOut_time := DEFAULT_FADE_OUT_TIME;
end else begin
AktSong.Medley.Source := msNone;
AktSong.Medley.StartBeat:=0;
AktSong.Medley.EndBeat:=0;
end;
// Save Song
if SDL_ModState = KMOD_LSHIFT then
begin
if (AktSong.Medley.Source = msTag) then
begin
ScreenPopupError.ShowPopup(Language.Translate('Medley and Relative is not supported!'));
Exit;
end;
SResult := SaveSong(AktSong, Czesci[0], Path + FileName, true); //save with relative
end else
SResult := SaveSong(AktSong, Czesci[0], Path + FileName, false);
if SResult then
begin
Text[TextDebug].Text := Language.Translate('INFO_FILE_SAVED');
CatSongs.Song[SongIndex] := AktSong;
end else
begin
ScreenPopupError.ShowPopup(Language.Translate('ERROR_SAVE_FILE_FAILED'));
end;
Exit;
end;
// set Medley tags
SDLK_A:
begin
if AktSong.Relative then
begin
ScreenPopupError.ShowPopup(Language.Translate('Medley and Relative is not supported!'));
Exit;
end;
if SDL_ModState = KMOD_LSHIFT then //Medley End Note
begin
if MedleyNotes.isEnd then
begin
if (Czesci[0].Akt=MedleyNotes.end_.line) and (AktNuta=MedleyNotes.end_.note) then
begin
MedleyNotes.isEnd := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].IsMedley := false;
end else
begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].IsMedley := true;
Czesci[0].Czesc[MedleyNotes.end_.line].Nuta[MedleyNotes.end_.note].IsMedley := false;
MedleyNotes.end_.line := Czesci[0].Akt;
MedleyNotes.end_.note := AktNuta;
end;
end else
begin
MedleyNotes.isEnd := true;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].IsMedley := true;
MedleyNotes.end_.line := Czesci[0].Akt;
MedleyNotes.end_.note := AktNuta;
end;
end else
begin //Medley Start Note
if MedleyNotes.isStart then
begin
if (Czesci[0].Akt=MedleyNotes.start.line) and (AktNuta=MedleyNotes.start.note) then
begin
MedleyNotes.isStart := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].IsMedley := false;
end else
begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].IsMedley := true;
Czesci[0].Czesc[MedleyNotes.start.line].Nuta[MedleyNotes.start.note].IsMedley := false;
MedleyNotes.start.line := Czesci[0].Akt;
MedleyNotes.start.note := AktNuta;
end;
end else
begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].IsMedley := true;
MedleyNotes.isStart := true;
MedleyNotes.start.line := Czesci[0].Akt;
MedleyNotes.start.note := AktNuta;
end;
end;
//show length of medley
Text[TextDebug].Text := FormatFloat('MedleyLength: #0.00s', GetMedleyLength);
Exit;
end;
// jump to Medley tags
SDLK_J:
begin
if AktSong.Relative then
begin
ScreenPopupError.ShowPopup(Language.Translate('Medley and Relative is not supported!'));
Exit;
end;
if (SDL_ModState = KMOD_LSHIFT) and MedleyNotes.IsEnd then //Medley End Note
begin
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
Czesci[0].Akt := MedleyNotes.end_.line;
AktNuta := MedleyNotes.end_.note;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.AddCzesc(Czesci[0].Akt);
Lyric.Selected := AktNuta;
Music.Stop;
PlaySentence := false;
end else if MedleyNotes.IsStart then
begin
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
Czesci[0].Akt := MedleyNotes.start.line;
AktNuta := MedleyNotes.start.note;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.AddCzesc(Czesci[0].Akt);
Lyric.Selected := AktNuta;
Music.Stop;
PlaySentence := false
end;
if (SDL_ModState = KMOD_LALT) then
begin
PlaySentenceMidi := false;
Music.Stop;
LineChanged:=false;
R := GetTimeFromBeat(Czesci[0].Czesc[MedleyNotes.start.line].Nuta[MedleyNotes.start.note].Start);
if R <= Music.Length then begin
Music.MoveTo(R);
PlayStopTime := GetTimeFromBeat(
Czesci[0].Czesc[MedleyNotes.end_.line].Nuta[MedleyNotes.end_.note].Start +
Czesci[0].Czesc[MedleyNotes.end_.line].Nuta[MedleyNotes.end_.note].Dlugosc);
PlaySentence := true;
Music.Play;
LastClick := -100;
end;
end;
//show length of medley
Text[TextDebug].Text := FormatFloat('MedleyLength: #0.00s', GetMedleyLength);
Exit;
end;
SDLK_K: //Preview Start
begin
if (SDL_ModState = KMOD_LSHIFT) then //jump to...
begin
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
Czesci[0].Akt := MedleyNotes.Preview.line;
AktNuta := MedleyNotes.Preview.note;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.AddCzesc(Czesci[0].Akt);
Lyric.Selected := AktNuta;
Music.Stop;
PlaySentence := false
end else
begin
if (Czesci[0].Akt = MedleyNotes.Preview.line) and (AktNuta = MedleyNotes.Preview.note) then //reset ?
begin
end else //set
begin
Czesci[0].Czesc[MedleyNotes.Preview.line].Nuta[MedleyNotes.Preview.note].IsStartPreview := false;
MedleyNotes.Preview.line := Czesci[0].Akt;
MedleyNotes.Preview.note := AktNuta;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].IsStartPreview := true;
AktSong.PreviewStart := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].start);
end;
end;
end;
SDLK_D:
begin
// Divide lengths by 2
CzesciDivide;
end;
SDLK_M:
begin
// Multiply lengths by 2
CzesciMultiply;
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;
end;
SDLK_R: //reload
begin
onHide;
onShow;
end;
SDLK_V:
begin
// Paste text
if SDL_ModState = KMOD_LCTRL then begin
if Czesci[0].Czesc[Czesci[0].Akt].IlNut >= Czesci[0].Czesc[CopySrc].IlNut then
PasteText
else
beep;
end;
if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then begin
CopySentence(CopySrc, Czesci[0].Akt);
end;
end;
SDLK_4:
begin
if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then begin
CopySentence(CopySrc, Czesci[0].Akt);
CopySentence(CopySrc+1, Czesci[0].Akt+1);
CopySentence(CopySrc+2, Czesci[0].Akt+2);
CopySentence(CopySrc+3, Czesci[0].Akt+3);
end;
if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT + KMOD_LALT then begin
CopySentences(CopySrc, Czesci[0].Akt, 4);
end;
end;
SDLK_5:
begin
if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT then begin
CopySentence(CopySrc, Czesci[0].Akt);
CopySentence(CopySrc+1, Czesci[0].Akt+1);
CopySentence(CopySrc+2, Czesci[0].Akt+2);
CopySentence(CopySrc+3, Czesci[0].Akt+3);
CopySentence(CopySrc+4, Czesci[0].Akt+4);
end;
if SDL_ModState = KMOD_LCTRL + KMOD_LSHIFT + KMOD_LALT then begin
CopySentences(CopySrc, Czesci[0].Akt, 5);
end;
end;
SDLK_T:
begin
// Fixes timings between sentences
FixTimings;
end;
SDLK_F4:
begin
// Enter Text Edit Mode
editText := Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst;
TextEditMode := true;
end;
SDLK_P:
begin
if SDL_ModState = 0 then begin
// Play Sentence
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Click := true;
Music.Stop;
R := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
if R <= Music.Length then begin
Music.MoveTo(R);
PlayStopTime := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Koniec);
PlaySentence := true;
Music.Play;
LastClick := -100;
end;
end;
if SDL_ModState = KMOD_LSHIFT then begin
PlaySentenceMidi := true;
MidiTime := USTime.GetTime;
Music.Stop;
PlaySentence := false;
MidiStart := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
MidiStop := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Koniec);
LastClick := -100;
end;
if SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL then begin
PlaySentenceMidi := true;
MidiTime := USTime.GetTime;
MidiStart := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
MidiStop := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Koniec);
LastClick := -100;
PlaySentence := true;
Click := true;
Music.Stop;
Music.MoveTo(GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].StartNote)+0{-0.10});
PlayStopTime := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Koniec)+0;
Music.Play;
LastClick := -100;
end;
//new: play hole file + LALT
if SDL_ModState = KMOD_LALT then begin
// Play Sentence
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Click := true;
Music.Stop;
R := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
if R <= Music.Length then begin
Music.MoveTo(R);
PlayStopTime := Music.Length;
PlaySentence := true;
Music.Play;
LastClick := -100;
end;
end;
if SDL_ModState = KMOD_LSHIFT or KMOD_LALT then begin
PlaySentenceMidi := true;
Music.Stop;
PlaySentence := false;
MidiTime := USTime.GetTime;
MidiStart := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
MidiStop := Music.Length;
LastClick := -100;
end;
if SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL or KMOD_LALT then begin
PlaySentenceMidi := true;
MidiTime := USTime.GetTime;
MidiStart := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
MidiStop := Music.Length;
LastClick := -100;
PlaySentence := true;
Click := true;
Music.Stop;
Music.MoveTo(GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].StartNote)+0{-0.10});
PlayStopTime := Music.Length;
Music.Play;
LastClick := -100;
end;
if PlaySentenceMidi or PlaySentence then
begin
noteStart := AktNuta;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
AktNuta := 0;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.Selected := AktNuta;
LineChanged:=false;
end;
end;
SDLK_SPACE:
begin
//Thx to f1fth_freed0m for his One Note Midi Playback
if SDL_ModState = KMOD_LSHIFT then begin //Play One Notes Midi [Shift + Space]
PlaySentenceMidi := true;
Music.Stop;
PlaySentence := false;
MidiTime := USTime.GetTime;
MidiStart := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start);
MidiStop := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc);
LastClick := -100;
end
else if SDL_ModState = KMOD_LSHIFT or KMOD_LCTRL then begin
//Play One Notes Midi + MP3 [CTRL + Shift + Space]
PlaySentenceMidi := true;
MidiTime := USTime.GetTime;
MidiStart := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start);
MidiStop := GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc);
LastClick := -100;
PlaySentence := true;
Click := true;
Music.Stop;
Music.MoveTo(GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start));
PlayStopTime := (GetTimeFromBeat(
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start +
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc));
Music.Play;
LastClick := -100;
end
Else
begin
// Play One Notes MP3 [Space]
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false; // stop midi
PlaySentence := true;
Click := false;
Music.Stop;
Music.MoveTo(GetTimeFromBeat(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start));
PlayStopTime := (GetTimeFromBeat(
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start +
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc));
Music.Play;
LastClick := -100;
end;
if PlaySentence or PlaySentenceMidi then
begin
noteStart := AktNuta;
LineChanged:=false;
end;
end;
SDLK_RETURN:
begin
end;
SDLK_LCTRL:
begin
end;
SDLK_DELETE:
begin
if SDL_ModState = KMOD_LCTRL then begin
// moves text to right in current sentence
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
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
Inc(AktNuta);
if AktNuta = Czesci[0].Czesc[Czesci[0].Akt].IlNut then AktNuta := 0;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.Selected := AktNuta;
end;
// ctrl + right
if SDL_ModState = KMOD_LCTRL then begin
if Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc > 1 then begin
Dec(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc);
Inc(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start);
if AktNuta = 0 then begin
Inc(Czesci[0].Czesc[Czesci[0].Akt].Start);
Inc(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
end;
FixTimings;
end;
end;
// shift + right
if SDL_ModState = KMOD_LSHIFT then begin
Inc(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start);
if AktNuta = 0 then begin
Inc(Czesci[0].Czesc[Czesci[0].Akt].Start);
Inc(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
end;
if AktNuta = Czesci[0].Czesc[Czesci[0].Akt].HighNut then
Inc(Czesci[0].Czesc[Czesci[0].Akt].Koniec);
FixTimings;
end;
// alt + right
if SDL_ModState = KMOD_LALT then begin
Inc(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc);
if AktNuta = Czesci[0].Czesc[Czesci[0].Akt].HighNut then
Inc(Czesci[0].Czesc[Czesci[0].Akt].Koniec);
FixTimings;
end;
// alt + ctrl + shift + right = move all from cursor to right
if SDL_ModState = KMOD_LALT + KMOD_LCTRL + KMOD_LSHIFT then begin
MoveAllToEnd(1);
FixTimings;
end;
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Music.Stop;
LineChanged:=false;
PlaySentence := false;
end;
SDLK_LEFT:
begin
// left
if SDL_ModState = 0 then begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
Dec(AktNuta);
if AktNuta = -1 then AktNuta := Czesci[0].Czesc[Czesci[0].Akt].HighNut;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.Selected := AktNuta;
end;
// ctrl + left
if SDL_ModState = KMOD_LCTRL then begin
Dec(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start);
Inc(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc);
if AktNuta = 0 then begin
Dec(Czesci[0].Czesc[Czesci[0].Akt].Start);
Dec(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
end;
FixTimings;
end;
// shift + left
if SDL_ModState = KMOD_LSHIFT then begin
Dec(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start);
// resizing sentences
if AktNuta = 0 then begin
Dec(Czesci[0].Czesc[Czesci[0].Akt].Start);
Dec(Czesci[0].Czesc[Czesci[0].Akt].StartNote);
end;
if AktNuta = Czesci[0].Czesc[Czesci[0].Akt].HighNut then
Dec(Czesci[0].Czesc[Czesci[0].Akt].Koniec);
FixTimings;
end;
// alt + left
if SDL_ModState = KMOD_LALT then begin
if Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc > 1 then begin
Dec(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc);
if AktNuta = Czesci[0].Czesc[Czesci[0].Akt].HighNut then
Dec(Czesci[0].Czesc[Czesci[0].Akt].Koniec);
end;
FixTimings;
end;
// alt + ctrl + shift + right = move all from cursor to left
if SDL_ModState = KMOD_LALT + KMOD_LCTRL + KMOD_LSHIFT then begin
MoveAllToEnd(-1);
FixTimings;
end;
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Music.Stop;
LineChanged:=false;
PlaySentence := false;
end;
SDLK_DOWN:
begin
// skip to next sentence
if SDL_ModState = 0 then begin
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
Inc(Czesci[0].Akt);
AktNuta := 0;
if Czesci[0].Akt > Czesci[0].High then
Czesci[0].Akt := 0;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.AddCzesc(Czesci[0].Akt);
Lyric.Selected := 0;
Music.Stop;
PlaySentence := false;
end;
// decrease tone
if SDL_ModState = KMOD_LCTRL then begin
TransposeNote(-1);
end;
end;
SDLK_UP:
begin
// skip to previous sentence
if SDL_ModState = 0 then begin
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
Dec(Czesci[0].Akt);
AktNuta := 0;
if Czesci[0].Akt = -1 then
Czesci[0].Akt := Czesci[0].High;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.AddCzesc(Czesci[0].Akt);
Lyric.Selected := 0;
Music.Stop;
PlaySentence := false;
end;
// increase tone
if SDL_ModState = KMOD_LCTRL then begin
TransposeNote(1);
end;
end;
// Golden Note Patch
SDLK_G:
begin
case Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Wartosc of
0, 1: Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Wartosc := 2;
2: Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Wartosc := 1;
end; // case
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Freestyle := False;
end;
// Freestyle Note Patch
SDLK_F:
begin
case Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Wartosc of
0:
begin;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Wartosc := 1;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Freestyle := False;
end;
1,2:
begin;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Wartosc := 0;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Freestyle := True;
end;
end; // case
end;
//MP3-Volume Up
SDLK_PAGEUP:
begin
if (MP3Volume<100) then
MP3Volume := MP3Volume+5;
Music.SetMusicVolume(MP3Volume);
Text[TextDebug].Text := 'MP3 Volume: ' + IntToStr(MP3Volume) + '%';
end;
//MP3-Volume Down
SDLK_PAGEDOWN:
begin
if (MP3Volume>0) then
MP3Volume := MP3Volume-5;
Music.SetMusicVolume(MP3Volume);
Text[TextDebug].Text := 'MP3 Volume: ' + IntToStr(MP3Volume) + '%';
end;
end;
end;
end; // if
end;
function TScreenEditSub.ParseInputEditText(PressedKey: Cardinal; ScanCode: byte; 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 Ini.Debug=1 then
Text[TextDebug].Text := 'PressedKey: ' + IntToStr(PressedKey) + ' ScanCode: ' + IntToStr(ScanCode);
// check normal keys
if not (ScanCode in [0..31, 127..159]) then //=isPrintable
begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst :=
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst + chr(ScanCode);
Lyric.ChangeCurText(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst);
Lyric.AddCzesc(Czesci[0].Akt);
Exit;
end;
If (PressedDown) Then
begin // Key Down
case PressedKey of
SDLK_ESCAPE:
begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst := editText;
Lyric.AddCzesc(Czesci[0].Akt);
TextEditMode := false;
end;
SDLK_F4, SDLK_RETURN:
begin
// Exit Text Edit Mode
TextEditMode := false;
end;
SDLK_BACKSPACE:
begin
Delete(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst,
Length(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst), 1);
Lyric.ChangeCurText(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst);
Lyric.AddCzesc(Czesci[0].Akt);
end;
SDLK_RIGHT:
begin
// right
if SDL_ModState = 0 then begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
Inc(AktNuta);
if AktNuta = Czesci[0].Czesc[Czesci[0].Akt].IlNut then AktNuta := 0;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.Selected := AktNuta;
editText := Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst;
end;
end;
SDLK_LEFT:
begin
// left
if SDL_ModState = 0 then begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
Dec(AktNuta);
if AktNuta = -1 then AktNuta := Czesci[0].Czesc[Czesci[0].Akt].HighNut;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.Selected := AktNuta;
editText := Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst;
end;
end;
end;
end;
end;
procedure TScreenEditSub.NewBeat;
begin
// click
{ for Pet := 0 to Czesci[0].Czesc[Czesci[0].Akt].HighNut do
if (Czesci[0].Czesc[Czesci[0].Akt].Nuta[Pet].Start = Czas.AktBeat) then begin
// old}
// Music.PlayClick;
end;
procedure TScreenEditSub.CzesciDivide;
var
C: integer;
N: integer;
begin
AktSong.BPM[0].BPM := AktSong.BPM[0].BPM / 2;
for C := 0 to Czesci[0].High do begin
Czesci[0].Czesc[C].Start := Czesci[0].Czesc[C].Start div 2;
Czesci[0].Czesc[C].StartNote := Czesci[0].Czesc[C].StartNote div 2;
Czesci[0].Czesc[C].Koniec := Czesci[0].Czesc[C].Koniec div 2;
for N := 0 to Czesci[0].Czesc[C].HighNut do begin
Czesci[0].Czesc[C].Nuta[N].Start := Czesci[0].Czesc[C].Nuta[N].Start div 2;
Czesci[0].Czesc[C].Nuta[N].Dlugosc := Round(Czesci[0].Czesc[C].Nuta[N].Dlugosc / 2);
end; // N
end; // C
end;
procedure TScreenEditSub.CzesciMultiply;
var
C: integer;
N: integer;
begin
AktSong.BPM[0].BPM := AktSong.BPM[0].BPM * 2;
for C := 0 to Czesci[0].High do begin
Czesci[0].Czesc[C].Start := Czesci[0].Czesc[C].Start * 2;
Czesci[0].Czesc[C].StartNote := Czesci[0].Czesc[C].StartNote * 2;
Czesci[0].Czesc[C].Koniec := Czesci[0].Czesc[C].Koniec * 2;
for N := 0 to Czesci[0].Czesc[C].HighNut do begin
Czesci[0].Czesc[C].Nuta[N].Start := Czesci[0].Czesc[C].Nuta[N].Start * 2;
Czesci[0].Czesc[C].Nuta[N].Dlugosc := Czesci[0].Czesc[C].Nuta[N].Dlugosc * 2;
end; // N
end; // C
end;
procedure TScreenEditSub.LyricsCapitalize;
var
C: integer;
N: integer; // temporary
S: string;
begin
// temporary
{ for C := 0 to Czesci[0].High do
for N := 0 to Czesci[0].Czesc[C].HighNut do
Czesci[0].Czesc[C].Nuta[N].Tekst := AnsiLowerCase(Czesci[0].Czesc[C].Nuta[N].Tekst);}
for C := 0 to Czesci[0].High do begin
S := AnsiUpperCase(Copy(Czesci[0].Czesc[C].Nuta[0].Tekst, 1, 1));
S := S + Copy(Czesci[0].Czesc[C].Nuta[0].Tekst, 2, Length(Czesci[0].Czesc[C].Nuta[0].Tekst)-1);
Czesci[0].Czesc[C].Nuta[0].Tekst := S;
end; // C
Lyric.AddCzesc(Czesci[0].Akt);
end;
procedure TScreenEditSub.LyricsCorrectSpaces;
var
C: integer;
N: integer;
begin
for C := 0 to Czesci[0].High do begin
// correct starting spaces in the first word
while Copy(Czesci[0].Czesc[C].Nuta[0].Tekst, 1, 1) = ' ' do
Czesci[0].Czesc[C].Nuta[0].Tekst := Copy(Czesci[0].Czesc[C].Nuta[0].Tekst, 2, 100);
// move spaces on the start to the end of the previous note
for N := 1 to Czesci[0].Czesc[C].HighNut do begin
while (Copy(Czesci[0].Czesc[C].Nuta[N].Tekst, 1, 1) = ' ') do begin
Czesci[0].Czesc[C].Nuta[N].Tekst := Copy(Czesci[0].Czesc[C].Nuta[N].Tekst, 2, 100);
Czesci[0].Czesc[C].Nuta[N-1].Tekst := Czesci[0].Czesc[C].Nuta[N-1].Tekst + ' ';
end;
end; // N
// correct '-' to '- '
for N := 0 to Czesci[0].Czesc[C].HighNut do begin
if Czesci[0].Czesc[C].Nuta[N].Tekst = '-' then
Czesci[0].Czesc[C].Nuta[N].Tekst := '- ';
end; // N
// add space to the previous note when the current word is '- '
for N := 1 to Czesci[0].Czesc[C].HighNut do begin
if Czesci[0].Czesc[C].Nuta[N].Tekst = '- ' then
Czesci[0].Czesc[C].Nuta[N-1].Tekst := Czesci[0].Czesc[C].Nuta[N-1].Tekst + ' ';
end; // N
// correct too many spaces at the end of note
for N := 0 to Czesci[0].Czesc[C].HighNut do begin
while Copy(Czesci[0].Czesc[C].Nuta[N].Tekst, Length(Czesci[0].Czesc[C].Nuta[N].Tekst)-1, 2) = ' ' do
Czesci[0].Czesc[C].Nuta[N].Tekst := Copy(Czesci[0].Czesc[C].Nuta[N].Tekst, 1, Length(Czesci[0].Czesc[C].Nuta[N].Tekst)-1);
end; // N
// and correct if there is no space at the end of sentence
N := Czesci[0].Czesc[C].HighNut;
if Copy(Czesci[0].Czesc[C].Nuta[N].Tekst, Length(Czesci[0].Czesc[C].Nuta[N].Tekst), 1) <> ' ' then
Czesci[0].Czesc[C].Nuta[N].Tekst := Czesci[0].Czesc[C].Nuta[N].Tekst + ' ';
end; // C
Lyric.AddCzesc(Czesci[0].Akt);
end;
procedure TScreenEditSub.FixTimings;
var
C: integer;
S: integer;
Min: integer;
Max: integer;
begin
for C := 1 to Czesci[0].High do begin
with Czesci[0].Czesc[C-1] do begin
Min := Nuta[HighNut].Start + Nuta[HighNut].Dlugosc;
Max := Czesci[0].Czesc[C].StartNote;
case (Max - Min) of
0: S := Max;
1: S := Max;
2: S := Max - 1;
3: S := Max - 2;
else
S := Min + 2;
end; // case
Czesci[0].Czesc[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;
NNewL: integer;
begin
// increase sentence length by 1
CLen := Length(Czesci[0].Czesc);
SetLength(Czesci[0].Czesc, CLen + 1);
Inc(Czesci[0].Ilosc);
Inc(Czesci[0].High);
// move needed sentences to one forward. newly has the copy of divided sentence
CStart := Czesci[0].Akt;
for C := CLen-1 downto CStart do
Czesci[0].Czesc[C+1] := Czesci[0].Czesc[C];
// clear and set new sentence
CNew := CStart + 1;
NStart := AktNuta;
Czesci[0].Czesc[CNew].Start := Czesci[0].Czesc[CStart].Nuta[NStart].Start;
Czesci[0].Czesc[CNew].StartNote := Czesci[0].Czesc[CStart].Nuta[NStart].Start;
Czesci[0].Czesc[CNew].Lyric := '';
Czesci[0].Czesc[CNew].LyricWidth := 0;
Czesci[0].Czesc[CNew].Koniec := 0;
Czesci[0].Czesc[CNew].BaseNote := 0; // 0.5.0: we modify it later in this procedure
Czesci[0].Czesc[CNew].IlNut := 0;
Czesci[0].Czesc[CNew].HighNut := -1;
SetLength(Czesci[0].Czesc[CNew].Nuta, 0);
// move right notes to new sentences
NHigh := Czesci[0].Czesc[CStart].HighNut;
for N := NStart to NHigh do begin
NNewL := Czesci[0].Czesc[CNew].IlNut;
SetLength(Czesci[0].Czesc[CNew].Nuta, NNewL + 1);
Czesci[0].Czesc[CNew].Nuta[NNewL] := Czesci[0].Czesc[CStart].Nuta[N];
// increase sentence counters
Inc(Czesci[0].Czesc[CNew].IlNut);
Inc(Czesci[0].Czesc[CNew].HighNut);
Czesci[0].Czesc[CNew].Koniec := Czesci[0].Czesc[CNew].Nuta[NNewL].Start +
Czesci[0].Czesc[CNew].Nuta[NNewL].Dlugosc;
end;
// clear old notes and set sentence counters
Czesci[0].Czesc[CStart].HighNut := NStart - 1;
Czesci[0].Czesc[CStart].IlNut := Czesci[0].Czesc[CStart].HighNut + 1;
Czesci[0].Czesc[CStart].Koniec := Czesci[0].Czesc[CStart].Nuta[NStart-1].Start +
Czesci[0].Czesc[CStart].Nuta[NStart-1].Dlugosc;
SetLength(Czesci[0].Czesc[CStart].Nuta, Czesci[0].Czesc[CStart].IlNut);
// 0.5.0: modify BaseNote
Czesci[0].Czesc[CNew].BaseNote := 120;
for N := 0 to Czesci[0].Czesc[CNew].IlNut do
if Czesci[0].Czesc[CNew].Nuta[N].Ton < Czesci[0].Czesc[CNew].BaseNote then
Czesci[0].Czesc[CNew].BaseNote := Czesci[0].Czesc[CNew].Nuta[N].Ton;
Czesci[0].Akt := Czesci[0].Akt + 1;
AktNuta := 0;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.AddCzesc(Czesci[0].Akt);
end;
procedure TScreenEditSub.JoinSentence;
var
C: integer;
N: integer;
NStart: integer;
NDst: integer;
begin
C := Czesci[0].Akt;
// set new sentence
NStart := Czesci[0].Czesc[C].IlNut;
Czesci[0].Czesc[C].IlNut := Czesci[0].Czesc[C].IlNut + Czesci[0].Czesc[C+1].IlNut;
Czesci[0].Czesc[C].HighNut := Czesci[0].Czesc[C].HighNut + Czesci[0].Czesc[C+1].IlNut;
SetLength(Czesci[0].Czesc[C].Nuta, Czesci[0].Czesc[C].IlNut);
// move right notes to new sentences
for N := 0 to Czesci[0].Czesc[C+1].HighNut do begin
NDst := NStart + N;
Czesci[0].Czesc[C].Nuta[NDst] := Czesci[0].Czesc[C+1].Nuta[N];
end;
// increase sentence counters
NDst := Czesci[0].Czesc[C].HighNut;
Czesci[0].Czesc[C].Koniec := Czesci[0].Czesc[C].Nuta[NDst].Start +
Czesci[0].Czesc[C].Nuta[NDst].Dlugosc;
// move needed sentences to one backward.
for C := Czesci[0].Akt + 1 to Czesci[0].High - 1 do
Czesci[0].Czesc[C] := Czesci[0].Czesc[C+1];
// increase sentence length by 1
SetLength(Czesci[0].Czesc, Length(Czesci[0].Czesc) - 1);
Dec(Czesci[0].Ilosc);
Dec(Czesci[0].High);
Lyric.AddCzesc(Czesci[0].Akt);
end;
procedure TScreenEditSub.DivideNote;
var
C: integer;
N: integer;
NLen: integer;
begin
C := Czesci[0].Akt;
NLen := Czesci[0].Czesc[C].IlNut + 1;
SetLength(Czesci[0].Czesc[C].Nuta, NLen);
Inc(Czesci[0].Czesc[C].HighNut);
Inc(Czesci[0].Czesc[C].IlNut);
// we copy all notes including selected one
for N := Czesci[0].Czesc[C].HighNut downto AktNuta+1 do begin
Czesci[0].Czesc[C].Nuta[N] := Czesci[0].Czesc[C].Nuta[N-1];
end;
// me slightly modify new note
Czesci[0].Czesc[C].Nuta[AktNuta].Dlugosc := 1;
Inc(Czesci[0].Czesc[C].Nuta[AktNuta+1].Start);
Dec(Czesci[0].Czesc[C].Nuta[AktNuta+1].Dlugosc);
Czesci[0].Czesc[C].Nuta[AktNuta+1].Tekst := '- ';
Czesci[0].Czesc[C].Nuta[AktNuta+1].Color := 2;
Lyric.AddCzesc(Czesci[0].Akt);
end;
procedure TScreenEditSub.DeleteNote;
var
C: integer;
N: integer;
NLen: integer;
begin
C := Czesci[0].Akt;
//Do Not delete Last Note
if (Czesci[0].High > 0) OR (Czesci[0].Czesc[C].HighNut > 0) then
begin
// we copy all notes from the next to the selected one
for N := AktNuta+1 to Czesci[0].Czesc[C].HighNut do begin
Czesci[0].Czesc[C].Nuta[N-1] := Czesci[0].Czesc[C].Nuta[N];
end;
NLen := Czesci[0].Czesc[C].IlNut - 1;
if (NLen > 0) then
begin
SetLength(Czesci[0].Czesc[C].Nuta, NLen);
Dec(Czesci[0].Czesc[C].HighNut);
Dec(Czesci[0].Czesc[C].IlNut);
// me slightly modify new note
if AktNuta > Czesci[0].Czesc[C].HighNut then Dec(AktNuta);
Czesci[0].Czesc[C].Nuta[AktNuta].Color := 2;
end
//Last Note of current Sentence Deleted - > Delete Sentence
else
begin
//Move all Sentences after the current to the Left
for N := C+1 to Czesci[0].High do
Czesci[0].Czesc[N-1] := Czesci[0].Czesc[N];
//Delete Last Sentence
SetLength(Czesci[0].Czesc, Czesci[0].High);
Czesci[0].High := High(Czesci[0].Czesc);
Czesci[0].Ilosc := Length(Czesci[0].Czesc);
AktNuta := 0;
if (C > 0) then
Czesci[0].Akt := C - 1
else
Czesci[0].Akt := 0;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
end;
end;
Lyric.AddCzesc(Czesci[0].Akt);
end;
procedure TScreenEditSub.TransposeNote(Transpose: integer);
begin
Inc(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Ton, Transpose);
end;
procedure TScreenEditSub.ChangeWholeTone(Tone: integer);
var
C: integer;
N: integer;
begin
for C := 0 to Czesci[0].High do begin
Czesci[0].Czesc[C].BaseNote := Czesci[0].Czesc[C].BaseNote + Tone;
for N := 0 to Czesci[0].Czesc[C].HighNut do
Czesci[0].Czesc[C].Nuta[N].Ton := Czesci[0].Czesc[C].Nuta[N].Ton + Tone;
end;
end;
procedure TScreenEditSub.MoveAllToEnd(Move: integer);
var
C: integer;
N: integer;
NStart: integer;
begin
for C := Czesci[0].Akt to Czesci[0].High do begin
NStart := 0;
if C = Czesci[0].Akt then NStart := AktNuta;
for N := NStart to Czesci[0].Czesc[C].HighNut do begin
Inc(Czesci[0].Czesc[C].Nuta[N].Start, Move); // move note start
if N = 0 then begin // fix beginning
Inc(Czesci[0].Czesc[C].Start, Move);
Inc(Czesci[0].Czesc[C].StartNote, Move);
end;
if N = Czesci[0].Czesc[C].HighNut then // fix ending
Inc(Czesci[0].Czesc[C].Koniec, Move);
end; // for
end; // for
Lyric.AddCzesc(Czesci[0].Akt);
end;
procedure TScreenEditSub.MoveTextToRight;
var
C: integer;
N: integer;
NHigh: integer;
begin
{ C := Czesci[0].Akt;
for N := Czesci[0].Czesc[C].HighNut downto 1 do begin
Czesci[0].Czesc[C].Nuta[N].Tekst := Czesci[0].Czesc[C].Nuta[N-1].Tekst;
end; // for
Czesci[0].Czesc[C].Nuta[0].Tekst := '- ';}
C := Czesci[0].Akt;
NHigh := Czesci[0].Czesc[C].HighNut;
// last word
Czesci[0].Czesc[C].Nuta[NHigh].Tekst := Czesci[0].Czesc[C].Nuta[NHigh-1].Tekst + Czesci[0].Czesc[C].Nuta[NHigh].Tekst;
// other words
for N := NHigh - 1 downto AktNuta + 1 do begin
Czesci[0].Czesc[C].Nuta[N].Tekst := Czesci[0].Czesc[C].Nuta[N-1].Tekst;
end; // for
Czesci[0].Czesc[C].Nuta[AktNuta].Tekst := '- ';
Lyric.AddCzesc(Czesci[0].Akt);
end;
procedure TScreenEditSub.MarkSrc;
begin
CopySrc := Czesci[0].Akt;
end;
procedure TScreenEditSub.PasteText;
var
C: integer;
N: integer;
begin
C := Czesci[0].Akt;
for N := 0 to Czesci[0].Czesc[CopySrc].HighNut do
Czesci[0].Czesc[C].Nuta[N].Tekst := Czesci[0].Czesc[CopySrc].Nuta[N].Tekst;
Lyric.AddCzesc(Czesci[0].Akt);
end;
procedure TScreenEditSub.CopySentence(Src, Dst: integer);
var
N: integer;
Time1: integer;
Time2: integer;
TD: integer;
begin
Time1 := Czesci[0].Czesc[Src].Nuta[0].Start;
Time2 := Czesci[0].Czesc[Dst].Nuta[0].Start;
TD := Time2-Time1;
SetLength(Czesci[0].Czesc[Dst].Nuta, Czesci[0].Czesc[Src].IlNut);
Czesci[0].Czesc[Dst].IlNut := Czesci[0].Czesc[Src].IlNut;
Czesci[0].Czesc[Dst].HighNut := Czesci[0].Czesc[Src].HighNut;
for N := 0 to Czesci[0].Czesc[Src].HighNut do begin
Czesci[0].Czesc[Dst].Nuta[N].Tekst := Czesci[0].Czesc[Src].Nuta[N].Tekst;
Czesci[0].Czesc[Dst].Nuta[N].Dlugosc := Czesci[0].Czesc[Src].Nuta[N].Dlugosc;
Czesci[0].Czesc[Dst].Nuta[N].Ton := Czesci[0].Czesc[Src].Nuta[N].Ton;
Czesci[0].Czesc[Dst].Nuta[N].Start := Czesci[0].Czesc[Src].Nuta[N].Start + TD;
end;
N := Czesci[0].Czesc[Src].HighNut;
Czesci[0].Czesc[Dst].Koniec := Czesci[0].Czesc[Dst].Nuta[N].Start + Czesci[0].Czesc[Dst].Nuta[N].Dlugosc;
end;
procedure TScreenEditSub.CopySentences(Src, Dst, Num: integer);
var
C: integer;
begin
// create place for new sentences
SetLength(Czesci[0].Czesc, Czesci[0].Ilosc + Num - 1);
// moves sentences next to the destination
for C := Czesci[0].High downto Dst + 1 do begin
Czesci[0].Czesc[C + Num - 1] := Czesci[0].Czesc[C];
end;
// prepares new sentences: sets sentence start and create first note
for C := 1 to Num-1 do begin
Czesci[0].Czesc[Dst + C].Start := Czesci[0].Czesc[Dst + C - 1].StartNote +
(Czesci[0].Czesc[Src + C].StartNote - Czesci[0].Czesc[Src + C - 1].StartNote);
SetLength(Czesci[0].Czesc[Dst + C].Nuta, 1);
Czesci[0].Czesc[Dst + C].IlNut := 1;
Czesci[0].Czesc[Dst + C].HighNut := 0;
Czesci[0].Czesc[Dst + C].Nuta[0].Start := Czesci[0].Czesc[Dst + C].Start;
Czesci[0].Czesc[Dst + C].Nuta[0].Dlugosc := 1;
Czesci[0].Czesc[Dst + C].StartNote := Czesci[0].Czesc[Dst + C].Start;
Czesci[0].Czesc[Dst + C].Koniec := Czesci[0].Czesc[Dst + C].Start + 1;
end;
// increase counters
Czesci[0].Ilosc := Czesci[0].Ilosc + Num - 1;
Czesci[0].High := Czesci[0].High + Num - 1;
for C := 0 to Num-1 do
CopySentence(Src + C, Dst + C);
end;
constructor TScreenEditSub.Create;
begin
inherited Create;
SetLength(Player, 1);
//Theme:
//bg
AddStatic(0, 0, 800, 600, 0.3, 0.5, 0.6, Skin.GetTextureFileName('ButtonFade'), 'JPG', 'Font Black');
// Line
AddStatic(20, 5, 200, 40, 0.95, 0.95, 0.95, Skin.GetTextureFileName('ButtonFade'), 'JPG', 'Font Black');
AddText(40, 14, 1, 8, 0, 0, 0, 'Line:');
TextSentence := AddText(110, 14, 1, 8, 0, 0, 0, '0 / 0');
// Note
AddStatic(260, 5, 200, 40, 0.95, 0.95, 0.95, Skin.GetTextureFileName('ButtonFade'), 'JPG', 'Font Black');
AddText(282, 14, 1, 8, 0, 0, 0, 'Note:');
TextNote := AddText(360, 14, 1, 8, 0, 0, 0, '0 / 0');
// some borders
AddStatic(18, 53, 764, 240, 0, 0, 0, Skin.GetTextureFileName('ButtonFade'), 'JPG', 'Font Black');
AddStatic(20, 55, 760, 236, 0.95, 0.95, 0.95, Skin.GetTextureFileName('ButtonFade'), 'JPG', 'Font Black');
AddStatic(18, 303, 764, 139, 0, 0, 0, Skin.GetTextureFileName('ButtonFade'), 'JPG', 'Font Black');
AddStatic(20, 305, 760, 135, 0.95, 0.95, 0.95, Skin.GetTextureFileName('ButtonFade'), 'JPG', 'Font Black');
AddStatic(18, 498, 764, 44, 0, 0, 0, Skin.GetTextureFileName('ButtonFade'), 'JPG', 'Font Black');
AddStatic(20, 500, 760, 40, 0.95, 0.95, 0.95, Skin.GetTextureFileName('ButtonFade'), 'JPG', 'Font Black');
AddText(30, 65, 0, 8, 0, 0, 0, 'Title:');
AddText(30, 90, 0, 8, 0, 0, 0, 'Artist:');
AddText(30, 115, 0, 8, 0, 0, 0, 'Mp3:');
AddText(30, 140, 0, 8, 0, 0, 0, 'BPM:');
AddText(30, 165, 0, 8, 0, 0, 0, 'GAP:');
TextTitle := AddText(180, 65, 0, 8, 0, 0, 0, 'a');
TextArtist := AddText(180, 90, 0, 8, 0, 0, 0, 'b');
TextMp3 := AddText(180, 115, 0, 8, 0, 0, 0, 'c');
TextBPM := AddText(180, 140, 0, 8, 0, 0, 0, 'd');
TextGAP := AddText(180, 165, 0, 8, 0, 0, 0, 'e');
{ AddInteraction(2, TextTitle);
AddInteraction(2, TextArtist);
AddInteraction(2, TextMp3);
AddInteraction(2, TextBPM);
AddInteraction(2, TextGAP);}
// note info
AddText(30, 190, 0, 8, 0, 0, 0, 'Start:');
AddText(30, 215, 0, 8, 0, 0, 0, 'Duration:');
AddText(30, 240, 0, 8, 0, 0, 0, 'Tone:');
AddText(30, 265, 0, 8, 0, 0, 0, 'Text:');
TextNStart := AddText(180, 190, 0, 8, 0, 0, 0, 'a');
TextNDlugosc := AddText(180, 215, 0, 8, 0, 0, 0, 'b');
TextNTon := AddText(180, 240, 0, 8, 0, 0, 0, 'c');
TextNText := AddText(180, 265, 0, 8, 0, 0, 0, 'd');
// debug
TextDebug := AddText(30, 550, 0, 9, 0, 0, 0, '');
end;
procedure TScreenEditSub.onShow;
begin
Log.LogStatus('Initializing', 'TEditScreen.onShow');
try
ResetSingTemp;
AktSong := CatSongs.Song[SongIndex];
Error := not LoadSong(Path + FileName, SONG_LOAD_COMPLETE);
if not Error then
FindRefrainStart(AktSong);
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
MidiOut := TMidiOutput.Create(nil);
MidiOut.Open;
//Set Volume
MP3Volume := 50;
Music.SetVolume(MP3Volume);
if not Help.SetHelpID(ID) then
Log.LogError('No Entry for Help-ID ' + ID + ' (ScreenEditSub)');
Text[TextTitle].Text := AktSong.Title;
Text[TextArtist].Text := AktSong.Artist;
Text[TextMp3].Text := AktSong.Mp3;
Czesci[0].Akt := 0;
AktNuta := 0;
noteStart := 0; //when playing sentence
Czesci[0].Czesc[0].Nuta[0].Color := 2;
if AktSong.Medley.Source <> msNone then
begin
MedleyNotes.isStart := true;
MedleyNotes.isEnd := true;
MedleyNotes.start := FindNote(AktSong.Medley.StartBeat);
MedleyNotes.end_ := FindNote(AktSong.Medley.EndBeat);
Czesci[0].Czesc[MedleyNotes.start.line].Nuta[MedleyNotes.start.note].IsMedley := true;
Czesci[0].Czesc[MedleyNotes.end_.line].Nuta[MedleyNotes.end_.note].IsMedley := true;
end;
//set Preview Start
MedleyNotes.Preview := FindNote(round(GetMidBeat(AktSong.PreviewStart-AktSong.Gap/1000)));
Czesci[0].Czesc[MedleyNotes.Preview.line].Nuta[MedleyNotes.Preview.note].IsStartPreview := true;
AktSong.PreviewStart := GetTimeFromBeat(Czesci[0].Czesc[MedleyNotes.Preview.line].Nuta[MedleyNotes.Preview.note].start);
Music.Open(Path + AktSong.Mp3);
//Set Down Music Volume for Better hearability of Midi Sounds
//Music.SetVolume(40);
Lyric.Clear;
Lyric.X := 400;
Lyric.Y := 500;
Lyric.Align := 1;
Lyric.Size := 14;
Lyric.ColR := 0;
Lyric.ColG := 0;
Lyric.ColB := 0;
Lyric.ColSR := Skin_FontHighlightR;
Lyric.ColSG := Skin_FontHighlightG;
Lyric.ColSB := Skin_FontHighlightB;
Lyric.Style := 0;
Lyric.AddCzesc(0);
Lyric.Selected := 0;
NotesH := 7;
NotesW := 4;
end;
// Interaction := 0;
TextEditMode := false;
end;
function TScreenEditSub.Draw: boolean;
var
Min: integer;
Sec: integer;
Tekst: string;
Pet: integer;
AktBeat: integer;
PlayClick: boolean;
line, note: integer;
end_: boolean;
begin
glClearColor(1,1,1,1);
PlayClick := false;
if PlaySentenceMidi or PlaySentence then
begin
MidiPos := USTime.GetTime - MidiTime + MidiStart;
// click
if PlaySentence then
begin
AktBeat := Floor(GetMidBeat(Music.Position - AktSong.GAP / 1000));
if Music.Position>PlayStopTime then
end_ := true
else
end_ := false;
end else
begin
AktBeat := Floor(GetMidBeat(MidiPos - AktSong.GAP / 1000));
if MidiPos>MidiStop then
end_ := true
else
end_ := false;
end;
if AktBeat <> LastClick then
begin
for line := 0 to Length(Czesci[0].Czesc) - 1 do
begin
for note := 0 to Length(Czesci[0].Czesc[line].Nuta) - 1 do
begin
//line change
if (Czesci[0].Czesc[line].Start = AktBeat) and (line <> Czesci[0].Akt) and not end_ then
begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
AktNuta := 0;
Inc(Czesci[0].Akt);
if Czesci[0].Akt > Length(Czesci[0].Czesc)-1 then //useful?
Czesci[0].Akt := 0;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 1;
Lyric.AddCzesc(Czesci[0].Akt);
Lyric.Selected := AktNuta;
LineChanged := true;
end;
if (Czesci[0].Czesc[line].Nuta[note].Start = AktBeat) then
begin
LastClick := AktBeat;
PlayClick := true;
end;
end;
end;
end;
end else
LineChanged := false;
// midi music
if PlaySentenceMidi then begin
// stop the music
if end_ then begin
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[MidiLastNote].Ton + 60, 127);
PlaySentenceMidi := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
AktNuta := noteStart;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.Selected := AktNuta;
end;
// click
Text[TextDebug].Text := IntToStr(AktBeat);
if PlayClick then
begin
for Pet := 0 to Czesci[0].Czesc[Czesci[0].Akt].HighNut do
if (Czesci[0].Czesc[Czesci[0].Akt].Nuta[Pet].Start = AktBeat) then
begin
if Pet > 0 then
MidiOut.PutShort($81, Czesci[0].Czesc[Czesci[0].Akt].Nuta[Pet-1].Ton + 60, 127);
MidiOut.PutShort($91, Czesci[0].Czesc[Czesci[0].Akt].Nuta[Pet].Ton + 60, 127);
MidiLastNote := Pet;
end;
end;
end; // if PlaySentenceMidi
// mp3 music
if PlaySentence then
begin
// stop the music
if end_ then begin
Music.Stop;
PlaySentence := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
AktNuta := noteStart;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.Selected := AktNuta;
end;
if (Click) and (PlaySentence) then
begin
Text[TextDebug].Text := IntToStr(AktBeat);
if PlayClick then
Music.PlayClick;
end; // click
end;
// move "cursor"
if (PlaySentence or PlaySentenceMidi) then
begin
for line := 0 to Length(Czesci[0].Czesc) - 1 do
begin
for note := 0 to Length(Czesci[0].Czesc[line].Nuta) - 1 do
begin
//note change
if (Czesci[0].Czesc[line].Nuta[note].Start = AktBeat) and
((note <> AktNuta) or LineChanged) then
begin
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 0;
if not LineChanged then
Inc(AktNuta)
else
LineChanged := false;
Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Color := 2;
Lyric.AddCzesc(Czesci[0].Akt);
Lyric.Selected := AktNuta;
end;
end;
end;
end;
Text[TextSentence].Text := IntToStr(Czesci[0].Akt + 1) + ' / ' + IntToStr(Czesci[0].Ilosc);
Text[TextNote].Text := IntToStr(AktNuta + 1) + ' / ' + IntToStr(Czesci[0].Czesc[Czesci[0].Akt].IlNut);
// Song info
Text[TextBPM].Text := FloatToStr(AktSong.BPM[0].BPM / 4);
Text[TextGAP].Text := FloatToStr(AktSong.GAP);
//Error reading Variables when no Song is loaded
if not Error then
begin
// Note info
Text[TextNStart].Text := IntToStr(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Start);
Text[TextNDlugosc].Text := IntToStr(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Dlugosc);
Text[TextNTon].Text := IntToStr(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Ton) + ' ( ' + GetNoteName(Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Ton) + ' )';
Text[TextNText].Text := Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Tekst;
//F and G and Medley Mod:
if Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].FreeStyle then
Text[TextNTon].Text := Text[TextNTon].Text + ' *F*'
else if Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].Wartosc = 2 then
Text[TextNTon].Text := Text[TextNTon].Text + ' *G*';
if MedleyNotes.isStart and (Czesci[0].Akt = MedleyNotes.start.line)
and (AktNuta = MedleyNotes.start.note) then
Text[TextNTon].Text := Text[TextNTon].Text + ' MedleyStart';
if MedleyNotes.isEnd and (Czesci[0].Akt = MedleyNotes.end_.line) and
(AktNuta = MedleyNotes.end_.note) then
Text[TextNTon].Text := Text[TextNTon].Text + ' MedleyEnd';
//preview mod
if Czesci[0].Czesc[Czesci[0].Akt].Nuta[AktNuta].IsStartPreview then
Text[TextNTon].Text := Text[TextNTon].Text + ' [PreviewStart]';
end;
// Text Edit Mode
if TextEditMode then
Text[TextNText].Text := Text[TextNText].Text + '|';
// draw static menu
inherited Draw;
// draw notes
SingDrawNoteLines(20, 305, 780, 15);
//Error Drawing when no Song is loaded
if not Error then
begin
SingDrawBeatDelimeters(40, 305, 760, 0);
EditDrawCzesc(40, 410, 760, 0, 15);
end;
// draw text
Lyric.Draw;
end;
procedure TScreenEditSub.onHide;
begin
MidiOut.Close;
MidiOut.Free;
//Music.SetVolume(100);
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;
function TScreenEditSub.GetMedleyLength: real;
begin
if MedleyNotes.isStart and MedleyNotes.isEnd then
begin
Result := GetTimeFromBeat(
Czesci[0].Czesc[MedleyNotes.end_.line].Nuta[MedleyNotes.end_.note].Start +
Czesci[0].Czesc[MedleyNotes.end_.line].Nuta[MedleyNotes.end_.note].Dlugosc) -
GetTimeFromBeat(Czesci[0].Czesc[MedleyNotes.start.line].Nuta[MedleyNotes.start.note].Start);
end else
Result := 0;
end;
end.