aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code
diff options
context:
space:
mode:
authors_alexander <s_alexander@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-04-03 15:00:10 +0000
committers_alexander <s_alexander@b956fd51-792f-4845-bead-9b4dfca2ff2c>2008-04-03 15:00:10 +0000
commit2bd6d1d2ea8d36eedac96053a7e4a818da22f654 (patch)
treee179e402ab7dbc9bac88ac788308b9b8697e8704 /Game/Code
parent6b0661cdb54c8764d25883065ec22697cc2d18f5 (diff)
downloadusdx-2bd6d1d2ea8d36eedac96053a7e4a818da22f654.tar.gz
usdx-2bd6d1d2ea8d36eedac96053a7e4a818da22f654.tar.xz
usdx-2bd6d1d2ea8d36eedac96053a7e4a818da22f654.zip
rewriting of the txt file parser
removed unused variables from TLines and TLine, removed TMelody overworked the TLines and TLine records git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@1000 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to '')
-rw-r--r--Game/Code/Classes/UDraw.pas48
-rw-r--r--Game/Code/Classes/UFiles.pas6
-rw-r--r--Game/Code/Classes/ULyrics.pas47
-rw-r--r--Game/Code/Classes/ULyrics_bak.pas2
-rw-r--r--Game/Code/Classes/UMain.pas2253
-rw-r--r--Game/Code/Classes/UMusic.pas21
-rw-r--r--Game/Code/Classes/USong.pas365
-rw-r--r--Game/Code/Classes/USong_TextFile.pas86
-rw-r--r--Game/Code/Classes/USong_Txt.pas438
-rw-r--r--Game/Code/Screens/UScreenEditConvert.pas2
-rw-r--r--Game/Code/Screens/UScreenEditSub.pas53
-rw-r--r--Game/Code/Screens/UScreenSing.pas2
-rw-r--r--Game/Code/Screens/UScreenSingModi.pas1393
-rw-r--r--Game/Code/UltraStar.dpr2
14 files changed, 2622 insertions, 2096 deletions
diff --git a/Game/Code/Classes/UDraw.pas b/Game/Code/Classes/UDraw.pas
index 18c347a7..4b7d02fc 100644
--- a/Game/Code/Classes/UDraw.pas
+++ b/Game/Code/Classes/UDraw.pas
@@ -202,16 +202,16 @@ var
Pet: integer;
TempR: real;
begin
- TempR := (Right-Left) / (Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ - Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote);
+ TempR := (Right-Left) / (Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ - Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start);
glEnable(GL_BLEND);
glBegin(GL_LINES);
- for Pet := Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote to Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ do begin
+ for Pet := Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start to Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ do begin
if (Pet mod Lines[NrCzesci].Resolution) = Lines[NrCzesci].NotesGAP then
glColor4f(0, 0, 0, 1)
else
glColor4f(0, 0, 0, 0.3);
- glVertex2f(Left + TempR * (Pet - Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote), Top);
- glVertex2f(Left + TempR * (Pet - Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote), Top + 135);
+ glVertex2f(Left + TempR * (Pet - Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start), Top);
+ glVertex2f(Left + TempR * (Pet - Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start), Top + 135);
end;
glEnd;
glDisable(GL_BLEND);
@@ -248,7 +248,7 @@ begin
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
lTmpA := (Right-Left);
- lTmpB := (Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ - Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote);
+ lTmpB := (Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ - Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start);
if ( lTmpA > 0 ) AND
( lTmpB > 0 ) THEN
@@ -264,22 +264,22 @@ begin
with Lines[NrCzesci].Line[Lines[NrCzesci].Current] do begin
for Pet := 0 to HighNote do begin
with Note[Pet] do begin
- if not FreeStyle then begin
+ if NoteType <> ntFreestyle then begin
if Ini.EffectSing = 0 then
// If Golden note Effect of then Change not Color
begin
case NoteType of
- 1: glColor4f(1, 1, 1, 1); // We set alpha to 1, cause we can control the transparency through the png itself
- 2: glColor4f(1, 1, 0.3, 1); // no stars, paint yellow -> glColor4f(1, 1, 0.3, 0.85); - we could
+ ntNormal: glColor4f(1, 1, 1, 1); // We set alpha to 1, cause we can control the transparency through the png itself
+ ntGolden: glColor4f(1, 1, 0.3, 1); // no stars, paint yellow -> glColor4f(1, 1, 0.3, 0.85); - we could
end; // case
end //Else all Notes same Color
else
glColor4f(1, 1, 1, 1); // We set alpha to 1, cause we can control the transparency through the png itself
// Czesci == teil, element == piece, element | koniec == end / ending
// lewa czesc - left part
- Rec.Left := (Start-Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote) * TempR + Left + 0.5 + 10*ScreenX;
+ Rec.Left := (Start-Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX;
Rec.Right := Rec.Left + NotesW;
Rec.Top := Top - (Tone-BaseNote)*Space/2 - NotesH;
Rec.Bottom := Rec.Top + 2 * NotesH;
@@ -297,7 +297,7 @@ begin
// srodkowa czesc - middle part
Rec.Left := Rec.Right;
- Rec.Right := (Start+Length-Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote) * TempR + Left - NotesW - 0.5 + 10*ScreenX; // Dlugosc == length
+ Rec.Right := (Start+Length-Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start) * TempR + Left - NotesW - 0.5 + 10*ScreenX; // Dlugosc == length
glBindTexture(GL_TEXTURE_2D, Tex_plain_Mid[PlayerNumber].TexNum);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
@@ -322,7 +322,7 @@ begin
glEnd;
// Golden Star Patch
- if (NoteType = 2) AND (Ini.EffectSing=1) then
+ if (NoteType = ntGolden) AND (Ini.EffectSing=1) then
begin
GoldenRec.SaveGoldenStarsRec(GoldenStarPos, Rec.Top, Rec.Right, Rec.Bottom);
end;
@@ -365,13 +365,13 @@ var
//// if Player[NrGracza].IlNut > 0 then
begin
- TempR := W / (Lines[0].Line[Lines[0].Current].End_ - Lines[0].Line[Lines[0].Current].StartNote);
+ TempR := W / (Lines[0].Line[Lines[0].Current].End_ - Lines[0].Line[Lines[0].Current].Note[0].Start);
for N := 0 to Player[NrGracza].HighNote do
begin
with Player[NrGracza].Note[N] do
begin
// Left part of note
- Rec.Left := X + (Start-Lines[0].Line[Lines[0].Current].StartNote) * TempR + 0.5 + 10*ScreenX;
+ Rec.Left := X + (Start-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR + 0.5 + 10*ScreenX;
Rec.Right := Rec.Left + NotesW;
// Draw it in half size, if not hit
@@ -399,7 +399,7 @@ var
// Middle part of the note
Rec.Left := Rec.Right;
- Rec.Right := X + (Start+Length-Lines[0].Line[Lines[0].Current].StartNote) * TempR - NotesW - 0.5 + 10*ScreenX;
+ Rec.Right := X + (Start+Length-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR - NotesW - 0.5 + 10*ScreenX;
// (nowe) - dunno
if (Start+Length-1 = LineState.CurrentBeatD) then
@@ -480,7 +480,7 @@ begin
lTmpA := (Right-Left);
- lTmpB := (Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ - Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote);
+ lTmpB := (Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ - Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start);
if ( lTmpA > 0 ) AND
@@ -496,16 +496,16 @@ begin
with Lines[NrCzesci].Line[Lines[NrCzesci].Current] do begin
for Pet := 0 to HighNote do begin
with Note[Pet] do begin
- if not FreeStyle then begin
+ if NoteType <> ntFreestyle then begin
// begin: 14, 20
// easy: 6, 11
W := NotesW * 2 + 2;
H := NotesH * 1.5 + 3.5;
- X2 := (Start-Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote) * TempR + Left + 0.5 + 10*ScreenX + 4; // wciecie
+ X2 := (Start-Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX + 4; // wciecie
X1 := X2-W;
- X3 := (Start+Length-Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote) * TempR + Left - 0.5 + 10*ScreenX - 4; // wciecie
+ X3 := (Start+Length-Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start) * TempR + Left - 0.5 + 10*ScreenX - 4; // wciecie
X4 := X3+W;
// left
@@ -1235,22 +1235,22 @@ begin
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- TempR := (Right-Left) / (Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ - Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote);
+ TempR := (Right-Left) / (Lines[NrCzesci].Line[Lines[NrCzesci].Current].End_ - Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start);
with Lines[NrCzesci].Line[Lines[NrCzesci].Current] do begin
for Pet := 0 to HighNote do begin
with Note[Pet] do begin
// Golden Note Patch
case NoteType of
- 0: glColor4f(1, 1, 1, 0.35);
- 1: glColor4f(1, 1, 1, 0.85);
- 2: glColor4f(1, 1, 0.3, 0.85);
+ ntFreestyle: glColor4f(1, 1, 1, 0.35);
+ ntNormal: glColor4f(1, 1, 1, 0.85);
+ ntGolden: Glcolor4f(1, 1, 0.3, 0.85);
end; // case
// lewa czesc - left part
- Rec.Left := (Start-Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote) * TempR + Left + 0.5 + 10*ScreenX;
+ Rec.Left := (Start-Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX;
Rec.Right := Rec.Left + NotesW;
Rec.Top := Top - (Tone-BaseNote)*Space/2 - NotesH;
Rec.Bottom := Rec.Top + 2 * NotesH;
@@ -1264,7 +1264,7 @@ begin
// srodkowa czesc - middle part
Rec.Left := Rec.Right;
- Rec.Right := (Start+Length-Lines[NrCzesci].Line[Lines[NrCzesci].Current].StartNote) * TempR + Left - NotesW - 0.5 + 10*ScreenX;
+ Rec.Right := (Start+Length-Lines[NrCzesci].Line[Lines[NrCzesci].Current].Note[0].Start) * TempR + Left - NotesW - 0.5 + 10*ScreenX;
glBindTexture(GL_TEXTURE_2D, Tex_Mid[Color].TexNum);
glBegin(GL_QUADS);
diff --git a/Game/Code/Classes/UFiles.pas b/Game/Code/Classes/UFiles.pas
index 076db441..6b506574 100644
--- a/Game/Code/Classes/UFiles.pas
+++ b/Game/Code/Classes/UFiles.pas
@@ -116,9 +116,9 @@ begin
//Golden + Freestyle Note Patch
case Lines.Line[C].Note[N].NoteType of
- 0: NoteState := 'F ';
- 1: NoteState := ': ';
- 2: NoteState := '* ';
+ ntFreestyle: NoteState := 'F ';
+ ntNormal: NoteState := ': ';
+ ntGolden: NoteState := '* ';
end; // case
S := NoteState + IntToStr(Start-RelativeSubTime) + ' ' + IntToStr(Length) + ' ' + IntToStr(Tone) + ' ' + Text;
diff --git a/Game/Code/Classes/ULyrics.pas b/Game/Code/Classes/ULyrics.pas
index 909ee835..09031cb5 100644
--- a/Game/Code/Classes/ULyrics.pas
+++ b/Game/Code/Classes/ULyrics.pas
@@ -368,9 +368,9 @@ begin
LyricLine.Words[I].Start := Line.Note[I].Start;
LyricLine.Words[I].Length := Line.Note[I].Length;
LyricLine.Words[I].Text := Line.Note[I].Text;
- LyricLine.Words[I].Freestyle := Line.Note[I].FreeStyle;
+ LyricLine.Words[I].Freestyle := Line.Note[I].NoteType = ntFreestyle;
- LyricLine.HasFreestyle := LyricLine.HasFreestyle OR Line.Note[I].FreeStyle;
+ LyricLine.HasFreestyle := LyricLine.HasFreestyle OR LyricLine.Words[I].Freestyle;
LyricLine.Text := LyricLine.Text + LyricLine.Words[I].Text;
if (I > 0) AND LyricLine.Words[I-1].Freestyle AND not LyricLine.Words[I].Freestyle then
@@ -556,7 +556,7 @@ begin
// this is actually a bit more than the real font size
// it helps adjusting the "zoom-center"
- LyricsHeight:=30 * (Line^.Size/10)+16;
+ LyricsHeight:=30.5 * (Line^.Size/10);
{
// duet mode
@@ -572,8 +572,8 @@ begin
LyricX2 := LyricX + Line^.Width;
// maybe center smaller lines
- LyricY := Y;
- //LyricY := Y + ((Size / Line.Size - 1) * LyricsHeight) / 2;
+ //LyricY := Y;
+ LyricY := Y + ((Size / Line.Size - 1) * LyricsHeight) / 2;
Alpha := 1;
@@ -641,7 +641,7 @@ begin
end;
end;
end;
-
+
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
@@ -661,6 +661,15 @@ begin
glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordStart+FreestyleDiff, LyricY);
glEnd;
+ // draw rest of sentence
+ glColorRGB(LineColor_en);
+ glBegin(GL_QUADS);
+ glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordEnd+FreestyleDiff, LyricY);
+ glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f(LyricX+CurWordEnd, LyricY + LyricsHeight);
+ glTexCoord2f(Line^.Width/1024, 1-LyricsHeight/64); glVertex2f(LyricX2, LyricY + LyricsHeight);
+ glTexCoord2f(Line^.Width/1024, 1); glVertex2f(LyricX2, LyricY);
+ glEnd;
+
// draw active word:
// type 0: simple lyric effect
// type 3: ball lyric effect
@@ -703,31 +712,21 @@ begin
glScalef(1.0+(1-progress)/2,1.0+(1-progress)/2,1.0);
glColor4f(LineColor_en.r,LineColor_en.g,LineColor_en.b,1-progress);
glBegin(GL_QUADS);
- glTexCoord2f((CurWordStart+FreestyleDiff)/1024+0.0001, 1); glVertex2f(-(CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2);
- glTexCoord2f(CurWordStart/1024+0.0001, 1-LyricsHeight/64); glVertex2f(-(CurWordEnd-CurWordStart)/2, + LyricsHeight/2);
- glTexCoord2f(CurWordEnd/1024-0.0001, 1-LyricsHeight/64); glVertex2f((CurWordEnd-CurWordStart)/2, + LyricsHeight/2);
- glTexCoord2f((CurWordEnd+FreestyleDiff)/1024-0.0001, 1); glVertex2f((CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2);
+ glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(-(CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2);
+ glTexCoord2f(CurWordStart/1024, 1-LyricsHeight/64); glVertex2f(-(CurWordEnd-CurWordStart)/2, + LyricsHeight/2);
+ glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f((CurWordEnd-CurWordStart)/2, + LyricsHeight/2);
+ glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f((CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2);
glEnd;
glColor4f(LineColor_act.r,LineColor_act.g,LineColor_act.b,1);
glBegin(GL_QUADS);
- glTexCoord2f((CurWordStart+FreestyleDiff)/1024+0.0001, 1); glVertex2f(-(CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2);
- glTexCoord2f(CurWordStart/1024+0.0001, 1-LyricsHeight/64); glVertex2f(-(CurWordEnd-CurWordStart)/2, + LyricsHeight/2);
- glTexCoord2f(CurWordEnd/1024-0.0001, 1-LyricsHeight/64); glVertex2f((CurWordEnd-CurWordStart)/2, + LyricsHeight/2);
- glTexCoord2f((CurWordEnd+FreestyleDiff)/1024-0.0001, 1); glVertex2f((CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2);
+ glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(-(CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2);
+ glTexCoord2f(CurWordStart/1024, 1-LyricsHeight/64); glVertex2f(-(CurWordEnd-CurWordStart)/2, + LyricsHeight/2);
+ glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f((CurWordEnd-CurWordStart)/2, + LyricsHeight/2);
+ glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f((CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2);
glEnd;
glPopMatrix;
end;
- // draw rest of sentence
- glColorRGB(LineColor_en);
- glBegin(GL_QUADS);
- glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordEnd+FreestyleDiff, LyricY);
- glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f(LyricX+CurWordEnd, LyricY + LyricsHeight);
- glTexCoord2f(Line^.Width/1024, 1-LyricsHeight/64); glVertex2f(LyricX2, LyricY + LyricsHeight);
- glTexCoord2f(Line^.Width/1024, 1); glVertex2f(LyricX2, LyricY);
- glEnd;
-
-
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
diff --git a/Game/Code/Classes/ULyrics_bak.pas b/Game/Code/Classes/ULyrics_bak.pas
index 620a28ad..e44800d6 100644
--- a/Game/Code/Classes/ULyrics_bak.pas
+++ b/Game/Code/Classes/ULyrics_bak.pas
@@ -265,7 +265,7 @@ var
begin
Clear;
for N := 0 to Lines[0].Line[NrCzesci].HighNote do begin
- Italic := Lines[0].Line[NrCzesci].Note[N].FreeStyle;
+ Italic := Lines[0].Line[NrCzesci].Note[N].NoteType = ntFreestyle;
AddWord(Lines[0].Line[NrCzesci].Note[N].Text);
Text := Text + Lines[0].Line[NrCzesci].Note[N].Text;
end;
diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas
index 9459334d..baefeff8 100644
--- a/Game/Code/Classes/UMain.pas
+++ b/Game/Code/Classes/UMain.pas
@@ -1,1131 +1,1122 @@
-unit UMain;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-uses
- SDL,
- UGraphic,
- UMusic,
- URecord,
- UTime,
- SysUtils,
- UDisplay,
- UIni,
- ULog,
- ULyrics,
- UScreenSing,
- USong,
- OpenGL12,
- UThemes;
-
-type
- TPlayer = record
- Name: string;
-
- // Index in Teaminfo record
- TeamID: Byte;
- PlayerID: Byte;
-
- // Scores
- Score: real;
- ScoreLine: real;
- ScoreGolden: real;
-
- ScoreI: integer;
- ScoreLineI: integer;
- ScoreGoldenI: integer;
- ScoreTotalI: integer;
-
- // LineBonus Mod
- ScoreLast: Real;//Last Line Score
-
- // PerfectLineTwinkle Mod (effect)
- LastSentencePerfect: Boolean;
-
- //Meter: real;
-
- HighNote: integer;
- IlNut: integer;
- Note: array of record
- Start: integer;
- Length: integer;
- Detekt: real; // accurate place, detected in the note
- Tone: real;
- Perfect: boolean; // true if the note matches the original one, lit the star
-
- // Half size Notes Patch
- Hit: boolean; // true if the note Hits the Line
- end;
- end;
-
-
-var
- // Absolute Paths
- GamePath: string;
- SoundPath: string;
- SongPath: string;
- LogPath: string;
- ThemePath: string;
- SkinsPath: string;
- ScreenshotsPath: string;
- CoversPath: string;
- LanguagesPath: string;
- PluginPath: string;
- VisualsPath: string;
- PlayListPath: string;
-
- UserSongPath: string = '';
- UserCoversPath: string = '';
- UserPlaylistPath: string = '';
-
- OGL: Boolean;
- Done: Boolean;
- Event: TSDL_event;
- FileName: string;
- Restart: boolean;
-
- // player and music info
- Player: array of TPlayer;
- PlayersPlay: integer;
-
- CurrentSong : TSong;
-
-procedure InitializePaths;
-
-Procedure Main;
-procedure MainLoop;
-procedure CheckEvents;
-procedure Sing(Sender: TScreenSing);
-procedure NewSentence(Sender: TScreenSing);
-procedure NewBeat(Sender: TScreenSing); // executed when on then new beat
-procedure NewBeatC(Sender: TScreenSing); // executed when on then new beat for click
-procedure NewBeatD(Sender: TScreenSing); // executed when on then new beat for detection
-//procedure NewHalf; // executed when in the half between beats
-procedure NewNote(Sender: TScreenSing); // detect note
-function GetMidBeat(Time: real): real;
-function GetTimeFromBeat(Beat: integer): real;
-procedure ClearScores(PlayerNum: integer);
-
-implementation
-
-uses
- USongs,
- UJoystick,
- math,
- UCommandLine,
- ULanguage,
- SDL_ttf,
- USkins,
- UCovers,
- UCatCovers,
- UDataBase,
- UPlaylist,
- UDLLManager,
- UParty,
- UConfig,
- UCore,
- UGraphicClasses,
- UPluginDefs,
- UPlatform;
-
-
-
-
-procedure Main;
-var
- WndTitle: string;
-begin
- try
- WndTitle := USDXVersionStr;
-
- if Platform.TerminateIfAlreadyRunning( {var} WndTitle) then
- Exit;
-
- //------------------------------
- //StartUp - Create Classes and Load Files
- //------------------------------
- USTime := TTime.Create;
-
- // Commandline Parameter Parser
- Params := TCMDParams.Create;
-
- // Log + Benchmark
- Log := TLog.Create;
- Log.Title := WndTitle;
- Log.Enabled := not Params.NoLog;
- Log.BenchmarkStart(0);
-
- // Language
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize Paths', 'Initialization');
- InitializePaths;
- Log.LogStatus('Load Language', 'Initialization');
- Language := TLanguage.Create;
-
- // Add Const Values:
- Language.AddConst('US_VERSION', USDXVersionStr);
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Language', 1);
-
- // SDL
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize SDL', 'Initialization');
- SDL_Init(SDL_INIT_VIDEO);
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing SDL', 1);
-
- // SDL_ttf
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize SDL_ttf', 'Initialization');
- TTF_Init();
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing SDL_ttf', 1);
-
- // Skin
- Log.BenchmarkStart(1);
- Log.LogStatus('Loading Skin List', 'Initialization');
- Skin := TSkin.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Skin List', 1);
-
- // Ini + Paths
- Log.BenchmarkStart(1);
- Log.LogStatus('Load Ini', 'Initialization');
- Ini := TIni.Create;
- Ini.Load;
-
- //Load Languagefile
- if (Params.Language <> -1) then
- Language.ChangeLanguage(ILanguage[Params.Language])
- else
- Language.ChangeLanguage(ILanguage[Ini.Language]);
-
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Ini', 1);
-
- // Sound
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize Sound', 'Initialization');
- InitializeSound();
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing Sound', 1);
-
- // Load Sound Settings from Ini
- Log.BenchmarkStart(1);
- Log.LogStatus('Load Sound Settings', 'Initialization');
- Ini.LoadSoundSettings;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Load Sound Settings', 1);
-
- // Theme
- Log.BenchmarkStart(1);
- Log.LogStatus('Load Themes', 'Initialization');
- Theme := TTheme.Create(ThemePath + ITheme[Ini.Theme] + '.ini', Ini.Color);
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Themes', 1);
-
- // Covers Cache
- Log.BenchmarkStart(1);
- Log.LogStatus('Creating Covers Cache', 'Initialization');
- Covers := TCovers.Create;
- Log.LogBenchmark('Loading Covers Cache Array', 1);
- Log.BenchmarkStart(1);
-
- // Category Covers
- Log.BenchmarkStart(1);
- Log.LogStatus('Creating Category Covers Array', 'Initialization');
- CatCovers:= TCatCovers.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Category Covers Array', 1);
-
- // Songs
- //Log.BenchmarkStart(1);
- Log.LogStatus('Creating Song Array', 'Initialization');
- Songs := TSongs.Create;
- //Songs.LoadSongList;
-
- Log.LogStatus('Creating 2nd Song Array', 'Initialization');
- CatSongs := TCatSongs.Create;
-
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Songs', 1);
-
- // PluginManager
- Log.BenchmarkStart(1);
- Log.LogStatus('PluginManager', 'Initialization');
- DLLMan := TDLLMan.Create; // Load PluginList
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading PluginManager', 1);
-
- {// Party Mode Manager
- Log.BenchmarkStart(1);
- Log.LogStatus('PartySession Manager', 'Initialization');
- PartySession := TPartySession.Create; //Load PartySession
-
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading PartySession Manager', 1); }
-
- // Graphics
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize 3D', 'Initialization');
- Initialize3D(WndTitle);
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing 3D', 1);
-
- // Score Saving System
- Log.BenchmarkStart(1);
- Log.LogStatus('DataBase System', 'Initialization');
- DataBase := TDataBaseSystem.Create;
-
- if (Params.ScoreFile = '') then
- DataBase.Init ('Ultrastar.db')
- else
- DataBase.Init (Params.ScoreFile);
-
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading DataBase System', 1);
-
- // Playlist Manager
- Log.BenchmarkStart(1);
- Log.LogStatus('Playlist Manager', 'Initialization');
- PlaylistMan := TPlaylistManager.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Playlist Manager', 1);
-
- // GoldenStarsTwinkleMod
- Log.BenchmarkStart(1);
- Log.LogStatus('Effect Manager', 'Initialization');
- GoldenRec := TEffectManager.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading Particel System', 1);
-
- // Joypad
- if (Ini.Joypad = 1) OR (Params.Joypad) then
- begin
- Log.BenchmarkStart(1);
- Log.LogStatus('Initialize Joystick', 'Initialization');
- Joy := TJoy.Create;
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Initializing Joystick', 1);
- end;
-
- Log.BenchmarkEnd(0);
- Log.LogBenchmark('Loading Time', 0);
-
- Log.LogError('Creating Core');
- Core := TCore.Create(
- USDXShortVersionStr,
- MakeVersion(USDX_VERSION_MAJOR,
- USDX_VERSION_MINOR,
- USDX_VERSION_RELEASE,
- chr(0))
- );
-
- Log.LogError('Running Core');
- Core.Run;
-
- //------------------------------
- //Start- Mainloop
- //------------------------------
- Log.LogStatus('Main Loop', 'Initialization');
- MainLoop;
-
- finally
- //------------------------------
- //Finish Application
- //------------------------------
-
- // TODO:
- // call an uninitialize routine for every initialize step
- // or at least use the corresponding Free-Methods
-
- UnloadOpenGL;
- //TTF_quit();
- SDL_Quit();
-
- (*
- {$ifdef WIN32}
- if assigned(LCD) and (Ini.LPT = 1) then
- LCD.Clear;
- if assigned(Light) and (Ini.LPT = 2) then
- Light.TurnOff;
- {$endif}
- *)
-
- if assigned(Log) then
- begin
- Log.LogStatus('Main Loop', 'Finished');
- Log.Free;
- end;
- end;
-end;
-
-procedure MainLoop;
-var
- Delay: integer;
-begin
- Delay := 0;
- SDL_EnableKeyRepeat(125, 125);
-
- CountSkipTime(); // JB - for some reason this seems to be needed when we use the SDL Timer functions.
- while not Done do
- begin
- // joypad
- if (Ini.Joypad = 1) or (Params.Joypad) then
- Joy.Update;
-
- // keyboard events
- CheckEvents;
-
- // display
- done := not Display.Draw;
- SwapBuffers;
-
- // light
- //Light.Refresh;
-
- // delay
- CountMidTime;
-
- Delay := Floor(1000 / 100 - 1000 * TimeMid);
-
- if Delay >= 1 then
- SDL_Delay(Delay); // dynamic, maximum is 100 fps
-
- CountSkipTime;
-
- // reinitialization of graphics
- if Restart then
- begin
- Reinitialize3D;
- Restart := false;
- end;
-
- end;
-End;
-
-procedure CheckEvents;
-begin
- if Assigned(Display.NextScreen) then
- Exit;
-
- while SDL_PollEvent( @event ) = 1 do
- begin
- case Event.type_ of
- SDL_QUITEV:
- begin
- Display.Fade := 0;
- Display.NextScreenWithCheck := nil;
- Display.CheckOK := True;
- end;
- {
- SDL_MOUSEBUTTONDOWN:
- with Event.button Do
- begin
- if State = SDL_BUTTON_LEFT Then
- begin
- //
- end;
- end;
- }
- SDL_VIDEORESIZE:
- begin
- ScreenW := Event.resize.w;
- ScreenH := Event.resize.h;
-
- screen := SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE);
- end;
- SDL_KEYDOWN:
- begin
- // remap the "keypad enter" key to the "standard enter" key
- if (Event.key.keysym.sym = SDLK_KP_ENTER) then
- Event.key.keysym.sym := SDLK_RETURN;
-
- if (Event.key.keysym.sym = SDLK_F11) or
- ((Event.key.keysym.sym = SDLK_RETURN) and
- ((Event.key.keysym.modifier and KMOD_ALT) <> 0)) then // toggle full screen
- begin
- Ini.FullScreen := integer( not boolean( Ini.FullScreen ) );
-
- if boolean( Ini.FullScreen ) then
- begin
- SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_FULLSCREEN);
- SDL_ShowCursor(0);
- end
- else
- begin
- SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE);
- SDL_ShowCursor(1);
- end;
-
- glViewPort(0, 0, ScreenW, ScreenH);
- end
- // ScreenShot hack. If Print is pressed-> Make screenshot and Save to Screenshots Path
- else if (Event.key.keysym.sym = SDLK_SYSREQ) or (Event.key.keysym.sym = SDLK_PRINT) then
- Display.ScreenShot
- // popup hack... if there is a visible popup then let it handle input instead of underlying screen
- // shoud be done in a way to be sure the topmost popup has preference (maybe error, then check)
- else if (ScreenPopupError <> nil) and (ScreenPopupError.Visible) then
- done := not ScreenPopupError.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True)
- else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
- done := not ScreenPopupCheck.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True)
- // end of popup hack
- else
- begin
- // check for Screen want to Exit
- done := not Display.CurrentScreen^.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True);
-
- // If Screen wants to Exit
- if done then
- begin
- // If Question Option is enabled then Show Exit Popup
- if (Ini.AskbeforeDel = 1) then
- begin
- Display.CurrentScreen^.CheckFadeTo(nil,'MSG_QUIT_USDX');
- end
- else // When asking for exit is disabled then simply exit
- begin
- Display.Fade := 0;
- Display.NextScreenWithCheck := nil;
- Display.CheckOK := True;
- end;
- end;
-
- end;
- end;
- {
- SDL_JOYAXISMOTION:
- begin
- // not implemented
- end;
- }
- SDL_JOYBUTTONDOWN:
- begin
- // not implemented
- end;
- end; // Case
- end; // While
-end;
-
-function GetTimeForBeats(BPM, Beats: real): real;
-begin
- Result := 60 / BPM * Beats;
-end;
-
-function GetBeats(BPM, msTime: real): real;
-begin
- Result := BPM * msTime / 60;
-end;
-
-procedure GetMidBeatSub(BPMNum: integer; var Time: real; var CurBeat: real);
-var
- NewTime: real;
-begin
- if High(CurrentSong.BPM) = BPMNum then
- begin
- // last BPM
- CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
- Time := 0;
- end
- else
- begin
- // not last BPM
- // count how much time is it for start of the new BPM and store it in NewTime
- NewTime := GetTimeForBeats(CurrentSong.BPM[BPMNum].BPM, CurrentSong.BPM[BPMNum+1].StartBeat - CurrentSong.BPM[BPMNum].StartBeat);
-
- // compare it to remaining time
- if (Time - NewTime) > 0 then
- begin
- // there is still remaining time
- CurBeat := CurrentSong.BPM[BPMNum].StartBeat;
- Time := Time - NewTime;
- end
- else
- begin
- // there is no remaining time
- CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
- Time := 0;
- end; // if
- end; // if
-end;
-
-function GetMidBeat(Time: real): real;
-var
- CurBeat: real;
- CurBPM: integer;
-// TopBeat: real;
-// TempBeat: real;
-// TempTime: real;
-begin
- Result := 0;
- if Length(CurrentSong.BPM) = 1 then
- Result := Time * CurrentSong.BPM[0].BPM / 60;
-
- (* 2 BPMs *)
-{ if Length(CurrentSong.BPM) > 1 then begin
- (* new system *)
- CurBeat := 0;
- TopBeat := GetBeats(CurrentSong.BPM[0].BPM, Time);
- if TopBeat > CurrentSong.BPM[1].StartBeat then begin
- // analyze second BPM
- Time := Time - GetTimeForBeats(CurrentSong.BPM[0].BPM, CurrentSong.BPM[1].StartBeat - CurBeat);
- CurBeat := CurrentSong.BPM[1].StartBeat;
- TopBeat := GetBeats(CurrentSong.BPM[1].BPM, Time);
- Result := CurBeat + TopBeat;
-
- end
- else
- begin
- (* pierwszy przedzial *)
- Result := TopBeat;
- end;
- end;}
-
- (* more BPMs *)
- if Length(CurrentSong.BPM) > 1 then
- begin
- CurBeat := 0;
- CurBPM := 0;
- while (Time > 0) do
- begin
- GetMidBeatSub(CurBPM, Time, CurBeat);
- Inc(CurBPM);
- end;
-
- Result := CurBeat;
- end;
-end;
-
-function GetTimeFromBeat(Beat: integer): real;
-var
- CurBPM: integer;
-begin
- Result := 0;
- if Length(CurrentSong.BPM) = 1 then
- Result := CurrentSong.GAP / 1000 + Beat * 60 / CurrentSong.BPM[0].BPM;
-
- (* more BPMs *)
- if Length(CurrentSong.BPM) > 1 then
- begin
- Result := CurrentSong.GAP / 1000;
- CurBPM := 0;
- while (CurBPM <= High(CurrentSong.BPM)) and
- (Beat > CurrentSong.BPM[CurBPM].StartBeat) do
- begin
- if (CurBPM < High(CurrentSong.BPM)) and
- (Beat >= CurrentSong.BPM[CurBPM+1].StartBeat) then
- begin
- // full range
- Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
- (CurrentSong.BPM[CurBPM+1].StartBeat - CurrentSong.BPM[CurBPM].StartBeat);
- end;
-
- if (CurBPM = High(CurrentSong.BPM)) or
- (Beat < CurrentSong.BPM[CurBPM+1].StartBeat) then
- begin
- // in the middle
- Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
- (Beat - CurrentSong.BPM[CurBPM].StartBeat);
- end;
- Inc(CurBPM);
- end;
-
- {
- while (Time > 0) do
- begin
- GetMidBeatSub(CurBPM, Time, CurBeat);
- Inc(CurBPM);
- end;
- }
- end; // if}
-end;
-
-procedure Sing(Sender: TScreenSing);
-var
- Count: integer;
- CountGr: integer;
- CP: integer;
- Done: real;
- N: integer;
-begin
- LineState.CurrentTime := LineState.CurrentTime + TimeSkip;
-
- LineState.OldBeat := LineState.CurrentBeat;
- LineState.MidBeat := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap{ + 90 I've forgotten for what it is}) / 1000); // new system with variable BPM in function
- LineState.CurrentBeat := Floor(LineState.MidBeat);
-
-// LineState.OldHalf := LineState.AktHalf;
-// LineState.MidHalf := LineState.MidBeat + 0.5;
-// LineState.AktHalf := Floor(LineState.MidHalf);
-
- LineState.OldBeatC := LineState.CurrentBeatC;
- LineState.MidBeatC := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap) / 1000);
- LineState.CurrentBeatC := Floor(LineState.MidBeatC);
-
- LineState.OldBeatD := LineState.CurrentBeatD;
- LineState.MidBeatD := -0.5+GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap + 120 + 20) / 1000); // MidBeat with addition GAP
- LineState.CurrentBeatD := Floor(LineState.MidBeatD);
- LineState.FracBeatD := Frac(LineState.MidBeatD);
-
- // sentences routines
- for CountGr := 0 to 0 do //High(Gracz)
- begin;
- CP := CountGr;
- // ustawianie starej parts
- LineState.OldLine := Lines[CP].Current;
-
- // wybieranie aktualnej parts
- for Count := 0 to Lines[CP].High do
- begin
- if LineState.CurrentBeat >= Lines[CP].Line[Count].Start then
- Lines[CP].Current := Count;
- end;
-
- // czysczenie nut gracza, gdy to jest nowa plansza
- // (optymizacja raz na halfbeat jest zla)
- if Lines[CP].Current <> LineState.OldLine then
- NewSentence(Sender);
-
- end; // for CountGr
-
- // wykonuje operacje raz na beat
- if (LineState.CurrentBeat >= 0) and (LineState.OldBeat <> LineState.CurrentBeat) then
- NewBeat(Sender);
-
- // make some operations on clicks
- if {(LineState.CurrentBeatC >= 0) and }(LineState.OldBeatC <> LineState.CurrentBeatC) then
- NewBeatC(Sender);
-
- // make some operations when detecting new voice pitch
- if (LineState.CurrentBeatD >= 0) and (LineState.OldBeatD <> LineState.CurrentBeatD) then
- NewBeatD(Sender);
-
- // wykonuje operacje w polowie beatu
-// if (LineState.AktHalf >= 1) and (LineState.OldHalf <> LineState.AktHalf) then
-// NewHalf;
-
- // plynnie przesuwa text
- Done := 1;
- for N := 0 to Lines[0].Line[Lines[0].Current].HighNote do
- begin
- if (Lines[0].Line[Lines[0].Current].Note[N].Start <= LineState.MidBeat) and
- (Lines[0].Line[Lines[0].Current].Note[N].Start + Lines[0].Line[Lines[0].Current].Note[N].Length >= LineState.MidBeat) then
- begin
- Done := (LineState.MidBeat - Lines[0].Line[Lines[0].Current].Note[N].Start) / (Lines[0].Line[Lines[0].Current].Note[N].Length);
- end;
- end;
-
- N := Lines[0].Line[Lines[0].Current].HighNote;
-
- // wylacza ostatnia nute po przejsciu
- {// todo: Lyrics
- if (Ini.LyricsEffect = 1) and (Done = 1) and
- (LineState.MidBeat > Lines[0].Line[Lines[0].Current].Note[N].Start + Lines[0].Line[Lines[0].Current].Note[N].Length)
- then Sender.LyricMain.Selected := -1;
-
- if Done > 1 then Done := 1;
- Sender.LyricMain.Done := Done; }
-
- // use Done with LCD
-{ with ScreenSing do begin
- if LyricMain.Selected >= 0 then begin
- LCD.MoveCursor(1, LyricMain.SelectedLetter + Round((LyricMain.SelectedLength-1) * Done));
- LCD.ShowCursor;
- end;
- end;}
-
-
-end;
-
-procedure NewSentence(Sender: TScreenSing);
-var
-G: Integer;
-begin
- // czyszczenie nut graczy
- for G := 0 to High(Player) do
- begin
- Player[G].IlNut := 0;
- Player[G].HighNote := -1;
- SetLength(Player[G].Note, 0);
- end;
-
- // Add Words to Lyrics
- with Sender do
- begin
- {LyricMain.AddCzesc(Lines[0].Current);
- if Lines[0].Current < Lines[0].High then
- LyricSub.AddCzesc(Lines[0].Current+1)
- else
- LyricSub.Clear;}
- while (not Lyrics.LineinQueue) and (Lyrics.LineCounter <= High(Lines[0].Line)) do
- Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]);
- end;
-
- //Sender.UpdateLCD;
-
- //On Sentence Change...
- Sender.onSentenceChange(Lines[0].Current);
-end;
-
-procedure NewBeat(Sender: TScreenSing);
-var
- Count: integer;
-// TempBeat: integer;
-begin
- // ustawia zaznaczenie tekstu
-// SingScreen.LyricMain.Selected := -1;
- for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
- if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LineState.CurrentBeat) then
- begin
- // operates on currently beated note
- //Todo: Lyrics
- //Sender.LyricMain.Selected := Count;
-
-// LCD.MoveCursor(1, ScreenSing.LyricMain.SelectedLetter);
-// LCD.ShowCursor;
-
- //LCD.MoveCursorBR(Sender.LyricMain.SelectedLetter);
- //LCD.ShowCursor;
- end;
-end;
-
-procedure NewBeatC;
-var
- Count: integer;
-// LPT_1: integer;
-// LPT_2: integer;
-begin
-// LPT_1 := 1;
-// LPT_2 := 1;
-
- // beat click
- if (Ini.BeatClick = 1) and ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then
- AudioPlayback.PlaySound(SoundLib.Click);
-
- // debug system on LPT
- if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then
- begin
- //LPT_1 := 0;
-// Light.LightOne(0, 150);
-
- (*
- Light.LightOne(1, 200); // beat light
- if ParamStr(1) = '-doublelights' then
- Light.LightOne(0, 200); // beat light
- *)
-
-
-{ if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod (Lines[0].Resolution * 2) = 0) then
- Light.LightOne(0, 150)
- else
- Light.LightOne(1, 150)}
- end;
-
- for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
- begin
- if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LineState.CurrentBeatC) then
- begin
- // click assist
- if Ini.ClickAssist = 1 then
- AudioPlayback.PlaySound(SoundLib.Click);
-
- //LPT_2 := 0;
- (*
- if ParamStr(1) <> '-doublelights' then
- Light.LightOne(0, 150); //125
- *)
-
- // drum machine
- (*
- TempBeat := LineState.CurrentBeat;// + 2;
- if (TempBeat mod 8 = 0) then Music.PlayDrum;
- if (TempBeat mod 8 = 4) then Music.PlayClap;
-// if (TempBeat mod 4 = 2) then Music.PlayHihat;
- if (TempBeat mod 4 <> 0) then Music.PlayHihat;
- *)
- end;
- end;
-
- {$IFDEF UseSerialPort}
- // PortWriteB($378, LPT_1 + LPT_2 * 2); // 0 zapala
- {$ENDIF}
-end;
-
-procedure NewBeatD(Sender: TScreenSing);
-begin
- NewNote(Sender);
-end;
-
-//procedure NewHalf;
-//begin
-// NewNote;
-//end;
-
-procedure NewNote(Sender: TScreenSing);
-var
- CP: integer; // current player
- S: integer; // sentence
- SMin: integer;
- SMax: integer;
- SDet: integer; // temporary: sentence of detected note
- Count: integer;
- Mozna: boolean;
- New: boolean;
- Range: integer;
- NoteHit:boolean;
-begin
- // Log.LogStatus('Beat ' + IntToStr(LineState.CurrentBeat) + ' HalfBeat ' + IntToStr(LineState.AktHalf), 'NewBeat');
-
- // On linux we get an AV @ NEWNOTE, line 600 of Classes/UMain.pas
- if not assigned( AudioInputProcessor.Sound ) then
- exit;
-
- // analizuje dla obu graczy ten sam sygnal (Sound.OneSrcForBoth)
- // albo juz lepiej nie
- for CP := 0 to PlayersPlay-1 do
- begin
- // analyze buffer
- AudioInputProcessor.Sound[CP].AnalyzeBuffer;
-
- // adds some noise
- //LineState.Tone := LineState.Tone + Round(Random(3)) - 1;
-
- // count min and max sentence range for checking (detection is delayed to the notes we see on the screen)
- SMin := Lines[0].Current-1;
- if SMin < 0 then
- SMin := 0;
- SMax := Lines[0].Current;
-
- // check if we can add new note
- Mozna := false;
- SDet:=SMin;
- for S := SMin to SMax do
- begin
- for Count := 0 to Lines[0].Line[S].HighNote do
- begin
- if ((Lines[0].Line[S].Note[Count].Start <= LineState.CurrentBeatD)
- and (Lines[0].Line[S].Note[Count].Start + Lines[0].Line[S].Note[Count].Length - 1 >= LineState.CurrentBeatD))
- and (not Lines[0].Line[S].Note[Count].FreeStyle) // but don't allow when it's FreeStyle note
- and (Lines[0].Line[S].Note[Count].Length > 0) then // and make sure the note lengths is at least 1
- begin
- SDet := S;
- Mozna := true;
- Break;
- end;
- end;
- end;
-
- S := SDet;
-
- //Czas.SzczytJest := true;
- //Czas.Tone := 27;
-
- // gdy moze, to dodaje nute - When Mozna, it adds note (?)
- if (AudioInputProcessor.Sound[CP].ToneValid) and (Mozna) then
- begin
- // operowanie na ostatniej nucie
- for Count := 0 to Lines[0].Line[S].HighNote do
- begin
- if (Lines[0].Line[S].Note[Count].Start <= LineState.OldBeatD+1) and
- (Lines[0].Line[S].Note[Count].Start +
- Lines[0].Line[S].Note[Count].Length > LineState.OldBeatD+1) then
- begin
- // to robi, tylko dla pary nut (oryginalnej i gracza)
-
- // przesuwanie tonu w odpowiednia game
- while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone > 6) do
- AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone - 12;
-
- while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone < -6) do
- AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone + 12;
-
- // Half size Notes Patch
- NoteHit := false;
-
- //if Ini.Difficulty = 0 then Range := 2;
- //if Ini.Difficulty = 1 then Range := 1;
- //if Ini.Difficulty = 2 then Range := 0;
- Range := 2 - Ini.Difficulty;
-
- if abs(Lines[0].Line[S].Note[Count].Tone - AudioInputProcessor.Sound[CP].Tone) <= Range then
- begin
- AudioInputProcessor.Sound[CP].Tone := Lines[0].Line[S].Note[Count].Tone;
-
- // Half size Notes Patch
- NoteHit := true;
-
- if (Ini.LineBonus = 0) then
- begin
- // add points without LineBonus
- case Lines[0].Line[S].Note[Count].NoteType of
- 1: Player[CP].Score := Player[CP].Score + 10000 / Lines[0].NoteType *
- Lines[0].Line[S].Note[Count].NoteType;
- 2: Player[CP].ScoreGolden := Player[CP].ScoreGolden + 10000 / Lines[0].NoteType *
- Lines[0].Line[S].Note[Count].NoteType;
- end;
- end
- else
- begin
- // add points with Line Bonus
- case Lines[0].Line[S].Note[Count].NoteType of
- 1: Player[CP].Score := Player[CP].Score + 9000 / Lines[0].NoteType *
- Lines[0].Line[S].Note[Count].NoteType;
- 2: Player[CP].ScoreGolden := Player[CP].ScoreGolden + 9000 / Lines[0].NoteType *
- Lines[0].Line[S].Note[Count].NoteType;
- end;
- end;
-
- Player[CP].ScoreI := Floor(Player[CP].Score / 10) * 10;
- Player[CP].ScoreGoldenI := Floor(Player[CP].ScoreGolden / 10) * 10;
-
- Player[CP].ScoreTotalI := Player[CP].ScoreI + Player[CP].ScoreGoldenI + Player[CP].ScoreLineI;
- end;
-
- end; // operowanie
- end; // for
-
- // sprawdzanie czy to nowa nuta, czy przedluzenie
- if S = SMax then
- begin
- New := true;
- // if last has the same tone
- if (Player[CP].IlNut > 0 ) and
- (Player[CP].Note[Player[CP].HighNote].Tone = AudioInputProcessor.Sound[CP].Tone) and
- (Player[CP].Note[Player[CP].HighNote].Start + Player[CP].Note[Player[CP].HighNote].Length = LineState.CurrentBeatD) then
- begin
- New := false;
- end;
-
- // if is not as new note to control "beacie" (TODO: translate polish "beacie")
- for Count := 0 to Lines[0].Line[S].HighNote do
- begin
- if (Lines[0].Line[S].Note[Count].Start = LineState.CurrentBeatD) then
- New := true;
- end;
-
- // dodawanie nowej nuty
- if New then
- begin
- // New Note
- Player[CP].IlNut := Player[CP].IlNut + 1;
- Player[CP].HighNote := Player[CP].HighNote + 1;
- SetLength(Player[CP].Note, Player[CP].IlNut);
- Player[CP].Note[Player[CP].HighNote].Start := LineState.CurrentBeatD;
- Player[CP].Note[Player[CP].HighNote].Length := 1;
- Player[CP].Note[Player[CP].HighNote].Tone := AudioInputProcessor.Sound[CP].Tone; // Ton || TonDokl
- Player[CP].Note[Player[CP].HighNote].Detekt := LineState.MidBeat;
-
- // Half Note Patch
- Player[CP].Note[Player[CP].HighNote].Hit := NoteHit;
-
- //Log.LogStatus('New Note ' + IntToStr(Gracz.Note[Gracz.HighNote].Start), 'NewBeat');
- end
- else
- begin
- // przedluzenie nuty
- Player[CP].Note[Player[CP].HighNote].Length := Player[CP].Note[Player[CP].HighNote].Length + 1;
- end;
-
- // check for perfect note and then lit the star (on Draw)
- for Count := 0 to Lines[0].Line[S].HighNote do
- begin
- if (Lines[0].Line[S].Note[Count].Start = Player[CP].Note[Player[CP].HighNote].Start) and
- (Lines[0].Line[S].Note[Count].Length = Player[CP].Note[Player[CP].HighNote].Length) and
- (Lines[0].Line[S].Note[Count].Tone = Player[CP].Note[Player[CP].HighNote].Tone) then
- begin
- Player[CP].Note[Player[CP].HighNote].Perfect := true;
- end;
- end;
- end; // if S = SMax
-
- end; // if moze
- end; // for CP
- // Log.LogStatus('EndBeat', 'NewBeat');
-
- //On Sentence End -> For LineBonus + SingBar
- if (sDet >= low(Lines[0].Line)) and (sDet <= high(Lines[0].Line)) then
- begin
- if assigned( Sender ) and
- ((Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Start + Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Length - 1) = LineState.CurrentBeatD) then
- begin
- Sender.onSentenceEnd(sDet);
- end;
- end;
-
-end;
-
-procedure ClearScores(PlayerNum: integer);
-begin
- Player[PlayerNum].Score := 0;
- Player[PlayerNum].ScoreI := 0;
- Player[PlayerNum].ScoreLine := 0;
- Player[PlayerNum].ScoreLineI := 0;
- Player[PlayerNum].ScoreGolden := 0;
- Player[PlayerNum].ScoreGoldenI := 0;
- Player[PlayerNum].ScoreTotalI := 0;
-end;
-
-//--------------------
-// Function sets all Absolute Paths e.g. Song Path and makes sure the Directorys exist
-//--------------------
-procedure InitializePaths;
-
- // Initialize a Path Variable
- // After Setting Paths, make sure that Paths exist
- function initialize_path( out aPathVar : string; const aLocation : string ): boolean;
- var
- lWriteable: Boolean;
- lAttrib : integer;
- begin
- lWriteable := false;
- aPathVar := aLocation;
-
- // Make sure the directory is needex
- ForceDirectories(aPathVar);
-
- if DirectoryExists(aPathVar) then
- begin
- lAttrib := fileGetAttr(aPathVar);
-
- lWriteable := (lAttrib and faDirectory <> 0) and
- not (lAttrib and faReadOnly <> 0)
- end;
-
- if not lWriteable then
- Log.LogError('Error: Dir ('+ aLocation +') is Readonly');
-
- result := lWriteable;
- end;
-
-begin
- initialize_path( LogPath , Platform.GetLogPath );
- initialize_path( SoundPath , Platform.GetGameSharedPath + 'Sounds' + PathDelim );
- initialize_path( ThemePath , Platform.GetGameSharedPath + 'Themes' + PathDelim );
- initialize_path( SkinsPath , Platform.GetGameSharedPath + 'Skins' + PathDelim );
- initialize_path( LanguagesPath , Platform.GetGameSharedPath + 'Languages' + PathDelim );
- initialize_path( PluginPath , Platform.GetGameSharedPath + 'Plugins' + PathDelim );
- initialize_path( VisualsPath , Platform.GetGameSharedPath + 'Visuals' + PathDelim );
-
- initialize_path( ScreenshotsPath , Platform.GetGameUserPath + 'Screenshots' + PathDelim );
-
- // Users Song Path ....
- initialize_path( UserSongPath , Platform.GetGameUserPath + 'Songs' + PathDelim );
- initialize_path( UserCoversPath , Platform.GetGameUserPath + 'Covers' + PathDelim );
- initialize_path( UserPlaylistPath , Platform.GetGameUserPath + 'Playlists' + PathDelim );
-
- // Shared Song Path ....
- initialize_path( SongPath , Platform.GetGameSharedPath + 'Songs' + PathDelim );
- initialize_path( CoversPath , Platform.GetGameSharedPath + 'Covers' + PathDelim );
- initialize_path( PlaylistPath , Platform.GetGameSharedPath + 'Playlists' + PathDelim );
-
- DecimalSeparator := '.';
-end;
-
-end.
-
+unit UMain;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ SDL,
+ UGraphic,
+ UMusic,
+ URecord,
+ UTime,
+ SysUtils,
+ UDisplay,
+ UIni,
+ ULog,
+ ULyrics,
+ UScreenSing,
+ USong,
+ OpenGL12,
+ UThemes;
+
+type
+ TPlayer = record
+ Name: string;
+
+ // Index in Teaminfo record
+ TeamID: Byte;
+ PlayerID: Byte;
+
+ // Scores
+ Score: real;
+ ScoreLine: real;
+ ScoreGolden: real;
+
+ ScoreI: integer;
+ ScoreLineI: integer;
+ ScoreGoldenI: integer;
+ ScoreTotalI: integer;
+
+ // LineBonus Mod
+ ScoreLast: Real;//Last Line Score
+
+ // PerfectLineTwinkle Mod (effect)
+ LastSentencePerfect: Boolean;
+
+ //Meter: real;
+
+ HighNote: integer;
+ IlNut: integer;
+ Note: array of record
+ Start: integer;
+ Length: integer;
+ Detekt: real; // accurate place, detected in the note
+ Tone: real;
+ Perfect: boolean; // true if the note matches the original one, lit the star
+
+ // Half size Notes Patch
+ Hit: boolean; // true if the note Hits the Line
+ end;
+ end;
+
+
+var
+ // Absolute Paths
+ GamePath: string;
+ SoundPath: string;
+ SongPath: string;
+ LogPath: string;
+ ThemePath: string;
+ SkinsPath: string;
+ ScreenshotsPath: string;
+ CoversPath: string;
+ LanguagesPath: string;
+ PluginPath: string;
+ VisualsPath: string;
+ PlayListPath: string;
+
+ UserSongPath: string = '';
+ UserCoversPath: string = '';
+ UserPlaylistPath: string = '';
+
+ OGL: Boolean;
+ Done: Boolean;
+ Event: TSDL_event;
+ FileName: string;
+ Restart: boolean;
+
+ // player and music info
+ Player: array of TPlayer;
+ PlayersPlay: integer;
+
+ CurrentSong : TSong;
+
+procedure InitializePaths;
+
+Procedure Main;
+procedure MainLoop;
+procedure CheckEvents;
+procedure Sing(Sender: TScreenSing);
+procedure NewSentence(Sender: TScreenSing);
+procedure NewBeat(Sender: TScreenSing); // executed when on then new beat
+procedure NewBeatC(Sender: TScreenSing); // executed when on then new beat for click
+procedure NewBeatD(Sender: TScreenSing); // executed when on then new beat for detection
+//procedure NewHalf; // executed when in the half between beats
+procedure NewNote(Sender: TScreenSing); // detect note
+function GetMidBeat(Time: real): real;
+function GetTimeFromBeat(Beat: integer): real;
+procedure ClearScores(PlayerNum: integer);
+
+implementation
+
+uses
+ USongs,
+ UJoystick,
+ math,
+ UCommandLine,
+ ULanguage,
+ SDL_ttf,
+ USkins,
+ UCovers,
+ UCatCovers,
+ UDataBase,
+ UPlaylist,
+ UDLLManager,
+ UParty,
+ UConfig,
+ UCore,
+ UGraphicClasses,
+ UPluginDefs,
+ UPlatform;
+
+
+
+
+procedure Main;
+var
+ WndTitle: string;
+begin
+ try
+ WndTitle := USDXVersionStr;
+
+ if Platform.TerminateIfAlreadyRunning( {var} WndTitle) then
+ Exit;
+
+ //------------------------------
+ //StartUp - Create Classes and Load Files
+ //------------------------------
+ USTime := TTime.Create;
+
+ // Commandline Parameter Parser
+ Params := TCMDParams.Create;
+
+ // Log + Benchmark
+ Log := TLog.Create;
+ Log.Title := WndTitle;
+ Log.Enabled := not Params.NoLog;
+ Log.BenchmarkStart(0);
+
+ // Language
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Initialize Paths', 'Initialization');
+ InitializePaths;
+ Log.LogStatus('Load Language', 'Initialization');
+ Language := TLanguage.Create;
+
+ // Add Const Values:
+ Language.AddConst('US_VERSION', USDXVersionStr);
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Language', 1);
+
+ // SDL
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Initialize SDL', 'Initialization');
+ SDL_Init(SDL_INIT_VIDEO);
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Initializing SDL', 1);
+
+ // SDL_ttf
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Initialize SDL_ttf', 'Initialization');
+ TTF_Init();
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Initializing SDL_ttf', 1);
+
+ // Skin
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Loading Skin List', 'Initialization');
+ Skin := TSkin.Create;
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Skin List', 1);
+
+ // Ini + Paths
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Load Ini', 'Initialization');
+ Ini := TIni.Create;
+ Ini.Load;
+
+ //Load Languagefile
+ if (Params.Language <> -1) then
+ Language.ChangeLanguage(ILanguage[Params.Language])
+ else
+ Language.ChangeLanguage(ILanguage[Ini.Language]);
+
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Ini', 1);
+
+ // Sound
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Initialize Sound', 'Initialization');
+ InitializeSound();
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Initializing Sound', 1);
+
+ // Load Sound Settings from Ini
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Load Sound Settings', 'Initialization');
+ Ini.LoadSoundSettings;
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Load Sound Settings', 1);
+
+ // Theme
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Load Themes', 'Initialization');
+ Theme := TTheme.Create(ThemePath + ITheme[Ini.Theme] + '.ini', Ini.Color);
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Themes', 1);
+
+ // Covers Cache
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Creating Covers Cache', 'Initialization');
+ Covers := TCovers.Create;
+ Log.LogBenchmark('Loading Covers Cache Array', 1);
+ Log.BenchmarkStart(1);
+
+ // Category Covers
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Creating Category Covers Array', 'Initialization');
+ CatCovers:= TCatCovers.Create;
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Category Covers Array', 1);
+
+ // Songs
+ //Log.BenchmarkStart(1);
+ Log.LogStatus('Creating Song Array', 'Initialization');
+ Songs := TSongs.Create;
+ //Songs.LoadSongList;
+
+ Log.LogStatus('Creating 2nd Song Array', 'Initialization');
+ CatSongs := TCatSongs.Create;
+
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Songs', 1);
+
+ // PluginManager
+ Log.BenchmarkStart(1);
+ Log.LogStatus('PluginManager', 'Initialization');
+ DLLMan := TDLLMan.Create; // Load PluginList
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading PluginManager', 1);
+
+ {// Party Mode Manager
+ Log.BenchmarkStart(1);
+ Log.LogStatus('PartySession Manager', 'Initialization');
+ PartySession := TPartySession.Create; //Load PartySession
+
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading PartySession Manager', 1); }
+
+ // Graphics
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Initialize 3D', 'Initialization');
+ Initialize3D(WndTitle);
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Initializing 3D', 1);
+
+ // Score Saving System
+ Log.BenchmarkStart(1);
+ Log.LogStatus('DataBase System', 'Initialization');
+ DataBase := TDataBaseSystem.Create;
+
+ if (Params.ScoreFile = '') then
+ DataBase.Init ('Ultrastar.db')
+ else
+ DataBase.Init (Params.ScoreFile);
+
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading DataBase System', 1);
+
+ // Playlist Manager
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Playlist Manager', 'Initialization');
+ PlaylistMan := TPlaylistManager.Create;
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Playlist Manager', 1);
+
+ // GoldenStarsTwinkleMod
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Effect Manager', 'Initialization');
+ GoldenRec := TEffectManager.Create;
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Particel System', 1);
+
+ // Joypad
+ if (Ini.Joypad = 1) OR (Params.Joypad) then
+ begin
+ Log.BenchmarkStart(1);
+ Log.LogStatus('Initialize Joystick', 'Initialization');
+ Joy := TJoy.Create;
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Initializing Joystick', 1);
+ end;
+
+ Log.BenchmarkEnd(0);
+ Log.LogBenchmark('Loading Time', 0);
+
+ Log.LogError('Creating Core');
+ Core := TCore.Create(
+ USDXShortVersionStr,
+ MakeVersion(USDX_VERSION_MAJOR,
+ USDX_VERSION_MINOR,
+ USDX_VERSION_RELEASE,
+ chr(0))
+ );
+
+ Log.LogError('Running Core');
+ Core.Run;
+
+ //------------------------------
+ //Start- Mainloop
+ //------------------------------
+ Log.LogStatus('Main Loop', 'Initialization');
+ MainLoop;
+
+ finally
+ //------------------------------
+ //Finish Application
+ //------------------------------
+
+ // TODO:
+ // call an uninitialize routine for every initialize step
+ // or at least use the corresponding Free-Methods
+
+ UnloadOpenGL;
+ //TTF_quit();
+ SDL_Quit();
+
+ (*
+ {$ifdef WIN32}
+ if assigned(LCD) and (Ini.LPT = 1) then
+ LCD.Clear;
+ if assigned(Light) and (Ini.LPT = 2) then
+ Light.TurnOff;
+ {$endif}
+ *)
+
+ if assigned(Log) then
+ begin
+ Log.LogStatus('Main Loop', 'Finished');
+ Log.Free;
+ end;
+ end;
+end;
+
+procedure MainLoop;
+var
+ Delay: integer;
+begin
+ Delay := 0;
+ SDL_EnableKeyRepeat(125, 125);
+
+ CountSkipTime(); // JB - for some reason this seems to be needed when we use the SDL Timer functions.
+ while not Done do
+ begin
+ // joypad
+ if (Ini.Joypad = 1) or (Params.Joypad) then
+ Joy.Update;
+
+ // keyboard events
+ CheckEvents;
+
+ // display
+ done := not Display.Draw;
+ SwapBuffers;
+
+ // light
+ //Light.Refresh;
+
+ // delay
+ CountMidTime;
+
+ Delay := Floor(1000 / 100 - 1000 * TimeMid);
+
+ if Delay >= 1 then
+ SDL_Delay(Delay); // dynamic, maximum is 100 fps
+
+ CountSkipTime;
+
+ // reinitialization of graphics
+ if Restart then
+ begin
+ Reinitialize3D;
+ Restart := false;
+ end;
+
+ end;
+End;
+
+procedure CheckEvents;
+begin
+ if Assigned(Display.NextScreen) then
+ Exit;
+
+ while SDL_PollEvent( @event ) = 1 do
+ begin
+ case Event.type_ of
+ SDL_QUITEV:
+ begin
+ Display.Fade := 0;
+ Display.NextScreenWithCheck := nil;
+ Display.CheckOK := True;
+ end;
+ {
+ SDL_MOUSEBUTTONDOWN:
+ with Event.button Do
+ begin
+ if State = SDL_BUTTON_LEFT Then
+ begin
+ //
+ end;
+ end;
+ }
+ SDL_VIDEORESIZE:
+ begin
+ ScreenW := Event.resize.w;
+ ScreenH := Event.resize.h;
+
+ screen := SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE);
+ end;
+ SDL_KEYDOWN:
+ begin
+ // remap the "keypad enter" key to the "standard enter" key
+ if (Event.key.keysym.sym = SDLK_KP_ENTER) then
+ Event.key.keysym.sym := SDLK_RETURN;
+
+ if (Event.key.keysym.sym = SDLK_F11) or
+ ((Event.key.keysym.sym = SDLK_RETURN) and
+ ((Event.key.keysym.modifier and KMOD_ALT) <> 0)) then // toggle full screen
+ begin
+ Ini.FullScreen := integer( not boolean( Ini.FullScreen ) );
+
+ if boolean( Ini.FullScreen ) then
+ begin
+ SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_FULLSCREEN);
+ SDL_ShowCursor(0);
+ end
+ else
+ begin
+ SDL_SetVideoMode(ScreenW, ScreenH, (Ini.Depth+1) * 16, SDL_OPENGL or SDL_RESIZABLE);
+ SDL_ShowCursor(1);
+ end;
+
+ glViewPort(0, 0, ScreenW, ScreenH);
+ end
+ // ScreenShot hack. If Print is pressed-> Make screenshot and Save to Screenshots Path
+ else if (Event.key.keysym.sym = SDLK_SYSREQ) or (Event.key.keysym.sym = SDLK_PRINT) then
+ Display.ScreenShot
+ // popup hack... if there is a visible popup then let it handle input instead of underlying screen
+ // shoud be done in a way to be sure the topmost popup has preference (maybe error, then check)
+ else if (ScreenPopupError <> nil) and (ScreenPopupError.Visible) then
+ done := not ScreenPopupError.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True)
+ else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
+ done := not ScreenPopupCheck.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True)
+ // end of popup hack
+ else
+ begin
+ // check for Screen want to Exit
+ done := not Display.CurrentScreen^.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), True);
+
+ // If Screen wants to Exit
+ if done then
+ begin
+ // If Question Option is enabled then Show Exit Popup
+ if (Ini.AskbeforeDel = 1) then
+ begin
+ Display.CurrentScreen^.CheckFadeTo(nil,'MSG_QUIT_USDX');
+ end
+ else // When asking for exit is disabled then simply exit
+ begin
+ Display.Fade := 0;
+ Display.NextScreenWithCheck := nil;
+ Display.CheckOK := True;
+ end;
+ end;
+
+ end;
+ end;
+ {
+ SDL_JOYAXISMOTION:
+ begin
+ // not implemented
+ end;
+ }
+ SDL_JOYBUTTONDOWN:
+ begin
+ // not implemented
+ end;
+ end; // Case
+ end; // While
+end;
+
+function GetTimeForBeats(BPM, Beats: real): real;
+begin
+ Result := 60 / BPM * Beats;
+end;
+
+function GetBeats(BPM, msTime: real): real;
+begin
+ Result := BPM * msTime / 60;
+end;
+
+procedure GetMidBeatSub(BPMNum: integer; var Time: real; var CurBeat: real);
+var
+ NewTime: real;
+begin
+ if High(CurrentSong.BPM) = BPMNum then
+ begin
+ // last BPM
+ CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
+ Time := 0;
+ end
+ else
+ begin
+ // not last BPM
+ // count how much time is it for start of the new BPM and store it in NewTime
+ NewTime := GetTimeForBeats(CurrentSong.BPM[BPMNum].BPM, CurrentSong.BPM[BPMNum+1].StartBeat - CurrentSong.BPM[BPMNum].StartBeat);
+
+ // compare it to remaining time
+ if (Time - NewTime) > 0 then
+ begin
+ // there is still remaining time
+ CurBeat := CurrentSong.BPM[BPMNum].StartBeat;
+ Time := Time - NewTime;
+ end
+ else
+ begin
+ // there is no remaining time
+ CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
+ Time := 0;
+ end; // if
+ end; // if
+end;
+
+function GetMidBeat(Time: real): real;
+var
+ CurBeat: real;
+ CurBPM: integer;
+// TopBeat: real;
+// TempBeat: real;
+// TempTime: real;
+begin
+ Result := 0;
+ if Length(CurrentSong.BPM) = 1 then
+ Result := Time * CurrentSong.BPM[0].BPM / 60;
+
+ (* 2 BPMs *)
+{ if Length(CurrentSong.BPM) > 1 then begin
+ (* new system *)
+ CurBeat := 0;
+ TopBeat := GetBeats(CurrentSong.BPM[0].BPM, Time);
+ if TopBeat > CurrentSong.BPM[1].StartBeat then begin
+ // analyze second BPM
+ Time := Time - GetTimeForBeats(CurrentSong.BPM[0].BPM, CurrentSong.BPM[1].StartBeat - CurBeat);
+ CurBeat := CurrentSong.BPM[1].StartBeat;
+ TopBeat := GetBeats(CurrentSong.BPM[1].BPM, Time);
+ Result := CurBeat + TopBeat;
+
+ end
+ else
+ begin
+ (* pierwszy przedzial *)
+ Result := TopBeat;
+ end;
+ end;}
+
+ (* more BPMs *)
+ if Length(CurrentSong.BPM) > 1 then
+ begin
+ CurBeat := 0;
+ CurBPM := 0;
+ while (Time > 0) do
+ begin
+ GetMidBeatSub(CurBPM, Time, CurBeat);
+ Inc(CurBPM);
+ end;
+
+ Result := CurBeat;
+ end;
+end;
+
+function GetTimeFromBeat(Beat: integer): real;
+var
+ CurBPM: integer;
+begin
+ Result := 0;
+ if Length(CurrentSong.BPM) = 1 then
+ Result := CurrentSong.GAP / 1000 + Beat * 60 / CurrentSong.BPM[0].BPM;
+
+ (* more BPMs *)
+ if Length(CurrentSong.BPM) > 1 then
+ begin
+ Result := CurrentSong.GAP / 1000;
+ CurBPM := 0;
+ while (CurBPM <= High(CurrentSong.BPM)) and
+ (Beat > CurrentSong.BPM[CurBPM].StartBeat) do
+ begin
+ if (CurBPM < High(CurrentSong.BPM)) and
+ (Beat >= CurrentSong.BPM[CurBPM+1].StartBeat) then
+ begin
+ // full range
+ Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
+ (CurrentSong.BPM[CurBPM+1].StartBeat - CurrentSong.BPM[CurBPM].StartBeat);
+ end;
+
+ if (CurBPM = High(CurrentSong.BPM)) or
+ (Beat < CurrentSong.BPM[CurBPM+1].StartBeat) then
+ begin
+ // in the middle
+ Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
+ (Beat - CurrentSong.BPM[CurBPM].StartBeat);
+ end;
+ Inc(CurBPM);
+ end;
+
+ {
+ while (Time > 0) do
+ begin
+ GetMidBeatSub(CurBPM, Time, CurBeat);
+ Inc(CurBPM);
+ end;
+ }
+ end; // if}
+end;
+
+procedure Sing(Sender: TScreenSing);
+var
+ Count: integer;
+ CountGr: integer;
+ CP: integer;
+ Done: real;
+ N: integer;
+begin
+ LineState.CurrentTime := LineState.CurrentTime + TimeSkip;
+
+ LineState.OldBeat := LineState.CurrentBeat;
+ LineState.MidBeat := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap{ + 90 I've forgotten for what it is}) / 1000); // new system with variable BPM in function
+ LineState.CurrentBeat := Floor(LineState.MidBeat);
+
+// LineState.OldHalf := LineState.AktHalf;
+// LineState.MidHalf := LineState.MidBeat + 0.5;
+// LineState.AktHalf := Floor(LineState.MidHalf);
+
+ LineState.OldBeatC := LineState.CurrentBeatC;
+ LineState.MidBeatC := GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap) / 1000);
+ LineState.CurrentBeatC := Floor(LineState.MidBeatC);
+
+ LineState.OldBeatD := LineState.CurrentBeatD;
+ LineState.MidBeatD := -0.5+GetMidBeat(LineState.CurrentTime - (CurrentSong.Gap + 120 + 20) / 1000); // MidBeat with addition GAP
+ LineState.CurrentBeatD := Floor(LineState.MidBeatD);
+ LineState.FracBeatD := Frac(LineState.MidBeatD);
+
+ // sentences routines
+ for CountGr := 0 to 0 do //High(Gracz)
+ begin;
+ CP := CountGr;
+ // ustawianie starej parts
+ LineState.OldLine := Lines[CP].Current;
+
+ // wybieranie aktualnej parts
+ for Count := 0 to Lines[CP].High do
+ begin
+ if LineState.CurrentBeat >= Lines[CP].Line[Count].Start then
+ Lines[CP].Current := Count;
+ end;
+
+ // czysczenie nut gracza, gdy to jest nowa plansza
+ // (optymizacja raz na halfbeat jest zla)
+ if Lines[CP].Current <> LineState.OldLine then
+ NewSentence(Sender);
+
+ end; // for CountGr
+
+ // wykonuje operacje raz na beat
+ if (LineState.CurrentBeat >= 0) and (LineState.OldBeat <> LineState.CurrentBeat) then
+ NewBeat(Sender);
+
+ // make some operations on clicks
+ if {(LineState.CurrentBeatC >= 0) and }(LineState.OldBeatC <> LineState.CurrentBeatC) then
+ NewBeatC(Sender);
+
+ // make some operations when detecting new voice pitch
+ if (LineState.CurrentBeatD >= 0) and (LineState.OldBeatD <> LineState.CurrentBeatD) then
+ NewBeatD(Sender);
+
+ // wykonuje operacje w polowie beatu
+// if (LineState.AktHalf >= 1) and (LineState.OldHalf <> LineState.AktHalf) then
+// NewHalf;
+
+ // plynnie przesuwa text
+ Done := 1;
+ for N := 0 to Lines[0].Line[Lines[0].Current].HighNote do
+ begin
+ if (Lines[0].Line[Lines[0].Current].Note[N].Start <= LineState.MidBeat) and
+ (Lines[0].Line[Lines[0].Current].Note[N].Start + Lines[0].Line[Lines[0].Current].Note[N].Length >= LineState.MidBeat) then
+ begin
+ Done := (LineState.MidBeat - Lines[0].Line[Lines[0].Current].Note[N].Start) / (Lines[0].Line[Lines[0].Current].Note[N].Length);
+ end;
+ end;
+
+ N := Lines[0].Line[Lines[0].Current].HighNote;
+
+ // wylacza ostatnia nute po przejsciu
+ {// todo: Lyrics
+ if (Ini.LyricsEffect = 1) and (Done = 1) and
+ (LineState.MidBeat > Lines[0].Line[Lines[0].Current].Note[N].Start + Lines[0].Line[Lines[0].Current].Note[N].Length)
+ then Sender.LyricMain.Selected := -1;
+
+ if Done > 1 then Done := 1;
+ Sender.LyricMain.Done := Done; }
+
+ // use Done with LCD
+{ with ScreenSing do begin
+ if LyricMain.Selected >= 0 then begin
+ LCD.MoveCursor(1, LyricMain.SelectedLetter + Round((LyricMain.SelectedLength-1) * Done));
+ LCD.ShowCursor;
+ end;
+ end;}
+
+
+end;
+
+procedure NewSentence(Sender: TScreenSing);
+var
+G: Integer;
+begin
+ // czyszczenie nut graczy
+ for G := 0 to High(Player) do
+ begin
+ Player[G].IlNut := 0;
+ Player[G].HighNote := -1;
+ SetLength(Player[G].Note, 0);
+ end;
+
+ // Add Words to Lyrics
+ with Sender do
+ begin
+ {LyricMain.AddCzesc(Lines[0].Current);
+ if Lines[0].Current < Lines[0].High then
+ LyricSub.AddCzesc(Lines[0].Current+1)
+ else
+ LyricSub.Clear;}
+ while (not Lyrics.LineinQueue) and (Lyrics.LineCounter <= High(Lines[0].Line)) do
+ Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]);
+ end;
+
+ //Sender.UpdateLCD;
+
+ //On Sentence Change...
+ Sender.onSentenceChange(Lines[0].Current);
+end;
+
+procedure NewBeat(Sender: TScreenSing);
+var
+ Count: integer;
+// TempBeat: integer;
+begin
+ // ustawia zaznaczenie tekstu
+// SingScreen.LyricMain.Selected := -1;
+ for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
+ if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LineState.CurrentBeat) then
+ begin
+ // operates on currently beated note
+ //Todo: Lyrics
+ //Sender.LyricMain.Selected := Count;
+
+// LCD.MoveCursor(1, ScreenSing.LyricMain.SelectedLetter);
+// LCD.ShowCursor;
+
+ //LCD.MoveCursorBR(Sender.LyricMain.SelectedLetter);
+ //LCD.ShowCursor;
+ end;
+end;
+
+procedure NewBeatC;
+var
+ Count: integer;
+// LPT_1: integer;
+// LPT_2: integer;
+begin
+// LPT_1 := 1;
+// LPT_2 := 1;
+
+ // beat click
+ if (Ini.BeatClick = 1) and ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then
+ AudioPlayback.PlaySound(SoundLib.Click);
+
+ // debug system on LPT
+ if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0) then
+ begin
+ //LPT_1 := 0;
+// Light.LightOne(0, 150);
+
+ (*
+ Light.LightOne(1, 200); // beat light
+ if ParamStr(1) = '-doublelights' then
+ Light.LightOne(0, 200); // beat light
+ *)
+
+
+{ if ((LineState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod (Lines[0].Resolution * 2) = 0) then
+ Light.LightOne(0, 150)
+ else
+ Light.LightOne(1, 150)}
+ end;
+
+ for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
+ begin
+ if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LineState.CurrentBeatC) then
+ begin
+ // click assist
+ if Ini.ClickAssist = 1 then
+ AudioPlayback.PlaySound(SoundLib.Click);
+
+ //LPT_2 := 0;
+ (*
+ if ParamStr(1) <> '-doublelights' then
+ Light.LightOne(0, 150); //125
+ *)
+
+ // drum machine
+ (*
+ TempBeat := LineState.CurrentBeat;// + 2;
+ if (TempBeat mod 8 = 0) then Music.PlayDrum;
+ if (TempBeat mod 8 = 4) then Music.PlayClap;
+// if (TempBeat mod 4 = 2) then Music.PlayHihat;
+ if (TempBeat mod 4 <> 0) then Music.PlayHihat;
+ *)
+ end;
+ end;
+
+ {$IFDEF UseSerialPort}
+ // PortWriteB($378, LPT_1 + LPT_2 * 2); // 0 zapala
+ {$ENDIF}
+end;
+
+procedure NewBeatD(Sender: TScreenSing);
+begin
+ NewNote(Sender);
+end;
+
+//procedure NewHalf;
+//begin
+// NewNote;
+//end;
+
+procedure NewNote(Sender: TScreenSing);
+var
+ CP: integer; // current player
+ S: integer; // sentence
+ SMin: integer;
+ SMax: integer;
+ SDet: integer; // temporary: sentence of detected note
+ Count: integer;
+ Mozna: boolean;
+ New: boolean;
+ Range: integer;
+ NoteHit:boolean;
+ MaxPoints: integer; // maximal points without line bonus
+begin
+ // Log.LogStatus('Beat ' + IntToStr(LineState.CurrentBeat) + ' HalfBeat ' + IntToStr(LineState.AktHalf), 'NewBeat');
+
+ // On linux we get an AV @ NEWNOTE, line 600 of Classes/UMain.pas
+ if not assigned( AudioInputProcessor.Sound ) then
+ exit;
+
+ // analizuje dla obu graczy ten sam sygnal (Sound.OneSrcForBoth)
+ // albo juz lepiej nie
+ for CP := 0 to PlayersPlay-1 do
+ begin
+ // analyze buffer
+ AudioInputProcessor.Sound[CP].AnalyzeBuffer;
+
+ // adds some noise
+ //LineState.Tone := LineState.Tone + Round(Random(3)) - 1;
+
+ // count min and max sentence range for checking (detection is delayed to the notes we see on the screen)
+ SMin := Lines[0].Current-1;
+ if SMin < 0 then
+ SMin := 0;
+ SMax := Lines[0].Current;
+
+ // check if we can add new note
+ Mozna := false;
+ SDet:=SMin;
+ for S := SMin to SMax do
+ begin
+ for Count := 0 to Lines[0].Line[S].HighNote do
+ begin
+ if ((Lines[0].Line[S].Note[Count].Start <= LineState.CurrentBeatD)
+ and (Lines[0].Line[S].Note[Count].Start + Lines[0].Line[S].Note[Count].Length - 1 >= LineState.CurrentBeatD))
+ and (Lines[0].Line[S].Note[Count].NoteType <> ntFreestyle) // but don't allow when it's FreeStyle note
+ and (Lines[0].Line[S].Note[Count].Length > 0) then // and make sure the note lengths is at least 1
+ begin
+ SDet := S;
+ Mozna := true;
+ Break;
+ end;
+ end;
+ end;
+
+ S := SDet;
+
+ //Czas.SzczytJest := true;
+ //Czas.Tone := 27;
+
+ // gdy moze, to dodaje nute - When Mozna, it adds note (?)
+ if (AudioInputProcessor.Sound[CP].ToneValid) and (Mozna) then
+ begin
+ // operowanie na ostatniej nucie
+ for Count := 0 to Lines[0].Line[S].HighNote do
+ begin
+ if (Lines[0].Line[S].Note[Count].Start <= LineState.OldBeatD+1) and
+ (Lines[0].Line[S].Note[Count].Start +
+ Lines[0].Line[S].Note[Count].Length > LineState.OldBeatD+1) then
+ begin
+ // to robi, tylko dla pary nut (oryginalnej i gracza)
+
+ // przesuwanie tonu w odpowiednia game
+ while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone > 6) do
+ AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone - 12;
+
+ while (AudioInputProcessor.Sound[CP].Tone - Lines[0].Line[S].Note[Count].Tone < -6) do
+ AudioInputProcessor.Sound[CP].Tone := AudioInputProcessor.Sound[CP].Tone + 12;
+
+ // Half size Notes Patch
+ NoteHit := false;
+
+ //if Ini.Difficulty = 0 then Range := 2;
+ //if Ini.Difficulty = 1 then Range := 1;
+ //if Ini.Difficulty = 2 then Range := 0;
+ Range := 2 - Ini.Difficulty;
+
+ if abs(Lines[0].Line[S].Note[Count].Tone - AudioInputProcessor.Sound[CP].Tone) <= Range then
+ begin
+ AudioInputProcessor.Sound[CP].Tone := Lines[0].Line[S].Note[Count].Tone;
+
+ // Half size Notes Patch
+ NoteHit := true;
+
+ MaxPoints := 10000;
+ if (Ini.LineBonus <> 0) then
+ MaxPoints := 9000;
+
+ case Lines[0].Line[S].Note[Count].NoteType of
+ ntNormal: Player[CP].Score := Player[CP].Score + MaxPoints / Lines[0].ScoreValue *
+ Lines[0].Line[S].Note[Count].Length;
+ ntGolden: Player[CP].ScoreGolden := Player[CP].ScoreGolden + MaxPoints / Lines[0].ScoreValue *
+ (Lines[0].Line[S].Note[Count].Length * 2);
+ end;
+
+ Player[CP].ScoreI := Floor(Player[CP].Score / 10) * 10;
+ Player[CP].ScoreGoldenI := Floor(Player[CP].ScoreGolden / 10) * 10;
+
+ Player[CP].ScoreTotalI := Player[CP].ScoreI + Player[CP].ScoreGoldenI + Player[CP].ScoreLineI;
+ end;
+
+ end; // operowanie
+ end; // for
+
+ // sprawdzanie czy to nowa nuta, czy przedluzenie
+ if S = SMax then
+ begin
+ New := true;
+ // if last has the same tone
+ if (Player[CP].IlNut > 0 ) and
+ (Player[CP].Note[Player[CP].HighNote].Tone = AudioInputProcessor.Sound[CP].Tone) and
+ (Player[CP].Note[Player[CP].HighNote].Start + Player[CP].Note[Player[CP].HighNote].Length = LineState.CurrentBeatD) then
+ begin
+ New := false;
+ end;
+
+ // if is not as new note to control "beacie" (TODO: translate polish "beacie")
+ for Count := 0 to Lines[0].Line[S].HighNote do
+ begin
+ if (Lines[0].Line[S].Note[Count].Start = LineState.CurrentBeatD) then
+ New := true;
+ end;
+
+ // dodawanie nowej nuty
+ if New then
+ begin
+ // New Note
+ Player[CP].IlNut := Player[CP].IlNut + 1;
+ Player[CP].HighNote := Player[CP].HighNote + 1;
+ SetLength(Player[CP].Note, Player[CP].IlNut);
+ Player[CP].Note[Player[CP].HighNote].Start := LineState.CurrentBeatD;
+ Player[CP].Note[Player[CP].HighNote].Length := 1;
+ Player[CP].Note[Player[CP].HighNote].Tone := AudioInputProcessor.Sound[CP].Tone; // Ton || TonDokl
+ Player[CP].Note[Player[CP].HighNote].Detekt := LineState.MidBeat;
+
+ // Half Note Patch
+ Player[CP].Note[Player[CP].HighNote].Hit := NoteHit;
+
+ //Log.LogStatus('New Note ' + IntToStr(Gracz.Note[Gracz.HighNote].Start), 'NewBeat');
+ end
+ else
+ begin
+ // przedluzenie nuty
+ Player[CP].Note[Player[CP].HighNote].Length := Player[CP].Note[Player[CP].HighNote].Length + 1;
+ end;
+
+ // check for perfect note and then lit the star (on Draw)
+ for Count := 0 to Lines[0].Line[S].HighNote do
+ begin
+ if (Lines[0].Line[S].Note[Count].Start = Player[CP].Note[Player[CP].HighNote].Start) and
+ (Lines[0].Line[S].Note[Count].Length = Player[CP].Note[Player[CP].HighNote].Length) and
+ (Lines[0].Line[S].Note[Count].Tone = Player[CP].Note[Player[CP].HighNote].Tone) then
+ begin
+ Player[CP].Note[Player[CP].HighNote].Perfect := true;
+ end;
+ end;
+ end; // if S = SMax
+
+ end; // if moze
+ end; // for CP
+ // Log.LogStatus('EndBeat', 'NewBeat');
+
+ //On Sentence End -> For LineBonus + SingBar
+ if (sDet >= low(Lines[0].Line)) and (sDet <= high(Lines[0].Line)) then
+ begin
+ if assigned( Sender ) and
+ ((Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Start + Lines[0].Line[SDet].Note[Lines[0].Line[SDet].HighNote].Length - 1) = LineState.CurrentBeatD) then
+ begin
+ Sender.onSentenceEnd(sDet);
+ end;
+ end;
+
+end;
+
+procedure ClearScores(PlayerNum: integer);
+begin
+ Player[PlayerNum].Score := 0;
+ Player[PlayerNum].ScoreI := 0;
+ Player[PlayerNum].ScoreLine := 0;
+ Player[PlayerNum].ScoreLineI := 0;
+ Player[PlayerNum].ScoreGolden := 0;
+ Player[PlayerNum].ScoreGoldenI := 0;
+ Player[PlayerNum].ScoreTotalI := 0;
+end;
+
+//--------------------
+// Function sets all Absolute Paths e.g. Song Path and makes sure the Directorys exist
+//--------------------
+procedure InitializePaths;
+
+ // Initialize a Path Variable
+ // After Setting Paths, make sure that Paths exist
+ function initialize_path( out aPathVar : string; const aLocation : string ): boolean;
+ var
+ lWriteable: Boolean;
+ lAttrib : integer;
+ begin
+ lWriteable := false;
+ aPathVar := aLocation;
+
+ // Make sure the directory is needex
+ ForceDirectories(aPathVar);
+
+ if DirectoryExists(aPathVar) then
+ begin
+ lAttrib := fileGetAttr(aPathVar);
+
+ lWriteable := (lAttrib and faDirectory <> 0) and
+ not (lAttrib and faReadOnly <> 0)
+ end;
+
+ if not lWriteable then
+ Log.LogError('Error: Dir ('+ aLocation +') is Readonly');
+
+ result := lWriteable;
+ end;
+
+begin
+ initialize_path( LogPath , Platform.GetLogPath );
+ initialize_path( SoundPath , Platform.GetGameSharedPath + 'Sounds' + PathDelim );
+ initialize_path( ThemePath , Platform.GetGameSharedPath + 'Themes' + PathDelim );
+ initialize_path( SkinsPath , Platform.GetGameSharedPath + 'Skins' + PathDelim );
+ initialize_path( LanguagesPath , Platform.GetGameSharedPath + 'Languages' + PathDelim );
+ initialize_path( PluginPath , Platform.GetGameSharedPath + 'Plugins' + PathDelim );
+ initialize_path( VisualsPath , Platform.GetGameSharedPath + 'Visuals' + PathDelim );
+
+ initialize_path( ScreenshotsPath , Platform.GetGameUserPath + 'Screenshots' + PathDelim );
+
+ // Users Song Path ....
+ initialize_path( UserSongPath , Platform.GetGameUserPath + 'Songs' + PathDelim );
+ initialize_path( UserCoversPath , Platform.GetGameUserPath + 'Covers' + PathDelim );
+ initialize_path( UserPlaylistPath , Platform.GetGameUserPath + 'Playlists' + PathDelim );
+
+ // Shared Song Path ....
+ initialize_path( SongPath , Platform.GetGameSharedPath + 'Songs' + PathDelim );
+ initialize_path( CoversPath , Platform.GetGameSharedPath + 'Covers' + PathDelim );
+ initialize_path( PlaylistPath , Platform.GetGameSharedPath + 'Playlists' + PathDelim );
+
+ DecimalSeparator := '.';
+end;
+
+end.
+
diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas
index c4123dd0..c389574b 100644
--- a/Game/Code/Classes/UMusic.pas
+++ b/Game/Code/Classes/UMusic.pas
@@ -14,19 +14,9 @@ uses
type
TNoteType = (ntFreestyle, ntNormal, ntGolden);
- //http://paste.ubuntu-nl.org/51892/
-
- TMelody = record
- Path: string;
- Start: integer; // start of song in ms
- IlNut: integer; // (TODO: Il = tone, Nut(a) = Note)
- NoteLength: integer;
- end;
-
PLine = ^TLine;
TLine = record
Start: integer;
- StartNote: integer;
Lyric: string;
LyricWidth: real;
End_: integer;
@@ -40,10 +30,8 @@ type
Start: integer;
Length: integer;
Tone: integer; // full range tone
- ToneGamus: integer; // tone unified to one octave
Text: string;
- FreeStyle: boolean;
- NoteType: integer; // normal-note: 1, golden-note: 2
+ NoteType: TNoteType;
end;
end;
ALine = array of TLine; // (TODO: rename to TLineArray)
@@ -52,10 +40,10 @@ type
TLines = record
Current: integer; // for drawing of current line
High: integer;
- Number: integer;
+ Number: integer;
Resolution: integer;
NotesGAP: integer;
- NoteType: integer;
+ ScoreValue: integer;
Line: ALine;
end;
@@ -288,9 +276,6 @@ type
end;
var // TODO : JB --- THESE SHOULD NOT BE GLOBAL
- // music
- Melody: TMelody;
-
// czesci z nutami;
Lines: array of TLines;
diff --git a/Game/Code/Classes/USong.pas b/Game/Code/Classes/USong.pas
index d6021811..60f5f0bf 100644
--- a/Game/Code/Classes/USong.pas
+++ b/Game/Code/Classes/USong.pas
@@ -126,23 +126,28 @@ type
SongID: Integer; //ID of this Song in the Song Database
FolderID: Integer; //ID of the Folder containing this Song
FileName: String; //Filename of this Song w/o Path
- FullPath: String; //Path + Filename
-
- Procedure ResetAttributes; virtual; //Reset all Attributes of this object
- Procedure ReadHeader; virtual; //Reads Fileheader (Implemented by Child only)
- Procedure ReadFile; virtual; //Reads complete File (Header + Notes) (Implemented by Child only)
- Procedure WriteFile; virtual; //Writes complete File (Header + Notes) (Implemented by Child only)
- Procedure ReadFromDB; virtual; //Reads all available Information from DB
- Function CheckDB: Integer; virtual; //Checks DB for Song. Result > 0 SongExists (ID Returned)
- Function UpdateDB: Integer; virtual;//Writes all Header Information set in this Song Object to DB. Returns ID (Required when Updated first Time)
- public
+ FilePath: String; //Path of this Song
+
+ Procedure ResetAttributes; virtual; //Reset all Attributes of this object
+ Procedure ReadHeader; virtual; abstract; //Reads Fileheader (Implemented by Child only)
+ Procedure ReadFile; virtual; abstract; //Reads complete File (Header + Notes) (Implemented by Child only)
+ Procedure WriteFile; virtual; abstract; //Writes complete File (Header + Notes) (Implemented by Child only)
+ Procedure ReadFromDB; virtual; //Reads all available Information from DB
+ Function CheckDB: Integer; virtual; //Checks DB for Song. Result > 0 SongExists (ID Returned)
+ Function UpdateDB: Integer; virtual; //Writes all Header Information set in this Song Object to DB. Returns ID (Required when Updated first Time)
+
+ // procedures to manage the lyrics
+ Procedure ResetLyrics;
+ Procedure AddLyricLine(const PlayerID: Integer; const StartBeat: Integer; const RelativeBeat: Integer = -1);
+ Procedure AddNote(const PlayerID: Integer; const NoteType: Char; const NoteStart, NoteLength, NoteTone: Integer; const NoteText: WideString);
+ Function SolmizatLyrics(const NoteTone: Integer; const NoteText: WideString): WideString;
+ public
//Required Information
Title: widestring;
Artist: widestring;
Mp3: widestring; //Full Path to MP3
- Text: widestring;
Creator: widestring;
Resolution: integer;
@@ -150,7 +155,6 @@ type
GAP: real; // in miliseconds
Base : array[0..1] of integer;
- Rel : array[0..1] of integer;
Mult : integer;
MultBPM : integer;
@@ -189,14 +193,16 @@ implementation
uses
TextGL,
UIni,
- UMusic, //needed for Lines
- UMain; //needed for Player
+ UMusic; //needed for Lines
+
+var
+ RelativPosition: array [0..1] of Integer;
constructor TSong.Create(const Path: String = ''; const FolderID: Integer = 0);
begin
If (Length(Path) > 0) AND (FolderID > 0) then
begin //Read Song Infos from File or DB
- FullPath := Path;
+ FilePath := ExtractFilePath(Path);
FileName := ExtractFileName(Path);
Self.FolderID := FolderID;
SongID := CheckDB;
@@ -249,36 +255,43 @@ end;
//--------
Procedure TSong.ResetAttributes;
begin
- //to do
-end;
-
-//--------
-// Reads Fileheader (Implemented by Child only)
-//--------
-Procedure TSong.ReadHeader;
-begin
- //Implented in Childs only!
+ SongID := 0;
+ FolderID := 0;
+ FileName := '';
+ FilePath := '';
+
+ Title := '';
+ Artist := '';
+ Mp3 := '';
+ SetLength(BPM, 0);
+
+ Creator := '';
+ Resolution := 0;
+ GAP := 0;
+
+ Base[0] := 100;
+ Base[1] := 100;
+
+ Mult := 1;
+ MultBPM := 4;
+
+ Cover := '';
+ CoverID := 0;
+ Background := '';
+ Video := '';
+ VideoGAP := 0;
+
+ NotesGAP := 0;
+ Start := 0;
+ Finish := 0;
+ Relative := False;
+
+ Genre := '';
+ Edition := '';
+ Language := '';
end;
//--------
-// Reads complete File (Header + Notes) (Implemented by Child only)
-//--------
-Procedure TSong.ReadFile;
-begin
- //Implented in Childs only!
-end;
-
-
-//--------
-// Writes complete File (Header + Notes) (Implemented by Child only)
-//--------
-Procedure TSong.WriteFile;
-begin
- //Implented in Childs only!
-end;
-
-
-//--------
// Reads all available Information from DB
//--------
Procedure TSong.ReadFromDB;
@@ -304,6 +317,154 @@ begin
// to- do
end;
+Procedure TSong.ResetLyrics;
+var
+ i: Integer;
+begin
+ for i := 0 to High(Lines) do
+ begin
+ SetLength(Lines[i].Line, 0);
+ Lines[i].High := -1;
+ end;
+
+ for i := 0 to High(RelativPosition) do
+ begin
+ RelativPosition[i] := 0;
+ end;
+end;
+
+Procedure TSong.AddLyricLine(const PlayerID: Integer; const StartBeat: Integer; const RelativeBeat: Integer = -1);
+var
+ NewLineIdx: Integer;
+begin
+ NewLineIdx := High(Lines[PlayerID].Line) + 1;
+
+ with Lines[PlayerID] do
+ begin
+ // recent added line is not the last of the song
+ if (NewLineIdx > 0) then
+ Lines[PlayerID].Line[NewLineIdx - 1].LastLine := False;
+
+ // if last line, has no notes, ignore the new line (except for the RelativeBeat)
+ if (NewLineIdx < 1) OR (Lines[PlayerID].Line[NewLineIdx - 1].HighNote > -1) then
+ begin
+ // create lyric line and update references
+ SetLength(Line, NewLineIdx);
+ High := NewLineIdx;
+ Number := Number + 1;
+ with Line[High] do
+ begin
+ // default values
+ TotalNotes := 0;
+ HighNote := -1;
+ LastLine := True;
+ BaseNote := 100;
+
+ // set start beat count of this new line
+ Start := (RelativPosition[PlayerID] + StartBeat) * Mult;
+ end;
+ end;
+
+ if Relative then
+ begin
+ if RelativeBeat >= 0 then
+ // if this is a relativ song, we have to update the relativ offset
+ RelativPosition[PlayerID] := (RelativPosition[PlayerID] + RelativeBeat) * Mult
+ else
+ RelativPosition[PlayerID] := (RelativPosition[PlayerID] + StartBeat) * Mult;
+ end;
+ end;
+end;
+
+Procedure TSong.AddNote(const PlayerID: Integer; const NoteType: Char; const NoteStart, NoteLength, NoteTone: Integer; const NoteText: WideString);
+begin
+ if (High(Lines[PlayerID].Line) < 0) then
+ AddLyricLine(PlayerID, NoteStart, 0);
+
+ with Lines[PlayerID].Line[Lines[PlayerID].High] do begin
+ // array of Notes expand to have space for new Note
+ HighNote := HighNote + 1;
+ TotalNotes := TotalNotes + 1;
+ SetLength(Note, HighNote + 1);
+
+ with Note[HighNote] do
+ begin
+ Start := (RelativPosition[PlayerID] + NoteStart) * Mult;
+ Length := NoteLength * Mult;
+ Tone := NoteTone;
+ Text := SolmizatLyrics(NoteTone, NoteText);
+ Lyric := Lyric + Text;
+
+ // identify lowest note of line
+ if Tone < BaseNote then
+ BaseNote := Tone;
+ end;
+
+ case NoteType of
+ 'F': Note[HighNote].NoteType := ntFreestyle;
+ ':': Note[HighNote].NoteType := ntNormal;
+ '*': Note[HighNote].NoteType := ntGolden;
+ end;
+
+ // calculate total score value
+ if (Note[HighNote].NoteType = ntNormal) then
+ begin
+ // normal notes
+ Lines[PlayerID].ScoreValue := Lines[PlayerID].ScoreValue + Note[HighNote].Length;
+ TotalNotes := TotalNotes + Note[HighNote].Length;
+ end
+ else if (Note[HighNote].NoteType = ntGolden) then
+ begin
+ // golden notes
+ Lines[PlayerID].ScoreValue := Lines[PlayerID].ScoreValue + (Note[HighNote].Length * 2);
+ TotalNotes := TotalNotes + (Note[HighNote].Length * 2);
+ end;
+
+ // finish of the line
+ End_ := Note[HighNote].Start + Note[HighNote].Length;
+ end; // with
+end;
+
+Function TSong.SolmizatLyrics(const NoteTone: Integer; const NoteText: WideString): WideString;
+begin
+ Result := NoteText;
+
+ case Ini.Solmization of
+ 1: // european
+ case (NoteTone mod 12) of
+ 0..1: Result := 'do ';
+ 2..3: Result := 're ';
+ 4: Result := 'mi ';
+ 5..6: Result := 'fa ';
+ 7..8: Result := 'sol ';
+ 9..10: Result := 'la ';
+ 11: Result := 'si ';
+ end;
+
+ 2: // japanese
+ case (NoteTone mod 12) of
+ 0..1: Result := 'do ';
+ 2..3: Result := 're ';
+ 4: Result := 'mi ';
+ 5..6: Result := 'fa ';
+ 7..8: Result := 'so ';
+ 9..10: Result := 'la ';
+ 11: Result := 'shi ';
+ end;
+
+ 3: // american
+ case (NoteTone mod 12) of
+ 0..1: Result := 'do ';
+ 2..3: Result := 're ';
+ 4: Result := 'mi ';
+ 5..6: Result := 'fa ';
+ 7..8: Result := 'sol ';
+ 9..10: Result := 'la ';
+ 11: Result := 'ti ';
+ end;
+ end; // case Ini.Solmization
+end;
+
{constructor TSong.create( const aFileName : WideString );
begin
@@ -998,126 +1159,6 @@ begin
end;
-procedure TSong.ParseNote(LineNumber: integer; TypeP: char; StartP, DurationP, NoteP: integer; LyricS: string);
-//var
-// Space: boolean; // Auto Removed, Unused Variable
-begin
- case Ini.Solmization of
- 1: // european
- begin
- case (NoteP mod 12) of
- 0..1: LyricS := ' do ';
- 2..3: LyricS := ' re ';
- 4: LyricS := ' mi ';
- 5..6: LyricS := ' fa ';
- 7..8: LyricS := ' sol ';
- 9..10: LyricS := ' la ';
- 11: LyricS := ' si ';
- end;
- end;
- 2: // japanese
- begin
- case (NoteP mod 12) of
- 0..1: LyricS := ' do ';
- 2..3: LyricS := ' re ';
- 4: LyricS := ' mi ';
- 5..6: LyricS := ' fa ';
- 7..8: LyricS := ' so ';
- 9..10: LyricS := ' la ';
- 11: LyricS := ' shi ';
- end;
- end;
- 3: // american
- begin
- case (NoteP mod 12) of
- 0..1: LyricS := ' do ';
- 2..3: LyricS := ' re ';
- 4: LyricS := ' mi ';
- 5..6: LyricS := ' fa ';
- 7..8: LyricS := ' sol ';
- 9..10: LyricS := ' la ';
- 11: LyricS := ' ti ';
- end;
- end;
- end; // case
-
- with Lines[LineNumber].Line[Lines[LineNumber].High] do begin
- SetLength(Note, Length(Note) + 1);
- IlNut := IlNut + 1;
- HighNote := HighNote + 1;
- Melody.IlNut := Melody.IlNut + 1;
-
- Note[HighNote].Start := StartP;
- if IlNut = 1 then begin
- StartNote := Note[HighNote].Start;
- if Lines[LineNumber].Number = 1 then
- Start := -100;
-// Start := Note[HighNote].Start;
- end;
-
- Note[HighNote].Length := DurationP;
- Melody.NoteLength := Melody.NoteLength + Note[HighNote].Length;
-
- // back to the normal system with normal, golden and now freestyle notes
- case TypeP of
- 'F': Note[HighNote].NoteType := 0;
- ':': Note[HighNote].NoteType := 1;
- '*': Note[HighNote].NoteType := 2;
- end;
-
- Lines[LineNumber].NoteType := Lines[LineNumber].NoteType + Note[HighNote].Length * Note[HighNote].NoteType;
-
- Note[HighNote].Tone := NoteP;
- if Note[HighNote].Tone < Base[LineNumber] then Base[LineNumber] := Note[HighNote].Tone;
- Note[HighNote].ToneGamus := Note[HighNote].ToneGamus mod 12;
-
- Note[HighNote].Text := Copy(LyricS, 2, 100);
- Lyric := Lyric + Note[HighNote].Text;
-
- if TypeP = 'F' then
- Note[HighNote].FreeStyle := true;
-
- End_ := Note[HighNote].Start + Note[HighNote].Length;
- end; // with
-end;
-
-procedure TSong.NewSentence(LineNumberP: integer; Param1, Param2: integer);
-var
-I: Integer;
-begin
-
- // stara czesc //Alter Satz //Update Old Part
- Lines[LineNumberP].Line[Lines[LineNumberP].High].BaseNote := Base[LineNumberP];
- Lines[LineNumberP].Line[Lines[LineNumberP].High].LyricWidth := glTextWidth(PChar(Lines[LineNumberP].Line[Lines[LineNumberP].High].Lyric));
-
- //Total Notes Patch
- Lines[LineNumberP].Line[Lines[LineNumberP].High].TotalNotes := 0;
- for I := low(Lines[LineNumberP].Line[Lines[LineNumberP].High].Note) to high(Lines[LineNumberP].Line[Lines[LineNumberP].High].Note) do
- begin
- Lines[LineNumberP].Line[Lines[LineNumberP].High].TotalNotes := Lines[LineNumberP].Line[Lines[LineNumberP].High].TotalNotes + Lines[LineNumberP].Line[Lines[LineNumberP].High].Note[I].Length * Lines[LineNumberP].Line[Lines[LineNumberP].High].Note[I].NoteType;
- end;
- //Total Notes Patch End
-
-
- // nowa czesc //Neuer Satz //Update New Part
- SetLength(Lines[LineNumberP].Line, Lines[LineNumberP].Number + 1);
- Lines[LineNumberP].High := Lines[LineNumberP].High + 1;
- Lines[LineNumberP].Number := Lines[LineNumberP].Number + 1;
- Lines[LineNumberP].Line[Lines[LineNumberP].High].HighNote := -1;
-
- if self.Relative then
- begin
- Lines[LineNumberP].Line[Lines[LineNumberP].High].Start := Param1;
- Rel[LineNumberP] := Rel[LineNumberP] + Param2;
- end
- else
- Lines[LineNumberP].Line[Lines[LineNumberP].High].Start := Param1;
-
- Lines[LineNumberP].Line[Lines[LineNumberP].High].LastLine := False;
-
- Base[LineNumberP] := 100; // high number
-end;
-
procedure TSong.clear();
begin
//Main Information
diff --git a/Game/Code/Classes/USong_TextFile.pas b/Game/Code/Classes/USong_TextFile.pas
new file mode 100644
index 00000000..a3e605de
--- /dev/null
+++ b/Game/Code/Classes/USong_TextFile.pas
@@ -0,0 +1,86 @@
+unit USong_TextFile;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ Classes,
+ SysUtils,
+ USong;
+
+type
+ {*******************
+ Child of the new TSong class.
+ implements filehandling to load a song from a text file
+ *******************}
+ TSong_TextFile = class(TSong)
+ protected
+ SongFile: TextFile;
+
+ Function OpenSongFile: Boolean;
+ Function IsDataAvailable: Boolean;
+ Function GetNextLine(): String;
+ Procedure CloseSongFile;
+ end;
+
+implementation
+
+uses
+ ULog;
+
+//--------
+// Open the SongFile
+//--------
+Function TSong_TextFile.OpenSongFile: Boolean;
+begin
+ Result := False;
+
+ if not FileExists(FilePath + FileName) then
+ Log.LogError('File does not exsist', FilePath + FileName)
+ else
+ begin
+ try
+ AssignFile(SongFile, FilePath + FileName);
+ Reset(SongFile);
+ Result := True;
+ except
+ Log.LogError('Faild to open file', FilePath + FileName)
+ end;
+ end;
+end;
+
+//--------
+// More data in songfile available?
+//--------
+Function TSong_TextFile.IsDataAvailable: Boolean;
+begin
+ Result := not eof(SongFile);
+end;
+
+//--------
+// Returns the next line from the SongFile
+//--------
+Function TSong_TextFile.GetNextLine(): String;
+begin
+ ReadLn(SongFile, Result);
+ Result := Trim(Result);
+end;
+
+//--------
+// Close the SongFile
+//--------
+Procedure TSong_TextFile.CloseSongFile;
+begin
+ try
+ CloseFile(SongFile);
+ except
+ Log.LogError('Error closing file', FilePath + FileName);
+ end;
+end;
+
+end. \ No newline at end of file
diff --git a/Game/Code/Classes/USong_Txt.pas b/Game/Code/Classes/USong_Txt.pas
new file mode 100644
index 00000000..23171517
--- /dev/null
+++ b/Game/Code/Classes/USong_Txt.pas
@@ -0,0 +1,438 @@
+unit USong_Txt;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+
+uses
+ Classes,
+ SysUtils,
+ USong_TextFile;
+
+type
+ {*******************
+ Child of the new TSong class.
+ implements methods to load a song form a txt file (ultrastar file format)
+ *******************}
+ TSong_Txt = class(TSong_TextFile)
+ public
+ Procedure ReadHeader; override; //Reads Fileheader (Implemented by Child only)
+ Procedure ReadFile; override; //Reads complete File (Header + Notes) (Implemented by Child only)
+ Procedure WriteFile; override; //Writes complete File (Header + Notes) (Implemented by Child only)
+ end;
+
+implementation
+
+uses
+ UMusic,
+ UMain,
+ UPlatform,
+ ULog;
+
+type
+ TTags = (ArtistTag, TitleTag, Mp3Tag, BPMTag);
+
+//--------
+// Reads Fileheader
+//--------
+Procedure TSong_Txt.ReadHeader;
+var
+ started: Boolean;
+ line, key, value: String;
+ FloatValue: Real;
+ FoundTags: Set of TTags;
+
+ // splits a headerline in key an value
+ // returns true on success and false if this is not a valid headerline
+ Function SplitHeaderLine(const Line: String; var Key, Value: String): Boolean;
+ var
+ idx: Integer;
+ begin
+ Result := False;
+
+ idx := Pos(':', Line);
+ if idx > 0 then
+ begin
+ Key := Uppercase(Trim(Copy(Line, 2, idx - 2))); //Uppercase is for Case Insensitive Checks
+ Value := Trim(Copy(Line, idx + 1,Length(Line) - idx));
+
+ if (Length(Key) > 0) AND (Length(Value) > 0) then
+ Result := True
+ end;
+ end;
+
+ function song_StrToFloat(const aValue : String): Extended;
+ var
+ lValue: String;
+ begin
+ lValue := aValue;
+
+ if (Pos(',', lValue) <> 0) then
+ lValue[Pos(',', lValue)] := '.';
+
+ Result := StrToFloatDef(lValue, 0);
+ end;
+
+begin
+ if not OpenSongFile then
+ exit;
+
+ started := False;
+ FoundTags := [];
+
+ while isDataAvailable do
+ begin
+ line := GetNextLine();
+
+ // break if header has finished
+ if started AND ((Length(line) > 0) AND (not (line[1] = '#'))) then
+ break;
+
+ // skip invalid lines at beginning
+ if (not started) AND (line[1] = '#') then
+ started := True;
+
+ // parse line
+ if started then
+ begin
+ if (Length(line) > 0) AND not SplitHeaderLine(line, key, value) then
+ begin
+ Log.LogError('Invalide line in Header of file: ' + FilePath + FileName);
+ Log.LogError('Line: ' + line);
+ break;
+ end;
+
+ {$IFDEF UTF8_FILENAMES}
+ if ((Key = 'MP3') or (Key = 'BACKGROUND') or (Key = 'COVER') or (Key = 'VIDEO')) then
+ Value := Utf8Encode(Value);
+ {$ENDIF}
+
+ //Title
+ if (Key = 'TITLE') then
+ begin
+ Title := Value;
+ FoundTags := FoundTags + [TitleTag];
+ continue;
+ end;
+
+ //Artist
+ if (Key = 'ARTIST') then
+ begin
+ Artist := Value;
+ FoundTags := FoundTags + [ArtistTag];
+ continue;
+ end;
+
+ //MP3 File //Test if Exists
+ if (Key = 'MP3') then
+ begin
+ if FileExists(FilePath + Value) then
+ begin
+ Mp3 := FilePath + Value;
+ FoundTags := FoundTags + [Mp3Tag];
+ end
+ else
+ Log.LogError('Can''t find MP3 File: ' + FilePath + Value + ' in Song: ' + FilePath + FileName);
+ continue;
+ end;
+
+ //Beats per Minute
+ if (Key = 'BPM') then
+ begin
+ FloatValue := song_StrtoFloat( Value ) * Mult * MultBPM;
+
+ if FloatValue <> 0 then
+ begin
+ SetLength(BPM, 1);
+ BPM[0].StartBeat := 0;
+ BPM[0].BPM := floatValue;
+ FoundTags := FoundTags + [BPMTag];
+ end;
+
+ continue;
+ end;
+
+ //---------
+ //Additional Header Information
+ //---------
+
+ // Gap
+ if (Key = 'GAP') then
+ begin
+ GAP := song_StrtoFloat( Value );
+
+ continue;
+ end;
+
+ //Cover Picture
+ if (Key = 'COVER') then
+ begin
+ if FileExists(FilePath + Value) then
+ Cover := FilePath + Value
+ else
+ Log.LogError('Can''t find Cover File: ' + FilePath + Value + ' in Song: ' + FilePath + FileName);
+
+ continue;
+ end;
+
+ //Background Picture
+ if (Key = 'BACKGROUND') then
+ begin
+ if FileExists(FilePath + Value) then
+ Background := FilePath + Value
+ else
+ Log.LogError('Can''t find Background File: ' + FilePath + Value + ' in Song: ' + FilePath + FileName);
+
+ continue;
+ end;
+
+ // Video File
+ if (Key = 'VIDEO') then
+ begin
+ if FileExists(FilePath + Value) then
+ Video := FilePath + Value
+ else
+ Log.LogError('Can''t find Video File: ' + FilePath + Value + ' in Song: ' + FilePath + FileName);
+
+ continue;
+ end;
+
+ // Video Gap
+ if (Key = 'VIDEOGAP') then
+ begin
+ VideoGAP := song_StrtoFloat(Value);
+ continue;
+ end;
+
+ //Genre Sorting
+ if (Key = 'GENRE') then
+ begin
+ Genre := Value;
+ continue;
+ end;
+
+ //Edition Sorting
+ if (Key = 'EDITION') then
+ begin
+ Edition := Value;
+ continue;
+ end;
+
+ //Creator Tag
+ if (Key = 'CREATOR') then
+ begin
+ Creator := Value;
+ continue;
+ end;
+
+ //Language Sorting
+ if (Key = 'LANGUAGE') then
+ begin
+ Language := Value;
+ continue;
+ end;
+
+ // Song Start
+ if (Key = 'START') then
+ begin
+ Start := song_StrtoFloat( Value );
+ continue;
+ end;
+
+ // Song Ending
+ if (Key = 'END') then
+ begin
+ TryStrtoInt(Value, Finish);
+ continue;
+ end;
+
+ // Resolution
+ if (Key = 'RESOLUTION') then
+ begin
+ TryStrtoInt(Value, Resolution);
+ continue;
+ end;
+
+ // Notes Gap
+ if (Key = 'NOTESGAP') then
+ begin
+ TryStrtoInt(Value, NotesGAP);
+ continue;
+ end;
+
+ // Relative Notes
+ if (Key = 'RELATIVE') AND (uppercase(Value) = 'YES') then
+ begin
+ Relative := True;
+ continue;
+ end;
+
+ end; // if started
+ end; // while
+
+ if Cover = '' then
+ begin
+ Cover := platform.FindSongFile(FilePath, '*[CO].jpg');
+ end;
+
+ // check if all required infos are given
+ if not (BPMTag in FoundTags) then
+ Log.LogError('BPM Tag missing: ' + FilePath + FileName);
+
+ if not (MP3Tag in FoundTags) then
+ Log.LogError('MP3 Tag missing or invalid file: ' + FilePath + FileName);
+
+ if not (ArtistTag in FoundTags) then
+ Log.LogError('Artist Tag missing: ' + FilePath + FileName);
+
+ if not (TitleTag in FoundTags) then
+ Log.LogError('Title Tag missing: ' + FilePath + FileName);
+
+ CloseSongFile();
+end;
+
+//--------
+// Reads complete File (Header + Notes)
+//--------
+Procedure TSong_Txt.ReadFile;
+var
+ Line: String;
+ NotesRead: Boolean;
+ Values: TStringList;
+
+ Procedure ParseDelimited(const StringList: TStringList; const Value: String; const Delimiter: String; const MaxParts: Integer);
+ var
+ idx: Integer;
+ Source: String;
+ Delta: Integer;
+ begin
+ Delta := Length(Delimiter);
+ Source := Value;
+ StringList.BeginUpdate;
+ StringList.Clear;
+ try
+ while ((Pos(Delimiter, Source) > 0) OR ((MaxParts > 0) AND (StringList.count+1 >= MaxParts))) do
+ begin
+ idx := Pos(Delimiter, Source);
+ StringList.Add(Copy(Source,0,idx-1));
+ Source := Copy(Source,idx+Delta, MaxInt);
+ end;
+
+ if (Length(Source) > 0) then
+ StringList.Add(Source);
+ finally
+ StringList.EndUpdate;
+ end;
+ end;
+
+begin
+ // read Header
+ Self.ReadHeader;
+
+ OpenSongFile();
+
+ ResetLyrics;
+ NotesRead := False;
+
+ while isDataAvailable do
+ begin
+ line := GetNextLine();
+
+ // end of song
+ if (line[1] = 'E') then
+ break;
+
+ // skip invalid lines
+ if (line[1] <> ':') OR (line[1] <> 'F') OR (line[1] <> '*') OR (line[1] <> '-') OR (line[1] <> 'B') then
+ continue;
+
+ // aktuelle Zeile in einzelne Werte aufteilen
+ Values := TStringList.Create;
+ ParseDelimited(Values, line, ' ', 5);
+
+ try
+ if (line[1] = '-') then
+ if (not NotesRead) then
+ // skip newline if no notes before
+ continue
+ else
+ begin
+ // new lyric line
+ // param count: 1 (relative: 2)
+
+ if (Values.Count > 2) then
+ // relativ offset
+ begin
+ // P1
+ AddLyricLine(0, StrToInt(Values[1]), StrToInt(Values[2]));
+
+ // P2
+ if Length(Player) = 2 Then
+ AddLyricLine(1, StrToInt(Values[1]), StrToInt(Values[2]))
+ end
+ else
+ begin
+ AddLyricLine(0, StrToInt(Values[1]));
+
+ // P2
+ if Length(Player) = 2 then
+ AddLyricLine(1, StrToInt(Values[1]))
+ end;
+ end;
+
+ // new BPM set
+ if (line[1] = 'B') then
+ begin
+ // param count: 2
+ {SetLength(BPM, Length(BPM) + 1);
+ Read(SongFile, BPM[High(BPM)].StartBeat);
+ BPM[High(BPM)].StartBeat := BPM[High(BPM)].StartBeat + Rel[0];
+
+ ReadLn(SongFile, Text);
+ BPM[High(BPM)].BPM := StrToFloat(Text);
+ BPM[High(BPM)].BPM := BPM[High(BPM)].BPM * Mult * MultBPM;}
+ end;
+
+ if (line[1] = ':') OR (line[1] = '*') OR (line[1] = 'F') then
+ begin
+ // param count: 4
+ if (Values.Count < 5) then
+ Log.LogError('Error parsing line: ' + line, 'Not enough arguments.')
+ else
+ begin
+ // Check for ZeroNote
+ if StrToInt(Values[2]) = 0 then
+ Log.LogError('Found ZeroNote: "' + line + '" -> Note ignored!')
+ else
+ begin
+ // P1
+ AddNote(0, line[1], StrToInt(Values[1]), StrToInt(Values[2]), StrToInt(Values[3]), Values[4]);
+
+ // P2
+ if Length(Player) = 2 then
+ AddNote(1, line[1], StrToInt(Values[1]), StrToInt(Values[2]), StrToInt(Values[3]), Values[4]);
+ end;
+ end;
+ end;
+ except
+ on E : Exception do
+ Log.LogError('Error parsing line: ' + line, E.ClassName + ': ' + E.Message);
+ end;
+ end;
+
+ CloseSongFile();
+end;
+
+//--------
+// Writes complete File (Header + Notes)
+//--------
+Procedure TSong_Txt.WriteFile;
+begin
+end;
+
+end. \ No newline at end of file
diff --git a/Game/Code/Screens/UScreenEditConvert.pas b/Game/Code/Screens/UScreenEditConvert.pas
index a45e8458..1749d4e2 100644
--- a/Game/Code/Screens/UScreenEditConvert.pas
+++ b/Game/Code/Screens/UScreenEditConvert.pas
@@ -349,7 +349,7 @@ begin
Lines.Line[C].Note[N].Tone := Note[Nu].Tone;
Lines.Line[C].Note[N].Text := Note[Nu].Lyric;
//All Notes are Freestyle when Converted Fix:
- Lines.Line[C].Note[N].NoteType := 1;
+ Lines.Line[C].Note[N].NoteType := ntNormal;
Inc(N);
end;
end;
diff --git a/Game/Code/Screens/UScreenEditSub.pas b/Game/Code/Screens/UScreenEditSub.pas
index 2cb9d333..85ddfb3b 100644
--- a/Game/Code/Screens/UScreenEditSub.pas
+++ b/Game/Code/Screens/UScreenEditSub.pas
@@ -195,7 +195,7 @@ begin
// Play Sentence
Click := true;
AudioPlayback.Stop;
- R := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].StartNote);
+ R := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start);
if R <= AudioPlayback.Length then
begin
AudioPlayback.Position := R;
@@ -210,7 +210,7 @@ begin
PlaySentenceMidi := true;
MidiTime := USTime.GetTime;
- MidiStart := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].StartNote);
+ MidiStart := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start);
MidiStop := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_);
LastClick := -100;
@@ -219,46 +219,40 @@ begin
begin
PlaySentenceMidi := true;
MidiTime := USTime.GetTime;
- MidiStart := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].StartNote);
+ 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].StartNote)+0{-0.10};
+ AudioPlayback.Position := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].Note[0].Start)+0{-0.10};
PlayStopTime := GetTimeFromBeat(Lines[0].Line[Lines[0].Current].End_)+0;
AudioPlayback.Play;
LastClick := -100;
end;
Exit;
end;
+
// Golden Note Patch
'G':
begin
- case Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType of
- 0: Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := 2;
- 1: Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := 2;
- 2: Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := 1;
- end; // case
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Freestyle := False;
+ if (Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType = ntGolden) then
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntNormal
+ else
+ Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := ntGolden;
+
Exit;
end;
+
// Freestyle Note Patch
'F':
begin
- case Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType of
- 0:
- begin;
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := 1;
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Freestyle := False;
- end;
- 1,2:
- begin;
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].NoteType := 0;
- Lines[0].Line[Lines[0].Current].Note[CurrentNote].Freestyle := True;
- end;
- end; // case
+ 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;
+
Exit;
end;
end;
@@ -446,7 +440,6 @@ begin
Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
if CurrentNote = 0 then begin
Inc(Lines[0].Line[Lines[0].Current].Start);
- Inc(Lines[0].Line[Lines[0].Current].StartNote);
end;
end;
end;
@@ -456,7 +449,6 @@ begin
Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Start);
if CurrentNote = 0 then begin
Inc(Lines[0].Line[Lines[0].Current].Start);
- Inc(Lines[0].Line[Lines[0].Current].StartNote);
end;
if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
Inc(Lines[0].Line[Lines[0].Current].End_);
@@ -493,7 +485,6 @@ begin
Inc(Lines[0].Line[Lines[0].Current].Note[CurrentNote].Length);
if CurrentNote = 0 then begin
Dec(Lines[0].Line[Lines[0].Current].Start);
- Dec(Lines[0].Line[Lines[0].Current].StartNote);
end;
end;
@@ -504,7 +495,6 @@ begin
// resizing sentences
if CurrentNote = 0 then begin
Dec(Lines[0].Line[Lines[0].Current].Start);
- Dec(Lines[0].Line[Lines[0].Current].StartNote);
end;
if CurrentNote = Lines[0].Line[Lines[0].Current].HighNote then
@@ -664,7 +654,6 @@ begin
CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM / 2;
for C := 0 to Lines[0].High do begin
Lines[0].Line[C].Start := Lines[0].Line[C].Start div 2;
- Lines[0].Line[C].StartNote := Lines[0].Line[C].StartNote div 2;
Lines[0].Line[C].End_ := Lines[0].Line[C].End_ div 2;
for N := 0 to Lines[0].Line[C].HighNote do begin
Lines[0].Line[C].Note[N].Start := Lines[0].Line[C].Note[N].Start div 2;
@@ -681,7 +670,6 @@ begin
CurrentSong.BPM[0].BPM := CurrentSong.BPM[0].BPM * 2;
for C := 0 to Lines[0].High do begin
Lines[0].Line[C].Start := Lines[0].Line[C].Start * 2;
- Lines[0].Line[C].StartNote := Lines[0].Line[C].StartNote * 2;
Lines[0].Line[C].End_ := Lines[0].Line[C].End_ * 2;
for N := 0 to Lines[0].Line[C].HighNote do begin
Lines[0].Line[C].Note[N].Start := Lines[0].Line[C].Note[N].Start * 2;
@@ -762,7 +750,7 @@ 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].StartNote;
+ Max := Lines[0].Line[C].Note[0].Start;
case (Max - Min) of
0: S := Max;
1: S := Max;
@@ -806,7 +794,6 @@ begin
CNew := CStart + 1;
NStart := CurrentNote;
Lines[0].Line[CNew].Start := Lines[0].Line[CStart].Note[NStart].Start;
- Lines[0].Line[CNew].StartNote := Lines[0].Line[CStart].Note[NStart].Start;
Lines[0].Line[CNew].Lyric := '';
Lines[0].Line[CNew].LyricWidth := 0;
Lines[0].Line[CNew].End_ := 0;
@@ -995,7 +982,6 @@ begin
if N = 0 then begin // fix beginning
Inc(Lines[0].Line[C].Start, Move);
- Inc(Lines[0].Line[C].StartNote, Move);
end;
if N = Lines[0].Line[C].HighNote then // fix ending
@@ -1089,14 +1075,13 @@ begin
// 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].StartNote +
- (Lines[0].Line[Src + C].StartNote - Lines[0].Line[Src + C - 1].StartNote);
+ 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].IlNut := 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].StartNote := Lines[0].Line[Dst + C].Start;
Lines[0].Line[Dst + C].End_ := Lines[0].Line[Dst + C].Start + 1;
end;
diff --git a/Game/Code/Screens/UScreenSing.pas b/Game/Code/Screens/UScreenSing.pas
index 5b185200..ccf75441 100644
--- a/Game/Code/Screens/UScreenSing.pas
+++ b/Game/Code/Screens/UScreenSing.pas
@@ -1357,7 +1357,7 @@ begin
//PhrasenBonus - Line Bonus Mod
//Generate Steps 0 to 8
- A := Floor(A / (B * Lines[0].Line[S].TotalNotes / Lines[0].NoteType) * 8);
+ A := Floor(A / (B * Lines[0].Line[S].TotalNotes / Lines[0].ScoreValue) * 8);
If (Ini.LineBonus > 0) then
begin
diff --git a/Game/Code/Screens/UScreenSingModi.pas b/Game/Code/Screens/UScreenSingModi.pas
index 2a3a64f5..87e01e00 100644
--- a/Game/Code/Screens/UScreenSingModi.pas
+++ b/Game/Code/Screens/UScreenSingModi.pas
@@ -1,702 +1,701 @@
-unit UScreenSingModi;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-
-uses UMenu,
- UMusic,
- SDL,
- SysUtils,
- UFiles,
- UTime,
- USongs,
- UIni,
- ULog,
- UTexture,
- ULyrics,
- TextGL,
- OpenGL12,
-
- UThemes,
- //ULCD, //TODO: maybe LCD Support as Plugin?
- UScreenSing,
- ModiSDK;
-
-type
- TScreenSingModi = class(TScreenSing)
- protected
- //paused: boolean; //Pause Mod
- //PauseTime: Real;
- //NumEmptySentences: integer;
- public
- //TextTime: integer;
-
- //StaticP1: integer;
- //StaticP1ScoreBG: integer;
- //TextP1: integer;
- //TextP1Score: integer;
-
- //StaticP2R: integer;
- //StaticP2RScoreBG: integer;
- //TextP2R: integer;
- //TextP2RScore: integer;
-
- //StaticP2M: integer;
- //StaticP2MScoreBG: integer;
- //TextP2M: integer;
- //TextP2MScore: integer;
-
- //StaticP3R: integer;
- //StaticP3RScoreBG: integer;
- //TextP3R: integer;
- //TextP3RScore: integer;
-
- //Tex_Background: TTexture;
- //FadeOut: boolean;
- //LyricMain: TLyric;
- //LyricSub: TLyric;
- Winner: Byte; //Who Wins
- PlayerInfo: TPlayerInfo;
- TeamInfo: TTeamInfo;
-
- constructor Create; override;
- procedure onShow; override;
- //procedure onShowFinish; override;
- function ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; override;
- function Draw: boolean; override;
- procedure Finish; override;
- //procedure UpdateLCD; //TODO: maybe LCD Support as Plugin?
- //procedure Pause; //Pause Mod(Toggles Pause)
- end;
-
-type
+unit UScreenSingModi;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+
+uses UMenu,
+ UMusic,
+ SDL,
+ SysUtils,
+ UFiles,
+ UTime,
+ USongs,
+ UIni,
+ ULog,
+ UTexture,
+ ULyrics,
+ TextGL,
+ OpenGL12,
+
+ UThemes,
+ //ULCD, //TODO: maybe LCD Support as Plugin?
+ UScreenSing,
+ ModiSDK;
+
+type
+ TScreenSingModi = class(TScreenSing)
+ protected
+ //paused: boolean; //Pause Mod
+ //PauseTime: Real;
+ //NumEmptySentences: integer;
+ public
+ //TextTime: integer;
+
+ //StaticP1: integer;
+ //StaticP1ScoreBG: integer;
+ //TextP1: integer;
+ //TextP1Score: integer;
+
+ //StaticP2R: integer;
+ //StaticP2RScoreBG: integer;
+ //TextP2R: integer;
+ //TextP2RScore: integer;
+
+ //StaticP2M: integer;
+ //StaticP2MScoreBG: integer;
+ //TextP2M: integer;
+ //TextP2MScore: integer;
+
+ //StaticP3R: integer;
+ //StaticP3RScoreBG: integer;
+ //TextP3R: integer;
+ //TextP3RScore: integer;
+
+ //Tex_Background: TTexture;
+ //FadeOut: boolean;
+ //LyricMain: TLyric;
+ //LyricSub: TLyric;
+ Winner: Byte; //Who Wins
+ PlayerInfo: TPlayerInfo;
+ TeamInfo: TTeamInfo;
+
+ constructor Create; override;
+ procedure onShow; override;
+ //procedure onShowFinish; override;
+ function ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; override;
+ function Draw: boolean; override;
+ procedure Finish; override;
+ //procedure UpdateLCD; //TODO: maybe LCD Support as Plugin?
+ //procedure Pause; //Pause Mod(Toggles Pause)
+ end;
+
+type
TCustomSoundEntry = record
Filename : String;
Stream : TAudioPlaybackStream;
end;
-var
- //Custom Sounds
- CustomSounds: array of TCustomSoundEntry;
-
-//Procedured for Plugin
-function LoadTex (const Name: PChar; Typ: TTextureType): TsmallTexture; stdcall;
-//function Translate (const Name: PChar): PChar; stdcall;
-procedure Print (const Style, Size: Byte; const X, Y: Real; const Text: PChar); stdcall; //Procedure to Print Text
-function LoadSound (const Name: PChar): Cardinal; stdcall; //Procedure that loads a Custom Sound
-procedure PlaySound (const Index: Cardinal); stdcall; //Plays a Custom Sound
-
-//Utilys
-function ToSentences(Const Lines: TLines): TSentences;
-
-implementation
-uses UGraphic, UDraw, UMain, Classes, URecord, ULanguage, math, UDLLManager, USkins, UGraphicClasses;
-
-// Method for input parsing. If False is returned, GetNextWindow
-// should be checked to know the next window to load;
-function TScreenSingModi.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean;
-begin
- Result := true;
- If (PressedDown) Then
- begin // Key Down
- case PressedKey of
-
- SDLK_ESCAPE,
- SDLK_BACKSPACE :
- begin
- Finish;
- AudioPlayback.PlaySound(SoundLib.Back);
- FadeTo(@ScreenPartyScore);
- end;
-
- else
- Result := inherited ParseInput(PressedKey, CharCode, PressedDown);
- end;
- end;
-end;
-
-constructor TScreenSingModi.Create;
-begin
- inherited Create;
-
-end;
-
-function ToSentences(Const Lines: TLines): TSentences;
-var
- I, J: Integer;
-begin
- Result.Current := Lines.Current;
- Result.High := Lines.High;
- Result.Number := Lines.Number;
- Result.Resolution := Lines.Resolution;
- Result.NotesGAP := Lines.NotesGAP;
- Result.TotalLength := Lines.NoteType;
-
- SetLength(Result.Sentence, Length(Lines.Line));
- for I := low(Result.Sentence) to high(Result.Sentence) do
- begin
- Result.Sentence[I].Start := Lines.Line[I].Start;
- Result.Sentence[I].StartNote := Lines.Line[I].StartNote;
- Result.Sentence[I].Lyric := Lines.Line[I].Lyric;
- Result.Sentence[I].LyricWidth := Lines.Line[I].LyricWidth;
- Result.Sentence[I].End_ := Lines.Line[I].End_;
- Result.Sentence[I].BaseNote := Lines.Line[I].BaseNote;
- Result.Sentence[I].HighNote := Lines.Line[I].HighNote;
- Result.Sentence[I].IlNut := Lines.Line[I].IlNut;
- Result.Sentence[I].TotalNotes := Lines.Line[I].TotalNotes;
-
- SetLength(Result.Sentence[I].Note, Length(Lines.Line[I].Note));
- for J := low(Result.Sentence[I].Note) to high(Result.Sentence[I].Note) do
- begin
- Result.Sentence[I].Note[J].Color := Lines.Line[I].Note[J].Color;
- Result.Sentence[I].Note[J].Start := Lines.Line[I].Note[J].Start;
- Result.Sentence[I].Note[J].Length := Lines.Line[I].Note[J].Length;
- Result.Sentence[I].Note[J].Tone := Lines.Line[I].Note[J].Tone;
- Result.Sentence[I].Note[J].ToneGamus := Lines.Line[I].Note[J].ToneGamus;
- //Result.Sentence[I].Note[J].Text := Lines.Line[I].Note[J].Tekst;
- Result.Sentence[I].Note[J].FreeStyle := Lines.Line[I].Note[J].FreeStyle;
- Result.Sentence[I].Note[J].Typ := Lines.Line[I].Note[J].NoteType;
- end;
- end;
-end;
-
-procedure TScreenSingModi.onShow;
-var
- I: Integer;
-begin
- inherited;
-
- PlayersPlay := TeamInfo.NumTeams;
-
- if DLLMan.Selected.LoadSong then //Start with Song
- begin
- inherited;
- end
- else //Start Without Song
- begin
- AudioInput.CaptureStart;
- end;
-
-//Set Playerinfo
- PlayerInfo.NumPlayers := PlayersPlay;
- for I := 0 to PlayerInfo.NumPlayers-1 do
- begin
- PlayerInfo.Playerinfo[I].Name := PChar(Ini.Name[I]);
- PlayerInfo.Playerinfo[I].Score := 0;
- PlayerInfo.Playerinfo[I].Bar := 50;
- PlayerInfo.Playerinfo[I].Enabled := True;
- end;
-
- for I := PlayerInfo.NumPlayers to high(PlayerInfo.Playerinfo) do
- begin
- PlayerInfo.Playerinfo[I].Score:= 0;
- PlayerInfo.Playerinfo[I].Bar := 0;
- PlayerInfo.Playerinfo[I].Enabled := False;
- end;
-
- {Case PlayersPlay of
- 1: begin
- PlayerInfo.Playerinfo[0].PosX := Static[StaticP1ScoreBG].Texture.X;
- PlayerInfo.Playerinfo[0].PosY := Static[StaticP1ScoreBG].Texture.Y + Static[StaticP1ScoreBG].Texture.H;
- end;
- 2,4: begin
- PlayerInfo.Playerinfo[0].PosX := Static[StaticP1TwoPScoreBG].Texture.X;
- PlayerInfo.Playerinfo[0].PosY := Static[StaticP1TwoPScoreBG].Texture.Y + Static[StaticP1TwoPScoreBG].Texture.H;
- PlayerInfo.Playerinfo[2].PosX := Static[StaticP1TwoPScoreBG].Texture.X;
- PlayerInfo.Playerinfo[2].PosY := Static[StaticP1TwoPScoreBG].Texture.Y + Static[StaticP1TwoPScoreBG].Texture.H;
- PlayerInfo.Playerinfo[1].PosX := Static[StaticP2RScoreBG].Texture.X;
- PlayerInfo.Playerinfo[1].PosY := Static[StaticP2RScoreBG].Texture.Y + Static[StaticP2RScoreBG].Texture.H;
- PlayerInfo.Playerinfo[3].PosX := Static[StaticP2RScoreBG].Texture.X;
- PlayerInfo.Playerinfo[3].PosY := Static[StaticP2RScoreBG].Texture.Y + Static[StaticP2RScoreBG].Texture.H;
- end;
- 3,6: begin
- PlayerInfo.Playerinfo[0].PosX := Static[StaticP1ThreePScoreBG].Texture.X;
- PlayerInfo.Playerinfo[0].PosY := Static[StaticP1ThreePScoreBG].Texture.Y + Static[StaticP1ThreePScoreBG].Texture.H;
- PlayerInfo.Playerinfo[3].PosX := Static[StaticP1ThreePScoreBG].Texture.X;
- PlayerInfo.Playerinfo[3].PosY := Static[StaticP1ThreePScoreBG].Texture.Y + Static[StaticP1ThreePScoreBG].Texture.H;
- PlayerInfo.Playerinfo[1].PosX := Static[StaticP2MScoreBG].Texture.X;
- PlayerInfo.Playerinfo[1].PosY := Static[StaticP2MScoreBG].Texture.Y + Static[StaticP2MScoreBG].Texture.H;
- PlayerInfo.Playerinfo[4].PosX := Static[StaticP2MScoreBG].Texture.X;
- PlayerInfo.Playerinfo[4].PosY := Static[StaticP2MScoreBG].Texture.Y + Static[StaticP2MScoreBG].Texture.H;
- PlayerInfo.Playerinfo[2].PosX := Static[StaticP3RScoreBG].Texture.X;
- PlayerInfo.Playerinfo[2].PosY := Static[StaticP3RScoreBG].Texture.Y + Static[StaticP3RScoreBG].Texture.H;
- PlayerInfo.Playerinfo[5].PosX := Static[StaticP3RScoreBG].Texture.X;
- PlayerInfo.Playerinfo[5].PosY := Static[StaticP3RScoreBG].Texture.Y + Static[StaticP3RScoreBG].Texture.H;
- end;
- end; }
-
- // play music (I)
- //Music.CaptureStart;
- //Music.MoveTo(AktSong.Start);
-
- //Init Plugin
- if not DLLMan.PluginInit(TeamInfo, PlayerInfo, ToSentences(Lines[0]), LoadTex, Print, LoadSound, PlaySound) then
- begin
- //Fehler
- Log.LogError('Could not Init Plugin');
- Halt;
- end;
-
- // Set Background (Little Workaround, maybe change sometime)
- if (DLLMan.Selected.LoadBack) AND (DLLMan.Selected.LoadSong) then
- ScreenSing.Tex_Background := Tex_Background;
-
- Winner := 0;
-
- //Set Score Visibility
- {if PlayersPlay = 1 then begin
- Text[TextP1Score].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP1ScoreBG].Visible := DLLMan.Selected.ShowScore;
- end;
-
- if (PlayersPlay = 2) OR (PlayersPlay = 4) then begin
- Text[TextP1TwoPScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP1TwoPScoreBG].Visible := DLLMan.Selected.ShowScore;
-
- Text[TextP2RScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP2RScoreBG].Visible := DLLMan.Selected.ShowScore;
- end;
-
- if (PlayersPlay = 3) OR (PlayersPlay = 6) then begin
- Text[TextP1ThreePScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP1ThreePScoreBG].Visible := DLLMan.Selected.ShowScore;
-
- Text[TextP2MScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP2MScoreBG].Visible := DLLMan.Selected.ShowScore;
-
- Text[TextP3RScore].Visible := DLLMan.Selected.ShowScore;
- Static[StaticP3RScoreBG].Visible := DLLMan.Selected.ShowScore;
- end; }
-end;
-
-function TScreenSingModi.Draw: boolean;
-var
- Min: integer;
- Sec: integer;
- Tekst: string;
- S, I: integer;
- T: integer;
-begin
- Result := false;
-
- //Set Playerinfo
- PlayerInfo.NumPlayers := PlayersPlay;
- for I := 0 to PlayerInfo.NumPlayers-1 do
- begin
- PlayerInfo.Playerinfo[I].Name := PChar(Player[I].Name);
- if PlayerInfo.Playerinfo[I].Enabled then
- begin
- if (Player[I].ScoreTotalI<=10000) then
- PlayerInfo.Playerinfo[I].Score:= Player[I].ScoreTotalI;
- PlayerInfo.Playerinfo[I].Bar := Round(Scores.Players[I].RBPos * 100);
- end;
- end;
-
- //Show Score
- if DLLMan.Selected.ShowScore then
- begin
- {//ScoreBG Mod
- // set player colors
- if PlayersPlay = 4 then begin
- if ScreenAct = 1 then begin
- LoadColor(Static[StaticP1TwoP].Texture.ColR, Static[StaticP1TwoP].Texture.ColG,
- Static[StaticP1TwoP].Texture.ColB, 'P1Dark');
- LoadColor(Static[StaticP2R].Texture.ColR, Static[StaticP2R].Texture.ColG,
- Static[StaticP2R].Texture.ColB, 'P2Dark');
-
-
-
- LoadColor(Static[StaticP1TwoPScoreBG].Texture.ColR, Static[StaticP1TwoPScoreBG].Texture.ColG,
- Static[StaticP1TwoPScoreBG].Texture.ColB, 'P1Dark');
- LoadColor(Static[StaticP2RScoreBG].Texture.ColR, Static[StaticP2RScoreBG].Texture.ColG,
- Static[StaticP2RScoreBG].Texture.ColB, 'P2Dark');
-
-
-
- end;
- if ScreenAct = 2 then begin
- LoadColor(Static[StaticP1TwoP].Texture.ColR, Static[StaticP1TwoP].Texture.ColG,
- Static[StaticP1TwoP].Texture.ColB, 'P3Dark');
- LoadColor(Static[StaticP2R].Texture.ColR, Static[StaticP2R].Texture.ColG,
- Static[StaticP2R].Texture.ColB, 'P4Dark');
-
-
-
- LoadColor(Static[StaticP1TwoPScoreBG].Texture.ColR, Static[StaticP1TwoPScoreBG].Texture.ColG,
- Static[StaticP1TwoPScoreBG].Texture.ColB, 'P3Dark');
- LoadColor(Static[StaticP2RScoreBG].Texture.ColR, Static[StaticP2RScoreBG].Texture.ColG,
- Static[StaticP2RScoreBG].Texture.ColB, 'P4Dark');
-
-
-
- end;
- end;
-
- if PlayersPlay = 6 then begin
- if ScreenAct = 1 then begin
- LoadColor(Static[StaticP1ThreeP].Texture.ColR, Static[StaticP1ThreeP].Texture.ColG,
- Static[StaticP1ThreeP].Texture.ColB, 'P1Dark');
- LoadColor(Static[StaticP2M].Texture.ColR, Static[StaticP2M].Texture.ColG,
- Static[StaticP2R].Texture.ColB, 'P2Dark');
- LoadColor(Static[StaticP3R].Texture.ColR, Static[StaticP3R].Texture.ColG,
- Static[StaticP3R].Texture.ColB, 'P3Dark');
-
-
-
- LoadColor(Static[StaticP1ThreePScoreBG].Texture.ColR, Static[StaticP1ThreePScoreBG].Texture.ColG,
- Static[StaticP1ThreePScoreBG].Texture.ColB, 'P1Dark');
- LoadColor(Static[StaticP2MScoreBG].Texture.ColR, Static[StaticP2MScoreBG].Texture.ColG,
- Static[StaticP2RScoreBG].Texture.ColB, 'P2Dark');
- LoadColor(Static[StaticP3RScoreBG].Texture.ColR, Static[StaticP3RScoreBG].Texture.ColG,
- Static[StaticP3RScoreBG].Texture.ColB, 'P3Dark');
-
-
-
- end;
- if ScreenAct = 2 then begin
- LoadColor(Static[StaticP1ThreeP].Texture.ColR, Static[StaticP1ThreeP].Texture.ColG,
- Static[StaticP1ThreeP].Texture.ColB, 'P4Dark');
- LoadColor(Static[StaticP2M].Texture.ColR, Static[StaticP2M].Texture.ColG,
- Static[StaticP2R].Texture.ColB, 'P5Dark');
- LoadColor(Static[StaticP3R].Texture.ColR, Static[StaticP3R].Texture.ColG,
- Static[StaticP3R].Texture.ColB, 'P6Dark');
-
-
-
-
- LoadColor(Static[StaticP1ThreePScoreBG].Texture.ColR, Static[StaticP1ThreePScoreBG].Texture.ColG,
- Static[StaticP1ThreePScoreBG].Texture.ColB, 'P4Dark');
- LoadColor(Static[StaticP2MScoreBG].Texture.ColR, Static[StaticP2MScoreBG].Texture.ColG,
- Static[StaticP2RScoreBG].Texture.ColB, 'P5Dark');
- LoadColor(Static[StaticP3RScoreBG].Texture.ColR, Static[StaticP3RScoreBG].Texture.ColG,
- Static[StaticP3RScoreBG].Texture.ColB, 'P6Dark');
-
-
-
-
- end;
- end;
- //end ScoreBG Mod }
-
- // set player names (for 2 screens and only Singstar skin)
- if ScreenAct = 1 then begin
- Text[TextP1].Text := 'P1';
- Text[TextP1TwoP].Text := 'P1'; // added for ps3 skin
- Text[TextP1ThreeP].Text := 'P1'; // added for ps3 skin
- Text[TextP2R].Text := 'P2';
- Text[TextP2M].Text := 'P2';
- Text[TextP3R].Text := 'P3';
- end;
-
- if ScreenAct = 2 then begin
- case PlayersPlay of
- 4: begin
- Text[TextP1TwoP].Text := 'P3';
- Text[TextP2R].Text := 'P4';
- end;
- 6: begin
- Text[TextP1ThreeP].Text := 'P4';
- Text[TextP2M].Text := 'P5';
- Text[TextP3R].Text := 'P6';
- end;
- end; // case
- end; // if
-
-
- // stereo <- and where iss P2M? or P3?
- Static[StaticP1].Texture.X := Static[StaticP1].Texture.X + 10*ScreenX;
- Text[TextP1].X := Text[TextP1].X + 10*ScreenX;
-
- {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X + 10*ScreenX;
- Text[TextP1Score].X := Text[TextP1Score].X + 10*ScreenX;}
-
- Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X + 10*ScreenX;
- Text[TextP2R].X := Text[TextP2R].X + 10*ScreenX;
-
- {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X + 10*ScreenX;
- Text[TextP2RScore].X := Text[TextP2RScore].X + 10*ScreenX;}
-
- // .. and scores
- {if PlayersPlay = 1 then begin
- Tekst := IntToStr(Player[0].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP1Score].Text := Tekst;
- end;
-
- if PlayersPlay = 2 then begin
- Tekst := IntToStr(Player[0].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP1TwoPScore].Text := Tekst;
-
- Tekst := IntToStr(Player[1].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP2RScore].Text := Tekst;
- end;
-
- if PlayersPlay = 3 then begin
- Tekst := IntToStr(Player[0].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP1ThreePScore].Text := Tekst;
-
- Tekst := IntToStr(Player[1].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP2MScore].Text := Tekst;
-
- Tekst := IntToStr(Player[2].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP3RScore].Text := Tekst;
- end;
-
- if PlayersPlay = 4 then begin
- if ScreenAct = 1 then begin
- Tekst := IntToStr(Player[0].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP1TwoPScore].Text := Tekst;
-
- Tekst := IntToStr(Player[1].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP2RScore].Text := Tekst;
- end;
- if ScreenAct = 2 then begin
- Tekst := IntToStr(Player[2].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP1TwoPScore].Text := Tekst;
-
- Tekst := IntToStr(Player[3].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP2RScore].Text := Tekst;
- end;
- end;
-
- if PlayersPlay = 6 then begin
- if ScreenAct = 1 then begin
- Tekst := IntToStr(Player[0].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP1ThreePScore].Text := Tekst;
-
- Tekst := IntToStr(Player[1].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP2MScore].Text := Tekst;
-
- Tekst := IntToStr(Player[2].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP3RScore].Text := Tekst;
- end;
- if ScreenAct = 2 then begin
- Tekst := IntToStr(Player[3].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP1ThreePScore].Text := Tekst;
-
- Tekst := IntToStr(Player[4].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP2MScore].Text := Tekst;
-
- Tekst := IntToStr(Player[5].ScoreTotalI);
- while Length(Tekst) < 5 do Tekst := '0' + Tekst;
- Text[TextP3RScore].Text := Tekst;
- end;
- end; }
-
- end; //ShowScore
-
- for S := 1 to 1 do
- Static[S].Texture.X := Static[S].Texture.X + 10*ScreenX;
-
- for T := 0 to 1 do
- Text[T].X := Text[T].X + 10*ScreenX;
-
- if DLLMan.Selected.LoadSong then
- begin
- // update static menu with time ...
- Min := Round(LineState.CurrentTime) div 60;
- Sec := Round(LineState.CurrentTime) mod 60;
- Text[TextTimeText].Text := '';
- if Min < 10 then Text[TextTimeText].Text := '0';
- Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Min) + ':';
- if Sec < 10 then Text[TextTimeText].Text := Text[TextTimeText].Text + '0';
- Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Sec);
- end;
-
- // draw static menu (BG)
- DrawBG;
-
- //Draw Background
- if (DllMan.Selected.LoadSong) AND (DllMan.Selected.LoadBack) then
- SingDrawBackground;
-
- // comment by blindy: wo zum henker wird denn in diesem screen ein video abgespielt?
- // update and draw movie
- // <mog> wie wo wadd? also in der selben funktion in der uscreensing kommt des video in der zeile 995, oder was wollteste wissen? :X
-{ if ShowFinish and CurrentSong.VideoLoaded AND DllMan.Selected.LoadVideo then begin
- UpdateSmpeg; // this only draws
- end;}
-
- // draw static menu (FG)
- DrawFG;
-
- if ShowFinish then begin
- if DllMan.Selected.LoadSong then
- begin
- if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or (LineState.CurrentTime*1000 <= CurrentSong.Finish)) then begin
- //Pause Mod:
- if not Paused then
- Sing(Self); // analyze song
- end else begin
- if not FadeOut then begin
- Finish;
- FadeOut := true;
- FadeTo(@ScreenPartyScore);
- end;
- end;
- end;
- end;
-
- // draw custom items
- SingModiDraw(PlayerInfo); // always draw
-
- //GoldenNoteStarsTwinkle Mod
- GoldenRec.SpawnRec;
- //GoldenNoteStarsTwinkle Mod
-
- //Update PlayerInfo
- for I := 0 to PlayerInfo.NumPlayers-1 do
- begin
- if PlayerInfo.Playerinfo[I].Enabled then
- begin
- //PlayerInfo.Playerinfo[I].Bar := Player[I].ScorePercent;
- PlayerInfo.Playerinfo[I].Score := Player[I].ScoreTotalI;
- end;
- end;
-
- if ((ShowFinish) AND (NOT Paused)) then
- begin
- if not DLLMan.PluginDraw(Playerinfo, Lines[0].Current) then
- begin
- if not FadeOut then begin
- Finish;
- FadeOut := true;
- FadeTo(@ScreenPartyScore);
- end;
- end;
- end;
-
- //Change PlayerInfo/Changeables
- for I := 0 to PlayerInfo.NumPlayers-1 do
- begin
- if (Player[I].ScoreTotalI <> PlayerInfo.Playerinfo[I].Score) then
- begin
- //Player[I].ScoreTotal := Player[I].ScoreTotal + (PlayerInfo.Playerinfo[I].Score - Player[I].ScoreTotalI);
- Player[I].ScoreTotalI := PlayerInfo.Playerinfo[I].Score;
- end;
- {if (PlayerInfo.Playerinfo[I].Bar <> Player[I].ScorePercent) then
- Player[I].ScorePercentTarget := PlayerInfo.Playerinfo[I].Bar; }
- end;
-
- // back stereo
- Static[StaticP1].Texture.X := Static[StaticP1].Texture.X - 10*ScreenX;
- Text[TextP1].X := Text[TextP1].X - 10*ScreenX;
-
- {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X - 10*ScreenX;
- Text[TextP1Score].X := Text[TextP1Score].X - 10*ScreenX;}
-
-
- Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X - 10*ScreenX;
- Text[TextP2R].X := Text[TextP2R].X - 10*ScreenX;
-
- {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X - 10*ScreenX;
- Text[TextP2RScore].X := Text[TextP2RScore].X - 10*ScreenX;}
-
-
- for S := 1 to 1 do
- Static[S].Texture.X := Static[S].Texture.X - 10*ScreenX;
-
- for T := 0 to 1 do
- Text[T].X := Text[T].X - 10*ScreenX;
-
- Result := true;
-end;
-
-procedure TScreenSingModi.Finish;
-begin
-inherited Finish;
-
-Winner := DllMan.PluginFinish(PlayerInfo);
-
-//Log.LogError('Winner: ' + InttoStr(Winner));
-
-//DLLMan.UnLoadPlugin;
-end;
-
-function LoadTex (const Name: PChar; Typ: TTextureType): TsmallTexture; stdcall;
-var
- Texname, EXT: String;
- Tex: TTexture;
-begin
- //Get texture Name
- TexName := Skin.GetTextureFileName(String(Name));
- //Get File Typ
- Ext := ExtractFileExt(TexName);
- if (uppercase(Ext) = '.JPG') then
- Ext := 'JPG'
- else
- Ext := 'BMP';
-
- Tex := Texture.LoadTexture(TexName, UTexture.TTextureType(Typ), 0);
-
- Result.TexNum := Tex.TexNum;
- Result.W := Tex.W;
- Result.H := Tex.H;
-end;
-{
-function Translate (const Name: PChar): PChar; stdcall;
-begin
- Result := PChar(Language.Translate(String(Name)));
-end; }
-
-procedure Print (const Style, Size: Byte; const X, Y: Real; const Text: PChar); stdcall; //Procedure to Print Text
-begin
- SetFontItalic ((Style and 128) = 128);
- SetFontStyle(Style and 7);
- SetFontSize(Size);
- SetFontPos (X, Y);
- glPrint (PChar(Language.Translate(String(Text))));
-end;
-
-function LoadSound (const Name: PChar): Cardinal; stdcall; //Procedure that loads a Custom Sound
-var
- S: TAudioPlaybackStream;
- I: Integer;
- F: String;
-begin
- //Search for Sound in already loaded Sounds
- F := UpperCase(SoundPath + FileName);
- For I := 0 to High(CustomSounds) do
- begin
- if (UpperCase(CustomSounds[I].Filename) = F) then
- begin
- Result := I;
- Exit;
- end;
- end;
-
- S := AudioPlayback.OpenSound(SoundPath + String(Name));
- if (S <> nil) then
- Result := High(CustomSounds)
- else
- Result := 0;
-end;
-
-procedure PlaySound (const Index: Cardinal); stdcall; //Plays a Custom Sound
-begin
- if (Index <= High(CustomSounds)) then
- AudioPlayback.PlaySound(CustomSounds[Index].Stream);
-end;
-
-end.
-
+var
+ //Custom Sounds
+ CustomSounds: array of TCustomSoundEntry;
+
+//Procedured for Plugin
+function LoadTex (const Name: PChar; Typ: TTextureType): TsmallTexture; stdcall;
+//function Translate (const Name: PChar): PChar; stdcall;
+procedure Print (const Style, Size: Byte; const X, Y: Real; const Text: PChar); stdcall; //Procedure to Print Text
+function LoadSound (const Name: PChar): Cardinal; stdcall; //Procedure that loads a Custom Sound
+procedure PlaySound (const Index: Cardinal); stdcall; //Plays a Custom Sound
+
+//Utilys
+function ToSentences(Const Lines: TLines): TSentences;
+
+implementation
+uses UGraphic, UDraw, UMain, Classes, URecord, ULanguage, math, UDLLManager, USkins, UGraphicClasses;
+
+// Method for input parsing. If False is returned, GetNextWindow
+// should be checked to know the next window to load;
+function TScreenSingModi.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean;
+begin
+ Result := true;
+ If (PressedDown) Then
+ begin // Key Down
+ case PressedKey of
+
+ SDLK_ESCAPE,
+ SDLK_BACKSPACE :
+ begin
+ Finish;
+ AudioPlayback.PlaySound(SoundLib.Back);
+ FadeTo(@ScreenPartyScore);
+ end;
+
+ else
+ Result := inherited ParseInput(PressedKey, CharCode, PressedDown);
+ end;
+ end;
+end;
+
+constructor TScreenSingModi.Create;
+begin
+ inherited Create;
+
+end;
+
+function ToSentences(Const Lines: TLines): TSentences;
+var
+ I, J: Integer;
+begin
+ Result.Current := Lines.Current;
+ Result.High := Lines.High;
+ Result.Number := Lines.Number;
+ Result.Resolution := Lines.Resolution;
+ Result.NotesGAP := Lines.NotesGAP;
+ Result.TotalLength := Lines.ScoreValue;
+
+ SetLength(Result.Sentence, Length(Lines.Line));
+ for I := low(Result.Sentence) to high(Result.Sentence) do
+ begin
+ Result.Sentence[I].Start := Lines.Line[I].Start;
+ Result.Sentence[I].StartNote := Lines.Line[I].Note[0].Start;
+ Result.Sentence[I].Lyric := Lines.Line[I].Lyric;
+ Result.Sentence[I].LyricWidth := Lines.Line[I].LyricWidth;
+ Result.Sentence[I].End_ := Lines.Line[I].End_;
+ Result.Sentence[I].BaseNote := Lines.Line[I].BaseNote;
+ Result.Sentence[I].HighNote := Lines.Line[I].HighNote;
+ Result.Sentence[I].IlNut := Lines.Line[I].IlNut;
+ Result.Sentence[I].TotalNotes := Lines.Line[I].TotalNotes;
+
+ SetLength(Result.Sentence[I].Note, Length(Lines.Line[I].Note));
+ for J := low(Result.Sentence[I].Note) to high(Result.Sentence[I].Note) do
+ begin
+ Result.Sentence[I].Note[J].Color := Lines.Line[I].Note[J].Color;
+ Result.Sentence[I].Note[J].Start := Lines.Line[I].Note[J].Start;
+ Result.Sentence[I].Note[J].Length := Lines.Line[I].Note[J].Length;
+ Result.Sentence[I].Note[J].Tone := Lines.Line[I].Note[J].Tone;
+ //Result.Sentence[I].Note[J].Text := Lines.Line[I].Note[J].Tekst;
+ Result.Sentence[I].Note[J].FreeStyle := (Lines.Line[I].Note[J].NoteType = ntFreestyle);
+ Result.Sentence[I].Note[J].Typ := Ord(Lines.Line[I].Note[J].NoteType);
+ end;
+ end;
+end;
+
+procedure TScreenSingModi.onShow;
+var
+ I: Integer;
+begin
+ inherited;
+
+ PlayersPlay := TeamInfo.NumTeams;
+
+ if DLLMan.Selected.LoadSong then //Start with Song
+ begin
+ inherited;
+ end
+ else //Start Without Song
+ begin
+ AudioInput.CaptureStart;
+ end;
+
+//Set Playerinfo
+ PlayerInfo.NumPlayers := PlayersPlay;
+ for I := 0 to PlayerInfo.NumPlayers-1 do
+ begin
+ PlayerInfo.Playerinfo[I].Name := PChar(Ini.Name[I]);
+ PlayerInfo.Playerinfo[I].Score := 0;
+ PlayerInfo.Playerinfo[I].Bar := 50;
+ PlayerInfo.Playerinfo[I].Enabled := True;
+ end;
+
+ for I := PlayerInfo.NumPlayers to high(PlayerInfo.Playerinfo) do
+ begin
+ PlayerInfo.Playerinfo[I].Score:= 0;
+ PlayerInfo.Playerinfo[I].Bar := 0;
+ PlayerInfo.Playerinfo[I].Enabled := False;
+ end;
+
+ {Case PlayersPlay of
+ 1: begin
+ PlayerInfo.Playerinfo[0].PosX := Static[StaticP1ScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[0].PosY := Static[StaticP1ScoreBG].Texture.Y + Static[StaticP1ScoreBG].Texture.H;
+ end;
+ 2,4: begin
+ PlayerInfo.Playerinfo[0].PosX := Static[StaticP1TwoPScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[0].PosY := Static[StaticP1TwoPScoreBG].Texture.Y + Static[StaticP1TwoPScoreBG].Texture.H;
+ PlayerInfo.Playerinfo[2].PosX := Static[StaticP1TwoPScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[2].PosY := Static[StaticP1TwoPScoreBG].Texture.Y + Static[StaticP1TwoPScoreBG].Texture.H;
+ PlayerInfo.Playerinfo[1].PosX := Static[StaticP2RScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[1].PosY := Static[StaticP2RScoreBG].Texture.Y + Static[StaticP2RScoreBG].Texture.H;
+ PlayerInfo.Playerinfo[3].PosX := Static[StaticP2RScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[3].PosY := Static[StaticP2RScoreBG].Texture.Y + Static[StaticP2RScoreBG].Texture.H;
+ end;
+ 3,6: begin
+ PlayerInfo.Playerinfo[0].PosX := Static[StaticP1ThreePScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[0].PosY := Static[StaticP1ThreePScoreBG].Texture.Y + Static[StaticP1ThreePScoreBG].Texture.H;
+ PlayerInfo.Playerinfo[3].PosX := Static[StaticP1ThreePScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[3].PosY := Static[StaticP1ThreePScoreBG].Texture.Y + Static[StaticP1ThreePScoreBG].Texture.H;
+ PlayerInfo.Playerinfo[1].PosX := Static[StaticP2MScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[1].PosY := Static[StaticP2MScoreBG].Texture.Y + Static[StaticP2MScoreBG].Texture.H;
+ PlayerInfo.Playerinfo[4].PosX := Static[StaticP2MScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[4].PosY := Static[StaticP2MScoreBG].Texture.Y + Static[StaticP2MScoreBG].Texture.H;
+ PlayerInfo.Playerinfo[2].PosX := Static[StaticP3RScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[2].PosY := Static[StaticP3RScoreBG].Texture.Y + Static[StaticP3RScoreBG].Texture.H;
+ PlayerInfo.Playerinfo[5].PosX := Static[StaticP3RScoreBG].Texture.X;
+ PlayerInfo.Playerinfo[5].PosY := Static[StaticP3RScoreBG].Texture.Y + Static[StaticP3RScoreBG].Texture.H;
+ end;
+ end; }
+
+ // play music (I)
+ //Music.CaptureStart;
+ //Music.MoveTo(AktSong.Start);
+
+ //Init Plugin
+ if not DLLMan.PluginInit(TeamInfo, PlayerInfo, ToSentences(Lines[0]), LoadTex, Print, LoadSound, PlaySound) then
+ begin
+ //Fehler
+ Log.LogError('Could not Init Plugin');
+ Halt;
+ end;
+
+ // Set Background (Little Workaround, maybe change sometime)
+ if (DLLMan.Selected.LoadBack) AND (DLLMan.Selected.LoadSong) then
+ ScreenSing.Tex_Background := Tex_Background;
+
+ Winner := 0;
+
+ //Set Score Visibility
+ {if PlayersPlay = 1 then begin
+ Text[TextP1Score].Visible := DLLMan.Selected.ShowScore;
+ Static[StaticP1ScoreBG].Visible := DLLMan.Selected.ShowScore;
+ end;
+
+ if (PlayersPlay = 2) OR (PlayersPlay = 4) then begin
+ Text[TextP1TwoPScore].Visible := DLLMan.Selected.ShowScore;
+ Static[StaticP1TwoPScoreBG].Visible := DLLMan.Selected.ShowScore;
+
+ Text[TextP2RScore].Visible := DLLMan.Selected.ShowScore;
+ Static[StaticP2RScoreBG].Visible := DLLMan.Selected.ShowScore;
+ end;
+
+ if (PlayersPlay = 3) OR (PlayersPlay = 6) then begin
+ Text[TextP1ThreePScore].Visible := DLLMan.Selected.ShowScore;
+ Static[StaticP1ThreePScoreBG].Visible := DLLMan.Selected.ShowScore;
+
+ Text[TextP2MScore].Visible := DLLMan.Selected.ShowScore;
+ Static[StaticP2MScoreBG].Visible := DLLMan.Selected.ShowScore;
+
+ Text[TextP3RScore].Visible := DLLMan.Selected.ShowScore;
+ Static[StaticP3RScoreBG].Visible := DLLMan.Selected.ShowScore;
+ end; }
+end;
+
+function TScreenSingModi.Draw: boolean;
+var
+ Min: integer;
+ Sec: integer;
+ Tekst: string;
+ S, I: integer;
+ T: integer;
+begin
+ Result := false;
+
+ //Set Playerinfo
+ PlayerInfo.NumPlayers := PlayersPlay;
+ for I := 0 to PlayerInfo.NumPlayers-1 do
+ begin
+ PlayerInfo.Playerinfo[I].Name := PChar(Player[I].Name);
+ if PlayerInfo.Playerinfo[I].Enabled then
+ begin
+ if (Player[I].ScoreTotalI<=10000) then
+ PlayerInfo.Playerinfo[I].Score:= Player[I].ScoreTotalI;
+ PlayerInfo.Playerinfo[I].Bar := Round(Scores.Players[I].RBPos * 100);
+ end;
+ end;
+
+ //Show Score
+ if DLLMan.Selected.ShowScore then
+ begin
+ {//ScoreBG Mod
+ // set player colors
+ if PlayersPlay = 4 then begin
+ if ScreenAct = 1 then begin
+ LoadColor(Static[StaticP1TwoP].Texture.ColR, Static[StaticP1TwoP].Texture.ColG,
+ Static[StaticP1TwoP].Texture.ColB, 'P1Dark');
+ LoadColor(Static[StaticP2R].Texture.ColR, Static[StaticP2R].Texture.ColG,
+ Static[StaticP2R].Texture.ColB, 'P2Dark');
+
+
+
+ LoadColor(Static[StaticP1TwoPScoreBG].Texture.ColR, Static[StaticP1TwoPScoreBG].Texture.ColG,
+ Static[StaticP1TwoPScoreBG].Texture.ColB, 'P1Dark');
+ LoadColor(Static[StaticP2RScoreBG].Texture.ColR, Static[StaticP2RScoreBG].Texture.ColG,
+ Static[StaticP2RScoreBG].Texture.ColB, 'P2Dark');
+
+
+
+ end;
+ if ScreenAct = 2 then begin
+ LoadColor(Static[StaticP1TwoP].Texture.ColR, Static[StaticP1TwoP].Texture.ColG,
+ Static[StaticP1TwoP].Texture.ColB, 'P3Dark');
+ LoadColor(Static[StaticP2R].Texture.ColR, Static[StaticP2R].Texture.ColG,
+ Static[StaticP2R].Texture.ColB, 'P4Dark');
+
+
+
+ LoadColor(Static[StaticP1TwoPScoreBG].Texture.ColR, Static[StaticP1TwoPScoreBG].Texture.ColG,
+ Static[StaticP1TwoPScoreBG].Texture.ColB, 'P3Dark');
+ LoadColor(Static[StaticP2RScoreBG].Texture.ColR, Static[StaticP2RScoreBG].Texture.ColG,
+ Static[StaticP2RScoreBG].Texture.ColB, 'P4Dark');
+
+
+
+ end;
+ end;
+
+ if PlayersPlay = 6 then begin
+ if ScreenAct = 1 then begin
+ LoadColor(Static[StaticP1ThreeP].Texture.ColR, Static[StaticP1ThreeP].Texture.ColG,
+ Static[StaticP1ThreeP].Texture.ColB, 'P1Dark');
+ LoadColor(Static[StaticP2M].Texture.ColR, Static[StaticP2M].Texture.ColG,
+ Static[StaticP2R].Texture.ColB, 'P2Dark');
+ LoadColor(Static[StaticP3R].Texture.ColR, Static[StaticP3R].Texture.ColG,
+ Static[StaticP3R].Texture.ColB, 'P3Dark');
+
+
+
+ LoadColor(Static[StaticP1ThreePScoreBG].Texture.ColR, Static[StaticP1ThreePScoreBG].Texture.ColG,
+ Static[StaticP1ThreePScoreBG].Texture.ColB, 'P1Dark');
+ LoadColor(Static[StaticP2MScoreBG].Texture.ColR, Static[StaticP2MScoreBG].Texture.ColG,
+ Static[StaticP2RScoreBG].Texture.ColB, 'P2Dark');
+ LoadColor(Static[StaticP3RScoreBG].Texture.ColR, Static[StaticP3RScoreBG].Texture.ColG,
+ Static[StaticP3RScoreBG].Texture.ColB, 'P3Dark');
+
+
+
+ end;
+ if ScreenAct = 2 then begin
+ LoadColor(Static[StaticP1ThreeP].Texture.ColR, Static[StaticP1ThreeP].Texture.ColG,
+ Static[StaticP1ThreeP].Texture.ColB, 'P4Dark');
+ LoadColor(Static[StaticP2M].Texture.ColR, Static[StaticP2M].Texture.ColG,
+ Static[StaticP2R].Texture.ColB, 'P5Dark');
+ LoadColor(Static[StaticP3R].Texture.ColR, Static[StaticP3R].Texture.ColG,
+ Static[StaticP3R].Texture.ColB, 'P6Dark');
+
+
+
+
+ LoadColor(Static[StaticP1ThreePScoreBG].Texture.ColR, Static[StaticP1ThreePScoreBG].Texture.ColG,
+ Static[StaticP1ThreePScoreBG].Texture.ColB, 'P4Dark');
+ LoadColor(Static[StaticP2MScoreBG].Texture.ColR, Static[StaticP2MScoreBG].Texture.ColG,
+ Static[StaticP2RScoreBG].Texture.ColB, 'P5Dark');
+ LoadColor(Static[StaticP3RScoreBG].Texture.ColR, Static[StaticP3RScoreBG].Texture.ColG,
+ Static[StaticP3RScoreBG].Texture.ColB, 'P6Dark');
+
+
+
+
+ end;
+ end;
+ //end ScoreBG Mod }
+
+ // set player names (for 2 screens and only Singstar skin)
+ if ScreenAct = 1 then begin
+ Text[TextP1].Text := 'P1';
+ Text[TextP1TwoP].Text := 'P1'; // added for ps3 skin
+ Text[TextP1ThreeP].Text := 'P1'; // added for ps3 skin
+ Text[TextP2R].Text := 'P2';
+ Text[TextP2M].Text := 'P2';
+ Text[TextP3R].Text := 'P3';
+ end;
+
+ if ScreenAct = 2 then begin
+ case PlayersPlay of
+ 4: begin
+ Text[TextP1TwoP].Text := 'P3';
+ Text[TextP2R].Text := 'P4';
+ end;
+ 6: begin
+ Text[TextP1ThreeP].Text := 'P4';
+ Text[TextP2M].Text := 'P5';
+ Text[TextP3R].Text := 'P6';
+ end;
+ end; // case
+ end; // if
+
+
+ // stereo <- and where iss P2M? or P3?
+ Static[StaticP1].Texture.X := Static[StaticP1].Texture.X + 10*ScreenX;
+ Text[TextP1].X := Text[TextP1].X + 10*ScreenX;
+
+ {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X + 10*ScreenX;
+ Text[TextP1Score].X := Text[TextP1Score].X + 10*ScreenX;}
+
+ Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X + 10*ScreenX;
+ Text[TextP2R].X := Text[TextP2R].X + 10*ScreenX;
+
+ {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X + 10*ScreenX;
+ Text[TextP2RScore].X := Text[TextP2RScore].X + 10*ScreenX;}
+
+ // .. and scores
+ {if PlayersPlay = 1 then begin
+ Tekst := IntToStr(Player[0].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP1Score].Text := Tekst;
+ end;
+
+ if PlayersPlay = 2 then begin
+ Tekst := IntToStr(Player[0].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP1TwoPScore].Text := Tekst;
+
+ Tekst := IntToStr(Player[1].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP2RScore].Text := Tekst;
+ end;
+
+ if PlayersPlay = 3 then begin
+ Tekst := IntToStr(Player[0].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP1ThreePScore].Text := Tekst;
+
+ Tekst := IntToStr(Player[1].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP2MScore].Text := Tekst;
+
+ Tekst := IntToStr(Player[2].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP3RScore].Text := Tekst;
+ end;
+
+ if PlayersPlay = 4 then begin
+ if ScreenAct = 1 then begin
+ Tekst := IntToStr(Player[0].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP1TwoPScore].Text := Tekst;
+
+ Tekst := IntToStr(Player[1].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP2RScore].Text := Tekst;
+ end;
+ if ScreenAct = 2 then begin
+ Tekst := IntToStr(Player[2].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP1TwoPScore].Text := Tekst;
+
+ Tekst := IntToStr(Player[3].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP2RScore].Text := Tekst;
+ end;
+ end;
+
+ if PlayersPlay = 6 then begin
+ if ScreenAct = 1 then begin
+ Tekst := IntToStr(Player[0].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP1ThreePScore].Text := Tekst;
+
+ Tekst := IntToStr(Player[1].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP2MScore].Text := Tekst;
+
+ Tekst := IntToStr(Player[2].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP3RScore].Text := Tekst;
+ end;
+ if ScreenAct = 2 then begin
+ Tekst := IntToStr(Player[3].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP1ThreePScore].Text := Tekst;
+
+ Tekst := IntToStr(Player[4].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP2MScore].Text := Tekst;
+
+ Tekst := IntToStr(Player[5].ScoreTotalI);
+ while Length(Tekst) < 5 do Tekst := '0' + Tekst;
+ Text[TextP3RScore].Text := Tekst;
+ end;
+ end; }
+
+ end; //ShowScore
+
+ for S := 1 to 1 do
+ Static[S].Texture.X := Static[S].Texture.X + 10*ScreenX;
+
+ for T := 0 to 1 do
+ Text[T].X := Text[T].X + 10*ScreenX;
+
+ if DLLMan.Selected.LoadSong then
+ begin
+ // update static menu with time ...
+ Min := Round(LineState.CurrentTime) div 60;
+ Sec := Round(LineState.CurrentTime) mod 60;
+ Text[TextTimeText].Text := '';
+ if Min < 10 then Text[TextTimeText].Text := '0';
+ Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Min) + ':';
+ if Sec < 10 then Text[TextTimeText].Text := Text[TextTimeText].Text + '0';
+ Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Sec);
+ end;
+
+ // draw static menu (BG)
+ DrawBG;
+
+ //Draw Background
+ if (DllMan.Selected.LoadSong) AND (DllMan.Selected.LoadBack) then
+ SingDrawBackground;
+
+ // comment by blindy: wo zum henker wird denn in diesem screen ein video abgespielt?
+ // update and draw movie
+ // <mog> wie wo wadd? also in der selben funktion in der uscreensing kommt des video in der zeile 995, oder was wollteste wissen? :X
+{ if ShowFinish and CurrentSong.VideoLoaded AND DllMan.Selected.LoadVideo then begin
+ UpdateSmpeg; // this only draws
+ end;}
+
+ // draw static menu (FG)
+ DrawFG;
+
+ if ShowFinish then begin
+ if DllMan.Selected.LoadSong then
+ begin
+ if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or (LineState.CurrentTime*1000 <= CurrentSong.Finish)) then begin
+ //Pause Mod:
+ if not Paused then
+ Sing(Self); // analyze song
+ end else begin
+ if not FadeOut then begin
+ Finish;
+ FadeOut := true;
+ FadeTo(@ScreenPartyScore);
+ end;
+ end;
+ end;
+ end;
+
+ // draw custom items
+ SingModiDraw(PlayerInfo); // always draw
+
+ //GoldenNoteStarsTwinkle Mod
+ GoldenRec.SpawnRec;
+ //GoldenNoteStarsTwinkle Mod
+
+ //Update PlayerInfo
+ for I := 0 to PlayerInfo.NumPlayers-1 do
+ begin
+ if PlayerInfo.Playerinfo[I].Enabled then
+ begin
+ //PlayerInfo.Playerinfo[I].Bar := Player[I].ScorePercent;
+ PlayerInfo.Playerinfo[I].Score := Player[I].ScoreTotalI;
+ end;
+ end;
+
+ if ((ShowFinish) AND (NOT Paused)) then
+ begin
+ if not DLLMan.PluginDraw(Playerinfo, Lines[0].Current) then
+ begin
+ if not FadeOut then begin
+ Finish;
+ FadeOut := true;
+ FadeTo(@ScreenPartyScore);
+ end;
+ end;
+ end;
+
+ //Change PlayerInfo/Changeables
+ for I := 0 to PlayerInfo.NumPlayers-1 do
+ begin
+ if (Player[I].ScoreTotalI <> PlayerInfo.Playerinfo[I].Score) then
+ begin
+ //Player[I].ScoreTotal := Player[I].ScoreTotal + (PlayerInfo.Playerinfo[I].Score - Player[I].ScoreTotalI);
+ Player[I].ScoreTotalI := PlayerInfo.Playerinfo[I].Score;
+ end;
+ {if (PlayerInfo.Playerinfo[I].Bar <> Player[I].ScorePercent) then
+ Player[I].ScorePercentTarget := PlayerInfo.Playerinfo[I].Bar; }
+ end;
+
+ // back stereo
+ Static[StaticP1].Texture.X := Static[StaticP1].Texture.X - 10*ScreenX;
+ Text[TextP1].X := Text[TextP1].X - 10*ScreenX;
+
+ {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X - 10*ScreenX;
+ Text[TextP1Score].X := Text[TextP1Score].X - 10*ScreenX;}
+
+
+ Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X - 10*ScreenX;
+ Text[TextP2R].X := Text[TextP2R].X - 10*ScreenX;
+
+ {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X - 10*ScreenX;
+ Text[TextP2RScore].X := Text[TextP2RScore].X - 10*ScreenX;}
+
+
+ for S := 1 to 1 do
+ Static[S].Texture.X := Static[S].Texture.X - 10*ScreenX;
+
+ for T := 0 to 1 do
+ Text[T].X := Text[T].X - 10*ScreenX;
+
+ Result := true;
+end;
+
+procedure TScreenSingModi.Finish;
+begin
+inherited Finish;
+
+Winner := DllMan.PluginFinish(PlayerInfo);
+
+//Log.LogError('Winner: ' + InttoStr(Winner));
+
+//DLLMan.UnLoadPlugin;
+end;
+
+function LoadTex (const Name: PChar; Typ: TTextureType): TsmallTexture; stdcall;
+var
+ Texname, EXT: String;
+ Tex: TTexture;
+begin
+ //Get texture Name
+ TexName := Skin.GetTextureFileName(String(Name));
+ //Get File Typ
+ Ext := ExtractFileExt(TexName);
+ if (uppercase(Ext) = '.JPG') then
+ Ext := 'JPG'
+ else
+ Ext := 'BMP';
+
+ Tex := Texture.LoadTexture(TexName, UTexture.TTextureType(Typ), 0);
+
+ Result.TexNum := Tex.TexNum;
+ Result.W := Tex.W;
+ Result.H := Tex.H;
+end;
+{
+function Translate (const Name: PChar): PChar; stdcall;
+begin
+ Result := PChar(Language.Translate(String(Name)));
+end; }
+
+procedure Print (const Style, Size: Byte; const X, Y: Real; const Text: PChar); stdcall; //Procedure to Print Text
+begin
+ SetFontItalic ((Style and 128) = 128);
+ SetFontStyle(Style and 7);
+ SetFontSize(Size);
+ SetFontPos (X, Y);
+ glPrint (PChar(Language.Translate(String(Text))));
+end;
+
+function LoadSound (const Name: PChar): Cardinal; stdcall; //Procedure that loads a Custom Sound
+var
+ S: TAudioPlaybackStream;
+ I: Integer;
+ F: String;
+begin
+ //Search for Sound in already loaded Sounds
+ F := UpperCase(SoundPath + FileName);
+ For I := 0 to High(CustomSounds) do
+ begin
+ if (UpperCase(CustomSounds[I].Filename) = F) then
+ begin
+ Result := I;
+ Exit;
+ end;
+ end;
+
+ S := AudioPlayback.OpenSound(SoundPath + String(Name));
+ if (S <> nil) then
+ Result := High(CustomSounds)
+ else
+ Result := 0;
+end;
+
+procedure PlaySound (const Index: Cardinal); stdcall; //Plays a Custom Sound
+begin
+ if (Index <= High(CustomSounds)) then
+ AudioPlayback.PlaySound(CustomSounds[Index].Stream);
+end;
+
+end.
+
diff --git a/Game/Code/UltraStar.dpr b/Game/Code/UltraStar.dpr
index 415ff8ff..42502802 100644
--- a/Game/Code/UltraStar.dpr
+++ b/Game/Code/UltraStar.dpr
@@ -98,6 +98,8 @@ uses
UTime in 'Classes\UTime.pas',
TextGL in 'Classes\TextGL.pas',
USong in 'Classes\USong.pas',
+ USong_TextFile in 'Classes\USong_TextFile.pas',
+ USong_Txt in 'Classes\USong_Txt.pas',
UXMLSong in 'Classes\UXMLSong.pas',
USongs in 'Classes\USongs.pas',
UIni in 'Classes\UIni.pas',