diff --git a/Docs/Changelog_sm-ssc.txt b/Docs/Changelog_sm-ssc.txt index 264cd0e836..963eba7d32 100644 --- a/Docs/Changelog_sm-ssc.txt +++ b/Docs/Changelog_sm-ssc.txt @@ -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 --------------------------------------- diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index 8a6e034b73..413ae0bc04 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -14,6 +14,8 @@ + + @@ -1489,6 +1491,17 @@ + + + + + + + + + + + @@ -1758,8 +1771,9 @@ + sm-ssc private beta 1.4 - 2010-01-25 + 2010-02-08 diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index dd15021700..a97f1e91ca 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -1071,7 +1071,7 @@ - Return the first of the corresponding to game. + Return the first for the specified game. Returns true if any noteskins exist for the specified Game g. @@ -2097,13 +2097,13 @@ Returns the displayed subtitle of the song. - + Returns the elapsed time from fBeat. - + Returns the first beat of the song. - + Returns the last beat of the song. diff --git a/src/CourseUtil.cpp b/src/CourseUtil.cpp index 486aefc030..ae1603ef16 100644 --- a/src/CourseUtil.cpp +++ b/src/CourseUtil.cpp @@ -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 &vpCours stable_sort( vpCoursesInOut.begin(), vpCoursesInOut.end(), MovePlayersBestToEnd ); } - void CourseUtil::SortCoursePointerArrayByNumPlays( vector &vpCoursesInOut, ProfileSlot slot, bool bDescending ) { diff --git a/src/LuaManager.cpp b/src/LuaManager.cpp index 903e411c63..fd031a10c0 100644 --- a/src/LuaManager.cpp +++ b/src/LuaManager.cpp @@ -116,6 +116,43 @@ void LuaHelpers::ReadArrayFromTableB( Lua *L, vector &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 ) { diff --git a/src/LuaManager.h b/src/LuaManager.h index 1ecea2bc84..a29ce779f0 100644 --- a/src/LuaManager.h +++ b/src/LuaManager.h @@ -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 &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 &aOut ); void ParseCommandList( lua_State *L, const RString &sCommands, const RString &sName ); diff --git a/src/MusicWheel.cpp b/src/MusicWheel.cpp index e11ee1621f..1b0b5add16 100644 --- a/src/MusicWheel.cpp +++ b/src/MusicWheel.cpp @@ -365,6 +365,7 @@ void MusicWheel::GetSongList( vector &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 &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 &arrayWheelIt // Make an array of Song*, then sort them vector arraySongs; - GetSongList(arraySongs, so); + GetSongList( arraySongs, so ); bool bUseSections = true; diff --git a/src/NoteField.cpp b/src/NoteField.cpp index b28a265ac2..22dda7d111 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -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 ); diff --git a/src/Player.h b/src/Player.h index 365ef8aa37..a611081135 100644 --- a/src/Player.h +++ b/src/Player.h @@ -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(); diff --git a/src/Profile.cpp b/src/Profile.cpp index ae82fa603f..82be153b8b 100644 --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -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 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 tag. Don't load it, but don't - * warn about it. */ + /* The placeholder stats.xml file has an 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 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 ); } }; diff --git a/src/Profile.h b/src/Profile.h index c97baaec75..2dce403afe 100644 --- a/src/Profile.h +++ b/src/Profile.h @@ -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 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; diff --git a/src/ProfileManager.h b/src/ProfileManager.h index 6fdbf2554d..26607f52b1 100644 --- a/src/ProfileManager.h +++ b/src/ProfileManager.h @@ -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 diff --git a/src/RageBitmapTexture.cpp b/src/RageBitmapTexture.cpp index 46fc5dd987..038880d494 100644 --- a/src/RageBitmapTexture.cpp +++ b/src/RageBitmapTexture.cpp @@ -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; } diff --git a/src/RageDisplay.cpp b/src/RageDisplay.cpp index 8c837679a7..c43302cd28 100644 --- a/src/RageDisplay.cpp +++ b/src/RageDisplay.cpp @@ -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 stack; diff --git a/src/RageFileDriverReadAhead.cpp b/src/RageFileDriverReadAhead.cpp index 37e1f0dfc5..d4088fcd0e 100644 --- a/src/RageFileDriverReadAhead.cpp +++ b/src/RageFileDriverReadAhead.cpp @@ -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; } diff --git a/src/RageFileManager_ReadAhead.cpp b/src/RageFileManager_ReadAhead.cpp index e78fa26d4a..dcbb84daba 100644 --- a/src/RageFileManager_ReadAhead.cpp +++ b/src/RageFileManager_ReadAhead.cpp @@ -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 diff --git a/src/RageFileManager_ReadAhead.h b/src/RageFileManager_ReadAhead.h index 9bbc9cdc9f..a5091ca089 100644 --- a/src/RageFileManager_ReadAhead.h +++ b/src/RageFileManager_ReadAhead.h @@ -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 ); }; diff --git a/src/Screen.h b/src/Screen.h index 8b86a8416c..33af0c8bba 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -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: diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 2ea693082b..b6670392d3 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -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 } */ diff --git a/src/ScreenGameplay.h b/src/ScreenGameplay.h index e02146d2e4..fdf75f40c8 100644 --- a/src/ScreenGameplay.h +++ b/src/ScreenGameplay.h @@ -119,9 +119,7 @@ public: bool Center1Player() const; - // // Lua - // virtual void PushSelf( lua_State *L ); Song *GetNextCourseSong() const; LifeMeter *GetLifeMeter( PlayerNumber pn ); diff --git a/src/ScreenGameplaySyncMachine.cpp b/src/ScreenGameplaySyncMachine.cpp index 59764229e3..eecdbc7eef 100644 --- a/src/ScreenGameplaySyncMachine.cpp +++ b/src/ScreenGameplaySyncMachine.cpp @@ -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 ); diff --git a/src/ScreenPrompt.cpp b/src/ScreenPrompt.cpp index 9863f770fb..23b2c695c2 100644 --- a/src/ScreenPrompt.cpp +++ b/src/ScreenPrompt.cpp @@ -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() diff --git a/src/ScreenReloadSongs.cpp b/src/ScreenReloadSongs.cpp index 9848f97280..e7626dc51c 100644 --- a/src/ScreenReloadSongs.cpp +++ b/src/ScreenReloadSongs.cpp @@ -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; diff --git a/src/ScreenSelectMaster.cpp b/src/ScreenSelectMaster.cpp index 4991d6a653..9cfe182ae6 100644 --- a/src/ScreenSelectMaster.cpp +++ b/src/ScreenSelectMaster.cpp @@ -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 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 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; cPlayCommand( 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; cPlayCommand( 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; cSortByDrawOrder(); } -//#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; + } } } } diff --git a/src/Sprite.cpp b/src/Sprite.cpp index c75c61872c..5c88b6cfc6 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -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 );