From 731dec0d29e29a5d30e728616bcb5aa35c7c75ea Mon Sep 17 00:00:00 2001 From: tobigun Date: Wed, 30 Apr 2008 12:54:51 +0000 Subject: Fixed some range-check errors. Explicitly disable range-checks {$R-} should not be necessary for the MacOSX build anymore. Note: Texture-numbers (e.g. texnum) are unsigned (GLuint) so do not init them to -1. Use 0 instead. git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@1040 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Game/Code/Classes/UCommon.pas | 2 +- Game/Code/Classes/UDraw.pas | 2690 +++++++++++++++---------------- Game/Code/Classes/ULyrics.pas | 1508 +++++++++--------- Game/Code/Classes/UServices.pas | 2 + Game/Code/Classes/USingScores.pas | 26 +- Game/Code/Classes/UTexture.pas | 1982 +++++++++++------------ Game/Code/Menu/UMenu.pas | 3170 ++++++++++++++++++------------------- Game/Code/Menu/UMenuButton.pas | 1140 ++++++------- Game/Code/Screens/UScreenSing.pas | 2860 ++++++++++++++++----------------- Game/Code/switches.inc | 232 +-- 10 files changed, 6802 insertions(+), 6810 deletions(-) (limited to 'Game') diff --git a/Game/Code/Classes/UCommon.pas b/Game/Code/Classes/UCommon.pas index 1872b789..f37322f4 100644 --- a/Game/Code/Classes/UCommon.pas +++ b/Game/Code/Classes/UCommon.pas @@ -387,7 +387,7 @@ begin end; // create window Result := CreateWindowEx(WS_EX_TOOLWINDOW, WndClass.lpszClassName, '', - WS_POPUP, 0, 0, 0, 0, 0, 0, HInstance, nil); + DWORD(WS_POPUP), 0, 0, 0, 0, 0, 0, HInstance, nil); if (Result = 0) then Exit; // assign individual callback procedure to the window diff --git a/Game/Code/Classes/UDraw.pas b/Game/Code/Classes/UDraw.pas index d77a06a3..679c6df1 100644 --- a/Game/Code/Classes/UDraw.pas +++ b/Game/Code/Classes/UDraw.pas @@ -1,1345 +1,1345 @@ -unit UDraw; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - -uses UThemes, - ModiSDK, - UGraphicClasses; - -procedure SingDraw; -procedure SingModiDraw (PlayerInfo: TPlayerInfo); -procedure SingDrawBackground; -procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer); -procedure SingDrawNoteLines(Left, Top, Right: real; Space: integer); -procedure SingDrawBeatDelimeters(Left, Top, Right: real; NrLines: integer); -procedure SingDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer); -procedure SingDrawPlayerLine(X, Y, W: real; NrGracza: integer; Space: integer); -procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, NrGracza: integer; Space: integer); - -// TimeBar -procedure SingDrawTimeBar(); - -//Draw Editor NoteLines -procedure EditDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer); - - -type - TRecR = record - Top: real; - Left: real; - Right: real; - Bottom: real; - - Width: real; - WMid: real; - Height: real; - HMid: real; - - Mid: real; - end; - -var - NotesW: real; - NotesH: real; - Starfr: integer; - StarfrG: integer; - - //SingBar - TickOld: cardinal; - TickOld2:cardinal; - -const - Przedz = 32; - -implementation - -uses - OpenGL12, - UGraphic, - SysUtils, - UMusic, - URecord, - ULog, - UScreenSing, - UScreenSingModi, - ULyrics, - UMain, - TextGL, - UTexture, - UDrawTexture, - UIni, - Math, - UDLLManager; - -procedure SingDrawBackground; -var - Rec: TRecR; - TexRec: TRecR; -begin - if ScreenSing.Tex_Background.TexNum >= 1 then begin - - glClearColor (1, 1, 1, 1); - glColor4f (1, 1, 1, 1); - - if (Ini.MovieSize <= 1) then //HalfSize BG - begin - (* half screen + gradient *) - Rec.Top := 110; // 80 - Rec.Bottom := Rec.Top + 20; - Rec.Left := 0; - Rec.Right := 800; - - TexRec.Top := (Rec.Top / 600) * ScreenSing.Tex_Background.TexH; - TexRec.Bottom := (Rec.Bottom / 600) * ScreenSing.Tex_Background.TexH; - TexRec.Left := 0; - TexRec.Right := ScreenSing.Tex_Background.TexW; - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, ScreenSing.Tex_Background.TexNum); - glEnable(GL_BLEND); - glBegin(GL_QUADS); - (* gradient draw *) - (* top *) - glColor4f(1, 1, 1, 0); - glTexCoord2f(TexRec.Right, TexRec.Top); glVertex2f(Rec.Right, Rec.Top); - glTexCoord2f(TexRec.Left, TexRec.Top); glVertex2f(Rec.Left, Rec.Top); - glColor4f(1, 1, 1, 1); - glTexCoord2f(TexRec.Left, TexRec.Bottom); glVertex2f(Rec.Left, Rec.Bottom); - glTexCoord2f(TexRec.Right, TexRec.Bottom); glVertex2f(Rec.Right, Rec.Bottom); - (* mid *) - Rec.Top := Rec.Bottom; - Rec.Bottom := 490 - 20; // 490 - 20 - TexRec.Top := TexRec.Bottom; - TexRec.Bottom := (Rec.Bottom / 600) * ScreenSing.Tex_Background.TexH; - glTexCoord2f(TexRec.Left, TexRec.Top); glVertex2f(Rec.Left, Rec.Top); - glTexCoord2f(TexRec.Left, TexRec.Bottom); glVertex2f(Rec.Left, Rec.Bottom); - glTexCoord2f(TexRec.Right, TexRec.Bottom); glVertex2f(Rec.Right, Rec.Bottom); - glTexCoord2f(TexRec.Right, TexRec.Top); glVertex2f(Rec.Right, Rec.Top); - (* bottom *) - Rec.Top := Rec.Bottom; - Rec.Bottom := 490; // 490 - TexRec.Top := TexRec.Bottom; - TexRec.Bottom := (Rec.Bottom / 600) * ScreenSing.Tex_Background.TexH; - glTexCoord2f(TexRec.Right, TexRec.Top); glVertex2f(Rec.Right, Rec.Top); - glTexCoord2f(TexRec.Left, TexRec.Top); glVertex2f(Rec.Left, Rec.Top); - glColor4f(1, 1, 1, 0); - glTexCoord2f(TexRec.Left, TexRec.Bottom); glVertex2f(Rec.Left, Rec.Bottom); - glTexCoord2f(TexRec.Right, TexRec.Bottom); glVertex2f(Rec.Right, Rec.Bottom); - - glEnd; - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - end - else //Full Size BG - begin - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, ScreenSing.Tex_Background.TexNum); - //glEnable(GL_BLEND); - glBegin(GL_QUADS); - - glTexCoord2f(0, 0); glVertex2f(0, 0); - glTexCoord2f(0, ScreenSing.Tex_Background.TexH); glVertex2f(0, 600); - glTexCoord2f( ScreenSing.Tex_Background.TexW, ScreenSing.Tex_Background.TexH); glVertex2f(800, 600); - glTexCoord2f( ScreenSing.Tex_Background.TexW, 0); glVertex2f(800, 0); - - glEnd; - glDisable(GL_TEXTURE_2D); - //glDisable(GL_BLEND); - end; - end; -end; - -procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer); -var - SampleIndex: integer; - Sound: TCaptureBuffer; - MaxX, MaxY: real; -begin; - Sound := AudioInputProcessor.Sound[NrSound]; - - // Log.LogStatus('Oscilloscope', 'SingDraw'); - glColor3f(Skin_OscR, Skin_OscG, Skin_OscB); - {if (ParamStr(1) = '-black') or (ParamStr(1) = '-fsblack') then - glColor3f(1, 1, 1); } - - MaxX := W-1; - MaxY := (H-1) / 2; - - glBegin(GL_LINE_STRIP); - for SampleIndex := 0 to High(Sound.BufferArray) do - begin - glVertex2f(X + MaxX * SampleIndex/High(Sound.BufferArray), - Y + MaxY * (1 - Sound.BufferArray[SampleIndex]/-Low(Smallint))); - end; - glEnd; -end; - - - -procedure SingDrawNoteLines(Left, Top, Right: real; Space: integer); -var - Count: integer; -begin - glEnable(GL_BLEND); - glColor4f(Skin_P1_LinesR, Skin_P1_LinesG, Skin_P1_LinesB, 0.4); - glBegin(GL_LINES); - for Count := 0 to 9 do begin - glVertex2f(Left, Top + Count * Space); - glVertex2f(Right, Top + Count * Space); - end; - glEnd; - glDisable(GL_BLEND); -end; - -procedure SingDrawBeatDelimeters(Left, Top, Right: real; NrLines: integer); -var - Count: integer; - TempR: real; -begin - TempR := (Right-Left) / (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start); - glEnable(GL_BLEND); - glBegin(GL_LINES); - for Count := Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start to Lines[NrLines].Line[Lines[NrLines].Current].End_ do begin - if (Count mod Lines[NrLines].Resolution) = Lines[NrLines].NotesGAP then - glColor4f(0, 0, 0, 1) - else - glColor4f(0, 0, 0, 0.3); - glVertex2f(Left + TempR * (Count - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start), Top); - glVertex2f(Left + TempR * (Count - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start), Top + 135); - end; - glEnd; - glDisable(GL_BLEND); -end; - -// draw blank Notebars -procedure SingDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer); -var - Rec: TRecR; - Count: integer; - TempR: real; - R,G,B: real; - - PlayerNumber: Integer; - - GoldenStarPos : real; - - lTmpA , - lTmpB : real; -begin -// We actually don't have a playernumber in this procedure, it should reside in NrLines - but it's always set to zero -// 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 - - PlayerNumber := NrLines + 1; // Player 1 is 0 - NrLines := 0; - -// exploit done - - glColor3f(1, 1, 1); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - lTmpA := (Right-Left); - lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start); - - if ( lTmpA > 0 ) AND - ( lTmpB > 0 ) THEN - begin - TempR := lTmpA / lTmpB; - end - else - begin - TempR := 0; - end; - - - with Lines[NrLines].Line[Lines[NrLines].Current] do begin - for Count := 0 to HighNote do begin - with Note[Count] do 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 - end; // case - end //Else all Notes same Color - else - glColor4f(1, 1, 1, 1); // We set alpha to 1, cause we can control the transparency through the png itself - // Czesci == teil, element == piece, element | koniec == end / ending - // lewa czesc - left part - Rec.Left := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX; - Rec.Right := Rec.Left + NotesW; - Rec.Top := Top - (Tone-BaseNote)*Space/2 - NotesH; - Rec.Bottom := Rec.Top + 2 * NotesH; - glBindTexture(GL_TEXTURE_2D, Tex_plain_Left[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; - - //We keep the postion of the top left corner b4 it's overwritten - GoldenStarPos := Rec.Left; - //done - - // srodkowa czesc - 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; // Dlugosc == length - - 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; - - // prawa czesc - 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; - - // Golden Star Patch - if (NoteType = ntGolden) AND (Ini.EffectSing=1) then - begin - GoldenRec.SaveGoldenStarsRec(GoldenStarPos, Rec.Top, Rec.Right, Rec.Bottom); - end; - - end; // if not FreeStyle - end; // with - end; // for - end; // with - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); -end; - - -// draw sung notes -procedure SingDrawPlayerLine(X, Y, W: real; NrGracza: integer; Space: integer); -var - TempR: real; - Rec: TRecR; - N: integer; - R: real; - G: real; - B: real; - A: real; - NotesH2: real; - begin -// Log.LogStatus('Player notes', 'SingDraw'); - -// if NrGracza = 0 then LoadColor(R, G, B, 'P1Light') -// else LoadColor(R, G, B, 'P2Light'); - -// R := 71/255; -// G := 175/255; -// B := 247/255; - - glColor3f(1, 1, 1); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - -//// if Player[NrGracza].IlNut > 0 then - begin - TempR := W / (Lines[0].Line[Lines[0].Current].End_ - Lines[0].Line[Lines[0].Current].Note[0].Start); - for N := 0 to Player[NrGracza].HighNote do - begin - with Player[NrGracza].Note[N] do - begin - // Left part of note - Rec.Left := X + (Start-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR + 0.5 + 10*ScreenX; - Rec.Right := Rec.Left + NotesW; - - // Draw it in half size, if not hit - if Hit then - begin - NotesH2 := NotesH - end - else - begin - NotesH2 := int(NotesH * 0.65); - end; - - Rec.Top := Y - (Tone-Lines[0].Line[Lines[0].Current].BaseNote)*Space/2 - NotesH2; - Rec.Bottom := Rec.Top + 2 *NotesH2; - - // draw the left part - glColor3f(1, 1, 1); - glBindTexture(GL_TEXTURE_2D, Tex_Left[NrGracza+1].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; - - // Middle part of the note - Rec.Left := Rec.Right; - Rec.Right := X + (Start+Length-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR - NotesW - 0.5 + 10*ScreenX; - - // (nowe) - dunno - if (Start+Length-1 = LineState.CurrentBeatD) then - Rec.Right := Rec.Right - (1-Frac(LineState.MidBeatD)) * TempR; - // the left note is more right than the right note itself, sounds weird - so we fix that xD - if Rec.Right <= Rec.Left then Rec.Right := Rec.Left; - - // draw the middle part - glBindTexture(GL_TEXTURE_2D, Tex_Mid[NrGracza+1].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; - glColor3f(1, 1, 1); - - // the right part of the note - Rec.Left := Rec.Right; - Rec.Right := Rec.Right + NotesW; - - glBindTexture(GL_TEXTURE_2D, Tex_Right[NrGracza+1].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; - - // Perfect note is stored - if Perfect and (Ini.EffectSing=1) then - begin - A := 1 - 2*(LineState.CurrentTime - GetTimeFromBeat(Start+Length)); - if not (Start+Length-1 = LineState.CurrentBeatD) then - - //Star animation counter - //inc(Starfr); - //Starfr := Starfr mod 128; - GoldenRec.SavePerfectNotePos(Rec.Left, Rec.Top); - end; - end; // with - end; // for - // eigentlich brauchen wir hier einen vergleich, um festzustellen, ob wir mit - // singen schon weiter wären, als bei Rec.Right, _auch, wenn nicht gesungen wird_ - // English Translation: - // actually we need a compare here, to determine if the singing process is ahead Rec.Right - // even if there is no singing - - - // passing on NrGracza... hope this is really something like the player-number, not only - // some kind of weird index into a colour-table - - if (Ini.EffectSing=1) then - GoldenRec.GoldenNoteTwinkle(Rec.Top,Rec.Bottom,Rec.Right, NrGracza); - end; // if -end; - -//draw Note glow -procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, NrGracza: integer; Space: integer); -var - Rec: TRecR; - Count: integer; - TempR: real; - R,G,B: real; - X1, X2, X3, X4: real; - W, H: real; - - lTmpA , - lTmpB : real; -begin - if (Player[NrGracza].ScoreTotalI >= 0) then begin - glColor4f(1, 1, 1, sqrt((1+sin( AudioPlayback.Position * 3))/4)/ 2 + 0.5 ); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - - lTmpA := (Right-Left); - lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start); - - - if ( lTmpA > 0 ) AND - ( lTmpB > 0 ) THEN - begin - TempR := lTmpA / lTmpB; - end - else - begin - TempR := 0; - end; - - with Lines[NrLines].Line[Lines[NrLines].Current] do begin - for Count := 0 to HighNote do begin - with Note[Count] do begin - if NoteType <> ntFreestyle then begin - // begin: 14, 20 - // easy: 6, 11 - W := NotesW * 2 + 2; - H := NotesH * 1.5 + 3.5; - - X2 := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX + 4; // wciecie - X1 := X2-W; - - X3 := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - 0.5 + 10*ScreenX - 4; // wciecie - X4 := X3+W; - - // left - Rec.Left := X1; - Rec.Right := X2; - Rec.Top := Top - (Tone-BaseNote)*Space/2 - H; - Rec.Bottom := Rec.Top + 2 * H; - - glBindTexture(GL_TEXTURE_2D, Tex_BG_Left[NrGracza+1].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; - - - // srodkowa czesc - Rec.Left := X2; - Rec.Right := X3; - - glBindTexture(GL_TEXTURE_2D, Tex_BG_Mid[NrGracza+1].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; - - // prawa czesc - Rec.Left := X3; - Rec.Right := X4; - - glBindTexture(GL_TEXTURE_2D, Tex_BG_Right[NrGracza+1].TexNum); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top); - glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom); - glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom); - glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top); - glEnd; - end; // if not FreeStyle - end; // with - end; // for - end; // with 1 - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - end; -end; - -procedure SingDraw; -var - Count: integer; - Pet2: integer; - TempR: real; - Rec: TRecR; - TexRec: TRecR; - NR: TRecR; - FS: real; - BarFrom: integer; - BarAlpha: real; - BarWspol: real; - TempCol: real; - Tekst: string; - PetCz: integer; - -begin - // positions - if Ini.SingWindow = 0 then - begin - NR.Left := 120; - end - else - begin - NR.Left := 20; - end; - - NR.Right := 780; - - NR.Width := NR.Right - NR.Left; - NR.WMid := NR.Width / 2; - NR.Mid := NR.Left + NR.WMid; - - // background //BG Fullsize Mod - //SingDrawBackground; - - //TimeBar mod - SingDrawTimeBar(); - //eoa TimeBar mod - - // rysuje paski pod nutami - if (PlayersPlay = 1) and (Ini.NoteLines = 1) 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); - 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); - end; - - // Draw Lyrics - ScreenSing.Lyrics.Draw(LineState.MidBeat); - - // todo: Lyrics -(* // rysuje pasek, podpowiadajacy poczatek spiwania w scenie - FS := 1.3; - BarFrom := Lines[0].Line[Lines[0].Current].StartNote - Lines[0].Line[Lines[0].Current].Start; - if BarFrom > 40 then BarFrom := 40; - if (Lines[0].Line[Lines[0].Current].StartNote - Lines[0].Line[Lines[0].Current].Start > 8) and // dluga przerwa //16->12 for more help bars and then 12->8 for even more - (Lines[0].Line[Lines[0].Current].StartNote - LineState.MidBeat > 0) and // przed tekstem - (Lines[0].Line[Lines[0].Current].StartNote - LineState.MidBeat < 40) then begin // ale nie za wczesnie - BarWspol := (LineState.MidBeat - (Lines[0].Line[Lines[0].Current].StartNote - BarFrom)) / BarFrom; - Rec.Left := NR.Left + BarWspol * -// (NR.WMid - Lines[0].Line[Lines[0].Current].LyricWidth / 2 * FS - 50); - (ScreenSing.LyricMain.ClientX - NR.Left - 50) + 10*ScreenX; - Rec.Right := Rec.Left + 50; - Rec.Top := Skin_LyricsT + 3; - Rec.Bottom := Rec.Top + 33;//SingScreen.LyricMain.Size * 3; -{ // zapalanie - BarAlpha := (BarWspol*10) * 0.5; - if BarAlpha > 0.5 then BarAlpha := 0.5; - - // gaszenie - if BarWspol > 0.95 then BarAlpha := 0.5 * (1 - (BarWspol - 0.95) * 20);}{ - - //Change fuer Crazy Joker - - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, Tex_Lyric_Help_Bar.TexNum); - glBegin(GL_QUADS); - glColor4f(1, 1, 1, 0); - glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top); - glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom); - glColor4f(1, 1, 1, 0.5); - glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom); - glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top); - glEnd; - glDisable(GL_BLEND); - - end; } -*) - // oscilloscope - if Ini.Oscilloscope = 1 then begin - if PlayersPlay = 1 then - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); - - if PlayersPlay = 2 then begin - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); - SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); - end; - - if PlayersPlay = 4 then begin - if ScreenAct = 1 then begin - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); - SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); - end; - if ScreenAct = 2 then begin - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2); - SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3); - end; - end; - - if PlayersPlay = 3 then begin - SingDrawOscilloscope(75 + 10*ScreenX, 95, 100, 20, 0); - SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); - SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); - end; - - if PlayersPlay = 6 then begin - if ScreenAct = 1 then begin - SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0); - SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); - SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); - end; - if ScreenAct = 2 then begin - SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3); - SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4); - SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5); - end; - end; - - end; - -// Set the note heights according to the difficulty level - case Ini.Difficulty of - 0: - begin - NotesH := 11; // 9 - NotesW := 6; // 5 - end; - 1: - begin - NotesH := 8; // 7 - NotesW := 4; // 4 - end; - 2: - begin - NotesH := 5; - NotesW := 3; - end; - end; - -// Draw the Notes - if PlayersPlay = 1 then begin - SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 0, 15); // Background glow - colorized in playercolor - SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15); // Plain unsung notes - colorized in playercolor - SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 0, 15); // imho the sung notes - end; - - if (PlayersPlay = 2) then begin - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 0, 15); - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 1, 15); - - SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15); - SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 1, 15); - - SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 0, 15); - SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 1, 15); - end; - - if PlayersPlay = 3 then begin - NotesW := NotesW * 0.8; - NotesH := NotesH * 0.8; - - SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 0, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 1, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 2, 12); - - SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12); - SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 1, 12); - SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 2, 12); - - SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 0, 12); - SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 1, 12); - SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 2, 12); - end; - - if PlayersPlay = 4 then begin - if ScreenAct = 1 then begin - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 0, 15); - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 1, 15); - end; - if ScreenAct = 2 then begin - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 2, 15); - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 3, 15); - end; - - if ScreenAct = 1 then begin - SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15); - SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 1, 15); - end; - if ScreenAct = 2 then begin - SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 2, 15); - SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 3, 15); - end; - - if ScreenAct = 1 then begin - SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 0, 15); - SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 1, 15); - end; - if ScreenAct = 2 then begin - SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 2, 15); - SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 3, 15); - end; - end; - - if PlayersPlay = 6 then begin - NotesW := NotesW * 0.8; - NotesH := NotesH * 0.8; - - if ScreenAct = 1 then begin - SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 0, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 1, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 2, 12); - end; - if ScreenAct = 2 then begin - SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 3, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 4, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 5, 12); - end; - - if ScreenAct = 1 then begin - SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12); - SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 1, 12); - SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 2, 12); - end; - if ScreenAct = 2 then begin - SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 3, 12); - SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 4, 12); - SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 5, 12); - end; - - if ScreenAct = 1 then begin - SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 0, 12); - SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 1, 12); - SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 2, 12); - end; - if ScreenAct = 2 then begin - SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 3, 12); - SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 4, 12); - SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 5, 12); - end; - end; - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); -end; - -// q'n'd for using the game mode dll's -procedure SingModiDraw (PlayerInfo: TPlayerInfo); -var - Count: integer; - Pet2: integer; - TempR: real; - Rec: TRecR; - TexRec: TRecR; - NR: TRecR; - FS: real; - BarFrom: integer; - BarAlpha: real; - BarWspol: real; - TempCol: real; - Tekst: string; - PetCz: integer; -begin - // positions - if Ini.SingWindow = 0 then begin - NR.Left := 120; - end else begin - NR.Left := 20; - end; - - NR.Right := 780; - NR.Width := NR.Right - NR.Left; - NR.WMid := NR.Width / 2; - NR.Mid := NR.Left + NR.WMid; - - // time bar - SingDrawTimeBar(); - - if DLLMan.Selected.ShowNotes then - begin - if PlayersPlay = 1 then - SingDrawNoteLines(Nr.Left + 10*ScreenX, Skin_P2_NotesB - 105, Nr.Right + 10*ScreenX, 15); - if (PlayersPlay = 2) or (PlayersPlay = 4) 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); - end; - - if (PlayersPlay = 3) or (PlayersPlay = 6) 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); - end; - end; - - // Draw Lyrics - ScreenSingModi.Lyrics.Draw(LineState.MidBeat); - - // todo: Lyrics -{ // rysuje pasek, podpowiadajacy poczatek spiwania w scenie - FS := 1.3; - BarFrom := Lines[0].Line[Lines[0].Current].StartNote - Lines[0].Line[Lines[0].Current].Start; - if BarFrom > 40 then BarFrom := 40; - if (Lines[0].Line[Lines[0].Current].StartNote - Lines[0].Line[Lines[0].Current].Start > 8) and // dluga przerwa //16->12 for more help bars and then 12->8 for even more - (Lines[0].Line[Lines[0].Current].StartNote - LineState.MidBeat > 0) and // przed tekstem - (Lines[0].Line[Lines[0].Current].StartNote - LineState.MidBeat < 40) then begin // ale nie za wczesnie - BarWspol := (LineState.MidBeat - (Lines[0].Line[Lines[0].Current].StartNote - BarFrom)) / BarFrom; - Rec.Left := NR.Left + BarWspol * (ScreenSingModi.LyricMain.ClientX - NR.Left - 50) + 10*ScreenX; - Rec.Right := Rec.Left + 50; - Rec.Top := Skin_LyricsT + 3; - Rec.Bottom := Rec.Top + 33;//SingScreen.LyricMain.Size * 3; - - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, Tex_Lyric_Help_Bar.TexNum); - glBegin(GL_QUADS); - glColor4f(1, 1, 1, 0); - glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top); - glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom); - glColor4f(1, 1, 1, 0.5); - glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom); - glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top); - glEnd; - glDisable(GL_BLEND); - end; - } - - // oscilloscope | the thing that moves when you yell into your mic (imho) - if (((Ini.Oscilloscope = 1) AND (DLLMan.Selected.ShowRateBar_O)) AND (NOT DLLMan.Selected.ShowRateBar)) then begin - if PlayersPlay = 1 then - if PlayerInfo.Playerinfo[0].Enabled then - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); - - if PlayersPlay = 2 then begin - if PlayerInfo.Playerinfo[0].Enabled then - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); - if PlayerInfo.Playerinfo[1].Enabled then - SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); - end; - - if PlayersPlay = 4 then begin - if ScreenAct = 1 then begin - if PlayerInfo.Playerinfo[0].Enabled then - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); - if PlayerInfo.Playerinfo[1].Enabled then - SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); - end; - if ScreenAct = 2 then begin - if PlayerInfo.Playerinfo[2].Enabled then - SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2); - if PlayerInfo.Playerinfo[3].Enabled then - SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3); - end; - end; - - if PlayersPlay = 3 then begin - if PlayerInfo.Playerinfo[0].Enabled then - SingDrawOscilloscope(75 + 10*ScreenX, 95, 100, 20, 0); - if PlayerInfo.Playerinfo[1].Enabled then - SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); - if PlayerInfo.Playerinfo[2].Enabled then - SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); - end; - - if PlayersPlay = 6 then begin - if ScreenAct = 1 then begin - if PlayerInfo.Playerinfo[0].Enabled then - SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0); - if PlayerInfo.Playerinfo[1].Enabled then - SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); - if PlayerInfo.Playerinfo[2].Enabled then - SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); - end; - if ScreenAct = 2 then begin - if PlayerInfo.Playerinfo[3].Enabled then - SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3); - if PlayerInfo.Playerinfo[4].Enabled then - SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4); - if PlayerInfo.Playerinfo[5].Enabled then - SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5); - end; - end; - - end; - -// resize the notes according to the difficulty level - case Ini.Difficulty of - 0: - begin - NotesH := 11; // 9 - NotesW := 6; // 5 - end; - 1: - begin - NotesH := 8; // 7 - NotesW := 4; // 4 - end; - 2: - begin - NotesH := 5; - NotesW := 3; - end; - end; - - if (DLLMAn.Selected.ShowNotes And DLLMan.Selected.LoadSong) then - begin - if (PlayersPlay = 1) And PlayerInfo.Playerinfo[0].Enabled then begin - SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 0, 15); - SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15); - SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 0, 15); - end; - - if (PlayersPlay = 2) then begin - if PlayerInfo.Playerinfo[0].Enabled then - begin - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 0, 15); - SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15); - SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 0, 15); - end; - if PlayerInfo.Playerinfo[1].Enabled then - begin - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 1, 15); - SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15); - SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 1, 15); - end; - - end; - - if PlayersPlay = 3 then begin - NotesW := NotesW * 0.8; - NotesH := NotesH * 0.8; - - if PlayerInfo.Playerinfo[0].Enabled then - begin - SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 0, 12); - SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12); - SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 0, 12); - end; - - if PlayerInfo.Playerinfo[1].Enabled then - begin - SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 1, 12); - SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 12); - SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 1, 12); - end; - - if PlayerInfo.Playerinfo[2].Enabled then - begin - SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 2, 12); - SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 12); - SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 2, 12); - end; - end; - - if PlayersPlay = 4 then begin - if ScreenAct = 1 then begin - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 0, 15); - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 1, 15); - end; - if ScreenAct = 2 then begin - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 2, 15); - SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 3, 15); - end; - - SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15); - SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15); - - if ScreenAct = 1 then begin - SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 0, 15); - SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 1, 15); - end; - if ScreenAct = 2 then begin - SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 2, 15); - SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 3, 15); - end; - end; - - if PlayersPlay = 6 then begin - NotesW := NotesW * 0.8; - NotesH := NotesH * 0.8; - - if ScreenAct = 1 then begin - SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 0, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 1, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 2, 12); - end; - if ScreenAct = 2 then begin - SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 3, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 4, 12); - SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 5, 12); - end; - - SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12); - SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 12); - SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 12); - - if ScreenAct = 1 then begin - SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 0, 12); - SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 1, 12); - SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 2, 12); - end; - if ScreenAct = 2 then begin - SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 3, 12); - SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 4, 12); - SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 5, 12); - end; - end; - end; - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); -end; - - -{//SingBar Mod -procedure SingDrawSingbar(X, Y, W, H: real; Percent: integer); -var - R: Real; - G: Real; - B: Real; - A: cardinal; - I: Integer; - -begin; - - //SingBar Background - glColor4f(1, 1, 1, 0.8); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Back.TexNum); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(X, Y); - glTexCoord2f(0, 1); glVertex2f(X, Y+H); - glTexCoord2f(1, 1); glVertex2f(X+W, Y+H); - glTexCoord2f(1, 0); glVertex2f(X+W, Y); - glEnd; - - //SingBar coloured Bar - Case Percent of - 0..22: begin - R := 1; - G := 0; - B := 0; - end; - 23..42: begin - R := 1; - G := ((Percent-23)/100)*5; - B := 0; - end; - 43..57: begin - R := 1; - G := 1; - B := 0; - end; - 58..77: begin - R := 1-(Percent - 58)/100*5; - G := 1; - B := 0; - end; - 78..99: begin - R := 0; - G := 1; - B := 0; - end; - End; //Case - - glColor4f(R, G, B, 1); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Bar.TexNum); - //Size= Player[PlayerNum].ScorePercent of W - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(X, Y); - glTexCoord2f(0, 1); glVertex2f(X, Y+H); - glTexCoord2f(1, 1); glVertex2f(X+(W/100 * (Percent +1)), Y+H); - glTexCoord2f(1, 0); glVertex2f(X+(W/100 * (Percent +1)), Y); - glEnd; - - //SingBar Front - glColor4f(1, 1, 1, 0.6); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Front.TexNum); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(X, Y); - glTexCoord2f(0, 1); glVertex2f(X, Y+H); - glTexCoord2f(1, 1); glVertex2f(X+W, Y+H); - glTexCoord2f(1, 0); glVertex2f(X+W, Y); - glEnd; -end; -//end Singbar Mod - -//PhrasenBonus - Line Bonus Pop Up -procedure SingDrawLineBonus( const X, Y: Single; Color: TRGB; Alpha: Single; Text: string; Age: Integer); -var -Length, X2: Real; //Length of Text -Size: Integer; //Size of Popup -begin -if Alpha <> 0 then -begin - -//Set Font Propertys -SetFontStyle(2); //Font: Outlined1 -if Age < 5 then SetFontSize(Age + 1) else SetFontSize(6); -SetFontItalic(False); - -//Check Font Size -Length := glTextWidth ( PChar(Text)) + 3; //Little Space for a Better Look ^^ - -//Text -SetFontPos (X + 50 - (Length / 2), Y + 12); //Position - - -if Age < 5 then Size := Age * 10 else Size := 50; - - //Draw Background - //glColor4f(Color.R, Color.G, Color.B, Alpha); //Set Color - glColor4f(1, 1, 1, Alpha); - - - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - - //New Method, Not Variable - glBindTexture(GL_TEXTURE_2D, Tex_SingLineBonusBack[2].TexNum); - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(X + 50 - Size, Y + 25 - (Size/2)); - glTexCoord2f(0, 1); glVertex2f(X + 50 - Size, Y + 25 + (Size/2)); - glTexCoord2f(1, 1); glVertex2f(X + 50 + Size, Y + 25 + (Size/2)); - glTexCoord2f(1, 0); glVertex2f(X + 50 + Size, Y + 25 - (Size/2)); - glEnd; - - glColor4f(1, 1, 1, Alpha); //Set Color - //Draw Text - glPrint (PChar(Text)); -end; -end; -//PhrasenBonus - Line Bonus Mod} - -// Draw Note Bars for Editor -//There are 11 Resons for a new Procdedure: (nice binary :D ) -// 1. It don't look good when you Draw the Golden Note Star Effect in the Editor -// 2. You can see the Freestyle Notes in the Editor SemiTransparent -// 3. Its easier and Faster then changing the old Procedure -procedure EditDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer); -var - Rec: TRecR; - Count: integer; - TempR: real; -begin - glColor3f(1, 1, 1); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - TempR := (Right-Left) / (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start); - with Lines[NrLines].Line[Lines[NrLines].Current] do begin - for Count := 0 to HighNote do begin - with Note[Count] do begin - - // Golden Note Patch - case NoteType of - ntFreestyle: glColor4f(1, 1, 1, 0.35); - ntNormal: glColor4f(1, 1, 1, 0.85); - ntGolden: Glcolor4f(1, 1, 0.3, 0.85); - end; // case - - - - // lewa czesc - left part - Rec.Left := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX; - Rec.Right := Rec.Left + NotesW; - Rec.Top := Top - (Tone-BaseNote)*Space/2 - NotesH; - Rec.Bottom := Rec.Top + 2 * NotesH; - glBindTexture(GL_TEXTURE_2D, Tex_Left[Color].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; - - // srodkowa czesc - 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_Mid[Color].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; - - // prawa czesc - right part - Rec.Left := Rec.Right; - Rec.Right := Rec.Right + NotesW; - - glBindTexture(GL_TEXTURE_2D, Tex_Right[Color].TexNum); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top); - glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom); - glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom); - glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top); - glEnd; - - end; // with - end; // for - end; // with - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); -end; - -procedure SingDrawTimeBar(); -var x,y: real; - width, height: real; - lTmp : real; -begin - x := Theme.Sing.StaticTimeProgress.x; - y := Theme.Sing.StaticTimeProgress.y; - - width := Theme.Sing.StaticTimeProgress.w; - height := Theme.Sing.StaticTimeProgress.h; - - glColor4f(Theme.Sing.StaticTimeProgress.ColR, - Theme.Sing.StaticTimeProgress.ColG, - Theme.Sing.StaticTimeProgress.ColB, 1); //Set Color - - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - - glBindTexture(GL_TEXTURE_2D, Tex_TimeProgress.TexNum); - - glBegin(GL_QUADS); - try - glTexCoord2f(0, 0); - glVertex2f(x,y); - - if ( LineState.CurrentTime > 0 ) AND - ( LineState.TotalTime > 0 ) THEN - BEGIN - lTmp := LineState.CurrentTime/LineState.TotalTime; - glTexCoord2f((width*LineState.CurrentTime/LineState.TotalTime)/8, 0); - glVertex2f(x+width*LineState.CurrentTime/LineState.TotalTime, y); - - glTexCoord2f((width*LineState.CurrentTime/LineState.TotalTime)/8, 1); - glVertex2f(x+width*LineState.CurrentTime/LineState.TotalTime, y+height); - END; - - glTexCoord2f(0, 1); - glVertex2f(x, y+height); - finally - glEnd; - end; - - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - glcolor4f(1,1,1,1); -end; - -end. - +unit UDraw; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses UThemes, + ModiSDK, + UGraphicClasses; + +procedure SingDraw; +procedure SingModiDraw (PlayerInfo: TPlayerInfo); +procedure SingDrawBackground; +procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer); +procedure SingDrawNoteLines(Left, Top, Right: real; Space: integer); +procedure SingDrawBeatDelimeters(Left, Top, Right: real; NrLines: integer); +procedure SingDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer); +procedure SingDrawPlayerLine(X, Y, W: real; NrGracza: integer; Space: integer); +procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, NrGracza: integer; Space: integer); + +// TimeBar +procedure SingDrawTimeBar(); + +//Draw Editor NoteLines +procedure EditDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer); + + +type + TRecR = record + Top: real; + Left: real; + Right: real; + Bottom: real; + + Width: real; + WMid: real; + Height: real; + HMid: real; + + Mid: real; + end; + +var + NotesW: real; + NotesH: real; + Starfr: integer; + StarfrG: integer; + + //SingBar + TickOld: cardinal; + TickOld2:cardinal; + +const + Przedz = 32; + +implementation + +uses + OpenGL12, + UGraphic, + SysUtils, + UMusic, + URecord, + ULog, + UScreenSing, + UScreenSingModi, + ULyrics, + UMain, + TextGL, + UTexture, + UDrawTexture, + UIni, + Math, + UDLLManager; + +procedure SingDrawBackground; +var + Rec: TRecR; + TexRec: TRecR; +begin + if (ScreenSing.Tex_Background.TexNum > 0) then begin + + glClearColor (1, 1, 1, 1); + glColor4f (1, 1, 1, 1); + + if (Ini.MovieSize <= 1) then //HalfSize BG + begin + (* half screen + gradient *) + Rec.Top := 110; // 80 + Rec.Bottom := Rec.Top + 20; + Rec.Left := 0; + Rec.Right := 800; + + TexRec.Top := (Rec.Top / 600) * ScreenSing.Tex_Background.TexH; + TexRec.Bottom := (Rec.Bottom / 600) * ScreenSing.Tex_Background.TexH; + TexRec.Left := 0; + TexRec.Right := ScreenSing.Tex_Background.TexW; + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, ScreenSing.Tex_Background.TexNum); + glEnable(GL_BLEND); + glBegin(GL_QUADS); + (* gradient draw *) + (* top *) + glColor4f(1, 1, 1, 0); + glTexCoord2f(TexRec.Right, TexRec.Top); glVertex2f(Rec.Right, Rec.Top); + glTexCoord2f(TexRec.Left, TexRec.Top); glVertex2f(Rec.Left, Rec.Top); + glColor4f(1, 1, 1, 1); + glTexCoord2f(TexRec.Left, TexRec.Bottom); glVertex2f(Rec.Left, Rec.Bottom); + glTexCoord2f(TexRec.Right, TexRec.Bottom); glVertex2f(Rec.Right, Rec.Bottom); + (* mid *) + Rec.Top := Rec.Bottom; + Rec.Bottom := 490 - 20; // 490 - 20 + TexRec.Top := TexRec.Bottom; + TexRec.Bottom := (Rec.Bottom / 600) * ScreenSing.Tex_Background.TexH; + glTexCoord2f(TexRec.Left, TexRec.Top); glVertex2f(Rec.Left, Rec.Top); + glTexCoord2f(TexRec.Left, TexRec.Bottom); glVertex2f(Rec.Left, Rec.Bottom); + glTexCoord2f(TexRec.Right, TexRec.Bottom); glVertex2f(Rec.Right, Rec.Bottom); + glTexCoord2f(TexRec.Right, TexRec.Top); glVertex2f(Rec.Right, Rec.Top); + (* bottom *) + Rec.Top := Rec.Bottom; + Rec.Bottom := 490; // 490 + TexRec.Top := TexRec.Bottom; + TexRec.Bottom := (Rec.Bottom / 600) * ScreenSing.Tex_Background.TexH; + glTexCoord2f(TexRec.Right, TexRec.Top); glVertex2f(Rec.Right, Rec.Top); + glTexCoord2f(TexRec.Left, TexRec.Top); glVertex2f(Rec.Left, Rec.Top); + glColor4f(1, 1, 1, 0); + glTexCoord2f(TexRec.Left, TexRec.Bottom); glVertex2f(Rec.Left, Rec.Bottom); + glTexCoord2f(TexRec.Right, TexRec.Bottom); glVertex2f(Rec.Right, Rec.Bottom); + + glEnd; + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + end + else //Full Size BG + begin + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, ScreenSing.Tex_Background.TexNum); + //glEnable(GL_BLEND); + glBegin(GL_QUADS); + + glTexCoord2f(0, 0); glVertex2f(0, 0); + glTexCoord2f(0, ScreenSing.Tex_Background.TexH); glVertex2f(0, 600); + glTexCoord2f( ScreenSing.Tex_Background.TexW, ScreenSing.Tex_Background.TexH); glVertex2f(800, 600); + glTexCoord2f( ScreenSing.Tex_Background.TexW, 0); glVertex2f(800, 0); + + glEnd; + glDisable(GL_TEXTURE_2D); + //glDisable(GL_BLEND); + end; + end; +end; + +procedure SingDrawOscilloscope(X, Y, W, H: real; NrSound: integer); +var + SampleIndex: integer; + Sound: TCaptureBuffer; + MaxX, MaxY: real; +begin; + Sound := AudioInputProcessor.Sound[NrSound]; + + // Log.LogStatus('Oscilloscope', 'SingDraw'); + glColor3f(Skin_OscR, Skin_OscG, Skin_OscB); + {if (ParamStr(1) = '-black') or (ParamStr(1) = '-fsblack') then + glColor3f(1, 1, 1); } + + MaxX := W-1; + MaxY := (H-1) / 2; + + glBegin(GL_LINE_STRIP); + for SampleIndex := 0 to High(Sound.BufferArray) do + begin + glVertex2f(X + MaxX * SampleIndex/High(Sound.BufferArray), + Y + MaxY * (1 - Sound.BufferArray[SampleIndex]/-Low(Smallint))); + end; + glEnd; +end; + + + +procedure SingDrawNoteLines(Left, Top, Right: real; Space: integer); +var + Count: integer; +begin + glEnable(GL_BLEND); + glColor4f(Skin_P1_LinesR, Skin_P1_LinesG, Skin_P1_LinesB, 0.4); + glBegin(GL_LINES); + for Count := 0 to 9 do begin + glVertex2f(Left, Top + Count * Space); + glVertex2f(Right, Top + Count * Space); + end; + glEnd; + glDisable(GL_BLEND); +end; + +procedure SingDrawBeatDelimeters(Left, Top, Right: real; NrLines: integer); +var + Count: integer; + TempR: real; +begin + TempR := (Right-Left) / (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start); + glEnable(GL_BLEND); + glBegin(GL_LINES); + for Count := Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start to Lines[NrLines].Line[Lines[NrLines].Current].End_ do begin + if (Count mod Lines[NrLines].Resolution) = Lines[NrLines].NotesGAP then + glColor4f(0, 0, 0, 1) + else + glColor4f(0, 0, 0, 0.3); + glVertex2f(Left + TempR * (Count - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start), Top); + glVertex2f(Left + TempR * (Count - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start), Top + 135); + end; + glEnd; + glDisable(GL_BLEND); +end; + +// draw blank Notebars +procedure SingDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer); +var + Rec: TRecR; + Count: integer; + TempR: real; + R,G,B: real; + + PlayerNumber: Integer; + + GoldenStarPos : real; + + lTmpA , + lTmpB : real; +begin +// We actually don't have a playernumber in this procedure, it should reside in NrLines - but it's always set to zero +// 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 + + PlayerNumber := NrLines + 1; // Player 1 is 0 + NrLines := 0; + +// exploit done + + glColor3f(1, 1, 1); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + lTmpA := (Right-Left); + lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start); + + if ( lTmpA > 0 ) AND + ( lTmpB > 0 ) THEN + begin + TempR := lTmpA / lTmpB; + end + else + begin + TempR := 0; + end; + + + with Lines[NrLines].Line[Lines[NrLines].Current] do begin + for Count := 0 to HighNote do begin + with Note[Count] do 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 + end; // case + end //Else all Notes same Color + else + glColor4f(1, 1, 1, 1); // We set alpha to 1, cause we can control the transparency through the png itself + // Czesci == teil, element == piece, element | koniec == end / ending + // lewa czesc - left part + Rec.Left := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX; + Rec.Right := Rec.Left + NotesW; + Rec.Top := Top - (Tone-BaseNote)*Space/2 - NotesH; + Rec.Bottom := Rec.Top + 2 * NotesH; + glBindTexture(GL_TEXTURE_2D, Tex_plain_Left[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; + + //We keep the postion of the top left corner b4 it's overwritten + GoldenStarPos := Rec.Left; + //done + + // srodkowa czesc - 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; // Dlugosc == length + + 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; + + // prawa czesc - 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; + + // Golden Star Patch + if (NoteType = ntGolden) AND (Ini.EffectSing=1) then + begin + GoldenRec.SaveGoldenStarsRec(GoldenStarPos, Rec.Top, Rec.Right, Rec.Bottom); + end; + + end; // if not FreeStyle + end; // with + end; // for + end; // with + + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); +end; + + +// draw sung notes +procedure SingDrawPlayerLine(X, Y, W: real; NrGracza: integer; Space: integer); +var + TempR: real; + Rec: TRecR; + N: integer; + R: real; + G: real; + B: real; + A: real; + NotesH2: real; + begin +// Log.LogStatus('Player notes', 'SingDraw'); + +// if NrGracza = 0 then LoadColor(R, G, B, 'P1Light') +// else LoadColor(R, G, B, 'P2Light'); + +// R := 71/255; +// G := 175/255; +// B := 247/255; + + glColor3f(1, 1, 1); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + +//// if Player[NrGracza].IlNut > 0 then + begin + TempR := W / (Lines[0].Line[Lines[0].Current].End_ - Lines[0].Line[Lines[0].Current].Note[0].Start); + for N := 0 to Player[NrGracza].HighNote do + begin + with Player[NrGracza].Note[N] do + begin + // Left part of note + Rec.Left := X + (Start-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR + 0.5 + 10*ScreenX; + Rec.Right := Rec.Left + NotesW; + + // Draw it in half size, if not hit + if Hit then + begin + NotesH2 := NotesH + end + else + begin + NotesH2 := int(NotesH * 0.65); + end; + + Rec.Top := Y - (Tone-Lines[0].Line[Lines[0].Current].BaseNote)*Space/2 - NotesH2; + Rec.Bottom := Rec.Top + 2 *NotesH2; + + // draw the left part + glColor3f(1, 1, 1); + glBindTexture(GL_TEXTURE_2D, Tex_Left[NrGracza+1].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; + + // Middle part of the note + Rec.Left := Rec.Right; + Rec.Right := X + (Start+Length-Lines[0].Line[Lines[0].Current].Note[0].Start) * TempR - NotesW - 0.5 + 10*ScreenX; + + // (nowe) - dunno + if (Start+Length-1 = LineState.CurrentBeatD) then + Rec.Right := Rec.Right - (1-Frac(LineState.MidBeatD)) * TempR; + // the left note is more right than the right note itself, sounds weird - so we fix that xD + if Rec.Right <= Rec.Left then Rec.Right := Rec.Left; + + // draw the middle part + glBindTexture(GL_TEXTURE_2D, Tex_Mid[NrGracza+1].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; + glColor3f(1, 1, 1); + + // the right part of the note + Rec.Left := Rec.Right; + Rec.Right := Rec.Right + NotesW; + + glBindTexture(GL_TEXTURE_2D, Tex_Right[NrGracza+1].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; + + // Perfect note is stored + if Perfect and (Ini.EffectSing=1) then + begin + A := 1 - 2*(LineState.CurrentTime - GetTimeFromBeat(Start+Length)); + if not (Start+Length-1 = LineState.CurrentBeatD) then + + //Star animation counter + //inc(Starfr); + //Starfr := Starfr mod 128; + GoldenRec.SavePerfectNotePos(Rec.Left, Rec.Top); + end; + end; // with + end; // for + // eigentlich brauchen wir hier einen vergleich, um festzustellen, ob wir mit + // singen schon weiter wären, als bei Rec.Right, _auch, wenn nicht gesungen wird_ + // English Translation: + // actually we need a compare here, to determine if the singing process is ahead Rec.Right + // even if there is no singing + + + // passing on NrGracza... hope this is really something like the player-number, not only + // some kind of weird index into a colour-table + + if (Ini.EffectSing=1) then + GoldenRec.GoldenNoteTwinkle(Rec.Top,Rec.Bottom,Rec.Right, NrGracza); + end; // if +end; + +//draw Note glow +procedure SingDrawPlayerBGLine(Left, Top, Right: real; NrLines, NrGracza: integer; Space: integer); +var + Rec: TRecR; + Count: integer; + TempR: real; + R,G,B: real; + X1, X2, X3, X4: real; + W, H: real; + + lTmpA , + lTmpB : real; +begin + if (Player[NrGracza].ScoreTotalI >= 0) then begin + glColor4f(1, 1, 1, sqrt((1+sin( AudioPlayback.Position * 3))/4)/ 2 + 0.5 ); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + + lTmpA := (Right-Left); + lTmpB := (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start); + + + if ( lTmpA > 0 ) AND + ( lTmpB > 0 ) THEN + begin + TempR := lTmpA / lTmpB; + end + else + begin + TempR := 0; + end; + + with Lines[NrLines].Line[Lines[NrLines].Current] do begin + for Count := 0 to HighNote do begin + with Note[Count] do begin + if NoteType <> ntFreestyle then begin + // begin: 14, 20 + // easy: 6, 11 + W := NotesW * 2 + 2; + H := NotesH * 1.5 + 3.5; + + X2 := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX + 4; // wciecie + X1 := X2-W; + + X3 := (Start+Length-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left - 0.5 + 10*ScreenX - 4; // wciecie + X4 := X3+W; + + // left + Rec.Left := X1; + Rec.Right := X2; + Rec.Top := Top - (Tone-BaseNote)*Space/2 - H; + Rec.Bottom := Rec.Top + 2 * H; + + glBindTexture(GL_TEXTURE_2D, Tex_BG_Left[NrGracza+1].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; + + + // srodkowa czesc + Rec.Left := X2; + Rec.Right := X3; + + glBindTexture(GL_TEXTURE_2D, Tex_BG_Mid[NrGracza+1].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; + + // prawa czesc + Rec.Left := X3; + Rec.Right := X4; + + glBindTexture(GL_TEXTURE_2D, Tex_BG_Right[NrGracza+1].TexNum); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top); + glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom); + glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom); + glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top); + glEnd; + end; // if not FreeStyle + end; // with + end; // for + end; // with 1 + + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + end; +end; + +procedure SingDraw; +var + Count: integer; + Pet2: integer; + TempR: real; + Rec: TRecR; + TexRec: TRecR; + NR: TRecR; + FS: real; + BarFrom: integer; + BarAlpha: real; + BarWspol: real; + TempCol: real; + Tekst: string; + PetCz: integer; + +begin + // positions + if Ini.SingWindow = 0 then + begin + NR.Left := 120; + end + else + begin + NR.Left := 20; + end; + + NR.Right := 780; + + NR.Width := NR.Right - NR.Left; + NR.WMid := NR.Width / 2; + NR.Mid := NR.Left + NR.WMid; + + // background //BG Fullsize Mod + //SingDrawBackground; + + //TimeBar mod + SingDrawTimeBar(); + //eoa TimeBar mod + + // rysuje paski pod nutami + if (PlayersPlay = 1) and (Ini.NoteLines = 1) 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); + 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); + end; + + // Draw Lyrics + ScreenSing.Lyrics.Draw(LineState.MidBeat); + + // todo: Lyrics +(* // rysuje pasek, podpowiadajacy poczatek spiwania w scenie + FS := 1.3; + BarFrom := Lines[0].Line[Lines[0].Current].StartNote - Lines[0].Line[Lines[0].Current].Start; + if BarFrom > 40 then BarFrom := 40; + if (Lines[0].Line[Lines[0].Current].StartNote - Lines[0].Line[Lines[0].Current].Start > 8) and // dluga przerwa //16->12 for more help bars and then 12->8 for even more + (Lines[0].Line[Lines[0].Current].StartNote - LineState.MidBeat > 0) and // przed tekstem + (Lines[0].Line[Lines[0].Current].StartNote - LineState.MidBeat < 40) then begin // ale nie za wczesnie + BarWspol := (LineState.MidBeat - (Lines[0].Line[Lines[0].Current].StartNote - BarFrom)) / BarFrom; + Rec.Left := NR.Left + BarWspol * +// (NR.WMid - Lines[0].Line[Lines[0].Current].LyricWidth / 2 * FS - 50); + (ScreenSing.LyricMain.ClientX - NR.Left - 50) + 10*ScreenX; + Rec.Right := Rec.Left + 50; + Rec.Top := Skin_LyricsT + 3; + Rec.Bottom := Rec.Top + 33;//SingScreen.LyricMain.Size * 3; +{ // zapalanie + BarAlpha := (BarWspol*10) * 0.5; + if BarAlpha > 0.5 then BarAlpha := 0.5; + + // gaszenie + if BarWspol > 0.95 then BarAlpha := 0.5 * (1 - (BarWspol - 0.95) * 20);}{ + + //Change fuer Crazy Joker + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, Tex_Lyric_Help_Bar.TexNum); + glBegin(GL_QUADS); + glColor4f(1, 1, 1, 0); + glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top); + glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom); + glColor4f(1, 1, 1, 0.5); + glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom); + glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top); + glEnd; + glDisable(GL_BLEND); + + end; } +*) + // oscilloscope + if Ini.Oscilloscope = 1 then begin + if PlayersPlay = 1 then + SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); + + if PlayersPlay = 2 then begin + SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); + SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); + end; + + if PlayersPlay = 4 then begin + if ScreenAct = 1 then begin + SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); + SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); + end; + if ScreenAct = 2 then begin + SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2); + SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3); + end; + end; + + if PlayersPlay = 3 then begin + SingDrawOscilloscope(75 + 10*ScreenX, 95, 100, 20, 0); + SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); + SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); + end; + + if PlayersPlay = 6 then begin + if ScreenAct = 1 then begin + SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0); + SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); + SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); + end; + if ScreenAct = 2 then begin + SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3); + SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4); + SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5); + end; + end; + + end; + +// Set the note heights according to the difficulty level + case Ini.Difficulty of + 0: + begin + NotesH := 11; // 9 + NotesW := 6; // 5 + end; + 1: + begin + NotesH := 8; // 7 + NotesW := 4; // 4 + end; + 2: + begin + NotesH := 5; + NotesW := 3; + end; + end; + +// Draw the Notes + if PlayersPlay = 1 then begin + SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 0, 15); // Background glow - colorized in playercolor + SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15); // Plain unsung notes - colorized in playercolor + SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 0, 15); // imho the sung notes + end; + + if (PlayersPlay = 2) then begin + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 0, 15); + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 1, 15); + + SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15); + SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 1, 15); + + SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 0, 15); + SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 1, 15); + end; + + if PlayersPlay = 3 then begin + NotesW := NotesW * 0.8; + NotesH := NotesH * 0.8; + + SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 0, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 1, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 2, 12); + + SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12); + SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 1, 12); + SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 2, 12); + + SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 0, 12); + SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 1, 12); + SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 2, 12); + end; + + if PlayersPlay = 4 then begin + if ScreenAct = 1 then begin + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 0, 15); + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 1, 15); + end; + if ScreenAct = 2 then begin + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 2, 15); + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 3, 15); + end; + + if ScreenAct = 1 then begin + SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15); + SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 1, 15); + end; + if ScreenAct = 2 then begin + SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 2, 15); + SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 3, 15); + end; + + if ScreenAct = 1 then begin + SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 0, 15); + SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 1, 15); + end; + if ScreenAct = 2 then begin + SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 2, 15); + SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 3, 15); + end; + end; + + if PlayersPlay = 6 then begin + NotesW := NotesW * 0.8; + NotesH := NotesH * 0.8; + + if ScreenAct = 1 then begin + SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 0, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 1, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 2, 12); + end; + if ScreenAct = 2 then begin + SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 3, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 4, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 5, 12); + end; + + if ScreenAct = 1 then begin + SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12); + SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 1, 12); + SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 2, 12); + end; + if ScreenAct = 2 then begin + SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 3, 12); + SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 4, 12); + SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 5, 12); + end; + + if ScreenAct = 1 then begin + SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 0, 12); + SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 1, 12); + SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 2, 12); + end; + if ScreenAct = 2 then begin + SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 3, 12); + SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 4, 12); + SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 5, 12); + end; + end; + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); +end; + +// q'n'd for using the game mode dll's +procedure SingModiDraw (PlayerInfo: TPlayerInfo); +var + Count: integer; + Pet2: integer; + TempR: real; + Rec: TRecR; + TexRec: TRecR; + NR: TRecR; + FS: real; + BarFrom: integer; + BarAlpha: real; + BarWspol: real; + TempCol: real; + Tekst: string; + PetCz: integer; +begin + // positions + if Ini.SingWindow = 0 then begin + NR.Left := 120; + end else begin + NR.Left := 20; + end; + + NR.Right := 780; + NR.Width := NR.Right - NR.Left; + NR.WMid := NR.Width / 2; + NR.Mid := NR.Left + NR.WMid; + + // time bar + SingDrawTimeBar(); + + if DLLMan.Selected.ShowNotes then + begin + if PlayersPlay = 1 then + SingDrawNoteLines(Nr.Left + 10*ScreenX, Skin_P2_NotesB - 105, Nr.Right + 10*ScreenX, 15); + if (PlayersPlay = 2) or (PlayersPlay = 4) 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); + end; + + if (PlayersPlay = 3) or (PlayersPlay = 6) 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); + end; + end; + + // Draw Lyrics + ScreenSingModi.Lyrics.Draw(LineState.MidBeat); + + // todo: Lyrics +{ // rysuje pasek, podpowiadajacy poczatek spiwania w scenie + FS := 1.3; + BarFrom := Lines[0].Line[Lines[0].Current].StartNote - Lines[0].Line[Lines[0].Current].Start; + if BarFrom > 40 then BarFrom := 40; + if (Lines[0].Line[Lines[0].Current].StartNote - Lines[0].Line[Lines[0].Current].Start > 8) and // dluga przerwa //16->12 for more help bars and then 12->8 for even more + (Lines[0].Line[Lines[0].Current].StartNote - LineState.MidBeat > 0) and // przed tekstem + (Lines[0].Line[Lines[0].Current].StartNote - LineState.MidBeat < 40) then begin // ale nie za wczesnie + BarWspol := (LineState.MidBeat - (Lines[0].Line[Lines[0].Current].StartNote - BarFrom)) / BarFrom; + Rec.Left := NR.Left + BarWspol * (ScreenSingModi.LyricMain.ClientX - NR.Left - 50) + 10*ScreenX; + Rec.Right := Rec.Left + 50; + Rec.Top := Skin_LyricsT + 3; + Rec.Bottom := Rec.Top + 33;//SingScreen.LyricMain.Size * 3; + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, Tex_Lyric_Help_Bar.TexNum); + glBegin(GL_QUADS); + glColor4f(1, 1, 1, 0); + glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top); + glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom); + glColor4f(1, 1, 1, 0.5); + glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom); + glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top); + glEnd; + glDisable(GL_BLEND); + end; + } + + // oscilloscope | the thing that moves when you yell into your mic (imho) + if (((Ini.Oscilloscope = 1) AND (DLLMan.Selected.ShowRateBar_O)) AND (NOT DLLMan.Selected.ShowRateBar)) then begin + if PlayersPlay = 1 then + if PlayerInfo.Playerinfo[0].Enabled then + SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); + + if PlayersPlay = 2 then begin + if PlayerInfo.Playerinfo[0].Enabled then + SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); + if PlayerInfo.Playerinfo[1].Enabled then + SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); + end; + + if PlayersPlay = 4 then begin + if ScreenAct = 1 then begin + if PlayerInfo.Playerinfo[0].Enabled then + SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 0); + if PlayerInfo.Playerinfo[1].Enabled then + SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 1); + end; + if ScreenAct = 2 then begin + if PlayerInfo.Playerinfo[2].Enabled then + SingDrawOscilloscope(190 + 10*ScreenX, 55, 180, 40, 2); + if PlayerInfo.Playerinfo[3].Enabled then + SingDrawOscilloscope(425 + 10*ScreenX, 55, 180, 40, 3); + end; + end; + + if PlayersPlay = 3 then begin + if PlayerInfo.Playerinfo[0].Enabled then + SingDrawOscilloscope(75 + 10*ScreenX, 95, 100, 20, 0); + if PlayerInfo.Playerinfo[1].Enabled then + SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); + if PlayerInfo.Playerinfo[2].Enabled then + SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); + end; + + if PlayersPlay = 6 then begin + if ScreenAct = 1 then begin + if PlayerInfo.Playerinfo[0].Enabled then + SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 0); + if PlayerInfo.Playerinfo[1].Enabled then + SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 1); + if PlayerInfo.Playerinfo[2].Enabled then + SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 2); + end; + if ScreenAct = 2 then begin + if PlayerInfo.Playerinfo[3].Enabled then + SingDrawOscilloscope( 75 + 10*ScreenX, 95, 100, 20, 3); + if PlayerInfo.Playerinfo[4].Enabled then + SingDrawOscilloscope(370 + 10*ScreenX, 95, 100, 20, 4); + if PlayerInfo.Playerinfo[5].Enabled then + SingDrawOscilloscope(670 + 10*ScreenX, 95, 100, 20, 5); + end; + end; + + end; + +// resize the notes according to the difficulty level + case Ini.Difficulty of + 0: + begin + NotesH := 11; // 9 + NotesW := 6; // 5 + end; + 1: + begin + NotesH := 8; // 7 + NotesW := 4; // 4 + end; + 2: + begin + NotesH := 5; + NotesW := 3; + end; + end; + + if (DLLMAn.Selected.ShowNotes And DLLMan.Selected.LoadSong) then + begin + if (PlayersPlay = 1) And PlayerInfo.Playerinfo[0].Enabled then begin + SingDrawPlayerBGLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 0, 15); + SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15); + SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 0, 15); + end; + + if (PlayersPlay = 2) then begin + if PlayerInfo.Playerinfo[0].Enabled then + begin + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 0, 15); + SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15); + SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 0, 15); + end; + if PlayerInfo.Playerinfo[1].Enabled then + begin + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 1, 15); + SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15); + SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 1, 15); + end; + + end; + + if PlayersPlay = 3 then begin + NotesW := NotesW * 0.8; + NotesH := NotesH * 0.8; + + if PlayerInfo.Playerinfo[0].Enabled then + begin + SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 0, 12); + SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12); + SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 0, 12); + end; + + if PlayerInfo.Playerinfo[1].Enabled then + begin + SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 1, 12); + SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 12); + SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 1, 12); + end; + + if PlayerInfo.Playerinfo[2].Enabled then + begin + SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 2, 12); + SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 12); + SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 2, 12); + end; + end; + + if PlayersPlay = 4 then begin + if ScreenAct = 1 then begin + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 0, 15); + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 1, 15); + end; + if ScreenAct = 2 then begin + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Right - 20, 0, 2, 15); + SingDrawPlayerBGLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Right - 20, 0, 3, 15); + end; + + SingDrawLine(NR.Left + 20, Skin_P1_NotesB, NR.Right - 20, 0, 15); + SingDrawLine(NR.Left + 20, Skin_P2_NotesB, NR.Right - 20, 0, 15); + + if ScreenAct = 1 then begin + SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 0, 15); + SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 1, 15); + end; + if ScreenAct = 2 then begin + SingDrawPlayerLine(Nr.Left + 20, Skin_P1_NotesB, Nr.Width - 40, 2, 15); + SingDrawPlayerLine(Nr.Left + 20, Skin_P2_NotesB, Nr.Width - 40, 3, 15); + end; + end; + + if PlayersPlay = 6 then begin + NotesW := NotesW * 0.8; + NotesH := NotesH * 0.8; + + if ScreenAct = 1 then begin + SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 0, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 1, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 2, 12); + end; + if ScreenAct = 2 then begin + SingDrawPlayerBGLine(Nr.Left + 20, 120+95, Nr.Right - 20, 0, 3, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 245+95, Nr.Right - 20, 0, 4, 12); + SingDrawPlayerBGLine(Nr.Left + 20, 370+95, Nr.Right - 20, 0, 5, 12); + end; + + SingDrawLine(NR.Left + 20, 120+95, NR.Right - 20, 0, 12); + SingDrawLine(NR.Left + 20, 245+95, NR.Right - 20, 0, 12); + SingDrawLine(NR.Left + 20, 370+95, NR.Right - 20, 0, 12); + + if ScreenAct = 1 then begin + SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 0, 12); + SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 1, 12); + SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 2, 12); + end; + if ScreenAct = 2 then begin + SingDrawPlayerLine(Nr.Left + 20, 120+95, Nr.Width - 40, 3, 12); + SingDrawPlayerLine(Nr.Left + 20, 245+95, Nr.Width - 40, 4, 12); + SingDrawPlayerLine(Nr.Left + 20, 370+95, Nr.Width - 40, 5, 12); + end; + end; + end; + + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); +end; + + +{//SingBar Mod +procedure SingDrawSingbar(X, Y, W, H: real; Percent: integer); +var + R: Real; + G: Real; + B: Real; + A: cardinal; + I: Integer; + +begin; + + //SingBar Background + glColor4f(1, 1, 1, 0.8); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Back.TexNum); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(X, Y); + glTexCoord2f(0, 1); glVertex2f(X, Y+H); + glTexCoord2f(1, 1); glVertex2f(X+W, Y+H); + glTexCoord2f(1, 0); glVertex2f(X+W, Y); + glEnd; + + //SingBar coloured Bar + Case Percent of + 0..22: begin + R := 1; + G := 0; + B := 0; + end; + 23..42: begin + R := 1; + G := ((Percent-23)/100)*5; + B := 0; + end; + 43..57: begin + R := 1; + G := 1; + B := 0; + end; + 58..77: begin + R := 1-(Percent - 58)/100*5; + G := 1; + B := 0; + end; + 78..99: begin + R := 0; + G := 1; + B := 0; + end; + End; //Case + + glColor4f(R, G, B, 1); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Bar.TexNum); + //Size= Player[PlayerNum].ScorePercent of W + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(X, Y); + glTexCoord2f(0, 1); glVertex2f(X, Y+H); + glTexCoord2f(1, 1); glVertex2f(X+(W/100 * (Percent +1)), Y+H); + glTexCoord2f(1, 0); glVertex2f(X+(W/100 * (Percent +1)), Y); + glEnd; + + //SingBar Front + glColor4f(1, 1, 1, 0.6); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, Tex_SingBar_Front.TexNum); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(X, Y); + glTexCoord2f(0, 1); glVertex2f(X, Y+H); + glTexCoord2f(1, 1); glVertex2f(X+W, Y+H); + glTexCoord2f(1, 0); glVertex2f(X+W, Y); + glEnd; +end; +//end Singbar Mod + +//PhrasenBonus - Line Bonus Pop Up +procedure SingDrawLineBonus( const X, Y: Single; Color: TRGB; Alpha: Single; Text: string; Age: Integer); +var +Length, X2: Real; //Length of Text +Size: Integer; //Size of Popup +begin +if Alpha <> 0 then +begin + +//Set Font Propertys +SetFontStyle(2); //Font: Outlined1 +if Age < 5 then SetFontSize(Age + 1) else SetFontSize(6); +SetFontItalic(False); + +//Check Font Size +Length := glTextWidth ( PChar(Text)) + 3; //Little Space for a Better Look ^^ + +//Text +SetFontPos (X + 50 - (Length / 2), Y + 12); //Position + + +if Age < 5 then Size := Age * 10 else Size := 50; + + //Draw Background + //glColor4f(Color.R, Color.G, Color.B, Alpha); //Set Color + glColor4f(1, 1, 1, Alpha); + + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + + //New Method, Not Variable + glBindTexture(GL_TEXTURE_2D, Tex_SingLineBonusBack[2].TexNum); + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(X + 50 - Size, Y + 25 - (Size/2)); + glTexCoord2f(0, 1); glVertex2f(X + 50 - Size, Y + 25 + (Size/2)); + glTexCoord2f(1, 1); glVertex2f(X + 50 + Size, Y + 25 + (Size/2)); + glTexCoord2f(1, 0); glVertex2f(X + 50 + Size, Y + 25 - (Size/2)); + glEnd; + + glColor4f(1, 1, 1, Alpha); //Set Color + //Draw Text + glPrint (PChar(Text)); +end; +end; +//PhrasenBonus - Line Bonus Mod} + +// Draw Note Bars for Editor +//There are 11 Resons for a new Procdedure: (nice binary :D ) +// 1. It don't look good when you Draw the Golden Note Star Effect in the Editor +// 2. You can see the Freestyle Notes in the Editor SemiTransparent +// 3. Its easier and Faster then changing the old Procedure +procedure EditDrawLine(Left, Top, Right: real; NrLines: integer; Space: integer); +var + Rec: TRecR; + Count: integer; + TempR: real; +begin + glColor3f(1, 1, 1); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + TempR := (Right-Left) / (Lines[NrLines].Line[Lines[NrLines].Current].End_ - Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start); + with Lines[NrLines].Line[Lines[NrLines].Current] do begin + for Count := 0 to HighNote do begin + with Note[Count] do begin + + // Golden Note Patch + case NoteType of + ntFreestyle: glColor4f(1, 1, 1, 0.35); + ntNormal: glColor4f(1, 1, 1, 0.85); + ntGolden: Glcolor4f(1, 1, 0.3, 0.85); + end; // case + + + + // lewa czesc - left part + Rec.Left := (Start-Lines[NrLines].Line[Lines[NrLines].Current].Note[0].Start) * TempR + Left + 0.5 + 10*ScreenX; + Rec.Right := Rec.Left + NotesW; + Rec.Top := Top - (Tone-BaseNote)*Space/2 - NotesH; + Rec.Bottom := Rec.Top + 2 * NotesH; + glBindTexture(GL_TEXTURE_2D, Tex_Left[Color].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; + + // srodkowa czesc - 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_Mid[Color].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; + + // prawa czesc - right part + Rec.Left := Rec.Right; + Rec.Right := Rec.Right + NotesW; + + glBindTexture(GL_TEXTURE_2D, Tex_Right[Color].TexNum); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(Rec.Left, Rec.Top); + glTexCoord2f(0, 1); glVertex2f(Rec.Left, Rec.Bottom); + glTexCoord2f(1, 1); glVertex2f(Rec.Right, Rec.Bottom); + glTexCoord2f(1, 0); glVertex2f(Rec.Right, Rec.Top); + glEnd; + + end; // with + end; // for + end; // with + + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); +end; + +procedure SingDrawTimeBar(); +var x,y: real; + width, height: real; + lTmp : real; +begin + x := Theme.Sing.StaticTimeProgress.x; + y := Theme.Sing.StaticTimeProgress.y; + + width := Theme.Sing.StaticTimeProgress.w; + height := Theme.Sing.StaticTimeProgress.h; + + glColor4f(Theme.Sing.StaticTimeProgress.ColR, + Theme.Sing.StaticTimeProgress.ColG, + Theme.Sing.StaticTimeProgress.ColB, 1); //Set Color + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + + glBindTexture(GL_TEXTURE_2D, Tex_TimeProgress.TexNum); + + glBegin(GL_QUADS); + try + glTexCoord2f(0, 0); + glVertex2f(x,y); + + if ( LineState.CurrentTime > 0 ) AND + ( LineState.TotalTime > 0 ) THEN + BEGIN + lTmp := LineState.CurrentTime/LineState.TotalTime; + glTexCoord2f((width*LineState.CurrentTime/LineState.TotalTime)/8, 0); + glVertex2f(x+width*LineState.CurrentTime/LineState.TotalTime, y); + + glTexCoord2f((width*LineState.CurrentTime/LineState.TotalTime)/8, 1); + glVertex2f(x+width*LineState.CurrentTime/LineState.TotalTime, y+height); + END; + + glTexCoord2f(0, 1); + glVertex2f(x, y+height); + finally + glEnd; + end; + + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glcolor4f(1,1,1,1); +end; + +end. + diff --git a/Game/Code/Classes/ULyrics.pas b/Game/Code/Classes/ULyrics.pas index 505c69f9..b11b39e2 100644 --- a/Game/Code/Classes/ULyrics.pas +++ b/Game/Code/Classes/ULyrics.pas @@ -1,759 +1,749 @@ -unit ULyrics; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - -uses OpenGL12, - UTexture, - UThemes, - UMusic; - -type - TLyricWord = record - X: Real; // left corner - Width: Real; // width - Start: Cardinal; // start of the word in quarters (beats) - Length: Cardinal; // length of the word in quarters - Text: String; // text - Freestyle: Boolean; // is freestyle? - end; - ALyricWord = array of TLyricWord; - - PLyricLine = ^TLyricLine; - TLyricLine = record - Text: String; // text - Tex: glUInt; // texture of the text - Width: Real; // width - Size: Byte; // fontsize - Words: ALyricWord; // words in this line - CurWord: Integer; // current active word idx (only valid if line is active) - Start: Cardinal; // start of this line in quarters - Length: Cardinal; // length in quarters - HasFreestyle: Boolean; // one or more word are freestyle? - CountFreestyle: Integer; // how often there is a change from freestyle to non freestyle in this line - Players: Byte; // players that should sing that line (bitset, Player1: 1, Player2: 2, Player3: 4) - Done: Boolean; // is sentence already sung? - LastLine: Boolean; // is this the last line ob the song? - end; - - TLyricEngine = class - private - EoLastSentence: Real; // end of the previous sentence (in beats) - LastDrawBeat: Real; - UpperLine: TLyricLine; // first line displayed (top) - LowerLine: TLyricLine; // second lind displayed (bottom) - QueueLine: TLyricLine; // third line (queue and will be displayed when next line is finished) - PUpperLine, PLowerLine, PQueueLine: PLyricLine; - - IndicatorTex: TTexture; // texture for lyric indikator - BallTex: TTexture; // texture of the ball for the lyric effect - - inQueue: Boolean; // is line in queue - LCounter: Word; // line counter - - // duet mode - textures for player icons - PlayerIconTex: array[0..5] of // player idx - array [0..1] of // enabled disabled - TTexture; - - - //Some helper Procedures for Lyric Drawing - procedure DrawLyrics (Beat: Real); - procedure DrawLyricsLine(const X, W, Y: Real; Size: Byte; const Line: PLyricLine; Beat: Real); - procedure DrawPlayerIcon(const Player: Byte; const Enabled: Boolean; const X, Y, Size, Alpha: Real); - procedure DrawBall(const XBall, YBall, Alpha:Real); - - public - // positions, line specific settings - UpperLineX: Real; //X Start Pos of UpperLine - UpperLineW: Real; //Width of UpperLine with Icon(s) and Text - UpperLineY: Real; //Y Start Pos of UpperLine - UpperLineSize: Byte; //Max Size of Lyrics Text in UpperLine - - LowerLineX: Real; //X Start Pos of LowerLine - LowerLineW: Real; //Width of LowerLine with Icon(s) and Text - LowerLineY: Real; //Y Start Pos of LowerLine - LowerLineSize: Byte; //Max Size of Lyrics Text in LowerLine - - // display propertys - LineColor_en: TRGBA; //Color of Words in an Enabled Line - LineColor_dis: TRGBA; //Color of Words in a Disabled Line - LineColor_act: TRGBA; //Color of teh active Word - FontStyle: Byte; //Font for the Lyric Text - FontReSize: Boolean; //ReSize Lyrics if they don't fit Screen - - { // currently not used - FadeInEffect: Byte; //Effect for Line Fading in: 0: No Effect; 1: Fade Effect; 2: Move Upwards from Bottom to Pos - FadeOutEffect: Byte; //Effect for Line Fading out: 0: No Effect; 1: Fade Effect; 2: Move Upwards - } - - UseLinearFilter:Boolean; //Should Linear Tex Filter be used - - // song specific settings - BPM: Real; - Resolution: Integer; - - - // properties to easily read options of this class - property LineinQueue: Boolean read inQueue; // line in queue? - property LineCounter: Word read LCounter; // lines that were progressed so far (after last clear) - - Procedure AddLine(Line: PLine); // adds a line to the queue, if there is space - Procedure Draw (Beat: Real); // draw the current (active at beat) lyrics - - Procedure Clear (const cBPM: Real = 0; // clears all cached song specific information - const cResolution: Integer = 0); - - Constructor Create; overload; - Constructor Create(ULX,ULY,ULW,ULS,LLX,LLY,LLW,LLS:Real); overload; - Procedure LoadTextures; - Destructor Free; - end; - -implementation - -uses SysUtils, - USkins, - TextGL, - UGraphic, - UDisplay, - math, - UIni; - -//----------- -//Helper procs to use TRGB in Opengl ...maybe this should be somewhere else -//----------- -procedure glColorRGB(Color: TRGB); overload; -begin - glColor3f(Color.R, Color.G, Color.B); -end; - -procedure glColorRGB(Color: TRGB; Alpha: Real); overload; -begin - glColor4f(Color.R, Color.G, Color.B, Alpha); -end; - -procedure glColorRGB(Color: TRGBA); overload; -begin - glColor4f(Color.R, Color.G, Color.B, Color.A); -end; - -procedure glColorRGB(Color: TRGBA; Alpha: Real); overload; -begin - glColor4f(Color.R, Color.G, Color.B, Min(Color.A, Alpha)); -end; - - - -//--------------- -// Create - Constructor, just get Memory -//--------------- -Constructor TLyricEngine.Create; -begin - BPM := 0; - Resolution := 0; - LCounter := 0; - inQueue := False; - - UpperLine.Done := True; - LowerLine.Done := True; - QueueLine.Done := True; - PUpperline:=@UpperLine; - PLowerLine:=@LowerLine; - PQueueLine:=@QueueLine; - - UseLinearFilter := True; - {$IFDEF DARWIN} - // eddie: Getting range check error with NAN on OS X: - LastDrawBeat:=0; - {$ELSE} - LastDrawBeat:=NAN; - {$ENDIF} -end; - -Constructor TLyricEngine.Create(ULX,ULY,ULW,ULS,LLX,LLY,LLW,LLS:Real); -begin - Create; - UpperLineX := ULX; - UpperLineW := ULW; - UpperLineY := ULY; - UpperLineSize := Trunc(ULS); - - LowerLineX := LLX; - LowerLineW := LLW; - LowerLineY := LLY; - LowerLineSize := Trunc(LLS); - LoadTextures; -end; - - -//--------------- -// Free - Frees Memory -//--------------- -Destructor TLyricEngine.Free; -begin - -end; - -//--------------- -// Clear - Clears all cached Song specific Information -//--------------- -Procedure TLyricEngine.Clear (const cBPM: Real; const cResolution: Integer); -begin - BPM := cBPM; - Resolution := cResolution; - LCounter := 0; - inQueue := False; - - UpperLine.Done := True; - LowerLine.Done := True; - QueueLine.Done := True; - - PUpperline:=@UpperLine; - PLowerLine:=@LowerLine; - PQueueLine:=@QueueLine; - - {$IFDEF DARWIN} - // eddie: Getting range check error with NAN on OS X: - LastDrawBeat:=0; - {$ELSE} - LastDrawBeat:=NAN; - {$ENDIF} -end; - - -//--------------- -// LoadTextures - Load Player Textures and Create Lyric Textures -//--------------- -Procedure TLyricEngine.LoadTextures; -var - I: Integer; - - function CreateLineTex: glUint; - var - PTexData: Pointer; - begin - try - // get memory - GetMem(pTexData, 1024*64*4); - - // generate and bind Texture - glGenTextures(1, @Result); - glBindTexture(GL_TEXTURE_2D, Result); - - // get texture memeory - glTexImage2D(GL_TEXTURE_2D, 0, 4, 1024, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, pTexData); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - if UseLinearFilter then - begin - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - end; - - finally - // free unused memory - FreeMem(pTexData); - end; - end; -begin - - // lyric indicator (bar that indicates when the line start) - IndicatorTex := Texture.LoadTexture(Skin.GetTextureFileName('LyricHelpBar'), TEXTURE_TYPE_TRANSPARENT, $FF00FF); - - // ball for current word hover in ball effect - BallTex := Texture.LoadTexture(Skin.GetTextureFileName('Ball'), TEXTURE_TYPE_TRANSPARENT, 0); - - // duet mode: load player icon - For I := 0 to 5 do - begin - PlayerIconTex[I][0] := Texture.LoadTexture(Skin.GetTextureFileName('LyricIcon_P' + InttoStr(I+1)), TEXTURE_TYPE_TRANSPARENT, 0); - PlayerIconTex[I][1] := Texture.LoadTexture(Skin.GetTextureFileName('LyricIconD_P' + InttoStr(I+1)), TEXTURE_TYPE_TRANSPARENT, 0); - end; - - // create line textures - UpperLine.Tex := CreateLineTex; - LowerLine.Tex := CreateLineTex; - QueueLine.Tex := CreateLineTex; -end; - - -//--------------- -// AddLine - Adds LyricLine to queue -//--------------- -Procedure TLyricEngine.AddLine(Line: PLine); -var - LyricLine: PLyricLine; - countNotes: Cardinal; - Viewport: Array[0..3] of Integer; - - PosX: Real; - I: Integer; - - function CalcWidth(LyricLine: PLyricLine): Real; - begin - Result := glTextWidth(PChar(LyricLine.Text)); - - Result := Result + (LyricLine.CountFreestyle * 10); - - // if the line ends with a freestyle not, then leave the place to finish to draw the text italic - if (LyricLine.Words[High(LyricLine.Words)].Freestyle) then - Result := Result + 12; - end; -begin - // only add lines, if there is space - If not LineinQueue then - begin - // set pointer to line to write - - If (LineCounter = 0) then - LyricLine := PUpperLine - else if (LineCounter = 1) then - LyricLine := PLowerLine - else - begin - LyricLine := PQueueLine; - - //now there is a queued line - inQueue := True; - end; - end - else - begin // rotate lines (round-robin-like) - LyricLine := PUpperLine; - PUpperLine := PLowerLine; - PLowerLine := PQueueLine; - PQueueLine := LyricLine; - end; - - // sentence has notes? - If Line = nil then - begin - // reset all values, if the new line is nil (lines after the last line) - LyricLine.Start := 0; - LyricLine.Length := 0; - LyricLine.CurWord := -1; - LyricLine.LastLine := False; - LyricLine.Width := 0; - SetLength(LyricLine.Words, 0); - end - else if Length(Line.Note) > 0 then - begin - // copy values from SongLine to LyricLine - CountNotes := High(Line.Note); - LyricLine.Start := Line.Note[0].Start; - LyricLine.Length := Line.Note[CountNotes].Start + Line.Note[CountNotes].Length - LyricLine.Start; - LyricLine.CurWord := -1; - LyricLine.LastLine := Line.LastLine; - - // default values - set later - LyricLine.HasFreestyle := False; - LyricLine.CountFreestyle := 0; - LyricLine.Text := ''; - - // duet mode: players of that line - LyricLine.Players := 127; - - //copy words - SetLength(LyricLine.Words, CountNotes + 1); - For I := 0 to CountNotes do - begin - LyricLine.Words[I].Start := Line.Note[I].Start; - LyricLine.Words[I].Length := Line.Note[I].Length; - LyricLine.Words[I].Text := Line.Note[I].Text; - LyricLine.Words[I].Freestyle := Line.Note[I].NoteType = ntFreestyle; - - LyricLine.HasFreestyle := LyricLine.HasFreestyle OR LyricLine.Words[I].Freestyle; - LyricLine.Text := LyricLine.Text + LyricLine.Words[I].Text; - - if (I > 0) AND LyricLine.Words[I-1].Freestyle AND not LyricLine.Words[I].Freestyle then - Inc(LyricLine.CountFreestyle); - end; - - // set font params - SetFontStyle(FontStyle); - SetFontPos(0, 0); - LyricLine.Size := UpperLineSize; - SetFontSize(LyricLine.Size); - SetFontItalic(False); - glColor4f(1, 1, 1, 1); - - // change fontsize to fit the screen - LyricLine.Width := CalcWidth(LyricLine); - while (LyricLine.Width > UpperLineW) do - begin - Dec(LyricLine.Size); - - if (LyricLine.Size <=1) then - Break; - - SetFontSize(LyricLine.Size); - LyricLine.Width := CalcWidth(LyricLine); - end; - - // create LyricTexture - prepare OpenGL - glGetIntegerv(GL_VIEWPORT, @ViewPort); - glClearColor(0.0,0.0,0.0,0.0); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - glViewPort(0,0,800,600); - - // set word positions and line size - PosX := 0; - for I := 0 to High(LyricLine.Words) do - begin - with LyricLine.Words[I] do - begin - SetFontItalic(Freestyle); - - X := PosX; - - //Draw Lyrics - SetFontPos(PosX, 0); - glPrint(PChar(Text)); - - Width := glTextWidth(PChar(Text)); - if (I < High(LyricLine.Words)) AND Freestyle AND not LyricLine.Words[I+1].Freestyle then - Width := Width + 10 - else - if (I = High(LyricLine.Words)) AND Freestyle then - Width := Width + 12; - PosX := PosX + Width; - end; - end; - end - else - begin - // create LyricTexture - prepare OpenGL - glGetIntegerv(GL_VIEWPORT, @ViewPort); - glClearColor(0.0,0.0,0.0,0.0); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - glViewPort(0,0,800,600); - end; - - //for debugging, is this used anymore? - //Display.ScreenShot; - - //Copy to Texture - glEnable(GL_ALPHA); - glBindTexture(GL_TEXTURE_2D, LyricLine.Tex); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 600-64, 1024, 64, 0); - glDisable(GL_ALPHA); - - //Clear Buffer - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - - glViewPort(ViewPort[0], ViewPort[1], ViewPort[2], ViewPort[3]); - - //Increase the Counter - Inc(LCounter); -end; - - -//--------------- -// Draw - Procedure Draws Lyrics; Beat is curent Beat in Quarters -// Draw just manage the Lyrics, drawing is done by a call of DrawLyrics -//--------------- -Procedure TLyricEngine.Draw (Beat: Real); -begin - DrawLyrics(Beat); - LastDrawBeat := Beat; -end; - -//--------------- -// DrawLyrics(private) - Helper for Draw; main Drawing procedure -//--------------- -procedure TLyricEngine.DrawLyrics (Beat: Real); -begin - DrawLyricsLine(UpperLineX, UpperLineW, UpperlineY, 15, PUpperline, Beat); - DrawLyricsLine(LowerLineX, LowerLineW, LowerlineY, 15, PLowerline, Beat); -end; - -//--------------- -// DrawPlayerIcon(private) - Helper for Draw; Draws a Playericon -//--------------- -procedure TLyricEngine.DrawPlayerIcon(const Player: Byte; const Enabled: Boolean; const X, Y, Size, Alpha: Real); -var IEnabled: Byte; -begin - Case Enabled of - True: IEnabled := 0; - False: IEnabled := 1; - end; - - try - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, PlayerIconTex[Player][IEnabled].TexNum); - - glColor4f(1,1,1,Alpha); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(X, Y); - glTexCoord2f(0, 1); glVertex2f(X, Y + Size); - glTexCoord2f(1, 1); glVertex2f(X + Size, Y + Size); - glTexCoord2f(1, 0); glVertex2f(X + Size, Y); - glEnd; - - finally - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - end; -end; - -//--------------- -// DrawBall(private) - Helper for Draw; Draws the Ball over the LyricLine if needed -//--------------- -procedure TLyricEngine.DrawBall(const XBall, YBall, Alpha:Real); -begin - try - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, BallTex.TexNum); - - glColor4f(1,1,1, Alpha); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(XBall - 10, YBall); - glTexCoord2f(0, 1); glVertex2f(XBall - 10, YBall + 20); - glTexCoord2f(1, 1); glVertex2f(XBall + 10, YBall + 20); - glTexCoord2f(1, 0); glVertex2f(XBall + 10, YBall); - glEnd; - - finally - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - end; -end; - -//--------------- -// DrawLyricsLine(private) - Helper for Draw; Draws one LyricLine -//--------------- -procedure TLyricEngine.DrawLyricsLine(const X, W, Y: Real; Size: Byte; const Line: PLyricLine; Beat: Real); -var - CurWordStart, CurWordEnd: Real; // screen coordinates of current word and the rest of the sentence - FreestyleDiff: Integer; // difference between top and bottom coordiantes for freestyle lyrics - Progress: Real; // progress of singing the current word - LyricX: Real; // left - LyricX2: Real; // right - LyricY: Real; // top - LyricsHeight: Real; // height the lyrics are displayed - Alpha: Real; // alphalevel to fade out at end - - {// duet mode - IconSize: Real; // size of player icons - IconAlpha: Real; // alpha level of player icons - } -begin - // lines with a width lower than 0, have not to be draw - if Line^.Width <= 0 then - exit; - - // this is actually a bit more than the real font size - // it helps adjusting the "zoom-center" - LyricsHeight:=30.5 * (Line^.Size/10); - - { - // duet mode - IconSize := (2 * Size); - IconAlpha := Frac(Beat/(Resolution*4)); - - DrawPlayerIcon (0, True, X, Y + (42 - IconSize) / 2 , IconSize, IconAlpha); - DrawPlayerIcon (1, True, X + IconSize + 1, Y + (42 - IconSize) / 2, IconSize, IconAlpha); - DrawPlayerIcon (2, True, X + (IconSize + 1)*2, Y + (42 - IconSize) / 2, IconSize, IconAlpha); - } - - LyricX := X+W/2 - Line^.Width/2; - LyricX2 := LyricX + Line^.Width; - - // maybe center smaller lines - //LyricY := Y; - LyricY := Y + ((Size / Line.Size - 1) * LyricsHeight) / 2; - - Alpha := 1; - - // word in the sentence is active? - if (Line^.Start < Beat) then - begin - // if this line just got active, then CurWord is still -1 - // this means, we should try to make the first word active - // then we check if the current active word is still meant to be active - // if not, we proceed to the next word - if Line^.CurWord = -1 then - Line^.CurWord:=0; - - if (Line^.CurWord < High(Line^.Words)) AND (Beat >= (Line^.Words[Line^.CurWord + 1].Start)) then - Line^.CurWord:=Line^.CurWord+1; - - FreestyleDiff := 0; - - // last word of this line finished, but this line did not hide - if (Line^.CurWord > High(Line^.Words)) then - begin - CurWordStart := Line^.Words[High(Line^.Words)].X + Line^.Words[High(Line^.Words)].Width; - CurWordEnd := CurWordStart; - - // fade out last line - if Line^.LastLine then - begin - Alpha := 1 - (Beat - (Line^.Words[High(Line^.Words)].Start + Line^.Words[High(Line^.Words)].Length)) / 15; - if (Alpha < 0) then - Alpha := 0; - end; - end - else - begin - with Line^.Words[Line^.CurWord] do - begin - Progress := (Beat - Start) / Length; - if Progress >= 1 then - Progress := 1; - - if Progress <= 0 then - Progress := 0; - - CurWordStart:=X; - CurWordEnd:=X+Width; - - // Slide Effect - // simply paint the active texture to the current position - if Ini.LyricsEffect = 2 then - begin - CurWordStart := CurWordStart + Width * progress; - CurWordEnd := CurWordStart; - end; - - if (Line^.CurWord < High(Line^.Words)) AND Freestyle AND not Line^.Words[Line^.CurWord + 1].Freestyle then - begin - FreestyleDiff := 2; - end - else - if Freestyle then - begin - FreestyleDiff := 12; - CurWordStart := CurWordStart - 1; - CurWordEnd := CurWordEnd - 2; - end; - end; - end; - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, Line^.Tex); - - // draw sentence up to current word - if (Ini.LyricsEffect = 3) or (Ini.LyricsEffect = 4) then - // ball lyric effect - only highlight current word and not that ones before in this line - glColorRGB(LineColor_en, Alpha) - else - glColorRGB(LineColor_act, Alpha); - - glBegin(GL_QUADS); - glTexCoord2f(0, 1); glVertex2f(LyricX, LyricY); - glTexCoord2f(0, 1-LyricsHeight/64); glVertex2f(LyricX, LyricY + LyricsHeight); - glTexCoord2f(CurWordStart/1024, 1-LyricsHeight/64); glVertex2f(LyricX+CurWordStart, LyricY + LyricsHeight); - glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordStart+FreestyleDiff, LyricY); - glEnd; - - // draw rest of sentence - glColorRGB(LineColor_en); - glBegin(GL_QUADS); - glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordEnd+FreestyleDiff, LyricY); - glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f(LyricX+CurWordEnd, LyricY + LyricsHeight); - glTexCoord2f(Line^.Width/1024, 1-LyricsHeight/64); glVertex2f(LyricX2, LyricY + LyricsHeight); - glTexCoord2f(Line^.Width/1024, 1); glVertex2f(LyricX2, LyricY); - glEnd; - - // draw active word: - // type 0: simple lyric effect - // type 3: ball lyric effect - // type 4: shift lyric effect - // only change the color of the current word - if (Ini.LyricsEffect = 0) or (Ini.LyricsEffect = 3) or (Ini.LyricsEffect = 4) then - begin - { // maybe fade in? - glColor4f(LineColor_en.r,LineColor_en.g,LineColor_en.b,1-progress); - glBegin(GL_QUADS); - glTexCoord2f(CurWordStart/1024, 1); glVertex2f(LyricX+CurWordStart, Y); - glTexCoord2f(CurWordStart/1024, 0); glVertex2f(LyricX+CurWordStart, Y + 64); - glTexCoord2f(CurWordEnd/1024, 0); glVertex2f(LyricX+CurWordEnd, Y + 64); - glTexCoord2f(CurWordEnd/1024, 1); glVertex2f(LyricX+CurWordEnd, Y); - glEnd; - } - - if (Ini.LyricsEffect = 4) then - LyricY := LyricY - 8 * (1-progress); - - glColor3f(LineColor_act.r,LineColor_act.g,LineColor_act.b); - glBegin(GL_QUADS); - glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordStart+FreestyleDiff, LyricY); - glTexCoord2f(CurWordStart/1024, 0); glVertex2f(LyricX+CurWordStart, LyricY + 64); - glTexCoord2f(CurWordEnd/1024, 0); glVertex2f(LyricX+CurWordEnd, LyricY + 64); - glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordEnd+FreestyleDiff, LyricY); - glEnd; - - if (Ini.LyricsEffect = 4) then - LyricY := LyricY + 8 * (1-progress); - end - - // draw active word: - // type 1: zoom lyric effect - // change color and zoom current word - else if Ini.LyricsEffect = 1 then - begin - glPushMatrix; - glTranslatef(LyricX+CurWordStart+(CurWordEnd-CurWordStart)/2,LyricY+LyricsHeight/2,0); - glScalef(1.0+(1-progress)/2,1.0+(1-progress)/2,1.0); - glColor4f(LineColor_en.r,LineColor_en.g,LineColor_en.b,1-progress); - glBegin(GL_QUADS); - glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(-(CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2); - glTexCoord2f(CurWordStart/1024, 1-LyricsHeight/64); glVertex2f(-(CurWordEnd-CurWordStart)/2, + LyricsHeight/2); - glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f((CurWordEnd-CurWordStart)/2, + LyricsHeight/2); - glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f((CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2); - glEnd; - glColor4f(LineColor_act.r,LineColor_act.g,LineColor_act.b,1); - glBegin(GL_QUADS); - glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(-(CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2); - glTexCoord2f(CurWordStart/1024, 1-LyricsHeight/64); glVertex2f(-(CurWordEnd-CurWordStart)/2, + LyricsHeight/2); - glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f((CurWordEnd-CurWordStart)/2, + LyricsHeight/2); - glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f((CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2); - glEnd; - glPopMatrix; - end; - - glDisable(GL_TEXTURE_2D); - glDisable(GL_BLEND); - - if Ini.LyricsEffect = 3 then - DrawBall(LyricX + CurWordStart + (CurWordEnd - CurWordStart) * progress, LyricY - 15 - 15*sin(progress * pi), Alpha); - end - else - begin - // draw complete inactive sentence if line hasn't started but is already shown - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, Line^.Tex); - - glColorRGB(LineColor_dis); - glBegin(GL_QUADS); - glTexCoord2f(0, 1); glVertex2f(LyricX, LyricY); - glTexCoord2f(0, 1-LyricsHeight/64); glVertex2f(LyricX, LyricY + LyricsHeight); - glTexCoord2f(Line^.Width/1024, 1-LyricsHeight/64); glVertex2f(LyricX2, LyricY + LyricsHeight); - glTexCoord2f(Line^.Width/1024, 1); glVertex2f(LyricX2, LyricY); - glEnd; - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - end; -end; - - -end. - +unit ULyrics; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses OpenGL12, + UTexture, + UThemes, + UMusic; + +type + TLyricWord = record + X: Real; // left corner + Width: Real; // width + Start: Cardinal; // start of the word in quarters (beats) + Length: Cardinal; // length of the word in quarters + Text: String; // text + Freestyle: Boolean; // is freestyle? + end; + ALyricWord = array of TLyricWord; + + PLyricLine = ^TLyricLine; + TLyricLine = record + Text: String; // text + Tex: glUInt; // texture of the text + Width: Real; // width + Size: Byte; // fontsize + Words: ALyricWord; // words in this line + CurWord: Integer; // current active word idx (only valid if line is active) + Start: Cardinal; // start of this line in quarters + Length: Cardinal; // length in quarters + HasFreestyle: Boolean; // one or more word are freestyle? + CountFreestyle: Integer; // how often there is a change from freestyle to non freestyle in this line + Players: Byte; // players that should sing that line (bitset, Player1: 1, Player2: 2, Player3: 4) + Done: Boolean; // is sentence already sung? + LastLine: Boolean; // is this the last line ob the song? + end; + + TLyricEngine = class + private + EoLastSentence: Real; // end of the previous sentence (in beats) + LastDrawBeat: Real; + UpperLine: TLyricLine; // first line displayed (top) + LowerLine: TLyricLine; // second lind displayed (bottom) + QueueLine: TLyricLine; // third line (queue and will be displayed when next line is finished) + PUpperLine, PLowerLine, PQueueLine: PLyricLine; + + IndicatorTex: TTexture; // texture for lyric indikator + BallTex: TTexture; // texture of the ball for the lyric effect + + inQueue: Boolean; // is line in queue + LCounter: Word; // line counter + + // duet mode - textures for player icons + PlayerIconTex: array[0..5] of // player idx + array [0..1] of // enabled disabled + TTexture; + + + //Some helper Procedures for Lyric Drawing + procedure DrawLyrics (Beat: Real); + procedure DrawLyricsLine(const X, W, Y: Real; Size: Byte; const Line: PLyricLine; Beat: Real); + procedure DrawPlayerIcon(const Player: Byte; const Enabled: Boolean; const X, Y, Size, Alpha: Real); + procedure DrawBall(const XBall, YBall, Alpha:Real); + + public + // positions, line specific settings + UpperLineX: Real; //X Start Pos of UpperLine + UpperLineW: Real; //Width of UpperLine with Icon(s) and Text + UpperLineY: Real; //Y Start Pos of UpperLine + UpperLineSize: Byte; //Max Size of Lyrics Text in UpperLine + + LowerLineX: Real; //X Start Pos of LowerLine + LowerLineW: Real; //Width of LowerLine with Icon(s) and Text + LowerLineY: Real; //Y Start Pos of LowerLine + LowerLineSize: Byte; //Max Size of Lyrics Text in LowerLine + + // display propertys + LineColor_en: TRGBA; //Color of Words in an Enabled Line + LineColor_dis: TRGBA; //Color of Words in a Disabled Line + LineColor_act: TRGBA; //Color of teh active Word + FontStyle: Byte; //Font for the Lyric Text + FontReSize: Boolean; //ReSize Lyrics if they don't fit Screen + + { // currently not used + FadeInEffect: Byte; //Effect for Line Fading in: 0: No Effect; 1: Fade Effect; 2: Move Upwards from Bottom to Pos + FadeOutEffect: Byte; //Effect for Line Fading out: 0: No Effect; 1: Fade Effect; 2: Move Upwards + } + + UseLinearFilter:Boolean; //Should Linear Tex Filter be used + + // song specific settings + BPM: Real; + Resolution: Integer; + + + // properties to easily read options of this class + property LineinQueue: Boolean read inQueue; // line in queue? + property LineCounter: Word read LCounter; // lines that were progressed so far (after last clear) + + Procedure AddLine(Line: PLine); // adds a line to the queue, if there is space + Procedure Draw (Beat: Real); // draw the current (active at beat) lyrics + + Procedure Clear (const cBPM: Real = 0; // clears all cached song specific information + const cResolution: Integer = 0); + + Constructor Create; overload; + Constructor Create(ULX,ULY,ULW,ULS,LLX,LLY,LLW,LLS:Real); overload; + Procedure LoadTextures; + Destructor Free; + end; + +implementation + +uses SysUtils, + USkins, + TextGL, + UGraphic, + UDisplay, + math, + UIni; + +//----------- +//Helper procs to use TRGB in Opengl ...maybe this should be somewhere else +//----------- +procedure glColorRGB(Color: TRGB); overload; +begin + glColor3f(Color.R, Color.G, Color.B); +end; + +procedure glColorRGB(Color: TRGB; Alpha: Real); overload; +begin + glColor4f(Color.R, Color.G, Color.B, Alpha); +end; + +procedure glColorRGB(Color: TRGBA); overload; +begin + glColor4f(Color.R, Color.G, Color.B, Color.A); +end; + +procedure glColorRGB(Color: TRGBA; Alpha: Real); overload; +begin + glColor4f(Color.R, Color.G, Color.B, Min(Color.A, Alpha)); +end; + + + +//--------------- +// Create - Constructor, just get Memory +//--------------- +Constructor TLyricEngine.Create; +begin + BPM := 0; + Resolution := 0; + LCounter := 0; + inQueue := False; + + UpperLine.Done := True; + LowerLine.Done := True; + QueueLine.Done := True; + PUpperline:=@UpperLine; + PLowerLine:=@LowerLine; + PQueueLine:=@QueueLine; + + UseLinearFilter := True; + LastDrawBeat:=0; +end; + +Constructor TLyricEngine.Create(ULX,ULY,ULW,ULS,LLX,LLY,LLW,LLS:Real); +begin + Create; + UpperLineX := ULX; + UpperLineW := ULW; + UpperLineY := ULY; + UpperLineSize := Trunc(ULS); + + LowerLineX := LLX; + LowerLineW := LLW; + LowerLineY := LLY; + LowerLineSize := Trunc(LLS); + LoadTextures; +end; + + +//--------------- +// Free - Frees Memory +//--------------- +Destructor TLyricEngine.Free; +begin + +end; + +//--------------- +// Clear - Clears all cached Song specific Information +//--------------- +Procedure TLyricEngine.Clear (const cBPM: Real; const cResolution: Integer); +begin + BPM := cBPM; + Resolution := cResolution; + LCounter := 0; + inQueue := False; + + UpperLine.Done := True; + LowerLine.Done := True; + QueueLine.Done := True; + + PUpperline:=@UpperLine; + PLowerLine:=@LowerLine; + PQueueLine:=@QueueLine; + + LastDrawBeat:=0; +end; + + +//--------------- +// LoadTextures - Load Player Textures and Create Lyric Textures +//--------------- +Procedure TLyricEngine.LoadTextures; +var + I: Integer; + + function CreateLineTex: glUint; + var + PTexData: Pointer; + begin + try + // get memory + GetMem(pTexData, 1024*64*4); + + // generate and bind Texture + glGenTextures(1, @Result); + glBindTexture(GL_TEXTURE_2D, Result); + + // get texture memeory + glTexImage2D(GL_TEXTURE_2D, 0, 4, 1024, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, pTexData); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + if UseLinearFilter then + begin + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + end; + + finally + // free unused memory + FreeMem(pTexData); + end; + end; +begin + + // lyric indicator (bar that indicates when the line start) + IndicatorTex := Texture.LoadTexture(Skin.GetTextureFileName('LyricHelpBar'), TEXTURE_TYPE_TRANSPARENT, $FF00FF); + + // ball for current word hover in ball effect + BallTex := Texture.LoadTexture(Skin.GetTextureFileName('Ball'), TEXTURE_TYPE_TRANSPARENT, 0); + + // duet mode: load player icon + For I := 0 to 5 do + begin + PlayerIconTex[I][0] := Texture.LoadTexture(Skin.GetTextureFileName('LyricIcon_P' + InttoStr(I+1)), TEXTURE_TYPE_TRANSPARENT, 0); + PlayerIconTex[I][1] := Texture.LoadTexture(Skin.GetTextureFileName('LyricIconD_P' + InttoStr(I+1)), TEXTURE_TYPE_TRANSPARENT, 0); + end; + + // create line textures + UpperLine.Tex := CreateLineTex; + LowerLine.Tex := CreateLineTex; + QueueLine.Tex := CreateLineTex; +end; + + +//--------------- +// AddLine - Adds LyricLine to queue +//--------------- +Procedure TLyricEngine.AddLine(Line: PLine); +var + LyricLine: PLyricLine; + countNotes: Cardinal; + Viewport: Array[0..3] of Integer; + + PosX: Real; + I: Integer; + + function CalcWidth(LyricLine: PLyricLine): Real; + begin + Result := glTextWidth(PChar(LyricLine.Text)); + + Result := Result + (LyricLine.CountFreestyle * 10); + + // if the line ends with a freestyle not, then leave the place to finish to draw the text italic + if (LyricLine.Words[High(LyricLine.Words)].Freestyle) then + Result := Result + 12; + end; +begin + // only add lines, if there is space + If not LineinQueue then + begin + // set pointer to line to write + + If (LineCounter = 0) then + LyricLine := PUpperLine + else if (LineCounter = 1) then + LyricLine := PLowerLine + else + begin + LyricLine := PQueueLine; + + //now there is a queued line + inQueue := True; + end; + end + else + begin // rotate lines (round-robin-like) + LyricLine := PUpperLine; + PUpperLine := PLowerLine; + PLowerLine := PQueueLine; + PQueueLine := LyricLine; + end; + + // sentence has notes? + If Line = nil then + begin + // reset all values, if the new line is nil (lines after the last line) + LyricLine.Start := 0; + LyricLine.Length := 0; + LyricLine.CurWord := -1; + LyricLine.LastLine := False; + LyricLine.Width := 0; + SetLength(LyricLine.Words, 0); + end + else if Length(Line.Note) > 0 then + begin + // copy values from SongLine to LyricLine + CountNotes := High(Line.Note); + LyricLine.Start := Line.Note[0].Start; + LyricLine.Length := Line.Note[CountNotes].Start + Line.Note[CountNotes].Length - LyricLine.Start; + LyricLine.CurWord := -1; + LyricLine.LastLine := Line.LastLine; + + // default values - set later + LyricLine.HasFreestyle := False; + LyricLine.CountFreestyle := 0; + LyricLine.Text := ''; + + // duet mode: players of that line + LyricLine.Players := 127; + + //copy words + SetLength(LyricLine.Words, CountNotes + 1); + For I := 0 to CountNotes do + begin + LyricLine.Words[I].Start := Line.Note[I].Start; + LyricLine.Words[I].Length := Line.Note[I].Length; + LyricLine.Words[I].Text := Line.Note[I].Text; + LyricLine.Words[I].Freestyle := Line.Note[I].NoteType = ntFreestyle; + + LyricLine.HasFreestyle := LyricLine.HasFreestyle OR LyricLine.Words[I].Freestyle; + LyricLine.Text := LyricLine.Text + LyricLine.Words[I].Text; + + if (I > 0) AND LyricLine.Words[I-1].Freestyle AND not LyricLine.Words[I].Freestyle then + Inc(LyricLine.CountFreestyle); + end; + + // set font params + SetFontStyle(FontStyle); + SetFontPos(0, 0); + LyricLine.Size := UpperLineSize; + SetFontSize(LyricLine.Size); + SetFontItalic(False); + glColor4f(1, 1, 1, 1); + + // change fontsize to fit the screen + LyricLine.Width := CalcWidth(LyricLine); + while (LyricLine.Width > UpperLineW) do + begin + Dec(LyricLine.Size); + + if (LyricLine.Size <=1) then + Break; + + SetFontSize(LyricLine.Size); + LyricLine.Width := CalcWidth(LyricLine); + end; + + // create LyricTexture - prepare OpenGL + glGetIntegerv(GL_VIEWPORT, @ViewPort); + glClearColor(0.0,0.0,0.0,0.0); + glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); + glViewPort(0,0,800,600); + + // set word positions and line size + PosX := 0; + for I := 0 to High(LyricLine.Words) do + begin + with LyricLine.Words[I] do + begin + SetFontItalic(Freestyle); + + X := PosX; + + //Draw Lyrics + SetFontPos(PosX, 0); + glPrint(PChar(Text)); + + Width := glTextWidth(PChar(Text)); + if (I < High(LyricLine.Words)) AND Freestyle AND not LyricLine.Words[I+1].Freestyle then + Width := Width + 10 + else + if (I = High(LyricLine.Words)) AND Freestyle then + Width := Width + 12; + PosX := PosX + Width; + end; + end; + end + else + begin + // create LyricTexture - prepare OpenGL + glGetIntegerv(GL_VIEWPORT, @ViewPort); + glClearColor(0.0,0.0,0.0,0.0); + glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); + glViewPort(0,0,800,600); + end; + + //for debugging, is this used anymore? + //Display.ScreenShot; + + //Copy to Texture + glEnable(GL_ALPHA); + glBindTexture(GL_TEXTURE_2D, LyricLine.Tex); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 600-64, 1024, 64, 0); + glDisable(GL_ALPHA); + + //Clear Buffer + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); + + glViewPort(ViewPort[0], ViewPort[1], ViewPort[2], ViewPort[3]); + + //Increase the Counter + Inc(LCounter); +end; + + +//--------------- +// Draw - Procedure Draws Lyrics; Beat is curent Beat in Quarters +// Draw just manage the Lyrics, drawing is done by a call of DrawLyrics +//--------------- +Procedure TLyricEngine.Draw (Beat: Real); +begin + DrawLyrics(Beat); + LastDrawBeat := Beat; +end; + +//--------------- +// DrawLyrics(private) - Helper for Draw; main Drawing procedure +//--------------- +procedure TLyricEngine.DrawLyrics (Beat: Real); +begin + DrawLyricsLine(UpperLineX, UpperLineW, UpperlineY, 15, PUpperline, Beat); + DrawLyricsLine(LowerLineX, LowerLineW, LowerlineY, 15, PLowerline, Beat); +end; + +//--------------- +// DrawPlayerIcon(private) - Helper for Draw; Draws a Playericon +//--------------- +procedure TLyricEngine.DrawPlayerIcon(const Player: Byte; const Enabled: Boolean; const X, Y, Size, Alpha: Real); +var IEnabled: Byte; +begin + Case Enabled of + True: IEnabled := 0; + False: IEnabled := 1; + end; + + try + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, PlayerIconTex[Player][IEnabled].TexNum); + + glColor4f(1,1,1,Alpha); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(X, Y); + glTexCoord2f(0, 1); glVertex2f(X, Y + Size); + glTexCoord2f(1, 1); glVertex2f(X + Size, Y + Size); + glTexCoord2f(1, 0); glVertex2f(X + Size, Y); + glEnd; + + finally + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + end; +end; + +//--------------- +// DrawBall(private) - Helper for Draw; Draws the Ball over the LyricLine if needed +//--------------- +procedure TLyricEngine.DrawBall(const XBall, YBall, Alpha:Real); +begin + try + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, BallTex.TexNum); + + glColor4f(1,1,1, Alpha); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); glVertex2f(XBall - 10, YBall); + glTexCoord2f(0, 1); glVertex2f(XBall - 10, YBall + 20); + glTexCoord2f(1, 1); glVertex2f(XBall + 10, YBall + 20); + glTexCoord2f(1, 0); glVertex2f(XBall + 10, YBall); + glEnd; + + finally + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + end; +end; + +//--------------- +// DrawLyricsLine(private) - Helper for Draw; Draws one LyricLine +//--------------- +procedure TLyricEngine.DrawLyricsLine(const X, W, Y: Real; Size: Byte; const Line: PLyricLine; Beat: Real); +var + CurWordStart, CurWordEnd: Real; // screen coordinates of current word and the rest of the sentence + FreestyleDiff: Integer; // difference between top and bottom coordiantes for freestyle lyrics + Progress: Real; // progress of singing the current word + LyricX: Real; // left + LyricX2: Real; // right + LyricY: Real; // top + LyricsHeight: Real; // height the lyrics are displayed + Alpha: Real; // alphalevel to fade out at end + + {// duet mode + IconSize: Real; // size of player icons + IconAlpha: Real; // alpha level of player icons + } +begin + // lines with a width lower than 0, have not to be draw + if Line^.Width <= 0 then + exit; + + // this is actually a bit more than the real font size + // it helps adjusting the "zoom-center" + LyricsHeight:=30.5 * (Line^.Size/10); + + { + // duet mode + IconSize := (2 * Size); + IconAlpha := Frac(Beat/(Resolution*4)); + + DrawPlayerIcon (0, True, X, Y + (42 - IconSize) / 2 , IconSize, IconAlpha); + DrawPlayerIcon (1, True, X + IconSize + 1, Y + (42 - IconSize) / 2, IconSize, IconAlpha); + DrawPlayerIcon (2, True, X + (IconSize + 1)*2, Y + (42 - IconSize) / 2, IconSize, IconAlpha); + } + + LyricX := X+W/2 - Line^.Width/2; + LyricX2 := LyricX + Line^.Width; + + // maybe center smaller lines + //LyricY := Y; + LyricY := Y + ((Size / Line.Size - 1) * LyricsHeight) / 2; + + Alpha := 1; + + // word in the sentence is active? + if (Line^.Start < Beat) then + begin + // if this line just got active, then CurWord is still -1 + // this means, we should try to make the first word active + // then we check if the current active word is still meant to be active + // if not, we proceed to the next word + if Line^.CurWord = -1 then + Line^.CurWord:=0; + + if (Line^.CurWord < High(Line^.Words)) AND (Beat >= (Line^.Words[Line^.CurWord + 1].Start)) then + Line^.CurWord:=Line^.CurWord+1; + + FreestyleDiff := 0; + + // last word of this line finished, but this line did not hide + if (Line^.CurWord > High(Line^.Words)) then + begin + CurWordStart := Line^.Words[High(Line^.Words)].X + Line^.Words[High(Line^.Words)].Width; + CurWordEnd := CurWordStart; + + // fade out last line + if Line^.LastLine then + begin + Alpha := 1 - (Beat - (Line^.Words[High(Line^.Words)].Start + Line^.Words[High(Line^.Words)].Length)) / 15; + if (Alpha < 0) then + Alpha := 0; + end; + end + else + begin + with Line^.Words[Line^.CurWord] do + begin + Progress := (Beat - Start) / Length; + if Progress >= 1 then + Progress := 1; + + if Progress <= 0 then + Progress := 0; + + CurWordStart:=X; + CurWordEnd:=X+Width; + + // Slide Effect + // simply paint the active texture to the current position + if Ini.LyricsEffect = 2 then + begin + CurWordStart := CurWordStart + Width * progress; + CurWordEnd := CurWordStart; + end; + + if (Line^.CurWord < High(Line^.Words)) AND Freestyle AND not Line^.Words[Line^.CurWord + 1].Freestyle then + begin + FreestyleDiff := 2; + end + else + if Freestyle then + begin + FreestyleDiff := 12; + CurWordStart := CurWordStart - 1; + CurWordEnd := CurWordEnd - 2; + end; + end; + end; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, Line^.Tex); + + // draw sentence up to current word + if (Ini.LyricsEffect = 3) or (Ini.LyricsEffect = 4) then + // ball lyric effect - only highlight current word and not that ones before in this line + glColorRGB(LineColor_en, Alpha) + else + glColorRGB(LineColor_act, Alpha); + + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex2f(LyricX, LyricY); + glTexCoord2f(0, 1-LyricsHeight/64); glVertex2f(LyricX, LyricY + LyricsHeight); + glTexCoord2f(CurWordStart/1024, 1-LyricsHeight/64); glVertex2f(LyricX+CurWordStart, LyricY + LyricsHeight); + glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordStart+FreestyleDiff, LyricY); + glEnd; + + // draw rest of sentence + glColorRGB(LineColor_en); + glBegin(GL_QUADS); + glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordEnd+FreestyleDiff, LyricY); + glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f(LyricX+CurWordEnd, LyricY + LyricsHeight); + glTexCoord2f(Line^.Width/1024, 1-LyricsHeight/64); glVertex2f(LyricX2, LyricY + LyricsHeight); + glTexCoord2f(Line^.Width/1024, 1); glVertex2f(LyricX2, LyricY); + glEnd; + + // draw active word: + // type 0: simple lyric effect + // type 3: ball lyric effect + // type 4: shift lyric effect + // only change the color of the current word + if (Ini.LyricsEffect = 0) or (Ini.LyricsEffect = 3) or (Ini.LyricsEffect = 4) then + begin + { // maybe fade in? + glColor4f(LineColor_en.r,LineColor_en.g,LineColor_en.b,1-progress); + glBegin(GL_QUADS); + glTexCoord2f(CurWordStart/1024, 1); glVertex2f(LyricX+CurWordStart, Y); + glTexCoord2f(CurWordStart/1024, 0); glVertex2f(LyricX+CurWordStart, Y + 64); + glTexCoord2f(CurWordEnd/1024, 0); glVertex2f(LyricX+CurWordEnd, Y + 64); + glTexCoord2f(CurWordEnd/1024, 1); glVertex2f(LyricX+CurWordEnd, Y); + glEnd; + } + + if (Ini.LyricsEffect = 4) then + LyricY := LyricY - 8 * (1-progress); + + glColor3f(LineColor_act.r,LineColor_act.g,LineColor_act.b); + glBegin(GL_QUADS); + glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordStart+FreestyleDiff, LyricY); + glTexCoord2f(CurWordStart/1024, 0); glVertex2f(LyricX+CurWordStart, LyricY + 64); + glTexCoord2f(CurWordEnd/1024, 0); glVertex2f(LyricX+CurWordEnd, LyricY + 64); + glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f(LyricX+CurWordEnd+FreestyleDiff, LyricY); + glEnd; + + if (Ini.LyricsEffect = 4) then + LyricY := LyricY + 8 * (1-progress); + end + + // draw active word: + // type 1: zoom lyric effect + // change color and zoom current word + else if Ini.LyricsEffect = 1 then + begin + glPushMatrix; + glTranslatef(LyricX+CurWordStart+(CurWordEnd-CurWordStart)/2,LyricY+LyricsHeight/2,0); + glScalef(1.0+(1-progress)/2,1.0+(1-progress)/2,1.0); + glColor4f(LineColor_en.r,LineColor_en.g,LineColor_en.b,1-progress); + glBegin(GL_QUADS); + glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(-(CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2); + glTexCoord2f(CurWordStart/1024, 1-LyricsHeight/64); glVertex2f(-(CurWordEnd-CurWordStart)/2, + LyricsHeight/2); + glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f((CurWordEnd-CurWordStart)/2, + LyricsHeight/2); + glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f((CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2); + glEnd; + glColor4f(LineColor_act.r,LineColor_act.g,LineColor_act.b,1); + glBegin(GL_QUADS); + glTexCoord2f((CurWordStart+FreestyleDiff)/1024, 1); glVertex2f(-(CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2); + glTexCoord2f(CurWordStart/1024, 1-LyricsHeight/64); glVertex2f(-(CurWordEnd-CurWordStart)/2, + LyricsHeight/2); + glTexCoord2f(CurWordEnd/1024, 1-LyricsHeight/64); glVertex2f((CurWordEnd-CurWordStart)/2, + LyricsHeight/2); + glTexCoord2f((CurWordEnd+FreestyleDiff)/1024, 1); glVertex2f((CurWordEnd-CurWordStart)/2+FreestyleDiff, -LyricsHeight/2); + glEnd; + glPopMatrix; + end; + + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + + if Ini.LyricsEffect = 3 then + DrawBall(LyricX + CurWordStart + (CurWordEnd - CurWordStart) * progress, LyricY - 15 - 15*sin(progress * pi), Alpha); + end + else + begin + // draw complete inactive sentence if line hasn't started but is already shown + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, Line^.Tex); + + glColorRGB(LineColor_dis); + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex2f(LyricX, LyricY); + glTexCoord2f(0, 1-LyricsHeight/64); glVertex2f(LyricX, LyricY + LyricsHeight); + glTexCoord2f(Line^.Width/1024, 1-LyricsHeight/64); glVertex2f(LyricX2, LyricY + LyricsHeight); + glTexCoord2f(Line^.Width/1024, 1); glVertex2f(LyricX2, LyricY); + glEnd; + + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + end; +end; + + +end. + diff --git a/Game/Code/Classes/UServices.pas b/Game/Code/Classes/UServices.pas index 7cc811bc..19561eeb 100644 --- a/Game/Code/Classes/UServices.pas +++ b/Game/Code/Classes/UServices.pas @@ -229,9 +229,11 @@ begin If (Service.isClass) then //Use Proc of Class + // FIXME: "function ... of object" does not fit into an integer (2x pointers: object + function-code -> 8byte on x86) Result := Service.ProcOfClass(wParam, lParam) Else //Use normal Proc + // FIXME: will not work with x64 CPUs, pointers will be 64bit there Result := Service.Proc(wParam, lParam); //Restore CurExecuted diff --git a/Game/Code/Classes/USingScores.pas b/Game/Code/Classes/USingScores.pas index 67f94824..56d2cd69 100644 --- a/Game/Code/Classes/USingScores.pas +++ b/Game/Code/Classes/USingScores.pas @@ -216,19 +216,19 @@ begin Settings.Phase2Time := 550; // shift it up ^[ ]^ Settings.Phase3Time := 200; // increase score [s++] - Settings.PopUpTex[0].TexNum := High(gluInt); - Settings.PopUpTex[1].TexNum := High(gluInt); - Settings.PopUpTex[2].TexNum := High(gluInt); - Settings.PopUpTex[3].TexNum := High(gluInt); - Settings.PopUpTex[4].TexNum := High(gluInt); - Settings.PopUpTex[5].TexNum := High(gluInt); - Settings.PopUpTex[6].TexNum := High(gluInt); - Settings.PopUpTex[7].TexNum := High(gluInt); - Settings.PopUpTex[8].TexNum := High(gluInt); - - Settings.RatingBar_BG_Tex.TexNum := High(gluInt); - Settings.RatingBar_FG_Tex.TexNum := High(gluInt); - Settings.RatingBar_Bar_Tex.TexNum := High(gluInt); + Settings.PopUpTex[0].TexNum := 0; + Settings.PopUpTex[1].TexNum := 0; + Settings.PopUpTex[2].TexNum := 0; + Settings.PopUpTex[3].TexNum := 0; + Settings.PopUpTex[4].TexNum := 0; + Settings.PopUpTex[5].TexNum := 0; + Settings.PopUpTex[6].TexNum := 0; + Settings.PopUpTex[7].TexNum := 0; + Settings.PopUpTex[8].TexNum := 0; + + Settings.RatingBar_BG_Tex.TexNum := 0; + Settings.RatingBar_FG_Tex.TexNum := 0; + Settings.RatingBar_Bar_Tex.TexNum := 0; end; //----------- diff --git a/Game/Code/Classes/UTexture.pas b/Game/Code/Classes/UTexture.pas index 07dc309f..8502c3e4 100644 --- a/Game/Code/Classes/UTexture.pas +++ b/Game/Code/Classes/UTexture.pas @@ -1,993 +1,993 @@ -unit UTexture; -// added for easier debug disabling -{$undef blindydebug} - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - -uses OpenGL12, - {$IFDEF win32} - windows, - {$ENDIF} - Math, - Classes, - SysUtils, - UCommon, - UImage, - SDL, - sdlutils, - SDL_Image; - -type - TTexture = record - TexNum: integer; - X: real; - Y: real; - Z: real; // new - W: real; - H: real; - ScaleW: real; // for dynamic scalling while leaving width constant - ScaleH: real; // for dynamic scalling while leaving height constant - Rot: real; // 0 - 2*pi - Int: real; // intensity - ColR: real; - ColG: real; - ColB: real; - TexW: real; // used? - TexH: real; // used? - TexX1: real; - TexY1: real; - TexX2: real; - TexY2: real; - Alpha: real; - Name: string; // 0.5.0: experimental for handling cache images. maybe it's useful for dynamic skins - end; - -type - TTextureType = ( - TEXTURE_TYPE_PLAIN, // Plain (alpha = 1) - TEXTURE_TYPE_TRANSPARENT, // Alpha is used - TEXTURE_TYPE_COLORIZED // Alpha is used; Hue of the HSV color-model will be replaced by a new value - ); -const - TextureTypeStr: array[TTextureType] of string = ( - 'Plain', - 'Transparent', - 'Colorized' - ); - -function TextureTypeToStr(TexType: TTextureType): string; -function ParseTextureType(const TypeStr: string; Default: TTextureType): TTextureType; - -type - TTextureEntry = record - Name: string; - Typ: TTextureType; - Color: Cardinal; - - // we use normal TTexture, it's easier to implement and if needed - we copy ready data - Texture: TTexture; - TextureCache: TTexture; - end; - - TTextureDatabase = record - Texture: array of TTextureEntry; - end; - - TTextureUnit = class - private - TnWidth, TnHeight: Cardinal; //Width and Height of the Cover Thumbnails - - TnBuffer: array of byte; - TnSurface: PSDL_Surface; - - function LoadImage(const Identifier: string): PSDL_Surface; - function pixfmt_eq(fmt1,fmt2: PSDL_Pixelformat): boolean; - procedure AdjustPixelFormat(var TexSurface: PSDL_Surface; Typ: TTextureType); - function GetScaledTexture(TexSurface: PSDL_Surface; W,H: Cardinal): PSDL_Surface; - procedure ScaleTexture(var TexSurface: PSDL_Surface; W,H: Cardinal); - procedure FitTexture(var TexSurface: PSDL_Surface; W,H: Cardinal); - procedure ColorizeTexture(TexSurface: PSDL_Surface; Col: Cardinal); - public - Limit: integer; - CreateCacheMipmap: boolean; - -// function GetNumberFor - function GetTexture(const Name: string; Typ: TTextureType; FromCache: boolean = true): TTexture; overload; - function GetTexture(const Name: string; Typ: TTextureType; Col: LongWord; FromCache: boolean = true): TTexture; overload; - function FindTexture(const Name: string; Typ: TTextureType; Col: Cardinal): integer; - function LoadTexture(FromRegistry: boolean; const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture; overload; - function LoadTexture(const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture; overload; - function LoadTexture(const Identifier: string): TTexture; overload; - function CreateTexture(var Data: array of byte; const Name: string; W, H: word; Bits: byte): TTexture; - procedure UnloadTexture(const Name: string; Typ: TTextureType; FromCache: boolean); overload; - procedure UnloadTexture(const Name: string; Typ: TTextureType; Col: Cardinal; FromCache: boolean); overload; - //procedure FlushTextureDatabase(); - - Function GetCoverThumbnail(const Name: string): Pointer; - Procedure SetCoverSize(W, H: Integer); - - Constructor Create; - Destructor Destroy; override; - end; - -var - Texture: TTextureUnit; - TextureDatabase: TTextureDatabase; - - ActTex: GLuint; - - Mipmapping: Boolean; - - CacheMipmap: array[0..256*256*3-1] of byte; // 3KB - CacheMipmapSurface: PSDL_Surface; - - -implementation - -uses ULog, - DateUtils, - UCovers, - UThemes, - {$IFDEF DARWIN} - MacResources, - {$ENDIF} - StrUtils; - -Constructor TTextureUnit.Create; -begin - inherited Create; -end; - -Destructor TTextureUnit.Destroy; -begin - inherited Destroy; -end; - -function TTextureUnit.pixfmt_eq(fmt1,fmt2: PSDL_Pixelformat): boolean; -begin - if (fmt1^.BitsPerPixel = fmt2^.BitsPerPixel) and - (fmt1^.BytesPerPixel = fmt2^.BytesPerPixel) and - (fmt1^.Rloss = fmt2^.Rloss) and (fmt1^.Gloss = fmt2^.Gloss) and - (fmt1^.Bloss = fmt2^.Bloss) and (fmt1^.Rmask = fmt2^.Rmask) and - (fmt1^.Gmask = fmt2^.Gmask) and (fmt1^.Bmask = fmt2^.Bmask) and - (fmt1^.Rshift = fmt2^.Rshift) and (fmt1^.Gshift = fmt2^.Gshift) and - (fmt1^.Bshift = fmt2^.Bshift) - then - Result:=True - else - Result:=False; -end; - -// +++++++++++++++++++++ helpers for loadimage +++++++++++++++ - function SdlStreamSeek( context : PSDL_RWops; offset : Integer; whence : Integer ) : integer; cdecl; - var - stream : TStream; - origin : Word; - begin - stream := TStream( context.unknown ); - if ( stream = nil ) then - raise EInvalidContainer.Create( 'SDLStreamSeek on nil' ); - case whence of - 0 : origin := soFromBeginning; // Offset is from the beginning of the resource. Seek moves to the position Offset. Offset must be >= 0. - 1 : origin := soFromCurrent; // Offset is from the current position in the resource. Seek moves to Position + Offset. - 2 : origin := soFromEnd; - else - origin := soFromBeginning; // just in case - end; - Result := stream.Seek( offset, origin ); - end; - - function SdlStreamRead( context : PSDL_RWops; Ptr : Pointer; size : Integer; maxnum: Integer ) : Integer; cdecl; - var - stream : TStream; - begin - stream := TStream( context.unknown ); - if ( stream = nil ) then - raise EInvalidContainer.Create( 'SDLStreamRead on nil' ); - try - Result := stream.read( Ptr^, Size * maxnum ) div size; - except - Result := -1; - end; - end; - - function SDLStreamClose( context : PSDL_RWops ) : Integer; cdecl; - var - stream : TStream; - begin - stream := TStream( context.unknown ); - if ( stream = nil ) then - raise EInvalidContainer.Create( 'SDLStreamClose on nil' ); - stream.Free; - Result := 1; - end; -// ----------------------------------------------- - -function TTextureUnit.LoadImage(const Identifier: string): PSDL_Surface; -var - TexRWops: PSDL_RWops; - TexStream: TStream; - FileName: string; -begin - Result := nil; - TexRWops := nil; - - if Identifier = '' then - exit; - - //Log.LogStatus( Identifier, 'LoadImage' ); - - FileName := Identifier; - - if (FileExistsInsensitive(FileName)) then - begin - // load from file - //Log.LogStatus( 'Is File ( Loading : '+FileName+')', ' LoadImage' ); - try - Result := IMG_Load(PChar(FileName)); - //Log.LogStatus( ' '+inttostr( integer( Result ) ), ' LoadImage' ); - except - Log.LogError('Could not load from file "'+FileName+'"', 'TTextureUnit.LoadImage'); - Exit; - end; - end - else - begin - //Log.LogStatus( 'IS Resource, because file does not exist.('+Identifier+')', ' LoadImage' ); - - TexStream := GetResourceStream(Identifier, 'TEX'); - if (not assigned(TexStream)) then - begin - Log.LogError( 'Invalid file or resource "'+ Identifier+'"', 'TTextureUnit.LoadImage'); - Exit; - end; - - TexRWops := SDL_AllocRW(); - if (TexRWops = nil) then - begin - Log.LogError( 'Could not assign resource "'+Identifier+'"', 'TTextureUnit.LoadImage'); - TexStream.Free(); - Exit; - end; - - // user defined RW-callbacks - with TexRWops^ do - begin - unknown := TUnknown(TexStream); - seek := SDLStreamSeek; - read := SDLStreamRead; - write := nil; - close := SDLStreamClose; - type_ := 2; - end; - - //Log.LogStatus( 'resource Assigned....' , Identifier); - try - Result := IMG_Load_RW(TexRWops, 0); - except - Log.LogError( 'Could not read resource "'+Identifier+'"', 'TTextureUnit.LoadImage'); - end; - - SDL_FreeRW(TexRWops); - TexStream.Free(); - end; -end; - -procedure TTextureUnit.AdjustPixelFormat(var TexSurface: PSDL_Surface; Typ: TTextureType); -var - TempSurface: PSDL_Surface; - NeededPixFmt: PSDL_Pixelformat; -begin - NeededPixFmt:=@PixelFmt_RGBA; - if (Typ = TEXTURE_TYPE_PLAIN) then - NeededPixFmt:=@PixelFmt_RGB - else if (Typ = TEXTURE_TYPE_TRANSPARENT) or - (Typ = TEXTURE_TYPE_COLORIZED) then - NeededPixFmt:=@PixelFmt_RGBA - else - NeededPixFmt:=@PixelFmt_RGB; - - - if not pixfmt_eq(TexSurface^.format, NeededPixFmt) then - begin - TempSurface:=TexSurface; - TexSurface:=SDL_ConvertSurface(TempSurface,NeededPixFmt,SDL_SWSURFACE); - SDL_FreeSurface(TempSurface); - end; -end; - -function TTextureUnit.GetScaledTexture(TexSurface: PSDL_Surface; W,H: Cardinal): PSDL_Surface; -var - TempSurface: PSDL_Surface; -begin - TempSurface:=TexSurface; - Result:=SDL_ScaleSurfaceRect(TempSurface, - 0,0,TempSurface^.W,TempSurface^.H, - W,H); - SDL_FreeSurface(TempSurface); -end; - -procedure TTextureUnit.ScaleTexture(var TexSurface: PSDL_Surface; W,H: Cardinal); -var - TempSurface: PSDL_Surface; -begin - TempSurface:=TexSurface; - TexSurface:=SDL_ScaleSurfaceRect(TempSurface, - 0,0,TempSurface^.W,TempSurface^.H, - W,H); - SDL_FreeSurface(TempSurface); -end; - -procedure TTextureUnit.FitTexture(var TexSurface: PSDL_Surface; W,H: Cardinal); -var - TempSurface: PSDL_Surface; -begin - TempSurface:=TexSurface; - with TempSurface^.format^ do - TexSurface:=SDL_CreateRGBSurface(SDL_SWSURFACE,W,H,BitsPerPixel,RMask, GMask, BMask, AMask); - SDL_SetAlpha(TexSurface, 0, 255); - SDL_SetAlpha(TempSurface, 0, 255); - SDL_BlitSurface(TempSurface,nil,TexSurface,nil); - SDL_FreeSurface(TempSurface); -end; - -procedure TTextureUnit.ColorizeTexture(TexSurface: PSDL_Surface; Col: Cardinal); - //returns hue within range [0.0-6.0) - function col2hue(Color:Cardinal): double; - var - clr: array[0..2] of double; - hue, max, delta: double; - begin - clr[0] := ((Color and $ff0000) shr 16)/255; // R - clr[1] := ((Color and $ff00) shr 8)/255; // G - clr[2] := (Color and $ff) /255; // B - max := maxvalue(clr); - delta := max - minvalue(clr); - // calc hue - if (delta = 0.0) then hue := 0 - else if (clr[0] = max) then hue := (clr[1]-clr[2])/delta - else if (clr[1] = max) then hue := 2.0+(clr[2]-clr[0])/delta - else if (clr[2] = max) then hue := 4.0+(clr[0]-clr[1])/delta; - if (hue < 0.0) then - hue := hue + 6.0; - Result := hue; - end; - -var - DestinationHue: Double; - PixelIndex: Cardinal; - Pixel: PByte; - PixelColors: PByteArray; -// clr: array[0..2] of Double; // [0: R, 1: G, 2: B] - clr2: array[0..2] of Uint32; -// hsv: array[0..2] of Double; // [0: H(ue), 1: S(aturation), 2: V(alue)] - hsv2: array[0..2] of UInt32;//LongInt; - dhue: UInt32;//LongInt; - h_int: Cardinal; -// delta, f, p, q, t: Double; - delta2,f2,p2,q2,t2: Longint;//LongInt; -// max: Double; - max2: Uint32; -begin - DestinationHue := col2hue(Col); - - dhue:=Trunc(DestinationHue*1024); - - Pixel := TexSurface^.Pixels; - - for PixelIndex := 0 to (TexSurface^.W * TexSurface^.H)-1 do - begin - PixelColors:=PByteArray(Pixel); - // inlined colorize per pixel - - // uses fixed point math - // get color values - clr2[0]:=PixelColors[0] shl 10; - clr2[1]:=PixelColors[1] shl 10; - clr2[2]:=PixelColors[2] shl 10; - //calculate luminance and saturation from rgb - - max2:=clr2[0]; - if clr2[1]>max2 then max2:=clr2[1]; - if clr2[2]>max2 then max2:=clr2[2]; - delta2:=clr2[0]; - if clr2[1]= 0. + 1 : origin := soFromCurrent; // Offset is from the current position in the resource. Seek moves to Position + Offset. + 2 : origin := soFromEnd; + else + origin := soFromBeginning; // just in case + end; + Result := stream.Seek( offset, origin ); + end; + + function SdlStreamRead( context : PSDL_RWops; Ptr : Pointer; size : Integer; maxnum: Integer ) : Integer; cdecl; + var + stream : TStream; + begin + stream := TStream( context.unknown ); + if ( stream = nil ) then + raise EInvalidContainer.Create( 'SDLStreamRead on nil' ); + try + Result := stream.read( Ptr^, Size * maxnum ) div size; + except + Result := -1; + end; + end; + + function SDLStreamClose( context : PSDL_RWops ) : Integer; cdecl; + var + stream : TStream; + begin + stream := TStream( context.unknown ); + if ( stream = nil ) then + raise EInvalidContainer.Create( 'SDLStreamClose on nil' ); + stream.Free; + Result := 1; + end; +// ----------------------------------------------- + +function TTextureUnit.LoadImage(const Identifier: string): PSDL_Surface; +var + TexRWops: PSDL_RWops; + TexStream: TStream; + FileName: string; +begin + Result := nil; + TexRWops := nil; + + if Identifier = '' then + exit; + + //Log.LogStatus( Identifier, 'LoadImage' ); + + FileName := Identifier; + + if (FileExistsInsensitive(FileName)) then + begin + // load from file + //Log.LogStatus( 'Is File ( Loading : '+FileName+')', ' LoadImage' ); + try + Result := IMG_Load(PChar(FileName)); + //Log.LogStatus( ' '+inttostr( integer( Result ) ), ' LoadImage' ); + except + Log.LogError('Could not load from file "'+FileName+'"', 'TTextureUnit.LoadImage'); + Exit; + end; + end + else + begin + //Log.LogStatus( 'IS Resource, because file does not exist.('+Identifier+')', ' LoadImage' ); + + TexStream := GetResourceStream(Identifier, 'TEX'); + if (not assigned(TexStream)) then + begin + Log.LogError( 'Invalid file or resource "'+ Identifier+'"', 'TTextureUnit.LoadImage'); + Exit; + end; + + TexRWops := SDL_AllocRW(); + if (TexRWops = nil) then + begin + Log.LogError( 'Could not assign resource "'+Identifier+'"', 'TTextureUnit.LoadImage'); + TexStream.Free(); + Exit; + end; + + // user defined RW-callbacks + with TexRWops^ do + begin + unknown := TUnknown(TexStream); + seek := SDLStreamSeek; + read := SDLStreamRead; + write := nil; + close := SDLStreamClose; + type_ := 2; + end; + + //Log.LogStatus( 'resource Assigned....' , Identifier); + try + Result := IMG_Load_RW(TexRWops, 0); + except + Log.LogError( 'Could not read resource "'+Identifier+'"', 'TTextureUnit.LoadImage'); + end; + + SDL_FreeRW(TexRWops); + TexStream.Free(); + end; +end; + +procedure TTextureUnit.AdjustPixelFormat(var TexSurface: PSDL_Surface; Typ: TTextureType); +var + TempSurface: PSDL_Surface; + NeededPixFmt: PSDL_Pixelformat; +begin + NeededPixFmt:=@PixelFmt_RGBA; + if (Typ = TEXTURE_TYPE_PLAIN) then + NeededPixFmt:=@PixelFmt_RGB + else if (Typ = TEXTURE_TYPE_TRANSPARENT) or + (Typ = TEXTURE_TYPE_COLORIZED) then + NeededPixFmt:=@PixelFmt_RGBA + else + NeededPixFmt:=@PixelFmt_RGB; + + + if not pixfmt_eq(TexSurface^.format, NeededPixFmt) then + begin + TempSurface:=TexSurface; + TexSurface:=SDL_ConvertSurface(TempSurface,NeededPixFmt,SDL_SWSURFACE); + SDL_FreeSurface(TempSurface); + end; +end; + +function TTextureUnit.GetScaledTexture(TexSurface: PSDL_Surface; W,H: Cardinal): PSDL_Surface; +var + TempSurface: PSDL_Surface; +begin + TempSurface:=TexSurface; + Result:=SDL_ScaleSurfaceRect(TempSurface, + 0,0,TempSurface^.W,TempSurface^.H, + W,H); + SDL_FreeSurface(TempSurface); +end; + +procedure TTextureUnit.ScaleTexture(var TexSurface: PSDL_Surface; W,H: Cardinal); +var + TempSurface: PSDL_Surface; +begin + TempSurface:=TexSurface; + TexSurface:=SDL_ScaleSurfaceRect(TempSurface, + 0,0,TempSurface^.W,TempSurface^.H, + W,H); + SDL_FreeSurface(TempSurface); +end; + +procedure TTextureUnit.FitTexture(var TexSurface: PSDL_Surface; W,H: Cardinal); +var + TempSurface: PSDL_Surface; +begin + TempSurface:=TexSurface; + with TempSurface^.format^ do + TexSurface:=SDL_CreateRGBSurface(SDL_SWSURFACE,W,H,BitsPerPixel,RMask, GMask, BMask, AMask); + SDL_SetAlpha(TexSurface, 0, 255); + SDL_SetAlpha(TempSurface, 0, 255); + SDL_BlitSurface(TempSurface,nil,TexSurface,nil); + SDL_FreeSurface(TempSurface); +end; + +procedure TTextureUnit.ColorizeTexture(TexSurface: PSDL_Surface; Col: Cardinal); + //returns hue within range [0.0-6.0) + function col2hue(Color:Cardinal): double; + var + clr: array[0..2] of double; + hue, max, delta: double; + begin + clr[0] := ((Color and $ff0000) shr 16)/255; // R + clr[1] := ((Color and $ff00) shr 8)/255; // G + clr[2] := (Color and $ff) /255; // B + max := maxvalue(clr); + delta := max - minvalue(clr); + // calc hue + if (delta = 0.0) then hue := 0 + else if (clr[0] = max) then hue := (clr[1]-clr[2])/delta + else if (clr[1] = max) then hue := 2.0+(clr[2]-clr[0])/delta + else if (clr[2] = max) then hue := 4.0+(clr[0]-clr[1])/delta; + if (hue < 0.0) then + hue := hue + 6.0; + Result := hue; + end; + +var + DestinationHue: Double; + PixelIndex: Cardinal; + Pixel: PByte; + PixelColors: PByteArray; +// clr: array[0..2] of Double; // [0: R, 1: G, 2: B] + clr2: array[0..2] of Uint32; +// hsv: array[0..2] of Double; // [0: H(ue), 1: S(aturation), 2: V(alue)] + hsv2: array[0..2] of UInt32;//LongInt; + dhue: UInt32;//LongInt; + h_int: Cardinal; +// delta, f, p, q, t: Double; + delta2,f2,p2,q2,t2: Longint;//LongInt; +// max: Double; + max2: Uint32; +begin + DestinationHue := col2hue(Col); + + dhue:=Trunc(DestinationHue*1024); + + Pixel := TexSurface^.Pixels; + + for PixelIndex := 0 to (TexSurface^.W * TexSurface^.H)-1 do + begin + PixelColors:=PByteArray(Pixel); + // inlined colorize per pixel + + // uses fixed point math + // get color values + clr2[0]:=PixelColors[0] shl 10; + clr2[1]:=PixelColors[1] shl 10; + clr2[2]:=PixelColors[2] shl 10; + //calculate luminance and saturation from rgb + + max2:=clr2[0]; + if clr2[1]>max2 then max2:=clr2[1]; + if clr2[2]>max2 then max2:=clr2[2]; + delta2:=clr2[0]; + if clr2[1] Limit) then - newWidth := Limit; - - if (newHeight > Limit) then - newHeight := Limit; - - if (TexSurface.W > newWidth) or (TexSurface.H > newHeight) then - begin - {$ifdef blindydebug} - Log.LogStatus('',' ScaleTexture'); - {$endif} - ScaleTexture(TexSurface,newWidth,newHeight); - {$ifdef blindydebug} - Log.LogStatus('',' ok'); - {$endif} - end; - - {$ifdef blindydebug} - Log.LogStatus('',' JB-1 : typ='+Typ); - {$endif} - - - - // don't actually understand, if this is needed... - // this should definately be changed... together with all this - // cover cache stuff - {if (CreateCacheMipmap) and (Typ = TEXTURE_TYPE_PLAIN) then - begin - {$ifdef blindydebug}{ - Log.LogStatus('',' JB-1 : Minimap'); - {$endif} - - {if (TnWidth <= 256) and (TnHeight <= 256) then - begin - {$ifdef blindydebug}{ - Log.LogStatus('',' GetScaledTexture('''+inttostr(Covers.W)+''','''+inttostr(Covers.H)+''') (for CacheMipmap)'); - {$endif}{ - MipmapSurface:=GetScaledTexture(TexSurface, TnWidth, TnHeight); - if assigned(MipmapSurface) then - begin - {$ifdef blindydebug}{ - Log.LogStatus('',' ok'); - Log.LogStatus('',' BlitSurface Stuff'); - {$endif}{ - // creating and freeing the surface could be done once, if Cover.W and Cover.H don't change - TnSurface:=SDL_CreateRGBSurfaceFrom(@TnBuffer[0], TnWidth, TnHeight, 24, TnWidth*3, $000000ff, $0000ff00, $00ff0000, 0); - SDL_BlitSurface(TnSurface, nil, TnSurface, nil); - SDL_FreeSurface(TnSurface); - {$ifdef blindydebug}{ - Log.LogStatus('',' ok'); - Log.LogStatus('',' SDL_FreeSurface (CacheMipmap)'); - {$endif}{ - SDL_FreeSurface(TnSurface); - {$ifdef blindydebug}{ - Log.LogStatus('',' ok'); - {$endif}{ - end - else - begin - Log.LogStatus(' Error creating CacheMipmap',' LoadTexture('''+Identifier+''')'); - end; - end; - // should i create a cache texture, if Covers.W/H are larger? - end; } - - {$ifdef blindydebug} - Log.LogStatus('',' JB-2'); - {$endif} - - - // now we might colorize the whole thing - if (Typ = TEXTURE_TYPE_COLORIZED) then - ColorizeTexture(TexSurface, Col); - - // save actual dimensions of our texture - oldWidth := newWidth; - oldHeight := newHeight; - // make texture dimensions be powers of 2 - newWidth := Round(Power(2, Ceil(Log2(newWidth)))); - newHeight := Round(Power(2, Ceil(Log2(newHeight)))); - if (newHeight <> oldHeight) or (newWidth <> oldWidth) then - FitTexture(TexSurface, newWidth, newHeight); - - // at this point we have the image in memory... - // scaled to be at most 1024x1024 pixels large - // scaled so that dimensions are powers of 2 - // and converted to either RGB or RGBA - - {$ifdef blindydebug} - Log.LogStatus('',' JB-3'); - {$endif} - - - // if we got a Texture of Type Plain, Transparent or Colorized, - // then we're done manipulating it - // and could now create our openGL texture from it - - // prepare OpenGL texture - - // JB_linux : this is causing AV's on linux... ActText seems to be nil ! -// {$IFnDEF win32} -// if pointer(ActTex) = nil then -// exit; -// {$endif} - - glGenTextures(1, @ActTex); - - glBindTexture(GL_TEXTURE_2D, ActTex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - // load data into gl texture - if (Typ = TEXTURE_TYPE_TRANSPARENT) or - (Typ = TEXTURE_TYPE_COLORIZED) then - begin - glTexImage2D(GL_TEXTURE_2D, 0, 4, newWidth, newHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, TexSurface.pixels); - end - else //if Typ = TEXTURE_TYPE_PLAIN then - begin - glTexImage2D(GL_TEXTURE_2D, 0, 3, newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, TexSurface.pixels); - end; - - {$ifdef blindydebug} - Log.LogStatus('',' JB-5'); - {$endif} - - - Result.X := 0; - Result.Y := 0; - Result.Z := 0; - Result.W := 0; - Result.H := 0; - Result.ScaleW := 1; - Result.ScaleH := 1; - Result.Rot := 0; - Result.TexNum := ActTex; - Result.TexW := oldWidth / newWidth; - Result.TexH := oldHeight / newHeight; - - Result.Int := 1; - Result.ColR := 1; - Result.ColG := 1; - Result.ColB := 1; - Result.Alpha := 1; - - // new test - default use whole texure, taking TexW and TexH as const and changing these - Result.TexX1 := 0; - Result.TexY1 := 0; - Result.TexX2 := 1; - Result.TexY2 := 1; - - {$ifdef blindydebug} - Log.LogStatus('',' JB-6'); - {$endif} - - Result.Name := Identifier; - - SDL_FreeSurface(TexSurface); - - {$ifdef blindydebug} - Log.LogStatus('',' JB-7'); - {$endif} - - - Log.BenchmarkEnd(4); - if Log.BenchmarkTimeLength[4] >= 1 then - Log.LogBenchmark('**********> Texture Load Time Warning - ' + Identifier + '/' + TextureTypeToStr(Typ), 4) - else Log.LogBenchmark('**********> Texture Load Time ' + ExtractFileName(Identifier) + '/' + TextureTypeToStr(Typ), 4); - {$ifdef blindydebug} - Log.LogStatus('',' JB-8'); - {$endif} - -end; - - -function TTextureUnit.GetTexture(const Name: string; Typ: TTextureType; FromCache: boolean): TTexture; -begin - Result := GetTexture(Name, Typ, 0, FromCache); -end; - -function TTextureUnit.GetTexture(const Name: string; Typ: TTextureType; Col: LongWord; FromCache: boolean): TTexture; -var - T: integer; // texture - C: integer; // cover - Data: array of byte; -begin - - if Name = '' then - exit; - - // find texture entry - T := FindTexture(Name, Typ, Col); - - if T = -1 then - begin - // create texture entry - T := Length(TextureDatabase.Texture); - SetLength(TextureDatabase.Texture, T+1); - - TextureDatabase.Texture[T].Name := Name; - TextureDatabase.Texture[T].Typ := Typ; - TextureDatabase.Texture[T].Color := Col; - - // inform database that no textures have been loaded into memory - TextureDatabase.Texture[T].Texture.TexNum := -1; - TextureDatabase.Texture[T].TextureCache.TexNum := -1; - end; - - // use preloaded texture - if (not FromCache) or (FromCache{ and (Covers.CoverExists(Name) < 0)}) then - begin - // use full texture - if TextureDatabase.Texture[T].Texture.TexNum = -1 then - begin - // load texture - {$ifdef blindydebug} - Log.LogStatus('...', 'GetTexture('''+Name+''','''+Typ+''')'); - {$endif} - TextureDatabase.Texture[T].Texture := LoadTexture(false, Name, Typ, Col); - {$ifdef blindydebug} - Log.LogStatus('done',' '); - {$endif} - end; - - // use texture - Result := TextureDatabase.Texture[T].Texture; - end; - - if FromCache and Covers.CoverExists(Name) then - begin - // use cache texture - C := Covers.CoverNumber(Name); - - if TextureDatabase.Texture[T].TextureCache.TexNum = -1 then - begin - // load texture - Covers.PrepareData(Name); - TextureDatabase.Texture[T].TextureCache := CreateTexture(Covers.Data, Name, Covers.Cover[C].W, Covers.Cover[C].H, 24); - end; - - // use texture - Result := TextureDatabase.Texture[T].TextureCache; - end; -end; - -//-------- -// Returns Pointer to an Array of Byte containing the Texture Data in the -// requested Size -//-------- -Function TTextureUnit.GetCoverThumbnail(const Name: string): Pointer; -var - TexSurface: PSDL_Surface; - newHeight, newWidth: Cardinal; -const - Typ = TEXTURE_TYPE_PLAIN; -begin - Result := nil; - If (FileExists(Name)) then - begin - {$ifdef blindydebug} - Log.LogStatus('',' ----------------------------------------------------'); - Log.LogStatus('',' GetCoverThumbnail('''+Name+''')'); - {$endif} - TexSurface := LoadImage(Name); - {$ifdef blindydebug} - Log.LogStatus('',' ok'); - {$endif} - if assigned(TexSurface) then - begin - // convert pixel format as needed - {$ifdef blindydebug} - Log.LogStatus('',' AdjustPixelFormat'); - {$endif} - AdjustPixelFormat(TexSurface, Typ); - - {$ifdef blindydebug} - Log.LogStatus('',' ok'); - {$endif} - - // Scale Texture to Covers Dimensions - {$ifdef blindydebug} - Log.LogStatus('',' ScaleTexture('''+inttostr(tnWidth)+''','''+inttostr(TnHeight)+''') (for CacheMipmap)'); - {$endif} - ScaleTexture(TexSurface, TnWidth, TnHeight); - - if assigned(TexSurface) AND assigned(TnSurface) then - begin - {$ifdef blindydebug} - Log.LogStatus('',' ok'); - Log.LogStatus('',' BlitSurface Stuff'); - {$endif} - - SDL_BlitSurface(TexSurface, nil, TnSurface, nil); - - Result := @TnBuffer[0]; - - {$ifdef blindydebug} - Log.LogStatus('',' ok'); - {$endif} - end - else - Log.LogStatus(' Error creating Cover Thumbnail',' LoadTexture('''+Name+''')'); - end - else - Log.LogError('Could not load texture for Cover Thumbnail: "' + name+' '+ TextureTypeToStr(Typ) +'"', - 'TTextureUnit.GetCoverThumbnail'); - - SDL_FreeSurface(TexSurface); - end; -end; - -//-------- -// Sets Textures Thumbnail Size Vars and Sets LEngth of DataBuffer and Create CoverSurface -//-------- -Procedure TTextureUnit.SetCoverSize(W, H: Integer); -begin - If (H > 0) AND (W > 0) then - begin - TnWidth := W; - TnHeight := H; - - SetLength(TnBuffer, TnWidth * TnHeight * 3); - - //Free if necesary and Create new Surface at Data - If (Assigned(TnSurface)) then - SDL_FreeSurface(TnSurface); - - TnSurface := SDL_CreateRGBSurfaceFrom(@TnBuffer[0], TnWidth, TnHeight, 24, TnWidth*3, $000000ff, $0000ff00, $00ff0000, 0); - end; -end; - -function TTextureUnit.FindTexture(const Name: string; Typ: TTextureType; Col: Cardinal): integer; -var - T: integer; // texture -begin - Result := -1; - for T := 0 to high(TextureDatabase.Texture) do - if (TextureDatabase.Texture[T].Name = Name) and - (TextureDatabase.Texture[T].Typ = Typ) then - begin - // colorized textures must match in their color too - if (TextureDatabase.Texture[T].Typ <> TEXTURE_TYPE_COLORIZED) or - (TextureDatabase.Texture[T].Color = Col) then - begin - Result := T; - break; - end; - end; -end; - -function TTextureUnit.LoadTexture(const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture; -begin - Result := LoadTexture(false, Identifier, Typ, Col); -end; - -function TTextureUnit.LoadTexture(const Identifier: string): TTexture; -begin - Result := LoadTexture(false, Identifier, TEXTURE_TYPE_PLAIN, 0); -end; - -function TTextureUnit.CreateTexture(var Data: array of byte; const Name: string; W, H: word; Bits: byte): TTexture; -var - Position: integer; - Position2: integer; - Pix: integer; - ColInt: real; - PPix: PByteArray; - TempA: integer; - Error: integer; -begin - Mipmapping := false; - - glGenTextures(1, @ActTex); // ActText = new texture number - glBindTexture(GL_TEXTURE_2D, ActTex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexImage2D(GL_TEXTURE_2D, 0, 3, W, H, 0, GL_RGB, GL_UNSIGNED_BYTE, @Data[0]); - if Mipmapping then begin - Error := gluBuild2DMipmaps(GL_TEXTURE_2D, 3, W, H, GL_RGB, GL_UNSIGNED_BYTE, @Data[0]); - if Error > 0 then - Log.LogError('gluBuild2DMipmaps() failed', 'TTextureUnit.CreateTexture'); - end; - - Result.X := 0; - Result.Y := 0; - Result.W := 0; - Result.H := 0; - Result.ScaleW := 1; - Result.ScaleH := 1; - Result.Rot := 0; - Result.TexNum := ActTex; - Result.TexW := 1; - Result.TexH := 1; - - Result.Int := 1; - Result.ColR := 1; - Result.ColG := 1; - Result.ColB := 1; - Result.Alpha := 1; - - // 0.4.2 new test - default use whole texure, taking TexW and TexH as const and changing these - Result.TexX1 := 0; - Result.TexY1 := 0; - Result.TexX2 := 1; - Result.TexY2 := 1; - - // 0.5.0 - Result.Name := Name; -end; - -procedure TTextureUnit.UnloadTexture(const Name: string; Typ: TTextureType; FromCache: boolean); -begin - UnloadTexture(Name, Typ, 0, FromCache); -end; - -procedure TTextureUnit.UnloadTexture(const Name: string; Typ: TTextureType; Col: Cardinal; FromCache: boolean); -var - T: integer; - TexNum: integer; -begin - T := FindTexture(Name, Typ, Col); - - if not FromCache then begin - TexNum := TextureDatabase.Texture[T].Texture.TexNum; - if TexNum >= 0 then begin - glDeleteTextures(1, PGLuint(@TexNum)); - TextureDatabase.Texture[T].Texture.TexNum := -1; -// Log.LogError('Unload texture no '+IntToStr(TexNum)); - end; - end else begin - TexNum := TextureDatabase.Texture[T].TextureCache.TexNum; - if TexNum >= 0 then begin - glDeleteTextures(1, @TexNum); - TextureDatabase.Texture[T].TextureCache.TexNum := -1; -// Log.LogError('Unload texture cache no '+IntToStr(TexNum)); - end; - end; -end; - -(* This needs some work -procedure TTextureUnit.FlushTextureDatabase(); -var - i: integer; - Tex: ^TTexture; -begin - for i := 0 to High(TextureDatabase.Texture) do - begin - // only delete non-cached entries - if (TextureDatabase.Texture[i].Texture.TexNum <> -1) then - begin - Tex := @TextureDatabase.Texture[i].Texture; - glDeleteTextures(1, PGLuint(Tex^.TexNum)); - Tex^.TexNum := -1; - end; - end; -end; -*) - -function TextureTypeToStr(TexType: TTextureType): string; -begin - Result := TextureTypeStr[TexType]; -end; - -function ParseTextureType(const TypeStr: string; Default: TTextureType): TTextureType; -var - TexType: TTextureType; - UpCaseStr: string; -begin - UpCaseStr := UpperCase(TypeStr); - for TexType := Low(TextureTypeStr) to High(TextureTypeStr) do - begin - if (UpCaseStr = UpperCase(TextureTypeStr[TexType])) then - begin - Result := TexType; - Exit; - end; - end; - Log.LogWarn('Unknown texture-type: "' + TypeStr + '"', 'ParseTextureType'); - Result := TEXTURE_TYPE_PLAIN; -end; - -end. + 2: begin clr2[0]:=p2; clr2[1]:=hsv2[2]; clr2[2]:=t2; end; // (p,v,t) + 3: begin clr2[0]:=p2; clr2[1]:=q2; clr2[2]:=hsv2[2]; end; // (p,q,v) + 4: begin clr2[0]:=t2; clr2[1]:=p2; clr2[2]:=hsv2[2]; end; // (t,p,v) + 5: begin clr2[0]:=hsv2[2]; clr2[1]:=p2; clr2[2]:=q2; end; // (v,p,q) + end; + + PixelColors[0]:=clr2[0] shr 10; + PixelColors[1]:=clr2[1] shr 10; + PixelColors[2]:=clr2[2] shr 10; + + // old floating point version +(* clr[0] := PixelColors[0]/255; + clr[1] := PixelColors[1]/255; + clr[2] := PixelColors[2]/255; + max := maxvalue(clr); + delta := max - minvalue(clr); + + hsv[0] := DestinationHue; // set H(ue) + hsv[2] := max; // set V(alue) + // calc S(aturation) + if (max = 0.0) then hsv[1] := 0.0 + else hsv[1] := delta/max; + +// ColorizePixel(PByteArray(Pixel), DestinationHue); + h_int := trunc(hsv[0]); // h_int = |_h_| + f := hsv[0]-h_int; // f = h-h_int + p := hsv[2]*(1.0-hsv[1]); // p = v*(1-s) + q := hsv[2]*(1.0-(hsv[1]*f)); // q = v*(1-s*f) + t := hsv[2]*(1.0-(hsv[1]*(1.0-f))); // t = v*(1-s*(1-f)) + case h_int of + 0: begin clr[0]:=hsv[2]; clr[1]:=t; clr[2]:=p; end; // (v,t,p) + 1: begin clr[0]:=q; clr[1]:=hsv[2]; clr[2]:=p; end; // (q,v,p) + 2: begin clr[0]:=p; clr[1]:=hsv[2]; clr[2]:=t; end; // (p,v,t) + 3: begin clr[0]:=p; clr[1]:=q; clr[2]:=hsv[2]; end; // (p,q,v) + 4: begin clr[0]:=t; clr[1]:=p; clr[2]:=hsv[2]; end; // (t,p,v) + 5: begin clr[0]:=hsv[2]; clr[1]:=p; clr[2]:=q; end; // (v,p,q) + end; + + // and store new rgb back into the image + PixelColors[0] := trunc(255*clr[0]); + PixelColors[1] := trunc(255*clr[1]); + PixelColors[2] := trunc(255*clr[2]); +*) + Inc(Pixel, TexSurface^.format.BytesPerPixel); + end; +end; + +function TTextureUnit.LoadTexture(FromRegistry: boolean; const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture; +var + TexSurface: PSDL_Surface; + MipmapSurface: PSDL_Surface; + newWidth, newHeight: Cardinal; + oldWidth, oldHeight: Cardinal; +begin + Log.BenchmarkStart(4); + Mipmapping := true; +(* + Log.LogStatus( '', '' ); + + if Identifier = nil then + Log.LogStatus(' ERROR unknown Identifier', 'Id:'''+Identifier+''' Fmt:'''+Format+''' Typ:'''+Typ+'''') + else + Log.LogStatus(' should be ok - trying to load', 'Id:'''+Identifier+''' Fmt:'''+Format+''' Typ:'''+Typ+''''); +*) + + // load texture data into memory + {$ifdef blindydebug} + Log.LogStatus('',' ----------------------------------------------------'); + Log.LogStatus('',' LoadImage('''+Identifier+''') (called by '+Format+')'); + {$endif} + TexSurface := LoadImage(Identifier); + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + {$endif} + if not assigned(TexSurface) then + begin + Log.LogError('Could not load texture: "' + Identifier +' '+ TextureTypeToStr(Typ) +'"', + 'TTextureUnit.LoadTexture'); + Exit; + end; + + // convert pixel format as needed + {$ifdef blindydebug} + Log.LogStatus('',' AdjustPixelFormat'); + {$endif} + AdjustPixelFormat(TexSurface, Typ); + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + {$endif} + // adjust texture size (scale down, if necessary) + newWidth := TexSurface.W; + newHeight := TexSurface.H; + + if (newWidth > Limit) then + newWidth := Limit; + + if (newHeight > Limit) then + newHeight := Limit; + + if (TexSurface.W > newWidth) or (TexSurface.H > newHeight) then + begin + {$ifdef blindydebug} + Log.LogStatus('',' ScaleTexture'); + {$endif} + ScaleTexture(TexSurface,newWidth,newHeight); + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + {$endif} + end; + + {$ifdef blindydebug} + Log.LogStatus('',' JB-1 : typ='+Typ); + {$endif} + + + + // don't actually understand, if this is needed... + // this should definately be changed... together with all this + // cover cache stuff + {if (CreateCacheMipmap) and (Typ = TEXTURE_TYPE_PLAIN) then + begin + {$ifdef blindydebug}{ + Log.LogStatus('',' JB-1 : Minimap'); + {$endif} + + {if (TnWidth <= 256) and (TnHeight <= 256) then + begin + {$ifdef blindydebug}{ + Log.LogStatus('',' GetScaledTexture('''+inttostr(Covers.W)+''','''+inttostr(Covers.H)+''') (for CacheMipmap)'); + {$endif}{ + MipmapSurface:=GetScaledTexture(TexSurface, TnWidth, TnHeight); + if assigned(MipmapSurface) then + begin + {$ifdef blindydebug}{ + Log.LogStatus('',' ok'); + Log.LogStatus('',' BlitSurface Stuff'); + {$endif}{ + // creating and freeing the surface could be done once, if Cover.W and Cover.H don't change + TnSurface:=SDL_CreateRGBSurfaceFrom(@TnBuffer[0], TnWidth, TnHeight, 24, TnWidth*3, $000000ff, $0000ff00, $00ff0000, 0); + SDL_BlitSurface(TnSurface, nil, TnSurface, nil); + SDL_FreeSurface(TnSurface); + {$ifdef blindydebug}{ + Log.LogStatus('',' ok'); + Log.LogStatus('',' SDL_FreeSurface (CacheMipmap)'); + {$endif}{ + SDL_FreeSurface(TnSurface); + {$ifdef blindydebug}{ + Log.LogStatus('',' ok'); + {$endif}{ + end + else + begin + Log.LogStatus(' Error creating CacheMipmap',' LoadTexture('''+Identifier+''')'); + end; + end; + // should i create a cache texture, if Covers.W/H are larger? + end; } + + {$ifdef blindydebug} + Log.LogStatus('',' JB-2'); + {$endif} + + + // now we might colorize the whole thing + if (Typ = TEXTURE_TYPE_COLORIZED) then + ColorizeTexture(TexSurface, Col); + + // save actual dimensions of our texture + oldWidth := newWidth; + oldHeight := newHeight; + // make texture dimensions be powers of 2 + newWidth := Round(Power(2, Ceil(Log2(newWidth)))); + newHeight := Round(Power(2, Ceil(Log2(newHeight)))); + if (newHeight <> oldHeight) or (newWidth <> oldWidth) then + FitTexture(TexSurface, newWidth, newHeight); + + // at this point we have the image in memory... + // scaled to be at most 1024x1024 pixels large + // scaled so that dimensions are powers of 2 + // and converted to either RGB or RGBA + + {$ifdef blindydebug} + Log.LogStatus('',' JB-3'); + {$endif} + + + // if we got a Texture of Type Plain, Transparent or Colorized, + // then we're done manipulating it + // and could now create our openGL texture from it + + // prepare OpenGL texture + + // JB_linux : this is causing AV's on linux... ActText seems to be nil ! +// {$IFnDEF win32} +// if pointer(ActTex) = nil then +// exit; +// {$endif} + + glGenTextures(1, @ActTex); + + glBindTexture(GL_TEXTURE_2D, ActTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + // load data into gl texture + if (Typ = TEXTURE_TYPE_TRANSPARENT) or + (Typ = TEXTURE_TYPE_COLORIZED) then + begin + glTexImage2D(GL_TEXTURE_2D, 0, 4, newWidth, newHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, TexSurface.pixels); + end + else //if Typ = TEXTURE_TYPE_PLAIN then + begin + glTexImage2D(GL_TEXTURE_2D, 0, 3, newWidth, newHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, TexSurface.pixels); + end; + + {$ifdef blindydebug} + Log.LogStatus('',' JB-5'); + {$endif} + + + Result.X := 0; + Result.Y := 0; + Result.Z := 0; + Result.W := 0; + Result.H := 0; + Result.ScaleW := 1; + Result.ScaleH := 1; + Result.Rot := 0; + Result.TexNum := ActTex; + Result.TexW := oldWidth / newWidth; + Result.TexH := oldHeight / newHeight; + + Result.Int := 1; + Result.ColR := 1; + Result.ColG := 1; + Result.ColB := 1; + Result.Alpha := 1; + + // new test - default use whole texure, taking TexW and TexH as const and changing these + Result.TexX1 := 0; + Result.TexY1 := 0; + Result.TexX2 := 1; + Result.TexY2 := 1; + + {$ifdef blindydebug} + Log.LogStatus('',' JB-6'); + {$endif} + + Result.Name := Identifier; + + SDL_FreeSurface(TexSurface); + + {$ifdef blindydebug} + Log.LogStatus('',' JB-7'); + {$endif} + + + Log.BenchmarkEnd(4); + if Log.BenchmarkTimeLength[4] >= 1 then + Log.LogBenchmark('**********> Texture Load Time Warning - ' + Identifier + '/' + TextureTypeToStr(Typ), 4) + else Log.LogBenchmark('**********> Texture Load Time ' + ExtractFileName(Identifier) + '/' + TextureTypeToStr(Typ), 4); + {$ifdef blindydebug} + Log.LogStatus('',' JB-8'); + {$endif} + +end; + + +function TTextureUnit.GetTexture(const Name: string; Typ: TTextureType; FromCache: boolean): TTexture; +begin + Result := GetTexture(Name, Typ, 0, FromCache); +end; + +function TTextureUnit.GetTexture(const Name: string; Typ: TTextureType; Col: LongWord; FromCache: boolean): TTexture; +var + T: integer; // texture + C: integer; // cover + Data: array of byte; +begin + + if Name = '' then + exit; + + // find texture entry + T := FindTexture(Name, Typ, Col); + + if T = -1 then + begin + // create texture entry + T := Length(TextureDatabase.Texture); + SetLength(TextureDatabase.Texture, T+1); + + TextureDatabase.Texture[T].Name := Name; + TextureDatabase.Texture[T].Typ := Typ; + TextureDatabase.Texture[T].Color := Col; + + // inform database that no textures have been loaded into memory + TextureDatabase.Texture[T].Texture.TexNum := 0; + TextureDatabase.Texture[T].TextureCache.TexNum := 0; + end; + + // use preloaded texture + if (not FromCache) or (FromCache{ and (Covers.CoverExists(Name) < 0)}) then + begin + // use full texture + if TextureDatabase.Texture[T].Texture.TexNum = 0 then + begin + // load texture + {$ifdef blindydebug} + Log.LogStatus('...', 'GetTexture('''+Name+''','''+Typ+''')'); + {$endif} + TextureDatabase.Texture[T].Texture := LoadTexture(false, Name, Typ, Col); + {$ifdef blindydebug} + Log.LogStatus('done',' '); + {$endif} + end; + + // use texture + Result := TextureDatabase.Texture[T].Texture; + end; + + if FromCache and Covers.CoverExists(Name) then + begin + // use cache texture + C := Covers.CoverNumber(Name); + + if TextureDatabase.Texture[T].TextureCache.TexNum = 0 then + begin + // load texture + Covers.PrepareData(Name); + TextureDatabase.Texture[T].TextureCache := CreateTexture(Covers.Data, Name, Covers.Cover[C].W, Covers.Cover[C].H, 24); + end; + + // use texture + Result := TextureDatabase.Texture[T].TextureCache; + end; +end; + +//-------- +// Returns Pointer to an Array of Byte containing the Texture Data in the +// requested Size +//-------- +Function TTextureUnit.GetCoverThumbnail(const Name: string): Pointer; +var + TexSurface: PSDL_Surface; + newHeight, newWidth: Cardinal; +const + Typ = TEXTURE_TYPE_PLAIN; +begin + Result := nil; + If (FileExists(Name)) then + begin + {$ifdef blindydebug} + Log.LogStatus('',' ----------------------------------------------------'); + Log.LogStatus('',' GetCoverThumbnail('''+Name+''')'); + {$endif} + TexSurface := LoadImage(Name); + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + {$endif} + if assigned(TexSurface) then + begin + // convert pixel format as needed + {$ifdef blindydebug} + Log.LogStatus('',' AdjustPixelFormat'); + {$endif} + AdjustPixelFormat(TexSurface, Typ); + + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + {$endif} + + // Scale Texture to Covers Dimensions + {$ifdef blindydebug} + Log.LogStatus('',' ScaleTexture('''+inttostr(tnWidth)+''','''+inttostr(TnHeight)+''') (for CacheMipmap)'); + {$endif} + ScaleTexture(TexSurface, TnWidth, TnHeight); + + if assigned(TexSurface) AND assigned(TnSurface) then + begin + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + Log.LogStatus('',' BlitSurface Stuff'); + {$endif} + + SDL_BlitSurface(TexSurface, nil, TnSurface, nil); + + Result := @TnBuffer[0]; + + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + {$endif} + end + else + Log.LogStatus(' Error creating Cover Thumbnail',' LoadTexture('''+Name+''')'); + end + else + Log.LogError('Could not load texture for Cover Thumbnail: "' + name+' '+ TextureTypeToStr(Typ) +'"', + 'TTextureUnit.GetCoverThumbnail'); + + SDL_FreeSurface(TexSurface); + end; +end; + +//-------- +// Sets Textures Thumbnail Size Vars and Sets LEngth of DataBuffer and Create CoverSurface +//-------- +Procedure TTextureUnit.SetCoverSize(W, H: Integer); +begin + If (H > 0) AND (W > 0) then + begin + TnWidth := W; + TnHeight := H; + + SetLength(TnBuffer, TnWidth * TnHeight * 3); + + //Free if necesary and Create new Surface at Data + If (Assigned(TnSurface)) then + SDL_FreeSurface(TnSurface); + + TnSurface := SDL_CreateRGBSurfaceFrom(@TnBuffer[0], TnWidth, TnHeight, 24, TnWidth*3, $000000ff, $0000ff00, $00ff0000, 0); + end; +end; + +function TTextureUnit.FindTexture(const Name: string; Typ: TTextureType; Col: Cardinal): integer; +var + T: integer; // texture +begin + Result := -1; + for T := 0 to high(TextureDatabase.Texture) do + if (TextureDatabase.Texture[T].Name = Name) and + (TextureDatabase.Texture[T].Typ = Typ) then + begin + // colorized textures must match in their color too + if (TextureDatabase.Texture[T].Typ <> TEXTURE_TYPE_COLORIZED) or + (TextureDatabase.Texture[T].Color = Col) then + begin + Result := T; + break; + end; + end; +end; + +function TTextureUnit.LoadTexture(const Identifier: string; Typ: TTextureType; Col: LongWord): TTexture; +begin + Result := LoadTexture(false, Identifier, Typ, Col); +end; + +function TTextureUnit.LoadTexture(const Identifier: string): TTexture; +begin + Result := LoadTexture(false, Identifier, TEXTURE_TYPE_PLAIN, 0); +end; + +function TTextureUnit.CreateTexture(var Data: array of byte; const Name: string; W, H: word; Bits: byte): TTexture; +var + Position: integer; + Position2: integer; + Pix: integer; + ColInt: real; + PPix: PByteArray; + TempA: integer; + Error: integer; +begin + Mipmapping := false; + + glGenTextures(1, @ActTex); // ActText = new texture number + glBindTexture(GL_TEXTURE_2D, ActTex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_2D, 0, 3, W, H, 0, GL_RGB, GL_UNSIGNED_BYTE, @Data[0]); + if Mipmapping then begin + Error := gluBuild2DMipmaps(GL_TEXTURE_2D, 3, W, H, GL_RGB, GL_UNSIGNED_BYTE, @Data[0]); + if Error > 0 then + Log.LogError('gluBuild2DMipmaps() failed', 'TTextureUnit.CreateTexture'); + end; + + Result.X := 0; + Result.Y := 0; + Result.W := 0; + Result.H := 0; + Result.ScaleW := 1; + Result.ScaleH := 1; + Result.Rot := 0; + Result.TexNum := ActTex; + Result.TexW := 1; + Result.TexH := 1; + + Result.Int := 1; + Result.ColR := 1; + Result.ColG := 1; + Result.ColB := 1; + Result.Alpha := 1; + + // 0.4.2 new test - default use whole texure, taking TexW and TexH as const and changing these + Result.TexX1 := 0; + Result.TexY1 := 0; + Result.TexX2 := 1; + Result.TexY2 := 1; + + // 0.5.0 + Result.Name := Name; +end; + +procedure TTextureUnit.UnloadTexture(const Name: string; Typ: TTextureType; FromCache: boolean); +begin + UnloadTexture(Name, Typ, 0, FromCache); +end; + +procedure TTextureUnit.UnloadTexture(const Name: string; Typ: TTextureType; Col: Cardinal; FromCache: boolean); +var + T: integer; + TexNum: GLuint; +begin + T := FindTexture(Name, Typ, Col); + + if not FromCache then begin + TexNum := TextureDatabase.Texture[T].Texture.TexNum; + if TexNum > 0 then begin + glDeleteTextures(1, PGLuint(@TexNum)); + TextureDatabase.Texture[T].Texture.TexNum := 0; +// Log.LogError('Unload texture no '+IntToStr(TexNum)); + end; + end else begin + TexNum := TextureDatabase.Texture[T].TextureCache.TexNum; + if TexNum > 0 then begin + glDeleteTextures(1, @TexNum); + TextureDatabase.Texture[T].TextureCache.TexNum := 0; +// Log.LogError('Unload texture cache no '+IntToStr(TexNum)); + end; + end; +end; + +(* This needs some work +procedure TTextureUnit.FlushTextureDatabase(); +var + i: integer; + Tex: ^TTexture; +begin + for i := 0 to High(TextureDatabase.Texture) do + begin + // only delete non-cached entries + if (TextureDatabase.Texture[i].Texture.TexNum > 0) then + begin + Tex := @TextureDatabase.Texture[i].Texture; + glDeleteTextures(1, PGLuint(Tex^.TexNum)); + Tex^.TexNum := 0; + end; + end; +end; +*) + +function TextureTypeToStr(TexType: TTextureType): string; +begin + Result := TextureTypeStr[TexType]; +end; + +function ParseTextureType(const TypeStr: string; Default: TTextureType): TTextureType; +var + TexType: TTextureType; + UpCaseStr: string; +begin + UpCaseStr := UpperCase(TypeStr); + for TexType := Low(TextureTypeStr) to High(TextureTypeStr) do + begin + if (UpCaseStr = UpperCase(TextureTypeStr[TexType])) then + begin + Result := TexType; + Exit; + end; + end; + Log.LogWarn('Unknown texture-type: "' + TypeStr + '"', 'ParseTextureType'); + Result := TEXTURE_TYPE_PLAIN; +end; + +end. diff --git a/Game/Code/Menu/UMenu.pas b/Game/Code/Menu/UMenu.pas index 5be44859..04a63b0a 100644 --- a/Game/Code/Menu/UMenu.pas +++ b/Game/Code/Menu/UMenu.pas @@ -1,1585 +1,1585 @@ -unit UMenu; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - -uses OpenGL12, SysUtils, UTexture, UMenuStatic, UMenuText, UMenuButton, UMenuSelect, UMenuSelectSlide, - UMenuInteract, UThemes, UMenuButtonCollection, Math, UMusic; - -type -{ Int16 = SmallInt;} - - PMenu = ^TMenu; - TMenu = class - protected - ButtonPos: Integer; - - Interactions: array of TInteract; - SelInteraction: integer; - Button: array of TButton; - Selects: array of TSelect; - SelectsS: array of TSelectSlide; - ButtonCollection: array of TButtonCollection; - BackImg: TTexture; - BackW: integer; - BackH: integer; - - fFileName : string; - public - Text: array of TText; - Static: array of TStatic; - mX: integer; // mouse X - mY: integer; // mouse Y - - Fade: integer; // fade type - ShowFinish: boolean; // true if there is no fade - - - destructor Destroy; override; - constructor Create; overload; virtual; - //constructor Create(Back: string); overload; virtual; // Back is a JPG resource name for background - //constructor Create(Back: string; W, H: integer); overload; virtual; // W and H are the number of overlaps - - // interaction - function WideCharUpperCase(wchar: WideChar) : WideString; - procedure AddInteraction(Typ, Num: integer); - procedure SetInteraction(Num: integer); - property Interaction: integer read SelInteraction write SetInteraction; - - //Procedure Load BG, Texts, Statics and Button Collections from ThemeBasic - procedure LoadFromTheme(const ThemeBasic: TThemeBasic); - - procedure PrepareButtonCollections(const Collections: AThemeButtonCollection); - procedure AddButtonCollection(const ThemeCollection: TThemeButtonCollection; Const Num: Byte); - - // background - procedure AddBackground(Name: string); - - // static - function AddStatic(ThemeStatic: TThemeStatic): integer; overload; - function AddStatic(X, Y, W, H: real; const Name: string): integer; overload; - function AddStatic(X, Y, W, H: real; const Name: string; Typ: TTextureType): integer; overload; - function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; overload; - function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; overload; - function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; overload; - function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; overload; - function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; TexX1, TexY1, TexX2, TexY2: real; const Name: string; Typ: TTextureType; Color: integer; Reflection: Boolean; ReflectionSpacing: Real): integer; overload; - - // text - function AddText(ThemeText: TThemeText): integer; overload; - function AddText(X, Y: real; const Text_: string): integer; overload; - function AddText(X, Y: real; Style: integer; Size, ColR, ColG, ColB: real; const Text: string): integer; overload; - function AddText(X, Y, W: real; Style: integer; Size, ColR, ColG, ColB: real; Align: integer; const Text_: string): integer; overload; - - // button - Procedure SetButtonLength(Length: Cardinal); //Function that Set Length of Button Array in one Step instead of register new Memory for every Button - function AddButton(ThemeButton: TThemeButton): integer; overload; - function AddButton(X, Y, W, H: real; const Name: String): integer; overload; - function AddButton(X, Y, W, H: real; const Name: String; Typ: TTextureType; Reflection: Boolean): integer; overload; - function AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real; const Name: String; Typ: TTextureType; Reflection: Boolean; ReflectionSpacing, DeSelectReflectionSpacing: Real): integer; overload; - procedure ClearButtons; - procedure AddButtonText(AddX, AddY: real; const AddText: string); overload; - procedure AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; const AddText: string); overload; - procedure AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); overload; - procedure AddButtonText(CustomButton: TButton; AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); overload; - - // select - function AddSelect(ThemeSelect: TThemeSelect; var Data: integer; Values: array of string): integer; overload; - function AddSelect(X, Y, W, H, SkipX, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt, - TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt, - SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt, - STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real; - const Name: String; Typ: TTextureType; const SBGName: String; SBGTyp: TTextureType; - const Caption: string; var Data: integer): integer; overload; - procedure AddSelectOption(AddX, AddY: real; const AddText: string); overload; - procedure AddSelectOption(SelectNo: Cardinal; AddX, AddY: real; const AddText: string); overload; - procedure UpdateSelectOptions(ThemeSelect: TThemeSelect; SelectNum: integer; Values: array of string; var Data: integer); - - // select slide - function AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; Values: array of string): integer; overload; - function AddSelectSlide(X, Y, W, H, SkipX, SBGW, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt, - TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt, - SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt, - STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real; - const Name: String; Typ: TTextureType; const SBGName: String; SBGTyp: TTextureType; - const Caption: string; var Data: integer): integer; overload; - procedure AddSelectSlideOption(const AddText: string); overload; - procedure AddSelectSlideOption(SelectNo: Cardinal; const AddText: string); overload; - procedure UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; Values: array of string; var Data: integer); - - -// function AddWidget(X, Y : UInt16; WidgetSrc : PSDL_Surface): Int16; -// procedure ClearWidgets(MinNumber : Int16); - procedure FadeTo(Screen: PMenu); overload; - procedure FadeTo(Screen: PMenu; aSound: TAudioPlaybackStream); overload; - //popup hack - procedure CheckFadeTo(Screen: PMenu; msg: String); - - function DrawBG: boolean; virtual; - function DrawFG: boolean; virtual; - function Draw: boolean; virtual; - function ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown : Boolean): Boolean; virtual; - // FIXME: ParseMouse is not implemented in any subclass and not even used anywhere in the code - // -> do this before activation of this method - //function ParseMouse(Typ: integer; X: integer; Y: integer): Boolean; virtual; abstract; - function InRegion(X1, Y1, X2, Y2, X, Y: real): Boolean; - function InStaticRegion(StaticNr: integer; X, Y: integer): Boolean; - procedure onShow; virtual; - procedure onShowFinish; virtual; - procedure onHide; virtual; - - procedure SetAnimationProgress(Progress: real); virtual; - - function IsSelectable(Int: Cardinal): Boolean; - - procedure InteractNext; virtual; - procedure InteractCustom(CustomSwitch: integer); virtual; - procedure InteractPrev; virtual; - procedure InteractInc; virtual; - procedure InteractDec; virtual; - - procedure AddBox(X, Y, W, H: real); - end; - -const - pmMove = 1; - pmClick = 2; - pmUnClick = 3; - - iButton = 0; // interaction type - iSelect = 1; - iText = 2; - iSelectS = 3; - iBCollectionChild = 5; - -// fBlack = 0; // fade type -// fWhite = 1; - -implementation - -uses UCommon, - ULog, - UMain, - UDrawTexture, - UGraphic, - UDisplay, - UCovers, - USkins; - -destructor TMenu.Destroy; -begin - inherited; -end; - -constructor TMenu.Create; -begin - Fade := 0;//fWhite; - - SetLength(Static, 0); - SetLength(Button, 0); - - BackImg.TexNum := -1; - - //Set ButtonPos to Autoset Length - ButtonPos := -1; - - - VideoPlayback.Init; -end; -{ -constructor TMenu.Create(Back: String); -begin - inherited Create; - - if Back <> '' then begin -// BackImg := Texture.GetTexture(true, Back, TEXTURE_TYPE_PLAIN, 0); - BackImg := Texture.GetTexture(Back, TEXTURE_TYPE_PLAIN, 0); // new theme system - BackImg.W := 800;//640; - BackImg.H := 600;//480; - BackW := 1; - BackH := 1; - end else - BackImg.TexNum := -1; - - //Set ButtonPos to Autoset Length - ButtonPos := -1; -end; - -constructor TMenu.Create(Back: string; W, H: integer); -begin - Create(Back); - BackImg.W := BackImg.W / W; - BackImg.H := BackImg.H / H; - BackW := W; - BackH := H; -end; } - -function RGBFloatToInt(R, G, B: Double): Cardinal; -begin - Result := (Trunc(255 * R) shl 16) or - (Trunc(255 * G) shl 8) or - Trunc(255 * B); -end; - -procedure TMenu.AddInteraction(Typ, Num: integer); -var - IntNum: integer; -begin - IntNum := Length(Interactions); - SetLength(Interactions, IntNum+1); - Interactions[IntNum].Typ := Typ; - Interactions[IntNum].Num := Num; - Interaction := 0; -end; - -procedure TMenu.SetInteraction(Num: integer); -var - OldNum, OldTyp: integer; - NewNum, NewTyp: integer; -begin - // set inactive - OldNum := Interactions[Interaction].Num; - OldTyp := Interactions[Interaction].Typ; - - NewNum := Interactions[Num].Num; - NewTyp := Interactions[Num].Typ; - - case OldTyp of - iButton: Button[OldNum].Selected := False; - iSelect: Selects[OldNum].Selected := False; - iText: Text[OldNum].Selected := False; - iSelectS: SelectsS[OldNum].Selected := False; - //Button Collection Mod - iBCollectionChild: - begin - Button[OldNum].Selected := False; - - //Deselect Collection if Next Button is Not from Collection - if (NewTyp <> iButton) Or (Button[NewNum].Parent <> Button[OldNum].Parent) then - ButtonCollection[Button[OldNum].Parent-1].Selected := False; - end; - end; - - // set active - SelInteraction := Num; - case NewTyp of - iButton: Button[NewNum].Selected := True; - iSelect: Selects[NewNum].Selected := True; - iText: Text[NewNum].Selected := True; - iSelectS: SelectsS[NewNum].Selected := True; - - //Button Collection Mod - iBCollectionChild: - begin - Button[NewNum].Selected := True; - ButtonCollection[Button[NewNum].Parent-1].Selected := True; - end; - end; -end; - -//---------------------- -//LoadFromTheme - Load BG, Texts, Statics and -//Button Collections from ThemeBasic -//---------------------- -procedure TMenu.LoadFromTheme(const ThemeBasic: TThemeBasic); -var - I: Integer; -begin - //Add Button Collections (Set Button CollectionsLength) - //Button Collections are Created when the first ChildButton is Created - PrepareButtonCollections(ThemeBasic.ButtonCollection); - - //Add Background - AddBackground(ThemeBasic.Background.Tex); - - //Add Statics and Texts - for I := 0 to High(ThemeBasic.Static) do - AddStatic(ThemeBasic.Static[I]); - - for I := 0 to High(ThemeBasic.Text) do - AddText(ThemeBasic.Text[I]); -end; - -procedure TMenu.AddBackground(Name: string); -//var -// lFileName : string; -begin - if Name <> '' then - begin - fFileName := Skin.GetTextureFileName(Name); - fFileName := AdaptFilePaths( fFileName ); - - if fileexists( fFileName ) then - begin - BackImg := Texture.GetTexture( fFileName , TEXTURE_TYPE_PLAIN); - - if ( BackImg.TexNum < 1 ) then - begin - if VideoPlayback.Open( fFileName ) then - VideoPlayback.Play; - end; - - BackImg.W := 800; - BackImg.H := 600; - BackW := 1; - BackH := 1; - end; - end; -end; - -//---------------------- -//PrepareButtonCollections: -//Add Button Collections (Set Button CollectionsLength) -//---------------------- -procedure TMenu.PrepareButtonCollections(const Collections: AThemeButtonCollection); -var - I: Integer; -begin - SetLength(ButtonCollection, Length(Collections)); - For I := 0 to High(ButtonCollection) do - AddButtonCollection(Collections[I], I); -end; - -//---------------------- -//AddButtonCollection: -//Create a Button Collection; -//---------------------- -procedure TMenu.AddButtonCollection(const ThemeCollection: TThemeButtonCollection; Const Num: Byte); -var - BT, BTLen: Integer; - TempCol, TempDCol: Cardinal; - -begin - if (Num > High(ButtonCollection)) then - exit; - - TempCol := 0; - - // colorize hack - if (ThemeCollection.Style.Typ = TEXTURE_TYPE_COLORIZED) then - begin - TempCol := RGBFloatToInt(ThemeCollection.Style.ColR, ThemeCollection.Style.ColG, ThemeCollection.Style.ColB); - TempDCol := RGBFloatToInt(ThemeCollection.Style.DColR, ThemeCollection.Style.DColG, ThemeCollection.Style.DColB); - // give encoded color to GetTexture() - ButtonCollection[Num] := TButtonCollection.Create( - Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.Tex), TEXTURE_TYPE_COLORIZED, TempCol), - Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.Tex), TEXTURE_TYPE_COLORIZED, TempDCol)); - end - else - begin - ButtonCollection[Num] := TButtonCollection.Create(Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.Tex), ThemeCollection.Style.Typ, true)); // use cache texture - end; - - //Set Parent menu - ButtonCollection[Num].ScreenButton := @Self.Button; - - //Set Attributes - ButtonCollection[Num].FirstChild := ThemeCollection.FirstChild; - ButtonCollection[Num].CountChilds := ThemeCollection.ChildCount; - ButtonCollection[Num].Parent := Num + 1; - - //Set Style - ButtonCollection[Num].X := ThemeCollection.Style.X; - ButtonCollection[Num].Y := ThemeCollection.Style.Y; - ButtonCollection[Num].W := ThemeCollection.Style.W; - ButtonCollection[Num].H := ThemeCollection.Style.H; - if (ThemeCollection.Style.Typ <> TEXTURE_TYPE_COLORIZED) then begin - ButtonCollection[Num].SelectColR := ThemeCollection.Style.ColR; - ButtonCollection[Num].SelectColG := ThemeCollection.Style.ColG; - ButtonCollection[Num].SelectColB := ThemeCollection.Style.ColB; - ButtonCollection[Num].DeselectColR := ThemeCollection.Style.DColR; - ButtonCollection[Num].DeselectColG := ThemeCollection.Style.DColG; - ButtonCollection[Num].DeselectColB := ThemeCollection.Style.DColB; - end; - ButtonCollection[Num].SelectInt := ThemeCollection.Style.Int; - ButtonCollection[Num].DeselectInt := ThemeCollection.Style.DInt; - ButtonCollection[Num].Texture.TexX1 := 0; - ButtonCollection[Num].Texture.TexY1 := 0; - ButtonCollection[Num].Texture.TexX2 := 1; - ButtonCollection[Num].Texture.TexY2 := 1; - ButtonCollection[Num].SetSelect(false); - - ButtonCollection[Num].Reflection := ThemeCollection.Style.Reflection; - ButtonCollection[Num].Reflectionspacing := ThemeCollection.Style.ReflectionSpacing; - ButtonCollection[Num].DeSelectReflectionspacing := ThemeCollection.Style.DeSelectReflectionSpacing; - - ButtonCollection[Num].Z := ThemeCollection.Style.Z; - - //Some Things from ButtonFading - ButtonCollection[Num].SelectH := ThemeCollection.Style.SelectH; - ButtonCollection[Num].SelectW := ThemeCollection.Style.SelectW; - - ButtonCollection[Num].Fade := ThemeCollection.Style.Fade; - ButtonCollection[Num].FadeText := ThemeCollection.Style.FadeText; - if (ThemeCollection.Style.Typ = TEXTURE_TYPE_COLORIZED) then - ButtonCollection[Num].FadeTex := Texture.GetTexture( - Skin.GetTextureFileName(ThemeCollection.Style.FadeTex), TEXTURE_TYPE_COLORIZED, TempCol) - else - ButtonCollection[Num].FadeTex := Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.FadeTex), ThemeCollection.Style.Typ, true); - ButtonCollection[Num].FadeTexPos := ThemeCollection.Style.FadeTexPos; - - - BTLen := Length(ThemeCollection.Style.Text); - for BT := 0 to BTLen-1 do begin - AddButtonText(ButtonCollection[Num], ThemeCollection.Style.Text[BT].X, ThemeCollection.Style.Text[BT].Y, - ThemeCollection.Style.Text[BT].ColR, ThemeCollection.Style.Text[BT].ColG, ThemeCollection.Style.Text[BT].ColB, - ThemeCollection.Style.Text[BT].Font, ThemeCollection.Style.Text[BT].Size, ThemeCollection.Style.Text[BT].Align, - ThemeCollection.Style.Text[BT].Text); - end; -end; - -function TMenu.AddStatic(ThemeStatic: TThemeStatic): integer; -begin - Result := AddStatic(ThemeStatic.X, ThemeStatic.Y, ThemeStatic.W, ThemeStatic.H, ThemeStatic.Z, - ThemeStatic.ColR, ThemeStatic.ColG, ThemeStatic.ColB, - ThemeStatic.TexX1, ThemeStatic.TexY1, ThemeStatic.TexX2, ThemeStatic.TexY2, - Skin.GetTextureFileName(ThemeStatic.Tex), - ThemeStatic.Typ, $FFFFFF, ThemeStatic.Reflection, ThemeStatic.Reflectionspacing); -end; - -function TMenu.AddStatic(X, Y, W, H: real; const Name: string): integer; -begin - Result := AddStatic(X, Y, W, H, Name, TEXTURE_TYPE_PLAIN); -end; - -function TMenu.AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; -var - StatNum: integer; -begin - Result := AddStatic(X, Y, W, H, ColR, ColG, ColB, Name, Typ, $FFFFFF); -end; - -function TMenu.AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; -var - StatNum: integer; -begin - Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, Name, Typ, $FFFFFF); -end; - -function TMenu.AddStatic(X, Y, W, H: real; const Name: string; Typ: TTextureType): integer; -var - StatNum: integer; -begin - // adds static - StatNum := Length(Static); - SetLength(Static, StatNum + 1); - Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, $FF00FF)); // new skin - - // configures static - Static[StatNum].Texture.X := X; - Static[StatNum].Texture.Y := Y; - Static[StatNum].Texture.W := W; - Static[StatNum].Texture.H := H; - Static[StatNum].Visible := true; - Result := StatNum; -end; - -function TMenu.AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; -var - StatNum: integer; -begin - Result := AddStatic(X, Y, W, H, 0, ColR, ColG, ColB, Name, Typ, Color); -end; - -function TMenu.AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; -begin - Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, 0, 0, 1, 1, Name, Typ, Color, False, 0); -end; - -function TMenu.AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; TexX1, TexY1, TexX2, TexY2: real; const Name: string; Typ: TTextureType; Color: integer; Reflection: Boolean; ReflectionSpacing: Real): integer; -var - StatNum: integer; -begin - // adds static - StatNum := Length(Static); - SetLength(Static, StatNum + 1); - - // colorize hack - if (Typ = TEXTURE_TYPE_COLORIZED) then - begin - // give encoded color to GetTexture() - Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB))); - end - else - begin - Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, Color)); // new skin - end; - - // configures static - Static[StatNum].Texture.X := X; - Static[StatNum].Texture.Y := Y; - Static[StatNum].Texture.W := W; - Static[StatNum].Texture.H := H; - Static[StatNum].Texture.Z := Z; - if (Typ <> TEXTURE_TYPE_COLORIZED) then begin - Static[StatNum].Texture.ColR := ColR; - Static[StatNum].Texture.ColG := ColG; - Static[StatNum].Texture.ColB := ColB; - end; - Static[StatNum].Texture.TexX1 := TexX1; - Static[StatNum].Texture.TexY1 := TexY1; - Static[StatNum].Texture.TexX2 := TexX2; - Static[StatNum].Texture.TexY2 := TexY2; - Static[StatNum].Texture.Alpha := 1; - Static[StatNum].Visible := true; - - //ReflectionMod - Static[StatNum].Reflection := Reflection; - Static[StatNum].ReflectionSpacing := ReflectionSpacing; - - Result := StatNum; -end; - -function TMenu.AddText(ThemeText: TThemeText): integer; -begin - Result := AddText(ThemeText.X, ThemeText.Y, ThemeText.W, ThemeText.Font, ThemeText.Size, - ThemeText.ColR, ThemeText.ColG, ThemeText.ColB, ThemeText.Align, ThemeText.Text); -end; - -function TMenu.AddText(X, Y: real; const Text_: string): integer; -var - TextNum: integer; -begin - // adds text - TextNum := Length(Text); - SetLength(Text, TextNum + 1); - Text[TextNum] := TText.Create(X, Y, Text_); - Result := TextNum; -end; - -function TMenu.AddText(X, Y: real; Style: integer; Size, ColR, ColG, ColB: real; const Text: string): integer; -begin - Result := AddText(X, Y, 0, Style, Size, ColR, ColG, ColB, 0, Text); -end; - -function TMenu.AddText(X, Y, W: real; Style: integer; Size, ColR, ColG, ColB: real; Align: integer; const Text_: string): integer; -var - TextNum: integer; -begin - // adds text - TextNum := Length(Text); - SetLength(Text, TextNum + 1); - Text[TextNum] := TText.Create(X, Y, W, Style, Size, ColR, ColG, ColB, Align, Text_); - Result := TextNum; -end; - -//Function that Set Length of Button Array in one Step instead of register new Memory for every Button -Procedure TMenu.SetButtonLength(Length: Cardinal); -begin - if (ButtonPos = -1) AND (Length > 0) then - begin - //Set Length of Button - SetLength(Button, Length); - - //Set ButtonPos to start with 0 - ButtonPos := 0; - end; -end; - - -// Method to add a button in our TMenu. It returns the assigned ButtonNumber -function TMenu.AddButton(ThemeButton: TThemeButton): integer; -var - BT: integer; - BTLen: integer; - temp: integer; - TempR, TempG, TempB, TempR2, TempG2, TempB2: Cardinal; -begin - Result := AddButton(ThemeButton.X, ThemeButton.Y, ThemeButton.W, ThemeButton.H, - ThemeButton.ColR, ThemeButton.ColG, ThemeButton.ColB, ThemeButton.Int, - ThemeButton.DColR, ThemeButton.DColG, ThemeButton.DColB, ThemeButton.DInt, - Skin.GetTextureFileName(ThemeButton.Tex), ThemeButton.Typ, - ThemeButton.Reflection, ThemeButton.Reflectionspacing, ThemeButton.DeSelectReflectionspacing); - - Button[Result].Z := ThemeButton.Z; - - //Button Visibility - Button[Result].Visible := ThemeButton.Visible; - - //Some Things from ButtonFading - Button[Result].SelectH := ThemeButton.SelectH; - Button[Result].SelectW := ThemeButton.SelectW; - - Button[Result].Fade := ThemeButton.Fade; - Button[Result].FadeText := ThemeButton.FadeText; - if (ThemeButton.Typ = TEXTURE_TYPE_COLORIZED) then begin - Button[Result].FadeTex := Texture.GetTexture( - Skin.GetTextureFileName(ThemeButton.FadeTex), TEXTURE_TYPE_COLORIZED, - RGBFloatToInt(ThemeButton.ColR, ThemeButton.ColG, ThemeButton.ColB)); - end - else - begin - Button[Result].FadeTex := Texture.GetTexture(Skin.GetTextureFileName(ThemeButton.FadeTex), ThemeButton.Typ, true); - end; - - Button[Result].FadeTexPos := ThemeButton.FadeTexPos; - - BTLen := Length(ThemeButton.Text); - for BT := 0 to BTLen-1 do begin - AddButtonText(ThemeButton.Text[BT].X, ThemeButton.Text[BT].Y, - ThemeButton.Text[BT].ColR, ThemeButton.Text[BT].ColG, ThemeButton.Text[BT].ColB, - ThemeButton.Text[BT].Font, ThemeButton.Text[BT].Size, ThemeButton.Text[BT].Align, - ThemeButton.Text[BT].Text); - end; - - //BAutton Collection Mod - if (ThemeButton.Parent <> 0) then - begin - //If Collection Exists then Change Interaction to Child Button - if (@ButtonCollection[ThemeButton.Parent-1] <> nil) then - begin - Interactions[High(Interactions)].Typ := iBCollectionChild; - Button[Result].Visible := False; - - for BT := 0 to BTLen-1 do - Button[Result].Text[BT].Alpha := 0; - - Button[Result].Parent := ThemeButton.Parent; - if (ButtonCollection[ThemeButton.Parent-1].Fade) then - Button[Result].Texture.Alpha := 0; - end; - end; - Log.BenchmarkEnd(6); - Log.LogBenchmark('====> Screen Options32', 6); -end; - -function TMenu.AddButton(X, Y, W, H: real; const Name: String): integer; -begin - Result := AddButton(X, Y, W, H, Name, TEXTURE_TYPE_PLAIN, False); -end; - -function TMenu.AddButton(X, Y, W, H: real; const Name: String; Typ: TTextureType; Reflection: Boolean): integer; -begin - Result := AddButton(X, Y, W, H, 1, 1, 1, 1, 1, 1, 1, 0.5, Name, TEXTURE_TYPE_PLAIN, Reflection, 15, 15); -end; - -function TMenu.AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real; - const Name: String; Typ: TTextureType; - Reflection: Boolean; ReflectionSpacing, DeSelectReflectionSpacing: Real): integer; -begin - // adds button - //SetLength is used once to reduce Memory usement - if (ButtonPos <> -1) then - begin - Result := ButtonPos; - Inc(ButtonPos) - end - else //Old Method -> Reserve new Memory for every Button - begin - Result := Length(Button); - SetLength(Button, Result + 1); - end; - // Button[Result] := TButton.Create(Texture.GetTexture(Name, Typ)); - - // check here for cache - // Texture.GetTexture(Name, Typ, false); // preloads textures and creates cahce mipmap when needed - // if Covers.CoverExists(Name) then - // colorize hack - if (Typ = TEXTURE_TYPE_COLORIZED) then - begin - // give encoded color to GetTexture() - Button[Result] := TButton.Create(Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)), - Texture.GetTexture(Name, Typ, RGBFloatToInt(DColR, DColG, DColB))); - end - else - begin - Button[Result] := TButton.Create(Texture.GetTexture(Name, Typ, true)); // use cache texture - end; - - // configures button - Button[Result].X := X; - Button[Result].Y := Y; - Button[Result].W := W; - Button[Result].H := H; - if (Typ <> TEXTURE_TYPE_COLORIZED) then begin - Button[Result].SelectColR := ColR; - Button[Result].SelectColG := ColG; - Button[Result].SelectColB := ColB; - Button[Result].DeselectColR := DColR; - Button[Result].DeselectColG := DColG; - Button[Result].DeselectColB := DColB; - end; - Button[Result].SelectInt := Int; - Button[Result].DeselectInt := DInt; - Button[Result].Texture.TexX1 := 0; - Button[Result].Texture.TexY1 := 0; - Button[Result].Texture.TexX2 := 1; - Button[Result].Texture.TexY2 := 1; - Button[Result].SetSelect(false); - - Button[Result].Reflection := Reflection; - Button[Result].Reflectionspacing := ReflectionSpacing; - Button[Result].DeSelectReflectionspacing := DeSelectReflectionSpacing; - - //Button Collection Mod - Button[Result].Parent := 0; - - - // adds interaction - AddInteraction(iButton, Result); - Interaction := 0; -end; - -procedure TMenu.ClearButtons; -begin - Setlength(Button, 0); -end; - -// Method to draw our TMenu and all his child buttons -function TMenu.DrawBG: boolean; -var - PetX: integer; - PetY: integer; -begin - - BackImg.ColR := 1; - BackImg.ColG := 1; - BackImg.ColB := 1; - BackImg.TexX1 := 0; - BackImg.TexY1 := 0; - BackImg.TexX2 := 1; - BackImg.TexY2 := 1; - if (BackImg.TexNum <> -1) then - begin - // does anyone know what these loops were for? - { - // draw texture with overlapping - for PetY := 1 to BackH do - for PetX := 1 to BackW do begin - BackImg.X := (PetX-1)/BackW * 800; //640 - BackImg.Y := (PetY-1)/BackH * 600; //480 - DrawTexture(BackImg); - end; // for PetX - } - { - BackImg.X:=BackW; - BackImg.Y:=BackW; - } - BackImg.X := 0; - BackImg.Y := 0; - BackImg.Z := 0; // todo: eddie: to the opengl experts: please check this! On the mac z is not initialized??? - BackImg.W := 800; - BackImg.H := 600; - DrawTexture(BackImg); - end; // if - - - //if assigned( VideoPlayback ) then - begin - VideoPlayback.GetFrame( now() ); - VideoPlayback.DrawGL(2); - end; - - Result := true; -end; - -function TMenu.DrawFG: boolean; -var - J: Integer; -begin - // We don't forget about newly implemented static for nice skin ... - for J := 0 to Length(Static) - 1 do - Static[J].Draw; - - // ... and slightly implemented menutext unit - for J := 0 to Length(Text) - 1 do - Text[J].Draw; - - - // Draw all ButtonCollections - For J := 0 to High(ButtonCollection) do - ButtonCollection[J].Draw; - - // Second, we draw all of our buttons - for J := 0 to Length(Button) - 1 do - Button[J].Draw; - - // Third, we draw all of our selects - for J := 0 to Length(Selects) - 1 do - Selects[J].Draw(1); - - for J := 0 to Length(SelectsS) - 1 do - SelectsS[J].Draw; - - // Third, we draw all our widgets - // for J := 0 to Length(WidgetsSrc) - 1 do - // SDL_BlitSurface(WidgetsSrc[J], nil, ParentBackBuf, WidgetsRect[J]); - Result := True; -end; - -function TMenu.Draw: boolean; -begin - DrawBG; - DrawFG; - Result := True; -end; - -{ -function TMenu.GetNextScreen(): PMenu; -begin - Result := NextScreen; -end; -} - -{ -function TMenu.AddWidget(X, Y : UInt16; WidgetSrc : PSDL_Surface): Int16; -var - WidgetNum : Int16; -begin - If (Assigned(WidgetSrc)) Then - begin - WidgetNum := Length(WidgetsSrc); - - SetLength(WidgetsSrc, WidgetNum + 1); - SetLength(WidgetsRect, WidgetNum + 1); - - WidgetsSrc[WidgetNum] := WidgetSrc; - WidgetsRect[WidgetNum] := new(PSDL_Rect); - WidgetsRect[WidgetNum]^.x := X; - WidgetsRect[WidgetNum]^.y := Y; - WidgetsRect[WidgetNum]^.w := WidgetSrc^.w; - WidgetsRect[WidgetNum]^.h := WidgetSrc^.h; - - Result := WidgetNum; - end - else - Result := -1; -end; -} - -{ -procedure TMenu.ClearWidgets(MinNumber : Int16); -var - J : Int16; -begin - For J := MinNumber to (Length(WidgetsSrc) - 1) do - begin - SDL_FreeSurface(WidgetsSrc[J]); - dispose(WidgetsRect[J]); - end; - - SetLength(WidgetsSrc, MinNumber); - SetLength(WidgetsRect, MinNumber); -end; -} - -function TMenu.IsSelectable(Int: Cardinal): Boolean; -begin - Result := True; - Case Interactions[Int].Typ of - //Button - iButton: Result := Button[Interactions[Int].Num].Visible and Button[Interactions[Int].Num].Selectable; - //Select - iSelect: Result := True; - //Select Slide - iSelectS: Result := SelectsS[Interactions[Int].Num].Visible; - - //ButtonCollection Child - iBCollectionChild: - Result := (ButtonCollection[Button[Interactions[Int].Num].Parent - 1].FirstChild - 1 = Int) AND ((Interactions[Interaction].Typ <> iBCollectionChild) OR (Button[Interactions[Interaction].Num].Parent <> Button[Interactions[Int].Num].Parent)); - end; -end; - -procedure TMenu.InteractNext; -var - Int: Integer; -begin - Int := Interaction; - - // change interaction as long as it's needed - repeat - Int := (Int + 1) Mod Length(Interactions); - - //If no Interaction is Selectable Simply Select Next - if (Int = Interaction) then Break; - - Until IsSelectable(Int); - - //Set Interaction - Interaction := Int; -end; - - -procedure TMenu.InteractPrev; -var - Int: Integer; -begin - Int := Interaction; - - // change interaction as long as it's needed - repeat - Int := Int - 1; - if Int = -1 then Int := High(Interactions); - - //If no Interaction is Selectable Simply Select Next - if (Int = Interaction) then Break; - Until IsSelectable(Int); - - //Set Interaction - Interaction := Int -end; - - -procedure TMenu.InteractCustom(CustomSwitch: integer); -var - Num: integer; - Typ: integer; - Again: boolean; -begin - //Code Commented atm, because it needs to be Rewritten - //it doesn't work with Button Collections - {then begin - CustomSwitch:= CustomSwitch*(-1); - Again := true; - // change interaction as long as it's needed - while (Again = true) do begin - Num := SelInteraction - CustomSwitch; - if Num = -1 then Num := High(Interactions); - Interaction := Num; - Again := false; // reset, default to accept changing interaction - - // checking newly interacted element - Num := Interactions[Interaction].Num; - Typ := Interactions[Interaction].Typ; - case Typ of - iButton: - begin - if Button[Num].Selectable = false then Again := True; - end; - end; // case - end; // while - end - else if num>0 then begin - Again := true; - // change interaction as long as it's needed - while (Again = true) do begin - Num := (Interaction + CustomSwitch) Mod Length(Interactions); - Interaction := Num; - Again := false; // reset, default to accept changing interaction - - - // checking newly interacted element - Num := Interactions[Interaction].Num; - Typ := Interactions[Interaction].Typ; - case Typ of - iButton: - begin - if Button[Num].Selectable = false then Again := True; - end; - end; // case - end; // while - end } -end; - - -procedure TMenu.FadeTo(Screen: PMenu); -begin - Display.Fade := 0; - Display.NextScreen := Screen; -end; - -procedure TMenu.FadeTo(Screen: PMenu; aSound: TAudioPlaybackStream); -begin - FadeTo( Screen ); - AudioPlayback.PlaySound( aSound ); -end; - - -//popup hack -procedure TMenu.CheckFadeTo(Screen: PMenu; msg: String); -begin - Display.Fade := 0; - Display.NextScreenWithCheck := Screen; - Display.CheckOK:=False; - ScreenPopupCheck.ShowPopup(msg); -end; - -procedure TMenu.AddButtonText(AddX, AddY: real; const AddText: string); -begin - AddButtonText(AddX, AddY, 1, 1, 1, AddText); -end; - -procedure TMenu.AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; const AddText: string); -var - Il: integer; -begin - with Button[High(Button)] do begin - Il := Length(Text); - SetLength(Text, Il+1); - Text[Il] := TText.Create(X + AddX, Y + AddY, AddText); - Text[Il].ColR := ColR; - Text[Il].ColG := ColG; - Text[Il].ColB := ColB; - Text[Il].Int := 1;//0.5; - end; -end; - -procedure TMenu.AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); -var - Il: integer; -begin - with Button[High(Button)] do begin - Il := Length(Text); - SetLength(Text, Il+1); - Text[Il] := TText.Create(X + AddX, Y + AddY, AddText); - Text[Il].ColR := ColR; - Text[Il].ColG := ColG; - Text[Il].ColB := ColB; - Text[Il].Int := 1;//0.5; - Text[Il].Style := Font; - Text[Il].Size := Size; - Text[Il].Align := Align; - end; -end; - -procedure TMenu.AddButtonText(CustomButton: TButton; AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); -var - Il: integer; -begin - with CustomButton do begin - Il := Length(Text); - SetLength(Text, Il+1); - Text[Il] := TText.Create(X + AddX, Y + AddY, AddText); - Text[Il].ColR := ColR; - Text[Il].ColG := ColG; - Text[Il].ColB := ColB; - Text[Il].Int := 1;//0.5; - Text[Il].Style := Font; - Text[Il].Size := Size; - Text[Il].Align := Align; - end; -end; - -function TMenu.AddSelect(ThemeSelect: TThemeSelect; var Data: integer; Values: array of string): integer; -var - SO: integer; -begin - Result := AddSelect(ThemeSelect.X, ThemeSelect.Y, ThemeSelect.W, ThemeSelect.H, ThemeSelect.SkipX, - ThemeSelect.ColR, ThemeSelect.ColG, ThemeSelect.ColB, ThemeSelect.Int, - ThemeSelect.DColR, ThemeSelect.DColG, ThemeSelect.DColB, ThemeSelect.DInt, - ThemeSelect.TColR, ThemeSelect.TColG, ThemeSelect.TColB, ThemeSelect.TInt, - ThemeSelect.TDColR, ThemeSelect.TDColG, ThemeSelect.TDColB, ThemeSelect.TDInt, - ThemeSelect.SBGColR, ThemeSelect.SBGColG, ThemeSelect.SBGColB, ThemeSelect.SBGInt, - ThemeSelect.SBGDColR, ThemeSelect.SBGDColG, ThemeSelect.SBGDColB, ThemeSelect.SBGDInt, - ThemeSelect.STColR, ThemeSelect.STColG, ThemeSelect.STColB, ThemeSelect.STInt, - ThemeSelect.STDColR, ThemeSelect.STDColG, ThemeSelect.STDColB, ThemeSelect.STDInt, - Skin.GetTextureFileName(ThemeSelect.Tex), TEXTURE_TYPE_COLORIZED, - Skin.GetTextureFileName(ThemeSelect.TexSBG), TEXTURE_TYPE_COLORIZED, - ThemeSelect.Text, Data); - for SO := 0 to High(Values) do - AddSelectOption(ThemeSelect.X + ThemeSelect.W + ThemeSelect.SkipX + SO * 100 + 20, ThemeSelect.Y + 20, Values[SO]); -end; - -function TMenu.AddSelect(X, Y, W, H, SkipX, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt, - TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt, - SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt, - STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real; - const Name: String; Typ: TTextureType; const SBGName: String; SBGTyp: TTextureType; - const Caption: string; var Data: integer): integer; -var - S: integer; -begin - S := Length(Selects); - SetLength(Selects, S + 1); - Selects[S] := TSelect.Create; - - if (Typ = TEXTURE_TYPE_COLORIZED) then - Selects[S].Texture := Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)) - else - Selects[S].Texture := Texture.GetTexture(Name, Typ); - Selects[S].X := X; - Selects[S].Y := Y; - Selects[S].W := W; - Selects[S].H := H; - Selects[S].ColR := ColR; - Selects[S].ColG := ColG; - Selects[S].ColB := ColB; - Selects[S].Int := Int; - Selects[S].DColR := DColR; - Selects[S].DColG := DColG; - Selects[S].DColB := DColB; - Selects[S].DInt := DInt; - - if (SBGTyp = TEXTURE_TYPE_COLORIZED) then - Selects[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp, RGBFloatToInt(SBGColR, SBGColG, SBGColB)) - else - Selects[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp); - Selects[S].TextureSBG.X := X + W + SkipX; - Selects[S].TextureSBG.Y := Y; - Selects[S].TextureSBG.W := 450; - Selects[S].TextureSBG.H := H; - Selects[S].SBGColR := SBGColR; - Selects[S].SBGColG := SBGColG; - Selects[S].SBGColB := SBGColB; - Selects[S].SBGInt := SBGInt; - Selects[S].SBGDColR := SBGDColR; - Selects[S].SBGDColG := SBGDColG; - Selects[S].SBGDColB := SBGDColB; - Selects[S].SBGDInt := SBGDInt; - - Selects[S].Text.X := X + 20; - Selects[S].Text.Y := Y + 20; - Selects[S].Text.Text := Caption; - Selects[S].Text.Size := 10; - Selects[S].Text.Visible := true; - Selects[S].TColR := TColR; - Selects[S].TColG := TColG; - Selects[S].TColB := TColB; - Selects[S].TInt := TInt; - Selects[S].TDColR := TDColR; - Selects[S].TDColG := TDColG; - Selects[S].TDColB := TDColB; - Selects[S].TDInt := TDInt; - - Selects[S].STColR := STColR; - Selects[S].STColG := STColG; - Selects[S].STColB := STColB; - Selects[S].STInt := STInt; - Selects[S].STDColR := STDColR; - Selects[S].STDColG := STDColG; - Selects[S].STDColB := STDColB; - Selects[S].STDInt := STDInt; - - // new - Selects[S].Texture.TexX1 := 0; - Selects[S].Texture.TexY1 := 0; - Selects[S].Texture.TexX2 := 1; - Selects[S].Texture.TexY2 := 1; - Selects[S].TextureSBG.TexX1 := 0; - Selects[S].TextureSBG.TexY1 := 0; - Selects[S].TextureSBG.TexX2 := 1; - Selects[S].TextureSBG.TexY2 := 1; - - // Sets Data to copy the value of selectops to global value; - Selects[S].PData := @Data; - - // Sets default value of selectopt from Data; - Selects[S].SelectedOption := Data; - - // Disables default selection - Selects[S].SetSelect(false); - - // adds interaction - AddInteraction(iSelect, S); -end; - -procedure TMenu.AddSelectOption(AddX, AddY: real; const AddText: string); -begin - AddSelectOption (High(Selects), AddX, AddY, AddText); -end; - -procedure TMenu.AddSelectOption(SelectNo: Cardinal; AddX, AddY: real; const AddText: string); -var - SO: integer; -begin - SO := Length(Selects[SelectNo].TextOpt); - SetLength(Selects[SelectNo].TextOpt, SO + 1); - - Selects[SelectNo].TextOpt[SO] := TText.Create; - - Selects[SelectNo].TextOpt[SO].X := AddX; - Selects[SelectNo].TextOpt[SO].Y := AddY; - Selects[SelectNo].TextOpt[SO].Text := AddText; - Selects[SelectNo].TextOpt[SO].Size := 10; - Selects[SelectNo].TextOpt[SO].ColR := Selects[SelectNo].STDColR; - Selects[SelectNo].TextOpt[SO].ColG := Selects[SelectNo].STDColG; - Selects[SelectNo].TextOpt[SO].ColB := Selects[SelectNo].STDColB; - Selects[SelectNo].TextOpt[SO].Int := Selects[SelectNo].STDInt; - Selects[SelectNo].TextOpt[SO].Visible := true; - - if SO = Selects[SelectNo].PData^ then Selects[SelectNo].SelectedOption := SO; -end; - -procedure TMenu.UpdateSelectOptions(ThemeSelect: TThemeSelect; SelectNum: integer; Values: array of string; var Data: integer); -var - SO: integer; -begin - SetLength(Selects[SelectNum].TextOpt, 0); - for SO := 0 to High(Values) do - AddSelectOption(SelectNum, ThemeSelect.X + ThemeSelect.W + ThemeSelect.SkipX + SO * 100 + 20, ThemeSelect.Y + 20, Values[SO]); -end; - -function TMenu.AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; Values: array of string): integer; -var - SO: integer; -begin - Result := AddSelectSlide(ThemeSelectS.X, ThemeSelectS.Y, ThemeSelectS.W, ThemeSelectS.H, ThemeSelectS.SkipX, ThemeSelectS.SBGW, - ThemeSelectS.ColR, ThemeSelectS.ColG, ThemeSelectS.ColB, ThemeSelectS.Int, - ThemeSelectS.DColR, ThemeSelectS.DColG, ThemeSelectS.DColB, ThemeSelectS.DInt, - ThemeSelectS.TColR, ThemeSelectS.TColG, ThemeSelectS.TColB, ThemeSelectS.TInt, - ThemeSelectS.TDColR, ThemeSelectS.TDColG, ThemeSelectS.TDColB, ThemeSelectS.TDInt, - ThemeSelectS.SBGColR, ThemeSelectS.SBGColG, ThemeSelectS.SBGColB, ThemeSelectS.SBGInt, - ThemeSelectS.SBGDColR, ThemeSelectS.SBGDColG, ThemeSelectS.SBGDColB, ThemeSelectS.SBGDInt, - ThemeSelectS.STColR, ThemeSelectS.STColG, ThemeSelectS.STColB, ThemeSelectS.STInt, - ThemeSelectS.STDColR, ThemeSelectS.STDColG, ThemeSelectS.STDColB, ThemeSelectS.STDInt, - Skin.GetTextureFileName(ThemeSelectS.Tex), TEXTURE_TYPE_COLORIZED, - Skin.GetTextureFileName(ThemeSelectS.TexSBG), TEXTURE_TYPE_COLORIZED, - ThemeSelectS.Text, Data); - for SO := 0 to High(Values) do - AddSelectSlideOption(Values[SO]); - - SelectsS[High(SelectsS)].Text.Size := ThemeSelectS.TextSize; - - SelectsS[High(SelectsS)].Texture.Z := ThemeSelectS.Z; - SelectsS[High(SelectsS)].TextureSBG.Z := ThemeSelectS.Z; - - //Generate Lines - SelectsS[High(SelectsS)].GenLines; - - SelectsS[High(SelectsS)].SelectedOption := SelectsS[High(SelectsS)].SelectOptInt; // refresh -end; - -function TMenu.AddSelectSlide(X, Y, W, H, SkipX, SBGW, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt, - TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt, - SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt, - STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real; - const Name: String; Typ: TTextureType; const SBGName: String; SBGTyp: TTextureType; - const Caption: string; var Data: integer): integer; -var - S: integer; - I: integer; -begin - S := Length(SelectsS); - SetLength(SelectsS, S + 1); - SelectsS[S] := TSelectSlide.Create; - - if (Typ = TEXTURE_TYPE_COLORIZED) then - SelectsS[S].Texture := Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)) - else - SelectsS[S].Texture := Texture.GetTexture(Name, Typ); - SelectsS[S].X := X; - SelectsS[S].Y := Y; - SelectsS[S].W := W; - SelectsS[S].H := H; - - SelectsS[S].ColR := ColR; - SelectsS[S].ColG := ColG; - SelectsS[S].ColB := ColB; - SelectsS[S].Int := Int; - SelectsS[S].DColR := DColR; - SelectsS[S].DColG := DColG; - SelectsS[S].DColB := DColB; - SelectsS[S].DInt := DInt; - - if (SBGTyp = TEXTURE_TYPE_COLORIZED) then - SelectsS[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp, RGBFloatToInt(SBGColR, SBGColG, SBGColB)) - else - SelectsS[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp); - SelectsS[S].TextureSBG.X := X + W + SkipX; - SelectsS[S].TextureSBG.Y := Y; - //SelectsS[S].TextureSBG.W := 450; - SelectsS[S].SBGW := SBGW; - SelectsS[S].TextureSBG.H := H; - SelectsS[S].SBGColR := SBGColR; - SelectsS[S].SBGColG := SBGColG; - SelectsS[S].SBGColB := SBGColB; - SelectsS[S].SBGInt := SBGInt; - SelectsS[S].SBGDColR := SBGDColR; - SelectsS[S].SBGDColG := SBGDColG; - SelectsS[S].SBGDColB := SBGDColB; - SelectsS[S].SBGDInt := SBGDInt; - - SelectsS[S].Text.X := X + 20; - SelectsS[S].Text.Y := Y + (SelectsS[S].TextureSBG.H / 2) - 15; - SelectsS[S].Text.Text := Caption; - SelectsS[S].Text.Size := 10; - SelectsS[S].Text.Visible := true; - SelectsS[S].TColR := TColR; - SelectsS[S].TColG := TColG; - SelectsS[S].TColB := TColB; - SelectsS[S].TInt := TInt; - SelectsS[S].TDColR := TDColR; - SelectsS[S].TDColG := TDColG; - SelectsS[S].TDColB := TDColB; - SelectsS[S].TDInt := TDInt; - - SelectsS[S].STColR := STColR; - SelectsS[S].STColG := STColG; - SelectsS[S].STColB := STColB; - SelectsS[S].STInt := STInt; - SelectsS[S].STDColR := STDColR; - SelectsS[S].STDColG := STDColG; - SelectsS[S].STDColB := STDColB; - SelectsS[S].STDInt := STDInt; - - // new - SelectsS[S].Texture.TexX1 := 0; - SelectsS[S].Texture.TexY1 := 0; - SelectsS[S].Texture.TexX2 := 1; - SelectsS[S].Texture.TexY2 := 1; - SelectsS[S].TextureSBG.TexX1 := 0; - SelectsS[S].TextureSBG.TexY1 := 0; - SelectsS[S].TextureSBG.TexX2 := 1; - SelectsS[S].TextureSBG.TexY2 := 1; - - // Sets Data to copy the value of selectops to global value; - SelectsS[S].PData := @Data; - // Configures Select options - {//SelectsS[S].TextOpt[0].Text := IntToStr(I+1); - SelectsS[S].TextOpt[0].Size := 10; - SelectsS[S].TextOpt[0].Align := 1; - - SelectsS[S].TextOpt[0].ColR := SelectsS[S].STDColR; - SelectsS[S].TextOpt[0].ColG := SelectsS[S].STDColG; - SelectsS[S].TextOpt[0].ColB := SelectsS[S].STDColB; - SelectsS[S].TextOpt[0].Int := SelectsS[S].STDInt; - SelectsS[S].TextOpt[0].Visible := true; } - - // Sets default value of selectopt from Data; - SelectsS[S].SelectedOption := Data; - - // Disables default selection - SelectsS[S].SetSelect(false); - - {// Configures 3 select options - for I := 0 to 2 do begin - SelectsS[S].TextOpt[I].X := SelectsS[S].TextureSBG.X + 20 + (50 + 20) + (150 - 20) * I; - SelectsS[S].TextOpt[I].Y := SelectsS[S].TextureSBG.Y + 20; - SelectsS[S].TextOpt[I].Text := IntToStr(I+1); - SelectsS[S].TextOpt[I].Size := 10; - SelectsS[S].TextOpt[I].Align := 1; - - - SelectsS[S].TextOpt[I].ColR := SelectsS[S].STDColR; - SelectsS[S].TextOpt[I].ColG := SelectsS[S].STDColG; - SelectsS[S].TextOpt[I].ColB := SelectsS[S].STDColB; - SelectsS[S].TextOpt[I].Int := SelectsS[S].STDInt; - SelectsS[S].TextOpt[I].Visible := true; - end;} - - - // adds interaction - AddInteraction(iSelectS, S); - Result := S; -end; - -procedure TMenu.AddSelectSlideOption(const AddText: string); -begin - AddSelectSlideOption(High(SelectsS), AddText); -end; - -procedure TMenu.AddSelectSlideOption(SelectNo: Cardinal; const AddText: string); -var - SO: integer; -begin - SO := Length(SelectsS[SelectNo].TextOptT); - - SetLength(SelectsS[SelectNo].TextOptT, SO + 1); - SelectsS[SelectNo].TextOptT[SO] := AddText; - - //SelectsS[S].SelectedOption := SelectsS[S].SelectOptInt; // refresh - - //if SO = Selects[S].PData^ then Selects[S].SelectedOption := SO; -end; - -procedure TMenu.UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; Values: array of string; var Data: integer); -var - SO: integer; -begin - SetLength(SelectsS[SelectNum].TextOptT, 0); - for SO := 0 to High(Values) do - AddSelectSlideOption(SelectNum, Values[SO]); - - SelectsS[SelectNum].GenLines; - -// SelectsS[SelectNum].SelectedOption := SelectsS[SelectNum].SelectOptInt; // refresh -// SelectS[SelectNum].SetSelectOpt(Data); -// SelectS[SelectNum].SelectedOption := 0;//Data; - -// Log.LogError(IntToStr(High(SelectsS[SelectNum].TextOptT))); -// if 0 <= High(SelectsS[SelectNum].TextOptT) then - - SelectsS[SelectNum].PData := @Data; - SelectsS[SelectNum].SelectedOption := Data; -end; - -function TMenu.InRegion(X1, Y1, X2, Y2, X, Y: real): Boolean; -begin - Result := false; - X1 := X1 * RenderW/640; - X2 := X2 * RenderW/640; - Y1 := Y1 * RenderH/480; - Y2 := Y2 * RenderH/480; - if (X >= X1) and (X <= X2) and (Y >= Y1) and (Y <= Y2) then - Result := true; -end; - -function TMenu.InStaticRegion(StaticNr: integer; X, Y: integer): Boolean; -begin - Result := InRegion(Static[StaticNr].Texture.X, - Static[StaticNr].Texture.Y, - Static[StaticNr].Texture.X + Static[StaticNr].Texture.W - 1, - Static[StaticNr].Texture.Y + Static[StaticNr].Texture.H - 1, - X, Y); -end; - -procedure TMenu.InteractInc; -var - Num: integer; - Value: integer; -begin - case Interactions[Interaction].Typ of - iSelect: begin - Num := Interactions[Interaction].Num; - Value := Selects[Num].SelectedOption; - Value := (Value + 1) Mod (Length(Selects[Num].TextOpt)); - Selects[Num].SelectedOption := Value; - end; - iSelectS: begin - Num := Interactions[Interaction].Num; - Value := SelectsS[Num].SelectedOption; -// Value := (Value + 1) Mod (Length(SelectsS[Num].TextOptT)); - - // limit - Value := Value + 1; - if Value <= High(SelectsS[Num].TextOptT) then - SelectsS[Num].SelectedOption := Value; - end; - //Button Collection Mod - iBCollectionChild: - begin - - //Select Next Button in Collection - For Num := 1 to High(Button) do - begin - Value := (Interaction + Num) Mod Length(Button); - if Value = 0 then - begin - InteractNext; - Break; - end; - if (Button[Value].Parent = Button[Interaction].Parent) then - begin - Interaction := Value; - Break; - end; - end; - end; - //interact Next if there is Nothing to Change - else InteractNext; - end; -end; - -procedure TMenu.InteractDec; -var - Num: integer; - Value: integer; -begin - case Interactions[Interaction].Typ of - iSelect: begin - Num := Interactions[Interaction].Num; - Value := Selects[Num].SelectedOption; - Value := Value - 1; - if Value = -1 then - Value := High(Selects[Num].TextOpt); - Selects[Num].SelectedOption := Value; - end; - iSelectS: begin - Num := Interactions[Interaction].Num; - Value := SelectsS[Num].SelectedOption; - Value := Value - 1; -// if Value = -1 then -// Value := High(SelectsS[Num].TextOptT); - - if Value >= 0 then - SelectsS[Num].SelectedOption := Value; - end; - //Button Collection Mod - iBCollectionChild: - begin - //Select Prev Button in Collection - For Num := High(Button) downto 1 do - begin - Value := (Interaction + Num) Mod Length(Button); - if Value = High(Button) then - begin - InteractPrev; - Break; - end; - if (Button[Value].Parent = Button[Interaction].Parent) then - begin - Interaction := Value; - Break; - end; - end; - end; - //interact Prev if there is Nothing to Change - else - begin - InteractPrev; - //If ButtonCollection with more than 1 Entry then Select Last Entry - if (Button[Interactions[Interaction].Num].Parent <> 0) AND (ButtonCollection[Button[Interactions[Interaction].Num].Parent-1].CountChilds > 1) then - begin - //Select Last Child - For Num := High(Button) downto 1 do - begin - Value := (Interaction + Num) Mod Length(Button); - if (Button[Value].Parent = Button[Interaction].Parent) then - begin - Interaction := Value; - Break; - end; - end; - end; - end; - end; -end; - -procedure TMenu.AddBox(X, Y, W, H: real); -begin - AddStatic(X, Y, W, H, 0, 0, 0, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED); - AddStatic(X+2, Y+2, W-4, H-4, 1, 1, 1, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED); -end; - -procedure TMenu.onShow; -begin - // nothing -(* - if fileexists( fFileName ) then - begin - if VideoPlayback.Open( fFileName ) then - VideoPlayback.Play; - end; -*) -end; - -procedure TMenu.onShowFinish; -begin - // nothing -end; - -function TMenu.WideCharUpperCase(wchar: WideChar) : WideString; -begin - // On Linux and MacOSX the cwstring unit is necessary for Unicode function-calls. - // Otherwise you will get an EIntOverflow exception (thrown by unimplementedwidestring()). - - // The FPC implementation of WideUpperCase returns nil if wchar is #0 (e.g. if an arrow key is pressed) - if (wchar <> #0) then - Result := WideUpperCase(wchar) - else - Result := #0; -end; - -procedure TMenu.onHide; -begin - // nothing -end; - -function TMenu.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; -begin - // nothing - Result := true; -end; - -procedure TMenu.SetAnimationProgress(Progress: real); -begin - // nothing -end; - -end. - +unit UMenu; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + +uses OpenGL12, SysUtils, UTexture, UMenuStatic, UMenuText, UMenuButton, UMenuSelect, UMenuSelectSlide, + UMenuInteract, UThemes, UMenuButtonCollection, Math, UMusic; + +type +{ Int16 = SmallInt;} + + PMenu = ^TMenu; + TMenu = class + protected + ButtonPos: Integer; + + Interactions: array of TInteract; + SelInteraction: integer; + Button: array of TButton; + Selects: array of TSelect; + SelectsS: array of TSelectSlide; + ButtonCollection: array of TButtonCollection; + BackImg: TTexture; + BackW: integer; + BackH: integer; + + fFileName : string; + public + Text: array of TText; + Static: array of TStatic; + mX: integer; // mouse X + mY: integer; // mouse Y + + Fade: integer; // fade type + ShowFinish: boolean; // true if there is no fade + + + destructor Destroy; override; + constructor Create; overload; virtual; + //constructor Create(Back: string); overload; virtual; // Back is a JPG resource name for background + //constructor Create(Back: string; W, H: integer); overload; virtual; // W and H are the number of overlaps + + // interaction + function WideCharUpperCase(wchar: WideChar) : WideString; + procedure AddInteraction(Typ, Num: integer); + procedure SetInteraction(Num: integer); + property Interaction: integer read SelInteraction write SetInteraction; + + //Procedure Load BG, Texts, Statics and Button Collections from ThemeBasic + procedure LoadFromTheme(const ThemeBasic: TThemeBasic); + + procedure PrepareButtonCollections(const Collections: AThemeButtonCollection); + procedure AddButtonCollection(const ThemeCollection: TThemeButtonCollection; Const Num: Byte); + + // background + procedure AddBackground(Name: string); + + // static + function AddStatic(ThemeStatic: TThemeStatic): integer; overload; + function AddStatic(X, Y, W, H: real; const Name: string): integer; overload; + function AddStatic(X, Y, W, H: real; const Name: string; Typ: TTextureType): integer; overload; + function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; overload; + function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; overload; + function AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; overload; + function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; overload; + function AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; TexX1, TexY1, TexX2, TexY2: real; const Name: string; Typ: TTextureType; Color: integer; Reflection: Boolean; ReflectionSpacing: Real): integer; overload; + + // text + function AddText(ThemeText: TThemeText): integer; overload; + function AddText(X, Y: real; const Text_: string): integer; overload; + function AddText(X, Y: real; Style: integer; Size, ColR, ColG, ColB: real; const Text: string): integer; overload; + function AddText(X, Y, W: real; Style: integer; Size, ColR, ColG, ColB: real; Align: integer; const Text_: string): integer; overload; + + // button + Procedure SetButtonLength(Length: Cardinal); //Function that Set Length of Button Array in one Step instead of register new Memory for every Button + function AddButton(ThemeButton: TThemeButton): integer; overload; + function AddButton(X, Y, W, H: real; const Name: String): integer; overload; + function AddButton(X, Y, W, H: real; const Name: String; Typ: TTextureType; Reflection: Boolean): integer; overload; + function AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real; const Name: String; Typ: TTextureType; Reflection: Boolean; ReflectionSpacing, DeSelectReflectionSpacing: Real): integer; overload; + procedure ClearButtons; + procedure AddButtonText(AddX, AddY: real; const AddText: string); overload; + procedure AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; const AddText: string); overload; + procedure AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); overload; + procedure AddButtonText(CustomButton: TButton; AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); overload; + + // select + function AddSelect(ThemeSelect: TThemeSelect; var Data: integer; Values: array of string): integer; overload; + function AddSelect(X, Y, W, H, SkipX, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt, + TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt, + SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt, + STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real; + const Name: String; Typ: TTextureType; const SBGName: String; SBGTyp: TTextureType; + const Caption: string; var Data: integer): integer; overload; + procedure AddSelectOption(AddX, AddY: real; const AddText: string); overload; + procedure AddSelectOption(SelectNo: Cardinal; AddX, AddY: real; const AddText: string); overload; + procedure UpdateSelectOptions(ThemeSelect: TThemeSelect; SelectNum: integer; Values: array of string; var Data: integer); + + // select slide + function AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; Values: array of string): integer; overload; + function AddSelectSlide(X, Y, W, H, SkipX, SBGW, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt, + TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt, + SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt, + STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real; + const Name: String; Typ: TTextureType; const SBGName: String; SBGTyp: TTextureType; + const Caption: string; var Data: integer): integer; overload; + procedure AddSelectSlideOption(const AddText: string); overload; + procedure AddSelectSlideOption(SelectNo: Cardinal; const AddText: string); overload; + procedure UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; Values: array of string; var Data: integer); + + +// function AddWidget(X, Y : UInt16; WidgetSrc : PSDL_Surface): Int16; +// procedure ClearWidgets(MinNumber : Int16); + procedure FadeTo(Screen: PMenu); overload; + procedure FadeTo(Screen: PMenu; aSound: TAudioPlaybackStream); overload; + //popup hack + procedure CheckFadeTo(Screen: PMenu; msg: String); + + function DrawBG: boolean; virtual; + function DrawFG: boolean; virtual; + function Draw: boolean; virtual; + function ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown : Boolean): Boolean; virtual; + // FIXME: ParseMouse is not implemented in any subclass and not even used anywhere in the code + // -> do this before activation of this method + //function ParseMouse(Typ: integer; X: integer; Y: integer): Boolean; virtual; abstract; + function InRegion(X1, Y1, X2, Y2, X, Y: real): Boolean; + function InStaticRegion(StaticNr: integer; X, Y: integer): Boolean; + procedure onShow; virtual; + procedure onShowFinish; virtual; + procedure onHide; virtual; + + procedure SetAnimationProgress(Progress: real); virtual; + + function IsSelectable(Int: Cardinal): Boolean; + + procedure InteractNext; virtual; + procedure InteractCustom(CustomSwitch: integer); virtual; + procedure InteractPrev; virtual; + procedure InteractInc; virtual; + procedure InteractDec; virtual; + + procedure AddBox(X, Y, W, H: real); + end; + +const + pmMove = 1; + pmClick = 2; + pmUnClick = 3; + + iButton = 0; // interaction type + iSelect = 1; + iText = 2; + iSelectS = 3; + iBCollectionChild = 5; + +// fBlack = 0; // fade type +// fWhite = 1; + +implementation + +uses UCommon, + ULog, + UMain, + UDrawTexture, + UGraphic, + UDisplay, + UCovers, + USkins; + +destructor TMenu.Destroy; +begin + inherited; +end; + +constructor TMenu.Create; +begin + Fade := 0;//fWhite; + + SetLength(Static, 0); + SetLength(Button, 0); + + BackImg.TexNum := 0; + + //Set ButtonPos to Autoset Length + ButtonPos := -1; + + + VideoPlayback.Init; +end; +{ +constructor TMenu.Create(Back: String); +begin + inherited Create; + + if Back <> '' then begin +// BackImg := Texture.GetTexture(true, Back, TEXTURE_TYPE_PLAIN, 0); + BackImg := Texture.GetTexture(Back, TEXTURE_TYPE_PLAIN, 0); // new theme system + BackImg.W := 800;//640; + BackImg.H := 600;//480; + BackW := 1; + BackH := 1; + end else + BackImg.TexNum := 0; + + //Set ButtonPos to Autoset Length + ButtonPos := -1; +end; + +constructor TMenu.Create(Back: string; W, H: integer); +begin + Create(Back); + BackImg.W := BackImg.W / W; + BackImg.H := BackImg.H / H; + BackW := W; + BackH := H; +end; } + +function RGBFloatToInt(R, G, B: Double): Cardinal; +begin + Result := (Trunc(255 * R) shl 16) or + (Trunc(255 * G) shl 8) or + Trunc(255 * B); +end; + +procedure TMenu.AddInteraction(Typ, Num: integer); +var + IntNum: integer; +begin + IntNum := Length(Interactions); + SetLength(Interactions, IntNum+1); + Interactions[IntNum].Typ := Typ; + Interactions[IntNum].Num := Num; + Interaction := 0; +end; + +procedure TMenu.SetInteraction(Num: integer); +var + OldNum, OldTyp: integer; + NewNum, NewTyp: integer; +begin + // set inactive + OldNum := Interactions[Interaction].Num; + OldTyp := Interactions[Interaction].Typ; + + NewNum := Interactions[Num].Num; + NewTyp := Interactions[Num].Typ; + + case OldTyp of + iButton: Button[OldNum].Selected := False; + iSelect: Selects[OldNum].Selected := False; + iText: Text[OldNum].Selected := False; + iSelectS: SelectsS[OldNum].Selected := False; + //Button Collection Mod + iBCollectionChild: + begin + Button[OldNum].Selected := False; + + //Deselect Collection if Next Button is Not from Collection + if (NewTyp <> iButton) Or (Button[NewNum].Parent <> Button[OldNum].Parent) then + ButtonCollection[Button[OldNum].Parent-1].Selected := False; + end; + end; + + // set active + SelInteraction := Num; + case NewTyp of + iButton: Button[NewNum].Selected := True; + iSelect: Selects[NewNum].Selected := True; + iText: Text[NewNum].Selected := True; + iSelectS: SelectsS[NewNum].Selected := True; + + //Button Collection Mod + iBCollectionChild: + begin + Button[NewNum].Selected := True; + ButtonCollection[Button[NewNum].Parent-1].Selected := True; + end; + end; +end; + +//---------------------- +//LoadFromTheme - Load BG, Texts, Statics and +//Button Collections from ThemeBasic +//---------------------- +procedure TMenu.LoadFromTheme(const ThemeBasic: TThemeBasic); +var + I: Integer; +begin + //Add Button Collections (Set Button CollectionsLength) + //Button Collections are Created when the first ChildButton is Created + PrepareButtonCollections(ThemeBasic.ButtonCollection); + + //Add Background + AddBackground(ThemeBasic.Background.Tex); + + //Add Statics and Texts + for I := 0 to High(ThemeBasic.Static) do + AddStatic(ThemeBasic.Static[I]); + + for I := 0 to High(ThemeBasic.Text) do + AddText(ThemeBasic.Text[I]); +end; + +procedure TMenu.AddBackground(Name: string); +//var +// lFileName : string; +begin + if Name <> '' then + begin + fFileName := Skin.GetTextureFileName(Name); + fFileName := AdaptFilePaths( fFileName ); + + if fileexists( fFileName ) then + begin + BackImg := Texture.GetTexture( fFileName , TEXTURE_TYPE_PLAIN); + + if ( BackImg.TexNum = 0 ) then + begin + if VideoPlayback.Open( fFileName ) then + VideoPlayback.Play; + end; + + BackImg.W := 800; + BackImg.H := 600; + BackW := 1; + BackH := 1; + end; + end; +end; + +//---------------------- +//PrepareButtonCollections: +//Add Button Collections (Set Button CollectionsLength) +//---------------------- +procedure TMenu.PrepareButtonCollections(const Collections: AThemeButtonCollection); +var + I: Integer; +begin + SetLength(ButtonCollection, Length(Collections)); + For I := 0 to High(ButtonCollection) do + AddButtonCollection(Collections[I], I); +end; + +//---------------------- +//AddButtonCollection: +//Create a Button Collection; +//---------------------- +procedure TMenu.AddButtonCollection(const ThemeCollection: TThemeButtonCollection; Const Num: Byte); +var + BT, BTLen: Integer; + TempCol, TempDCol: Cardinal; + +begin + if (Num > High(ButtonCollection)) then + exit; + + TempCol := 0; + + // colorize hack + if (ThemeCollection.Style.Typ = TEXTURE_TYPE_COLORIZED) then + begin + TempCol := RGBFloatToInt(ThemeCollection.Style.ColR, ThemeCollection.Style.ColG, ThemeCollection.Style.ColB); + TempDCol := RGBFloatToInt(ThemeCollection.Style.DColR, ThemeCollection.Style.DColG, ThemeCollection.Style.DColB); + // give encoded color to GetTexture() + ButtonCollection[Num] := TButtonCollection.Create( + Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.Tex), TEXTURE_TYPE_COLORIZED, TempCol), + Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.Tex), TEXTURE_TYPE_COLORIZED, TempDCol)); + end + else + begin + ButtonCollection[Num] := TButtonCollection.Create(Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.Tex), ThemeCollection.Style.Typ, true)); // use cache texture + end; + + //Set Parent menu + ButtonCollection[Num].ScreenButton := @Self.Button; + + //Set Attributes + ButtonCollection[Num].FirstChild := ThemeCollection.FirstChild; + ButtonCollection[Num].CountChilds := ThemeCollection.ChildCount; + ButtonCollection[Num].Parent := Num + 1; + + //Set Style + ButtonCollection[Num].X := ThemeCollection.Style.X; + ButtonCollection[Num].Y := ThemeCollection.Style.Y; + ButtonCollection[Num].W := ThemeCollection.Style.W; + ButtonCollection[Num].H := ThemeCollection.Style.H; + if (ThemeCollection.Style.Typ <> TEXTURE_TYPE_COLORIZED) then begin + ButtonCollection[Num].SelectColR := ThemeCollection.Style.ColR; + ButtonCollection[Num].SelectColG := ThemeCollection.Style.ColG; + ButtonCollection[Num].SelectColB := ThemeCollection.Style.ColB; + ButtonCollection[Num].DeselectColR := ThemeCollection.Style.DColR; + ButtonCollection[Num].DeselectColG := ThemeCollection.Style.DColG; + ButtonCollection[Num].DeselectColB := ThemeCollection.Style.DColB; + end; + ButtonCollection[Num].SelectInt := ThemeCollection.Style.Int; + ButtonCollection[Num].DeselectInt := ThemeCollection.Style.DInt; + ButtonCollection[Num].Texture.TexX1 := 0; + ButtonCollection[Num].Texture.TexY1 := 0; + ButtonCollection[Num].Texture.TexX2 := 1; + ButtonCollection[Num].Texture.TexY2 := 1; + ButtonCollection[Num].SetSelect(false); + + ButtonCollection[Num].Reflection := ThemeCollection.Style.Reflection; + ButtonCollection[Num].Reflectionspacing := ThemeCollection.Style.ReflectionSpacing; + ButtonCollection[Num].DeSelectReflectionspacing := ThemeCollection.Style.DeSelectReflectionSpacing; + + ButtonCollection[Num].Z := ThemeCollection.Style.Z; + + //Some Things from ButtonFading + ButtonCollection[Num].SelectH := ThemeCollection.Style.SelectH; + ButtonCollection[Num].SelectW := ThemeCollection.Style.SelectW; + + ButtonCollection[Num].Fade := ThemeCollection.Style.Fade; + ButtonCollection[Num].FadeText := ThemeCollection.Style.FadeText; + if (ThemeCollection.Style.Typ = TEXTURE_TYPE_COLORIZED) then + ButtonCollection[Num].FadeTex := Texture.GetTexture( + Skin.GetTextureFileName(ThemeCollection.Style.FadeTex), TEXTURE_TYPE_COLORIZED, TempCol) + else + ButtonCollection[Num].FadeTex := Texture.GetTexture(Skin.GetTextureFileName(ThemeCollection.Style.FadeTex), ThemeCollection.Style.Typ, true); + ButtonCollection[Num].FadeTexPos := ThemeCollection.Style.FadeTexPos; + + + BTLen := Length(ThemeCollection.Style.Text); + for BT := 0 to BTLen-1 do begin + AddButtonText(ButtonCollection[Num], ThemeCollection.Style.Text[BT].X, ThemeCollection.Style.Text[BT].Y, + ThemeCollection.Style.Text[BT].ColR, ThemeCollection.Style.Text[BT].ColG, ThemeCollection.Style.Text[BT].ColB, + ThemeCollection.Style.Text[BT].Font, ThemeCollection.Style.Text[BT].Size, ThemeCollection.Style.Text[BT].Align, + ThemeCollection.Style.Text[BT].Text); + end; +end; + +function TMenu.AddStatic(ThemeStatic: TThemeStatic): integer; +begin + Result := AddStatic(ThemeStatic.X, ThemeStatic.Y, ThemeStatic.W, ThemeStatic.H, ThemeStatic.Z, + ThemeStatic.ColR, ThemeStatic.ColG, ThemeStatic.ColB, + ThemeStatic.TexX1, ThemeStatic.TexY1, ThemeStatic.TexX2, ThemeStatic.TexY2, + Skin.GetTextureFileName(ThemeStatic.Tex), + ThemeStatic.Typ, $FFFFFF, ThemeStatic.Reflection, ThemeStatic.Reflectionspacing); +end; + +function TMenu.AddStatic(X, Y, W, H: real; const Name: string): integer; +begin + Result := AddStatic(X, Y, W, H, Name, TEXTURE_TYPE_PLAIN); +end; + +function TMenu.AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; +var + StatNum: integer; +begin + Result := AddStatic(X, Y, W, H, ColR, ColG, ColB, Name, Typ, $FFFFFF); +end; + +function TMenu.AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; +var + StatNum: integer; +begin + Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, Name, Typ, $FFFFFF); +end; + +function TMenu.AddStatic(X, Y, W, H: real; const Name: string; Typ: TTextureType): integer; +var + StatNum: integer; +begin + // adds static + StatNum := Length(Static); + SetLength(Static, StatNum + 1); + Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, $FF00FF)); // new skin + + // configures static + Static[StatNum].Texture.X := X; + Static[StatNum].Texture.Y := Y; + Static[StatNum].Texture.W := W; + Static[StatNum].Texture.H := H; + Static[StatNum].Visible := true; + Result := StatNum; +end; + +function TMenu.AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; +var + StatNum: integer; +begin + Result := AddStatic(X, Y, W, H, 0, ColR, ColG, ColB, Name, Typ, Color); +end; + +function TMenu.AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; +begin + Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, 0, 0, 1, 1, Name, Typ, Color, False, 0); +end; + +function TMenu.AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; TexX1, TexY1, TexX2, TexY2: real; const Name: string; Typ: TTextureType; Color: integer; Reflection: Boolean; ReflectionSpacing: Real): integer; +var + StatNum: integer; +begin + // adds static + StatNum := Length(Static); + SetLength(Static, StatNum + 1); + + // colorize hack + if (Typ = TEXTURE_TYPE_COLORIZED) then + begin + // give encoded color to GetTexture() + Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB))); + end + else + begin + Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, Color)); // new skin + end; + + // configures static + Static[StatNum].Texture.X := X; + Static[StatNum].Texture.Y := Y; + Static[StatNum].Texture.W := W; + Static[StatNum].Texture.H := H; + Static[StatNum].Texture.Z := Z; + if (Typ <> TEXTURE_TYPE_COLORIZED) then begin + Static[StatNum].Texture.ColR := ColR; + Static[StatNum].Texture.ColG := ColG; + Static[StatNum].Texture.ColB := ColB; + end; + Static[StatNum].Texture.TexX1 := TexX1; + Static[StatNum].Texture.TexY1 := TexY1; + Static[StatNum].Texture.TexX2 := TexX2; + Static[StatNum].Texture.TexY2 := TexY2; + Static[StatNum].Texture.Alpha := 1; + Static[StatNum].Visible := true; + + //ReflectionMod + Static[StatNum].Reflection := Reflection; + Static[StatNum].ReflectionSpacing := ReflectionSpacing; + + Result := StatNum; +end; + +function TMenu.AddText(ThemeText: TThemeText): integer; +begin + Result := AddText(ThemeText.X, ThemeText.Y, ThemeText.W, ThemeText.Font, ThemeText.Size, + ThemeText.ColR, ThemeText.ColG, ThemeText.ColB, ThemeText.Align, ThemeText.Text); +end; + +function TMenu.AddText(X, Y: real; const Text_: string): integer; +var + TextNum: integer; +begin + // adds text + TextNum := Length(Text); + SetLength(Text, TextNum + 1); + Text[TextNum] := TText.Create(X, Y, Text_); + Result := TextNum; +end; + +function TMenu.AddText(X, Y: real; Style: integer; Size, ColR, ColG, ColB: real; const Text: string): integer; +begin + Result := AddText(X, Y, 0, Style, Size, ColR, ColG, ColB, 0, Text); +end; + +function TMenu.AddText(X, Y, W: real; Style: integer; Size, ColR, ColG, ColB: real; Align: integer; const Text_: string): integer; +var + TextNum: integer; +begin + // adds text + TextNum := Length(Text); + SetLength(Text, TextNum + 1); + Text[TextNum] := TText.Create(X, Y, W, Style, Size, ColR, ColG, ColB, Align, Text_); + Result := TextNum; +end; + +//Function that Set Length of Button Array in one Step instead of register new Memory for every Button +Procedure TMenu.SetButtonLength(Length: Cardinal); +begin + if (ButtonPos = -1) AND (Length > 0) then + begin + //Set Length of Button + SetLength(Button, Length); + + //Set ButtonPos to start with 0 + ButtonPos := 0; + end; +end; + + +// Method to add a button in our TMenu. It returns the assigned ButtonNumber +function TMenu.AddButton(ThemeButton: TThemeButton): integer; +var + BT: integer; + BTLen: integer; + temp: integer; + TempR, TempG, TempB, TempR2, TempG2, TempB2: Cardinal; +begin + Result := AddButton(ThemeButton.X, ThemeButton.Y, ThemeButton.W, ThemeButton.H, + ThemeButton.ColR, ThemeButton.ColG, ThemeButton.ColB, ThemeButton.Int, + ThemeButton.DColR, ThemeButton.DColG, ThemeButton.DColB, ThemeButton.DInt, + Skin.GetTextureFileName(ThemeButton.Tex), ThemeButton.Typ, + ThemeButton.Reflection, ThemeButton.Reflectionspacing, ThemeButton.DeSelectReflectionspacing); + + Button[Result].Z := ThemeButton.Z; + + //Button Visibility + Button[Result].Visible := ThemeButton.Visible; + + //Some Things from ButtonFading + Button[Result].SelectH := ThemeButton.SelectH; + Button[Result].SelectW := ThemeButton.SelectW; + + Button[Result].Fade := ThemeButton.Fade; + Button[Result].FadeText := ThemeButton.FadeText; + if (ThemeButton.Typ = TEXTURE_TYPE_COLORIZED) then begin + Button[Result].FadeTex := Texture.GetTexture( + Skin.GetTextureFileName(ThemeButton.FadeTex), TEXTURE_TYPE_COLORIZED, + RGBFloatToInt(ThemeButton.ColR, ThemeButton.ColG, ThemeButton.ColB)); + end + else + begin + Button[Result].FadeTex := Texture.GetTexture(Skin.GetTextureFileName(ThemeButton.FadeTex), ThemeButton.Typ, true); + end; + + Button[Result].FadeTexPos := ThemeButton.FadeTexPos; + + BTLen := Length(ThemeButton.Text); + for BT := 0 to BTLen-1 do begin + AddButtonText(ThemeButton.Text[BT].X, ThemeButton.Text[BT].Y, + ThemeButton.Text[BT].ColR, ThemeButton.Text[BT].ColG, ThemeButton.Text[BT].ColB, + ThemeButton.Text[BT].Font, ThemeButton.Text[BT].Size, ThemeButton.Text[BT].Align, + ThemeButton.Text[BT].Text); + end; + + //BAutton Collection Mod + if (ThemeButton.Parent <> 0) then + begin + //If Collection Exists then Change Interaction to Child Button + if (@ButtonCollection[ThemeButton.Parent-1] <> nil) then + begin + Interactions[High(Interactions)].Typ := iBCollectionChild; + Button[Result].Visible := False; + + for BT := 0 to BTLen-1 do + Button[Result].Text[BT].Alpha := 0; + + Button[Result].Parent := ThemeButton.Parent; + if (ButtonCollection[ThemeButton.Parent-1].Fade) then + Button[Result].Texture.Alpha := 0; + end; + end; + Log.BenchmarkEnd(6); + Log.LogBenchmark('====> Screen Options32', 6); +end; + +function TMenu.AddButton(X, Y, W, H: real; const Name: String): integer; +begin + Result := AddButton(X, Y, W, H, Name, TEXTURE_TYPE_PLAIN, False); +end; + +function TMenu.AddButton(X, Y, W, H: real; const Name: String; Typ: TTextureType; Reflection: Boolean): integer; +begin + Result := AddButton(X, Y, W, H, 1, 1, 1, 1, 1, 1, 1, 0.5, Name, TEXTURE_TYPE_PLAIN, Reflection, 15, 15); +end; + +function TMenu.AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real; + const Name: String; Typ: TTextureType; + Reflection: Boolean; ReflectionSpacing, DeSelectReflectionSpacing: Real): integer; +begin + // adds button + //SetLength is used once to reduce Memory usement + if (ButtonPos <> -1) then + begin + Result := ButtonPos; + Inc(ButtonPos) + end + else //Old Method -> Reserve new Memory for every Button + begin + Result := Length(Button); + SetLength(Button, Result + 1); + end; + // Button[Result] := TButton.Create(Texture.GetTexture(Name, Typ)); + + // check here for cache + // Texture.GetTexture(Name, Typ, false); // preloads textures and creates cahce mipmap when needed + // if Covers.CoverExists(Name) then + // colorize hack + if (Typ = TEXTURE_TYPE_COLORIZED) then + begin + // give encoded color to GetTexture() + Button[Result] := TButton.Create(Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)), + Texture.GetTexture(Name, Typ, RGBFloatToInt(DColR, DColG, DColB))); + end + else + begin + Button[Result] := TButton.Create(Texture.GetTexture(Name, Typ, true)); // use cache texture + end; + + // configures button + Button[Result].X := X; + Button[Result].Y := Y; + Button[Result].W := W; + Button[Result].H := H; + if (Typ <> TEXTURE_TYPE_COLORIZED) then begin + Button[Result].SelectColR := ColR; + Button[Result].SelectColG := ColG; + Button[Result].SelectColB := ColB; + Button[Result].DeselectColR := DColR; + Button[Result].DeselectColG := DColG; + Button[Result].DeselectColB := DColB; + end; + Button[Result].SelectInt := Int; + Button[Result].DeselectInt := DInt; + Button[Result].Texture.TexX1 := 0; + Button[Result].Texture.TexY1 := 0; + Button[Result].Texture.TexX2 := 1; + Button[Result].Texture.TexY2 := 1; + Button[Result].SetSelect(false); + + Button[Result].Reflection := Reflection; + Button[Result].Reflectionspacing := ReflectionSpacing; + Button[Result].DeSelectReflectionspacing := DeSelectReflectionSpacing; + + //Button Collection Mod + Button[Result].Parent := 0; + + + // adds interaction + AddInteraction(iButton, Result); + Interaction := 0; +end; + +procedure TMenu.ClearButtons; +begin + Setlength(Button, 0); +end; + +// Method to draw our TMenu and all his child buttons +function TMenu.DrawBG: boolean; +var + PetX: integer; + PetY: integer; +begin + + BackImg.ColR := 1; + BackImg.ColG := 1; + BackImg.ColB := 1; + BackImg.TexX1 := 0; + BackImg.TexY1 := 0; + BackImg.TexX2 := 1; + BackImg.TexY2 := 1; + if (BackImg.TexNum > 0) then + begin + // does anyone know what these loops were for? + { + // draw texture with overlapping + for PetY := 1 to BackH do + for PetX := 1 to BackW do begin + BackImg.X := (PetX-1)/BackW * 800; //640 + BackImg.Y := (PetY-1)/BackH * 600; //480 + DrawTexture(BackImg); + end; // for PetX + } + { + BackImg.X:=BackW; + BackImg.Y:=BackW; + } + BackImg.X := 0; + BackImg.Y := 0; + BackImg.Z := 0; // todo: eddie: to the opengl experts: please check this! On the mac z is not initialized??? + BackImg.W := 800; + BackImg.H := 600; + DrawTexture(BackImg); + end; // if + + + //if assigned( VideoPlayback ) then + begin + VideoPlayback.GetFrame( now() ); + VideoPlayback.DrawGL(2); + end; + + Result := true; +end; + +function TMenu.DrawFG: boolean; +var + J: Integer; +begin + // We don't forget about newly implemented static for nice skin ... + for J := 0 to Length(Static) - 1 do + Static[J].Draw; + + // ... and slightly implemented menutext unit + for J := 0 to Length(Text) - 1 do + Text[J].Draw; + + + // Draw all ButtonCollections + For J := 0 to High(ButtonCollection) do + ButtonCollection[J].Draw; + + // Second, we draw all of our buttons + for J := 0 to Length(Button) - 1 do + Button[J].Draw; + + // Third, we draw all of our selects + for J := 0 to Length(Selects) - 1 do + Selects[J].Draw(1); + + for J := 0 to Length(SelectsS) - 1 do + SelectsS[J].Draw; + + // Third, we draw all our widgets + // for J := 0 to Length(WidgetsSrc) - 1 do + // SDL_BlitSurface(WidgetsSrc[J], nil, ParentBackBuf, WidgetsRect[J]); + Result := True; +end; + +function TMenu.Draw: boolean; +begin + DrawBG; + DrawFG; + Result := True; +end; + +{ +function TMenu.GetNextScreen(): PMenu; +begin + Result := NextScreen; +end; +} + +{ +function TMenu.AddWidget(X, Y : UInt16; WidgetSrc : PSDL_Surface): Int16; +var + WidgetNum : Int16; +begin + If (Assigned(WidgetSrc)) Then + begin + WidgetNum := Length(WidgetsSrc); + + SetLength(WidgetsSrc, WidgetNum + 1); + SetLength(WidgetsRect, WidgetNum + 1); + + WidgetsSrc[WidgetNum] := WidgetSrc; + WidgetsRect[WidgetNum] := new(PSDL_Rect); + WidgetsRect[WidgetNum]^.x := X; + WidgetsRect[WidgetNum]^.y := Y; + WidgetsRect[WidgetNum]^.w := WidgetSrc^.w; + WidgetsRect[WidgetNum]^.h := WidgetSrc^.h; + + Result := WidgetNum; + end + else + Result := -1; +end; +} + +{ +procedure TMenu.ClearWidgets(MinNumber : Int16); +var + J : Int16; +begin + For J := MinNumber to (Length(WidgetsSrc) - 1) do + begin + SDL_FreeSurface(WidgetsSrc[J]); + dispose(WidgetsRect[J]); + end; + + SetLength(WidgetsSrc, MinNumber); + SetLength(WidgetsRect, MinNumber); +end; +} + +function TMenu.IsSelectable(Int: Cardinal): Boolean; +begin + Result := True; + Case Interactions[Int].Typ of + //Button + iButton: Result := Button[Interactions[Int].Num].Visible and Button[Interactions[Int].Num].Selectable; + //Select + iSelect: Result := True; + //Select Slide + iSelectS: Result := SelectsS[Interactions[Int].Num].Visible; + + //ButtonCollection Child + iBCollectionChild: + Result := (ButtonCollection[Button[Interactions[Int].Num].Parent - 1].FirstChild - 1 = Int) AND ((Interactions[Interaction].Typ <> iBCollectionChild) OR (Button[Interactions[Interaction].Num].Parent <> Button[Interactions[Int].Num].Parent)); + end; +end; + +procedure TMenu.InteractNext; +var + Int: Integer; +begin + Int := Interaction; + + // change interaction as long as it's needed + repeat + Int := (Int + 1) Mod Length(Interactions); + + //If no Interaction is Selectable Simply Select Next + if (Int = Interaction) then Break; + + Until IsSelectable(Int); + + //Set Interaction + Interaction := Int; +end; + + +procedure TMenu.InteractPrev; +var + Int: Integer; +begin + Int := Interaction; + + // change interaction as long as it's needed + repeat + Int := Int - 1; + if Int = -1 then Int := High(Interactions); + + //If no Interaction is Selectable Simply Select Next + if (Int = Interaction) then Break; + Until IsSelectable(Int); + + //Set Interaction + Interaction := Int +end; + + +procedure TMenu.InteractCustom(CustomSwitch: integer); +var + Num: integer; + Typ: integer; + Again: boolean; +begin + //Code Commented atm, because it needs to be Rewritten + //it doesn't work with Button Collections + {then begin + CustomSwitch:= CustomSwitch*(-1); + Again := true; + // change interaction as long as it's needed + while (Again = true) do begin + Num := SelInteraction - CustomSwitch; + if Num = -1 then Num := High(Interactions); + Interaction := Num; + Again := false; // reset, default to accept changing interaction + + // checking newly interacted element + Num := Interactions[Interaction].Num; + Typ := Interactions[Interaction].Typ; + case Typ of + iButton: + begin + if Button[Num].Selectable = false then Again := True; + end; + end; // case + end; // while + end + else if num>0 then begin + Again := true; + // change interaction as long as it's needed + while (Again = true) do begin + Num := (Interaction + CustomSwitch) Mod Length(Interactions); + Interaction := Num; + Again := false; // reset, default to accept changing interaction + + + // checking newly interacted element + Num := Interactions[Interaction].Num; + Typ := Interactions[Interaction].Typ; + case Typ of + iButton: + begin + if Button[Num].Selectable = false then Again := True; + end; + end; // case + end; // while + end } +end; + + +procedure TMenu.FadeTo(Screen: PMenu); +begin + Display.Fade := 0; + Display.NextScreen := Screen; +end; + +procedure TMenu.FadeTo(Screen: PMenu; aSound: TAudioPlaybackStream); +begin + FadeTo( Screen ); + AudioPlayback.PlaySound( aSound ); +end; + + +//popup hack +procedure TMenu.CheckFadeTo(Screen: PMenu; msg: String); +begin + Display.Fade := 0; + Display.NextScreenWithCheck := Screen; + Display.CheckOK:=False; + ScreenPopupCheck.ShowPopup(msg); +end; + +procedure TMenu.AddButtonText(AddX, AddY: real; const AddText: string); +begin + AddButtonText(AddX, AddY, 1, 1, 1, AddText); +end; + +procedure TMenu.AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; const AddText: string); +var + Il: integer; +begin + with Button[High(Button)] do begin + Il := Length(Text); + SetLength(Text, Il+1); + Text[Il] := TText.Create(X + AddX, Y + AddY, AddText); + Text[Il].ColR := ColR; + Text[Il].ColG := ColG; + Text[Il].ColB := ColB; + Text[Il].Int := 1;//0.5; + end; +end; + +procedure TMenu.AddButtonText(AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); +var + Il: integer; +begin + with Button[High(Button)] do begin + Il := Length(Text); + SetLength(Text, Il+1); + Text[Il] := TText.Create(X + AddX, Y + AddY, AddText); + Text[Il].ColR := ColR; + Text[Il].ColG := ColG; + Text[Il].ColB := ColB; + Text[Il].Int := 1;//0.5; + Text[Il].Style := Font; + Text[Il].Size := Size; + Text[Il].Align := Align; + end; +end; + +procedure TMenu.AddButtonText(CustomButton: TButton; AddX, AddY: real; ColR, ColG, ColB: real; Font: integer; Size: integer; Align: integer; const AddText: string); +var + Il: integer; +begin + with CustomButton do begin + Il := Length(Text); + SetLength(Text, Il+1); + Text[Il] := TText.Create(X + AddX, Y + AddY, AddText); + Text[Il].ColR := ColR; + Text[Il].ColG := ColG; + Text[Il].ColB := ColB; + Text[Il].Int := 1;//0.5; + Text[Il].Style := Font; + Text[Il].Size := Size; + Text[Il].Align := Align; + end; +end; + +function TMenu.AddSelect(ThemeSelect: TThemeSelect; var Data: integer; Values: array of string): integer; +var + SO: integer; +begin + Result := AddSelect(ThemeSelect.X, ThemeSelect.Y, ThemeSelect.W, ThemeSelect.H, ThemeSelect.SkipX, + ThemeSelect.ColR, ThemeSelect.ColG, ThemeSelect.ColB, ThemeSelect.Int, + ThemeSelect.DColR, ThemeSelect.DColG, ThemeSelect.DColB, ThemeSelect.DInt, + ThemeSelect.TColR, ThemeSelect.TColG, ThemeSelect.TColB, ThemeSelect.TInt, + ThemeSelect.TDColR, ThemeSelect.TDColG, ThemeSelect.TDColB, ThemeSelect.TDInt, + ThemeSelect.SBGColR, ThemeSelect.SBGColG, ThemeSelect.SBGColB, ThemeSelect.SBGInt, + ThemeSelect.SBGDColR, ThemeSelect.SBGDColG, ThemeSelect.SBGDColB, ThemeSelect.SBGDInt, + ThemeSelect.STColR, ThemeSelect.STColG, ThemeSelect.STColB, ThemeSelect.STInt, + ThemeSelect.STDColR, ThemeSelect.STDColG, ThemeSelect.STDColB, ThemeSelect.STDInt, + Skin.GetTextureFileName(ThemeSelect.Tex), TEXTURE_TYPE_COLORIZED, + Skin.GetTextureFileName(ThemeSelect.TexSBG), TEXTURE_TYPE_COLORIZED, + ThemeSelect.Text, Data); + for SO := 0 to High(Values) do + AddSelectOption(ThemeSelect.X + ThemeSelect.W + ThemeSelect.SkipX + SO * 100 + 20, ThemeSelect.Y + 20, Values[SO]); +end; + +function TMenu.AddSelect(X, Y, W, H, SkipX, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt, + TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt, + SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt, + STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real; + const Name: String; Typ: TTextureType; const SBGName: String; SBGTyp: TTextureType; + const Caption: string; var Data: integer): integer; +var + S: integer; +begin + S := Length(Selects); + SetLength(Selects, S + 1); + Selects[S] := TSelect.Create; + + if (Typ = TEXTURE_TYPE_COLORIZED) then + Selects[S].Texture := Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)) + else + Selects[S].Texture := Texture.GetTexture(Name, Typ); + Selects[S].X := X; + Selects[S].Y := Y; + Selects[S].W := W; + Selects[S].H := H; + Selects[S].ColR := ColR; + Selects[S].ColG := ColG; + Selects[S].ColB := ColB; + Selects[S].Int := Int; + Selects[S].DColR := DColR; + Selects[S].DColG := DColG; + Selects[S].DColB := DColB; + Selects[S].DInt := DInt; + + if (SBGTyp = TEXTURE_TYPE_COLORIZED) then + Selects[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp, RGBFloatToInt(SBGColR, SBGColG, SBGColB)) + else + Selects[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp); + Selects[S].TextureSBG.X := X + W + SkipX; + Selects[S].TextureSBG.Y := Y; + Selects[S].TextureSBG.W := 450; + Selects[S].TextureSBG.H := H; + Selects[S].SBGColR := SBGColR; + Selects[S].SBGColG := SBGColG; + Selects[S].SBGColB := SBGColB; + Selects[S].SBGInt := SBGInt; + Selects[S].SBGDColR := SBGDColR; + Selects[S].SBGDColG := SBGDColG; + Selects[S].SBGDColB := SBGDColB; + Selects[S].SBGDInt := SBGDInt; + + Selects[S].Text.X := X + 20; + Selects[S].Text.Y := Y + 20; + Selects[S].Text.Text := Caption; + Selects[S].Text.Size := 10; + Selects[S].Text.Visible := true; + Selects[S].TColR := TColR; + Selects[S].TColG := TColG; + Selects[S].TColB := TColB; + Selects[S].TInt := TInt; + Selects[S].TDColR := TDColR; + Selects[S].TDColG := TDColG; + Selects[S].TDColB := TDColB; + Selects[S].TDInt := TDInt; + + Selects[S].STColR := STColR; + Selects[S].STColG := STColG; + Selects[S].STColB := STColB; + Selects[S].STInt := STInt; + Selects[S].STDColR := STDColR; + Selects[S].STDColG := STDColG; + Selects[S].STDColB := STDColB; + Selects[S].STDInt := STDInt; + + // new + Selects[S].Texture.TexX1 := 0; + Selects[S].Texture.TexY1 := 0; + Selects[S].Texture.TexX2 := 1; + Selects[S].Texture.TexY2 := 1; + Selects[S].TextureSBG.TexX1 := 0; + Selects[S].TextureSBG.TexY1 := 0; + Selects[S].TextureSBG.TexX2 := 1; + Selects[S].TextureSBG.TexY2 := 1; + + // Sets Data to copy the value of selectops to global value; + Selects[S].PData := @Data; + + // Sets default value of selectopt from Data; + Selects[S].SelectedOption := Data; + + // Disables default selection + Selects[S].SetSelect(false); + + // adds interaction + AddInteraction(iSelect, S); +end; + +procedure TMenu.AddSelectOption(AddX, AddY: real; const AddText: string); +begin + AddSelectOption (High(Selects), AddX, AddY, AddText); +end; + +procedure TMenu.AddSelectOption(SelectNo: Cardinal; AddX, AddY: real; const AddText: string); +var + SO: integer; +begin + SO := Length(Selects[SelectNo].TextOpt); + SetLength(Selects[SelectNo].TextOpt, SO + 1); + + Selects[SelectNo].TextOpt[SO] := TText.Create; + + Selects[SelectNo].TextOpt[SO].X := AddX; + Selects[SelectNo].TextOpt[SO].Y := AddY; + Selects[SelectNo].TextOpt[SO].Text := AddText; + Selects[SelectNo].TextOpt[SO].Size := 10; + Selects[SelectNo].TextOpt[SO].ColR := Selects[SelectNo].STDColR; + Selects[SelectNo].TextOpt[SO].ColG := Selects[SelectNo].STDColG; + Selects[SelectNo].TextOpt[SO].ColB := Selects[SelectNo].STDColB; + Selects[SelectNo].TextOpt[SO].Int := Selects[SelectNo].STDInt; + Selects[SelectNo].TextOpt[SO].Visible := true; + + if SO = Selects[SelectNo].PData^ then Selects[SelectNo].SelectedOption := SO; +end; + +procedure TMenu.UpdateSelectOptions(ThemeSelect: TThemeSelect; SelectNum: integer; Values: array of string; var Data: integer); +var + SO: integer; +begin + SetLength(Selects[SelectNum].TextOpt, 0); + for SO := 0 to High(Values) do + AddSelectOption(SelectNum, ThemeSelect.X + ThemeSelect.W + ThemeSelect.SkipX + SO * 100 + 20, ThemeSelect.Y + 20, Values[SO]); +end; + +function TMenu.AddSelectSlide(ThemeSelectS: TThemeSelectSlide; var Data: integer; Values: array of string): integer; +var + SO: integer; +begin + Result := AddSelectSlide(ThemeSelectS.X, ThemeSelectS.Y, ThemeSelectS.W, ThemeSelectS.H, ThemeSelectS.SkipX, ThemeSelectS.SBGW, + ThemeSelectS.ColR, ThemeSelectS.ColG, ThemeSelectS.ColB, ThemeSelectS.Int, + ThemeSelectS.DColR, ThemeSelectS.DColG, ThemeSelectS.DColB, ThemeSelectS.DInt, + ThemeSelectS.TColR, ThemeSelectS.TColG, ThemeSelectS.TColB, ThemeSelectS.TInt, + ThemeSelectS.TDColR, ThemeSelectS.TDColG, ThemeSelectS.TDColB, ThemeSelectS.TDInt, + ThemeSelectS.SBGColR, ThemeSelectS.SBGColG, ThemeSelectS.SBGColB, ThemeSelectS.SBGInt, + ThemeSelectS.SBGDColR, ThemeSelectS.SBGDColG, ThemeSelectS.SBGDColB, ThemeSelectS.SBGDInt, + ThemeSelectS.STColR, ThemeSelectS.STColG, ThemeSelectS.STColB, ThemeSelectS.STInt, + ThemeSelectS.STDColR, ThemeSelectS.STDColG, ThemeSelectS.STDColB, ThemeSelectS.STDInt, + Skin.GetTextureFileName(ThemeSelectS.Tex), TEXTURE_TYPE_COLORIZED, + Skin.GetTextureFileName(ThemeSelectS.TexSBG), TEXTURE_TYPE_COLORIZED, + ThemeSelectS.Text, Data); + for SO := 0 to High(Values) do + AddSelectSlideOption(Values[SO]); + + SelectsS[High(SelectsS)].Text.Size := ThemeSelectS.TextSize; + + SelectsS[High(SelectsS)].Texture.Z := ThemeSelectS.Z; + SelectsS[High(SelectsS)].TextureSBG.Z := ThemeSelectS.Z; + + //Generate Lines + SelectsS[High(SelectsS)].GenLines; + + SelectsS[High(SelectsS)].SelectedOption := SelectsS[High(SelectsS)].SelectOptInt; // refresh +end; + +function TMenu.AddSelectSlide(X, Y, W, H, SkipX, SBGW, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt, + TColR, TColG, TColB, TInt, TDColR, TDColG, TDColB, TDInt, + SBGColR, SBGColG, SBGColB, SBGInt, SBGDColR, SBGDColG, SBGDColB, SBGDInt, + STColR, STColG, STColB, STInt, STDColR, STDColG, STDColB, STDInt: real; + const Name: String; Typ: TTextureType; const SBGName: String; SBGTyp: TTextureType; + const Caption: string; var Data: integer): integer; +var + S: integer; + I: integer; +begin + S := Length(SelectsS); + SetLength(SelectsS, S + 1); + SelectsS[S] := TSelectSlide.Create; + + if (Typ = TEXTURE_TYPE_COLORIZED) then + SelectsS[S].Texture := Texture.GetTexture(Name, Typ, RGBFloatToInt(ColR, ColG, ColB)) + else + SelectsS[S].Texture := Texture.GetTexture(Name, Typ); + SelectsS[S].X := X; + SelectsS[S].Y := Y; + SelectsS[S].W := W; + SelectsS[S].H := H; + + SelectsS[S].ColR := ColR; + SelectsS[S].ColG := ColG; + SelectsS[S].ColB := ColB; + SelectsS[S].Int := Int; + SelectsS[S].DColR := DColR; + SelectsS[S].DColG := DColG; + SelectsS[S].DColB := DColB; + SelectsS[S].DInt := DInt; + + if (SBGTyp = TEXTURE_TYPE_COLORIZED) then + SelectsS[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp, RGBFloatToInt(SBGColR, SBGColG, SBGColB)) + else + SelectsS[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp); + SelectsS[S].TextureSBG.X := X + W + SkipX; + SelectsS[S].TextureSBG.Y := Y; + //SelectsS[S].TextureSBG.W := 450; + SelectsS[S].SBGW := SBGW; + SelectsS[S].TextureSBG.H := H; + SelectsS[S].SBGColR := SBGColR; + SelectsS[S].SBGColG := SBGColG; + SelectsS[S].SBGColB := SBGColB; + SelectsS[S].SBGInt := SBGInt; + SelectsS[S].SBGDColR := SBGDColR; + SelectsS[S].SBGDColG := SBGDColG; + SelectsS[S].SBGDColB := SBGDColB; + SelectsS[S].SBGDInt := SBGDInt; + + SelectsS[S].Text.X := X + 20; + SelectsS[S].Text.Y := Y + (SelectsS[S].TextureSBG.H / 2) - 15; + SelectsS[S].Text.Text := Caption; + SelectsS[S].Text.Size := 10; + SelectsS[S].Text.Visible := true; + SelectsS[S].TColR := TColR; + SelectsS[S].TColG := TColG; + SelectsS[S].TColB := TColB; + SelectsS[S].TInt := TInt; + SelectsS[S].TDColR := TDColR; + SelectsS[S].TDColG := TDColG; + SelectsS[S].TDColB := TDColB; + SelectsS[S].TDInt := TDInt; + + SelectsS[S].STColR := STColR; + SelectsS[S].STColG := STColG; + SelectsS[S].STColB := STColB; + SelectsS[S].STInt := STInt; + SelectsS[S].STDColR := STDColR; + SelectsS[S].STDColG := STDColG; + SelectsS[S].STDColB := STDColB; + SelectsS[S].STDInt := STDInt; + + // new + SelectsS[S].Texture.TexX1 := 0; + SelectsS[S].Texture.TexY1 := 0; + SelectsS[S].Texture.TexX2 := 1; + SelectsS[S].Texture.TexY2 := 1; + SelectsS[S].TextureSBG.TexX1 := 0; + SelectsS[S].TextureSBG.TexY1 := 0; + SelectsS[S].TextureSBG.TexX2 := 1; + SelectsS[S].TextureSBG.TexY2 := 1; + + // Sets Data to copy the value of selectops to global value; + SelectsS[S].PData := @Data; + // Configures Select options + {//SelectsS[S].TextOpt[0].Text := IntToStr(I+1); + SelectsS[S].TextOpt[0].Size := 10; + SelectsS[S].TextOpt[0].Align := 1; + + SelectsS[S].TextOpt[0].ColR := SelectsS[S].STDColR; + SelectsS[S].TextOpt[0].ColG := SelectsS[S].STDColG; + SelectsS[S].TextOpt[0].ColB := SelectsS[S].STDColB; + SelectsS[S].TextOpt[0].Int := SelectsS[S].STDInt; + SelectsS[S].TextOpt[0].Visible := true; } + + // Sets default value of selectopt from Data; + SelectsS[S].SelectedOption := Data; + + // Disables default selection + SelectsS[S].SetSelect(false); + + {// Configures 3 select options + for I := 0 to 2 do begin + SelectsS[S].TextOpt[I].X := SelectsS[S].TextureSBG.X + 20 + (50 + 20) + (150 - 20) * I; + SelectsS[S].TextOpt[I].Y := SelectsS[S].TextureSBG.Y + 20; + SelectsS[S].TextOpt[I].Text := IntToStr(I+1); + SelectsS[S].TextOpt[I].Size := 10; + SelectsS[S].TextOpt[I].Align := 1; + + + SelectsS[S].TextOpt[I].ColR := SelectsS[S].STDColR; + SelectsS[S].TextOpt[I].ColG := SelectsS[S].STDColG; + SelectsS[S].TextOpt[I].ColB := SelectsS[S].STDColB; + SelectsS[S].TextOpt[I].Int := SelectsS[S].STDInt; + SelectsS[S].TextOpt[I].Visible := true; + end;} + + + // adds interaction + AddInteraction(iSelectS, S); + Result := S; +end; + +procedure TMenu.AddSelectSlideOption(const AddText: string); +begin + AddSelectSlideOption(High(SelectsS), AddText); +end; + +procedure TMenu.AddSelectSlideOption(SelectNo: Cardinal; const AddText: string); +var + SO: integer; +begin + SO := Length(SelectsS[SelectNo].TextOptT); + + SetLength(SelectsS[SelectNo].TextOptT, SO + 1); + SelectsS[SelectNo].TextOptT[SO] := AddText; + + //SelectsS[S].SelectedOption := SelectsS[S].SelectOptInt; // refresh + + //if SO = Selects[S].PData^ then Selects[S].SelectedOption := SO; +end; + +procedure TMenu.UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; Values: array of string; var Data: integer); +var + SO: integer; +begin + SetLength(SelectsS[SelectNum].TextOptT, 0); + for SO := 0 to High(Values) do + AddSelectSlideOption(SelectNum, Values[SO]); + + SelectsS[SelectNum].GenLines; + +// SelectsS[SelectNum].SelectedOption := SelectsS[SelectNum].SelectOptInt; // refresh +// SelectS[SelectNum].SetSelectOpt(Data); +// SelectS[SelectNum].SelectedOption := 0;//Data; + +// Log.LogError(IntToStr(High(SelectsS[SelectNum].TextOptT))); +// if 0 <= High(SelectsS[SelectNum].TextOptT) then + + SelectsS[SelectNum].PData := @Data; + SelectsS[SelectNum].SelectedOption := Data; +end; + +function TMenu.InRegion(X1, Y1, X2, Y2, X, Y: real): Boolean; +begin + Result := false; + X1 := X1 * RenderW/640; + X2 := X2 * RenderW/640; + Y1 := Y1 * RenderH/480; + Y2 := Y2 * RenderH/480; + if (X >= X1) and (X <= X2) and (Y >= Y1) and (Y <= Y2) then + Result := true; +end; + +function TMenu.InStaticRegion(StaticNr: integer; X, Y: integer): Boolean; +begin + Result := InRegion(Static[StaticNr].Texture.X, + Static[StaticNr].Texture.Y, + Static[StaticNr].Texture.X + Static[StaticNr].Texture.W - 1, + Static[StaticNr].Texture.Y + Static[StaticNr].Texture.H - 1, + X, Y); +end; + +procedure TMenu.InteractInc; +var + Num: integer; + Value: integer; +begin + case Interactions[Interaction].Typ of + iSelect: begin + Num := Interactions[Interaction].Num; + Value := Selects[Num].SelectedOption; + Value := (Value + 1) Mod (Length(Selects[Num].TextOpt)); + Selects[Num].SelectedOption := Value; + end; + iSelectS: begin + Num := Interactions[Interaction].Num; + Value := SelectsS[Num].SelectedOption; +// Value := (Value + 1) Mod (Length(SelectsS[Num].TextOptT)); + + // limit + Value := Value + 1; + if Value <= High(SelectsS[Num].TextOptT) then + SelectsS[Num].SelectedOption := Value; + end; + //Button Collection Mod + iBCollectionChild: + begin + + //Select Next Button in Collection + For Num := 1 to High(Button) do + begin + Value := (Interaction + Num) Mod Length(Button); + if Value = 0 then + begin + InteractNext; + Break; + end; + if (Button[Value].Parent = Button[Interaction].Parent) then + begin + Interaction := Value; + Break; + end; + end; + end; + //interact Next if there is Nothing to Change + else InteractNext; + end; +end; + +procedure TMenu.InteractDec; +var + Num: integer; + Value: integer; +begin + case Interactions[Interaction].Typ of + iSelect: begin + Num := Interactions[Interaction].Num; + Value := Selects[Num].SelectedOption; + Value := Value - 1; + if Value = -1 then + Value := High(Selects[Num].TextOpt); + Selects[Num].SelectedOption := Value; + end; + iSelectS: begin + Num := Interactions[Interaction].Num; + Value := SelectsS[Num].SelectedOption; + Value := Value - 1; +// if Value = -1 then +// Value := High(SelectsS[Num].TextOptT); + + if Value >= 0 then + SelectsS[Num].SelectedOption := Value; + end; + //Button Collection Mod + iBCollectionChild: + begin + //Select Prev Button in Collection + For Num := High(Button) downto 1 do + begin + Value := (Interaction + Num) Mod Length(Button); + if Value = High(Button) then + begin + InteractPrev; + Break; + end; + if (Button[Value].Parent = Button[Interaction].Parent) then + begin + Interaction := Value; + Break; + end; + end; + end; + //interact Prev if there is Nothing to Change + else + begin + InteractPrev; + //If ButtonCollection with more than 1 Entry then Select Last Entry + if (Button[Interactions[Interaction].Num].Parent <> 0) AND (ButtonCollection[Button[Interactions[Interaction].Num].Parent-1].CountChilds > 1) then + begin + //Select Last Child + For Num := High(Button) downto 1 do + begin + Value := (Interaction + Num) Mod Length(Button); + if (Button[Value].Parent = Button[Interaction].Parent) then + begin + Interaction := Value; + Break; + end; + end; + end; + end; + end; +end; + +procedure TMenu.AddBox(X, Y, W, H: real); +begin + AddStatic(X, Y, W, H, 0, 0, 0, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED); + AddStatic(X+2, Y+2, W-4, H-4, 1, 1, 1, Skin.GetTextureFileName('MainBar'), TEXTURE_TYPE_COLORIZED); +end; + +procedure TMenu.onShow; +begin + // nothing +(* + if fileexists( fFileName ) then + begin + if VideoPlayback.Open( fFileName ) then + VideoPlayback.Play; + end; +*) +end; + +procedure TMenu.onShowFinish; +begin + // nothing +end; + +function TMenu.WideCharUpperCase(wchar: WideChar) : WideString; +begin + // On Linux and MacOSX the cwstring unit is necessary for Unicode function-calls. + // Otherwise you will get an EIntOverflow exception (thrown by unimplementedwidestring()). + + // The FPC implementation of WideUpperCase returns nil if wchar is #0 (e.g. if an arrow key is pressed) + if (wchar <> #0) then + Result := WideUpperCase(wchar) + else + Result := #0; +end; + +procedure TMenu.onHide; +begin + // nothing +end; + +function TMenu.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; +begin + // nothing + Result := true; +end; + +procedure TMenu.SetAnimationProgress(Progress: real); +begin + // nothing +end; + +end. + diff --git a/Game/Code/Menu/UMenuButton.pas b/Game/Code/Menu/UMenuButton.pas index 652b5112..8cda0b1d 100644 --- a/Game/Code/Menu/UMenuButton.pas +++ b/Game/Code/Menu/UMenuButton.pas @@ -1,570 +1,570 @@ -unit UMenuButton; - -interface - -{$I switches.inc} - -uses TextGL, UTexture, OpenGL12, UMenuText,SDL; - -type - CButton = class of TButton; - TButton = class - protected - SelectBool: Boolean; - - FadeProgress: Real; - FadeLastTick: Cardinal; - - DeSelectW: Real; - DeSelectH: Real; - PosX: Real; - PosY: Real; - - constructor Create(); overload; - - public - Text: Array of TText; - Texture: TTexture; // Button Screen position and size - Texture2: TTexture; // second texture only used for fading full resolution covers - //colorized hack - Colorized: Boolean; - DeSelectTexture: TTexture; // texture for colorized hack - - FadeTex: TTexture; //Texture for beautiful fading - FadeTexPos: byte; //Pos of the FadeTexture (0: Top, 1: Left, 2: Bottom, 3: Right) -// Texture2Blend: real; // blending factor for second texture (0=invisible, 1=visible) - // now uses alpha - - DeselectType: integer; // not used yet - Visible: boolean; - //Reflection Mod - Reflection: boolean; - Reflectionspacing: Real; - DeSelectReflectionspacing: Real; - - //Fade Mod - Fade: Boolean; - FadeText: Boolean; - - Selectable: boolean; - - //No of the Parent Collection, 0 if in no Collection - Parent: Byte; - - SelectColR: real; - SelectColG: real; - SelectColB: real; - SelectInt: real; - SelectTInt: real; - //Fade Mod - SelectW: real; - SelectH: real; - - DeselectColR: real; - DeselectColG: real; - DeselectColB: real; - DeselectInt: real; - DeselectTInt: real; - - procedure SetY(Value: real); - procedure SetX(Value: real); - procedure SetW(Value: real); - procedure SetH(Value: real); - - procedure SetSelect(Value: Boolean); virtual; - property X: real read PosX write SetX; - property Y: real read PosY write SetY; - property Z: real read Texture.z write Texture.z; - property W: real read DeSelectW write SetW; - property H: real read DeSelectH write SetH; - property Selected: Boolean read SelectBool write SetSelect; - - procedure Draw; virtual; - - constructor Create(Textura: TTexture); overload; - constructor Create(Textura, DSTexture: TTexture); overload; - destructor Destroy; override; - end; - -implementation - -uses SysUtils, - UDrawTexture; - -procedure TButton.SetX(Value: real); -{var - dx: real; - T: integer; // text} -begin - {dY := Value - Texture.y; - - Texture.X := Value; - - for T := 0 to High(Text) do - Text[T].X := Text[T].X + dY;} - - PosX := Value; - if (FadeTex.TexNum = -1) then - Texture.X := Value; - -end; - -procedure TButton.SetY(Value: real); -{var - dY: real; - T: integer; // text} -begin - {dY := Value - PosY; - - - for T := 0 to High(Text) do - Text[T].Y := Text[T].Y + dY;} - - PosY := Value; - if (FadeTex.TexNum = -1) then - Texture.y := Value; -end; - -procedure TButton.SetW(Value: real); -begin - if SelectW = DeSelectW then - SelectW := Value; - - DeSelectW := Value; - - if Not Fade then - begin - if SelectBool then - Texture.W := SelectW - else - Texture.W := DeSelectW; - end; -end; - -procedure TButton.SetH(Value: real); -begin - if SelectH = DeSelectH then - SelectH := Value; - - DeSelectH := Value; - - if Not Fade then - begin - if SelectBool then - Texture.H := SelectH - else - Texture.H := DeSelectH; - end; -end; - -procedure TButton.SetSelect(Value : Boolean); -var - T: integer; -begin - SelectBool := Value; - if (Value) then begin - Texture.ColR := SelectColR; - Texture.ColG := SelectColG; - Texture.ColB := SelectColB; - Texture.Int := SelectInt; - - Texture2.ColR := SelectColR; - Texture2.ColG := SelectColG; - Texture2.ColB := SelectColB; - Texture2.Int := SelectInt; - - for T := 0 to High(Text) do - Text[T].Int := SelectTInt; - - //Fade Mod - if Fade then - begin - if (FadeProgress <= 0) then - FadeProgress := 0.125; - end - else - begin - Texture.W := SelectW; - Texture.H := SelectH; - end; - end else begin - Texture.ColR := DeselectColR; - Texture.ColG := DeselectColG; - Texture.ColB := DeselectColB; - Texture.Int := DeselectInt; - - Texture2.ColR := DeselectColR; - Texture2.ColG := DeselectColG; - Texture2.ColB := DeselectColB; - Texture2.Int := DeselectInt; - - for T := 0 to High(Text) do - Text[T].Int := DeselectTInt; - - //Fade Mod - if Fade then - begin - if (FadeProgress >= 1) then - FadeProgress := 0.875; - end - else - begin - Texture.W := DeSelectW; - Texture.H := DeSelectH; - end; - end; -end; - -constructor TButton.Create(); -begin - inherited Create; - // We initialize all to 0, nil or false - Visible := true; - SelectBool := false; - DeselectType := 0; - Selectable := true; - //Reflection Mod - Reflection := true; - - //colorized hack - Colorized:=False; - - // Default -// SelectInt := 1; -// DeselectInt := 0.5; - -{ SelectColR := 0.5; - SelectColG := 0.75; - SelectColB := 0; - SelectInt := 1; - SelectTInt := 1; - - DeselectColR := 1; - DeselectColG := 1; - DeselectColB := 1; - DeselectInt := 0.5; - DeselectTInt := 1;} - - SelectColR := 1; - SelectColG := 1; - SelectColB := 1; - SelectInt := 1; - SelectTInt := 1; - - DeselectColR := 1; - DeselectColG := 1; - DeselectColB := 1; - DeselectInt := 0.5; - DeselectTInt := 1; - - FadeTex.TexNum := -1; - - FadeProgress := 0; - Fade := False; - FadeText := False; - SelectW := DeSelectW; - SelectH := DeSelectH; - - PosX := 0; - PosY := 0; - - Parent := 0; -end; - -// ***** Public methods ****** // - -procedure TButton.Draw; -var - T: integer; - Tick: Cardinal; - Spacing: Real; -begin - if Visible then begin - //Fade Mod - T:=0; - if Fade then - begin - if (FadeProgress < 1) and (FadeProgress > 0) then - begin - Tick := SDL_GetTicks() div 16; - if (Tick <> FadeLastTick) then - begin - FadeLastTick := Tick; - if SelectBool then - FadeProgress := FadeProgress + 0.125 - else - FadeProgress := FadeProgress - 0.125; - - if (FadeText) then - begin - For T := 0 to high(Text) do - begin - Text[T].MoveX := (SelectW - DeSelectW) * FadeProgress; - Text[T].MoveY := (SelectH - DeSelectH) * FadeProgress; - end; - end; - end; - end; - //Method without Fade Texture - if (FadeTex.TexNum = -1) then - begin - Texture.W := DeSelectW + (SelectW - DeSelectW) * FadeProgress; - Texture.H := DeSelectH + (SelectH - DeSelectH) * FadeProgress; - DeselectTexture.W := Texture.W; - DeselectTexture.H := Texture.H; - end - else //method with Fade Texture - begin - Texture.W := DeSelectW; - Texture.H := DeSelectH; - DeselectTexture.W := Texture.W; - DeselectTexture.H := Texture.H; - - FadeTex.ColR := Texture.ColR; - FadeTex.ColG := Texture.ColG; - FadeTex.ColB := Texture.ColB; - FadeTex.Int := Texture.Int; - - FadeTex.Z := Texture.Z; - - FadeTex.Alpha := Texture.Alpha; - FadeTex.TexX1 := 0; - FadeTex.TexX2 := 1; - FadeTex.TexY1 := 0; - FadeTex.TexY2 := 1; - - Case FadeTexPos of - 0: //FadeTex on Top - begin - //Standard Texture - Texture.X := PosX; - Texture.Y := PosY + (SelectH - DeSelectH) * FadeProgress; - DeselectTexture.X := Texture.X; - DeselectTexture.Y := Texture.Y; - //Fade Tex - FadeTex.X := PosX; - FadeTex.Y := PosY; - FadeTex.W := Texture.W; - FadeTex.H := (SelectH - DeSelectH) * FadeProgress; - FadeTex.ScaleW := Texture.ScaleW; - //Some Hack that Fixes a little Space between both Textures - FadeTex.TexY2 := 0.9; - end; - 1: //FadeTex on Left - begin - //Standard Texture - Texture.X := PosX + (SelectW - DeSelectW) * FadeProgress; - Texture.Y := PosY; - DeselectTexture.X := Texture.X; - DeselectTexture.Y := Texture.Y; - //Fade Tex - FadeTex.X := PosX; - FadeTex.Y := PosY; - FadeTex.H := Texture.H; - FadeTex.W := (SelectW - DeSelectW) * FadeProgress; - FadeTex.ScaleH := Texture.ScaleH; - //Some Hack that Fixes a little Space between both Textures - FadeTex.TexX2 := 0.9; - end; - 2: //FadeTex on Bottom - begin - //Standard Texture - Texture.X := PosX; - Texture.Y := PosY; - DeselectTexture.X := Texture.X; - DeselectTexture.Y := Texture.Y; - //Fade Tex - FadeTex.X := PosX; - FadeTex.Y := PosY + (SelectH - DeSelectH) * FadeProgress;; - FadeTex.W := Texture.W; - FadeTex.H := (SelectH - DeSelectH) * FadeProgress; - FadeTex.ScaleW := Texture.ScaleW; - //Some Hack that Fixes a little Space between both Textures - FadeTex.TexY1 := 0.1; - end; - 3: //FadeTex on Right - begin - //Standard Texture - Texture.X := PosX; - Texture.Y := PosY; - DeselectTexture.X := Texture.X; - DeselectTexture.Y := Texture.Y; - //Fade Tex - FadeTex.X := PosX + (SelectW - DeSelectW) * FadeProgress; - FadeTex.Y := PosY; - FadeTex.H := Texture.H; - FadeTex.W := (SelectW - DeSelectW) * FadeProgress; - FadeTex.ScaleH := Texture.ScaleH; - //Some Hack that Fixes a little Space between both Textures - FadeTex.TexX1 := 0.1; - end; - end; - end; - end - else if (FadeText) then - begin - Text[T].MoveX := (SelectW - DeSelectW); - Text[T].MoveY := (SelectH - DeSelectH); - end; - - if SelectBool or (FadeProgress > 0) or not Colorized then - DrawTexture(Texture) - else - DrawTexture(DeselectTexture); - - //Draw FadeTex - if (FadeTex.TexNum <> -1) then - DrawTexture(FadeTex); - - if Texture2.Alpha > 0 then begin - Texture2.ScaleW := Texture.ScaleW; - Texture2.ScaleH := Texture.ScaleH; - - Texture2.X := Texture.X; - Texture2.Y := Texture.Y; - Texture2.W := Texture.W; - Texture2.H := Texture.H; - - Texture2.ColR := Texture.ColR; - Texture2.ColG := Texture.ColG; - Texture2.ColB := Texture.ColB; - Texture2.Int := Texture.Int; - - Texture2.Z := Texture.Z; - - DrawTexture(Texture2); - end; - - //Reflection Mod - if (Reflection) then // Draw Reflections - begin - if (FadeProgress <> 0) AND (FadeProgress <> 1) then - begin - Spacing := DeSelectReflectionspacing - (DeSelectReflectionspacing - Reflectionspacing) * FadeProgress; - end - else if SelectBool then - Spacing := Reflectionspacing - else - Spacing := DeSelectReflectionspacing; - - if SelectBool or not Colorized then - with Texture do - begin - //Bind Tex and GL Attributes - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - - glDepthRange(0, 10); - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, TexNum); - - //Draw - glBegin(GL_QUADS);//Top Left - glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3); - glTexCoord2f(TexX1*TexW, TexY2*TexH); - glVertex3f(x, y+h*scaleH+ Spacing, z); - - //Bottom Left - glColor4f(ColR * Int, ColG * Int, ColB * Int, 0); - glTexCoord2f(TexX1*TexW, TexY1+TexH*0.5); - glVertex3f(x, y+h*scaleH + h*scaleH/2 + Spacing, z); - - - //Bottom Right - glColor4f(ColR * Int, ColG * Int, ColB * Int, 0); - glTexCoord2f(TexX2*TexW, TexY1+TexH*0.5); - glVertex3f(x+w*scaleW, y+h*scaleH + h*scaleH/2 + Spacing, z); - - //Top Right - glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3); - glTexCoord2f(TexX2*TexW, TexY2*TexH); - glVertex3f(x+w*scaleW, y+h*scaleH + Spacing, z); - glEnd; - - glDisable(GL_TEXTURE_2D); - glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - end else - with DeselectTexture do - begin - //Bind Tex and GL Attributes - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - - glDepthRange(0, 10); - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, TexNum); - - //Draw - glBegin(GL_QUADS);//Top Left - glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3); - glTexCoord2f(TexX1*TexW, TexY2*TexH); - glVertex3f(x, y+h*scaleH+ Spacing, z); - - //Bottom Left - glColor4f(ColR * Int, ColG * Int, ColB * Int, 0); - glTexCoord2f(TexX1*TexW, TexY1+TexH*0.5); - glVertex3f(x, y+h*scaleH + h*scaleH/2 + Spacing, z); - - - //Bottom Right - glColor4f(ColR * Int, ColG * Int, ColB * Int, 0); - glTexCoord2f(TexX2*TexW, TexY1+TexH*0.5); - glVertex3f(x+w*scaleW, y+h*scaleH + h*scaleH/2 + Spacing, z); - - //Top Right - glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3); - glTexCoord2f(TexX2*TexW, TexY2*TexH); - glVertex3f(x+w*scaleW, y+h*scaleH + Spacing, z); - glEnd; - - glDisable(GL_TEXTURE_2D); - glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - end; - end; - - for T := 0 to High(Text) do begin - Text[T].Draw; - end; - end; -end; - -// ***** ****** // - -destructor TButton.Destroy; -begin - inherited; -end; - -constructor TButton.Create(Textura: TTexture); -begin - Create(); - Texture := Textura; - DeselectTexture:=Textura; - Texture.ColR := 0; - Texture.ColG := 0.5; - Texture.ColB := 0; - Texture.Int := 1; - Colorized:=False; -end; - -constructor TButton.Create(Textura, DSTexture: TTexture); -begin - Create(); - Texture := Textura; - DeselectTexture := DSTexture; - Texture.ColR := 1; - Texture.ColG := 1; - Texture.ColB := 1; - Texture.Int := 1; - Colorized:=True; -end; - -end. +unit UMenuButton; + +interface + +{$I switches.inc} + +uses TextGL, UTexture, OpenGL12, UMenuText,SDL; + +type + CButton = class of TButton; + TButton = class + protected + SelectBool: Boolean; + + FadeProgress: Real; + FadeLastTick: Cardinal; + + DeSelectW: Real; + DeSelectH: Real; + PosX: Real; + PosY: Real; + + constructor Create(); overload; + + public + Text: Array of TText; + Texture: TTexture; // Button Screen position and size + Texture2: TTexture; // second texture only used for fading full resolution covers + //colorized hack + Colorized: Boolean; + DeSelectTexture: TTexture; // texture for colorized hack + + FadeTex: TTexture; //Texture for beautiful fading + FadeTexPos: byte; //Pos of the FadeTexture (0: Top, 1: Left, 2: Bottom, 3: Right) +// Texture2Blend: real; // blending factor for second texture (0=invisible, 1=visible) + // now uses alpha + + DeselectType: integer; // not used yet + Visible: boolean; + //Reflection Mod + Reflection: boolean; + Reflectionspacing: Real; + DeSelectReflectionspacing: Real; + + //Fade Mod + Fade: Boolean; + FadeText: Boolean; + + Selectable: boolean; + + //No of the Parent Collection, 0 if in no Collection + Parent: Byte; + + SelectColR: real; + SelectColG: real; + SelectColB: real; + SelectInt: real; + SelectTInt: real; + //Fade Mod + SelectW: real; + SelectH: real; + + DeselectColR: real; + DeselectColG: real; + DeselectColB: real; + DeselectInt: real; + DeselectTInt: real; + + procedure SetY(Value: real); + procedure SetX(Value: real); + procedure SetW(Value: real); + procedure SetH(Value: real); + + procedure SetSelect(Value: Boolean); virtual; + property X: real read PosX write SetX; + property Y: real read PosY write SetY; + property Z: real read Texture.z write Texture.z; + property W: real read DeSelectW write SetW; + property H: real read DeSelectH write SetH; + property Selected: Boolean read SelectBool write SetSelect; + + procedure Draw; virtual; + + constructor Create(Textura: TTexture); overload; + constructor Create(Textura, DSTexture: TTexture); overload; + destructor Destroy; override; + end; + +implementation + +uses SysUtils, + UDrawTexture; + +procedure TButton.SetX(Value: real); +{var + dx: real; + T: integer; // text} +begin + {dY := Value - Texture.y; + + Texture.X := Value; + + for T := 0 to High(Text) do + Text[T].X := Text[T].X + dY;} + + PosX := Value; + if (FadeTex.TexNum = 0) then + Texture.X := Value; + +end; + +procedure TButton.SetY(Value: real); +{var + dY: real; + T: integer; // text} +begin + {dY := Value - PosY; + + + for T := 0 to High(Text) do + Text[T].Y := Text[T].Y + dY;} + + PosY := Value; + if (FadeTex.TexNum = 0) then + Texture.y := Value; +end; + +procedure TButton.SetW(Value: real); +begin + if SelectW = DeSelectW then + SelectW := Value; + + DeSelectW := Value; + + if Not Fade then + begin + if SelectBool then + Texture.W := SelectW + else + Texture.W := DeSelectW; + end; +end; + +procedure TButton.SetH(Value: real); +begin + if SelectH = DeSelectH then + SelectH := Value; + + DeSelectH := Value; + + if Not Fade then + begin + if SelectBool then + Texture.H := SelectH + else + Texture.H := DeSelectH; + end; +end; + +procedure TButton.SetSelect(Value : Boolean); +var + T: integer; +begin + SelectBool := Value; + if (Value) then begin + Texture.ColR := SelectColR; + Texture.ColG := SelectColG; + Texture.ColB := SelectColB; + Texture.Int := SelectInt; + + Texture2.ColR := SelectColR; + Texture2.ColG := SelectColG; + Texture2.ColB := SelectColB; + Texture2.Int := SelectInt; + + for T := 0 to High(Text) do + Text[T].Int := SelectTInt; + + //Fade Mod + if Fade then + begin + if (FadeProgress <= 0) then + FadeProgress := 0.125; + end + else + begin + Texture.W := SelectW; + Texture.H := SelectH; + end; + end else begin + Texture.ColR := DeselectColR; + Texture.ColG := DeselectColG; + Texture.ColB := DeselectColB; + Texture.Int := DeselectInt; + + Texture2.ColR := DeselectColR; + Texture2.ColG := DeselectColG; + Texture2.ColB := DeselectColB; + Texture2.Int := DeselectInt; + + for T := 0 to High(Text) do + Text[T].Int := DeselectTInt; + + //Fade Mod + if Fade then + begin + if (FadeProgress >= 1) then + FadeProgress := 0.875; + end + else + begin + Texture.W := DeSelectW; + Texture.H := DeSelectH; + end; + end; +end; + +constructor TButton.Create(); +begin + inherited Create; + // We initialize all to 0, nil or false + Visible := true; + SelectBool := false; + DeselectType := 0; + Selectable := true; + //Reflection Mod + Reflection := true; + + //colorized hack + Colorized:=False; + + // Default +// SelectInt := 1; +// DeselectInt := 0.5; + +{ SelectColR := 0.5; + SelectColG := 0.75; + SelectColB := 0; + SelectInt := 1; + SelectTInt := 1; + + DeselectColR := 1; + DeselectColG := 1; + DeselectColB := 1; + DeselectInt := 0.5; + DeselectTInt := 1;} + + SelectColR := 1; + SelectColG := 1; + SelectColB := 1; + SelectInt := 1; + SelectTInt := 1; + + DeselectColR := 1; + DeselectColG := 1; + DeselectColB := 1; + DeselectInt := 0.5; + DeselectTInt := 1; + + FadeTex.TexNum := 0; + + FadeProgress := 0; + Fade := False; + FadeText := False; + SelectW := DeSelectW; + SelectH := DeSelectH; + + PosX := 0; + PosY := 0; + + Parent := 0; +end; + +// ***** Public methods ****** // + +procedure TButton.Draw; +var + T: integer; + Tick: Cardinal; + Spacing: Real; +begin + if Visible then begin + //Fade Mod + T:=0; + if Fade then + begin + if (FadeProgress < 1) and (FadeProgress > 0) then + begin + Tick := SDL_GetTicks() div 16; + if (Tick <> FadeLastTick) then + begin + FadeLastTick := Tick; + if SelectBool then + FadeProgress := FadeProgress + 0.125 + else + FadeProgress := FadeProgress - 0.125; + + if (FadeText) then + begin + For T := 0 to high(Text) do + begin + Text[T].MoveX := (SelectW - DeSelectW) * FadeProgress; + Text[T].MoveY := (SelectH - DeSelectH) * FadeProgress; + end; + end; + end; + end; + //Method without Fade Texture + if (FadeTex.TexNum = 0) then + begin + Texture.W := DeSelectW + (SelectW - DeSelectW) * FadeProgress; + Texture.H := DeSelectH + (SelectH - DeSelectH) * FadeProgress; + DeselectTexture.W := Texture.W; + DeselectTexture.H := Texture.H; + end + else //method with Fade Texture + begin + Texture.W := DeSelectW; + Texture.H := DeSelectH; + DeselectTexture.W := Texture.W; + DeselectTexture.H := Texture.H; + + FadeTex.ColR := Texture.ColR; + FadeTex.ColG := Texture.ColG; + FadeTex.ColB := Texture.ColB; + FadeTex.Int := Texture.Int; + + FadeTex.Z := Texture.Z; + + FadeTex.Alpha := Texture.Alpha; + FadeTex.TexX1 := 0; + FadeTex.TexX2 := 1; + FadeTex.TexY1 := 0; + FadeTex.TexY2 := 1; + + Case FadeTexPos of + 0: //FadeTex on Top + begin + //Standard Texture + Texture.X := PosX; + Texture.Y := PosY + (SelectH - DeSelectH) * FadeProgress; + DeselectTexture.X := Texture.X; + DeselectTexture.Y := Texture.Y; + //Fade Tex + FadeTex.X := PosX; + FadeTex.Y := PosY; + FadeTex.W := Texture.W; + FadeTex.H := (SelectH - DeSelectH) * FadeProgress; + FadeTex.ScaleW := Texture.ScaleW; + //Some Hack that Fixes a little Space between both Textures + FadeTex.TexY2 := 0.9; + end; + 1: //FadeTex on Left + begin + //Standard Texture + Texture.X := PosX + (SelectW - DeSelectW) * FadeProgress; + Texture.Y := PosY; + DeselectTexture.X := Texture.X; + DeselectTexture.Y := Texture.Y; + //Fade Tex + FadeTex.X := PosX; + FadeTex.Y := PosY; + FadeTex.H := Texture.H; + FadeTex.W := (SelectW - DeSelectW) * FadeProgress; + FadeTex.ScaleH := Texture.ScaleH; + //Some Hack that Fixes a little Space between both Textures + FadeTex.TexX2 := 0.9; + end; + 2: //FadeTex on Bottom + begin + //Standard Texture + Texture.X := PosX; + Texture.Y := PosY; + DeselectTexture.X := Texture.X; + DeselectTexture.Y := Texture.Y; + //Fade Tex + FadeTex.X := PosX; + FadeTex.Y := PosY + (SelectH - DeSelectH) * FadeProgress;; + FadeTex.W := Texture.W; + FadeTex.H := (SelectH - DeSelectH) * FadeProgress; + FadeTex.ScaleW := Texture.ScaleW; + //Some Hack that Fixes a little Space between both Textures + FadeTex.TexY1 := 0.1; + end; + 3: //FadeTex on Right + begin + //Standard Texture + Texture.X := PosX; + Texture.Y := PosY; + DeselectTexture.X := Texture.X; + DeselectTexture.Y := Texture.Y; + //Fade Tex + FadeTex.X := PosX + (SelectW - DeSelectW) * FadeProgress; + FadeTex.Y := PosY; + FadeTex.H := Texture.H; + FadeTex.W := (SelectW - DeSelectW) * FadeProgress; + FadeTex.ScaleH := Texture.ScaleH; + //Some Hack that Fixes a little Space between both Textures + FadeTex.TexX1 := 0.1; + end; + end; + end; + end + else if (FadeText) then + begin + Text[T].MoveX := (SelectW - DeSelectW); + Text[T].MoveY := (SelectH - DeSelectH); + end; + + if SelectBool or (FadeProgress > 0) or not Colorized then + DrawTexture(Texture) + else + DrawTexture(DeselectTexture); + + //Draw FadeTex + if (FadeTex.TexNum > 0) then + DrawTexture(FadeTex); + + if Texture2.Alpha > 0 then begin + Texture2.ScaleW := Texture.ScaleW; + Texture2.ScaleH := Texture.ScaleH; + + Texture2.X := Texture.X; + Texture2.Y := Texture.Y; + Texture2.W := Texture.W; + Texture2.H := Texture.H; + + Texture2.ColR := Texture.ColR; + Texture2.ColG := Texture.ColG; + Texture2.ColB := Texture.ColB; + Texture2.Int := Texture.Int; + + Texture2.Z := Texture.Z; + + DrawTexture(Texture2); + end; + + //Reflection Mod + if (Reflection) then // Draw Reflections + begin + if (FadeProgress <> 0) AND (FadeProgress <> 1) then + begin + Spacing := DeSelectReflectionspacing - (DeSelectReflectionspacing - Reflectionspacing) * FadeProgress; + end + else if SelectBool then + Spacing := Reflectionspacing + else + Spacing := DeSelectReflectionspacing; + + if SelectBool or not Colorized then + with Texture do + begin + //Bind Tex and GL Attributes + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + + glDepthRange(0, 10); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, TexNum); + + //Draw + glBegin(GL_QUADS);//Top Left + glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3); + glTexCoord2f(TexX1*TexW, TexY2*TexH); + glVertex3f(x, y+h*scaleH+ Spacing, z); + + //Bottom Left + glColor4f(ColR * Int, ColG * Int, ColB * Int, 0); + glTexCoord2f(TexX1*TexW, TexY1+TexH*0.5); + glVertex3f(x, y+h*scaleH + h*scaleH/2 + Spacing, z); + + + //Bottom Right + glColor4f(ColR * Int, ColG * Int, ColB * Int, 0); + glTexCoord2f(TexX2*TexW, TexY1+TexH*0.5); + glVertex3f(x+w*scaleW, y+h*scaleH + h*scaleH/2 + Spacing, z); + + //Top Right + glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3); + glTexCoord2f(TexX2*TexW, TexY2*TexH); + glVertex3f(x+w*scaleW, y+h*scaleH + Spacing, z); + glEnd; + + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + end else + with DeselectTexture do + begin + //Bind Tex and GL Attributes + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + + glDepthRange(0, 10); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, TexNum); + + //Draw + glBegin(GL_QUADS);//Top Left + glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3); + glTexCoord2f(TexX1*TexW, TexY2*TexH); + glVertex3f(x, y+h*scaleH+ Spacing, z); + + //Bottom Left + glColor4f(ColR * Int, ColG * Int, ColB * Int, 0); + glTexCoord2f(TexX1*TexW, TexY1+TexH*0.5); + glVertex3f(x, y+h*scaleH + h*scaleH/2 + Spacing, z); + + + //Bottom Right + glColor4f(ColR * Int, ColG * Int, ColB * Int, 0); + glTexCoord2f(TexX2*TexW, TexY1+TexH*0.5); + glVertex3f(x+w*scaleW, y+h*scaleH + h*scaleH/2 + Spacing, z); + + //Top Right + glColor4f(ColR * Int, ColG * Int, ColB * Int, Alpha-0.3); + glTexCoord2f(TexX2*TexW, TexY2*TexH); + glVertex3f(x+w*scaleW, y+h*scaleH + Spacing, z); + glEnd; + + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + end; + end; + + for T := 0 to High(Text) do begin + Text[T].Draw; + end; + end; +end; + +// ***** ****** // + +destructor TButton.Destroy; +begin + inherited; +end; + +constructor TButton.Create(Textura: TTexture); +begin + Create(); + Texture := Textura; + DeselectTexture:=Textura; + Texture.ColR := 0; + Texture.ColG := 0.5; + Texture.ColB := 0; + Texture.Int := 1; + Colorized:=False; +end; + +constructor TButton.Create(Textura, DSTexture: TTexture); +begin + Create(); + Texture := Textura; + DeselectTexture := DSTexture; + Texture.ColR := 1; + Texture.ColG := 1; + Texture.ColB := 1; + Texture.Int := 1; + Colorized:=True; +end; + +end. diff --git a/Game/Code/Screens/UScreenSing.pas b/Game/Code/Screens/UScreenSing.pas index f6b5a3c2..7c4d69bd 100644 --- a/Game/Code/Screens/UScreenSing.pas +++ b/Game/Code/Screens/UScreenSing.pas @@ -1,1430 +1,1430 @@ -unit UScreenSing; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - - -uses UMenu, - UMusic, - SDL, - SysUtils, - UFiles, - UTime, - USongs, - UIni, - ULog, - UTexture, - ULyrics, - TextGL, - OpenGL12, - UThemes, - //ULCD, //TODO: maybe LCD Support as Plugin? - UGraphicClasses, - USingScores; - -type - TScreenSing = class(TMenu) - protected - paused: boolean; //Pause Mod - PauseTime: Real; - NumEmptySentences: integer; - public - //TextTime: integer; - - //TimeBar mod - StaticTimeProgress: integer; - TextTimeText: integer; - //eoa TimeBar mod - - StaticP1: integer; - TextP1: integer; - {StaticP1ScoreBG: integer; - TextP1Score: integer;} - - {//moveable singbar mod - StaticP1SingBar: integer; - StaticP1ThreePSingBar: integer; - StaticP1TwoPSingBar: integer; - StaticP2RSingBar: integer; - StaticP2MSingBar: integer; - StaticP3SingBar: integer; - //eoa moveable singbar } - - //Added for ps3 skin - //shown when game is in 2/4 player modus - StaticP1TwoP: integer; - TextP1TwoP: integer; - - {StaticP1TwoPScoreBG: integer; - TextP1TwoPScore: integer;} - //shown when game is in 3/6 player modus - StaticP1ThreeP: integer; - TextP1ThreeP: integer; - - {TextP1ThreePScore: integer; - StaticP1ThreePScoreBG: integer; } - //eoa - - StaticP2R: integer; - TextP2R: integer; - - {StaticP2RScoreBG: integer; - TextP2RScore: integer;} - - StaticP2M: integer; - TextP2M: integer; - - {StaticP2MScoreBG: integer; - TextP2MScore: integer; } - - StaticP3R: integer; - TextP3R: integer; - - {StaticP3RScoreBG: integer; - TextP3RScore: integer;} - StaticPausePopup: integer; - - Tex_Background: TTexture; - FadeOut: boolean; -// LyricMain: TLyric; -// LyricSub: TLyric; - Lyrics: TLyricEngine; - - //Score Manager: - Scores: TSingScores; - - fShowVisualization : boolean; - fCurrentVideoPlaybackEngine : IVideoPlayback; - - constructor Create; override; - procedure onShow; override; - procedure onShowFinish; override; - - function ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; override; - function Draw: boolean; override; - - procedure Finish; virtual; - //procedure UpdateLCD; //TODO: maybe LCD Support as Plugin? - procedure Pause; //Pause Mod(Toggles Pause) - - procedure onSentenceEnd(S: Cardinal); //OnSentenceEnd for LineBonus + Singbar - procedure onSentenceChange(S: Cardinal); //OnSentenceChange (for Golden Notes) - end; - -implementation - -uses UGraphic, - UDraw, - UMain, - USong, - Classes, - URecord, - ULanguage, - math; - -// Method for input parsing. If False is returned, GetNextWindow -// should be checked to know the next window to load; -function TScreenSing.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; -begin - Result := true; - If (PressedDown) Then - begin // Key Down - // check normal keys - case WideCharUpperCase(CharCode)[1] of - 'Q': - begin - //When not ask before Exit then Finish now - if (Ini.AskbeforeDel <> 1) then - Finish - //else just Pause and let the Popup make the Work - else if not paused then - Pause; - - Result := false; - Exit; - end; - 'V': //Show Visualization - begin - fShowVisualization := not fShowVisualization; - - if fShowVisualization then - fCurrentVideoPlaybackEngine := Visualization - else - fCurrentVideoPlaybackEngine := VideoPlayback; - - if fShowVisualization then - fCurrentVideoPlaybackEngine.play; - - Exit; - end; - 'P': - begin - Pause; - Exit; - end; - end; - - // check special keys - case PressedKey of - SDLK_ESCAPE, - SDLK_BACKSPACE : - begin - //Record Sound Hack: - //Sound[0].BufferLong - - Finish; - AudioPlayback.PlaySound(SoundLib.Back); - FadeTo(@ScreenScore); - end; - - SDLK_SPACE: - begin - Pause; - end; - - SDLK_TAB: //Change Visualization Preset - begin - if fShowVisualization then - fCurrentVideoPlaybackEngine.Position := now; // move to a random position - end; - - SDLK_RETURN: - begin - end; - - // 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 : - begin - end; - SDLK_UP : - begin - end; - end; - end; -end; - -//Pause Mod -procedure TScreenSing.Pause; -begin - if not paused then //enable Pause - begin - // pause Time - PauseTime := LineState.CurrentTime; - Paused := true; - - // pause Music - AudioPlayback.Pause; - - // pause Video - if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then - fCurrentVideoPlaybackEngine.Pause; - - end - else //disable Pause - begin - LineState.CurrentTime := PauseTime; //Position of Notes - - // Position of Music - // FIXME: remove this and provide LineState.CurrentTime as sync-source instead - // so every stream can synch itself - AudioPlayback.Position := PauseTime; - - // Play Music - AudioPlayback.Play; - - // Video - if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then - fCurrentVideoPlaybackEngine.Pause; - - Paused := false; - end; -end; -//Pause Mod End - -constructor TScreenSing.Create; -var - I: integer; - P: integer; -begin - inherited Create; - - fShowVisualization := false; - fCurrentVideoPlaybackEngine := VideoPlayback; - - - //Create Score Class - Scores := TSingScores.Create; - Scores.LoadfromTheme; - - LoadFromTheme(Theme.Sing); - - //TimeBar - StaticTimeProgress := AddStatic(Theme.Sing.StaticTimeProgress); - TextTimeText := AddText(Theme.Sing.TextTimeText); - -// 1 player | P1 - StaticP1 := AddStatic(Theme.Sing.StaticP1); - TextP1 := AddText(Theme.Sing.TextP1); - - {StaticP1ScoreBG := AddStatic(Theme.Sing.StaticP1ScoreBG); - TextP1Score := AddText(Theme.Sing.TextP1Score); - StaticP1SingBar := AddStatic(Theme.Sing.StaticP1SingBar);} - -// 2 or 4 players | P1 - StaticP1TwoP := AddStatic(Theme.Sing.StaticP1TwoP); - TextP1TwoP := AddText(Theme.Sing.TextP1TwoP); - - {StaticP1TwoPScoreBG := AddStatic(Theme.Sing.StaticP1TwoPScoreBG); - TextP1TwoPScore := AddText(Theme.Sing.TextP1TwoPScore); - StaticP1TwoPSingBar := AddStatic(Theme.Sing.StaticP2RSingBar);} - - // | P2 - StaticP2R := AddStatic(Theme.Sing.StaticP2R); - TextP2R := AddText(Theme.Sing.TextP2R); - - {StaticP2RScoreBG := AddStatic(Theme.Sing.StaticP2RScoreBG); - TextP2RScore := AddText(Theme.Sing.TextP2RScore); - StaticP2RSingBar := AddStatic(Theme.Sing.StaticP2RSingBar); } - -// 3 or 6 players | P1 - StaticP1ThreeP := AddStatic(Theme.Sing.StaticP1ThreeP); - TextP1ThreeP := AddText(Theme.Sing.TextP1ThreeP); - - {StaticP1ThreePScoreBG := AddStatic(Theme.Sing.StaticP1ThreePScoreBG); - TextP1ThreePScore := AddText(Theme.Sing.TextP1ThreePScore); - StaticP1ThreePSingBar := AddStatic(Theme.Sing.StaticP1ThreePSingBar);} - - // | P2 - StaticP2M := AddStatic(Theme.Sing.StaticP2M); - TextP2M := AddText(Theme.Sing.TextP2M); - - {StaticP2MScoreBG := AddStatic(Theme.Sing.StaticP2MScoreBG); - TextP2MScore := AddText(Theme.Sing.TextP2MScore); - StaticP2MSingBar := AddStatic(Theme.Sing.StaticP2MSingBar);} - - // | P3 - StaticP3R := AddStatic(Theme.Sing.StaticP3R); - TextP3R := AddText(Theme.Sing.TextP3R); - - {StaticP3RScoreBG := AddStatic(Theme.Sing.StaticP3RScoreBG); - TextP3RScore := AddText(Theme.Sing.TextP3RScore); - StaticP3SingBar := AddStatic(Theme.Sing.StaticP3SingBar);} - - StaticPausePopup := AddStatic(Theme.Sing.PausePopUp); - Static[StaticPausePopup].Visible := false; //Pausepopup is not visibile at the beginning - - if ScreenAct = 2 then begin - // katze und affe - - end; - - Lyrics := TLyricEngine.Create(80,Skin_LyricsT,640,12,80,Skin_LyricsT+36,640,12); - - if assigned( fCurrentVideoPlaybackEngine ) then - fCurrentVideoPlaybackEngine.Init(); -end; - -procedure TScreenSing.onShow; -var - P: integer; - V1: boolean; - V1TwoP: boolean; //added for ps3 skin - V1ThreeP: boolean; //added for ps3 skin - V2R: boolean; - V2M: boolean; - V3R: boolean; - NR: TRecR; //Line Bonus Mod - - Color: TRGB; - - success: boolean; -begin - inherited; - - Log.LogStatus('Begin', 'onShow'); - FadeOut := false; // 0.5.0: early 0.5.0 problems were by this line commented - - // reset video playback engine, to play Video Clip... - fCurrentVideoPlaybackEngine := VideoPlayback; - - //SetUp Score Manager - Scores.ClearPlayers; //Clear Old Player Values - Color.R := 0; Color.G := 0; Color.B := 0; //Dummy atm - For P := 0 to PlayersPlay -1 do //Add new Ones - begin - Scores.AddPlayer(Tex_ScoreBG[P], Color); - end; - - Scores.Init; //Get Positions for Players - - - - // prepare players - SetLength(Player, PlayersPlay); -// Player[0].ScoreTotalI := 0; - - case PlayersPlay of - 1: begin - V1 := true; - V1TwoP := false; - V1ThreeP := false; - V2R := false; - V2M := false; - V3R := false; - end; - 2: begin - V1 := false; - V1TwoP := true; - V1ThreeP := false; - V2R := true; - V2M := false; - V3R := false; - end; - 3: begin - V1 := false; - V1TwoP := false; - V1ThreeP := true; - V2R := false; - V2M := true; - V3R := true; - end; - 4: begin // double screen - V1 := false; - V1TwoP := true; - V1ThreeP := false; - V2R := true; - V2M := false; - V3R := false; - end; - 6: begin // double screen - V1 := false; - V1TwoP := false; - V1ThreeP := true; - V2R := false; - V2M := true; - V3R := true; - end; - - end; - - //This one is shown in 1P mode - Static[StaticP1].Visible := V1; - Text[TextP1].Visible := V1; - - {Static[StaticP1ScoreBG].Visible := V1; - Text[TextP1Score].Visible := V1;} - - - //This one is shown in 2/4P mode - Static[StaticP1TwoP].Visible := V1TwoP; - Text[TextP1TwoP].Visible := V1TwoP; - - {Static[StaticP1TwoPScoreBG].Visible := V1TwoP; - Text[TextP1TwoPScore].Visible := V1TwoP;} - - Static[StaticP2R].Visible := V2R; - Text[TextP2R].Visible := V2R; - - {Static[StaticP2RScoreBG].Visible := V2R; - Text[TextP2RScore].Visible := V2R; } - - - //This one is shown in 3/6P mode - Static[StaticP1ThreeP].Visible := V1ThreeP; - Text[TextP1ThreeP].Visible := V1ThreeP; - - {Static[StaticP1ThreePScoreBG].Visible := V1ThreeP; - Text[TextP1ThreePScore].Visible := V1ThreeP; } - - Static[StaticP2M].Visible := V2M; - Text[TextP2M].Visible := V2M; - - {Static[StaticP2MScoreBG].Visible := V2M; - Text[TextP2MScore].Visible := V2M; } - - Static[StaticP3R].Visible := V3R; - Text[TextP3R].Visible := V3R; - - {Static[StaticP3RScoreBG].Visible := V3R; - Text[TextP3RScore].Visible := V3R; } - - // FIXME: sets Path and Filename to '' - ResetSingTemp; - - CurrentSong := CatSongs.Song[CatSongs.Selected]; - - // FIXME: bad style, put the try-except into LoadSong() and not here - try - //Check if File is XML - if copy(CurrentSong.FileName,length(CurrentSong.FileName)-3,4) = '.xml' - then success := CurrentSong.LoadXMLSong() - else success := CurrentSong.LoadSong(); - except - success := false; - end; - - if (not success) then - begin - //Error Loading Song -> Go back to Song Screen and Show some Error Message - FadeTo(@ScreenSong); - //Select New Song in Party Mode - if ScreenSong.Mode = smPartyMode then - ScreenSong.SelectRandomSong(); - ScreenPopupError.ShowPopup (Language.Translate('ERROR_CORRUPT_SONG')); - // FIXME: do we need this? - CurrentSong.Path := CatSongs.Song[CatSongs.Selected].Path; - Exit; - end; - - - - // reset video playback engine, to play Video Clip... - - Visualization.Init(); - - fCurrentVideoPlaybackEngine.Close; - fCurrentVideoPlaybackEngine := VideoPlayback; - - // set movie - CurrentSong.VideoLoaded := false; - fShowVisualization := false; - if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then - begin - // todo: VideoGap and Start time verwursten - - fCurrentVideoPlaybackEngine.Open( CurrentSong.Path + CurrentSong.Video ); - - fCurrentVideoPlaybackEngine.position := CurrentSong.VideoGAP + CurrentSong.Start; - - CurrentSong.VideoLoaded := true; - end; - - // set background - if (CurrentSong.Background <> '') and (CurrentSong.VideoLoaded = false) then - try - Tex_Background := Texture.LoadTexture(CurrentSong.Path + CurrentSong.Background); - except - log.LogError('Background could not be loaded: ' + CurrentSong.Path + CurrentSong.Background); - Tex_Background.TexNum := -1; - end - else - Tex_Background.TexNum := -1; - - - - // play music (I) - AudioInput.CaptureStart; - AudioPlayback.Position := CurrentSong.Start; -// Music.Play; - - // prepare timer (I) -// CountSkipTimeSet; - LineState.CurrentTime := CurrentSong.Start; - LineState.TotalTime := AudioPlayback.Length; - if (CurrentSong.Finish > 0) then LineState.TotalTime := CurrentSong.Finish / 1000; - LineState.OldBeat := -1; - for P := 0 to High(Player) do - ClearScores(P); - - // main text - Lyrics.Clear (CurrentSong.BPM[0].BPM, CurrentSong.Resolution); - - // set custom options - case Ini.LyricsFont of - 0: - begin - Lyrics.UpperLineSize := 14; - Lyrics.LowerLineSize := 14; - Lyrics.FontStyle := 0; - - Lyrics.LineColor_en.R := Skin_FontR; - Lyrics.LineColor_en.G := Skin_FontG; - Lyrics.LineColor_en.B := Skin_FontB; - Lyrics.LineColor_en.A := 1; - - Lyrics.LineColor_dis.R := 0.4; - Lyrics.LineColor_dis.G := 0.4; - Lyrics.LineColor_dis.B := 0.4; - Lyrics.LineColor_dis.A := 1; - - Lyrics.LineColor_act.R := 5/256; - Lyrics.LineColor_act.G := 163/256; - Lyrics.LineColor_act.B := 210/256; - Lyrics.LineColor_act.A := 1; - - { - LyricSub.FontStyle := 0; - LyricMain.Size := 14; // 13 - LyricSub.Size := 14; // 13 - LyricMain.ColR := Skin_FontR; - LyricMain.ColG := Skin_FontG; - LyricMain.ColB := Skin_FontB; //Change für Crazy Joker - } - { - LyricMain.ColSR := Skin_FontHighlightR; - LyricMain.ColSG := Skin_FontHighlightG; - LyricMain.ColSB := Skin_FontHighlightB; - }{ - LyricMain.ColSR := 5/255; //26 - LyricMain.ColSG := 163/255; //165 - LyricMain.ColSB := 210/255; //220 - - LyricSub.ColR := 0.4; //0.6 - LyricSub.ColG := 0.4; //0.6 - LyricSub.ColB := 0.4; //0.6 - } - end; - 1: - begin - { - LyricMain.FontStyle := 2; - LyricSub.FontStyle := 2; - LyricMain.Size := 14; - LyricSub.Size := 14; - LyricMain.ColR := 0.75; - LyricMain.ColG := 0.75; - LyricMain.ColB := 1; - LyricMain.ColSR := 0.5; - LyricMain.ColSG := 0.5; - LyricMain.ColSB := 1; - LyricSub.ColR := 0.8; - LyricSub.ColG := 0.8; - LyricSub.ColB := 0.8; - } - - Lyrics.UpperLineSize := 14; - Lyrics.LowerLineSize := 14; - Lyrics.FontStyle := 2; - - Lyrics.LineColor_en.R := 0.75; - Lyrics.LineColor_en.G := 0.75; - Lyrics.LineColor_en.B := 1; - Lyrics.LineColor_en.A := 1; - - Lyrics.LineColor_dis.R := 0.8; - Lyrics.LineColor_dis.G := 0.8; - Lyrics.LineColor_dis.B := 0.8; - Lyrics.LineColor_dis.A := 1; - - Lyrics.LineColor_act.R := 0.5; - Lyrics.LineColor_act.G := 0.5; - Lyrics.LineColor_act.B := 1; - Lyrics.LineColor_act.A := 1; - end; - 2: - begin - Lyrics.UpperLineSize := 12; - Lyrics.LowerLineSize := 12; - Lyrics.FontStyle := 3; - - Lyrics.LineColor_en.R := 0.75; - Lyrics.LineColor_en.G := 0.75; - Lyrics.LineColor_en.B := 1; - Lyrics.LineColor_en.A := 1; - - Lyrics.LineColor_dis.R := 0.8; - Lyrics.LineColor_dis.G := 0.8; - Lyrics.LineColor_dis.B := 0.8; - Lyrics.LineColor_dis.A := 1; - - Lyrics.LineColor_act.R := 0.5; - Lyrics.LineColor_act.G := 0.5; - Lyrics.LineColor_act.B := 1; - Lyrics.LineColor_act.A := 1; - { - LyricSub.FontStyle := 3; - LyricMain.Size := 12; - LyricSub.Size := 12; - LyricMain.ColR := 0.75; - LyricMain.ColG := 0.75; - LyricMain.ColB := 1; - LyricMain.ColSR := 0.5; - LyricMain.ColSG := 0.5; - LyricMain.ColSB := 1; - LyricSub.ColR := 0.8; - LyricSub.ColG := 0.8; - LyricSub.ColB := 0.8; - } - end; - end; // case - - // Add Lines to Lyrics - While (not Lyrics.LineinQueue) AND (Lyrics.LineCounter <= High(Lines[0].Line)) do - Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]); - - //UpdateLCD; //TODO: maybe LCD Support as Plugin? - - //Deactivate Pause - Paused := False; - - //Kill all Stars not Killed yet - //GoldenStarsTwinkle Mod - GoldenRec.SentenceChange; - //GoldenStarsTwinkle Mod End - - {//Set Position of Line Bonus - PhrasenBonus - if (Ini.LineBonus = 1) then //Show Line Bonus at Scores - begin - Case PlayersPlay of - 1: begin - Player[0].LineBonus_TargetX := Theme.Sing.StaticP1ScoreBG.x; - Player[0].LineBonus_TargetY := Theme.Sing.TextP1Score.Y; - Player[0].LineBonus_StartX := Theme.Sing.StaticP1ScoreBG.x; - Player[0].LineBonus_StartY := Theme.Sing.TextP1Score.Y + 65; - end; - - 2: begin - //P1 - Player[0].LineBonus_TargetX := Theme.Sing.StaticP1TwoPScoreBG.x; - Player[0].LineBonus_TargetY := Theme.Sing.TextP1TwoPScore.Y; - Player[0].LineBonus_StartX := Theme.Sing.StaticP1TwoPScoreBG.X; - Player[0].LineBonus_StartY := Theme.Sing.TextP1TwoPScore.Y + 65; - - //P2 - Player[1].LineBonus_TargetX := Theme.Sing.StaticP2RScoreBG.X; - Player[1].LineBonus_TargetY := Theme.Sing.TextP2RScore.Y; - Player[1].LineBonus_StartX := Theme.Sing.StaticP2RScoreBG.X; - Player[1].LineBonus_StartY := Theme.Sing.TextP2RScore.Y + 65; - end; - - 3: begin - //P1 - Player[0].LineBonus_TargetX := Theme.Sing.StaticP1ThreePScoreBG.x; - Player[0].LineBonus_TargetY := Theme.Sing.TextP1ThreePScore.Y; - Player[0].LineBonus_StartX := Theme.Sing.StaticP1ThreePScoreBG.x; - Player[0].LineBonus_StartY := Theme.Sing.TextP1ThreePScore.Y + 65; - - //P2 - Player[1].LineBonus_TargetX := Theme.Sing.StaticP2MScoreBG.x; - Player[1].LineBonus_TargetY := Theme.Sing.TextP2MScore.Y; - Player[1].LineBonus_StartX := Theme.Sing.StaticP2MScoreBG.x; - Player[1].LineBonus_StartY := Theme.Sing.TextP2MScore.Y + 65; - - //P3 - Player[2].LineBonus_TargetX := Theme.Sing.StaticP3RScoreBG.x; - Player[2].LineBonus_TargetY := Theme.Sing.TextP3RScore.Y; - Player[2].LineBonus_StartX := Theme.Sing.StaticP3RScoreBG.x; - Player[2].LineBonus_StartY := Theme.Sing.TextP3RScore.Y + 65; - end; - - 4: begin - //P1 - Player[0].LineBonus_TargetX := Theme.Sing.StaticP1TwoPScoreBG.x; - Player[0].LineBonus_TargetY := Theme.Sing.TextP1TwoPScore.Y; - Player[0].LineBonus_StartX := Theme.Sing.StaticP1TwoPScoreBG.x; - Player[0].LineBonus_StartY := Theme.Sing.TextP1TwoPScore.Y + 65; - - //P2 - Player[1].LineBonus_TargetX := Theme.Sing.StaticP2RScoreBG.x; - Player[1].LineBonus_TargetY := Theme.Sing.TextP2RScore.Y; - Player[1].LineBonus_StartX := Theme.Sing.StaticP2RScoreBG.x; - Player[1].LineBonus_StartY := Theme.Sing.TextP2RScore.Y + 65; - - //P3 - Player[2].LineBonus_TargetX := Theme.Sing.StaticP1TwoPScoreBG.x; - Player[2].LineBonus_TargetY := Theme.Sing.TextP1TwoPScore.Y; - Player[2].LineBonus_StartX := Theme.Sing.StaticP1TwoPScoreBG.x; - Player[2].LineBonus_StartY := Theme.Sing.TextP1TwoPScore.Y + 65; - - //P4 - Player[3].LineBonus_TargetX := Theme.Sing.StaticP2RScoreBG.x; - Player[3].LineBonus_TargetY := Theme.Sing.TextP2RScore.Y; - Player[3].LineBonus_StartX := Theme.Sing.StaticP2RScoreBG.x; - Player[3].LineBonus_StartY := Theme.Sing.TextP2RScore.Y + 65; - end; - - 6: begin - //P1 - Player[0].LineBonus_TargetX := Theme.Sing.StaticP1ThreePScoreBG.x; - Player[0].LineBonus_TargetY := Theme.Sing.TextP1ThreePScore.Y; - Player[0].LineBonus_StartX := Theme.Sing.StaticP1ThreePScoreBG.x; - Player[0].LineBonus_StartY := Theme.Sing.TextP1ThreePScore.Y + 65; - - //P2 - Player[1].LineBonus_TargetX := Theme.Sing.StaticP2MScoreBG.x; - Player[1].LineBonus_TargetY := Theme.Sing.TextP2MScore.Y; - Player[1].LineBonus_StartX := Theme.Sing.StaticP2MScoreBG.x; - Player[1].LineBonus_StartY := Theme.Sing.TextP2MScore.Y + 65; - - //P3 - Player[2].LineBonus_TargetX := Theme.Sing.StaticP3RScoreBG.x; - Player[2].LineBonus_TargetY := Theme.Sing.TextP3RScore.Y; - Player[2].LineBonus_StartX := Theme.Sing.StaticP3RScoreBG.x; - Player[2].LineBonus_StartY := Theme.Sing.TextP3RScore.Y + 65; - - //P4 - Player[3].LineBonus_TargetX := Theme.Sing.StaticP1ThreePScoreBG.x; - Player[3].LineBonus_TargetY := Theme.Sing.TextP1ThreePScore.Y; - Player[3].LineBonus_StartX := Theme.Sing.StaticP1ThreePScoreBG.x; - Player[3].LineBonus_StartY := Theme.Sing.TextP1ThreePScore.Y + 65; - - //P5 - Player[4].LineBonus_TargetX := Theme.Sing.StaticP2MScoreBG.x; - Player[4].LineBonus_TargetY := Theme.Sing.TextP2MScore.Y; - Player[4].LineBonus_StartX := Theme.Sing.StaticP2MScoreBG.x; - Player[4].LineBonus_StartY := Theme.Sing.TextP2MScore.Y + 65; - - //P6 - Player[5].LineBonus_TargetX := Theme.Sing.StaticP3RScoreBG.x; - Player[5].LineBonus_TargetY := Theme.Sing.TextP3RScore.Y; - Player[5].LineBonus_StartX := Theme.Sing.StaticP3RScoreBG.x; - Player[5].LineBonus_StartY := Theme.Sing.TextP3RScore.Y + 65; - end; - end; - end - else if (Ini.LineBonus = 2) then //Show Line Bonus at Notes - begin - - // positions - if Ini.SingWindow = 0 then begin - NR.Left := 120; - end else begin - NR.Left := 20; - end; - NR.Right := 780; - - NR.Width := NR.Right - NR.Left; - NR.WMid := NR.Width / 2; - NR.Mid := NR.Left + NR.WMid; - - Case PlayersPlay of - 1: begin - Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_TargetY := Skin_P2_NotesB - 105 - 65; - Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_StartY := Skin_P2_NotesB - 105; - end; - - 2: begin - //P1 - Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_TargetY := Skin_P1_NotesB - 105 - 65 + 28; - Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_StartY := Skin_P1_NotesB - 105 + 28; - - //P2 - Player[1].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[1].LineBonus_TargetY := Skin_P2_NotesB - 105 - 65 + 28; - Player[1].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[1].LineBonus_StartY := Skin_P2_NotesB - 105 + 28; - end; - - 3: begin - //P1 - Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_TargetY := 120 - 65 + 28; - Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_StartY := 120 + 28; - - //P2 - Player[1].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[1].LineBonus_TargetY := 245 - 65 + 28; - Player[1].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[1].LineBonus_StartY := 245 + 28; - - //P3 - Player[2].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[2].LineBonus_TargetY := 370 - 65 + 28; - Player[2].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[2].LineBonus_StartY := 370 + 28; - end; - - 4: begin - //P1 - Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_TargetY := Skin_P1_NotesB - 105 - 65 + 28; - Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_StartY := Skin_P1_NotesB - 105 + 28; - - //P2 - Player[1].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[1].LineBonus_TargetY := Skin_P2_NotesB - 105 - 65 + 28; - Player[1].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[1].LineBonus_StartY := Skin_P2_NotesB - 105 + 28; - - //P3 - Player[2].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[2].LineBonus_TargetY := Skin_P1_NotesB - 105 - 65 + 28; - Player[2].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[2].LineBonus_StartY := Skin_P1_NotesB - 105 + 28; - - //P4 - Player[3].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[3].LineBonus_TargetY := Skin_P2_NotesB - 105 - 65 + 28; - Player[3].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[3].LineBonus_StartY := Skin_P2_NotesB - 105 + 28; - end; - - 6: begin - //P1 - Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_TargetY := 120 - 65 + 28; - Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[0].LineBonus_StartY := 120 + 28; - - //P2 - Player[1].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[1].LineBonus_TargetY := 245 - 65 + 28; - Player[1].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[1].LineBonus_StartY := 245 + 28; - - //P3 - Player[2].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[2].LineBonus_TargetY := 370 - 65 + 28; - Player[2].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[2].LineBonus_StartY := 370 + 28; - - //P4 - Player[3].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[3].LineBonus_TargetY := 120 - 65 + 28; - Player[3].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[3].LineBonus_StartY := 120 + 28; - - //P5 - Player[4].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[4].LineBonus_TargetY := 245 - 65 + 28; - Player[4].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[4].LineBonus_StartY := 245 + 28; - - //P6 - Player[5].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); - Player[5].LineBonus_TargetY := 370 - 65 + 28; - Player[5].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); - Player[5].LineBonus_StartY := 370 + 28; - end; - end; - end; } - - //Set Position of Line Bonus - PhrasenBonus End - //Set Num of Empty Sentences for Phrasen Bonus - NumEmptySentences := 0; - for P := low(Lines[0].Line) to high(Lines[0].Line) do - if Lines[0].Line[P].TotalNotes = 0 then Inc(NumEmptySentences); - - Log.LogStatus('End', 'onShow'); -end; - -procedure TScreenSing.onShowFinish; -begin - // play movie (II) - - if CurrentSong.VideoLoaded then - begin - try - fCurrentVideoPlaybackEngine.GetFrame(LineState.CurrentTime); - fCurrentVideoPlaybackEngine.DrawGL(ScreenAct); -// PlaySmpeg; - except - - on E : Exception do - begin - //If an Error occurs Reading Video: prevent Video from being Drawn again and Close Video - CurrentSong.VideoLoaded := False; - Log.LogError('Error drawing Video, Video has been disabled for this Song/Session.'); - Log.LogError('Error Message : '+ E.message ); - Log.LogError(' In : '+ E.ClassName +' (TScreenSing.onShowFinish)' ); - Log.LogError('Corrupted File: ' + CurrentSong.Video); - try -// CloseSmpeg; - fCurrentVideoPlaybackEngine.Close; - except - - end; - end; - end; - end; - - - // play music (II) - AudioPlayback.Play; - - // prepare timer (II) - CountSkipTimeSet; -end; - -function TScreenSing.Draw: boolean; -var - Min: integer; - Sec: integer; - Tekst: string; - Flash: real; - S: integer; - T: integer; -begin - - - - //ScoreBG Mod | den wirren Scheiss hier brauch mer nimmer, wir haben colorized png's - no need for wirrness also - // set player colors - macht nichts weiter als die farben des statics zu wechseln, was zu unschönen effekten bei colorized png führt -{ if PlayersPlay = 4 then begin - if ScreenAct = 1 then begin - LoadColor(Static[StaticP1TwoP].Texture.ColR, Static[StaticP1TwoP].Texture.ColG, - Static[StaticP1TwoP].Texture.ColB, 'P1Dark'); - LoadColor(Static[StaticP2R].Texture.ColR, Static[StaticP2R].Texture.ColG, - Static[StaticP2R].Texture.ColB, 'P2Dark'); - - LoadColor(Static[StaticP1TwoPScoreBG].Texture.ColR, Static[StaticP1TwoPScoreBG].Texture.ColG, - Static[StaticP1TwoPScoreBG].Texture.ColB, 'P1Dark'); - LoadColor(Static[StaticP2RScoreBG].Texture.ColR, Static[StaticP2RScoreBG].Texture.ColG, - Static[StaticP2RScoreBG].Texture.ColB, 'P2Dark'); - end; - if ScreenAct = 2 then begin - LoadColor(Static[StaticP1TwoP].Texture.ColR, Static[StaticP1TwoP].Texture.ColG, - Static[StaticP1TwoP].Texture.ColB, 'P3Dark'); - LoadColor(Static[StaticP2R].Texture.ColR, Static[StaticP2R].Texture.ColG, - Static[StaticP2R].Texture.ColB, 'P4Dark'); - - LoadColor(Static[StaticP1TwoPScoreBG].Texture.ColR, Static[StaticP1TwoPScoreBG].Texture.ColG, - Static[StaticP1TwoPScoreBG].Texture.ColB, 'P3Dark'); - LoadColor(Static[StaticP2RScoreBG].Texture.ColR, Static[StaticP2RScoreBG].Texture.ColG, - Static[StaticP2RScoreBG].Texture.ColB, 'P4Dark'); - end; - end; - - if PlayersPlay = 6 then begin - if ScreenAct = 1 then begin - LoadColor(Static[StaticP1ThreeP].Texture.ColR, Static[StaticP1ThreeP].Texture.ColG, - Static[StaticP1ThreeP].Texture.ColB, 'P1Dark'); - LoadColor(Static[StaticP2M].Texture.ColR, Static[StaticP2M].Texture.ColG, - Static[StaticP2R].Texture.ColB, 'P2Dark'); - LoadColor(Static[StaticP3R].Texture.ColR, Static[StaticP3R].Texture.ColG, - Static[StaticP3R].Texture.ColB, 'P3Dark'); - - LoadColor(Static[StaticP1ThreePScoreBG].Texture.ColR, Static[StaticP1ThreePScoreBG].Texture.ColG, - Static[StaticP1ThreePScoreBG].Texture.ColB, 'P1Dark'); - LoadColor(Static[StaticP2MScoreBG].Texture.ColR, Static[StaticP2MScoreBG].Texture.ColG, - Static[StaticP2RScoreBG].Texture.ColB, 'P2Dark'); - LoadColor(Static[StaticP3RScoreBG].Texture.ColR, Static[StaticP3RScoreBG].Texture.ColG, - Static[StaticP3RScoreBG].Texture.ColB, 'P3Dark'); - end; - if ScreenAct = 2 then begin - - LoadColor(Static[StaticP1ThreeP].Texture.ColR, Static[StaticP1ThreeP].Texture.ColG, - Static[StaticP1ThreeP].Texture.ColB, 'P4Dark'); - LoadColor(Static[StaticP2M].Texture.ColR, Static[StaticP2M].Texture.ColG, - Static[StaticP2R].Texture.ColB, 'P5Dark'); - LoadColor(Static[StaticP3R].Texture.ColR, Static[StaticP3R].Texture.ColG, - Static[StaticP3R].Texture.ColB, 'P6Dark'); - - - LoadColor(Static[StaticP1ThreePScoreBG].Texture.ColR, Static[StaticP1ThreePScoreBG].Texture.ColG, - Static[StaticP1ThreePScoreBG].Texture.ColB, 'P4Dark'); - LoadColor(Static[StaticP2MScoreBG].Texture.ColR, Static[StaticP2MScoreBG].Texture.ColG, - Static[StaticP2RScoreBG].Texture.ColB, 'P5Dark'); - LoadColor(Static[StaticP3RScoreBG].Texture.ColR, Static[StaticP3RScoreBG].Texture.ColG, - Static[StaticP3RScoreBG].Texture.ColB, 'P6Dark'); - end; - end; - } - - // set player names (for 2 screens and only Singstar skin) - if ScreenAct = 1 then begin - Text[TextP1].Text := 'P1'; - Text[TextP1TwoP].Text := 'P1'; - Text[TextP1ThreeP].Text := 'P1'; - Text[TextP2R].Text := 'P2'; - Text[TextP2M].Text := 'P2'; - Text[TextP3R].Text := 'P3'; - end; - - if ScreenAct = 2 then begin - case PlayersPlay of -{ 1: begin - Text[TextP1].Text := 'P2'; - end; - 2: begin - Text[TextP1].Text := 'P3'; - Text[TextP2R].Text := 'P4'; - end; - 3: begin - Text[TextP1].Text := 'P4'; - Text[TextP2M].Text := 'P5'; - Text[TextP3R].Text := 'P6'; - end;} - - 4: begin - Text[TextP1TwoP].Text := 'P3'; - Text[TextP2R].Text := 'P4'; - end; - 6: begin - Text[TextP1ThreeP].Text := 'P4'; - Text[TextP2M].Text := 'P5'; - Text[TextP3R].Text := 'P6'; - end; - end; // case - end; // if - - // stereo - -// weird stuff, maybe this is for "dual screen?", but where is player three then? | okay, i commented the stuff out the other day - nothing was missing on screen w/ 6 players - so do we even need this stuff? -// okay this stuff appears again some lines beneath this one, I commented it out for testing what it does - seems like it's doing nothing -// but I might be wrong, so what is this stuff here doing? O.o - Static[StaticP1].Texture.X := Static[StaticP1].Texture.X + 10*ScreenX; - - Text[TextP1].X := Text[TextP1].X + 10*ScreenX; - - {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X + 10*ScreenX; - Text[TextP1Score].X := Text[TextP1Score].X + 10*ScreenX;} - - - Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X + 10*ScreenX; - - Text[TextP2R].X := Text[TextP2R].X + 10*ScreenX; - - {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X + 10*ScreenX; - Text[TextP2RScore].X := Text[TextP2RScore].X + 10*ScreenX;} -// end of weird stuff - - for S := 1 to 1 do //wtf? - Static[S].Texture.X := Static[S].Texture.X + 10*ScreenX; - - for T := 0 to 1 do - Text[T].X := Text[T].X + 10*ScreenX; - - // update static menu with time ... - Min := Round(LineState.CurrentTime) div 60; - Sec := Round(LineState.CurrentTime) mod 60; - Text[TextTimeText].Text := ''; - if Min < 10 then Text[TextTimeText].Text := '0'; - Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Min) + ':'; - if Sec < 10 then Text[TextTimeText].Text := Text[TextTimeText].Text + '0'; - Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Sec); - - {// .. and scores - if PlayersPlay = 1 then begin - Tekst := IntToStr(Player[0].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP1Score].Text := Tekst; - end; - - if PlayersPlay = 2 then begin - Tekst := IntToStr(Player[0].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP1TwoPScore].Text := Tekst; - - Tekst := IntToStr(Player[1].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP2RScore].Text := Tekst; - end; - - if PlayersPlay = 3 then begin - Tekst := IntToStr(Player[0].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP1ThreePScore].Text := Tekst; - - Tekst := IntToStr(Player[1].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP2MScore].Text := Tekst; - - Tekst := IntToStr(Player[2].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP3RScore].Text := Tekst; - end; - - if PlayersPlay = 4 then begin - if ScreenAct = 1 then begin - Tekst := IntToStr(Player[0].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP1TwoPScore].Text := Tekst; - - Tekst := IntToStr(Player[1].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP2RScore].Text := Tekst; - end; - if ScreenAct = 2 then begin - Tekst := IntToStr(Player[2].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP1TwoPScore].Text := Tekst; - - Tekst := IntToStr(Player[3].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP2RScore].Text := Tekst; - end; - end; - - if PlayersPlay = 6 then begin - if ScreenAct = 1 then begin - Tekst := IntToStr(Player[0].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP1ThreePScore].Text := Tekst; - - Tekst := IntToStr(Player[1].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP2MScore].Text := Tekst; - - Tekst := IntToStr(Player[2].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP3RScore].Text := Tekst; - end; - if ScreenAct = 2 then begin - Tekst := IntToStr(Player[3].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP1ThreePScore].Text := Tekst; - - Tekst := IntToStr(Player[4].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP2MScore].Text := Tekst; - - Tekst := IntToStr(Player[5].ScoreTotalI); - while Length(Tekst) < 5 do Tekst := '0' + Tekst; - Text[TextP3RScore].Text := Tekst; - end; - end; } - - // draw static menu (BG) - //DrawBG; // there is no menu and the animated background brakes the video playback because the timecode is in a different format - //Draw Background - SingDrawBackground; - // update and draw movie - - if ShowFinish and - ( CurrentSong.VideoLoaded or fShowVisualization ) then -// if ShowFinish then - begin -// try -// UpdateSmpeg; // this only draws - // todo: find a way to determine, when a new frame is needed - // toto: same for the need to skip frames - - if assigned( fCurrentVideoPlaybackEngine ) then - begin - fCurrentVideoPlaybackEngine.GetFrame(LineState.CurrentTime); - fCurrentVideoPlaybackEngine.DrawGL(ScreenAct); - end; - -(* - except - on E : Exception do - begin - - //If an Error occurs drawing: prevent Video from being Drawn again and Close Video - CurrentSong.VideoLoaded := False; - log.LogError('Error drawing Video, Video has been disabled for this Song/Session.'); - Log.LogError('Error Message : '+ E.message ); - Log.LogError(' In : '+ E.ClassName +' (TScreenSing.Draw)' ); - - Log.LogError('Corrupted File: ' + CurrentSong.Video); - try -// CloseSmpeg; - fCurrentVideoPlaybackEngine.Close; - except - - end; - end; - end; -*) - - end; - - // draw static menu (FG) - DrawFG; - - // check for music finish -// Log.LogError('Check for music finish: ' + BoolToStr(Music.Finished) + ' ' + FloatToStr(LineState.CurrentTime*1000) + ' ' + IntToStr(CurrentSong.Finish)); - if ShowFinish then begin - if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or (LineState.CurrentTime*1000 <= CurrentSong.Finish)) then begin - //Pause Mod: - if not Paused then Sing(Self); // analyze song - end else begin -// Log.LogError('End'); - if not FadeOut then begin -// Log.LogError('End2'); - Finish; - FadeOut := true; - FadeTo(@ScreenScore); - end; - end; - end; - - // draw custom items - SingDraw; // always draw - -//GoldenNoteStarsTwinkle Mod - GoldenRec.SpawnRec; -//GoldenNoteStarsTwinkle Mod - - //Draw Scores - Scores.Draw; - - // back stereo - -// weird stuff, maybe this is for "dual screen?", but where is player three then? -// okay this stuff appears again some lines above this one, I commented it out for testing what it does - seems like it's doing nothing -// but I might be wrong, so what is this stuff here doing? O.o - Static[StaticP1].Texture.X := Static[StaticP1].Texture.X - 10*ScreenX; - Text[TextP1].X := Text[TextP1].X - 10*ScreenX; - - {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X - 10*ScreenX; - Text[TextP1Score].X := Text[TextP1Score].X - 10*ScreenX;} - - - Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X - 10*ScreenX; - Text[TextP2R].X := Text[TextP2R].X - 10*ScreenX; - - {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X - 10*ScreenX; - Text[TextP2RScore].X := Text[TextP2RScore].X - 10*ScreenX;} -//weird end - - for S := 1 to 1 do // wtf? - Static[S].Texture.X := Static[S].Texture.X - 10*ScreenX; - - for T := 0 to 1 do - Text[T].X := Text[T].X - 10*ScreenX; - - //Draw Pausepopup - //I use this workaround that the Static is drawen over the Lyrics, Lines, Scores and Effects - //maybe someone could find a better solution - if Paused then - begin - Static[StaticPausePopup].Visible := true; - Static[StaticPausePopup].Draw; - Static[StaticPausePopup].Visible := false; - end; - -end; - -procedure TScreenSing.Finish; -begin - AudioInput.CaptureStop; - AudioPlayback.Stop; - - if Ini.SavePlayback = 1 then begin - Log.BenchmarkStart(0); - Log.LogVoice(0); - Log.LogVoice(1); - Log.LogVoice(2); - Log.BenchmarkEnd(0); - Log.LogBenchmark('Creating files', 0); - end; - - if CurrentSong.VideoLoaded then - begin -// CloseSmpeg; - fCurrentVideoPlaybackEngine.Close; - CurrentSong.VideoLoaded := false; // to prevent drawing closed video - end; - - SetFontItalic (False); -end; - -(* -procedure TScreenSing.UpdateLCD; //TODO: maybe LCD Support as Plugin? -var - T: string; -begin - //Todo: Lyrics -{ LCD.HideCursor; - LCD.Clear; - - T := LyricMain.Text; - if Copy(T, Length(T), 1) <> ' ' then T := T + ' '; - LCD.AddTextBR(T); - - T := LyricSub.Text; - if Copy(T, Length(T), 1) <> ' ' then T := T + ' '; - LCD.AddTextBR(T);} -end; -*) - -procedure TScreenSing.onSentenceEnd(S: Cardinal); -var -I: Integer; -A: Real; -B: integer; //Max Points for Notes -begin - - //Check for Empty Sentence - if (Lines[0].Line[S].TotalNotes<=0) then - exit; - - //Set Max Note Points - if (Ini.LineBonus > 0) then - B := 9000 - else - B := 10000; - - for I := 0 to High(Player) do begin - A := Player[I].Score + Player[I].ScoreGolden - Player[I].ScoreLast + 2; - - - //PhrasenBonus - Line Bonus Mod - - //Generate Steps 0 to 8 - A := Floor(A / (B * Lines[0].Line[S].TotalNotes / Lines[0].ScoreValue) * 8); - - If (Ini.LineBonus > 0) then - begin - //PhrasenBonus give Points - Player[I].ScoreLine := Player[I].ScoreLine + (1000 / (Length(Lines[0].Line) - NumEmptySentences) * A / 8); - Player[I].ScoreLineI := Round(Player[I].ScoreLine / 10) * 10; - //Update Total Score - Player[I].ScoreTotalI := Player[I].ScoreI + Player[I].ScoreGoldenI + Player[I].ScoreLineI; - - //Spawn PopUp - If (A >= 8) then - A := 8 - else IF A < 0 then - A := 0; - - Scores.SpawnPopUp(I, Floor(A), Player[I].ScoreTotalI); - end; - //PhrasenBonus - Line Bonus Mod End// } - - //PerfectLineTwinkle Mod (effect) Pt.1 - If (Ini.EffectSing=1) then - begin - if A >= 8 then Player[I].LastSentencePerfect := True - else Player[I].LastSentencePerfect := False; - end; - //PerfectLineTwinkle Mod end - - //Refresh LastScore - Player[I].ScoreLast := Player[I].Score + Player[I].ScoreGolden; - - end; - - //PerfectLineTwinkle Mod (effect) Pt.2 - if Ini.EffectSing=1 then - GoldenRec.SpawnPerfectLineTwinkle; - //PerfectLineTwinkle Mod end - - - // if we are shoing a visualization... change to a new preset after each sentence.. - // Maybe we should make this less often or something... just a - if fShowVisualization then - fCurrentVideoPlaybackEngine.Position := now; // move to a random position -end; - -//Called on Sentence Change S= New Current Sentence -procedure TScreenSing.onSentenceChange(S: Cardinal); -begin - //GoldenStarsTwinkle Mod - GoldenRec.SentenceChange; - if (Lyrics.LineCounter <= High(Lines[0].Line)) then - begin - Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]); - end - else - Lyrics.AddLine(nil); - - // addline uses display memory - // calling draw makes sure, there's the singscreen in it, when the next - // swap between onscreen and offscreen buffers is done - // (this eliminates the onSentenceChange flickering) - // note: maybe it would be better to make sure, a display redraw is done - // right after the sentence change (before buffer swap) or make sure - // onsentencechange is only called right before calling Display.Draw - // (or whatever it was called) - Draw; - - //GoldenStarsTwinkle Mod End -end; - -end. +unit UScreenSing; + +interface + +{$IFDEF FPC} + {$MODE Delphi} +{$ENDIF} + +{$I switches.inc} + + +uses UMenu, + UMusic, + SDL, + SysUtils, + UFiles, + UTime, + USongs, + UIni, + ULog, + UTexture, + ULyrics, + TextGL, + OpenGL12, + UThemes, + //ULCD, //TODO: maybe LCD Support as Plugin? + UGraphicClasses, + USingScores; + +type + TScreenSing = class(TMenu) + protected + paused: boolean; //Pause Mod + PauseTime: Real; + NumEmptySentences: integer; + public + //TextTime: integer; + + //TimeBar mod + StaticTimeProgress: integer; + TextTimeText: integer; + //eoa TimeBar mod + + StaticP1: integer; + TextP1: integer; + {StaticP1ScoreBG: integer; + TextP1Score: integer;} + + {//moveable singbar mod + StaticP1SingBar: integer; + StaticP1ThreePSingBar: integer; + StaticP1TwoPSingBar: integer; + StaticP2RSingBar: integer; + StaticP2MSingBar: integer; + StaticP3SingBar: integer; + //eoa moveable singbar } + + //Added for ps3 skin + //shown when game is in 2/4 player modus + StaticP1TwoP: integer; + TextP1TwoP: integer; + + {StaticP1TwoPScoreBG: integer; + TextP1TwoPScore: integer;} + //shown when game is in 3/6 player modus + StaticP1ThreeP: integer; + TextP1ThreeP: integer; + + {TextP1ThreePScore: integer; + StaticP1ThreePScoreBG: integer; } + //eoa + + StaticP2R: integer; + TextP2R: integer; + + {StaticP2RScoreBG: integer; + TextP2RScore: integer;} + + StaticP2M: integer; + TextP2M: integer; + + {StaticP2MScoreBG: integer; + TextP2MScore: integer; } + + StaticP3R: integer; + TextP3R: integer; + + {StaticP3RScoreBG: integer; + TextP3RScore: integer;} + StaticPausePopup: integer; + + Tex_Background: TTexture; + FadeOut: boolean; +// LyricMain: TLyric; +// LyricSub: TLyric; + Lyrics: TLyricEngine; + + //Score Manager: + Scores: TSingScores; + + fShowVisualization : boolean; + fCurrentVideoPlaybackEngine : IVideoPlayback; + + constructor Create; override; + procedure onShow; override; + procedure onShowFinish; override; + + function ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; override; + function Draw: boolean; override; + + procedure Finish; virtual; + //procedure UpdateLCD; //TODO: maybe LCD Support as Plugin? + procedure Pause; //Pause Mod(Toggles Pause) + + procedure onSentenceEnd(S: Cardinal); //OnSentenceEnd for LineBonus + Singbar + procedure onSentenceChange(S: Cardinal); //OnSentenceChange (for Golden Notes) + end; + +implementation + +uses UGraphic, + UDraw, + UMain, + USong, + Classes, + URecord, + ULanguage, + math; + +// Method for input parsing. If False is returned, GetNextWindow +// should be checked to know the next window to load; +function TScreenSing.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; +begin + Result := true; + If (PressedDown) Then + begin // Key Down + // check normal keys + case WideCharUpperCase(CharCode)[1] of + 'Q': + begin + //When not ask before Exit then Finish now + if (Ini.AskbeforeDel <> 1) then + Finish + //else just Pause and let the Popup make the Work + else if not paused then + Pause; + + Result := false; + Exit; + end; + 'V': //Show Visualization + begin + fShowVisualization := not fShowVisualization; + + if fShowVisualization then + fCurrentVideoPlaybackEngine := Visualization + else + fCurrentVideoPlaybackEngine := VideoPlayback; + + if fShowVisualization then + fCurrentVideoPlaybackEngine.play; + + Exit; + end; + 'P': + begin + Pause; + Exit; + end; + end; + + // check special keys + case PressedKey of + SDLK_ESCAPE, + SDLK_BACKSPACE : + begin + //Record Sound Hack: + //Sound[0].BufferLong + + Finish; + AudioPlayback.PlaySound(SoundLib.Back); + FadeTo(@ScreenScore); + end; + + SDLK_SPACE: + begin + Pause; + end; + + SDLK_TAB: //Change Visualization Preset + begin + if fShowVisualization then + fCurrentVideoPlaybackEngine.Position := now; // move to a random position + end; + + SDLK_RETURN: + begin + end; + + // 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 : + begin + end; + SDLK_UP : + begin + end; + end; + end; +end; + +//Pause Mod +procedure TScreenSing.Pause; +begin + if not paused then //enable Pause + begin + // pause Time + PauseTime := LineState.CurrentTime; + Paused := true; + + // pause Music + AudioPlayback.Pause; + + // pause Video + if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then + fCurrentVideoPlaybackEngine.Pause; + + end + else //disable Pause + begin + LineState.CurrentTime := PauseTime; //Position of Notes + + // Position of Music + // FIXME: remove this and provide LineState.CurrentTime as sync-source instead + // so every stream can synch itself + AudioPlayback.Position := PauseTime; + + // Play Music + AudioPlayback.Play; + + // Video + if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then + fCurrentVideoPlaybackEngine.Pause; + + Paused := false; + end; +end; +//Pause Mod End + +constructor TScreenSing.Create; +var + I: integer; + P: integer; +begin + inherited Create; + + fShowVisualization := false; + fCurrentVideoPlaybackEngine := VideoPlayback; + + + //Create Score Class + Scores := TSingScores.Create; + Scores.LoadfromTheme; + + LoadFromTheme(Theme.Sing); + + //TimeBar + StaticTimeProgress := AddStatic(Theme.Sing.StaticTimeProgress); + TextTimeText := AddText(Theme.Sing.TextTimeText); + +// 1 player | P1 + StaticP1 := AddStatic(Theme.Sing.StaticP1); + TextP1 := AddText(Theme.Sing.TextP1); + + {StaticP1ScoreBG := AddStatic(Theme.Sing.StaticP1ScoreBG); + TextP1Score := AddText(Theme.Sing.TextP1Score); + StaticP1SingBar := AddStatic(Theme.Sing.StaticP1SingBar);} + +// 2 or 4 players | P1 + StaticP1TwoP := AddStatic(Theme.Sing.StaticP1TwoP); + TextP1TwoP := AddText(Theme.Sing.TextP1TwoP); + + {StaticP1TwoPScoreBG := AddStatic(Theme.Sing.StaticP1TwoPScoreBG); + TextP1TwoPScore := AddText(Theme.Sing.TextP1TwoPScore); + StaticP1TwoPSingBar := AddStatic(Theme.Sing.StaticP2RSingBar);} + + // | P2 + StaticP2R := AddStatic(Theme.Sing.StaticP2R); + TextP2R := AddText(Theme.Sing.TextP2R); + + {StaticP2RScoreBG := AddStatic(Theme.Sing.StaticP2RScoreBG); + TextP2RScore := AddText(Theme.Sing.TextP2RScore); + StaticP2RSingBar := AddStatic(Theme.Sing.StaticP2RSingBar); } + +// 3 or 6 players | P1 + StaticP1ThreeP := AddStatic(Theme.Sing.StaticP1ThreeP); + TextP1ThreeP := AddText(Theme.Sing.TextP1ThreeP); + + {StaticP1ThreePScoreBG := AddStatic(Theme.Sing.StaticP1ThreePScoreBG); + TextP1ThreePScore := AddText(Theme.Sing.TextP1ThreePScore); + StaticP1ThreePSingBar := AddStatic(Theme.Sing.StaticP1ThreePSingBar);} + + // | P2 + StaticP2M := AddStatic(Theme.Sing.StaticP2M); + TextP2M := AddText(Theme.Sing.TextP2M); + + {StaticP2MScoreBG := AddStatic(Theme.Sing.StaticP2MScoreBG); + TextP2MScore := AddText(Theme.Sing.TextP2MScore); + StaticP2MSingBar := AddStatic(Theme.Sing.StaticP2MSingBar);} + + // | P3 + StaticP3R := AddStatic(Theme.Sing.StaticP3R); + TextP3R := AddText(Theme.Sing.TextP3R); + + {StaticP3RScoreBG := AddStatic(Theme.Sing.StaticP3RScoreBG); + TextP3RScore := AddText(Theme.Sing.TextP3RScore); + StaticP3SingBar := AddStatic(Theme.Sing.StaticP3SingBar);} + + StaticPausePopup := AddStatic(Theme.Sing.PausePopUp); + Static[StaticPausePopup].Visible := false; //Pausepopup is not visibile at the beginning + + if ScreenAct = 2 then begin + // katze und affe + + end; + + Lyrics := TLyricEngine.Create(80,Skin_LyricsT,640,12,80,Skin_LyricsT+36,640,12); + + if assigned( fCurrentVideoPlaybackEngine ) then + fCurrentVideoPlaybackEngine.Init(); +end; + +procedure TScreenSing.onShow; +var + P: integer; + V1: boolean; + V1TwoP: boolean; //added for ps3 skin + V1ThreeP: boolean; //added for ps3 skin + V2R: boolean; + V2M: boolean; + V3R: boolean; + NR: TRecR; //Line Bonus Mod + + Color: TRGB; + + success: boolean; +begin + inherited; + + Log.LogStatus('Begin', 'onShow'); + FadeOut := false; // 0.5.0: early 0.5.0 problems were by this line commented + + // reset video playback engine, to play Video Clip... + fCurrentVideoPlaybackEngine := VideoPlayback; + + //SetUp Score Manager + Scores.ClearPlayers; //Clear Old Player Values + Color.R := 0; Color.G := 0; Color.B := 0; //Dummy atm + For P := 0 to PlayersPlay -1 do //Add new Ones + begin + Scores.AddPlayer(Tex_ScoreBG[P], Color); + end; + + Scores.Init; //Get Positions for Players + + + + // prepare players + SetLength(Player, PlayersPlay); +// Player[0].ScoreTotalI := 0; + + case PlayersPlay of + 1: begin + V1 := true; + V1TwoP := false; + V1ThreeP := false; + V2R := false; + V2M := false; + V3R := false; + end; + 2: begin + V1 := false; + V1TwoP := true; + V1ThreeP := false; + V2R := true; + V2M := false; + V3R := false; + end; + 3: begin + V1 := false; + V1TwoP := false; + V1ThreeP := true; + V2R := false; + V2M := true; + V3R := true; + end; + 4: begin // double screen + V1 := false; + V1TwoP := true; + V1ThreeP := false; + V2R := true; + V2M := false; + V3R := false; + end; + 6: begin // double screen + V1 := false; + V1TwoP := false; + V1ThreeP := true; + V2R := false; + V2M := true; + V3R := true; + end; + + end; + + //This one is shown in 1P mode + Static[StaticP1].Visible := V1; + Text[TextP1].Visible := V1; + + {Static[StaticP1ScoreBG].Visible := V1; + Text[TextP1Score].Visible := V1;} + + + //This one is shown in 2/4P mode + Static[StaticP1TwoP].Visible := V1TwoP; + Text[TextP1TwoP].Visible := V1TwoP; + + {Static[StaticP1TwoPScoreBG].Visible := V1TwoP; + Text[TextP1TwoPScore].Visible := V1TwoP;} + + Static[StaticP2R].Visible := V2R; + Text[TextP2R].Visible := V2R; + + {Static[StaticP2RScoreBG].Visible := V2R; + Text[TextP2RScore].Visible := V2R; } + + + //This one is shown in 3/6P mode + Static[StaticP1ThreeP].Visible := V1ThreeP; + Text[TextP1ThreeP].Visible := V1ThreeP; + + {Static[StaticP1ThreePScoreBG].Visible := V1ThreeP; + Text[TextP1ThreePScore].Visible := V1ThreeP; } + + Static[StaticP2M].Visible := V2M; + Text[TextP2M].Visible := V2M; + + {Static[StaticP2MScoreBG].Visible := V2M; + Text[TextP2MScore].Visible := V2M; } + + Static[StaticP3R].Visible := V3R; + Text[TextP3R].Visible := V3R; + + {Static[StaticP3RScoreBG].Visible := V3R; + Text[TextP3RScore].Visible := V3R; } + + // FIXME: sets Path and Filename to '' + ResetSingTemp; + + CurrentSong := CatSongs.Song[CatSongs.Selected]; + + // FIXME: bad style, put the try-except into LoadSong() and not here + try + //Check if File is XML + if copy(CurrentSong.FileName,length(CurrentSong.FileName)-3,4) = '.xml' + then success := CurrentSong.LoadXMLSong() + else success := CurrentSong.LoadSong(); + except + success := false; + end; + + if (not success) then + begin + //Error Loading Song -> Go back to Song Screen and Show some Error Message + FadeTo(@ScreenSong); + //Select New Song in Party Mode + if ScreenSong.Mode = smPartyMode then + ScreenSong.SelectRandomSong(); + ScreenPopupError.ShowPopup (Language.Translate('ERROR_CORRUPT_SONG')); + // FIXME: do we need this? + CurrentSong.Path := CatSongs.Song[CatSongs.Selected].Path; + Exit; + end; + + + + // reset video playback engine, to play Video Clip... + + Visualization.Init(); + + fCurrentVideoPlaybackEngine.Close; + fCurrentVideoPlaybackEngine := VideoPlayback; + + // set movie + CurrentSong.VideoLoaded := false; + fShowVisualization := false; + if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then + begin + // todo: VideoGap and Start time verwursten + + fCurrentVideoPlaybackEngine.Open( CurrentSong.Path + CurrentSong.Video ); + + fCurrentVideoPlaybackEngine.position := CurrentSong.VideoGAP + CurrentSong.Start; + + CurrentSong.VideoLoaded := true; + end; + + // set background + if (CurrentSong.Background <> '') and (CurrentSong.VideoLoaded = false) then + try + Tex_Background := Texture.LoadTexture(CurrentSong.Path + CurrentSong.Background); + except + log.LogError('Background could not be loaded: ' + CurrentSong.Path + CurrentSong.Background); + Tex_Background.TexNum := 0; + end + else + Tex_Background.TexNum := 0; + + + + // play music (I) + AudioInput.CaptureStart; + AudioPlayback.Position := CurrentSong.Start; +// Music.Play; + + // prepare timer (I) +// CountSkipTimeSet; + LineState.CurrentTime := CurrentSong.Start; + LineState.TotalTime := AudioPlayback.Length; + if (CurrentSong.Finish > 0) then LineState.TotalTime := CurrentSong.Finish / 1000; + LineState.OldBeat := -1; + for P := 0 to High(Player) do + ClearScores(P); + + // main text + Lyrics.Clear (CurrentSong.BPM[0].BPM, CurrentSong.Resolution); + + // set custom options + case Ini.LyricsFont of + 0: + begin + Lyrics.UpperLineSize := 14; + Lyrics.LowerLineSize := 14; + Lyrics.FontStyle := 0; + + Lyrics.LineColor_en.R := Skin_FontR; + Lyrics.LineColor_en.G := Skin_FontG; + Lyrics.LineColor_en.B := Skin_FontB; + Lyrics.LineColor_en.A := 1; + + Lyrics.LineColor_dis.R := 0.4; + Lyrics.LineColor_dis.G := 0.4; + Lyrics.LineColor_dis.B := 0.4; + Lyrics.LineColor_dis.A := 1; + + Lyrics.LineColor_act.R := 5/256; + Lyrics.LineColor_act.G := 163/256; + Lyrics.LineColor_act.B := 210/256; + Lyrics.LineColor_act.A := 1; + + { + LyricSub.FontStyle := 0; + LyricMain.Size := 14; // 13 + LyricSub.Size := 14; // 13 + LyricMain.ColR := Skin_FontR; + LyricMain.ColG := Skin_FontG; + LyricMain.ColB := Skin_FontB; //Change für Crazy Joker + } + { + LyricMain.ColSR := Skin_FontHighlightR; + LyricMain.ColSG := Skin_FontHighlightG; + LyricMain.ColSB := Skin_FontHighlightB; + }{ + LyricMain.ColSR := 5/255; //26 + LyricMain.ColSG := 163/255; //165 + LyricMain.ColSB := 210/255; //220 + + LyricSub.ColR := 0.4; //0.6 + LyricSub.ColG := 0.4; //0.6 + LyricSub.ColB := 0.4; //0.6 + } + end; + 1: + begin + { + LyricMain.FontStyle := 2; + LyricSub.FontStyle := 2; + LyricMain.Size := 14; + LyricSub.Size := 14; + LyricMain.ColR := 0.75; + LyricMain.ColG := 0.75; + LyricMain.ColB := 1; + LyricMain.ColSR := 0.5; + LyricMain.ColSG := 0.5; + LyricMain.ColSB := 1; + LyricSub.ColR := 0.8; + LyricSub.ColG := 0.8; + LyricSub.ColB := 0.8; + } + + Lyrics.UpperLineSize := 14; + Lyrics.LowerLineSize := 14; + Lyrics.FontStyle := 2; + + Lyrics.LineColor_en.R := 0.75; + Lyrics.LineColor_en.G := 0.75; + Lyrics.LineColor_en.B := 1; + Lyrics.LineColor_en.A := 1; + + Lyrics.LineColor_dis.R := 0.8; + Lyrics.LineColor_dis.G := 0.8; + Lyrics.LineColor_dis.B := 0.8; + Lyrics.LineColor_dis.A := 1; + + Lyrics.LineColor_act.R := 0.5; + Lyrics.LineColor_act.G := 0.5; + Lyrics.LineColor_act.B := 1; + Lyrics.LineColor_act.A := 1; + end; + 2: + begin + Lyrics.UpperLineSize := 12; + Lyrics.LowerLineSize := 12; + Lyrics.FontStyle := 3; + + Lyrics.LineColor_en.R := 0.75; + Lyrics.LineColor_en.G := 0.75; + Lyrics.LineColor_en.B := 1; + Lyrics.LineColor_en.A := 1; + + Lyrics.LineColor_dis.R := 0.8; + Lyrics.LineColor_dis.G := 0.8; + Lyrics.LineColor_dis.B := 0.8; + Lyrics.LineColor_dis.A := 1; + + Lyrics.LineColor_act.R := 0.5; + Lyrics.LineColor_act.G := 0.5; + Lyrics.LineColor_act.B := 1; + Lyrics.LineColor_act.A := 1; + { + LyricSub.FontStyle := 3; + LyricMain.Size := 12; + LyricSub.Size := 12; + LyricMain.ColR := 0.75; + LyricMain.ColG := 0.75; + LyricMain.ColB := 1; + LyricMain.ColSR := 0.5; + LyricMain.ColSG := 0.5; + LyricMain.ColSB := 1; + LyricSub.ColR := 0.8; + LyricSub.ColG := 0.8; + LyricSub.ColB := 0.8; + } + end; + end; // case + + // Add Lines to Lyrics + While (not Lyrics.LineinQueue) AND (Lyrics.LineCounter <= High(Lines[0].Line)) do + Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]); + + //UpdateLCD; //TODO: maybe LCD Support as Plugin? + + //Deactivate Pause + Paused := False; + + //Kill all Stars not Killed yet + //GoldenStarsTwinkle Mod + GoldenRec.SentenceChange; + //GoldenStarsTwinkle Mod End + + {//Set Position of Line Bonus - PhrasenBonus + if (Ini.LineBonus = 1) then //Show Line Bonus at Scores + begin + Case PlayersPlay of + 1: begin + Player[0].LineBonus_TargetX := Theme.Sing.StaticP1ScoreBG.x; + Player[0].LineBonus_TargetY := Theme.Sing.TextP1Score.Y; + Player[0].LineBonus_StartX := Theme.Sing.StaticP1ScoreBG.x; + Player[0].LineBonus_StartY := Theme.Sing.TextP1Score.Y + 65; + end; + + 2: begin + //P1 + Player[0].LineBonus_TargetX := Theme.Sing.StaticP1TwoPScoreBG.x; + Player[0].LineBonus_TargetY := Theme.Sing.TextP1TwoPScore.Y; + Player[0].LineBonus_StartX := Theme.Sing.StaticP1TwoPScoreBG.X; + Player[0].LineBonus_StartY := Theme.Sing.TextP1TwoPScore.Y + 65; + + //P2 + Player[1].LineBonus_TargetX := Theme.Sing.StaticP2RScoreBG.X; + Player[1].LineBonus_TargetY := Theme.Sing.TextP2RScore.Y; + Player[1].LineBonus_StartX := Theme.Sing.StaticP2RScoreBG.X; + Player[1].LineBonus_StartY := Theme.Sing.TextP2RScore.Y + 65; + end; + + 3: begin + //P1 + Player[0].LineBonus_TargetX := Theme.Sing.StaticP1ThreePScoreBG.x; + Player[0].LineBonus_TargetY := Theme.Sing.TextP1ThreePScore.Y; + Player[0].LineBonus_StartX := Theme.Sing.StaticP1ThreePScoreBG.x; + Player[0].LineBonus_StartY := Theme.Sing.TextP1ThreePScore.Y + 65; + + //P2 + Player[1].LineBonus_TargetX := Theme.Sing.StaticP2MScoreBG.x; + Player[1].LineBonus_TargetY := Theme.Sing.TextP2MScore.Y; + Player[1].LineBonus_StartX := Theme.Sing.StaticP2MScoreBG.x; + Player[1].LineBonus_StartY := Theme.Sing.TextP2MScore.Y + 65; + + //P3 + Player[2].LineBonus_TargetX := Theme.Sing.StaticP3RScoreBG.x; + Player[2].LineBonus_TargetY := Theme.Sing.TextP3RScore.Y; + Player[2].LineBonus_StartX := Theme.Sing.StaticP3RScoreBG.x; + Player[2].LineBonus_StartY := Theme.Sing.TextP3RScore.Y + 65; + end; + + 4: begin + //P1 + Player[0].LineBonus_TargetX := Theme.Sing.StaticP1TwoPScoreBG.x; + Player[0].LineBonus_TargetY := Theme.Sing.TextP1TwoPScore.Y; + Player[0].LineBonus_StartX := Theme.Sing.StaticP1TwoPScoreBG.x; + Player[0].LineBonus_StartY := Theme.Sing.TextP1TwoPScore.Y + 65; + + //P2 + Player[1].LineBonus_TargetX := Theme.Sing.StaticP2RScoreBG.x; + Player[1].LineBonus_TargetY := Theme.Sing.TextP2RScore.Y; + Player[1].LineBonus_StartX := Theme.Sing.StaticP2RScoreBG.x; + Player[1].LineBonus_StartY := Theme.Sing.TextP2RScore.Y + 65; + + //P3 + Player[2].LineBonus_TargetX := Theme.Sing.StaticP1TwoPScoreBG.x; + Player[2].LineBonus_TargetY := Theme.Sing.TextP1TwoPScore.Y; + Player[2].LineBonus_StartX := Theme.Sing.StaticP1TwoPScoreBG.x; + Player[2].LineBonus_StartY := Theme.Sing.TextP1TwoPScore.Y + 65; + + //P4 + Player[3].LineBonus_TargetX := Theme.Sing.StaticP2RScoreBG.x; + Player[3].LineBonus_TargetY := Theme.Sing.TextP2RScore.Y; + Player[3].LineBonus_StartX := Theme.Sing.StaticP2RScoreBG.x; + Player[3].LineBonus_StartY := Theme.Sing.TextP2RScore.Y + 65; + end; + + 6: begin + //P1 + Player[0].LineBonus_TargetX := Theme.Sing.StaticP1ThreePScoreBG.x; + Player[0].LineBonus_TargetY := Theme.Sing.TextP1ThreePScore.Y; + Player[0].LineBonus_StartX := Theme.Sing.StaticP1ThreePScoreBG.x; + Player[0].LineBonus_StartY := Theme.Sing.TextP1ThreePScore.Y + 65; + + //P2 + Player[1].LineBonus_TargetX := Theme.Sing.StaticP2MScoreBG.x; + Player[1].LineBonus_TargetY := Theme.Sing.TextP2MScore.Y; + Player[1].LineBonus_StartX := Theme.Sing.StaticP2MScoreBG.x; + Player[1].LineBonus_StartY := Theme.Sing.TextP2MScore.Y + 65; + + //P3 + Player[2].LineBonus_TargetX := Theme.Sing.StaticP3RScoreBG.x; + Player[2].LineBonus_TargetY := Theme.Sing.TextP3RScore.Y; + Player[2].LineBonus_StartX := Theme.Sing.StaticP3RScoreBG.x; + Player[2].LineBonus_StartY := Theme.Sing.TextP3RScore.Y + 65; + + //P4 + Player[3].LineBonus_TargetX := Theme.Sing.StaticP1ThreePScoreBG.x; + Player[3].LineBonus_TargetY := Theme.Sing.TextP1ThreePScore.Y; + Player[3].LineBonus_StartX := Theme.Sing.StaticP1ThreePScoreBG.x; + Player[3].LineBonus_StartY := Theme.Sing.TextP1ThreePScore.Y + 65; + + //P5 + Player[4].LineBonus_TargetX := Theme.Sing.StaticP2MScoreBG.x; + Player[4].LineBonus_TargetY := Theme.Sing.TextP2MScore.Y; + Player[4].LineBonus_StartX := Theme.Sing.StaticP2MScoreBG.x; + Player[4].LineBonus_StartY := Theme.Sing.TextP2MScore.Y + 65; + + //P6 + Player[5].LineBonus_TargetX := Theme.Sing.StaticP3RScoreBG.x; + Player[5].LineBonus_TargetY := Theme.Sing.TextP3RScore.Y; + Player[5].LineBonus_StartX := Theme.Sing.StaticP3RScoreBG.x; + Player[5].LineBonus_StartY := Theme.Sing.TextP3RScore.Y + 65; + end; + end; + end + else if (Ini.LineBonus = 2) then //Show Line Bonus at Notes + begin + + // positions + if Ini.SingWindow = 0 then begin + NR.Left := 120; + end else begin + NR.Left := 20; + end; + NR.Right := 780; + + NR.Width := NR.Right - NR.Left; + NR.WMid := NR.Width / 2; + NR.Mid := NR.Left + NR.WMid; + + Case PlayersPlay of + 1: begin + Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_TargetY := Skin_P2_NotesB - 105 - 65; + Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_StartY := Skin_P2_NotesB - 105; + end; + + 2: begin + //P1 + Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_TargetY := Skin_P1_NotesB - 105 - 65 + 28; + Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_StartY := Skin_P1_NotesB - 105 + 28; + + //P2 + Player[1].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[1].LineBonus_TargetY := Skin_P2_NotesB - 105 - 65 + 28; + Player[1].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[1].LineBonus_StartY := Skin_P2_NotesB - 105 + 28; + end; + + 3: begin + //P1 + Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_TargetY := 120 - 65 + 28; + Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_StartY := 120 + 28; + + //P2 + Player[1].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[1].LineBonus_TargetY := 245 - 65 + 28; + Player[1].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[1].LineBonus_StartY := 245 + 28; + + //P3 + Player[2].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[2].LineBonus_TargetY := 370 - 65 + 28; + Player[2].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[2].LineBonus_StartY := 370 + 28; + end; + + 4: begin + //P1 + Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_TargetY := Skin_P1_NotesB - 105 - 65 + 28; + Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_StartY := Skin_P1_NotesB - 105 + 28; + + //P2 + Player[1].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[1].LineBonus_TargetY := Skin_P2_NotesB - 105 - 65 + 28; + Player[1].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[1].LineBonus_StartY := Skin_P2_NotesB - 105 + 28; + + //P3 + Player[2].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[2].LineBonus_TargetY := Skin_P1_NotesB - 105 - 65 + 28; + Player[2].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[2].LineBonus_StartY := Skin_P1_NotesB - 105 + 28; + + //P4 + Player[3].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[3].LineBonus_TargetY := Skin_P2_NotesB - 105 - 65 + 28; + Player[3].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[3].LineBonus_StartY := Skin_P2_NotesB - 105 + 28; + end; + + 6: begin + //P1 + Player[0].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_TargetY := 120 - 65 + 28; + Player[0].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[0].LineBonus_StartY := 120 + 28; + + //P2 + Player[1].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[1].LineBonus_TargetY := 245 - 65 + 28; + Player[1].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[1].LineBonus_StartY := 245 + 28; + + //P3 + Player[2].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[2].LineBonus_TargetY := 370 - 65 + 28; + Player[2].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[2].LineBonus_StartY := 370 + 28; + + //P4 + Player[3].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[3].LineBonus_TargetY := 120 - 65 + 28; + Player[3].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[3].LineBonus_StartY := 120 + 28; + + //P5 + Player[4].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[4].LineBonus_TargetY := 245 - 65 + 28; + Player[4].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[4].LineBonus_StartY := 245 + 28; + + //P6 + Player[5].LineBonus_TargetX := Round(Nr.Right + 10*ScreenX - 100); + Player[5].LineBonus_TargetY := 370 - 65 + 28; + Player[5].LineBonus_StartX := Round(Nr.Right + 10*ScreenX - 100); + Player[5].LineBonus_StartY := 370 + 28; + end; + end; + end; } + + //Set Position of Line Bonus - PhrasenBonus End + //Set Num of Empty Sentences for Phrasen Bonus + NumEmptySentences := 0; + for P := low(Lines[0].Line) to high(Lines[0].Line) do + if Lines[0].Line[P].TotalNotes = 0 then Inc(NumEmptySentences); + + Log.LogStatus('End', 'onShow'); +end; + +procedure TScreenSing.onShowFinish; +begin + // play movie (II) + + if CurrentSong.VideoLoaded then + begin + try + fCurrentVideoPlaybackEngine.GetFrame(LineState.CurrentTime); + fCurrentVideoPlaybackEngine.DrawGL(ScreenAct); +// PlaySmpeg; + except + + on E : Exception do + begin + //If an Error occurs Reading Video: prevent Video from being Drawn again and Close Video + CurrentSong.VideoLoaded := False; + Log.LogError('Error drawing Video, Video has been disabled for this Song/Session.'); + Log.LogError('Error Message : '+ E.message ); + Log.LogError(' In : '+ E.ClassName +' (TScreenSing.onShowFinish)' ); + Log.LogError('Corrupted File: ' + CurrentSong.Video); + try +// CloseSmpeg; + fCurrentVideoPlaybackEngine.Close; + except + + end; + end; + end; + end; + + + // play music (II) + AudioPlayback.Play; + + // prepare timer (II) + CountSkipTimeSet; +end; + +function TScreenSing.Draw: boolean; +var + Min: integer; + Sec: integer; + Tekst: string; + Flash: real; + S: integer; + T: integer; +begin + + + + //ScoreBG Mod | den wirren Scheiss hier brauch mer nimmer, wir haben colorized png's - no need for wirrness also + // set player colors - macht nichts weiter als die farben des statics zu wechseln, was zu unschönen effekten bei colorized png führt +{ if PlayersPlay = 4 then begin + if ScreenAct = 1 then begin + LoadColor(Static[StaticP1TwoP].Texture.ColR, Static[StaticP1TwoP].Texture.ColG, + Static[StaticP1TwoP].Texture.ColB, 'P1Dark'); + LoadColor(Static[StaticP2R].Texture.ColR, Static[StaticP2R].Texture.ColG, + Static[StaticP2R].Texture.ColB, 'P2Dark'); + + LoadColor(Static[StaticP1TwoPScoreBG].Texture.ColR, Static[StaticP1TwoPScoreBG].Texture.ColG, + Static[StaticP1TwoPScoreBG].Texture.ColB, 'P1Dark'); + LoadColor(Static[StaticP2RScoreBG].Texture.ColR, Static[StaticP2RScoreBG].Texture.ColG, + Static[StaticP2RScoreBG].Texture.ColB, 'P2Dark'); + end; + if ScreenAct = 2 then begin + LoadColor(Static[StaticP1TwoP].Texture.ColR, Static[StaticP1TwoP].Texture.ColG, + Static[StaticP1TwoP].Texture.ColB, 'P3Dark'); + LoadColor(Static[StaticP2R].Texture.ColR, Static[StaticP2R].Texture.ColG, + Static[StaticP2R].Texture.ColB, 'P4Dark'); + + LoadColor(Static[StaticP1TwoPScoreBG].Texture.ColR, Static[StaticP1TwoPScoreBG].Texture.ColG, + Static[StaticP1TwoPScoreBG].Texture.ColB, 'P3Dark'); + LoadColor(Static[StaticP2RScoreBG].Texture.ColR, Static[StaticP2RScoreBG].Texture.ColG, + Static[StaticP2RScoreBG].Texture.ColB, 'P4Dark'); + end; + end; + + if PlayersPlay = 6 then begin + if ScreenAct = 1 then begin + LoadColor(Static[StaticP1ThreeP].Texture.ColR, Static[StaticP1ThreeP].Texture.ColG, + Static[StaticP1ThreeP].Texture.ColB, 'P1Dark'); + LoadColor(Static[StaticP2M].Texture.ColR, Static[StaticP2M].Texture.ColG, + Static[StaticP2R].Texture.ColB, 'P2Dark'); + LoadColor(Static[StaticP3R].Texture.ColR, Static[StaticP3R].Texture.ColG, + Static[StaticP3R].Texture.ColB, 'P3Dark'); + + LoadColor(Static[StaticP1ThreePScoreBG].Texture.ColR, Static[StaticP1ThreePScoreBG].Texture.ColG, + Static[StaticP1ThreePScoreBG].Texture.ColB, 'P1Dark'); + LoadColor(Static[StaticP2MScoreBG].Texture.ColR, Static[StaticP2MScoreBG].Texture.ColG, + Static[StaticP2RScoreBG].Texture.ColB, 'P2Dark'); + LoadColor(Static[StaticP3RScoreBG].Texture.ColR, Static[StaticP3RScoreBG].Texture.ColG, + Static[StaticP3RScoreBG].Texture.ColB, 'P3Dark'); + end; + if ScreenAct = 2 then begin + + LoadColor(Static[StaticP1ThreeP].Texture.ColR, Static[StaticP1ThreeP].Texture.ColG, + Static[StaticP1ThreeP].Texture.ColB, 'P4Dark'); + LoadColor(Static[StaticP2M].Texture.ColR, Static[StaticP2M].Texture.ColG, + Static[StaticP2R].Texture.ColB, 'P5Dark'); + LoadColor(Static[StaticP3R].Texture.ColR, Static[StaticP3R].Texture.ColG, + Static[StaticP3R].Texture.ColB, 'P6Dark'); + + + LoadColor(Static[StaticP1ThreePScoreBG].Texture.ColR, Static[StaticP1ThreePScoreBG].Texture.ColG, + Static[StaticP1ThreePScoreBG].Texture.ColB, 'P4Dark'); + LoadColor(Static[StaticP2MScoreBG].Texture.ColR, Static[StaticP2MScoreBG].Texture.ColG, + Static[StaticP2RScoreBG].Texture.ColB, 'P5Dark'); + LoadColor(Static[StaticP3RScoreBG].Texture.ColR, Static[StaticP3RScoreBG].Texture.ColG, + Static[StaticP3RScoreBG].Texture.ColB, 'P6Dark'); + end; + end; + } + + // set player names (for 2 screens and only Singstar skin) + if ScreenAct = 1 then begin + Text[TextP1].Text := 'P1'; + Text[TextP1TwoP].Text := 'P1'; + Text[TextP1ThreeP].Text := 'P1'; + Text[TextP2R].Text := 'P2'; + Text[TextP2M].Text := 'P2'; + Text[TextP3R].Text := 'P3'; + end; + + if ScreenAct = 2 then begin + case PlayersPlay of +{ 1: begin + Text[TextP1].Text := 'P2'; + end; + 2: begin + Text[TextP1].Text := 'P3'; + Text[TextP2R].Text := 'P4'; + end; + 3: begin + Text[TextP1].Text := 'P4'; + Text[TextP2M].Text := 'P5'; + Text[TextP3R].Text := 'P6'; + end;} + + 4: begin + Text[TextP1TwoP].Text := 'P3'; + Text[TextP2R].Text := 'P4'; + end; + 6: begin + Text[TextP1ThreeP].Text := 'P4'; + Text[TextP2M].Text := 'P5'; + Text[TextP3R].Text := 'P6'; + end; + end; // case + end; // if + + // stereo + +// weird stuff, maybe this is for "dual screen?", but where is player three then? | okay, i commented the stuff out the other day - nothing was missing on screen w/ 6 players - so do we even need this stuff? +// okay this stuff appears again some lines beneath this one, I commented it out for testing what it does - seems like it's doing nothing +// but I might be wrong, so what is this stuff here doing? O.o + Static[StaticP1].Texture.X := Static[StaticP1].Texture.X + 10*ScreenX; + + Text[TextP1].X := Text[TextP1].X + 10*ScreenX; + + {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X + 10*ScreenX; + Text[TextP1Score].X := Text[TextP1Score].X + 10*ScreenX;} + + + Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X + 10*ScreenX; + + Text[TextP2R].X := Text[TextP2R].X + 10*ScreenX; + + {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X + 10*ScreenX; + Text[TextP2RScore].X := Text[TextP2RScore].X + 10*ScreenX;} +// end of weird stuff + + for S := 1 to 1 do //wtf? + Static[S].Texture.X := Static[S].Texture.X + 10*ScreenX; + + for T := 0 to 1 do + Text[T].X := Text[T].X + 10*ScreenX; + + // update static menu with time ... + Min := Round(LineState.CurrentTime) div 60; + Sec := Round(LineState.CurrentTime) mod 60; + Text[TextTimeText].Text := ''; + if Min < 10 then Text[TextTimeText].Text := '0'; + Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Min) + ':'; + if Sec < 10 then Text[TextTimeText].Text := Text[TextTimeText].Text + '0'; + Text[TextTimeText].Text := Text[TextTimeText].Text + IntToStr(Sec); + + {// .. and scores + if PlayersPlay = 1 then begin + Tekst := IntToStr(Player[0].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP1Score].Text := Tekst; + end; + + if PlayersPlay = 2 then begin + Tekst := IntToStr(Player[0].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP1TwoPScore].Text := Tekst; + + Tekst := IntToStr(Player[1].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP2RScore].Text := Tekst; + end; + + if PlayersPlay = 3 then begin + Tekst := IntToStr(Player[0].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP1ThreePScore].Text := Tekst; + + Tekst := IntToStr(Player[1].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP2MScore].Text := Tekst; + + Tekst := IntToStr(Player[2].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP3RScore].Text := Tekst; + end; + + if PlayersPlay = 4 then begin + if ScreenAct = 1 then begin + Tekst := IntToStr(Player[0].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP1TwoPScore].Text := Tekst; + + Tekst := IntToStr(Player[1].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP2RScore].Text := Tekst; + end; + if ScreenAct = 2 then begin + Tekst := IntToStr(Player[2].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP1TwoPScore].Text := Tekst; + + Tekst := IntToStr(Player[3].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP2RScore].Text := Tekst; + end; + end; + + if PlayersPlay = 6 then begin + if ScreenAct = 1 then begin + Tekst := IntToStr(Player[0].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP1ThreePScore].Text := Tekst; + + Tekst := IntToStr(Player[1].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP2MScore].Text := Tekst; + + Tekst := IntToStr(Player[2].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP3RScore].Text := Tekst; + end; + if ScreenAct = 2 then begin + Tekst := IntToStr(Player[3].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP1ThreePScore].Text := Tekst; + + Tekst := IntToStr(Player[4].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP2MScore].Text := Tekst; + + Tekst := IntToStr(Player[5].ScoreTotalI); + while Length(Tekst) < 5 do Tekst := '0' + Tekst; + Text[TextP3RScore].Text := Tekst; + end; + end; } + + // draw static menu (BG) + //DrawBG; // there is no menu and the animated background brakes the video playback because the timecode is in a different format + //Draw Background + SingDrawBackground; + // update and draw movie + + if ShowFinish and + ( CurrentSong.VideoLoaded or fShowVisualization ) then +// if ShowFinish then + begin +// try +// UpdateSmpeg; // this only draws + // todo: find a way to determine, when a new frame is needed + // toto: same for the need to skip frames + + if assigned( fCurrentVideoPlaybackEngine ) then + begin + fCurrentVideoPlaybackEngine.GetFrame(LineState.CurrentTime); + fCurrentVideoPlaybackEngine.DrawGL(ScreenAct); + end; + +(* + except + on E : Exception do + begin + + //If an Error occurs drawing: prevent Video from being Drawn again and Close Video + CurrentSong.VideoLoaded := False; + log.LogError('Error drawing Video, Video has been disabled for this Song/Session.'); + Log.LogError('Error Message : '+ E.message ); + Log.LogError(' In : '+ E.ClassName +' (TScreenSing.Draw)' ); + + Log.LogError('Corrupted File: ' + CurrentSong.Video); + try +// CloseSmpeg; + fCurrentVideoPlaybackEngine.Close; + except + + end; + end; + end; +*) + + end; + + // draw static menu (FG) + DrawFG; + + // check for music finish +// Log.LogError('Check for music finish: ' + BoolToStr(Music.Finished) + ' ' + FloatToStr(LineState.CurrentTime*1000) + ' ' + IntToStr(CurrentSong.Finish)); + if ShowFinish then begin + if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or (LineState.CurrentTime*1000 <= CurrentSong.Finish)) then begin + //Pause Mod: + if not Paused then Sing(Self); // analyze song + end else begin +// Log.LogError('End'); + if not FadeOut then begin +// Log.LogError('End2'); + Finish; + FadeOut := true; + FadeTo(@ScreenScore); + end; + end; + end; + + // draw custom items + SingDraw; // always draw + +//GoldenNoteStarsTwinkle Mod + GoldenRec.SpawnRec; +//GoldenNoteStarsTwinkle Mod + + //Draw Scores + Scores.Draw; + + // back stereo + +// weird stuff, maybe this is for "dual screen?", but where is player three then? +// okay this stuff appears again some lines above this one, I commented it out for testing what it does - seems like it's doing nothing +// but I might be wrong, so what is this stuff here doing? O.o + Static[StaticP1].Texture.X := Static[StaticP1].Texture.X - 10*ScreenX; + Text[TextP1].X := Text[TextP1].X - 10*ScreenX; + + {Static[StaticP1ScoreBG].Texture.X := Static[StaticP1ScoreBG].Texture.X - 10*ScreenX; + Text[TextP1Score].X := Text[TextP1Score].X - 10*ScreenX;} + + + Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X - 10*ScreenX; + Text[TextP2R].X := Text[TextP2R].X - 10*ScreenX; + + {Static[StaticP2RScoreBG].Texture.X := Static[StaticP2RScoreBG].Texture.X - 10*ScreenX; + Text[TextP2RScore].X := Text[TextP2RScore].X - 10*ScreenX;} +//weird end + + for S := 1 to 1 do // wtf? + Static[S].Texture.X := Static[S].Texture.X - 10*ScreenX; + + for T := 0 to 1 do + Text[T].X := Text[T].X - 10*ScreenX; + + //Draw Pausepopup + //I use this workaround that the Static is drawen over the Lyrics, Lines, Scores and Effects + //maybe someone could find a better solution + if Paused then + begin + Static[StaticPausePopup].Visible := true; + Static[StaticPausePopup].Draw; + Static[StaticPausePopup].Visible := false; + end; + +end; + +procedure TScreenSing.Finish; +begin + AudioInput.CaptureStop; + AudioPlayback.Stop; + + if Ini.SavePlayback = 1 then begin + Log.BenchmarkStart(0); + Log.LogVoice(0); + Log.LogVoice(1); + Log.LogVoice(2); + Log.BenchmarkEnd(0); + Log.LogBenchmark('Creating files', 0); + end; + + if CurrentSong.VideoLoaded then + begin +// CloseSmpeg; + fCurrentVideoPlaybackEngine.Close; + CurrentSong.VideoLoaded := false; // to prevent drawing closed video + end; + + SetFontItalic (False); +end; + +(* +procedure TScreenSing.UpdateLCD; //TODO: maybe LCD Support as Plugin? +var + T: string; +begin + //Todo: Lyrics +{ LCD.HideCursor; + LCD.Clear; + + T := LyricMain.Text; + if Copy(T, Length(T), 1) <> ' ' then T := T + ' '; + LCD.AddTextBR(T); + + T := LyricSub.Text; + if Copy(T, Length(T), 1) <> ' ' then T := T + ' '; + LCD.AddTextBR(T);} +end; +*) + +procedure TScreenSing.onSentenceEnd(S: Cardinal); +var +I: Integer; +A: Real; +B: integer; //Max Points for Notes +begin + + //Check for Empty Sentence + if (Lines[0].Line[S].TotalNotes<=0) then + exit; + + //Set Max Note Points + if (Ini.LineBonus > 0) then + B := 9000 + else + B := 10000; + + for I := 0 to High(Player) do begin + A := Player[I].Score + Player[I].ScoreGolden - Player[I].ScoreLast + 2; + + + //PhrasenBonus - Line Bonus Mod + + //Generate Steps 0 to 8 + A := Floor(A / (B * Lines[0].Line[S].TotalNotes / Lines[0].ScoreValue) * 8); + + If (Ini.LineBonus > 0) then + begin + //PhrasenBonus give Points + Player[I].ScoreLine := Player[I].ScoreLine + (1000 / (Length(Lines[0].Line) - NumEmptySentences) * A / 8); + Player[I].ScoreLineI := Round(Player[I].ScoreLine / 10) * 10; + //Update Total Score + Player[I].ScoreTotalI := Player[I].ScoreI + Player[I].ScoreGoldenI + Player[I].ScoreLineI; + + //Spawn PopUp + If (A >= 8) then + A := 8 + else IF A < 0 then + A := 0; + + Scores.SpawnPopUp(I, Floor(A), Player[I].ScoreTotalI); + end; + //PhrasenBonus - Line Bonus Mod End// } + + //PerfectLineTwinkle Mod (effect) Pt.1 + If (Ini.EffectSing=1) then + begin + if A >= 8 then Player[I].LastSentencePerfect := True + else Player[I].LastSentencePerfect := False; + end; + //PerfectLineTwinkle Mod end + + //Refresh LastScore + Player[I].ScoreLast := Player[I].Score + Player[I].ScoreGolden; + + end; + + //PerfectLineTwinkle Mod (effect) Pt.2 + if Ini.EffectSing=1 then + GoldenRec.SpawnPerfectLineTwinkle; + //PerfectLineTwinkle Mod end + + + // if we are shoing a visualization... change to a new preset after each sentence.. + // Maybe we should make this less often or something... just a + if fShowVisualization then + fCurrentVideoPlaybackEngine.Position := now; // move to a random position +end; + +//Called on Sentence Change S= New Current Sentence +procedure TScreenSing.onSentenceChange(S: Cardinal); +begin + //GoldenStarsTwinkle Mod + GoldenRec.SentenceChange; + if (Lyrics.LineCounter <= High(Lines[0].Line)) then + begin + Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]); + end + else + Lyrics.AddLine(nil); + + // addline uses display memory + // calling draw makes sure, there's the singscreen in it, when the next + // swap between onscreen and offscreen buffers is done + // (this eliminates the onSentenceChange flickering) + // note: maybe it would be better to make sure, a display redraw is done + // right after the sentence change (before buffer swap) or make sure + // onsentencechange is only called right before calling Display.Draw + // (or whatever it was called) + Draw; + + //GoldenStarsTwinkle Mod End +end; + +end. diff --git a/Game/Code/switches.inc b/Game/Code/switches.inc index 1162df35..10ca6b71 100644 --- a/Game/Code/switches.inc +++ b/Game/Code/switches.inc @@ -1,116 +1,116 @@ -// Comment by eddie: -// The mac port currently also uses the WIN32 define. -// Once I get the beast compiled, linked and running -// I will change this. -// There are some parts where the WIN32 define could not -// be used. I changed the WIN32 to MSWINDOWS. -// So, for Windows-only code use the MSWINDOWS define. - -// compiler/IDE dependent config -{$IFDEF FPC} - {$IFDEF DARWIN} - {$H+} // enables usage of AnsiString as String-type - {$R-} // disables range-checks - {$ENDIF} - - // if -dDEBUG is specified on the command-line, FPC uses some default - // compiler-flags specified in fpc.cfg -> use -dDEBUG_MODE instead - {$IFDEF DEBUG_MODE} - {$DEFINE DEBUG} - {$ENDIF} - - {$DEFINE HasInline} -{$ELSE} - {$DEFINE Delphi} - - // Delphi version numbers (ignore versions released before Delphi 6 as they miss the $IF directive): - // Delphi 6 (VER140), Delphi 7 (VER150), Delphi 8 (VER160) - // Delphi 9/2005 (VER170), Delphi 10/2006 (VER180) - - // the inline-procedure directive was introduced with Delphi 2005 - {$IF not (Defined(VER140) or Defined(VER150) or Defined(VER160))} - {$DEFINE HasInline} - {$IFEND} -{$ENDIF} - - -// platform dependent config -{$IF Defined(MSWINDOWS)} - // include defines but no constants - {$I config-win.inc} - - // enable debug-mode. For development only! - //{$DEFINE DEBUG} - {$IFDEF DEBUG} - // windows apps are either GUI- or console-apps. Console-apps will open - // an additional console-window for output. For development only! - {$DEFINE CONSOLE} - {$ENDIF} - - {$DEFINE HaveBASS} - {$UNDEF UseSerialPort} - {$DEFINE UseMIDIPort} -{$ELSEIF Defined(LINUX)} - // include defines but no constants - {$I config-linux.inc} - - // use "configure --enable-debug", "make debug" or - // the command-line parameter "-debug" instead of defining DEBUG directly - //{$DEFINE DEBUG} - // linux apps are always console-apps so leave this defined. - {$DEFINE CONSOLE} -{$ELSEIF Defined(DARWIN)} - // include defines but no constants - {$I config-macosx.inc} - - // enable debug-mode. For development only! - //{$DEFINE DEBUG} - {$DEFINE CONSOLE} - - {$DEFINE HaveBASS} - {$DEFINE DLL_CDECL} - {$DEFINE WIN32} - {$DEFINE UTF8_FILENAMES} -{$IFEND} - -// audio config -{$IF Defined(HaveBASS)} - {$DEFINE UseBASSPlayback} - {$DEFINE UseBASSInput} -{$ELSEIF Defined(HavePortaudio)} - //{$DEFINE UsePortaudioPlayback} - {$DEFINE UseSDLPlayback} - {$DEFINE UsePortaudioInput} - {$IFDEF HavePortmixer} - {$DEFINE UsePortmixer} - {$ENDIF} -{$IFEND} - -// ffmpeg config -{$IFDEF HaveFFMpeg} - {$DEFINE UseFFMpegDecoder} - {$DEFINE UseFFMpegVideo} - {$IFDEF HaveSWScale} - {$DEFINE UseSWScale} - {$ENDIF} -{$ENDIF} - -// projectM config -{$IF Defined(HaveProjectM)} - {$DEFINE UseProjectM} -{$IFEND} - -// specify some useful defines - -{$IF Defined(UseFFMpegVideo) or Defined(UseFFMpegDecoder)} - {$DEFINE UseFFMpeg} -{$IFEND} - -{$IF Defined(UseBASSInput) or Defined(UseBASSPlayback)} - {$DEFINE UseBASS} -{$IFEND} - -{$IF Defined(UsePortaudioInput) or Defined(UsePortaudioPlayback)} - {$DEFINE UsePortaudio} -{$IFEND} - +// Comment by eddie: +// The mac port currently also uses the WIN32 define. +// Once I get the beast compiled, linked and running +// I will change this. +// There are some parts where the WIN32 define could not +// be used. I changed the WIN32 to MSWINDOWS. +// So, for Windows-only code use the MSWINDOWS define. + +// compiler/IDE dependent config +{$IFDEF FPC} + {$IFDEF DARWIN} + {$H+} // enables usage of AnsiString as String-type + {$R-} // disable range-checks (eddie: please test if this is still necessary) + {$ENDIF} + + // if -dDEBUG is specified on the command-line, FPC uses some default + // compiler-flags specified in fpc.cfg -> use -dDEBUG_MODE instead + {$IFDEF DEBUG_MODE} + {$DEFINE DEBUG} + {$ENDIF} + + {$DEFINE HasInline} +{$ELSE} + {$DEFINE Delphi} + + // Delphi version numbers (ignore versions released before Delphi 6 as they miss the $IF directive): + // Delphi 6 (VER140), Delphi 7 (VER150), Delphi 8 (VER160) + // Delphi 9/2005 (VER170), Delphi 10/2006 (VER180) + + // the inline-procedure directive was introduced with Delphi 2005 + {$IF not (Defined(VER140) or Defined(VER150) or Defined(VER160))} + {$DEFINE HasInline} + {$IFEND} +{$ENDIF} + + +// platform dependent config +{$IF Defined(MSWINDOWS)} + // include defines but no constants + {$I config-win.inc} + + // enable debug-mode. For development only! + //{$DEFINE DEBUG} + {$IFDEF DEBUG} + // windows apps are either GUI- or console-apps. Console-apps will open + // an additional console-window for output. For development only! + {$DEFINE CONSOLE} + {$ENDIF} + + {$DEFINE HaveBASS} + {$UNDEF UseSerialPort} + {$DEFINE UseMIDIPort} +{$ELSEIF Defined(LINUX)} + // include defines but no constants + {$I config-linux.inc} + + // use "configure --enable-debug", "make debug" or + // the command-line parameter "-debug" instead of defining DEBUG directly + //{$DEFINE DEBUG} + // linux apps are always console-apps so leave this defined. + {$DEFINE CONSOLE} +{$ELSEIF Defined(DARWIN)} + // include defines but no constants + {$I config-macosx.inc} + + // enable debug-mode. For development only! + //{$DEFINE DEBUG} + {$DEFINE CONSOLE} + + {$DEFINE HaveBASS} + {$DEFINE DLL_CDECL} + {$DEFINE WIN32} + {$DEFINE UTF8_FILENAMES} +{$IFEND} + +// audio config +{$IF Defined(HaveBASS)} + {$DEFINE UseBASSPlayback} + {$DEFINE UseBASSInput} +{$ELSEIF Defined(HavePortaudio)} + //{$DEFINE UsePortaudioPlayback} + {$DEFINE UseSDLPlayback} + {$DEFINE UsePortaudioInput} + {$IFDEF HavePortmixer} + {$DEFINE UsePortmixer} + {$ENDIF} +{$IFEND} + +// ffmpeg config +{$IFDEF HaveFFMpeg} + {$DEFINE UseFFMpegDecoder} + {$DEFINE UseFFMpegVideo} + {$IFDEF HaveSWScale} + {$DEFINE UseSWScale} + {$ENDIF} +{$ENDIF} + +// projectM config +{$IF Defined(HaveProjectM)} + {$DEFINE UseProjectM} +{$IFEND} + +// specify some useful defines + +{$IF Defined(UseFFMpegVideo) or Defined(UseFFMpegDecoder)} + {$DEFINE UseFFMpeg} +{$IFEND} + +{$IF Defined(UseBASSInput) or Defined(UseBASSPlayback)} + {$DEFINE UseBASS} +{$IFEND} + +{$IF Defined(UsePortaudioInput) or Defined(UsePortaudioPlayback)} + {$DEFINE UsePortaudio} +{$IFEND} + -- cgit v1.2.3