aboutsummaryrefslogtreecommitdiffstats
path: root/src/screens0/UScreenSing.pas
diff options
context:
space:
mode:
Diffstat (limited to 'src/screens0/UScreenSing.pas')
-rw-r--r--src/screens0/UScreenSing.pas934
1 files changed, 0 insertions, 934 deletions
diff --git a/src/screens0/UScreenSing.pas b/src/screens0/UScreenSing.pas
deleted file mode 100644
index 911d122e..00000000
--- a/src/screens0/UScreenSing.pas
+++ /dev/null
@@ -1,934 +0,0 @@
-unit UScreenSing;
-
-interface
-
-{$IFDEF FPC}
- {$MODE Delphi}
-{$ENDIF}
-
-{$I switches.inc}
-
-
-uses UMenu,
- UMusic,
- SDL,
- SysUtils,
- UFiles,
- UTime,
- USongs,
- UIni,
- ULog,
- UTexture,
- ULyrics,
- TextGL,
- gl,
- UThemes,
- UGraphicClasses,
- USingScores;
-
-type
- TLyricsSyncSource = class(TSyncSource)
- function GetClock(): real; override;
- end;
-
-type
- TScreenSing = class(TMenu)
- protected
- Paused: boolean; //Pause Mod
- LyricsSync: TLyricsSyncSource;
- NumEmptySentences: integer;
- public
- //TextTime: integer;
-
- // TimeBar fields
- StaticTimeProgress: integer;
- TextTimeText: integer;
-
- StaticP1: integer;
- TextP1: integer;
-
- //shown when game is in 2/4 player modus
- StaticP1TwoP: integer;
- TextP1TwoP: integer;
-
- //shown when game is in 3/6 player modus
- StaticP1ThreeP: integer;
- TextP1ThreeP: integer;
-
- StaticP2R: integer;
- TextP2R: integer;
-
- StaticP2M: integer;
- TextP2M: integer;
-
- StaticP3R: integer;
- TextP3R: integer;
-
- StaticPausePopup: integer;
-
- Tex_Background: TTexture;
- FadeOut: boolean;
- 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 Pause; // Toggle Pause
-
- procedure OnSentenceEnd(SentenceIndex: cardinal); // for LineBonus + Singbar
- procedure OnSentenceChange(SentenceIndex: cardinal); // 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
- Paused := True;
-
- LyricsState.Pause();
-
- // pause Music
- AudioPlayback.Pause;
-
- // pause Video
- if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path +
- CurrentSong.Video) then
- fCurrentVideoPlaybackEngine.Pause;
-
- end
- else //disable Pause
- begin
- LyricsState.Resume();
-
- // 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);
-
- // 2 or 4 players | P1
- StaticP1TwoP := AddStatic(Theme.Sing.StaticP1TwoP);
- TextP1TwoP := AddText(Theme.Sing.TextP1TwoP);
-
- // | P2
- StaticP2R := AddStatic(Theme.Sing.StaticP2R);
- TextP2R := AddText(Theme.Sing.TextP2R);
-
- // 3 or 6 players | P1
- StaticP1ThreeP := AddStatic(Theme.Sing.StaticP1ThreeP);
- TextP1ThreeP := AddText(Theme.Sing.TextP1ThreeP);
-
- // | P2
- StaticP2M := AddStatic(Theme.Sing.StaticP2M);
- TextP2M := AddText(Theme.Sing.TextP2M);
-
- // | P3
- StaticP3R := AddStatic(Theme.Sing.StaticP3R);
- TextP3R := AddText(Theme.Sing.TextP3R);
-
- StaticPausePopup := AddStatic(Theme.Sing.PausePopUp);
-
- //<note>Pausepopup is not visibile at the beginning</note>
- Static[StaticPausePopup].Visible := False;
-
- Lyrics := TLyricEngine.Create(80, Skin_LyricsT, 640, 12, 80, Skin_LyricsT + 36, 640, 12);
-
- LyricsSync := TLyricsSyncSource.Create();
-end;
-
-procedure TScreenSing.onShow;
-var
- P: integer;
- V1: boolean;
- V1TwoP: boolean; //Position of ScoreBox in two-player mode
- V1ThreeP: boolean; //Position of ScoreBox in three-player mode
- V2R: boolean;
- V2M: boolean;
- V3R: boolean;
- NR: TRecR; //Some enlightment of who, how and what this is here please
- Color: TRGB;
-
- success: boolean;
-begin
- inherited;
-
- Log.LogStatus('Begin', 'onShow');
- FadeOut := False;
-
- // 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 <- \(O.o)/? B like bummy?
-
- // add new players
- for P := 0 to PlayersPlay - 1 do
- begin
- Scores.AddPlayer(Tex_ScoreBG[P], Color);
- end;
-
- Scores.Init; //Get Positions for Players
-
- // prepare players
- SetLength(Player, PlayersPlay);
-
- 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;
-
-
- //This one is shown in 2/4P mode
- Static[StaticP1TwoP].Visible := V1TwoP;
- Text[TextP1TwoP].Visible := V1TwoP;
-
- Static[StaticP2R].Visible := V2R;
- Text[TextP2R].Visible := V2R;
-
-
- //This one is shown in 3/6P mode
- Static[StaticP1ThreeP].Visible := V1ThreeP;
- Text[TextP1ThreeP].Visible := V1ThreeP;
-
-
- Static[StaticP2M].Visible := V2M;
- Text[TextP2M].Visible := V2M;
-
-
- Static[StaticP3R].Visible := V3R;
- Text[TextP3R].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...
- fCurrentVideoPlaybackEngine.Close;
- fCurrentVideoPlaybackEngine := VideoPlayback;
-{**
- * == Background ==
- * We have four types of backgrounds:
- * + Blank : Nothing has been set, this is our fallback
- * + Picture : Picture has been set, and exists - otherwise we fallback
- * + Video : Video has been set, and exists - otherwise we fallback
- * + Visualization: + Off : No Visialization
- * + WhenNoVideo: Overwrites Blank and Picture
- * + On : Overwrites Blank, Picture and Video
- *}
-{**
- * set background to: video
- *}
- CurrentSong.VideoLoaded := False;
- fShowVisualization := False;
- if (CurrentSong.Video <> '') and FileExists(CurrentSong.Path + CurrentSong.Video) then
- begin
- if (fCurrentVideoPlaybackEngine.Open(CurrentSong.Path + CurrentSong.Video)) then
- begin
- fShowVisualization := False;
- fCurrentVideoPlaybackEngine := VideoPlayback;
- fCurrentVideoPlaybackEngine.Position := CurrentSong.VideoGAP + CurrentSong.Start;
- CurrentSong.VideoLoaded := True;
- fCurrentVideoPlaybackEngine.play;
- end;
- end;
-
-{**
- * set background to: picture
- *}
- if (CurrentSong.Background <> '') and (CurrentSong.VideoLoaded = False)
- and (TVisualizerOption(Ini.VisualizerOption) = voOff) 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;
-{**
- * set background to: visualization (Overwrites all)
- *}
- if (TVisualizerOption(Ini.VisualizerOption) in [voOn]) then
- begin
- fShowVisualization := True;
- fCurrentVideoPlaybackEngine := Visualization;
- fCurrentVideoPlaybackEngine.play;
- end;
-
-{**
- * set background to: visualization (Videos are still shown)
- *}
- if ((TVisualizerOption(Ini.VisualizerOption) in [voWhenNoVideo]) and
- (CurrentSong.VideoLoaded = False)) then
- begin
- fShowVisualization := True;
- fCurrentVideoPlaybackEngine := Visualization;
- fCurrentVideoPlaybackEngine.play;
- end;
-
- // prepare lyrics timer
- LyricsState.Reset();
- LyricsState.SetCurrentTime(CurrentSong.Start);
- LyricsState.StartTime := CurrentSong.Gap;
- if (CurrentSong.Finish > 0) then
- LyricsState.TotalTime := CurrentSong.Finish / 1000
- else
- LyricsState.TotalTime := AudioPlayback.Length;
- LyricsState.UpdateBeats();
-
- // prepare music
- AudioPlayback.Stop();
- AudioPlayback.Position := CurrentSong.Start;
- // synchronize music to the lyrics
- AudioPlayback.SetSyncSource(LyricsSync);
-
- // prepare and start voice-capture
- AudioInput.CaptureStart;
-
- 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;
- end;
- 1:
- begin
- 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;
- end;
- end; // case
-
- // Initialize lyrics by filling its queue
- while (not Lyrics.IsQueueFull) and (Lyrics.LineCounter <=
- High(Lines[0].Line)) do
- begin
- Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]);
- end;
-
- // Deactivate pause
- Paused := False;
-
- // Kill all stars not killed yet (GoldenStarsTwinkle Mod)
- GoldenRec.SentenceChange;
-
- // set Position of Line Bonus - Line Bonus end
- // set number of empty sentences for Line 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
- // start lyrics
- LyricsState.Resume();
-
- // start music
- AudioPlayback.Play();
-
- // start timer
- CountSkipTimeSet;
-end;
-
-function TScreenSing.Draw: boolean;
-var
- Min: integer;
- Sec: integer;
- Tekst: string;
- Flash: real;
- S: integer;
- T: integer;
- CurLyricsTime: real;
-begin
-
- // 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
- 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
-
-
- ////
- // dual screen, part 1
- ////////////////////////
-
- // Note: ScreenX is the offset of the current screen in dual-screen mode so we
- // will move the statics and texts to the correct screen here.
- // FIXME: clean up this weird stuff. Commenting this stuff out, nothing
- // was missing on screen w/ 6 players - so do we even need this stuff?
- 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
-
- Static[1].Texture.X := Static[1].Texture.X + 10 * ScreenX;
-
- for T := 0 to 1 do
- Text[T].X := Text[T].X + 10 * ScreenX;
-
-
-
- // retrieve current lyrics time, we have to store the value to avoid
- // that min- and sec-values do not match
- CurLyricsTime := LyricsState.GetCurrentTime();
- Min := Round(CurLyricsTime) div 60;
- Sec := Round(CurLyricsTime) mod 60;
-
- // update static menu with time ...
- 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);
-
- // draw static menu (BG)
- // Note: there is no menu and the animated background brakes the video playback
- //DrawBG;
-
- // Draw Background
- SingDrawBackground;
-
- // update and draw movie
- if (ShowFinish and (CurrentSong.VideoLoaded or fShowVisualization)) then
- begin
- if assigned(fCurrentVideoPlaybackEngine) then
- begin
- fCurrentVideoPlaybackEngine.GetFrame(LyricsState.GetCurrentTime());
- fCurrentVideoPlaybackEngine.DrawGL(ScreenAct);
- end;
- end;
-
- // draw static menu (FG)
- DrawFG;
-
- // check for music finish
- //Log.LogError('Check for music finish: ' + BoolToStr(Music.Finished) + ' ' + FloatToStr(LyricsState.CurrentTime*1000) + ' ' + IntToStr(CurrentSong.Finish));
- if ShowFinish then
- begin
- if (not AudioPlayback.Finished) and ((CurrentSong.Finish = 0) or
- (LyricsState.GetCurrentTime() * 1000 <= CurrentSong.Finish)) then
- begin
- // analyze song if not paused
- if (not Paused) then
- Sing(Self);
- end
- else
- begin
- if (not FadeOut) then
- begin
- Finish;
- FadeOut := True;
- FadeTo(@ScreenScore);
- end;
- end;
- end;
-
- // always draw custom items
- SingDraw;
-
- //GoldenNoteStarsTwinkle
- GoldenRec.SpawnRec;
-
- //Draw Scores
- Scores.Draw;
-
- ////
- // dual screen, part 2
- ////////////////////////
-
- // Note: ScreenX is the offset of the current screen in dual-screen mode so we
- // will move the statics and texts to the correct screen here.
- // FIXME: clean up this weird stuff
-
- Static[StaticP1].Texture.X := Static[StaticP1].Texture.X - 10 * ScreenX;
- Text[TextP1].X := Text[TextP1].X - 10 * ScreenX;
-
- Static[StaticP2R].Texture.X := Static[StaticP2R].Texture.X - 10 * ScreenX;
- Text[TextP2R].X := Text[TextP2R].X - 10 * ScreenX;
-
- //end of weird
-
- Static[1].Texture.X := Static[1].Texture.X - 10 * ScreenX;
-
- for T := 0 to 1 do
- Text[T].X := Text[T].X - 10 * ScreenX;
-
- // Draw Pausepopup
- // FIXME: this is a workaround that the Static is drawn 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;
-
- Result := True;
-end;
-
-procedure TScreenSing.Finish;
-begin
- AudioInput.CaptureStop;
- AudioPlayback.Stop;
- AudioPlayback.SetSyncSource(nil);
-
- 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
- fCurrentVideoPlaybackEngine.Close;
- CurrentSong.VideoLoaded := False; // to prevent drawing closed video
- end;
-
- SetFontItalic(False);
-end;
-
-procedure TScreenSing.OnSentenceEnd(SentenceIndex: cardinal);
-var
- PlayerIndex: integer;
- CurrentPlayer: PPLayer;
- CurrentScore: real;
- Line: PLine;
- LinePerfection: real; // perfection of singing performance on the current line
- Rating: integer;
- LineScore: real;
- LineBonus: real;
- MaxSongScore: integer; // max. points for the song (without line bonus)
- MaxLineScore: real; // max. points for the current line
-const
- // TODO: move this to a better place
- MAX_LINE_RATING = 8; // max. rating for singing performance
-begin
- Line := @Lines[0].Line[SentenceIndex];
-
- // check for empty sentence
- if (Line.TotalNotes <= 0) then
- Exit;
-
- // set max song score
- if (Ini.LineBonus = 0) then
- MaxSongScore := MAX_SONG_SCORE
- else
- MaxSongScore := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS;
-
- // Note: ScoreValue is the sum of all note values of the song
- MaxLineScore := MaxSongScore * (Line.TotalNotes / Lines[0].ScoreValue);
-
- for PlayerIndex := 0 to High(Player) do
- begin
- CurrentPlayer := @Player[PlayerIndex];
- CurrentScore := CurrentPlayer.Score + CurrentPlayer.ScoreGolden;
-
- // Line Bonus
-
- // points for this line
- LineScore := CurrentScore - CurrentPlayer.ScoreLast;
-
- // determine LinePerfection
- // Note: the "+2" extra points are a little bonus so the player does not
- // have to be that perfect to reach the bonus steps.
- LinePerfection := (LineScore + 2) / MaxLineScore;
-
- // clamp LinePerfection to range [0..1]
- if (LinePerfection < 0) then
- LinePerfection := 0
- else if (LinePerfection > 1) then
- LinePerfection := 1;
-
- // add line-bonus if enabled
- if (Ini.LineBonus > 0) then
- begin
- // line-bonus points (same for each line, no matter how long the line is)
- LineBonus := MAX_SONG_LINE_BONUS / (Length(Lines[0].Line) -
- NumEmptySentences);
- // apply line-bonus
- CurrentPlayer.ScoreLine :=
- CurrentPlayer.ScoreLine + LineBonus * LinePerfection;
- CurrentPlayer.ScoreLineInt := Round(CurrentPlayer.ScoreLine / 10) * 10;
- // update total score
- CurrentPlayer.ScoreTotalInt :=
- CurrentPlayer.ScoreInt +
- CurrentPlayer.ScoreGoldenInt
- + CurrentPlayer.ScoreLineInt;
-
- // spawn rating pop-up
- Rating := Round(LinePerfection * MAX_LINE_RATING);
- Scores.SpawnPopUp(PlayerIndex, Rating, CurrentPlayer.ScoreTotalInt);
- end;
-
- // PerfectLineTwinkle (effect), Part 1
- if (Ini.EffectSing = 1) then
- CurrentPlayer.LastSentencePerfect := (LinePerfection >= 1);
-
- // refresh last score
- CurrentPlayer.ScoreLast := CurrentScore;
- end;
-
- // PerfectLineTwinkle (effect), Part 2
- if (Ini.EffectSing = 1) then
- GoldenRec.SpawnPerfectLineTwinkle;
-end;
-
- // Called on sentence change
- // SentenceIndex: index of the new active sentence
-procedure TScreenSing.OnSentenceChange(SentenceIndex: cardinal);
-var
- LyricEngine: TLyricEngine;
-begin
- //GoldenStarsTwinkle
- GoldenRec.SentenceChange;
-
- // Fill lyrics queue and set upper line to the current sentence
- while (Lyrics.GetUpperLineIndex() < SentenceIndex) or
- (not Lyrics.IsQueueFull) do
- begin
- // Add the next line to the queue or a dummy if no more lines are available
- if (Lyrics.LineCounter <= High(Lines[0].Line)) then
- Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter])
- else
- Lyrics.AddLine(nil);
- end;
-
- // AddLine draws the passed line to the back-buffer of the render context
- // and copies it into a texture afterwards (offscreen rendering).
- // This leaves an in invalidated screen. Calling Draw() makes sure,
- // that the back-buffer stores the sing-screen, when the next
- // swap between the back- and front-buffer is done (eliminates flickering)
- // <note> calling AddLine() right before the regular screen update (Display.Draw)
- // would be a better solution.</note>
- Draw;
-end;
-
-function TLyricsSyncSource.GetClock(): real;
-begin
- Result := LyricsState.GetCurrentTime();
-end;
-
-end.
-