various changes from sm4 and sm-ssc (svn); see updated changelog for the full information

This commit is contained in:
AJ Kelly
2010-02-18 23:17:24 -06:00
parent f9bfc80fa9
commit 5c5ef54a48
26 changed files with 436 additions and 260 deletions
+132
View File
@@ -9,6 +9,138 @@ Not all changes are documented, for various reasons.
supported but exist anyways.)
_____________________________________________________________________________
20100218
--------
* Added Fonts/ScreenReloadSongs LoadingText, making the text on
ScreenReloadSongs themeable.
* Added Fonts/NoteField MeasureNumber, ScreenGameplay debug,
ScreenGameplaySyncMachine SyncInfo.
20100216
--------
sm4svn r28309: Fix crash in course mode, another (and, from the looks of it,
the last) dumb bug this block o' hack caused [vyhd]
20100215
--------
Some more sm4svn commits:
* r28304: read-ahead tweaks; support os read cache flushing [Glenn Maynard]
* r28306: experimental code for storing Lua data in Profiles and
converting between XML and Lua data. [vyhd]
20100214
--------
sm4svn catchup... Noticing a pattern?
* r28293: add RageFile::GetFD for specialized file handling [Glenn Maynard]
(FD meaning File Descriptor -aj)
* r28294: "remove absolutely pointless revision tags that cause [aclocal.m4 and
ltmain.sh in libmad] to constantly show up as modified" [Glenn Maynard]
* r28295: [fix] copy and paste error [Glenn Maynard]
* r28296: Experimental: hint the OS caching to avoid skips when starting/looping
movies [Glenn Maynard]
* r28297: fix a bug, then disable the whole thing for now due to dup()
braindamage; Linux version works fine (posix_fadvise) [Glenn Maynard]
* r28299: fix m_iFilePos updating on seek [Glenn Maynard]
* r28300: Added theme metric for Routine noteskins (to enforce separate noteskins
per player, or at least conscious thought toward that issue), added fix for
ScreenEdit only handling switching players on dance-routine [vyhd]
(editor's note: the new metrics are RoutineNoteSkinP1 and RoutineNoteSkinP2 -aj)
* r28303: make sure routine always writes as two charts, even if only one has
steps; DEBUG_ASSERT -> ASSERT [Glenn Maynard]
20100213
--------
Even more sm4svn catchup:
* r28277: remove preferred group filtering (leaving the setting in for later use) [Glenn Maynard]
* r28279: simplify SongUtil::GetStepsTypeAndDifficultyFromSortOrder [Glenn Maynard]
* r28281: fix SSM crashes when selecting a song with only one
player enabled [Glenn Maynard]
* r28284: add Style::GetUsesCenteredArrows (doubles + routine)
* r28285: sanity check (on ScreenGameplay) [Glenn Maynard]
* various commits related to routine mode [Glenn Maynard]
(specifically, r28282,r28286,r28287,r28289,r28290)
* r28291: fix pump routine right side DownLeft not drawn [Chris Danford]
* r28292: easier debug stepping [Chris Danford]
20100211
--------
sm-ssc:
* Fix a crash with AutoKeysounds.
Playing catch-up with sm4svn. This happens a lot.
* r28273: "Added more logical handling of Routine mode selection
(see source code comments); hopefully, we can write up a more standard
solution to this later, since this is kind of a hack" [vyhd]
* r28274: course type param to GetCustomDifficulty is optional [Glenn Maynard]
* r28276: Lua binding for MeterDisplay. Allow setting and changing the
width dynamically. Phase out the "StreamWidth" node property; set it with
SetStreamWidth instead. [Glenn Maynard]
20100210
--------
* Possible fix for handling of delays in autoplay. May also fix things
elsewhere (editor?), but that is untested. Autoplay seemed to work well
with Uprock (the song), so I have no complaints. -aj
* Glenn started to revert some of Frieza's code in sm4:
* "Personally, there is an assert for checking if the noteskin is not empty.
Based on other code, it seems like the noteskin would have to be set
somewhere else. If this is a problem somewhere else, find where it's a
problem and don't patch this function." -aj re: NoteSkinManager.cpp r2098
* r28076 "Adds metric options to flash the lifebar when a note is hit"
My comment on why I did this: "Any competent themer can make a lifebar
flash when a note is hit. Just hook something up to a JudgmentMesageCommand,
read the params, and go from there. If it doesn't work on
StreamDisplay/LifeMeterBar, then GO CODE YOUR OWN LIFE METER IN LUA!!
Seriously there are enough publicly available references (moonlight,
optical, NCEvo if you want to go back in time to see a different type
of life meter) that claiming 'oh I don't know how to' isn't an excuse.
Please actually put in effort and seek examples when you try stuff
kthx i told you this would be ranty" -aj
20100209
--------
* sm4svn r28266: Fix GAMESTATE:GetCurrentSteps() only returns single-player
steps for any difficulty [vyhd]
20100207
--------
* sm4svn r28264: subtractive blend (OpenGL only for now) [Glenn Maynard]
(D3D version untested, I'm unsure of the behavior -aj)
20100204
--------
* [MusicWheel] add RecentSongsToShow metric.
20100203
--------
* "First pass of toasty message, hopefully this doesn't break!" [Midiman]
20100202
--------
* [Course.cpp] HasTimedMods() now actually checks for timed mods
(technically non-global) instead of being a clone of HasMods().
* [Player.cpp] add MAX_HOLD_LIFE/[Player] MaxHoldLife metric
20100130
--------
* "various commits from wolfman from the hg repo; mostly cleanup aside from
rev. 79071b3442, which adds a new metric. (that change is forthcoming)"
20100128
--------
* Add DELAYS to list of known .sm tags [Wolfman; sm-ssc hg ebb2bda5b4]
* fix Windows icons for compiling on VS2003 and VS2005
* add ScoreKeeperShared.cpp/.h to VS2k3 project
20100127
--------
* sm4svn r28259: Change OptionsList behavior to pop menu on Select and
default to Exit only on SELECT_ONE [vyhd]
20100126
--------
* Add ScreenGameplayShared, ScoreKeeperShared to Makefile.am
sm-ssc Private Beta Wave 1.4 | 20100125
---------------------------------------
+15 -1
View File
@@ -14,6 +14,8 @@
<Function name='ColorMidTone'/>
<Function name='ColorToHSV'/>
<Function name='ColorToHex'/>
<Function name='ComboContinue'/>
<Function name='ComboMaintain'/>
<Function name='ComboTransformCommand'/>
<Function name='ConnectToServer'/>
<Function name='CourseDifficultyToLocalizedString'/>
@@ -1489,6 +1491,17 @@
<EnumValue name='&apos;MusicWheelUsesSections_Always&apos;' value='1'/>
<EnumValue name='&apos;MusicWheelUsesSections_ABCOnly&apos;' value='2'/>
</Enum>
<Enum name='NotePart'>
<EnumValue name='&apos;NotePart_TapNote&apos;' value='0'/>
<EnumValue name='&apos;NotePart_TapMine&apos;' value='1'/>
<EnumValue name='&apos;NotePart_TapLift&apos;' value='2'/>
<EnumValue name='&apos;NotePart_TapFake&apos;' value='3'/>
<EnumValue name='&apos;NotePart_HoldHead&apos;' value='4'/>
<EnumValue name='&apos;NotePart_HoldTail&apos;' value='5'/>
<EnumValue name='&apos;NotePart_HoldTopCap&apos;' value='6'/>
<EnumValue name='&apos;NotePart_HoldBody&apos;' value='7'/>
<EnumValue name='&apos;NotePart_HoldBottomCap&apos;' value='8'/>
</Enum>
<Enum name='NoteType'>
<EnumValue name='&apos;NoteType_4th&apos;' value='0'/>
<EnumValue name='&apos;NoteType_8th&apos;' value='1'/>
@@ -1758,8 +1771,9 @@
<Constant name='left' value='&apos;HorizAlign_Left&apos;'/>
<Constant name='middle' value='&apos;VertAlign_Middle&apos;'/>
<Constant name='right' value='&apos;HorizAlign_Right&apos;'/>
<Constant name='sGame' value='&apos;dance&apos;'/>
<Constant name='top' value='&apos;VertAlign_Top&apos;'/>
</Constants>
<Version>sm-ssc private beta 1.4</Version>
<Date>2010-01-25</Date>
<Date>2010-02-08</Date>
</Lua>
+4 -4
View File
@@ -1071,7 +1071,7 @@
</Class>
<Class name='GameManager'>
<Function name='GetFirstStepsTypeForGame' return='StepsType' arguments='Game game'>
Return the first of the <Link class='StepsType' /> corresponding to <code>game</code>.
Return the first <Link class='StepsType' /> for the specified <code>game</code>.
</Function>
<Function name='IsGameEnabled' sm-ssc='true' return='bool' arguments='Game g'>
Returns <code>true</code> if any noteskins exist for the specified Game <code>g</code>.
@@ -2097,13 +2097,13 @@
<Function name='GetDisplaySubTitle' return='string' arguments=''>
Returns the displayed subtitle of the song.
</Function>
<Function name='GetElapsedTimeFromBeat' sm-ssc='true' return='float' arguments='float fBeat'>
<Function name='GetElapsedTimeFromBeat' return='float' arguments='float fBeat'>
Returns the elapsed time from <code>fBeat</code>.
</Function>
<Function name='GetFirstBeat' sm-ssc='true' return='float' arguments=''>
<Function name='GetFirstBeat' return='float' arguments=''>
Returns the first beat of the song.
</Function>
<Function name='GetLastBeat' sm-ssc='true' return='float' arguments=''>
<Function name='GetLastBeat' return='float' arguments=''>
Returns the last beat of the song.
</Function>
<Function name='GetLyricsPath' sm-ssc='true' return='string' arguments=''>
-4
View File
@@ -16,10 +16,7 @@
#include "RageFileManager.h"
#include "CourseWriterCRS.h"
//
// Sorting stuff
//
static bool CompareCoursePointersByName( const Course* pCourse1, const Course* pCourse2 )
{
RString sName1 = pCourse1->GetDisplayFullTitle();
@@ -187,7 +184,6 @@ void CourseUtil::SortCoursePointerArrayByAvgDifficulty( vector<Course*> &vpCours
stable_sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), MovePlayersBestToEnd );
}
void CourseUtil::SortCoursePointerArrayByNumPlays( vector<Course*> &vpCoursesInOut, ProfileSlot slot, bool bDescending )
{
+37
View File
@@ -116,6 +116,43 @@ void LuaHelpers::ReadArrayFromTableB( Lua *L, vector<bool> &aOut )
}
}
namespace
{
/* Creates a table from an XNode and leaves it on the stack. */
void CreateTableFromXNodeRecursive( Lua *L, const XNode *pNode )
{
// create our base table
lua_newtable( L );
FOREACH_CONST_Attr( pNode, pAttr )
{
lua_pushstring( L, pAttr->first ); // push key
pNode->PushAttrValue( L, pAttr->first ); // push value
//add key-value pair to our table
lua_settable( L, -3 );
}
FOREACH_CONST_Child( pNode, c )
{
const XNode *pChild = c;
lua_pushstring( L, pChild->m_sName ); // push key
// push value (more correctly, build this child's table and leave it there
CreateTableFromXNodeRecursive( L, pChild );
// add key-value pair to the table
lua_settable( L, -3 );
}
}
}
void LuaHelpers::CreateTableFromXNode( Lua *L, const XNode *pNode )
{
// This creates our table and leaves it on the stack.
CreateTableFromXNodeRecursive( L, pNode );
}
static int GetLuaStack( lua_State *L )
{
+11 -8
View File
@@ -30,12 +30,12 @@ public:
Lua *Get();
void Release( Lua *&p );
/* Explicitly lock and unlock Lua access. This is done automatically by Get() and
* Release(). */
/* Explicitly lock and unlock Lua access. This is done automatically by
* Get() and Release(). */
void YieldLua();
void UnyieldLua();
/* Register all subscribing types. There's no harm in registering when already registered. */
// Register all subscribing types. There's no harm in registering when already registered.
void RegisterTypes();
void SetGlobal( const RString &sName, int val );
@@ -60,12 +60,12 @@ namespace LuaHelpers
* false is returned. */
bool RunScriptOnStack( Lua *L, RString &sError, int iArgs = 0, int iReturnValues = 0 );
/* LoadScript the given script, and RunScriptOnStack it. iArgs arguments are
/* LoadScript the given script, and RunScriptOnStack it. iArgs arguments are
* at the top of the stack. */
bool RunScript( Lua *L, const RString &sScript, const RString &sName, RString &sError, int iArgs = 0, int iReturnValues = 0 );
/* Run the given expression, returning a single value, and leave the return value on the
* stack. On error, push nil. */
/* Run the given expression, returning a single value, and leave the return
* value on the stack. On error, push nil. */
bool RunExpression( Lua *L, const RString &sExpression, const RString &sName = "" );
bool RunScriptFile( const RString &sFile );
@@ -73,12 +73,15 @@ namespace LuaHelpers
/* Create a Lua array (a table with indices starting at 1) of the given vector,
* and push it on the stack. */
void CreateTableFromArrayB( Lua *L, const vector<bool> &aIn );
// Create a Lua table with contents set from this XNode, then push it on the stack.
void CreateTableFromXNode( Lua *L, const XNode *pNode );
/* Recursively copy elements from the table at stack element -2 into the table
* at stack -1. Pop both elements from the stack. */
void DeepCopy( lua_State *L );
/* Read the table at the top of the stack back into a vector. */
// Read the table at the top of the stack back into a vector.
void ReadArrayFromTableB( Lua *L, vector<bool> &aOut );
void ParseCommandList( lua_State *L, const RString &sCommands, const RString &sName );
+3 -1
View File
@@ -365,6 +365,7 @@ void MusicWheel::GetSongList( vector<Song*> &arraySongs, SortOrder so )
if( (so!=SORT_ROULETTE || !RANDOM_PICKS_LOCKED_SONGS) && iLocked )
continue;
if( PREFSMAN->m_bOnlyPreferredDifficulties )
{
// if the song has steps that fit the preferred difficulty of the default player
@@ -378,6 +379,7 @@ void MusicWheel::GetSongList( vector<Song*> &arraySongs, SortOrder so )
arraySongs.push_back( pSong );
}
}
/* Hack: Add extra stage item if it was eliminated for any reason (eg. it's a long
@@ -437,7 +439,7 @@ void MusicWheel::BuildWheelItemDatas( vector<MusicWheelItemData *> &arrayWheelIt
// Make an array of Song*, then sort them
vector<Song*> arraySongs;
GetSongList(arraySongs, so);
GetSongList( arraySongs, so );
bool bUseSections = true;
+1 -1
View File
@@ -36,7 +36,7 @@ NoteField::NoteField()
m_pNoteData = NULL;
m_pCurDisplay = NULL;
m_textMeasureNumber.LoadFromFont( THEME->GetPathF("Common","normal") );
m_textMeasureNumber.LoadFromFont( THEME->GetPathF("NoteField","MeasureNumber") );
m_textMeasureNumber.SetZoom( 1.0f );
m_textMeasureNumber.SetShadowLength( 2 );
m_textMeasureNumber.SetWrapWidthPixels( 300 );
+2 -2
View File
@@ -71,7 +71,7 @@ public:
// Called when a fret, step, or strum type button changes
void Fret( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease );
// Called when the strum bar is pressed down
void Strum( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease );
@@ -86,7 +86,7 @@ public:
// called by Fret for Hammer-ons and Pull-offs
void Hopo( int col, int row, const RageTimer &tm, bool bHeld, bool bRelease ) { StepStrumHopo(col, row, tm, bHeld, bRelease, ButtonType_Hopo); }
void RandomizeNotes( int iNoteRow );
void FadeToFail();
void CacheAllUsedNoteSkins();
+67 -48
View File
@@ -147,6 +147,8 @@ void Profile::InitGeneralData()
m_iNumTotalSongsPlayed = 0;
ZERO( m_iNumStagesPassedByPlayMode );
ZERO( m_iNumStagesPassedByGrade );
m_UserData.Unset();
}
void Profile::InitSongScores()
@@ -328,50 +330,50 @@ float Profile::GetSongsPossible( StepsType st, Difficulty dc ) const
float Profile::GetSongsActual( StepsType st, Difficulty dc ) const
{
CHECKPOINT_M( ssprintf("Profile::GetSongsActual(%d,%d)",st,dc) );
float fTotalPercents = 0;
// add steps high scores
FOREACHM_CONST( SongID, HighScoresForASong, m_SongHighScores, i )
{
const SongID &id = i->first;
Song* pSong = id.ToSong();
CHECKPOINT_M( ssprintf("Profile::GetSongsActual: %p", pSong) );
// If the Song isn't loaded on the current machine, then we can't
// get radar values to compute dance points.
if( pSong == NULL )
continue;
if( !pSong->NormallyDisplayed() )
continue; // skip
CHECKPOINT_M( ssprintf("Profile::GetSongsActual: song %s", pSong->GetSongDir().c_str()) );
const HighScoresForASong &hsfas = i->second;
FOREACHM_CONST( StepsID, HighScoresForASteps, hsfas.m_StepsHighScores, j )
{
const StepsID &id = j->first;
Steps* pSteps = id.ToSteps( pSong, true );
CHECKPOINT_M( ssprintf("Profile::GetSongsActual: song %p, steps %p", pSong, pSteps) );
// If the Steps isn't loaded on the current machine, then we can't
// get radar values to compute dance points.
if( pSteps == NULL )
continue;
if( pSteps->m_StepsType != st )
continue;
CHECKPOINT_M( ssprintf("Profile::GetSongsActual: n %s = %p", id.ToString().c_str(), pSteps) );
if( pSteps->GetDifficulty() != dc )
continue; // skip
CHECKPOINT;
const HighScoresForASteps& h = j->second;
const HighScoreList& hsl = h.hsl;
fTotalPercents += hsl.GetTopScore().GetPercentDP();
}
CHECKPOINT;
@@ -418,11 +420,11 @@ float Profile::GetCoursesPossible( StepsType st, CourseDifficulty cd ) const
return (float) iTotalTrails;
}
float Profile::GetCoursesActual( StepsType st, CourseDifficulty cd ) const
{
float fTotalPercents = 0;
vector<Course*> vpCourses;
GetHighScoreCourses( vpCourses );
FOREACH_CONST( Course*, vpCourses, c )
@@ -550,9 +552,7 @@ Course *Profile::GetMostPopularCourse() const
return id.ToCourse();
}
//
// Steps high scores
//
void Profile::AddStepsHighScore( const Song* pSong, const Steps* pSteps, HighScore hs, int &iIndexOut )
{
GetStepsHighScoreList(pSong,pSteps).AddHighScore( hs, iIndexOut, IsMachine() );
@@ -567,10 +567,10 @@ HighScoreList& Profile::GetStepsHighScoreList( const Song* pSong, const Steps* p
{
SongID songID;
songID.FromSong( pSong );
StepsID stepsID;
stepsID.FromSteps( pSteps );
HighScoresForASong &hsSong = m_SongHighScores[songID]; // operator[] inserts into map
HighScoresForASteps &hsSteps = hsSong.m_StepsHighScores[stepsID]; // operator[] inserts into map
@@ -639,7 +639,6 @@ void Profile::GetGrades( const Song* pSong, StepsType st, int iCounts[NUM_Grade]
SongID songID;
songID.FromSong( pSong );
memset( iCounts, 0, sizeof(int)*NUM_Grade );
const HighScoresForASong *hsSong = GetHighScoresForASong( songID );
if( hsSong == NULL )
@@ -660,9 +659,7 @@ void Profile::GetGrades( const Song* pSong, StepsType st, int iCounts[NUM_Grade]
}
}
//
// Course high scores
//
void Profile::AddCourseHighScore( const Course* pCourse, const Trail* pTrail, HighScore hs, int &iIndexOut )
{
GetCourseHighScoreList(pCourse,pTrail).AddHighScore( hs, iIndexOut, IsMachine() );
@@ -739,9 +736,7 @@ void Profile::IncrementCoursePlayCount( const Course* pCourse, const Trail* pTra
GetCourseHighScoreList(pCourse,pTrail).IncrementPlayCount( now );
}
//
// Category high scores
//
void Profile::AddCategoryHighScore( StepsType st, RankingCategory rc, HighScore hs, int &iIndexOut )
{
m_CategoryHighScores[st][rc].AddHighScore( hs, iIndexOut, IsMachine() );
@@ -772,10 +767,7 @@ void Profile::IncrementCategoryPlayCount( StepsType st, RankingCategory rc )
}
//
// Loading and saving
//
#define WARN_PARSER ShowWarningOrTrace( __FILE__, __LINE__, "Error parsing file.", true )
#define WARN_AND_RETURN { WARN_PARSER; return; }
#define WARN_AND_CONTINUE { WARN_PARSER; continue; }
@@ -801,7 +793,7 @@ ProfileLoadResult Profile::LoadAllFromDir( RString sDir, bool bRequireSignature
// Not critical if this fails
LoadEditableDataFromDir( sDir );
// Check for the existance of stats.xml
RString fn = sDir + STATS_XML;
bool bCompressed = false;
@@ -836,9 +828,7 @@ ProfileLoadResult Profile::LoadAllFromDir( RString sDir, bool bRequireSignature
pFile.reset( pInflate );
}
//
// Don't unreasonably large stats.xml files.
//
// Don't load unreasonably large stats.xml files.
if( !IsMachine() ) // only check stats coming from the player
{
int iBytes = pFile->GetFileSize();
@@ -884,8 +874,8 @@ ProfileLoadResult Profile::LoadAllFromDir( RString sDir, bool bRequireSignature
ProfileLoadResult Profile::LoadStatsXmlFromNode( const XNode *xml, bool bIgnoreEditable )
{
/* The placeholder stats.xml file has an <html> tag. Don't load it, but don't
* warn about it. */
/* The placeholder stats.xml file has an <html> tag. Don't load it,
* but don't warn about it. */
if( xml->GetName() == "html" )
return ProfileLoadResult_FailedNoProfile;
@@ -895,8 +885,7 @@ ProfileLoadResult Profile::LoadStatsXmlFromNode( const XNode *xml, bool bIgnoreE
return ProfileLoadResult_FailedTampered;
}
/* These are loaded from Editable, so we usually want to ignore them
* here. */
// These are loaded from Editable, so we usually want to ignore them here.
RString sName = m_sDisplayName;
RString sCharacterID = m_sCharacterID;
RString sLastUsedHighScoreName = m_sLastUsedHighScoreName;
@@ -929,7 +918,7 @@ bool Profile::SaveAllToDir( RString sDir, bool bSignData ) const
SaveEditableDataToDir( sDir );
bool bSaved = SaveStatsXmlToDir( sDir, bSignData );
SaveStatsWebPageToDir( sDir );
// Empty directories if none exist.
@@ -963,7 +952,7 @@ bool Profile::SaveStatsXmlToDir( RString sDir, bool bSignData ) const
{
LOG->Trace( "SaveStatsXmlToDir: %s", sDir.c_str() );
auto_ptr<XNode> xml( SaveStatsXmlCreateNode() );
// Save stats.xml
RString fn = sDir + (g_bProfileDataCompress? STATS_XML_GZ:STATS_XML);
@@ -975,7 +964,7 @@ bool Profile::SaveStatsXmlToDir( RString sDir, bool bSignData ) const
LOG->Warn( "Couldn't open %s for writing: %s", fn.c_str(), f.GetError().c_str() );
return false;
}
if( g_bProfileDataCompress )
{
RageFileObjGzip gzip( &f );
@@ -1097,7 +1086,7 @@ XNode* Profile::SaveGeneralDataCreateNode() const
XNode* pNumSongsPlayedByPlayMode = pGeneralDataNode->AppendChild("NumSongsPlayedByPlayMode");
FOREACH_ENUM( PlayMode, pm )
{
/* Don't save unplayed PlayModes. */
// Don't save unplayed PlayModes.
if( !m_iNumSongsPlayedByPlayMode[pm] )
continue;
pNumSongsPlayedByPlayMode->AppendChild( PlayModeToString(pm), m_iNumSongsPlayedByPlayMode[pm] );
@@ -1144,7 +1133,7 @@ XNode* Profile::SaveGeneralDataCreateNode() const
XNode* pNumStagesPassedByPlayMode = pGeneralDataNode->AppendChild("NumStagesPassedByPlayMode");
FOREACH_ENUM( PlayMode, pm )
{
/* Don't save unplayed PlayModes. */
// Don't save unplayed PlayModes.
if( !m_iNumStagesPassedByPlayMode[pm] )
continue;
pNumStagesPassedByPlayMode->AppendChild( PlayModeToString(pm), m_iNumStagesPassedByPlayMode[pm] );
@@ -1161,6 +1150,19 @@ XNode* Profile::SaveGeneralDataCreateNode() const
}
}
// Load Lua UserData from profile
if( !IsMachine() && m_UserData.IsSet() )
{
Lua *L = LUA->Get();
m_UserData.PushSelf( L );
XNode* pUserTable = XmlFileUtil::XNodeFromTable( L );
LUA->Release( L );
// XXX: XNodeFromTable returns a root node with the name "Layer".
pUserTable->m_sName = "UserData";
pGeneralDataNode->AppendChild( pUserTable );
}
return pGeneralDataNode;
}
@@ -1168,13 +1170,11 @@ ProfileLoadResult Profile::LoadEditableDataFromDir( RString sDir )
{
RString fn = sDir + EDITABLE_INI;
//
// Don't load unreasonably large editable.xml files.
//
int iBytes = FILEMAN->GetFileSizeInBytes( fn );
if( iBytes > MAX_EDITABLE_INI_SIZE_BYTES )
{
LOG->Warn( "The file '%s' is unreasonably large. It won't be loaded.", fn.c_str() );
LOG->Warn( "The file '%s' is unreasonably large. It won't be loaded.", fn.c_str() );
return ProfileLoadResult_FailedTampered;
}
@@ -1331,7 +1331,24 @@ void Profile::LoadGeneralDataFromNode( const XNode* pNode )
if( pNumStagesPassedByPlayMode )
FOREACH_ENUM( PlayMode, pm )
pNumStagesPassedByPlayMode->GetChildValue( PlayModeToString(pm), m_iNumStagesPassedByPlayMode[pm] );
}
// Build the custom data table from the existing XNode.
if( !IsMachine() )
{
const XNode *pUserData = pNode->GetChild( "UserData" );
Lua *L = LUA->Get();
// If we have custom data, load it. Otherwise, make a blank table.
if( pUserData )
LuaHelpers::CreateTableFromXNode( L, pUserData );
else
lua_newtable( L );
m_UserData.SetFromStack( L );
LUA->Release( L );
}
}
@@ -1361,7 +1378,7 @@ XNode* Profile::SaveSongScoresCreateNode() const
XNode* pNode = new XNode( "SongScores" );
FOREACHM_CONST( SongID, HighScoresForASong, m_SongHighScores, i )
{
{
const SongID &songID = i->first;
const HighScoresForASong &hsSong = i->second;
@@ -1374,7 +1391,7 @@ XNode* Profile::SaveSongScoresCreateNode() const
int jCheck2 = hsSong.m_StepsHighScores.size();
int jCheck1 = 0;
FOREACHM_CONST( StepsID, HighScoresForASteps, hsSong.m_StepsHighScores, j )
{
{
jCheck1++;
ASSERT( jCheck1 <= jCheck2 );
const StepsID &stepsID = j->first;
@@ -1391,7 +1408,7 @@ XNode* Profile::SaveSongScoresCreateNode() const
pStepsNode->AppendChild( hsl.CreateNode() );
}
}
return pNode;
}
@@ -1440,7 +1457,7 @@ XNode* Profile::SaveCourseScoresCreateNode() const
ASSERT( pProfile );
XNode* pNode = new XNode( "CourseScores" );
FOREACHM_CONST( CourseID, HighScoresForACourse, m_CourseHighScores, i )
{
const CourseID &courseID = i->first;
@@ -1490,7 +1507,7 @@ void Profile::LoadCourseScoresFromNode( const XNode* pCourseScores )
courseID.LoadFromNode( pCourse );
if( !courseID.IsValid() )
WARN_AND_CONTINUE;
// Backward compatability hack to fix importing scores of old style
// courses that weren't in group folder but have now been moved into
@@ -2001,6 +2018,7 @@ public:
static int GetTotalRolls( T* p, lua_State *L ) { lua_pushnumber(L, p->m_iTotalRolls ); return 1; }
static int GetTotalMines( T* p, lua_State *L ) { lua_pushnumber(L, p->m_iTotalMines ); return 1; }
static int GetTotalHands( T* p, lua_State *L ) { lua_pushnumber(L, p->m_iTotalHands ); return 1; }
static int GetUserData( T* p, lua_State *L ) { p->m_UserData.PushSelf(L); return 1; }
LunaProfile()
{
@@ -2044,6 +2062,7 @@ public:
ADD_METHOD( GetTotalRolls );
ADD_METHOD( GetTotalMines );
ADD_METHOD( GetTotalHands );
ADD_METHOD( GetUserData );
}
};
+2 -20
View File
@@ -15,6 +15,7 @@
#include "CourseUtil.h" // for CourseID
#include "TrailUtil.h" // for TrailID
#include "StyleUtil.h" // for StyleID
#include "LuaReference.h"
class XNode;
struct lua_State;
@@ -63,9 +64,7 @@ public:
InitAll();
}
//
// smart accessors
//
RString GetDisplayNameOrHighScoreName() const;
Character *GetCharacter() const;
RString GetDisplayTotalCaloriesBurned() const; // remove me and use Lua instead
@@ -92,17 +91,13 @@ public:
bool IsMachine() const;
//
// Editable data
//
RString m_sDisplayName;
RString m_sCharacterID;
RString m_sLastUsedHighScoreName; // this doesn't really belong in "editable", but we need it in the smaller editable file so that it can be ready quickly.
int m_iWeightPounds; // 0 == not set
//
// General data
//
static RString MakeGuid();
RString m_sGuid;
@@ -143,10 +138,9 @@ public:
int m_iNumTotalSongsPlayed;
int m_iNumStagesPassedByPlayMode[NUM_PlayMode];
int m_iNumStagesPassedByGrade[NUM_Grade];
LuaReference m_UserData;
//
// Song high scores
//
struct HighScoresForASteps
{
HighScoreList hsl;
@@ -170,9 +164,7 @@ public:
bool HasPassedSteps( const Song* pSong, const Steps* pSteps ) const;
bool HasPassedAnyStepsInSong( const Song* pSong ) const;
//
// Course high scores
//
// struct was a typedef'd array of HighScores, but VC6 freaks out
// in processing the templates for map::operator[].
struct HighScoresForATrail
@@ -195,9 +187,7 @@ public:
void IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail );
//
// Category high scores
//
HighScoreList m_CategoryHighScores[NUM_StepsType][NUM_RankingCategory];
void AddCategoryHighScore( StepsType st, RankingCategory rc, HighScore hs, int &iIndexOut );
@@ -207,17 +197,13 @@ public:
void IncrementCategoryPlayCount( StepsType st, RankingCategory rc );
//
// Screenshot Data
//
vector<Screenshot> m_vScreenshots;
void AddScreenshot( const Screenshot &screenshot );
int GetNextScreenshotIndex() { return m_vScreenshots.size(); }
//
// Calorie Data
//
// Why track calories in a map, and not in a static sized array like
// Bookkeeping? The machine's clock is not guaranteed to be set correctly.
// If calorie array is in a static sized array, playing on a machine with
@@ -263,9 +249,7 @@ public:
void SaveCourseRecentScore( const Course* pCourse, const Trail* pTrail, HighScore hs );
*/
//
// Init'ing
//
void InitAll()
{
InitEditableData();
@@ -285,9 +269,7 @@ public:
void InitCalorieData();
void ClearStats();
//
// Loading and saving
//
ProfileLoadResult LoadAllFromDir( RString sDir, bool bRequireSignature );
bool SaveAllToDir( RString sDir, bool bSignData ) const;
+2 -10
View File
@@ -35,7 +35,7 @@ public:
Profile *GetLocalProfile( const RString &sProfileID ) { return (Profile*) ((const ProfileManager *) this)->GetLocalProfile(sProfileID); }
Profile *GetLocalProfileFromIndex( int iIndex );
RString GetLocalProfileIDFromIndex( int iIndex );
bool CreateLocalProfile( RString sName, RString &sProfileIDOut );
void AddLocalProfileByID( Profile *pProfile, RString sProfileID ); // transfers ownership of pProfile
bool RenameLocalProfile( RString sProfileID, RString sNewName );
@@ -82,24 +82,17 @@ public:
bool LastLoadWasTamperedOrCorrupt( PlayerNumber pn ) const;
bool LastLoadWasFromLastGood( PlayerNumber pn ) const;
//
// Song stats
//
int GetSongNumTimesPlayed( const Song* pSong, ProfileSlot card ) const;
bool IsSongNew( const Song* pSong ) const { return GetSongNumTimesPlayed(pSong,ProfileSlot_Machine)==0; }
void AddStepsScore( const Song* pSong, const Steps* pSteps , PlayerNumber pn, const HighScore &hs, int &iPersonalIndexOut, int &iMachineIndexOut );
void IncrementStepsPlayCount( const Song* pSong, const Steps* pSteps, PlayerNumber pn );
//
// Course stats
//
void AddCourseScore( const Course* pCourse, const Trail* pTrail, PlayerNumber pn, const HighScore &hs, int &iPersonalIndexOut, int &iMachineIndexOut );
void IncrementCoursePlayCount( const Course* pCourse, const Trail* pTrail, PlayerNumber pn );
//
// Category stats
//
void AddCategoryScore( StepsType st, RankingCategory rc, PlayerNumber pn, const HighScore &hs, int &iPersonalIndexOut, int &iMachineIndexOut );
void IncrementCategoryPlayCount( StepsType st, RankingCategory rc, PlayerNumber pn );
@@ -126,12 +119,11 @@ private:
bool m_bLastLoadWasTamperedOrCorrupt[NUM_PLAYERS]; // true if Stats.xml was present, but failed to load (probably because of a signature failure)
bool m_bLastLoadWasFromLastGood[NUM_PLAYERS]; // if true, then m_bLastLoadWasTamperedOrCorrupt is also true
mutable bool m_bNeedToBackUpLastLoad[NUM_PLAYERS]; // if true, back up profile on next save
Profile *m_pMemoryCardProfile[NUM_PLAYERS]; // holds Profile for the currently inserted card
Profile *m_pMachineProfile;
};
extern ProfileManager* PROFILEMAN; // global and accessable from anywhere in our program
#endif
+1 -2
View File
@@ -19,7 +19,6 @@ static void GetResolutionFromFileName( RString sPath, int &iWidth, int &iHeight
* Foo (res 512x128).png
* Also allow, eg:
* Foo (dither, res 512x128).png
*
* Be careful that this doesn't get mixed up with frame dimensions. */
static Regex re( "\\([^\\)]*res ([0-9]+)x([0-9]+).*\\)" );
@@ -202,7 +201,7 @@ void RageBitmapTexture::Create()
case 1:
pixfmt = PixelFormat_RGB5A1;
break;
default:
default:
pixfmt = PixelFormat_RGBA4;
break;
}
+5 -8
View File
@@ -15,9 +15,7 @@
#include "DisplayResolutions.h"
#include "arch/ArchHooks/ArchHooks.h"
//
// Statistics stuff
//
RageTimer g_LastCheckTimer;
int g_iNumVerts;
int g_iFPS, g_iVPF, g_iCFPS;
@@ -145,7 +143,7 @@ void RageDisplay::ResetStats()
RString RageDisplay::GetStats() const
{
RString s;
/* If FPS == 0, we don't have stats yet. */
// If FPS == 0, we don't have stats yet.
if( !GetFPS() )
s = "-- FPS\n-- av FPS\n-- VPF";
@@ -182,7 +180,7 @@ void RageDisplay::StatsAddVerts( int iNumVertsRendered ) { g_iVertsRenderedSince
* angle of the line. */
void RageDisplay::DrawPolyLine(const RageSpriteVertex &p1, const RageSpriteVertex &p2, float LineWidth )
{
/* soh cah toa strikes strikes again! */
// soh cah toa strikes strikes again!
float opp = p2.p.x - p1.p.x;
float adj = p2.p.y - p1.p.y;
float hyp = powf(opp*opp + adj*adj, 0.5f);
@@ -197,7 +195,7 @@ void RageDisplay::DrawPolyLine(const RageSpriteVertex &p1, const RageSpriteVerte
float ydist = lsin * LineWidth/2;
float xdist = lcos * LineWidth/2;
v[0].p.x += xdist;
v[0].p.y -= ydist;
v[1].p.x -= xdist;
@@ -221,7 +219,7 @@ void RageDisplay::DrawLineStripInternal( const RageSpriteVertex v[], int iNumVer
for( int i = 0; i < iNumVerts-1; ++i )
DrawPolyLine(v[i], v[i+1], LineWidth);
/* Join the lines with circles so we get rounded corners. */
// Join the lines with circles so we get rounded corners.
for( int i = 0; i < iNumVerts; ++i )
DrawCircle( v[i], LineWidth/2 );
}
@@ -253,6 +251,7 @@ void RageDisplay::SetDefaultRenderStates()
SetCullMode( CULL_NONE );
SetZWrite( false );
SetZTestMode( ZTEST_OFF );
SetStencilTestMode( STENCILTEST_OFF );
SetAlphaTest( true );
SetBlendMode( BLEND_NORMAL );
SetTextureFiltering( TextureUnit_1, true );
@@ -261,9 +260,7 @@ void RageDisplay::SetDefaultRenderStates()
}
//
// Matrix stuff
//
class MatrixStack
{
vector<RageMatrix> stack;
+25 -20
View File
@@ -65,7 +65,6 @@ RageFileDriverReadAhead::RageFileDriverReadAhead( RageFileBasic *pFile, int iCac
m_pFile = pFile;
m_iFilePos = pFile->Tell();
m_bFileOwned = false;
m_bReadAheadNeeded = true;
m_iPostBufferReadAhead = iPostBufferReadAhead;
FillBuffer( iCacheBytes );
@@ -79,7 +78,6 @@ RageFileDriverReadAhead::RageFileDriverReadAhead( const RageFileDriverReadAhead
m_iFilePos = cpy.m_iFilePos;
m_bFileOwned = true;
m_iPostBufferReadAhead = cpy.m_iPostBufferReadAhead;
m_bReadAheadNeeded = cpy.m_bReadAheadNeeded;
RageFileManagerReadAhead::CacheHintStreaming( m_pFile );
}
@@ -117,32 +115,39 @@ void RageFileDriverReadAhead::FillBuffer( int iBytes )
int RageFileDriverReadAhead::ReadInternal( void *pBuffer, size_t iBytes )
{
/* If we're in the buffered area, and we havn't already done read-ahead, start it. */
int iRet = -1;
if( m_bReadAheadNeeded && m_iFilePos < (int) m_sBuffer.size() )
{
RageFileManagerReadAhead::ReadAhead( m_pFile, m_iPostBufferReadAhead );
m_bReadAheadNeeded = false;
// If we can serve data out of the buffer, use it.
iRet = min( iBytes, m_sBuffer.size() - m_iFilePos );
memcpy( pBuffer, m_sBuffer.data() + m_iFilePos, iRet );
}
else if( !m_bReadAheadNeeded && m_iFilePos >= (int) m_sBuffer.size() )
else
{
/* Reset, so next time we rewind we'll read-ahead again. */
m_bReadAheadNeeded = true;
// Read out of the underlying file.
iRet = m_pFile->Read( pBuffer, iBytes );
}
/* If we can serve data out of the buffer, use it. */
if( m_iFilePos < (int) m_sBuffer.size() )
{
size_t iFromBuffer = min( iBytes, m_sBuffer.size() - m_iFilePos );
memcpy( pBuffer, m_sBuffer.data() + m_iFilePos, iFromBuffer );
m_iFilePos += iFromBuffer;
return iFromBuffer;
}
/* Read out of the underlying file. */
int iRet = m_pFile->Read( pBuffer, iBytes );
if( iRet != -1 )
m_iFilePos += iRet;
/*
* Hint the read-ahead. We only strictly need to do this when reading data from
* m_sBuffer, so the kernel knows to start reading data ahead of it. Always
* doing it is simpler, and reduces some skips when under I/O load.
*/
RageFileManagerReadAhead::ReadAhead( m_pFile, m_iPostBufferReadAhead );
/*
* We're streaming the file, so we don't need data that we've already read in cache.
* Hint the OS to discard it, so it doesn't push more useful data out of cache.
*
* Keep the previous 32k of data in cache. This prevents an issue in Linux: if we're at
* the end of the file, flush the cache, then try to read (resulting in 0 bytes), it'll
* hit the disk if we've flushed.
*/
RageFileManagerReadAhead::DiscardCache( m_pFile, -m_iPostBufferReadAhead - 1024*32, m_iPostBufferReadAhead );
return iRet;
}
+22
View File
@@ -22,6 +22,26 @@ void RageFileManagerReadAhead::ReadAhead( RageFileBasic *pFile, int iBytes )
posix_fadvise( iFD, iStart, iBytes, POSIX_FADV_WILLNEED );
}
void RageFileManagerReadAhead::DiscardCache( RageFileBasic *pFile, int iRelativePosition, int iBytes )
{
int iFD = pFile->GetFD();
if( iFD == -1 )
return;
int iStart = lseek( iFD, 0, SEEK_CUR );
iStart += iRelativePosition;
if( iStart < 0 )
{
iBytes -= iStart;
iStart = 0;
}
if( iBytes == 0 )
return;
posix_fadvise( iFD, iStart, iBytes, POSIX_FADV_DONTNEED );
}
#else
#if 0
/* This doesn't currently work, because dup() locks the file position of the new FD with the old
@@ -123,10 +143,12 @@ void RageFileManagerReadAhead::ReadAhead( RageFileBasic *pFile, int iBytes )
}
}
}
void RageFileManagerReadAhead::DiscardCache( RageFileBasic *pFile, int iRelativePosition, int iBytes ) { }
#else
void RageFileManagerReadAhead::Init() { }
void RageFileManagerReadAhead::Shutdown() { }
void RageFileManagerReadAhead::ReadAhead( RageFileBasic *pFile, int iBytes ) { }
void RageFileManagerReadAhead::DiscardCache( RageFileBasic *pFile, int iRelativePosition, int iBytes ) { }
#endif
#endif
+5 -1
View File
@@ -8,9 +8,13 @@ namespace RageFileManagerReadAhead
void Init();
void Shutdown();
/* Nonblockingly read bytes from a file. */
// Nonblockingly read ahead iBytes in pFile, starting at the current file position.
void ReadAhead( RageFileBasic *pFile, int iBytes );
/* Discard iBytes of kernel cache, starting at the current file position plus
* iRelativePosition (which may be negative). */
void DiscardCache( RageFileBasic *pFile, int iRelativePosition, int iBytes );
void CacheHintStreaming( RageFileBasic *pFile );
};
-2
View File
@@ -60,9 +60,7 @@ public:
bool AllowOperatorMenuButton() const { return ALLOW_OPERATOR_MENU_BUTTON; }
virtual bool AllowLateJoin() const { return false; }
//
// Lua
//
virtual void PushSelf( lua_State *L );
protected:
+10 -6
View File
@@ -34,7 +34,7 @@
#include "LightsManager.h"
#include "ProfileManager.h"
#include "StatsManager.h"
#include "PlayerAI.h" // for NUM_SKILL_LEVELS
#include "PlayerAI.h" // for NUM_SKILL_LEVELS
#include "NetworkSyncManager.h"
#include "Foreach.h"
#include "DancingCharacters.h"
@@ -58,6 +58,7 @@
#include "SongUtil.h"
#include "Song.h"
#include "XmlFileUtil.h"
#include "Profile.h" // for replay data stuff
// Defines
#define SHOW_LIFE_METER_FOR_DISABLED_PLAYERS THEME->GetMetricB(m_sName,"ShowLifeMeterForDisabledPlayers")
@@ -671,7 +672,7 @@ void ScreenGameplay::Init()
m_Failed.SetDrawOrder( DRAW_ORDER_TRANSITIONS-1 ); // on top of everything else
this->AddChild( &m_Failed );
m_textDebug.LoadFromFont( THEME->GetPathF("Common","normal") );
m_textDebug.LoadFromFont( THEME->GetPathF(m_sName,"debug") );
m_textDebug.SetName( "Debug" );
LOAD_ALL_COMMANDS_AND_SET_XY( m_textDebug );
m_textDebug.SetDrawOrder( DRAW_ORDER_TRANSITIONS-1 ); // just under transitions, over the foreground
@@ -2760,14 +2761,16 @@ void ScreenGameplay::SaveReplay()
* Add proper steps hash?
* Add modifiers used
* Add date played, machine played on, etc.
* Add/use player GUID
*/
FOREACH_HumanPlayer( pn )
{
FOREACH_EnabledPlayerInfo( m_vPlayerInfo, pi )
{
Profile *pTempProfile = PROFILEMAN->GetProfile(pn);
XNode *p = new XNode("ReplayData");
// todo: add version number, since this will change in the future -aj
// append version number (in case the format changes)
p->AppendAttr("Version",0);
// song information node
SongID songID;
@@ -2787,7 +2790,8 @@ void ScreenGameplay::SaveReplay()
// player information node (rival data sup)
XNode *pPlayerInfoNode = new XNode("Player");
pPlayerInfoNode->AppendChild("Name", PROFILEMAN->GetPlayerName(pn));
pPlayerInfoNode->AppendChild("DisplayName", pTempProfile->m_sDisplayName);
pPlayerInfoNode->AppendChild("Guid", pTempProfile->m_sGuid);
p->AppendChild(pPlayerInfoNode);
// the timings.
@@ -2825,7 +2829,7 @@ void ScreenGameplay::SaveReplay()
/*
bool ScreenGameplay::LoadReplay()
{
// Load
// Load replay which was selected via options
}
*/
-2
View File
@@ -119,9 +119,7 @@ public:
bool Center1Player() const;
//
// Lua
//
virtual void PushSelf( lua_State *L );
Song *GetNextCourseSong() const;
LifeMeter *GetLifeMeter( PlayerNumber pn );
+1 -1
View File
@@ -41,7 +41,7 @@ void ScreenGameplaySyncMachine::Init()
m_DancingState = STATE_DANCING;
m_textSyncInfo.SetName( "SyncInfo" );
m_textSyncInfo.LoadFromFont( THEME->GetPathF("Common","normal") );
m_textSyncInfo.LoadFromFont( THEME->GetPathF(m_sName,"SyncInfo") );
ActorUtil::LoadAllCommands( m_textSyncInfo, m_sName );
this->AddChild( &m_textSyncInfo );
+1 -3
View File
@@ -43,12 +43,10 @@ void ScreenPrompt::SetPromptSettings( const RString &sText, PromptType type, Pro
void ScreenPrompt::Prompt( ScreenMessage smSendOnPop, const RString &sText, PromptType type, PromptAnswer defaultAnswer, void(*OnYes)(void*), void(*OnNo)(void*), void* pCallbackData )
{
SetPromptSettings( sText, type, defaultAnswer, OnYes, OnNo, pCallbackData );
SCREENMAN->AddNewScreenToTop( "ScreenPrompt", smSendOnPop );
}
REGISTER_SCREEN_CLASS( ScreenPrompt );
void ScreenPrompt::Init()
+5 -4
View File
@@ -29,8 +29,8 @@ public:
void Paint()
{
/* We load songs much faster than we draw frames. Cap the draw rate, so we don't
* slow down the reload. */
/* We load songs much faster than we draw frames. Cap the draw rate,
* so we don't slow down the reload. */
if( m_LastDraw.PeekDeltaTime() < 1.0f/DrawFrameRate )
return;
m_LastDraw.GetDeltaTime();
@@ -51,7 +51,8 @@ void ScreenReloadSongs::Init()
m_iUpdates = 0;
m_Loading.LoadFromFont( THEME->GetPathF("Common", "normal") );
m_Loading.SetName("LoadingText");
m_Loading.LoadFromFont( THEME->GetPathF(m_sName, "LoadingText") );
m_Loading.SetXY( SCREEN_CENTER_X, SCREEN_CENTER_Y );
this->AddChild( &m_Loading );
@@ -68,7 +69,7 @@ void ScreenReloadSongs::Update( float fDeltaTime )
{
Screen::Update( fDeltaTime );
/* Start the reload on the second update. On the first, 0, SCREENMAN->Draw won't draw. */
/* Start the reload on the second update. On the first (0), SCREENMAN->Draw won't draw. */
++m_iUpdates;
if( m_iUpdates != 2 )
return;
+38 -52
View File
@@ -67,7 +67,7 @@ void ScreenSelectMaster::Init()
OPTION_ORDER2.Load( m_sName, OPTION_ORDER_NAME_LIST2, NUM_MenuDir );
DO_SWITCH_ANYWAYS.Load( m_sName, "DoSwitchAnyways" );
WRAP_CURSOR.Load( m_sName, "WrapCursor" );
WRAP_SCROLLER.Load( m_sName, "WrapScroller" );
LOOP_SCROLLER.Load( m_sName, "LoopScroller" );
@@ -90,7 +90,6 @@ void ScreenSelectMaster::Init()
#define PLAYER_APPEND_NO_SPACE(p) (SHARED_SELECTION ? RString() : ssprintf("P%d",(p)+1))
this->SubscribeToMessage( SM_MenuTimer );
// init cursor
if( SHOW_CURSOR )
{
@@ -415,11 +414,9 @@ void ScreenSelectMaster::HandleScreenMessage( const ScreenMessage SM )
{
ScreenSelect::HandleScreenMessage( SM );
vector<PlayerNumber> vpns;
GetActiveElementPlayerNumbers( vpns );
if( SM == SM_PlayPostSwitchPage )
{
int iNewChoice = m_iChoice[ GAMESTATE->m_MasterPlayerNumber ];
@@ -441,8 +438,6 @@ void ScreenSelectMaster::HandleScreenMessage( const ScreenMessage SM )
int iChoice = m_iChoice[*p];
m_vsprScroll[*p][iChoice]->HandleMessage( msg );
}
}
m_fLockInputSecs = POST_SWITCH_PAGE_SECONDS;
@@ -458,10 +453,9 @@ void ScreenSelectMaster::HandleScreenMessage( const ScreenMessage SM )
InputEventPlus iep;
iep.pn = p;
MenuStart( iep );
}
}
}
}
}
int ScreenSelectMaster::GetSelectionIndex( PlayerNumber pn )
@@ -532,17 +526,15 @@ void ScreenSelectMaster::UpdateSelectableChoices()
}
}
/*
* If no options are playable at all, just wait. Some external
/* If no options are playable at all, just wait. Some external
* stimulus may make options available (such as coin insertion).
*
* If any options are playable, make sure one is selected.
*/
* If any options are playable, make sure one is selected. */
FOREACH_HumanPlayer( p )
{
if(m_bUsingTwoLists && m_iSelectedList == 1)
{
m_iChoice[p] = 0; // reset their choice position since we are moving to the new list
// reset their choice position since we are moving to the new list:
m_iChoice[p] = 0;
if( !m_aGameCommandsB[m_iChoice[p]].IsPlayable() )
Move( p, MenuDir_Auto );
}
@@ -556,19 +548,19 @@ void ScreenSelectMaster::UpdateSelectableChoices()
bool ScreenSelectMaster::AnyOptionsArePlayable() const
{
// if they're using the second list
if(m_bUsingTwoLists && m_iSelectedList == 1)
{
for( unsigned i = 0; i < m_aGameCommandsB.size(); ++i )
if( m_aGameCommandsB[i].IsPlayable() )
return true;
}
else
{
for( unsigned i = 0; i < m_aGameCommands.size(); ++i )
if( m_aGameCommands[i].IsPlayable() )
return true;
}
// if they're using the second list
if(m_bUsingTwoLists && m_iSelectedList == 1)
{
for( unsigned i = 0; i < m_aGameCommandsB.size(); ++i )
if( m_aGameCommandsB[i].IsPlayable() )
return true;
}
else
{
for( unsigned i = 0; i < m_aGameCommands.size(); ++i )
if( m_aGameCommands[i].IsPlayable() )
return true;
}
return false;
}
@@ -695,14 +687,12 @@ void ScreenSelectMaster::MenuUp( const InputEventPlus &input )
m_soundChange.Play();
MESSAGEMAN->Broadcast( (MessageID)(Message_MenuUpP1+pn) );
MESSAGEMAN->Broadcast( (MessageID)(Message_MenuSelectionChanged) );
// if they use double select
if(DOUBLE_PRESS_TO_SELECT)
{
m_bDoubleChoice[pn] = false; // player has cancelled their selection
}
}
}
@@ -732,7 +722,6 @@ void ScreenSelectMaster::MenuDown( const InputEventPlus &input )
{
m_bDoubleChoice[pn] = false; // player has cancelled their selection
}
}
}
@@ -756,7 +745,7 @@ bool ScreenSelectMaster::ChangePage( int iNewChoice )
if( SHOW_ICON )
for( unsigned c = 0; c < m_aGameCommands.size(); ++c )
m_vsprIcon[c]->PlayCommand( sIconAndExplanationCommand );
FOREACH_ENUM( Page, page )
{
m_sprExplanation[page]->PlayCommand( sIconAndExplanationCommand );
@@ -786,7 +775,7 @@ bool ScreenSelectMaster::ChangePage( int iNewChoice )
{
// XXX: only play this once (I thought we already did that?)
// Play it on every change to page 2. -Chris
/* That sounds ugly if you go back and forth quickly. -g */
// That sounds ugly if you go back and forth quickly. -g
// Should we lock input while it's scrolling? -Chris
m_soundDifficult.Stop();
m_soundDifficult.PlayRandom();
@@ -1057,7 +1046,7 @@ void ScreenSelectMaster::MenuStart( const InputEventPlus &input )
if( input.type != IET_FIRST_PRESS )
return;
PlayerNumber pn = input.pn;
if( m_fLockInputSecs > 0 )
return;
if( m_bChosen[pn] )
@@ -1070,7 +1059,7 @@ void ScreenSelectMaster::MenuStart( const InputEventPlus &input )
if(DOUBLE_PRESS_TO_SELECT && !m_bDoubleChoice[pn])
{
m_soundStart.PlayCopy();
m_bDoubleChoice[pn] = true;
m_bDoubleChoice[pn] = true;
if(SHOW_SCROLLER)
{
@@ -1096,10 +1085,10 @@ void ScreenSelectMaster::MenuStart( const InputEventPlus &input )
* If any options are playable, then the selection must be playable. */
if( !AnyOptionsArePlayable() )
return;
SOUND->PlayOnceFromDir( ANNOUNCER->GetPathTo(ssprintf("%s comment %s",m_sName.c_str(), mc.m_sName.c_str())) );
/* Play a copy of the sound, so it'll finish playing even if we leave the screen immediately. */
// Play a copy of the sound, so it'll finish playing even if we leave the screen immediately.
if( mc.m_sSoundPath.empty() && !m_bDoubleChoiceNoSound )
m_soundStart.PlayCopy();
@@ -1108,12 +1097,12 @@ void ScreenSelectMaster::MenuStart( const InputEventPlus &input )
mc.ApplyToAllPlayers();
return;
}
float fSecs = 0;
bool bAllDone = true;
if( (bool)SHARED_SELECTION || GetCurrentPage() == PAGE_2 )
{
/* Only one player has to pick. Choose this for all the other players, too. */
// Only one player has to pick. Choose this for all the other players, too.
FOREACH_PlayerNumber( p )
{
ASSERT( !m_bChosen[p] );
@@ -1132,18 +1121,15 @@ void ScreenSelectMaster::MenuStart( const InputEventPlus &input )
this->PostScreenMessage( SM_BeginFadingOut, fSecs );// tell our owner it's time to move on
}
/*
* We want all items to always run OnCommand and either GainFocus or LoseFocus on
/* We want all items to always run OnCommand and either GainFocus or LoseFocus on
* tween-in. If we only run OnCommand, then it has to contain a copy of either
* GainFocus or LoseFocus, which implies that the default setting is hard-coded in
* the theme. Always run both.
*
* GainFocus or LoseFocus, which implies that the default setting is hard-coded
* in the theme. Always run both.
* However, the actual tween-in is OnCommand; we don't always want to actually run
* through the Gain/LoseFocus tweens during initial tween-in. So, we run the focus
* command first, do a FinishTweening to pop it in place, and then run OnCommand.
* This means that the focus command should be position neutral; eg. only use "addx",
* not "x".
*/
* not "x". */
void ScreenSelectMaster::TweenOnScreen()
{
vector<PlayerNumber> vpns;
@@ -1175,8 +1161,8 @@ void ScreenSelectMaster::TweenOnScreen()
{
FOREACH( PlayerNumber, vpns, p )
{
// Play Gain/LoseFocus before playing the on command. Gain/Lose will
// often stop tweening, which ruins the OnCommand.
// Play Gain/LoseFocus before playing the on command.
// Gain/Lose will often stop tweening, which ruins the OnCommand.
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
{
m_vsprScrollB[*p][c]->PlayCommand( int(c) == m_iChoice[*p]? "GainFocus":"LoseFocus" );
@@ -1190,8 +1176,8 @@ void ScreenSelectMaster::TweenOnScreen()
{
FOREACH( PlayerNumber, vpns, p )
{
// Play Gain/LoseFocus before playing the on command. Gain/Lose will
// often stop tweening, which ruins the OnCommand.
// Play Gain/LoseFocus before playing the on command.
// Gain/Lose will often stop tweening, which ruins the OnCommand.
for( unsigned c=0; c<m_aGameCommands.size(); c++ )
{
m_vsprScroll[*p][c]->PlayCommand( int(c) == m_iChoice[*p]? "GainFocus":"LoseFocus" );
@@ -1223,7 +1209,7 @@ void ScreenSelectMaster::TweenOffScreen()
GetActiveElementPlayerNumbers( vpns );
// using two lists -- may need to consider throwing a wider range of commands
// for themers if tweening out with one/two lists/focussed/not focussed etc?
// for themers if tweening out with one/two lists/focused/not focused etc?
if(m_bUsingTwoLists && m_iSelectedList == 1)
{
for( unsigned c=0; c<m_aGameCommandsB.size(); c++ )
+47 -54
View File
@@ -192,10 +192,8 @@ void ScreenSelectMusic::Init()
this->SortByDrawOrder();
}
//#include "RageTimer.h"
void ScreenSelectMusic::BeginScreen()
{
//RageTimer tm;
g_ScreenStartedLoadingAt.Touch();
if( CommonMetrics::AUTO_SET_STYLE )
@@ -215,7 +213,6 @@ void ScreenSelectMusic::BeginScreen()
GAMESTATE->m_PlayMode.Set( PLAY_MODE_REGULAR );
LOG->Trace( "PlayMode not set, setting as regular." );
}
//LOG->Trace("XXX 1 %f", tm.GetDeltaTime());
FOREACH_ENUM( PlayerNumber, pn )
{
if( GAMESTATE->IsHumanPlayer(pn) )
@@ -226,30 +223,23 @@ void ScreenSelectMusic::BeginScreen()
OPTIONS_MENU_AVAILABLE.Load( m_sName, "OptionsMenuAvailable" );
PlayCommand( "Mods" );
//LOG->Trace("XXX 2a %f", tm.GetDeltaTime());
m_MusicWheel.BeginScreen();
//LOG->Trace("XXX 2b %f", tm.GetDeltaTime());
m_SelectionState = SelectionState_SelectingSong;
ZERO( m_bStepsChosen );
m_bGoToOptions = false;
m_bAllowOptionsMenu = m_bAllowOptionsMenuRepeat = false;
ZERO( m_iSelection );
//LOG->Trace("XXX 3 %f", tm.GetDeltaTime());
if( USE_OPTIONS_LIST )
FOREACH_PlayerNumber( pn )
m_OptionsList[pn].Reset();
//LOG->Trace("XXX 4a %f", tm.GetDeltaTime());
AfterMusicChange();
//LOG->Trace("XXX 4b %f", tm.GetDeltaTime());
SOUND->PlayOnceFromAnnouncer( "select music intro" );
//LOG->Trace("XXX 4c %f", tm.GetDeltaTime());
ScreenWithMenuElements::BeginScreen();
//LOG->Trace("XXX 5 %f", tm.GetDeltaTime());
}
ScreenSelectMusic::~ScreenSelectMusic()
@@ -1010,61 +1000,64 @@ void ScreenSelectMusic::MenuStart( const InputEventPlus &input )
* (Right now, we bump them to Beginner...can we come up with something better?)
*/
bool bSelectedRoutineSteps[NUM_PLAYERS], bAnySelectedRoutine = false;
bool bSelectedSameSteps = GAMESTATE->m_pCurSteps[PLAYER_1] == GAMESTATE->m_pCurSteps[PLAYER_2];
FOREACH_HumanPlayer( p )
if( !GAMESTATE->IsCourseMode() && GAMESTATE->GetNumSidesJoined() == 2 )
{
const Steps *pSteps = GAMESTATE->m_pCurSteps[p];
const StepsTypeInfo &sti = GAMEMAN->GetStepsTypeInfo( pSteps->m_StepsType );
bool bSelectedRoutineSteps[NUM_PLAYERS], bAnySelectedRoutine = false;
bool bSelectedSameSteps = GAMESTATE->m_pCurSteps[PLAYER_1] == GAMESTATE->m_pCurSteps[PLAYER_2];
bSelectedRoutineSteps[p] = sti.m_StepsTypeCategory == StepsTypeCategory_Routine;
bAnySelectedRoutine |= bSelectedRoutineSteps[p];
}
if( bAnySelectedRoutine )
{
/* Timer ran out. If we haven't agreed on steps, move players with Routine steps down
* to Beginner. I'll admit that's annoying, but at least they won't lose more stages. */
if( bInitiatedByMenuTimer && !bSelectedSameSteps )
FOREACH_HumanPlayer( p )
{
// Since m_vpSteps is sorted by Difficulty, the first entry should be the easiest.
ASSERT( m_vpSteps.size() );
Steps *pSteps = m_vpSteps[0];
const Steps *pSteps = GAMESTATE->m_pCurSteps[p];
const StepsTypeInfo &sti = GAMEMAN->GetStepsTypeInfo( pSteps->m_StepsType );
FOREACH_PlayerNumber( p )
{
if( bSelectedRoutineSteps[p] )
GAMESTATE->m_pCurSteps[p].Set( pSteps );
}
break;
bSelectedRoutineSteps[p] = sti.m_StepsTypeCategory == StepsTypeCategory_Routine;
bAnySelectedRoutine |= bSelectedRoutineSteps[p];
}
// If the steps don't match up, we need to check some more conditions...
if( !bSelectedSameSteps )
if( bAnySelectedRoutine )
{
const PlayerNumber other = OPPOSITE_PLAYER[pn];
if( m_bStepsChosen[other] )
/* Timer ran out. If we haven't agreed on steps, move players with Routine steps down
* to Beginner. I'll admit that's annoying, but at least they won't lose more stages. */
if( bInitiatedByMenuTimer && !bSelectedSameSteps )
{
/* Unready the other player if they selected Routine steps, but we didn't. */
if( bSelectedRoutineSteps[other] )
/* Since m_vpSteps is sorted by Difficulty, the first entry should be the easiest. */
ASSERT( m_vpSteps.size() );
Steps *pSteps = m_vpSteps[0];
FOREACH_PlayerNumber( p )
{
m_bStepsChosen[other] = false;
bAllPlayersDoneSelectingSteps = false; // if the timer ran out, we handled it earlier
// HACK: send an event to Input to tell it to unready.
InputEventPlus event;
event.MenuI = GAME_BUTTON_SELECT;
event.pn = other;
this->Input( event );
if( bSelectedRoutineSteps[p] )
GAMESTATE->m_pCurSteps[p].Set( pSteps );
}
else if( bSelectedRoutineSteps[pn] )
break;
}
/* If the steps don't match up, we need to check some more conditions... */
if( !bSelectedSameSteps )
{
const PlayerNumber other = OPPOSITE_PLAYER[pn];
if( m_bStepsChosen[other] )
{
// They selected non-Routine steps, so we can't select Routine steps.
return;
/* Unready the other player if they selected Routine steps, but we didn't. */
if( bSelectedRoutineSteps[other] )
{
m_bStepsChosen[other] = false;
bAllPlayersDoneSelectingSteps = false; // if the timer ran out, we handled it earlier
// HACK: send an event to Input to tell it to unready.
InputEventPlus event;
event.MenuI = GAME_BUTTON_SELECT;
event.pn = other;
this->Input( event );
}
else if( bSelectedRoutineSteps[pn] )
{
/* They selected non-Routine steps, so we can't select Routine steps. */
return;
}
}
}
}
-6
View File
@@ -540,9 +540,7 @@ void Sprite::DrawTexture( const TweenState *state )
{
DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Modulate );
//////////////////////
// render the shadow
//////////////////////
if( m_fShadowLengthX != 0 || m_fShadowLengthY != 0 )
{
DISPLAY->PushMatrix();
@@ -554,9 +552,7 @@ void Sprite::DrawTexture( const TweenState *state )
DISPLAY->PopMatrix();
}
//////////////////////
// render the diffuse pass
//////////////////////
v[0].c = state->diffuse[0]; // top left
v[1].c = state->diffuse[2]; // bottom left
v[2].c = state->diffuse[3]; // bottom right
@@ -564,9 +560,7 @@ void Sprite::DrawTexture( const TweenState *state )
DISPLAY->DrawQuad( v );
}
//////////////////////
// render the glow pass
//////////////////////
if( state->glow.a > 0.0001f )
{
DISPLAY->SetTextureMode( TextureUnit_1, TextureMode_Glow );