aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Medley/game/themes/Deluxe.ini18
-rw-r--r--Medley/src/base/UDraw.pas9
-rw-r--r--Medley/src/base/UNote.pas36
-rw-r--r--Medley/src/base/USong.pas329
-rw-r--r--Medley/src/base/USongs.pas19
-rw-r--r--Medley/src/base/UThemes.pas16
-rw-r--r--Medley/src/screens/UScreenScore.pas241
-rw-r--r--Medley/src/screens/UScreenSing.pas399
-rw-r--r--Medley/src/screens/UScreenSong.pas150
9 files changed, 1058 insertions, 159 deletions
diff --git a/Medley/game/themes/Deluxe.ini b/Medley/game/themes/Deluxe.ini
index cf3ad368..d7ac8adb 100644
--- a/Medley/game/themes/Deluxe.ini
+++ b/Medley/game/themes/Deluxe.ini
@@ -991,6 +991,24 @@ Size = 18
Color = White
Align = 1
+[SingSongNameStatic]
+X = 5
+Y = 3
+W = 790
+H = 34
+Tex = Button
+Color = White
+Type = Transparen
+
+[SingSongNameText]
+Text = should not see me
+X = 400
+Y = 5
+Font = 1
+Size = 30
+Color = Black
+Align = 1
+
# O N E P L A Y E R M O D E # # # # # # # # # # # # # # # # # # # #
#PlayerOne
[SingP1Static]
diff --git a/Medley/src/base/UDraw.pas b/Medley/src/base/UDraw.pas
index 1783986f..8bb2c210 100644
--- a/Medley/src/base/UDraw.pas
+++ b/Medley/src/base/UDraw.pas
@@ -97,6 +97,7 @@ uses
URecord,
UScreenSing,
UScreenSingModi,
+ USong,
UTexture;
procedure SingDrawBackground;
@@ -1387,7 +1388,13 @@ begin
if (CurLyricsTime > 0) and
(LyricsState.TotalTime > 0) then
begin
- LyricsProgress := CurLyricsTime / LyricsState.TotalTime;
+ if ScreenSong.Mode <> smMedley then
+ LyricsProgress := CurLyricsTime / LyricsState.TotalTime
+ else
+ LyricsProgress := (CurLyricsTime - GetTimeFromBeat(CurrentSong.Medley.StartBeat) +
+ CurrentSong.Medley.FadeIn_time) / (GetTimeFromBeat(CurrentSong.Medley.EndBeat) +
+ CurrentSong.Medley.FadeOut_time - GetTimeFromBeat(CurrentSong.Medley.StartBeat) +
+ CurrentSong.Medley.FadeIn_time);
glTexCoord2f((width * LyricsProgress) / 8, 0);
glVertex2f(x + width * LyricsProgress, y);
diff --git a/Medley/src/base/UNote.pas b/Medley/src/base/UNote.pas
index 8e5b709a..bc91c892 100644
--- a/Medley/src/base/UNote.pas
+++ b/Medley/src/base/UNote.pas
@@ -88,13 +88,30 @@ type
Note: array of TPlayerNote;
end;
+ TStats = record
+ Player: array of TPlayer;
+ SongArtist: UTF8String;
+ SongTitle: UTF8String;
+ end;
+
+ TMedleyPlaylist = record
+ Song: array of integer;
+ NumMedleySongs: integer;
+ CurrentMedleySong: integer;
+ ApplausePlayed: boolean;
+ Stats: array of TStats;
+ NumPlayer: integer;
+ end;
+
var
// player and music info
Player: array of TPlayer;
PlayersPlay: integer;
-
+ PlaylistMedley: TMedleyPlaylist;
CurrentSong: TSong;
+ max_song_score_medley: integer;
+ max_song_line_bonus_medley: integer;
const
MAX_SONG_SCORE = 10000; // max. achievable points per song
@@ -463,10 +480,19 @@ begin
// half size notes patch
NoteHit := true;
- if (Ini.LineBonus > 0) then
- MaxSongPoints := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS
- else
- MaxSongPoints := MAX_SONG_SCORE;
+ if ScreenSong.Mode <> smMedley then
+ begin
+ if (Ini.LineBonus > 0) then
+ MaxSongPoints := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS
+ else
+ MaxSongPoints := MAX_SONG_SCORE;
+ end else
+ begin
+ if (Ini.LineBonus > 0) then
+ MaxSongPoints := max_song_score_medley - max_song_line_bonus_medley
+ else
+ MaxSongPoints := max_song_score_medley;
+ end;
// Note: ScoreValue is the sum of all note values of the song
// (MaxSongPoints / ScoreValue) is the points that a player
diff --git a/Medley/src/base/USong.pas b/Medley/src/base/USong.pas
index c465f198..d4eb714d 100644
--- a/Medley/src/base/USong.pas
+++ b/Medley/src/base/USong.pas
@@ -64,7 +64,8 @@ uses
type
- TSingMode = ( smNormal, smPartyMode, smPlaylistRandom );
+ TSingMode = ( smNormal, smPartyMode, smPlaylistRandom, smMedley );
+ TMedleySource = ( msNone, msCalculated, msTag );
TBPM = record
BPM: real;
@@ -85,6 +86,16 @@ type
Content: UTF8String;
end;
+ TMedley = record
+ Source: TMedleySource; //source of the information
+ StartBeat: integer; //start beat of medley
+ EndBeat: integer; //end beat of medley
+ FadeIn: integer; //start beat of fadein
+ FadeOut: integer; //end beat of fadeout
+ FadeIn_time: real; //FadeIn-Time in seconds
+ FadeOut_time: real; //FadeIn-Time in seconds
+ end;
+
TSong = class
private
FileLineNo : integer; // line, which is read last, for error reporting
@@ -157,6 +168,9 @@ type
MultBPM : integer;
LastError: AnsiString;
+
+ Medley: TMedley; //infos for medley-mode and preview start
+
function GetErrorLineNo: integer;
property ErrorLineNo: integer read GetErrorLineNo;
@@ -168,6 +182,9 @@ type
function Analyse(const ReadCustomTags: Boolean = false): boolean;
function AnalyseXML(): boolean;
procedure Clear();
+ procedure FindRefrainStart;
+ procedure SetMedleyMode;
+ function ReadMedleyFile(MedleyFilePath: IPath): boolean;
end;
implementation
@@ -178,7 +195,7 @@ uses
UIni,
UPathUtils,
UMusic, //needed for Lines
- UNote; //needed for Player
+ UNote;
const
DEFAULT_ENCODING = encAuto;
@@ -461,6 +478,7 @@ begin
Exit;
end;
+ SetLength(Lines, 0); //just a fix.. for medley-mod
SetLength(Lines, 2);
for Count := 0 to High(Lines) do
begin
@@ -589,7 +607,6 @@ begin
if (High(Lines[Count].Line) >= 0) then
Lines[Count].Line[High(Lines[Count].Line)].LastLine := true;
end;
-
Result := true;
end;
@@ -1292,6 +1309,7 @@ begin
Creator := '';
Relative := false;
+ Medley.Source := msNone;
end;
function TSong.Analyse(const ReadCustomTags: Boolean): boolean;
@@ -1310,7 +1328,10 @@ begin
Self.clear;
//Read Header
- Result := Self.ReadTxTHeader(SongFile, ReadCustomTags)
+ Result := Self.ReadTxTHeader(SongFile, ReadCustomTags);
+
+ //Load Song (for testing)
+ Result := Result and Self.LoadSong;
finally
SongFile.Free;
end;
@@ -1318,7 +1339,6 @@ end;
function TSong.AnalyseXML(): boolean;
-
begin
Result := false;
@@ -1331,6 +1351,305 @@ begin
//Read Header
Result := self.ReadXMLHeader( FileName );
+ //Load Song (for testing)
+ Result := Result and self.LoadXMLSong;
+
+end;
+
+
+{* new procedure for preview
+ tries find out the beginning of a refrain *}
+procedure TSong.FindRefrainStart();
+Type
+ TSeries = record
+ start: integer; //Start sentence of series
+ end_: integer; //End sentence of series
+ len: integer; //Length of sentence series
+ end;
+
+var
+ I, J, K, num_lines: integer;
+ sentences: array of UTF8String;
+ series: array of TSeries;
+ temp_series: TSeries;
+ max: integer;
+
+begin
+ if Medley.Source = msTag then
+ Exit;
+
+ num_lines := Length(Lines[0].Line);
+ SetLength(sentences, num_lines);
+
+ //build sentences array
+ for I := 0 to num_lines - 1 do
+ begin
+ sentences[I] := '';
+ for J := 0 to Length(Lines[0].Line[I].Note) - 1 do
+ begin
+ sentences[I] := sentences[I] + Lines[0].Line[I].Note[J].Text;
+ end;
+ end;
+
+ //find equal sentences series
+ SetLength(series, 0);
+
+ for I := 0 to num_lines - 2 do
+ begin
+ for J := I+1 to num_lines - 1 do
+ begin
+ if sentences[I]=sentences[J] then
+ begin
+ temp_series.start := I;
+ temp_series.end_ := I;
+
+ if (J+J-I-1>num_lines-1) then
+ max:=num_lines-1-J
+ else
+ max:=J-I-1;
+
+ for K := 1 to max do
+ begin
+ if sentences[I+K]=sentences[J+K] then
+ temp_series.end_ := I+K
+ else
+ break;
+ end;
+ temp_series.len := temp_series.end_ - temp_series.start + 1;
+ SetLength(series, Length(series)+1);
+ series[Length(series)-1] := temp_series;
+ end;
+ end;
+ end;
+
+ //search for longest sequence
+ if Length(series)>0 then
+ begin
+ max := 0;
+ for I := 0 to Length(series) - 1 do
+ begin
+ if series[I].len > series[max].len then
+ max := I;
+ end;
+ end;
+
+ if (Length(series)>0) and (series[max].len > 3) then
+ begin
+ Medley.Source := msCalculated;
+ Medley.StartBeat := Lines[0].Line[series[max].start].Note[0].Start;
+ end else
+ Medley.Source := msNone;
+end;
+
+//sets a song to medley-mod:
+//converts all unneeded notes into freestyle
+//updates score values
+procedure TSong.SetMedleyMode;
+var
+ pl, line, note: integer;
+ LF: TLineFragment;
+ start: integer;
+ end_: integer;
+begin
+ start := self.Medley.StartBeat;
+ end_ := self.Medley.EndBeat;
+
+ for pl := 0 to Length(Lines) - 1 do
+ begin
+ Lines[pl].ScoreValue := 0;
+ for line := 0 to Length(Lines[pl].Line) - 1 do
+ begin
+ Lines[pl].Line[line].TotalNotes := 0;
+ for note := 0 to Length(Lines[pl].Line[line].Note) - 1 do
+ begin
+ LF := Lines[pl].Line[line].Note[note];
+ if LF.Start < start then //check start
+ Lines[pl].Line[line].Note[note].NoteType := ntFreestyle
+ else if LF.Start>= end_ then //check end
+ Lines[pl].Line[line].Note[note].NoteType := ntFreestyle
+ else
+ begin
+ //add this notes value ("notes length" * "notes scorefactor") to the current songs entire value
+ Inc(Lines[pl].ScoreValue, LF.Length * ScoreFactor[LF.NoteType]);
+ //and to the current lines entire value
+ Inc(Lines[pl].Line[line].TotalNotes, LF.Length * ScoreFactor[LF.NoteType]);
+ end;
+ end;
+ end;
+ end;
+end;
+
+//reads the txtm
+//TODO move this to ReadTXTHeader and implement the MEDLEY-TAGS in txt-file:
+//conversion: START-> MEDLEY_START
+// END-> MEDLEY_END
+// FADE_IN -> MEDLEY_FADE_IN
+// FADE_OUT-> MEDLEY_FADE_OUT
+//TODO: write a tool to convert existing txtm
+function TSong.ReadMedleyFile(MedleyFilePath: IPath): boolean;
+const
+ DEFAULT_FADE_IN_TIME = 10;
+ DEFAULT_FADE_OUT_TIME = 4;
+var
+ Line, Identifier: string;
+ Value: string;
+ SepPos: integer; // separator position
+ Done: byte; // bit-vector of mandatory fields
+ EncFile: IPath; // encoded filename
+ FullFileName: string;
+ LineNo: integer;
+ MedleyFile: TTextFileStream;
+ found_fadeIn, found_fadeOut: boolean;
+
+begin
+ Result := true;
+ Done := 0;
+
+ MedleyFile := TMemTextFileStream.Create(MedleyFilePath, fmOpenRead);
+ FullFileName := MedleyFilePath.ToNative;
+
+ //set standard values
+ found_fadeIn := false;
+ found_fadeOut := false;
+
+ //Read first Line
+ MedleyFile.ReadLine(Line);
+ if (Length(Line) <= 0) then
+ begin
+ Log.LogError('File starts with empty line: ' + FullFileName,
+ 'TSong.ReadMedleyFile');
+ Result := false;
+ Exit;
+ end;
+
+ // check if file begins with a UTF-8 BOM, if so set encoding to UTF-8
+ if (CheckReplaceUTF8BOM(Line)) then
+ Encoding := encUTF8;
+
+ //Read Lines while Line starts with # or its empty
+ while (Length(Line) = 0) or (Line[1] = '#') do
+ begin
+ //Increase Line Number
+ Inc (LineNo);
+ SepPos := Pos(':', Line);
+
+ //Line has no Seperator, ignore non header field
+ if (SepPos = 0) then
+ begin
+ // read next line
+ if (not MedleyFile.ReadLine(Line)) then
+ begin
+ Result := false;
+ Log.LogError('File incomplete or not Ultrastar txtm (A): ' + FullFileName);
+ Break;
+ end;
+ Continue;
+ end;
+
+ //Read Identifier and Value
+ Identifier := UpperCase(Trim(Copy(Line, 2, SepPos - 2))); //Uppercase is for Case Insensitive Checks
+ Value := Trim(Copy(Line, SepPos + 1, Length(Line) - SepPos));
+
+ //Check the Identifier (If Value is given)
+ if (Length(Value) = 0) then
+ begin
+ Log.LogWarn('Empty field "'+Identifier+'" in file ' + FullFileName,
+ 'TSong.ReadMedleyFile');
+ end
+ else
+ begin
+
+ //-----------
+ //Required Attributes
+ //-----------
+
+ if (Identifier = 'START') then
+ begin
+ if TryStrtoInt(Value, self.Medley.StartBeat) then
+ //Add START flag to Done
+ Done := Done or 1;
+ end
+
+ else if (Identifier = 'END') then
+ begin
+ if TryStrtoInt(Value, self.Medley.EndBeat) then
+ //Add END Flag to Done
+ Done := Done or 2;
+ end
+
+ //---------
+ //Additional Header Information
+ //---------
+
+ else if (Identifier = 'FADE_IN') then
+ begin
+ if TryStrtoInt(Value, self.Medley.FadeIn) then
+ found_fadeIn := true;
+ end
+
+ else if (Identifier = 'FADE_OUT') then
+ begin
+ if TryStrtoInt(Value, self.Medley.FadeOut) then
+ found_fadeOut := true;
+ end
+ end; // End check for non-empty Value
+
+ // read next line
+ if (not MedleyFile.ReadLine(Line)) then
+ begin
+ Result := false;
+ Log.LogError('File incomplete or not Ultrastar txtm (A): ' + FullFileName);
+ Break;
+ end;
+ end; // while
+
+ //Check if all Required Values are given
+ if (Done <> 3) then
+ begin
+ Result := false;
+ if (Done and 2) = 0 then //No End Flag
+ Log.LogError('END tag missing: ' + FullFileName)
+ else if (Done and 1) = 0 then //No Start Flag
+ Log.LogError('START tag missing: ' + FullFileName)
+ else //unknown Error
+ Log.LogError('File incomplete or not Ultrastar txtm (B - '+ inttostr(Done) +'): ' + FullFileName);
+
+ Self.Medley.Source := msNone;
+ end else if self.Medley.StartBeat>=self.Medley.EndBeat then
+ begin
+ Log.LogError('Failed to load MEDLEY-TAGS (Start>=End): ' + FullFileName);
+ self.Medley.Source := msNone;
+ Result := false;
+ end else if found_fadeIn and (self.Medley.FadeIn>=self.Medley.StartBeat) then
+ begin
+ Log.LogError('Failed to load MEDLEY-TAGS (FadeIn>=Start): ' + FullFileName);
+ self.Medley.Source := msNone;
+ Result := false;
+ end else if found_fadeOut and (self.Medley.EndBeat>=self.Medley.FadeOut) then
+ begin
+ Log.LogError('Failed to load MEDLEY-TAGS (End>=FadeOut): ' + FullFileName);
+ self.Medley.Source := msNone;
+ Result := false;
+ end else
+ begin
+ self.Medley.Source := msTag;
+ CurrentSong := self;
+ if not found_fadeIn then //set FadeIn if not defined
+ begin // TODO: what if FadeIn < song start?
+ self.Medley.FadeIn := self.Medley.StartBeat - round(GetMidBeat(DEFAULT_FADE_IN_TIME));
+ end;
+ if not found_fadeOut then //set FadeOut if not defined
+ begin // TODO: what if FadeOut > song end?
+ self.Medley.FadeOut := self.Medley.EndBeat + round(GetMidBeat(DEFAULT_FADE_OUT_TIME));
+ end;
+
+ //calculate fade time
+
+ self.Medley.FadeIn_time := GetTimeFromBeat(CurrentSong.Medley.StartBeat) -
+ GetTimeFromBeat(CurrentSong.Medley.FadeIn);
+ self.Medley.FadeOut_time := GetTimeFromBeat(CurrentSong.Medley.FadeOut) -
+ GetTimeFromBeat(CurrentSong.Medley.EndBeat);
+ end;
end;
end.
diff --git a/Medley/src/base/USongs.pas b/Medley/src/base/USongs.pas
index baeec13a..af7f7a16 100644
--- a/Medley/src/base/USongs.pas
+++ b/Medley/src/base/USongs.pas
@@ -312,18 +312,33 @@ var
Files: TPathDynArray;
Song: TSong;
Extension: IPath;
+ MedleyFiles: TPathDynArray;
+ MedleyExtension: IPath;
begin
SetLength(Files, 0);
+
Extension := Path('.txt');
+ MedleyExtension := Path('.txtm');
FindFilesByExtension(Dir, Extension, true, Files);
+
for I := 0 to High(Files) do
begin
Song := TSong.Create(Files[I]);
if Song.Analyse then
- SongList.Add(Song)
- else
+ begin
+ //medley support... TODO: move it (see USong...)
+ SetLength(MedleyFiles, 0);
+ FindFilesByExtension(Files[I].GetPath, MedleyExtension, true, MedleyFiles);
+
+ if Length(MedleyFiles)>0 then
+ begin
+ Song.ReadMedleyFile(MedleyFiles[0]);
+ end;
+
+ SongList.Add(Song);
+ end else
begin
Log.LogError('AnalyseFile failed for "' + Files[I].ToNative + '".');
FreeAndNil(Song);
diff --git a/Medley/src/base/UThemes.pas b/Medley/src/base/UThemes.pas
index 4322815e..6ffeb3b1 100644
--- a/Medley/src/base/UThemes.pas
+++ b/Medley/src/base/UThemes.pas
@@ -306,6 +306,9 @@ type
end;
TThemeSing = class(TThemeBasic)
+ //Show actual SongName
+ StaticSongName : TThemeStatic;
+ TextSongName : TThemeText;
//TimeBar mod
StaticTimeProgress: TThemeStatic;
@@ -358,7 +361,7 @@ type
LineBonusText: array [0..8] of UTF8String;
//Pause Popup
- PausePopUp: TThemeStatic;
+ PausePopUp: TThemeStatic;
end;
TThemeLyricBar = record
@@ -1051,10 +1054,13 @@ begin
// Sing
ThemeLoadBasic(Sing, 'Sing');
- //TimeBar mod
- ThemeLoadStatic(Sing.StaticTimeProgress, 'SingTimeProgress');
- ThemeLoadText(Sing.TextTimeText, 'SingTimeText');
- //eoa TimeBar mod
+ ThemeLoadStatic(Sing.StaticSongName, 'SingSongNameStatic');
+ ThemeLoadText(Sing.TextSongName, 'SingSongNameText');
+
+ //TimeBar mod
+ ThemeLoadStatic(Sing.StaticTimeProgress, 'SingTimeProgress');
+ ThemeLoadText(Sing.TextTimeText, 'SingTimeText');
+ //eoa TimeBar mod
//moveable singbar mod
ThemeLoadStatic(Sing.StaticP1SingBar, 'SingP1SingBar');
diff --git a/Medley/src/screens/UScreenScore.pas b/Medley/src/screens/UScreenScore.pas
index ce1b11e5..5a50a3dc 100644
--- a/Medley/src/screens/UScreenScore.pas
+++ b/Medley/src/screens/UScreenScore.pas
@@ -39,6 +39,7 @@ uses
SysUtils,
UDisplay,
UMusic,
+ USong,
USongs,
UThemes,
gl,
@@ -74,19 +75,30 @@ type
BarGolden_ActualHeight: real;
end;
+ TPlayerScoreData = record
+ Data: array[1..6] of TPlayerScoreScreenData;
+ end;
+
TPlayerScoreRatingPics = record // a fine array of the rating pictures
RateEaseStep: integer;
RateEaseValue: real;
end;
+ TPLayerScorePics = record
+ Data: array[1..6] of TPlayerScoreRatingPics;
+ end;
+
TScreenScore = class(TMenu)
private
BarTime: cardinal;
ArrayStartModifier: integer;
public
+ //TeamInfo: TTeamInfo;
aPlayerScoreScreenTextures: array[1..6] of TPlayerScoreScreenTexture;
- aPlayerScoreScreenDatas: array[1..6] of TPlayerScoreScreenData;
- aPlayerScoreScreenRatings: array[1..6] of TPlayerScoreRatingPics;
+ aPlayerScoreScreenDatas: array of TPlayerScoreData;
+ aPlayerScoreScreenRatings: array of TPlayerScorePics;
+
+ ActualRound: integer;
BarScore_EaseOut_Step: real;
BarPhrase_EaseOut_Step: real;
@@ -133,6 +145,7 @@ type
procedure OnShow; override;
procedure OnShowFinish; override;
function Draw: boolean; override;
+ procedure RefreshTexts;
procedure FillPlayer(Item, P: integer);
procedure EaseBarIn(PlayerNumber: integer; BarType: string);
@@ -190,6 +203,22 @@ begin
begin
Display.SaveScreenShot;
end;
+ SDLK_RIGHT:
+ begin
+ if ActualRound<Length(PlaylistMedley.Stats)-1 then
+ begin
+ inc(ActualRound);
+ RefreshTexts;
+ end;
+ end;
+ SDLK_LEFT:
+ begin
+ if ActualRound>0 then
+ begin
+ dec(ActualRound);
+ RefreshTexts;
+ end;
+ end;
end;
end;
end;
@@ -203,6 +232,37 @@ begin
end;
end;
+procedure TScreenScore.RefreshTexts;
+begin
+ if (ActualRound < Length(PlaylistMedley.Stats)-1) then
+ begin
+ Text[TextArtist].Text := IntToStr(ActualRound+1) + '/' +
+ IntToStr(Length(PlaylistMedley.Stats)-1) + ': ' +
+ PlaylistMedley.Stats[ActualRound].SongArtist;
+ Text[TextTitle].Text := PlaylistMedley.Stats[ActualRound].SongTitle;
+ Text[TextTitle].Visible := true;
+ Text[TextArtistTitle].Text := IntToStr(ActualRound+1) + '/' +
+ IntToStr(Length(PlaylistMedley.Stats)-1) + ': ' +
+ PlaylistMedley.Stats[ActualRound].SongArtist +
+ ' - ' + PlaylistMedley.Stats[ActualRound].SongTitle;
+ end else
+ begin
+ if (ScreenSong.Mode = smMedley) then
+ begin
+ Text[TextArtist].Text := Language.Translate('SING_TOTAL');
+ Text[TextTitle].Visible := false;
+ Text[TextArtistTitle].Text := Language.Translate('SING_TOTAL');
+ end else
+ begin
+ Text[TextArtist].Text := PlaylistMedley.Stats[ActualRound].SongArtist;
+ Text[TextTitle].Text := PlaylistMedley.Stats[ActualRound].SongTitle;
+ Text[TextTitle].Visible := true;
+ Text[TextArtistTitle].Text := PlaylistMedley.Stats[ActualRound].SongArtist + ' - ' +
+ PlaylistMedley.Stats[ActualRound].SongTitle;
+ end;
+ end;
+end;
+
constructor TScreenScore.Create;
var
Player: integer;
@@ -293,20 +353,21 @@ begin
else
ArrayStartModifier := 0; //this should never happen
end;
+ ActualRound:=0;
+ SetLength(aPlayerScoreScreenDatas, Length(PlaylistMedley.Stats));
+ SetLength(aPlayerScoreScreenRatings, Length(PlaylistMedley.Stats));
- for P := 1 to PlayersPlay do
+ for I := 0 to Length(PlaylistMedley.Stats) - 1 do
begin
- // data
- aPlayerScoreScreenDatas[P].Bar_Y := Theme.Score.StaticBackLevel[P + ArrayStartModifier].Y;
-
- // ratings
- aPlayerScoreScreenRatings[P].RateEaseStep := 1;
- aPlayerScoreScreenRatings[P].RateEaseValue := 20;
+ for P := 1 to PlayersPlay do
+ begin
+ aPlayerScoreScreenDatas[I].Data[P].Bar_Y :=
+ Theme.Score.StaticBackLevel[P + ArrayStartModifier].Y;
+ aPlayerScoreScreenRatings[I].Data[P].RateEaseStep := 1;
+ aPlayerScoreScreenRatings[I].Data[P].RateEaseValue := 20;
+ end;
end;
-
- Text[TextArtist].Text := CurrentSong.Artist;
- Text[TextTitle].Text := CurrentSong.Title;
- Text[TextArtistTitle].Text := CurrentSong.Artist + ' - ' + CurrentSong.Title;
+ RefreshTexts;
// set visibility
case PlayersPlay of
@@ -405,18 +466,6 @@ var
PStart: integer;
PHigh: integer;
begin
-{*
- player[0].ScoreInt := 7000;
- player[0].ScoreLineInt := 2000;
- player[0].ScoreGoldenInt := 1000;
- player[0].ScoreTotalInt := 10000;
-
- player[1].ScoreInt := 2500;
- player[1].ScoreLineInt := 1100;
- player[1].ScoreGoldenInt := 900;
- player[1].ScoreTotalInt := 4500;
-*}
-
//Draw the Background
DrawBG;
@@ -548,7 +597,8 @@ begin
Text[TextNotesScore[ThemeIndex]].Alpha := (BarScore_EaseOut_Step / 100);
// total score
- Text[TextTotalScore[ThemeIndex]].Text := IntToStr(TextScore_ActualValue[PlayerNumber] + TextPhrase_ActualValue[PlayerNumber] + TextGolden_ActualValue[PlayerNumber]);
+ Text[TextTotalScore[ThemeIndex]].Text := IntToStr(TextScore_ActualValue[PlayerNumber] +
+ TextPhrase_ActualValue[PlayerNumber] + TextGolden_ActualValue[PlayerNumber]);
Text[TextTotalScore[ThemeIndex]].Alpha := (BarScore_EaseOut_Step / 100);
Text[TextTotal[ThemeIndex]].Alpha := (BarScore_EaseOut_Step / 100);
@@ -562,9 +612,13 @@ begin
end;
procedure TScreenScore.ShowRating(PlayerNumber: integer);
+const
+ rate_factor: array[0..7] of real = (2.0, 4.0, 5.0, 6.0, 7.5, 8.5, 9.0, 10.0);
var
Rating: integer;
ThemeIndex: integer;
+ rate_max: array[0..7] of integer;
+ max, I: integer;
begin
// We have to do this here because we use the same Theme Object
@@ -575,55 +629,57 @@ begin
6: ThemeIndex := ((PlayerNumber-1) mod 3) + 1 + ArrayStartModifier;
end;
- case (Player[PlayerNumber-1].ScoreTotalInt) of
- 0..2009:
- begin
- Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_TONE_DEAF');
- Rating := 0;
- end;
- 2010..4009:
- begin
- Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_AMATEUR');
- Rating := 1;
- end;
- 4010..5009:
- begin
- Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_WANNABE');
- Rating := 2;
- end;
- 5010..6009:
- begin
- Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_HOPEFUL');
- Rating := 3;
- end;
- 6010..7509:
- begin
- Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_RISING_STAR');
- Rating := 4;
- end;
- 7510..8509:
- begin
- Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_LEAD_SINGER');
- Rating := 5;
- end;
- 8510..9009:
- begin
- Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_SUPERSTAR');
- Rating := 6;
- end;
- 9010..10000:
- begin
- Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_ULTRASTAR');
- Rating := 7;
- end;
+ //build rating scores
+ if ActualRound = Length(PlaylistMedley.Stats)-1 then
+ max := MAX_SONG_SCORE
else
+ max := max_song_score_medley;
+
+ for I := 0 to 6 do
+ rate_max[I] := round(max/10*rate_factor[I])+9;
+
+ //fix 7
+ rate_max[7] := 10000;
+
+ if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[0] then
+ begin
+ Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_TONE_DEAF');
+ Rating := 0;
+ end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[1] then
+ begin
+ Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_AMATEUR');
+ Rating := 1;
+ end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[2] then
+ begin
+ Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_WANNABE');
+ Rating := 2;
+ end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[3] then
+ begin
+ Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_HOPEFUL');
+ Rating := 3;
+ end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[4] then
+ begin
+ Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_RISING_STAR');
+ Rating := 4;
+ end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[5] then
+ begin
+ Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_LEAD_SINGER');
+ Rating := 5;
+ end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[6] then
+ begin
+ Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_SUPERSTAR');
+ Rating := 6;
+ end else if PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreTotalInt<=rate_max[7] then
+ begin
+ Text[TextScore[ThemeIndex]].Text := Language.Translate('SING_SCORE_ULTRASTAR');
+ Rating := 7;
+ end else
Rating := 0; // Cheata :P
- end;
//todo: this could break if the width is not given, for instance when there's a skin with no picture for ratings
- if ( Theme.Score.StaticRatings[ThemeIndex].W > 0 ) and ( aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue > 0 ) then
+ if ( Theme.Score.StaticRatings[ThemeIndex].W > 0 ) and ( aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseValue > 0 ) then
begin
- Text[TextScore[ThemeIndex]].Alpha := aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue / Theme.Score.StaticRatings[ThemeIndex].W;
+ Text[TextScore[ThemeIndex]].Alpha := aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseValue / Theme.Score.StaticRatings[ThemeIndex].W;
end;
// end todo
@@ -642,7 +698,7 @@ begin
PosX := Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].X + (Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].W * 0.5);
PosY := Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].Y + (Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].H * 0.5); ;
- Width := aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue/2;
+ Width := aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseValue/2;
glBindTexture(GL_TEXTURE_2D, Tex_Score_Ratings[Rating].TexNum);
@@ -669,7 +725,7 @@ var
RaiseStep, MaxVal: real;
EaseOut_Step: integer;
begin
- EaseOut_Step := aPlayerScoreScreenRatings[PlayerNumber].RateEaseStep;
+ EaseOut_Step := aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseStep;
MaxVal := Theme.Score.StaticRatings[PlayerNumber + ArrayStartModifier].W;
RaiseStep := EaseOut_Step;
@@ -688,8 +744,8 @@ begin
s := p/(2*PI) * arcsin (1);
ReturnValue := MaxVal * power(2,-5 * RaiseStep) * sin( (RaiseStep * MaxVal - s) * (2 * PI) / p) + MaxVal;
- inc(aPlayerScoreScreenRatings[PlayerNumber].RateEaseStep);
- aPlayerScoreScreenRatings[PlayerNumber].RateEaseValue := ReturnValue;
+ inc(aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseStep);
+ aPlayerScoreScreenRatings[ActualRound].Data[PlayerNumber].RateEaseValue := ReturnValue;
end;
Result := ReturnValue;
@@ -716,21 +772,21 @@ begin
// EaseOut_Step is the actual step in the raising process, like the 20iest step of EaseOut_MaxSteps
if (BarType = 'Note') then
begin
- Score := Player[PlayerNumber - 1].ScoreInt;
+ Score := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber - 1].ScoreInt;
RaiseStep := BarScore_EaseOut_Step;
BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y + MaxHeight;
end
else if (BarType = 'Line') then
begin
- Score := Player[PlayerNumber - 1].ScoreLineInt;
+ Score := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber - 1].ScoreLineInt;
RaiseStep := BarPhrase_EaseOut_Step;
- BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight + MaxHeight;
+ BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarScore_ActualHeight + MaxHeight;
end
else if (BarType = 'Golden') then
begin
- Score := Player[PlayerNumber - 1].ScoreGoldenInt;
+ Score := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber - 1].ScoreGoldenInt;
RaiseStep := BarGolden_EaseOut_Step;
- BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight - aPlayerScoreScreenDatas[PlayerNumber].BarLine_ActualHeight + MaxHeight;
+ BarStartPosY := Theme.Score.StaticBackLevel[PlayerNumber + ArrayStartModifier].Y - aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarScore_ActualHeight - aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarLine_ActualHeight + MaxHeight;
end
else
begin
@@ -739,9 +795,12 @@ begin
end;
// the height dependend of the score
- Height2Reach := (Score / MAX_SONG_SCORE) * MaxHeight;
+ if ActualRound=Length(PlaylistMedley.Stats)-1 then
+ Height2Reach := (Score / MAX_SONG_SCORE) * MaxHeight
+ else
+ Height2Reach := (Score / max_song_score_medley) * MaxHeight;
- if (aPlayerScoreScreenDatas[PlayerNumber].Bar_Actual_Height < Height2Reach) then
+ if (aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].Bar_Actual_Height < Height2Reach) then
begin
// Check http://proto.layer51.com/d.aspx?f=400 for more info on easing functions
// Calculate the actual step according to the maxsteps
@@ -761,11 +820,11 @@ begin
DrawBar(BarType, PlayerNumber, BarStartPosY, NewHeight);
if (BarType = 'Note') then
- aPlayerScoreScreenDatas[PlayerNumber].BarScore_ActualHeight := NewHeight
+ aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarScore_ActualHeight := NewHeight
else if (BarType = 'Line') then
- aPlayerScoreScreenDatas[PlayerNumber].BarLine_ActualHeight := NewHeight
+ aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarLine_ActualHeight := NewHeight
else if (BarType = 'Golden') then
- aPlayerScoreScreenDatas[PlayerNumber].BarGolden_ActualHeight := NewHeight;
+ aPlayerScoreScreenDatas[ActualRound].Data[PlayerNumber].BarGolden_ActualHeight := NewHeight;
end;
procedure TscreenScore.DrawBar(BarType: string; PlayerNumber: integer; BarStartPosY: single; NewHeight: real);
@@ -839,19 +898,19 @@ begin
begin
EaseOut_Step := BarScore_EaseOut_Step;
ActualScoreValue := TextScore_ActualValue[PlayerNumber];
- ScoreReached := Player[PlayerNumber-1].ScoreInt;
+ ScoreReached := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreInt;
end;
if (ScoreType = 'Line') then
begin
EaseOut_Step := BarPhrase_EaseOut_Step;
ActualScoreValue := TextPhrase_ActualValue[PlayerNumber];
- ScoreReached := Player[PlayerNumber-1].ScoreLineInt;
+ ScoreReached := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreLineInt;
end;
if (ScoreType = 'Golden') then
begin
EaseOut_Step := BarGolden_EaseOut_Step;
ActualScoreValue := TextGolden_ActualValue[PlayerNumber];
- ScoreReached := Player[PlayerNumber-1].ScoreGoldenInt;
+ ScoreReached := PlaylistMedley.Stats[ActualRound].Player[PlayerNumber-1].ScoreGoldenInt;
end;
// EaseOut_Step is the actual step in the raising process, like the 20iest step of EaseOut_MaxSteps
@@ -893,7 +952,7 @@ var
begin
Text[TextName[Item]].Text := Ini.Name[P];
- S := IntToStr((Round(Player[P].Score) div 10) * 10);
+ S := IntToStr((Round(PlaylistMedley.Stats[ActualRound].Player[P].Score) div 10) * 10);
while (Length(S)<4) do
S := '0' + S;
Text[TextNotesScore[Item]].Text := S;
@@ -903,17 +962,17 @@ begin
//fixed: line bonus and golden notes don't show up,
// another bug: total score was shown without added golden-, linebonus
- S := IntToStr(Player[P].ScoreTotalInt);
+ S := IntToStr(PlaylistMedley.Stats[ActualRound].Player[P].ScoreTotalInt);
while (Length(S)<5) do
S := '0' + S;
Text[TextTotalScore[Item]].Text := S;
- S := IntToStr(Player[P].ScoreLineInt);
+ S := IntToStr(PlaylistMedley.Stats[ActualRound].Player[P].ScoreLineInt);
while (Length(S)<4) do
S := '0' + S;
Text[TextLineBonusScore[Item]].Text := S;
- S := IntToStr(Player[P].ScoreGoldenInt);
+ S := IntToStr(PlaylistMedley.Stats[ActualRound].Player[P].ScoreGoldenInt);
while (Length(S)<4) do
S := '0' + S;
Text[TextGoldenNotesScore[Item]].Text := S;
diff --git a/Medley/src/screens/UScreenSing.pas b/Medley/src/screens/UScreenSing.pas
index 342abac1..1bc16754 100644
--- a/Medley/src/screens/UScreenSing.pas
+++ b/Medley/src/screens/UScreenSing.pas
@@ -46,10 +46,12 @@ uses
UMenu,
UMusic,
USingScores,
+ USong,
USongs,
UTexture,
UThemes,
UPath,
+ UPathUtils,
UTime;
type
@@ -95,6 +97,11 @@ type
FadeOut: boolean;
Lyrics: TLyricEngine;
+ SongNameStatic: integer;
+ SongNameText: integer;
+
+ ApplauseSounds: array of TAudioPlaybackStream;
+
// score manager:
Scores: TSingScores;
@@ -112,6 +119,8 @@ type
function ParseInput(PressedKey: cardinal; CharCode: UCS4Char;
PressedDown: boolean): boolean; override;
function Draw: boolean; override;
+ procedure LoadNextSong;
+ procedure UpdateMedleyStats(medley_end: boolean);
procedure Finish; virtual;
procedure Pause; // toggle pause
@@ -130,7 +139,6 @@ uses
ULanguage,
UNote,
URecord,
- USong,
UDisplay,
UUnicodeUtils;
@@ -149,7 +157,14 @@ begin
begin
// when not ask before exit then finish now
if (Ini.AskbeforeDel <> 1) then
- Finish
+ begin
+ if ScreenSong.Mode=smMedley then
+ PlaylistMedley.CurrentMedleySong:=PlaylistMedley.NumMedleySongs+1;
+ Finish;
+ AudioPlayback.PlaySound(SoundLib.Back);
+ FadeOut := true;
+ FadeTo(@ScreenScore);
+ end
// else just pause and let the popup make the work
else if not Paused then
Pause;
@@ -185,9 +200,11 @@ begin
begin
// record sound hack:
//Sound[0].BufferLong
-
+ if ScreenSong.Mode=smMedley then
+ PlaylistMedley.CurrentMedleySong:=PlaylistMedley.NumMedleySongs+1;
Finish;
AudioPlayback.PlaySound(SoundLib.Back);
+ FadeOut := true;
FadeTo(@ScreenScore);
end;
@@ -307,11 +324,18 @@ begin
// <note> pausepopup is not visibile at the beginning </note>
Static[StaticPausePopup].Visible := false;
+ SongNameStatic := AddStatic(Theme.Sing.StaticSongName);
+ SongNameText := AddText(Theme.Sing.TextSongName);
+
Lyrics := TLyricEngine.Create(
Theme.LyricBar.UpperX, Theme.LyricBar.UpperY, Theme.LyricBar.UpperW, Theme.LyricBar.UpperH,
Theme.LyricBar.LowerX, Theme.LyricBar.LowerY, Theme.LyricBar.LowerW, Theme.LyricBar.LowerH);
LyricsSync := TLyricsSyncSource.Create();
+
+ SetLength(ApplauseSounds, 1);
+ FreeAndNil(ApplauseSounds[0]);
+ ApplauseSounds[0] := AudioPlayback.OpenSound(SoundPath.Append('Applause.mp3'));
end;
procedure TScreenSing.OnShow;
@@ -334,6 +358,19 @@ begin
//the song was sung to the end
SungToEnd := false;
+ //Reset Player Medley stats
+ if ScreenSong.Mode = smMedley then
+ begin
+ PlaylistMedley.CurrentMedleySong:=1;
+ PlaylistMedley.ApplausePlayed := false;
+
+ //max_song_score_medley := round(MAX_SONG_SCORE / NumMedleySongs);
+ //max_song_line_bonus_medley := round(MAX_SONG_LINE_BONUS / NumMedleySongs);
+ PlaylistMedley.NumPlayer := PlayersPlay;
+ SetLength(PlaylistMedley.Stats, 0);
+ max_song_score_medley := round(MAX_SONG_SCORE / PlaylistMedley.NumMedleySongs);
+ max_song_line_bonus_medley := round(MAX_SONG_LINE_BONUS / PlaylistMedley.NumMedleySongs);
+ end;
// reset video playback engine, to play video clip ...
fCurrentVideoPlaybackEngine := VideoPlayback;
@@ -425,10 +462,43 @@ begin
Static[StaticP3R].Visible := V3R;
Text[TextP3R].Visible := V3R;
+ if ScreenSong.Mode = smMedley then
+ begin
+ Static[SongNameStatic].Visible := true;
+ Text[SongNameText].Visible := true;
+ end else
+ begin
+ Static[SongNameStatic].Visible := false;
+ Text[SongNameText].Visible := false;
+ end;
+
+ LoadNextSong;
+
+ Log.LogStatus('End', 'OnShow');
+end;
+
+procedure TScreenSing.LoadNextSong;
+var
+ Index: integer;
+ VideoFile, BgFile: IPath;
+ success: boolean;
+
+begin
// FIXME: sets path and filename to ''
+ //AudioPlayback.Stop();
ResetSingTemp;
-
- CurrentSong := CatSongs.Song[CatSongs.Selected];
+
+ if ScreenSong.Mode <> smMedley then
+ CurrentSong := CatSongs.Song[CatSongs.Selected]
+ else
+ begin
+ CurrentSong := CatSongs.Song[PlaylistMedley.Song[PlaylistMedley.CurrentMedleySong-1]];
+ {AudioPlayback.Open(CurrentSong[CatSongsMedley.Selected].Path.Append(CatSongsMedley.Song[CatSongsMedley.Selected].Mp3));
+ CurrentSong := CatSongsMedley.Song[CatSongsMedley.Selected];
+ Text[SongNameText].Text := 'Medley ' + IntToStr(CurrentMedleySong)+'/'+
+ IntToStr(NumMedleySongs)+': '+
+ CurrentSong.Artist+' - '+CurrentSong.Title;}
+ end;
// FIXME: bad style, put the try-except into loadsong() and not here
try
@@ -445,6 +515,7 @@ begin
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();
@@ -453,10 +524,17 @@ begin
else
ScreenPopupError.ShowPopup(Language.Translate('ERROR_CORRUPT_SONG'));
// FIXME: do we need this?
- CurrentSong.Path := CatSongs.Song[CatSongs.Selected].Path;
+ //CurrentSong.Path := CatSongs.Song[CatSongs.Selected].Path;
Exit;
end;
+ if ScreenSong.Mode = smMedley then
+ begin
+ CurrentSong.SetMedleyMode;
+ Text[SongNameText].Text := IntToStr(PlaylistMedley.CurrentMedleySong) +
+ '/' + IntToStr(PlaylistMedley.NumMedleySongs) + ': ' +
+ CurrentSong.Artist + ' - ' + CurrentSong.Title;
+ end;
// reset video playback engine, to play video clip ...
fCurrentVideoPlaybackEngine.Close;
fCurrentVideoPlaybackEngine := VideoPlayback;
@@ -484,7 +562,12 @@ begin
begin
fShowVisualization := false;
fCurrentVideoPlaybackEngine := VideoPlayback;
- fCurrentVideoPlaybackEngine.Position := CurrentSong.VideoGAP + CurrentSong.Start;
+ if ScreenSong.Mode <> smMedley then
+ fCurrentVideoPlaybackEngine.Position := CurrentSong.VideoGAP + CurrentSong.Start
+ else
+ fCurrentVideoPlaybackEngine.Position := CurrentSong.VideoGAP +
+ GetTimeFromBeat(CurrentSong.Medley.StartBeat) - CurrentSong.Medley.FadeIn_time +
+ CurrentSong.Start;
fCurrentVideoPlaybackEngine.Play;
VideoLoaded := true;
end;
@@ -534,17 +617,34 @@ begin
// 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();
+ if ScreenSong.Mode <> smMedley then
+ begin
+ LyricsState.SetCurrentTime(CurrentSong.Start); //in seconds
+ LyricsState.StartTime := CurrentSong.Gap; //in milliseconds
+ if (CurrentSong.Finish > 0) then
+ LyricsState.TotalTime := CurrentSong.Finish / 1000 //in seconds
+ else
+ LyricsState.TotalTime := AudioPlayback.Length;
+ LyricsState.UpdateBeats();
- // prepare music
- AudioPlayback.Stop();
- AudioPlayback.Position := CurrentSong.Start;
+ // prepare music
+ AudioPlayback.Stop();
+ AudioPlayback.Position := CurrentSong.Start;
+ end else
+ begin
+ LyricsState.SetCurrentTime(GetTimeFromBeat(CurrentSong.Medley.StartBeat) - CurrentSong.Medley.FadeIn_time);
+ LyricsState.StartTime := CurrentSong.Gap;
+ if (CurrentSong.Finish > 0) then
+ LyricsState.TotalTime := CurrentSong.Finish / 1000 //in seconds
+ else
+ LyricsState.TotalTime := AudioPlayback.Length;
+ LyricsState.UpdateBeats();
+
+ // prepare music
+ AudioPlayback.Stop();
+ AudioPlayback.Open(CurrentSong.Path.Append(CurrentSong.Mp3));
+ AudioPlayback.Position := GetTimeFromBeat(CurrentSong.Medley.StartBeat) - CurrentSong.Medley.FadeIn_time;
+ end;
// synchronize music to the lyrics
AudioPlayback.SetSyncSource(LyricsSync);
@@ -572,7 +672,7 @@ begin
// main text
Lyrics.Clear(CurrentSong.BPM[0].BPM, CurrentSong.Resolution);
-
+
// set custom options
case Ini.LyricsFont of
0: // normal fonts
@@ -615,42 +715,82 @@ begin
end;
end; // case
- // initialize lyrics by filling its queue
- while (not Lyrics.IsQueueFull) and
+ if ScreenSong.Mode <> smMedley then
+ begin
+ // 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 Index := Low(Lines[0].Line) to High(Lines[0].Line) do
+ if Lines[0].Line[Index].TotalNotes = 0 then
+ Inc(NumEmptySentences);
+ end else
begin
- Lyrics.AddLine(@Lines[0].Line[Lyrics.LineCounter]);
+ // 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 Index := Low(Lines[0].Line) to High(Lines[0].Line) do
+ if Lines[0].Line[Index].TotalNotes = 0 then
+ Inc(NumEmptySentences);
end;
- // deactivate pause
- Paused := false;
+ //Test
+ // start lyrics
+ LyricsState.Resume();
- // kill all stars not killed yet (goldenstarstwinkle mod)
- GoldenRec.SentenceChange;
+ // start music
+ if ScreenSong.Mode <> smMedley then
+ AudioPlayback.Play()
+ else
+ begin
+ AudioPlayback.SetVolume(0.3);
+ AudioPlayback.FadeIn(CurrentSong.Medley.FadeIn_time, 1.0);
+ end;
- // set position of line bonus - line bonus end
- // set number of empty sentences for line bonus
- NumEmptySentences := 0;
- for Index := Low(Lines[0].Line) to High(Lines[0].Line) do
- if Lines[0].Line[Index].TotalNotes = 0 then
- Inc(NumEmptySentences);
+ // start timer
+ CountSkipTimeSet;
- Log.LogStatus('End', 'OnShow');
+ PlaylistMedley.ApplausePlayed := false;
end;
procedure TScreenSing.onShowFinish;
begin
- // hide cursor on singscreen show
+ //hide cursor on singscreen show
Display.SetCursor;
-
+
// start lyrics
- LyricsState.Resume();
+ //LyricsState.Resume();
// start music
- AudioPlayback.Play();
+ //AudioPlayback.Play();
// start timer
- CountSkipTimeSet;
+ //CountSkipTimeSet;
end;
procedure TScreenSing.OnHide;
@@ -672,6 +812,8 @@ var
Sec: integer;
T: integer;
CurLyricsTime: real;
+ medley_end: boolean;
+ medley_start_applause: boolean;
Line: TLyricLine;
LastWord: TLyricWord;
begin
@@ -742,7 +884,12 @@ begin
// retrieve current lyrics time, we have to store the value to avoid
// that min- and sec-values do not match
- CurLyricsTime := LyricsState.GetCurrentTime();
+ if ScreenSong.Mode <> smMedley then
+ CurLyricsTime := LyricsState.TotalTime - LyricsState.GetCurrentTime()
+ else
+ CurLyricsTime := GetTimeFromBeat(CurrentSong.Medley.EndBeat) +
+ CurrentSong.Medley.FadeOut_time - LyricsState.GetCurrentTime();
+
Min := Round(CurLyricsTime) div 60;
Sec := Round(CurLyricsTime) mod 60;
@@ -785,24 +932,44 @@ begin
// draw static menu (FG)
DrawFG;
+ if (ScreenSong.Mode = smMedley) and (LyricsState.GetCurrentTime() >
+ GetTimeFromBeat(CurrentSong.Medley.EndBeat) + CurrentSong.Medley.FadeOut_time) then
+ medley_end := true
+ else
+ medley_end := false;
+
+ if (ScreenSong.Mode = smMedley) and (LyricsState.GetCurrentTime() >
+ GetTimeFromBeat(CurrentSong.Medley.EndBeat)) then
+ medley_start_applause := true
+ else
+ medley_start_applause := false;
+
// 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
+ if (not AudioPlayback.Finished) and not medley_end and ((CurrentSong.Finish = 0) or
(LyricsState.GetCurrentTime() * 1000 <= CurrentSong.Finish)) then
begin
// analyze song if not paused
if (not Paused) then
+ begin
Sing(Self);
+ //Update Medley Stats
+ if (ScreenSong.Mode = smMedley) and not FadeOut then
+ UpdateMedleyStats(medley_start_applause);
+ end;
end
else
begin
if (not FadeOut) then
begin
Finish;
- FadeOut := true;
- FadeTo(@ScreenScore);
+ if ScreenSong.Mode = smNormal then
+ begin
+ FadeOut := true;
+ FadeTo(@ScreenScore);
+ end;
end;
end;
end;
@@ -850,7 +1017,49 @@ begin
Result := true;
end;
+procedure TScreenSing.UpdateMedleyStats(medley_end: boolean);
+var
+ len, num, I : integer;
+ lastline: boolean;
+ vol: real;
+begin
+ len := Length(PlaylistMedley.Stats);
+ num := PlaylistMedley.NumPlayer;
+
+ if (PlaylistMedley.CurrentMedleySong>len) and
+ (PlaylistMedley.CurrentMedleySong<=PlaylistMedley.NumMedleySongs) then
+ begin
+ inc(len);
+ SetLength(PlaylistMedley.Stats, len);
+ SetLength(PlaylistMedley.Stats[len-1].Player, num);
+ PlaylistMedley.Stats[len-1].SongArtist := CurrentSong.Artist;
+ PlaylistMedley.Stats[len-1].SongTitle := CurrentSong.Title;
+ end;
+
+ if (PlaylistMedley.CurrentMedleySong<=PlaylistMedley.NumMedleySongs) then
+ for I := 0 to num - 1 do
+ PlaylistMedley.Stats[len-1].Player[I] := Player[I];
+
+ if medley_end and not PlaylistMedley.ApplausePlayed and
+ (PlaylistMedley.CurrentMedleySong<=PlaylistMedley.NumMedleySongs) then
+ begin
+ PlaylistMedley.ApplausePlayed:=true;
+ AudioPlayback.PlaySound(ApplauseSounds[0]);
+ end;
+
+ if(LyricsState.GetCurrentTime() > GetTimeFromBeat(CurrentSong.Medley.EndBeat)) then
+ begin
+ vol := 1-(LyricsState.GetCurrentTime() - GetTimeFromBeat(CurrentSong.Medley.EndBeat))/
+ CurrentSong.Medley.FadeOut_time ;
+ AudioPlayback.SetVolume(vol); //used as fade out!
+ end;
+end;
+
procedure TScreenSing.Finish;
+var
+ I, J: integer;
+ len, num: integer;
+ Color: TRGB;
begin
AudioInput.CaptureStop;
AudioPlayback.Stop;
@@ -879,6 +1088,91 @@ begin
end;
SetFontItalic(false);
+
+ if ScreenSong.Mode = smMedley then
+ begin
+ {***** just a quick and dirty fix.... *******}
+ // setup score manager
+ Scores.ClearPlayers; // clear old player values
+
+ Color.R := 0;
+ Color.G := 0;
+ Color.B := 0;
+ // add new players
+ for I := 0 to PlayersPlay - 1 do
+ begin
+ Scores.AddPlayer(Tex_ScoreBG[I], Color);
+ end;
+
+ Scores.Init; // get positions for players
+
+ // prepare players
+ SetLength(Player, PlayersPlay);
+ {***** end of quick and dirty fix ******}
+
+ if not FadeOut then
+ begin
+ inc(PlaylistMedley.CurrentMedleySong);
+ if PlaylistMedley.CurrentMedleySong<=PlaylistMedley.NumMedleySongs then
+ begin
+ //AudioPlayback.PlaySound(SoundLib.Applause);
+ LoadNextSong;
+ end else
+ begin
+ //build sums
+ len := Length(PlaylistMedley.Stats);
+ num := PlaylistMedley.NumPlayer;
+
+ SetLength(PlaylistMedley.Stats, len+1);
+ SetLength(PlaylistMedley.Stats[len].Player, num);
+
+ for J := 0 to len - 1 do
+ begin
+ for I := 0 to num - 1 do
+ begin
+ PlaylistMedley.Stats[len].Player[I].Score :=
+ PlaylistMedley.Stats[len].Player[I].Score +
+ PlaylistMedley.Stats[J].Player[I].Score;
+
+ PlaylistMedley.Stats[len].Player[I].ScoreLine :=
+ PlaylistMedley.Stats[len].Player[I].ScoreLine +
+ PlaylistMedley.Stats[J].Player[I].ScoreLine;
+
+ PlaylistMedley.Stats[len].Player[I].ScoreGolden :=
+ PlaylistMedley.Stats[len].Player[I].ScoreGolden +
+ PlaylistMedley.Stats[J].Player[I].ScoreGolden;
+
+ PlaylistMedley.Stats[len].Player[I].ScoreInt :=
+ PlaylistMedley.Stats[len].Player[I].ScoreInt +
+ PlaylistMedley.Stats[J].Player[I].ScoreInt;
+
+ PlaylistMedley.Stats[len].Player[I].ScoreLineInt :=
+ PlaylistMedley.Stats[len].Player[I].ScoreLineInt +
+ PlaylistMedley.Stats[J].Player[I].ScoreLineInt;
+
+ PlaylistMedley.Stats[len].Player[I].ScoreGoldenInt :=
+ PlaylistMedley.Stats[len].Player[I].ScoreGoldenInt +
+ PlaylistMedley.Stats[J].Player[I].ScoreGoldenInt;
+
+ PlaylistMedley.Stats[len].Player[I].ScoreTotalInt :=
+ PlaylistMedley.Stats[len].Player[I].ScoreTotalInt +
+ PlaylistMedley.Stats[J].Player[I].ScoreTotalInt;
+ end; //of for I
+ end; //of for J
+
+ FadeOut:=true;
+ FadeTo(@ScreenScore);
+ end;
+ end;
+ end else
+ begin
+ SetLength(PlaylistMedley.Stats, 1);
+ SetLength(PlaylistMedley.Stats[0].Player, PlayersPlay);
+ for I := 0 to PlayersPlay - 1 do
+ PlaylistMedley.Stats[0].Player[I] := Player[I];
+ PlaylistMedley.Stats[0].SongArtist := CurrentSong.Artist;
+ PlaylistMedley.Stats[0].SongTitle := CurrentSong.Title;
+ end;
end;
procedure TScreenSing.OnSentenceEnd(SentenceIndex: cardinal);
@@ -904,10 +1198,19 @@ begin
Exit;
// set max song score
- if (Ini.LineBonus = 0) then
- MaxSongScore := MAX_SONG_SCORE
- else
- MaxSongScore := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS;
+ if ScreenSong.Mode <> smMedley then
+ begin
+ if (Ini.LineBonus = 0) then
+ MaxSongScore := MAX_SONG_SCORE
+ else
+ MaxSongScore := MAX_SONG_SCORE - MAX_SONG_LINE_BONUS;
+ end else
+ begin
+ if (Ini.LineBonus = 0) then
+ MaxSongScore := max_song_score_medley
+ else
+ MaxSongScore := max_song_score_medley - max_song_line_bonus_medley;
+ end;
// Note: ScoreValue is the sum of all note values of the song
MaxLineScore := MaxSongScore * (Line.TotalNotes / Lines[0].ScoreValue);
@@ -941,7 +1244,11 @@ begin
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) -
+ if ScreenSong.Mode <> smMedley then
+ LineBonus := MAX_SONG_LINE_BONUS / (Length(Lines[0].Line) -
+ NumEmptySentences)
+ else
+ LineBonus := max_song_line_bonus_medley / (Length(Lines[0].Line) -
NumEmptySentences);
// apply line-bonus
CurrentPlayer.ScoreLine :=
diff --git a/Medley/src/screens/UScreenSong.pas b/Medley/src/screens/UScreenSong.pas
index bd5eebe5..bab2ef51 100644
--- a/Medley/src/screens/UScreenSong.pas
+++ b/Medley/src/screens/UScreenSong.pas
@@ -53,6 +53,8 @@ uses
UTime;
type
+ TVisArr = array of integer;
+
TScreenSong = class(TMenu)
private
Equalizer: Tms_Equalizer;
@@ -138,6 +140,9 @@ type
procedure HideCatTL;// Show Cat in Tob left
procedure Refresh; //Refresh Song Sorting
procedure ChangeMusic;
+
+ function getVisibleMedleyArr(): TVisArr;
+ procedure StartMedley(num: integer);
//Party Mode
procedure SelectRandomSong;
procedure SetJoker;
@@ -345,6 +350,21 @@ begin
Exit;
end;
+ Ord('S'):
+ begin
+ if (Length(getVisibleMedleyArr()) > 0) and (Mode = smNormal) and
+ (CatSongs.Song[Interaction].Medley.Source = msTag) then
+ begin
+ StartMedley(0);
+ end;
+ end;
+ Ord('D'):
+ begin
+ if (Length(getVisibleMedleyArr()) > 0) and (Mode = smNormal) then
+ begin
+ StartMedley(5);
+ end;
+ end;
Ord('M'): //Show SongMenu
begin
if (Songs.SongList.Count > 0) then
@@ -1002,6 +1022,11 @@ begin
// Set texts
Text[TextArtist].Text := CatSongs.Song[Interaction].Artist;
Text[TextTitle].Text := CatSongs.Song[Interaction].Title;
+
+ //medley mod
+ if CatSongs.Song[Interaction].Medley.Source = msTag then
+ Text[TextTitle].Text := Text[TextTitle].Text + '[M]';
+
if (Ini.TabsAtStartup = 1) and (CatSongs.CatNumShow = -1) then
begin
Text[TextNumber].Text := IntToStr(CatSongs.Song[Interaction].OrderNum) + '/' + IntToStr(CatSongs.CatCount);
@@ -1496,6 +1521,9 @@ begin
AudioPlayback.Stop;
+ if Mode = smMedley then
+ Mode := smNormal;
+
if Ini.Players <= 3 then PlayersPlay := Ini.Players + 1;
if Ini.Players = 4 then PlayersPlay := 6;
@@ -1725,19 +1753,29 @@ end;
procedure TScreenSong.StartMusicPreview();
var
- Song: TSong;
+ Song: TSong;
+ success: boolean;
begin
AudioPlayback.Close();
+ if CatSongs.Song[Interaction].Main then
+ Exit;
+
Song := CatSongs.Song[Interaction];
- if not assigned(Song) then
+ if not assigned(Song) or Song.Main then
Exit;
if AudioPlayback.Open(Song.Path.Append(Song.Mp3)) then
begin
PreviewOpened := Interaction;
-
- AudioPlayback.Position := AudioPlayback.Length / 4;
+
+ if Song.Medley.Source <> msNone then
+ begin
+ CurrentSong := Song;
+ AudioPlayback.Position := GetTimeFromBeat(Song.Medley.StartBeat);
+ end else
+ AudioPlayback.Position := AudioPlayback.Length / 4;
+
// set preview volume
if (Ini.PreviewFading = 0) then
begin
@@ -1747,6 +1785,10 @@ begin
end
else
begin
+ AudioPlayback.Position := AudioPlayback.Position - Ini.PreviewFading;
+ if AudioPlayback.Position<0 then
+ AudioPlayback.Position := 0;
+
// music fade enabled: start muted and fade-in
AudioPlayback.SetVolume(0);
AudioPlayback.FadeIn(Ini.PreviewFading, IPreviewVolumeVals[Ini.PreviewVolume]);
@@ -1796,6 +1838,106 @@ begin
end;
end;
+function TScreenSong.getVisibleMedleyArr(): TVisArr;
+var
+ I: integer;
+ res: TVisArr;
+begin
+ SetLength(res, 0);
+ for I := 0 to Length(CatSongs.Song) - 1 do
+ begin
+ if CatSongs.Song[I].Visible and (CatSongs.Song[I].Medley.Source = msTag) then
+ begin
+ SetLength(res, Length(res)+1);
+ res[Length(res)-1] := I;
+ end;
+ end;
+ Result := res;
+end;
+
+//start Medley round
+procedure TScreenSong.StartMedley(num: integer);
+ procedure AddSong(SongNr: integer);
+ begin
+ SetLength(PlaylistMedley.Song, Length(PlaylistMedley.Song)+1);
+ PlaylistMedley.Song[Length(PlaylistMedley.Song)-1] := SongNr;
+ end;
+
+ function SongAdded(SongNr: integer): boolean;
+ var
+ i: integer;
+ skipped :boolean;
+ begin
+ skipped := false;
+ for i := 0 to Length(PlaylistMedley.Song) - 1 do
+ begin
+ if (SongNr=PlaylistMedley.Song[i]) then
+ begin
+ skipped:=true;
+ break;
+ end;
+ end;
+ Result:=skipped;
+ end;
+
+ function NumSongsAdded(): Integer;
+ begin
+ Result := Length(PlaylistMedley.Song);
+ end;
+
+ function GetNextSongNr: integer;
+ var
+ I, num: integer;
+ unused_arr: array of integer;
+ visible_arr: TVisArr;
+ begin
+ SetLength(unused_arr, 0);
+ visible_arr := getVisibleMedleyArr();
+ for I := 0 to Length(visible_arr) - 1 do
+ begin
+ if (not SongAdded(visible_arr[I])) then
+ begin
+ SetLength(unused_arr, Length(unused_arr)+1);
+ unused_arr[Length(unused_arr)-1] := visible_arr[I];
+ end;
+ end;
+
+ num := random(Length(unused_arr));
+ Result := unused_arr[num];
+end;
+
+var
+ I: integer;
+ VS: integer;
+
+begin
+ StopMusicPreview();
+ Mode := smMedley;
+
+ if num>0 then
+ begin
+ VS := Length(getVisibleMedleyArr());
+ if VS < num then
+ PlaylistMedley.NumMedleySongs := VS
+ else
+ PlaylistMedley.NumMedleySongs := num;
+
+ Randomize;
+ //set up Playlist Medley
+ SetLength(PlaylistMedley.Song, 0);
+ for I := 0 to PlaylistMedley.NumMedleySongs - 1 do
+ begin
+ AddSong(GetNextSongNr);
+ end;
+ end else
+ begin
+ SetLength(PlaylistMedley.Song, 1);
+ PlaylistMedley.Song[0] := Interaction;
+ PlaylistMedley.NumMedleySongs := 1;
+ end;
+ FadeTo(@ScreenSing);
+end;
+
procedure TScreenSong.SkipTo(Target: cardinal);
var
i: integer;