From dfd860609390a6feab746a16eae300c223a96509 Mon Sep 17 00:00:00 2001 From: freem Date: Sun, 19 Oct 2014 18:29:06 -0500 Subject: [PATCH 01/25] modify StretchNoLoop and StretchRewind to only run certain commands if they exist. fixes issue #337 I also modified StretchNoLoop to start at the beginning of the movie to prevent it from freezing on the last frame (which I'm assuming is not the intended behavior; let me know if that's wrong) --- BackgroundEffects/StretchNoLoop.lua | 12 +++++++++++- BackgroundEffects/StretchRewind.lua | 10 +++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/BackgroundEffects/StretchNoLoop.lua b/BackgroundEffects/StretchNoLoop.lua index c48fe01b0a..0051588fea 100644 --- a/BackgroundEffects/StretchNoLoop.lua +++ b/BackgroundEffects/StretchNoLoop.lua @@ -2,7 +2,17 @@ local Color1 = color(Var "Color1"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;loop,false;effectclock,"music"); + OnCommand=function(self) + self:xy(SCREEN_CENTER_X,SCREEN_CENTER_Y) + self:scale_or_crop_background() + self:diffuse(Color1) + if self.loop ~= nil then + self:loop(false) + -- make videos start at beginning to prevent sticking on last frame + self:position(0) + end + self:effectclock("music") + end; GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; diff --git a/BackgroundEffects/StretchRewind.lua b/BackgroundEffects/StretchRewind.lua index 2e48a26010..9d649131f2 100644 --- a/BackgroundEffects/StretchRewind.lua +++ b/BackgroundEffects/StretchRewind.lua @@ -2,7 +2,15 @@ local Color1 = color(Var "Color1"); local t = Def.ActorFrame { LoadActor(Var "File1") .. { - OnCommand=cmd(x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y;scale_or_crop_background;diffuse,Color1;position,0;effectclock,"music"); + OnCommand=function(self) + self:xy(SCREEN_CENTER_X,SCREEN_CENTER_Y) + self:scale_or_crop_background() + self:diffuse(Color1) + if self.position ~= nil then + self:position(0) + end + self:effectclock("music") + end; GainFocusCommand=cmd(play); LoseFocusCommand=cmd(pause); }; From 6322803d3354cadd0a7b978a88e852329dd1fcbd Mon Sep 17 00:00:00 2001 From: freem Date: Sun, 19 Oct 2014 19:43:23 -0500 Subject: [PATCH 02/25] update changelog with the last fix; SM5 beta 4a shortly. --- Docs/Changelog_sm5.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 5407c5f707..2060b1404d 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -8,6 +8,10 @@ ________________________________________________________________________________ StepMania 5.0 beta 4a | 20141015 -------------------------------------------------------------------------------- +2014/10/19 +---------- +* [BackgroundEffects] Fix error reporting messages coming up unnecessarily. + 2014/10/13 ---------- * [NoteDisplay] Var Player and Var Controller work for non-receptor arrows. From c85bf564d50942d6bb425ccb8f84f974799473e9 Mon Sep 17 00:00:00 2001 From: freem Date: Sun, 19 Oct 2014 19:55:30 -0500 Subject: [PATCH 03/25] changelog cleanup on aisle 5; this feature was just reverted, oops sorry --- Docs/Changelog_sm5.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 2060b1404d..f37ebcfcff 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -14,16 +14,14 @@ StepMania 5.0 beta 4a | 20141015 2014/10/13 ---------- -* [NoteDisplay] Var Player and Var Controller work for non-receptor arrows. +* [NoteDisplay] Var Player and Var Controller work for non-receptor arrows. [hanubeki] * [Mac OS X] Allow StepMania to be built and run in Yosemite. 2014/10/11 ---------- * [NoteDisplay] Add two noteskin metrics, {PartName}NoteColorType and {PartName}NoteColorCount. View https://github.com/stepmania/stepmania/pull/328 -for more information. -* [Steps] If an unrecognized step type is saved, preserve that step instead of -deleting it. A warning will be placed in the log file during song load. +for more information. [hanubeki] ================================================================================ StepMania 5.0 beta 4 | 20140930 From 5ef72ab8b0e3b4dc2ab11095f539872c7f091cae Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Sun, 19 Oct 2014 20:24:06 -0600 Subject: [PATCH 04/25] Set StepsTypeStr in Steps::CreateBlank. --- src/Steps.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Steps.cpp b/src/Steps.cpp index 8f8c9b6016..5883efe1cf 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -497,6 +497,7 @@ void Steps::CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds void Steps::CreateBlank( StepsType ntTo ) { m_StepsType = ntTo; + m_StepsTypeStr= GAMEMAN->GetStepsTypeInfo(ntTo).szName; NoteData noteData; noteData.SetNumTracks( GAMEMAN->GetStepsTypeInfo(ntTo).iNumTracks ); this->SetNoteData( noteData ); From c16f045cb4acc4e5fd3e7844e351e7c2a59b5989 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Mon, 20 Oct 2014 05:14:54 -0600 Subject: [PATCH 05/25] Fixed UnknownStyleSupport. --- src/NotesLoaderSM.cpp | 3 ++- src/NotesLoaderSSC.cpp | 2 ++ src/NotesWriterSM.cpp | 4 ++-- src/NotesWriterSSC.cpp | 4 ++-- src/Song.cpp | 37 +++++++++++++++++++++++++++++++++---- src/Song.h | 2 ++ src/Steps.cpp | 12 +++++++++++- src/Steps.h | 2 ++ 8 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/NotesLoaderSM.cpp b/src/NotesLoaderSM.cpp index 0907970741..11d91d5226 100644 --- a/src/NotesLoaderSM.cpp +++ b/src/NotesLoaderSM.cpp @@ -73,7 +73,7 @@ void SMLoader::LoadFromTokens( Trim( sDifficulty ); Trim( sNoteData ); - // LOG->Trace( "Steps::LoadFromTokens()" ); + // LOG->Trace( "Steps::LoadFromTokens(), %s", sStepsType.c_str() ); // backwards compatibility hacks: // HACK: We eliminated "ez2-single-hard", but we should still handle it. @@ -85,6 +85,7 @@ void SMLoader::LoadFromTokens( sStepsType = "para-single"; out.m_StepsType = GAMEMAN->StringToStepsType( sStepsType ); + out.m_StepsTypeStr = sStepsType; out.SetDescription( sDescription ); out.SetCredit( sDescription ); // this is often used for both. out.SetChartName(sDescription); // yeah, one more for good measure. diff --git a/src/NotesLoaderSSC.cpp b/src/NotesLoaderSSC.cpp index 9f4be80a2c..5f1d084dfb 100644 --- a/src/NotesLoaderSSC.cpp +++ b/src/NotesLoaderSSC.cpp @@ -643,6 +643,7 @@ bool SSCLoader::LoadFromSimfile( const RString &sPath, Song &out, bool bFromCach if( sValueName=="STEPSTYPE" ) { pNewNotes->m_StepsType = GAMEMAN->StringToStepsType( sParams[1] ); + pNewNotes->m_StepsTypeStr= sParams[1]; } else if( sValueName=="CHARTSTYLE" ) @@ -965,6 +966,7 @@ bool SSCLoader::LoadEditFromMsd(const MsdFile &msd, if( sValueName=="STEPSTYPE" ) { pNewNotes->m_StepsType = GAMEMAN->StringToStepsType( sParams[1] ); + pNewNotes->m_StepsTypeStr= sParams[1]; bSSCFormat = true; } diff --git a/src/NotesWriterSM.cpp b/src/NotesWriterSM.cpp index 8f131b9210..504b3ebafe 100644 --- a/src/NotesWriterSM.cpp +++ b/src/NotesWriterSM.cpp @@ -206,9 +206,9 @@ static RString GetSMNotesTag( const Song &song, const Steps &in ) lines.push_back( "" ); // Escape to prevent some clown from making a comment of "\r\n;" lines.push_back( ssprintf("//---------------%s - %s----------------", - GAMEMAN->GetStepsTypeInfo(in.m_StepsType).szName, SmEscape(in.GetDescription()).c_str()) ); + in.m_StepsTypeStr.c_str(), SmEscape(in.GetDescription()).c_str()) ); lines.push_back( song.m_vsKeysoundFile.empty() ? "#NOTES:" : "#NOTES2:" ); - lines.push_back( ssprintf( " %s:", GAMEMAN->GetStepsTypeInfo(in.m_StepsType).szName ) ); + lines.push_back( ssprintf( " %s:", in.m_StepsTypeStr.c_str() ) ); RString desc = (USE_CREDIT ? in.GetCredit() : in.GetChartName()); lines.push_back( ssprintf( " %s:", SmEscape(desc).c_str() ) ); lines.push_back( ssprintf( " %s:", DifficultyToString(in.GetDifficulty()).c_str() ) ); diff --git a/src/NotesWriterSSC.cpp b/src/NotesWriterSSC.cpp index 3bb8fdfa73..1f5971f149 100644 --- a/src/NotesWriterSSC.cpp +++ b/src/NotesWriterSSC.cpp @@ -349,10 +349,10 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa lines.push_back( "" ); // Escape to prevent some clown from making a comment of "\r\n;" lines.push_back( ssprintf("//---------------%s - %s----------------", - GAMEMAN->GetStepsTypeInfo(in.m_StepsType).szName, SmEscape(in.GetDescription()).c_str()) ); + in.m_StepsTypeStr.c_str(), SmEscape(in.GetDescription()).c_str()) ); lines.push_back( "#NOTEDATA:;" ); // our new separator. lines.push_back( ssprintf( "#CHARTNAME:%s;", SmEscape(in.GetChartName()).c_str())); - lines.push_back( ssprintf( "#STEPSTYPE:%s;", GAMEMAN->GetStepsTypeInfo(in.m_StepsType).szName ) ); + lines.push_back( ssprintf( "#STEPSTYPE:%s;", in.m_StepsTypeStr.c_str() ) ); lines.push_back( ssprintf( "#DESCRIPTION:%s;", SmEscape(in.GetDescription()).c_str() ) ); lines.push_back( ssprintf( "#CHARTSTYLE:%s;", SmEscape(in.GetChartStyle()).c_str() ) ); lines.push_back( ssprintf( "#DIFFICULTY:%s;", DifficultyToString(in.GetDifficulty()).c_str() ) ); diff --git a/src/Song.cpp b/src/Song.cpp index 9d1495a681..27c20aa76f 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -42,7 +42,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 220; +const int FILE_CACHE_VERSION = 221; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; @@ -89,6 +89,11 @@ Song::~Song() FOREACH( Steps*, m_vpSteps, s ) SAFE_DELETE( *s ); m_vpSteps.clear(); + FOREACH(Steps*, m_UnknownStyleSteps, s) + { + SAFE_DELETE(*s); + } + m_UnknownStyleSteps.clear(); // It's the responsibility of the owner of this Song to make sure // that all pointers to this Song and its Steps are invalidated. @@ -99,6 +104,7 @@ void Song::DetachSteps() m_vpSteps.clear(); FOREACH_ENUM( StepsType, st ) m_vpStepsByType[st].clear(); + m_UnknownStyleSteps.clear(); } float Song::GetFirstSecond() const @@ -154,6 +160,11 @@ void Song::Reset() m_vpSteps.clear(); FOREACH_ENUM( StepsType, st ) m_vpStepsByType[st].clear(); + FOREACH(Steps*, m_UnknownStyleSteps, s) + { + SAFE_DELETE(*s); + } + m_UnknownStyleSteps.clear(); Song empty; *this = empty; @@ -1023,6 +1034,10 @@ bool Song::SaveToSMFile() vpStepsToSave.push_back( pSteps ); } + FOREACH_CONST(Steps*, m_UnknownStyleSteps, s) + { + vpStepsToSave.push_back(*s); + } return NotesWriterSM::Write( sPath, *this, vpStepsToSave ); @@ -1055,6 +1070,10 @@ bool Song::SaveToSSCFile( RString sPath, bool bSavingCache ) pSteps->SetFilename(path); vpStepsToSave.push_back( pSteps ); } + FOREACH_CONST(Steps*, m_UnknownStyleSteps, s) + { + vpStepsToSave.push_back(*s); + } if (bSavingCache) { @@ -1504,9 +1523,19 @@ RString Song::GetTranslitFullTitle() const void Song::AddSteps( Steps* pSteps ) { - m_vpSteps.push_back( pSteps ); - ASSERT_M( pSteps->m_StepsType < NUM_StepsType, ssprintf("%i", pSteps->m_StepsType) ); - m_vpStepsByType[pSteps->m_StepsType].push_back( pSteps ); + // Songs of unknown stepstype are saved as a forwards compatibility feature + // so that editing a simfile made by a future version that has a new style + // won't delete those steps. -Kyz + if(pSteps->m_StepsType != StepsType_Invalid) + { + m_vpSteps.push_back( pSteps ); + ASSERT_M( pSteps->m_StepsType < NUM_StepsType, ssprintf("%i", pSteps->m_StepsType) ); + m_vpStepsByType[pSteps->m_StepsType].push_back( pSteps ); + } + else + { + m_UnknownStyleSteps.push_back(pSteps); + } } void Song::DeleteSteps( const Steps* pSteps, bool bReAutoGen ) diff --git a/src/Song.h b/src/Song.h index 65486e7327..d786cb1b90 100644 --- a/src/Song.h +++ b/src/Song.h @@ -447,6 +447,8 @@ private: vector m_vpSteps; /** @brief the Steps of a particular StepsType that belong to this Song. */ vector m_vpStepsByType[NUM_StepsType]; + /** @brief the Steps that are of unrecognized Styles. */ + vector m_UnknownStyleSteps; }; #endif diff --git a/src/Steps.cpp b/src/Steps.cpp index 247c651e67..1b672ffb2d 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -258,8 +258,16 @@ float Steps::PredictMeter() const void Steps::TidyUpData() { + // Don't set the StepsType to dance single if it's invalid. That just + // causes unrecognized charts to end up where they don't belong. + // Leave it as StepsType_Invalid so the Song can handle it specially. This + // is a forwards compatibility feature, so that if a future version adds a + // new style, editing a simfile with unrecognized Steps won't silently + // delete them. -Kyz if( m_StepsType == StepsType_Invalid ) - m_StepsType = StepsType_dance_single; + { + LOG->Warn("Detected steps with unknown style '%s' in '%s'", m_StepsTypeStr.c_str(), m_pSong->m_sSongFileName.c_str()); + } if( GetDifficulty() == Difficulty_Invalid ) SetDifficulty( StringToDifficulty(GetDescription()) ); @@ -465,12 +473,14 @@ void Steps::AutogenFrom( const Steps *parent_, StepsType ntTo ) { parent = parent_; m_StepsType = ntTo; + m_StepsTypeStr= GAMEMAN->GetStepsTypeInfo(ntTo).szName; m_Timing = parent->m_Timing; } void Steps::CopyFrom( Steps* pSource, StepsType ntTo, float fMusicLengthSeconds ) // pSource does not have to be of the same StepsType { m_StepsType = ntTo; + m_StepsTypeStr= GAMEMAN->GetStepsTypeInfo(ntTo).szName; NoteData noteData; pSource->GetNoteData( noteData ); noteData.SetNumTracks( GAMEMAN->GetStepsTypeInfo(ntTo).iNumTracks ); diff --git a/src/Steps.h b/src/Steps.h index 178a0ab725..05440011b6 100644 --- a/src/Steps.h +++ b/src/Steps.h @@ -177,6 +177,8 @@ public: void PushSelf( lua_State *L ); StepsType m_StepsType; + /** @brief The string form of the StepsType, for dealing with unrecognized styles. */ + RString m_StepsTypeStr; /** @brief The Song these Steps are associated with */ Song *m_pSong; From 1d061ac4ddb368310f4f556efa7c72e94ec6731d Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Mon, 20 Oct 2014 12:26:29 -0600 Subject: [PATCH 06/25] Don't crash if AI.ini doesn't exist. --- src/PlayerAI.cpp | 108 ++++++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 44 deletions(-) diff --git a/src/PlayerAI.cpp b/src/PlayerAI.cpp index b7bf80905e..29b73a9bf7 100644 --- a/src/PlayerAI.cpp +++ b/src/PlayerAI.cpp @@ -11,6 +11,29 @@ struct TapScoreDistribution { float fPercent[NUM_TapNoteScore]; + void ChangeWeightsToPercents() + { + float sum= 0; + for(int i= 0; i < NUM_TapNoteScore; ++i) + { + sum+= fPercent[i]; + } + for(int i= 0; i < NUM_TapNoteScore; ++i) + { + fPercent[i]/= sum; + } + } + void SetDefaultWeights() + { + fPercent[TNS_None] = 0; + fPercent[TNS_Miss] = 1; + fPercent[TNS_W5] = 0; + fPercent[TNS_W4] = 0; + fPercent[TNS_W3] = 0; + fPercent[TNS_W2] = 0; + fPercent[TNS_W1] = 0; + } + TapNoteScore GetTapNoteScore() { float fRand = randomf(0,1); @@ -31,57 +54,54 @@ static TapScoreDistribution g_Distributions[NUM_SKILL_LEVELS]; void PlayerAI::InitFromDisk() { - bool bSuccess; - IniFile ini; - bSuccess = ini.ReadFile( AI_PATH ); - ASSERT( bSuccess ); - - for( int i=0; iGetAttrValue( "WeightMiss", dist.fPercent[TNS_Miss] ); - SET_MALF_IF(!bSuccess, TNS_Miss); - bSuccess = pNode->GetAttrValue( "WeightW5", dist.fPercent[TNS_W5] ); - SET_MALF_IF(!bSuccess, TNS_W5); - bSuccess = pNode->GetAttrValue( "WeightW4", dist.fPercent[TNS_W4] ); - SET_MALF_IF(!bSuccess, TNS_W4); - bSuccess = pNode->GetAttrValue( "WeightW3", dist.fPercent[TNS_W3] ); - SET_MALF_IF(!bSuccess, TNS_W3); - bSuccess = pNode->GetAttrValue( "WeightW2", dist.fPercent[TNS_W2] ); - SET_MALF_IF(!bSuccess, TNS_W2); - bSuccess = pNode->GetAttrValue( "WeightW1", dist.fPercent[TNS_W1] ); - SET_MALF_IF(!bSuccess, TNS_W1); -#undef SET_MALF_IF + else + { + #define SET_MALF_IF(condition, tns) \ + if(condition) \ + { \ + LuaHelpers::ReportScriptErrorFmt("AI weight for " #tns " in \"%s\" section not set.", sKey.c_str()); \ + dist.fPercent[tns]= 0; \ + } + dist.fPercent[TNS_None] = 0; + bSuccess = pNode->GetAttrValue( "WeightMiss", dist.fPercent[TNS_Miss] ); + SET_MALF_IF(!bSuccess, TNS_Miss); + bSuccess = pNode->GetAttrValue( "WeightW5", dist.fPercent[TNS_W5] ); + SET_MALF_IF(!bSuccess, TNS_W5); + bSuccess = pNode->GetAttrValue( "WeightW4", dist.fPercent[TNS_W4] ); + SET_MALF_IF(!bSuccess, TNS_W4); + bSuccess = pNode->GetAttrValue( "WeightW3", dist.fPercent[TNS_W3] ); + SET_MALF_IF(!bSuccess, TNS_W3); + bSuccess = pNode->GetAttrValue( "WeightW2", dist.fPercent[TNS_W2] ); + SET_MALF_IF(!bSuccess, TNS_W2); + bSuccess = pNode->GetAttrValue( "WeightW1", dist.fPercent[TNS_W1] ); + SET_MALF_IF(!bSuccess, TNS_W1); + #undef SET_MALF_IF + } + dist.ChangeWeightsToPercents(); } - - float fSum = 0; - for( int j=0; j Date: Mon, 20 Oct 2014 22:17:20 -0600 Subject: [PATCH 07/25] Added StageStats:GetStepsSeconds lua function. --- Docs/Changelog_sm5.txt | 12 +++++++++--- Docs/Luadoc/Lua.xml | 1 + Docs/Luadoc/LuaDocumentation.xml | 3 +++ src/StageStats.cpp | 2 ++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index f37ebcfcff..4b5ee89309 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -4,13 +4,19 @@ The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt. ________________________________________________________________________________ +2014/10/20 +---------- +* [StageStats] GetStepsSeconds function added. +* [Steps] If an unrecognized step type is saved, preserve that step instead of + deleting it. A warning will be placed in the log file during song load. + ================================================================================ StepMania 5.0 beta 4a | 20141015 -------------------------------------------------------------------------------- 2014/10/19 ---------- -* [BackgroundEffects] Fix error reporting messages coming up unnecessarily. +* [BackgroundEffects] Fixed errors in StretchNoLoop and StretchRewind. 2014/10/13 ---------- @@ -20,8 +26,8 @@ StepMania 5.0 beta 4a | 20141015 2014/10/11 ---------- * [NoteDisplay] Add two noteskin metrics, {PartName}NoteColorType and -{PartName}NoteColorCount. View https://github.com/stepmania/stepmania/pull/328 -for more information. [hanubeki] + {PartName}NoteColorCount. View https://github.com/stepmania/stepmania/pull/328 + for more information. [hanubeki] ================================================================================ StepMania 5.0 beta 4 | 20140930 diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index 56e03b147b..de8282d3f5 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -1584,6 +1584,7 @@ + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index e92ed90d92..e9c33fedd4 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -2464,6 +2464,9 @@ save yourself some time, copy this for undocumented things: Returns the current stage index. + + Returns the current StepsSeconds, which is the time value used to set the samples in a player's life record. + Return the random seed for the current stage. diff --git a/src/StageStats.cpp b/src/StageStats.cpp index 0a0812bf52..348b0c0ecb 100644 --- a/src/StageStats.cpp +++ b/src/StageStats.cpp @@ -377,6 +377,7 @@ public: static int AllFailed( T* p, lua_State *L ) { lua_pushboolean(L, p->AllFailed()); return 1; } static int GetStage( T* p, lua_State *L ) { LuaHelpers::Push( L, p->m_Stage ); return 1; } DEFINE_METHOD( GetStageIndex, m_iStageIndex ) + DEFINE_METHOD(GetStepsSeconds, m_fStepsSeconds) static int PlayerHasHighScore( T* p, lua_State *L ) { lua_pushboolean(L, p->PlayerHasHighScore(Enum::Check(L, 1))); @@ -395,6 +396,7 @@ public: ADD_METHOD( AllFailed ); ADD_METHOD( GetStage ); ADD_METHOD( GetStageIndex ); + ADD_METHOD( GetStepsSeconds ); ADD_METHOD( PlayerHasHighScore ); ADD_METHOD( GetEarnedExtraStage ); } From ca4eb65b61754524d0f05ee639ca038a82e7e6ca Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Thu, 23 Oct 2014 00:13:13 -0600 Subject: [PATCH 08/25] Added lerp, lerp_color, approach, and multiapproach lua functions. --- Docs/Changelog_sm5.txt | 4 ++ Docs/Luadoc/Lua.xml | 4 ++ Docs/Luadoc/LuaDocumentation.xml | 17 +++++- Themes/_fallback/Scripts/02 Utilities.lua | 2 + src/LuaManager.h | 5 ++ src/RageTypes.cpp | 25 +++++++- src/RageTypes.h | 1 + src/RageUtil.cpp | 70 +++++++++++++++++++++++ 8 files changed, 125 insertions(+), 3 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 4b5ee89309..8dc574e629 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -4,6 +4,10 @@ The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt. ________________________________________________________________________________ +2014/10/23 +---------- +* [Global] approach, multiapproach, lerp, and lerp_color lua functions added. + 2014/10/20 ---------- * [StageStats] GetStepsSeconds function added. diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml index de8282d3f5..ab33c6e73d 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/Luadoc/Lua.xml @@ -203,6 +203,7 @@ + @@ -219,11 +220,14 @@ + + + diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index e9c33fedd4..ae50abaebf 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -31,6 +31,10 @@ save yourself some time, copy this for undocumented things: [02 Colors.lua] Returns a color with the specified alpha. + + Use this to make a current value approach a goal value at the given speed. Speed must not be negative. The value will not overshoot the goal.
+ Note: When you see the error "approach: speed 1 is negative." it means that the speed value passed was negative. The 1 is there because approach and multiapproach use the same internal function and can be ignored when using approach. +
[03 CustomSpeedMods.lua] @@ -136,7 +140,7 @@ save yourself some time, copy this for undocumented things: [03 Gameplay.lua]
- [02 Utilities.lua] + [02 Utilities.lua] Old name for approach. [02 Utilities.lua] Return the index of a true value in list. @@ -327,6 +331,12 @@ save yourself some time, copy this for undocumented things: [02 Colors.lua] + + Returns a number linearly interpolated between start and end by percent. + + + Same as lerp, but for colors. All channels will reach the end of the interpolation at the same time. + Returns an Actor definition for the actor at sPath. If sPath points to a Lua file, any additional arguments will be passed to that script. @@ -369,6 +379,11 @@ save yourself some time, copy this for undocumented things: Returns Month m as a string. + + Similar to approach, but operates on tables of values instead of single values. This will modify the contents of currents in place, as well as returning currents.
+ currents, goals, and speeds must all be the same size and contain only numbers.
+ Note: When you see the error "approach: speed 1 is negative." it means that a speed value passed was negative. The 1 tells you which entry in the table was invalid. +
"Allows a program to traverse all fields of a table. Its first argument is a table and its second argument is an index in this table. diff --git a/Themes/_fallback/Scripts/02 Utilities.lua b/Themes/_fallback/Scripts/02 Utilities.lua index 4750c48b7d..53a3acf534 100644 --- a/Themes/_fallback/Scripts/02 Utilities.lua +++ b/Themes/_fallback/Scripts/02 Utilities.lua @@ -66,6 +66,8 @@ function wrap(val,n) end function fapproach(val, other_val, to_move) + -- This does not use the (faster) C++ side version of approach because I + -- don't want to find out how many themes pass a negative speed. -Kyz if val == other_val then return val -- already done! end diff --git a/src/LuaManager.h b/src/LuaManager.h index 644780eb67..8573394ee4 100644 --- a/src/LuaManager.h +++ b/src/LuaManager.h @@ -266,6 +266,11 @@ void LuaFunc_Register_##func( lua_State *L ); \ void LuaFunc_Register_##func( lua_State *L ) { lua_register( L, #func, LuaFunc_##func ); } \ REGISTER_WITH_LUA_FUNCTION( LuaFunc_Register_##func ); +#define LUAFUNC_REGISTER_COMMON(func_name) \ +void LuaFunc_Register_##func_name(lua_State* L); \ +void LuaFunc_Register_##func_name(lua_State* L) { lua_register(L, #func_name, LuaFunc_##func_name); } \ +REGISTER_WITH_LUA_FUNCTION(LuaFunc_Register_##func_name); + #endif /* diff --git a/src/RageTypes.cpp b/src/RageTypes.cpp index b3d96215a2..b554a042e7 100644 --- a/src/RageTypes.cpp +++ b/src/RageTypes.cpp @@ -74,6 +74,14 @@ RString RageColor::NormalizeColorString( RString sColor ) return c.ToString(); } +void lerp_rage_color(RageColor& out, RageColor const& a, RageColor const& b, float t) +{ + out.b= lerp(t, a.b, b.b); + out.g= lerp(t, a.g, b.g); + out.r= lerp(t, a.r, b.r); + out.a= lerp(t, a.a, b.a); +} + void WeightedAvergeOfRSVs(RageSpriteVertex& average_out, RageSpriteVertex const& rsv1, RageSpriteVertex const& rsv2, float percent_between) { average_out.p= lerp(percent_between, rsv1.p, rsv2.p); @@ -207,8 +215,21 @@ int LuaFunc_color( lua_State *L ) c.PushTable( L ); return 1; } -void LuaFunc_Register_color( lua_State *L ) { lua_register( L, "color", LuaFunc_color ); } -REGISTER_WITH_LUA_FUNCTION( LuaFunc_Register_color ); +LUAFUNC_REGISTER_COMMON(color); + +int LuaFunc_lerp_color(lua_State *L) +{ + // Args: percent, color, color + // Returns: color + float percent= FArg(1); + RageColor a, b, c; + a.FromStack(L, 2); + b.FromStack(L, 3); + lerp_rage_color(c, a, b, percent); + c.PushTable(L); + return 1; +} +LUAFUNC_REGISTER_COMMON(lerp_color); /* * Copyright (c) 2006 Glenn Maynard diff --git a/src/RageTypes.h b/src/RageTypes.h index 0a5d51a1c9..ddfc3e88ec 100644 --- a/src/RageTypes.h +++ b/src/RageTypes.h @@ -342,6 +342,7 @@ struct RageSpriteVertex // has color RageVector2 t; // texture coordinates }; +void lerp_rage_color(RageColor& out, RageColor const& a, RageColor const& b, float t); void WeightedAvergeOfRSVs(RageSpriteVertex& average_out, RageSpriteVertex const& rsv1, RageSpriteVertex const& rsv2, float percent_between); struct RageModelVertex // doesn't have color. Relies on material color diff --git a/src/RageUtil.cpp b/src/RageUtil.cpp index 8255f9e96d..c2d033f87e 100644 --- a/src/RageUtil.cpp +++ b/src/RageUtil.cpp @@ -2329,6 +2329,76 @@ LuaFunction( PrettyPercent, PrettyPercent( FArg(1), FArg(2) ) ); //LuaFunction( IsHexVal, IsHexVal( SArg(1) ) ); static bool UndocumentedFeature( RString s ){ sm_crash(s); return true; } LuaFunction( UndocumentedFeature, UndocumentedFeature(SArg(1)) ); +LuaFunction( lerp, lerp(FArg(1), FArg(2), FArg(3)) ); + +void luafunc_approach_internal(lua_State* L, int valind, int goalind, int speedind); +void luafunc_approach_internal(lua_State* L, int valind, int goalind, int speedind, int process_index) +{ +#define TONUMBER_NICE(dest, num_name, index) \ + if(!lua_isnumber(L, index)) \ + { \ + luaL_error(L, "approach: " #num_name " for approach %d is not a number.", process_index); \ + } \ + dest= lua_tonumber(L, index); + float val= 0; + float goal= 0; + float speed= 0; + TONUMBER_NICE(val, current, valind); + TONUMBER_NICE(goal, goal, goalind); + TONUMBER_NICE(speed, speed, speedind); +#undef TONUMBER_NICE + if(speed < 0) + { + luaL_error(L, "approach: speed %d is negative.", process_index); + } + fapproach(val, goal, speed); + lua_pushnumber(L, val); +} + +int LuaFunc_approach(lua_State* L); +int LuaFunc_approach(lua_State* L) +{ + // Args: current, goal, speed + // Returns: new_current + luafunc_approach_internal(L, 1, 2, 3, 1); + return 1; +} +LUAFUNC_REGISTER_COMMON(approach); + +int LuaFunc_multiapproach(lua_State* L); +int LuaFunc_multiapproach(lua_State* L) +{ + // Args: {currents}, {goals}, {speeds} + // Returns: {currents} + // Modifies the values in {currents} in place. + if(lua_gettop(L) != 3) + { + luaL_error(L, "multiapproach: A table of current values, a table of goal values, and a table of speeds must be passed."); + } + size_t currents_len= lua_objlen(L, 1); + size_t goals_len= lua_objlen(L, 2); + size_t speeds_len= lua_objlen(L, 3); + if(currents_len != goals_len || currents_len != speeds_len) + { + luaL_error(L, "multiapproach: There must be the same number of current values, goal values, and speeds."); + } + if(!lua_istable(L, 1) || !lua_istable(L, 2) || !lua_istable(L, 3)) + { + luaL_error(L, "multiapproach: current, goal, and speed must all be tables."); + } + for(size_t i= 1; i <= currents_len; ++i) + { + lua_rawgeti(L, 1, i); + lua_rawgeti(L, 2, i); + lua_rawgeti(L, 3, i); + luafunc_approach_internal(L, -3, -2, -1, i); + lua_rawseti(L, 1, i); + lua_pop(L, 3); + } + lua_pushvalue(L, 1); + return 1; +} +LUAFUNC_REGISTER_COMMON(multiapproach); /* * Copyright (c) 2001-2005 Chris Danford, Glenn Maynard From c407feeb341acbf05777ad04ffb644b8a4cd1d65 Mon Sep 17 00:00:00 2001 From: hanubeki Date: Mon, 27 Oct 2014 00:14:35 +0900 Subject: [PATCH 09/25] Fix P2 input when PlayerAutoplay in P1 --- src/ScreenGameplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 5b6c7ff8fa..3d058200e3 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -2369,7 +2369,7 @@ bool ScreenGameplay::Input( const InputEventPlus &input ) { AbortGiveUp( true ); - if( GamePreferences::m_AutoPlay == PC_HUMAN && GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetCurrent().m_fPlayerAutoPlay == 0 ) + if( GamePreferences::m_AutoPlay == PC_HUMAN && GAMESTATE->m_pPlayerState[input.pn]->m_PlayerOptions.GetCurrent().m_fPlayerAutoPlay == 0 ) { PlayerInfo& pi = GetPlayerInfoForInput( input ); From 5639a0d31f418c3a1af81fd0b710a7609f07fc88 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Tue, 28 Oct 2014 20:32:38 -0600 Subject: [PATCH 10/25] Lineage reporting for nil commands in RunCommands. Stricter type checking for FormatPercentScore in PercentageDisplay. --- Themes/_fallback/metrics.ini | 4 ++-- Themes/default/metrics.ini | 2 -- src/Actor.cpp | 8 ++++---- src/PercentageDisplay.cpp | 39 ++++++++++++++++++++++++++---------- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 80822b09eb..8f5acd8502 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -706,7 +706,7 @@ PercentUseRemainder=false ApplyScoreDisplayOptions=true DancePointsDigits=5 # -Format="%2d" +Format=FormatPercentScore # RemainderFormat= # @@ -1399,7 +1399,7 @@ DancePointsDigits=1 PercentUseRemainder=true ApplyScoreDisplayOptions=false FormatPercentScore=FormatPercentScore -Format= +Format=FormatPercentScore [SoundEffectControl] LockToHold=false diff --git a/Themes/default/metrics.ini b/Themes/default/metrics.ini index 1ca22b3422..dc6b0a6018 100644 --- a/Themes/default/metrics.ini +++ b/Themes/default/metrics.ini @@ -140,8 +140,6 @@ NumLivesP2OnCommand=zoomx,-1 NumLivesP2LoseLifeCommand=zoomx,-1.5;zoomy,1.5;linear,0.15;zoomx,-1;zoomy,1 [LifeMeterBattery Percent] -# still asking for this even though it's in fallback... -aj -Format= # PercentP2OnCommand=zoom,0.7;zoomx,-0.7;shadowlength,0;diffuse,PlayerColor(PLAYER_2) DancePointsP2OnCommand=zoom,0.7;zoomx,-0.7;shadowlength,0;diffuse,PlayerColor(PLAYER_2) diff --git a/src/Actor.cpp b/src/Actor.cpp index c93509fa69..3d8e8b9694 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -785,7 +785,7 @@ RString Actor::GetLineage() const if( m_pParent ) sPath = m_pParent->GetLineage() + '/'; - sPath += ssprintf( "<%s> %s", typeid(*this).name(), m_sName.c_str() ); + sPath += ssprintf( " %s", typeid(*this).name(), m_sName.c_str() ); return sPath; } @@ -1130,7 +1130,7 @@ void Actor::RunCommands( const LuaReference& cmds, const LuaReference *pParamTab { if( !cmds.IsSet() || cmds.IsNil() ) { - LuaHelpers::ReportScriptError("RunCommands: command is unset or nil"); + LuaHelpers::ReportScriptErrorFmt("RunCommands: commands for %s are unset or nil", GetLineage().c_str()); return; } @@ -1140,7 +1140,7 @@ void Actor::RunCommands( const LuaReference& cmds, const LuaReference *pParamTab cmds.PushSelf( L ); if( lua_isnil(L, -1) ) { - LuaHelpers::ReportScriptError("Error compiling commands"); + LuaHelpers::ReportScriptErrorFmt("RunCommands: Error compiling commands for %s", GetLineage().c_str()); LUA->Release(L); return; } @@ -1155,7 +1155,7 @@ void Actor::RunCommands( const LuaReference& cmds, const LuaReference *pParamTab pParamTable->PushSelf( L ); // call function with 2 arguments and 0 results - RString Error= "Error playing command: "; + RString Error= "Error playing command:"; LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); LUA->Release(L); diff --git a/src/PercentageDisplay.cpp b/src/PercentageDisplay.cpp index 28eec2fa7e..99cc9971e4 100644 --- a/src/PercentageDisplay.cpp +++ b/src/PercentageDisplay.cpp @@ -33,10 +33,22 @@ void PercentageDisplay::LoadFromNode( const XNode* pNode ) pNode->GetAttrValue( "AutoRefresh", m_bAutoRefresh ); { Lua *L = LUA->Get(); - if( pNode->PushAttrValue(L, "FormatPercentScore") ) + if(pNode->PushAttrValue(L, "FormatPercentScore")) + { m_FormatPercentScore.SetFromStack( L ); + if(m_FormatPercentScore.GetLuaType() != LUA_TFUNCTION) + { + // Not reported as an error because _fallback and default provided bad + // examples in their [LifeMeterBattery Percent]:Format metric and nobody + // realized it was supposed to be set to a function. -Kyz + LOG->Trace("Format attribute for PercentageDisplay named '%s' is not a function. Defaulting to 'FormatPercentScore'.", GetName().c_str()); + m_FormatPercentScore.SetFromExpression("FormatPercentScore"); + } + } else + { lua_pop(L, 1); + } LUA->Release(L); } @@ -86,9 +98,12 @@ void PercentageDisplay::Load( const PlayerState *pPlayerState, const PlayerStage m_sPercentFormat = THEME->GetMetric( sMetricsGroup, "PercentFormat" ); m_sRemainderFormat = THEME->GetMetric( sMetricsGroup, "RemainderFormat" ); - if( m_FormatPercentScore.IsNil() ) + if(m_FormatPercentScore.GetLuaType() != LUA_TFUNCTION) { - LOG->Trace( "Format is nil in [%s]. Defaulting to 'FormatPercentScore'.", sMetricsGroup.c_str() ); + // Not reported as an error because _fallback and default provided bad + // examples in their [LifeMeterBattery Percent]:Format metric and nobody + // realized it was supposed to be set to a function. -Kyz + LOG->Trace("Format metric is not a function in [%s]. Defaulting to 'FormatPercentScore'.", sMetricsGroup.c_str()); m_FormatPercentScore.SetFromExpression( "FormatPercentScore" ); } @@ -157,14 +172,16 @@ void PercentageDisplay::Refresh() } else { - Lua *L = LUA->Get(); - m_FormatPercentScore.PushSelf( L ); - ASSERT( !lua_isnil(L, -1) ); - LuaHelpers::Push( L, fPercentDancePoints ); - RString Error= "Error running FormatPercentScore: "; - LuaHelpers::RunScriptOnStack(L, Error, 1, 1, true); // 1 arg, 1 result - LuaHelpers::Pop( L, sNumToDisplay ); - LUA->Release(L); + if(m_FormatPercentScore.GetLuaType() == LUA_TFUNCTION) + { + Lua *L = LUA->Get(); + m_FormatPercentScore.PushSelf( L ); + LuaHelpers::Push( L, fPercentDancePoints ); + RString Error= "Error running FormatPercentScore: "; + LuaHelpers::RunScriptOnStack(L, Error, 1, 1, true); // 1 arg, 1 result + LuaHelpers::Pop( L, sNumToDisplay ); + LUA->Release(L); + } // HACK: Use the last frame in the numbers texture as '-' sNumToDisplay.Replace('-','x'); From d2b61644f32050238ed1641127ff4965f7a581e8 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Wed, 29 Oct 2014 00:14:13 -0600 Subject: [PATCH 11/25] Changed ColorToHex to just use string.format instead of useless number to hexstring to number to hexstring conversion. --- Themes/_fallback/Scripts/02 Colors.lua | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/Themes/_fallback/Scripts/02 Colors.lua b/Themes/_fallback/Scripts/02 Colors.lua index 3fe7335e3d..31b2036ba6 100644 --- a/Themes/_fallback/Scripts/02 Colors.lua +++ b/Themes/_fallback/Scripts/02 Colors.lua @@ -191,8 +191,6 @@ end -- ColorToHex(c) -- Takes in a normal color("") and returns the hex representation. --- Adapted from code in LuaBit (http://luaforge.net/projects/bit/), --- which is MIT licensed and copyright (C) 2006~2007 hanzhao. function ColorToHex(c) local r = c[1] local g = c[2] @@ -200,27 +198,7 @@ function ColorToHex(c) local a = HasAlpha(c) local function hex(value) - value = math.ceil(value) - - local hexVals = { 'A', 'B', 'C', 'D', 'E', 'F' } - local out = "" - local last = 0 - - while(value ~= 0) do - last = math.mod(value, 16) - if(last < 10) then - out = tostring(last) .. out - else - out = hexVals[(last-10)+1] .. out - end - value = math.floor(value/16) - end - - if(out == "") then - return "00" - end - - return string.format( "%02X", tonumber(out,16) ) + return ("%02X"):format(value) end local rX = hex( scale(r, 0, 1, 0, 255) ) From a5289ddacae105cd5ea63af5a8a732e159fbddc3 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Wed, 29 Oct 2014 17:43:37 -0600 Subject: [PATCH 12/25] Fixed broken else-if chain in Actor::SetEffectClockString. Changed error to not crash Stepmania. --- src/Actor.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 3d8e8b9694..0e487dcd9a 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -889,7 +889,7 @@ void Actor::ScaleTo( const RectF &rect, StretchType st ) void Actor::SetEffectClockString( const RString &s ) { if (s.EqualsNoCase("timer")) this->SetEffectClock( CLOCK_TIMER ); - if (s.EqualsNoCase("timerglobal")) this->SetEffectClock( CLOCK_TIMER_GLOBAL ); + else if(s.EqualsNoCase("timerglobal")) this->SetEffectClock( CLOCK_TIMER_GLOBAL ); else if(s.EqualsNoCase("beat")) this->SetEffectClock( CLOCK_BGM_BEAT ); else if(s.EqualsNoCase("music")) this->SetEffectClock( CLOCK_BGM_TIME ); else if(s.EqualsNoCase("bgm")) this->SetEffectClock( CLOCK_BGM_BEAT ); // compat, deprecated @@ -899,9 +899,13 @@ void Actor::SetEffectClockString( const RString &s ) { CabinetLight cl = StringToCabinetLight( s ); if( cl == CabinetLight_Invalid ) - FAIL_M(ssprintf("Invalid cabinet light: %s", s.c_str())); - - this->SetEffectClock( (EffectClock) (cl + CLOCK_LIGHT_1) ); + { + LuaHelpers::ReportScriptErrorFmt("String '%s' is not an effect clock string or the name of a cabinet light.", s.c_str()); + } + else + { + this->SetEffectClock(static_cast(cl + CLOCK_LIGHT_1)); + } } } From 4d703b887026f5ca394bba4617e1fe19ce9ac7f9 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Wed, 29 Oct 2014 20:29:56 -0600 Subject: [PATCH 13/25] Minor docs change for effect colors. --- Docs/Luadoc/LuaDocumentation.xml | 14 +++++++------- Docs/Themerdocs/effect_colors.txt | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) create mode 100644 Docs/Themerdocs/effect_colors.txt diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml index ae50abaebf..c6209eb1d4 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/Luadoc/LuaDocumentation.xml @@ -984,7 +984,7 @@ save yourself some time, copy this for undocumented things: Sets the Actor's alpha level to fAlpha, where fAlpha is in the range 0..1. - Makes the Actor switch between two colors immediately. + Makes the Actor switch between two colors immediately. See Themerdocs/effect_colors.txt for an example. Sets the Actor's bottom edge color to c. @@ -1002,13 +1002,13 @@ save yourself some time, copy this for undocumented things: Sets the Actor's lower right corner color to c. - Makes the Actor switch between two colors, jumping back to the first after reaching the second. + Makes the Actor switch between two colors, jumping back to the first after reaching the second. See Themerdocs/effect_colors.txt for an example. Sets the Actor's right edge color to c. - Makes the Actor shift between two colors smoothly. + Makes the Actor shift between two colors smoothly. See Themerdocs/effect_colors.txt for an example. Sets the Actor's top edge color to c. @@ -1144,13 +1144,13 @@ save yourself some time, copy this for undocumented things: Sets the Actor's glow color. - Makes the Actor glow between two colors immediately. + Makes the Actor glow between two colors immediately. See Themerdocs/effect_colors.txt for an example. - Makes the Actor glow between two colors smoothly, jumping back to the first at the end. + Makes the Actor glow between two colors smoothly, jumping back to the first at the end. See Themerdocs/effect_colors.txt for an example. - Makes the Actor glow between two colors smoothly. + Makes the Actor glow between two colors smoothly. See Themerdocs/effect_colors.txt for an example. Set the fractional horizontal alignment of the Actor according to fAlign which should be a float in the range 0..1. An alignment of 0 is left aligned while an alignment of 1 is right aligned. See for the common case. @@ -1207,7 +1207,7 @@ save yourself some time, copy this for undocumented things: Basically creates a command named !sMessageName (Note the ! at the beginning. The source code says this: "Hack: use "!" as a marker to broadcast a command, instead of playing a command, so we don't have to add yet another element to every tween state for this rarely-used command.") - Makes the Actor change colors continually using colors of the rainbow. + Makes the Actor change colors continually using colors of the rainbow. Each channel follows a cosine wave, red starts at 0, green starts at 2pi/3, and blue starts at 4pi/3. Sets the roll of this Actor to fRoll. diff --git a/Docs/Themerdocs/effect_colors.txt b/Docs/Themerdocs/effect_colors.txt new file mode 100644 index 0000000000..4ebecb1ba8 --- /dev/null +++ b/Docs/Themerdocs/effect_colors.txt @@ -0,0 +1,16 @@ +General note on functions that use effect colors: +diffuseblink, diffuseramp, diffuseshift, glowblink, glowramp, and glowshift all use the two effect colors. +They set the effect colors to white when called, so you should call effectcolor1 and effectcolor2 afterwards to set the effect colors to the colors you want. +You should also call effectperiod to set the effect period if you don't want the default of 1. + +Example: +Def.Quad{ + Name= "glow quad test", InitCommand= function(self) + self:setsize(40, 40) + self:glowshift() + self:effectcolor1(color("#dc322f")) + self:effectcolor2(color("#2aa198")) + self:effectperiod(4) + self:xy(_screen.cx, _screen.cy) + end +} From 1f844d6627429acb6a15e0bf30659b9962f82a30 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Sat, 1 Nov 2014 13:30:41 -0600 Subject: [PATCH 14/25] Fixed coloring and cropping of RollingNumbers during tweens. --- Docs/Changelog_sm5.txt | 4 ++++ src/RollingNumbers.cpp | 33 ++++++++++++++++++++------------- src/RollingNumbers.h | 2 ++ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 8dc574e629..bd36d4a91c 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -4,6 +4,10 @@ The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt. ________________________________________________________________________________ +2014/11/01 +---------- +* [RollingNumbers] Cropping and color during tweens fixed. + 2014/10/23 ---------- * [Global] approach, multiapproach, lerp, and lerp_color lua functions added. diff --git a/src/RollingNumbers.cpp b/src/RollingNumbers.cpp index f267ed87b3..5e8c6389ac 100644 --- a/src/RollingNumbers.cpp +++ b/src/RollingNumbers.cpp @@ -25,10 +25,25 @@ void RollingNumbers::Load( const RString &sMetricsGroup ) UpdateText(); } +void RollingNumbers::DrawPart(RageColor const& diffuse, RageColor const& stroke, + float crop_left, float crop_right) +{ + for(int i= 0; i < 4; ++i) + { + m_pTempState->diffuse[i]= diffuse; + } + SetStrokeColor(stroke); + m_pTempState->crop.left= crop_left; + m_pTempState->crop.right= crop_right; + BitmapText::DrawPrimitives(); +} + void RollingNumbers::DrawPrimitives() { RageColor c_orig = this->GetDiffuse(); RageColor c2_orig = this->GetStrokeColor(); + float original_crop_left= m_pTempState->crop.left; + float original_crop_right= m_pTempState->crop.right; RageColor c = this->GetDiffuse(); c *= LEADING_ZERO_MULTIPLY_COLOR; @@ -53,21 +68,13 @@ void RollingNumbers::DrawPrimitives() float f = i / (float)s.length(); // draw leading part - SetDiffuse( c ); - SetStrokeColor( c2 ); - SetCropLeft( 0 ); - SetCropRight( 1-f ); - BitmapText::DrawPrimitives(); - + DrawPart(c, c2, max(0, original_crop_left), max(1-f, original_crop_right)); // draw regular color part - SetDiffuse( c_orig ); - SetStrokeColor( c2_orig ); - SetCropLeft( f ); - SetCropRight( 0 ); - BitmapText::DrawPrimitives(); + DrawPart(c_orig, c2_orig, max(f, original_crop_left), + max(0, original_crop_right)); - SetCropLeft( 0 ); - SetCropRight( 0 ); + m_pTempState->crop.left= original_crop_left; + m_pTempState->crop.right= original_crop_right; } void RollingNumbers::Update( float fDeltaTime ) diff --git a/src/RollingNumbers.h b/src/RollingNumbers.h index 56f04fc2e3..6b1130c412 100644 --- a/src/RollingNumbers.h +++ b/src/RollingNumbers.h @@ -13,6 +13,8 @@ public: void Load( const RString &sMetricsGroup ); virtual RollingNumbers *Copy() const; + void DrawPart(RageColor const& diffuse, RageColor const& stroke, + float crop_left, float crop_right); virtual void DrawPrimitives(); virtual void Update( float fDeltaTime ); From 50df61a0caf1b3e1fcda0abbbd0e9fb60bc7091f Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Sat, 1 Nov 2014 16:42:51 -0600 Subject: [PATCH 15/25] Fixed RollingNumbers to work with corner diffuse colors. Changed diffuse loops to use NUM_DIFFUSE_COLORS instead of 4. --- src/Actor.cpp | 18 +++++++++--------- src/Actor.h | 13 ++++++++++--- src/RollingNumbers.cpp | 29 ++++++++++++++++------------- src/RollingNumbers.h | 2 +- src/ScreenOptions.cpp | 4 ++-- 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 0e487dcd9a..15eab5f0b5 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -370,21 +370,21 @@ void Actor::PreDraw() // calculate actor properties /* XXX: Should diffuse_blink and diffuse_shift multiply the tempState color? * (That would have the same effect with 1,1,1,1, and allow tweening the diffuse * while blinking and shifting.) */ - for(int i=0; i<4; i++) + for(int i=0; idiffuse[i]= diffuse; + m_pTempState->diffuse[i]= diffuse[i]; } SetStrokeColor(stroke); m_pTempState->crop.left= crop_left; @@ -40,16 +40,18 @@ void RollingNumbers::DrawPart(RageColor const& diffuse, RageColor const& stroke, void RollingNumbers::DrawPrimitives() { - RageColor c_orig = this->GetDiffuse(); - RageColor c2_orig = this->GetStrokeColor(); + RageColor diffuse_orig[NUM_DIFFUSE_COLORS]; + RageColor diffuse_temp[NUM_DIFFUSE_COLORS]; + RageColor stroke_orig= GetStrokeColor(); + RageColor stroke_temp= GetStrokeColor() * LEADING_ZERO_MULTIPLY_COLOR; + for(int i= 0; i < NUM_DIFFUSE_COLORS; ++i) + { + diffuse_orig[i]= m_pTempState->diffuse[i]; + diffuse_temp[i]= m_pTempState->diffuse[i] * LEADING_ZERO_MULTIPLY_COLOR; + } float original_crop_left= m_pTempState->crop.left; float original_crop_right= m_pTempState->crop.right; - RageColor c = this->GetDiffuse(); - c *= LEADING_ZERO_MULTIPLY_COLOR; - RageColor c2 = this->GetStrokeColor(); - c2 *= LEADING_ZERO_MULTIPLY_COLOR; - RString s = this->GetText(); int i; // find the first non-zero non-comma character, or the last character @@ -68,10 +70,11 @@ void RollingNumbers::DrawPrimitives() float f = i / (float)s.length(); // draw leading part - DrawPart(c, c2, max(0, original_crop_left), max(1-f, original_crop_right)); + DrawPart(diffuse_temp, stroke_temp, + max(0, original_crop_left), max(1-f, original_crop_right)); // draw regular color part - DrawPart(c_orig, c2_orig, max(f, original_crop_left), - max(0, original_crop_right)); + DrawPart(diffuse_orig, stroke_orig, + max(f, original_crop_left), max(0, original_crop_right)); m_pTempState->crop.left= original_crop_left; m_pTempState->crop.right= original_crop_right; diff --git a/src/RollingNumbers.h b/src/RollingNumbers.h index 6b1130c412..9dec441c37 100644 --- a/src/RollingNumbers.h +++ b/src/RollingNumbers.h @@ -13,7 +13,7 @@ public: void Load( const RString &sMetricsGroup ); virtual RollingNumbers *Copy() const; - void DrawPart(RageColor const& diffuse, RageColor const& stroke, + void DrawPart(RageColor const* diffuse, RageColor const& stroke, float crop_left, float crop_right); virtual void DrawPrimitives(); virtual void Update( float fDeltaTime ); diff --git a/src/ScreenOptions.cpp b/src/ScreenOptions.cpp index c91c44d520..72bedd4007 100644 --- a/src/ScreenOptions.cpp +++ b/src/ScreenOptions.cpp @@ -673,7 +673,7 @@ void ScreenOptions::PositionRows( bool bTween ) i < first_start || (i >= first_end && i < second_start) || i >= second_end; - for( int j=0; j<4; j++ ) + for( int j=0; jSetDestination( tsDestination, bTween ); } From 2834cded9e9a1d68ba2eb2c91f4f0ed8e5b49d1f Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Sat, 1 Nov 2014 18:49:48 -0600 Subject: [PATCH 16/25] Created tween queue and functions for BitmapText so the stroke color can be tweened. --- src/Actor.h | 2 +- src/BitmapText.cpp | 71 +++++++++++++++++++++++++++++++++++++----- src/BitmapText.h | 45 ++++++++++++++++++++++++-- src/RollingNumbers.cpp | 6 ++-- 4 files changed, 109 insertions(+), 15 deletions(-) diff --git a/src/Actor.h b/src/Actor.h index 3c78536314..2be5f711bd 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -279,7 +279,7 @@ public: virtual void Update( float fDeltaTime ); // this can short circuit UpdateInternal virtual void UpdateInternal( float fDeltaTime ); // override this void UpdateTweening( float fDeltaTime ); - // These next functions should all be overridden by a derived class that has its own tweening states to handl. + // These next functions should all be overridden by a derived class that has its own tweening states to handle. virtual void SetCurrentTweenStart() {} virtual void EraseHeadTween() {} virtual void UpdatePercentThroughTween( float PercentThroughTween ) {} diff --git a/src/BitmapText.cpp b/src/BitmapText.cpp index ebb975973c..c2981cba21 100644 --- a/src/BitmapText.cpp +++ b/src/BitmapText.cpp @@ -56,9 +56,6 @@ BitmapText::BitmapText() m_iVertSpacing = 0; m_MaxDimensionUsesZoom= false; m_bHasGlowAttribute = false; - // We'd be better off not adding strokes to things we can't control - // themewise (ScreenDebugOverlay for example). -Midiman - m_StrokeColor = RageColor(0,0,0,0); // Never, this way we dont have awkward settings between themes. -Midiman SetShadowLength( 0 ); // SM4SVN r28328, "draw glow using stroke texture" forces the BitmapText to @@ -95,7 +92,9 @@ BitmapText & BitmapText::operator=(const BitmapText &cpy) CPY( m_vpFontPageTextures ); CPY( m_mAttributes ); CPY( m_bHasGlowAttribute ); - CPY( m_StrokeColor ); + CPY( BMT_Tweens ); + CPY( BMT_current ); + CPY( BMT_start ); #undef CPY if( m_pFont ) @@ -117,6 +116,60 @@ BitmapText::BitmapText( const BitmapText &cpy ): *this = cpy; } +void BitmapText::SetCurrentTweenStart() +{ + BMT_start= BMT_current; +} + +void BitmapText::EraseHeadTween() +{ + BMT_current= BMT_Tweens[0]; + BMT_Tweens.erase(BMT_Tweens.begin()); +} + +void BitmapText::UpdatePercentThroughTween(float between) +{ + BMT_TweenState::MakeWeightedAverage(BMT_current, BMT_start, BMT_Tweens[0], + between); +} + +void BitmapText::BeginTweening(float time, ITween* interp) +{ + Actor::BeginTweening(time, interp); + if(!BMT_Tweens.empty()) + { + BMT_Tweens.push_back(BMT_Tweens.back()); + } + else + { + BMT_Tweens.push_back(BMT_current); + } +} + +void BitmapText::StopTweening() +{ + BMT_Tweens.clear(); + Actor::StopTweening(); +} + +void BitmapText::FinishTweening() +{ + if(!BMT_Tweens.empty()) + { + BMT_current= BMT_DestTweenState(); + } + Actor::FinishTweening(); +} + +void BitmapText::BMT_TweenState::MakeWeightedAverage(BMT_TweenState& out, + BMT_TweenState const& from, BMT_TweenState const& to, float between) +{ + out.m_stroke_color.b= lerp(between, from.m_stroke_color.b, to.m_stroke_color.b); + out.m_stroke_color.g= lerp(between, from.m_stroke_color.g, to.m_stroke_color.g); + out.m_stroke_color.r= lerp(between, from.m_stroke_color.r, to.m_stroke_color.r); + out.m_stroke_color.a= lerp(between, from.m_stroke_color.a, to.m_stroke_color.a); +} + void BitmapText::LoadFromNode( const XNode* node ) { RString text; @@ -613,12 +666,12 @@ void BitmapText::DrawPrimitives() } // render the stroke - if( m_StrokeColor.a > 0 ) + RageColor stroke_color= GetCurrStrokeColor(); + if( stroke_color.a > 0 ) { - RageColor c = m_StrokeColor; - c.a *= m_pTempState->diffuse[0].a; + stroke_color.a *= m_pTempState->diffuse[0].a; for( unsigned i=0; iClearAttributes(); return 0; } static int strokecolor( T* p, lua_State *L ) { RageColor c; c.FromStackCompat( L, 1 ); p->SetStrokeColor( c ); return 0; } + DEFINE_METHOD(getstrokecolor, GetStrokeColor()); static int uppercase( T* p, lua_State *L ) { p->SetUppercase( BArg(1) ); return 0; } static int textglowmode( T* p, lua_State *L ) { p->SetTextGlowMode( Enum::Check(L, 1) ); return 0; } @@ -933,6 +987,7 @@ public: ADD_METHOD( AddAttribute ); ADD_METHOD( ClearAttributes ); ADD_METHOD( strokecolor ); + ADD_METHOD( getstrokecolor ); ADD_METHOD( uppercase ); ADD_METHOD( textglowmode ); //ADD_METHOD( LoadFromFont ); diff --git a/src/BitmapText.h b/src/BitmapText.h index 329c5540f1..d98daff4d7 100644 --- a/src/BitmapText.h +++ b/src/BitmapText.h @@ -19,6 +19,41 @@ public: virtual void LoadFromNode( const XNode* pNode ); virtual BitmapText *Copy() const; + struct BMT_TweenState + { + // We'd be better off not adding strokes to things we can't control + // themewise (ScreenDebugOverlay for example). -Midiman + BMT_TweenState(): m_stroke_color(RageColor(0,0,0,0)) {} + static void MakeWeightedAverage(BMT_TweenState& out, + BMT_TweenState const& from, BMT_TweenState const& to, float between); + bool operator==(BMT_TweenState const& other) const; + bool operator!=(BMT_TweenState const& other) const { return !operator==(other); } + void SetStrokeColor(RageColor const& c) { m_stroke_color= c; } + RageColor const& GetStrokeColor() { return m_stroke_color; } + private: + RageColor m_stroke_color; + }; + + BMT_TweenState& BMT_DestTweenState() + { + if(BMT_Tweens.empty()) + { return BMT_current; } + else + { return BMT_Tweens.back(); } + } + BMT_TweenState const& BMT_DestTweenState() const { return const_cast(this)->BMT_DestTweenState(); } + + virtual void SetCurrentTweenStart(); + virtual void EraseHeadTween(); + virtual void UpdatePercentThroughTween(float between); + virtual void BeginTweening(float time, ITween* interp); + // This function exists because the compiler tried to connect a call of + // "BeginTweening(1.2f)" to the function above. -Kyz + virtual void BeginTweening(float time, TweenType tt = TWEEN_LINEAR) + { Actor::BeginTweening(time, tt); } + virtual void StopTweening(); + virtual void FinishTweening(); + bool LoadFromFont( const RString& sFontName ); bool LoadFromTextureAndChars( const RString& sTexturePath, const RString& sChars ); virtual void SetText( const RString& sText, const RString& sAlternateText = "", int iWrapWidthPixels = -1 ); @@ -40,8 +75,10 @@ public: void SetHorizAlign( float f ); - void SetStrokeColor( RageColor c ) { m_StrokeColor = c; } - RageColor GetStrokeColor() { return m_StrokeColor; } + void SetStrokeColor(RageColor c) { BMT_DestTweenState().SetStrokeColor(c); } + RageColor const& GetStrokeColor() { return BMT_DestTweenState().GetStrokeColor(); } + void SetCurrStrokeColor(RageColor c) { BMT_current.SetStrokeColor(c); } + RageColor const& GetCurrStrokeColor() { return BMT_current.GetStrokeColor(); } void SetTextGlowMode( TextGlowMode tgm ) { m_TextGlowMode = tgm; } @@ -91,7 +128,6 @@ protected: map m_mAttributes; bool m_bHasGlowAttribute; - RageColor m_StrokeColor; TextGlowMode m_TextGlowMode; // recalculate the items in SetText() @@ -101,6 +137,9 @@ protected: private: void SetTextInternal(); + vector BMT_Tweens; + BMT_TweenState BMT_current; + BMT_TweenState BMT_start; }; #endif diff --git a/src/RollingNumbers.cpp b/src/RollingNumbers.cpp index cd0d70c482..db20620013 100644 --- a/src/RollingNumbers.cpp +++ b/src/RollingNumbers.cpp @@ -32,7 +32,7 @@ void RollingNumbers::DrawPart(RageColor const* diffuse, RageColor const& stroke, { m_pTempState->diffuse[i]= diffuse[i]; } - SetStrokeColor(stroke); + SetCurrStrokeColor(stroke); m_pTempState->crop.left= crop_left; m_pTempState->crop.right= crop_right; BitmapText::DrawPrimitives(); @@ -42,8 +42,8 @@ void RollingNumbers::DrawPrimitives() { RageColor diffuse_orig[NUM_DIFFUSE_COLORS]; RageColor diffuse_temp[NUM_DIFFUSE_COLORS]; - RageColor stroke_orig= GetStrokeColor(); - RageColor stroke_temp= GetStrokeColor() * LEADING_ZERO_MULTIPLY_COLOR; + RageColor stroke_orig= GetCurrStrokeColor(); + RageColor stroke_temp= stroke_orig * LEADING_ZERO_MULTIPLY_COLOR; for(int i= 0; i < NUM_DIFFUSE_COLORS; ++i) { diffuse_orig[i]= m_pTempState->diffuse[i]; From 548736290285e27de1cef218b1a417a006297978 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Wed, 5 Nov 2014 22:26:25 -0700 Subject: [PATCH 17/25] Fixed ScreenPrompt::AnswerOnCommand metrics by calling LOAD_ALL_COMMANDS after the name was set. --- Docs/Changelog_sm5.txt | 4 ++++ src/BitmapText.cpp | 2 +- src/BitmapText.h | 2 +- src/ScreenPrompt.cpp | 10 +++++++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index bd36d4a91c..8c3efa2d91 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -4,6 +4,10 @@ The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt. ________________________________________________________________________________ +2014/11/05 +---------- +* [ScreenPrompt] Answer OnCommand metrics fixed to actually work. + 2014/11/01 ---------- * [RollingNumbers] Cropping and color during tweens fixed. diff --git a/src/BitmapText.cpp b/src/BitmapText.cpp index c2981cba21..823c730bda 100644 --- a/src/BitmapText.cpp +++ b/src/BitmapText.cpp @@ -885,7 +885,7 @@ void BitmapText::Attribute::FromStack( lua_State *L, int iPos ) lua_getfield( L, iTab, "Diffuses" ); if( !lua_isnil(L, -1) ) { - for( int i = 1; i <= 4; ++i ) + for( int i = 1; i <= NUM_DIFFUSE_COLORS; ++i ) { lua_rawgeti( L, -i, i ); diffuse[i-1].FromStack( L, -1 ); diff --git a/src/BitmapText.h b/src/BitmapText.h index d98daff4d7..b4cb21205d 100644 --- a/src/BitmapText.h +++ b/src/BitmapText.h @@ -93,7 +93,7 @@ public: { Attribute() : length(-1), glow() { } int length; - RageColor diffuse[4]; + RageColor diffuse[NUM_DIFFUSE_COLORS]; RageColor glow; void FromStack( lua_State *L, int iPos ); diff --git a/src/ScreenPrompt.cpp b/src/ScreenPrompt.cpp index b033a1746a..94dd89d561 100644 --- a/src/ScreenPrompt.cpp +++ b/src/ScreenPrompt.cpp @@ -66,7 +66,12 @@ void ScreenPrompt::Init() for( int i=0; iGetPathF(m_sName,"answer") ); - LOAD_ALL_COMMANDS( m_textAnswer[i] ); + // The name of the actor isn't set because it is not known at this point + // how many answers there will be, and the name depends on the number of + // answers as a clumsy way of letting the themer set different positions + // for different answer groups. The name is set in BeginScreen, and + // then the commands are loaded. -Kyz (At least, that seems like the + // explanation to me, reading the code years after the author left) this->AddChild( &m_textAnswer[i] ); } @@ -90,6 +95,9 @@ void ScreenPrompt::BeginScreen() { RString sElem = ssprintf("Answer%dOf%d", i+1, g_PromptType+1); m_textAnswer[i].SetName( sElem ); + LOAD_ALL_COMMANDS(m_textAnswer[i]); + // Side note: Because LOAD_ALL_COMMANDS occurs here, InitCommand will + // not be run for the actors. People can just use OnCommand instead. RString sAnswer = PromptAnswerToString( (PromptAnswer)i ); // FRAGILE if( g_PromptType == PROMPT_OK ) From 1f8205b5d7848b8e4325da286fb54051c77f49f4 Mon Sep 17 00:00:00 2001 From: psmay Date: Thu, 6 Nov 2014 16:55:51 -0500 Subject: [PATCH 18/25] en.ini: Fix "guage" --- Themes/default/Languages/en.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/default/Languages/en.ini b/Themes/default/Languages/en.ini index 59926aa903..d7b8c55c90 100644 --- a/Themes/default/Languages/en.ini +++ b/Themes/default/Languages/en.ini @@ -246,7 +246,7 @@ Information=Information Feet=Your feet will be used to play! Tap=When the arrows rise to this point,\nstep on the matching panels. Jump=Step on both panels if two different\narrows appear at the same time! -Miss=If you misstep repeatedly, your dance\nguage will decrease until the game is\nis over! +Miss=If you misstep repeatedly, your dance\ngauge will decrease until the game is\nis over! [Protiming] From 77130ed3c44fb6f7a5e3ba630a093f07d154c3a4 Mon Sep 17 00:00:00 2001 From: freem Date: Thu, 6 Nov 2014 16:11:29 -0600 Subject: [PATCH 19/25] no more double "is", either. --- Themes/default/Languages/en.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/default/Languages/en.ini b/Themes/default/Languages/en.ini index d7b8c55c90..4ff4543f29 100644 --- a/Themes/default/Languages/en.ini +++ b/Themes/default/Languages/en.ini @@ -246,7 +246,7 @@ Information=Information Feet=Your feet will be used to play! Tap=When the arrows rise to this point,\nstep on the matching panels. Jump=Step on both panels if two different\narrows appear at the same time! -Miss=If you misstep repeatedly, your dance\ngauge will decrease until the game is\nis over! +Miss=If you misstep repeatedly, your dance\ngauge will decrease until the game\nis over! [Protiming] From 9b847caa45904ef14ab5233251e8cd83cc15a80a Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Sat, 15 Nov 2014 17:18:42 -0700 Subject: [PATCH 20/25] DefaultFailType preference removed because DefaultModifiers was overriding it. DefaultFailType ConfOptionRow now works by putting the fail type in DefaultModifiers. Fixed double InitCommand bug in Foreground. Disabled odd dimension check for screen texture. --- Docs/Changelog_sm5.txt | 5 +++++ src/Foreground.cpp | 4 +++- src/PlayerOptions.cpp | 1 - src/PrefsManager.cpp | 1 - src/PrefsManager.h | 1 - src/RageBitmapTexture.cpp | 7 ++++++ src/ScreenOptionsMasterPrefs.cpp | 38 +++++++++++++++++++++++++++----- 7 files changed, 48 insertions(+), 9 deletions(-) diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt index 8c3efa2d91..a1c06e7e9f 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/Changelog_sm5.txt @@ -4,6 +4,11 @@ The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt. ________________________________________________________________________________ +2014/11/15 +---------- +* [Preferences] Default Fail Type preference mechanism changed internally again. + Set your Default Fail Type preference again. + 2014/11/05 ---------- * [ScreenPrompt] Answer OnCommand metrics fixed to actually work. diff --git a/src/Foreground.cpp b/src/Foreground.cpp index 38d73b6ff1..95d3f8fed2 100644 --- a/src/Foreground.cpp +++ b/src/Foreground.cpp @@ -54,7 +54,9 @@ void Foreground::LoadFromSong( const Song *pSong ) if( bga.m_bga == NULL ) continue; bga.m_bga->SetName( sBGName ); - bga.m_bga->PlayCommand( "Init" ); + // ActorUtil::MakeActor calls LoadFromNode to load the actor, and + // LoadFromNode takes care of running the InitCommand, so do not run the + // InitCommand here. -Kyz bga.m_fStartBeat = change.m_fStartBeat; bga.m_bFinished = false; diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index a579d1483f..65d37800ce 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -74,7 +74,6 @@ void PlayerOptions::Init() ZERO( m_bTurns ); ZERO( m_bTransforms ); m_bMuteOnError = false; - m_FailType = PREFSMAN->m_DefaultFailType; m_sNoteSkin = ""; } diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index 54f9059add..7fd7c2e6aa 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -286,7 +286,6 @@ PrefsManager::PrefsManager() : m_sCoursesToShowRanking ( "CoursesToShowRanking", "" ), m_bQuirksMode ( "QuirksMode", false ), - m_DefaultFailType("DefaultFailtype", FailType_ImmediateContinue), /* Debug: */ m_bLogToDisk ( "LogToDisk", true ), diff --git a/src/PrefsManager.h b/src/PrefsManager.h index 97d40fb5c4..19f51e07e2 100644 --- a/src/PrefsManager.h +++ b/src/PrefsManager.h @@ -294,7 +294,6 @@ public: /** @brief Enable some quirky behavior used by some older versions of StepMania. */ Preference m_bQuirksMode; - Preference m_DefaultFailType; // Debug: Preference m_bLogToDisk; diff --git a/src/RageBitmapTexture.cpp b/src/RageBitmapTexture.cpp index 17252e7f59..c6628ed6ba 100644 --- a/src/RageBitmapTexture.cpp +++ b/src/RageBitmapTexture.cpp @@ -289,6 +289,13 @@ void RageBitmapTexture::Create() if( !TEXTUREMAN->GetOddDimensionWarning() ) bRunCheck = false; + // Don't check if this is the screen texture, the theme can't do anything + // about it. -Kyz + if(actualID == TEXTUREMAN->GetScreenTextureID()) + { + bRunCheck= false; + } + if( bRunCheck ) { float fFrameWidth = this->GetSourceWidth() / (float)this->GetFramesWide(); diff --git a/src/ScreenOptionsMasterPrefs.cpp b/src/ScreenOptionsMasterPrefs.cpp index 7098210eeb..4b50face7d 100644 --- a/src/ScreenOptionsMasterPrefs.cpp +++ b/src/ScreenOptionsMasterPrefs.cpp @@ -30,10 +30,12 @@ static void GetPrefsDefaultModifiers( PlayerOptions &po, SongOptions &so ) static void SetPrefsDefaultModifiers( const PlayerOptions &po, const SongOptions &so ) { vector as; - if( po.GetString() != "" ) - as.push_back( po.GetString() ); - if( so.GetString() != "" ) - as.push_back( so.GetString() ); +#define remove_empty_back() if(as.back() == "") { as.pop_back(); } + as.push_back(po.GetString()); + remove_empty_back(); + as.push_back(so.GetString()); + remove_empty_back(); +#undef remove_empty_back PREFSMAN->m_sDefaultModifiers.Set( join(", ",as) ); } @@ -336,6 +338,32 @@ static void DefaultNoteSkin( int &sel, bool ToSel, const ConfOption *pConfOption } } +static void DefaultFailChoices(vector& out) +{ + out.push_back("Immediate"); + out.push_back("ImmediateContinue"); + out.push_back("EndOfSong"); + out.push_back("Off"); +} + +static void DefaultFailType(int& sel, bool to_sel, const ConfOption* conf_option) +{ + if(to_sel) + { + PlayerOptions po; + po.FromString(PREFSMAN->m_sDefaultModifiers); + sel= po.m_FailType; + } + else + { + PlayerOptions po; + SongOptions so; + GetPrefsDefaultModifiers(po, so); + po.m_FailType= static_cast(sel); + SetPrefsDefaultModifiers(po, so); + } +} + // Background options static void BGBrightness( int &sel, bool ToSel, const ConfOption *pConfOption ) { @@ -708,7 +736,7 @@ static void InitializeConfOptions() ADD( ConfOption( "ProgressiveLifebar", MovePref, "Off","|1","|2","|3","|4","|5","|6","|7","|8") ); ADD( ConfOption( "ProgressiveStageLifebar", MovePref, "Off","|1","|2","|3","|4","|5","|6","|7","|8","Insanity") ); ADD( ConfOption( "ProgressiveNonstopLifebar", MovePref, "Off","|1","|2","|3","|4","|5","|6","|7","|8","Insanity") ); - ADD( ConfOption( "DefaultFailType", MovePref, "Immediate","ImmediateContinue","EndOfSong","Off" ) ); + ADD( ConfOption( "DefaultFailType", DefaultFailType, DefaultFailChoices ) ); ADD( ConfOption( "CoinsPerCredit", CoinsPerCredit, "|1","|2","|3","|4","|5","|6","|7","|8","|9","|10","|11","|12","|13","|14","|15","|16" ) ); ADD( ConfOption( "Premium", MovePref, "Off","Double for 1 Credit","2 Players for 1 Credit" ) ); ADD( ConfOption( "JointPremium", JointPremium, "Off","2 Players for 1 Credit" ) ); From a5d9f029f385282e54b2cb100b9f08b4262bf2b7 Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Mon, 17 Nov 2014 04:24:20 -0700 Subject: [PATCH 21/25] Added optional config ini file for configuring key mappings used by Edit Mode. --- Docs/Mapping_keys_for_edit_mode.txt | 287 ++++++++++++++++++++++++++++ src/InputMapper.cpp | 2 +- src/InputMapper.h | 1 + src/ScreenEdit.cpp | 155 +++++++++++++++ src/ScreenEdit.h | 3 + src/SpecialFiles.cpp | 1 + src/SpecialFiles.h | 4 + 7 files changed, 452 insertions(+), 1 deletion(-) create mode 100644 Docs/Mapping_keys_for_edit_mode.txt diff --git a/Docs/Mapping_keys_for_edit_mode.txt b/Docs/Mapping_keys_for_edit_mode.txt new file mode 100644 index 0000000000..5f237910a9 --- /dev/null +++ b/Docs/Mapping_keys_for_edit_mode.txt @@ -0,0 +1,287 @@ +Don't try to change the way keys are mapped in edit mode unless you have a good reason. It's complicated and easy to mess up. +If you do make a mistake, you can go back to the default edit mode keymapping just by removing the "User Data Folder/Save/EditMode_Keymaps.ini" file. + +Edit Mode loads key mapping settings from "User Data Folder/Save/EditMode_Keymaps.ini". "User Data Folder" is a special name that means the folder where all your user data for stepmania is stored, the name depends on what OS you're on. See Docs/Userdocs/sm5_beginner.txt and search for "User Data Folder" to learn where it is on your OS. + +Entries in EditMode_Keymaps.ini set which what keys trigger an action. Any function that doesn't have an entry in EditMode_Keymaps.ini will use the default mapping. Be careful when choosing a key for a function to make sure that same key isn't already mapped to something else either in the default mapping or in the mapping you are creating. +If you hold F3, you can use the Debug Menu to reload the screen while in Edit Mode, which will reload the key mapping, so you can adjust the mapping while stepmania is running. + +EditMode_Keymaps.ini is broken up into four sections, one for each major mode that Edit Mode can be in. The "Edit" section is for when in normal editing mode. The "Play" section is for when Edit Mode is playing back a song. The "Record" section is for record mode, and the "RecordPaused" section is for when Record mode is paused. + +Each line in a section is the name of the function being set, followed by "=", then the name of the key for that function. You can list two keys by seperating them with a ":". Examples: +SNAP_NEXT=Key_s +SNAP_PREV=Key_d:Key_v + +Note that you cannot change which keys need to be held down for certain things, like holding shift for rolls. + +Next will be a list of function names (headed by "Function Names"), then a list of key names (headed by "Key Names"), then the default key mapping (headed by "Default Mapping") as an example. + +Function Names: +COLUMN_0 +COLUMN_1 +COLUMN_2 +COLUMN_3 +COLUMN_4 +COLUMN_5 +COLUMN_6 +COLUMN_7 +COLUMN_8 +COLUMN_9 +RIGHT_SIDE +LAY_ROLL +LAY_TAP_ATTACK +REMOVE_NOTE +CYCLE_TAP_LEFT +CYCLE_TAP_RIGHT +CYCLE_SEGMENT_LEFT +CYCLE_SEGMENT_RIGHT +SCROLL_UP_LINE +SCROLL_UP_PAGE +SCROLL_UP_TS +SCROLL_DOWN_LINE +SCROLL_DOWN_PAGE +SCROLL_DOWN_TS +SCROLL_NEXT_MEASURE +SCROLL_PREV_MEASURE +SCROLL_HOME +SCROLL_END +SCROLL_NEXT +SCROLL_PREV +SEGMENT_NEXT +SEGMENT_PREV +SCROLL_SELECT +LAY_SELECT +SCROLL_SPEED_UP +SCROLL_SPEED_DOWN +SNAP_NEXT +SNAP_PREV +OPEN_EDIT_MENU +OPEN_TIMING_MENU +OPEN_ALTER_MENU +OPEN_AREA_MENU +OPEN_BGCHANGE_LAYER1_MENU +OPEN_BGCHANGE_LAYER2_MENU +OPEN_COURSE_MENU +OPEN_COURSE_ATTACK_MENU +OPEN_STEP_ATTACK_MENU +ADD_STEP_MODS +OPEN_INPUT_HELP +BAKE_RANDOM_FROM_SONG_GROUP +BAKE_RANDOM_FROM_SONG_GROUP_AND_GENRE +PLAY_FROM_START +PLAY_FROM_CURSOR +PLAY_SELECTION +RECORD_FROM_CURSOR +RECORD_SELECTION +RETURN_TO_EDIT +INSERT +DELETE +INSERT_SHIFT_PAUSES +DELETE_SHIFT_PAUSES +OPEN_NEXT_STEPS +OPEN_PREV_STEPS +PLAY_SAMPLE_MUSIC +BPM_UP +BPM_DOWN +STOP_UP +STOP_DOWN +DELAY_UP +DELAY_DOWN +OFFSET_UP +OFFSET_DOWN +SAMPLE_START_UP +SAMPLE_START_DOWN +SAMPLE_LENGTH_UP +SAMPLE_LENGTH_DOWN +ADJUST_FINE +SAVE +UNDO +ADD_COURSE_MODS +SWITCH_PLAYERS +SWITCH_TIMINGS + + +Key Names: +(If you're really having trouble finding the name for a key, map it to something in the normal controller mapping screen and check Keymaps.ini to see what its name is.) +Most keys can be set with something like this: "Key_a", where "a" is the character typed by the key. This includes keys like ".", ",", and so on. For other keys, there are special names that can be used, which are listed below. "Key_." and "Key_period" both mean the same thing. +Some key names have spaces in them. + +Key_period +Key_comma +Key_space +Key_delete +Key_backspace +Key_tab +Key_enter +Key_pause +Key_escape +Key_F1 +Key_F2 +(Don't map F3, it's used for the debug menu, so probably won't work.) +Key_F4 +Key_F5 +Key_F6 +Key_F7 +Key_F8 +Key_F9 +Key_F10 +Key_F11 +Key_F12 +Key_F13 +Key_F14 +Key_F15 +Key_F16 +Key_left ctrl +Key_right ctrl +Key_left shift +Key_right shift +Key_left alt +Key_right alt +Key_left meta +Key_right meta +Key_left super +Key_right super +Key_menu +Key_function +Key_num lock +Key_scroll lock +Key_caps lock +Key_prtsc +Key_up +Key_down +Key_left +Key_right +Key_insert +Key_home +Key_end +Key_pgup +Key_pgdn +Key_KP 0 +Key_KP 1 +Key_KP 2 +Key_KP 3 +Key_KP 4 +Key_KP 5 +Key_KP 6 +Key_KP 7 +Key_KP 8 +Key_KP 9 +Key_KP / +Key_KP * +Key_KP - +Key_KP + +Key_KP . +Key_KP = +Key_KP enter + + +Default Mapping: +Comments are in this section to tell which things require a modifier key to be held. +Note that not all sections map all functions. This is because those functions aren't useful in all modes. +(if you spot a key name that is in all caps in this section, I missed it when editing at 4 AM and it's supposed to be lower case) + +[Edit] +SCROLL_UP_LINE=Key_up +SCROLL_DOWN_LINE=Key_down +SCROLL_UP_PAGE=Key_pgup:Key_; +SCROLL_DOWN_PAGE=Key_pgdn:Key_' +# Scrolling by timing segments actually requires holding Ctrl. +SCROLL_UP_TS=Key_pgup:Key_; +SCROLL_DOWN_TS=Key_pgdn:Key_' +SCROLL_HOME=Key_home +SCROLL_END=Key_end +SCROLL_NEXT=Key_period +SCROLL_PREV=Key_comma +# Hold Ctrl for SEGMENT_NEXT and SEGMENT_PREV. +SEGMENT_NEXT=Key_period +SEGMENT_PREV=Key_comma +SCROLL_SELECT=Key_left shift:Key_right shift +LAY_SELECT=Key_space +# Hold Ctrl for PLAY_FROM_START. +PLAY_FROM_START=Key_p +# Hold Shift for PLAY_FROM_CURSOR. +PLAY_FROM_CURSOR=Key_p +PLAY_SELECTION=Key_p +OPEN_TIMING_MENU=Key_F4 +# OPEN_PREV_STEPS/OPEN_NEXT_STEPS aren't allowed in home mode. It breaks the "delay creation until first save" logic. +OPEN_PREV_STEPS=Key_F5 +OPEN_NEXT_STEPS=Key_F6 +BPM_DOWN=Key_F7 +BPM_UP=Key_F8 +STOP_DOWN=Key_F9 +STOP_UP=Key_F10 +# Hold Shift for DELAY_DOWN and DELAY_UP. +DELAY_DOWN=Key_F9 +DELAY_UP=Key_F10 +OFFSET_DOWN=Key_F11 +OFFSET_UP=Key_F12 +SAMPLE_START_UP=Key_] +SAMPLE_START_DOWN=Key_[ +# Hold Shift for SAMPLE_LENGTH_UP and SAMPLE_LENGTH_DOWN. +SAMPLE_LENGTH_UP=Key_] +SAMPLE_LENGTH_DOWN=Key_[ +PLAY_SAMPLE_MUSIC=Key_l +OPEN_BGCHANGE_LAYER1_MENU=Key_b +# Hold Shift for OPEN_BGCHANGE_LAYER2_MENU. +OPEN_BGCHANGE_LAYER2_MENU=Key_b +# Hold Ctrl for INSERT_SHIFT_PAUSES and DELETE_SHIFT_PAUSES. +INSERT_SHIFT_PAUSES=Key_insert +DELETE_SHIFT_PAUSES=Key_DEL +COLUMN_0=Key_1 +COLUMN_1=Key_2 +COLUMN_2=Key_3 +COLUMN_3=Key_4 +COLUMN_4=Key_5 +COLUMN_5=Key_6 +COLUMN_6=Key_7 +COLUMN_7=Key_8 +COLUMN_8=Key_9 +COLUMN_9=Key_0 +# Yeah, you're screwed when editing techno-double8, bm-double5, or bm-double7, or any other style with more than 10 columns. +RIGHT_SIDE=Key_left alt:Key_right alt +LAY_ROLL=Key_left shift:Key_right shift +CYCLE_TAP_LEFT=Key_n +CYCLE_TAP_RIGHT=Key_m +# Hold Ctrl for CYCLE_SEGMENT_LEFT and CYCLE_SEGMENT_RIGHT. +CYCLE_SEGMENT_LEFT=Key_n +CYCLE_SEGMENT_RIGHT=Key_m +# Hold Ctrl for SCROLL_SPEED_UP and SCROLL_SPEED_DOWN +SCROLL_SPEED_UP=Key_up +SCROLL_SPEED_DOWN=Key_down +SCROLL_SELECT=Key_left shift:Key_right shift +SNAP_NEXT=Key_left +SNAP_PREV=Key_right +OPEN_EDIT_MENU=Key_escape +OPEN_AREA_MENU=Key_enter +OPEN_ALTER_MENU=Key_a +OPEN_INPUT_HELP=Key_F1 +# Hold Alt for BAKE_RANDOM_FROM_SONG_GROUP. +BAKE_RANDOM_FROM_SONG_GROUP=Key_b +# Hold Ctrl for BAKE_RANDOM_FROM_SONG_GROUP_AND_GENRE. +BAKE_RANDOM_FROM_SONG_GROUP_AND_GENRE=Key_b +# Hold Ctrl for RECORD_SELECTION. +RECORD_SELECTION=Key_r +INSERT=Key_insert:Key_\ +DELETE=Key_delete +ADJUST_FINE=Key_right alt:Key_left alt +# Hold Ctrl or Cmd (OS X) for SAVE. +SAVE=Key_s +UNDO=Key_u +SWITCH_PLAYERS=Key_/ +SWITCH_TIMINGS=Key_t + +[Play] +RETURN_TO_EDIT=Key_enter:Key_escape + +[Record] +LAY_ROLL=Key_left shift:Key_right shift +REMOVE_NOTE=Key_left alt:Key_right alt +RETURN_TO_EDIT=Key_escape:Key_enter + +[RecordPaused] +PLAY_SELECTION=Key_p +# Hold Ctrl for RECORD_SELECTION. +RECORD_SELECTION=Key_r +RECORD_FROM_CURSOR=Key_r +RETURN_TO_EDIT=Key_escape +UNDO=Key_u diff --git a/src/InputMapper.cpp b/src/InputMapper.cpp index cc61833c64..b6a4e90cc9 100644 --- a/src/InputMapper.cpp +++ b/src/InputMapper.cpp @@ -639,7 +639,7 @@ const InputScheme *InputMapper::GetInputScheme() const return m_pInputScheme; } -static const RString DEVICE_INPUT_SEPARATOR = ":"; // this isn't used in any key names +const RString DEVICE_INPUT_SEPARATOR = ":"; // this isn't used in any key names void InputMapper::ReadMappingsFromDisk() { diff --git a/src/InputMapper.h b/src/InputMapper.h index 9d2f2c10f5..64c5c8bf34 100644 --- a/src/InputMapper.h +++ b/src/InputMapper.h @@ -9,6 +9,7 @@ struct Game; const int NUM_GAME_TO_DEVICE_SLOTS = 5; // five device inputs may map to one game input const int NUM_SHOWN_GAME_TO_DEVICE_SLOTS = 3; const int NUM_USER_GAME_TO_DEVICE_SLOTS = 2; +extern const RString DEVICE_INPUT_SEPARATOR; struct AutoMappingEntry { diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 315d2a8ade..4878aa53b3 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -30,6 +30,7 @@ #include "ScreenTextEntry.h" #include "SongManager.h" #include "SongUtil.h" +#include "SpecialFiles.h" #include "StepsUtil.h" #include "Style.h" #include "ThemeManager.h" @@ -115,8 +116,120 @@ static const char *EditStateNames[] = { XToString( EditState ); LuaXType( EditState ); +map name_to_edit_button; + void ScreenEdit::InitEditMappings() { + // Created courtesy of query replace regex. + name_to_edit_button["COLUMN_0"]= EDIT_BUTTON_COLUMN_0; + name_to_edit_button["COLUMN_1"]= EDIT_BUTTON_COLUMN_1; + name_to_edit_button["COLUMN_2"]= EDIT_BUTTON_COLUMN_2; + name_to_edit_button["COLUMN_3"]= EDIT_BUTTON_COLUMN_3; + name_to_edit_button["COLUMN_4"]= EDIT_BUTTON_COLUMN_4; + name_to_edit_button["COLUMN_5"]= EDIT_BUTTON_COLUMN_5; + name_to_edit_button["COLUMN_6"]= EDIT_BUTTON_COLUMN_6; + name_to_edit_button["COLUMN_7"]= EDIT_BUTTON_COLUMN_7; + name_to_edit_button["COLUMN_8"]= EDIT_BUTTON_COLUMN_8; + name_to_edit_button["COLUMN_9"]= EDIT_BUTTON_COLUMN_9; + + name_to_edit_button["RIGHT_SIDE"]= EDIT_BUTTON_RIGHT_SIDE; + name_to_edit_button["LAY_ROLL"]= EDIT_BUTTON_LAY_ROLL; + name_to_edit_button["LAY_TAP_ATTACK"]= EDIT_BUTTON_LAY_TAP_ATTACK; + name_to_edit_button["REMOVE_NOTE"]= EDIT_BUTTON_REMOVE_NOTE; + + name_to_edit_button["CYCLE_TAP_LEFT"]= EDIT_BUTTON_CYCLE_TAP_LEFT; + name_to_edit_button["CYCLE_TAP_RIGHT"]= EDIT_BUTTON_CYCLE_TAP_RIGHT; + + name_to_edit_button["CYCLE_SEGMENT_LEFT"]= EDIT_BUTTON_CYCLE_SEGMENT_LEFT; + name_to_edit_button["CYCLE_SEGMENT_RIGHT"]= EDIT_BUTTON_CYCLE_SEGMENT_RIGHT; + + name_to_edit_button["SCROLL_UP_LINE"]= EDIT_BUTTON_SCROLL_UP_LINE; + name_to_edit_button["SCROLL_UP_PAGE"]= EDIT_BUTTON_SCROLL_UP_PAGE; + name_to_edit_button["SCROLL_UP_TS"]= EDIT_BUTTON_SCROLL_UP_TS; + name_to_edit_button["SCROLL_DOWN_LINE"]= EDIT_BUTTON_SCROLL_DOWN_LINE; + name_to_edit_button["SCROLL_DOWN_PAGE"]= EDIT_BUTTON_SCROLL_DOWN_PAGE; + name_to_edit_button["SCROLL_DOWN_TS"]= EDIT_BUTTON_SCROLL_DOWN_TS; + name_to_edit_button["SCROLL_NEXT_MEASURE"]= EDIT_BUTTON_SCROLL_NEXT_MEASURE; + name_to_edit_button["SCROLL_PREV_MEASURE"]= EDIT_BUTTON_SCROLL_PREV_MEASURE; + name_to_edit_button["SCROLL_HOME"]= EDIT_BUTTON_SCROLL_HOME; + name_to_edit_button["SCROLL_END"]= EDIT_BUTTON_SCROLL_END; + name_to_edit_button["SCROLL_NEXT"]= EDIT_BUTTON_SCROLL_NEXT; + name_to_edit_button["SCROLL_PREV"]= EDIT_BUTTON_SCROLL_PREV; + + name_to_edit_button["SEGMENT_NEXT"]= EDIT_BUTTON_SEGMENT_NEXT; + name_to_edit_button["SEGMENT_PREV"]= EDIT_BUTTON_SEGMENT_PREV; + + name_to_edit_button["SCROLL_SELECT"]= EDIT_BUTTON_SCROLL_SELECT; + + name_to_edit_button["LAY_SELECT"]= EDIT_BUTTON_LAY_SELECT; + + name_to_edit_button["SCROLL_SPEED_UP"]= EDIT_BUTTON_SCROLL_SPEED_UP; + name_to_edit_button["SCROLL_SPEED_DOWN"]= EDIT_BUTTON_SCROLL_SPEED_DOWN; + + name_to_edit_button["SNAP_NEXT"]= EDIT_BUTTON_SNAP_NEXT; + name_to_edit_button["SNAP_PREV"]= EDIT_BUTTON_SNAP_PREV; + + name_to_edit_button["OPEN_EDIT_MENU"]= EDIT_BUTTON_OPEN_EDIT_MENU; + name_to_edit_button["OPEN_TIMING_MENU"]= EDIT_BUTTON_OPEN_TIMING_MENU; + name_to_edit_button["OPEN_ALTER_MENU"]= EDIT_BUTTON_OPEN_ALTER_MENU; + name_to_edit_button["OPEN_AREA_MENU"]= EDIT_BUTTON_OPEN_AREA_MENU; + name_to_edit_button["OPEN_BGCHANGE_LAYER1_MENU"]= EDIT_BUTTON_OPEN_BGCHANGE_LAYER1_MENU; + name_to_edit_button["OPEN_BGCHANGE_LAYER2_MENU"]= EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU; + name_to_edit_button["OPEN_COURSE_MENU"]= EDIT_BUTTON_OPEN_COURSE_MENU; + name_to_edit_button["OPEN_COURSE_ATTACK_MENU"]= EDIT_BUTTON_OPEN_COURSE_ATTACK_MENU; + + name_to_edit_button["OPEN_STEP_ATTACK_MENU"]= EDIT_BUTTON_OPEN_STEP_ATTACK_MENU; + name_to_edit_button["ADD_STEP_MODS"]= EDIT_BUTTON_ADD_STEP_MODS; + + name_to_edit_button["OPEN_INPUT_HELP"]= EDIT_BUTTON_OPEN_INPUT_HELP; + + name_to_edit_button["BAKE_RANDOM_FROM_SONG_GROUP"]= EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP; + name_to_edit_button["BAKE_RANDOM_FROM_SONG_GROUP_AND_GENRE"]= EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP_AND_GENRE; + + name_to_edit_button["PLAY_FROM_START"]= EDIT_BUTTON_PLAY_FROM_START; + name_to_edit_button["PLAY_FROM_CURSOR"]= EDIT_BUTTON_PLAY_FROM_CURSOR; + name_to_edit_button["PLAY_SELECTION"]= EDIT_BUTTON_PLAY_SELECTION; + name_to_edit_button["RECORD_FROM_CURSOR"]= EDIT_BUTTON_RECORD_FROM_CURSOR; + name_to_edit_button["RECORD_SELECTION"]= EDIT_BUTTON_RECORD_SELECTION; + + name_to_edit_button["RETURN_TO_EDIT"]= EDIT_BUTTON_RETURN_TO_EDIT; + + name_to_edit_button["INSERT"]= EDIT_BUTTON_INSERT; + name_to_edit_button["DELETE"]= EDIT_BUTTON_DELETE; + name_to_edit_button["INSERT_SHIFT_PAUSES"]= EDIT_BUTTON_INSERT_SHIFT_PAUSES; + name_to_edit_button["DELETE_SHIFT_PAUSES"]= EDIT_BUTTON_DELETE_SHIFT_PAUSES; + + name_to_edit_button["OPEN_NEXT_STEPS"]= EDIT_BUTTON_OPEN_NEXT_STEPS; + name_to_edit_button["OPEN_PREV_STEPS"]= EDIT_BUTTON_OPEN_PREV_STEPS; + name_to_edit_button["PLAY_SAMPLE_MUSIC"]= EDIT_BUTTON_PLAY_SAMPLE_MUSIC; + + name_to_edit_button["BPM_UP"]= EDIT_BUTTON_BPM_UP; + name_to_edit_button["BPM_DOWN"]= EDIT_BUTTON_BPM_DOWN; + name_to_edit_button["STOP_UP"]= EDIT_BUTTON_STOP_UP; + name_to_edit_button["STOP_DOWN"]= EDIT_BUTTON_STOP_DOWN; + + name_to_edit_button["DELAY_UP"]= EDIT_BUTTON_DELAY_UP; + name_to_edit_button["DELAY_DOWN"]= EDIT_BUTTON_DELAY_DOWN; + + name_to_edit_button["OFFSET_UP"]= EDIT_BUTTON_OFFSET_UP; + name_to_edit_button["OFFSET_DOWN"]= EDIT_BUTTON_OFFSET_DOWN; + name_to_edit_button["SAMPLE_START_UP"]= EDIT_BUTTON_SAMPLE_START_UP; + name_to_edit_button["SAMPLE_START_DOWN"]= EDIT_BUTTON_SAMPLE_START_DOWN; + name_to_edit_button["SAMPLE_LENGTH_UP"]= EDIT_BUTTON_SAMPLE_LENGTH_UP; + name_to_edit_button["SAMPLE_LENGTH_DOWN"]= EDIT_BUTTON_SAMPLE_LENGTH_DOWN; + + name_to_edit_button["ADJUST_FINE"]= EDIT_BUTTON_ADJUST_FINE; + + name_to_edit_button["SAVE"]= EDIT_BUTTON_SAVE; + + name_to_edit_button["UNDO"]= EDIT_BUTTON_UNDO; + + name_to_edit_button["ADD_COURSE_MODS"]= EDIT_BUTTON_ADD_COURSE_MODS; + + name_to_edit_button["SWITCH_PLAYERS"]= EDIT_BUTTON_SWITCH_PLAYERS; + + name_to_edit_button["SWITCH_TIMINGS"]= EDIT_BUTTON_SWITCH_TIMINGS; + m_EditMappingsDeviceInput.Clear(); // Common mappings: @@ -381,8 +494,50 @@ void ScreenEdit::InitEditMappings() m_RecordPausedMappingsDeviceInput.button[EDIT_BUTTON_RETURN_TO_EDIT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_ESC); m_RecordPausedMappingsMenuButton.button[EDIT_BUTTON_RETURN_TO_EDIT][1] = GAME_BUTTON_BACK; m_RecordPausedMappingsDeviceInput.button[EDIT_BUTTON_UNDO][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cu); + + IniFile mapping_ini; + // Only use the mappings file if it exists. It's meant to be optional, and + // only used in rare cases like someone having critical keys broken. -Kyz + if(mapping_ini.ReadFile(SpecialFiles::EDIT_MODE_KEYMAPS_PATH)) + { + LoadKeymapSectionIntoMappingsMember(mapping_ini.GetChild("Edit"), + m_EditMappingsDeviceInput); + LoadKeymapSectionIntoMappingsMember(mapping_ini.GetChild("Play"), + m_PlayMappingsDeviceInput); + LoadKeymapSectionIntoMappingsMember(mapping_ini.GetChild("Record"), + m_RecordMappingsDeviceInput); + LoadKeymapSectionIntoMappingsMember(mapping_ini.GetChild("RecordPaused"), + m_RecordPausedMappingsDeviceInput); + } } +void ScreenEdit::LoadKeymapSectionIntoMappingsMember(XNode const* section, MapEditToDI& mappings) +{ + if(section == NULL) {return;} // Not an error, sections are optional. -Kyz + FOREACH_CONST_Attr(section, attr) + { + map::iterator name_entry= + name_to_edit_button.find(attr->first); + if(name_entry != name_to_edit_button.end()) + { + RString joined_names; + attr->second->GetValue(joined_names); + vector key_names; + split(joined_names, DEVICE_INPUT_SEPARATOR, key_names, false); + for(size_t k= 0; k < key_names.size() && k < NUM_EDIT_TO_DEVICE_SLOTS; ++k) + { + DeviceInput devi; + devi.FromString(key_names[k]); + if(devi.IsValid()) + { + mappings.button[name_entry->second][k]= devi; + } + } + } + } +} + + /* Given a DeviceInput that was just depressed, return an active edit function. */ EditButton ScreenEdit::DeviceToEdit( const DeviceInput &DeviceI ) const { diff --git a/src/ScreenEdit.h b/src/ScreenEdit.h index 79836f08de..481ea6f35d 100644 --- a/src/ScreenEdit.h +++ b/src/ScreenEdit.h @@ -39,6 +39,7 @@ LuaDeclareType( EditState ); enum EditButton { + // Add to the name_to_edit_button list when adding to this enum. -Kyz EDIT_BUTTON_COLUMN_0, EDIT_BUTTON_COLUMN_1, EDIT_BUTTON_COLUMN_2, @@ -151,6 +152,7 @@ enum EditButton EDIT_BUTTON_SWITCH_TIMINGS, /**< Allow switching between Song and Step TimingData. */ + // Add to the name_to_edit_button list when adding to this enum. -Kyz NUM_EditButton, // leave this at the end EditButton_Invalid }; @@ -665,6 +667,7 @@ public: bool EditIsBeingPressed( EditButton button ) const; const MapEditToDI *GetCurrentDeviceInputMap() const; const MapEditButtonToMenuButton *GetCurrentMenuButtonMap() const; + void LoadKeymapSectionIntoMappingsMember(XNode const* section, MapEditToDI& mappings); MapEditToDI m_EditMappingsDeviceInput; MapEditToDI m_PlayMappingsDeviceInput; MapEditToDI m_RecordMappingsDeviceInput; diff --git a/src/SpecialFiles.cpp b/src/SpecialFiles.cpp index 27d4e0515a..5f6d5c50e8 100644 --- a/src/SpecialFiles.cpp +++ b/src/SpecialFiles.cpp @@ -4,6 +4,7 @@ const RString SpecialFiles::USER_PACKAGES_DIR = "UserPackages/"; const RString SpecialFiles::PACKAGES_DIR = "Packages/"; const RString SpecialFiles::KEYMAPS_PATH = "Save/Keymaps.ini"; +const RString SpecialFiles::EDIT_MODE_KEYMAPS_PATH = "Save/EditMode_Keymaps.ini"; const RString SpecialFiles::PREFERENCES_INI_PATH = "Save/Preferences.ini"; const RString SpecialFiles::THEMES_DIR = "Themes/"; const RString SpecialFiles::LANGUAGES_SUBDIR = "Languages/"; diff --git a/src/SpecialFiles.h b/src/SpecialFiles.h index 32bb54b6d2..dc6782d0d5 100644 --- a/src/SpecialFiles.h +++ b/src/SpecialFiles.h @@ -16,6 +16,10 @@ namespace SpecialFiles * This is not the user packages directory. */ extern const RString PACKAGES_DIR; extern const RString KEYMAPS_PATH; + /** @brief Edit Mode keymaps are separate from standard keymaps because + * it should not change with the gametype, and to avoid possible + * interference with the normal keymaps system. -Kyz */ + extern const RString EDIT_MODE_KEYMAPS_PATH; extern const RString PREFERENCES_INI_PATH; /** @brief The directory that contains the themes. */ extern const RString THEMES_DIR; From 54725b1356b7529fafbab95edebf2ad6adbe66e8 Mon Sep 17 00:00:00 2001 From: Colby Klein Date: Mon, 17 Nov 2014 14:05:03 -0800 Subject: [PATCH 22/25] Hide song options by default. It's still in the options menu, don't worry. --- src/PrefsManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index 7fd7c2e6aa..d3d4702397 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -221,7 +221,7 @@ PrefsManager::PrefsManager() : m_iSongsPerPlay ( "SongsPerPlay", 3, ValidateSongsPerPlay ), m_bDelayedCreditsReconcile ( "DelayedCreditsReconcile", false ), m_bComboContinuesBetweenSongs ( "ComboContinuesBetweenSongs", false ), - m_ShowSongOptions ( "ShowSongOptions", Maybe_YES ), + m_ShowSongOptions ( "ShowSongOptions", Maybe_NO ), m_bDancePointsForOni ( "DancePointsForOni", true ), m_bPercentageScoring ( "PercentageScoring", false ), m_fMinPercentageForMachineSongHighScore ( "MinPercentageForMachineSongHighScore", 0.0001f ), // This is for home, who cares how bad you do? From 75fdf7c650fdc5c760098f33f83033f6cd42f6aa Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Wed, 19 Nov 2014 12:00:40 -0700 Subject: [PATCH 23/25] Doc listing all announcer files added. --- Docs/Themerdocs/announcer_files.txt | 84 +++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 Docs/Themerdocs/announcer_files.txt diff --git a/Docs/Themerdocs/announcer_files.txt b/Docs/Themerdocs/announcer_files.txt new file mode 100644 index 0000000000..1bb9d84aee --- /dev/null +++ b/Docs/Themerdocs/announcer_files.txt @@ -0,0 +1,84 @@ +This could use a bit nicer formatting, and something else should explain screen inheritance, but here's everything I was able to find on announcers from searching the source. +Each entry lists the event that triggers it, then the name of the folder that is searched for a sound to play. + + +Screen inheritance note: +The screen names listed below are actually the names of screen classes. Every screen has a class type, and some screen class types inherit from others. You can find the class type of a screen by looking at the metrics for the theme and reading the Class metric in a screen's metric group. +So sound names with "" in them will actually occur on any screen that inherits from that class type, and the actual name of the screen will be inserted into the string when the announcer system goes to play the sound. + + +ScreenNameEntry +(entering screen) "name entry" + +ScreenEnding +(entering screen) "music scroll" + +ScreenEvaluation +(entering screen): (only one will occur, listed in order of precedence) +"evaluation new record" +"evaluation full combo W1" +"evaluation full combo W2" +grade string values: "AAAA" (tier 1), "AAA" (tier 2), "AA" (tier 3), "A" (tier 4), "B" (tier 5), "C" (tier 6), "D" (tier 7), "E" (tier failed), "N" (tier nodata) +"evaluation final " (only in course mode on summary screen) +"evaluation win" (only in battle mode) +"evaluation lose" (only in battle mode) +"evaluation " (only in non-course, non-battle) +(after CheerDelaySeconds) "evaluation cheer" + +ScreenPlayerOptions +(entering screen) "player options intro" + +ScreenSelectCharacter +(entering screen) "select group intro" + +ScreenSelectMaster +(ScreenSelectMaster is the name of the class type of several different screens, so these will actually occur on any of the following: "ScreenTitleMenu", "ScreenSelectLanguage", "ScreenUnlockBrowse", "ScreenSelectStyle", "ScreenSelectPlayMode", "ScreenGameInformation", or any other screen that has "ScreenSelectMaster" as its Class metric) +(on moving to second page) "select difficulty challenge" +(side note: choices on ScreenSelectMaster are split into two pages, all choices after the amount set by the NumChoicesOnPage1 metric are on the second page. Default is 1024, so this will never play unless the theme sets the metric lower to have a second page) +(on picking a choice) " comment " +( will be the full name of the screen, will be the name field of the gamecommand that defines the choice, so this could be literally anything the themer feels like) + +ScreenSelect +(every IdleCommentSeconds) " IdleComment" + +ScreenTitleMenu +(entering screen) "title menu game name" + +ScreenWithMenuElements +(entering screen) " intro" + +ScreenSelectMusic +(entering screen) "select music intro" +(every IdleCommentSeconds) " IdleComment" +(on picking a song played already this round) "select music comment repeat" +(on picking a song never played before) "select music comment new" +(on picking a song with a meter >= 10) "select music comment hard" +(on picking a song that is not one of the above) "select music comment general" +(on picking a course) "select course comment general" + +ScreenGameplay +(entering screen) "gameplay intro" +(after fading in) "gameplay ready" +(on song start extra stage) "gameplay here we go extra" +(on song start final stage) "gameplay here we go final" +(on song start non-final non-extra stage) "gameplay here we go normal" +(on enemy death in battle mode?) "gameplay battle damage level3" +(on finishing gameplay, earned extra) "gameplay extra" +(on finishing gameplay, not earned extra) "gameplay cleared" +(when failing over halfway through course) "gameplay oni failed halfway" +(when failing less than halfway through course) "gameplay oni failed" +(when failing non-course) "gameplay failed" +(following separated by SecondsBetweenComments metric) +(when one life meter is hot) "gameplay comment hot" +(when one life meter is in danger) "gameplay comment danger" +(when neither of the above two) "gameplay comment good" +(in nonstop, oni, or endless mode) "gameplay comment oni" +(every hundred combos) "gameplay combo" ( ranges from 100 to 1000) +(combo stopped) "gameplay combo stopped" +(combo continuing (every hundred over 1k)) "gameplay combo overflow" +(when a battle trick occurs) "gameplay battle trick level" ( can be 1, 2, or 3) +(when battle damage occurs) "gameplay battle damage level" ( can be 1, 2, or 3) + +(when a menu timer runs low) "hurry up" + +(whenever the theme calls SOUND:PlayAnnouncer("")) "" From b862fbec0b01aacfafdf0ca495d10e416647241e Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Sat, 22 Nov 2014 15:35:11 -0700 Subject: [PATCH 24/25] Fix PlayMode_Rave condition for turning off Life and Combo graph on Evaluation. --- .../BGAnimations/ScreenEvaluation decorations/default.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/default/BGAnimations/ScreenEvaluation decorations/default.lua b/Themes/default/BGAnimations/ScreenEvaluation decorations/default.lua index 7e27b3437d..1a738fc954 100644 --- a/Themes/default/BGAnimations/ScreenEvaluation decorations/default.lua +++ b/Themes/default/BGAnimations/ScreenEvaluation decorations/default.lua @@ -70,13 +70,13 @@ local t = LoadFallbackB(); t[#t+1] = StandardDecorationFromFileOptional("StageDisplay","StageDisplay"); -if ShowStandardDecoration("GraphDisplay") and not GAMESTATE:GetPlayMode() == "PlayMode_Rave" then +if ShowStandardDecoration("GraphDisplay") and GAMESTATE:GetPlayMode() ~= "PlayMode_Rave" then for pn in ivalues(GAMESTATE:GetHumanPlayers()) do t[#t+1] = StandardDecorationFromTable( "GraphDisplay" .. ToEnumShortString(pn), GraphDisplay(pn) ); end end -if ShowStandardDecoration("ComboGraph") and not GAMESTATE:GetPlayMode() == "PlayMode_Rave" then +if ShowStandardDecoration("ComboGraph") and GAMESTATE:GetPlayMode() ~= "PlayMode_Rave" then for pn in ivalues(GAMESTATE:GetHumanPlayers()) do t[#t+1] = StandardDecorationFromTable( "ComboGraph" .. ToEnumShortString(pn), ComboGraph(pn) ); end From 1a51b069342e0e9d03985b4227993043702dc93a Mon Sep 17 00:00:00 2001 From: Kyzentun Date: Sun, 23 Nov 2014 01:50:58 -0700 Subject: [PATCH 25/25] Fixed mistake that caused steps from non-ssc or non-sm files have blank StepsTypeStr. --- src/Song.cpp | 2 +- src/Steps.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Song.cpp b/src/Song.cpp index 27c20aa76f..30bc97265e 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -42,7 +42,7 @@ * @brief The internal version of the cache for StepMania. * * Increment this value to invalidate the current cache. */ -const int FILE_CACHE_VERSION = 221; +const int FILE_CACHE_VERSION = 222; /** @brief How long does a song sample last by default? */ const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; diff --git a/src/Steps.cpp b/src/Steps.cpp index 1b672ffb2d..c7640e2e88 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -268,6 +268,10 @@ void Steps::TidyUpData() { LOG->Warn("Detected steps with unknown style '%s' in '%s'", m_StepsTypeStr.c_str(), m_pSong->m_sSongFileName.c_str()); } + else if(m_StepsTypeStr == "") + { + m_StepsTypeStr= GAMEMAN->GetStepsTypeInfo(m_StepsType).szName; + } if( GetDifficulty() == Difficulty_Invalid ) SetDifficulty( StringToDifficulty(GetDescription()) );