aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/base/UConfig.pas18
-rw-r--r--src/base/UDraw.pas119
-rw-r--r--src/base/UGraphic.pas13
-rw-r--r--src/base/UMain.pas43
-rw-r--r--src/base/UParty.pas1021
-rw-r--r--src/base/USingScores.pas57
-rw-r--r--src/base/UThemes.pas36
-rw-r--r--src/lib/Lua/ULua.pas1085
-rw-r--r--src/lua/UHookableEvent.pas380
-rw-r--r--src/lua/ULuaCore.pas1014
-rw-r--r--src/lua/ULuaGl.pas1513
-rw-r--r--src/lua/ULuaLog.pas167
-rw-r--r--src/lua/ULuaParty.pas389
-rw-r--r--src/lua/ULuaScreenSing.pas489
-rw-r--r--src/lua/ULuaTextGL.pas147
-rw-r--r--src/lua/ULuaTexture.pas63
-rw-r--r--src/lua/ULuaUsdx.pas145
-rw-r--r--src/lua/ULuaUtils.pas186
-rw-r--r--src/menu/UDisplay.pas66
-rw-r--r--src/menu/UMenu.pas4
-rw-r--r--src/screens/UScreenMain.pas19
-rw-r--r--src/screens/UScreenPartyNewRound.pas272
-rw-r--r--src/screens/UScreenPartyOptions.pas90
-rw-r--r--src/screens/UScreenPartyPlayer.pas206
-rw-r--r--src/screens/UScreenPartyRounds.pas237
-rw-r--r--src/screens/UScreenPartyScore.pas107
-rw-r--r--src/screens/UScreenPartyWin.pas52
-rw-r--r--src/screens/UScreenSing.pas62
-rw-r--r--src/screens/UScreenSong.pas78
-rw-r--r--src/screens/UScreenSongMenu.pas25
-rw-r--r--src/ultrastardx.dpr16
31 files changed, 7284 insertions, 835 deletions
diff --git a/src/base/UConfig.pas b/src/base/UConfig.pas
index f6dc69a5..a24242e8 100644
--- a/src/base/UConfig.pas
+++ b/src/base/UConfig.pas
@@ -58,7 +58,7 @@ unit UConfig;
// not possible to use the version-numbers in this uses-clause.
// Example:
// interface
-// uses
+// uses
// versions, // include this file
// {$IF USE_UNIT_XYZ}xyz;{$IFEND} // Error: USE_UNIT_XYZ not defined
// const
@@ -68,13 +68,13 @@ unit UConfig;
//
// Even if this file was an include-file no constants could be declared
// before the interface's uses clause.
-// In FPC macros {$DEFINE VER:= 3} could be used to declare the version-numbers
+// In FPC macros {$DEFINE VER:= 3} could be used to declare the version-numbers
// but this is incompatible to Delphi. In addition macros do not allow expand
-// arithmetic expressions. Although you can define
+// arithmetic expressions. Although you can define
// {$DEFINE FPC_VER:= FPC_VERSION*1000000+FPC_RELEASE*1000+FPC_PATCH}
// the following check would fail:
// {$IF FPC_VERSION_INT >= 002002000}
-// would fail because FPC_VERSION_INT is interpreted as a string.
+// would fail because FPC_VERSION_INT is interpreted as a string.
//
// PLEASE consider this if you use version numbers in $IF compiler-
// directives. Otherwise you might break portability.
@@ -88,7 +88,7 @@ interface
{$ENDIF}
{$I switches.inc}
-
+
uses
SysUtils;
@@ -151,7 +151,7 @@ const
FPC_RELEASE = 0;
FPC_PATCH = 0;
{$ENDIF}
-
+
FPC_VERSION_INT = (FPC_VERSION * VERSION_MAJOR) +
(FPC_RELEASE * VERSION_MINOR) +
(FPC_PATCH * VERSION_RELEASE);
@@ -185,13 +185,13 @@ const
{$ENDIF}
- {$IFDEF HaveProjectM}
+ {$IFDEF HaveProjectM}
PROJECTM_VERSION = (PROJECTM_VERSION_MAJOR * VERSION_MAJOR) +
(PROJECTM_VERSION_MINOR * VERSION_MINOR) +
(PROJECTM_VERSION_RELEASE * VERSION_RELEASE);
{$ENDIF}
- {$IFDEF HavePortaudio}
+ {$IFDEF HavePortaudio}
PORTAUDIO_VERSION = (PORTAUDIO_VERSION_MAJOR * VERSION_MAJOR) +
(PORTAUDIO_VERSION_MINOR * VERSION_MINOR) +
(PORTAUDIO_VERSION_RELEASE * VERSION_RELEASE);
@@ -229,4 +229,4 @@ begin
' Build';
end;
-end.
+end. \ No newline at end of file
diff --git a/src/base/UDraw.pas b/src/base/UDraw.pas
index 1783986f..47863f62 100644
--- a/src/base/UDraw.pas
+++ b/src/base/UDraw.pas
@@ -258,19 +258,21 @@ begin
// So we exploit this behavior a bit - we give NrLines the playernumber, keep it in playernumber - and then we set NrLines to zero
// This could also come quite in handy when we do the duet mode, cause just the notes for the player that has to sing should be drawn then
// BUT this is not implemented yet, all notes are drawn! :D
+ if (ScreenSing.settings.NotesVisible and (1 shl NrLines) <> 0) then
+ begin
- PlayerNumber := NrLines + 1; // Player 1 is 0
- NrLines := 0;
+ PlayerNumber := NrLines + 1; // Player 1 is 0
+ NrLines := 0;
-// exploit done
+ // exploit done
- glColor3f(1, 1, 1);
- glEnable(GL_TEXTURE_2D);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor3f(1, 1, 1);
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- lTmpA := (Right-Left);
- lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start);
+ lTmpA := (Right-Left);
+ lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start);
if ( lTmpA > 0 ) and ( lTmpB > 0 ) then
TempR := lTmpA / lTmpB
@@ -285,16 +287,17 @@ begin
begin
if NoteType <> ntFreestyle then
begin
- if Ini.EffectSing = 0 then
- // If Golden note Effect of then Change not Color
- begin
- case NoteType of
- ntNormal: glColor4f(1, 1, 1, 1); // We set alpha to 1, cause we can control the transparency through the png itself
- ntGolden: glColor4f(1, 1, 0.3, 1); // no stars, paint yellow -> glColor4f(1, 1, 0.3, 0.85); - we could
+
+ if Ini.EffectSing = 0 then
+ // If Golden note Effect of then Change not Color
+ begin
+ case NoteType of
+ ntNormal: glColor4f(1, 1, 1, 1); // We set alpha to 1, cause we can control the transparency through the png itself
+ ntGolden: glColor4f(1, 1, 0.3, 1); // no stars, paint yellow -> glColor4f(1, 1, 0.3, 0.85); - we could
end; // case
- end //Else all Notes same Color
- else
- glColor4f(1, 1, 1, 1); // We set alpha to 1, cause we can control the transparency through the png itself
+ end //Else all Notes same Color
+ else
+ glColor4f(1, 1, 1, 1); // We set alpha to 1, cause we can control the transparency through the png itself
// left part
Rec.Left := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX;
@@ -309,35 +312,35 @@ begin
glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
glEnd;
- //We keep the postion of the top left corner b4 it's overwritten
+ //We keep the postion of the top left corner b4 it's overwritten
GoldenStarPos := Rec.Left;
- //done
+ //done
- // middle part
- Rec.Left := Rec.Right;
- Rec.Right := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - NotesW - 0.5 + 10*ScreenX;
+ // middle part
+ Rec.Left := Rec.Right;
+ Rec.Right := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - NotesW - 0.5 + 10*ScreenX;
- glBindTexture(GL_TEXTURE_2D, Tex_plain_Mid[PlayerNumber].TexNum);
- glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
- glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
- glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
- glTexCoord2f(round((Rec.Right-Rec.Left)/32), 1); glVertex2f(Rec.Right, Rec.Bottom);
- glTexCoord2f(round((Rec.Right-Rec.Left)/32), 0); glVertex2f(Rec.Right, Rec.Top);
- glEnd;
+ glBindTexture(GL_TEXTURE_2D, Tex_plain_Mid[PlayerNumber].TexNum);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
+ glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
+ glTexCoord2f(round((Rec.Right-Rec.Left)/32), 1); glVertex2f(Rec.Right, Rec.Bottom);
+ glTexCoord2f(round((Rec.Right-Rec.Left)/32), 0); glVertex2f(Rec.Right, Rec.Top);
+ glEnd;
// right part
Rec.Left := Rec.Right;
Rec.Right := Rec.Right + NotesW;
- glBindTexture(GL_TEXTURE_2D, Tex_plain_Right[PlayerNumber].TexNum);
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
- glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
- glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
- glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
- glEnd;
+ glBindTexture(GL_TEXTURE_2D, Tex_plain_Right[PlayerNumber].TexNum);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top);
+ glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom);
+ glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom);
+ glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top);
+ glEnd;
// Golden Star Patch
if (NoteType = ntGolden) and (Ini.EffectSing=1) then
@@ -345,13 +348,14 @@ begin
GoldenRec.SaveGoldenStarsRec(GoldenStarPos, Rec.Top, Rec.Right, Rec.Bottom);
end;
- end; // if not FreeStyle
- end; // with
- end; // for
- end; // with
+ end; // if not FreeStyle
+ end; // with
+ end; // for
+ end; // with
- glDisable(GL_BLEND);
- glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+ glDisable(GL_TEXTURE_2D);
+ end;
end;
// draw sung notes
@@ -481,7 +485,7 @@ var
W, H: real;
lTmpA, lTmpB: real;
begin
- if (Player[PlayerIndex].ScoreTotalInt >= 0) then
+ if (ScreenSing.settings.NotesVisible and (1 shl PlayerIndex) <> 0) then
begin
glColor4f(1, 1, 1, sqrt((1+sin( AudioPlayback.Position * 3))/4)/ 2 + 0.5 );
glEnable(GL_TEXTURE_2D);
@@ -683,20 +687,25 @@ begin
// draw note-lines
- if (PlayersPlay = 1) and (Ini.NoteLines = 1) then
+ // to-do : needs fix when party mode works w/ 2 screens
+ if (PlayersPlay = 1) and (Ini.NoteLines = 1) and (ScreenSing.settings.NotesVisible and (1) <> 0) then
SingDrawNoteLines(NR.Left + 10*ScreenX, Skin_P2_NotesB - 105, NR.Right + 10*ScreenX, 15);
if ((PlayersPlay = 2) or (PlayersPlay = 4)) and (Ini.NoteLines = 1) then
begin
- SingDrawNoteLines(NR.Left + 10*ScreenX, Skin_P1_NotesB - 105, NR.Right + 10*ScreenX, 15);
- SingDrawNoteLines(NR.Left + 10*ScreenX, Skin_P2_NotesB - 105, NR.Right + 10*ScreenX, 15);
+ if (ScreenSing.settings.NotesVisible and (1 shl 0) <> 0) then
+ SingDrawNoteLines(Nr.Left + 10*ScreenX, Skin_P1_NotesB - 105, Nr.Right + 10*ScreenX, 15);
+ if (ScreenSing.settings.NotesVisible and (1 shl 1) <> 0) then
+ SingDrawNoteLines(Nr.Left + 10*ScreenX, Skin_P2_NotesB - 105, Nr.Right + 10*ScreenX, 15);
end;
- if ((PlayersPlay = 3) or (PlayersPlay = 6)) and (Ini.NoteLines = 1) then
- begin
- SingDrawNoteLines(NR.Left + 10*ScreenX, 120, NR.Right + 10*ScreenX, 12);
- SingDrawNoteLines(NR.Left + 10*ScreenX, 245, NR.Right + 10*ScreenX, 12);
- SingDrawNoteLines(NR.Left + 10*ScreenX, 370, NR.Right + 10*ScreenX, 12);
+ if ((PlayersPlay = 3) or (PlayersPlay = 6)) and (Ini.NoteLines = 1) then begin
+ if (ScreenSing.settings.NotesVisible and (1 shl 0) <> 0) then
+ SingDrawNoteLines(Nr.Left + 10*ScreenX, 120, Nr.Right + 10*ScreenX, 12);
+ if (ScreenSing.settings.NotesVisible and (1 shl 1) <> 0) then
+ SingDrawNoteLines(Nr.Left + 10*ScreenX, 245, Nr.Right + 10*ScreenX, 12);
+ if (ScreenSing.settings.NotesVisible and (1 shl 2) <> 0) then
+ SingDrawNoteLines(Nr.Left + 10*ScreenX, 370, Nr.Right + 10*ScreenX, 12);
end;
// draw Lyrics
@@ -937,7 +946,7 @@ begin
end;
// Draw Lyrics
- ScreenSingModi.Lyrics.Draw(LyricsState.MidBeat);
+ //ScreenSingModi.Lyrics.Draw(LyricsState.MidBeat);
// TODO: Lyrics helper
// oscilloscope | the thing that moves when you yell into your mic (imho)
diff --git a/src/base/UGraphic.pas b/src/base/UGraphic.pas
index b0e5a7d8..f658c800 100644
--- a/src/base/UGraphic.pas
+++ b/src/base/UGraphic.pas
@@ -77,6 +77,7 @@ uses
UScreenPartyOptions,
UScreenPartyWin,
UScreenPartyPlayer,
+ UScreenPartyRounds,
{Stats Screens}
UScreenStatMain,
UScreenStatDetail,
@@ -133,12 +134,13 @@ var
ScreenSongJumpto: TScreenSongJumpto;
//Party Screens
- ScreenSingModi: TScreenSingModi;
+ //ScreenSingModi: TScreenSingModi;
ScreenPartyNewRound: TScreenPartyNewRound;
ScreenPartyScore: TScreenPartyScore;
ScreenPartyWin: TScreenPartyWin;
ScreenPartyOptions: TScreenPartyOptions;
ScreenPartyPlayer: TScreenPartyPlayer;
+ ScreenPartyRounds: TScreenPartyRounds;
//StatsScreens
ScreenStatMain: TScreenStatMain;
@@ -747,8 +749,8 @@ begin
// Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Edit Header', 3); Log.BenchmarkStart(3);
ScreenOpen := TScreenOpen.Create;
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Open', 3); Log.BenchmarkStart(3);
- ScreenSingModi := TScreenSingModi.Create;
- Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Sing with Modi support', 3); Log.BenchmarkStart(3);
+ //ScreenSingModi := TScreenSingModi.Create;
+ //Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Sing with Modi support', 3); Log.BenchmarkStart(3);
ScreenSongMenu := TScreenSongMenu.Create;
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen SongMenu', 3); Log.BenchmarkStart(3);
ScreenSongJumpto := TScreenSongJumpto.Create;
@@ -769,6 +771,8 @@ begin
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyOptions', 3); Log.BenchmarkStart(3);
ScreenPartyPlayer := TScreenPartyPlayer.Create;
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyPlayer', 3); Log.BenchmarkStart(3);
+ ScreenPartyRounds := TScreenPartyRounds.Create;
+ Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen PartyRounds', 3); Log.BenchmarkStart(3);
ScreenStatMain := TScreenStatMain.Create;
Log.BenchmarkEnd(3); Log.LogBenchmark('====> Screen Stat Main', 3); Log.BenchmarkStart(3);
ScreenStatDetail := TScreenStatDetail.Create;
@@ -805,7 +809,7 @@ begin
ScreenEdit.Destroy;
ScreenEditConvert.Destroy;
ScreenOpen.Destroy;
- ScreenSingModi.Destroy;
+ //ScreenSingModi.Destroy;
ScreenSongMenu.Destroy;
ScreenSongJumpto.Destroy;
ScreenPopupCheck.Destroy;
@@ -816,6 +820,7 @@ begin
ScreenPartyWin.Destroy;
ScreenPartyOptions.Destroy;
ScreenPartyPlayer.Destroy;
+ ScreenPartyRounds.Destroy;
ScreenStatMain.Destroy;
ScreenStatDetail.Destroy;
end;
diff --git a/src/base/UMain.pas b/src/base/UMain.pas
index d5e0ccb3..7b082c57 100644
--- a/src/base/UMain.pas
+++ b/src/base/UMain.pas
@@ -35,6 +35,7 @@ interface
uses
SysUtils,
+
SDL;
var
@@ -89,6 +90,14 @@ uses
USongs,
UThemes,
UParty,
+ ULuaCore,
+ UHookableEvent,
+ ULuaGl,
+ ULuaLog,
+ ULuaTexture,
+ ULuaTextGL,
+ ULuaParty,
+ ULuaScreenSing,
UTime;
procedure Main;
@@ -124,6 +133,10 @@ begin
SDL_Init(SDL_INIT_VIDEO or SDL_INIT_TIMER);
SDL_EnableUnicode(1);
+ // create luacore first so other classes can register their events
+ LuaCore := TLuaCore.Create;
+
+
USTime := TTime.Create;
VideoBGTimer := TRelativeTimer.Create;
@@ -227,13 +240,6 @@ begin
Log.BenchmarkEnd(1);
Log.LogBenchmark('Loading PluginManager', 1);
- // Party Mode Manager
- Log.BenchmarkStart(1);
- Log.LogStatus('PartySession Manager', 'Initialization');
- PartySession := TPartySession.Create; //Load PartySession
- Log.BenchmarkEnd(1);
- Log.LogBenchmark('Loading PartySession Manager', 1);
-
// Graphics
Log.BenchmarkStart(1);
Log.LogStatus('Initialize 3D', 'Initialization');
@@ -278,6 +284,29 @@ begin
Log.LogBenchmark('Initializing Joystick', 1);
end;
+ // Lua
+ Log.BenchmarkStart(1);
+ Party := TPartyGame.Create;
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Initializing Party Manager', 1);
+
+ Log.BenchmarkStart(1);
+ LuaCore.RegisterModule('Log', ULuaLog_Lib_f);
+ LuaCore.RegisterModule('Gl', ULuaGl_Lib_f);
+ LuaCore.RegisterModule('TextGl', ULuaTextGl_Lib_f);
+ LuaCore.RegisterModule('Party', ULuaParty_Lib_f);
+ LuaCore.RegisterModule('ScreenSing', ULuaScreenSing_Lib_f);
+
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Initializing LuaCore', 1);
+
+ Log.BenchmarkStart(1);
+ LuaCore.LoadPlugins;
+ Log.BenchmarkEnd(1);
+ Log.LogBenchmark('Loading Lua Plugins', 1);
+
+ LuaCore.DumpPlugins;
+
Log.BenchmarkEnd(0);
Log.LogBenchmark('Loading Time', 0);
diff --git a/src/base/UParty.pas b/src/base/UParty.pas
index 52eb5a05..94580241 100644
--- a/src/base/UParty.pas
+++ b/src/base/UParty.pas
@@ -34,355 +34,938 @@ interface
{$I switches.inc}
uses
- ModiSDK;
+ ULua;
type
- TRoundInfo = record
- Plugin: word;
- Winner: byte;
+ { array holds ids of modes or Party_Round_Random
+ its length defines the number of rounds
+ it is used as argument for TPartyGame.StartParty }
+ ARounds = array of integer;
+
+ { element of APartyTeamRanking returned by TPartyGame.GetTeamRanking
+ and parameter for TPartyGame.SetWinner }
+ TParty_TeamRanking = record
+ Team: Integer; //< id of team
+ Rank: Integer; //< 1 to Length(Teams) e.g. 1 is for placed first
end;
+ AParty_TeamRanking = array of TParty_TeamRanking; //< returned by TPartyGame.GetTeamRanking
- TeamOrderEntry = record
- TeamNum: byte;
- Score: byte;
+ TParty_RoundList = record
+ Index: integer;
+ Name: UTF8String;
end;
+ AParty_ModeList = array of TParty_RoundList;
+
+ { record used by TPartyGame to store round specific data }
+ TParty_Round = record
+ Mode: Integer;
+ AlreadyPlayed: Boolean; //< true if round was already played
+ Ranking: AParty_TeamRanking;
+ RankingSet: Boolean; //< true if Self.Ranking is already set
+ end;
+
+ TParty_ModeInfo = record
+ Name: String; // name of this mode
+ Parent: Integer; // Id of owning plugin
+
+ CanNonParty: Boolean; //< is playable when not in party mode
+ CanParty: Boolean; //< is playable in party mode
+
+ // one bit in the following settings stands for
+ // a player or team count
+ // PlayerCount = 2 or 4 indicates that the mode is playable with 2 and 3 players per team
+ // TeamCount = 1 or 2 or 4 or 8 or 16 or 32 indicates that the mode is playable with 1 to 6 teams
+ PlayerCount: Integer; //< playable with one, two, three etc. players per team
+ TeamCount: Integer; //< playable with one, two, three etc. different teams
+
+
+ Functions: record // lua functions that will be called at specific events
+ BeforeSongSelect: String; // default actions are executed if functions = nil
+ AfterSongSelect: String;
+
+ BeforeSing: String;
+ OnSing: String;
+ AfterSing: String;
+ end;
+ end;
+
+ { used by TPartyGame to store player specific data }
+ TParty_PlayerInfo = record
+ Name: String; //< Playername
+ TimesPlayed: Integer; //< How often this Player has Sung
+ end;
+
+ { used by TPartyGame to store team specific data }
+ TParty_TeamInfo = record
+ Name: String; //< name of the Team
+ Score: Word; //< current score
+ JokersLeft: Integer; //< jokers this team has left
- TeamOrderArray = array[0..5] of byte;
+ NextPlayer: Integer; //Id of the player that plays the next (the current) song
- TPartyPlugin = record
- ID: byte;
- TimesPlayed: byte;
+ Players: array of TParty_PlayerInfo;
end;
- TPartySession = class
+ TPartyGame = class
private
- function GetRandomPlayer(Team: byte): byte;
- function GetRandomPlugin(Plugins: array of TPartyPlugin): byte;
- function IsWinner(Player, Winner: byte): boolean;
+ bPartyGame: boolean; //< are we playing party or standard mode
+ CurRound: Integer; //< indicates which of the elements of Rounds is played next (at the moment)
+
+ bPartyStarted: Boolean;
+
+ TimesPlayed: array of Integer; //< times every mode was played in current party game (for random mode calculation)
+
procedure GenScores;
+ function GetRandomMode: integer;
+ function GetRandomPlayer(Team: integer): integer;
+
+ { returns true if a mode is playable with current playerconfig }
+ function ModePlayable(I: integer): boolean;
+
+ function CallLua(Parent: Integer; Func: String):Boolean;
+
+ procedure SetRankingByScore;
public
- Teams: TTeamInfo;
- Rounds: array of TRoundInfo;
- CurRound: byte;
+ //Teams: TTeamInfo;
+ Rounds: array of TParty_Round; //< holds info which modes are played in this party game (if started)
+ Teams: array of TParty_TeamInfo; //< holds info of teams playing in current round (private for easy manipulation of lua functions)
+
+ Modes: array of TParty_ModeInfo; //< holds info of registred party modes
+
+ property CurrentRound: Integer read CurRound;
constructor Create;
- procedure StartNewParty(NumRounds: byte);
- procedure StartRound;
- procedure EndRound;
- function GetTeamOrder: TeamOrderArray;
- function GetWinnerString(Round: byte): UTF8String;
+ { set the attributes of Info to default values }
+ procedure DefaultModeInfo(var Info: TParty_ModeInfo);
+
+ { registers a new mode, returns true on success
+ (mode name does not already exist) }
+ function RegisterMode(Info: TParty_ModeInfo): Boolean;
+
+ { returns true if modes are available for
+ players and teams that are currently set
+ up. if there are no teams set up it returns
+ if there are any party modes available }
+ function ModesAvailable: Boolean;
+
+ { returns an array with the name of all available modes (that
+ are playable with current player configuration }
+ function GetAvailableModes: AParty_ModeList;
+
+ { clears all party specific data previously stored }
+ procedure Clear;
+
+ { adds a team to the team array, returning its id
+ can only be called when game is not already started }
+ function AddTeam(Name: String): Integer;
+
+ { adds a player to the player array, returning its id
+ can only be called when game is not already started }
+ function AddPlayer(Team: Integer; Name: String): Integer;
+
+ { starts a new PartyGame, returns true on success
+ before a call of this function teams and players
+ has to be added by AddTeam and AddPlayer }
+
+ function StartGame(Rounds: ARounds): Boolean;
+
+ { sets the winner(s) of current round
+ returns true on success }
+ function SetRanking(Ranking: AParty_TeamRanking): Boolean;
+
+ { increases round counter by 1 and clears all round specific information;
+ returns the number of the current round or -1 if last round has already
+ been played }
+ function NextRound: integer;
+
+ { indicates that current round has already been played }
+ procedure RoundPlayed;
+
+ { true if in a Party Game (not in standard mode) }
+ property PartyGame: Boolean read BPartyGame;
+
+
+ { returns true if last round was already played }
+ function GameFinished: Boolean;
+
+ { call plugins defined function and/or default procedure
+ only default procedure is called when no function is defined by plugin
+ if plugins function returns true then default is called after plugins
+ function was executed}
+ procedure CallBeforeSongSelect;
+ procedure CallAfterSongSelect;
+ procedure CallBeforeSing;
+ procedure CallOnSing;
+ procedure CallAfterSing;
+
+ { returns an array[1..6] of TParty_TeamRanking.
+ the index stands for the placing,
+ team is the team number (in the team array)
+ rank is correct rank if some teams have the
+ same score.
+ }
+ function GetTeamRanking: AParty_TeamRanking;
+
+ { returns a string like "Team 1 (and Team 2) win" }
+ function GetWinnerString(Round: integer): UTF8String;
+
+ destructor Destroy;
end;
+const
+ { minimal amount of teams for party mode }
+ Party_Teams_Min = 2;
+
+ { maximal amount of teams for party mode }
+ Party_Teams_Max = 3;
+
+ { minimal amount of players for party mode }
+ Party_Players_Min = 1;
+
+ { maximal amount of players for party mode }
+ Party_Players_Max = 4;
+
+ { amount of jokers each team gets at the beginning of the game }
+ Party_Count_Jokers = 5;
+
+ { to indicate that element (mode) should set randomly in ARounds array }
+ Party_Round_Random = -1;
+
+ { values for TParty_TeamRanking.Rank }
+ PR_First = 1;
+ PR_Second = 2;
+ PR_Third = 3;
+
+ StandardModus = 0; //Modus Id that will be played in non-party mode
+
var
- PartySession: TPartySession;
+ Party: TPartyGame;
implementation
uses
- UDLLManager,
UGraphic,
- UNote,
ULanguage,
- ULog;
+ ULog,
+ ULuaCore,
+ UDisplay,
+ USong,
+ UNote,
+ SysUtils;
-constructor TPartySession.Create;
+//-------------
+// Just the constructor
+//-------------
+constructor TPartyGame.Create;
begin
inherited;
+
+ Clear;
end;
-//----------
-// Returns a number of a random plugin
-//----------
-function TPartySession.GetRandomPlugin(Plugins: array of TPartyPlugin): byte;
+destructor TPartyGame.Destroy;
+begin
+ inherited;
+end;
+
+{ clears all party specific data previously stored }
+procedure TPartyGame.Clear;
+ var
+ I: Integer;
+begin
+ bPartyGame := false; // no party game
+ CurRound := low(integer);
+
+ bPartyStarted := false; //game not startet
+
+ SetLength(Teams, 0); //remove team info
+ SetLength(Rounds, 0); //remove round info
+
+ // clear times played
+ for I := 0 to High(TimesPlayed) do
+ TimesPlayed[I] := 0;
+end;
+
+{ private: some intelligent randomnes for plugins }
+function TPartyGame.GetRandomMode: integer;
+var
+ LowestTP: integer;
+ NumPwithLTP: integer;
+ I: integer;
+ R: integer;
+begin
+ Result := 0; //If there are no matching modes, play first modus
+ LowestTP := high(Integer);
+ NumPwithLTP := 0;
+
+ // search for the plugins less played yet
+ for I := 0 to high(Modes) do
+ begin
+ if (ModePlayable(I)) then
+ begin
+ if (TimesPlayed[I] < lowestTP) then
+ begin
+ lowestTP := TimesPlayed[I];
+ NumPwithLTP := 1;
+ end
+ else if (TimesPlayed[I] = lowestTP) then
+ begin
+ Inc(NumPwithLTP);
+ end;
+ end;
+ end;
+
+ // create random number
+ R := Random(NumPwithLTP);
+
+ // select the random mode from the modes with less timesplayed
+ for I := 0 to high(Modes) do
+ begin
+ if (TimesPlayed[I] = lowestTP) and (ModePlayable(I)) then
+ begin
+ //Plugin found
+ if (R = 0) then
+ begin
+ Result := I;
+ Inc(TimesPlayed[I]);
+ Break;
+ end;
+
+ Dec(R);
+ end;
+ end;
+end;
+
+{ private: GetRandomPlayer - returns a random player
+ that does not play to often ;) }
+function TPartyGame.GetRandomPlayer(Team: integer): integer;
var
- LowestTP: byte;
- NumPwithLTP: word;
- I: integer;
- R: word;
+ I, R: integer;
+ lowestTP: Integer;
+ NumPwithLTP: Integer;
begin
- LowestTP := high(byte);
+ LowestTP := high(Integer);
NumPwithLTP := 0;
+ Result := 0;
- //Search for Plugins not often played yet
- for I := 0 to high(Plugins) do
+ // search for players that have less played yet
+ for I := 0 to High(Teams[Team].Players) do
begin
- if (Plugins[I].TimesPlayed < lowestTP) then
+ if (Teams[Team].Players[I].TimesPlayed < lowestTP) then
begin
- lowestTP := Plugins[I].TimesPlayed;
+ lowestTP := Teams[Team].Players[I].TimesPlayed;
NumPwithLTP := 1;
end
- else if (Plugins[I].TimesPlayed = lowestTP) then
+ else if (Teams[Team].Players[I].TimesPlayed = lowestTP) then
begin
Inc(NumPwithLTP);
end;
end;
- //Create random no
+ // create random number
R := Random(NumPwithLTP);
- //Search for random plugin
- for I := 0 to high(Plugins) do
+ // search for selected random player
+ for I := 0 to High(Teams[Team].Players) do
begin
- if Plugins[I].TimesPlayed = LowestTP then
+ if Teams[Team].Players[I].TimesPlayed = lowestTP then
begin
- //Plugin found
if (R = 0) then
- begin
- Result := Plugins[I].ID;
- Inc(Plugins[I].TimesPlayed);
+ begin // found selected player
+ Result := I;
Break;
end;
+
Dec(R);
end;
end;
end;
//----------
-//StartNewParty - Reset and prepares for new party
+//GenScores - inc scores for cur. round
//----------
-procedure TPartySession.StartNewParty(NumRounds: byte);
+procedure TPartyGame.GenScores;
var
- Plugins: array of TPartyPlugin;
- TeamMode: boolean;
- Len: integer;
- I, J: integer;
+ I: Integer;
+begin
+ if (Length(Teams) = 2) then
+ begin // score generation for 2 teams, winner gets 1 point
+ for I := 0 to High(Rounds[CurRound].Ranking) do
+ if (Rounds[CurRound].Ranking[I].Rank = PR_First) then
+ Inc(Teams[Rounds[CurRound].Ranking[I].Team].Score);
+ end
+ else if (Length(Teams) = 3) then
+ begin // score generation for 3 teams,
+ // winner gets 3 points 2nd gets 1 point
+ for I := 0 to High(Rounds[CurRound].Ranking) do
+ if (Rounds[CurRound].Ranking[I].Rank = PR_First) then
+ Inc(Teams[Rounds[CurRound].Ranking[I].Team].Score, 3)
+ else if (Rounds[CurRound].Ranking[I].Rank = PR_Second) then
+ Inc(Teams[Rounds[CurRound].Ranking[I].Team].Score);
+ end
+end;
+
+{ set the attributes of Info to default values }
+procedure TPartyGame.DefaultModeInfo(var Info: TParty_ModeInfo);
begin
- //Set current round to 1
- CurRound := 255;
+ Info.Name := 'undefined';
+ Info.Parent := -1; //< not loaded by plugin (e.g. Duell)
+ Info.CanNonParty := false;
+ Info.CanParty := false;
+ Info.PlayerCount := High(Integer); //< no restrictions either on player count
+ Info.TeamCount := High(Integer); //< nor on team count
+ Info.Functions.BeforeSongSelect := ''; //< use default functions
+ Info.Functions.AfterSongSelect := '';
+ Info.Functions.BeforeSing := '';
+ Info.Functions.OnSing := '';
+ Info.Functions.AfterSing := '';
+end;
- PlayersPlay := Teams.NumTeams;
+{ registers a new mode, returns true on success
+ (mode name does not already exist) }
+function TPartyGame.RegisterMode(Info: TParty_ModeInfo): Boolean;
+ var
+ Len: integer;
+ LowerName: String;
+ I: integer;
+begin
+ Result := false;
- //Get team-mode and set joker, also set TimesPlayed
- TeamMode := true;
- for I := 0 to Teams.NumTeams - 1 do
+ if (Info.Name <> 'undefined') then
begin
- if Teams.Teaminfo[I].NumPlayers < 2 then
+ // search for a plugin w/ same name
+ LowerName := lowercase(Info.Name); // case sensitive search
+ for I := 0 to high(Modes) do
+ if (LowerName = lowercase(Modes[I].Name)) then
+ exit; //< no success (name already exist)
+
+ // add new mode to array and append and clear a new TimesPlayed element
+ Len := Length(Modes);
+ SetLength(Modes, Len + 1);
+ SetLength(TimesPlayed, Len + 1);
+
+ Modes[Len] := Info;
+ TimesPlayed[Len] := 0;
+
+ Result := True;
+ end;
+end;
+
+{ returns true if a mode is playable with current playerconfig }
+function TPartyGame.ModePlayable(I: integer): boolean;
+ var
+ J: integer;
+begin
+ if (Length(Teams) = 0) then
+ Result := true
+ else
+ begin
+ if (Modes[I].TeamCount and (1 shl (Length(Teams) - 1)) <> 0) then
begin
- TeamMode := false;
+ Result := true;
+
+ for J := 0 to High(Teams) do
+ Result := Result and (Modes[I].PlayerCount and (1 shl (Length(Teams[J].Players) - 1)) <> 0);
+ end
+ else
+ Result := false;
+ end;
+end;
+
+{ returns true if modes are available for
+ players and teams that are currently set
+ up. if there are no teams set up it returns
+ if there are any party modes available }
+function TPartyGame.ModesAvailable: Boolean;
+ var
+ I: integer;
+ CountTeams: integer;
+begin
+ CountTeams := Length(Teams);
+ if CountTeams = 0 then
+ begin
+ Result := (Length(Modes) > 0);
+ end
+ else
+ begin
+ Result := false;
+ for I := 0 to High(Modes) do
+ begin
+ Result := ModePlayable(I);
+
+ if Result then
+ Exit;
end;
- //Set player attributes
- for J := 0 to Teams.TeamInfo[I].NumPlayers-1 do
+ end;
+end;
+
+{ returns an array with the name of all available modes (that
+ are playable with current player configuration }
+function TPartyGame.GetAvailableModes: AParty_ModeList;
+ var
+ I: integer;
+ Len: integer;
+begin
+ Len := 0;
+ SetLength(Result, Len + 1);
+ Result[Len].Index := Party_Round_Random;
+ Result[Len].Name := Language.Translate('MODE_RANDOM_NAME');
+
+ for I := 0 to High(Modes) do
+ if (ModePlayable(I)) then
begin
- Teams.TeamInfo[I].Playerinfo[J].TimesPlayed := 0;
+ Inc(Len);
+ SetLength(Result, Len + 1);
+ Result[Len].Index := I;
+ Result[Len].Name := Language.Translate('MODE_' + Uppercase(Modes[I].Name) + '_NAME');
end;
- Teams.Teaminfo[I].Joker := Round(NumRounds * 0.7);
- Teams.Teaminfo[I].Score := 0;
+end;
+
+{ adds a team to the team array, returning its id
+ can only be called when game is not already started }
+function TPartyGame.AddTeam(Name: String): Integer;
+begin
+ Result := -1;
+ if (not bPartyStarted) and (Length(Name) > 0) and (Length(Teams) < Party_Teams_Max) then
+ begin
+ Result := Length(Teams);
+ SetLength(Teams, Result + 1);
+
+ Teams[Result].Name := Name;
+ Teams[Result].Score := 0;
+ Teams[Result].JokersLeft := Party_Count_Jokers;
+ Teams[Result].NextPlayer := -1;
end;
+end;
+
+{ adds a player to the player array, returning its id
+ can only be called when game is not already started }
+function TPartyGame.AddPlayer(Team: Integer; Name: String): Integer;
+begin
+ Result := -1;
- //Fill plugin array
- SetLength(Plugins, 0);
- for I := 0 to high(DLLMan.Plugins) do
+ if (not bPartyStarted) and (Team >= 0) and (Team <= High(Teams)) and (Length(Teams[Team].Players) < Party_Players_Max) and (Length(Name) > 0) then
begin
- if TeamMode or (not DLLMan.Plugins[I].TeamModeOnly) then
- begin
- //Add only those plugins playable with current PlayerConfiguration
- Len := Length(Plugins);
- SetLength(Plugins, Len + 1);
- Plugins[Len].ID := I;
- Plugins[Len].TimesPlayed := 0;
- end;
+ // append element to players array
+ Result := Length(Teams[Team].Players);
+ SetLength(Teams[Team].Players, Result + 1);
+
+ // fill w/ data
+ Teams[Team].Players[Result].Name := Name;
+ Teams[Team].Players[Result].TimesPlayed := 0;
end;
+end;
+
+{ starts a new PartyGame, returns true on success
+ before a call of this function teams and players
+ has to be added by AddTeam and AddPlayer }
+function TPartyGame.StartGame(Rounds: ARounds): Boolean;
+ var
+ I: integer;
+begin
+ Result := false;
- //Set rounds
- if (Length(Plugins) >= 1) then
+ if (not bPartyStarted) and (Length(Rounds) > 0) and (Length(Teams) >= Party_Teams_Min) then
begin
- SetLength (Rounds, NumRounds);
- for I := 0 to NumRounds - 1 do
+ // check teams for minimal player count
+ for I := 0 to High(Teams) do
+ if (Length(Teams[I].Players) < Party_Players_Min) then
+ exit;
+
+ // create rounds array
+ SetLength(Self.Rounds, Length(Rounds));
+
+ for I := 0 to High(Rounds) do
begin
- PartySession.Rounds[I].Plugin := GetRandomPlugin(Plugins);
- PartySession.Rounds[I].Winner := 255;
+ // copy round or select a random round
+ if (Rounds[I] <> Party_Round_Random) and (Rounds[I] >= 0) and (Rounds[I] <= High(Modes)) then
+ Self.Rounds[I].Mode := Rounds[I]
+ else
+ Self.Rounds[I].Mode := GetRandomMode;
+
+ Self.Rounds[I].AlreadyPlayed := false;
+ Self.Rounds[I].RankingSet := false;
+
+ SetLength(Self.Rounds[I].Ranking, 0);
end;
+
+ // get the party started!11
+ bPartyStarted := true;
+ bPartyGame := true;
+ CurRound := low(integer); //< set not to -1 to indicate that party game is not finished
+
+ // first round
+ NextRound;
+
+ Result := True;
+ end;
+end;
+
+{ sets the winner(s) of current round
+ returns true on success }
+function TPartyGame.SetRanking(Ranking: AParty_TeamRanking): Boolean;
+ var
+ I, J: Integer;
+ TeamExists: Integer;
+ Len: Integer;
+ Temp: TParty_TeamRanking;
+begin
+ if (bPartyStarted) and (CurRound >= 0) and (CurRound <= High(Rounds)) then
+ begin
+ Rounds[CurRound].Ranking := Ranking;
+ Result := true;
+
+ // look for teams that don't exist
+ TeamExists := 0;
+ for I := 0 to High(Rounds[CurRound].Ranking) do
+ TeamExists := TeamExists or (1 shl (Rounds[CurRound].Ranking[I].Team-1));
+
+ // create teams that don't exist
+ Len := Length(Rounds[CurRound].Ranking);
+ for I := 0 to High(Teams) do
+ if (TeamExists and (1 shl I) = 0) then
+ begin
+ Inc(Len);
+ SetLength(Rounds[CurRound].Ranking, Len);
+ Rounds[CurRound].Ranking[Len-1].Team := I + 1;
+ Rounds[CurRound].Ranking[Len-1].Rank := Length(Teams);
+ end;
+
+ // we may remove rankings from invalid teams here to
+ // but at the moment this is not necessary, because the
+ // functions this function is called from don't create
+ // invalid rankings
+
+ // bubble sort rankings by team
+ J := High(Rounds[CurRound].Ranking);
+ repeat
+ for I := 0 to J - 1 do
+ if (Rounds[CurRound].Ranking[I].Team > Rounds[CurRound].Ranking[I+1].Team) then
+ begin
+ Temp := Rounds[CurRound].Ranking[I];
+ Rounds[CurRound].Ranking[I] := Rounds[CurRound].Ranking[I+1];
+ Rounds[CurRound].Ranking[I+1] := Temp;
+ end;
+ Dec(J);
+ until J <= 0;
+
+ //set rounds RankingSet to true
+ Rounds[CurRound].RankingSet := true;
end
else
- SetLength (Rounds, 0);
+ Result := false;
end;
-{**
- * Returns a random player to play next round
- *}
-function TPartySession.GetRandomPlayer(Team: byte): byte;
-var
- I, R: integer;
- LowestTP: byte;
- NumPwithLTP: byte;
+{ sets ranking of current round by score saved in players array }
+procedure TPartyGame.SetRankingByScore;
+ var
+ I, J: Integer;
+ Rank: Integer;
+ Ranking: AParty_TeamRanking;
+ Scores: array of Integer;
+ TmpRanking: TParty_TeamRanking;
+ TmpScore: Integer;
begin
- LowestTP := high(byte);
- NumPwithLTP := 0;
- Result := 0;
-
- //Search for players that have not often played yet
- for I := 0 to Teams.Teaminfo[Team].NumPlayers - 1 do
+ if (Length(Player) = Length(Teams)) then
begin
- if (Teams.Teaminfo[Team].Playerinfo[I].TimesPlayed < lowestTP) then
+ SetLength(Ranking, Length(Teams));
+ SetLength(Scores, Length(Teams));
+
+ // fill ranking array
+ for I := 0 to High(Ranking) do
begin
- lowestTP := Teams.Teaminfo[Team].Playerinfo[I].TimesPlayed;
- NumPwithLTP := 1;
- end
- else if (Teams.Teaminfo[Team].Playerinfo[I].TimesPlayed = lowestTP) then
+ Ranking[I].Team := I;
+ Ranking[I].Rank := 0;
+ Scores[I] := Player[I].ScoreTotalInt;
+ end;
+
+ // bubble sort by score
+ J := High(Ranking);
+ repeat
+ for I := 0 to J - 1 do
+ if (Scores[I] < Scores[I+1]) then
+ begin
+ TmpRanking := Ranking[I];
+ Ranking[I] := Ranking[I+1];
+ Ranking[I+1] := TmpRanking;
+
+ TmpScore := Scores[I];
+ Scores[I] := Scores[I+1];
+ Scores[I+1] := TmpScore;
+ end;
+ Dec(J);
+ until J <= 0;
+
+ // set rank field
+ Rank := 1; //first rank has id 1
+ for I := 0 to High(Ranking) do
begin
- Inc(NumPwithLTP);
+ Ranking[I].Rank := Rank;
+
+ if (I < High(Ranking)) and (Scores[I] <> Scores[I+1]) then
+ Inc(Rank); // next rank if next team has different score
end;
+ end
+ else
+ SetLength(Ranking, 0);
+
+ SetRanking(Ranking);
+end;
+
+{ increases round counter by 1 and clears all round specific information;
+ returns the number of the current round or -1 if last round has already
+ been played }
+function TPartyGame.NextRound: integer;
+ var I: Integer;
+begin
+ // some lines concerning the previous round
+ if (CurRound >= 0) then
+ begin
+ Rounds[CurRound].AlreadyPlayed := true;
+
+ GenScores;
end;
- //Create random number
- R := Random(NumPwithLTP);
+ // increase round counter
+ Inc(CurRound);
+ if (CurRound < -1) then // we start first round
+ CurRound := 0;
- //Search for random player
- for I := 0 to Teams.Teaminfo[Team].NumPlayers - 1 do
+ if (CurRound > High(Rounds)) then
+ CurRound := -1; //< last round played
+
+ Result := CurRound;
+
+ // some lines concerning the next round
+ if (CurRound >= 0) then
begin
- if Teams.Teaminfo[Team].Playerinfo[I].TimesPlayed = lowestTP then
- begin
- //Player found
- if (R = 0) then
- begin
- Result := I;
- Break;
- end;
-
- Dec(R);
- end;
+ // select player
+ for I := 0 to High(Teams) do
+ Teams[I].NextPlayer := GetRandomPlayer(I);
end;
end;
-{**
- * Prepares ScreenSingModi for next round and loads plugin
- *}
-procedure TPartySession.StartRound;
-var
- I: integer;
+{ indicates that current round has already been played }
+procedure TPartyGame.RoundPlayed;
begin
- if ((CurRound < high(Rounds)) or (CurRound = high(CurRound))) then
+ if (bPartyStarted) and (CurRound >= 0) and (CurRound <= High(Rounds)) then
begin
- // Increase Current Round but not beyond its limit
- // CurRound is set to 255 to begin with!
- // Ugly solution if you ask me.
- if CurRound < high(CurRound) then
- Inc(CurRound)
- else
- CurRound := 0;
+ // set rounds ranking by score if it was not set by plugin
+ if (not Rounds[CurRound].RankingSet) then
+ SetRankingByScore;
+
+ Rounds[CurRound].AlreadyPlayed := True;
+ end;
+end;
+
+{ returns true if last round was already played }
+function TPartyGame.GameFinished: Boolean;
+begin
+ Result := (bPartyStarted and (CurRound = -1));
+end;
- Rounds[CurRound].Winner := 255;
- DllMan.LoadPlugin(Rounds[CurRound].Plugin);
+{ private: calls the specified function Func from lua plugin Parent
+ if both exist.
+ return true if default function should be called
+ (function or plugin does not exist, or function returns
+ true) }
+function TPartyGame.CallLua(Parent: Integer; Func: String):Boolean;
+ var
+ P: TLuaPlugin;
+begin
+ // call default function by default
+ Result := true;
- //Select Players
- for I := 0 to Teams.NumTeams - 1 do
- Teams.Teaminfo[I].CurPlayer := GetRandomPlayer(I);
+ // check for core plugin and empty function name
+ if (Parent >= 0) and (Length(Func) > 0) then
+ begin
+ // get plugin that registred the mode
+ P := LuaCore.GetPluginById(Parent);
- //Set ScreenSingModie Variables
- ScreenSingModi.TeamInfo := Teams;
+ if (P <> nil) then
+ begin
+ if (P.CallFunctionByName(Func, 0, 1)) then
+ // check result
+ Result := (lua_toboolean(P.LuaState, 1));
+ end;
end;
end;
-//----------
-//EndRound - Get Winner from ScreenSingModi and Save Data to RoundArray
-//----------
-procedure TPartySession.EndRound;
-var
- I: Integer;
+{ call plugins defined function and/or default procedure
+ only default procedure is called when no function is defined by plugin
+ if plugins function returns true then default is called after plugins
+ function was executed}
+procedure TPartyGame.CallBeforeSongSelect;
begin
- //Copy Winner
- Rounds[CurRound].Winner := ScreenSingModi.Winner;
- //Set Scores
- GenScores;
+ if (CurRound >= 0) then
+ begin
+ // we set screen song to party mode
+ // plugin should not have to do this if it
+ // don't want default procedure to be executed
+ ScreenSong.Mode := smPartyMode;
+
+ with Modes[Rounds[CurRound].Mode] do
+ if (CallLua(Parent, Functions.BeforeSongSelect)) then
+ begin // execute default function:
+ // display song select screen
+ Display.FadeTo(@ScreenSong);
+ end;
+ end;
+end;
- //Increase TimesPlayed 4 all Players
- For I := 0 to Teams.NumTeams-1 do
- Inc(Teams.Teaminfo[I].Playerinfo[Teams.Teaminfo[I].CurPlayer].TimesPlayed);
+procedure TPartyGame.CallAfterSongSelect;
+begin
+ if (CurRound >= 0) then
+ begin
+ with Modes[Rounds[CurRound].Mode] do
+ if (CallLua(Parent, Functions.AfterSongSelect)) then
+ begin // execute default function:
+ // display sing screen
+ ScreenSong.StartSong;
+ end;
+ end;
end;
-//----------
-//IsWinner - returns true if the player's bit is set in the winner byte
-//----------
-function TPartySession.IsWinner(Player, Winner: byte): boolean;
-var
- Mask: byte;
+procedure TPartyGame.CallBeforeSing;
begin
- Mask := 1 shl Player;
- Result := (Winner and Mask) <> 0;
+ if (CurRound >= 0) then
+ begin
+ with Modes[Rounds[CurRound].Mode] do
+ if (CallLua(Parent, Functions.BeforeSing)) then
+ begin // execute default function:
+
+ //nothing atm
+ { to-do : compartmentalize TSingScreen.OnShow into
+ functions for init of a specific part of
+ sing screen.
+ these functions should be called here before
+ sing screen is shown, or it should be called
+ by plugin if it wants to define a custom
+ singscreen start up. }
+
+ //set correct playersplay
+ if (bPartyGame) then
+ PlayersPlay := Length(Teams);
+ end;
+ end;
end;
-//----------
-//GenScores - increase scores for current round
-//----------
-procedure TPartySession.GenScores;
-var
- I: byte;
+procedure TPartyGame.CallOnSing;
begin
- for I := 0 to Teams.NumTeams - 1 do
+ if (CurRound >= 0) then
begin
- if isWinner(I, Rounds[CurRound].Winner) then
- Inc(Teams.Teaminfo[I].Score);
+ with Modes[Rounds[CurRound].Mode] do
+ if (CallLua(Parent, Functions.OnSing)) then
+ begin // execute default function:
+
+ //nothing atm
+ end;
end;
end;
-//----------
-//GetTeamOrder - returns the placement of each Team [First Position of Array is Teamnum of first placed Team, ...]
-//----------
-function TPartySession.GetTeamOrder: TeamOrderArray;
-var
- I, J: integer;
- ATeams: array [0..5] of TeamOrderEntry;
- TempTeam: TeamOrderEntry;
+procedure TPartyGame.CallAfterSing;
begin
- // TODO: PartyMode: Write this in another way, so that teams with the same score get the same place
- //Fill Team array
- for I := 0 to Teams.NumTeams - 1 do
+ if (CurRound >= 0) then
+ begin
+ with Modes[Rounds[CurRound].Mode] do
+ if (CallLua(Parent, Functions.AfterSing)) then
+ begin // execute default function:
+
+ if (bPartyGame) then
+ // display party score screen
+ Display.FadeTo(@ScreenPartyScore)
+ else //display standard score screen
+ Display.FadeTo(@ScreenScore);
+ end;
+ end;
+end;
+
+{ returns an array[1..6] of integer. the index stands for the placing,
+ value is the team number (in the team array) }
+function TPartyGame.GetTeamRanking: AParty_TeamRanking;
+ var
+ I, J: Integer;
+ Temp: TParty_TeamRanking;
+ Rank: Integer;
+begin
+ SetLength(Result, Length(Teams));
+
+ // fill ranking array
+ for I := 0 to High(Result) do
begin
- ATeams[I].Teamnum := I;
- ATeams[I].Score := Teams.Teaminfo[I].Score;
+ Result[I].Team := I;
+ Result[I].Rank := 0;
end;
- //Sort teams
- for J := 0 to Teams.NumTeams - 1 do
- for I := 1 to Teams.NumTeams - 1 do
- if ATeams[I].Score > ATeams[I-1].Score then
+ // bubble sort by score
+ J := High(Result);
+ repeat
+ for I := 0 to J - 1 do
+ if (Teams[Result[I].Team].Score < Teams[Result[I+1].Team].Score) then
begin
- TempTeam := ATeams[I-1];
- ATeams[I-1] := ATeams[I];
- ATeams[I] := TempTeam;
+ Temp := Result[I];
+ Result[I] := Result[I+1];
+ Result[I+1] := Temp;
end;
+ Dec(J);
+ until J <= 0;
- //Copy to Result
- for I := 0 to Teams.NumTeams-1 do
- Result[I] := ATeams[I].TeamNum;
+ // set rank field
+ Rank := 1; //first rank has id 1
+ for I := 0 to High(Result) do
+ begin
+ Result[I].Rank := Rank;
+
+ if (I < High(Result)) and (Teams[Result[I].Team].Score <> Teams[Result[I+1].Team].Score) then
+ Inc(Rank); // next rank if next team has different score
+ end;
end;
-//----------
-//GetWinnerString - Get string with WinnerTeam Name, when there is more than one Winner than Connect with and or ,
-//----------
-function TPartySession.GetWinnerString(Round: byte): UTF8String;
+{ returns a string like "Team 1 (and Team 2) win"
+ if Round is in range from 0 to high(Rounds) then
+ result is name of winners of specified round.
+ if Round is -1 the result is name of winners of
+ the whole party game}
+function TPartyGame.GetWinnerString(Round: integer): UTF8String;
var
Winners: array of UTF8String;
- I: integer;
+ I: integer;
+ Ranking: AParty_TeamRanking;
begin
- Result := Language.Translate('PARTY_NOBODY');
+ Result := '';
+ Ranking := nil;
- if (Round > High(Rounds)) then
- exit;
-
- if (Rounds[Round].Winner = 0) then
+ if (Round >= 0) and (Round <= High(Rounds)) then
begin
- exit;
- end;
+ if (not Rounds[Round].AlreadyPlayed) then
+ Result := Language.Translate('PARTY_NOTPLAYEDYET')
+ else
+ Ranking := Rounds[Round].Ranking;
+ end
+ else if (Round = -1) then
+ Ranking := GetTeamRanking;
- if (Rounds[Round].Winner = 255) then
- begin
- Result := Language.Translate('PARTY_NOTPLAYEDYET');
- exit;
- end;
- SetLength(Winners, 0);
- for I := 0 to Teams.NumTeams - 1 do
+ if (Ranking <> nil) then
begin
- if isWinner(I, Rounds[Round].Winner) then
+ SetLength(Winners, 0);
+ for I := 0 to High(Ranking) do
begin
- SetLength(Winners, Length(Winners) + 1);
- Winners[high(Winners)] := Teams.TeamInfo[I].Name;
+ if (Ranking[I].Rank = PR_First) and (Ranking[I].Team >= 0) and (Ranking[I].Team <= High(Teams)) then
+ begin
+ SetLength(Winners, Length(Winners) + 1);
+ Winners[high(Winners)] := UTF8String(Teams[Ranking[I].Team].Name);
+ end;
end;
+
+ if (Length(Winners) > 0) then
+ Result := Language.Implode(Winners);
end;
- Result := Language.Implode(Winners);
+
+ if (Length(Result) = 0) then
+ Result := Language.Translate('PARTY_NOBODY');
end;
end.
diff --git a/src/base/USingScores.pas b/src/base/USingScores.pas
index f280900e..6fdfaeb6 100644
--- a/src/base/USingScores.pas
+++ b/src/base/USingScores.pas
@@ -129,7 +129,7 @@ type
//-----------
TSingScores = class
private
- Positions: aScorePosition;
+ aPositions: aScorePosition;
aPlayers: aScorePlayer;
oPositionCount: byte;
oPlayerCount: byte;
@@ -187,6 +187,7 @@ type
property PositionCount: byte read oPositionCount;
property PlayerCount: byte read oPlayerCount;
property Players: aScorePlayer read aPlayers;
+ property Positions: aScorePosition read aPositions;
// constructor just sets some standard settings
constructor Create;
@@ -286,7 +287,7 @@ procedure TSingScores.AddPosition(const pPosition: PScorePosition);
begin
if (PositionCount < MaxPositions) then
begin
- Positions[PositionCount] := pPosition^;
+ aPositions[PositionCount] := pPosition^;
Inc(oPositionCount);
end;
end;
@@ -606,7 +607,7 @@ var
for I := 0 to PositionCount - 1 do
begin
- if ((Positions[I].PlayerCount and bPlayerCount) <> 0) then
+ if ((aPositions[I].PlayerCount and bPlayerCount) <> 0) then
Inc(Result);
end;
end;
@@ -620,7 +621,7 @@ var
for I := 0 to PositionCount - 1 do
begin
- if ((Positions[I].PlayerCount and bPlayerCount) <> 0) then
+ if ((aPositions[I].PlayerCount and bPlayerCount) <> 0) then
begin
if (bPlayer = 0) then
begin
@@ -806,13 +807,13 @@ begin
Progress := TimeDiff / Settings.Phase1Time;
- W := Positions[PIndex].PUW * Sin(Progress/2*Pi);
- H := Positions[PIndex].PUH * Sin(Progress/2*Pi);
+ W := aPositions[PIndex].PUW * Sin(Progress/2*Pi);
+ H := aPositions[PIndex].PUH * Sin(Progress/2*Pi);
- X := Positions[PIndex].PUStartX + (Positions[PIndex].PUW - W)/2;
- Y := Positions[PIndex].PUStartY + (Positions[PIndex].PUH - H)/2;
+ X := aPositions[PIndex].PUStartX + (aPositions[PIndex].PUW - W)/2;
+ Y := aPositions[PIndex].PUStartY + (aPositions[PIndex].PUH - H)/2;
- FontSize := Round(Progress * Positions[PIndex].PUFontSize);
+ FontSize := Round(Progress * aPositions[PIndex].PUFontSize);
FontOffset := (H - FontSize) / 2;
Alpha := 1;
end
@@ -822,20 +823,20 @@ begin
// phase 2 - the moving
Progress := (TimeDiff - Settings.Phase1Time) / Settings.Phase2Time;
- W := Positions[PIndex].PUW;
- H := Positions[PIndex].PUH;
+ W := aPositions[PIndex].PUW;
+ H := aPositions[PIndex].PUH;
- PosDiff := Positions[PIndex].PUTargetX - Positions[PIndex].PUStartX;
+ PosDiff := aPositions[PIndex].PUTargetX - aPositions[PIndex].PUStartX;
if PosDiff > 0 then
PosDiff := PosDiff + W;
- X := Positions[PIndex].PUStartX + PosDiff * sqr(Progress);
+ X := aPositions[PIndex].PUStartX + PosDiff * sqr(Progress);
- PosDiff := Positions[PIndex].PUTargetY - Positions[PIndex].PUStartY;
+ PosDiff := aPositions[PIndex].PUTargetY - aPositions[PIndex].PUStartY;
if PosDiff < 0 then
- PosDiff := PosDiff + Positions[PIndex].BGH;
- Y := Positions[PIndex].PUStartY + PosDiff * sqr(Progress);
+ PosDiff := PosDiff + aPositions[PIndex].BGH;
+ Y := aPositions[PIndex].PUStartY + PosDiff * sqr(Progress);
- FontSize := Positions[PIndex].PUFontSize;
+ FontSize := aPositions[PIndex].PUFontSize;
FontOffset := (H - FontSize) / 2;
Alpha := 1 - 0.3 * Progress;
end
@@ -868,24 +869,24 @@ begin
// set positions etc.
Alpha := 0.7 - 0.7 * Progress;
- W := Positions[PIndex].PUW;
- H := Positions[PIndex].PUH;
+ W := aPositions[PIndex].PUW;
+ H := aPositions[PIndex].PUH;
- PosDiff := Positions[PIndex].PUTargetX - Positions[PIndex].PUStartX;
+ PosDiff := aPositions[PIndex].PUTargetX - aPositions[PIndex].PUStartX;
if (PosDiff > 0) then
PosDiff := W
else
PosDiff := 0;
- X := Positions[PIndex].PUTargetX + PosDiff * Progress;
+ X := aPositions[PIndex].PUTargetX + PosDiff * Progress;
- PosDiff := Positions[PIndex].PUTargetY - Positions[PIndex].PUStartY;
+ PosDiff := aPositions[PIndex].PUTargetY - aPositions[PIndex].PUStartY;
if (PosDiff < 0) then
- PosDiff := -Positions[PIndex].BGH
+ PosDiff := -aPositions[PIndex].BGH
else
PosDiff := 0;
- Y := Positions[PIndex].PUTargetY - PosDiff * (1 - Progress);
+ Y := aPositions[PIndex].PUTargetY - PosDiff * (1 - Progress);
- FontSize := Positions[PIndex].PUFontSize;
+ FontSize := aPositions[PIndex].PUFontSize;
FontOffset := (H - FontSize) / 2;
end
else
@@ -922,7 +923,7 @@ begin
glDisable(GL_BLEND);
// set font style and size
- SetFontStyle(Positions[PIndex].PUFont);
+ SetFontStyle(aPositions[PIndex].PUFont);
SetFontItalic(false);
SetFontSize(FontSize);
SetFontReflection(false, 0);
@@ -958,7 +959,7 @@ begin
// only draw if player is on cur screen
if (((Players[Index].Position and 128) = 0) = (ScreenAct = 1)) and Players[Index].Visible then
begin
- Position := @Positions[Players[Index].Position and 127];
+ Position := @aPositions[Players[Index].Position and 127];
// draw scorebg
glEnable(GL_TEXTURE_2D);
@@ -1010,7 +1011,7 @@ begin
Players[index].RBVisible and
Players[index].Visible) then
begin
- Position := @Positions[Players[Index].Position and 127];
+ Position := @aPositions[Players[Index].Position and 127];
if (Enabled and Players[Index].Enabled) then
begin
diff --git a/src/base/UThemes.pas b/src/base/UThemes.pas
index 4322815e..2ecaa9f4 100644
--- a/src/base/UThemes.pas
+++ b/src/base/UThemes.pas
@@ -648,17 +648,17 @@ type
SelectLevel: TThemeSelectSlide;
SelectPlayList: TThemeSelectSlide;
SelectPlayList2: TThemeSelectSlide;
- SelectRounds: TThemeSelectSlide;
- SelectTeams: TThemeSelectSlide;
- SelectPlayers1: TThemeSelectSlide;
- SelectPlayers2: TThemeSelectSlide;
- SelectPlayers3: TThemeSelectSlide;
{ButtonNext: TThemeButton;
ButtonPrev: TThemeButton;}
end;
TThemePartyPlayer = class(TThemeBasic)
+ SelectTeams: TThemeSelectSlide;
+ SelectPlayers1: TThemeSelectSlide;
+ SelectPlayers2: TThemeSelectSlide;
+ SelectPlayers3: TThemeSelectSlide;
+
Team1Name: TThemeButton;
Player1Name: TThemeButton;
Player2Name: TThemeButton;
@@ -681,6 +681,11 @@ type
ButtonPrev: TThemeButton;}
end;
+ TThemePartyRounds = class(TThemeBasic)
+ SelectRoundCount: TThemeSelectSlide;
+ SelectRound: array [0..6] of TThemeSelectSlide;
+ end;
+
//Stats Screens
TThemeStatMain = class(TThemeBasic)
ButtonScores: TThemeButton;
@@ -756,6 +761,7 @@ type
PartyWin: TThemePartyWin;
PartyOptions: TThemePartyOptions;
PartyPlayer: TThemePartyPlayer;
+ PartyRounds: TThemePartyRounds;
//Stats Screens:
StatMain: TThemeStatMain;
@@ -886,6 +892,7 @@ begin
PartyScore := TThemePartyScore.Create;
PartyOptions := TThemePartyOptions.Create;
PartyPlayer := TThemePartyPlayer.Create;
+ PartyRounds := TThemePartyRounds.Create;
//Stats Screens:
StatMain := TThemeStatMain.Create;
@@ -1435,17 +1442,17 @@ begin
ThemeLoadSelectSlide(PartyOptions.SelectLevel, 'PartyOptionsSelectLevel');
ThemeLoadSelectSlide(PartyOptions.SelectPlayList, 'PartyOptionsSelectPlayList');
ThemeLoadSelectSlide(PartyOptions.SelectPlayList2, 'PartyOptionsSelectPlayList2');
- ThemeLoadSelectSlide(PartyOptions.SelectRounds, 'PartyOptionsSelectRounds');
- ThemeLoadSelectSlide(PartyOptions.SelectTeams, 'PartyOptionsSelectTeams');
- ThemeLoadSelectSlide(PartyOptions.SelectPlayers1, 'PartyOptionsSelectPlayers1');
- ThemeLoadSelectSlide(PartyOptions.SelectPlayers2, 'PartyOptionsSelectPlayers2');
- ThemeLoadSelectSlide(PartyOptions.SelectPlayers3, 'PartyOptionsSelectPlayers3');
-
{ThemeLoadButton (ButtonNext, 'ButtonNext');
ThemeLoadButton (ButtonPrev, 'ButtonPrev');}
//Party Player
ThemeLoadBasic(PartyPlayer, 'PartyPlayer');
+
+ ThemeLoadSelectSlide(PartyPlayer.SelectTeams, 'PartyPlayerSelectTeams');
+ ThemeLoadSelectSlide(PartyPlayer.SelectPlayers1, 'PartyPlayerSelectPlayers1');
+ ThemeLoadSelectSlide(PartyPlayer.SelectPlayers2, 'PartyPlayerSelectPlayers2');
+ ThemeLoadSelectSlide(PartyPlayer.SelectPlayers3, 'PartyPlayerSelectPlayers3');
+
ThemeLoadButton(PartyPlayer.Team1Name, 'PartyPlayerTeam1Name');
ThemeLoadButton(PartyPlayer.Player1Name, 'PartyPlayerPlayer1Name');
ThemeLoadButton(PartyPlayer.Player2Name, 'PartyPlayerPlayer2Name');
@@ -1464,6 +1471,13 @@ begin
ThemeLoadButton(PartyPlayer.Player11Name, 'PartyPlayerPlayer11Name');
ThemeLoadButton(PartyPlayer.Player12Name, 'PartyPlayerPlayer12Name');
+ // Party Rounds
+ ThemeLoadBasic(PartyRounds, 'PartyRounds');
+
+ ThemeLoadSelectSlide(PartyRounds.SelectRoundCount, 'PartyRoundsSelectRoundCount');
+ for I := 0 to High(PartyRounds.SelectRound) do
+ ThemeLoadSelectSlide(PartyRounds.SelectRound[I], 'PartyRoundsSelectRound' + IntToStr(I + 1));
+
{ThemeLoadButton(ButtonNext, 'PartyPlayerButtonNext');
ThemeLoadButton(ButtonPrev, 'PartyPlayerButtonPrev');}
diff --git a/src/lib/Lua/ULua.pas b/src/lib/Lua/ULua.pas
new file mode 100644
index 00000000..3da3a275
--- /dev/null
+++ b/src/lib/Lua/ULua.pas
@@ -0,0 +1,1085 @@
+unit ULua;
+
+(*
+ * A complete Pascal wrapper for Lua 5.1 DLL module.
+ *
+ * Created by Geo Massar, 2006
+ * Distributed as free/open source.
+ *)
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$IFDEF UNIX}
+uses
+ dl;
+{$ENDIF}
+
+{$DEFINE LUA51}
+
+type
+ size_t = type Cardinal;
+ Psize_t = ^size_t;
+ PPointer = ^Pointer;
+
+ lua_State = record end;
+ Plua_State = ^lua_State;
+
+const
+{$IFDEF WIN32}
+ LuaDLL = 'lua5.1.dll';
+{$ENDIF}
+{$IFDEF UNIX}
+{$IFDEF DARWIN}
+ LuaDLL = 'liblua.5.1.dylib';
+ {$linklib liblua.5.1}
+{$ELSE}
+ LuaDLL = 'lua5.1.so';
+{$ENDIF}
+{$ENDIF}
+{$IFDEF MACOS}
+ SDLgfxLibName = 'lua5.1';
+{$ENDIF}
+
+(* formats for Lua numbers *)
+{$IFNDEF LUA_NUMBER_SCAN}
+const
+ LUA_NUMBER_SCAN = '%lf';
+{$ENDIF}
+
+{$IFNDEF LUA_NUMBER_FMT}
+const
+ LUA_NUMBER_FMT = '%.14g';
+{$ENDIF}
+
+(*****************************************************************************)
+(* luaconfig.h *)
+(*****************************************************************************)
+
+(*
+** $Id: luaconf.h,v 1.81 2006/02/10 17:44:06 roberto Exp $
+** Configuration file for Lua
+** See Copyright Notice in lua.h
+*)
+
+(*
+** {==================================================================
+@@ LUA_NUMBER is the type of numbers in Lua.
+** CHANGE the following definitions only if you want to build Lua
+** with a number type different from double. You may also need to
+** change lua_number2int & lua_number2integer.
+** ===================================================================
+*)
+type
+ LUA_NUMBER_ = type Double; // ending underscore is needed in Pascal
+ LUA_INTEGER_ = type Integer;
+
+(*
+@@ LUA_IDSIZE gives the maximum size for the description of the source
+@* of a function in debug information.
+** CHANGE it if you want a different size.
+*)
+const
+ LUA_IDSIZE = 60;
+
+(*
+@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.
+*)
+const
+ LUAL_BUFFERSIZE = 1024;
+
+(*
+@@ LUA_PROMPT is the default prompt used by stand-alone Lua.
+@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.
+** CHANGE them if you want different prompts. (You can also change the
+** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
+*)
+const
+ LUA_PROMPT = '> ';
+ LUA_PROMPT2 = '>> ';
+
+(*
+@@ lua_readline defines how to show a prompt and then read a line from
+@* the standard input.
+@@ lua_saveline defines how to "save" a read line in a "history".
+@@ lua_freeline defines how to free a line read by lua_readline.
+** CHANGE them if you want to improve this functionality (e.g., by using
+** GNU readline and history facilities).
+*)
+function lua_readline(L : Plua_State; var b : PChar; p : PChar): Boolean;
+procedure lua_saveline(L : Plua_State; idx : Integer);
+procedure lua_freeline(L : Plua_State; b : PChar);
+
+(*
+@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that
+@* is, whether we're running lua interactively).
+** CHANGE it if you have a better definition for non-POSIX/non-Windows
+** systems.
+*/
+#include <io.h>
+#include <stdio.h>
+#define lua_stdin_is_tty() _isatty(_fileno(stdin))
+*)
+const
+ lua_stdin_is_tty = TRUE;
+
+(*****************************************************************************)
+(* lua.h *)
+(*****************************************************************************)
+
+(*
+** $Id: lua.h,v 1.216 2006/01/10 12:50:13 roberto Exp $
+** Lua - An Extensible Extension Language
+** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
+** See Copyright Notice at the end of this file
+*)
+
+const
+ LUA_VERSION = 'Lua 5.1';
+ LUA_VERSION_NUM = 501;
+ LUA_COPYRIGHT = 'Copyright (C) 1994-2006 Tecgraf, PUC-Rio';
+ LUA_AUTHORS = 'R. Ierusalimschy, L. H. de Figueiredo & W. Celes';
+
+ (* mark for precompiled code (`<esc>Lua') *)
+ LUA_SIGNATURE = #27'Lua';
+
+ (* option for multiple returns in `lua_pcall' and `lua_call' *)
+ LUA_MULTRET = -1;
+
+ (*
+ ** pseudo-indices
+ *)
+ LUA_REGISTRYINDEX = -10000;
+ LUA_ENVIRONINDEX = -10001;
+ LUA_GLOBALSINDEX = -10002;
+
+function lua_upvalueindex(idx : Integer) : Integer; // a marco
+
+const
+ (* thread status; 0 is OK *)
+ LUA_YIELD_ = 1; // Note: the ending underscore is needed in Pascal
+ LUA_ERRRUN = 2;
+ LUA_ERRSYNTAX = 3;
+ LUA_ERRMEM = 4;
+ LUA_ERRERR = 5;
+
+type
+ lua_CFunction = function(L : Plua_State) : Integer; cdecl;
+
+ (*
+ ** functions that read/write blocks when loading/dumping Lua chunks
+ *)
+ lua_Reader = function (L : Plua_State; ud : Pointer;
+ sz : Psize_t) : PChar; cdecl;
+ lua_Writer = function (L : Plua_State; const p : Pointer; sz : size_t;
+ ud : Pointer) : Integer; cdecl;
+
+ (*
+ ** prototype for memory-allocation functions
+ *)
+ lua_Alloc = function (ud, ptr : Pointer;
+ osize, nsize : size_t) : Pointer; cdecl;
+
+const
+ (*
+ ** basic types
+ *)
+ LUA_TNONE = -1;
+
+ LUA_TNIL = 0;
+ LUA_TBOOLEAN = 1;
+ LUA_TLIGHTUSERDATA = 2;
+ LUA_TNUMBER = 3;
+ LUA_TSTRING = 4;
+ LUA_TTABLE = 5;
+ LUA_TFUNCTION = 6;
+ LUA_TUSERDATA = 7;
+ LUA_TTHREAD = 8;
+
+ (* minimum Lua stack available to a C function *)
+ LUA_MINSTACK = 20;
+
+type
+ (* type of numbers in Lua *)
+ lua_Number = LUA_NUMBER_;
+
+ (* type for integer functions *)
+ lua_Integer = LUA_INTEGER_;
+
+(*
+** state manipulation
+*)
+function lua_newstate(f : lua_Alloc; ud : Pointer) : Plua_State;
+ cdecl; external LuaDLL;
+procedure lua_close(L: Plua_State);
+ cdecl; external LuaDLL;
+function lua_newthread(L : Plua_State) : Plua_State;
+ cdecl; external LuaDLL;
+
+function lua_atpanic(L : Plua_State; panicf : lua_CFunction) : lua_CFunction;
+ cdecl; external LuaDLL;
+
+
+(*
+** basic stack manipulation
+*)
+function lua_gettop(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+procedure lua_settop(L : Plua_State; idx : Integer);
+ cdecl; external LuaDLL;
+procedure lua_pushvalue(L : Plua_State; idx : Integer);
+ cdecl; external LuaDLL;
+procedure lua_remove(L : Plua_State; idx : Integer);
+ cdecl; external LuaDLL;
+procedure lua_insert(L : Plua_State; idx : Integer);
+ cdecl; external LuaDLL;
+procedure lua_replace(L : Plua_State; idx : Integer);
+ cdecl; external LuaDLL;
+function lua_checkstack(L : Plua_State; sz : Integer) : LongBool;
+ cdecl; external LuaDLL;
+
+procedure lua_xmove(src, dest : Plua_State; n : Integer);
+ cdecl; external LuaDLL;
+
+
+(*
+** access functions (stack -> C)
+*)
+function lua_isnumber(L : Plua_State; idx : Integer) : LongBool;
+ cdecl; external LuaDLL;
+function lua_isstring(L : Plua_State; idx : Integer) : LongBool;
+ cdecl; external LuaDLL;
+function lua_iscfunction(L : Plua_State; idx : Integer) : LongBool;
+ cdecl; external LuaDLL;
+function lua_isuserdata(L : Plua_State; idx : Integer) : LongBool;
+ cdecl; external LuaDLL;
+function lua_type(L : Plua_State; idx : Integer) : Integer;
+ cdecl; external LuaDLL;
+function lua_typename(L : Plua_State; tp : Integer) : PChar;
+ cdecl; external LuaDLL;
+
+function lua_equal(L : Plua_State; idx1, idx2 : Integer) : LongBool;
+ cdecl; external LuaDLL;
+function lua_rawequal(L : Plua_State; idx1, idx2 : Integer) : LongBool;
+ cdecl; external LuaDLL;
+function lua_lessthan(L : Plua_State; idx1, idx2 : Integer) : LongBool;
+ cdecl; external LuaDLL;
+
+function lua_tonumber(L : Plua_State; idx : Integer) : lua_Number;
+ cdecl; external LuaDLL;
+function lua_tointeger(L : Plua_State; idx : Integer) : lua_Integer;
+ cdecl; external LuaDLL;
+function lua_toboolean(L : Plua_State; idx : Integer) : LongBool;
+ cdecl; external LuaDLL;
+function lua_tolstring(L : Plua_State; idx : Integer;
+ len : Psize_t) : PChar;
+ cdecl; external LuaDLL;
+function lua_objlen(L : Plua_State; idx : Integer) : size_t;
+ cdecl; external LuaDLL;
+function lua_tocfunction(L : Plua_State; idx : Integer) : lua_CFunction;
+ cdecl; external LuaDLL;
+function lua_touserdata(L : Plua_State; idx : Integer) : Pointer;
+ cdecl; external LuaDLL;
+function lua_tothread(L : Plua_State; idx : Integer) : Plua_State;
+ cdecl; external LuaDLL;
+function lua_topointer(L : Plua_State; idx : Integer) : Pointer;
+ cdecl; external LuaDLL;
+
+
+(*
+** push functions (C -> stack)
+*)
+procedure lua_pushnil(L : Plua_State);
+ cdecl; external LuaDLL;
+procedure lua_pushnumber(L : Plua_State; n : lua_Number);
+ cdecl; external LuaDLL;
+procedure lua_pushinteger(L : Plua_State; n : lua_Integer);
+ cdecl; external LuaDLL;
+procedure lua_pushlstring(L : Plua_State; const s : PChar; ls : size_t);
+ cdecl; external LuaDLL;
+procedure lua_pushstring(L : Plua_State; const s : PChar);
+ cdecl; external LuaDLL;
+function lua_pushvfstring(L : Plua_State;
+ const fmt : PChar; argp : Pointer) : PChar;
+ cdecl; external LuaDLL;
+function lua_pushfstring(L : Plua_State; const fmt : PChar) : PChar; varargs;
+ cdecl; external LuaDLL;
+procedure lua_pushcclosure(L : Plua_State; fn : lua_CFunction; n : Integer);
+ cdecl; external LuaDLL;
+procedure lua_pushboolean(L : Plua_State; b : LongBool);
+ cdecl; external LuaDLL;
+procedure lua_pushlightuserdata(L : Plua_State; p : Pointer);
+ cdecl; external LuaDLL;
+function lua_pushthread(L : Plua_state) : Cardinal;
+ cdecl; external LuaDLL;
+
+
+(*
+** get functions (Lua -> stack)
+*)
+procedure lua_gettable(L : Plua_State ; idx : Integer);
+ cdecl; external LuaDLL;
+procedure lua_getfield(L : Plua_State; idx : Integer; k : PChar);
+ cdecl; external LuaDLL;
+procedure lua_rawget(L : Plua_State; idx : Integer);
+ cdecl; external LuaDLL;
+procedure lua_rawgeti(L : Plua_State; idx, n : Integer);
+ cdecl; external LuaDLL;
+procedure lua_createtable(L : Plua_State; narr, nrec : Integer);
+ cdecl; external LuaDLL;
+function lua_newuserdata(L : Plua_State; sz : size_t) : Pointer;
+ cdecl; external LuaDLL;
+function lua_getmetatable(L : Plua_State; objindex : Integer) : LongBool;
+ cdecl; external LuaDLL;
+procedure lua_getfenv(L : Plua_State; idx : Integer);
+ cdecl; external LuaDLL;
+
+
+(*
+** set functions (stack -> Lua)
+*)
+procedure lua_settable(L : Plua_State; idx : Integer);
+ cdecl; external LuaDLL;
+procedure lua_setfield(L : Plua_State; idx : Integer; const k : PChar);
+ cdecl; external LuaDLL;
+procedure lua_rawset(L : Plua_State; idx : Integer);
+ cdecl; external LuaDLL;
+procedure lua_rawseti(L : Plua_State; idx , n: Integer);
+ cdecl; external LuaDLL;
+function lua_setmetatable(L : Plua_State; objindex : Integer): LongBool;
+ cdecl; external LuaDLL;
+function lua_setfenv(L : Plua_State; idx : Integer): LongBool;
+ cdecl; external LuaDLL;
+
+(*
+** `load' and `call' functions (load and run Lua code)
+*)
+procedure lua_call(L : Plua_State; nargs, nresults : Integer);
+ cdecl; external LuaDLL;
+function lua_pcall(L : Plua_State;
+ nargs, nresults, errfunc : Integer) : Integer;
+ cdecl; external LuaDLL;
+function lua_cpcall(L : Plua_State;
+ func : lua_CFunction; ud : Pointer) : Integer;
+ cdecl; external LuaDLL;
+function lua_load(L : Plua_State; reader : lua_Reader;
+ dt : Pointer; const chunkname : PChar) : Integer;
+ cdecl; external LuaDLL;
+
+function lua_dump(L : Plua_State; writer : lua_Writer; data: Pointer) : Integer;
+ cdecl; external LuaDLL;
+
+
+(*
+** coroutine functions
+*)
+function lua_yield(L : Plua_State; nresults : Integer) : Integer;
+ cdecl; external LuaDLL;
+function lua_resume(L : Plua_State; narg : Integer) : Integer;
+ cdecl; external LuaDLL;
+function lua_status(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+(*
+** garbage-collection functions and options
+*)
+const
+ LUA_GCSTOP = 0;
+ LUA_GCRESTART = 1;
+ LUA_GCCOLLECT = 2;
+ LUA_GCCOUNT = 3;
+ LUA_GCCOUNTB = 4;
+ LUA_GCSTEP = 5;
+ LUA_GCSETPAUSE = 6;
+ LUA_GCSETSTEPMUL = 7;
+
+function lua_gc(L : Plua_State; what, data : Integer) : Integer;
+ cdecl; external LuaDLL;
+
+(*
+** miscellaneous functions
+*)
+function lua_error(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+function lua_next(L : Plua_State; idx : Integer) : Integer;
+ cdecl; external LuaDLL;
+
+procedure lua_concat(L : Plua_State; n : Integer);
+ cdecl; external LuaDLL;
+
+function lua_getallocf(L : Plua_State; ud : PPointer) : lua_Alloc;
+ cdecl; external LuaDLL;
+procedure lua_setallocf(L : Plua_State; f : lua_Alloc; ud : Pointer);
+ cdecl; external LuaDLL;
+
+(*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*)
+procedure lua_pop(L : Plua_State; n : Integer);
+
+procedure lua_newtable(L : Plua_State);
+
+procedure lua_register(L : Plua_State; n : PChar; f : lua_CFunction);
+
+procedure lua_pushcfunction(L : Plua_State; f : lua_CFunction);
+
+function lua_strlen(L : Plua_State; idx : Integer) : Integer;
+
+function lua_isfunction(L : Plua_State; n : Integer) : Boolean;
+function lua_istable(L : Plua_State; n : Integer) : Boolean;
+function lua_islightuserdata(L : Plua_State; n : Integer) : Boolean;
+function lua_isnil(L : Plua_State; n : Integer) : Boolean;
+function lua_isboolean(L : Plua_State; n : Integer) : Boolean;
+function lua_isthread(L : Plua_State; n : Integer) : Boolean;
+function lua_isnone(L : Plua_State; n : Integer) : Boolean;
+function lua_isnoneornil(L : Plua_State; n : Integer) : Boolean;
+
+procedure lua_pushliteral(L : Plua_State; s : PChar);
+
+procedure lua_setglobal(L : Plua_State; s : PChar);
+procedure lua_getglobal(L : Plua_State; s : PChar);
+
+function lua_tostring(L : Plua_State; idx : Integer) : PChar;
+
+
+(*
+** compatibility macros and functions
+*)
+function lua_open : Plua_State;
+
+procedure lua_getregistry(L : Plua_State);
+
+function lua_getgccount(L : Plua_State) : Integer;
+
+type
+ lua_Chuckreader = type lua_Reader;
+ lua_Chuckwriter = type lua_Writer;
+
+(* ====================================================================== *)
+
+(*
+** {======================================================================
+** Debug API
+** =======================================================================
+*)
+
+(*
+** Event codes
+*)
+const
+ LUA_HOOKCALL = 0;
+ LUA_HOOKRET = 1;
+ LUA_HOOKLINE = 2;
+ LUA_HOOKCOUNT = 3;
+ LUA_HOOKTAILRET = 4;
+
+
+(*
+** Event masks
+*)
+ LUA_MASKCALL = 1 shl LUA_HOOKCALL;
+ LUA_MASKRET = 1 shl LUA_HOOKRET;
+ LUA_MASKLINE = 1 shl LUA_HOOKLINE;
+ LUA_MASKCOUNT = 1 shl LUA_HOOKCOUNT;
+
+type
+ lua_Debug = packed record
+ event : Integer;
+ name : PChar; (* (n) *)
+ namewhat : PChar; (* (n) `global', `local', `field', `method' *)
+ what : PChar; (* (S) `Lua', `C', `main', `tail' *)
+ source : PChar; (* (S) *)
+ currentline : Integer; (* (l) *)
+ nups : Integer; (* (u) number of upvalues *)
+ linedefined : Integer; (* (S) *)
+ short_src : array [0..LUA_IDSIZE-1] of Char; (* (S) *)
+ (* private part *)
+ i_ci : Integer; (* active function *)
+ end;
+ Plua_Debug = ^lua_Debug;
+
+ (* Functions to be called by the debuger in specific events *)
+ lua_Hook = procedure (L : Plua_State; ar : Plua_Debug); cdecl;
+
+
+function lua_getstack(L : Plua_State; level : Integer;
+ ar : Plua_Debug) : Integer;
+ cdecl; external LuaDLL;
+function lua_getinfo(L : Plua_State; const what : PChar;
+ ar: Plua_Debug): Integer;
+ cdecl; external LuaDLL;
+function lua_getlocal(L : Plua_State;
+ ar : Plua_Debug; n : Integer) : PChar;
+ cdecl; external LuaDLL;
+function lua_setlocal(L : Plua_State;
+ ar : Plua_Debug; n : Integer) : PChar;
+ cdecl; external LuaDLL;
+function lua_getupvalue(L : Plua_State; funcindex, n : Integer) : PChar;
+ cdecl; external LuaDLL;
+function lua_setupvalue(L : Plua_State; funcindex, n : Integer) : PChar;
+ cdecl; external LuaDLL;
+
+function lua_sethook(L : Plua_State; func : lua_Hook;
+ mask, count: Integer): Integer;
+ cdecl; external LuaDLL;
+{
+function lua_gethook(L : Plua_State) : lua_Hook;
+ cdecl; external LuaDLL;
+}
+function lua_gethookmask(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+function lua_gethookcount(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+
+(*****************************************************************************)
+(* lualib.h *)
+(*****************************************************************************)
+
+(*
+** $Id: lualib.h,v 1.36 2005/12/27 17:12:00 roberto Exp $
+** Lua standard libraries
+** See Copyright Notice at the end of this file
+*)
+
+const
+ (* Key to file-handle type *)
+ LUA_FILEHANDLE = 'FILE*';
+
+ LUA_COLIBNAME = 'coroutine';
+ LUA_TABLIBNAME = 'table';
+ LUA_IOLIBNAME = 'io';
+ LUA_OSLIBNAME = 'os';
+ LUA_STRLIBNAME = 'string';
+ LUA_MATHLIBNAME = 'math';
+ LUA_DBLIBNAME = 'debug';
+ LUA_LOADLIBNAME = 'package';
+
+function luaopen_base(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+function luaopen_table(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+function luaopen_io(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+function luaopen_os(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+function luaopen_string(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+function luaopen_math(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+function luaopen_debug(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+function luaopen_package(L : Plua_State) : Integer;
+ cdecl; external LuaDLL;
+
+procedure luaL_openlibs(L : Plua_State);
+ cdecl; external LuaDLL;
+
+procedure lua_assert(x : Boolean); // a macro
+
+
+(*****************************************************************************)
+(* lauxlib.h *)
+(*****************************************************************************)
+
+(*
+** $Id: lauxlib.h,v 1.87 2005/12/29 15:32:11 roberto Exp $
+** Auxiliary functions for building Lua libraries
+** See Copyright Notice at the end of this file.
+*)
+
+// not compatibility with the behavior of setn/getn in Lua 5.0
+function luaL_getn(L : Plua_State; idx : Integer) : Integer;
+procedure luaL_setn(L : Plua_State; i, j : Integer);
+
+const
+ LUA_ERRFILE = LUA_ERRERR + 1;
+
+type
+ luaL_Reg = packed record
+ name : PChar;
+ func : lua_CFunction;
+ end;
+ PluaL_Reg = ^luaL_Reg;
+
+
+procedure luaL_openlib(L : Plua_State; const libname : PChar;
+ const lr : PluaL_Reg; nup : Integer);
+ cdecl; external LuaDLL;
+procedure luaL_register(L : Plua_State; const libname : PChar;
+ const lr : PluaL_Reg);
+ cdecl; external LuaDLL;
+function luaL_getmetafield(L : Plua_State; obj : Integer;
+ const e : PChar) : Integer;
+ cdecl; external LuaDLL;
+function luaL_callmeta(L : Plua_State; obj : Integer;
+ const e : PChar) : Integer;
+ cdecl; external LuaDLL;
+function luaL_typerror(L : Plua_State; narg : Integer;
+ const tname : PChar) : Integer;
+ cdecl; external LuaDLL;
+function luaL_argerror(L : Plua_State; numarg : Integer;
+ const extramsg : PChar) : Integer;
+ cdecl; external LuaDLL;
+function luaL_checklstring(L : Plua_State; numArg : Integer;
+ ls : Psize_t) : PChar;
+ cdecl; external LuaDLL;
+function luaL_optlstring(L : Plua_State; numArg : Integer;
+ const def: PChar; ls: Psize_t) : PChar;
+ cdecl; external LuaDLL;
+function luaL_checknumber(L : Plua_State; numArg : Integer) : lua_Number;
+ cdecl; external LuaDLL;
+function luaL_optnumber(L : Plua_State; nArg : Integer;
+ def : lua_Number) : lua_Number;
+ cdecl; external LuaDLL;
+
+function luaL_checkinteger(L : Plua_State; numArg : Integer) : lua_Integer;
+ cdecl; external LuaDLL;
+function luaL_optinteger(L : Plua_State; nArg : Integer;
+ def : lua_Integer) : lua_Integer;
+ cdecl; external LuaDLL;
+
+procedure luaL_checkstack(L : Plua_State; sz : Integer; const msg : PChar);
+ cdecl; external LuaDLL;
+procedure luaL_checktype(L : Plua_State; narg, t : Integer);
+ cdecl; external LuaDLL;
+procedure luaL_checkany(L : Plua_State; narg : Integer);
+ cdecl; external LuaDLL;
+
+function luaL_newmetatable(L : Plua_State; const tname : PChar) : Integer;
+ cdecl; external LuaDLL;
+function luaL_checkudata(L : Plua_State; ud : Integer;
+ const tname : PChar) : Pointer;
+ cdecl; external LuaDLL;
+
+procedure luaL_where(L : Plua_State; lvl : Integer);
+ cdecl; external LuaDLL;
+function luaL_error(L : Plua_State; const fmt : PChar) : Integer; varargs;
+ cdecl; external LuaDLL;
+
+function luaL_checkoption(L : Plua_State; narg : Integer; const def : PChar;
+ const lst : array of PChar) : Integer;
+ cdecl; external LuaDLL;
+
+function luaL_ref(L : Plua_State; t : Integer) : Integer;
+ cdecl; external LuaDLL;
+procedure luaL_unref(L : Plua_State; t, ref : Integer);
+ cdecl; external LuaDLL;
+
+function luaL_loadfile(L : Plua_State; const filename : PChar) : Integer;
+ cdecl; external LuaDLL;
+function luaL_loadbuffer(L : Plua_State; const buff : PChar;
+ sz : size_t; const name: PChar) : Integer;
+ cdecl; external LuaDLL;
+
+function luaL_loadstring(L : Plua_State; const s : Pchar) : Integer;
+ cdecl; external LuaDLL;
+
+function luaL_newstate : Plua_State;
+ cdecl; external LuaDLL;
+
+function luaL_gsub(L : Plua_State; const s, p, r : PChar) : PChar;
+ cdecl; external LuaDLL;
+
+function luaL_findtable(L : Plua_State; idx : Integer;
+ const fname : PChar; szhint : Integer) : PChar;
+ cdecl; external LuaDLL;
+
+
+(*
+** ===============================================================
+** some useful macros
+** ===============================================================
+*)
+
+function luaL_argcheck(L : Plua_State; cond : Boolean; numarg : Integer;
+ extramsg : PChar): Integer;
+function luaL_checkstring(L : Plua_State; n : Integer) : PChar;
+function luaL_optstring(L : Plua_State; n : Integer; d : PChar) : PChar;
+function luaL_checkint(L : Plua_State; n : Integer) : Integer;
+function luaL_optint(L : Plua_State; n, d : Integer): Integer;
+function luaL_checklong(L : Plua_State; n : LongInt) : LongInt;
+function luaL_optlong(L : Plua_State; n : Integer; d : LongInt) : LongInt;
+
+function luaL_typename(L : Plua_State; idx : Integer) : PChar;
+
+function luaL_dofile(L : Plua_State; fn : PChar) : Integer;
+
+function luaL_dostring(L : Plua_State; s : PChar) : Integer;
+
+procedure luaL_getmetatable(L : Plua_State; n : PChar);
+
+(* not implemented yet
+#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
+*)
+
+(*
+** {======================================================
+** Generic Buffer manipulation
+** =======================================================
+*)
+
+type
+ luaL_Buffer = packed record
+ p : PChar; (* current position in buffer *)
+ lvl : Integer; (* number of strings in the stack (level) *)
+ L : Plua_State;
+ buffer : array [0..LUAL_BUFFERSIZE-1] of Char;
+ end;
+ PluaL_Buffer = ^luaL_Buffer;
+
+procedure luaL_addchar(B : PluaL_Buffer; c : Char);
+
+(* compatibility only *)
+procedure luaL_putchar(B : PluaL_Buffer; c : Char);
+
+procedure luaL_addsize(B : PluaL_Buffer; n : Integer);
+
+procedure luaL_buffinit(L : Plua_State; B : PluaL_Buffer);
+ cdecl; external LuaDLL;
+function luaL_prepbuffer(B : PluaL_Buffer) : PChar;
+ cdecl; external LuaDLL;
+procedure luaL_addlstring(B : PluaL_Buffer; const s : PChar; ls : size_t);
+ cdecl; external LuaDLL;
+procedure luaL_addstring(B : PluaL_Buffer; const s : PChar);
+ cdecl; external LuaDLL;
+procedure luaL_addvalue(B : PluaL_Buffer);
+ cdecl; external LuaDLL;
+procedure luaL_pushresult(B : PluaL_Buffer);
+ cdecl; external LuaDLL;
+
+(* ====================================================== *)
+
+
+(* compatibility with ref system *)
+
+(* pre-defined references *)
+const
+ LUA_NOREF = -2;
+ LUA_REFNIL = -1;
+
+function lua_ref(L : Plua_State; lock : Boolean) : Integer;
+
+procedure lua_unref(L : Plua_State; ref : Integer);
+
+procedure lua_getref(L : Plua_State; ref : Integer);
+
+
+(******************************************************************************)
+(******************************************************************************)
+(******************************************************************************)
+
+implementation
+
+uses
+ SysUtils;
+
+(*****************************************************************************)
+(* luaconfig.h *)
+(*****************************************************************************)
+
+function lua_readline(L : Plua_State; var b : PChar; p : PChar): Boolean;
+var
+ s : AnsiString;
+begin
+ Write(p); // show prompt
+ ReadLn(s); // get line
+ b := PChar(s); // and return it
+ lua_readline := (b[0] <> #4); // test for ctrl-D
+end;
+
+procedure lua_saveline(L : Plua_State; idx : Integer);
+begin
+end;
+
+procedure lua_freeline(L : Plua_State; b : PChar);
+begin
+end;
+
+
+(*****************************************************************************)
+(* lua.h *)
+(*****************************************************************************)
+
+function lua_upvalueindex(idx : Integer) : Integer;
+begin
+ lua_upvalueindex := LUA_GLOBALSINDEX - idx;
+end;
+
+procedure lua_pop(L : Plua_State; n : Integer);
+begin
+ lua_settop(L, -n - 1);
+end;
+
+procedure lua_newtable(L : Plua_State);
+begin
+ lua_createtable(L, 0, 0);
+end;
+
+procedure lua_register(L : Plua_State; n : PChar; f : lua_CFunction);
+begin
+ lua_pushcfunction(L, f);
+ lua_setglobal(L, n);
+end;
+
+procedure lua_pushcfunction(L : Plua_State; f : lua_CFunction);
+begin
+ lua_pushcclosure(L, f, 0);
+end;
+
+function lua_strlen(L : Plua_State; idx : Integer) : Integer;
+begin
+ lua_strlen := lua_objlen(L, idx);
+end;
+
+function lua_isfunction(L : Plua_State; n : Integer) : Boolean;
+begin
+ lua_isfunction := lua_type(L, n) = LUA_TFUNCTION;
+end;
+
+function lua_istable(L : Plua_State; n : Integer) : Boolean;
+begin
+ lua_istable := lua_type(L, n) = LUA_TTABLE;
+end;
+
+function lua_islightuserdata(L : Plua_State; n : Integer) : Boolean;
+begin
+ lua_islightuserdata := lua_type(L, n) = LUA_TLIGHTUSERDATA;
+end;
+
+function lua_isnil(L : Plua_State; n : Integer) : Boolean;
+begin
+ lua_isnil := lua_type(L, n) = LUA_TNIL;
+end;
+
+function lua_isboolean(L : Plua_State; n : Integer) : Boolean;
+begin
+ lua_isboolean := lua_type(L, n) = LUA_TBOOLEAN;
+end;
+
+function lua_isthread(L : Plua_State; n : Integer) : Boolean;
+begin
+ lua_isthread := lua_type(L, n) = LUA_TTHREAD;
+end;
+
+function lua_isnone(L : Plua_State; n : Integer) : Boolean;
+begin
+ lua_isnone := lua_type(L, n) = LUA_TNONE;
+end;
+
+function lua_isnoneornil(L : Plua_State; n : Integer) : Boolean;
+begin
+ lua_isnoneornil := lua_type(L, n) <= 0;
+end;
+
+procedure lua_pushliteral(L : Plua_State; s : PChar);
+begin
+ lua_pushlstring(L, s, StrLen(s));
+end;
+
+procedure lua_setglobal(L : Plua_State; s : PChar);
+begin
+ lua_setfield(L, LUA_GLOBALSINDEX, s);
+end;
+
+procedure lua_getglobal(L: Plua_State; s: PChar);
+begin
+ lua_getfield(L, LUA_GLOBALSINDEX, s);
+end;
+
+function lua_tostring(L : Plua_State; idx : Integer) : PChar;
+begin
+ lua_tostring := lua_tolstring(L, idx, nil);
+end;
+
+function lua_open : Plua_State;
+begin
+ lua_open := luaL_newstate;
+end;
+
+procedure lua_getregistry(L : Plua_State);
+begin
+ lua_pushvalue(L, LUA_REGISTRYINDEX);
+end;
+
+function lua_getgccount(L : Plua_State) : Integer;
+begin
+ lua_getgccount := lua_gc(L, LUA_GCCOUNT, 0);
+end;
+
+
+(*****************************************************************************)
+(* lualib.h *)
+(*****************************************************************************)
+
+procedure lua_assert(x : Boolean);
+begin
+end;
+
+
+(*****************************************************************************)
+(* lauxlib.h n *)
+(*****************************************************************************)
+
+function luaL_getn(L : Plua_State; idx : Integer) : Integer;
+begin
+ luaL_getn := lua_objlen(L, idx);
+end;
+
+procedure luaL_setn(L : plua_State; i, j : Integer);
+begin
+ (* no op *)
+end;
+
+function luaL_argcheck(L : Plua_State; cond : Boolean; numarg : Integer;
+ extramsg : PChar): Integer;
+begin
+ if not cond then
+ luaL_argcheck := luaL_argerror(L, numarg, extramsg)
+ else
+ luaL_argcheck := 0;
+end;
+
+function luaL_checkstring(L : Plua_State; n : Integer) : PChar;
+begin
+ luaL_checkstring := luaL_checklstring(L, n, nil);
+end;
+
+function luaL_optstring(L : Plua_State; n : Integer; d : PChar) : PChar;
+begin
+ luaL_optstring := luaL_optlstring(L, n, d, nil);
+end;
+
+function luaL_checkint(L : Plua_State; n : Integer) : Integer;
+begin
+ luaL_checkint := luaL_checkinteger(L, n);
+end;
+
+function luaL_optint(L : Plua_State; n, d : Integer): Integer;
+begin
+ luaL_optint := luaL_optinteger(L, n, d);
+end;
+
+function luaL_checklong(L : Plua_State; n : LongInt) : LongInt;
+begin
+ luaL_checklong := luaL_checkinteger(L, n);
+end;
+
+function luaL_optlong(L : Plua_State; n : Integer; d : LongInt) : LongInt;
+begin
+ luaL_optlong := luaL_optinteger(L, n, d);
+end;
+
+function luaL_typename(L : Plua_State; idx : Integer) : PChar;
+begin
+ luaL_typename := lua_typename( L, lua_type(L, idx) );
+end;
+
+function luaL_dofile(L : Plua_State; fn : PChar) : Integer;
+Var
+ Res : Integer;
+begin
+ // WC 2007\03\22 - Updated for Delphi
+ Res := luaL_loadfile(L, fn);
+ if Res = 0 then
+ Res := lua_pcall(L, 0, LUA_MULTRET, 0);
+ Result := Res;
+end;
+
+function luaL_dostring(L : Plua_State; s : PChar) : Integer;
+Var
+ Res : Integer;
+begin
+ // WC 2007\03\22 - Updated for Delphi
+ Res := luaL_loadstring(L, s);
+ if Res = 0 then
+ Res := lua_pcall(L, 0, LUA_MULTRET, 0);
+ Result := Res;
+end;
+
+procedure luaL_getmetatable(L : Plua_State; n : PChar);
+begin
+ lua_getfield(L, LUA_REGISTRYINDEX, n);
+end;
+
+procedure luaL_addchar(B : PluaL_Buffer; c : Char);
+begin
+ if not(B^.p < B^.buffer + LUAL_BUFFERSIZE) then
+ luaL_prepbuffer(B);
+ B^.p^ := c;
+ Inc(B^.p);
+end;
+
+procedure luaL_putchar(B : PluaL_Buffer; c : Char);
+begin
+ luaL_addchar(B, c);
+end;
+
+procedure luaL_addsize(B : PluaL_Buffer; n : Integer);
+begin
+ Inc(B^.p, n);
+end;
+
+function lua_ref(L : Plua_State; lock : Boolean) : Integer;
+begin
+ if lock then
+ lua_ref := luaL_ref(L, LUA_REGISTRYINDEX)
+ else begin
+ lua_pushstring(L, 'unlocked references are obsolete');
+ lua_error(L);
+ lua_ref := 0;
+ end;
+end;
+
+procedure lua_unref(L : Plua_State; ref : Integer);
+begin
+ luaL_unref(L, LUA_REGISTRYINDEX, ref);
+end;
+
+procedure lua_getref(L : Plua_State; ref : Integer);
+begin
+ lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
+end;
+
+
+(******************************************************************************
+* Original copyright for the lua source and headers:
+* 1994-2004 Tecgraf, PUC-Rio.
+* www.lua.org.
+*
+*
+* Permission is hereby granted, free of charge, to any person obtaining
+* a copy of this software and associated documentation files (the
+* "Software"), to deal in the Software without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************)
+
+end.
+
diff --git a/src/lua/UHookableEvent.pas b/src/lua/UHookableEvent.pas
new file mode 100644
index 00000000..8ad7ea9c
--- /dev/null
+++ b/src/lua/UHookableEvent.pas
@@ -0,0 +1,380 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit UHookableEvent;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses ULua;
+
+type
+ { Record holding information about a hook of an event }
+ PHook = ^THook;
+ THook = record
+ Handle: Integer; //< Handle to identify the hook, e.g. for unhooking by plugin
+ Parent: Integer; //< Lua Core Handle this hook belongs to
+
+ Func: String; //< Name of the global that holds the function
+
+ Next: PHook; //< Next Hook in list (nil for the first)
+ end;
+
+ { procedure is called before each call to the hooking lua functions, to push values on stack
+ returns the number of pushed arguments}
+ PrepareStackProc = Function(L: PLua_State): Integer;
+
+ { class representing a hookable event }
+ THookableEvent = class
+ private
+ iHandle: Integer; //< used to unregister at lua core
+ LastHook: PHook; //< last hook in hook list, first to be called
+ NextHookHandle: Integer; //< handle to identify next hook
+
+ sName: String; //< the events name
+
+ PrepareStack: PrepareStackProc; //< prepare stack procedure passed to constructor
+ CallinProcess: boolean; //< true if a chain call is in process, to prepare unhooking during calls
+ HooksToRemove: array of PHook; // hooks to delete after chaincall
+
+ procedure RemoveWaitingHooks;
+ public
+ constructor Create(Name: String; const Proc: PrepareStackProc = nil);
+
+ property Name: String read sName; //< returns the events name
+ property Handle: Integer read iHandle; //< returns the events name
+
+ procedure Hook(L: Plua_State; Parent: Integer; Func: String); //< pushes hook object/table to the lua stack
+ procedure UnHook(L: Plua_State; hHook: Integer); //< unhook by plugin. push true or error string to lua stack
+
+ procedure UnHookByParent(Parent: Integer); //< deletes all hooks by a specified parent (unhook by core)
+
+ function CallHookChain(Breakable: Boolean): PLua_State; //< calls the events hookchain. if breakable, plugin can breake the chain by returning a value != 0 or false or nil
+
+ destructor Destroy; override;
+ end;
+
+{ the default function for THookableEvent.PrepareStack it don't pass any arguments }
+function PrepareStack_Dummy(L: PLua_State): Integer;
+
+{ function in resulting hook table. it calls the unhook command of the event on plugins demand }
+function LuaHook_UnHook(L: Plua_State): Integer; cdecl;
+
+implementation
+uses ULuaCore;
+
+constructor THookableEvent.Create(Name: String; const Proc: PrepareStackProc);
+begin
+ inherited Create;
+
+ Self.sName := Name;
+
+ if (@Proc = nil) then
+ Self.PrepareStack := @PrepareStack_Dummy
+ else
+ Self.PrepareStack := Proc;
+
+ //init LastHook pointer w/ nil
+ LastHook := nil;
+ NextHookHandle := 1;
+
+ iHandle := LuaCore.RegisterEvent(Self);
+end;
+
+destructor THookableEvent.Destroy;
+var
+ Prev: PHook;
+ Cur: PHook;
+begin
+ //delete all hooks
+ Cur := LastHook;
+ While (Cur <> nil) do
+ begin
+ Prev := Cur;
+ Cur := Prev.Next;
+
+ Dispose(Prev);
+ end;
+
+ //remove from luacores list
+ LuaCore.UnRegisterEvent(iHandle);
+
+ inherited;
+end;
+
+{ adds hook to events list and pushes hook object/table to the lua stack }
+procedure THookableEvent.Hook(L: PLua_State; Parent: Integer; Func: String);
+ var
+ Item: PHook;
+ P: TLuaPlugin;
+begin
+ P := LuaCore.GetPluginById(Parent);
+ if (P <> nil) then
+ begin
+ // get mem and fill it w/ data
+ New(Item);
+ Item.Handle := NextHookHandle;
+ Inc(NextHookHandle);
+
+ Item.Parent := Parent;
+ Item.Func := Func;
+
+ // add at front of the hook chain
+ Item.Next := LastHook;
+ LastHook := Item;
+
+ //we need 2 free stack slots
+ lua_checkstack(L, 2);
+
+ //create the hook table, we need 2 elements (event name and unhook function)
+ lua_createtable(L, 0, 2);
+
+ //push events name
+ lua_pushstring(L, PAnsiChar(Name));
+
+ //add the name to the table
+ lua_setfield(L, -2, 'Event');
+
+ //push hook id to the stack
+ lua_pushinteger(L, Item.Handle);
+
+ //create a c closure, append one value from stack(the id)
+ //this will pop both, the function and the id
+ lua_pushcclosure(L, LuaHook_UnHook, 1);
+
+ //add the function to our table
+ lua_setfield(L, -2, 'Unhook');
+
+ //the table is left on the stack, it is our result
+ end;
+end;
+
+{ removes hooks in HookstoRemove array from chain }
+procedure THookableEvent.RemoveWaitingHooks;
+ function IsInArray(Cur: PHook): boolean;
+ var I: Integer;
+ begin
+ Result := false;
+ for I := 0 to high(HooksToRemove) do
+ if (HooksToRemove[I] = Cur) then
+ begin
+ Result := true;
+ Break;
+ end;
+ end;
+
+ var
+ Cur, Prev: PHook;
+begin
+ Prev := nil;
+ Cur := LastHook;
+
+ while (Cur <> nil) do
+ begin
+ if (IsInArray(Cur)) then
+ begin //we found the hook
+ if (prev <> nil) then
+ Prev.Next := Cur.Next
+ else //last hook found
+ LastHook := Cur.Next;
+
+ //free hooks memory
+ Dispose(Cur);
+
+ if (prev <> nil) then
+ Cur := Prev.Next
+ else
+ Cur := LastHook;
+ end
+ else
+ begin
+ Prev := Cur;
+ Cur := Prev.Next;
+ end;
+ end;
+
+ SetLength(HooksToRemove, 0);
+end;
+
+{ unhook by plugin. push true or error string to lua stack }
+procedure THookableEvent.UnHook(L: Plua_State; hHook: Integer);
+ var
+ Cur, Prev: PHook;
+ Len: integer;
+begin
+ if (hHook < NextHookHandle) and (hHook > 0) then
+ begin
+ //Search for the Hook
+ Prev := nil;
+ Cur := LastHook;
+
+ while (Cur <> nil) do
+ begin
+ if (Cur.Handle = hHook) then
+ begin //we found the hook
+ if not CallinProcess then
+ begin // => remove it
+ if (prev <> nil) then
+ Prev.Next := Cur.Next
+ else //last hook found
+ LastHook := Cur.Next;
+
+ //free hooks memory
+ Dispose(Cur);
+ end
+ else
+ begin // add to list of hooks to remove
+ Len := Length(HooksToRemove);
+ SetLength(HooksToRemove, Len + 1);
+ HooksToRemove[Len] := Cur;
+ end;
+
+ //indicate success
+ lua_pushboolean(L, True);
+ exit; //break the chain and exit the function
+ end;
+ Prev := Cur;
+ Cur := Prev.Next;
+ end;
+
+ lua_pushstring(L, PAnsiChar('handle already unhooked')); //the error description
+ end
+ else
+ lua_pushstring(L, PAnsiChar('undefined hook handle')); //the error description
+end;
+
+{ deletes all hooks by a specified parent (unhook by core) }
+procedure THookableEvent.UnHookByParent(Parent: Integer);
+ var
+ Cur, Prev: PHook;
+begin
+ Prev := nil;
+ Cur := LastHook;
+
+ While (Cur <> nil) do
+ begin
+ if (Cur.Parent = Parent) then
+ begin //found a hook from parent => remove it
+ if (Prev <> nil) then
+ Prev.Next := Cur.Next
+ Else
+ LastHook := Cur.Next;
+
+ Dispose(Cur);
+
+ if (Prev <> nil) then
+ Cur := Prev.Next
+ else
+ Cur := LastHook;
+ end
+ else //move through the chain
+ begin
+ Prev := Cur;
+ Cur := Prev.Next;
+ end;
+ end;
+end;
+
+{ calls the events hookchain. if breakable, plugin can breake the chain
+ by returning a value
+ breakable is pushed as the first parameter to the hooking functions
+ if chain is broken the LuaStack is returned, with all results left
+ you may call lua_clearstack }
+function THookableEvent.CallHookChain(Breakable: Boolean): Plua_State;
+ var
+ Cur: PHook;
+ P: TLuaPlugin;
+begin
+ Result := nil;
+
+ CallinProcess := true;
+
+ Cur := LastHook;
+ While (Cur <> nil) do
+ begin
+ P := LuaCore.GetPluginById(Cur.Parent);
+ lua_pushboolean(P.LuaState, Breakable);
+
+ if (P.CallFunctionByName(Cur.Func, 1 + PrepareStack(P.LuaState), LUA_MULTRET))
+ and Breakable
+ and (lua_gettop(P.LuaState) > 0) then
+ begin //Chain Broken
+ Result := P.LuaState;
+ Break;
+ end;
+
+ Cur := Cur.Next;
+ end;
+
+ RemoveWaitingHooks;
+ CallinProcess := false;
+end;
+
+{ the default function for THookableEvent.PrepareStack it don't pass any arguments }
+function PrepareStack_Dummy(L: PLua_State): Integer;
+begin
+ Result := 0;
+end;
+
+{ function in resulting hook table. it calls the unhook command of the event on plugins demand }
+function LuaHook_UnHook(L: Plua_State): Integer; cdecl;
+ var
+ Name: string;
+ Event: THookableEvent;
+ hHook: integer;
+begin
+ Result := 0;
+
+ if not lua_isTable(L, 1) then
+ LuaL_Error(L, 'Can''t find hook table in LuaHook_Unhook. Please call Unhook with method seperator (colon) instead of a point.');
+
+ // get event name
+ Lua_GetField(L, 1, 'Event');
+ if not lua_isString(L, -1) then
+ LuaL_Error(L, 'Can''t get event name in LuaHook_Unhook');
+
+ Name := Lua_ToString(L, -1);
+
+ // get event by name
+ Event := LuaCore.GetEventbyName(Name);
+
+ // free stack slots
+ Lua_pop(L, Lua_GetTop(L));
+
+ if (Event = nil) then
+ LuaL_Error(L, PAnsiChar('event ' + Name + ' does not exist (anymore?) in LuaHook_Unhook'));
+
+ // get the hookid
+ hHook := lua_ToInteger(L, lua_upvalueindex(1));
+
+ Event.UnHook(L, hHook);
+end;
+
+end. \ No newline at end of file
diff --git a/src/lua/ULuaCore.pas b/src/lua/ULuaCore.pas
new file mode 100644
index 00000000..9b2e08c6
--- /dev/null
+++ b/src/lua/ULuaCore.pas
@@ -0,0 +1,1014 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaCore;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses SysUtils, ULua, UHookableEvent, UPath;
+
+type
+ { this exception is raised when the lua panic function
+ is called. Only in case we use call instead of pcall.
+ it has the lua error string in its message attribute }
+ ELuaException = class(Exception);
+
+ { record represents item of Eventlist of TLuaCore }
+ PEventListItem = ^TEventListItem;
+ TEventListItem = record
+ Event: THookableEvent;
+ Next: PEventListItem;
+ end;
+
+ { record represents a module }
+ TLuaModule = record
+ Name: String;
+ Functions: Array of luaL_reg; //modules functions, w/ trailing nils this time
+ end;
+
+ TLuaPlugin_Status = (psNone, psRunning, psClosed, psErrorOnLoad, psErrorOnCall, psErrorInInit, psErrorOnRun);
+ { class represents a loaded plugin }
+ TLuaPlugin = class
+ private
+ iId: Integer;
+ Filename: IPath;
+ State: Plua_State; //< all functions of this plugin are called with this Lua state
+ bPaused: Boolean; //< If true no lua functions from this state are called
+ ErrorCount: Integer; //< counts the errors that occured during function calls of this plugin
+ ShutDown: Boolean; //< for self shutdown by plugin. true if plugin wants to be unloaded after execution of current function
+
+ sName: String;
+ sVersion: String;
+ sAuthor: String;
+ sURL: String;
+
+ sStatus: TLuaPlugin_Status;
+ public
+ constructor Create(Filename: IPath; Id: Integer);
+
+ property Id: Integer read iId;
+ property Name: String read sName;
+ property Version: String read sVersion;
+ property Author: String read sAuthor;
+ property Url: String read sUrl;
+
+ property Status: TLuaPlugin_Status read sStatus;
+ property CountErrors: Integer read ErrorCount;
+
+ property LuaState: Plua_State read State;
+
+ procedure Load;
+
+ procedure Register(Name, Version, Author, Url: String);
+ function HasRegistred: Boolean;
+
+ procedure PausePlugin(doPause: Boolean);
+ property Paused: boolean read bPaused write PausePlugin;
+
+ procedure ShutMeDown;
+
+ { calls the lua function in the global w/ the given name.
+ the arguments to the function have to be pushed to the stack
+ before calling this function.
+ the arguments and the function will be removed from stack
+ results will not be removed.
+ if result is false there was an error calling the function
+ if ReportErrors is true the errorstring is popped from stack
+ and written to error.log otherwise it is left on stack}
+ function CallFunctionByName(Name: String; const nArgs: Integer = 0; const nResults: Integer = 0; const ReportErrors: Boolean = True): Boolean;
+ procedure ClearStack;
+
+ procedure Unload; //< Destroys the Luastate, and frees as much mem as possible, w/o destroying the class and important information
+
+ destructor Destroy; override;
+ end;
+
+ { class managing the plugins w/ their LuaStates, the events and modules
+ it also offers the usdx table to the plugins w/ some basic functionality
+ like self unload or hook getting}
+ TLuaCore = class
+ private
+ EventList: PEventListItem; //< pointer to first registred Event, ordered by name
+ EventHandles: Array of String; //< Index is Events handle, value is events name. if length(value) is 0 handle is considered unregistred
+
+ Plugins: Array of TLuaPlugin;
+
+ eLoadingFinished: THookableEvent;
+ protected
+ Modules: Array of TLuaModule; //< modules that has been registred, has to be proctected because fucntions of this unit need to get access
+
+ function GetModuleIdByName(Name: String): Integer; //returns id of given module, or -1 if module is not found
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ procedure LoadPlugins; //< calls LoadPlugin w/ Plugindir and LoadingFinished Eventchain
+
+ procedure BrowseDir(Dir: IPath); //< searches for files w/ extension .usdx in the specified dir and tries to load them w/ lua
+ procedure LoadPlugin(Filename: IPath); //< tries to load filename w/ lua and creates the default usdx lua environment for the plugins state
+
+ function GetPluginByName(Name: String): TLuaPlugin;
+ function GetPluginById(Id: Integer): TLuaPlugin;
+
+ { this function adds a module loader for your functions
+ name is the name the script needs to write in its require()
+ Functions is an array of lua calling compatible functions
+ w/o trailing nils! }
+ procedure RegisterModule(Name: String; const Functions: Array of luaL_reg);
+
+ function RegisterEvent(Event: THookableEvent): Integer; //< adds the event to eventlist and returns its handle
+ procedure UnRegisterEvent(hEvent: Integer); //< removes the event from eventlist by handle
+
+ function GetEventbyName(Name: String): THookableEvent; //< tries to find the event w/ the given name in the list
+ function GetEventbyHandle(hEvent: Integer): THookableEvent; //< tries to find the event w/ the given handle
+
+ procedure UnHookByParent(Parent: Integer); //< remove all hooks by given parent id from all events
+
+ procedure PrepareState(L: Plua_State);
+
+ procedure DumpPlugins; //< prints plugin runtime information w/ Log.LogStatus
+ end;
+
+//some luastyle functions to call from lua scripts
+{ register global, used by plugins to identify
+ register(plugin name, plugin version, [plugin author], [plugin homepage])
+ can only be called once since the global "register" is niled by the function
+ returns true on success. (name does not exist)}
+function TLuaPlugin_Register (L: Plua_State): Integer; cdecl;
+
+{ moduleloader for usdx.* modules
+ stored in package.loaders[3]
+ package.loaders[3] (module name)
+ returns a function to load the requested module or a error
+ description(string) when the module is not found }
+function TLuaCore_ModuleLoader (L: Plua_State): Integer; cdecl;
+
+{ loads module specified by a cfunction upvalue to
+ usdx.modulename and returns it.
+ loadmodule(module name) }
+function TLuaCore_LoadModule (L: Plua_State): Integer; cdecl;
+
+{ custom lua panic function
+ it writes error string to error.log and raises an ELuaException
+ that may be caught }
+function TLua_CustomPanic (L: Plua_State): Integer; cdecl;
+
+{ replacement for luas require function
+ can be called with more than one parameter to require
+ some modules at once. e.g.: require('math', 'Usdx.Log')
+ modules are loaded from right to left
+ unlike standard require the module tables are not returned
+ the standard require function in _require is called by
+ this function }
+function TLua_CustomRequire(L: PLua_State): Integer; cdecl;
+
+
+var
+ LuaCore: TLuaCore;
+
+implementation
+uses
+ StrUtils,
+ ULog,
+ UFilesystem,
+ ULuaUsdx,
+ UPathUtils,
+ ULuaUtils;
+
+constructor TLuaCore.Create;
+begin
+ inherited;
+
+ //init EventList w/ nil
+ EventList := nil;
+
+ eLoadingFinished := nil;
+end;
+
+destructor TLuaCore.Destroy;
+var
+ Cur: PEventListItem;
+ Prev: PEventListItem;
+begin
+ SetLength(EventHandles, 0);
+
+ //delete event list
+ Cur := EventList;
+
+ While(Cur <> nil) do
+ begin
+ Prev := Cur;
+ Cur := Prev.Next;
+
+ Dispose(Prev);
+ end;
+
+ inherited;
+end;
+
+{ calls BrowseDir w/ plugin dir and LoadingFinished eventchain }
+procedure TLuaCore.LoadPlugins;
+begin
+ // we have to create event here, because in create it can
+ // not be registred, because LuaCore is no assigned
+ if (not Assigned(eLoadingFinished)) then
+ eLoadingFinished := THookableEvent.Create('Usdx.LoadingFinished');
+
+ BrowseDir(PluginPath);
+ eLoadingFinished.CallHookChain(false);
+end;
+
+{ searches for files w/ extension .usdx in the specified
+ dir and tries to load them w/ lua }
+procedure TLuaCore.BrowseDir(Dir: IPath);
+ var
+ Iter: IFileIterator;
+ FileInfo: TFileInfo;
+ FileName: IPath;
+ Ext: IPath;
+begin
+ Ext := Path('.usdx');
+
+ // search for all files and directories
+ Iter := FileSystem.FileFind(Dir.Append('*'), faAnyFile);
+ while (Iter.HasNext) do
+ begin
+ FileInfo := Iter.Next;
+ FileName := FileInfo.Name;
+ if ((FileInfo.Attr and faDirectory) <> 0) then
+ begin
+ if (not FileName.Equals('.')) and (not FileName.Equals('..')) then
+ BrowseDir(Dir.Append(FileName));
+ end
+ else
+ begin
+ if (Ext.Equals(FileName.GetExtension(), true)) then
+ begin
+ LoadPlugin(Dir.Append(FileName));
+ end;
+ end;
+ end;
+end;
+
+{ tries to load filename w/ lua and creates the default
+ usdx lua environment for the plugins state }
+procedure TLuaCore.LoadPlugin(Filename: IPath);
+ var
+ Len: Integer;
+begin
+ Len := Length(Plugins);
+ SetLength(Plugins, Len + 1);
+ Plugins[Len] := TLuaPlugin.Create(Filename, Len);
+ Plugins[Len].Load;
+end;
+
+{ returns Plugin on success nil on failure }
+function TLuaCore.GetPluginByName(Name: String): TLuaPlugin;
+ var
+ I: Integer;
+begin
+ Result := nil;
+ Name := lowercase(Name);
+
+ For I := 0 to High(Plugins) do
+ If (lowercase(Plugins[I].Name) = Name) then
+ begin
+ Result := GetPluginById(I);
+ Exit;
+ end;
+end;
+
+{ returns Plugin on success nil on failure }
+function TLuaCore.GetPluginById(Id: Integer): TLuaPlugin;
+begin
+ If (Id >= 0) AND (Id <= High(Plugins)) then
+ Result := Plugins[Id]
+ Else
+ Result := nil;
+end;
+
+{ this function adds a module loader for your functions
+ name is the name the script needs to write in its require()
+ Functions is an array of lua calling compatible functions
+ w/o trailing nils! }
+procedure TLuaCore.RegisterModule(Name: String; const Functions: Array of luaL_reg);
+ var
+ Len: Integer;
+ FuncLen: Integer;
+ I: Integer;
+begin
+ Len := Length(Modules);
+ SetLength(Modules, Len + 1);
+ Modules[Len].Name := Name;
+
+ FuncLen := Length(Functions);
+ SetLength(Modules[Len].Functions, FuncLen + 1);
+
+ For I := 0 to FuncLen-1 do
+ Modules[Len].Functions[I] := Functions[I];
+
+ Modules[Len].Functions[FuncLen].name := nil;
+ Modules[Len].Functions[FuncLen].func := nil;
+end;
+
+{ adds the event to eventlist and returns its handle
+ called by THookableEvent on creation }
+function TLuaCore.RegisterEvent(Event: THookableEvent): Integer;
+var
+ Cur, Prev, Item: PEventListItem;
+begin
+ If (Event <> nil) and (Length(Event.Name) > 0) then
+ begin
+ Result := Length(EventHandles);
+ SetLength(EventHandles, Result + 1); //get Handle and copy it to result
+
+ EventHandles[Result] := Event.Name;
+
+ //create eventlist item
+ New(Item);
+ Item.Event := Event;
+
+ //search for a place for this event in alphabetical order
+ Prev := nil;
+ Cur := EventList;
+
+ While (Cur <> nil) and (CompareStr(Cur.Event.Name, EventHandles[Result]) < 0) do
+ begin
+ Prev := Cur;
+ Cur := Prev.Next;
+ end;
+
+ //found the place => add new item
+ if (Prev <> nil) then
+ Prev.Next := Item
+ else //first item
+ EventList := Item;
+
+ Item.Next := Cur;
+ end
+ else
+ Result := -1;
+end;
+
+{ removes the event from eventlist by handle }
+procedure TLuaCore.UnRegisterEvent(hEvent: Integer);
+ var
+ Cur, Prev: PEventListItem;
+begin
+ If (hEvent >= 0) AND (hEvent <= High(EventHandles)) AND (Length(EventHandles[hEvent]) > 0) then
+ begin //hEvent in bounds and not already deleted
+ //delete from eventlist
+ Prev := nil;
+ Cur := EventList;
+
+ While (Cur <> nil) and (CompareStr(Cur.Event.Name, EventHandles[hEvent]) < 0) do
+ begin
+ Prev := Cur;
+ Cur := Prev.Next;
+ end;
+
+ If (Cur <> nil) and (Cur.Event.Name = EventHandles[hEvent]) then
+ begin //delete if found
+ Prev.Next := Cur.Next; // remove from list
+ Dispose(Cur); // free memory
+ end;
+
+ //delete from handle array
+ EventHandles[hEvent] := '';
+ end;
+end;
+
+{ tries to find the event w/ the given name in the list
+ to-do : use binary search algorithm instead of linear search here
+ check whether this is possible (events are saved in a pointer list) }
+function TLuaCore.GetEventbyName(Name: String): THookableEvent;
+ var
+ Cur: PEventListItem;
+begin
+ Result := nil;
+
+ if (Length(Name) > 0) then
+ begin
+ //search in eventlist
+ Cur := EventList;
+
+ While (Cur <> nil) and (CompareStr(Cur.Event.Name, Name) < 0) do
+ begin
+ Cur := Cur.Next;
+ end;
+
+ If (Cur <> nil) and (Cur.Event.Name = Name) then
+ begin //we found what we want to find
+ Result := Cur.Event;
+ end;
+ end;
+end;
+
+{ tries to find the event w/ the given handle }
+function TLuaCore.GetEventbyHandle(hEvent: Integer): THookableEvent;
+begin
+ If (hEvent >= 0) AND (hEvent <= High(EventHandles)) AND (Length(EventHandles[hEvent]) > 0) then
+ begin //hEvent in bounds and not already deleted
+ Result := GetEventByName(EventHandles[hEvent]);
+ end
+ else
+ Result := nil;
+end;
+
+{ remove all hooks by given parent id from all events }
+procedure TLuaCore.UnHookByParent(Parent: Integer);
+ var
+ Cur: PEventListItem;
+begin
+ if (Parent >= 0) and (Parent <= High(Plugins)) then
+ begin
+ // go through event list
+ Cur := EventList;
+
+ While (Cur <> nil) do
+ begin
+ Cur.Event.UnHookByParent(Parent);
+ Cur := Cur.Next;
+ end;
+ end;
+end;
+
+{ prepares the given already opened Lua state with the
+ basic usdx environment, e.g.: base and package Modules,
+ usdx moduleloader and usdx table }
+procedure TLuaCore.PrepareState(L: Plua_State);
+begin
+ //load basic lib functionality
+ lua_pushcfunction(L, luaopen_base);
+ lua_call(L, 0, 0);
+ lua_pop(L, lua_gettop(L)); //pop the results
+
+ //load module functionality
+ lua_pushcfunction(L, luaopen_package);
+ lua_call(L, 0, 0);
+ lua_pop(L, lua_gettop(L)); //pop the results
+
+ { adds the loader for the other standard lib to package.preload table
+ plugins can call e.g. require('math') if they need math functionality }
+
+ // we need 3 free stack slots
+ lua_checkstack(L, 3);
+
+ // get package table
+ lua_getglobal (L, PChar('package'));
+
+ // get package.preload table
+ lua_getfield (L, -1, PChar('preload'));
+
+ {**** add string lib }
+
+ // push loader function
+ lua_pushcfunction(L, luaopen_string);
+
+ // set package.preload.x loader
+ lua_setfield (L, -2, PChar('string'));
+
+ {**** add table lib }
+
+ // push loader function
+ lua_pushcfunction(L, luaopen_table);
+
+ // set package.preload.x loader
+ lua_setfield (L, -2, PChar('table'));
+
+ {**** add math lib }
+
+ // push loader function
+ lua_pushcfunction(L, luaopen_math);
+
+ // set package.preload.x loader
+ lua_setfield (L, -2, PChar('math'));
+
+ {**** add os lib }
+
+ // push loader function
+ lua_pushcfunction(L, luaopen_os);
+
+ // set package.preload.x loader
+ lua_setfield (L, -2, PChar('os'));
+
+ //pop package.preload table from stack
+ lua_pop(L, 1);
+
+ // get package.loaders table
+ lua_getfield (L, -1, PChar('loaders'));
+
+ {**** Move C-Library and all-in-one module loader backwards,
+ slot 3 is free now }
+ // get package.loaders[4] function
+ lua_pushinteger(L, 5); //push new index
+ lua_pushinteger(L, 4); //push old index
+ lua_gettable (L, -3);
+
+ // and move it to package.loaders[5]
+ lua_settable (L, -3);
+
+ // get package.loaders[3] function
+ lua_pushinteger(L, 4); //push new index
+ lua_pushinteger(L, 3); //push old index
+ lua_gettable (L, -3);
+
+ // and move it to package.loaders[4]
+ lua_settable (L, -3);
+
+ {**** now we add the core module to package.loaders[3] }
+ lua_pushinteger(L, 3); //push new loaders index
+ lua_pushcfunction(L, TLuaCore_ModuleLoader);
+
+ // and move it to package.loaders[3]
+ lua_settable (L, -3);
+
+ //pop both package and package.loaders tables from stack
+ lua_pop(L, 2);
+
+ {**** replace the standard require w/ our custom require function }
+ // first move standard require function to _require
+ lua_getfield(L, LUA_GLOBALSINDEX, PChar('require'));
+ lua_setfield(L, LUA_GLOBALSINDEX, PChar('_require'));
+
+ // then save custom require function to require
+ lua_pushcfunction(L, TLua_CustomRequire);
+ lua_setfield(L, LUA_GLOBALSINDEX, PChar('require'));
+
+ {**** now we create the usdx table }
+ //at first functions from ULuaUsdx
+ luaL_register(L, 'Usdx', @ULuaUsdx_Lib_f[0]);
+end;
+
+{ returns id of given module, or -1 if module is not found }
+function TLuaCore.GetModuleIdByName(Name: String): Integer;
+ var
+ I: Integer;
+begin
+ Result := -1;
+
+ for I := 0 to High(Modules) do
+ if (Modules[I].Name = Name) then
+ begin
+ Result := I;
+ Exit;
+ end;
+end;
+
+{ moduleloader for usdx.* modules
+ stored in package.loaders[3]
+ package.loaders[3] (module name)
+ returns a function to load the requested module or an error
+ description(string) when the module is not found }
+function TLuaCore_ModuleLoader (L: Plua_State): Integer; cdecl;
+ var
+ Name: String;
+ ID: Integer;
+begin
+ Result := 1; //we will return one value in every case (or never return in case of an error)
+
+ if (lua_gettop(L) >= 1) then
+ begin
+ // pop all arguments but the first
+ if (lua_gettop(L) > 1) then
+ lua_pop(L, lua_gettop(L)-1);
+
+
+ if (lua_IsString(L, 1)) then
+ begin //we got the name => go get it
+ Name := lua_toString(L, 1);
+
+ //we need at least 6 letters
+ //and first 5 letters have to be usdx.
+ if (Length(Name) > 5) and (lowercase(copy(Name, 1, 5))='usdx.') then
+ begin
+ ID := LuaCore.GetModuleIdByName(copy(Name, 6, Length(Name) - 5));
+ If (ID >= 0) then
+ begin //found the module -> return loader function
+ lua_pushinteger(L, Id);
+ lua_pushcclosure(L, TLuaCore_LoadModule, 1);
+ //the function is the result, so we leave it on stack
+ end
+ else
+ lua_pushString(L, PChar('usdx module "' + Name + '" couldn''t be found'));
+ end
+ else
+ lua_pushString(L, PChar('module doesn''t have "Usdx." prefix'));
+
+ end
+ else
+ luaL_argerror(L, 1, PChar('string expected'));
+ end
+ else
+ luaL_error(L, PChar('no modulename specified in usdx moduleloader'));
+end;
+
+{ loads module specified by a cfunction upvalue to
+ usdx.modulename and returns it.
+ loadmodule(module name) }
+function TLuaCore_LoadModule (L: Plua_State): Integer; cdecl;
+ var
+ Id: Integer;
+begin
+ if (not lua_isnoneornil(L, lua_upvalueindex(1))) then
+ begin
+ Id := lua_ToInteger(L, lua_upvalueindex(1));
+
+ luaL_register(L, PChar('Usdx.' + LuaCore.Modules[Id].Name), @LuaCore.Modules[Id].Functions[0]);
+
+ // set the modules table as global "modulename"
+ // so it can be accessed either by Usdx.modulename.x() or
+ // by modulename.x()
+ lua_setglobal(L, PChar(LuaCore.Modules[Id].Name));
+
+ // no we net to push the table again to return it
+ lua_getglobal(L, PChar(LuaCore.Modules[Id].Name));
+
+ Result := 1; //return table
+ end
+ else
+ luaL_error(L, PChar('no upvalue found in LuaCore_LoadModule'));
+end;
+
+{ prints plugin runtime information w/ Log.LogStatus }
+procedure TLuaCore.DumpPlugins;
+ function PluginStatusToString(Status: TLuaPlugin_Status): String;
+ begin
+ Case Status of
+ psNone: Result := 'not loaded';
+ psRunning: Result := 'running';
+ psClosed: Result := 'closed';
+ psErrorOnLoad: Result := 'error during load';
+ psErrorOnCall: Result := 'error during call';
+ psErrorInInit: Result := 'error in plugin_init()';
+ psErrorOnRun: Result := 'error on function call';
+ else Result := 'unknown';
+ end;
+ end;
+ var
+ I: Integer;
+begin
+ //print table header
+ Log.LogError(' # ' + #09 + ' name ' + #09 + ' version ' + #09 + ' status ' + #09 + ' paused ' + #09 + ' #errors ', 'plugins');
+
+
+ For I := 0 to High(Plugins) do
+ Log.LogError(' ' + IntToStr(Plugins[I].Id) + ' ' + #09 +
+ ' ' + Plugins[I].Name + ' ' + #09 +
+ ' ' + Plugins[I].Version + ' ' + #09 +
+ ' ' + PluginStatusToString(Plugins[I].Status) + ' ' + #09 +
+ ' ' + BoolToStr(Plugins[I].Paused, true) + ' ' + #09 +
+ ' ' + IntToStr(Plugins[I].CountErrors) + ' ', 'plugins');
+
+ If (High(Plugins)<0) then
+ Log.LogError(' no plugins loaded ');
+end;
+
+// Implementation of TLuaPlugin
+//--------
+constructor TLuaPlugin.Create(Filename: IPath; Id: Integer);
+begin
+ inherited Create;
+ Self.iId := Id;
+ Self.Filename := Filename;
+
+ // set some default attributes
+ Self.bPaused := False;
+ Self.ErrorCount := 0;
+ Self.sName := 'not registred';
+ Self.sStatus := psNone;
+ Self.ShutDown := False;
+
+ State := nil; //< to prevent calls to unopened state
+end;
+
+destructor TLuaPlugin.Destroy;
+begin
+ Unload;
+ inherited;
+end;
+
+{ does the main loading part
+ can not be called by create, because Plugins[Id] isn't defined there }
+procedure TLuaPlugin.Load;
+begin
+ // create Lua state for this plugin
+ State := luaL_newstate;
+
+ //set our custom panic function if s/t went wrong along the init
+ //we don't expect
+ lua_atPanic(State, TLua_CustomPanic);
+
+ if (LuaL_LoadFile(State, PChar(Filename.ToNative)) = 0) then
+ begin // file loaded successful
+ { note: we run the file here, but the environment isn't
+ set up now. it just causes the functions to
+ register in globals and runs the code in the file
+ body. At least there should be no code, it could
+ neither use functions from baselibs nor load libs
+ with require, this code would be useless. }
+ if (lua_pcall(State, 0, 0, 0) = 0) then
+ begin // file called successful
+
+ //let the core prepare our state
+ LuaCore.PrepareState(State);
+
+ // set register function
+ lua_checkstack(State, 2);
+ lua_pushinteger(State, Id);
+ lua_pushcclosure(State, TLuaPlugin_Register, 1);
+ lua_setglobal(State, PChar('register'));
+
+ // write plugin id to registry
+ lua_pushinteger(State, iId);
+ lua_setfield (State, LUA_REGISTRYINDEX, '_USDX_STATE_ID');
+ lua_pop(State, Lua_GetTop(State));
+
+ // now run the plugin_init function
+ // plugin_init() if false or nothing is returned plugin init is aborted
+ if (CallFunctionByName('plugin_init', 0, 1)) then
+ begin
+ If (HasRegistred) AND (sStatus = psNone) AND (lua_toBoolean(State, 1)) then
+ begin
+ sStatus := psRunning;
+ ClearStack;
+ end
+ else
+ Unload;
+ end
+ else
+ begin
+ sStatus := psErrorInInit;
+ Log.LogError('error in plugin_init: ' + Self.Filename.ToNative, 'lua');
+ Unload;
+ end;
+ end
+ else
+ begin
+ sStatus := psErrorOnLoad;
+ Log.LogError(String(lua_toString(State, 1)), 'lua');
+ Log.LogError('unable to call file: ' + Self.Filename.ToNative, 'lua');
+ Unload;
+ end;
+
+ end
+ else
+ begin
+ sStatus := psErrorOnLoad;
+ Log.LogError(String(lua_toString(State, 1)), 'lua');
+ Log.LogError('unable to load file: ' + Self.Filename.ToNative, 'lua');
+ Unload;
+ end;
+end;
+
+procedure TLuaPlugin.Register(Name, Version, Author, Url: String);
+begin
+ sName := Name;
+ sVersion := Version;
+ sAuthor := Author;
+ sURL := Url;
+end;
+
+{ returns true if plugin has called register }
+function TLuaPlugin.HasRegistred: Boolean;
+begin
+ Result := (Self.sName <> 'not registred');
+end;
+
+procedure TLuaPlugin.PausePlugin(doPause: Boolean);
+begin
+ bPaused := doPause;
+end;
+
+{ unload plugin after execution of the current function }
+procedure TLuaPlugin.ShutMeDown;
+begin
+ ShutDown := True;
+end;
+
+{ calls the lua function in the global w/ the given name.
+ the arguments to the function have to be pushed to the stack
+ before calling this function.
+ the arguments and the function will be removed from stack
+ results will not be removed.
+ if result is false there was an error calling the function,
+ if ReportErrors is true the errorstring is popped from stack
+ and written to error.log otherwise it is left on stack}
+function TLuaPlugin.CallFunctionByName(Name: String; const nArgs: Integer; const nResults: Integer; const ReportErrors: Boolean): Boolean;
+begin
+ Result := false;
+ if (State <> nil) then
+ begin
+ if (not bPaused) then
+ begin
+ // we need at least one stack slot free
+ lua_checkstack(State, 1);
+
+ // lua_getglobal(State, PChar(Name)); //this is just a macro:
+ lua_getfield(State, LUA_GLOBALSINDEX, PChar(Name));
+
+ if (lua_isfunction(State, -1)) then
+ begin //we got a function
+ // move function in front of the arguments (if any)
+ if (nArgs > 0) then
+ lua_insert(State, -(nArgs + 1));
+
+ // call it!
+ if (lua_pcall(State, nArgs, nResults, 0) = 0) then
+ Result := true //called w/o errors
+ else //increase error counter
+ Inc (ErrorCount);
+ end
+ else
+ begin //we have to pop the args and the field we pushed from stack
+ lua_pop(State, nArgs + 1);
+ //leave an errormessage on stack
+ lua_pushstring(State, Pchar('could not find function named ' + Name));
+ end;
+ end
+ else
+ begin //we have to pop the args from stack
+ lua_pop(State, nArgs);
+ //leave an errormessage on stack
+ lua_pushstring(State, PChar('plugin paused'));
+ end;
+
+ if (not Result) AND (ReportErrors) then
+ Log.LogError(lua_toString(State, -1), 'lua/' + sName);
+
+ if ShutDown then
+ begin // plugin indicates self shutdown
+ ShutDown := False;
+ Unload;
+ Result := False;
+ end
+ end
+ else
+ begin
+ Log.LogError('trying to call function of closed or not opened lua state', IfThen(HasRegistred, Name, Filename.ToUTF8));
+ end;
+end;
+
+{ removes all values from stack }
+procedure TLuaPlugin.ClearStack;
+begin
+ if (State <> nil) and (lua_gettop(State) > 0) then
+ lua_pop(State, lua_gettop(State));
+end;
+
+{ destroys the lua state, and frees as much mem as possible,
+ w/o destroying the class and important information }
+procedure TLuaPlugin.Unload;
+begin
+ if (State <> nil) then
+ begin
+ if (Status in [psRunning, psErrorOnRun]) then
+ CallFunctionByName('plugin_unload');
+
+ ClearStack;
+ lua_close(State);
+ State := nil; //don't forget to nil it ;)
+
+ LuaCore.UnHookByParent(iId);
+
+ if (sStatus = psRunning) then
+ sStatus := psClosed;
+ end;
+end;
+
+function TLuaPlugin_Register (L: Plua_State): Integer; cdecl;
+ var
+ Id: Integer;
+ P: TLuaPlugin;
+ Name, Version, Author, Url: String;
+begin
+ if (lua_gettop(L) >= 2) then
+ begin // we got at least name and version
+ if (not lua_isNumber(L, lua_upvalueindex(1))) then
+ luaL_Error(L, PChar('upvalue missing'));
+
+ if (not lua_isString(L, 1)) then
+ luaL_ArgError(L, 1, 'string expected');
+
+ if (not lua_isString(L, 2)) then
+ luaL_ArgError(L, 1, 'string expected');
+
+ Id := lua_ToInteger(L, lua_upvalueindex(1));
+
+ //get version and name
+ Name := lua_tostring(L, 1);
+ Version := lua_tostring(L, 2);
+
+ //get optional parameters
+ if (lua_isString(L, 3)) then //author
+ Author := lua_toString(L, 3)
+ else
+ begin
+ Author := 'unknown';
+ end;
+
+ // homepage
+ if (lua_isString(L, 4)) then
+ Url := lua_toString(L, 4)
+ else
+ begin
+ Url := '';
+ end;
+
+ //clear stack
+ if (lua_gettop(L) > 0) then
+ lua_pop(L, lua_gettop(L));
+
+ //call register
+ P := LuaCore.GetPluginById(Id);
+ if (P <> nil) then
+ P.Register(Name, Version, Author, Url)
+ Else
+ luaL_error(L, PChar('wrong id in upstream'));
+
+ // remove function from global register
+ lua_pushnil(L);
+ lua_setglobal(L, PChar('register'));
+
+ // return true
+ Result := 1;
+ lua_pushboolean(L, True);
+ end
+ else
+ luaL_error(L, PChar('not enough arguments, at least 2 expected. in TLuaPlugin_Register'));
+end;
+
+{ custom lua panic function
+ it writes error string to error.log and raises an ELuaException
+ that may be caught }
+function TLua_CustomPanic (L: Plua_State): Integer; cdecl;
+ var
+ Msg: String;
+begin
+ if (lua_isString(L, -1)) then
+ Msg := lua_toString(L, -1)
+ else
+ Msg := 'undefined lua panic';
+
+ Log.LogError(Msg, 'lua');
+
+ raise ELuaException.Create(Msg);;
+
+ Result := 0;
+end;
+
+{ replacement for luas require function
+ can be called with more than one parameter to require
+ some modules at once. e.g.: require('math', 'Usdx.Log')
+ modules are loaded from right to left
+ unlike standard require the module tables are not returned
+ the standard require function in _require is called by
+ this function }
+function TLua_CustomRequire(L: PLua_State): Integer; cdecl;
+begin
+ // no results
+ Result := 0;
+
+ // move through parameters
+ while (lua_getTop(L) >= 1) do
+ begin
+ // get luas require function
+ lua_getfield(L, LUA_GLOBALSINDEX, PChar('_require'));
+
+ // move it under the top param
+ lua_insert(L, -2);
+
+ // call it w/ next param (function + param are poped from stack)
+ lua_call(L, 1, 0);
+ end;
+end;
+
+end. \ No newline at end of file
diff --git a/src/lua/ULuaGl.pas b/src/lua/ULuaGl.pas
new file mode 100644
index 00000000..178853b6
--- /dev/null
+++ b/src/lua/ULuaGl.pas
@@ -0,0 +1,1513 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaGl;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ SysUtils,
+ gl,
+ ULua;
+
+function luaopen_gl (L: Plua_State): Integer; cdecl;
+function ULuaGl_StringToEnum(Str: String): GLenum;
+
+{ lua lib functions }
+function ULuaGl_Begin(L: Plua_State): Integer; cdecl;
+function ULuaGl_BindTexture(L: Plua_State): Integer; cdecl;
+function ULuaGl_BlendFunc(L: Plua_State): Integer; cdecl;
+function ULuaGl_Clear(L: Plua_State): Integer; cdecl;
+function ULuaGl_ClearAccum(L: Plua_State): Integer; cdecl;
+function ULuaGl_ClearColor(L: Plua_State): Integer; cdecl;
+function ULuaGl_Color(L: Plua_State): Integer; cdecl;
+function ULuaGl_CullFace(L: Plua_State): Integer; cdecl;
+function ULuaGl_DepthFunc(L: Plua_State): Integer; cdecl;
+function ULuaGl_DepthRange(L: Plua_State): Integer; cdecl;
+function ULuaGl_Disable(L: Plua_State): Integer; cdecl;
+function ULuaGl_DisableClientState(L: Plua_State): Integer; cdecl;
+function ULuaGl_DrawBuffer(L: Plua_State): Integer; cdecl;
+function ULuaGl_Enable(L: Plua_State): Integer; cdecl;
+function ULuaGl_EnableClientState(L: Plua_State): Integer; cdecl;
+function ULuaGl_End(L: Plua_State): Integer; cdecl;
+function ULuaGl_EndList(L: Plua_State): Integer; cdecl;
+function ULuaGl_Finish(L: Plua_State): Integer; cdecl;
+function ULuaGl_Flush(L: Plua_State): Integer; cdecl;
+function ULuaGl_FrontFace(L: Plua_State): Integer; cdecl;
+function ULuaGl_InitNames(L: Plua_State): Integer; cdecl;
+function ULuaGl_LoadIdentity(L: Plua_State): Integer; cdecl;
+function ULuaGl_LogicOp(L: Plua_State): Integer; cdecl;
+function ULuaGl_MatrixMode(L: Plua_State): Integer; cdecl;
+function ULuaGl_Ortho(L: Plua_State): Integer; cdecl;
+function ULuaGl_PopAttrib(L: Plua_State): Integer; cdecl;
+function ULuaGl_PopClientAttrib(L: Plua_State): Integer; cdecl;
+function ULuaGl_PopMatrix(L: Plua_State): Integer; cdecl;
+function ULuaGl_PopName(L: Plua_State): Integer; cdecl;
+function ULuaGl_PushMatrix(L: Plua_State): Integer; cdecl;
+function ULuaGl_RasterPos(L: Plua_State): Integer; cdecl;
+function ULuaGl_ReadBuffer(L: Plua_State): Integer; cdecl;
+function ULuaGl_Rect(L: Plua_State): Integer; cdecl;
+function ULuaGl_Rotate(L: Plua_State): Integer; cdecl;
+function ULuaGl_Scale(L: Plua_State): Integer; cdecl;
+function ULuaGl_ShadeModel(L: Plua_State): Integer; cdecl;
+function ULuaGl_TexCoord(L: Plua_State): Integer; cdecl;
+function ULuaGl_Translate(L: Plua_State): Integer; cdecl;
+function ULuaGl_Vertex(L: Plua_State): Integer; cdecl;
+function ULuaGl_Viewport(L: Plua_State): Integer; cdecl;
+function ULuaGl_Dummy(L: Plua_State): Integer; cdecl;
+
+const
+ ULuaGl_Lib_f: array [0..40] of lual_reg = (
+ (name:'Begin';func:ULuaGl_Begin),
+ (name:'BindTexture';func:ULuaGl_BindTexture),
+ (name:'BlendFunc';func:ULuaGl_BlendFunc),
+ (name:'Clear';func:ULuaGl_Clear),
+ (name:'ClearAccum';func:ULuaGl_ClearAccum),
+ (name:'ClearColor';func:ULuaGl_ClearColor),
+ (name:'Color';func:ULuaGl_Color),
+ (name:'CullFace';func:ULuaGl_CullFace),
+ (name:'DepthFunc';func:ULuaGl_DepthFunc),
+ (name:'DepthRange';func:ULuaGl_DepthRange),
+ (name:'Disable';func:ULuaGl_Disable),
+ (name:'DisableClientState';func:ULuaGl_DisableClientState),
+ (name:'DrawBuffer';func:ULuaGl_DrawBuffer),
+ (name:'Enable';func:ULuaGl_Enable),
+ (name:'EnableClientState';func:ULuaGl_EnableClientState),
+ (name:'End';func:ULuaGl_End),
+ (name:'EndList';func:ULuaGl_EndList),
+ (name:'Finish';func:ULuaGl_Finish),
+ (name:'Flush';func:ULuaGl_Flush),
+ (name:'FrontFace';func:ULuaGl_FrontFace),
+ (name:'InitNames';func:ULuaGl_InitNames),
+ (name:'LoadIdentity';func:ULuaGl_LoadIdentity),
+ (name:'LogicOp';func:ULuaGl_LogicOp),
+ (name:'MatrixMode';func:ULuaGl_MatrixMode),
+ (name:'Ortho';func:ULuaGl_Ortho),
+ (name:'PopAttrib';func:ULuaGl_PopAttrib),
+ (name:'PopClientAttrib';func:ULuaGl_PopClientAttrib),
+ (name:'PopMatrix';func:ULuaGl_PopMatrix),
+ (name:'PopName';func:ULuaGl_PopName),
+ (name:'PushMatrix';func:ULuaGl_PushMatrix),
+ (name:'RasterPos';func:ULuaGl_RasterPos),
+ (name:'ReadBuffer';func:ULuaGl_ReadBuffer),
+ (name:'Rotate';func:ULuaGl_Rotate),
+ (name:'Rect';func:ULuaGl_Rect),
+ (name:'Scale';func:ULuaGl_Scale),
+ (name:'ShadeModel';func:ULuaGl_ShadeModel),
+ (name:'TexCoord';func:ULuaGl_TexCoord),
+ (name:'Translate';func:ULuaGl_Translate),
+ (name:'Vertex';func:ULuaGl_Vertex),
+ (name:'Viewport';func:ULuaGl_Viewport),
+ (name:nil;func:nil)
+ );
+
+implementation
+
+uses
+ ULog;
+
+type
+ TULuaGl_Enums = record
+ Text: string;
+ Value: GLenum;
+ end;
+const
+ ULuaGl_EnumERROR = $fffffffe;
+
+function ULuaGl_Begin(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.Begin''');
+
+ glBegin(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_BindTexture(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.BindTexture''');
+
+ glBindTexture(e,lual_checkinteger(L,2));
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_BlendFunc(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+ f : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+ f := ULuaGl_StringToEnum(lual_checkstring(L,2));
+
+ if (e = ULuaGl_EnumERROR) or (f = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.BlendFunc''');
+
+ glBlendFunc(e,f);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_Clear(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.Clear''');
+
+ glClear(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_ClearAccum(L: Plua_State): Integer; cdecl;
+var
+ i: Integer;
+begin
+ if lua_istable(L, 1) then
+ for i := 1 to lua_objlen(L,1) do
+ lua_rawgeti(L,1,i);
+
+ if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+ glClearAccum(lual_checknumber(L,-4),
+ lual_checknumber(L,-3),
+ lual_checknumber(L,-2),
+ lual_checknumber(L,-1))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.ClearAccum''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_ClearColor(L: Plua_State): Integer; cdecl;
+var
+ i: Integer;
+begin
+ if lua_istable(L, 1) then
+ for i := 1 to lua_objlen(L,1) do
+ lua_rawgeti(L,1,i);
+
+ if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+ glClearColor(lual_checknumber(L,-4),
+ lual_checknumber(L,-3),
+ lual_checknumber(L,-2),
+ lual_checknumber(L,-1))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.ClearColor''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_Color(L: Plua_State): Integer; cdecl;
+var
+ i: Integer;
+begin
+ if lua_istable(L, 1) then
+ for i := 1 to lua_objlen(L,1) do
+ lua_rawgeti(L,1,i);
+
+ if (lua_istable(L, 1) and (lua_objlen(L,1) = 3)) or (lua_gettop(L) = 3) then
+ glColor3d(GLdouble(lual_checknumber(L,-3)),
+ GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+ glColor4d(GLdouble(lual_checknumber(L,-4)),
+ GLdouble(lual_checknumber(L,-3)),
+ GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.Color''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_CullFace(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.CullFace''');
+
+ glCullFace(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_DepthFunc(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.DepthFunc''');
+
+ glDepthFunc(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_DepthRange(L: Plua_State): Integer; cdecl;
+var
+ i: Integer;
+begin
+ if lua_istable(L, 1) then
+ for i := 1 to lua_objlen(L,1) do
+ lua_rawgeti(L,1,i);
+
+ if (lua_istable(L, 1) and (lua_objlen(L,1) = 2))
+ or (lua_gettop(L) = 2) then
+ glDepthRange(lual_checkinteger(L,-2),
+ lual_checkinteger(L,-1))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.DepthRange''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_Disable(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.Disable''');
+
+ glDisable(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_DisableClientState(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.DisableClientState''');
+
+ glDisableClientState(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_DrawBuffer(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.DrawBuffer''');
+
+ glDrawBuffer(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_Enable(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.Enable''');
+
+ glEnable(e);
+ result:=0; // number of results
+end;
+
+function ULuaGl_EnableClientState(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.EnableClientState''');
+
+ glEnableClientState(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_End(L: Plua_State): Integer; cdecl;
+begin
+ glEnd();
+ result:=0; // number of results
+end;
+
+function ULuaGl_EndList(L: Plua_State): Integer; cdecl;
+begin
+ glEndList();
+ result:=0; // number of results
+end;
+
+function ULuaGl_Finish(L: Plua_State): Integer; cdecl;
+begin
+ glFinish();
+ result:=0; // number of results
+end;
+
+function ULuaGl_Flush(L: Plua_State): Integer; cdecl;
+begin
+ glFlush();
+ result:=0; // number of results
+end;
+
+function ULuaGl_FrontFace(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.FrontFace''');
+
+ glFrontFace(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_InitNames(L: Plua_State): Integer; cdecl;
+begin
+ glInitNames();
+ result:=0; // number of results
+end;
+
+function ULuaGl_LoadIdentity(L: Plua_State): Integer; cdecl;
+begin
+ glLoadIdentity();
+ result:=0; // number of results
+end;
+
+function ULuaGl_LogicOp(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.LogicOp''');
+
+ glLogicOp(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_MatrixMode(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.MatrixMode''');
+
+ glMatrixMode(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_Ortho(L: Plua_State): Integer; cdecl;
+begin
+ if (lua_gettop(L) = 6) then
+ glOrtho(lual_checkinteger(L,-6),
+ lual_checkinteger(L,-5),
+ lual_checkinteger(L,-4),
+ lual_checkinteger(L,-3),
+ lual_checkinteger(L,-2),
+ lual_checkinteger(L,-1))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.Ortho''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_PopAttrib(L: Plua_State): Integer; cdecl;
+begin
+ glPopAttrib();
+ result:=0; // number of results
+end;
+
+function ULuaGl_PopClientAttrib(L: Plua_State): Integer; cdecl;
+begin
+ glPopClientAttrib();
+ result:=0; // number of results
+end;
+
+function ULuaGl_PopMatrix(L: Plua_State): Integer; cdecl;
+begin
+ glPopMatrix();
+ result:=0; // number of results
+end;
+
+function ULuaGl_PopName(L: Plua_State): Integer; cdecl;
+begin
+ glPopName();
+ result:=0; // number of results
+end;
+
+function ULuaGl_PushMatrix(L: Plua_State): Integer; cdecl;
+begin
+ glPopName();
+ result:=0; // number of results
+end;
+
+function ULuaGl_RasterPos(L: Plua_State): Integer; cdecl;
+var
+ i: Integer;
+begin
+ if lua_istable(L, 1) then
+ for i := 1 to lua_objlen(L,1) do
+ lua_rawgeti(L,1,i);
+
+ if (lua_istable(L, 1) and (lua_objlen(L,1) = 2)) or (lua_gettop(L) = 2) then
+ glRasterPos2d(GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else if (lua_istable(L, 1) and (lua_objlen(L,1) = 3)) or (lua_gettop(L) = 3) then
+ glRasterPos3d(GLdouble(lual_checknumber(L,-3)),
+ GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+ glRasterPos4d(GLdouble(lual_checknumber(L,-4)),
+ GLdouble(lual_checknumber(L,-3)),
+ GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.RasterPos''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_ReadBuffer(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.ReadBuffer''');
+
+ glReadBuffer(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_Rect(L: Plua_State): Integer; cdecl;
+var
+ i: Integer;
+begin
+ if lua_istable(L, 1) and lua_istable(L, 2) then
+ begin
+ for i := 1 to lua_objlen(L,1) do
+ lua_rawgeti(L,1,i);
+ for i := 1 to lua_objlen(L,2) do
+ lua_rawgeti(L,2,i);
+ end;
+
+ if (lua_istable(L, 1) and (lua_objlen(L,1) = 2))
+ and (lua_istable(L, 2) and (lua_objlen(L,2) = 2))
+ or (lua_gettop(L) = 4) then
+ glRectD(lual_checknumber(L,-4),
+ lual_checknumber(L,-3),
+ lual_checknumber(L,-2),
+ lual_checknumber(L,-1))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.Rect''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_Rotate(L: Plua_State): Integer; cdecl;
+begin
+ if (lua_gettop(L) = 3) then
+ glRotated(lual_checkinteger(L,-4),
+ lual_checkinteger(L,-3),
+ lual_checkinteger(L,-2),
+ lual_checkinteger(L,-1))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.Rotate''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_Scale(L: Plua_State): Integer; cdecl;
+begin
+ if (lua_gettop(L) = 3) then
+ glScaled(lual_checkinteger(L,-3),
+ lual_checkinteger(L,-2),
+ lual_checkinteger(L,-1))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.Scale''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_ShadeModel(L: Plua_State): Integer; cdecl;
+var
+ e : GLenum;
+begin
+ e := ULuaGl_StringToEnum(lual_checkstring(L,1));
+
+ if (e = ULuaGl_EnumERROR) then
+ luaL_error(L, 'incorrect string argument to function ''gl.ShadeModel''');
+
+ glShadeModel(e);
+
+ result:=0; // number of results
+end;
+
+function ULuaGl_TexCoord(L: Plua_State): Integer; cdecl;
+var
+ i: Integer;
+begin
+ if lua_istable(L, 1) then
+ for i := 1 to lua_objlen(L,1) do
+ lua_rawgeti(L,1,i);
+
+ if (lua_istable(L, 1) and (lua_objlen(L,1) = 1)) or (lua_gettop(L) = 1) then
+ glTexCoord1d(GLdouble(lual_checknumber(L,-1)))
+ else if (lua_istable(L, 1) and (lua_objlen(L,1) = 2)) or (lua_gettop(L) = 2) then
+ glTexCoord2d(GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else if (lua_istable(L, 1) and (lua_objlen(L,1) = 3)) or (lua_gettop(L) = 3) then
+ glTexCoord3d(GLdouble(lual_checknumber(L,-3)),
+ GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+ glTexCoord4d(GLdouble(lual_checknumber(L,-4)),
+ GLdouble(lual_checknumber(L,-3)),
+ GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.TexCoord''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_Translate(L: Plua_State): Integer; cdecl;
+begin
+ if (lua_gettop(L) = 3) then
+ glTranslated(lual_checkinteger(L,-3),
+ lual_checkinteger(L,-2),
+ lual_checkinteger(L,-1))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.Translate''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_Vertex(L: Plua_State): Integer; cdecl;
+var
+ i: Integer;
+begin
+ if lua_istable(L, 1) then
+ for i := 1 to lua_objlen(L,1) do
+ lua_rawgeti(L,1,i);
+
+ if (lua_istable(L, 1) and (lua_objlen(L,1) = 2)) or (lua_gettop(L) = 2) then
+ glVertex2d(GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else if (lua_istable(L, 1) and (lua_objlen(L,1) = 3)) or (lua_gettop(L) = 3) then
+ glVertex3d(GLdouble(lual_checknumber(L,-3)),
+ GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else if (lua_istable(L, 1) and (lua_objlen(L,1) = 4)) or (lua_gettop(L) = 4) then
+ glVertex4d(GLdouble(lual_checknumber(L,-4)),
+ GLdouble(lual_checknumber(L,-3)),
+ GLdouble(lual_checknumber(L,-2)),
+ GLdouble(lual_checknumber(L,-1)))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.Vertex''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_Viewport(L: Plua_State): Integer; cdecl;
+var
+ i: Integer;
+begin
+ if lua_istable(L, 1) and lua_istable(L, 2) then
+ begin
+ for i := 1 to lua_objlen(L,1) do
+ lua_rawgeti(L,1,i);
+ for i := 1 to lua_objlen(L,2) do
+ lua_rawgeti(L,2,i);
+ end;
+
+ if (lua_istable(L, 1) and (lua_objlen(L,1) = 2))
+ and (lua_istable(L, 2) and (lua_objlen(L,2) = 2))
+ or (lua_gettop(L) = 4) then
+ glViewport(lual_checkinteger(L,-4),
+ lual_checkinteger(L,-3),
+ lual_checkinteger(L,-2),
+ lual_checkinteger(L,-1))
+ else
+ luaL_error(L, 'incorrect argument to function ''gl.Viewport''');
+ result:=0; // number of results
+end;
+
+function ULuaGl_Dummy(L: Plua_State): Integer; cdecl;
+begin
+ result:=0; // number of results
+end;
+
+function luaopen_gl (L: Plua_State): Integer; cdecl;
+begin
+ luaL_register(L,'gl',@ULuaGl_Lib_f[0]);
+ result:=1;
+end;
+
+(*
+ glAccum: procedure(op: GLenum; value: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glAlphaFunc: procedure(func: GLenum; ref: GLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glAreTexturesResident: function (n: GLsizei; const textures: PGLuint; residences: PGLboolean): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glArrayElement: procedure(i: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glBitmap: procedure (width, height: GLsizei; xorig, yorig: GLfloat; xmove, ymove: GLfloat; const bitmap: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glCallList: procedure(list: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glCallLists: procedure(n: GLsizei; atype: GLenum; const lists: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glClearDepth: procedure(depth: GLclampd); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glClearIndex: procedure(c: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glClearStencil: procedure(s: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glClipPlane: procedure(plane: GLenum; const equation: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+ glColorMask: procedure(red, green, blue, alpha: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glColorMaterial: procedure(face, mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glColorPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glCopyPixels: procedure(x, y: GLint; width, height: GLsizei; atype: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glCopyTexImage1D: procedure (target: GLenum; level: GLint; internalFormat: GLenum; x, y: GLint; width: GLsizei; border: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glCopyTexImage2D: procedure(target: GLenum; level: GLint; internalFormat: GLenum; x, y: GLint; width, height: GLsizei; border: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glCopyTexSubImage1D: procedure(target: GLenum; level, xoffset, x, y: GLint; width: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glCopyTexSubImage2D: procedure(target: GLenum; level, xoffset, yoffset, x, y: GLint; width, height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glDeleteLists: procedure(list: GLuint; range: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glDeleteTextures: procedure(n: GLsizei; const textures: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glDepthMask: procedure(flag: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glDrawArrays: procedure(mode: GLenum; first: GLint; count: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glDrawElements: procedure(mode: GLenum; count: GLsizei; atype: GLenum; const indices: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glDrawPixels: procedure(width, height: GLsizei; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEdgeFlag: procedure(flag: GLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEdgeFlagPointer: procedure(stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEdgeFlagv: procedure(const flag: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+ glEvalCoord1d: procedure(u: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalCoord1dv: procedure(const u: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalCoord1f: procedure(u: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalCoord1fv: procedure(const u: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalCoord2d: procedure(u, v: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalCoord2dv: procedure(const u: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalCoord2f: procedure(u, v: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalCoord2fv: procedure(const u: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+ glEvalMesh1: procedure(mode: GLenum; i1, i2: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalMesh2: procedure(mode: GLenum; i1, i2, j1, j2: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalPoint1: procedure(i: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glEvalPoint2: procedure(i, j: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glFeedbackBuffer: procedure(size: GLsizei; atype: GLenum; buffer: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glFogf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glFogfv: procedure(pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glFogi: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glFogiv: procedure(pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glFrustum: procedure(left, right, bottom, top, zNear, zFar: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGenLists: function(range: GLsizei): GLuint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGenTextures: procedure(n: GLsizei; textures: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetBooleanv: procedure(pname: GLenum; params: PGLboolean); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetClipPlane: procedure(plane: GLenum; equation: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetDoublev: procedure(pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+// glGetError: function: GLenum; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetFloatv: procedure(pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetIntegerv: procedure(pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetLightfv: procedure(light, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetLightiv: procedure(light, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetMapdv: procedure(target, query: GLenum; v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetMapfv: procedure(target, query: GLenum; v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetMapiv: procedure(target, query: GLenum; v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetMaterialfv: procedure(face, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetMaterialiv: procedure(face, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetPixelMapfv: procedure(map: GLenum; values: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetPixelMapuiv: procedure(map: GLenum; values: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetPixelMapusv: procedure(map: GLenum; values: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetPointerv: procedure(pname: GLenum; params: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetPolygonStipple: procedure(mask: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+/ glGetString: function(name: GLenum): PChar; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexEnvfv: procedure(target, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexEnviv: procedure(target, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexGendv: procedure(coord, pname: GLenum; params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexGenfv: procedure(coord, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexGeniv: procedure(coord, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexImage: procedure(target: GLenum; level: GLint; format: GLenum; atype: GLenum; pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexLevelParameterfv: procedure(target: GLenum; level: GLint; pname: GLenum; params: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexLevelParameteriv: procedure(target: GLenum; level: GLint; pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexParameterfv: procedure(target, pname: GLenum; params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glGetTexParameteriv: procedure(target, pname: GLenum; params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glHint: procedure(target, mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexMask: procedure(mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+ glIndexPointer: procedure(atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexd: procedure(c: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexdv: procedure(const c: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexf: procedure(c: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexfv: procedure(const c: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexi: procedure(c: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexiv: procedure(const c: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexs: procedure(c: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexsv: procedure(const c: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexub: procedure(c: GLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIndexubv: procedure(const c: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+ glInterleavedArrays: procedure(format: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+/ glIsEnabled: function(cap: GLenum): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIsList: function(list: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glIsTexture: function(texture: GLuint): GLboolean; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLightModelf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLightModelfv: procedure(pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLightModeli: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLightModeliv: procedure(pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLightf: procedure(light, pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLightfv: procedure(light, pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLighti: procedure(light, pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLightiv: procedure(light, pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLineStipple: procedure(factor: GLint; pattern: GLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLineWidth: procedure(width: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glListBase: procedure(base: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLoadMatrixd: procedure(const m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLoadMatrixf: procedure(const m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glLoadName: procedure(name: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMap1d: procedure(target: GLenum; u1, u2: GLdouble; stride, order: GLint; const points: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMap1f: procedure(target: GLenum; u1, u2: GLfloat; stride, order: GLint; const points: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMap2d: procedure(target: GLenum; u1, u2: GLdouble; ustride, uorder: GLint; v1, v2: GLdouble; vstride, vorder: GLint; const points: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMap2f: procedure(target: GLenum; u1, u2: GLfloat; ustride, uorder: GLint; v1, v2: GLfloat; vstride, vorder: GLint; const points: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMapGrid1d: procedure(un: GLint; u1, u2: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMapGrid1f: procedure(un: GLint; u1, u2: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMapGrid2d: procedure(un: GLint; u1, u2: GLdouble; vn: GLint; v1, v2: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMapGrid2f: procedure(un: GLint; u1, u2: GLfloat; vn: GLint; v1, v2: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMaterialf: procedure(face, pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMaterialfv: procedure(face, pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMateriali: procedure(face, pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMaterialiv: procedure(face, pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMultMatrixd: procedure(const m: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glMultMatrixf: procedure(const m: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNewList: procedure(list: GLuint; mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3b: procedure(nx, ny, nz: GLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3bv: procedure(const v: PGLbyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3d: procedure(nx, ny, nz: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3dv: procedure(const v: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3f: procedure(nx, ny, nz: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3fv: procedure(const v: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3i: procedure(nx, ny, nz: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3iv: procedure(const v: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3s: procedure(nx, ny, nz: GLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormal3sv: procedure(const v: PGLshort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glNormalPointer: procedure(atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPassThrough: procedure(token: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPixelMapfv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPixelMapuiv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPixelMapusv: procedure(map: GLenum; mapsize: GLsizei; const values: PGLushort); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPixelStoref: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPixelStorei: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPixelTransferf: procedure(pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPixelTransferi: procedure(pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPixelZoom: procedure(xfactor, yfactor: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPointSize: procedure(size: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPolygonMode: procedure(face, mode: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPolygonOffset: procedure(factor, units: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPolygonStipple: procedure(const mask: PGLubyte); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPrioritizeTextures: procedure(n: GLsizei; const textures: PGLuint; const priorities: PGLclampf); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPushAttrib: procedure(mask: GLbitfield); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPushClientAttrib: procedure(mask: GLbitfield); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glPushName: procedure(name: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glReadPixels: procedure(x, y: GLint; width, height: GLsizei; format, atype: GLenum; pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+ glRenderMode: function(mode: GLint): GLint; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glScissor: procedure(x, y: GLint; width, height: GLsizei); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glSelectBuffer: procedure(size: GLsizei; buffer: PGLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glStencilFunc: procedure(func: GLenum; ref: GLint; mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glStencilMask: procedure(mask: GLuint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glStencilOp: procedure(fail, zfail, zpass: GLenum); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+
+ glTexCoordPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexEnvf: procedure(target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexEnvfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexEnvi: procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexEnviv: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexGend: procedure(coord: GLenum; pname: GLenum; param: GLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexGendv: procedure(coord: GLenum; pname: GLenum; const params: PGLdouble); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexGenf: procedure(coord: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexGenfv: procedure(coord: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexGeni: procedure(coord: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexGeniv: procedure(coord: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexImage1D: procedure(target: GLenum; level, internalformat: GLint; width: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexImage2D: procedure(target: GLenum; level, internalformat: GLint; width, height: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexParameterf: procedure(target: GLenum; pname: GLenum; param: GLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexParameterfv: procedure(target: GLenum; pname: GLenum; const params: PGLfloat); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexParameteri: procedure(target: GLenum; pname: GLenum; param: GLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexParameteriv: procedure(target: GLenum; pname: GLenum; const params: PGLint); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexSubImage1D: procedure(target: GLenum; level, xoffset: GLint; width: GLsizei; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glTexSubImage2D: procedure(target: GLenum; level, xoffset, yoffset: GLint; width, height: GLsizei; format, atype: GLenum; const pixels: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ glVertexPointer: procedure(size: GLint; atype: GLenum; stride: GLsizei; const pointer: Pointer); {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ {$IFDEF WINDOWS}
+ ChoosePixelFormat: function(DC: HDC; p2: PPixelFormatDescriptor): Integer; {$IFDEF WINDOWS}stdcall;{$ELSE}cdecl;{$ENDIF}
+ {$ENDIF}
+ *)
+
+ const
+ ULuaGl_Enum: array [0..579] of TULuaGl_Enums = (
+ (Text:'GL_VERSION_1_1';Value:GL_VERSION_1_1),
+ (Text:'GL_ACCUM';Value:GL_ACCUM),
+ (Text:'GL_LOAD';Value:GL_LOAD),
+ (Text:'GL_RETURN';Value:GL_RETURN),
+ (Text:'GL_MULT';Value:GL_MULT),
+ (Text:'GL_ADD';Value:GL_ADD),
+ (Text:'GL_NEVER';Value:GL_NEVER),
+ (Text:'GL_LESS';Value:GL_LESS),
+ (Text:'GL_EQUAL';Value:GL_EQUAL),
+ (Text:'GL_LEQUAL';Value:GL_LEQUAL),
+ (Text:'GL_GREATER';Value:GL_GREATER),
+ (Text:'GL_NOTEQUAL';Value:GL_NOTEQUAL),
+ (Text:'GL_GEQUAL';Value:GL_GEQUAL),
+ (Text:'GL_ALWAYS';Value:GL_ALWAYS),
+ (Text:'GL_CURRENT_BIT';Value:GL_CURRENT_BIT),
+ (Text:'GL_POINT_BIT';Value:GL_POINT_BIT),
+ (Text:'GL_LINE_BIT';Value:GL_LINE_BIT),
+ (Text:'GL_POLYGON_BIT';Value:GL_POLYGON_BIT),
+ (Text:'GL_POLYGON_STIPPLE_BIT';Value:GL_POLYGON_STIPPLE_BIT),
+ (Text:'GL_PIXEL_MODE_BIT';Value:GL_PIXEL_MODE_BIT),
+ (Text:'GL_LIGHTING_BIT';Value:GL_LIGHTING_BIT),
+ (Text:'GL_FOG_BIT';Value:GL_FOG_BIT),
+ (Text:'GL_DEPTH_BUFFER_BIT';Value:GL_DEPTH_BUFFER_BIT),
+ (Text:'GL_ACCUM_BUFFER_BIT';Value:GL_ACCUM_BUFFER_BIT),
+ (Text:'GL_STENCIL_BUFFER_BIT';Value:GL_STENCIL_BUFFER_BIT),
+ (Text:'GL_VIEWPORT_BIT';Value:GL_VIEWPORT_BIT),
+ (Text:'GL_TRANSFORM_BIT';Value:GL_TRANSFORM_BIT),
+ (Text:'GL_ENABLE_BIT';Value:GL_ENABLE_BIT),
+ (Text:'GL_COLOR_BUFFER_BIT';Value:GL_COLOR_BUFFER_BIT),
+ (Text:'GL_HINT_BIT';Value:GL_HINT_BIT),
+ (Text:'GL_EVAL_BIT';Value:GL_EVAL_BIT),
+ (Text:'GL_LIST_BIT';Value:GL_LIST_BIT),
+ (Text:'GL_TEXTURE_BIT';Value:GL_TEXTURE_BIT),
+ (Text:'GL_SCISSOR_BIT';Value:GL_SCISSOR_BIT),
+ (Text:'GL_ALL_ATTRIB_BITS';Value:GL_ALL_ATTRIB_BITS),
+ (Text:'GL_POINTS';Value:GL_POINTS),
+ (Text:'GL_LINES';Value:GL_LINES),
+ (Text:'GL_LINE_LOOP';Value:GL_LINE_LOOP),
+ (Text:'GL_LINE_STRIP';Value:GL_LINE_STRIP),
+ (Text:'GL_TRIANGLES';Value:GL_TRIANGLES),
+ (Text:'GL_TRIANGLE_STRIP';Value:GL_TRIANGLE_STRIP),
+ (Text:'GL_TRIANGLE_FAN';Value:GL_TRIANGLE_FAN),
+ (Text:'GL_QUADS';Value:GL_QUADS),
+ (Text:'GL_QUAD_STRIP';Value:GL_QUAD_STRIP),
+ (Text:'GL_POLYGON';Value:GL_POLYGON),
+ (Text:'GL_ZERO';Value:GL_ZERO),
+ (Text:'GL_ONE';Value:GL_ONE),
+ (Text:'GL_SRC_COLOR';Value:GL_SRC_COLOR),
+ (Text:'GL_ONE_MINUS_SRC_COLOR';Value:GL_ONE_MINUS_SRC_COLOR),
+ (Text:'GL_SRC_ALPHA';Value:GL_SRC_ALPHA),
+ (Text:'GL_ONE_MINUS_SRC_ALPHA';Value:GL_ONE_MINUS_SRC_ALPHA),
+ (Text:'GL_DST_ALPHA';Value:GL_DST_ALPHA),
+ (Text:'GL_ONE_MINUS_DST_ALPHA';Value:GL_ONE_MINUS_DST_ALPHA),
+ (Text:'GL_DST_COLOR';Value:GL_DST_COLOR),
+ (Text:'GL_ONE_MINUS_DST_COLOR';Value:GL_ONE_MINUS_DST_COLOR),
+ (Text:'GL_SRC_ALPHA_SATURATE';Value:GL_SRC_ALPHA_SATURATE),
+ (Text:'GL_TRUE';Value:GL_TRUE),
+ (Text:'GL_FALSE';Value:GL_FALSE),
+ (Text:'GL_CLIP_PLANE0';Value:GL_CLIP_PLANE0),
+ (Text:'GL_CLIP_PLANE1';Value:GL_CLIP_PLANE1),
+ (Text:'GL_CLIP_PLANE2';Value:GL_CLIP_PLANE2),
+ (Text:'GL_CLIP_PLANE3';Value:GL_CLIP_PLANE3),
+ (Text:'GL_CLIP_PLANE4';Value:GL_CLIP_PLANE4),
+ (Text:'GL_CLIP_PLANE5';Value:GL_CLIP_PLANE5),
+ (Text:'GL_BYTE';Value:GL_BYTE),
+ (Text:'GL_UNSIGNED_BYTE';Value:GL_UNSIGNED_BYTE),
+ (Text:'GL_SHORT';Value:GL_SHORT),
+ (Text:'GL_UNSIGNED_SHORT';Value:GL_UNSIGNED_SHORT),
+ (Text:'GL_INT';Value:GL_INT),
+ (Text:'GL_UNSIGNED_INT';Value:GL_UNSIGNED_INT),
+ (Text:'GL_FLOAT';Value:GL_FLOAT),
+ (Text:'GL_2_BYTES';Value:GL_2_BYTES),
+ (Text:'GL_3_BYTES';Value:GL_3_BYTES),
+ (Text:'GL_4_BYTES';Value:GL_4_BYTES),
+ (Text:'GL_DOUBLE';Value:GL_DOUBLE),
+ (Text:'GL_NONE';Value:GL_NONE),
+ (Text:'GL_FRONT_LEFT';Value:GL_FRONT_LEFT),
+ (Text:'GL_FRONT_RIGHT';Value:GL_FRONT_RIGHT),
+ (Text:'GL_BACK_LEFT';Value:GL_BACK_LEFT),
+ (Text:'GL_BACK_RIGHT';Value:GL_BACK_RIGHT),
+ (Text:'GL_FRONT';Value:GL_FRONT),
+ (Text:'GL_BACK';Value:GL_BACK),
+ (Text:'GL_LEFT';Value:GL_LEFT),
+ (Text:'GL_RIGHT';Value:GL_RIGHT),
+ (Text:'GL_FRONT_AND_BACK';Value:GL_FRONT_AND_BACK),
+ (Text:'GL_AUX0';Value:GL_AUX0),
+ (Text:'GL_AUX1';Value:GL_AUX1),
+ (Text:'GL_AUX2';Value:GL_AUX2),
+ (Text:'GL_AUX3';Value:GL_AUX3),
+ (Text:'GL_NO_ERROR';Value:GL_NO_ERROR),
+ (Text:'GL_INVALID_ENUM';Value:GL_INVALID_ENUM),
+ (Text:'GL_INVALID_VALUE';Value:GL_INVALID_VALUE),
+ (Text:'GL_INVALID_OPERATION';Value:GL_INVALID_OPERATION),
+ (Text:'GL_STACK_OVERFLOW';Value:GL_STACK_OVERFLOW),
+ (Text:'GL_STACK_UNDERFLOW';Value:GL_STACK_UNDERFLOW),
+ (Text:'GL_OUT_OF_MEMORY';Value:GL_OUT_OF_MEMORY),
+ (Text:'GL_2D';Value:GL_2D),
+ (Text:'GL_3D';Value:GL_3D),
+ (Text:'GL_3D_COLOR';Value:GL_3D_COLOR),
+ (Text:'GL_3D_COLOR_TEXTURE';Value:GL_3D_COLOR_TEXTURE),
+ (Text:'GL_4D_COLOR_TEXTURE';Value:GL_4D_COLOR_TEXTURE),
+ (Text:'GL_PASS_THROUGH_TOKEN';Value:GL_PASS_THROUGH_TOKEN),
+ (Text:'GL_POINT_TOKEN';Value:GL_POINT_TOKEN),
+ (Text:'GL_LINE_TOKEN';Value:GL_LINE_TOKEN),
+ (Text:'GL_POLYGON_TOKEN';Value:GL_POLYGON_TOKEN),
+ (Text:'GL_BITMAP_TOKEN';Value:GL_BITMAP_TOKEN),
+ (Text:'GL_DRAW_PIXEL_TOKEN';Value:GL_DRAW_PIXEL_TOKEN),
+ (Text:'GL_COPY_PIXEL_TOKEN';Value:GL_COPY_PIXEL_TOKEN),
+ (Text:'GL_LINE_RESET_TOKEN';Value:GL_LINE_RESET_TOKEN),
+ (Text:'GL_EXP';Value:GL_EXP),
+ (Text:'GL_EXP2';Value:GL_EXP2),
+ (Text:'GL_CW';Value:GL_CW),
+ (Text:'GL_CCW';Value:GL_CCW),
+ (Text:'GL_COEFF';Value:GL_COEFF),
+ (Text:'GL_ORDER';Value:GL_ORDER),
+ (Text:'GL_DOMAIN';Value:GL_DOMAIN),
+ (Text:'GL_CURRENT_COLOR';Value:GL_CURRENT_COLOR),
+ (Text:'GL_CURRENT_INDEX';Value:GL_CURRENT_INDEX),
+ (Text:'GL_CURRENT_NORMAL';Value:GL_CURRENT_NORMAL),
+ (Text:'GL_CURRENT_TEXTURE_COORDS';Value:GL_CURRENT_TEXTURE_COORDS),
+ (Text:'GL_CURRENT_RASTER_COLOR';Value:GL_CURRENT_RASTER_COLOR),
+ (Text:'GL_CURRENT_RASTER_INDEX';Value:GL_CURRENT_RASTER_INDEX),
+ (Text:'GL_CURRENT_RASTER_TEXTURE_COORDS';Value:GL_CURRENT_RASTER_TEXTURE_COORDS),
+ (Text:'GL_CURRENT_RASTER_POSITION';Value:GL_CURRENT_RASTER_POSITION),
+ (Text:'GL_CURRENT_RASTER_POSITION_VALID';Value:GL_CURRENT_RASTER_POSITION_VALID),
+ (Text:'GL_CURRENT_RASTER_DISTANCE';Value:GL_CURRENT_RASTER_DISTANCE),
+ (Text:'GL_POINT_SMOOTH';Value:GL_POINT_SMOOTH),
+ (Text:'GL_POINT_SIZE';Value:GL_POINT_SIZE),
+ (Text:'GL_POINT_SIZE_RANGE';Value:GL_POINT_SIZE_RANGE),
+ (Text:'GL_POINT_SIZE_GRANULARITY';Value:GL_POINT_SIZE_GRANULARITY),
+ (Text:'GL_LINE_SMOOTH';Value:GL_LINE_SMOOTH),
+ (Text:'GL_LINE_WIDTH';Value:GL_LINE_WIDTH),
+ (Text:'GL_LINE_WIDTH_RANGE';Value:GL_LINE_WIDTH_RANGE),
+ (Text:'GL_LINE_WIDTH_GRANULARITY';Value:GL_LINE_WIDTH_GRANULARITY),
+ (Text:'GL_LINE_STIPPLE';Value:GL_LINE_STIPPLE),
+ (Text:'GL_LINE_STIPPLE_PATTERN';Value:GL_LINE_STIPPLE_PATTERN),
+ (Text:'GL_LINE_STIPPLE_REPEAT';Value:GL_LINE_STIPPLE_REPEAT),
+ (Text:'GL_LIST_MODE';Value:GL_LIST_MODE),
+ (Text:'GL_MAX_LIST_NESTING';Value:GL_MAX_LIST_NESTING),
+ (Text:'GL_LIST_BASE';Value:GL_LIST_BASE),
+ (Text:'GL_LIST_INDEX';Value:GL_LIST_INDEX),
+ (Text:'GL_POLYGON_MODE';Value:GL_POLYGON_MODE),
+ (Text:'GL_POLYGON_SMOOTH';Value:GL_POLYGON_SMOOTH),
+ (Text:'GL_POLYGON_STIPPLE';Value:GL_POLYGON_STIPPLE),
+ (Text:'GL_EDGE_FLAG';Value:GL_EDGE_FLAG),
+ (Text:'GL_CULL_FACE';Value:GL_CULL_FACE),
+ (Text:'GL_CULL_FACE_MODE';Value:GL_CULL_FACE_MODE),
+ (Text:'GL_FRONT_FACE';Value:GL_FRONT_FACE),
+ (Text:'GL_LIGHTING';Value:GL_LIGHTING),
+ (Text:'GL_LIGHT_MODEL_LOCAL_VIEWER';Value:GL_LIGHT_MODEL_LOCAL_VIEWER),
+ (Text:'GL_LIGHT_MODEL_TWO_SIDE';Value:GL_LIGHT_MODEL_TWO_SIDE),
+ (Text:'GL_LIGHT_MODEL_AMBIENT';Value:GL_LIGHT_MODEL_AMBIENT),
+ (Text:'GL_SHADE_MODEL';Value:GL_SHADE_MODEL),
+ (Text:'GL_COLOR_MATERIAL_FACE';Value:GL_COLOR_MATERIAL_FACE),
+ (Text:'GL_COLOR_MATERIAL_PARAMETER';Value:GL_COLOR_MATERIAL_PARAMETER),
+ (Text:'GL_COLOR_MATERIAL';Value:GL_COLOR_MATERIAL),
+ (Text:'GL_FOG';Value:GL_FOG),
+ (Text:'GL_FOG_INDEX';Value:GL_FOG_INDEX),
+ (Text:'GL_FOG_DENSITY';Value:GL_FOG_DENSITY),
+ (Text:'GL_FOG_START';Value:GL_FOG_START),
+ (Text:'GL_FOG_END';Value:GL_FOG_END),
+ (Text:'GL_FOG_MODE';Value:GL_FOG_MODE),
+ (Text:'GL_FOG_COLOR';Value:GL_FOG_COLOR),
+ (Text:'GL_DEPTH_RANGE';Value:GL_DEPTH_RANGE),
+ (Text:'GL_DEPTH_TEST';Value:GL_DEPTH_TEST),
+ (Text:'GL_DEPTH_WRITEMASK';Value:GL_DEPTH_WRITEMASK),
+ (Text:'GL_DEPTH_CLEAR_VALUE';Value:GL_DEPTH_CLEAR_VALUE),
+ (Text:'GL_DEPTH_FUNC';Value:GL_DEPTH_FUNC),
+ (Text:'GL_ACCUM_CLEAR_VALUE';Value:GL_ACCUM_CLEAR_VALUE),
+ (Text:'GL_STENCIL_TEST';Value:GL_STENCIL_TEST),
+ (Text:'GL_STENCIL_CLEAR_VALUE';Value:GL_STENCIL_CLEAR_VALUE),
+ (Text:'GL_STENCIL_FUNC';Value:GL_STENCIL_FUNC),
+ (Text:'GL_STENCIL_VALUE_MASK';Value:GL_STENCIL_VALUE_MASK),
+ (Text:'GL_STENCIL_FAIL';Value:GL_STENCIL_FAIL),
+ (Text:'GL_STENCIL_PASS_DEPTH_FAIL';Value:GL_STENCIL_PASS_DEPTH_FAIL),
+ (Text:'GL_STENCIL_PASS_DEPTH_PASS';Value:GL_STENCIL_PASS_DEPTH_PASS),
+ (Text:'GL_STENCIL_REF';Value:GL_STENCIL_REF),
+ (Text:'GL_STENCIL_WRITEMASK';Value:GL_STENCIL_WRITEMASK),
+ (Text:'GL_MATRIX_MODE';Value:GL_MATRIX_MODE),
+ (Text:'GL_NORMALIZE';Value:GL_NORMALIZE),
+ (Text:'GL_VIEWPORT';Value:GL_VIEWPORT),
+ (Text:'GL_MODELVIEW_STACK_DEPTH';Value:GL_MODELVIEW_STACK_DEPTH),
+ (Text:'GL_PROJECTION_STACK_DEPTH';Value:GL_PROJECTION_STACK_DEPTH),
+ (Text:'GL_TEXTURE_STACK_DEPTH';Value:GL_TEXTURE_STACK_DEPTH),
+ (Text:'GL_MODELVIEW_MATRIX';Value:GL_MODELVIEW_MATRIX),
+ (Text:'GL_PROJECTION_MATRIX';Value:GL_PROJECTION_MATRIX),
+ (Text:'GL_TEXTURE_MATRIX';Value:GL_TEXTURE_MATRIX),
+ (Text:'GL_ATTRIB_STACK_DEPTH';Value:GL_ATTRIB_STACK_DEPTH),
+ (Text:'GL_CLIENT_ATTRIB_STACK_DEPTH';Value:GL_CLIENT_ATTRIB_STACK_DEPTH),
+ (Text:'GL_ALPHA_TEST';Value:GL_ALPHA_TEST),
+ (Text:'GL_ALPHA_TEST_FUNC';Value:GL_ALPHA_TEST_FUNC),
+ (Text:'GL_ALPHA_TEST_REF';Value:GL_ALPHA_TEST_REF),
+ (Text:'GL_DITHER';Value:GL_DITHER),
+ (Text:'GL_BLEND_DST';Value:GL_BLEND_DST),
+ (Text:'GL_BLEND_SRC';Value:GL_BLEND_SRC),
+ (Text:'GL_BLEND';Value:GL_BLEND),
+ (Text:'GL_LOGIC_OP_MODE';Value:GL_LOGIC_OP_MODE),
+ (Text:'GL_INDEX_LOGIC_OP';Value:GL_INDEX_LOGIC_OP),
+ (Text:'GL_COLOR_LOGIC_OP';Value:GL_COLOR_LOGIC_OP),
+ (Text:'GL_AUX_BUFFERS';Value:GL_AUX_BUFFERS),
+ (Text:'GL_DRAW_BUFFER';Value:GL_DRAW_BUFFER),
+ (Text:'GL_READ_BUFFER';Value:GL_READ_BUFFER),
+ (Text:'GL_SCISSOR_BOX';Value:GL_SCISSOR_BOX),
+ (Text:'GL_SCISSOR_TEST';Value:GL_SCISSOR_TEST),
+ (Text:'GL_INDEX_CLEAR_VALUE';Value:GL_INDEX_CLEAR_VALUE),
+ (Text:'GL_INDEX_WRITEMASK';Value:GL_INDEX_WRITEMASK),
+ (Text:'GL_COLOR_CLEAR_VALUE';Value:GL_COLOR_CLEAR_VALUE),
+ (Text:'GL_COLOR_WRITEMASK';Value:GL_COLOR_WRITEMASK),
+ (Text:'GL_INDEX_MODE';Value:GL_INDEX_MODE),
+ (Text:'GL_RGBA_MODE';Value:GL_RGBA_MODE),
+ (Text:'GL_DOUBLEBUFFER';Value:GL_DOUBLEBUFFER),
+ (Text:'GL_STEREO';Value:GL_STEREO),
+ (Text:'GL_RENDER_MODE';Value:GL_RENDER_MODE),
+ (Text:'GL_PERSPECTIVE_CORRECTION_HINT';Value:GL_PERSPECTIVE_CORRECTION_HINT),
+ (Text:'GL_POINT_SMOOTH_HINT';Value:GL_POINT_SMOOTH_HINT),
+ (Text:'GL_LINE_SMOOTH_HINT';Value:GL_LINE_SMOOTH_HINT),
+ (Text:'GL_POLYGON_SMOOTH_HINT';Value:GL_POLYGON_SMOOTH_HINT),
+ (Text:'GL_FOG_HINT';Value:GL_FOG_HINT),
+ (Text:'GL_TEXTURE_GEN_S';Value:GL_TEXTURE_GEN_S),
+ (Text:'GL_TEXTURE_GEN_T';Value:GL_TEXTURE_GEN_T),
+ (Text:'GL_TEXTURE_GEN_R';Value:GL_TEXTURE_GEN_R),
+ (Text:'GL_TEXTURE_GEN_Q';Value:GL_TEXTURE_GEN_Q),
+ (Text:'GL_PIXEL_MAP_I_TO_I';Value:GL_PIXEL_MAP_I_TO_I),
+ (Text:'GL_PIXEL_MAP_S_TO_S';Value:GL_PIXEL_MAP_S_TO_S),
+ (Text:'GL_PIXEL_MAP_I_TO_R';Value:GL_PIXEL_MAP_I_TO_R),
+ (Text:'GL_PIXEL_MAP_I_TO_G';Value:GL_PIXEL_MAP_I_TO_G),
+ (Text:'GL_PIXEL_MAP_I_TO_B';Value:GL_PIXEL_MAP_I_TO_B),
+ (Text:'GL_PIXEL_MAP_I_TO_A';Value:GL_PIXEL_MAP_I_TO_A),
+ (Text:'GL_PIXEL_MAP_R_TO_R';Value:GL_PIXEL_MAP_R_TO_R),
+ (Text:'GL_PIXEL_MAP_G_TO_G';Value:GL_PIXEL_MAP_G_TO_G),
+ (Text:'GL_PIXEL_MAP_B_TO_B';Value:GL_PIXEL_MAP_B_TO_B),
+ (Text:'GL_PIXEL_MAP_A_TO_A';Value:GL_PIXEL_MAP_A_TO_A),
+ (Text:'GL_PIXEL_MAP_I_TO_I_SIZE';Value:GL_PIXEL_MAP_I_TO_I_SIZE),
+ (Text:'GL_PIXEL_MAP_S_TO_S_SIZE';Value:GL_PIXEL_MAP_S_TO_S_SIZE),
+ (Text:'GL_PIXEL_MAP_I_TO_R_SIZE';Value:GL_PIXEL_MAP_I_TO_R_SIZE),
+ (Text:'GL_PIXEL_MAP_I_TO_G_SIZE';Value:GL_PIXEL_MAP_I_TO_G_SIZE),
+ (Text:'GL_PIXEL_MAP_I_TO_B_SIZE';Value:GL_PIXEL_MAP_I_TO_B_SIZE),
+ (Text:'GL_PIXEL_MAP_I_TO_A_SIZE';Value:GL_PIXEL_MAP_I_TO_A_SIZE),
+ (Text:'GL_PIXEL_MAP_R_TO_R_SIZE';Value:GL_PIXEL_MAP_R_TO_R_SIZE),
+ (Text:'GL_PIXEL_MAP_G_TO_G_SIZE';Value:GL_PIXEL_MAP_G_TO_G_SIZE),
+ (Text:'GL_PIXEL_MAP_B_TO_B_SIZE';Value:GL_PIXEL_MAP_B_TO_B_SIZE),
+ (Text:'GL_PIXEL_MAP_A_TO_A_SIZE';Value:GL_PIXEL_MAP_A_TO_A_SIZE),
+ (Text:'GL_UNPACK_SWAP_BYTES';Value:GL_UNPACK_SWAP_BYTES),
+ (Text:'GL_UNPACK_LSB_FIRST';Value:GL_UNPACK_LSB_FIRST),
+ (Text:'GL_UNPACK_ROW_LENGTH';Value:GL_UNPACK_ROW_LENGTH),
+ (Text:'GL_UNPACK_SKIP_ROWS';Value:GL_UNPACK_SKIP_ROWS),
+ (Text:'GL_UNPACK_SKIP_PIXELS';Value:GL_UNPACK_SKIP_PIXELS),
+ (Text:'GL_UNPACK_ALIGNMENT';Value:GL_UNPACK_ALIGNMENT),
+ (Text:'GL_PACK_SWAP_BYTES';Value:GL_PACK_SWAP_BYTES),
+ (Text:'GL_PACK_LSB_FIRST';Value:GL_PACK_LSB_FIRST),
+ (Text:'GL_PACK_ROW_LENGTH';Value:GL_PACK_ROW_LENGTH),
+ (Text:'GL_PACK_SKIP_ROWS';Value:GL_PACK_SKIP_ROWS),
+ (Text:'GL_PACK_SKIP_PIXELS';Value:GL_PACK_SKIP_PIXELS),
+ (Text:'GL_PACK_ALIGNMENT';Value:GL_PACK_ALIGNMENT),
+ (Text:'GL_MAP_COLOR';Value:GL_MAP_COLOR),
+ (Text:'GL_MAP_STENCIL';Value:GL_MAP_STENCIL),
+ (Text:'GL_INDEX_SHIFT';Value:GL_INDEX_SHIFT),
+ (Text:'GL_INDEX_OFFSET';Value:GL_INDEX_OFFSET),
+ (Text:'GL_RED_SCALE';Value:GL_RED_SCALE),
+ (Text:'GL_RED_BIAS';Value:GL_RED_BIAS),
+ (Text:'GL_ZOOM_X';Value:GL_ZOOM_X),
+ (Text:'GL_ZOOM_Y';Value:GL_ZOOM_Y),
+ (Text:'GL_GREEN_SCALE';Value:GL_GREEN_SCALE),
+ (Text:'GL_GREEN_BIAS';Value:GL_GREEN_BIAS),
+ (Text:'GL_BLUE_SCALE';Value:GL_BLUE_SCALE),
+ (Text:'GL_BLUE_BIAS';Value:GL_BLUE_BIAS),
+ (Text:'GL_ALPHA_SCALE';Value:GL_ALPHA_SCALE),
+ (Text:'GL_ALPHA_BIAS';Value:GL_ALPHA_BIAS),
+ (Text:'GL_DEPTH_SCALE';Value:GL_DEPTH_SCALE),
+ (Text:'GL_DEPTH_BIAS';Value:GL_DEPTH_BIAS),
+ (Text:'GL_MAX_EVAL_ORDER';Value:GL_MAX_EVAL_ORDER),
+ (Text:'GL_MAX_LIGHTS';Value:GL_MAX_LIGHTS),
+ (Text:'GL_MAX_CLIP_PLANES';Value:GL_MAX_CLIP_PLANES),
+ (Text:'GL_MAX_TEXTURE_SIZE';Value:GL_MAX_TEXTURE_SIZE),
+ (Text:'GL_MAX_PIXEL_MAP_TABLE';Value:GL_MAX_PIXEL_MAP_TABLE),
+ (Text:'GL_MAX_ATTRIB_STACK_DEPTH';Value:GL_MAX_ATTRIB_STACK_DEPTH),
+ (Text:'GL_MAX_MODELVIEW_STACK_DEPTH';Value:GL_MAX_MODELVIEW_STACK_DEPTH),
+ (Text:'GL_MAX_NAME_STACK_DEPTH';Value:GL_MAX_NAME_STACK_DEPTH),
+ (Text:'GL_MAX_PROJECTION_STACK_DEPTH';Value:GL_MAX_PROJECTION_STACK_DEPTH),
+ (Text:'GL_MAX_TEXTURE_STACK_DEPTH';Value:GL_MAX_TEXTURE_STACK_DEPTH),
+ (Text:'GL_MAX_VIEWPORT_DIMS';Value:GL_MAX_VIEWPORT_DIMS),
+ (Text:'GL_MAX_CLIENT_ATTRIB_STACK_DEPTH';Value:GL_MAX_CLIENT_ATTRIB_STACK_DEPTH),
+ (Text:'GL_SUBPIXEL_BITS';Value:GL_SUBPIXEL_BITS),
+ (Text:'GL_INDEX_BITS';Value:GL_INDEX_BITS),
+ (Text:'GL_RED_BITS';Value:GL_RED_BITS),
+ (Text:'GL_GREEN_BITS';Value:GL_GREEN_BITS),
+ (Text:'GL_BLUE_BITS';Value:GL_BLUE_BITS),
+ (Text:'GL_ALPHA_BITS';Value:GL_ALPHA_BITS),
+ (Text:'GL_DEPTH_BITS';Value:GL_DEPTH_BITS),
+ (Text:'GL_STENCIL_BITS';Value:GL_STENCIL_BITS),
+ (Text:'GL_ACCUM_RED_BITS';Value:GL_ACCUM_RED_BITS),
+ (Text:'GL_ACCUM_GREEN_BITS';Value:GL_ACCUM_GREEN_BITS),
+ (Text:'GL_ACCUM_BLUE_BITS';Value:GL_ACCUM_BLUE_BITS),
+ (Text:'GL_ACCUM_ALPHA_BITS';Value:GL_ACCUM_ALPHA_BITS),
+ (Text:'GL_NAME_STACK_DEPTH';Value:GL_NAME_STACK_DEPTH),
+ (Text:'GL_AUTO_NORMAL';Value:GL_AUTO_NORMAL),
+ (Text:'GL_MAP1_COLOR_4';Value:GL_MAP1_COLOR_4),
+ (Text:'GL_MAP1_INDEX';Value:GL_MAP1_INDEX),
+ (Text:'GL_MAP1_NORMAL';Value:GL_MAP1_NORMAL),
+ (Text:'GL_MAP1_TEXTURE_COORD_1';Value:GL_MAP1_TEXTURE_COORD_1),
+ (Text:'GL_MAP1_TEXTURE_COORD_2';Value:GL_MAP1_TEXTURE_COORD_2),
+ (Text:'GL_MAP1_TEXTURE_COORD_3';Value:GL_MAP1_TEXTURE_COORD_3),
+ (Text:'GL_MAP1_TEXTURE_COORD_4';Value:GL_MAP1_TEXTURE_COORD_4),
+ (Text:'GL_MAP1_VERTEX_3';Value:GL_MAP1_VERTEX_3),
+ (Text:'GL_MAP1_VERTEX_4';Value:GL_MAP1_VERTEX_4),
+ (Text:'GL_MAP2_COLOR_4';Value:GL_MAP2_COLOR_4),
+ (Text:'GL_MAP2_INDEX';Value:GL_MAP2_INDEX),
+ (Text:'GL_MAP2_NORMAL';Value:GL_MAP2_NORMAL),
+ (Text:'GL_MAP2_TEXTURE_COORD_1';Value:GL_MAP2_TEXTURE_COORD_1),
+ (Text:'GL_MAP2_TEXTURE_COORD_2';Value:GL_MAP2_TEXTURE_COORD_2),
+ (Text:'GL_MAP2_TEXTURE_COORD_3';Value:GL_MAP2_TEXTURE_COORD_3),
+ (Text:'GL_MAP2_TEXTURE_COORD_4';Value:GL_MAP2_TEXTURE_COORD_4),
+ (Text:'GL_MAP2_VERTEX_3';Value:GL_MAP2_VERTEX_3),
+ (Text:'GL_MAP2_VERTEX_4';Value:GL_MAP2_VERTEX_4),
+ (Text:'GL_MAP1_GRID_DOMAIN';Value:GL_MAP1_GRID_DOMAIN),
+ (Text:'GL_MAP1_GRID_SEGMENTS';Value:GL_MAP1_GRID_SEGMENTS),
+ (Text:'GL_MAP2_GRID_DOMAIN';Value:GL_MAP2_GRID_DOMAIN),
+ (Text:'GL_MAP2_GRID_SEGMENTS';Value:GL_MAP2_GRID_SEGMENTS),
+ (Text:'GL_TEXTURE_1D';Value:GL_TEXTURE_1D),
+ (Text:'GL_TEXTURE_2D';Value:GL_TEXTURE_2D),
+ (Text:'GL_FEEDBACK_BUFFER_POINTER';Value:GL_FEEDBACK_BUFFER_POINTER),
+ (Text:'GL_FEEDBACK_BUFFER_SIZE';Value:GL_FEEDBACK_BUFFER_SIZE),
+ (Text:'GL_FEEDBACK_BUFFER_TYPE';Value:GL_FEEDBACK_BUFFER_TYPE),
+ (Text:'GL_SELECTION_BUFFER_POINTER';Value:GL_SELECTION_BUFFER_POINTER),
+ (Text:'GL_SELECTION_BUFFER_SIZE';Value:GL_SELECTION_BUFFER_SIZE),
+ (Text:'GL_TEXTURE_WIDTH';Value:GL_TEXTURE_WIDTH),
+ (Text:'GL_TEXTURE_HEIGHT';Value:GL_TEXTURE_HEIGHT),
+ (Text:'GL_TEXTURE_INTERNAL_FORMAT';Value:GL_TEXTURE_INTERNAL_FORMAT),
+ (Text:'GL_TEXTURE_BORDER_COLOR';Value:GL_TEXTURE_BORDER_COLOR),
+ (Text:'GL_TEXTURE_BORDER';Value:GL_TEXTURE_BORDER),
+ (Text:'GL_DONT_CARE';Value:GL_DONT_CARE),
+ (Text:'GL_FASTEST';Value:GL_FASTEST),
+ (Text:'GL_NICEST';Value:GL_NICEST),
+ (Text:'GL_LIGHT0';Value:GL_LIGHT0),
+ (Text:'GL_LIGHT1';Value:GL_LIGHT1),
+ (Text:'GL_LIGHT2';Value:GL_LIGHT2),
+ (Text:'GL_LIGHT3';Value:GL_LIGHT3),
+ (Text:'GL_LIGHT4';Value:GL_LIGHT4),
+ (Text:'GL_LIGHT5';Value:GL_LIGHT5),
+ (Text:'GL_LIGHT6';Value:GL_LIGHT6),
+ (Text:'GL_LIGHT7';Value:GL_LIGHT7),
+ (Text:'GL_AMBIENT';Value:GL_AMBIENT),
+ (Text:'GL_DIFFUSE';Value:GL_DIFFUSE),
+ (Text:'GL_SPECULAR';Value:GL_SPECULAR),
+ (Text:'GL_POSITION';Value:GL_POSITION),
+ (Text:'GL_SPOT_DIRECTION';Value:GL_SPOT_DIRECTION),
+ (Text:'GL_SPOT_EXPONENT';Value:GL_SPOT_EXPONENT),
+ (Text:'GL_SPOT_CUTOFF';Value:GL_SPOT_CUTOFF),
+ (Text:'GL_CONSTANT_ATTENUATION';Value:GL_CONSTANT_ATTENUATION),
+ (Text:'GL_LINEAR_ATTENUATION';Value:GL_LINEAR_ATTENUATION),
+ (Text:'GL_QUADRATIC_ATTENUATION';Value:GL_QUADRATIC_ATTENUATION),
+ (Text:'GL_COMPILE';Value:GL_COMPILE),
+ (Text:'GL_COMPILE_AND_EXECUTE';Value:GL_COMPILE_AND_EXECUTE),
+ (Text:'GL_CLEAR';Value:GL_CLEAR),
+ (Text:'GL_AND';Value:GL_AND),
+ (Text:'GL_AND_REVERSE';Value:GL_AND_REVERSE),
+ (Text:'GL_COPY';Value:GL_COPY),
+ (Text:'GL_AND_INVERTED';Value:GL_AND_INVERTED),
+ (Text:'GL_NOOP';Value:GL_NOOP),
+ (Text:'GL_XOR';Value:GL_XOR),
+ (Text:'GL_OR';Value:GL_OR),
+ (Text:'GL_NOR';Value:GL_NOR),
+ (Text:'GL_EQUIV';Value:GL_EQUIV),
+ (Text:'GL_INVERT';Value:GL_INVERT),
+ (Text:'GL_OR_REVERSE';Value:GL_OR_REVERSE),
+ (Text:'GL_COPY_INVERTED';Value:GL_COPY_INVERTED),
+ (Text:'GL_OR_INVERTED';Value:GL_OR_INVERTED),
+ (Text:'GL_NAND';Value:GL_NAND),
+ (Text:'GL_SET';Value:GL_SET),
+ (Text:'GL_EMISSION';Value:GL_EMISSION),
+ (Text:'GL_SHININESS';Value:GL_SHININESS),
+ (Text:'GL_AMBIENT_AND_DIFFUSE';Value:GL_AMBIENT_AND_DIFFUSE),
+ (Text:'GL_COLOR_INDEXES';Value:GL_COLOR_INDEXES),
+ (Text:'GL_MODELVIEW';Value:GL_MODELVIEW),
+ (Text:'GL_PROJECTION';Value:GL_PROJECTION),
+ (Text:'GL_TEXTURE';Value:GL_TEXTURE),
+ (Text:'GL_COLOR';Value:GL_COLOR),
+ (Text:'GL_DEPTH';Value:GL_DEPTH),
+ (Text:'GL_STENCIL';Value:GL_STENCIL),
+ (Text:'GL_COLOR_INDEX';Value:GL_COLOR_INDEX),
+ (Text:'GL_STENCIL_INDEX';Value:GL_STENCIL_INDEX),
+ (Text:'GL_DEPTH_COMPONENT';Value:GL_DEPTH_COMPONENT),
+ (Text:'GL_RED';Value:GL_RED),
+ (Text:'GL_GREEN';Value:GL_GREEN),
+ (Text:'GL_BLUE';Value:GL_BLUE),
+ (Text:'GL_ALPHA';Value:GL_ALPHA),
+ (Text:'GL_RGB';Value:GL_RGB),
+ (Text:'GL_RGBA';Value:GL_RGBA),
+ (Text:'GL_LUMINANCE';Value:GL_LUMINANCE),
+ (Text:'GL_LUMINANCE_ALPHA';Value:GL_LUMINANCE_ALPHA),
+ (Text:'GL_BITMAP';Value:GL_BITMAP),
+ (Text:'GL_POINT';Value:GL_POINT),
+ (Text:'GL_LINE';Value:GL_LINE),
+ (Text:'GL_FILL';Value:GL_FILL),
+ (Text:'GL_RENDER';Value:GL_RENDER),
+ (Text:'GL_FEEDBACK';Value:GL_FEEDBACK),
+ (Text:'GL_SELECT';Value:GL_SELECT),
+ (Text:'GL_FLAT';Value:GL_FLAT),
+ (Text:'GL_SMOOTH';Value:GL_SMOOTH),
+ (Text:'GL_KEEP';Value:GL_KEEP),
+ (Text:'GL_REPLACE';Value:GL_REPLACE),
+ (Text:'GL_INCR';Value:GL_INCR),
+ (Text:'GL_DECR';Value:GL_DECR),
+ (Text:'GL_VENDOR';Value:GL_VENDOR),
+ (Text:'GL_RENDERER';Value:GL_RENDERER),
+ (Text:'GL_VERSION';Value:GL_VERSION),
+ (Text:'GL_EXTENSIONS';Value:GL_EXTENSIONS),
+ (Text:'GL_S';Value:GL_S),
+ (Text:'GL_T';Value:GL_T),
+ (Text:'GL_R';Value:GL_R),
+ (Text:'GL_Q';Value:GL_Q),
+ (Text:'GL_MODULATE';Value:GL_MODULATE),
+ (Text:'GL_DECAL';Value:GL_DECAL),
+ (Text:'GL_TEXTURE_ENV_MODE';Value:GL_TEXTURE_ENV_MODE),
+ (Text:'GL_TEXTURE_ENV_COLOR';Value:GL_TEXTURE_ENV_COLOR),
+ (Text:'GL_TEXTURE_ENV';Value:GL_TEXTURE_ENV),
+ (Text:'GL_EYE_LINEAR';Value:GL_EYE_LINEAR),
+ (Text:'GL_OBJECT_LINEAR';Value:GL_OBJECT_LINEAR),
+ (Text:'GL_SPHERE_MAP';Value:GL_SPHERE_MAP),
+ (Text:'GL_TEXTURE_GEN_MODE';Value:GL_TEXTURE_GEN_MODE),
+ (Text:'GL_OBJECT_PLANE';Value:GL_OBJECT_PLANE),
+ (Text:'GL_EYE_PLANE';Value:GL_EYE_PLANE),
+ (Text:'GL_NEAREST';Value:GL_NEAREST),
+ (Text:'GL_LINEAR';Value:GL_LINEAR),
+ (Text:'GL_NEAREST_MIPMAP_NEAREST';Value:GL_NEAREST_MIPMAP_NEAREST),
+ (Text:'GL_LINEAR_MIPMAP_NEAREST';Value:GL_LINEAR_MIPMAP_NEAREST),
+ (Text:'GL_NEAREST_MIPMAP_LINEAR';Value:GL_NEAREST_MIPMAP_LINEAR),
+ (Text:'GL_LINEAR_MIPMAP_LINEAR';Value:GL_LINEAR_MIPMAP_LINEAR),
+ (Text:'GL_TEXTURE_MAG_FILTER';Value:GL_TEXTURE_MAG_FILTER),
+ (Text:'GL_TEXTURE_MIN_FILTER';Value:GL_TEXTURE_MIN_FILTER),
+ (Text:'GL_TEXTURE_WRAP_S';Value:GL_TEXTURE_WRAP_S),
+ (Text:'GL_TEXTURE_WRAP_T';Value:GL_TEXTURE_WRAP_T),
+ (Text:'GL_CLAMP';Value:GL_CLAMP),
+ (Text:'GL_REPEAT';Value:GL_REPEAT),
+ (Text:'GL_CLIENT_PIXEL_STORE_BIT';Value:GL_CLIENT_PIXEL_STORE_BIT),
+ (Text:'GL_CLIENT_VERTEX_ARRAY_BIT';Value:GL_CLIENT_VERTEX_ARRAY_BIT),
+ (Text:'GL_CLIENT_ALL_ATTRIB_BITS';Value:GL_CLIENT_ALL_ATTRIB_BITS),
+ (Text:'GL_POLYGON_OFFSET_FACTOR';Value:GL_POLYGON_OFFSET_FACTOR),
+ (Text:'GL_POLYGON_OFFSET_UNITS';Value:GL_POLYGON_OFFSET_UNITS),
+ (Text:'GL_POLYGON_OFFSET_POINT';Value:GL_POLYGON_OFFSET_POINT),
+ (Text:'GL_POLYGON_OFFSET_LINE';Value:GL_POLYGON_OFFSET_LINE),
+ (Text:'GL_POLYGON_OFFSET_FILL';Value:GL_POLYGON_OFFSET_FILL),
+ (Text:'GL_ALPHA4';Value:GL_ALPHA4),
+ (Text:'GL_ALPHA8';Value:GL_ALPHA8),
+ (Text:'GL_ALPHA12';Value:GL_ALPHA12),
+ (Text:'GL_ALPHA16';Value:GL_ALPHA16),
+ (Text:'GL_LUMINANCE4';Value:GL_LUMINANCE4),
+ (Text:'GL_LUMINANCE8';Value:GL_LUMINANCE8),
+ (Text:'GL_LUMINANCE12';Value:GL_LUMINANCE12),
+ (Text:'GL_LUMINANCE16';Value:GL_LUMINANCE16),
+ (Text:'GL_LUMINANCE4_ALPHA4';Value:GL_LUMINANCE4_ALPHA4),
+ (Text:'GL_LUMINANCE6_ALPHA2';Value:GL_LUMINANCE6_ALPHA2),
+ (Text:'GL_LUMINANCE8_ALPHA8';Value:GL_LUMINANCE8_ALPHA8),
+ (Text:'GL_LUMINANCE12_ALPHA4';Value:GL_LUMINANCE12_ALPHA4),
+ (Text:'GL_LUMINANCE12_ALPHA12';Value:GL_LUMINANCE12_ALPHA12),
+ (Text:'GL_LUMINANCE16_ALPHA16';Value:GL_LUMINANCE16_ALPHA16),
+ (Text:'GL_INTENSITY';Value:GL_INTENSITY),
+ (Text:'GL_INTENSITY4';Value:GL_INTENSITY4),
+ (Text:'GL_INTENSITY8';Value:GL_INTENSITY8),
+ (Text:'GL_INTENSITY12';Value:GL_INTENSITY12),
+ (Text:'GL_INTENSITY16';Value:GL_INTENSITY16),
+ (Text:'GL_R3_G3_B2';Value:GL_R3_G3_B2),
+ (Text:'GL_RGB4';Value:GL_RGB4),
+ (Text:'GL_RGB5';Value:GL_RGB5),
+ (Text:'GL_RGB8';Value:GL_RGB8),
+ (Text:'GL_RGB10';Value:GL_RGB10),
+ (Text:'GL_RGB12';Value:GL_RGB12),
+ (Text:'GL_RGB16';Value:GL_RGB16),
+ (Text:'GL_RGBA2';Value:GL_RGBA2),
+ (Text:'GL_RGBA4';Value:GL_RGBA4),
+ (Text:'GL_RGB5_A1';Value:GL_RGB5_A1),
+ (Text:'GL_RGBA8';Value:GL_RGBA8),
+ (Text:'GL_RGB10_A2';Value:GL_RGB10_A2),
+ (Text:'GL_RGBA12';Value:GL_RGBA12),
+ (Text:'GL_RGBA16';Value:GL_RGBA16),
+ (Text:'GL_TEXTURE_RED_SIZE';Value:GL_TEXTURE_RED_SIZE),
+ (Text:'GL_TEXTURE_GREEN_SIZE';Value:GL_TEXTURE_GREEN_SIZE),
+ (Text:'GL_TEXTURE_BLUE_SIZE';Value:GL_TEXTURE_BLUE_SIZE),
+ (Text:'GL_TEXTURE_ALPHA_SIZE';Value:GL_TEXTURE_ALPHA_SIZE),
+ (Text:'GL_TEXTURE_LUMINANCE_SIZE';Value:GL_TEXTURE_LUMINANCE_SIZE),
+ (Text:'GL_TEXTURE_INTENSITY_SIZE';Value:GL_TEXTURE_INTENSITY_SIZE),
+ (Text:'GL_PROXY_TEXTURE_1D';Value:GL_PROXY_TEXTURE_1D),
+ (Text:'GL_PROXY_TEXTURE_2D';Value:GL_PROXY_TEXTURE_2D),
+ (Text:'GL_TEXTURE_PRIORITY';Value:GL_TEXTURE_PRIORITY),
+ (Text:'GL_TEXTURE_RESIDENT';Value:GL_TEXTURE_RESIDENT),
+ (Text:'GL_TEXTURE_BINDING_1D';Value:GL_TEXTURE_BINDING_1D),
+ (Text:'GL_TEXTURE_BINDING_2D';Value:GL_TEXTURE_BINDING_2D),
+ (Text:'GL_VERTEX_ARRAY';Value:GL_VERTEX_ARRAY),
+ (Text:'GL_NORMAL_ARRAY';Value:GL_NORMAL_ARRAY),
+ (Text:'GL_COLOR_ARRAY';Value:GL_COLOR_ARRAY),
+ (Text:'GL_INDEX_ARRAY';Value:GL_INDEX_ARRAY),
+ (Text:'GL_TEXTURE_COORD_ARRAY';Value:GL_TEXTURE_COORD_ARRAY),
+ (Text:'GL_EDGE_FLAG_ARRAY';Value:GL_EDGE_FLAG_ARRAY),
+ (Text:'GL_VERTEX_ARRAY_SIZE';Value:GL_VERTEX_ARRAY_SIZE),
+ (Text:'GL_VERTEX_ARRAY_TYPE';Value:GL_VERTEX_ARRAY_TYPE),
+ (Text:'GL_VERTEX_ARRAY_STRIDE';Value:GL_VERTEX_ARRAY_STRIDE),
+ (Text:'GL_NORMAL_ARRAY_TYPE';Value:GL_NORMAL_ARRAY_TYPE),
+ (Text:'GL_NORMAL_ARRAY_STRIDE';Value:GL_NORMAL_ARRAY_STRIDE),
+ (Text:'GL_COLOR_ARRAY_SIZE';Value:GL_COLOR_ARRAY_SIZE),
+ (Text:'GL_COLOR_ARRAY_TYPE';Value:GL_COLOR_ARRAY_TYPE),
+ (Text:'GL_COLOR_ARRAY_STRIDE';Value:GL_COLOR_ARRAY_STRIDE),
+ (Text:'GL_INDEX_ARRAY_TYPE';Value:GL_INDEX_ARRAY_TYPE),
+ (Text:'GL_INDEX_ARRAY_STRIDE';Value:GL_INDEX_ARRAY_STRIDE),
+ (Text:'GL_TEXTURE_COORD_ARRAY_SIZE';Value:GL_TEXTURE_COORD_ARRAY_SIZE),
+ (Text:'GL_TEXTURE_COORD_ARRAY_TYPE';Value:GL_TEXTURE_COORD_ARRAY_TYPE),
+ (Text:'GL_TEXTURE_COORD_ARRAY_STRIDE';Value:GL_TEXTURE_COORD_ARRAY_STRIDE),
+ (Text:'GL_EDGE_FLAG_ARRAY_STRIDE';Value:GL_EDGE_FLAG_ARRAY_STRIDE),
+ (Text:'GL_VERTEX_ARRAY_POINTER';Value:GL_VERTEX_ARRAY_POINTER),
+ (Text:'GL_NORMAL_ARRAY_POINTER';Value:GL_NORMAL_ARRAY_POINTER),
+ (Text:'GL_COLOR_ARRAY_POINTER';Value:GL_COLOR_ARRAY_POINTER),
+ (Text:'GL_INDEX_ARRAY_POINTER';Value:GL_INDEX_ARRAY_POINTER),
+ (Text:'GL_TEXTURE_COORD_ARRAY_POINTER';Value:GL_TEXTURE_COORD_ARRAY_POINTER),
+ (Text:'GL_EDGE_FLAG_ARRAY_POINTER';Value:GL_EDGE_FLAG_ARRAY_POINTER),
+ (Text:'GL_V2F';Value:GL_V2F),
+ (Text:'GL_V3F';Value:GL_V3F),
+ (Text:'GL_C4UB_V2F';Value:GL_C4UB_V2F),
+ (Text:'GL_C4UB_V3F';Value:GL_C4UB_V3F),
+ (Text:'GL_C3F_V3F';Value:GL_C3F_V3F),
+ (Text:'GL_N3F_V3F';Value:GL_N3F_V3F),
+ (Text:'GL_C4F_N3F_V3F';Value:GL_C4F_N3F_V3F),
+ (Text:'GL_T2F_V3F';Value:GL_T2F_V3F),
+ (Text:'GL_T4F_V4F';Value:GL_T4F_V4F),
+ (Text:'GL_T2F_C4UB_V3F';Value:GL_T2F_C4UB_V3F),
+ (Text:'GL_T2F_C3F_V3F';Value:GL_T2F_C3F_V3F),
+ (Text:'GL_T2F_N3F_V3F';Value:GL_T2F_N3F_V3F),
+ (Text:'GL_T2F_C4F_N3F_V3F';Value:GL_T2F_C4F_N3F_V3F),
+ (Text:'GL_T4F_C4F_N3F_V4F';Value:GL_T4F_C4F_N3F_V4F),
+ (Text:'GL_EXT_vertex_array';Value:GL_EXT_vertex_array),
+ (Text:'GL_WIN_swap_hint';Value:GL_WIN_swap_hint),
+ (Text:'GL_EXT_bgra';Value:GL_EXT_bgra),
+ (Text:'GL_EXT_paletted_texture';Value:GL_EXT_paletted_texture),
+ (Text:'GL_VERTEX_ARRAY_EXT';Value:GL_VERTEX_ARRAY_EXT),
+ (Text:'GL_NORMAL_ARRAY_EXT';Value:GL_NORMAL_ARRAY_EXT),
+ (Text:'GL_COLOR_ARRAY_EXT';Value:GL_COLOR_ARRAY_EXT),
+ (Text:'GL_INDEX_ARRAY_EXT';Value:GL_INDEX_ARRAY_EXT),
+ (Text:'GL_TEXTURE_COORD_ARRAY_EXT';Value:GL_TEXTURE_COORD_ARRAY_EXT),
+ (Text:'GL_EDGE_FLAG_ARRAY_EXT';Value:GL_EDGE_FLAG_ARRAY_EXT),
+ (Text:'GL_VERTEX_ARRAY_SIZE_EXT';Value:GL_VERTEX_ARRAY_SIZE_EXT),
+ (Text:'GL_VERTEX_ARRAY_TYPE_EXT';Value:GL_VERTEX_ARRAY_TYPE_EXT),
+ (Text:'GL_VERTEX_ARRAY_STRIDE_EXT';Value:GL_VERTEX_ARRAY_STRIDE_EXT),
+ (Text:'GL_VERTEX_ARRAY_COUNT_EXT';Value:GL_VERTEX_ARRAY_COUNT_EXT),
+ (Text:'GL_NORMAL_ARRAY_TYPE_EXT';Value:GL_NORMAL_ARRAY_TYPE_EXT),
+ (Text:'GL_NORMAL_ARRAY_STRIDE_EXT';Value:GL_NORMAL_ARRAY_STRIDE_EXT),
+ (Text:'GL_NORMAL_ARRAY_COUNT_EXT';Value:GL_NORMAL_ARRAY_COUNT_EXT),
+ (Text:'GL_COLOR_ARRAY_SIZE_EXT';Value:GL_COLOR_ARRAY_SIZE_EXT),
+ (Text:'GL_COLOR_ARRAY_TYPE_EXT';Value:GL_COLOR_ARRAY_TYPE_EXT),
+ (Text:'GL_COLOR_ARRAY_STRIDE_EXT';Value:GL_COLOR_ARRAY_STRIDE_EXT),
+ (Text:'GL_COLOR_ARRAY_COUNT_EXT';Value:GL_COLOR_ARRAY_COUNT_EXT),
+ (Text:'GL_INDEX_ARRAY_TYPE_EXT';Value:GL_INDEX_ARRAY_TYPE_EXT),
+ (Text:'GL_INDEX_ARRAY_STRIDE_EXT';Value:GL_INDEX_ARRAY_STRIDE_EXT),
+ (Text:'GL_INDEX_ARRAY_COUNT_EXT';Value:GL_INDEX_ARRAY_COUNT_EXT),
+ (Text:'GL_TEXTURE_COORD_ARRAY_SIZE_EXT';Value:GL_TEXTURE_COORD_ARRAY_SIZE_EXT),
+ (Text:'GL_TEXTURE_COORD_ARRAY_TYPE_EXT';Value:GL_TEXTURE_COORD_ARRAY_TYPE_EXT),
+ (Text:'GL_TEXTURE_COORD_ARRAY_STRIDE_EXT';Value:GL_TEXTURE_COORD_ARRAY_STRIDE_EXT),
+ (Text:'GL_TEXTURE_COORD_ARRAY_COUNT_EXT';Value:GL_TEXTURE_COORD_ARRAY_COUNT_EXT),
+ (Text:'GL_EDGE_FLAG_ARRAY_STRIDE_EXT';Value:GL_EDGE_FLAG_ARRAY_STRIDE_EXT),
+ (Text:'GL_EDGE_FLAG_ARRAY_COUNT_EXT';Value:GL_EDGE_FLAG_ARRAY_COUNT_EXT),
+ (Text:'GL_VERTEX_ARRAY_POINTER_EXT';Value:GL_VERTEX_ARRAY_POINTER_EXT),
+ (Text:'GL_NORMAL_ARRAY_POINTER_EXT';Value:GL_NORMAL_ARRAY_POINTER_EXT),
+ (Text:'GL_COLOR_ARRAY_POINTER_EXT';Value:GL_COLOR_ARRAY_POINTER_EXT),
+ (Text:'GL_INDEX_ARRAY_POINTER_EXT';Value:GL_INDEX_ARRAY_POINTER_EXT),
+ (Text:'GL_TEXTURE_COORD_ARRAY_POINTER_EXT';Value:GL_TEXTURE_COORD_ARRAY_POINTER_EXT),
+ (Text:'GL_EDGE_FLAG_ARRAY_POINTER_EXT';Value:GL_EDGE_FLAG_ARRAY_POINTER_EXT),
+ (Text:'GL_DOUBLE_EXT';Value:GL_DOUBLE_EXT),
+ (Text:'GL_BGR_EXT';Value:GL_BGR_EXT),
+ (Text:'GL_BGRA_EXT';Value:GL_BGRA_EXT),
+ (Text:'GL_COLOR_TABLE_FORMAT_EXT';Value:GL_COLOR_TABLE_FORMAT_EXT),
+ (Text:'GL_COLOR_TABLE_WIDTH_EXT';Value:GL_COLOR_TABLE_WIDTH_EXT),
+ (Text:'GL_COLOR_TABLE_RED_SIZE_EXT';Value:GL_COLOR_TABLE_RED_SIZE_EXT),
+ (Text:'GL_COLOR_TABLE_GREEN_SIZE_EXT';Value:GL_COLOR_TABLE_GREEN_SIZE_EXT),
+ (Text:'GL_COLOR_TABLE_BLUE_SIZE_EXT';Value:GL_COLOR_TABLE_BLUE_SIZE_EXT),
+ (Text:'GL_COLOR_TABLE_ALPHA_SIZE_EXT';Value:GL_COLOR_TABLE_ALPHA_SIZE_EXT),
+ (Text:'GL_COLOR_TABLE_LUMINANCE_SIZE_EXT';Value:GL_COLOR_TABLE_LUMINANCE_SIZE_EXT),
+ (Text:'GL_COLOR_TABLE_INTENSITY_SIZE_EXT';Value:GL_COLOR_TABLE_INTENSITY_SIZE_EXT),
+ (Text:'GL_COLOR_INDEX1_EXT';Value:GL_COLOR_INDEX1_EXT),
+ (Text:'GL_COLOR_INDEX2_EXT';Value:GL_COLOR_INDEX2_EXT),
+ (Text:'GL_COLOR_INDEX4_EXT';Value:GL_COLOR_INDEX4_EXT),
+ (Text:'GL_COLOR_INDEX8_EXT';Value:GL_COLOR_INDEX8_EXT),
+ (Text:'GL_COLOR_INDEX12_EXT';Value:GL_COLOR_INDEX12_EXT),
+ (Text:'GL_COLOR_INDEX16_EXT';Value:GL_COLOR_INDEX16_EXT)
+ );
+
+function ULuaGl_StringToEnum(Str: String): GLenum;
+ function GetEnum(const Str: String): GLenum;
+ var
+ i : Integer;
+ begin
+ for i := 0 to high(ULuaGl_Enum) do
+ begin
+ if 0 = AnsiCompareText(Str, ULuaGl_Enum[i].Text) then
+ begin
+ Result := ULuaGl_Enum[i].Value;
+ Exit;
+ end;
+ end;
+ Result := ULuaGl_EnumERROR;
+ end;
+ var
+ i : Integer;
+ j : Integer;
+ temp : GLenum;
+begin
+ Result := 0;
+ j := 1;
+ for i := 1 to Length(Str) do
+ begin
+ if Str[i] = ',' then
+ begin
+ temp := GetEnum(Copy(Str,j,i-j));
+ if temp <> ULuaGl_EnumERROR then
+ Result := Result or temp;
+ j := i + 1;
+ end;
+ end;
+
+ temp := GetEnum(Copy(Str,j,MaxInt));
+ if (temp = ULuaGl_EnumERROR) then
+ begin
+ if Result = 0 then
+ Result := ULuaGl_EnumERROR;
+ exit;
+ end;
+ Result := Result or temp;
+end;
+end.
+
diff --git a/src/lua/ULuaLog.pas b/src/lua/ULuaLog.pas
new file mode 100644
index 00000000..95efaa19
--- /dev/null
+++ b/src/lua/ULuaLog.pas
@@ -0,0 +1,167 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaLog;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ SysUtils,
+ ULog,
+ ULua;
+
+function luaopen_Log (L: Plua_State): Integer; cdecl;
+
+function ULuaLog_LogError(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogMsg(L: Plua_State): Integer; cdecl;
+function ULuaLog_BenchmarkStart(L: Plua_State): Integer; cdecl;
+function ULuaLog_BenchmarkEnd(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogBenchmark(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogDebug(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogInfo(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogStatus(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogWarn(L: Plua_State): Integer; cdecl;
+function ULuaLog_LogCritical(L: Plua_State): Integer; cdecl;
+function ULuaLog_CriticalError(L: Plua_State): Integer; cdecl;
+function ULuaLog_GetLogLevel(L: Plua_State): Integer; cdecl;
+function ULuaLog_SetLogLevel(L: Plua_State): Integer; cdecl;
+
+
+const
+ ULuaLog_Lib_f: array [0..13] of lual_reg = (
+ (name:'LogError';func:ULuaLog_LogError),
+ (name:'LogMsg';func:ULuaLog_LogMsg),
+ (name:'BenchmarkStart';func:ULuaLog_BenchmarkStart),
+ (name:'BenchmarkEnd';func:ULuaLog_BenchmarkEnd),
+ (name:'LogBenchmark';func:ULuaLog_LogBenchmark),
+ (name:'LogDebug';func:ULuaLog_LogDebug),
+ (name:'LogInfo';func:ULuaLog_LogInfo),
+ (name:'LogStatus';func:ULuaLog_LogStatus),
+ (name:'LogWarn';func:ULuaLog_LogWarn),
+ (name:'LogCritical';func:ULuaLog_LogCritical),
+ (name:'CriticalError';func:ULuaLog_CriticalError),
+ (name:'SetLogLevel';func:ULuaLog_GetLogLevel),
+ (name:'GetLogLevel';func:ULuaLog_SetLogLevel),
+ (name:nil;func:nil)
+ );
+
+implementation
+
+function ULuaLog_LogError(L: Plua_State): Integer; cdecl;
+begin
+ if (lua_gettop(L) > 1) then
+ Log.LogError(luaL_checkstring(L,-2),luaL_checkstring(L,-1))
+ else
+ Log.LogError(luaL_checkstring(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_LogMsg(L: Plua_State): Integer; cdecl;
+begin
+ if (lua_gettop(L) > 2) then
+ Log.LogMsg(luaL_checkstring(L,-3),luaL_checkstring(L,-1),luaL_checkinteger(L,-2))
+ else
+ Log.LogMsg(luaL_checkstring(L,-2),luaL_checkinteger(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_BenchmarkStart(L: Plua_State): Integer; cdecl;
+begin
+ Log.BenchmarkStart(luaL_checkinteger(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_BenchmarkEnd(L: Plua_State): Integer; cdecl;
+begin
+ Log.BenchmarkEnd(luaL_checkinteger(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_LogBenchmark(L: Plua_State): Integer; cdecl;
+begin
+ Log.LogBenchmark(luaL_checkstring(L,-2),luaL_checkinteger(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_LogDebug(L: Plua_State): Integer; cdecl;
+begin
+ Log.LogDebug(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_LogInfo(L: Plua_State): Integer; cdecl;
+begin
+ Log.LogInfo(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_LogStatus(L: Plua_State): Integer; cdecl;
+begin
+ Log.LogStatus(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_LogWarn(L: Plua_State): Integer; cdecl;
+begin
+ Log.LogWarn(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_LogCritical(L: Plua_State): Integer; cdecl;
+begin
+ Log.LogCritical(luaL_checkstring(L,-2),luaL_checkstring(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_CriticalError(L: Plua_State): Integer; cdecl;
+begin
+ Log.CriticalError(luaL_checkstring(L,-1));
+ result:=0; // number of results
+end;
+
+function ULuaLog_GetLogLevel(L: Plua_State): Integer; cdecl;
+begin
+ lua_pushinteger(L,Log.GetLogLevel());
+ result:=1; // number of results
+end;
+
+function ULuaLog_SetLogLevel(L: Plua_State): Integer; cdecl;
+begin
+ Log.SetLogLevel(luaL_checkinteger(L,-1));
+ result:=0; // number of results
+end;
+
+function luaopen_Log (L: Plua_State): Integer; cdecl;
+begin
+ luaL_register(L,'Log',@ULuaLog_Lib_f[0]);
+ result:=1;
+end;
+end.
diff --git a/src/lua/ULuaParty.pas b/src/lua/ULuaParty.pas
new file mode 100644
index 00000000..883c3aec
--- /dev/null
+++ b/src/lua/ULuaParty.pas
@@ -0,0 +1,389 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaParty;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses ULua;
+
+{ lua c functions from Party table. Enables creating of party modes w/ lua scripts }
+
+{ Party.Register - register party mode at party manager
+ arguments: info: table
+ Name: String; //< Name used as identifier (language strings, etc.). Has to be set.
+ CanNonParty: Boolean //< mode is playable when not in party mode. defaulted to false if not set
+ CanParty: Boolean //< mode is playable in party mode. defaulted to false if not set
+ PlayerCount: Table //< playable with one, two, three etc. players per team. defaulted to no restrictions if not set. (use table constructor e.g. {1, 2, 3) means playable w/ 1, 2 or three players)
+ TeamCount: Table //< playable with one, two, three etc. different teams. defaulted to no restrictions if not set. (use table constructor e.g. {1, 2, 3) means playable w/ 1, 2 or three players)
+
+ BeforeSongSelect: String //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+ AfterSongSelect: String //< name of global that will be called after song is selected (if nil, not callable or returns true, default action will be executed)
+
+ BeforeSing: String //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+ OnSing: String //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+ AfterSing: String //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)}
+function ULuaParty_Register(L: Plua_State): Integer; cdecl;
+
+{ Party.GameFinished - returns true if no party game is running or all rounds
+ of current game were played }
+function ULuaParty_GameFinished(L: Plua_State): Integer; cdecl;
+
+(* Party.SetRoundRanking - sets ranking of current party round,
+ arguments: Ranking: table
+ ranking of team i is the value (integer from 1 to number of teams) of the
+ table with index [i: number].
+ you may call this function in the following way:
+ Party.SetRoundRanking({3, 1, 2});
+ this means: team 1 is ranked third, team 2 is ranked first and team 3 is
+ ranked second.
+ if no party game is started or party game is finished
+ it will raise an error *)
+function ULuaParty_SetRoundRanking(L: Plua_State): Integer; cdecl;
+
+{ Party.GetTeams - returns a table with all information and structure as
+ in the TPartyGame.Teams array }
+function ULuaParty_GetTeams(L: Plua_State): Integer; cdecl;
+
+{ Party.SetTeams - changes all fields from TPartyGame.Teams that have been
+ set in the table given as first argument}
+function ULuaParty_SetTeams(L: Plua_State): Integer; cdecl;
+
+const
+ ULuaParty_Lib_f: array [0..4] of lual_reg = (
+ (name:'Register'; func:ULuaParty_Register),
+ (name:'GameFinished'; func:ULuaParty_GameFinished),
+ (name:'SetRoundRanking'; func:ULuaParty_SetRoundRanking),
+ (name:'GetTeams'; func:ULuaParty_GetTeams),
+ (name:'SetTeams'; func:ULuaParty_SetTeams)
+ );
+
+implementation
+uses ULuaCore, ULuaUtils, UParty, SysUtils;
+
+
+{ Party.Register - register party mode at party manager
+ arguments: info: table
+ Name: String; //< Name used as identifier (language strings, etc.). Has to be set.
+ CanNonParty: Boolean //< mode is playable when not in party mode. defaulted to false if not set
+ CanParty: Boolean //< mode is playable in party mode. defaulted to false if not set
+ PlayerCount: Table //< playable with one, two, three etc. players per team. defaulted to no restrictions if not set. (use table constructor e.g. {1, 2, 3) means playable w/ 1, 2 or three players)
+ TeamCount: Table //< playable with one, two, three etc. different teams. defaulted to no restrictions if not set. (use table constructor e.g. {1, 2, 3) means playable w/ 1, 2 or three players)
+
+ BeforeSongSelect: String //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+ AfterSongSelect: String //< name of global that will be called after song is selected (if nil, not callable or returns true, default action will be executed)
+
+ BeforeSing: String //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+ OnSing: String //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)
+ AfterSing: String //< name of global that will be called before song select screen is shown (if nil, not callable or returns true, default action will be executed)}
+function ULuaParty_Register(L: Plua_State): Integer; cdecl;
+ var
+ Info: TParty_ModeInfo;
+ Key: String;
+ P: TLuaPlugin;
+begin
+ Result := 0;
+
+ // check for table on stack
+ luaL_checkType(L, 1, LUA_TTABLE);
+
+ // get parent id
+ P := Lua_GetOwner(L);
+
+
+ // set mode info to default
+ Party.DefaultModeInfo(Info);
+
+
+ // set parent in info rec and pop it from stack
+ Info.Parent := P.Id;
+
+ // go through table elements
+ lua_pushNil(L);
+ while (lua_Next(L, 1) <> 0) do
+ begin
+ Key := lowercase(lua_ToString(L, -2));
+
+ if (Key = 'name') and lua_isString(L, -1) then
+ Info.Name := lua_toString(L, -1)
+ else if (Key = 'cannonparty') and lua_isBoolean(L, -1) then
+ Info.CanNonParty := lua_toBoolean(L, -1)
+ else if (Key = 'canparty') and lua_isBoolean(L, -1) then
+ Info.CanParty := lua_toBoolean(L, -1)
+ else if (Key = 'playercount') and lua_isTable(L, -1) then
+ Info.PlayerCount := lua_toBinInt(L, -1)
+ else if (Key = 'teamcount') and lua_isTable(L, -1) then
+ Info.TeamCount := lua_toBinInt(L, -1)
+ else if (Key = 'beforesongselect') and lua_isString(L, -1) then
+ Info.Functions.BeforeSongSelect := lua_toString(L, -1)
+ else if (Key = 'aftersongselect') and lua_isString(L, -1) then
+ Info.Functions.AfterSongSelect := lua_toString(L, -1)
+ else if (Key = 'beforesing') and lua_isString(L, -1) then
+ Info.Functions.BeforeSing := lua_toString(L, -1)
+ else if (Key = 'onsing') and lua_isString(L, -1) then
+ Info.Functions.OnSing := lua_toString(L, -1)
+ else if (Key = 'aftersing') and lua_isString(L, -1) then
+ Info.Functions.AfterSing := lua_toString(L, -1);
+
+ // pop value from stack so key is on top
+ lua_pop(L, 1);
+ end;
+
+ // clear stack from table
+ lua_pop(L, lua_gettop(L));
+
+ if not Party.RegisterMode(Info) then
+ luaL_error(L, PChar('can''t register party mode at party manager in Party.Register. Is Info.Name defined or is there another mode with this name?'));
+end;
+
+{ Party.GameFinished - returns true if no party game is running or all rounds
+ of current game were played }
+function ULuaParty_GameFinished(L: Plua_State): Integer; cdecl;
+begin
+ // clear stack
+ lua_pop(L, lua_gettop(L));
+
+ // push result
+ lua_pushBoolean(L, Party.GameFinished);
+
+ //we return one value
+ Result := 1;
+end;
+
+{ Party.SetRoundRanking - sets ranking of current party round,
+ if no party game is started or party game is finished
+ it will raise an error }
+function ULuaParty_SetRoundRanking(L: Plua_State): Integer; cdecl;
+var
+ R: AParty_TeamRanking;
+ I: Integer;
+ Rank: Integer;
+begin
+ Result := 0;
+
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ lua_checkstack(L, 1);
+
+ SetLength(R, Length(Party.Teams));
+
+ for I := 0 to High(R) do
+ begin
+ lua_pushInteger(L, I);
+ lua_gettable(L, 1);
+
+ R[I].Rank := Length(R);
+ if (lua_isnumber(L, -1)) then
+ begin
+ Rank := lua_toInteger(L, -1);
+ if (Rank >= 1) and (Rank <= Length(R)) then
+ R[I].Rank := Rank;
+ end;
+
+ lua_pop(L, 1);
+ end;
+
+ // pop table
+ lua_pop(L, 1);
+
+ if (not Party.SetRanking(R)) then
+ luaL_error(L, PChar('cann''t set party round ranking. Is party started and not finished yet?'));
+end;
+
+{ Party.GetTeams - returns a table with all information and structure as
+ in the TPartyGame.Teams array }
+function ULuaParty_GetTeams(L: Plua_State): Integer; cdecl;
+ var
+ Team: Integer;
+ Player: Integer;
+begin
+ // clear stack
+ lua_pop(L, lua_gettop(L));
+
+ // ensure we have enough stack slots left
+ lua_checkstack(L, 7);
+
+ // create the table we want to return
+ lua_createtable(L, Length(Party.Teams), 0);
+
+ // add the teams
+ for Team := 0 to High(Party.Teams) do
+ begin
+ // push key for current teams value. lua array beggins at 1
+ lua_pushInteger(L, Team + 1);
+
+ // push table containing team info and players table
+ lua_createtable(L, 0, 5);
+
+ // team name
+ lua_pushString(L, PChar(Party.Teams[Team].Name));
+ lua_setField(L, -2, 'Name');
+
+ // team score
+ lua_pushInteger(L, Party.Teams[Team].Score);
+ lua_setField(L, -2, 'Score');
+
+ // team jokers left
+ lua_pushInteger(L, Party.Teams[Team].JokersLeft);
+ lua_setField(L, -2, 'JokersLeft');
+
+ // team nextPlayer
+ lua_pushInteger(L, Party.Teams[Team].NextPlayer);
+ lua_setField(L, -2, 'NextPlayer');
+
+ // team players table
+ lua_createtable(L, Length(Party.Teams[Team].Players), 0);
+
+ //add players
+ for Player := 0 to High(Party.Teams[Team].Players) do
+ begin
+ // push key for current players value. lua array beggins at 1
+ lua_pushInteger(L, Player + 1);
+
+ // push table containing player info
+ lua_createTable(L, 0, 2);
+
+ // player name
+ lua_PushString(L, PChar(Party.Teams[Team].Players[Player].Name));
+ lua_SetField(L, -2, 'Name');
+
+ // players times played
+ lua_PushInteger(L, Party.Teams[Team].Players[Player].TimesPlayed);
+ lua_SetField(L, -2, 'TimesPlayed');
+
+ // add value - key - pair to teams player table
+ lua_setTable(L, -3);
+ end;
+
+ lua_setField(L, -2, 'Players');
+
+ // add value - key - pair to returned table
+ lua_setTable(L, -3);
+ end;
+
+ // we return 1 value (the first table)
+ Result := 1;
+end;
+
+{ Party.SetTeams - changes all fields from TPartyGame.Teams that have been
+ set in the table given as first argument}
+function ULuaParty_SetTeams(L: Plua_State): Integer; cdecl;
+
+ procedure Do_Player(Team, Player: Integer);
+ var
+ Key: String;
+ begin
+ if (Player >= 0) and (Player <= High(Party.Teams[Team].Players)) then
+ begin
+ // go through table elements
+ lua_pushNil(L);
+ while (lua_Next(L, -2) <> 0) do
+ begin
+ Key := lowercase(lua_ToString(L, -2));
+
+ if (Key = 'name') and lua_isString(L, -1) then
+ Party.Teams[Team].Players[Player].Name := lua_toString(L, -1)
+ else if (Key = 'timesplayed') and lua_isNumber(L, -1) then
+ Party.Teams[Team].Players[Player].TimesPlayed := lua_toInteger(L, -1);
+
+ // pop value from stack so key is on top
+ lua_pop(L, 1);
+ end;
+ end;
+ end;
+
+ procedure Do_Players(Team: Integer);
+ begin
+ // go through table elements
+ lua_pushNil(L);
+ while (lua_Next(L, -2) <> 0) do
+ begin
+ // check if key is a number and value is a table
+ if (lua_isNumber(L, -2)) and (lua_isTable(L, -1)) then
+ Do_Player(Team, lua_toInteger(L, -2));
+
+ // pop value from stack so key is on top
+ lua_pop(L, 1);
+ end;
+ end;
+
+ procedure Do_Team(Team: Integer);
+ var
+ Key: String;
+ begin
+ if (Team >= 0) and (Team <= High(Party.Teams)) then
+ begin
+ // go through table elements
+ lua_pushNil(L);
+ while (lua_Next(L, -2) <> 0) do
+ begin
+ Key := lowercase(lua_ToString(L, -2));
+
+ if (Key = 'name') and lua_isString(L, -1) then
+ Party.Teams[Team].Name := lua_toString(L, -1)
+ else if (Key = 'score') and lua_isNumber(L, -1) then
+ Party.Teams[Team].Score := lua_toInteger(L, -1)
+ else if (Key = 'jokersleft') and lua_isNumber(L, -1) then
+ Party.Teams[Team].JokersLeft := lua_toInteger(L, -1)
+ else if (Key = 'currentplayer') and lua_isNumber(L, -1) then
+ Party.Teams[Team].NextPlayer := lua_toInteger(L, -1)
+ else if (Key = 'players') and lua_isTable(L, -1) then
+ Do_Players(Team);
+
+ // pop value from stack so key is on top
+ lua_pop(L, 1);
+ end;
+ end;
+ end;
+begin
+ Result := 0;
+
+ // check for table on stack
+ luaL_checkType(L, 1, LUA_TTABLE);
+
+
+ // go through table elements
+ lua_pushNil(L);
+ while (lua_Next(L, 1) <> 0) do
+ begin
+ // check if key is a number and value is a table
+ if (lua_isNumber(L, -2)) and (lua_isTable(L, -1)) then
+ Do_Team(lua_toInteger(L, -2));
+
+ // pop value from stack so key is on top
+ lua_pop(L, 1);
+ end;
+
+ // clear stack from table
+ lua_pop(L, lua_gettop(L));
+end;
+
+end. \ No newline at end of file
diff --git a/src/lua/ULuaScreenSing.pas b/src/lua/ULuaScreenSing.pas
new file mode 100644
index 00000000..7e17224c
--- /dev/null
+++ b/src/lua/ULuaScreenSing.pas
@@ -0,0 +1,489 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/branches/experimental/Lua/src/lua/ULuaTexture.pas $
+ * $Id: ULuaTexture.pas 1551 2009-01-04 14:08:33Z Hawkear $
+ *}
+
+unit ULuaScreenSing;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ ULua;
+
+{ returns a table with following structure:
+ t[1..playercount] = score of player i }
+function ULuaScreenSing_GetScores(L: Plua_State): Integer; cdecl;
+
+{ returns a table with following structure:
+ t[1..playercount] = rating of player i range: [0..1] }
+function ULuaScreenSing_GetRating(L: Plua_State): Integer; cdecl;
+
+{ returns a table with following structure:
+ t[1..playercount] = rect of players score background: table(x, y, w, h) }
+function ULuaScreenSing_GetScoreBGRect(L: Plua_State): Integer; cdecl;
+
+{ returns a table with following structure:
+ t[1..playercount] = rect of players rating bar: table(x, y, w, h) }
+function ULuaScreenSing_GetRBRect(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.GetBPM - no arguments
+ returns the beats per minutes of the current song in quarts }
+function ULuaScreenSing_GetBPM(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.BeatsToSeconds(Beats: float)
+ returns the time in seconds that the given number of beats (in quarts) last }
+function ULuaScreenSing_BeatsToSeconds(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.SecondsToBeats(Seconds: float)
+ returns the Beats in quarts that the given seconds last }
+function ULuaScreenSing_SecondsToBeats(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.GetBeat() - returns current beat of lyricstate (in quarts) }
+function ULuaScreenSing_GetBeat(L: Plua_State): Integer; cdecl;
+
+{ finishes current song, if sing screen is not shown it will raise
+ an error }
+function ULuaScreenSing_Finish(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.GetSettings - no arguments
+ returns a table filled with the data of TScreenSing.Settings }
+function ULuaScreenSing_GetSettings(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.SetSettings - arguments: Table
+ sets all attributes of TScreenSing.Settings that are
+ unequal to nil in Table }
+function ULuaScreenSing_SetSettings(L: Plua_State): Integer; cdecl;
+
+{ ScreenSing.GetSongLines - no arguments
+ returns a table filled with lines of the loaded song or
+ nil if no song is loaded (singscreen is not displayed)
+ structure of returned table:
+ array [1.."count of lines"]
+ \
+ | Start: integer - beat the line is displayed at (on top of lyrics display)
+ | Lyric: string - full lyric of the line
+ | Notes: array [1.."count notes of this line"]
+ \
+ | Start: integer - beat the note starts at
+ | Length: integer - length in beats
+ | Tone: integer - pitch that has to be sung, full range
+ | NoteType: integer - 0 for freestyle, 1 for normal, 2 for golden
+ | Text: string - text of this fragment }
+function ULuaScreenSing_GetSongLines(L: Plua_State): Integer; cdecl;
+
+const
+ ULuaScreenSing_Lib_f: array [0..11] of lual_reg = (
+ (name:'GetScores';func:ULuaScreenSing_GetScores),
+ (name:'GetRating';func:ULuaScreenSing_GetRating),
+ (name:'GetBPM';func:ULuaScreenSing_GetBPM),
+ (name:'BeatsToSeconds';func:ULuaScreenSing_BeatsToSeconds),
+ (name:'SecondsToBeats';func:ULuaScreenSing_SecondsToBeats),
+ (name:'GetBeat';func:ULuaScreenSing_GetBeat),
+ (name:'GetScoreBGRect';func:ULuaScreenSing_GetScoreBGRect),
+ (name:'GetRBRect';func:ULuaScreenSing_GetRBRect),
+ (name:'Finish';func:ULuaScreenSing_Finish),
+ (name:'GetSettings';func:ULuaScreenSing_GetSettings),
+ (name:'SetSettings';func:ULuaScreenSing_SetSettings),
+ (name:'GetSongLines';func:ULuaScreenSing_GetSongLines)
+ );
+
+implementation
+uses UScreenSing, UNote, UDisplay, UGraphic, UMusic, ULuaUtils, SysUtils;
+
+{ returns a table with following structure:
+ t[1..playercount] = score of player i }
+function ULuaScreenSing_GetScores(L: Plua_State): Integer; cdecl;
+ var
+ Top: Integer;
+ I: Integer;
+begin
+ Result := 1;
+
+ // pop arguments
+ Top := lua_getTop(L);
+ if (Top > 0) then
+ lua_pop(L, Top);
+
+ // create table
+ lua_createtable(L, Length(Player), 0);
+
+ // fill w/ values
+ for I := 0 to High(Player) do
+ begin
+ lua_pushInteger(L, I + 1);
+ lua_pushInteger(L, Player[I].ScoreTotalInt);
+
+ lua_settable(L, -3);
+ end;
+
+ // leave table on stack, it is our result
+end;
+
+{ returns a table with following structure:
+ t[1..playercount] = rating of player i range: [0..1] }
+function ULuaScreenSing_GetRating(L: Plua_State): Integer; cdecl;
+ var
+ Top: Integer;
+ I: Integer;
+begin
+ Result := 1;
+
+ // pop arguments
+ Top := lua_getTop(L);
+ if (Top > 0) then
+ lua_pop(L, Top);
+
+ // create table
+ lua_createtable(L, Length(Player), 0);
+
+ // fill w/ values
+ for I := 0 to High(ScreenSing.Scores.Players) do
+ begin
+ lua_pushInteger(L, I + 1);
+ lua_pushNumber(L, ScreenSing.Scores.Players[I].RBPos);
+
+ lua_settable(L, -3);
+ end;
+
+ // leave table on stack, it is our result
+end;
+
+{ ScreenSing.GetBPM - no arguments
+ returns the beats per minutes of the current song in quarts }
+function ULuaScreenSing_GetBPM(L: Plua_State): Integer; cdecl;
+begin
+ lua_ClearStack(L);
+ Result := 1;
+
+ if (CurrentSong = nil) or (Length(CurrentSong.BPM) = 0) or (Display.CurrentScreen <> @ScreenSing) then
+ lua_PushNumber(L, 0) // in case of error
+ else if (Length(CurrentSong.BPM) = 1) then
+ lua_PushNumber(L, CurrentSong.BPM[0].BPM)
+ else
+ begin
+ // to-do: do this for songs w/ BPM changes
+ // or drop support for BPM changes?!
+ end;
+end;
+
+{ ScreenSing.BeatsToSeconds(Beats: float)
+ returns the time in seconds that the given number of beats (in quarts) last }
+function ULuaScreenSing_BeatsToSeconds(L: Plua_State): Integer; cdecl;
+begin
+ Result := 1;
+
+ if (CurrentSong = nil) or (Length(CurrentSong.BPM) = 0) or (Display.CurrentScreen <> @ScreenSing) then
+ lua_PushNumber(L, 0) // in case of error
+ else if (Length(CurrentSong.BPM) = 1) then
+ lua_PushNumber(L, luaL_CheckNumber(L, 1) * 60 / CurrentSong.BPM[0].BPM)
+ else
+ begin
+ // to-do: do this for songs w/ BPM changes
+ // or drop support for BPM changes?!
+ end;
+end;
+
+{ ScreenSing.BeatsToSeconds(Seconds: float)
+ returns the Beats in quarts that the given seconds last }
+function ULuaScreenSing_SecondsToBeats(L: Plua_State): Integer; cdecl;
+begin
+ Result := 1;
+
+ if (CurrentSong = nil) or (Length(CurrentSong.BPM) = 0) or (Display.CurrentScreen <> @ScreenSing) then
+ lua_PushNumber(L, 0)
+ else if (Length(CurrentSong.BPM) = 1) then
+ lua_PushNumber(L, luaL_CheckNumber(L, 1) * CurrentSong.BPM[0].BPM / 60)
+ else
+ begin
+ // to-do: do this for songs w/ BPM changes
+ // or drop support for BPM changes?!
+ end;
+end;
+
+{ ScreenSing.GetBeat() - returns current beat of lyricstate (in quarts) }
+function ULuaScreenSing_GetBeat(L: Plua_State): Integer; cdecl;
+var top: Integer;
+begin
+ //remove arguments (if any)
+ top := lua_gettop(L);
+
+ if (top > 0) then
+ lua_pop(L, top);
+
+ //push result
+ lua_pushnumber(L, LyricsState.MidBeat);
+ Result := 1; //one result
+end;
+
+{ returns a table with following structure:
+ t[1..playercount] = rect of players ScoreBG: table(x, y, w, h) }
+function ULuaScreenSing_GetScoreBGRect(L: Plua_State): Integer; cdecl;
+ var
+ Top: Integer;
+ I: Integer;
+begin
+ Result := 1;
+
+ // pop arguments
+ Top := lua_getTop(L);
+ if (Top > 0) then
+ lua_pop(L, Top);
+
+ // create table
+ lua_createtable(L, Length(ScreenSing.Scores.Players), 0);
+
+ // fill w/ values
+ for I := 0 to High(ScreenSing.Scores.Players) do
+ begin
+ lua_pushInteger(L, I + 1);
+
+ if (ScreenSing.Scores.Players[I].Position = High(Byte)) then
+ // player has no position, prevent crash by pushing nil
+ lua_pushNil(L)
+ else
+ with ScreenSing.Scores.Positions[ScreenSing.Scores.Players[I].Position] do
+ lua_PushRect(L, BGX, BGY, BGW, BGH);
+
+
+ lua_settable(L, -3);
+ end;
+
+ // leave table on stack, it is our result
+end;
+
+{ returns a table with following structure:
+ t[1..playercount] = rect of players rating bar: table(x, y, w, h) }
+function ULuaScreenSing_GetRBRect(L: Plua_State): Integer; cdecl;
+ var
+ Top: Integer;
+ I: Integer;
+begin
+ Result := 1;
+
+ // pop arguments
+ Top := lua_getTop(L);
+ if (Top > 0) then
+ lua_pop(L, Top);
+
+ // create table
+ lua_createtable(L, Length(ScreenSing.Scores.Players), 0);
+
+ // fill w/ values
+ for I := 0 to High(ScreenSing.Scores.Players) do
+ begin
+ lua_pushInteger(L, I + 1);
+
+ if (ScreenSing.Scores.Players[I].Position = High(Byte)) then
+ // player has no position, prevent crash by pushing nil
+ lua_pushNil(L)
+ else
+ with ScreenSing.Scores.Positions[ScreenSing.Scores.Players[I].Position] do
+ lua_PushRect(L, RBX, RBY, RBW, RBH);
+
+
+ lua_settable(L, -3);
+ end;
+
+ // leave table on stack, it is our result
+end;
+
+{ finishes current song, if sing screen is not shown it will raise
+ an error }
+function ULuaScreenSing_Finish(L: Plua_State): Integer; cdecl;
+ var Top: Integer;
+begin
+ Result := 0;
+
+ // pop arguments
+ Top := lua_getTop(L);
+ if (Top > 0) then
+ lua_pop(L, Top);
+
+ if (Display.CurrentScreen^ = ScreenSing) then
+ begin
+ ScreenSing.EndSong;
+ end
+ else
+ LuaL_error(L, 'Usdx.ScreenSing.Finish is called, but sing screen is not shown.');
+end;
+
+{ ScreenSing.GetSettings - no arguments
+ returns a table filled with the data of TScreenSing }
+function ULuaScreenSing_GetSettings(L: Plua_State): Integer; cdecl;
+ var Top: Integer;
+begin
+ // pop arguments
+ Top := lua_getTop(L);
+ if (Top > 0) then
+ lua_pop(L, Top);
+
+ lua_createtable(L, 0, 3);
+
+ //fill table w/ info
+ lua_pushBoolean(L, ScreenSing.Settings.LyricsVisible);
+ lua_setField(L, -2, 'LyricsVisible');
+
+ lua_pushBinInt(L, ScreenSing.Settings.NotesVisible);
+ lua_setField(L, -2, 'NotesVisible');
+
+ lua_pushBinInt(L, ScreenSing.Settings.PlayerEnabled);
+ lua_setField(L, -2, 'PlayerEnabled');
+
+
+ Result := 1;
+end;
+
+{ ScreenSing.SetSettings - arguments: Table
+ sets all attributes of TScreenSing.Settings that are
+ unequal to nil in Table }
+function ULuaScreenSing_SetSettings(L: Plua_State): Integer; cdecl;
+ var
+ Key: String;
+begin
+ Result := 0;
+
+ // check for table on stack
+ luaL_checkType(L, 1, LUA_TTABLE);
+
+ // go through table elements
+ lua_pushNil(L);
+ while (lua_Next(L, 1) <> 0) do
+ begin
+ Key := lowercase(lua_ToString(L, -2));
+
+ if (Key = 'lyricsvisible') and (lua_isBoolean(L, -1)) then
+ ScreenSing.settings.LyricsVisible := lua_toBoolean(L, -1)
+ else if (Key = 'notesvisible') and (lua_isTable(L, -1)) then
+ ScreenSing.settings.NotesVisible := lua_toBinInt(L, -1)
+ else if (Key = 'playerenabled') and (lua_isTable(L, -1)) then
+ ScreenSing.settings.PlayerEnabled := lua_toBinInt(L, -1);
+
+ // pop value from stack so key is on top
+ lua_pop(L, 1);
+ end;
+
+ // clear stack from table
+ lua_pop(L, lua_gettop(L));
+
+ ScreenSing.ApplySettings;
+end;
+
+{ ScreenSing.GetSongLines - no arguments
+ returns a table filled with lines of the loaded song or
+ nil if no song is loaded (singscreen is not displayed)
+ structure of returned table:
+ array [1.."count of lines"]
+ \
+ | Start: integer - beat the line is displayed at (on top of lyrics display)
+ | Lyric: string - full lyric of the line
+ | Notes: array [1.."count notes of this line"]
+ \
+ | Start: integer - beat the note starts at
+ | Length: integer - length in beats
+ | Tone: integer - pitch that has to be sung, full range
+ | NoteType: integer - 0 for freestyle, 1 for normal, 2 for golden
+ | Text: string - text of this fragment }
+function ULuaScreenSing_GetSongLines(L: Plua_State): Integer; cdecl;
+ var
+ I, J: Integer;
+begin
+ Result := 1;
+ if (Length(Lines) >= 1) then
+ begin
+ lua_ClearStack(L);
+
+ if not lua_CheckStack(L, 7) then
+ luaL_Error(L, PChar('can''t allocate enough stack space in ULuaScreenSing_GetSongLines'));
+
+ // lines array table
+ lua_CreateTable(L, Length(Lines[0].Line), 0);
+
+ for I := 0 to High(Lines[0].Line) do
+ with Lines[0].Line[I] do
+ begin
+ lua_pushInteger(L, I+1);
+
+ // line struct table
+ lua_CreateTable(L, 0, 3);
+
+ // line start
+ lua_PushInteger(L, Start);
+ lua_SetField(L, -2, PChar('Start'));
+
+ // line lyric
+ lua_PushString(L, PChar(Lyric));
+ lua_SetField(L, -2, PChar('Lyric'));
+
+ //line notes array table
+ lua_CreateTable(L, Length(Note), 0);
+
+ for J := 0 to High(Note) do
+ begin
+ lua_PushInteger(L, J + 1);
+
+ // note struct table
+ lua_CreateTable(L, 0, 5);
+
+ // Notes[J+1].Start
+ lua_PushInteger(L, Note[J].Start);
+ lua_SetField(L, -2, PChar('Start'));
+
+ // Notes[J+1].Length
+ lua_PushInteger(L, Note[J].Length);
+ lua_SetField(L, -2, PChar('Length'));
+
+ // Notes[J+1].Tone
+ lua_PushInteger(L, Note[J].Tone);
+ lua_SetField(L, -2, PChar('Tone'));
+
+ // Notes[J+1].NoteType
+ lua_PushInteger(L, Integer(Note[J].NoteType));
+ lua_SetField(L, -2, PChar('NoteType'));
+
+ // Notes[J+1].Text
+ lua_PushString(L, PChar(Note[J].Text));
+ lua_SetField(L, -2, PChar('Text'));
+
+ lua_SetTable(L, -3);
+ end;
+
+ lua_SetField(L, -2, PChar('Notes'));
+
+ // save line to array table
+ lua_setTable(L, -3);
+ end;
+ end
+ else
+ begin
+ lua_ClearStack(L);
+ lua_pushNil(L);
+ end;
+end;
+
+end. \ No newline at end of file
diff --git a/src/lua/ULuaTextGL.pas b/src/lua/ULuaTextGL.pas
new file mode 100644
index 00000000..1db41b21
--- /dev/null
+++ b/src/lua/ULuaTextGL.pas
@@ -0,0 +1,147 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaTextGL;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ TextGL,
+ ULua;
+
+{ TextGl.Pos(X, Y: Float) : sets font position }
+function ULuaTextGL_Pos(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Size(Size: Float) : sets font size }
+function ULuaTextGL_Size(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Style(Style: int) : sets font style (from 0 to 3) }
+function ULuaTextGL_Style(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Italic(isItalic: boolean) : sets if font is italic }
+function ULuaTextGL_Italic(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Width(Text: String) : returns width of Text if printed
+ w/ current settings in pixels }
+function ULuaTextGL_Width(L: Plua_State): Integer; cdecl;
+
+{ TextGl.Print(Text: String) : prints text to screen w/ current
+ settings}
+function ULuaTextGL_Print(L: Plua_State): Integer; cdecl;
+
+const
+ ULuaTextGl_Lib_f: array [0..5] of lual_reg = (
+ (name:'Pos'; func:ULuaTextGl_Pos),
+ (name:'Size'; func:ULuaTextGl_Size),
+ (name:'Style'; func:ULuaTextGl_Style),
+ (name:'Italic'; func:ULuaTextGl_Italic),
+ (name:'Width'; func:ULuaTextGl_Width),
+ (name:'Print'; func:ULuaTextGl_Print)
+ );
+
+
+implementation
+
+{ TextGl.Pos(X, Y: Float) : sets font position }
+function ULuaTextGL_Pos(L: Plua_State): Integer; cdecl;
+ var X, Y: Double;
+begin
+ X := luaL_checknumber(L, 1);
+ Y := luaL_checknumber(L, 2);
+
+ SetFontPos(X, Y);
+
+ Result := 0;
+end;
+
+{ TextGl.Size(Size: Float) : sets font size }
+function ULuaTextGL_Size(L: Plua_State): Integer; cdecl;
+ var Size: Double;
+begin
+ Size := luaL_checknumber(L, 1);
+
+ SetFontSize(Size);
+
+ Result := 0;
+end;
+
+{ TextGl.Style(Style: int) : sets font style (from 0 to 3) }
+function ULuaTextGL_Style(L: Plua_State): Integer; cdecl;
+ var Style: Integer;
+begin
+ Style := luaL_checkinteger(L, 1);
+
+ if (Style >= 0) and (Style <= 3) then
+ SetFontStyle(Style)
+ else
+ luaL_ArgError(L, 1, PChar('number from 0 to 3 expected'));
+
+ Result := 0;
+end;
+
+{ TextGl.Italic(isItalic: boolean) : sets if font is italic }
+function ULuaTextGL_Italic(L: Plua_State): Integer; cdecl;
+ var isItalic: Boolean;
+begin
+ luaL_checkany(L, 1);
+ isItalic := lua_toBoolean(L, 1);
+
+ SetFontItalic(isItalic);
+
+ Result := 0;
+end;
+
+{ TextGl.Width(Text: String) : returns width of Text if printed
+ w/ current settings in pixels }
+function ULuaTextGL_Width(L: Plua_State): Integer; cdecl;
+ var Text: String;
+begin
+ Text := luaL_checkstring(L, 1);
+ lua_pop(L, lua_gettop(L));
+
+ lua_PushNumber(L, glTextWidth(Text));
+
+ Result := 1;
+end;
+
+{ TextGl.Print(Text: String) : prints text to screen w/ current
+ settings}
+function ULuaTextGL_Print(L: Plua_State): Integer; cdecl;
+ var Text: String;
+begin
+ Text := luaL_checkstring(L, 1);
+
+ glPrint(Text);
+
+ Result := 0;
+end;
+
+end.
diff --git a/src/lua/ULuaTexture.pas b/src/lua/ULuaTexture.pas
new file mode 100644
index 00000000..931c0405
--- /dev/null
+++ b/src/lua/ULuaTexture.pas
@@ -0,0 +1,63 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaTexture;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ SysUtils,
+ ULua,
+ UTexture;
+
+function luaopen_Texture (L: Plua_State): Integer; cdecl;
+
+function ULuaTexture_Dummy(L: Plua_State): Integer; cdecl;
+
+implementation
+
+function ULuaTexture_Dummy(L: Plua_State): Integer; cdecl;
+begin
+ result:=0; // number of results
+end;
+
+const
+ ULuaTexture_Lib_f: array [0..1] of lual_reg = (
+ (name:'Add';func:ULuaTexture_Dummy),
+ (name:nil;func:nil)
+ );
+
+function luaopen_Texture (L: Plua_State): Integer; cdecl;
+begin
+ luaL_register(L,'Texture',@ULuaTexture_Lib_f[0]);
+ result:=1;
+end;
+end.
diff --git a/src/lua/ULuaUsdx.pas b/src/lua/ULuaUsdx.pas
new file mode 100644
index 00000000..d92289b1
--- /dev/null
+++ b/src/lua/ULuaUsdx.pas
@@ -0,0 +1,145 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaUsdx;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses ULua;
+
+{ some basic lua c functions from usdx table }
+
+{ Usdx.Time - returns sdl_time to have time numbers comparable with
+ ultrastar deluxe ones. no arguments }
+function ULuaUsdx_Time(L: Plua_State): Integer; cdecl;
+
+{ Usdx.Version - returns Usdx version string (the same that US_Version
+ language-constant does). no arguments }
+function ULuaUsdx_Version(L: Plua_State): Integer; cdecl;
+
+{ Usdx.Hook - returns an hook table with name and Unhook function
+ arguments: event_name: string }
+function ULuaUsdx_Hook(L: Plua_State): Integer; cdecl;
+
+{ Usdx.ShutMeDown - no results, no arguments
+ unloads the calling plugin }
+function ULuaUsdx_ShutMeDown(L: Plua_State): Integer; cdecl;
+
+const
+ ULuaUsdx_Lib_f: array [0..4] of lual_reg = (
+ (name:'Version'; func:ULuaUsdx_Version),
+ (name:'Time'; func:ULuaUsdx_Time),
+ (name:'Hook'; func:ULuaUsdx_Hook),
+ (name:'ShutMeDown'; func:ULuaUsdx_ShutMeDown),
+ (name:nil;func:nil)
+ );
+
+implementation
+uses SDL, ULuaCore, ULuaUtils, UHookableEvent, UConfig;
+
+{ Usdx.Time - returns sdl_time to have time numbers comparable with
+ ultrastar deluxe ones. no arguments }
+function ULuaUsdx_Time(L: Plua_State): Integer; cdecl;
+ var top: Integer;
+begin
+ //remove arguments (if any)
+ top := lua_gettop(L);
+
+ if (top > 0) then
+ lua_pop(L, top);
+
+ //push result
+ lua_pushinteger(L, SDL_GetTicks);
+ Result := 1; //one result
+end;
+
+{ Usdx.Version - returns Usdx version string (the same that US_Version
+ language-constant does). no arguments }
+function ULuaUsdx_Version(L: Plua_State): Integer; cdecl;
+ var top: Integer;
+begin
+ //remove arguments (if any)
+ top := lua_gettop(L);
+
+ if (top > 0) then
+ lua_pop(L, top);
+
+ //push result
+ lua_pushstring(L, PChar(USDXVersionStr()));
+ Result := 1; //one result
+end;
+
+{ Usdx.Hook - returns an hook table with name and Unhook function
+ arguments: event_name: string; function_name: string }
+function ULuaUsdx_Hook(L: Plua_State): Integer; cdecl;
+var
+ EventName: String;
+ FunctionName: String;
+ P: TLuaPlugin;
+ Event: THookableEvent;
+begin
+ EventName := luaL_checkstring(L, 1);
+ FunctionName := luaL_checkstring(L, 2);
+
+ P := Lua_GetOwner(L);
+
+ lua_pop(L, lua_gettop(L)); //clear stack
+
+ Result := 1;
+
+ Event := LuaCore.GetEventByName(EventName);
+ if (Event <> nil) then
+ begin
+ Event.Hook(L, P.Id, FunctionName);
+ end
+ else
+ luaL_error(L, PChar('event does not exist: ' + EventName));
+end;
+
+function ULuaUsdx_ShutMeDown(L: Plua_State): Integer; cdecl;
+ var
+ top: Integer;
+ P: TLuaPlugin;
+begin
+ Result := 0;
+
+ //remove arguments (if any)
+ top := lua_gettop(L);
+
+ if (top > 0) then
+ lua_pop(L, top);
+
+ P := Lua_GetOwner(L);
+
+ P.ShutMeDown;
+end;
+
+end. \ No newline at end of file
diff --git a/src/lua/ULuaUtils.pas b/src/lua/ULuaUtils.pas
new file mode 100644
index 00000000..143b34d4
--- /dev/null
+++ b/src/lua/ULuaUtils.pas
@@ -0,0 +1,186 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *}
+
+unit ULuaUtils;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses ULua, ULuaCore;
+
+{ converts a lua table with a structure like:
+ * = 1 , * = 4 , * = 5
+ to an integer with the value:
+ 0b11001
+ does not pop anything }
+function Lua_ToBinInt(L: PLua_State; idx: Integer): Integer;
+
+{ converts an integer with the value:
+ 0b11001
+ to a lua table with a structure like:
+ * = 1 , * = 4 , * = 5
+ and pushed the table onto the stack }
+procedure Lua_PushBinInt(L: PLua_State; BinInt: Integer);
+
+{ pushes a table with position and size of a rectangle
+ t.x => position of the rectangle in pixels at x-axis
+ t.y => position of the rectangle in pixels at y-axis
+ t.w => width of the rectangle
+ t.h => height of the rectangle }
+procedure Lua_PushRect(L: PLua_State; X, Y, W, H: Double);
+
+{ returns plugin that is the owner of the given state
+ may raise a lua error if the parent id is not found
+ in states registry, if state owner does not exists
+ or is not loaded. So a check for a nil value is not
+ necessary }
+function Lua_GetOwner(L: PLua_State): TLuaPlugin;
+
+{ this is a helper in case an evenet owner don't has no use for the results
+ returns number of popped elements }
+function Lua_ClearStack(L: Plua_State): Integer;
+
+
+implementation
+
+{ converts a lua table with a structure like:
+ * = 1 , * = 4 , * = 5
+ to an integer with the value:
+ 0b11001
+ does not pop anything }
+function Lua_ToBinInt(L: PLua_State; idx: Integer): Integer;
+ var
+ I: Integer;
+begin
+ // default: no bits set
+ Result := 0;
+
+ lua_checkstack(L, 2);
+
+ if (idx < 0) then
+ dec(idx); // we will push one value before using this
+
+ lua_PushNil(L);
+ while (lua_next(L, idx) <> 0) do
+ begin
+ if (lua_isNumber(L, -1)) then
+ begin //check if we got an integer value from 1 to 32
+ I := lua_toInteger(L, -1);
+ if (I >= 1) and (I <= 32) then
+ Result := Result or 1 shl (I - 1);
+ end;
+
+ // pop value, so key is on top
+ lua_pop(L, 1);
+ end;
+end;
+
+{ converts an integer with the value:
+ 0b11001
+ to a lua table with a structure like:
+ * = 1 , * = 4 , * = 5
+ and pushed the table onto the stack }
+procedure Lua_PushBinInt(L: PLua_State; BinInt: Integer);
+var
+ I, Index: Integer;
+begin
+ lua_newTable(L);
+
+
+ Index := 1; //< lua starts w/ index 1
+ for I := 0 to 31 do
+ if (BinInt and (1 shl I) <> 0) then
+ begin
+ lua_pushInteger(L, Index);
+ lua_pushInteger(L, I);
+ lua_settable(L, -3);
+
+ Inc(Index);
+ end;
+end;
+
+{ pushes a table with position and size of a rectangle
+ t.x => position of the rectangle in pixels at x-axis
+ t.y => position of the rectangle in pixels at y-axis
+ t.w => width of the rectangle
+ t.h => height of the rectangle }
+procedure Lua_PushRect(L: PLua_State; X, Y, W, H: Double);
+begin
+ lua_createtable(L, 0, 4); // table w/ 4 record fields
+
+ // x pos
+ lua_pushNumber(L, X);
+ lua_setField(L, -2, 'x');
+
+ // y pos
+ lua_pushNumber(L, Y);
+ lua_setField(L, -2, 'y');
+
+ // width
+ lua_pushNumber(L, W);
+ lua_setField(L, -2, 'w');
+
+ // height
+ lua_pushNumber(L, H);
+ lua_setField(L, -2, 'h');
+end;
+
+{ returns plugin that is the owner of the given state
+ may raise a lua error if the parent id is not found
+ in states registry, if state owner does not exists
+ or is not loaded. So a check for a nil value is not
+ necessary }
+function Lua_GetOwner(L: PLua_State): TLuaPlugin;
+begin
+ lua_checkstack(L, 1);
+
+ lua_getfield (L, LUA_REGISTRYINDEX, '_USDX_STATE_ID');
+ if (not lua_isNumber(L, -1)) then
+ luaL_error(L, 'unable to get _USDX_STATE_ID');
+
+ Result := LuaCore.GetPluginById(lua_toInteger(L, -1));
+
+ lua_pop(L, 1); //< remove state id from stack
+
+ if (Result = nil) then
+ luaL_error(L, '_USDX_STATE_ID has invalid value')
+ else if (Result.Status > psRunning) then
+ luaL_error(L, 'owning plugin is not loaded or already unloaded in Lua_GetOwner');
+end;
+
+{ this is a helper in case an evenet owner don't has no use for the results
+ returns number of popped elements }
+function Lua_ClearStack(L: Plua_State): Integer;
+begin
+ Result := lua_gettop(L);
+ lua_pop(L, Result);
+end;
+
+end. \ No newline at end of file
diff --git a/src/menu/UDisplay.pas b/src/menu/UDisplay.pas
index 927a1256..f8f9c43f 100644
--- a/src/menu/UDisplay.pas
+++ b/src/menu/UDisplay.pas
@@ -40,11 +40,16 @@ uses
glu,
SysUtils,
UMenu,
- UPath;
+ UPath,
+ UMusic,
+ UHookableEvent;
type
TDisplay = class
private
+ ePreDraw: THookableEvent;
+ eDraw: THookableEvent;
+
//fade-to-black-hack
BlackScreen: boolean;
@@ -105,7 +110,11 @@ type
{ called when left or right mousebutton is pressed or released }
procedure OnMouseButton(Pressed: boolean);
+ { fades to specific screen (playing specified sound) }
+ function FadeTo(Screen: PMenu; const aSound: TAudioPlaybackStream = nil): PMenu;
+ { abort fading to the current screen, may be used in OnShow, or during fade process }
+ procedure AbortScreenChange;
{ draws software cursor }
procedure DrawCursor;
@@ -142,6 +151,10 @@ var
begin
inherited Create;
+ // create events for plugins
+ ePreDraw := THookableEvent.Create('Display.PreDraw');
+ eDraw := THookableEvent.Create('Display.Draw');
+
//popup hack
CheckOK := false;
NextScreen := nil;
@@ -225,6 +238,7 @@ begin
if (not assigned(NextScreen)) and (not BlackScreen) then
begin
+ ePreDraw.CallHookChain(false);
CurrentScreen.Draw;
//popup mod
@@ -241,6 +255,8 @@ begin
FadeEnabled := true
else if (Ini.ScreenFade = 0) then
FadeEnabled := false;
+
+ eDraw.CallHookChain(false);
end
else
begin
@@ -259,8 +275,11 @@ begin
glPushAttrib(GL_VIEWPORT_BIT);
glViewPort(0, 0, 512, 512);
+
// draw screen that will be faded
+ ePreDraw.CallHookChain(false);
CurrentScreen.Draw;
+ eDraw.CallHookChain(false);
// clear OpenGL errors, otherwise fading might be disabled due to some
// older errors in previous OpenGL calls.
@@ -299,7 +318,11 @@ begin
// blackscreen-hack
if not BlackScreen then
- NextScreen.Draw // draw next screen
+ begin
+ ePreDraw.CallHookChain(false);
+ NextScreen.Draw; // draw next screen
+ eDraw.CallHookChain(false);
+ end
else if ScreenAct = 1 then
begin
glClearColor(0, 0, 0 , 0);
@@ -540,6 +563,45 @@ begin
Result := True;
end;
+{ abort fading to the next screen, may be used in OnShow, or during fade process }
+procedure TDisplay.AbortScreenChange;
+ var
+ Temp: PMenu;
+begin
+ // this is some kind of "hack" it is based on the
+ // code that is used to change the screens in TDisplay.Draw
+ // we should rewrite this whole behaviour, as it is not well
+ // structured and not well extendable. Also we should offer
+ // a possibility to change screens to plugins
+ // change this code when restructuring is done
+ if (assigned(NextScreen)) then
+ begin
+ // we have to swap the screens
+ Temp := CurrentScreen;
+ CurrentScreen := NextScreen;
+ NextScreen := Temp;
+
+ // and call the OnShow procedure of the previous screen
+ // because it was already called by default fade procedure
+ NextScreen.OnShow;
+
+ end;
+end;
+
+{ fades to specific screen (playing specified sound)
+ returns old screen }
+function TDisplay.FadeTo(Screen: PMenu; const aSound: TAudioPlaybackStream = nil): PMenu;
+begin
+ Result := CurrentScreen;
+ if (Result <> nil) then
+ begin
+ if (aSound <> nil) then
+ Result.FadeTo(Screen, aSound)
+ else
+ Result.FadeTo(Screen);
+ end;
+end;
+
procedure TDisplay.SaveScreenShot;
var
Num: integer;
diff --git a/src/menu/UMenu.pas b/src/menu/UMenu.pas
index 659d4213..3ac487de 100644
--- a/src/menu/UMenu.pas
+++ b/src/menu/UMenu.pas
@@ -1187,8 +1187,8 @@ begin
begin
if (Display.CurrentScreen = @ScreenSing) then
ScreenSing.Finish
- else if (Display.CurrentScreen = @ScreenSingModi) then
- ScreenSingModi.Finish;
+ {else if (Display.CurrentScreen = @ScreenSingModi) then
+ ScreenSingModi.Finish;}
end;
end
else
diff --git a/src/screens/UScreenMain.pas b/src/screens/UScreenMain.pas
index ca4ba7cc..b342281c 100644
--- a/src/screens/UScreenMain.pas
+++ b/src/screens/UScreenMain.pas
@@ -153,12 +153,7 @@ begin
begin
if (Songs.SongList.Count >= 1) then
begin
- if (Length(DLLMan.Plugins) >= 1) then
- begin
- FadeTo(@ScreenPartyOptions, SoundLib.Start);
- end
- else //show error message, No Plugins Loaded
- ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_PLUGINS'));
+ FadeTo(@ScreenPartyOptions, SoundLib.Start);
end
else //show error message, No Songs Loaded
ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_SONGS'));
@@ -241,12 +236,18 @@ procedure TScreenMain.OnShow;
begin
inherited;
+ {**
+ * Clean up TPartyGame here
+ * at the moment there is no better place for this
+ *}
+ Party.Clear;
+
{ display cursor (on moved) }
Display.SetCursor;
-{**
- * Start background music
- *}
+ {**
+ * Start background music
+ *}
SoundLib.StartBgMusic;
end;
diff --git a/src/screens/UScreenPartyNewRound.pas b/src/screens/UScreenPartyNewRound.pas
index c4295502..b52efd21 100644
--- a/src/screens/UScreenPartyNewRound.pas
+++ b/src/screens/UScreenPartyNewRound.pas
@@ -46,21 +46,9 @@ type
TScreenPartyNewRound = class(TMenu)
public
//Texts:
- TextRound1: cardinal;
- TextRound2: cardinal;
- TextRound3: cardinal;
- TextRound4: cardinal;
- TextRound5: cardinal;
- TextRound6: cardinal;
- TextRound7: cardinal;
-
- TextWinner1: cardinal;
- TextWinner2: cardinal;
- TextWinner3: cardinal;
- TextWinner4: cardinal;
- TextWinner5: cardinal;
- TextWinner6: cardinal;
- TextWinner7: cardinal;
+ TextRound: array [0..6] of cardinal;
+
+ TextWinner: array [0..6] of cardinal;
TextNextRound: cardinal;
TextNextRoundNo: cardinal;
@@ -69,13 +57,7 @@ type
TextNextPlayer3: cardinal;
//Statics
- StaticRound1: cardinal;
- StaticRound2: cardinal;
- StaticRound3: cardinal;
- StaticRound4: cardinal;
- StaticRound5: cardinal;
- StaticRound6: cardinal;
- StaticRound7: cardinal;
+ StaticRound: array [0..6] of cardinal;
//Scores
TextScoreTeam1: cardinal;
@@ -144,16 +126,7 @@ begin
SDLK_RETURN:
begin
AudioPlayback.PlaySound(SoundLib.Start);
- if DLLMan.Selected.LoadSong then
- begin
- //Select PartyMode ScreenSong
- ScreenSong.Mode := smPartyMode;
- FadeTo(@ScreenSong);
- end
- else
- begin
- FadeTo(@ScreenSingModi);
- end;
+ Party.CallBeforeSongSelect;
end;
end;
end;
@@ -163,21 +136,21 @@ constructor TScreenPartyNewRound.Create;
begin
inherited Create;
- TextRound1 := AddText (Theme.PartyNewRound.TextRound1);
- TextRound2 := AddText (Theme.PartyNewRound.TextRound2);
- TextRound3 := AddText (Theme.PartyNewRound.TextRound3);
- TextRound4 := AddText (Theme.PartyNewRound.TextRound4);
- TextRound5 := AddText (Theme.PartyNewRound.TextRound5);
- TextRound6 := AddText (Theme.PartyNewRound.TextRound6);
- TextRound7 := AddText (Theme.PartyNewRound.TextRound7);
-
- TextWinner1 := AddText (Theme.PartyNewRound.TextWinner1);
- TextWinner2 := AddText (Theme.PartyNewRound.TextWinner2);
- TextWinner3 := AddText (Theme.PartyNewRound.TextWinner3);
- TextWinner4 := AddText (Theme.PartyNewRound.TextWinner4);
- TextWinner5 := AddText (Theme.PartyNewRound.TextWinner5);
- TextWinner6 := AddText (Theme.PartyNewRound.TextWinner6);
- TextWinner7 := AddText (Theme.PartyNewRound.TextWinner7);
+ TextRound[0] := AddText (Theme.PartyNewRound.TextRound1);
+ TextRound[1] := AddText (Theme.PartyNewRound.TextRound2);
+ TextRound[2] := AddText (Theme.PartyNewRound.TextRound3);
+ TextRound[3] := AddText (Theme.PartyNewRound.TextRound4);
+ TextRound[4] := AddText (Theme.PartyNewRound.TextRound5);
+ TextRound[5] := AddText (Theme.PartyNewRound.TextRound6);
+ TextRound[6] := AddText (Theme.PartyNewRound.TextRound7);
+
+ TextWinner[0] := AddText (Theme.PartyNewRound.TextWinner1);
+ TextWinner[1] := AddText (Theme.PartyNewRound.TextWinner2);
+ TextWinner[2] := AddText (Theme.PartyNewRound.TextWinner3);
+ TextWinner[3] := AddText (Theme.PartyNewRound.TextWinner4);
+ TextWinner[4] := AddText (Theme.PartyNewRound.TextWinner5);
+ TextWinner[5] := AddText (Theme.PartyNewRound.TextWinner6);
+ TextWinner[6] := AddText (Theme.PartyNewRound.TextWinner7);
TextNextRound := AddText (Theme.PartyNewRound.TextNextRound);
TextNextRoundNo := AddText (Theme.PartyNewRound.TextNextRoundNo);
@@ -185,13 +158,13 @@ begin
TextNextPlayer2 := AddText (Theme.PartyNewRound.TextNextPlayer2);
TextNextPlayer3 := AddText (Theme.PartyNewRound.TextNextPlayer3);
- StaticRound1 := AddStatic (Theme.PartyNewRound.StaticRound1);
- StaticRound2 := AddStatic (Theme.PartyNewRound.StaticRound2);
- StaticRound3 := AddStatic (Theme.PartyNewRound.StaticRound3);
- StaticRound4 := AddStatic (Theme.PartyNewRound.StaticRound4);
- StaticRound5 := AddStatic (Theme.PartyNewRound.StaticRound5);
- StaticRound6 := AddStatic (Theme.PartyNewRound.StaticRound6);
- StaticRound7 := AddStatic (Theme.PartyNewRound.StaticRound7);
+ StaticRound[0] := AddStatic (Theme.PartyNewRound.StaticRound1);
+ StaticRound[1] := AddStatic (Theme.PartyNewRound.StaticRound2);
+ StaticRound[2] := AddStatic (Theme.PartyNewRound.StaticRound3);
+ StaticRound[3] := AddStatic (Theme.PartyNewRound.StaticRound4);
+ StaticRound[4] := AddStatic (Theme.PartyNewRound.StaticRound5);
+ StaticRound[5] := AddStatic (Theme.PartyNewRound.StaticRound6);
+ StaticRound[6] := AddStatic (Theme.PartyNewRound.StaticRound7);
//Scores
TextScoreTeam1 := AddText (Theme.PartyNewRound.TextScoreTeam1);
@@ -219,18 +192,18 @@ end;
procedure TScreenPartyNewRound.OnShow;
var
I: integer;
- function GetTeamPlayers(const Num: byte): UTF8String;
+ function GetTeamPlayers(const Num: integer): UTF8String;
var
Players: array of UTF8String;
- J: byte;
+ J: integer;
begin
- if (Num-1 >= PartySession.Teams.NumTeams) then
+ if (Num > High(Party.Teams)) or (Num < 0) then
exit;
//Create Players array
- SetLength(Players, PartySession.Teams.TeamInfo[Num-1].NumPlayers);
- for J := 0 to PartySession.Teams.TeamInfo[Num-1].NumPlayers-1 do
- Players[J] := UTF8String(PartySession.Teams.TeamInfo[Num-1].PlayerInfo[J].Name);
+ SetLength(Players, Length(Party.Teams[Num].Players));
+ For J := 0 to High(Party.Teams[Num].Players) do
+ Players[J] := UTF8String(Party.Teams[Num].Players[J].Name);
//Implode and Return
Result := Language.Implode(Players);
@@ -238,135 +211,34 @@ var
begin
inherited;
- PartySession.StartRound;
-
//Set Visibility of Round Infos
- I := Length(PartySession.Rounds);
- if (I >= 1) then
- begin
- Static[StaticRound1].Visible := true;
- Text[TextRound1].Visible := true;
- Text[TextWinner1].Visible := true;
-
- //Texts:
- Text[TextRound1].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[0].Plugin].Name);
- Text[TextWinner1].Text := PartySession.GetWinnerString(0);
- end
- else
- begin
- Static[StaticRound1].Visible := false;
- Text[TextRound1].Visible := false;
- Text[TextWinner1].Visible := false;
- end;
-
- if (I >= 2) then
- begin
- Static[StaticRound2].Visible := true;
- Text[TextRound2].Visible := true;
- Text[TextWinner2].Visible := true;
-
- //Texts:
- Text[TextRound2].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[1].Plugin].Name);
- Text[TextWinner2].Text := PartySession.GetWinnerString(1);
- end
- else
- begin
- Static[StaticRound2].Visible := false;
- Text[TextRound2].Visible := false;
- Text[TextWinner2].Visible := false;
- end;
-
- if (I >= 3) then
- begin
- Static[StaticRound3].Visible := true;
- Text[TextRound3].Visible := true;
- Text[TextWinner3].Visible := true;
-
- //Texts:
- Text[TextRound3].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[2].Plugin].Name);
- Text[TextWinner3].Text := PartySession.GetWinnerString(2);
- end
- else
- begin
- Static[StaticRound3].Visible := false;
- Text[TextRound3].Visible := false;
- Text[TextWinner3].Visible := false;
- end;
-
- if (I >= 4) then
- begin
- Static[StaticRound4].Visible := true;
- Text[TextRound4].Visible := true;
- Text[TextWinner4].Visible := true;
-
- //Texts:
- Text[TextRound4].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[3].Plugin].Name);
- Text[TextWinner4].Text := PartySession.GetWinnerString(3);
- end
- else
+ for I := 0 to 6 do
begin
- Static[StaticRound4].Visible := false;
- Text[TextRound4].Visible := false;
- Text[TextWinner4].Visible := false;
- end;
-
- if (I >= 5) then
- begin
- Static[StaticRound5].Visible := true;
- Text[TextRound5].Visible := true;
- Text[TextWinner5].Visible := true;
-
- //Texts:
- Text[TextRound5].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[4].Plugin].Name);
- Text[TextWinner5].Text := PartySession.GetWinnerString(4);
- end
- else
- begin
- Static[StaticRound5].Visible := false;
- Text[TextRound5].Visible := false;
- Text[TextWinner5].Visible := false;
- end;
-
- if (I >= 6) then
- begin
- Static[StaticRound6].Visible := true;
- Text[TextRound6].Visible := true;
- Text[TextWinner6].Visible := true;
-
- //Texts:
- Text[TextRound6].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[5].Plugin].Name);
- Text[TextWinner6].Text := PartySession.GetWinnerString(5);
- end
- else
- begin
- Static[StaticRound6].Visible := false;
- Text[TextRound6].Visible := false;
- Text[TextWinner6].Visible := false;
+ if (I <= High(Party.Rounds)) then
+ begin
+ Static[StaticRound[I]].Visible := True;
+ Text[TextRound[I]].Visible := True;
+ Text[TextWinner[I]].Visible := True;
+
+ // update texts:
+ Text[TextRound[I]].Text := Language.Translate('MODE_' + uppercase(Party.Modes[Party.Rounds[I].Mode].Name) + '_NAME');
+ Text[TextWinner[I]].Text := Party.GetWinnerString(I);
+ end
+ else
+ begin
+ Static[StaticRound[I]].Visible := False;
+ Text[TextRound[I]].Visible := False;
+ Text[TextWinner[I]].Visible := False;
+ end;
end;
- if (I >= 7) then
- begin
- Static[StaticRound7].Visible := true;
- Text[TextRound7].Visible := true;
- Text[TextWinner7].Visible := true;
-
- //Texts:
- Text[TextRound7].Text := Language.Translate(DllMan.Plugins[PartySession.Rounds[6].Plugin].Name);
- Text[TextWinner7].Text := PartySession.GetWinnerString(6);
- end
- else
- begin
- Static[StaticRound7].Visible := false;
- Text[TextRound7].Visible := false;
- Text[TextWinner7].Visible := false;
- end;
//Display Scores
- if (PartySession.Teams.NumTeams >= 1) then
+ if (Length(Party.Teams) >= 1) then
begin
- Text[TextScoreTeam1].Text := InttoStr(PartySession.Teams.TeamInfo[0].Score);
- Text[TextNameTeam1].Text := UTF8String(PartySession.Teams.TeamInfo[0].Name);
- Text[TextTeam1Players].Text := GetTeamPlayers(1);
+ Text[TextScoreTeam1].Text := InttoStr(Party.Teams[0].Score);
+ Text[TextNameTeam1].Text := UTF8String(Party.Teams[0].Name);
+ Text[TextTeam1Players].Text := GetTeamPlayers(0);
Text[TextScoreTeam1].Visible := true;
Text[TextNameTeam1].Visible := true;
@@ -383,11 +255,11 @@ begin
Static[StaticNextPlayer1].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 2) then
+ if (Length(Party.Teams) >= 2) then
begin
- Text[TextScoreTeam2].Text := InttoStr(PartySession.Teams.TeamInfo[1].Score);
- Text[TextNameTeam2].Text := UTF8String(PartySession.Teams.TeamInfo[1].Name);
- Text[TextTeam2Players].Text := GetTeamPlayers(2);
+ Text[TextScoreTeam2].Text := InttoStr(Party.Teams[1].Score);
+ Text[TextNameTeam2].Text := UTF8String(Party.Teams[1].Name);
+ Text[TextTeam2Players].Text := GetTeamPlayers(1);
Text[TextScoreTeam2].Visible := true;
Text[TextNameTeam2].Visible := true;
@@ -404,11 +276,11 @@ begin
Static[StaticNextPlayer2].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Text[TextScoreTeam3].Text := InttoStr(PartySession.Teams.TeamInfo[2].Score);
- Text[TextNameTeam3].Text := UTF8String(PartySession.Teams.TeamInfo[2].Name);
- Text[TextTeam3Players].Text := GetTeamPlayers(3);
+ Text[TextScoreTeam3].Text := InttoStr(Party.Teams[2].Score);
+ Text[TextNameTeam3].Text := UTF8String(Party.Teams[2].Name);
+ Text[TextTeam3Players].Text := GetTeamPlayers(2);
Text[TextScoreTeam3].Visible := true;
Text[TextNameTeam3].Visible := true;
@@ -423,30 +295,30 @@ begin
Text[TextTeam3Players].Visible := false;
Static[StaticTeam3].Visible := false;
Static[StaticNextPlayer3].Visible := false;
- end;
+ end;
//nextRound Texts
- Text[TextNextRound].Text := Language.Translate(DllMan.Selected.PluginDesc);
- Text[TextNextRoundNo].Text := InttoStr(PartySession.CurRound + 1);
- if (PartySession.Teams.NumTeams >= 1) then
+ Text[TextNextRound].Text := Language.Translate('MODE_' + uppercase(Party.Modes[Party.Rounds[Party.CurrentRound].Mode].Name) + '_DESC');
+ Text[TextNextRoundNo].Text := InttoStr(Party.CurrentRound + 1);
+ if (Length(Party.Teams) >= 1) then
begin
- Text[TextNextPlayer1].Text := PartySession.Teams.Teaminfo[0].Playerinfo[PartySession.Teams.Teaminfo[0].CurPlayer].Name;
+ Text[TextNextPlayer1].Text := Party.Teams[0].Players[Party.Teams[0].NextPlayer].Name;
Text[TextNextPlayer1].Visible := true;
end
else
Text[TextNextPlayer1].Visible := false;
-
- if (PartySession.Teams.NumTeams >= 2) then
+
+ if (Length(Party.Teams) >= 2) then
begin
- Text[TextNextPlayer2].Text := PartySession.Teams.Teaminfo[1].Playerinfo[PartySession.Teams.Teaminfo[1].CurPlayer].Name;
+ Text[TextNextPlayer2].Text := Party.Teams[1].Players[Party.Teams[1].NextPlayer].Name;
Text[TextNextPlayer2].Visible := true;
end
else
Text[TextNextPlayer2].Visible := false;
- if (PartySession.Teams.NumTeams >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Text[TextNextPlayer3].Text := PartySession.Teams.Teaminfo[2].Playerinfo[PartySession.Teams.Teaminfo[2].CurPlayer].Name;
+ Text[TextNextPlayer3].Text := Party.Teams[2].Players[Party.Teams[2].NextPlayer].Name;
Text[TextNextPlayer3].Visible := true;
end
else
diff --git a/src/screens/UScreenPartyOptions.pas b/src/screens/UScreenPartyOptions.pas
index 2deffda6..3dce9954 100644
--- a/src/screens/UScreenPartyOptions.pas
+++ b/src/screens/UScreenPartyOptions.pas
@@ -44,38 +44,26 @@ uses
type
TScreenPartyOptions = class(TMenu)
- public
+ private
SelectLevel: cardinal;
SelectPlayList: cardinal;
SelectPlayList2: cardinal;
SelectRounds: cardinal;
- SelectTeams: cardinal;
- SelectPlayers1: cardinal;
- SelectPlayers2: cardinal;
- SelectPlayers3: cardinal;
+
+ IPlaylist: array[0..2] of UTF8String;
+ IPlaylist2: array of UTF8String;
PlayList: integer;
PlayList2: integer;
- Rounds: integer;
- NumTeams: integer;
- NumPlayer1, NumPlayer2, NumPlayer3: integer;
-
+
+ procedure SetPlaylist2;
+ public
constructor Create; override;
function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
procedure OnShow; override;
procedure SetAnimationProgress(Progress: real); override;
- procedure SetPlaylist2;
end;
-var
- IPlaylist: array[0..2] of UTF8String;
- IPlaylist2: array of UTF8String;
-
- const
- ITeams: array[0..1] of UTF8String = ('2', '3');
- IPlayers: array[0..3] of UTF8String = ('1', '2', '3', '4');
- IRounds: array[0..5] of UTF8String = ('2', '3', '4', '5', '6', '7');
-
implementation
uses
@@ -122,27 +110,11 @@ begin
//Don'T start when Playlist is Selected and there are no Playlists
if (Playlist = 2) and (Length(PlaylistMan.Playlists) = 0) then
Exit;
- // Don't start when SinglePlayer Teams but only Multiplayer Plugins available
- OnlyMultiPlayer := true;
- for I := 0 to High(DLLMan.Plugins) do
- begin
- OnlyMultiPlayer := (OnlyMultiPlayer and DLLMan.Plugins[I].TeamModeOnly);
- end;
- if (OnlyMultiPlayer) and ((NumPlayer1 = 0) or (NumPlayer2 = 0) or ((NumPlayer3 = 0) and (NumTeams = 1))) then
- begin
- ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_PLUGINS'));
- Exit;
- end;
+
//Save Difficulty
Ini.Difficulty := SelectsS[SelectLevel].SelectedOption;
Ini.SaveLevel;
- //Save Num Teams:
- PartySession.Teams.NumTeams := NumTeams + 2;
- PartySession.Teams.Teaminfo[0].NumPlayers := NumPlayer1+1;
- PartySession.Teams.Teaminfo[1].NumPlayers := NumPlayer2+1;
- PartySession.Teams.Teaminfo[2].NumPlayers := NumPlayer3+1;
-
//Save Playlist
PlaylistMan.Mode := TSingMode( Playlist );
PlaylistMan.CurPlayList := High(cardinal);
@@ -169,9 +141,6 @@ begin
else
PlaylistMan.CurPlayList := Playlist2;
- //Start Party
- PartySession.StartNewParty(Rounds + 2);
-
AudioPlayback.PlaySound(SoundLib.Start);
//Go to Player Screen
FadeTo(@ScreenPartyPlayer);
@@ -191,10 +160,6 @@ begin
if (Interaction = 1) then
begin
SetPlaylist2;
- end //Change Team3 Players visibility
- else if (Interaction = 4) then
- begin
- SelectsS[7].Visible := (NumTeams = 1);
end;
end;
SDLK_LEFT:
@@ -206,10 +171,6 @@ begin
if (Interaction = 1) then
begin
SetPlaylist2;
- end //Change Team3 Players visibility
- else if (Interaction = 4) then
- begin
- SelectsS[7].Visible := (NumTeams = 1);
end;
end;
end;
@@ -229,30 +190,25 @@ begin
IPlaylist2[0] := '---';
//Clear all Selects
- NumTeams := 0;
- NumPlayer1 := 0;
- NumPlayer2 := 0;
- NumPlayer3 := 0;
- Rounds := 5;
PlayList := 0;
PlayList2 := 0;
//Load Screen From Theme
LoadFromTheme(Theme.PartyOptions);
+ Theme.PartyOptions.SelectLevel.oneItemOnly := true;
+ Theme.PartyOptions.SelectLevel.showArrows := true;
SelectLevel := AddSelectSlide(Theme.PartyOptions.SelectLevel, Ini.Difficulty, Theme.ILevel);
+
+ Theme.PartyOptions.SelectPlayList.oneItemOnly := true;
+ Theme.PartyOptions.SelectPlayList.showArrows := true;
SelectPlayList := AddSelectSlide(Theme.PartyOptions.SelectPlayList, PlayList, IPlaylist);
+
+ Theme.PartyOptions.SelectPlayList2.oneItemOnly := true;
+ Theme.PartyOptions.SelectPlayList2.showArrows := true;
SelectPlayList2 := AddSelectSlide(Theme.PartyOptions.SelectPlayList2, PlayList2, IPlaylist2);
- SelectRounds := AddSelectSlide(Theme.PartyOptions.SelectRounds, Rounds, IRounds);
- SelectTeams := AddSelectSlide(Theme.PartyOptions.SelectTeams, NumTeams, ITeams);
- SelectPlayers1 := AddSelectSlide(Theme.PartyOptions.SelectPlayers1, NumPlayer1, IPlayers);
- SelectPlayers2 := AddSelectSlide(Theme.PartyOptions.SelectPlayers2, NumPlayer2, IPlayers);
- SelectPlayers3 := AddSelectSlide(Theme.PartyOptions.SelectPlayers3, NumPlayer3, IPlayers);
Interaction := 0;
-
- //Hide Team3 Players
- SelectsS[7].Visible := false;
end;
procedure TScreenPartyOptions.SetPlaylist2;
@@ -306,7 +262,19 @@ procedure TScreenPartyOptions.OnShow;
begin
inherited;
- Randomize;
+ Party.Clear;
+
+ // check if there are loaded modes
+ if Party.ModesAvailable then
+ begin
+ // modes are loaded
+ Randomize;
+ end
+ else
+ begin // no modes found
+ ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_PLUGINS'));
+ Display.AbortScreenChange;
+ end;
end;
procedure TScreenPartyOptions.SetAnimationProgress(Progress: real);
diff --git a/src/screens/UScreenPartyPlayer.pas b/src/screens/UScreenPartyPlayer.pas
index 887d5202..3fcaa4ba 100644
--- a/src/screens/UScreenPartyPlayer.pas
+++ b/src/screens/UScreenPartyPlayer.pas
@@ -44,6 +44,14 @@ uses
type
TScreenPartyPlayer = class(TMenu)
+ private
+ CountTeams: integer;
+ CountPlayer: array [0..2] of integer;
+
+ SelectTeams: cardinal;
+ SelectPlayers: array [0..2] of cardinal;
+ procedure UpdateInterface;
+ procedure UpdateParty;
public
Team1Name: cardinal;
Player1Name: cardinal;
@@ -69,6 +77,10 @@ type
procedure SetAnimationProgress(Progress: real); override;
end;
+const
+ ITeams: array[0..1] of UTF8String = ('2', '3');
+ IPlayers: array[0..3] of UTF8String = ('1', '2', '3', '4');
+
implementation
uses
@@ -77,24 +89,92 @@ uses
UIni,
UTexture,
UParty,
- UUnicodeUtils;
+ UUnicodeUtils,
+ UScreenPartyOptions,
+ ULanguage;
+
+procedure TScreenPartyPlayer.UpdateInterface;
+ var
+ I: integer;
+ Btn: integer;
+begin
+ SelectsS[SelectPlayers[2]].Visible := (CountTeams = 1);
+
+ Btn := 0;
+ for I := 0 to 2 do
+ begin
+ if (CountTeams + 1 >= I) then
+ begin
+ Button[Btn + 0].Visible := true;
+ Button[Btn + 1].Visible := (CountPlayer[I] + 1 >= 1);
+ Button[Btn + 2].Visible := (CountPlayer[I] + 1 >= 2);
+ Button[Btn + 3].Visible := (CountPlayer[I] + 1 >= 3);
+ Button[Btn + 4].Visible := (CountPlayer[I] + 1 >= 4);
+ end
+ else
+ begin
+ Button[Btn + 0].Visible := false;
+ Button[Btn + 1].Visible := false;
+ Button[Btn + 2].Visible := false;
+ Button[Btn + 3].Visible := false;
+ Button[Btn + 4].Visible := false;
+ end;
+ Inc(Btn, 5);
+ end;
+end;
+
+procedure TScreenPartyPlayer.UpdateParty;
+ var
+ I, J: integer;
+ Rounds: ARounds;
+begin
+ {//Save PlayerNames
+ for I := 0 to PartySession.Teams.NumTeams-1 do
+ begin
+ PartySession.Teams.Teaminfo[I].Name := PChar(Button[I*5].Text[0].Text);
+ for J := 0 to PartySession.Teams.Teaminfo[I].NumPlayers-1 do
+ begin
+ PartySession.Teams.Teaminfo[I].Playerinfo[J].Name := PChar(Button[I*5 + J+1].Text[0].Text);
+ PartySession.Teams.Teaminfo[I].Playerinfo[J].TimesPlayed := 0;
+ end;
+ end; }
+
+ // add teams to party
+
+ for I := 0 to CountTeams + 1 do
+ begin
+ Party.AddTeam(Button[I * 5].Text[0].Text);
+
+ for J := 0 to CountPlayer[I] do
+ Party.AddPlayer(I, Button[I * 5 + 1 + J].Text[0].Text);
+ end;
+
+ if (Party.ModesAvailable) then
+ begin //mode for current playersetup available
+ FadeTo(@ScreenPartyRounds, SoundLib.Start);
+ end
+ else
+ begin
+ // no mode available for current player setup
+ ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_MODES_FOR_CURRENT_SETUP'));
+ Party.Clear;
+ end;
+end;
function TScreenPartyPlayer.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
var
SDL_ModState: word;
- I, J: integer;
-
procedure IntNext;
begin
repeat
InteractNext;
- until Button[Interaction].Visible;
+ until (Interactions[Interaction].Typ <> iButton) or (Button[Interactions[Interaction].Num].Visible);
end;
procedure IntPrev;
begin
repeat
InteractPrev;
- until Button[Interaction].Visible;
+ until (Interactions[Interaction].Typ <> iButton) or (Button[Interactions[Interaction].Num].Visible);
end;
begin
Result := true;
@@ -244,31 +324,31 @@ begin
FadeTo(@ScreenPartyOptions);
end;
- SDLK_RETURN:
- begin
-
- //Save PlayerNames
- for I := 0 to PartySession.Teams.NumTeams-1 do
- begin
- PartySession.Teams.Teaminfo[I].Name := PChar(Button[I*5].Text[0].Text);
- for J := 0 to PartySession.Teams.Teaminfo[I].NumPlayers-1 do
- begin
- PartySession.Teams.Teaminfo[I].Playerinfo[J].Name := PChar(Button[I*5 + J+1].Text[0].Text);
- PartySession.Teams.Teaminfo[I].Playerinfo[J].TimesPlayed := 0;
- end;
- end;
-
- AudioPlayback.PlaySound(SoundLib.Start);
- FadeTo(@ScreenPartyNewRound);
- end;
+ SDLK_RETURN: UpdateParty;
// Up and Down could be done at the same time,
// but I don't want to declare variables inside
// functions like this one, called so many times
SDLK_DOWN: IntNext;
SDLK_UP: IntPrev;
- SDLK_RIGHT: IntNext;
- SDLK_LEFT: IntPrev;
+ SDLK_RIGHT: begin
+ if (Interaction in [0,2,8,14]) then
+ begin
+ AudioPlayback.PlaySound(SoundLib.Option);
+ InteractInc;
+
+ UpdateInterface;
+ end;
+ end;
+ SDLK_LEFT: begin
+ if (Interaction in [0,2,8,14]) then
+ begin
+ AudioPlayback.PlaySound(SoundLib.Option);
+ InteractDec;
+
+ UpdateInterface;
+ end;
+ end;
end;
end;
end;
@@ -279,25 +359,47 @@ begin
LoadFromTheme(Theme.PartyPlayer);
+ Theme.PartyPlayer.SelectTeams.oneItemOnly := true;
+ Theme.PartyPlayer.SelectTeams.showArrows := true;
+ SelectTeams := AddSelectSlide(Theme.PartyPlayer.SelectTeams, CountTeams, ITeams);
+
Team1Name := AddButton(Theme.PartyPlayer.Team1Name);
+ Theme.PartyPlayer.SelectPlayers1.oneItemOnly := true;
+ Theme.PartyPlayer.SelectPlayers1.showArrows := true;
+ SelectPlayers[0] := AddSelectSlide(Theme.PartyPlayer.SelectPlayers1, CountPlayer[0], IPlayers);
+
AddButton(Theme.PartyPlayer.Player1Name);
AddButton(Theme.PartyPlayer.Player2Name);
AddButton(Theme.PartyPlayer.Player3Name);
AddButton(Theme.PartyPlayer.Player4Name);
Team2Name := AddButton(Theme.PartyPlayer.Team2Name);
+ Theme.PartyPlayer.SelectPlayers2.oneItemOnly := true;
+ Theme.PartyPlayer.SelectPlayers2.showArrows := true;
+ SelectPlayers[1] := AddSelectSlide(Theme.PartyPlayer.SelectPlayers2, CountPlayer[1], IPlayers);
+
AddButton(Theme.PartyPlayer.Player5Name);
AddButton(Theme.PartyPlayer.Player6Name);
AddButton(Theme.PartyPlayer.Player7Name);
AddButton(Theme.PartyPlayer.Player8Name);
Team3Name := AddButton(Theme.PartyPlayer.Team3Name);
+ Theme.PartyPlayer.SelectPlayers3.oneItemOnly := true;
+ Theme.PartyPlayer.SelectPlayers3.showArrows := true;
+ SelectPlayers[2] := AddSelectSlide(Theme.PartyPlayer.SelectPlayers3, CountPlayer[2], IPlayers);
+
AddButton(Theme.PartyPlayer.Player9Name);
AddButton(Theme.PartyPlayer.Player10Name);
AddButton(Theme.PartyPlayer.Player11Name);
AddButton(Theme.PartyPlayer.Player12Name);
Interaction := 0;
+
+ //Clear Selects
+ CountTeams := 0;
+ CountPlayer[0] := 0;
+ CountPlayer[1] := 0;
+ CountPlayer[2] := 0;
end;
procedure TScreenPartyPlayer.OnShow;
@@ -320,66 +422,18 @@ begin
Button[5].Text[0].Text := Ini.NameTeam[1];
Button[10].Text[0].Text := Ini.NameTeam[2];
// Templates for Names Mod end
-
- if (PartySession.Teams.NumTeams>=1) then
- begin
- Button[0].Visible := true;
- Button[1].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=1);
- Button[2].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=2);
- Button[3].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=3);
- Button[4].Visible := (PartySession.Teams.Teaminfo[0].NumPlayers >=4);
- end
- else
- begin
- Button[0].Visible := false;
- Button[1].Visible := false;
- Button[2].Visible := false;
- Button[3].Visible := false;
- Button[4].Visible := false;
- end;
- if (PartySession.Teams.NumTeams>=2) then
- begin
- Button[5].Visible := true;
- Button[6].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=1);
- Button[7].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=2);
- Button[8].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=3);
- Button[9].Visible := (PartySession.Teams.Teaminfo[1].NumPlayers >=4);
- end
- else
- begin
- Button[5].Visible := false;
- Button[6].Visible := false;
- Button[7].Visible := false;
- Button[8].Visible := false;
- Button[9].Visible := false;
- end;
-
- if (PartySession.Teams.NumTeams>=3) then
- begin
- Button[10].Visible := true;
- Button[11].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=1);
- Button[12].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=2);
- Button[13].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=3);
- Button[14].Visible := (PartySession.Teams.Teaminfo[2].NumPlayers >=4);
- end
- else
- begin
- Button[10].Visible := false;
- Button[11].Visible := false;
- Button[12].Visible := false;
- Button[13].Visible := false;
- Button[14].Visible := false;
- end;
+ Party.Clear;
+ UpdateInterface;
end;
procedure TScreenPartyPlayer.SetAnimationProgress(Progress: real);
var
I: integer;
begin
- for I := 0 to high(Button) do
- Button[I].Texture.ScaleW := Progress;
+ {for I := 0 to high(Button) do
+ Button[I].Texture.ScaleW := Progress; }
end;
end.
diff --git a/src/screens/UScreenPartyRounds.pas b/src/screens/UScreenPartyRounds.pas
new file mode 100644
index 00000000..146b8beb
--- /dev/null
+++ b/src/screens/UScreenPartyRounds.pas
@@ -0,0 +1,237 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/branches/experimental/Lua/src/screens/UScreenPartyOptions.pas $
+ * $Id: UScreenPartyOptions.pas 2036 2009-12-14 20:59:44Z whiteshark0 $
+ *}
+
+unit UScreenPartyRounds;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ UMenu,
+ SDL,
+ UDisplay,
+ UMusic,
+ UFiles,
+ SysUtils,
+ UThemes;
+
+type
+ TScreenPartyRounds = class(TMenu)
+ private
+ SelectRoundCount: cardinal;
+ SelectRound: array [0..6] of cardinal;
+
+ RoundCount: integer;
+ Round: array [0..6] of integer;
+
+ IModeNames: array of UTF8String;
+ IModeIDs: array of integer;
+
+ procedure UpdateInterface;
+ procedure StartParty;
+ public
+ constructor Create; override;
+ function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean; override;
+ procedure OnShow; override;
+ procedure SetAnimationProgress(Progress: real); override;
+ end;
+
+const
+ IRoundCount: array[0..5] of UTF8String = ('2', '3', '4', '5', '6', '7');
+
+implementation
+
+uses
+ UGraphic,
+ UMain,
+ UIni,
+ UTexture,
+ ULanguage,
+ UParty,
+ USong,
+ UDLLManager,
+ UPlaylist,
+ USongs,
+ UUnicodeUtils;
+
+procedure TScreenPartyRounds.UpdateInterface;
+ var
+ I: integer;
+ ActualRounds: integer;
+begin
+ ActualRounds := RoundCount + 2;
+
+ for I := 0 to High(SelectRound) do
+ SelectsS[SelectRound[I]].Visible := (I < ActualRounds);
+end;
+
+procedure TScreenPartyRounds.StartParty;
+ var
+ GameRounds: ARounds;
+ I: integer;
+begin
+ SetLength(GameRounds, RoundCount + 2);
+
+ for I := 0 to High(GameRounds) do
+ GameRounds[I] := IModeIds[Round[I]];
+
+ // start party game
+ if (Party.StartGame(GameRounds)) then
+ begin
+ FadeTo(@ScreenPartyNewRound, SoundLib.Start);
+ end
+ else
+ begin
+ //error starting party game
+ ScreenPopupError.ShowPopup(Language.Translate('ERROR_CAN_NOT_START_PARTY'));
+ end;
+end;
+
+function TScreenPartyRounds.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown: boolean): boolean;
+var
+ I, J: integer;
+ OnlyMultiPlayer: boolean;
+begin
+ Result := true;
+ if (PressedDown) then
+ begin // Key Down
+ // check normal keys
+ case UCS4UpperCase(CharCode) of
+ Ord('Q'):
+ begin
+ Result := false;
+ Exit;
+ end;
+ end;
+
+ // check special keys
+ case PressedKey of
+ SDLK_ESCAPE,
+ SDLK_BACKSPACE :
+ begin
+ AudioPlayback.PlaySound(SoundLib.Back);
+ FadeTo(@ScreenPartyPlayer);
+ end;
+
+ SDLK_RETURN: StartParty;
+
+ // Up and Down could be done at the same time,
+ // but I don't want to declare variables inside
+ // functions like this one, called so many times
+ SDLK_DOWN: InteractNext;
+ SDLK_UP: InteractPrev;
+ SDLK_RIGHT:
+ begin
+ AudioPlayback.PlaySound(SoundLib.Option);
+ InteractInc;
+
+ if Interaction = 0 then
+ UpdateInterface;
+ end;
+ SDLK_LEFT:
+ begin
+ AudioPlayback.PlaySound(SoundLib.Option);
+ InteractDec;
+
+ if Interaction = 0 then
+ UpdateInterface;
+ end;
+ end;
+ end;
+end;
+
+constructor TScreenPartyRounds.Create;
+ var
+ I: integer;
+begin
+ inherited Create;
+ RoundCount := 5;
+
+ //Load Screen From Theme
+ LoadFromTheme(Theme.PartyRounds);
+
+ Theme.PartyRounds.SelectRoundCount.oneItemOnly := true;
+ Theme.PartyRounds.SelectRoundCount.showArrows := true;
+ SelectRoundCount := AddSelectSlide(Theme.PartyRounds.SelectRoundCount, RoundCount, IRoundCount);
+
+ SetLength(IModeNames, 1);
+ IModeNames[0] := '---';
+ for I := 0 to high(Theme.PartyRounds.SelectRound) do
+ begin
+ Round[I] := 0;
+ Theme.PartyRounds.SelectRound[I].oneItemOnly := true;
+ Theme.PartyRounds.SelectRound[I].showArrows := true;
+ SelectRound[I] := AddSelectSlide(Theme.PartyRounds.SelectRound[I], Round[I], IModeNames);
+ end;
+
+
+ Interaction := 0;
+end;
+
+procedure TScreenPartyRounds.OnShow;
+ var
+ ModeList: AParty_ModeList;
+ I: integer;
+begin
+ inherited;
+
+ // check if there are loaded modes
+ if Party.ModesAvailable then
+ begin
+ UpdateInterface;
+
+ ModeList := Party.GetAvailableModes;
+ SetLength(IModeNames, Length(ModeList));
+ SetLength(IModeIds, Length(ModeList));
+ for I := 0 to High(ModeList) do
+ begin
+ IModeNames[I] := ModeList[I].Name;
+ IModeIds[I] := ModeList[I].Index;
+ end;
+
+ for I := 0 to High(SelectRound) do
+ UpdateSelectSlideOptions(Theme.PartyRounds.SelectRound[I] , SelectRound[I], IModeNames, Round[I]);
+ end
+ else
+ begin
+ // no mode available for current player setup
+ ScreenPopupError.ShowPopup(Language.Translate('ERROR_NO_MODES_FOR_CURRENT_SETUP'));
+ Party.Clear;
+ Display.AbortScreenChange;
+ end;
+end;
+
+procedure TScreenPartyRounds.SetAnimationProgress(Progress: real);
+begin
+ {for I := 0 to 6 do
+ SelectS[I].Texture.ScaleW := Progress;}
+end;
+
+end.
diff --git a/src/screens/UScreenPartyScore.pas b/src/screens/UScreenPartyScore.pas
index 2de240b8..e2d4814b 100644
--- a/src/screens/UScreenPartyScore.pas
+++ b/src/screens/UScreenPartyScore.pas
@@ -103,26 +103,22 @@ begin
// check special keys
case PressedKey of
SDLK_ESCAPE,
- SDLK_BACKSPACE :
+ SDLK_BACKSPACE,
+ SDLK_RETURN :
begin
AudioPlayback.PlaySound(SoundLib.Start);
- if (PartySession.CurRound < High(PartySession.Rounds)) then
- FadeTo(@ScreenPartyNewRound)
+
+ Party.NextRound; //< go to next round
+
+ if (not Party.GameFinished) then
+ begin
+ FadeTo(@ScreenPartyNewRound);
+ end
else
begin
- PartySession.EndRound;
FadeTo(@ScreenPartyWin);
end;
end;
-
- SDLK_RETURN:
- begin
- AudioPlayback.PlaySound(SoundLib.Start);
- if (PartySession.CurRound < High(PartySession.Rounds)) then
- FadeTo(@ScreenPartyNewRound)
- else
- FadeTo(@ScreenPartyWin);
- end;
end;
end;
end;
@@ -204,29 +200,18 @@ end;
procedure TScreenPartyScore.OnShow;
var
I, J: integer;
- Placings: array [0..5] of byte;
+ Ranking: AParty_TeamRanking;
begin
inherited;
- //Get Maxscore
+ // indicate that round is finished
+ Party.RoundPlayed;
- MaxScore := 0;
- for I := 0 to ScreenSingModi.PlayerInfo.NumPlayers - 1 do
- begin
- if (ScreenSingModi.PlayerInfo.Playerinfo[I].Score > MaxScore) then
- MaxScore := ScreenSingModi.PlayerInfo.Playerinfo[I].Score;
- end;
+ // get rankings for current round
+ Ranking := Party.Rounds[Party.CurrentRound].Ranking;
- //Get Placings
- for I := 0 to ScreenSingModi.PlayerInfo.NumPlayers - 1 do
- begin
- Placings[I] := 0;
- for J := 0 to ScreenSingModi.PlayerInfo.NumPlayers - 1 do
- if (ScreenSingModi.PlayerInfo.Playerinfo[J].Score > ScreenSingModi.PlayerInfo.Playerinfo[I].Score) then
- Inc(Placings[I]);
- end;
- //Set Static Length
+ {//Set Static Length
Static[StaticTeam1].Texture.ScaleW := ScreenSingModi.PlayerInfo.Playerinfo[0].Percentage / 100;
Static[StaticTeam2].Texture.ScaleW := ScreenSingModi.PlayerInfo.Playerinfo[1].Percentage / 100;
Static[StaticTeam3].Texture.ScaleW := ScreenSingModi.PlayerInfo.Playerinfo[2].Percentage / 100;
@@ -234,26 +219,26 @@ begin
//fix: prevents static from drawn out of bounds.
if Static[StaticTeam1].Texture.ScaleW > 99 then Static[StaticTeam1].Texture.ScaleW := 99;
if Static[StaticTeam2].Texture.ScaleW > 99 then Static[StaticTeam2].Texture.ScaleW := 99;
- if Static[StaticTeam3].Texture.ScaleW > 99 then Static[StaticTeam3].Texture.ScaleW := 99;
-
- //End Last Round
- PartySession.EndRound;
+ if Static[StaticTeam3].Texture.ScaleW > 99 then Static[StaticTeam3].Texture.ScaleW := 99; }
//Set Winnertext
- Text[TextWinner].Text := Format(Language.Translate('PARTY_SCORE_WINS'), [PartySession.GetWinnerString(PartySession.CurRound)]);
+ Text[TextWinner].Text := Format(Language.Translate('PARTY_SCORE_WINS'), [Party.GetWinnerString(Party.CurrentRound)]);
- if (ScreenSingModi.PlayerInfo.NumPlayers >= 1) then
+ if (Length(Party.Teams) >= 1) then
begin
- Text[TextScoreTeam1].Text := InttoStr(ScreenSingModi.PlayerInfo.Playerinfo[0].Score);
- Text[TextNameTeam1].Text := UTF8String(ScreenSingModi.TeamInfo.Teaminfo[0].Name);
+ Text[TextScoreTeam1].Text := InttoStr(Party.Teams[0].Score);
+ Text[TextNameTeam1].Text := Utf8String(Party.Teams[0].Name);
//Set Deco Texture
if Theme.PartyScore.DecoTextures.ChangeTextures then
begin
- Static[StaticTeam1Deco].Texture.TexNum := DecoTex[Placings[0]];
- Static[StaticTeam1Deco].Texture.ColR := DecoColor[Placings[0]].R;
- Static[StaticTeam1Deco].Texture.ColG := DecoColor[Placings[0]].G;
- Static[StaticTeam1Deco].Texture.ColB := DecoColor[Placings[0]].B;
+ if (Length(Ranking) >= 1) and (Ranking[0].Rank >= 1) and (Ranking[0].Rank <= Length(DecoTex)) then
+ begin
+ Static[StaticTeam1Deco].Texture.TexNum := DecoTex[Ranking[0].Rank-1];
+ Static[StaticTeam1Deco].Texture.ColR := DecoColor[Ranking[0].Rank-1].R;
+ Static[StaticTeam1Deco].Texture.ColG := DecoColor[Ranking[0].Rank-1].G;
+ Static[StaticTeam1Deco].Texture.ColB := DecoColor[Ranking[0].Rank-1].B;
+ end;
end;
Text[TextScoreTeam1].Visible := true;
@@ -271,18 +256,21 @@ begin
Static[StaticTeam1Deco].Visible := false;
end;
- if (ScreenSingModi.PlayerInfo.NumPlayers >= 2) then
+ if (Length(Party.Teams) >= 2) then
begin
- Text[TextScoreTeam2].Text := InttoStr(ScreenSingModi.PlayerInfo.Playerinfo[1].Score);
- Text[TextNameTeam2].Text := UTF8String(ScreenSingModi.TeamInfo.Teaminfo[1].Name);
+ Text[TextScoreTeam2].Text := InttoStr(Party.Teams[1].Score);
+ Text[TextNameTeam2].Text := UTF8String(Party.Teams[1].Name);
//Set Deco Texture
if Theme.PartyScore.DecoTextures.ChangeTextures then
begin
- Static[StaticTeam2Deco].Texture.TexNum := DecoTex[Placings[1]];
- Static[StaticTeam2Deco].Texture.ColR := DecoColor[Placings[1]].R;
- Static[StaticTeam2Deco].Texture.ColG := DecoColor[Placings[1]].G;
- Static[StaticTeam2Deco].Texture.ColB := DecoColor[Placings[1]].B;
+ if (Length(Ranking) >= 2) and (Ranking[1].Rank >= 1) and (Ranking[1].Rank <= Length(DecoTex)) then
+ begin
+ Static[StaticTeam2Deco].Texture.TexNum := DecoTex[Ranking[1].Rank-1];
+ Static[StaticTeam2Deco].Texture.ColR := DecoColor[Ranking[1].Rank-1].R;
+ Static[StaticTeam2Deco].Texture.ColG := DecoColor[Ranking[1].Rank-1].G;
+ Static[StaticTeam2Deco].Texture.ColB := DecoColor[Ranking[1].Rank-1].B;
+ end;
end;
Text[TextScoreTeam2].Visible := true;
@@ -300,18 +288,21 @@ begin
Static[StaticTeam2Deco].Visible := false;
end;
- if (ScreenSingModi.PlayerInfo.NumPlayers >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Text[TextScoreTeam3].Text := InttoStr(ScreenSingModi.PlayerInfo.Playerinfo[2].Score);
- Text[TextNameTeam3].Text := UTF8String(ScreenSingModi.TeamInfo.Teaminfo[2].Name);
+ Text[TextScoreTeam3].Text := InttoStr(Party.Teams[2].Score);
+ Text[TextNameTeam3].Text := UTF8String(Party.Teams[2].Name);
//Set Deco Texture
if Theme.PartyScore.DecoTextures.ChangeTextures then
begin
- Static[StaticTeam3Deco].Texture.TexNum := DecoTex[Placings[2]];
- Static[StaticTeam3Deco].Texture.ColR := DecoColor[Placings[2]].R;
- Static[StaticTeam3Deco].Texture.ColG := DecoColor[Placings[2]].G;
- Static[StaticTeam3Deco].Texture.ColB := DecoColor[Placings[2]].B;
+ if (Length(Ranking) >= 3) and (Ranking[2].Rank >= 1) and (Ranking[2].Rank <= Length(DecoTex)) then
+ begin
+ Static[StaticTeam3Deco].Texture.TexNum := DecoTex[Ranking[2].Rank-1];
+ Static[StaticTeam3Deco].Texture.ColR := DecoColor[Ranking[2].Rank-1].R;
+ Static[StaticTeam3Deco].Texture.ColG := DecoColor[Ranking[2].Rank-1].G;
+ Static[StaticTeam3Deco].Texture.ColB := DecoColor[Ranking[2].Rank-1].B;
+ end;
end;
Text[TextScoreTeam3].Visible := true;
@@ -332,12 +323,12 @@ end;
procedure TScreenPartyScore.SetAnimationProgress(Progress: real);
begin
- if (ScreenSingModi.PlayerInfo.NumPlayers >= 1) then
+ {if (ScreenSingModi.PlayerInfo.NumPlayers >= 1) then
Static[StaticTeam1].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[0].Percentage / 100;
if (ScreenSingModi.PlayerInfo.NumPlayers >= 2) then
Static[StaticTeam2].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[1].Percentage / 100;
if (ScreenSingModi.PlayerInfo.NumPlayers >= 3) then
- Static[StaticTeam3].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[2].Percentage / 100;
+ Static[StaticTeam3].Texture.ScaleW := Progress * ScreenSingModi.PlayerInfo.Playerinfo[2].Percentage / 100;}
end;
end.
diff --git a/src/screens/UScreenPartyWin.pas b/src/screens/UScreenPartyWin.pas
index afa5ce83..18a6e69e 100644
--- a/src/screens/UScreenPartyWin.pas
+++ b/src/screens/UScreenPartyWin.pas
@@ -94,13 +94,8 @@ begin
// check special keys
case PressedKey of
SDLK_ESCAPE,
- SDLK_BACKSPACE :
- begin
- AudioPlayback.PlaySound(SoundLib.Start);
- FadeTo(@ScreenMain);
- end;
-
- SDLK_RETURN:
+ SDLK_BACKSPACE,
+ SDLK_RETURN :
begin
AudioPlayback.PlaySound(SoundLib.Start);
FadeTo(@ScreenMain);
@@ -139,10 +134,10 @@ end;
procedure TScreenPartyWin.OnShow;
var
- I: integer;
- Placing: TeamOrderArray;
+ I, J: integer;
+ Ranking: AParty_TeamRanking;
- Function GetTeamColor(Team: byte): cardinal;
+ Function GetTeamColor(Team: integer): cardinal;
var
NameString: string;
begin
@@ -154,15 +149,16 @@ var
begin
inherited;
- //Get Team Placing
- Placing := PartySession.GetTeamOrder;
+ // get team ranking
+ // Ranking is sorted by score
+ Ranking := Party.GetTeamRanking;
//Set Winnertext
- Text[TextWinner].Text := Format(Language.Translate('PARTY_SCORE_WINS'), [PartySession.Teams.Teaminfo[Placing[0]].Name]);
- if (PartySession.Teams.NumTeams >= 1) then
+ Text[TextWinner].Text := Format(Language.Translate('PARTY_SCORE_WINS'), [Party.GetWinnerString(-1)]);
+ if (Length(Party.Teams) >= 1) then
begin
- Text[TextScoreTeam1].Text := InttoStr(PartySession.Teams.TeamInfo[Placing[0]].Score);
- Text[TextNameTeam1].Text := string(PartySession.Teams.TeamInfo[Placing[0]].Name);
+ Text[TextScoreTeam1].Text := IntToStr(Party.Teams[Ranking[0].Team].Score);
+ Text[TextNameTeam1].Text := Party.Teams[Ranking[0].Team].Name;
Text[TextScoreTeam1].Visible := true;
Text[TextNameTeam1].Visible := true;
@@ -173,7 +169,7 @@ begin
//Set Static Color to Team Color
if (Theme.PartyWin.StaticTeam1BG.Color = 'TeamColor') then
begin
- I := GetTeamColor(Placing[0]);
+ I := GetTeamColor(Ranking[0].Team);
if (I <> -1) then
begin
Static[StaticTeam1BG].Texture.ColR := Color[I].RGB.R;
@@ -184,7 +180,7 @@ begin
if (Theme.PartyWin.StaticTeam1.Color = 'TeamColor') then
begin
- I := GetTeamColor(Placing[0]);
+ I := GetTeamColor(Ranking[0].Team);
if (I <> -1) then
begin
Static[StaticTeam1].Texture.ColR := Color[I].RGB.R;
@@ -202,10 +198,10 @@ begin
Static[StaticTeam1Deco].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 2) then
+ if (Length(Party.Teams) >= 2) then
begin
- Text[TextScoreTeam2].Text := InttoStr(PartySession.Teams.TeamInfo[Placing[1]].Score);
- Text[TextNameTeam2].Text := string(PartySession.Teams.TeamInfo[Placing[1]].Name);
+ Text[TextScoreTeam2].Text := IntToStr(Party.Teams[Ranking[1].Team].Score);
+ Text[TextNameTeam2].Text := Party.Teams[Ranking[1].Team].Name;
Text[TextScoreTeam2].Visible := true;
Text[TextNameTeam2].Visible := true;
@@ -216,7 +212,7 @@ begin
//Set Static Color to Team Color
if (Theme.PartyWin.StaticTeam2BG.Color = 'TeamColor') then
begin
- I := GetTeamColor(Placing[1]);
+ I := GetTeamColor(Ranking[1].Team);
if (I <> -1) then
begin
Static[StaticTeam2BG].Texture.ColR := Color[I].RGB.R;
@@ -227,7 +223,7 @@ begin
if (Theme.PartyWin.StaticTeam2.Color = 'TeamColor') then
begin
- I := GetTeamColor(Placing[1]);
+ I := GetTeamColor(Ranking[1].Team);
if (I <> -1) then
begin
Static[StaticTeam2].Texture.ColR := Color[I].RGB.R;
@@ -245,10 +241,10 @@ begin
Static[StaticTeam2Deco].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Text[TextScoreTeam3].Text := InttoStr(PartySession.Teams.TeamInfo[Placing[2]].Score);
- Text[TextNameTeam3].Text := string(PartySession.Teams.TeamInfo[Placing[2]].Name);
+ Text[TextScoreTeam3].Text := IntToStr(Party.Teams[Ranking[2].Team].Score);
+ Text[TextNameTeam3].Text := Party.Teams[Ranking[2].Team].Name;
Text[TextScoreTeam3].Visible := true;
Text[TextNameTeam3].Visible := true;
@@ -259,7 +255,7 @@ begin
//Set Static Color to Team Color
if (Theme.PartyWin.StaticTeam3BG.Color = 'TeamColor') then
begin
- I := GetTeamColor(Placing[2]);
+ I := GetTeamColor(Ranking[2].Team);
if (I <> -1) then
begin
Static[StaticTeam3BG].Texture.ColR := Color[I].RGB.R;
@@ -270,7 +266,7 @@ begin
if (Theme.PartyWin.StaticTeam3.Color = 'TeamColor') then
begin
- I := GetTeamColor(Placing[2]);
+ I := GetTeamColor(Ranking[2].Team);
if (I <> -1) then
begin
Static[StaticTeam3].Texture.ColR := Color[I].RGB.R;
diff --git a/src/screens/UScreenSing.pas b/src/screens/UScreenSing.pas
index 20f3b15e..18496517 100644
--- a/src/screens/UScreenSing.pas
+++ b/src/screens/UScreenSing.pas
@@ -50,7 +50,8 @@ uses
UTexture,
UThemes,
UPath,
- UTime;
+ UTime,
+ UHookableEvent;
type
TLyricsSyncSource = class(TSyncSource)
@@ -61,7 +62,9 @@ type
TScreenSing = class(TMenu)
protected
VideoLoaded: boolean;
- Paused: boolean; // pause mod
+ eSongLoaded: THookableEvent; //< event is called after lyrics of a song are loaded on OnShow
+ protected
+ Paused: boolean; //pause Mod
LyricsSync: TLyricsSyncSource;
NumEmptySentences: integer;
public
@@ -104,6 +107,19 @@ type
fShowVisualization: boolean;
fCurrentVideoPlaybackEngine: IVideoPlayback;
+ // some settings to be set by plugins
+ settings: record
+ Finish: Boolean; //< if true, screen will finish on next draw
+
+ LyricsVisible: Boolean; //< shows or hides lyrics
+ NotesVisible: Integer; //< if bit[playernum] is set the notes for the specified player are visible. By default all players notes are visible
+
+ PlayerEnabled: Integer; //< defines whether a player can score atm
+ end;
+ procedure ClearSettings;
+ procedure ApplySettings; //< applies changes of settings record
+ procedure EndSong;
+
constructor Create; override;
procedure OnShow; override;
procedure OnShowFinish; override;
@@ -132,6 +148,7 @@ uses
URecord,
USong,
UDisplay,
+ UParty,
UUnicodeUtils;
// method for input parsing. if false is returned, getnextwindow
@@ -312,6 +329,10 @@ begin
Theme.LyricBar.LowerX, Theme.LyricBar.LowerY, Theme.LyricBar.LowerW, Theme.LyricBar.LowerH);
LyricsSync := TLyricsSyncSource.Create();
+
+ eSongLoaded := THookableEvent.Create('ScreenSing.SongLoaded');
+
+ ClearSettings;
end;
procedure TScreenSing.OnShow;
@@ -334,8 +355,10 @@ begin
//the song was sung to the end
SungToEnd := false;
+ ClearSettings;
+ Party.CallBeforeSing;
- // reset video playback engine, to play video clip ...
+ // reset video playback engine, to play Video Clip...
fCurrentVideoPlaybackEngine := VideoPlayback;
// setup score manager
@@ -443,8 +466,8 @@ begin
if (not success) then
begin
- // error loading song -> go back to song screen and show some error message
- FadeTo(@ScreenSong);
+ // error loading song -> go back to previous screen and show some error message
+ Display.AbortScreenChange;
// select new song in party mode
if ScreenSong.Mode = smPartyMode then
ScreenSong.SelectRandomSong();
@@ -635,6 +658,8 @@ begin
if Lines[0].Line[Index].TotalNotes = 0 then
Inc(NumEmptySentences);
+ eSongLoaded.CallHookChain(False);
+
Log.LogStatus('End', 'OnShow');
end;
@@ -653,6 +678,25 @@ begin
CountSkipTimeSet;
end;
+procedure TScreenSing.ClearSettings;
+begin
+ Settings.Finish := False;
+ Settings.LyricsVisible := True;
+ Settings.NotesVisible := high(Integer);
+ Settings.PlayerEnabled := high(Integer);
+end;
+
+{ applies changes of settings record }
+procedure TScreenSing.ApplySettings;
+begin
+ //
+end;
+
+procedure TScreenSing.EndSong;
+begin
+ Settings.Finish := True;
+end;
+
procedure TScreenSing.OnHide;
begin
// background texture
@@ -790,11 +834,14 @@ begin
if ShowFinish then
begin
if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or
- (LyricsState.GetCurrentTime() * 1000 <= CurrentSong.Finish)) then
+ (LyricsState.GetCurrentTime() * 1000 <= CurrentSong.Finish)) and (not Settings.Finish) then
begin
// analyze song if not paused
if (not Paused) then
+ begin
Sing(Self);
+ Party.CallOnSing;
+ end;
end
else
begin
@@ -802,7 +849,6 @@ begin
begin
Finish;
FadeOut := true;
- FadeTo(@ScreenScore);
end;
end;
end;
@@ -879,6 +925,8 @@ begin
end;
SetFontItalic(false);
+
+ Party.CallAfterSing;
end;
procedure TScreenSing.OnSentenceEnd(SentenceIndex: cardinal);
diff --git a/src/screens/UScreenSong.pas b/src/screens/UScreenSong.pas
index a2760ae3..5bc42a68 100644
--- a/src/screens/UScreenSong.pas
+++ b/src/screens/UScreenSong.pas
@@ -145,7 +145,7 @@ type
//procedures for Menu
procedure StartSong;
procedure OpenEditor;
- procedure DoJoker(Team: byte);
+ procedure DoJoker(Team: integer);
procedure SelectPlayers;
procedure UnloadDetailedCover;
@@ -602,7 +602,7 @@ begin
if (Ini.PartyPopup = 1) then
ScreenSongMenu.MenuShow(SM_Party_Main)
else
- ScreenSong.StartSong;
+ Party.CallAfterSongSelect;
end;
end;
end;
@@ -717,35 +717,17 @@ begin
SDLK_1:
begin //Joker
- if (Mode = smPartyMode) and (PartySession.Teams.NumTeams >= 1) and (PartySession.Teams.Teaminfo[0].Joker > 0) then
- begin
- //Use Joker
- Dec(PartySession.Teams.Teaminfo[0].Joker);
- SelectRandomSong;
- SetJoker;
- end;
+ DoJoker(0);
end;
SDLK_2:
begin //Joker
- if (Mode = smPartyMode) and (PartySession.Teams.NumTeams >= 2) and (PartySession.Teams.Teaminfo[1].Joker > 0) then
- begin
- //Use Joker
- Dec(PartySession.Teams.Teaminfo[1].Joker);
- SelectRandomSong;
- SetJoker;
- end;
+ DoJoker(1);
end;
SDLK_3:
begin //Joker
- if (Mode = smPartyMode) and (PartySession.Teams.NumTeams >= 3) and (PartySession.Teams.Teaminfo[2].Joker > 0) then
- begin
- //Use Joker
- Dec(PartySession.Teams.Teaminfo[2].Joker);
- SelectRandomSong;
- SetJoker;
- end;
+ DoJoker(2);
end;
end;
end; // if (PressedDown)
@@ -1555,8 +1537,8 @@ begin
AudioPlayback.SetVolume(1.0);
// if hide then stop music (for party mode popup on exit)
- if (Display.NextScreen <> @ScreenSing) and
- (Display.NextScreen <> @ScreenSingModi) then
+ if (Display.NextScreen <> @ScreenSing) {and
+ (Display.NextScreen <> @ScreenSingModi) }then
begin
StopMusicPreview();
end;
@@ -1883,13 +1865,13 @@ begin
// If Party Mode
if Mode = smPartyMode then //Show Joker that are available
begin
- if (PartySession.Teams.NumTeams >= 1) then
+ if (Length(Party.Teams) >= 1) then
begin
- Static[StaticTeam1Joker1].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 1);
- Static[StaticTeam1Joker2].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 2);
- Static[StaticTeam1Joker3].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 3);
- Static[StaticTeam1Joker4].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 4);
- Static[StaticTeam1Joker5].Visible := (PartySession.Teams.Teaminfo[0].Joker >= 5);
+ Static[StaticTeam1Joker1].Visible := (Party.Teams[0].JokersLeft >= 1);
+ Static[StaticTeam1Joker2].Visible := (Party.Teams[0].JokersLeft >= 2);
+ Static[StaticTeam1Joker3].Visible := (Party.Teams[0].JokersLeft >= 3);
+ Static[StaticTeam1Joker4].Visible := (Party.Teams[0].JokersLeft >= 4);
+ Static[StaticTeam1Joker5].Visible := (Party.Teams[0].JokersLeft >= 5);
end
else
begin
@@ -1900,13 +1882,13 @@ begin
Static[StaticTeam1Joker5].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 2) then
+ if (Length(Party.Teams) >= 2) then
begin
- Static[StaticTeam2Joker1].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 1);
- Static[StaticTeam2Joker2].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 2);
- Static[StaticTeam2Joker3].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 3);
- Static[StaticTeam2Joker4].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 4);
- Static[StaticTeam2Joker5].Visible := (PartySession.Teams.Teaminfo[1].Joker >= 5);
+ Static[StaticTeam2Joker1].Visible := (Party.Teams[1].JokersLeft >= 1);
+ Static[StaticTeam2Joker2].Visible := (Party.Teams[1].JokersLeft >= 2);
+ Static[StaticTeam2Joker3].Visible := (Party.Teams[1].JokersLeft >= 3);
+ Static[StaticTeam2Joker4].Visible := (Party.Teams[1].JokersLeft >= 4);
+ Static[StaticTeam2Joker5].Visible := (Party.Teams[1].JokersLeft >= 5);
end
else
begin
@@ -1917,13 +1899,13 @@ begin
Static[StaticTeam2Joker5].Visible := false;
end;
- if (PartySession.Teams.NumTeams >= 3) then
+ if (Length(Party.Teams) >= 3) then
begin
- Static[StaticTeam3Joker1].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 1);
- Static[StaticTeam3Joker2].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 2);
- Static[StaticTeam3Joker3].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 3);
- Static[StaticTeam3Joker4].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 4);
- Static[StaticTeam3Joker5].Visible := (PartySession.Teams.Teaminfo[2].Joker >= 5);
+ Static[StaticTeam3Joker1].Visible := (Party.Teams[2].JokersLeft >= 1);
+ Static[StaticTeam3Joker2].Visible := (Party.Teams[2].JokersLeft >= 2);
+ Static[StaticTeam3Joker3].Visible := (Party.Teams[2].JokersLeft >= 3);
+ Static[StaticTeam3Joker4].Visible := (Party.Teams[2].JokersLeft >= 4);
+ Static[StaticTeam3Joker5].Visible := (Party.Teams[2].JokersLeft >= 5);
end
else
begin
@@ -1990,7 +1972,7 @@ begin
//Party Mode
if (Mode = smPartyMode) then
begin
- FadeTo(@ScreenSingModi);
+ FadeTo(@ScreenSing);
end
else
begin
@@ -2021,14 +2003,14 @@ begin
end;
//Team No of Team (0-5)
-procedure TScreenSong.DoJoker (Team: byte);
+procedure TScreenSong.DoJoker (Team: integer);
begin
if (Mode = smPartyMode) and
- (PartySession.Teams.NumTeams >= Team + 1) and
- (PartySession.Teams.Teaminfo[Team].Joker > 0) then
+ (High(Party.Teams) >= Team) and
+ (Party.Teams[Team].JokersLeft > 0) then
begin
//Use Joker
- Dec(PartySession.Teams.Teaminfo[Team].Joker);
+ Dec(Party.Teams[Team].JokersLeft);
SelectRandomSong;
SetJoker;
end;
diff --git a/src/screens/UScreenSongMenu.pas b/src/screens/UScreenSongMenu.pas
index ec893c7a..173ac2c8 100644
--- a/src/screens/UScreenSongMenu.pas
+++ b/src/screens/UScreenSongMenu.pas
@@ -401,16 +401,19 @@ begin
begin
CurMenu := sMenu;
Text[0].Text := Language.Translate('SONG_MENU_NAME_PARTY_JOKER');
-
- Button[0].Visible := (PartySession.Teams.NumTeams >= 1) and (PartySession.Teams.Teaminfo[0].Joker > 0);
- Button[1].Visible := (PartySession.Teams.NumTeams >= 2) and (PartySession.Teams.Teaminfo[1].Joker > 0);
- Button[2].Visible := (PartySession.Teams.NumTeams >= 3) and (PartySession.Teams.Teaminfo[2].Joker > 0);
- Button[3].Visible := true;
- SelectsS[0].Visible := false;
-
- Button[0].Text[0].Text := UTF8String(PartySession.Teams.Teaminfo[0].Name);
- Button[1].Text[0].Text := UTF8String(PartySession.Teams.Teaminfo[1].Name);
- Button[2].Text[0].Text := UTF8String(PartySession.Teams.Teaminfo[2].Name);
+ // to-do : Party
+ Button[0].Visible := (Length(Party.Teams) >= 1) AND (Party.Teams[0].JokersLeft > 0);
+ Button[1].Visible := (Length(Party.Teams) >= 2) AND (Party.Teams[1].JokersLeft > 0);
+ Button[2].Visible := (Length(Party.Teams) >= 3) AND (Party.Teams[2].JokersLeft > 0);
+ Button[3].Visible := True;
+ SelectsS[0].Visible := False;
+
+ if (Button[0].Visible) then
+ Button[0].Text[0].Text := UTF8String(Party.Teams[0].Name);
+ if (Button[1].Visible) then
+ Button[1].Text[0].Text := UTF8String(Party.Teams[1].Name);
+ if (Button[2].Visible) then
+ Button[2].Text[0].Text := UTF8String(Party.Teams[2].Name);
Button[3].Text[0].Text := Language.Translate('SONG_MENU_CANCEL');
// set right interaction
@@ -614,7 +617,7 @@ begin
0: // button 1
begin
// start singing
- ScreenSong.StartSong;
+ Party.CallAfterSongSelect;
Visible := false;
end;
diff --git a/src/ultrastardx.dpr b/src/ultrastardx.dpr
index eca3ecc2..a0ee7c20 100644
--- a/src/ultrastardx.dpr
+++ b/src/ultrastardx.dpr
@@ -148,6 +148,21 @@ uses
{$ENDIF}
//------------------------------
+ //Includes - Lua Support
+ //------------------------------
+ ULua in 'lib\Lua\ULua.pas',
+ ULuaUtils in 'lua\ULuaUtils.pas',
+ ULuaGl in 'lua\ULuaGl.pas',
+ ULuaLog in 'lua\ULuaLog.pas',
+ ULuaTextGL in 'lua\ULuaTextGL.pas',
+ ULuaTexture in 'lua\ULuaTexture.pas',
+ UHookableEvent in 'lua\UHookableEvent.pas',
+ ULuaCore in 'lua\ULuaCore.pas',
+ ULuaUsdx in 'lua\ULuaUsdx.pas',
+ ULuaParty in 'lua\ULuaParty.pas',
+ ULuaScreenSing in 'lua\ULuaScreenSing.pas',
+
+ //------------------------------
//Includes - Menu System
//------------------------------
UDisplay in 'menu\UDisplay.pas',
@@ -322,6 +337,7 @@ uses
UScreenPartyScore in 'screens\UScreenPartyScore.pas',
UScreenPartyPlayer in 'screens\UScreenPartyPlayer.pas',
UScreenPartyOptions in 'screens\UScreenPartyOptions.pas',
+ UScreenPartyRounds in 'screens\UScreenPartyRounds.pas',
UScreenPartyWin in 'screens\UScreenPartyWin.pas',