We now have lyric support!.. I gotta sleep some, will add an option to turn lyrics on/off when I get home from work
This commit is contained in:
@@ -20,6 +20,8 @@ bool LyricsLoader::LoadFromLRCFile( CString sPath, Song &out )
|
|||||||
|
|
||||||
LRCFile lrc;
|
LRCFile lrc;
|
||||||
bool bResult = lrc.ReadFile( sPath );
|
bool bResult = lrc.ReadFile( sPath );
|
||||||
|
CString m_sLastFoundColor = "0x00ff00";
|
||||||
|
|
||||||
if( !bResult )
|
if( !bResult )
|
||||||
RageException::Throw( "Error opening file '%s' for reading.", sPath.GetString() );
|
RageException::Throw( "Error opening file '%s' for reading.", sPath.GetString() );
|
||||||
|
|
||||||
@@ -39,35 +41,29 @@ bool LyricsLoader::LoadFromLRCFile( CString sPath, Song &out )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle the data
|
// handle the data
|
||||||
if( 0==stricmp(sValueName,"COLOUR") )
|
if( 0==stricmp(sValueName,"COLOUR") || 0==stricmp(sValueName,"COLOR") )
|
||||||
{
|
{
|
||||||
// set color var here
|
// set color var here for this segment
|
||||||
LOG->Trace("\n\n\n Got color tag from lyric file \n\n\n");
|
m_sLastFoundColor = sValueData;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* If we've gotten this far, and no other statement caught
|
/* If we've gotten this far, and no other statement caught
|
||||||
this value before this does, assume it's a time value.
|
this value before this does, assume it's a time value. */
|
||||||
Add the lyric segment! */
|
|
||||||
|
|
||||||
// For the sorting routine, we need a numerical version of the 'time'
|
LyricSegment LYRICSTRING;
|
||||||
CString sTempTime = sValueName.GetBuffer();
|
LYRICSTRING.m_sColor = m_sLastFoundColor;
|
||||||
sTempTime.Replace( ".", "" );
|
LYRICSTRING.m_fStartTime = TimeToSeconds(sValueName);
|
||||||
sTempTime.Replace( ":", "." );
|
LYRICSTRING.m_sLyric = sValueData;
|
||||||
|
|
||||||
// float m_fStartTime = (float)atof(sTempTime); // hush "variable not referenced"
|
LYRICSTRING.m_sLyric.Replace( "\\", "\\" ); // to avoid possible screw-ups
|
||||||
CString m_sLyric = sValueData;
|
// if someone uses a \ for whatever
|
||||||
CString m_sStartTime = sValueName;
|
// reason in their lyrics -- Miryokuteki
|
||||||
//--
|
|
||||||
|
|
||||||
//LyricSegment MOOZ;
|
LYRICSTRING.m_sLyric.Replace( "|","\n" ); // Pipe symbols denote a new line in LRC files
|
||||||
//MOOZ.m_fStartTime = (float)atof((LPCTSTR)sTempTime);
|
out.AddLyricSegment( LYRICSTRING );
|
||||||
//MOOZ.m_sStartTime = sValueName.GetBuffer();
|
|
||||||
//MOOZ.m_sLyric = sValueData.GetBuffer();
|
|
||||||
|
|
||||||
//out.AddLyricSegment( LyricSegment( m_fStartTime, m_sLyric, m_sStartTime ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,9 +32,13 @@
|
|||||||
#include "RageTimer.h"
|
#include "RageTimer.h"
|
||||||
#include "ScoreKeeperMAX2.h"
|
#include "ScoreKeeperMAX2.h"
|
||||||
|
|
||||||
|
#include "LyricsLoader.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Defines
|
// Defines
|
||||||
//
|
//
|
||||||
|
#define LYRICS_X THEME->GetMetricF("ScreenGameplay","LyricsX")
|
||||||
|
#define LYRICS_Y THEME->GetMetricF("ScreenGameplay","LyricsY")
|
||||||
#define SONGSEL_SCREEN THEME->GetMetric("ScreenGameplay","SongSelectScreen")
|
#define SONGSEL_SCREEN THEME->GetMetric("ScreenGameplay","SongSelectScreen")
|
||||||
#define MAXCOMBO_X THEME->GetMetricF("ScreenGameplay","MaxComboX")
|
#define MAXCOMBO_X THEME->GetMetricF("ScreenGameplay","MaxComboX")
|
||||||
#define MAXCOMBO_Y THEME->GetMetricF("ScreenGameplay","MaxComboY")
|
#define MAXCOMBO_Y THEME->GetMetricF("ScreenGameplay","MaxComboY")
|
||||||
@@ -110,9 +114,32 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Lyrics loader
|
||||||
|
|
||||||
|
LyricsLoader LL;
|
||||||
|
if( GAMESTATE->m_pCurSong->GetLyricsPath() != "NULL" )
|
||||||
|
{
|
||||||
|
LL.LoadFromLRCFile(GAMESTATE->m_pCurSong->GetLyricsPath(), *GAMESTATE->m_pCurSong);
|
||||||
|
|
||||||
m_textLyrics.LoadFromFont( THEME->GetPathTo("Fonts","normal") );
|
m_textLyrics.LoadFromFont( THEME->GetPathTo("Fonts","normal") );
|
||||||
m_textLyrics.SetXY( 100,100 );
|
m_textLyrics.SetXY( LYRICS_X,LYRICS_Y );
|
||||||
m_textLyrics.SetDiffuse( RageColor(1,1,1,1) );
|
m_textLyrics.SetDiffuse( RageColor(1,1,1,1) );
|
||||||
|
// We need to use the Color Tag that's in m_pCurSong->m_LyricSegments[?].m_sColor
|
||||||
|
// But since the value there is in Hex, need to convert to RageColor I guess.
|
||||||
|
// Until that gets done, this will default to white (&HFFFFFF)
|
||||||
|
|
||||||
|
m_bHasLyrics = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_bHasLyrics = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ~~
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if( GAMESTATE->m_pCurSong == NULL && GAMESTATE->m_pCurCourse == NULL )
|
if( GAMESTATE->m_pCurSong == NULL && GAMESTATE->m_pCurCourse == NULL )
|
||||||
@@ -404,7 +431,7 @@ ScreenGameplay::ScreenGameplay( bool bDemonstration )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//this->AddChild( &m_textLyrics ); -- THIS IS NOT DONE YET!! (Miryokuteki)
|
this->AddChild( &m_textLyrics );// -- THIS IS NOT DONE YET!! (Miryokuteki)
|
||||||
|
|
||||||
|
|
||||||
m_textAutoPlay.LoadFromFont( THEME->GetPathTo("Fonts","header2") );
|
m_textAutoPlay.LoadFromFont( THEME->GetPathTo("Fonts","header2") );
|
||||||
@@ -818,8 +845,52 @@ void ScreenGameplay::Update( float fDeltaTime )
|
|||||||
//
|
//
|
||||||
// Check if we should show lyrics now
|
// Check if we should show lyrics now
|
||||||
//
|
//
|
||||||
|
if( (m_bHasLyrics) ) // Every song without lyrics would crash here.. bug fix -- Miryokuteki
|
||||||
|
{
|
||||||
m_fLyricsTime += fDeltaTime;
|
m_fLyricsTime += fDeltaTime;
|
||||||
m_textLyrics.SetText( SecondsToTime( m_fLyricsTime ) );
|
float fStartTime = (GAMESTATE->m_pCurSong->m_LyricSegments[m_iCurLyricNumber].m_fStartTime);
|
||||||
|
|
||||||
|
// Make sure we don't go over the array's boundry
|
||||||
|
if( m_iCurLyricNumber <= GAMESTATE->m_pCurSong->m_LyricSegments.size() )
|
||||||
|
{
|
||||||
|
// Check if it's time to animate the old lyrics to off-screen
|
||||||
|
if( (fStartTime - m_fLyricsTime) <= .30 || (fStartTime - m_fLyricsTime) <= -.30f)
|
||||||
|
{
|
||||||
|
m_textLyrics.FadeOff( 0, "foldy", .20f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_fLyricsTime >= fStartTime )
|
||||||
|
{
|
||||||
|
/*I figure for longer lines of text, the Lyric display object should
|
||||||
|
be scaled down, if needed, by the .ScaleTo() function. But somehow
|
||||||
|
it jus ain't working for me at all.. anyone able to do this
|
||||||
|
properly?? We prolly should also add detection of where to put
|
||||||
|
the Lyric object, if the arrows are on reverse? Jus an idea,
|
||||||
|
but it kinda defeats the purpose of the Lyric object X/Y being a
|
||||||
|
theme element :)
|
||||||
|
|
||||||
|
BTW: Once the function is done, this will also be where the color
|
||||||
|
of this lyric block will be set -- Miryokuteki */
|
||||||
|
//m_textLyrics.SetDiffuse(COLOR HERE);
|
||||||
|
|
||||||
|
/*if( GAMESTATE->m_pCurSong->m_LyricSegments[m_iCurLyricNumber].m_sLyric == "" || GAMESTATE->m_pCurSong->m_LyricSegments[m_iCurLyricNumber].m_sLyric == " " )
|
||||||
|
{
|
||||||
|
For some reason, once this fades off, it never comes back when
|
||||||
|
it's called! -- Miryokuteki
|
||||||
|
|
||||||
|
m_textLyrics.FadeOff( 0, "fade", .10f );
|
||||||
|
m_iCurLyricNumber++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*/
|
||||||
|
m_textLyrics.FadeOn( 0, "foldy", .20f );
|
||||||
|
m_textLyrics.SetText( GAMESTATE->m_pCurSong->m_LyricSegments[m_iCurLyricNumber].m_sLyric );
|
||||||
|
m_iCurLyricNumber++;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Update players' alive time
|
// Update players' alive time
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ protected:
|
|||||||
|
|
||||||
float m_fTimeLeftBeforeDancingComment; // this counter is only running while STATE_DANCING
|
float m_fTimeLeftBeforeDancingComment; // this counter is only running while STATE_DANCING
|
||||||
float m_fLyricsTime;
|
float m_fLyricsTime;
|
||||||
|
int m_iCurLyricNumber;
|
||||||
|
bool m_bHasLyrics;
|
||||||
|
|
||||||
|
|
||||||
Background m_Background;
|
Background m_Background;
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ const float TWEEN_TIME = 0.5f;
|
|||||||
static const ScreenMessage SM_AllowOptionsMenuRepeat = ScreenMessage(SM_User+1);
|
static const ScreenMessage SM_AllowOptionsMenuRepeat = ScreenMessage(SM_User+1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ScreenSelectMusic::ScreenSelectMusic()
|
ScreenSelectMusic::ScreenSelectMusic()
|
||||||
{
|
{
|
||||||
LOG->Trace( "ScreenSelectMusic::ScreenSelectMusic()" );
|
LOG->Trace( "ScreenSelectMusic::ScreenSelectMusic()" );
|
||||||
|
|||||||
+12
-46
@@ -77,16 +77,6 @@ void SortBackgroundChangesArray( vector<BackgroundChange> &arrayBackgroundChange
|
|||||||
sort( arrayBackgroundChanges.begin(), arrayBackgroundChanges.end(), CompareBackgroundChanges );
|
sort( arrayBackgroundChanges.begin(), arrayBackgroundChanges.end(), CompareBackgroundChanges );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CompareLyricSegments(const LyricSegment &seg1, const LyricSegment &seg2)
|
|
||||||
{
|
|
||||||
return seg1.m_fStartTime < seg2.m_fStartTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SortLyricSegmentsArray( vector<LyricSegment> &arrayLyricSegments )
|
|
||||||
{
|
|
||||||
sort( arrayLyricSegments.begin(), arrayLyricSegments.end(), CompareLyricSegments );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// Song
|
// Song
|
||||||
@@ -137,7 +127,6 @@ void Song::AddBackgroundChange( BackgroundChange seg )
|
|||||||
void Song::AddLyricSegment( LyricSegment seg )
|
void Song::AddLyricSegment( LyricSegment seg )
|
||||||
{
|
{
|
||||||
m_LyricSegments.push_back( seg );
|
m_LyricSegments.push_back( seg );
|
||||||
SortLyricSegmentsArray( m_LyricSegments );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -309,36 +298,6 @@ bool Song::LoadWithoutCache( CString sDir )
|
|||||||
bool success = ld->LoadFromDir( sDir, *this );
|
bool success = ld->LoadFromDir( sDir, *this );
|
||||||
delete ld;
|
delete ld;
|
||||||
|
|
||||||
LOG->Trace("\n\n\n SONG NAME:: %s", this->GetDisplayMainTitle().GetBuffer() );
|
|
||||||
/*
|
|
||||||
if( this->GetDisplayMainTitle().GetBuffer() == "Future Girls" )
|
|
||||||
* This is incorrect; it's comparing two string pointers, which doesn't
|
|
||||||
* work like you expect. Drop the "GetBuffer".
|
|
||||||
*
|
|
||||||
* I don't believe we should be loading lyrics into Song directly, as part of
|
|
||||||
* the data. Instead, I'd treat it as a separate resource (like images
|
|
||||||
* and movies) and load it on demand; eg. into a LyricsDisplay actor. The
|
|
||||||
* primary reason is that it's more modular: the Song class is already too
|
|
||||||
* monolithic. (Note that lyrics can get substantially more detailed; for
|
|
||||||
* example, we might want to add SSA support.)
|
|
||||||
*
|
|
||||||
* I'm still undecided, personally, as to whether we should ultimately
|
|
||||||
* store lyrics inside the SM or in a separate file, but since we'll want
|
|
||||||
* to support LRC anyway (which is what you're doing) and we don't need to
|
|
||||||
* actually write it to disk at this point, we don't have to decide on this yet.
|
|
||||||
* (I'm leaning to changing my opinion to leaving it in a separate file, but
|
|
||||||
* I need to think on it some more.)
|
|
||||||
*
|
|
||||||
* -glenn */
|
|
||||||
/* if( this->GetDisplayMainTitle() == "Future Girls" ) <- this is what you wanted
|
|
||||||
{
|
|
||||||
LOG->Trace("AAA");
|
|
||||||
} */
|
|
||||||
if( HasLyrics() )
|
|
||||||
{
|
|
||||||
LOG->Trace("\n\n\n LOAD LYRICS HERE!! \n\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!success)
|
if(!success)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -603,8 +562,8 @@ void Song::TidyUpData()
|
|||||||
|
|
||||||
|
|
||||||
LOG->Trace("Looking for lyrics..");
|
LOG->Trace("Looking for lyrics..");
|
||||||
//if( HasLyrics() )
|
if( HasLyrics() )
|
||||||
//{
|
{
|
||||||
//Check if there is a lyric file in here
|
//Check if there is a lyric file in here
|
||||||
CStringArray arrayLyricFiles;
|
CStringArray arrayLyricFiles;
|
||||||
GetDirListing(m_sSongDir + CString("*.lrc"), arrayLyricFiles );
|
GetDirListing(m_sSongDir + CString("*.lrc"), arrayLyricFiles );
|
||||||
@@ -614,7 +573,7 @@ void Song::TidyUpData()
|
|||||||
LyricsLoader ll;
|
LyricsLoader ll;
|
||||||
ll.LoadFromLRCFile(m_sLyricsFile.GetBuffer(), *GAMESTATE->m_pCurSong);
|
ll.LoadFromLRCFile(m_sLyricsFile.GetBuffer(), *GAMESTATE->m_pCurSong);
|
||||||
}
|
}
|
||||||
//}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1260,8 +1219,15 @@ CString Song::GetBannerPath() const
|
|||||||
|
|
||||||
CString Song::GetLyricsPath() const
|
CString Song::GetLyricsPath() const
|
||||||
{
|
{
|
||||||
LOG->Trace("\n\n\n TRYING TO GET LYRICS FROM:: %s%s", m_sSongDir.GetString(), m_sBannerFile.GetString());
|
//LOG->Trace("\n\n\n TRYING TO GET LYRICS FROM:: %s%s", m_sSongDir, m_sLyricsFile);
|
||||||
return m_sSongDir+m_sLyricsFile;
|
CStringArray arrayLyricFiles;
|
||||||
|
GetDirListing(m_sSongDir + CString("*.lrc"), arrayLyricFiles );
|
||||||
|
if( !arrayLyricFiles.empty() )
|
||||||
|
{
|
||||||
|
return m_sSongDir+arrayLyricFiles[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return CString("NULL");
|
||||||
}
|
}
|
||||||
|
|
||||||
CString Song::GetCDTitlePath() const
|
CString Song::GetCDTitlePath() const
|
||||||
|
|||||||
@@ -51,11 +51,11 @@ void SortBackgroundChangesArray( vector<BackgroundChange> &arrayBackgroundChange
|
|||||||
|
|
||||||
struct LyricSegment
|
struct LyricSegment
|
||||||
{
|
{
|
||||||
LyricSegment() { m_fStartTime = -1; };
|
float m_fStartTime;
|
||||||
LyricSegment( float a, CString m_sLyric, CString m_sStartTime ) { m_fStartTime = a, m_sLyric = m_sLyric, m_sStartTime = m_sStartTime; };
|
|
||||||
float m_fStartTime; // For the sorting routine
|
|
||||||
CString m_sLyric;
|
CString m_sLyric;
|
||||||
CString m_sStartTime;
|
CString m_sColor; /* This will eventually be a RAGECOLOR, but until a function
|
||||||
|
is made to convert a hex color to RAGECOLOR, it's a CString.
|
||||||
|
This allows for multiple colors of lyric blocks. -- Miryokuteki */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user