aboutsummaryrefslogtreecommitdiffstats
path: root/Game/Code/Classes
diff options
context:
space:
mode:
authorbrunzelchen <brunzelchen@b956fd51-792f-4845-bead-9b4dfca2ff2c>2010-10-05 18:28:42 +0000
committerbrunzelchen <brunzelchen@b956fd51-792f-4845-bead-9b4dfca2ff2c>2010-10-05 18:28:42 +0000
commit65ddad359ed3b9b739215ec89a7645455ae10dce (patch)
tree7fdc703f290b37e68ce0e6a2c56d5bdd2f7ee07b /Game/Code/Classes
parentdbe444f87b85da27a37f38e80bfd540178b8dde0 (diff)
downloadusdx-65ddad359ed3b9b739215ec89a7645455ae10dce.tar.gz
usdx-65ddad359ed3b9b739215ec89a7645455ae10dce.tar.xz
usdx-65ddad359ed3b9b739215ec89a7645455ae10dce.zip
- added webcam support
- faster program start - faster sorting (mergesort) - sync lyrics to music - some new backgrounds and credits graphics (thx to MezzoX) - own thread for video decoding - finished 6-Player-on-one-screen-mode - changqed player-colors - fixed some bugs... git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/1.0.1 Challenge MOD@2637 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to 'Game/Code/Classes')
-rw-r--r--Game/Code/Classes/UCatCovers.pas57
-rw-r--r--Game/Code/Classes/UCovers.pas141
-rw-r--r--Game/Code/Classes/UDataBase.pas126
-rw-r--r--Game/Code/Classes/UDraw.pas109
-rw-r--r--Game/Code/Classes/UFiles.pas83
-rw-r--r--Game/Code/Classes/UGraphic.pas28
-rw-r--r--Game/Code/Classes/UGraphicClasses.pas55
-rw-r--r--Game/Code/Classes/UHelp.pas34
-rw-r--r--Game/Code/Classes/UIni.pas59
-rw-r--r--Game/Code/Classes/ULog.pas228
-rw-r--r--Game/Code/Classes/UMain.pas29
-rw-r--r--Game/Code/Classes/UMergeSort.pas101
-rw-r--r--Game/Code/Classes/UMusic.pas75
-rw-r--r--Game/Code/Classes/UParty.pas2
-rw-r--r--Game/Code/Classes/UPartyM2.pas1
-rw-r--r--Game/Code/Classes/URecord.pas4
-rw-r--r--Game/Code/Classes/USongs.pas286
-rw-r--r--Game/Code/Classes/UTexture.pas20
-rw-r--r--Game/Code/Classes/UThemes.pas117
-rw-r--r--Game/Code/Classes/UVideo.pas495
-rw-r--r--Game/Code/Classes/UWebCam.pas253
21 files changed, 1564 insertions, 739 deletions
diff --git a/Game/Code/Classes/UCatCovers.pas b/Game/Code/Classes/UCatCovers.pas
index 34742902..e52b53d7 100644
--- a/Game/Code/Classes/UCatCovers.pas
+++ b/Game/Code/Classes/UCatCovers.pas
@@ -89,55 +89,54 @@ end;
//Add a Cover
procedure TCatCovers.Add(Sorting: integer; Name, Filename: string);
begin
-if FileExists (Filename) then //If Exists -> Add
-begin
-SetLength (CNames[Sorting], Length(CNames[Sorting]) + 1);
-SetLength (CFiles[Sorting], Length(CNames[Sorting]) + 1);
+ if FileExists (Filename) then //If Exists -> Add
+ begin
+ SetLength (CNames[Sorting], Length(CNames[Sorting]) + 1);
+ SetLength (CFiles[Sorting], Length(CNames[Sorting]) + 1);
-CNames[Sorting][high(cNames[Sorting])] := Uppercase(Name);
-CFiles[Sorting][high(cNames[Sorting])] := FileName;
-end;
+ CNames[Sorting][high(cNames[Sorting])] := Uppercase(Name);
+ CFiles[Sorting][high(cNames[Sorting])] := FileName;
+ end;
end;
//Returns True when a cover with the given Name exists
function TCatCovers.CoverExists(Sorting: integer; Name: string): boolean;
var
-I: Integer;
+ I: Integer;
begin
-Result := False;
-Name := Uppercase(Name); //Case Insensitiv
+ Result := False;
+ Name := Uppercase(Name); //Case Insensitiv
-for I := low(cNames[Sorting]) to high(cNames[Sorting]) do
-begin
- if (cNames[Sorting][I] = Name) then //Found Name
+ for I := low(cNames[Sorting]) to high(cNames[Sorting]) do
begin
- Result := true;
- break; //Break For Loop
+ if (cNames[Sorting][I] = Name) then //Found Name
+ begin
+ Result := true;
+ break; //Break For Loop
+ end;
end;
end;
-end;
//Returns the Filename of a Cover
function TCatCovers.GetCover(Sorting: integer; Name: string): string;
var
-I: Integer;
+ I: Integer;
begin
-Result := '';
-Name := Uppercase(Name);
+ Result := '';
+ Name := Uppercase(Name);
-for I := low(cNames[Sorting]) to high(cNames[Sorting]) do
-begin
- if cNames[Sorting][I] = Name then
+ for I := low(cNames[Sorting]) to high(cNames[Sorting]) do
begin
- Result := cFiles[Sorting][I];
- Break;
+ if cNames[Sorting][I] = Name then
+ begin
+ Result := cFiles[Sorting][I];
+ Break;
+ end;
end;
-end;
-
-//No Cover
-if (Result = '') AND (FileExists(CoversPath + 'NoCover.jpg')) then
- Result := CoversPath + 'NoCover.jpg';
+ //No Cover
+ if (Result = '') AND (FileExists(CoversPath + 'NoCover.jpg')) then
+ Result := CoversPath + 'NoCover.jpg';
end;
end.
diff --git a/Game/Code/Classes/UCovers.pas b/Game/Code/Classes/UCovers.pas
index c74bbaf4..2cb63a8d 100644
--- a/Game/Code/Classes/UCovers.pas
+++ b/Game/Code/Classes/UCovers.pas
@@ -14,6 +14,9 @@ type
end;
TCovers = class
+ private
+ SearchPos: integer;
+ public
Cover: array of TCover;
W: word;
H: word;
@@ -24,10 +27,10 @@ type
constructor Create;
procedure Load;
procedure Save;
- procedure AddCover(Name: string);
- function CoverExists(Name: string): boolean;
- function CoverNumber(Name: string): integer;
- procedure PrepareData(Name: string);
+ procedure AddCover(const Name: string);
+ function CoverExists(const Name: string): boolean;
+ function CoverNumber(const Name: string): integer;
+ procedure PrepareData(const Name: string);
end;
var
@@ -43,6 +46,7 @@ begin
Size := W*H*3;
Load;
WritetoFile := True;
+ SearchPos := 0;
end;
procedure TCovers.Load;
@@ -53,47 +57,39 @@ var
Bits: byte;
NLen: word;
Name: string;
-// Data: array of byte;
-begin
- if FileExists(GamePath + 'covers.cache') then begin
- AssignFile(F, GamePath + 'covers.cache');
- Reset(F, 1);
-
- WritetoFile := not FileIsReadOnly(GamePath + 'covers.cache');
-
- SetLength(Cover, 0);
- while not EOF(F) do begin
- SetLength(Cover, Length(Cover)+1);
+begin
+ if FileExists(GamePath + 'covers.cache') then
+ begin
+ AssignFile(F, GamePath + 'covers.cache');
+ Reset(F, 1);
- BlockRead(F, W, 2);
- Cover[High(Cover)].W := W;
+ WritetoFile := not FileIsReadOnly(GamePath + 'covers.cache');
- BlockRead(F, H, 2);
- Cover[High(Cover)].H := H;
+ SetLength(Cover, 0);
- BlockRead(F, Bits, 1);
+ while not EOF(F) do
+ begin
+ SetLength(Cover, Length(Cover)+1);
- Cover[High(Cover)].Size := W * H * (Bits div 8);
+ BlockRead(F, W, 2);
+ Cover[High(Cover)].W := W;
- // test
-// W := 128;
-// H := 128;
-// Bits := 24;
-// Seek(F, FilePos(F) + 3);
+ BlockRead(F, H, 2);
+ Cover[High(Cover)].H := H;
- BlockRead(F, NLen, 2);
- SetLength(Name, NLen);
+ BlockRead(F, Bits, 1);
- BlockRead(F, Name[1], NLen);
- Cover[High(Cover)].Name := Name;
+ Cover[High(Cover)].Size := W * H * (Bits div 8);
- Cover[High(Cover)].Position := FilePos(F);
- Seek(F, FilePos(F) + W*H*(Bits div 8));
+ BlockRead(F, NLen, 2);
+ SetLength(Name, NLen);
-// SetLength(Cover[High(Cover)].Data, W*H*(Bits div 8));
-// BlockRead(F, Cover[High(Cover)].Data[0], W*H*(Bits div 8));
+ BlockRead(F, Name[1], NLen);
+ Cover[High(Cover)].Name := Name;
+ Cover[High(Cover)].Position := FilePos(F);
+ Seek(F, FilePos(F) + W*H*(Bits div 8));
end;
CloseFile(F);
@@ -131,7 +127,7 @@ begin
CloseFile(F);}
end;
-procedure TCovers.AddCover(Name: string);
+procedure TCovers.AddCover(const Name: string);
var
//B: integer;
F: File;
@@ -139,7 +135,8 @@ var
NLen: word;
Bits: byte;
begin
- if not CoverExists(Name) then begin
+ if not CoverExists(Name) then
+ begin
SetLength(Cover, Length(Cover)+1);
Cover[High(Cover)].Name := Name;
@@ -147,70 +144,88 @@ begin
Cover[High(Cover)].H := H;
Cover[High(Cover)].Size := Size;
- // do not copy data. write them directly to file
-// SetLength(Cover[High(Cover)].Data, Size);
-// for B := 0 to Size-1 do
-// Cover[High(Cover)].Data[B] := CacheMipmap[B];
-
if WritetoFile then
begin
AssignFile(F, GamePath + 'covers.cache');
- if FileExists(GamePath + 'covers.cache') then begin
+
+ if FileExists(GamePath + 'covers.cache') then
+ begin
Reset(F, 1);
Seek(F, FileSize(F));
end else
Rewrite(F, 1);
- Bits := 24;
+ Bits := 24;
- BlockWrite(F, W, 2);
- BlockWrite(F, H, 2);
- BlockWrite(F, Bits, 1);
+ BlockWrite(F, W, 2);
+ BlockWrite(F, H, 2);
+ BlockWrite(F, Bits, 1);
- NLen := Length(Name);
- BlockWrite(F, NLen, 2);
- BlockWrite(F, Name[1], NLen);
+ NLen := Length(Name);
+ BlockWrite(F, NLen, 2);
+ BlockWrite(F, Name[1], NLen);
- Cover[High(Cover)].Position := FilePos(F);
- BlockWrite(F, CacheMipmap[0], W*H*(Bits div 8));
+ Cover[High(Cover)].Position := FilePos(F);
+ BlockWrite(F, CacheMipmap[0], W*H*(Bits div 8));
- CloseFile(F);
- end;
- end
- else
+ CloseFile(F);
+ end;
+ end else
Cover[High(Cover)].Position := 0;
end;
-function TCovers.CoverExists(Name: string): boolean;
+function TCovers.CoverExists(const Name: string): boolean;
var
C: integer; // cover
begin
Result := false;
+ C := SearchPos;
+ while (C <= High(Cover)) and not Result do
+ begin
+ if Cover[C].Name = Name then
+ begin
+ Result := true;
+ SearchPos := C;
+ end;
+ Inc(C);
+ end;
+
+ if Result then
+ Exit;
+
C := 0;
- while (C <= High(Cover)) and (Result = false) do begin
- if Cover[C].Name = Name then Result := true;
+ while (C <= High(Cover)) and not Result do
+ begin
+ if Cover[C].Name = Name then
+ begin
+ Result := true;
+ SearchPos := C;
+ end;
Inc(C);
end;
end;
-function TCovers.CoverNumber(Name: string): integer;
+function TCovers.CoverNumber(const Name: string): integer;
var
C: integer;
begin
Result := -1;
C := 0;
- while (C <= High(Cover)) and (Result = -1) do begin
- if Cover[C].Name = Name then Result := C;
+ while (C <= High(Cover)) and (Result = -1) do
+ begin
+ if Cover[C].Name = Name then
+ Result := C;
Inc(C);
end;
end;
-procedure TCovers.PrepareData(Name: string);
+procedure TCovers.PrepareData(const Name: string);
var
F: File;
C: integer;
begin
- if FileExists(GamePath + 'covers.cache') then begin
+ if FileExists(GamePath + 'covers.cache') then
+ begin
AssignFile(F, GamePath + 'covers.cache');
Reset(F, 1);
diff --git a/Game/Code/Classes/UDataBase.pas b/Game/Code/Classes/UDataBase.pas
index 1233dae0..586e742d 100644
--- a/Game/Code/Classes/UDataBase.pas
+++ b/Game/Code/Classes/UDataBase.pas
@@ -70,8 +70,10 @@ function TDataBaseSystem.GetHandicap(P1: string; P2: string): THandicapResult;
const
min = 3;
var
- P1m, P2m, temp: real;
+ P1m, P2m: real;
P1c, P2c: integer;
+
+ tP1, tP2: string;
begin
if not Assigned(ScoreDB) then
Exit;
@@ -83,22 +85,25 @@ begin
P2m := 0;
try
+ tP1 := StringReplace(P1,'"','""',[rfReplaceAll, rfIgnoreCase]);
+ tP2 := StringReplace(P2,'"','""',[rfReplaceAll, rfIgnoreCase]);
+
P1c := ScoreDB.GetTableValue('SELECT COUNT(`SongID`) FROM `US_Scores` '+
- 'WHERE `Player` = "' + P1 + '";');
+ 'WHERE `Player` = "' + tP1 + '";');
P2c := ScoreDB.GetTableValue('SELECT COUNT(`SongID`) FROM `US_Scores` '+
- 'WHERE `Player` = "' + P2 + '";');
+ 'WHERE `Player` = "' + tP2 + '";');
if (P1c>min) and (P2c>min) then
begin
P1m := ScoreDB.GetTableFloat('SELECT AVG(`Score`) FROM `US_Scores` '+
'WHERE `Score` IN ('+
'SELECT Score FROM `US_Scores` '+
- 'WHERE `Player` = "' + P1 + '" ORDER BY `rowid` DESC LIMIT 10);');
+ 'WHERE `Player` = "' + tP1 + '" ORDER BY `rowid` DESC LIMIT 10);');
P2m := ScoreDB.GetTableFloat('SELECT AVG(`Score`) FROM `US_Scores` '+
'WHERE `Score` IN ('+
'SELECT Score FROM `US_Scores` '+
- 'WHERE `Player` = "' + P2 + '" ORDER BY `rowid` DESC LIMIT 10);');
+ 'WHERE `Player` = "' + tP2 + '" ORDER BY `rowid` DESC LIMIT 10);');
end;
except
P1m := 0;
@@ -107,37 +112,30 @@ begin
if (P1m>0) and (P2m>0) then
begin
- if (P1m>P2m) then
- begin
- temp := (P2m/P1m) + (P2m/P1m)*0.2;
- if temp<=1 then
- Result.P1m := temp
- else
- Result.P1m := 1;
- end else
- begin
- temp := (P1m/P2m) + (P1m/P2m)*0.2;
- if temp<=1 then
- Result.P2m := temp
- else
- Result.P2m := 1;
- end;
+ if (P1m>=P2m) then
+ Result.P1m := 1-((P1m-P2m)/10000)/1.75
+ else
+ Result.P2m := 1-((P2m-P1m)/10000)/1.75
end;
end;
function TDataBaseSystem.GetAspect(Artist, Title: string; def: integer): integer;
var
- ID: Integer;
+ ID: Integer;
+ tArtist, tTitle: string;
begin
try
+ tArtist := StringReplace(Artist,'"','""',[rfReplaceAll, rfIgnoreCase]);
+ tTitle := StringReplace(Title,'"','""',[rfReplaceAll, rfIgnoreCase]);
+
ID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' +
- Artist + '" AND `Title` = "' + Title + '"');
+ tArtist + '" AND `Title` = "' + tTitle + '"');
if ID = 0 then //Song doesn't exist -> Create
begin
ScoreDB.ExecSQL ('INSERT INTO `US_Songs` ( `ID` , `Artist` , `Title` , `TimesPlayed`, `Aspect` ) '+
- 'VALUES (NULL , "' + Artist + '", "' + Title + '", "0", "'+ IntToStr(def) +'");');
+ 'VALUES (NULL , "' + tArtist + '", "' + tTitle + '", "0", "'+ IntToStr(def) +'");');
Result := def;
end else
begin
@@ -151,17 +149,21 @@ end;
procedure TDataBaseSystem.SetAspect(Artist, Title: string; aspect: integer);
var
- ID: Integer;
+ ID: Integer;
+ tArtist, tTitle: string;
begin
try
+ tArtist := StringReplace(Artist,'"','""',[rfReplaceAll, rfIgnoreCase]);
+ tTitle := StringReplace(Title,'"','""',[rfReplaceAll, rfIgnoreCase]);
+
ID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' +
- Artist + '" AND `Title` = "' + Title + '"');
+ tArtist + '" AND `Title` = "' + tTitle + '"');
if ID = 0 then //Song doesn't exist -> Create
begin
ScoreDB.ExecSQL ('INSERT INTO `US_Songs` ( `ID` , `Artist` , `Title` , `TimesPlayed`, `Aspect` ) '+
- 'VALUES (NULL , "' + Artist + '", "' + Title + '", "0", "'+ IntToStr(Aspect) +'");');
+ 'VALUES (NULL , "' + tArtist + '", "' + tTitle + '", "0", "'+ IntToStr(Aspect) +'");');
end else
begin
@@ -260,31 +262,36 @@ var
PlayerListed: boolean;
DateStr: string;
num: array[0..2] of integer; //num entries easy, medium, hard
+ tArtist,
+ tTitle: string;
begin
if not Assigned(ScoreDB) then
Exit;
try
+ tArtist := StringReplace(Song.Artist,'"','""',[rfReplaceAll, rfIgnoreCase]);
+ tTitle := StringReplace(Song.Title,'"','""',[rfReplaceAll, rfIgnoreCase]);
+
//count num entries
if(sum=1) then
begin
num[0] := ScoreDB.GetTableValue('SELECT COUNT(`SongID`) FROM `US_Scores` '+
'WHERE `Difficulty` = 0 and '+
'`SongID` = (SELECT `ID` FROM `us_songs` WHERE `Artist` = "' +
- Song.Artist + '" AND `Title` = "' + Song.Title +
+ tArtist + '" AND `Title` = "' + tTitle +
'" LIMIT 1);');
num[1] := ScoreDB.GetTableValue('SELECT COUNT(`SongID`) FROM `US_Scores` '+
'WHERE `Difficulty` = 1 and '+
'`SongID` = (SELECT `ID` FROM `us_songs` WHERE `Artist` = "' +
- Song.Artist + '" AND `Title` = "' + Song.Title +
+ tArtist + '" AND `Title` = "' + tTitle +
'" LIMIT 1);');
num[2] := ScoreDB.GetTableValue('SELECT COUNT(`SongID`) FROM `US_Scores` '+
'WHERE `Difficulty` = 2 and '+
'`SongID` = (SELECT `ID` FROM `us_songs` WHERE `Artist` = "' +
- Song.Artist + '" AND `Title` = "' + Song.Title +
+ tArtist + '" AND `Title` = "' + tTitle +
'" LIMIT 1);');
end;
@@ -292,7 +299,7 @@ begin
TableData := ScoreDB.GetTable('SELECT `Difficulty`, `Player`, `Score`, `Date` '+
'FROM `us_scores` WHERE '+
'`SongID` = (SELECT `ID` FROM `us_songs` WHERE `Artist` = "' +
- Song.Artist + '" AND `Title` = "' + Song.Title +
+ tArtist + '" AND `Title` = "' + tTitle +
'" LIMIT 1) ORDER BY `Score` DESC;');
//Empty Old Scores
SetLength (Song.Score[0], 0); //easy
@@ -359,55 +366,54 @@ end;
//--------------------
procedure TDataBaseSystem.AddScore(var Song: TSong; Level: integer; Name: string; Score: integer; TimeStamp: integer);
var
-ID: Integer;
-//TableData: TSqliteTable;
+ ID: Integer;
+ tArtist, tTitle, tName: string;
+
begin
- //ScoreDB := TSqliteDatabase.Create(sFilename);
- try
//Prevent 0 Scores from being added
if (Score > 0) then
begin
- try //todo : wrapper shouldn't throw exceptions at all - this fixed a wine bug, thanks linnex! (11.11.07)
- ID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' + Song.Artist + '" AND `Title` = "' + Song.Title + '"');
- if ID = 0 then //Song doesn't exist -> Create
- begin
- ScoreDB.ExecSQL ('INSERT INTO `US_Songs` ( `ID` , `Artist` , `Title` , `TimesPlayed` ) '+
- 'VALUES (NULL , "' + Song.Artist + '", "' + Song.Title + '", "0");');
- ID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' + Song.Artist + '" AND `Title` = "' + Song.Title + '"');
+ tArtist := StringReplace(Song.Artist,'"','""',[rfReplaceAll, rfIgnoreCase]);
+ tTitle := StringReplace(Song.Title,'"','""',[rfReplaceAll, rfIgnoreCase]);
+ tName := StringReplace(Name,'"','""',[rfReplaceAll, rfIgnoreCase]);
- if ID = 0 then //Could not Create Table
- exit;
- end;
+ try //todo : wrapper shouldn't throw exceptions at all - this fixed a wine bug, thanks linnex! (11.11.07)
+ ID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' + tArtist +
+ '" AND `Title` = "' + tTitle + '"');
+ if ID = 0 then //Song doesn't exist -> Create
+ begin
+ ScoreDB.ExecSQL ('INSERT INTO `US_Songs` ( `ID` , `Artist` , `Title` , `TimesPlayed` ) '+
+ 'VALUES (NULL , "' + tArtist + '", "' + tTitle + '", "0");');
+ ID := ScoreDB.GetTableValue('SELECT `ID` FROM `US_Songs` WHERE `Artist` = "' + tArtist +
+ '" AND `Title` = "' + tTitle + '"');
- //Create new Entry
- ScoreDB.ExecSQL('INSERT INTO `US_Scores` ( `SongID` , `Difficulty` , `Player` , `Score` , `Date` ) '+
- 'VALUES ("' + InttoStr(ID) + '", "' + InttoStr(Level) + '", "' +
- Name + '", "' + InttoStr(Score) + '","' + InttoStr(TimeStamp) + '");');
+ if ID = 0 then //Could not Create Table
+ exit;
+ end;
- {
- //Delete Last Position when there are more than 5 Entrys
- if ScoreDB.GetTableValue('SELECT COUNT(`SongID`) FROM `US_Scores` WHERE `SongID` = "' + InttoStr(ID) + '" AND `Difficulty` = "' + InttoStr(Level) +'"') > 5 then
- begin
- TableData := ScoreDB.GetTable('SELECT `Player`, `Score` FROM `US_Scores` WHERE SongID = "' + InttoStr(ID) + '" AND `Difficulty` = "' + InttoStr(Level) +'" ORDER BY `Score` ASC LIMIT 1');
- ScoreDB.ExecSQL('DELETE FROM `US_Scores` WHERE SongID = "' + InttoStr(ID) + '" AND `Difficulty` = "' + InttoStr(Level) +'" AND `Player` = "' + TableData.FieldAsString(TableData.FieldIndex['Player']) + '" AND `Score` = "' + TableData.FieldAsString(TableData.FieldIndex['Score']) + '"');
- end; }
+ //Create new Entry
+ ScoreDB.ExecSQL('INSERT INTO `US_Scores` ( `SongID` , `Difficulty` , `Player` , `Score` , `Date` ) '+
+ 'VALUES ("' + InttoStr(ID) + '", "' + InttoStr(Level) + '", "' +
+ tName + '", "' + InttoStr(Score) + '","' + InttoStr(TimeStamp) + '");');
except
- // katze!
+
end;
end;
- finally
- //ScoreDB.Free;
- end;
end;
//--------------------
//WriteScore - Not needed with new System; But used for Increment Played Count
//--------------------
procedure TDataBaseSystem.WriteScore(var Song: TSong);
+var
+ tArtist, tTitle: string;
begin
try
+ tArtist := StringReplace(Song.Artist,'"','""',[rfReplaceAll, rfIgnoreCase]);
+ tTitle := StringReplace(Song.Title,'"','""',[rfReplaceAll, rfIgnoreCase]);
//Increase TimesPlayed
- ScoreDB.ExecSQL ('UPDATE `us_songs` SET `TimesPlayed` = `TimesPlayed` + "1" WHERE `Title` = "' + Song.Title + '" AND `Artist` = "' + Song.Artist + '";');
+ ScoreDB.ExecSQL ('UPDATE `us_songs` SET `TimesPlayed` = `TimesPlayed` + "1" WHERE `Title` = "' +
+ tTitle + '" AND `Artist` = "' + tArtist + '";');
except
end;
diff --git a/Game/Code/Classes/UDraw.pas b/Game/Code/Classes/UDraw.pas
index 38e94482..c304cc0a 100644
--- a/Game/Code/Classes/UDraw.pas
+++ b/Game/Code/Classes/UDraw.pas
@@ -41,7 +41,7 @@ procedure SingDrawStar(X, Y, A: real);
procedure SingGoldenStar(X, Y, A: real);
}
// The Singbar
-procedure SingDrawSingbar(X, Y, W, H: real; Percent, ScoreMax, ScoreCurrent: integer);
+procedure SingDrawSingbar(X, Y, W, H: real; P: integer);
//Phrasen Bonus - Line Bonus
procedure SingDrawLineBonus( const X, Y: Single; Color: TRGB; Alpha: Single; Text: string; Age: Integer);
@@ -98,7 +98,8 @@ var
Rec: TRecR;
TexRec: TRecR;
begin
- if ScreenSing.Tex_Background.TexNum >= 1 then begin
+ if ScreenSing.Tex_Background.TexNum >= 1 then
+ begin
glClearColor (1, 1, 1, 1);
glColor4f (1, 1, 1, 1);
@@ -790,56 +791,56 @@ begin
end; //if
if PlayersPlay = 1 then
begin
- SingDrawSingbar(Theme.Sing.StaticP1SingBar.x, Theme.Sing.StaticP1SingBar.y, Theme.Sing.StaticP1SingBar.w, Theme.Sing.StaticP1SingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1SingBar.x, Theme.Sing.StaticP1SingBar.y, Theme.Sing.StaticP1SingBar.w, Theme.Sing.StaticP1SingBar.h , 0);
end;
if PlayersPlay = 2 then
begin
- SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , Player[1].ScorePercent, Player[1].ScoreMax, Player[1].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , 0);
+ SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , 1);
end;
if PlayersPlay = 3 then
begin
- SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , Player[1].ScorePercent, Player[1].ScoreMax, Player[1].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , Player[2].ScorePercent, Player[2].ScoreMax, Player[2].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , 0);
+ SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , 1);
+ SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , 2);
end;
if PlayersPlay = 4 then
begin
if ScreenAct = 1 then
begin
- SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , Player[1].ScorePercent, Player[1].ScoreMax, Player[1].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , 0);
+ SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , 1);
if P4Mode then
begin
- SingDrawSingbar(Theme.Sing.StaticP3FourPSingBar.x, Theme.Sing.StaticP3FourPSingBar.y, Theme.Sing.StaticP3FourPSingBar.w, Theme.Sing.StaticP3FourPSingBar.h , Player[2].ScorePercent, Player[2].ScoreMax, Player[2].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP4FourPSingBar.x, Theme.Sing.StaticP4FourPSingBar.y, Theme.Sing.StaticP4FourPSingBar.w, Theme.Sing.StaticP4FourPSingBar.h , Player[3].ScorePercent, Player[3].ScoreMax, Player[3].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP3FourPSingBar.x, Theme.Sing.StaticP3FourPSingBar.y, Theme.Sing.StaticP3FourPSingBar.w, Theme.Sing.StaticP3FourPSingBar.h , 2);
+ SingDrawSingbar(Theme.Sing.StaticP4FourPSingBar.x, Theme.Sing.StaticP4FourPSingBar.y, Theme.Sing.StaticP4FourPSingBar.w, Theme.Sing.StaticP4FourPSingBar.h , 3);
end;
end;
if ScreenAct = 2 then
begin
- SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , Player[2].ScorePercent, Player[2].ScoreMax, Player[2].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , Player[3].ScorePercent, Player[3].ScoreMax, Player[3].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , 2);
+ SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , 3);
end;
end;
if PlayersPlay = 6 then
begin
if ScreenAct = 1 then
begin
- SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , Player[1].ScorePercent, Player[1].ScoreMax, Player[1].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , Player[2].ScorePercent, Player[2].ScoreMax, Player[2].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , 0);
+ SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , 1);
+ SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , 2);
if P4Mode then
begin
- SingDrawSingbar(Theme.Sing.StaticP4SixPSingBar.x, Theme.Sing.StaticP4SixPSingBar.y, Theme.Sing.StaticP4SixPSingBar.w, Theme.Sing.StaticP4SixPSingBar.h , Player[3].ScorePercent, Player[3].ScoreMax, Player[3].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP5SingBar.x, Theme.Sing.StaticP5SingBar.y, Theme.Sing.StaticP5SingBar.w, Theme.Sing.StaticP5SingBar.h , Player[4].ScorePercent, Player[4].ScoreMax, Player[4].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP6SingBar.x, Theme.Sing.StaticP6SingBar.y, Theme.Sing.StaticP6SingBar.w, Theme.Sing.StaticP6SingBar.h , Player[5].ScorePercent, Player[5].ScoreMax, Player[5].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP4SixPSingBar.x, Theme.Sing.StaticP4SixPSingBar.y, Theme.Sing.StaticP4SixPSingBar.w, Theme.Sing.StaticP4SixPSingBar.h , 3);
+ SingDrawSingbar(Theme.Sing.StaticP5SingBar.x, Theme.Sing.StaticP5SingBar.y, Theme.Sing.StaticP5SingBar.w, Theme.Sing.StaticP5SingBar.h , 4);
+ SingDrawSingbar(Theme.Sing.StaticP6SingBar.x, Theme.Sing.StaticP6SingBar.y, Theme.Sing.StaticP6SingBar.w, Theme.Sing.StaticP6SingBar.h , 5);
end;
end;
if ScreenAct = 2 then
begin
- SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , Player[3].ScorePercent, Player[3].ScoreMax, Player[3].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , Player[4].ScorePercent, Player[4].ScoreMax, Player[4].ScoreTotalI);
- SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , Player[5].ScorePercent, Player[5].ScoreMax, Player[5].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , 3);
+ SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , 4);
+ SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , 5);
end;
end;
end;
@@ -1389,67 +1390,67 @@ begin
if PlayersPlay = 1 then begin
if PlayerInfo.Playerinfo[0].Enabled then
//SingDrawSingbar( 75 + 10*ScreenX, 95, 100, 8, Player[0].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP1SingBar.x, Theme.Sing.StaticP1SingBar.y, Theme.Sing.StaticP1SingBar.w, Theme.Sing.StaticP1SingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1SingBar.x, Theme.Sing.StaticP1SingBar.y, Theme.Sing.StaticP1SingBar.w, Theme.Sing.StaticP1SingBar.h , 0);
end;
if PlayersPlay = 2 then begin
if PlayerInfo.Playerinfo[0].Enabled then
//SingDrawSingbar( 75 + 10*ScreenX, 95, 100, 8, Player[0].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , 0);
if PlayerInfo.Playerinfo[1].Enabled then
//SingDrawSingbar(620 + 10*ScreenX, 95, 100, 8, Player[1].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , Player[1].ScorePercent, Player[1].ScoreMax, Player[1].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , 1);
end;
if PlayersPlay = 3 then begin
if PlayerInfo.Playerinfo[0].Enabled then
//SingDrawSingbar( 75 + 10*ScreenX, 95, 100, 8, Player[0].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , 0);
if PlayerInfo.Playerinfo[1].Enabled then
//SingDrawSingbar(370 + 10*ScreenX, 95, 100, 8, Player[1].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , Player[1].ScorePercent, Player[1].ScoreMax, Player[1].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , 1);
if PlayerInfo.Playerinfo[2].Enabled then
//SingDrawSingbar(670 + 10*ScreenX, 95, 100, 8, Player[2].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , Player[2].ScorePercent, Player[2].ScoreMax, Player[2].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , 2);
end;
if PlayersPlay = 4 then begin
if ScreenAct = 1 then begin
if PlayerInfo.Playerinfo[0].Enabled then
//SingDrawSingbar( 75 + 10*ScreenX, 95, 100, 8, Player[0].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , 0);
if PlayerInfo.Playerinfo[1].Enabled then
//SingDrawSingbar(620 + 10*ScreenX, 95, 100, 8, Player[1].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , Player[1].ScorePercent, Player[1].ScoreMax, Player[1].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , 1);
end;
if ScreenAct = 2 then begin
if PlayerInfo.Playerinfo[2].Enabled then
//SingDrawSingbar( 75 + 10*ScreenX, 95, 100, 8, Player[2].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , Player[2].ScorePercent, Player[2].ScoreMax, Player[2].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1TwoPSingBar.x, Theme.Sing.StaticP1TwoPSingBar.y, Theme.Sing.StaticP1TwoPSingBar.w, Theme.Sing.StaticP1TwoPSingBar.h , 2);
if PlayerInfo.Playerinfo[3].Enabled then
//SingDrawSingbar(620 + 10*ScreenX, 95, 100, 8, Player[3].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , Player[3].ScorePercent, Player[3].ScoreMax, Player[3].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP2RSingBar.x, Theme.Sing.StaticP2RSingBar.y, Theme.Sing.StaticP2RSingBar.w, Theme.Sing.StaticP2RSingBar.h , 3);
end;
end;
if PlayersPlay = 6 then begin
if ScreenAct = 1 then begin
if PlayerInfo.Playerinfo[0].Enabled then
//SingDrawSingbar( 75 + 10*ScreenX, 95, 100, 8, Player[0].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , Player[0].ScorePercent, Player[0].ScoreMax, Player[0].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , 0);
if PlayerInfo.Playerinfo[1].Enabled then
//SingDrawSingbar(370 + 10*ScreenX, 95, 100, 8, Player[1].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , Player[1].ScorePercent, Player[1].ScoreMax, Player[1].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , 1);
if PlayerInfo.Playerinfo[2].Enabled then
//SingDrawSingbar(670 + 10*ScreenX, 95, 100, 8, Player[2].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , Player[2].ScorePercent, Player[2].ScoreMax, Player[2].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , 2);
end;
if ScreenAct = 2 then begin
if PlayerInfo.Playerinfo[3].Enabled then
//SingDrawSingbar( 75 + 10*ScreenX, 95, 100, 8, Player[3].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , Player[3].ScorePercent, Player[3].ScoreMax, Player[3].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP1ThreePSingBar.x, Theme.Sing.StaticP1ThreePSingBar.y, Theme.Sing.StaticP1ThreePSingBar.w, Theme.Sing.StaticP1ThreePSingBar.h , 3);
if PlayerInfo.Playerinfo[4].Enabled then
//SingDrawSingbar(370 + 10*ScreenX, 95, 100, 8, Player[4].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , Player[4].ScorePercent, Player[4].ScoreMax, Player[4].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP2MSingBar.x, Theme.Sing.StaticP2MSingBar.y, Theme.Sing.StaticP2MSingBar.w, Theme.Sing.StaticP2MSingBar.h , 4);
if PlayerInfo.Playerinfo[5].Enabled then
//SingDrawSingbar(670 + 10*ScreenX, 95, 100, 8, Player[5].ScorePercent);
- SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , Player[5].ScorePercent, Player[5].ScoreMax, Player[5].ScoreTotalI);
+ SingDrawSingbar(Theme.Sing.StaticP3SingBar.x, Theme.Sing.StaticP3SingBar.y, Theme.Sing.StaticP3SingBar.w, Theme.Sing.StaticP3SingBar.h , 5);
end;
end;
end;
@@ -1673,14 +1674,18 @@ end;
//SingBar Mod
-procedure SingDrawSingbar(X, Y, W, H: real; Percent, ScoreMax, ScoreCurrent: integer);
+procedure SingDrawSingbar(X, Y, W, H: real; P: integer);
var
R: Real;
G: Real;
B: Real;
str: string;
wd: real;
+ Percent, ScoreMax, ScoreCurrent: integer;
begin;
+ Percent := Player[P].ScorePercent;
+ ScoreMax := Player[P].ScoreMax;
+ ScoreCurrent := Player[P].ScoreTotalI;
//SingBar Background
glColor4f(1, 1, 1, 0.8);
@@ -1778,7 +1783,7 @@ begin;
glTexCoord2f(1, 1); glVertex2f(X+W*ScoreCurrent/9990, Y+H*2);
glTexCoord2f(1, 0); glVertex2f(X+W*ScoreCurrent/9990, Y+H);
glEnd;
- end else
+ end else if (Ini.PossibleScore=2) then
begin
glColor4f(1, 1, 1, 0.8);
glEnable(GL_TEXTURE_2D);
@@ -1800,6 +1805,28 @@ begin;
wd := glTextWidth(PChar(str));
SetFontPos (X+W/2-wd/2, Y+H);
glPrint(PChar(str));
+ end else
+ begin
+ glColor4f(1, 1, 1, 0.8);
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Back.TexNum);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(X, Y+H);
+ glTexCoord2f(0, 1); glVertex2f(X, Y+H*3);
+ glTexCoord2f(1, 1); glVertex2f(X+W, Y+H*3);
+ glTexCoord2f(1, 0); glVertex2f(X+W, Y+H);
+ glEnd;
+
+ glColor4f(0, 0, 0, 0.7);
+ SetFontStyle(1);
+ SetFontItalic(false);
+ SetFontSize(H*0.7);
+ str := Ini.Name[P];
+ wd := glTextWidth(PChar(str));
+ SetFontPos (X+W/2-wd/2, Y+H);
+ glPrint(PChar(str));
end;
end;
//end Singbar Mod
diff --git a/Game/Code/Classes/UFiles.pas b/Game/Code/Classes/UFiles.pas
index 2b051353..ebeb1314 100644
--- a/Game/Code/Classes/UFiles.pas
+++ b/Game/Code/Classes/UFiles.pas
@@ -4,6 +4,7 @@ interface
uses USongs,
SysUtils,
+ StrUtils,
ULog,
UMusic;
@@ -11,6 +12,18 @@ const
DEFAULT_FADE_IN_TIME = 8; //TODO in INI
DEFAULT_FADE_OUT_TIME = 2;
+ //from USDX 1.1:
+ UTF8_BOM: UTF8String = #$EF#$BB#$BF;
+ //
+
+type
+ // from USDX 1.1:
+ //
+ // String with unknown encoding. Introduced with Delphi 2009 and maybe soon
+ // with FPC.
+ RawByteString = AnsiString;
+ //
+
procedure InitializePaths; //Function sets All Absolute Paths eg. for Songs
function ReadTXTHeader(var Song: TSong): boolean; //Reads Standard TXT Header
function AnalyseFile(var Song: TSong): boolean; //Analyse Song File and Read Header
@@ -137,7 +150,7 @@ begin
//Required Information
Song.Mp3 := '';
- Song.BPM := 0;
+ SetLength(Song.BPM, 0);
Song.GAP := 0;
Song.Start := 0;
Song.Finish := 0;
@@ -147,6 +160,7 @@ begin
//Additional Information
Song.Background := '';
Song.Cover := '';
+ Song.CoverTex.TexNum := -1;
Song.Video := '';
Song.VideoGAP := 0;
Song.NotesGAP := 0;
@@ -185,6 +199,17 @@ var
Song.CustomTags[Len].Content := Content;
end;
+ function CheckReplaceUTF8BOM(var Text: RawByteString): boolean;
+ begin
+ if AnsiStartsStr(UTF8_BOM, Text) then
+ begin
+ Text := Copy(Text, Length(UTF8_BOM)+1, Length(Text)-Length(UTF8_BOM));
+ Result := true;
+ Exit;
+ end;
+ Result := false;
+ end;
+
begin
Result := true;
Done := 0;
@@ -197,13 +222,21 @@ begin
//Read first Line
ReadLn (SongFile, Line);
+ if CheckReplaceUTF8BOM(Line) then
+ begin
+ Log.LogError('File is encoded in UTF8 (not supported in this version): ' + Song.Path + Song.FileName);
+ Result := False;
+ Exit;
+ end;
+
if (Length(Line)<=0) then
begin
- Log.LogError('File Starts with Empty Line: ' + Song.FileName);
+ Log.LogError('File Starts with Empty Line: ' + Song.Path + Song.FileName);
Result := False;
Exit;
end;
+
//Read Lines while Line starts with #
While (Length(Line) = 0) OR (Line[1] = '#') do
begin
@@ -289,13 +322,19 @@ begin
//Cover Picture
else if (Identifier = 'COVER') then
begin
- Song.Cover := Value;
+ if (FileExists(Song.Path + Value)) then
+ Song.Cover := Value
+ else
+ Log.LogError('Can''t find Cover File in Song: ' + Song.Path + Song.FileName);
end
//Background Picture
else if (Identifier = 'BACKGROUND') then
begin
- Song.Background := Value;
+ if (FileExists(Song.Path + Value)) then
+ Song.Background := Value
+ else
+ Log.LogError('Can''t find Background File in Song: ' + Song.Path + Song.FileName);
end
// Video File
@@ -471,15 +510,15 @@ begin
If lWarnIfTagsNotFound then
begin
if (Done and 8) = 0 then //No BPM Flag
- Log.LogError('BPM Tag Missing: ' + Song.FileName)
+ Log.LogError('BPM Tag Missing: ' + Song.Path + Song.FileName)
else if (Done and 4) = 0 then //No MP3 Flag
- Log.LogError('MP3 Tag/File Missing: ' + Song.FileName)
+ Log.LogError('MP3 Tag/File Missing: ' + Song.Path + Song.FileName)
else if (Done and 2) = 0 then //No Artist Flag
- Log.LogError('Artist Tag Missing: ' + Song.FileName)
+ Log.LogError('Artist Tag Missing: ' + Song.Path + Song.FileName)
else if (Done and 1) = 0 then //No Title Flag
- Log.LogError('Title Tag Missing: ' + Song.FileName)
+ Log.LogError('Title Tag Missing: ' + Song.Path + Song.FileName)
else //unknown Error
- Log.LogError('File Incomplete or not Ultrastar TxT: ' + Song.FileName);
+ Log.LogError('File Incomplete or not Ultrastar TxT: ' + Song.Path + Song.FileName);
end;
end else
begin //check medley tags
@@ -704,6 +743,8 @@ var
begin
Result := true;
+ foundMedleyStart := false;
+ foundMedleyEnd := false;
if(AktSong.Medley.Source = msTag) then
begin
@@ -729,7 +770,7 @@ begin
if(numLines=0) then
begin
Log.LogError('Song ' + AktSong.Path + AktSong.Filename + ' has no lines?');
- if (Ini.LoadFaultySongs=0) then
+ if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end;
@@ -740,7 +781,7 @@ begin
if(numNotes=0) then
begin
Log.LogError('Sentence ' + IntToStr(line+1) + ' in song ' + AktSong.Path + AktSong.Filename + ' has no notes?');
- if (Ini.LoadFaultySongs=0) then
+ if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end;
@@ -748,7 +789,7 @@ begin
begin
Log.LogError('Beat error in sentence ' + IntToStr(line+1) + ', on beat ' + IntToStr(Czesci[p].Czesc[line].Start) +
' in song ' + AktSong.Path + AktSong.Filename);
- if (Ini.LoadFaultySongs=0) then
+ if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end;
bt := Czesci[p].Czesc[line].Start;
@@ -759,7 +800,7 @@ begin
begin
Log.LogError('Beat error in sentence ' + IntToStr(line+1) + ', on beat ' + IntToStr(Czesci[p].Czesc[line].Nuta[note].Start) +
' in song ' + AktSong.Path + AktSong.Filename);
- if (Ini.LoadFaultySongs=0) then
+ if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end;
bt := Czesci[p].Czesc[line].Nuta[note].Start;
@@ -768,7 +809,7 @@ begin
begin
Log.LogError('Note length <0 in sentence ' + IntToStr(line+1) + ', on beat ' + IntToStr(Czesci[p].Czesc[line].Nuta[note].Start) +
' in song ' + AktSong.Path + AktSong.Filename);
- if (Ini.LoadFaultySongs=0) then
+ if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end;
@@ -776,7 +817,7 @@ begin
begin
Log.LogError('Note length =0 in sentence ' + IntToStr(line+1) + ', on beat ' + IntToStr(Czesci[p].Czesc[line].Nuta[note].Start) +
' in song ' + AktSong.Path + AktSong.Filename);
- if (Ini.LoadFaultySongs=0) then
+ if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end;
@@ -791,7 +832,7 @@ begin
begin
Log.LogError('Note length error in sentence ' + IntToStr(line+1) + ', on beat ' + IntToStr(Czesci[p].Czesc[line].Nuta[note].Start) +
' in song ' + AktSong.Path + AktSong.Filename);
- if (Ini.LoadFaultySongs=0) then
+ if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end;
@@ -809,12 +850,12 @@ begin
if(medley and not foundMedleyStart) then
begin
Log.LogError('Error MedleyStartBeat: no corresponding note start (beat) in song ' + AktSong.Path + AktSong.Filename);
- if (Ini.LoadFaultySongs=0) then
+ if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end else if(medley and not foundMedleyEnd) then
begin
Log.LogError('Error MedleyEndBeat: no corresponding note start+length in song ' + AktSong.Path + AktSong.Filename);
- if (Ini.LoadFaultySongs=0) then
+ if (Ini.LoadFaultySongs=0) and (Ini.LoadFaultySongs_temp=0) then
Result := false;
end;
end;
@@ -883,8 +924,6 @@ begin
end;
end;
- Result := False;
-
Reset(SongFile);
FileLineNo := 0;
//Search for Note Begining
@@ -1071,12 +1110,10 @@ end;
function SaveSong(Song: TSong; Czesc: array of TCzesci; Name: string; Relative: boolean): boolean;
var
C: integer;
- N: integer;
S: string;
B: integer;
RelativeSubTime: integer;
NoteState: String;
- CP: integer;
P: integer;
procedure WriteCustomTags; //from 1.1 (modified)
@@ -1322,9 +1359,9 @@ begin
end;
//search for longest sequence
+ max := 0;
if Length(series)>0 then
begin
- max := 0;
for I := 0 to Length(series) - 1 do
begin
if series[I].len > series[max].len then
diff --git a/Game/Code/Classes/UGraphic.pas b/Game/Code/Classes/UGraphic.pas
index 4d5bf3c7..99ffe3a1 100644
--- a/Game/Code/Classes/UGraphic.pas
+++ b/Game/Code/Classes/UGraphic.pas
@@ -4,7 +4,8 @@ interface
uses
SDL, gl, glext, UVideo, UTexture, ULanguage, TextGL, ULog, SysUtils, ULyrics, UScreenLoading,
UScreenWelcome, UScreenMain, UScreenName, UScreenLevel, UScreenOptions, UScreenOptionsGame,
- UScreenOptionsGraphics, UScreenOptionsSound, UScreenOptionsLyrics, UScreenOptionsThemes, UScreenOptionsRecord, UScreenOptionsAdvanced,
+ UScreenOptionsGraphics, UScreenOptionsSound, UScreenOptionsLyrics, UScreenOptionsThemes, UScreenOptionsRecord,
+ UScreenOptionsAdvanced,
UScreenSong, UScreenSing, UScreenScore, UScreenTop, UScreenEditSub,
UScreenEdit, UScreenEditConvert, UScreenEditHeader, UScreenOpen, UThemes, USkins, UScreenSongMenu, UScreenSongJumpto,
{Party Screens} UScreenSingModi, UScreenPartyNewRound, UScreenPartyScore, UScreenPartyOptions, UScreenPartyWin, UScreenPartyPlayer,
@@ -191,7 +192,7 @@ procedure UnLoadScreens;
procedure UpdateScreenLoading(txt: string);
implementation
-uses UMain, UIni, UDisplay, UCommandLine, Graphics, Classes, Windows;
+uses UMain, UIni, UDisplay, UCommandLine, Graphics, Classes, Windows, UWebCam;
procedure LoadTextures;
var
@@ -319,7 +320,13 @@ begin
if (Ini.LoadFaultySongs=1) and (Log.NumErrors>0) then
ScreenMain.ShowNumErrors := true;
- Display.ActualScreen^.FadeTo(@ScreenMain);
+ if (Ini.ShowCredits=1) then
+ begin
+ Ini.ShowCredits := 0;
+ Ini.Save;
+ Display.ActualScreen^.FadeTo(@ScreenCredits)
+ end else
+ Display.ActualScreen^.FadeTo(@ScreenMain);
Log.BenchmarkEnd(2);
Log.LogBenchmark('--> Loading Screens', 2);
@@ -444,6 +451,7 @@ begin
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
SwapBuffers;
+ SDL_Delay(1);
end;
procedure LoadScreens( aShowLoading : boolean = true );
@@ -458,7 +466,7 @@ begin
Display.Draw;
SwapBuffers;
end;
-
+ SDL_Delay(1);
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Loading', 3); Log.BenchmarkStart(3);
{ ScreenWelcome := TScreenWelcome.Create; //'BG', 4, 3);
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Welcome', 3); Log.BenchmarkStart(3);}
@@ -473,7 +481,7 @@ begin
if(aShowLoading) then
UpdateScreenLoading(Language.Translate('SING_LOADING'));
-
+ SDL_Delay(1);
ScreenSongMenu := TScreenSongMenu.Create;
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Song Menu', 3); Log.BenchmarkStart(3);
ScreenSing := TScreenSing.Create;
@@ -534,10 +542,11 @@ begin
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Stat Main', 3); Log.BenchmarkStart(3);
ScreenStatDetail := TScreenStatDetail.Create;
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Stat Detail', 3); Log.BenchmarkStart(3);
- //Now Created when needed
- //ScreenCredits := TScreenCredits.Create;
- //Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Credits', 3); Log.BenchmarkStart(3);
-
+ if (Ini.ShowCredits=1) then
+ begin
+ ScreenCredits := TScreenCredits.Create;
+ Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Credits', 3); Log.BenchmarkStart(3);
+ end;
//PartyM2 Screens
ScreenPartyOptionsM2 := TScreenPartyOptionsM2.Create;
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyOptionsM2', 3); Log.BenchmarkStart(3);
@@ -545,6 +554,7 @@ begin
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyPlayerM2', 3); Log.BenchmarkStart(3);
ScreenPartyNewRoundM2 := TScreenPartyNewRoundM2.Create;
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyNewRoundM2', 3); Log.BenchmarkStart(3);
+ SDL_Delay(1);
end;
procedure UnLoadScreens;
diff --git a/Game/Code/Classes/UGraphicClasses.pas b/Game/Code/Classes/UGraphicClasses.pas
index ac19af6c..d9aeb227 100644
--- a/Game/Code/Classes/UGraphicClasses.pas
+++ b/Game/Code/Classes/UGraphicClasses.pas
@@ -595,9 +595,11 @@ end;
procedure TEffectManager.SpawnPerfectLineTwinkle();
var
- P,I,Life: Cardinal;
+ P,I,Life: Cardinal;
Left, Right, Top, Bottom: Cardinal;
- cScreen: Integer;
+ cScreen: Integer;
+
+ P4Mode: boolean;
begin
// calculation of coordinates done with hardcoded values like in UDraw.pas
// might need to be adjusted if drawing of SingScreen is modified
@@ -607,10 +609,12 @@ begin
begin
Left := 30;
Right := 770;
+ P4Mode := false;
end else
begin
Left := 15;
Right := 385;
+ P4Mode := true;
end;
// spawn effect for every player with a perfect line
@@ -635,10 +639,14 @@ begin
Top:=Bottom-105;
end;
end;
- case P of
- 0,1: cScreen:=1;
- else cScreen:=2;
- end;
+ if not P4Mode then
+ begin
+ case P of
+ 0,1: cScreen:=1;
+ else cScreen:=2;
+ end;
+ end else
+ cScreen := 1;
end;
3,6: begin
case P of
@@ -655,17 +663,42 @@ begin
Bottom:=Top+85;
end;
end;
- case P of
- 0,1,2: cScreen:=1;
- else cScreen:=2;
- end;
+ if not P4Mode then
+ begin
+ case P of
+ 0,1,2: cScreen:=1;
+ else cScreen:=2;
+ end;
+ end else
+ cScreen:=1;
end;
end;
// spawn Sparkling Stars inside calculated coordinates
for I:= 0 to 80 do
begin
Life:=RandomRange(8,16);
- Spawn(RandomRange(Left,Right), RandomRange(Top,Bottom), cScreen, Life, 16-Life, -1, PerfectLineTwinkle, P, (P+1) mod 2);
+ if not P4Mode then
+ Spawn(RandomRange(Left,Right), RandomRange(Top,Bottom), cScreen, Life, 16-Life, -1, PerfectLineTwinkle, P, (P+1) mod 2)
+ else
+ begin
+ if PlayersPlay=4 then
+ begin
+ case P of
+ 0,1:
+ Spawn(RandomRange(Left,Right), RandomRange(Top,Bottom), cScreen, Life, 16-Life, -1, PerfectLineTwinkle, P, (P+1) mod 2);
+ 2,3:
+ Spawn(RandomRange(Left+400,Right+400), RandomRange(Top,Bottom), cScreen, Life, 16-Life, -1, PerfectLineTwinkle, P, (P+1) mod 2);
+ end;
+ end else
+ begin
+ case P of
+ 0,1,2:
+ Spawn(RandomRange(Left,Right), RandomRange(Top,Bottom), cScreen, Life, 16-Life, -1, PerfectLineTwinkle, P, (P+1) mod 2);
+ 3,4,5:
+ Spawn(RandomRange(Left+400,Right+400), RandomRange(Top,Bottom), cScreen, Life, 16-Life, -1, PerfectLineTwinkle, P, (P+1) mod 2);
+ end;
+ end;
+ end;
end;
end;
end;
diff --git a/Game/Code/Classes/UHelp.pas b/Game/Code/Classes/UHelp.pas
index d3595e52..95143584 100644
--- a/Game/Code/Classes/UHelp.pas
+++ b/Game/Code/Classes/UHelp.pas
@@ -58,11 +58,12 @@ type
THelp = class
private
+ actualID: string;
ScrollPos: double;
- Entry: array of TEntry;
- SEntry: array of TEntry;
- AEntry: TEntry;
- List: array of TLanguageList;
+ Entry: array of TEntry;
+ SEntry: array of TEntry;
+ AEntry: TEntry;
+ List: array of TLanguageList;
Implode_Glue1, Implode_Glue2: String;
public
MaxLines: integer;
@@ -72,6 +73,7 @@ type
procedure ChangeLanguage(Language: String);
//procedure LoadKeys;
function SetHelpID(ID: String):boolean;
+ function GetHelpID(): string;
function GetHelpStr(): TTextResult;
procedure SetScrollPos(pos: double);
function GetScrollPos(): double;
@@ -131,6 +133,8 @@ begin
if (I = high(List)) then
Log.LogError('English Languagefile missing! No standard Translation loaded (Help System)');
end;
+
+ actualID := '';
//Standard Language END
end;
@@ -322,13 +326,7 @@ begin
begin
Result := true;
AEntry := Entry[E];
- {
- SetLength(AEntry.Keys, Length(Entry[E].Keys));
- AEntry.ID := Entry[E].ID;
- AEntry.Title := Entry[E].Title;
- AEntry.Description := Entry[E].Description;
- for J := low(Entry[E].Keys) to high(Entry[E].Keys) do
- AEntry.Keys[J] := Entry[E].Keys[J];}
+ actualID := ID;
exit;
end;
end;
@@ -341,20 +339,18 @@ begin
begin
Result := true;
AEntry := SEntry[E];
- {
- SetLength(AEntry.Keys, Length(SEntry[E].Keys));
- AEntry.ID := SEntry[E].ID;
- AEntry.Title := SEntry[E].Title;
- AEntry.Description := SEntry[E].Description;
- for J := low(SEntry[E].Keys) to high(SEntry[E].Keys) do
- AEntry.Keys[J] := SEntry[E].Keys[J]; }
-
+ actualID := ID;
exit;
end;
end;
//Standard Language END
end;
+function THelp.GetHelpID(): string;
+begin
+ Result := actualID;
+end;
+
function THelp.GetHelpStr(): TTextResult;
var
K, I, J: Integer;
diff --git a/Game/Code/Classes/UIni.pas b/Game/Code/Classes/UIni.pas
index 97030d1d..6ea24653 100644
--- a/Game/Code/Classes/UIni.pas
+++ b/Game/Code/Classes/UIni.pas
@@ -25,7 +25,10 @@ type
ShuffleTime: integer;
Debug: integer;
LoadFaultySongs:integer;
+ LoadFaultySongs_temp: integer;
NewPartyPoints: integer;
+ ShowCredits: integer;
+ NewPartySelectionMode: integer;
// Graphics
Screens: integer;
@@ -72,6 +75,9 @@ type
ChannelL: integer;
ChannelR: integer;
end;
+ EnableWebCam: integer;
+ WebCamID: integer;
+ WebCamMediaID: integer;
// Advanced
LoadAnimation: integer;
@@ -136,6 +142,8 @@ const
IDebug: array[0..1] of string = ('Off', 'On');
ILoadFaultySongs: array[0..1] of string = ('Off', 'On');
INewPartyPoints: array[0..1] of string = ('Off', 'On');
+ IShowCredits: array[0..1] of string = ('Off', 'On');
+ INewPartySelectionMode: array[0..1] of string = ('Off', 'On');
IScreens: array[0..1] of string = ('1', '2');
IFullScreen: array[0..1] of string = ('Off', 'On');
@@ -153,6 +161,7 @@ const
IAspectCorrect: array[0..2] of String = ('Stretch', 'Crop', 'LetterBox');
IPerformanceMode:array[0..1] of string = ('Off', 'On');
IEnablePBO: array[0..1] of string = ('Off', 'On');
+ IEnableWebCam: array[0..1] of string = ('Off', 'On');
IMicBoost: array[0..3] of string = ('Off', '+6dB', '+12dB', '+18dB');
IClickAssist: array[0..1] of string = ('Off', 'On');
@@ -180,7 +189,7 @@ const
IPartyPopup: array[0..1] of string = ('Off', 'On');
ISumPlayers: array[0..2] of string = ('Never', 'Dynamic', 'Always');
IDuelRatio: array[0..9] of string = ('normal', '10%', '20%', '30%', '40%', '50%', '60%', '70%', '80%', '90%');
- IPossibleScore: array[0..2] of string = ('Off', 'Bar', 'Numbers');
+ IPossibleScore: array[0..3] of string = ('Off', 'Bar', 'Numbers', 'Name');
ILogSession: array[0..1] of string = ('Off', 'On');
IChannel: array[0..6] of string = ('Off', '1', '2', '3', '4', '5', '6');
@@ -274,13 +283,22 @@ begin
Tekst := IniFile.ReadString('Game', 'LoadFaultySongs', ILoadFaultySongs[0]);
for Pet := 0 to High(ILoadFaultySongs) do
if Tekst = ILoadFaultySongs[Pet] then Ini.LoadFaultySongs := Pet;
+ LoadFaultySongs_temp := LoadFaultySongs;
// NewPartyPoints
Tekst := IniFile.ReadString('Game', 'NewPartyPoints', INewPartyPoints[1]);
for Pet := 0 to High(INewPartyPoints) do
if Tekst = INewPartyPoints[Pet] then Ini.NewPartyPoints := Pet;
- //if Ini.Debug = 1 then SongPath := 'E:\UltraStar 03\Songs\';
+ // ShowCredits
+ Tekst := IniFile.ReadString('Game', 'ShowCredits', IShowCredits[1]);
+ for Pet := 0 to High(IShowCredits) do
+ if Tekst = IShowCredits[Pet] then Ini.ShowCredits := Pet;
+
+ // NewPartySelectionMode
+ Tekst := IniFile.ReadString('Game', 'NewPartySelectionMode', INewPartySelectionMode[1]);
+ for Pet := 0 to High(INewPartySelectionMode) do
+ if Tekst = INewPartySelectionMode[Pet] then Ini.NewPartySelectionMode := Pet;
// Screens
Tekst := IniFile.ReadString('Graphics', 'Screens', IScreens[0]);
@@ -377,7 +395,7 @@ begin
if Tekst = IMoviePreview[Pet] then Ini.MoviePreview := Pet;
// AspectCorrection
- Tekst := IniFile.ReadString('Graphics', 'AspectCorrect', IAspectCorrect[2]);
+ Tekst := IniFile.ReadString('Graphics', 'AspectCorrect', IAspectCorrect[1]);
for Pet := 0 to High(IAspectCorrect) do
if Tekst = IAspectCorrect[Pet] then Ini.AspectCorrect := Pet;
@@ -560,6 +578,21 @@ begin
end;
end;
+ // enable WebCam
+ Tekst := IniFile.ReadString('Record', 'EnableWebCam', IEnableWebCam[0]);
+ for Pet := 0 to High(IEnableWebCam) do
+ if Tekst = IEnableWebCam[Pet] then Ini.EnableWebCam := Pet;
+
+ // WebCamID
+ Tekst := IniFile.ReadString('Record', 'WebCamID', '0');
+ if not TryStrToInt(Tekst, Ini.WebCamID) then
+ Ini.WebCamID := 0;
+
+ // WebCamMediaID
+ Tekst := IniFile.ReadString('Record', 'WebCamMediaID', '0');
+ if not TryStrToInt(Tekst, Ini.WebCamMediaID) then
+ Ini.WebCamMediaID := 0;
+
//Advanced Settings
// LoadAnimation
@@ -682,6 +715,14 @@ begin
Tekst := INewPartyPoints[Ini.NewPartyPoints];
IniFile.WriteString('Game', 'NewPartyPoints', Tekst);
+ // ShowCredits
+ Tekst := IShowCredits[Ini.ShowCredits];
+ IniFile.WriteString('Game', 'ShowCredits', Tekst);
+
+ // NewPartySelectionMode
+ Tekst := IShowCredits[Ini.NewPartySelectionMode];
+ IniFile.WriteString('Game', 'NewPartySelectionMode', Tekst);
+
// Screens
Tekst := IScreens[Ini.Screens];
IniFile.WriteString('Graphics', 'Screens', Tekst);
@@ -804,6 +845,18 @@ begin
//Log.LogError(InttoStr(Length(CardList)) + ' Cards Saved');
+ // enable WebCam
+ Tekst := IEnableWebCam[Ini.EnableWebCam];
+ IniFile.WriteString('Record', 'EnableWebCam', Tekst);
+
+ // WebCamID
+ Tekst := IntToStr(Ini.WebCamID);
+ IniFile.WriteString('Record', 'WebCamID', Tekst);
+
+ // WebCamMediaID
+ Tekst := IntToStr(Ini.WebCamMediaID);
+ IniFile.WriteString('Record', 'WebCamMediaID', Tekst);
+
//Advanced Settings
//LoadAnimation
diff --git a/Game/Code/Classes/ULog.pas b/Game/Code/Classes/ULog.pas
index 8be7a8ca..737364e8 100644
--- a/Game/Code/Classes/ULog.pas
+++ b/Game/Code/Classes/ULog.pas
@@ -49,11 +49,235 @@ type
procedure LogError(Log1, Log2: string); overload;
end;
+ TPerfLog = record
+ starttime: integer;
+ stoptime: integer;
+ cycle: array of record
+ starttime: integer;
+ stoptime: integer;
+ comment: array of record
+ timestamp: integer;
+ text: string;
+ end;
+ end;
+ end;
+
+ TPerformanceLog = class
+ private
+ active: boolean;
+ PerfLog: TPerflog;
+ public
+ procedure StartNewLog;
+ procedure StopLogging;
+
+ procedure CycleStart;
+ procedure CycleEnd;
+ procedure AddComment(comment: string);
+
+ property isActive: boolean read active;
+ end;
+
var
- Log: TLog;
+ Log: TLog;
+ PerfLog: TPerformanceLog;
implementation
-uses UFiles, SysUtils, DateUtils, URecord, UTime, UIni, Windows, UCommandLine;
+uses UFiles, SysUtils, DateUtils, URecord, UTime, UIni, Windows, UCommandLine, SDL;
+
+procedure TPerformanceLog.StartNewLog;
+begin
+ SetLength(PerfLog.cycle, 0);
+ PerfLog.starttime := SDL_GetTicks();
+ PerfLog.stoptime := -1;
+ active := true;
+end;
+
+procedure TPerformanceLog.StopLogging;
+var
+ i, j: integer;
+ LogFile: TextFile;
+ CsvFile: TextFile;
+ TimeTemp: integer;
+ pos: integer;
+
+ FileName: string;
+ FileNameCSV:string;
+ Num: integer;
+ Year, Month, Day: word;
+ Hour, Min, Sec, MSec: word;
+ timestamp: integer;
+ datestr: string;
+ timestr: string;
+
+ function Fill(w: word): string;
+ begin
+ Result := '';
+ if (w<10) then
+ Result := '0';
+
+ Result := Result + IntToStr(w);
+ end;
+
+ function duration(t1, t2: integer): integer; //ms
+ begin
+ result := round(t2-t1);
+ end;
+begin
+ if not active then
+ exit;
+
+ Timetemp := SDL_GetTicks();
+ PerfLog.stoptime := TimeTemp;
+
+ pos := Length(PerfLog.cycle);
+ if (pos>0) then
+ begin
+ if (PerfLog.cycle[pos-1].stoptime<0) then
+ PerfLog.cycle[pos-1].stoptime := TimeTemp;
+ end;
+
+ timestamp := DateTimeToUnix(Now());
+ DecodeDate(UnixToDateTime(timestamp), Year, Month, Day);
+ DecodeTime(UnixToDateTime(timestamp), Hour, Min, Sec, MSec);
+
+ datestr := IntToStr(Year) + Fill(Month) + Fill(Day);
+ timestr := Fill(Hour) + Fill(Min) + Fill(Sec);
+
+ FileName := GamePath + 'PerfLog_' + datestr + '-' + timestr + '.log';
+
+ if FileExists(FileName) then
+ begin
+ for Num := 1 to 9999 do
+ begin
+ FileName := IntToStr(Num);
+ while Length(FileName) < 4 do FileName := '0' + FileName;
+ FileName := GamePath + 'PerfLog_' + datestr + '-' + timestr + '_' + FileName + '.log';
+ if not FileExists(FileName) then break
+ end;
+ end;
+
+ AssignFile(LogFile, FileName);
+ {$I-}
+ Rewrite(LogFile);
+ if IOResult <> 0 then exit;
+ {$I+}
+
+
+ FileNameCSV := GamePath + 'PerfLog_' + datestr + '-' + timestr + '.csv';
+
+ if FileExists(FileNameCSV) then
+ begin
+ for Num := 1 to 9999 do
+ begin
+ FileNameCSV := IntToStr(Num);
+ while Length(FileNameCSV) < 4 do FileNameCSV := '0' + FileNameCSV;
+ FileNameCSV := GamePath + 'PerfLog_' + datestr + '-' + timestr + '_' + FileNameCSV + '.csv';
+ if not FileExists(FileNameCSV) then break
+ end;
+ end;
+
+ AssignFile(CsvFile, FileNameCSV);
+ {$I-}
+ Rewrite(CsvFile);
+ if IOResult <> 0 then exit;
+ {$I+}
+
+ //If File is opened write Date to File
+ WriteLn(LogFile, 'Performance Log');
+ WriteLn(LogFile, 'Date: ' + IntToStr(Year) + '-' + Fill(Month) + '-' + Fill(Day) +
+ ' Time: ' + Fill(Hour) + ':' + Fill(Min) + ':' + Fill(Sec));
+ WriteLn(LogFile, '');
+ WriteLn(LogFile, '# Start : ' + IntToStr(duration(PerfLog.starttime, PerfLog.starttime)));
+ WriteLn(LogFile, '# End : ' + IntToStr(duration(PerfLog.starttime, PerfLog.stoptime)));
+ WriteLn(LogFile, '# Duration : ' + IntToStr(duration(PerfLog.starttime, PerfLog.stoptime)));
+ Flush(LogFile);
+
+ for i := 0 to Length(PerfLog.cycle) - 1 do
+ begin
+ WriteLn(LogFile, '');
+ WriteLn(LogFile, '');
+ WriteLn(LogFile, '#----------------------------------------------------------------');
+ WriteLn(LogFile, '# Cycle-Nr.: ' + IntToStr(i+1));
+ WriteLn(LogFile, '# Start : ' + IntToStr(duration(PerfLog.starttime, PerfLog.cycle[i].starttime)));
+ WriteLn(LogFile, '# End : ' + IntToStr(duration(PerfLog.starttime, PerfLog.cycle[i].stoptime)));
+ WriteLn(LogFile, '# Duration : ' + IntToStr(duration(PerfLog.cycle[i].starttime, PerfLog.cycle[i].stoptime)));
+ WriteLn(LogFile, '#----------------------------------------------------------------');
+
+ WriteLn(CsvFile, IntToStr(duration(PerfLog.starttime, PerfLog.cycle[i].starttime))+';'+
+ IntToStr(duration(PerfLog.cycle[i].starttime, PerfLog.cycle[i].stoptime)));
+ for j := 0 to Length(PerfLog.cycle[i].comment) - 1 do
+ begin
+ WriteLn(LogFile, '# Comment ' + IntToStr(j) + ': ' + PerfLog.cycle[i].comment[j].text);
+ WriteLn(LogFile, '# time: ' + IntToStr(duration(PerfLog.starttime, PerfLog.cycle[i].comment[j].timestamp)));
+ WriteLn(LogFile, '#');
+ end;
+ WriteLn(LogFile, '#-----------------------------------------------------------------');
+
+ end;
+ Flush(LogFile);
+ Flush(CsvFile);
+
+ active := false;
+end;
+
+procedure TPerformanceLog.CycleStart;
+var
+ pos: integer;
+ TimeTemp: integer;
+begin
+ if not active then
+ exit;
+
+ TimeTemp := SDL_GetTicks();
+
+ pos := Length(PerfLog.cycle);
+ if (pos>0) then
+ begin
+ if (PerfLog.cycle[pos-1].stoptime<0) then
+ PerfLog.cycle[pos-1].stoptime := TimeTemp;
+ end;
+
+ SetLength(PerfLog.cycle, pos+1);
+ PerfLog.cycle[pos].starttime := TimeTemp;
+ PerfLog.cycle[pos].stoptime := -1;
+
+ SetLength(PerfLog.cycle[pos].comment, 0);
+end;
+
+procedure TPerformanceLog.CycleEnd;
+var
+ pos: integer;
+begin
+ if not active then
+ exit;
+
+ pos := Length(PerfLog.cycle)-1;
+
+ if (pos>=0) then
+ PerfLog.cycle[pos].stoptime := SDL_GetTicks();
+end;
+
+procedure TPerformanceLog.AddComment(comment: string);
+var
+ pos: integer;
+ posc: integer;
+begin
+ if not active then
+ exit;
+
+ pos := Length(PerfLog.cycle)-1;
+ if (pos<0) then
+ exit;
+
+ posc := Length(PerfLog.cycle[pos].comment);
+ SetLength(PerfLog.cycle[pos].comment, posc+1);
+
+ PerfLog.cycle[pos].comment[posc].text := comment;
+ PerfLog.cycle[pos].comment[posc].timestamp := SDL_GetTicks();
+end;
+
+
+
destructor TLog.Free;
begin
diff --git a/Game/Code/Classes/UMain.pas b/Game/Code/Classes/UMain.pas
index 2b947908..c8b398b7 100644
--- a/Game/Code/Classes/UMain.pas
+++ b/Game/Code/Classes/UMain.pas
@@ -114,7 +114,7 @@ function GetTimeFromBeat(Beat: integer): real;
procedure ClearScores(PlayerNum: integer);
implementation
-uses USongs, Math, UCommandLine, UVideo;
+uses USongs, Math, UCommandLine, UVideo, UWebCam;
procedure MainLoop;
var
@@ -123,6 +123,7 @@ begin
SDL_EnableKeyRepeat(125, 125);
While not Done do
Begin
+ PerfLog.CycleStart;
// keyboard events
CheckEvents;
@@ -133,7 +134,7 @@ begin
// delay
CountMidTime;
- Delay := Floor(1000 / 200 - 1000 * TimeMid);
+ Delay := Floor(1000 / 100 - 1000 * TimeMid);
if Delay >= 1 then
SDL_Delay(Delay);
CountSkipTime;
@@ -143,8 +144,10 @@ begin
Reinitialize3D;
Restart := false;
end;
-
+ PerfLog.CycleEnd;
End;
+ wClose;
+ acClose;
FreeOpenGL;
End;
@@ -360,16 +363,13 @@ var
Done: real;
N: integer;
begin
- Czas.Teraz := Czas.Teraz + TimeSkip;
+ //Czas.Teraz := Czas.Teraz + TimeSkip;
+ Czas.Teraz := Music.Position;
Czas.OldBeat := Czas.AktBeat;
Czas.MidBeat := GetMidBeat(Czas.Teraz - (AktSong.Gap{ + 90 I've forgotten for what it is}) / 1000); // new system with variable BPM in function
Czas.AktBeat := Floor(Czas.MidBeat);
-// Czas.OldHalf := Czas.AktHalf;
-// Czas.MidHalf := Czas.MidBeat + 0.5;
-// Czas.AktHalf := Floor(Czas.MidHalf);
-
Czas.OldBeatC := Czas.AktBeatC;
Czas.MidBeatC := GetMidBeat(Czas.Teraz - (AktSong.Gap) / 1000);
Czas.AktBeatC := Floor(Czas.MidBeatC);
@@ -547,6 +547,9 @@ end;
//end;
procedure NewNote(P: integer; Sender: TScreenSing);
+const
+ DEBUG_NOTE_HIT = false;
+
var
CP: integer; // current player
S: integer; // sentence
@@ -597,7 +600,7 @@ begin
S := SDet;
- if (Sound[CP].SzczytJest) and (Mozna) then
+ if (Sound[CP].SzczytJest or DEBUG_NOTE_HIT) and (Mozna) then
begin
// operowanie na ostatniej nucie
for Pet := 0 to Czesci[P].Czesc[S].HighNut do
@@ -619,7 +622,8 @@ begin
//if Ini.Difficulty = 1 then Range := 1;
//if Ini.Difficulty = 2 then Range := 0;
Range := 2 - Ini.Difficulty;
- if abs(Czesci[P].Czesc[S].Nuta[Pet].Ton - Sound[CP].Ton) <= Range then
+ if (abs(Czesci[P].Czesc[S].Nuta[Pet].Ton - Sound[CP].Ton) <= Range) or
+ DEBUG_NOTE_HIT then
begin
Sound[CP].Ton := Czesci[P].Czesc[S].Nuta[Pet].Ton;
@@ -771,7 +775,7 @@ begin
S := SDet;
- if (Sound[CP].SzczytJest) and (Mozna) then
+ if (Sound[CP].SzczytJest or DEBUG_NOTE_HIT) and (Mozna) then
begin
// operowanie na ostatniej nucie
for Pet := 0 to Czesci[P].Czesc[S].HighNut do
@@ -793,7 +797,8 @@ begin
//if Ini.Difficulty = 1 then Range := 1;
//if Ini.Difficulty = 2 then Range := 0;
Range := 2 - Ini.Difficulty;
- if abs(Czesci[P].Czesc[S].Nuta[Pet].Ton - Sound[CP].Ton) <= Range then
+ if (abs(Czesci[P].Czesc[S].Nuta[Pet].Ton - Sound[CP].Ton) <= Range) or
+ DEBUG_NOTE_HIT then
begin
Sound[CP].Ton := Czesci[P].Czesc[S].Nuta[Pet].Ton;
diff --git a/Game/Code/Classes/UMergeSort.pas b/Game/Code/Classes/UMergeSort.pas
new file mode 100644
index 00000000..8a0aa124
--- /dev/null
+++ b/Game/Code/Classes/UMergeSort.pas
@@ -0,0 +1,101 @@
+unit UMergeSort;
+
+interface
+
+type
+ TDirection = (dSourceSource, dSourceTemp, dTempTemp, dTempSource);
+
+ TCompareProc = function(TempIndex, SourceIndex: integer): boolean; cdecl;
+ PCompareProc = ^TCompareProc;
+
+ TCopyProc = function(iSourceIndex, iDestIndex: integer; bDirection: TDirection): boolean; cdecl;
+ PCopyProc = ^TCopyProc;
+
+ TMergeSorter = class
+ private
+ n: integer;
+
+ aCallbackCompare: TCompareProc;
+ aCallbackCopy: TCopyProc;
+
+ procedure MergeSort(lo, hi: integer);
+ procedure Merge(lo, m, hi: integer);
+ public
+ procedure Sort(n: integer; aCompare: TCompareProc; aCopy: TCopyProc);
+ end;
+
+
+implementation
+
+procedure TMergeSorter.Sort(n: integer; aCompare: TCompareProc; aCopy: TCopyProc);
+begin
+ Self.n := n;
+ Self.aCallbackCompare := aCompare;
+ Self.aCallbackCopy := aCopy;
+ MergeSort(0, n-1);
+end;
+
+procedure TMergeSorter.MergeSort(lo, hi: integer);
+var
+ m: integer;
+
+begin
+ if (lo<hi) then
+ begin
+ m := (lo+hi) div 2;
+ MergeSort(lo, m);
+ MergeSort(m+1, hi);
+ Merge(lo, m, hi);
+ end;
+end;
+
+procedure TMergeSorter.Merge(lo, m, hi: integer);
+var
+ i, j, k: integer;
+
+begin
+ i := 0;
+ j := lo;
+
+ // vordere Hälfte von a in Hilfsarray b kopieren
+ while (j<=m) do
+ begin
+ aCallbackCopy(j, i, dSourceTemp);
+ //b[i] := a[j];
+ inc(i);
+ inc(j);
+ end;
+
+ i := 0;
+ k := lo;
+ // jeweils das nächstgrößte Element zurückkopieren
+ while ((k<j) and (j<=hi)) do
+ begin
+ if aCallbackCompare(i, j) then
+ //if (b[i]<=a[j]) then
+ begin
+ aCallbackCopy(i, k, dTempSource);
+ //a[k] := b[i];
+ inc(k);
+ inc(i);
+ end else
+ begin
+ aCallbackCopy(j, k, dSourceSource);
+ //a[k] := a[j];
+ inc(k);
+ inc(j);
+ end;
+ end;
+
+ // Rest von b falls vorhanden zurückkopieren
+ while (k<j) do
+ begin
+ aCallbackCopy(i, k, dTempSource);
+ //a[k] := b[i];
+ inc(k);
+ inc(i);
+ end;
+
+end;
+
+end.
diff --git a/Game/Code/Classes/UMusic.pas b/Game/Code/Classes/UMusic.pas
index 13d7fcb6..d192927e 100644
--- a/Game/Code/Classes/UMusic.pas
+++ b/Game/Code/Classes/UMusic.pas
@@ -65,6 +65,7 @@ type
DSP_VocalRemover: HDSP;
public
Bass: hStream;
+ PlayerI: array of integer;
// SoundCard: array of TSoundCard;
procedure InitializePlayback;
@@ -105,7 +106,7 @@ type
procedure CaptureStart;
procedure CaptureStop;
- procedure CaptureCard(RecordI, PlayerLeft, PlayerRight: byte);
+ procedure CaptureCard(RecordI: byte);
procedure StopCard(Card: byte);
function LoadPlayerFromFile(var MediaPlayer: TMediaPlayer; Name: string): boolean;
function LoadSoundFromFile(var hStream: hStream; Name: string): boolean;
@@ -205,8 +206,8 @@ type
OldCzesc: array [0..1] of integer; // poprzednio wyswietlana czesc
// akt jest w czesci.akt
- Teraz: real; // aktualny czas w utworze
- Razem: real; // caly czas utworu
+ Teraz: real; // actual time
+ Razem: real; // total time
// TerazSek: integer;
end;
@@ -773,42 +774,16 @@ begin
for S := 0 to High(Sound) do
Sound[S].BufferLong[0].Clear;
-{ case PlayersPlay of
- 1: begin
- CaptureCard(0, 0, 1, 0);
- end;
- 2: begin
- if Ini.TwoPlayerMode = 0 then begin
- CaptureCard(0, 0, 1, 2);
- end else begin
- CaptureCard(0, 0, 1, 0);
- CaptureCard(1, 1, 2, 0);
- end;
- end;
- 3: begin
- CaptureCard(0, 0, 1, 2);
- CaptureCard(1, 1, 3, 0);
- end;
- end; // case}
-
-// CaptureCard(0, 0, 0, 0);
-// end;
+ SetLength(PlayerI, High(Ini.CardList)+1);
- {for SC := 0 to High(SoundCard) do begin
- P1 := Ini.SoundCard[SC, 1];
- P2 := Ini.SoundCard[SC, 2];
- if P1 > PlayersPlay then P1 := 0;
- if P2 > PlayersPlay then P2 := 0;
- CaptureCard(SC, P1, P2);
- end; }
- // 0.5.2: new
for SC := 0 to High(Ini.CardList) do begin
P1 := Ini.CardList[SC].ChannelL;
P2 := Ini.CardList[SC].ChannelR;
if P1 > PlayersPlay then P1 := 0;
if P2 > PlayersPlay then P2 := 0;
+ PlayerI[SC] := P1 + P2*256;
if (P1 > 0) or (P2 > 0) then
- CaptureCard(SC, P1, P2);
+ CaptureCard(SC);
end;
end;
@@ -818,31 +793,6 @@ var
P1: integer;
P2: integer;
begin
-{ if RecordSystem = 1 then begin
- case PlayersPlay of
- 1: begin
- StopCard(0);
- end;
- 2: begin
- if Ini.TwoPlayerMode = 0 then begin
- StopCard(0);
- end else begin
- StopCard(0);
- StopCard(1);
- end;
- end;
- 3: begin
- StopCard(0);
- StopCard(1);
- end;
- end;
- end;}
-
- {for SC := 0 to High(SoundCard) do begin
- StopCard(SC);
- end; }
-
- // 0.5.2
for SC := 0 to High(Ini.CardList) do begin
P1 := Ini.CardList[SC].ChannelL;
P2 := Ini.CardList[SC].ChannelR;
@@ -850,15 +800,14 @@ begin
if P2 > PlayersPlay then P2 := 0;
if (P1 > 0) or (P2 > 0) then StopCard(SC);
end;
-
end;
//procedure TMusic.CaptureCard(RecordI, SoundNum, PlayerLeft, PlayerRight: byte);
-procedure TMusic.CaptureCard(RecordI, PlayerLeft, PlayerRight: byte);
+procedure TMusic.CaptureCard(RecordI: byte);
var
Error: integer;
ErrorMsg: string;
- Player: integer;
+ //Player: integer;
begin
if not BASS_RecordInit(RecordI) then begin
Error := BASS_ErrorGetCode;
@@ -873,16 +822,16 @@ begin
+ IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: '
+ ErrorMsg);}
Log.LogError('Error initializing record [' + IntToStr(RecordI) + ', '
- + IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: '
+ //+ IntToStr(PlayerLeft) + ', '+ IntToStr(PlayerRight) + ']: '
+ ErrorMsg);
Log.LogError('Music -> CaptureCard: Error initializing record: ' + ErrorMsg);
end else
begin
- Player := PlayerLeft + PlayerRight*256;
+ //Player := PlayerLeft + PlayerRight*256;
//SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, PlayerLeft + PlayerRight*256);
- Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, Pointer(Player));
+ Recording.SoundCard[RecordI].BassRecordStream := BASS_RecordStart(44100, 2, MakeLong(0, 20) , @GetMicrophone, Pointer(PlayerI[RecordI]));
{if SoundCard[RecordI].BassRecordStream = 0 then begin
Error := BASS_ErrorGetCode;
diff --git a/Game/Code/Classes/UParty.pas b/Game/Code/Classes/UParty.pas
index a416bb4c..c0fc9daf 100644
--- a/Game/Code/Classes/UParty.pas
+++ b/Game/Code/Classes/UParty.pas
@@ -132,7 +132,7 @@ begin
//Set cur Round to Round 1
CurRound := 255;
- Rand3 := true;
+ Rand3 := (Ini.NewPartySelectionMode=1);
//Set Rounds
NumMedleys := 0;
diff --git a/Game/Code/Classes/UPartyM2.pas b/Game/Code/Classes/UPartyM2.pas
index 8c572610..d776de96 100644
--- a/Game/Code/Classes/UPartyM2.pas
+++ b/Game/Code/Classes/UPartyM2.pas
@@ -310,7 +310,6 @@ begin
//build the playlist
SetLength (arr, 0);
SetLength (arr, NumRounds);
- Randomize;
for I := 0 to NumRounds - 1 do
begin
diff --git a/Game/Code/Classes/URecord.pas b/Game/Code/Classes/URecord.pas
index 03cf137e..ebb0f5b8 100644
--- a/Game/Code/Classes/URecord.pas
+++ b/Game/Code/Classes/URecord.pas
@@ -77,7 +77,7 @@ begin
S := L - n;
L := n;
end;
-
+
// copy to array
for A := L+1 to n do
BufferArray[A-L] := BufferArray[A];
@@ -214,9 +214,9 @@ var
P1: integer;
P2: integer;
Boost: byte;
+
begin
// Log.LogDebug('Record -> GetMicrophone: len='+inttstr(len));
-
// set boost
case Ini.MicBoost of
0: Boost := 1;
diff --git a/Game/Code/Classes/USongs.pas b/Game/Code/Classes/USongs.pas
index e669edf6..61473535 100644
--- a/Game/Code/Classes/USongs.pas
+++ b/Game/Code/Classes/USongs.pas
@@ -1,7 +1,7 @@
unit USongs;
interface
-uses SysUtils, ULog, UTexture, UCatCovers;
+uses SysUtils, ULog, SDL, UTexture, UCovers, UCatCovers, UMergeSort;
const
SONG_LOAD_COMPLETE = true;
@@ -90,16 +90,17 @@ type
TSongs = class
private
- BrowsePos: Cardinal; //Actual Pos in Song Array
+ BrowsePos: Cardinal; //Actual Pos in Song Array
public
Song: array of TSong; // array of songs
SongSort: array of TSong;
Selected: integer; // selected song index
NumFaultySongs: integer;
+
+ function FindSongFile(Dir, Mask: string): string;
procedure LoadSongList; // load all songs
procedure BrowseDir(Dir: string); // should return number of songs in the future
procedure Sort(Order: integer);
- function FindSongFile(Dir, Mask: string): string;
end;
TCatSongs = class
@@ -134,12 +135,93 @@ implementation
uses UFiles, UIni, StrUtils, Umusic, UGraphic;
+var
+ TempSongArr: array of TSong;
+ SongSort: array of TSong;
+ SortOrder: integer; // number used for ordernum
+
+function SortCompare(TempIndex, SourceIndex: integer): boolean; cdecl;
+begin
+ Result := false;
+
+ case SortOrder of
+ sEdition: // by edition
+ if CompareText(TempSongArr[TempIndex].Edition[0], Songs.SongSort[SourceIndex].Edition[0]) <= 0 then
+ Result := true;
+
+ sGenre: // by genre
+ if CompareText(TempSongArr[TempIndex].Genre[0], Songs.SongSort[SourceIndex].Genre[0]) <= 0 then
+ Result := true;
+
+ sTitle: // by title
+ if CompareText(TempSongArr[TempIndex].Title, Songs.SongSort[SourceIndex].Title) <= 0 then
+ Result := true;
+
+ sArtist: // by artist
+ if CompareText(TempSongArr[TempIndex].Artist, Songs.SongSort[SourceIndex].Artist) <= 0 then
+ Result := true;
+
+ sFolder: // by folder
+ if CompareText(TempSongArr[TempIndex].Folder, Songs.SongSort[SourceIndex].Folder) <= 0 then
+ Result := true;
+
+ sTitle2: // by title2
+ if CompareText(TempSongArr[TempIndex].Title, Songs.SongSort[SourceIndex].Title) <= 0 then
+ Result := true;
+
+ sArtist2: // by artist2
+ if CompareText(TempSongArr[TempIndex].Artist, Songs.SongSort[SourceIndex].Artist) <= 0 then
+ Result := true;
+
+ sLanguage: // by Language
+ if CompareText(TempSongArr[TempIndex].Language, Songs.SongSort[SourceIndex].Language) <= 0 then
+ Result := true;
+
+ sRandom:
+ if (Random(2) = 0) then
+ Result := true;
+ end; // case
+end;
+
+function SortCopy(iSourceIndex, iDestIndex: integer; bDirection: TDirection): boolean; cdecl;
+var
+ TempSong: TSong;
+
+begin
+ Result := true;
+ case bDirection of
+ dSourceSource:
+ begin
+ TempSong := Songs.SongSort[iSourceIndex];
+ Songs.SongSort[iDestIndex] := TempSong;
+ end;
+
+ dSourceTemp:
+ begin
+ TempSong := Songs.SongSort[iSourceIndex];
+ TempSongArr[iDestIndex] := TempSong;
+ end;
+
+ dTempTemp:
+ begin
+ TempSong := TempSongArr[iSourceIndex];
+ TempSongArr[iDestIndex] := TempSong;
+ end;
+
+ dTempSource:
+ begin
+ TempSong := TempSongArr[iSourceIndex];
+ Songs.SongSort[iDestIndex] := TempSong;
+ end;
+ end;
+end;
+
procedure TSongs.LoadSongList;
begin
Log.LogStatus('Initializing', 'LoadSongList');
// clear
- Setlength(Song, 50);
+ Setlength(Song, 100);
NumFaultySongs := 0;
BrowsePos := 0;
@@ -155,6 +237,7 @@ var
SR: TSearchRec; // for parsing Songs Directory
SLen: integer;
res: boolean;
+ Name: string;
begin
if FindFirst(Dir + '*', faDirectory, SR) = 0 then begin
@@ -183,7 +266,7 @@ begin
begin
SetLength(Czesci, 1);
AktSong := Song[SLen];
- res := LoadSong(Song[SLen].Path + Song[SLen].FileName, SONG_LOAD_NOTES); //TODO Hash?
+ res := LoadSong(Song[SLen].Path + Song[SLen].FileName, SONG_LOAD_NOTES);
if not CheckOK then
inc(NumFaultySongs);
@@ -200,18 +283,54 @@ begin
// scanning complete, file is good
// if there is no cover then try to find it
- if Song[SLen].Cover = '' then Song[SLen].Cover := FindSongFile(Dir, '*[CO].jpg');
+ if Song[SLen].Cover = '' then
+ begin
+ Song[SLen].Cover := FindSongFile(Dir, '*[CO].jpg');
+ if not FileExists(Song[SLen].Path + Song[SLen].Cover) then
+ Song[SLen].Cover := '';
+ end;
+
+ try
+ Song[SLen].CoverTex.TexNum := -1;
+ if (Song[SLen].Cover <> '') then
+ begin
+ Name := Song[SLen].Path + Song[SLen].Cover;
+ Texture.Limit := 512;
+ // cache texture if there is a need to this
+ if not Covers.CoverExists(Name) then
+ begin
+ Texture.CreateCacheMipmap := true;
+ Texture.GetTexture(Name, 'Plain', true); // preloads textures and creates cache mipmap
+ Texture.CreateCacheMipmap := false;
+
+ // puts this texture to the cache file
+ Covers.AddCover(Name);
+
+ // unload full size texture
+ Texture.UnloadTexture(Name, false);
+ end;
+
+ Song[SLen].CoverTex := Texture.GetTexture(Name, 'Plain', true);
+ Texture.Limit := 1024*1024;
+ end;
+ except
+ Song[SLen].CoverTex.TexNum := -1;
+ Texture.Limit := 1024*1024;
+ end;
Inc(BrowsePos);
end;
end;
- //Change Length Only every 50 Entrys
- if (BrowsePos mod 50 = 0) AND (BrowsePos <> 0) and res then
- SetLength(Song, Length(Song) + 50);
+ //Change Length Only every 100 Entrys
+ if (BrowsePos mod 100 = 0) AND (BrowsePos <> 0) and res then
+ SetLength(Song, Length(Song) + 100);
- if (BrowsePos mod 5 = 0) and res then
+ if (BrowsePos mod 100 = 0) and res then
+ begin
UpdateScreenLoading('Songs: '+IntToStr(BrowsePos));
+ SDL_Delay(1);
+ end;
until FindNext(SR) <> 0;
end; // if FindFirst
@@ -220,126 +339,26 @@ end;
procedure TSongs.Sort(Order: integer);
var
- S: integer;
- S2: integer;
- TempSong: TSong;
+ S: integer;
+ S2: integer;
+
+ I: integer;
+ //TempSong: TSong;
+ MergeSort: TMergeSorter;
+ //TempSongArr: array of TSong;
+
begin
- case Order of
- sEdition: // by edition
- begin
- for S2 := 0 to Length(SongSort)-1 do
- for S := 1 to Length(SongSort)-1 do
- if CompareText(SongSort[S].Edition[0], SongSort[S-1].Edition[0]) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongSort[S-1];
- SongSort[S-1] := SongSort[S];
- SongSort[S] := TempSong;
- end;
- end;
- sGenre: // by genre
- begin
- for S2 := 0 to Length(SongSort)-1 do
- for S := 1 to Length(SongSort)-1 do
- if CompareText(SongSort[S].Genre[0], SongSort[S-1].Genre[0]) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongSort[S-1];
- SongSort[S-1] := SongSort[S];
- SongSort[S] := TempSong;
- end;
- end;
- sTitle: // by title
- begin
- for S2 := 0 to Length(SongSort)-1 do
- for S := 1 to Length(SongSort)-1 do
- if CompareText(SongSort[S].Title, SongSort[S-1].Title) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongSort[S-1];
- SongSort[S-1] := SongSort[S];
- SongSort[S] := TempSong;
- end;
+ MergeSort := TMergeSorter.Create();
- end;
- sArtist: // by artist
- begin
- for S2 := 0 to Length(SongSort)-1 do
- for S := 1 to Length(SongSort)-1 do
- if CompareText(SongSort[S].Artist, SongSort[S-1].Artist) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongSort[S-1];
- SongSort[S-1] := SongSort[S];
- SongSort[S] := TempSong;
- end;
- end;
- sFolder: // by folder
- begin
- for S2 := 0 to Length(SongSort)-1 do
- for S := 1 to Length(SongSort)-1 do
- if CompareText(SongSort[S].Folder, SongSort[S-1].Folder) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongSort[S-1];
- SongSort[S-1] := SongSort[S];
- SongSort[S] := TempSong;
- end;
- end;
- sTitle2: // by title2
- begin
- for S2 := 0 to Length(SongSort)-1 do
- for S := 1 to Length(SongSort)-1 do
- if CompareText(SongSort[S].Title, SongSort[S-1].Title) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongSort[S-1];
- SongSort[S-1] := SongSort[S];
- SongSort[S] := TempSong;
- end;
+ SetLength(TempSongArr, 0);
+ SetLength(TempSongArr, (Length(SongSort)+1) div 2);
- end;
- sArtist2: // by artist2
- begin
- for S2 := 0 to Length(SongSort)-1 do
- for S := 1 to Length(SongSort)-1 do
- if CompareText(SongSort[S].Artist, SongSort[S-1].Artist) < 0 then
- begin
- // zamiana miejscami
- TempSong := SongSort[S-1];
- SongSort[S-1] := SongSort[S];
- SongSort[S] := TempSong;
- end;
- end;
- sLanguage: // by Language
- begin
- for S2 := 0 to Length(SongSort)-1 do
- for S := 1 to Length(SongSort)-1 do
- if CompareText(SongSort[S].Language, SongSort[S-1].Language) < 0 then
- begin
- TempSong := SongSort[S-1];
- SongSort[S-1] := SongSort[S];
- SongSort[S] := TempSong;
- end;
- end;
- sRandom:
- begin
- for S2 := 0 to Length(SongSort)-1 do
- begin
- for S := 1 to Length(SongSort)-1 do
- begin
- if (Random(2) = 0) then
- begin
- TempSong := SongSort[S-1];
- SongSort[S-1] := SongSort[S];
- SongSort[S] := TempSong;
- end;
- end;
- end;
- end;
+ SortOrder := Order;
+ MergeSort.Sort(Length(SongSort), @SortCompare, @SortCopy);
- end; // case
+ FreeAndNil(MergeSort);
+ SetLength(TempSongArr, 0);
end;
function TSongs.FindSongFile(Dir, Mask: string): string;
@@ -405,6 +424,7 @@ var
end;
end;
begin
+ Log.BenchmarkStart(3);
CatNumShow := -1;
SetLength(Songs.SongSort, 0);
@@ -438,7 +458,10 @@ begin
end;
end;
end;
+ Log.BenchmarkEnd(3);
+ Log.LogBenchmark('====> Workaround for Editions/Genres', 3);
+ Log.BenchmarkStart(3);
case Ini.Sorting of
sEdition: begin
Songs.Sort(sArtist);
@@ -463,8 +486,10 @@ begin
sRandom: Songs.Sort(sRandom);
end; // case
+ Log.BenchmarkEnd(3);
+ Log.LogBenchmark('====> Sort Songs', 3);
-
+ Log.BenchmarkStart(3);
Letter := ' ';
SS := '';
Order := 0;
@@ -715,10 +740,14 @@ begin
end;
CatSongs.Song[CatLen].Visible := true;
- end
+ end;
end;
CatLen := Length(CatSongs.Song);
+
+ if (CatLen>0) and CatSongs.Song[CatLen-1].Main then
+ CatSongs.Song[CatLen-1].CoverTex.TexNum := -1;
+
SetLength(CatSongs.Song, CatLen+1);
Inc (CatNumber); //Increase Number in Cat
@@ -740,6 +769,9 @@ begin
Song[CatLen - CatNumber].CatNumber := CatNumber;//Set CatNumber of Categroy
//CatCount Patch
CatCount := Order;
+
+ Log.BenchmarkEnd(3);
+ Log.LogBenchmark('====> Build Cat-Structure', 3);
end;
procedure TCatSongs.ShowCategory(Index: integer);
diff --git a/Game/Code/Classes/UTexture.pas b/Game/Code/Classes/UTexture.pas
index 1e5bd276..d7d3e690 100644
--- a/Game/Code/Classes/UTexture.pas
+++ b/Game/Code/Classes/UTexture.pas
@@ -119,7 +119,7 @@ uses ULog, DateUtils, UCovers;
function TTextureUnit.GetTexture(Name, Typ: string): TTexture;
begin
- Result := GetTexture(Name, Typ, true);
+ Result := GetTexture(Name, Typ, false);
end;
function TTextureUnit.GetTexture(Name, Typ: string; FromCache: boolean): TTexture;
@@ -144,9 +144,11 @@ begin
end;
// use preloaded texture
- if (not FromCache) or (FromCache and not Covers.CoverExists(Name)) then begin
+ if (not FromCache) or (FromCache and not Covers.CoverExists(Name)) then
+ begin
// use full texture
- if TextureDatabase.Texture[T].Texture.TexNum = -1 then begin
+ if TextureDatabase.Texture[T].Texture.TexNum = -1 then
+ begin
// load texture
TextureDatabase.Texture[T].Texture := LoadTexture(false, pchar(Name), 'JPG', pchar(Typ), $0);
end;
@@ -156,19 +158,15 @@ begin
end;
- if FromCache and Covers.CoverExists(Name) then begin
+ if FromCache and Covers.CoverExists(Name) then
+ begin
// use cache texture
C := Covers.CoverNumber(Name);
- if TextureDatabase.Texture[T].TextureCache.TexNum = -1 then begin
+ if TextureDatabase.Texture[T].TextureCache.TexNum = -1 then
+ begin
// load texture
Covers.PrepareData(Name);
-{ Covers.Data[0] := 0;
- Covers.Data[1] := 0;
- Covers.Data[2] := 0;
- Covers.Data[3] := 255;
- Covers.Data[4] := 255;
- Covers.Data[5] := 255;}
TextureDatabase.Texture[T].TextureCache := CreateTexture(Covers.Data, Name, Covers.Cover[C].W, Covers.Cover[C].H, 24);
end;
diff --git a/Game/Code/Classes/UThemes.pas b/Game/Code/Classes/UThemes.pas
index 52893dc6..25cec01b 100644
--- a/Game/Code/Classes/UThemes.pas
+++ b/Game/Code/Classes/UThemes.pas
@@ -443,31 +443,29 @@ type
StaticMedleyNav: TThemeStatic;
TextMedleyNav: TThemeText;
- PlayerStatic: array[1..10] of AThemeStatic;
- PlayerTexts: array[1..10] of AThemeText;
-
- TextName: array[1..10] of TThemeText;
- TextScore: array[1..10] of TThemeText;
-
- TextNotes: array[1..10] of TThemeText;
- TextNotesScore: array[1..10] of TThemeText;
- TextLineBonus: array[1..10] of TThemeText;
- TextLineBonusScore: array[1..10] of TThemeText;
- TextGoldenNotes: array[1..10] of TThemeText;
- TextGoldenNotesScore: array[1..10] of TThemeText;
- TextTotal: array[1..10] of TThemeText;
- TextTotalScore: array[1..10] of TThemeText;
-
- StaticBoxLightest: array[1..10] of TThemeStatic;
- StaticBoxLight: array[1..10] of TThemeStatic;
- StaticBoxDark: array[1..10] of TThemeStatic;
-
- StaticBackLevel: array[1..10] of TThemeStatic;
- StaticBackLevelRound: array[1..10] of TThemeStatic;
- StaticLevel: array[1..10] of TThemeStatic;
- StaticLevelRound: array[1..10] of TThemeStatic;
-
-// Description: array[0..5] of string;}
+ PlayerStatic: array[1..16] of AThemeStatic;
+ PlayerTexts: array[1..16] of AThemeText;
+
+ TextName: array[1..16] of TThemeText;
+ TextScore: array[1..16] of TThemeText;
+
+ TextNotes: array[1..16] of TThemeText;
+ TextNotesScore: array[1..16] of TThemeText;
+ TextLineBonus: array[1..16] of TThemeText;
+ TextLineBonusScore: array[1..16] of TThemeText;
+ TextGoldenNotes: array[1..16] of TThemeText;
+ TextGoldenNotesScore: array[1..16] of TThemeText;
+ TextTotal: array[1..16] of TThemeText;
+ TextTotalScore: array[1..16] of TThemeText;
+
+ StaticBoxLightest: array[1..16] of TThemeStatic;
+ StaticBoxLight: array[1..16] of TThemeStatic;
+ StaticBoxDark: array[1..16] of TThemeStatic;
+
+ StaticBackLevel: array[1..16] of TThemeStatic;
+ StaticBackLevelRound: array[1..16] of TThemeStatic;
+ StaticLevel: array[1..16] of TThemeStatic;
+ StaticLevelRound: array[1..16] of TThemeStatic;
end;
TThemeTop = class(TThemeBasic)
@@ -547,6 +545,11 @@ type
SelectSlideInput: TThemeSelectSlide;
SelectSlideChannelL: TThemeSelectSlide;
SelectSlideChannelR: TThemeSelectSlide;
+
+ SelectSlideWebCamOnOff: TThemeSelectSlide;
+ SelectSlideWebCamDevice: TThemeSelectSlide;
+ SelectSlideWebCamMedia: TThemeSelectSlide;
+
ButtonExit: TThemeButton;
end;
@@ -916,6 +919,7 @@ type
function ColorExists(Name: string): integer;
procedure LoadColor(var R, G, B: real; ColorName: string);
+function GetPlayerColor(Player: integer): TRGB;
function GetSystemColor(Color: integer): TRGB;
function ColorSqrt(RGB: TRGB): TRGB;
@@ -1251,11 +1255,11 @@ begin
ThemeLoadStatic(Sing.StaticP5Singbar, 'SingP2MSingBar');
ThemeLoadStatic(Sing.StaticP6Singbar, 'SingP3SingBar');
- Sing.OFF_P1 := -20;
- Sing.OFF_P2 := -180;
+ Sing.OFF_P1 := -30;
+ Sing.OFF_P2 := -205;
Sing.OFF_P3 := -380;
- Sing.OFF_P4 := 380;
- Sing.OFF_P5 := 180;
+ Sing.OFF_P4 := 370;
+ Sing.OFF_P5 := 195;
Sing.OFF_P6 := 20;
{Sing.StaticP3FourPSingbar.X := Sing.StaticP3FourPSingbar.X +
@@ -1396,7 +1400,7 @@ begin
ThemeLoadStatic(Score.StaticMedleyNav, 'ScoreMedleyNavStatic');
ThemeLoadText(Score.TextMedleyNav, 'ScoreMedleyNavText');
- for I := 1 to 10 do
+ for I := 1 to 16 do
begin
ThemeLoadStatics(Score.PlayerStatic[I], 'ScorePlayer' + IntToStr(I) + 'Static');
ThemeLoadTexts(Score.PlayerTexts[I], 'ScorePlayer' + IntToStr(I) + 'Text');
@@ -1519,6 +1523,11 @@ begin
ThemeLoadSelectSlide(OptionsRecord.SelectSlideInput, 'OptionsRecordSelectSlideInput');
ThemeLoadSelectSlide(OptionsRecord.SelectSlideChannelL, 'OptionsRecordSelectSlideChannelL');
ThemeLoadSelectSlide(OptionsRecord.SelectSlideChannelR, 'OptionsRecordSelectSlideChannelR');
+
+ ThemeLoadSelectSlide(OptionsRecord.SelectSlideWebCamOnOff, 'OptionsRecordSelectSlideWebCamOnOff');
+ ThemeLoadSelectSlide(OptionsRecord.SelectSlideWebCamDevice, 'OptionsRecordSelectSlideWebCamDevice');
+ ThemeLoadSelectSlide(OptionsRecord.SelectSlideWebCamMedia, 'OptionsRecordSelectSlideWebCamMedia');
+
ThemeLoadButton(OptionsRecord.ButtonExit, 'OptionsRecordButtonExit');
//Options Advanced
@@ -2201,7 +2210,7 @@ begin
// P1
C := C+1;
Color[C].Name := 'P1Dark';
- Color[C].RGB := GetSystemColor(0); // 0 - blue
+ Color[C].RGB := GetPlayerColor(1); // 0 - blue
C := C+1;
Color[C].Name := 'P1Light';
@@ -2214,7 +2223,7 @@ begin
// P2
C := C+1;
Color[C].Name := 'P2Dark';
- Color[C].RGB := GetSystemColor(3); // 3 - red
+ Color[C].RGB := GetPlayerColor(2); // 3 - red
C := C+1;
Color[C].Name := 'P2Light';
@@ -2227,7 +2236,7 @@ begin
// P3
C := C+1;
Color[C].Name := 'P3Dark';
- Color[C].RGB := GetSystemColor(1); // 1 - green
+ Color[C].RGB := GetPlayerColor(3); // 1 - green
C := C+1;
Color[C].Name := 'P3Light';
@@ -2240,7 +2249,7 @@ begin
// P4
C := C+1;
Color[C].Name := 'P4Dark';
- Color[C].RGB := GetSystemColor(4); // 4 - brown
+ Color[C].RGB := GetPlayerColor(4); // 4 - violet
C := C+1;
Color[C].Name := 'P4Light';
@@ -2253,7 +2262,7 @@ begin
// P5
C := C+1;
Color[C].Name := 'P5Dark';
- Color[C].RGB := GetSystemColor(5); // 5 - yellow
+ Color[C].RGB := GetPlayerColor(5); // 5 - yellow
C := C+1;
Color[C].Name := 'P5Light';
@@ -2266,7 +2275,7 @@ begin
// P6
C := C+1;
Color[C].Name := 'P6Dark';
- Color[C].RGB := GetSystemColor(6); // 6 - violet
+ Color[C].RGB := GetPlayerColor(6); // 6 - brown
C := C+1;
Color[C].Name := 'P6Light';
@@ -2301,6 +2310,42 @@ begin
end;
end;
+function GetPlayerColor(Player: integer): TRGB;
+begin
+ case Player of
+ 1: begin // - blue
+ Result.R := 1/255;
+ Result.G := 1/255;
+ Result.B := 205/255;
+ end;
+ 2: begin // - red
+ Result.R := 205/255;
+ Result.G := 1/255;
+ Result.B := 1/255;
+ end;
+ 3: begin // - green
+ Result.R := 1/255;
+ Result.G := 205/255;
+ Result.B := 1/255;
+ end;
+ 4: begin // - violet
+ Result.R := 205/255;
+ Result.G := 1/255;
+ Result.B := 205/255;
+ end;
+ 5: begin // - yellow
+ Result.R := 200/255;
+ Result.G := 200/255;
+ Result.B := 1/255;
+ end;
+ 6: begin // - brown
+ Result.R := 204/255;
+ Result.G := 102/255;
+ Result.B := 1/255;
+ end;
+ end;
+end;
+
function GetSystemColor(Color: integer): TRGB;
begin
case Color of
diff --git a/Game/Code/Classes/UVideo.pas b/Game/Code/Classes/UVideo.pas
index 6f646093..2eaa72bd 100644
--- a/Game/Code/Classes/UVideo.pas
+++ b/Game/Code/Classes/UVideo.pas
@@ -35,7 +35,8 @@ uses SDL,
{$endif}
{$ENDIF}
UIni,
- UTime;
+ UTime,
+ windows;
type
TAspectCorrection = (acoStretch, acoCrop, acoLetterBox); //from 1.1
@@ -50,20 +51,36 @@ type
ZoomFaktor: real;
end;
+ TFrameThread = class(TThread)
+ private
+ Time: Extended;
+ Gap: Single;
+ Start: Single;
+
+ iSkip: Boolean;
+ iDecode: Boolean;
+
+ procedure DoDecode;
+ procedure DoSkip;
+ protected
+ constructor Create;
+ procedure Execute; override;
+ procedure Update();
+ end;
+
procedure Init;
procedure acOpenFile(FileName: pAnsiChar);
procedure acClose;
procedure acGetFrame(Time: Extended);
-function acSearch(Time: Extended): integer;
-procedure acDrawGL(Screen: integer);
-procedure acDrawGLi(Screen: integer; Window: TRectCoords; Blend: real);
+procedure acDrawGL(Screen: integer; DoDraw: boolean);
+procedure acDrawGLi(Screen: integer; Window: TRectCoords; Blend: real; DoDraw: boolean);
procedure acTogglePause;
-procedure acSkip(Gap: Single; Start: Single);
procedure acSkip2(Gap: Single; Start: Single);
procedure ToggleAspectCorrection;
procedure GetVideoRect(var ScreenRect, TexRect: TRectCoords; Window: TRectCoords);
procedure SetAspectCorrection(aspect: TAspectCorrection);
procedure ResetAspectCorrection;
+procedure UploadNewFrame;
Const
MIN_FPS = 40;
@@ -118,6 +135,15 @@ var
EnableVideoDraw: boolean;
+ FrameData: Pointer;
+ NewFrame: boolean;
+ SetTime: Extended;
+ SetGap: Single;
+ SetStart: Single;
+ SetSkip: boolean;
+
+ FrameThread: TFrameThread;
+
implementation
@@ -133,7 +159,7 @@ end;
function seek_proc(sender: Pointer; pos: int64; whence: integer): int64; cdecl;
begin
- result := fs.Seek(pos, TSeekOrigin(whence))
+ result := fs.Seek(pos, TSeekOrigin(whence));
end;
procedure Init;
@@ -161,6 +187,16 @@ begin
PIXEL_FORMAT := GL_RGBA;
EnableVideoDraw := true;
+
+ SetTime := 0;
+ if(FrameData<>nil) then
+ FreeMem(FrameData);
+ FrameData := nil;
+
+ if (FrameThread<>nil) then
+ begin
+ FrameThread.Terminate;
+ end;
end;
procedure acOpenFile(FileName: pAnsiChar);
@@ -168,6 +204,7 @@ var
I: integer;
begin
+ acClose;
VideoPaused := False;
VideoTimeBase := 0;
@@ -175,7 +212,6 @@ begin
LastFrameTime := 0;
TimeDifference := 0;
Counter := 0;
- acClose;
if not FileExists(FileName) then
Exit; //TODO: error.log
@@ -234,6 +270,8 @@ begin
dataX := Round(Power(2, Ceil(Log2(TexX))));
dataY := Round(Power(2, Ceil(Log2(TexY))));
+ GetMem(FrameData, numBytes*TexX*TexY);
+
// calculate some information for video display
VideoAspect:=videodecoder^.stream_info.additional_info.video_info.pixel_aspect;
if (VideoAspect = 0) then
@@ -268,11 +306,27 @@ begin
end;
mmfps := (MAX_FPS-MIN_FPS)/2;
+
+ SetTime := 0;
+ NewFrame := false;
+ SetSkip := false;
+ FrameThread := TFrameThread.Create();
end;
procedure acClose;
begin
- if VideoOpened then begin
+ if VideoOpened then
+ begin
+ if (FrameThread<>nil) then
+ begin
+ FrameThread.Terminate;
+ FrameThread.WaitFor;
+ FrameThread.Free;
+ FrameThread := nil;
+ end;
+
+ NewFrame := false;
+ SetSkip := false;
if videodecoder <> nil then
ac_free_decoder(videodecoder);
@@ -286,6 +340,12 @@ begin
VideoOpened:=False;
fName := '';
+
+ if(FrameData<>nil) then
+ FreeMem(FrameData);
+ FrameData := nil;
+
+
end;
end;
@@ -297,117 +357,20 @@ end;
procedure acSkip2(Gap: Single; Start: Single);
begin
- VideoSkiptime:=Gap;
- NegativeSkipTime:=Start+Gap;
- if Start+Gap > 0 then
- begin
- VideoTime:=Start+Gap;
- try
- ac_seek(videodecoder, -1, Floor((Start+Gap)*1000));
- except
- Log.LogError('Error seeking Video "acSkip2" on video ('+fName+')');
- acClose;
- end;
- end else
- begin
- try
- ac_seek(videodecoder, 0, 0);
- except
- Log.LogError('Error seeking Video "acSkip2" on video ('+fName+')');
- acClose;
- end;
- VideoTime:=0;
- end;
+ SetGap := Gap;
+ SetStart := Start;
+ SetSkip := true;
end;
-procedure acSkip(Gap: Single; Start: Single);
-begin
- VideoSkiptime:=Gap;
- NegativeSkipTime:=Start+Gap;
- if Start+Gap > 0 then
- begin
- VideoTime:=0;
- ac_seek(videodecoder, -1, Floor((Start+Gap)*1000));
- if (acSearch(Gap+Start)=0) then
- begin
- ac_seek(videodecoder, 0, 0);
- VideoTime:=0;
- acSearch(Gap+Start);
- end;
- end else
- begin
- ac_seek(videodecoder, 0, 0);
- VideoTime:=0;
- end;
-end;
-
-function acSearch(Time: Extended): integer;
-var
- FrameFinished: Integer;
- errnum: Integer;
- FrameDataPtr: PByteArray;
- myTime: Extended;
-
+procedure acGetFrame(Time: Extended);
begin
- Result := 0;
- if not VideoOpened then Exit;
- if (NegativeSkipTime < 0)and(Time+NegativeSkipTime>=0) then
- NegativeSkipTime:=0;
-
- myTime:=Time+VideoSkipTime;
- TimeDifference:=myTime-VideoTime;
-
- if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then begin
- Exit;// we don't need a new frame now
- end;
-
- pack := ac_read_package(inst);
- FrameFinished:=0;
- // read packets until we have a finished frame (or there are no more packets)
- while ((VideoTime < Time-VideoTimeBase)) and (pack <> nil) do
- begin
- // if we got a packet from the video stream, then decode it
- if (videodecoder^.stream_index = pack^.stream_index) then
- begin
- FrameFinished := ac_decode_package(pack, videodecoder);
- VideoTime := videodecoder^.timecode;
- ac_free_package(pack);
- if ((VideoTime < Time-VideoTimeBase)) then
- pack := ac_read_package(inst);
- end else
- begin
- ac_free_package(pack);
- pack := ac_read_package(inst);
- end;
- end;
- if (pack<>nil) then
- ac_free_package(pack);
-
- // if we did not get an new frame, there's nothing more to do
- if Framefinished=0 then
- begin
- Exit;
- end;
-
- errnum:=1; //TODO!!
- if errnum >=0 then begin
- FrameDataPtr:=Pointer(videodecoder^.buffer);
- Result := 1;
- glBindTexture(GL_TEXTURE_2D, VideoTex);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY, PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[0]);
-
- if Ini.Debug = 1 then
- begin
- //frame decode debug display
- GoldenRec.Spawn(200,85,1,16,0,-1,ColoredStar,$ffff00,0);
- end;
-
- end;
+ SetTime := Time;
end;
-procedure acGetFrame(Time: Extended);
+procedure TFrameThread.DoDecode;
Const
MAX = 3000;
+ FRAMEDROPCOUNT=3;
var
FrameFinished: Integer;
@@ -417,16 +380,8 @@ var
myTime: Extended;
DropFrame: Boolean;
droppedFrames: Integer;
- I: Integer;
- glError: glEnum;
- glErrorStr: String;
-const
- FRAMEDROPCOUNT=3;
begin
- if not VideoOpened then Exit;
- if VideoPaused then Exit;
-
mmfps := (Display.mFPS+mmfps)/2;
if(Ini.PerformanceMode=1) then
begin
@@ -461,38 +416,27 @@ begin
myTime:=Time+VideoSkipTime;
TimeDifference:=myTime-VideoTime;
- if Ini.Debug = 1 then
- begin
- timediff_str:= 't-diff: ' + FormatFloat('#0.00', TimeDifference);
- mtime_str:= 'mytime: ' + FormatFloat('#0.00', myTime);
- end;
-
DropFrame:=False;
- if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then begin
- if Ini.Debug = 1 then
- begin
- // frame delay debug display
- GoldenRec.Spawn(200,65,1,16,0,-1,ColoredStar,$00ff00,0);
- end;
- Exit;// we don't need a new frame now
- end;
-
- if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then begin // skip frames
- if Ini.Debug = 1 then
- begin
- //frame drop debug display
- GoldenRec.Spawn(200,105,1,16,0,-1,ColoredStar,$ff0000,0);
- end;
+ if (VideoTime <> 0) and (TimeDifference <= VideoTimeBase) then
+ Exit;
+ if TimeDifference >= (FRAMEDROPCOUNT-1)*VideoTimeBase then
+ begin // skip frames
DropFrame:=True;
end;
+ if terminated then
+ Exit;
+
pack := ac_read_package(inst);
FrameFinished:=0;
// read packets until we have a finished frame (or there are no more packets)
while (FrameFinished=0) and (pack <> nil) do
begin
+ if terminated then
+ Exit;
+
// if we got a packet from the video stream, then decode it
if (videodecoder^.stream_index = pack^.stream_index) then
begin
@@ -513,11 +457,16 @@ begin
//acSearch(Time);
for droppedFrames:=1 to FRAMEDROPCOUNT do
begin
+ if terminated then
+ Exit;
pack := ac_read_package(inst);
FrameFinished:=0;
// read packets until we have a finished frame (or there are no more packets)
while (FrameFinished=0) and (pack <> nil) do
begin
+ if terminated then
+ Exit;
+
// if we got a packet from the video stream, then decode it
if (videodecoder^.stream_index = pack^.stream_index) then
begin
@@ -537,105 +486,93 @@ begin
// if we did not get an new frame, there's nothing more to do
if Framefinished=0 then
begin
-// GoldenRec.Spawn(220,15,1,16,0,-1,ColoredStar,$0000ff);
- acClose;
+ //acClose;
Exit;
end;
errnum:=1; //TODO!!
if errnum >=0 then
begin
- if(not pbo_supported) then
- begin
- FrameDataPtr:=Pointer(videodecoder^.buffer);
+ FrameDataPtr := FrameData;
+ FrameDataPtr2:=Pointer(videodecoder^.buffer);
- glBindTexture(GL_TEXTURE_2D, VideoTex);
+ if terminated then
+ Exit;
- if(SkipLines>0)then
- begin
- for I := 0 to TexY - 1 do
- begin
- if(I mod (SkipLines+1) = 0) then
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, (I div (SkipLines+1)), TexX, 1,
- PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[I*numBytes*TexX]);
- end;
- end else
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY,
- PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[0]);
- end else
- begin
- glGetError();
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
+ move(FrameDataPtr2[0], FrameDataPtr[0], numBytes*TexX*TexY);
- glError := glGetError;
- if glError <> GL_NO_ERROR then
- begin
- acClose;
- Log.LogError('Error drawing Video "glBindBuffer"');
- Exit;
- end;
+ VideoTime := videodecoder^.timecode;
+ NewFrame := true;
+ end;
+end;
- FrameDataPtr := glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
- glError := glGetError;
- if glError <> GL_NO_ERROR then
- begin
- acClose;
- Log.LogError('Error drawing Video pbo "glMapBuffer"');
- Exit;
- end;
+procedure TFrameThread.DoSkip;
+begin
+ VideoSkiptime:=Gap;
+ NegativeSkipTime:=Start+Gap;
+ if Start+Gap > 0 then
+ begin
+ VideoTime:=Start+Gap;
+ try
+ ac_seek(videodecoder, -1, Floor((Start+Gap)*1000));
+ except
+ Log.LogError('Error seeking Video "acSkip2" on video ('+fName+')');
+ //acClose;
+ end;
+ end else
+ begin
+ try
+ ac_seek(videodecoder, 0, 0);
+ except
+ Log.LogError('Error seeking Video "acSkip2" on video ('+fName+')');
+ //acClose;
+ end;
+ VideoTime:=0;
+ end;
+end;
- FrameDataPtr2:=Pointer(videodecoder^.buffer);
- move(FrameDataPtr2[0], FrameDataPtr[0], numBytes*TexX*TexY);
+constructor TFrameThread.Create;
+begin
+ inherited Create(true);
- glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
- glError := glGetError;
- if glError <> GL_NO_ERROR then
- begin
- acClose;
- Log.LogError('Error drawing Video pbo "glUnmapBuffer"');
- Exit;
- end;
+ Self.Priority := tpLower;
+ Self.FreeOnTerminate := false;
- glBindTexture(GL_TEXTURE_2D, VideoTex);
- glError := glGetError;
- if glError <> GL_NO_ERROR then
- begin
- acClose;
- Log.LogError('Error drawing Video pbo "glBindTexture"');
- Exit;
- end;
+ Time := 0;
+ iDecode := false;
+ iSkip := false;
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY,
- PIXEL_FORMAT, GL_UNSIGNED_BYTE, nil);
+ Self.Resume;
+end;
- glError := glGetError;
- if glError <> GL_NO_ERROR then
- begin
- acClose;
- case glError of
- GL_INVALID_ENUM: glErrorStr:='INVALID_ENUM';
- GL_INVALID_VALUE: glErrorStr:='INVALID_VALUE';
- GL_INVALID_OPERATION: glErrorStr:='INVALID_OPERATION';
- GL_STACK_OVERFLOW: glErrorStr:='STACK_OVERFLOW';
- GL_STACK_UNDERFLOW: glErrorStr:='STACK_UNDERFLOW';
- GL_OUT_OF_MEMORY: glErrorStr:='OUT_OF_MEMORY';
- else glErrorStr:='unknown error';
- end;
- Log.LogError('Error drawing Video pbo "glTexSubImage2D" ('+glErrorStr+')');
- Exit;
- end;
- glBindTexture(GL_TEXTURE_2D, 0);
- glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
- end;
- VideoTime := videodecoder^.timecode;
+procedure TFrameThread.Execute;
+begin
+ while not terminated do
+ begin
+ try
+ if iSkip then
+ DoSkip;
- if Ini.Debug = 1 then
- begin
- //frame decode debug display
- GoldenRec.Spawn(200,85,1,16,0,-1,ColoredStar,$ffff00,0);
- end;
+ if iDecode then
+ DoDecode();
+
+ if not terminated then
+ Update();
+ except
+
+ end;
+ Sleep(0);
+ end;
+end;
- end;
+procedure TFrameThread.Update;
+begin
+ Time := SetTime;
+ iDecode := VideoOpened and not VideoPaused and not NewFrame;
+ iSkip := SetSkip;
+ SetSkip := false;
+ Gap := SetGap;
+ Start := SetStart;
end;
procedure ToggleAspectCorrection();
@@ -756,7 +693,7 @@ begin
TexRect.Lower := TexY/ dataY;
end;
-procedure acDrawGL(Screen: integer);
+procedure acDrawGL(Screen: integer; DoDraw: boolean);
var
Window: TRectCoords;
begin
@@ -767,14 +704,120 @@ begin
Window.windowed := false;
Window.Reflection := false;
Window.TargetAspect := fAspectCorrection;
- acDrawGLi(Screen, Window, 1);
+ acDrawGLi(Screen, Window, 1, DoDraw);
+end;
+
+procedure UploadNewFrame;
+var
+ FrameDataPtr: PByteArray;
+ FrameDataPtr2: PByteArray;
+ I: Integer;
+ glError: glEnum;
+ glErrorStr: String;
+
+begin
+ if VideoOpened and NewFrame then
+ begin
+ if(not pbo_supported) then
+ begin
+ FrameDataPtr:=FrameData;
+
+ glBindTexture(GL_TEXTURE_2D, VideoTex);
+
+ if(SkipLines>0)then
+ begin
+ for I := 0 to TexY - 1 do
+ begin
+ if(I mod (SkipLines+1) = 0) then
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, (I div (SkipLines+1)), TexX, 1,
+ PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[I*numBytes*TexX]);
+ end;
+ end else
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY,
+ PIXEL_FORMAT, GL_UNSIGNED_BYTE, @FrameDataPtr[0]);
+ end else
+ begin
+ glGetError();
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
+
+ glError := glGetError;
+ if glError <> GL_NO_ERROR then
+ begin
+ acClose;
+ Log.LogError('Error drawing Video "glBindBuffer"');
+ Exit;
+ end;
+
+ FrameDataPtr := glMapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY);
+ glError := glGetError;
+ if glError <> GL_NO_ERROR then
+ begin
+ acClose;
+ Log.LogError('Error drawing Video pbo "glMapBuffer"');
+ Exit;
+ end;
+
+ FrameDataPtr2:=FrameData;
+ move(FrameDataPtr2[0], FrameDataPtr[0], numBytes*TexX*TexY);
+
+ glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB);
+ glError := glGetError;
+ if glError <> GL_NO_ERROR then
+ begin
+ acClose;
+ Log.LogError('Error drawing Video pbo "glUnmapBuffer"');
+ Exit;
+ end;
+
+ glBindTexture(GL_TEXTURE_2D, VideoTex);
+ glError := glGetError;
+ if glError <> GL_NO_ERROR then
+ begin
+ acClose;
+ Log.LogError('Error drawing Video pbo "glBindTexture"');
+ Exit;
+ end;
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TexX, TexY,
+ PIXEL_FORMAT, GL_UNSIGNED_BYTE, nil);
+
+ glError := glGetError;
+ if glError <> GL_NO_ERROR then
+ begin
+ acClose;
+ case glError of
+ GL_INVALID_ENUM: glErrorStr:='INVALID_ENUM';
+ GL_INVALID_VALUE: glErrorStr:='INVALID_VALUE';
+ GL_INVALID_OPERATION: glErrorStr:='INVALID_OPERATION';
+ GL_STACK_OVERFLOW: glErrorStr:='STACK_OVERFLOW';
+ GL_STACK_UNDERFLOW: glErrorStr:='STACK_UNDERFLOW';
+ GL_OUT_OF_MEMORY: glErrorStr:='OUT_OF_MEMORY';
+ else glErrorStr:='unknown error';
+ end;
+ Log.LogError('Error drawing Video pbo "glTexSubImage2D" ('+glErrorStr+')');
+ Exit;
+ end;
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ end;
+
+ NewFrame := false;
+ end;
end;
-procedure acDrawGLi(Screen: integer; Window: TRectCoords; Blend: real);
+procedure acDrawGLi(Screen: integer; Window: TRectCoords; Blend: real; DoDraw: boolean);
var
ScreenRect, TexRect: TRectCoords;
begin
+ if DoDraw then
+ UploadNewFrame
+ else
+ begin
+ NewFrame := false;
+ Exit;
+ end;
+
// have a nice black background to draw on (even if there were errors opening the vid)
if Not Window.windowed then
begin
diff --git a/Game/Code/Classes/UWebCam.pas b/Game/Code/Classes/UWebCam.pas
new file mode 100644
index 00000000..a0ba38f0
--- /dev/null
+++ b/Game/Code/Classes/UWebCam.pas
@@ -0,0 +1,253 @@
+unit UWebCam;
+
+interface
+
+uses
+ math,
+ gl,
+ glu,
+ glext,
+ SysUtils,
+ UIni,
+ UTime,
+ SDL,
+ UCaptureWDM;
+
+function wStartWebCam: boolean;
+procedure wStopWebCam;
+
+procedure wInit;
+procedure wClose;
+procedure wDraw(DoDraw: boolean);
+
+
+var
+ WebCamReady: boolean;
+ FGrabFrameFlag : boolean;
+
+ FTex: glUint;
+ FTexX, FTexY: integer;
+ FdataX, FdataY: integer;
+ FrameDataPtr: PByteArray;
+
+ frame: Pointer;
+
+ WDMSample: TSampleClass;
+
+implementation
+
+uses
+ UGraphic,
+ ULog,
+ UDisplay;
+
+function wStartWebCam(): boolean;
+begin
+ if not WebCamReady then
+ wInit();
+
+ Result := WebCamReady;
+ if WebCamReady and not FGrabFrameFlag then
+ begin
+ glBindTexture(GL_TEXTURE_2D, FTex);
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, FTexX, FTexY,
+ GL_BGR, GL_UNSIGNED_BYTE, @FrameDataPtr[0]);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ FGrabFrameFlag := true;
+
+ WDMSample.Start;
+ end;
+end;
+
+procedure wStopWebCam();
+begin
+ if WebCamReady and FGrabFrameFlag then
+ begin
+ FGrabFrameFlag := false;
+ WDMSample.Stop;
+ end;
+end;
+
+procedure wInit;
+const
+ width = 320;
+ height = 240;
+
+begin
+ if WebCamReady then
+ exit;
+
+ WebCamReady := false;
+
+ if(Ini.EnableWebCam=0) then
+ exit;
+
+ if (Length(GetCapDevices())-1 < Ini.WebCamID) then
+ Exit;
+
+ try
+ WDMSample := TSampleClass.Create(Ini.WebCamID, Ini.WebCamMediaID);
+ except
+ wClose;
+ Log.LogError('Error init WDM (UWebCam.wInitWDM)');
+ Exit;
+ end;
+
+ FTexX := width;
+ FTexY := height;
+ FdataX := Round(Power(2, Ceil(Log2(FTexX))));
+ FdataY := Round(Power(2, Ceil(Log2(FTexY))));
+
+ FrameDataPtr:=WDMSample.FramePtr;
+
+ glGenTextures(1, @FTex);
+ glBindTexture(GL_TEXTURE_2D, FTex);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, 3, FdataX, FdataY, 0,
+ GL_BGR, GL_UNSIGNED_BYTE, nil);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ FGrabFrameFlag := false;
+ WebCamReady := true;
+end;
+
+procedure UploadNewFrame;
+begin
+ if (not WDMSample.CapStatus) then
+ exit;
+
+ FrameDataPtr := WDMSample.FramePtr;
+
+ if (FTexX<>WDMSample.GetWidth) or (FTexY<>WDMSample.GetHeight) then
+ begin
+ FTexX := WDMSample.GetWidth;
+ FTexY := WDMSample.GetHeight;
+ FdataX := Round(Power(2, Ceil(Log2(FTexX))));
+ FdataY := Round(Power(2, Ceil(Log2(FTexY))));
+
+ glGenTextures(1, @FTex);
+ glBindTexture(GL_TEXTURE_2D, FTex);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1.0);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, 3, FdataX, FdataY, 0,
+ GL_BGR, GL_UNSIGNED_BYTE, nil);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ end;
+
+ glBindTexture(GL_TEXTURE_2D, FTex);
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, FTexX, FTexY,
+ GL_BGR, GL_UNSIGNED_BYTE, @FrameDataPtr[0]);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ WDMSample.TriggerCapture;
+end;
+
+
+procedure wDraw(DoDraw: boolean);
+var
+ SRect: record
+ left, right, upper, lower: double;
+ end;
+
+ ScreenAspect: double;
+ CamAspect: double;
+ ScaledVideoWidth: double;
+ ScaledVideoHeight: double;
+
+begin
+ if not WebCamReady then
+ exit;
+
+ if DoDraw then
+ begin
+ try
+ UploadNewFrame;
+ except
+ wClose;
+ Log.LogError('Error Uploading new Frame (UWebCam.wDraw)');
+ Exit;
+ end;
+ end else
+ Exit;
+
+ ScreenAspect := (ScreenW/Screens) / ScreenH;
+ CamAspect := FTexX/FTexY;
+ if (ScreenAspect >= 1) then
+ begin
+ ScaledVideoWidth := RenderW;
+ ScaledVideoHeight := RenderH * ScreenAspect/CamAspect;
+ end else
+ begin
+ ScaledVideoHeight := RenderH;
+ ScaledVideoWidth := RenderW * CamAspect/ScreenAspect;
+ end;
+
+ SRect.left := (RenderW - ScaledVideoWidth) / 2;
+ SRect.right := SRect.left + ScaledVideoWidth;
+ SRect.lower := (RenderH - ScaledVideoHeight) / 2;
+ SRect.upper := SRect.lower + ScaledVideoHeight;
+
+ // have a nice black background to draw on (even if there were errors opening the vid)
+ glClearColor(0,0,0,1);
+ glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+
+ glColor4f(1, 1, 1, 1);
+ glBindTexture(GL_TEXTURE_2D, FTex);
+ glbegin(gl_quads);
+ // upper-left coord
+ glTexCoord2f(FTexX/FdataX, 0);
+ glVertex2f(SRect.left, SRect.upper);
+ // lower-left coord
+ glTexCoord2f(FTexX/FdataX, FTexY/FdataY);
+ glVertex2f(SRect.left, SRect.lower);
+ // lower-right coord
+ glTexCoord2f(0, FTexY/FdataY);
+ glVertex2f(SRect.Right, SRect.lower);
+ // upper-right coord
+ glTexCoord2f(0, 0);
+ glVertex2f(SRect.Right, SRect.upper);
+ glEnd;
+
+ glDisable(GL_BLEND);
+end;
+
+procedure wClose();
+begin
+ WebCamReady := false;
+ FGrabFrameFlag := false;
+ if (WDMSample<>nil) then
+ begin
+ WDMSample.Terminate;
+ WDMSample.WaitFor;
+ WDMSample.Free;
+ WDMSample := nil;
+ end;
+
+ if(frame<>nil) then
+ FreeMem(frame);
+ frame := nil;
+
+ WebCamReady := false;
+ glDeleteTextures(1, @FTex);
+end;
+
+end.