aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authork-m_schindler <k-m_schindler@b956fd51-792f-4845-bead-9b4dfca2ff2c>2009-03-07 21:14:14 +0000
committerk-m_schindler <k-m_schindler@b956fd51-792f-4845-bead-9b4dfca2ff2c>2009-03-07 21:14:14 +0000
commitf469075a0335399c753ae5d2d362047dedf116b1 (patch)
treeac7a292610b13ab868361903c59d097922e4b1c8
parentb38fa5a07ab1f5604372176c8e84ddfb075133ee (diff)
downloadusdx-f469075a0335399c753ae5d2d362047dedf116b1.tar.gz
usdx-f469075a0335399c753ae5d2d362047dedf116b1.tar.xz
usdx-f469075a0335399c753ae5d2d362047dedf116b1.zip
final cleanup of Umain. Creation of UNote
git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@1627 b956fd51-792f-4845-bead-9b4dfca2ff2c
-rw-r--r--src/base/UDraw.pas20
-rw-r--r--src/base/UFiles.pas4
-rw-r--r--src/base/UGraphicClasses.pas14
-rw-r--r--src/base/UMain.pas527
-rw-r--r--src/base/UMusic.pas2
-rw-r--r--src/base/UNote.pas593
-rw-r--r--src/base/UParty.pas2
-rw-r--r--src/base/URecord.pas2
-rw-r--r--src/base/USong.pas2
-rw-r--r--src/base/USongs.pas2
-rw-r--r--src/screens/UScreenEditSub.pas2
-rw-r--r--src/screens/UScreenMain.pas2
-rw-r--r--src/screens/UScreenName.pas15
-rw-r--r--src/screens/UScreenScore.pas4
-rw-r--r--src/screens/UScreenSing.pas33
-rw-r--r--src/screens/UScreenSingModi.pas2
-rw-r--r--src/screens/UScreenSong.pas347
-rw-r--r--src/screens/UScreenTop5.pas96
-rw-r--r--src/ultrastardx.dpr1
19 files changed, 914 insertions, 756 deletions
diff --git a/src/base/UDraw.pas b/src/base/UDraw.pas
index 5de521cd..8a66d271 100644
--- a/src/base/UDraw.pas
+++ b/src/base/UDraw.pas
@@ -82,22 +82,22 @@ var
implementation
uses
+ SysUtils,
+ Math,
gl,
+ TextGL,
+ UDLLManager,
+ UDrawTexture,
UGraphic,
- SysUtils,
+ UIni,
+ ULog,
+ ULyrics,
+ UNote,
UMusic,
URecord,
- ULog,
UScreenSing,
UScreenSingModi,
- ULyrics,
- UMain,
- TextGL,
- UTexture,
- UDrawTexture,
- UIni,
- Math,
- UDLLManager;
+ UTexture;
procedure SingDrawBackground;
var
diff --git a/src/base/UFiles.pas b/src/base/UFiles.pas
index d639c304..0495dfbb 100644
--- a/src/base/UFiles.pas
+++ b/src/base/UFiles.pas
@@ -58,8 +58,8 @@ implementation
uses
TextGL,
UIni,
- UPlatform,
- UMain;
+ UNote,
+ UPlatform;
//--------------------
// Resets the temporary Sentence Arrays for each Player and some other Variables
diff --git a/src/base/UGraphicClasses.pas b/src/base/UGraphicClasses.pas
index 3fbe262f..cdaa238e 100644
--- a/src/base/UGraphicClasses.pas
+++ b/src/base/UGraphicClasses.pas
@@ -124,16 +124,16 @@ var
implementation
uses
- sysutils,
+ SysUtils,
+ Math,
gl,
+ UCommon,
+ UDrawTexture,
+ UGraphic,
UIni,
- UMain,
- UThemes,
+ UNote,
USkins,
- UGraphic,
- UDrawTexture,
- UCommon,
- math;
+ UThemes;
//TParticle
constructor TParticle.Create(cX, cY : real;
diff --git a/src/base/UMain.pas b/src/base/UMain.pas
index 7cd69c24..f7dc6ef3 100644
--- a/src/base/UMain.pas
+++ b/src/base/UMain.pas
@@ -48,71 +48,14 @@ uses
USong,
gl;
-type
- PPLayerNote = ^TPlayerNote;
- TPlayerNote = record
- Start: integer;
- Length: integer;
- Detect: real; // accurate place, detected in the note
- Tone: real;
- Perfect: boolean; // true if the note matches the original one, light the star
- Hit: boolean; // true if the note hits the line
- end;
-
- PPLayer = ^TPlayer;
- TPlayer = record
- Name: string;
-
- // Index in Teaminfo record
- TeamID: byte;
- PlayerID: byte;
-
- // Scores
- Score: real;
- ScoreLine: real;
- ScoreGolden: real;
-
- ScoreInt: integer;
- ScoreLineInt: integer;
- ScoreGoldenInt: integer;
- ScoreTotalInt: integer;
-
- // LineBonus
- ScoreLast: real; // Last Line Score
-
- // PerfectLineTwinkle (effect)
- LastSentencePerfect: boolean;
-
- HighNote: integer; // index of last note (= High(Note)?)
- LengthNote: integer; // number of notes (= Length(Note)?).
- Note: array of TPlayerNote;
- end;
-
var
- Done: boolean;
- Restart: boolean;
-
- // player and music info
- Player: array of TPlayer;
- PlayersPlay: integer;
-
- CurrentSong: TSong;
-
-const
- MAX_SONG_SCORE = 10000; // max. achievable points per song
- MAX_SONG_LINE_BONUS = 1000; // max. achievable line bonus per song
+ Done: boolean;
+ Restart: boolean;
procedure Main;
procedure MainLoop;
procedure CheckEvents;
-procedure Sing(Screen: TScreenSing);
-procedure NewSentence(Screen: TScreenSing);
-procedure NewBeatClick(Screen: TScreenSing); // executed when on then new beat for click
-procedure NewBeatDetect(Screen: TScreenSing); // executed when on then new beat for detection
-procedure NewNote(Screen: TScreenSing); // detect note
-function GetMidBeat(Time: real): real;
-function GetTimeFromBeat(Beat: integer): real;
type
TMainThreadExecProc = procedure(Data: Pointer);
@@ -417,7 +360,7 @@ begin
CheckEvents;
// display
- done := not Display.Draw;
+ Done := not Display.Draw;
SwapBuffers;
// delay
@@ -519,16 +462,16 @@ begin
// if there is a visible popup then let it handle input instead of underlying screen
// shoud be done in a way to be sure the topmost popup has preference (maybe error, then check)
else if (ScreenPopupError <> nil) and (ScreenPopupError.Visible) then
- done := not ScreenPopupError.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), true)
+ Done := not ScreenPopupError.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), true)
else if (ScreenPopupCheck <> nil) and (ScreenPopupCheck.Visible) then
- done := not ScreenPopupCheck.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), true)
+ Done := not ScreenPopupCheck.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), true)
else
begin
// check if screen wants to exit
- done := not Display.CurrentScreen^.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), true);
+ Done := not Display.CurrentScreen^.ParseInput(Event.key.keysym.sym, WideChar(Event.key.keysym.unicode), true);
// if screen wants to exit
- if done then
+ if Done then
begin
// if question option is enabled then show exit popup
if (Ini.AskbeforeDel = 1) then
@@ -576,460 +519,4 @@ begin
SDL_PushEvent(@Event);
end;
-function GetTimeForBeats(BPM, Beats: real): real;
-begin
- Result := 60 / BPM * Beats;
-end;
-
-function GetBeats(BPM, msTime: real): real;
-begin
- Result := BPM * msTime / 60;
-end;
-
-procedure GetMidBeatSub(BPMNum: integer; var Time: real; var CurBeat: real);
-var
- NewTime: real;
-begin
- if High(CurrentSong.BPM) = BPMNum then
- begin
- // last BPM
- CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
- Time := 0;
- end
- else
- begin
- // not last BPM
- // count how much time is it for start of the new BPM and store it in NewTime
- NewTime := GetTimeForBeats(CurrentSong.BPM[BPMNum].BPM, CurrentSong.BPM[BPMNum+1].StartBeat - CurrentSong.BPM[BPMNum].StartBeat);
-
- // compare it to remaining time
- if (Time - NewTime) > 0 then
- begin
- // there is still remaining time
- CurBeat := CurrentSong.BPM[BPMNum].StartBeat;
- Time := Time - NewTime;
- end
- else
- begin
- // there is no remaining time
- CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
- Time := 0;
- end; // if
- end; // if
-end;
-
-function GetMidBeat(Time: real): real;
-var
- CurBeat: real;
- CurBPM: integer;
-begin
- // static BPM
- if Length(CurrentSong.BPM) = 1 then
- begin
- Result := Time * CurrentSong.BPM[0].BPM / 60;
- end
- // variable BPM
- else if Length(CurrentSong.BPM) > 1 then
- begin
- CurBeat := 0;
- CurBPM := 0;
- while (Time > 0) do
- begin
- GetMidBeatSub(CurBPM, Time, CurBeat);
- Inc(CurBPM);
- end;
-
- Result := CurBeat;
- end
- // invalid BPM
- else
- begin
- Result := 0;
- end;
-end;
-
-function GetTimeFromBeat(Beat: integer): real;
-var
- CurBPM: integer;
-begin
- // static BPM
- if Length(CurrentSong.BPM) = 1 then
- begin
- Result := CurrentSong.GAP / 1000 + Beat * 60 / CurrentSong.BPM[0].BPM;
- end
- // variable BPM
- else if Length(CurrentSong.BPM) > 1 then
- begin
- Result := CurrentSong.GAP / 1000;
- CurBPM := 0;
- while (CurBPM <= High(CurrentSong.BPM)) and
- (Beat > CurrentSong.BPM[CurBPM].StartBeat) do
- begin
- if (CurBPM < High(CurrentSong.BPM)) and
- (Beat >= CurrentSong.BPM[CurBPM+1].StartBeat) then
- begin
- // full range
- Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
- (CurrentSong.BPM[CurBPM+1].StartBeat - CurrentSong.BPM[CurBPM].StartBeat);
- end;
-
- if (CurBPM = High(CurrentSong.BPM)) or
- (Beat < CurrentSong.BPM[CurBPM+1].StartBeat) then
- begin
- // in the middle
- Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
- (Beat - CurrentSong.BPM[CurBPM].StartBeat);
- end;
- Inc(CurBPM);
- end;
-
- {
- while (Time > 0) do
- begin
- GetMidBeatSub(CurBPM, Time, CurBeat);
- Inc(CurBPM);
- end;
- }
- end
- // invalid BPM
- else
- begin
- Result := 0;
- end;
-end;
-
-procedure Sing(Screen: TScreenSing);
-var
- Count: integer;
- CountGr: integer;
- CP: integer;
- N: integer;
-begin
- LyricsState.UpdateBeats();
-
- // sentences routines
- for CountGr := 0 to 0 do //High(Lines)
- begin;
- CP := CountGr;
- // old parts
- LyricsState.OldLine := Lines[CP].Current;
-
- // choose current parts
- for Count := 0 to Lines[CP].High do
- begin
- if LyricsState.CurrentBeat >= Lines[CP].Line[Count].Start then
- Lines[CP].Current := Count;
- end;
-
- // clean player note if there is a new line
- // (optimization on halfbeat time)
- if Lines[CP].Current <> LyricsState.OldLine then
- NewSentence(Screen);
-
- end; // for CountGr
-
- // make some operations on clicks
- if {(LyricsState.CurrentBeatC >= 0) and }(LyricsState.OldBeatC <> LyricsState.CurrentBeatC) then
- NewBeatClick(Screen);
-
- // make some operations when detecting new voice pitch
- if (LyricsState.CurrentBeatD >= 0) and (LyricsState.OldBeatD <> LyricsState.CurrentBeatD) then
- NewBeatDetect(Screen);
-end;
-
-procedure NewSentence(Screen: TScreenSing);
-var
- i: integer;
-begin
- // clean note of player
- for i := 0 to High(Player) do
- begin
- Player[i].LengthNote := 0;
- Player[i].HighNote := -1;
- SetLength(Player[i].Note, 0);
- end;
-
- // on sentence change...
- Screen.onSentenceChange(Lines[0].Current);
-end;
-
-procedure NewBeatClick;
-var
- Count: integer;
-begin
- // beat click
- if ((Ini.BeatClick = 1) and
- ((LyricsState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0)) then
- begin
- AudioPlayback.PlaySound(SoundLib.Click);
- end;
-
- for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
- begin
- if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LyricsState.CurrentBeatC) then
- begin
- // click assist
- if Ini.ClickAssist = 1 then
- AudioPlayback.PlaySound(SoundLib.Click);
-
- // drum machine
- (*
- TempBeat := LyricsState.CurrentBeat; // + 2;
- if (TempBeat mod 8 = 0) then Music.PlayDrum;
- if (TempBeat mod 8 = 4) then Music.PlayClap;
- //if (TempBeat mod 4 = 2) then Music.PlayHihat;
- if (TempBeat mod 4 <> 0) then Music.PlayHihat;
- *)
- end;
- end;
-end;
-
-procedure NewBeatDetect(Screen: TScreenSing);
-begin
- NewNote(Screen);
-end;
-
-procedure NewNote(Screen: TScreenSing);
-var
- LineFragmentIndex: integer;
- CurrentLineFragment: PLineFragment;
- PlayerIndex: integer;
- CurrentSound: TCaptureBuffer;
- CurrentPlayer: PPlayer;
- LastPlayerNote: PPlayerNote;
- Line: PLine;
- SentenceIndex: integer;
- SentenceMin: integer;
- SentenceMax: integer;
- SentenceDetected: integer; // sentence of detected note
- NoteAvailable: boolean;
- NewNote: boolean;
- Range: integer;
- NoteHit: boolean;
- MaxSongPoints: integer; // max. points for the song (without line bonus)
- CurNotePoints: real; // Points for the cur. Note (PointsperNote * ScoreFactor[CurNote])
-begin
- // TODO: add duet mode support
- // use Lines[LineSetIndex] with LineSetIndex depending on the current player
-
- // count min and max sentence range for checking
- // (detection is delayed to the notes we see on the screen)
- SentenceMin := Lines[0].Current-1;
- if (SentenceMin < 0) then
- SentenceMin := 0;
- SentenceMax := Lines[0].Current;
-
- // check for an active note at the current time defined in the lyrics
- NoteAvailable := false;
- SentenceDetected := SentenceMin;
- for SentenceIndex := SentenceMin to SentenceMax do
- begin
- Line := @Lines[0].Line[SentenceIndex];
- for LineFragmentIndex := 0 to Line.HighNote do
- begin
- CurrentLineFragment := @Line.Note[LineFragmentIndex];
- // check if line is active
- if ((CurrentLineFragment.Start <= LyricsState.CurrentBeatD) and
- (CurrentLineFragment.Start + CurrentLineFragment.Length-1 >= LyricsState.CurrentBeatD)) and
- (CurrentLineFragment.NoteType <> ntFreestyle) and // but ignore FreeStyle notes
- (CurrentLineFragment.Length > 0) then // and make sure the note length is at least 1
- begin
- SentenceDetected := SentenceIndex;
- NoteAvailable := true;
- Break;
- end;
- end;
- // TODO: break here, if NoteAvailable is true? We would then use the first instead
- // of the last note matching the current beat if notes overlap. But notes
- // should not overlap at all.
- // if (NoteAvailable) then
- // Break;
- end;
-
- // analyze player signals
- for PlayerIndex := 0 to PlayersPlay-1 do
- begin
- CurrentPlayer := @Player[PlayerIndex];
- CurrentSound := AudioInputProcessor.Sound[PlayerIndex];
-
- // at the beginning of the song there is no previous note
- if (Length(CurrentPlayer.Note) > 0) then
- LastPlayerNote := @CurrentPlayer.Note[CurrentPlayer.HighNote]
- else
- LastPlayerNote := nil;
-
- // analyze buffer
- CurrentSound.AnalyzeBuffer;
-
- // add some noise
- // TODO: do we need this?
- //LyricsState.Tone := LyricsState.Tone + Round(Random(3)) - 1;
-
- // add note if possible
- if (CurrentSound.ToneValid and NoteAvailable) then
- begin
- Line := @Lines[0].Line[SentenceDetected];
-
- // process until last note
- for LineFragmentIndex := 0 to Line.HighNote do
- begin
- CurrentLineFragment := @Line.Note[LineFragmentIndex];
- if (CurrentLineFragment.Start <= LyricsState.OldBeatD+1) and
- (CurrentLineFragment.Start + CurrentLineFragment.Length > LyricsState.OldBeatD+1) then
- begin
- // compare notes (from song-file and from player)
-
- // move players tone to proper octave
- while (CurrentSound.Tone - CurrentLineFragment.Tone > 6) do
- CurrentSound.Tone := CurrentSound.Tone - 12;
-
- while (CurrentSound.Tone - CurrentLineFragment.Tone < -6) do
- CurrentSound.Tone := CurrentSound.Tone + 12;
-
- // half size notes patch
- NoteHit := false;
-
- // if Ini.Difficulty = 0 then Range := 2;
- // if Ini.Difficulty = 1 then Range := 1;
- // if Ini.Difficulty = 2 then Range := 0;
- Range := 2 - Ini.Difficulty;
-
- // check if the player hit the correct tone within the tolerated range
- if (Abs(CurrentLineFragment.Tone - CurrentSound.Tone) <= Range) then
- begin
- // adjust the players tone to the correct one
- // TODO: do we need to do this?
- // Philipp: I think we do, at least when we draw the notes.
- // Otherwise the notehit thing would be shifted to the
- // correct unhit note. I think this will look kind of strange.
- CurrentSound.Tone := CurrentLineFragment.Tone;
-
- // half size notes patch
- NoteHit := true;
-
- if (Ini.LineBonus > 0) then
- MaxSongPoints := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS
- else
- MaxSongPoints := MAX_SONG_SCORE;
-
- // Note: ScoreValue is the sum of all note values of the song
- // (MaxSongPoints / ScoreValue) is the points that a player
- // gets for a hit of one beat of a normal note
- // CurNotePoints is the amount of points that is meassured
- // for a hit of the note per full beat
- CurNotePoints := (MaxSongPoints / Lines[0].ScoreValue) * ScoreFactor[CurrentLineFragment.NoteType];
-
- case CurrentLineFragment.NoteType of
- ntNormal: CurrentPlayer.Score := CurrentPlayer.Score + CurNotePoints;
- ntGolden: CurrentPlayer.ScoreGolden := CurrentPlayer.ScoreGolden + CurNotePoints;
- end;
-
- // a problem if we use floor instead of round is that a score of
- // 10000 points is only possible if the last digit of the total points
- // for golden and normal notes is 0.
- // if we use round, the max score is 10000 for most songs
- // but a score of 10010 is possible if the last digit of the total
- // points for golden and normal notes is 5
- // the best solution is to use round for one of these scores
- // and round the other score in the opposite direction
- // so we assure that the highest possible score is 10000 in every case.
- CurrentPlayer.ScoreInt := round(CurrentPlayer.Score / 10) * 10;
-
- if (CurrentPlayer.ScoreInt < CurrentPlayer.Score) then
- //normal score is floored so we have to ceil golden notes score
- CurrentPlayer.ScoreGoldenInt := ceil(CurrentPlayer.ScoreGolden / 10) * 10
- else
- //normal score is ceiled so we have to floor golden notes score
- CurrentPlayer.ScoreGoldenInt := floor(CurrentPlayer.ScoreGolden / 10) * 10;
-
-
- CurrentPlayer.ScoreTotalInt := CurrentPlayer.ScoreInt +
- CurrentPlayer.ScoreGoldenInt +
- CurrentPlayer.ScoreLineInt;
- end;
-
- end; // operation
- end; // for
-
- // check if we have to add a new note or extend the note's length
- if (SentenceDetected = SentenceMax) then
- begin
- // we will add a new note
- NewNote := true;
-
- // if previous note (if any) was the same, extend previous note
- if ((CurrentPlayer.LengthNote > 0) and
- (LastPlayerNote <> nil) and
- (LastPlayerNote.Tone = CurrentSound.Tone) and
- ((LastPlayerNote.Start + LastPlayerNote.Length) = LyricsState.CurrentBeatD)) then
- begin
- NewNote := false;
- end;
-
- // if is not as new note to control
- for LineFragmentIndex := 0 to Line.HighNote do
- begin
- if (Line.Note[LineFragmentIndex].Start = LyricsState.CurrentBeatD) then
- NewNote := true;
- end;
-
- // add new note
- if NewNote then
- begin
- // new note
- Inc(CurrentPlayer.LengthNote);
- Inc(CurrentPlayer.HighNote);
- SetLength(CurrentPlayer.Note, CurrentPlayer.LengthNote);
-
- // update player's last note
- LastPlayerNote := @CurrentPlayer.Note[CurrentPlayer.HighNote];
- with LastPlayerNote^ do
- begin
- Start := LyricsState.CurrentBeatD;
- Length := 1;
- Tone := CurrentSound.Tone; // Tone || ToneAbs
- Detect := LyricsState.MidBeat;
- Hit := NoteHit; // half note patch
- end;
- end
- else
- begin
- // extend note length
- if (LastPlayerNote <> nil) then
- Inc(LastPlayerNote.Length);
- end;
-
- // check for perfect note and then light the star (on Draw)
- for LineFragmentIndex := 0 to Line.HighNote do
- begin
- CurrentLineFragment := @Line.Note[LineFragmentIndex];
- if (CurrentLineFragment.Start = LastPlayerNote.Start) and
- (CurrentLineFragment.Length = LastPlayerNote.Length) and
- (CurrentLineFragment.Tone = LastPlayerNote.Tone) then
- begin
- LastPlayerNote.Perfect := true;
- end;
- end;
- end; // if SentenceDetected = SentenceMax
-
- end; // if Detected
- end; // for PlayerIndex
-
- //Log.LogStatus('EndBeat', 'NewBeat');
-
- // on sentence end -> for LineBonus and display of SingBar (rating pop-up)
- if (SentenceDetected >= Low(Lines[0].Line)) and
- (SentenceDetected <= High(Lines[0].Line)) then
- begin
- Line := @Lines[0].Line[SentenceDetected];
- CurrentLineFragment := @Line.Note[Line.HighNote];
- if ((CurrentLineFragment.Start + CurrentLineFragment.Length - 1) = LyricsState.CurrentBeatD) then
- begin
- if assigned(Screen) then
- Screen.OnSentenceEnd(SentenceDetected);
- end;
- end;
-
-end;
-
end.
diff --git a/src/base/UMusic.pas b/src/base/UMusic.pas
index 727088c8..b86f3aad 100644
--- a/src/base/UMusic.pas
+++ b/src/base/UMusic.pas
@@ -573,7 +573,7 @@ implementation
uses
math,
UIni,
- UMain,
+ UNote,
UCommandLine,
URecord,
ULog,
diff --git a/src/base/UNote.pas b/src/base/UNote.pas
new file mode 100644
index 00000000..5e70bfe1
--- /dev/null
+++ b/src/base/UNote.pas
@@ -0,0 +1,593 @@
+{* UltraStar Deluxe - Karaoke Game
+ *
+ * UltraStar Deluxe is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://ultrastardx.svn.sourceforge.net/svnroot/ultrastardx/trunk/src/base/UNote.pas $
+ * $Id: UNote.pas 1626 2009-03-07 19:53:00Z k-m_schindler $
+ *}
+
+unit UNote;
+
+interface
+
+{$IFDEF FPC}
+ {$MODE Delphi}
+{$ENDIF}
+
+{$I switches.inc}
+
+uses
+ SysUtils,
+ Classes,
+ SDL,
+ UMusic,
+ URecord,
+ UTime,
+ UDisplay,
+ UIni,
+ ULog,
+ ULyrics,
+ UScreenSing,
+ USong,
+ gl;
+
+type
+ PPLayerNote = ^TPlayerNote;
+ TPlayerNote = record
+ Start: integer;
+ Length: integer;
+ Detect: real; // accurate place, detected in the note
+ Tone: real;
+ Perfect: boolean; // true if the note matches the original one, light the star
+ Hit: boolean; // true if the note hits the line
+ end;
+
+ PPLayer = ^TPlayer;
+ TPlayer = record
+ Name: string;
+
+ // Index in Teaminfo record
+ TeamID: byte;
+ PlayerID: byte;
+
+ // Scores
+ Score: real;
+ ScoreLine: real;
+ ScoreGolden: real;
+
+ ScoreInt: integer;
+ ScoreLineInt: integer;
+ ScoreGoldenInt: integer;
+ ScoreTotalInt: integer;
+
+ // LineBonus
+ ScoreLast: real; // Last Line Score
+
+ // PerfectLineTwinkle (effect)
+ LastSentencePerfect: boolean;
+
+ HighNote: integer; // index of last note (= High(Note)?)
+ LengthNote: integer; // number of notes (= Length(Note)?).
+ Note: array of TPlayerNote;
+ end;
+
+var
+
+ // player and music info
+ Player: array of TPlayer;
+ PlayersPlay: integer;
+
+ CurrentSong: TSong;
+
+const
+ MAX_SONG_SCORE = 10000; // max. achievable points per song
+ MAX_SONG_LINE_BONUS = 1000; // max. achievable line bonus per song
+
+procedure Sing(Screen: TScreenSing);
+procedure NewSentence(Screen: TScreenSing);
+procedure NewBeatClick(Screen: TScreenSing); // executed when on then new beat for click
+procedure NewBeatDetect(Screen: TScreenSing); // executed when on then new beat for detection
+procedure NewNote(Screen: TScreenSing); // detect note
+function GetMidBeat(Time: real): real;
+function GetTimeFromBeat(Beat: integer): real;
+
+implementation
+
+uses
+ Math,
+ StrUtils,
+ USongs,
+ UJoystick,
+ UCommandLine,
+ ULanguage,
+ //SDL_ttf,
+ USkins,
+ UCovers,
+ UCatCovers,
+ UDataBase,
+ UPlaylist,
+ UDLLManager,
+ UParty,
+ UConfig,
+ UCore,
+ UCommon,
+ UGraphic,
+ UGraphicClasses,
+ UPath,
+ UPluginDefs,
+ UPlatform,
+ UThemes;
+
+function GetTimeForBeats(BPM, Beats: real): real;
+begin
+ Result := 60 / BPM * Beats;
+end;
+
+function GetBeats(BPM, msTime: real): real;
+begin
+ Result := BPM * msTime / 60;
+end;
+
+procedure GetMidBeatSub(BPMNum: integer; var Time: real; var CurBeat: real);
+var
+ NewTime: real;
+begin
+ if High(CurrentSong.BPM) = BPMNum then
+ begin
+ // last BPM
+ CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
+ Time := 0;
+ end
+ else
+ begin
+ // not last BPM
+ // count how much time is it for start of the new BPM and store it in NewTime
+ NewTime := GetTimeForBeats(CurrentSong.BPM[BPMNum].BPM, CurrentSong.BPM[BPMNum+1].StartBeat - CurrentSong.BPM[BPMNum].StartBeat);
+
+ // compare it to remaining time
+ if (Time - NewTime) > 0 then
+ begin
+ // there is still remaining time
+ CurBeat := CurrentSong.BPM[BPMNum].StartBeat;
+ Time := Time - NewTime;
+ end
+ else
+ begin
+ // there is no remaining time
+ CurBeat := CurrentSong.BPM[BPMNum].StartBeat + GetBeats(CurrentSong.BPM[BPMNum].BPM, Time);
+ Time := 0;
+ end; // if
+ end; // if
+end;
+
+function GetMidBeat(Time: real): real;
+var
+ CurBeat: real;
+ CurBPM: integer;
+begin
+ // static BPM
+ if Length(CurrentSong.BPM) = 1 then
+ begin
+ Result := Time * CurrentSong.BPM[0].BPM / 60;
+ end
+ // variable BPM
+ else if Length(CurrentSong.BPM) > 1 then
+ begin
+ CurBeat := 0;
+ CurBPM := 0;
+ while (Time > 0) do
+ begin
+ GetMidBeatSub(CurBPM, Time, CurBeat);
+ Inc(CurBPM);
+ end;
+
+ Result := CurBeat;
+ end
+ // invalid BPM
+ else
+ begin
+ Result := 0;
+ end;
+end;
+
+function GetTimeFromBeat(Beat: integer): real;
+var
+ CurBPM: integer;
+begin
+ // static BPM
+ if Length(CurrentSong.BPM) = 1 then
+ begin
+ Result := CurrentSong.GAP / 1000 + Beat * 60 / CurrentSong.BPM[0].BPM;
+ end
+ // variable BPM
+ else if Length(CurrentSong.BPM) > 1 then
+ begin
+ Result := CurrentSong.GAP / 1000;
+ CurBPM := 0;
+ while (CurBPM <= High(CurrentSong.BPM)) and
+ (Beat > CurrentSong.BPM[CurBPM].StartBeat) do
+ begin
+ if (CurBPM < High(CurrentSong.BPM)) and
+ (Beat >= CurrentSong.BPM[CurBPM+1].StartBeat) then
+ begin
+ // full range
+ Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
+ (CurrentSong.BPM[CurBPM+1].StartBeat - CurrentSong.BPM[CurBPM].StartBeat);
+ end;
+
+ if (CurBPM = High(CurrentSong.BPM)) or
+ (Beat < CurrentSong.BPM[CurBPM+1].StartBeat) then
+ begin
+ // in the middle
+ Result := Result + (60 / CurrentSong.BPM[CurBPM].BPM) *
+ (Beat - CurrentSong.BPM[CurBPM].StartBeat);
+ end;
+ Inc(CurBPM);
+ end;
+
+ {
+ while (Time > 0) do
+ begin
+ GetMidBeatSub(CurBPM, Time, CurBeat);
+ Inc(CurBPM);
+ end;
+ }
+ end
+ // invalid BPM
+ else
+ begin
+ Result := 0;
+ end;
+end;
+
+procedure Sing(Screen: TScreenSing);
+var
+ Count: integer;
+ CountGr: integer;
+ CP: integer;
+begin
+ LyricsState.UpdateBeats();
+
+ // sentences routines
+ for CountGr := 0 to 0 do //High(Lines)
+ begin;
+ CP := CountGr;
+ // old parts
+ LyricsState.OldLine := Lines[CP].Current;
+
+ // choose current parts
+ for Count := 0 to Lines[CP].High do
+ begin
+ if LyricsState.CurrentBeat >= Lines[CP].Line[Count].Start then
+ Lines[CP].Current := Count;
+ end;
+
+ // clean player note if there is a new line
+ // (optimization on halfbeat time)
+ if Lines[CP].Current <> LyricsState.OldLine then
+ NewSentence(Screen);
+
+ end; // for CountGr
+
+ // make some operations on clicks
+ if {(LyricsState.CurrentBeatC >= 0) and }(LyricsState.OldBeatC <> LyricsState.CurrentBeatC) then
+ NewBeatClick(Screen);
+
+ // make some operations when detecting new voice pitch
+ if (LyricsState.CurrentBeatD >= 0) and (LyricsState.OldBeatD <> LyricsState.CurrentBeatD) then
+ NewBeatDetect(Screen);
+end;
+
+procedure NewSentence(Screen: TScreenSing);
+var
+ i: integer;
+begin
+ // clean note of player
+ for i := 0 to High(Player) do
+ begin
+ Player[i].LengthNote := 0;
+ Player[i].HighNote := -1;
+ SetLength(Player[i].Note, 0);
+ end;
+
+ // on sentence change...
+ Screen.onSentenceChange(Lines[0].Current);
+end;
+
+procedure NewBeatClick;
+var
+ Count: integer;
+begin
+ // beat click
+ if ((Ini.BeatClick = 1) and
+ ((LyricsState.CurrentBeatC + Lines[0].Resolution + Lines[0].NotesGAP) mod Lines[0].Resolution = 0)) then
+ begin
+ AudioPlayback.PlaySound(SoundLib.Click);
+ end;
+
+ for Count := 0 to Lines[0].Line[Lines[0].Current].HighNote do
+ begin
+ if (Lines[0].Line[Lines[0].Current].Note[Count].Start = LyricsState.CurrentBeatC) then
+ begin
+ // click assist
+ if Ini.ClickAssist = 1 then
+ AudioPlayback.PlaySound(SoundLib.Click);
+
+ // drum machine
+ (*
+ TempBeat := LyricsState.CurrentBeat; // + 2;
+ if (TempBeat mod 8 = 0) then Music.PlayDrum;
+ if (TempBeat mod 8 = 4) then Music.PlayClap;
+ //if (TempBeat mod 4 = 2) then Music.PlayHihat;
+ if (TempBeat mod 4 <> 0) then Music.PlayHihat;
+ *)
+ end;
+ end;
+end;
+
+procedure NewBeatDetect(Screen: TScreenSing);
+begin
+ NewNote(Screen);
+end;
+
+procedure NewNote(Screen: TScreenSing);
+var
+ LineFragmentIndex: integer;
+ CurrentLineFragment: PLineFragment;
+ PlayerIndex: integer;
+ CurrentSound: TCaptureBuffer;
+ CurrentPlayer: PPlayer;
+ LastPlayerNote: PPlayerNote;
+ Line: PLine;
+ SentenceIndex: integer;
+ SentenceMin: integer;
+ SentenceMax: integer;
+ SentenceDetected: integer; // sentence of detected note
+ NoteAvailable: boolean;
+ NewNote: boolean;
+ Range: integer;
+ NoteHit: boolean;
+ MaxSongPoints: integer; // max. points for the song (without line bonus)
+ CurNotePoints: real; // Points for the cur. Note (PointsperNote * ScoreFactor[CurNote])
+begin
+ // TODO: add duet mode support
+ // use Lines[LineSetIndex] with LineSetIndex depending on the current player
+
+ // count min and max sentence range for checking
+ // (detection is delayed to the notes we see on the screen)
+ SentenceMin := Lines[0].Current-1;
+ if (SentenceMin < 0) then
+ SentenceMin := 0;
+ SentenceMax := Lines[0].Current;
+
+ // check for an active note at the current time defined in the lyrics
+ NoteAvailable := false;
+ SentenceDetected := SentenceMin;
+ for SentenceIndex := SentenceMin to SentenceMax do
+ begin
+ Line := @Lines[0].Line[SentenceIndex];
+ for LineFragmentIndex := 0 to Line.HighNote do
+ begin
+ CurrentLineFragment := @Line.Note[LineFragmentIndex];
+ // check if line is active
+ if ((CurrentLineFragment.Start <= LyricsState.CurrentBeatD) and
+ (CurrentLineFragment.Start + CurrentLineFragment.Length-1 >= LyricsState.CurrentBeatD)) and
+ (CurrentLineFragment.NoteType <> ntFreestyle) and // but ignore FreeStyle notes
+ (CurrentLineFragment.Length > 0) then // and make sure the note length is at least 1
+ begin
+ SentenceDetected := SentenceIndex;
+ NoteAvailable := true;
+ Break;
+ end;
+ end;
+ // TODO: break here, if NoteAvailable is true? We would then use the first instead
+ // of the last note matching the current beat if notes overlap. But notes
+ // should not overlap at all.
+ // if (NoteAvailable) then
+ // Break;
+ end;
+
+ // analyze player signals
+ for PlayerIndex := 0 to PlayersPlay-1 do
+ begin
+ CurrentPlayer := @Player[PlayerIndex];
+ CurrentSound := AudioInputProcessor.Sound[PlayerIndex];
+
+ // at the beginning of the song there is no previous note
+ if (Length(CurrentPlayer.Note) > 0) then
+ LastPlayerNote := @CurrentPlayer.Note[CurrentPlayer.HighNote]
+ else
+ LastPlayerNote := nil;
+
+ // analyze buffer
+ CurrentSound.AnalyzeBuffer;
+
+ // add some noise
+ // TODO: do we need this?
+ //LyricsState.Tone := LyricsState.Tone + Round(Random(3)) - 1;
+
+ // add note if possible
+ if (CurrentSound.ToneValid and NoteAvailable) then
+ begin
+ Line := @Lines[0].Line[SentenceDetected];
+
+ // process until last note
+ for LineFragmentIndex := 0 to Line.HighNote do
+ begin
+ CurrentLineFragment := @Line.Note[LineFragmentIndex];
+ if (CurrentLineFragment.Start <= LyricsState.OldBeatD+1) and
+ (CurrentLineFragment.Start + CurrentLineFragment.Length > LyricsState.OldBeatD+1) then
+ begin
+ // compare notes (from song-file and from player)
+
+ // move players tone to proper octave
+ while (CurrentSound.Tone - CurrentLineFragment.Tone > 6) do
+ CurrentSound.Tone := CurrentSound.Tone - 12;
+
+ while (CurrentSound.Tone - CurrentLineFragment.Tone < -6) do
+ CurrentSound.Tone := CurrentSound.Tone + 12;
+
+ // half size notes patch
+ NoteHit := false;
+
+ // if Ini.Difficulty = 0 then Range := 2;
+ // if Ini.Difficulty = 1 then Range := 1;
+ // if Ini.Difficulty = 2 then Range := 0;
+ Range := 2 - Ini.Difficulty;
+
+ // check if the player hit the correct tone within the tolerated range
+ if (Abs(CurrentLineFragment.Tone - CurrentSound.Tone) <= Range) then
+ begin
+ // adjust the players tone to the correct one
+ // TODO: do we need to do this?
+ // Philipp: I think we do, at least when we draw the notes.
+ // Otherwise the notehit thing would be shifted to the
+ // correct unhit note. I think this will look kind of strange.
+ CurrentSound.Tone := CurrentLineFragment.Tone;
+
+ // half size notes patch
+ NoteHit := true;
+
+ if (Ini.LineBonus > 0) then
+ MaxSongPoints := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS
+ else
+ MaxSongPoints := MAX_SONG_SCORE;
+
+ // Note: ScoreValue is the sum of all note values of the song
+ // (MaxSongPoints / ScoreValue) is the points that a player
+ // gets for a hit of one beat of a normal note
+ // CurNotePoints is the amount of points that is meassured
+ // for a hit of the note per full beat
+ CurNotePoints := (MaxSongPoints / Lines[0].ScoreValue) * ScoreFactor[CurrentLineFragment.NoteType];
+
+ case CurrentLineFragment.NoteType of
+ ntNormal: CurrentPlayer.Score := CurrentPlayer.Score + CurNotePoints;
+ ntGolden: CurrentPlayer.ScoreGolden := CurrentPlayer.ScoreGolden + CurNotePoints;
+ end;
+
+ // a problem if we use floor instead of round is that a score of
+ // 10000 points is only possible if the last digit of the total points
+ // for golden and normal notes is 0.
+ // if we use round, the max score is 10000 for most songs
+ // but a score of 10010 is possible if the last digit of the total
+ // points for golden and normal notes is 5
+ // the best solution is to use round for one of these scores
+ // and round the other score in the opposite direction
+ // so we assure that the highest possible score is 10000 in every case.
+ CurrentPlayer.ScoreInt := round(CurrentPlayer.Score / 10) * 10;
+
+ if (CurrentPlayer.ScoreInt < CurrentPlayer.Score) then
+ //normal score is floored so we have to ceil golden notes score
+ CurrentPlayer.ScoreGoldenInt := ceil(CurrentPlayer.ScoreGolden / 10) * 10
+ else
+ //normal score is ceiled so we have to floor golden notes score
+ CurrentPlayer.ScoreGoldenInt := floor(CurrentPlayer.ScoreGolden / 10) * 10;
+
+
+ CurrentPlayer.ScoreTotalInt := CurrentPlayer.ScoreInt +
+ CurrentPlayer.ScoreGoldenInt +
+ CurrentPlayer.ScoreLineInt;
+ end;
+
+ end; // operation
+ end; // for
+
+ // check if we have to add a new note or extend the note's length
+ if (SentenceDetected = SentenceMax) then
+ begin
+ // we will add a new note
+ NewNote := true;
+
+ // if previous note (if any) was the same, extend previous note
+ if ((CurrentPlayer.LengthNote > 0) and
+ (LastPlayerNote <> nil) and
+ (LastPlayerNote.Tone = CurrentSound.Tone) and
+ ((LastPlayerNote.Start + LastPlayerNote.Length) = LyricsState.CurrentBeatD)) then
+ begin
+ NewNote := false;
+ end;
+
+ // if is not as new note to control
+ for LineFragmentIndex := 0 to Line.HighNote do
+ begin
+ if (Line.Note[LineFragmentIndex].Start = LyricsState.CurrentBeatD) then
+ NewNote := true;
+ end;
+
+ // add new note
+ if NewNote then
+ begin
+ // new note
+ Inc(CurrentPlayer.LengthNote);
+ Inc(CurrentPlayer.HighNote);
+ SetLength(CurrentPlayer.Note, CurrentPlayer.LengthNote);
+
+ // update player's last note
+ LastPlayerNote := @CurrentPlayer.Note[CurrentPlayer.HighNote];
+ with LastPlayerNote^ do
+ begin
+ Start := LyricsState.CurrentBeatD;
+ Length := 1;
+ Tone := CurrentSound.Tone; // Tone || ToneAbs
+ Detect := LyricsState.MidBeat;
+ Hit := NoteHit; // half note patch
+ end;
+ end
+ else
+ begin
+ // extend note length
+ if (LastPlayerNote <> nil) then
+ Inc(LastPlayerNote.Length);
+ end;
+
+ // check for perfect note and then light the star (on Draw)
+ for LineFragmentIndex := 0 to Line.HighNote do
+ begin
+ CurrentLineFragment := @Line.Note[LineFragmentIndex];
+ if (CurrentLineFragment.Start = LastPlayerNote.Start) and
+ (CurrentLineFragment.Length = LastPlayerNote.Length) and
+ (CurrentLineFragment.Tone = LastPlayerNote.Tone) then
+ begin
+ LastPlayerNote.Perfect := true;
+ end;
+ end;
+ end; // if SentenceDetected = SentenceMax
+
+ end; // if Detected
+ end; // for PlayerIndex
+
+ //Log.LogStatus('EndBeat', 'NewBeat');
+
+ // on sentence end -> for LineBonus and display of SingBar (rating pop-up)
+ if (SentenceDetected >= Low(Lines[0].Line)) and
+ (SentenceDetected <= High(Lines[0].Line)) then
+ begin
+ Line := @Lines[0].Line[SentenceDetected];
+ CurrentLineFragment := @Line.Note[Line.HighNote];
+ if ((CurrentLineFragment.Start + CurrentLineFragment.Length - 1) = LyricsState.CurrentBeatD) then
+ begin
+ if assigned(Screen) then
+ Screen.OnSentenceEnd(SentenceDetected);
+ end;
+ end;
+
+end;
+
+end.
diff --git a/src/base/UParty.pas b/src/base/UParty.pas
index 18d15745..23012dfe 100644
--- a/src/base/UParty.pas
+++ b/src/base/UParty.pas
@@ -111,9 +111,9 @@ implementation
uses
UCore,
UGraphic,
- UMain,
ULanguage,
ULog,
+ UNote,
SysUtils;
{*********************
diff --git a/src/base/URecord.pas b/src/base/URecord.pas
index ec6935bd..8f37262d 100644
--- a/src/base/URecord.pas
+++ b/src/base/URecord.pas
@@ -162,7 +162,7 @@ implementation
uses
ULog,
- UMain;
+ UNote;
var
singleton_AudioInputProcessor : TAudioInputProcessor = nil;
diff --git a/src/base/USong.pas b/src/base/USong.pas
index 4dd6be0f..1197f3be 100644
--- a/src/base/USong.pas
+++ b/src/base/USong.pas
@@ -149,7 +149,7 @@ uses
TextGL,
UIni,
UMusic, //needed for Lines
- UMain; //needed for Player
+ UNote; //needed for Player
constructor TSong.Create();
begin
diff --git a/src/base/USongs.pas b/src/base/USongs.pas
index 79e1eb59..6c356d06 100644
--- a/src/base/USongs.pas
+++ b/src/base/USongs.pas
@@ -158,7 +158,7 @@ uses
UGraphic,
UIni,
UPath,
- UMain;
+ UNote;
constructor TSongs.Create();
begin
diff --git a/src/screens/UScreenEditSub.pas b/src/screens/UScreenEditSub.pas
index d30781fe..bdf85028 100644
--- a/src/screens/UScreenEditSub.pas
+++ b/src/screens/UScreenEditSub.pas
@@ -128,7 +128,7 @@ implementation
uses
UGraphic,
UDraw,
- UMain,
+ UNote,
USkins,
ULanguage;
diff --git a/src/screens/UScreenMain.pas b/src/screens/UScreenMain.pas
index 2a2d0613..4980021e 100644
--- a/src/screens/UScreenMain.pas
+++ b/src/screens/UScreenMain.pas
@@ -63,7 +63,7 @@ implementation
uses
UGraphic,
- UMain,
+ UNote,
UIni,
UTexture,
USongs,
diff --git a/src/screens/UScreenName.pas b/src/screens/UScreenName.pas
index dd11b882..055f644e 100644
--- a/src/screens/UScreenName.pas
+++ b/src/screens/UScreenName.pas
@@ -34,7 +34,13 @@ interface
{$I switches.inc}
uses
- UMenu, SDL, UDisplay, UMusic, UFiles, SysUtils, UThemes;
+ SysUtils,
+ SDL,
+ UDisplay,
+ UFiles,
+ UMenu,
+ UMusic,
+ UThemes;
type
TScreenName = class(TMenu)
@@ -48,7 +54,12 @@ type
implementation
-uses UGraphic, UMain, UIni, UTexture, UCommon;
+uses
+ UCommon,
+ UGraphic,
+ UIni,
+ UNote,
+ UTexture;
function TScreenName.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean;
diff --git a/src/screens/UScreenScore.pas b/src/screens/UScreenScore.pas
index 6e6d77c7..f3f888b3 100644
--- a/src/screens/UScreenScore.pas
+++ b/src/screens/UScreenScore.pas
@@ -154,10 +154,10 @@ uses
UScreenSong,
UMenuStatic,
UTime,
- UMain,
UIni,
ULog,
- ULanguage;
+ ULanguage,
+ UNote;
function TScreenScore.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
begin
diff --git a/src/screens/UScreenSing.pas b/src/screens/UScreenSing.pas
index f232bdc1..fcf448a9 100644
--- a/src/screens/UScreenSing.pas
+++ b/src/screens/UScreenSing.pas
@@ -33,22 +33,23 @@ interface
{$I switches.inc}
-uses UMenu,
- UMusic,
- SDL,
+uses
SysUtils,
+ gl,
+ SDL,
+ TextGL,
UFiles,
- UTime,
- USongs,
+ UGraphicClasses,
UIni,
ULog,
- UTexture,
ULyrics,
- TextGL,
- gl,
+ UMenu,
+ UMusic,
+ USingScores,
+ USongs,
+ UTexture,
UThemes,
- UGraphicClasses,
- USingScores;
+ UTime;
type
TLyricsSyncSource = class(TSyncSource)
@@ -119,14 +120,14 @@ type
implementation
uses
- UGraphic,
- UDraw,
- UMain,
- USong,
Classes,
- URecord,
+ Math,
+ UDraw,
+ UGraphic,
ULanguage,
- Math;
+ UNote,
+ URecord,
+ USong;
// method for input parsing. if false is returned, getnextwindow
// should be checked to know the next window to load;
diff --git a/src/screens/UScreenSingModi.pas b/src/screens/UScreenSingModi.pas
index 9c48104e..4ead8e55 100644
--- a/src/screens/UScreenSingModi.pas
+++ b/src/screens/UScreenSingModi.pas
@@ -128,7 +128,7 @@ uses
UGraphic,
UGraphicClasses,
ULanguage,
- UMain,
+ UNote,
UPath,
URecord,
USkins;
diff --git a/src/screens/UScreenSong.pas b/src/screens/UScreenSong.pas
index 28358353..8aa5acca 100644
--- a/src/screens/UScreenSong.pas
+++ b/src/screens/UScreenSong.pas
@@ -65,7 +65,7 @@ type
TextNumber: integer;
//Video Icon Mod
- VideoIcon: Cardinal;
+ VideoIcon: cardinal;
TextCat: integer;
StaticCat: integer;
@@ -88,28 +88,28 @@ type
Mode: TSingMode;
//party Statics (Joker)
- StaticTeam1Joker1: Cardinal;
- StaticTeam1Joker2: Cardinal;
- StaticTeam1Joker3: Cardinal;
- StaticTeam1Joker4: Cardinal;
- StaticTeam1Joker5: Cardinal;
-
- StaticTeam2Joker1: Cardinal;
- StaticTeam2Joker2: Cardinal;
- StaticTeam2Joker3: Cardinal;
- StaticTeam2Joker4: Cardinal;
- StaticTeam2Joker5: Cardinal;
-
- StaticTeam3Joker1: Cardinal;
- StaticTeam3Joker2: Cardinal;
- StaticTeam3Joker3: Cardinal;
- StaticTeam3Joker4: Cardinal;
- StaticTeam3Joker5: Cardinal;
-
- StaticParty: array of Cardinal;
- TextParty: array of Cardinal;
- StaticNonParty: array of Cardinal;
- TextNonParty: array of Cardinal;
+ StaticTeam1Joker1: cardinal;
+ StaticTeam1Joker2: cardinal;
+ StaticTeam1Joker3: cardinal;
+ StaticTeam1Joker4: cardinal;
+ StaticTeam1Joker5: cardinal;
+
+ StaticTeam2Joker1: cardinal;
+ StaticTeam2Joker2: cardinal;
+ StaticTeam2Joker3: cardinal;
+ StaticTeam2Joker4: cardinal;
+ StaticTeam2Joker5: cardinal;
+
+ StaticTeam3Joker1: cardinal;
+ StaticTeam3Joker2: cardinal;
+ StaticTeam3Joker3: cardinal;
+ StaticTeam3Joker4: cardinal;
+ StaticTeam3Joker5: cardinal;
+
+ StaticParty: array of cardinal;
+ TextParty: array of cardinal;
+ StaticNonParty: array of cardinal;
+ TextNonParty: array of cardinal;
constructor Create; override;
@@ -120,18 +120,18 @@ type
procedure SetScroll4;
procedure SetScroll5;
procedure SetScroll6;
- function ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; override;
+ function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
function Draw: boolean; override;
procedure GenerateThumbnails();
procedure onShow; override;
procedure onHide; override;
procedure SelectNext;
procedure SelectPrev;
- procedure SkipTo(Target: Cardinal);
+ procedure SkipTo(Target: cardinal);
procedure FixSelected; //Show Wrong Song when Tabs on Fix
procedure FixSelected2; //Show Wrong Song when Tabs on Fix
- procedure ShowCatTL(Cat: Integer);// Show Cat in Top left
- procedure ShowCatTLCustom(Caption: String);// Show Custom Text in Top left
+ procedure ShowCatTL(Cat: integer);// Show Cat in Top left
+ procedure ShowCatTLCustom(Caption: string);// Show Custom Text in Top left
procedure HideCatTL;// Show Cat in Tob left
procedure Refresh; //Refresh Song Sorting
procedure ChangeMusic;
@@ -154,23 +154,25 @@ type
implementation
uses
- UGraphic,
- UMain,
- UCovers,
- math,
+ Math,
gl,
- USkins,
+ UCovers,
UDLLManager,
+ UGraphic,
+ UMain,
+ UMenuButton,
+ UNote,
UParty,
UPlaylist,
- UMenuButton,
- UScreenSongMenu;
+ UScreenSongMenu,
+ USkins;
// ***** Public methods ****** //
//Show Wrong Song when Tabs on Fix
procedure TScreenSong.FixSelected;
-var I, I2: Integer;
+var
+ I, I2: integer;
begin
if CatSongs.VisibleSongs > 0 then
begin
@@ -190,7 +192,8 @@ begin
end;
procedure TScreenSong.FixSelected2;
-var I, I2: Integer;
+var
+ I, I2: integer;
begin
if CatSongs.VisibleSongs > 0 then
begin
@@ -209,15 +212,15 @@ begin
end;
//Show Wrong Song when Tabs on Fix End
-procedure TScreenSong.ShowCatTLCustom(Caption: String);// Show Custom Text in Top left
+procedure TScreenSong.ShowCatTLCustom(Caption: string);// Show Custom Text in Top left
begin
Text[TextCat].Text := Caption;
Text[TextCat].Visible := true;
- Static[StaticCat].Visible := False;
+ Static[StaticCat].Visible := false;
end;
//Show Cat in Top Left Mod
-procedure TScreenSong.ShowCatTL(Cat: Integer);
+procedure TScreenSong.ShowCatTL(Cat: integer);
begin
//Change
Text[TextCat].Text := CatSongs.Song[Cat].Artist;
@@ -225,7 +228,7 @@ begin
//Show
Text[TextCat].Visible := true;
- Static[StaticCat].Visible := True;
+ Static[StaticCat].Visible := true;
end;
procedure TScreenSong.HideCatTL;
@@ -234,7 +237,7 @@ begin
//Text[TextCat].Visible := false;
Static[StaticCat].Visible := false;
//New -> Show Text specified in Theme
- Text[TextCat].Visible := True;
+ Text[TextCat].Visible := true;
Text[TextCat].Text := Theme.Song.TextCat.Text;
end;
//Show Cat in Top Left Mod End
@@ -242,7 +245,7 @@ end;
// Method for input parsing. If False is returned, GetNextWindow
// should be checked to know the next window to load;
-function TScreenSong.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean;
+function TScreenSong.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
var
I: integer;
I2: integer;
@@ -379,7 +382,7 @@ begin
begin
if (Songs.SongList.Count > 0) and (Mode = smNormal) then
begin
- ScreenSongJumpto.Visible := True;
+ ScreenSongJumpto.Visible := true;
end;
Exit;
end;
@@ -451,7 +454,8 @@ begin
SelectNext;
//Fix: Not Existing Song selected:
- //if (I+1=I2) then Inc(I2);
+ //if (I+1=I2) then
+ Inc(I2);
//Choose Song
SkipTo(I2-I);
@@ -505,7 +509,7 @@ begin
SelectNext;
FixSelected;
//SelectPrev;
- //CatSongs.Song[0].Visible := False;
+ //CatSongs.Song[0].Visible := false;
end
else
begin
@@ -605,7 +609,8 @@ begin
if Ini.TabsAtStartup = 1 then
begin
I := Interaction;
- if I <= 0 then I := 1;
+ if I <= 0 then
+ I := 1;
while not catsongs.Song[I].Main do
begin
@@ -646,7 +651,8 @@ begin
begin
I := Interaction;
I2 := 0;
- if I <= 0 then I := 1;
+ if I <= 0 then
+ I := 1;
while not catsongs.Song[I].Main or (I2 = 0) do
begin
@@ -808,7 +814,7 @@ end;
procedure TScreenSong.GenerateThumbnails();
var
- I: Integer;
+ I: integer;
CoverButtonIndex: integer;
CoverButton: TButton;
CoverName: string;
@@ -869,7 +875,7 @@ end;
procedure TScreenSong.SetScroll;
var
- VS, B: Integer;
+ VS, B: integer;
begin
VS := CatSongs.VisibleSongs;
if VS > 0 then
@@ -913,7 +919,7 @@ begin
Text[TextArtist].Text := '';
Text[TextTitle].Text := '';
for B := 0 to High(Button) do
- Button[B].Visible := False;
+ Button[B].Visible := false;
end;
end;
@@ -943,29 +949,37 @@ begin
VisCount := 0;
for B := 0 to High(Button) do
- if CatSongs.Song[B].Visible then Inc(VisCount);
+ if CatSongs.Song[B].Visible then
+ Inc(VisCount);
VisInt := 0;
for B := 0 to Interaction-1 do
- if CatSongs.Song[B].Visible then Inc(VisInt);
+ if CatSongs.Song[B].Visible then
+ Inc(VisInt);
- if VisCount <= 6 then begin
+ if VisCount <= 6 then
+ begin
Typ := 0;
- end else begin
- if VisInt <= 3 then begin
+ end
+ else
+ begin
+ if VisInt <= 3 then
+ begin
Typ := 1;
Count := 7;
Ready := true;
end;
- if (VisCount - VisInt) <= 3 then begin
+ if (VisCount - VisInt) <= 3 then
+ begin
Typ := 2;
Count := 7;
Ready := true;
end;
- if not Ready then begin
+ if not Ready then
+ begin
Typ := 3;
Src := Interaction;
end;
@@ -974,13 +988,15 @@ begin
// hide all buttons
- for B := 0 to High(Button) do begin
+ for B := 0 to High(Button) do
+ begin
Button[B].Visible := false;
Button[B].Selectable := CatSongs.Song[B].Visible;
end;
{
- for B := Src to Dst do begin
+ for B := Src to Dst do
+ begin
//Button[B].Visible := true;
Button[B].Visible := CatSongs.Song[B].Visible;
Button[B].Selectable := Button[B].Visible;
@@ -989,9 +1005,12 @@ begin
}
- if Typ = 0 then begin
- for B := 0 to High(Button) do begin
- if CatSongs.Song[B].Visible then begin
+ if Typ = 0 then
+ begin
+ for B := 0 to High(Button) do
+ begin
+ if CatSongs.Song[B].Visible then
+ begin
Button[B].Visible := true;
Button[B].Y := 140 + (Placed) * 60;
Inc(Placed);
@@ -999,10 +1018,13 @@ begin
end;
end;
- if Typ = 1 then begin
+ if Typ = 1 then
+ begin
B := 0;
- while (Count > 0) do begin
- if CatSongs.Song[B].Visible then begin
+ while (Count > 0) do
+ begin
+ if CatSongs.Song[B].Visible then
+ begin
Button[B].Visible := true;
Button[B].Y := 140 + (Placed) * 60;
Inc(Placed);
@@ -1012,10 +1034,13 @@ begin
end;
end;
- if Typ = 2 then begin
+ if Typ = 2 then
+ begin
B := High(Button);
- while (Count > 0) do begin
- if CatSongs.Song[B].Visible then begin
+ while (Count > 0) do
+ begin
+ if CatSongs.Song[B].Visible then
+ begin
Button[B].Visible := true;
Button[B].Y := 140 + (6-Placed) * 60;
Inc(Placed);
@@ -1025,11 +1050,14 @@ begin
end;
end;
- if Typ = 3 then begin
+ if Typ = 3 then
+ begin
B := Src;
Count := 4;
- while (Count > 0) do begin
- if CatSongs.Song[B].Visible then begin
+ while (Count > 0) do
+ begin
+ if CatSongs.Song[B].Visible then
+ begin
Button[B].Visible := true;
Button[B].Y := 140 + (3+Placed) * 60;
Inc(Placed);
@@ -1041,8 +1069,10 @@ begin
B := Src-1;
Placed := 0;
Count := 3;
- while (Count > 0) do begin
- if CatSongs.Song[B].Visible then begin
+ while (Count > 0) do
+ begin
+ if CatSongs.Song[B].Visible then
+ begin
Button[B].Visible := true;
Button[B].Y := 140 + (2-Placed) * 60;
Inc(Placed);
@@ -1067,7 +1097,8 @@ begin
for B := 0 to High(Button) do
Button[B].X := 300 + (B - Interaction) * 260;
- if Length(Button) >= 3 then begin
+ if Length(Button) >= 3 then
+ begin
if Interaction = 0 then
Button[High(Button)].X := 300 - 260;
@@ -1077,7 +1108,8 @@ begin
// circle
{
- for B := 0 to High(Button) do begin
+ for B := 0 to High(Button) do
+ begin
Factor := (B - Interaction); // 0 to center, -1: to left, +1 to right
Factor2 := Factor / Length(Button);
Button[B].X := 300 + 10000 * sin(2*pi*Factor2);
@@ -1100,13 +1132,14 @@ begin
begin
Button[B].X := 300 + (B - SongCurrent) * 260;
if (Button[B].X < -Button[B].W) or (Button[B].X > 800) then
- Button[B].Visible := False
+ Button[B].Visible := false
else
- Button[B].Visible := True;
+ Button[B].Visible := true;
end;
{
- if Length(Button) >= 3 then begin
+ if Length(Button) >= 3 then
+ begin
if Interaction = 0 then
Button[High(Button)].X := 300 - 260;
@@ -1117,7 +1150,8 @@ begin
// circle
{
- for B := 0 to High(Button) do begin
+ for B := 0 to High(Button) do
+ begin
Factor := (B - Interaction); // 0 to center, -1: to left, +1 to right
Factor2 := Factor / Length(Button);
Button[B].X := 300 + 10000 * sin(2*pi*Factor2);
@@ -1174,10 +1208,10 @@ procedure TScreenSong.SetScroll5;
var
B: integer;
Angle: real;
- Pos: Real;
+ Pos: real;
VS: integer;
Padding: real;
- X: Real;
+ X: real;
{
Theme.Song.CoverW: circle radius
Theme.Song.CoverX: x-pos. of the left edge of the selected cover
@@ -1249,13 +1283,13 @@ end;
procedure TScreenSong.SetScroll6; // rotate (slotmachine style)
var
B: integer;
- Angle: real;
- Pos: Real;
+ Angle: real;
+ Pos: real;
VS: integer;
- diff: real;
- X: Real;
- Factor: real;
- Z, Z2: real;
+ diff: real;
+ X: real;
+ Factor: real;
+ Z, Z2: real;
begin
VS := CatSongs.VisibleSongs;
if VS <= 5 then
@@ -1264,22 +1298,23 @@ begin
for B := 0 to High(Button) do
begin
Button[B].Visible := CatSongs.Song[B].Visible;
- if Button[B].Visible then begin // optimization for 1000 songs - updates only visible songs, hiding in tabs becomes useful for maintaing good speed
-
- Factor := 2 * pi * (CatSongs.VisibleIndex(B) - SongCurrent) / VS {CatSongs.VisibleSongs};// 0.5.0 (II): takes another 16ms
+ if Button[B].Visible then // optimization for 1000 songs - updates only visible songs, hiding in tabs becomes useful for maintaing good speed
+ begin
+
+ Factor := 2 * pi * (CatSongs.VisibleIndex(B) - SongCurrent) / VS {CatSongs.VisibleSongs};// 0.5.0 (II): takes another 16ms
- Z := (1 + cos(Factor)) / 2;
- Z2 := (1 + 2*Z) / 3;
+ Z := (1 + cos(Factor)) / 2;
+ Z2 := (1 + 2*Z) / 3;
- Button[B].Y := Theme.Song.Cover.Y + (0.185 * Theme.Song.Cover.H * VS * sin(Factor)) * Z2 - ((Button[B].H - Theme.Song.Cover.H)/2); // 0.5.0 (I): 2 times faster by not calling CatSongs.VisibleSongs
- Button[B].Z := Z / 2 + 0.3;
+ Button[B].Y := Theme.Song.Cover.Y + (0.185 * Theme.Song.Cover.H * VS * sin(Factor)) * Z2 - ((Button[B].H - Theme.Song.Cover.H)/2); // 0.5.0 (I): 2 times faster by not calling CatSongs.VisibleSongs
+ Button[B].Z := Z / 2 + 0.3;
- Button[B].W := Theme.Song.Cover.H * Z2;
+ Button[B].W := Theme.Song.Cover.H * Z2;
- //Button[B].Y := {50 +} 140 + 50 - 50 * Z2;
- Button[B].X := Theme.Song.Cover.X + (Theme.Song.Cover.H - Abs(Button[B].H)) * 0.7 ;
- Button[B].H := Button[B].W;
+ //Button[B].Y := {50 +} 140 + 50 - 50 * Z2;
+ Button[B].X := Theme.Song.Cover.X + (Theme.Song.Cover.H - Abs(Button[B].H)) * 0.7 ;
+ Button[B].H := Button[B].W;
end;
end;
end
@@ -1287,10 +1322,10 @@ begin
begin
//Change Pos of all Buttons
for B := low(Button) to high(Button) do
- begin
- Button[B].Visible := CatSongs.Song[B].Visible; //Adjust Visibility
+ begin
+ Button[B].Visible := CatSongs.Song[B].Visible; //Adjust Visibility
if Button[B].Visible then //Only Change Pos for Visible Buttons
- begin
+ begin
Pos := (CatSongs.VisibleIndex(B) - SongCurrent);
if (Pos < -VS/2) then
Pos := Pos + VS
@@ -1300,7 +1335,7 @@ begin
if (Abs(Pos) < 2.5) then {fixed Positions}
begin
Angle := Pi * (Pos / 5);
- //Button[B].Visible := False;
+ //Button[B].Visible := false;
Button[B].H := Abs(Theme.Song.Cover.H * cos(Angle*0.8));//Power(Z2, 3);
@@ -1323,8 +1358,10 @@ begin
begin {Behind the Front Covers}
// limit-bg-covers hack
- if (abs(VS/2-abs(Pos))>10) then Button[B].Visible:=False;
- if VS > 25 then VS:=25;
+ if (abs(VS/2-abs(Pos))>10) then
+ Button[B].Visible := false;
+ if VS > 25 then
+ VS:=25;
// end of limit-bg-covers hack
if Pos < 0 then
@@ -1442,9 +1479,9 @@ end;
function TScreenSong.Draw: boolean;
var
- dx: real;
- dt: real;
- I: Integer;
+ dx: real;
+ dt: real;
+ I: integer;
begin
dx := SongTarget-SongCurrent;
dt := TimeSkip * 7;
@@ -1455,7 +1492,8 @@ begin
SongCurrent := SongCurrent + dx*dt;
{
- if SongCurrent > Catsongs.VisibleSongs then begin
+ if SongCurrent > Catsongs.VisibleSongs then
+ begin
SongCurrent := SongCurrent - Catsongs.VisibleSongs;
SongTarget := SongTarget - Catsongs.VisibleSongs;
end;
@@ -1521,8 +1559,8 @@ end;
procedure TScreenSong.SelectNext;
var
- Skip: integer;
- VS: Integer;
+ Skip: integer;
+ VS: integer;
begin
VS := CatSongs.VisibleSongs;
@@ -1541,7 +1579,8 @@ begin
Interaction := (Interaction + Skip) mod Length(Interactions);
// try to keep all at the beginning
- if SongTarget > VS-1 then begin
+ if SongTarget > VS-1 then
+ begin
SongTarget := SongTarget - VS;
SongCurrent := SongCurrent - VS;
end;
@@ -1555,8 +1594,8 @@ end;
procedure TScreenSong.SelectPrev;
var
- Skip: integer;
- VS: Integer;
+ Skip: integer;
+ VS: integer;
begin
VS := CatSongs.VisibleSongs;
@@ -1566,13 +1605,15 @@ begin
Skip := 1;
- while (not CatSongs.Song[(Interaction - Skip + Length(Interactions)) mod Length(Interactions)].Visible) do Inc(Skip);
+ while (not CatSongs.Song[(Interaction - Skip + Length(Interactions)) mod Length(Interactions)].Visible) do
+ Inc(Skip);
SongTarget := SongTarget - 1;//Skip;
Interaction := (Interaction - Skip + Length(Interactions)) mod Length(Interactions);
// try to keep all at the beginning
- if SongTarget < 0 then begin
+ if SongTarget < 0 then
+ begin
SongTarget := SongTarget + CatSongs.VisibleSongs;
SongCurrent := SongCurrent + CatSongs.VisibleSongs;
end;
@@ -1652,9 +1693,9 @@ begin
end;
end;
-procedure TScreenSong.SkipTo(Target: Cardinal);
+procedure TScreenSong.SkipTo(Target: cardinal);
var
- i: integer;
+ i: integer;
begin
UnLoadDetailedCover;
@@ -1669,7 +1710,7 @@ end;
procedure TScreenSong.SelectRandomSong;
var
- I, I2: Integer;
+ I, I2: integer;
begin
case PlaylistMan.Mode of
smNormal: //All Songs Just Select Random Song
@@ -1748,11 +1789,11 @@ begin
end
else
begin
- Static[StaticTeam1Joker1].Visible := False;
- Static[StaticTeam1Joker2].Visible := False;
- Static[StaticTeam1Joker3].Visible := False;
- Static[StaticTeam1Joker4].Visible := False;
- Static[StaticTeam1Joker5].Visible := False;
+ Static[StaticTeam1Joker1].Visible := false;
+ Static[StaticTeam1Joker2].Visible := false;
+ Static[StaticTeam1Joker3].Visible := false;
+ Static[StaticTeam1Joker4].Visible := false;
+ Static[StaticTeam1Joker5].Visible := false;
end;
if (PartySession.Teams.NumTeams >= 2) then
@@ -1765,11 +1806,11 @@ begin
end
else
begin
- Static[StaticTeam2Joker1].Visible := False;
- Static[StaticTeam2Joker2].Visible := False;
- Static[StaticTeam2Joker3].Visible := False;
- Static[StaticTeam2Joker4].Visible := False;
- Static[StaticTeam2Joker5].Visible := False;
+ Static[StaticTeam2Joker1].Visible := false;
+ Static[StaticTeam2Joker2].Visible := false;
+ Static[StaticTeam2Joker3].Visible := false;
+ Static[StaticTeam2Joker4].Visible := false;
+ Static[StaticTeam2Joker5].Visible := false;
end;
if (PartySession.Teams.NumTeams >= 3) then
@@ -1782,40 +1823,40 @@ begin
end
else
begin
- Static[StaticTeam3Joker1].Visible := False;
- Static[StaticTeam3Joker2].Visible := False;
- Static[StaticTeam3Joker3].Visible := False;
- Static[StaticTeam3Joker4].Visible := False;
- Static[StaticTeam3Joker5].Visible := False;
+ Static[StaticTeam3Joker1].Visible := false;
+ Static[StaticTeam3Joker2].Visible := false;
+ Static[StaticTeam3Joker3].Visible := false;
+ Static[StaticTeam3Joker4].Visible := false;
+ Static[StaticTeam3Joker5].Visible := false;
end;
*)
end
else
begin //Hide all
- Static[StaticTeam1Joker1].Visible := False;
- Static[StaticTeam1Joker2].Visible := False;
- Static[StaticTeam1Joker3].Visible := False;
- Static[StaticTeam1Joker4].Visible := False;
- Static[StaticTeam1Joker5].Visible := False;
-
- Static[StaticTeam2Joker1].Visible := False;
- Static[StaticTeam2Joker2].Visible := False;
- Static[StaticTeam2Joker3].Visible := False;
- Static[StaticTeam2Joker4].Visible := False;
- Static[StaticTeam2Joker5].Visible := False;
-
- Static[StaticTeam3Joker1].Visible := False;
- Static[StaticTeam3Joker2].Visible := False;
- Static[StaticTeam3Joker3].Visible := False;
- Static[StaticTeam3Joker4].Visible := False;
- Static[StaticTeam3Joker5].Visible := False;
+ Static[StaticTeam1Joker1].Visible := false;
+ Static[StaticTeam1Joker2].Visible := false;
+ Static[StaticTeam1Joker3].Visible := false;
+ Static[StaticTeam1Joker4].Visible := false;
+ Static[StaticTeam1Joker5].Visible := false;
+
+ Static[StaticTeam2Joker1].Visible := false;
+ Static[StaticTeam2Joker2].Visible := false;
+ Static[StaticTeam2Joker3].Visible := false;
+ Static[StaticTeam2Joker4].Visible := false;
+ Static[StaticTeam2Joker5].Visible := false;
+
+ Static[StaticTeam3Joker1].Visible := false;
+ Static[StaticTeam3Joker2].Visible := false;
+ Static[StaticTeam3Joker3].Visible := false;
+ Static[StaticTeam3Joker4].Visible := false;
+ Static[StaticTeam3Joker5].Visible := false;
end;
end;
procedure TScreenSong.SetStatics;
var
- I: Integer;
- Visible: Boolean;
+ I: integer;
+ Visible: boolean;
begin
//Set Visibility of Party Statics and Text
Visible := (Mode = smPartyMode);
@@ -1859,7 +1900,7 @@ begin
CatSongs.Selected := Interaction;
StopMusicPreview();
- ScreenName.Goto_SingScreen := True;
+ ScreenName.Goto_SingScreen := true;
FadeTo(@ScreenName);
end;
diff --git a/src/screens/UScreenTop5.pas b/src/screens/UScreenTop5.pas
index 59f5972b..c45f01bf 100644
--- a/src/screens/UScreenTop5.pas
+++ b/src/screens/UScreenTop5.pas
@@ -34,34 +34,46 @@ interface
{$I switches.inc}
uses
- UMenu, SDL, SysUtils, UDisplay, UMusic, USongs, UThemes;
+ SysUtils,
+ SDL,
+ UDisplay,
+ UMenu,
+ UMusic,
+ USongs,
+ UThemes;
type
TScreenTop5 = class(TMenu)
public
- TextLevel: integer;
- TextArtistTitle: integer;
+ TextLevel: integer;
+ TextArtistTitle: integer;
- StaticNumber: array[1..5] of integer;
- TextNumber: array[1..5] of integer;
- TextName: array[1..5] of integer;
- TextScore: array[1..5] of integer;
+ StaticNumber: array[1..5] of integer;
+ TextNumber: array[1..5] of integer;
+ TextName: array[1..5] of integer;
+ TextScore: array[1..5] of integer;
+
+ Fadeout: boolean;
- Fadeout: boolean;
constructor Create; override;
- function ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean; override;
+ function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean; override;
procedure onShow; override;
function Draw: boolean; override;
end;
implementation
-uses UGraphic, UDataBase, UMain, UIni;
+uses
+ UDataBase,
+ UGraphic,
+ UIni,
+ UNote;
-function TScreenTop5.ParseInput(PressedKey: Cardinal; CharCode: WideChar; PressedDown: Boolean): Boolean;
+function TScreenTop5.ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown: boolean): boolean;
begin
Result := true;
- If (PressedDown) Then begin
+ if (PressedDown) then
+ begin
// check normal keys
case WideCharUpperCase(CharCode)[1] of
'Q':
@@ -70,14 +82,15 @@ begin
Exit;
end;
end;
-
+
// check special keys
case PressedKey of
SDLK_ESCAPE,
SDLK_BACKSPACE,
SDLK_RETURN:
begin
- if (not Fadeout) then begin
+ if (not Fadeout) then
+ begin
FadeTo(@ScreenSong);
Fadeout := true;
end;
@@ -92,7 +105,7 @@ end;
constructor TScreenTop5.Create;
var
- I: integer;
+ I: integer;
begin
inherited Create;
@@ -116,8 +129,8 @@ end;
procedure TScreenTop5.onShow;
var
- I: integer;
- PMax: integer;
+ I: integer;
+ PMax: integer;
begin
inherited;
@@ -126,7 +139,8 @@ begin
//ReadScore(CurrentSong);
PMax := Ini.Players;
- if PMax = 4 then PMax := 5;
+ if PMax = 4 then
+ PMax := 5;
for I := 0 to PMax do
DataBase.AddScore(CurrentSong, Ini.Difficulty, Ini.Name[I], Round(Player[I].ScoreTotalInt));
@@ -135,7 +149,8 @@ begin
Text[TextArtistTitle].Text := CurrentSong.Artist + ' - ' + CurrentSong.Title;
- for I := 1 to Length(CurrentSong.Score[Ini.Difficulty]) do begin
+ for I := 1 to Length(CurrentSong.Score[Ini.Difficulty]) do
+ begin
Static[StaticNumber[I]].Visible := true;
Text[TextNumber[I]].Visible := true;
Text[TextName[I]].Visible := true;
@@ -145,7 +160,8 @@ begin
Text[TextScore[I]].Text := IntToStr(CurrentSong.Score[Ini.Difficulty, I-1].Score);
end;
- for I := Length(CurrentSong.Score[Ini.Difficulty])+1 to 5 do begin
+ for I := Length(CurrentSong.Score[Ini.Difficulty])+1 to 5 do
+ begin
Static[StaticNumber[I]].Visible := false;
Text[TextNumber[I]].Visible := false;
Text[TextName[I]].Visible := false;
@@ -157,24 +173,30 @@ end;
function TScreenTop5.Draw: boolean;
//var
-{ Min: real;
- Max: real;
- Factor: real;
- Factor2: real;
-
- Item: integer;
- P: integer;
- C: integer;}
+{
+ Min: real;
+ Max: real;
+ Factor: real;
+ Factor2: real;
+
+ Item: integer;
+ P: integer;
+ C: integer;
+}
begin
// Singstar - let it be...... with 6 statics
-(* if PlayersPlay = 6 then begin
- for Item := 4 to 6 do begin
+(*
+ if PlayersPlay = 6 then
+ begin
+ for Item := 4 to 6 do
+ begin
if ScreenAct = 1 then P := Item-4;
if ScreenAct = 2 then P := Item-1;
FillPlayer(Item, P);
-
-{ if ScreenAct = 1 then begin
+{
+ if ScreenAct = 1 then
+ begin
LoadColor(
Static[StaticBoxLightest[Item]].Texture.ColR,
Static[StaticBoxLightest[Item]].Texture.ColG,
@@ -182,16 +204,18 @@ begin
'P1Dark');
end;
- if ScreenAct = 2 then begin
+ if ScreenAct = 2 then
+ begin
LoadColor(
Static[StaticBoxLightest[Item]].Texture.ColR,
Static[StaticBoxLightest[Item]].Texture.ColG,
Static[StaticBoxLightest[Item]].Texture.ColB,
'P4Dark');
- end; }
-
+ end;
+}
end;
- end; *)
+ end;
+*)
Result := inherited Draw;
end;
diff --git a/src/ultrastardx.dpr b/src/ultrastardx.dpr
index f4e06b0c..f2896cd2 100644
--- a/src/ultrastardx.dpr
+++ b/src/ultrastardx.dpr
@@ -199,6 +199,7 @@ uses
USingScores in 'base\USingScores.pas',
USingNotes in 'base\USingNotes.pas',
UPath in 'base\UPath.pas',
+ UNote in 'base\UNote.pas',
//------------------------------
//Includes - Plugin Support