Changed many places that used RageException to use ReportScriptError instead. Wrote ScreenOptionsExample.ini as documentation example for the OptionRow system. Rewrote gamecommands.txt to include all GameCommands. Fixed Commands::GetOriginalCommandString to insert the semicolons that separated the original commands. Changed nonsensical boolean |= true statements in GameCommand.cpp to just use =. Added protection to ReportScriptError to keep it from recursing through itself when an error occurs in error reporting. Added UseAbort option to ReportScriptError for places that want to use an AbortRetryIgnore dialog to query the user. Added ScriptErrorMessage for places that need to handle the warning/dialog part separately. Added logging flag to MESSAGEMAN so that all messages broadcast can be logged when desired. Changed OptionRowHandler::LoadInternal to return a boolean success value as part of error handling.
This commit is contained in:
+85
-91
@@ -117,6 +117,18 @@ int OptionRowHandlerUtil::GetOneSelection( const vector<bool> &vbSelected )
|
||||
|
||||
static LocalizedString OFF ( "OptionRowHandler", "Off" );
|
||||
|
||||
#define ROW_INVALID_IF(condition, message, retval) \
|
||||
if(condition) \
|
||||
{ \
|
||||
LuaHelpers::ReportScriptError("Parse error in option row: " message); \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
#define CHECK_WRONG_NUM_ARGS(num) \
|
||||
ROW_INVALID_IF(command.m_vsArgs.size() != num, "Wrong number of args to option row.", false);
|
||||
#define CHECK_BLANK_ARG \
|
||||
ROW_INVALID_IF(sParam.size() == 0, "Blank arg to Steps row.", false);
|
||||
|
||||
// begin OptionRow handlers
|
||||
class OptionRowHandlerList : public OptionRowHandler
|
||||
{
|
||||
@@ -135,31 +147,24 @@ public:
|
||||
m_bUseModNameForIcon = false;
|
||||
m_vsBroadcastOnExport.clear();
|
||||
}
|
||||
virtual void LoadInternal( const Commands &cmds )
|
||||
virtual bool LoadInternal( const Commands &cmds )
|
||||
{
|
||||
ASSERT( cmds.v.size() == 1 );
|
||||
const Command &command = cmds.v[0];
|
||||
RString sParam = command.GetArg(1).s;
|
||||
ASSERT( command.m_vsArgs.size() == 2 );
|
||||
ASSERT( sParam.size() != 0 );
|
||||
|
||||
m_bUseModNameForIcon = true;
|
||||
|
||||
m_Def.m_sName = sParam;
|
||||
|
||||
m_Default.Load( -1, ParseCommands(ENTRY_DEFAULT(sParam)) );
|
||||
|
||||
{
|
||||
// Parse the basic configuration metric.
|
||||
Commands lCmds = ParseCommands( ENTRY(sParam) );
|
||||
if( lCmds.v.size() < 1 )
|
||||
{
|
||||
LuaHelpers::ReportScriptErrorFmt("Parse error in \"ScreenOptionsMaster::%s\".", sParam.c_str());
|
||||
lCmds= ParseCommands("0");
|
||||
}
|
||||
ROW_INVALID_IF(lCmds.v.size() < 1, "Row command is empty.", false);
|
||||
|
||||
m_Def.m_bOneChoiceForAllPlayers = false;
|
||||
ROW_INVALID_IF(lCmds.v[0].m_vsArgs.size() != 1, "Row command has invalid args to number of entries.", false);
|
||||
const int NumCols = StringToInt( lCmds.v[0].m_vsArgs[0] );
|
||||
ROW_INVALID_IF(NumCols < 1, "Not enough entries in list.", false);
|
||||
for( unsigned i=1; i<lCmds.v.size(); i++ )
|
||||
{
|
||||
const Command &cmd = lCmds.v[i];
|
||||
@@ -198,20 +203,9 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
LuaHelpers::ReportScriptErrorFmt( "Unkown row flag \"%s\".", sName.c_str() );
|
||||
LuaHelpers::ReportScriptErrorFmt("Unkown row flag \"%s\".", sName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if(NumCols < 1)
|
||||
{
|
||||
LuaHelpers::ReportScriptErrorFmt(sParam + " has %d choices.", NumCols);
|
||||
GameCommand mc;
|
||||
mc.ApplyCommitsScreens( false );
|
||||
mc.Load( 0, ParseCommands("name,Error") );
|
||||
m_aListEntries.push_back(mc);
|
||||
RString sChoice = mc.m_sName;
|
||||
m_Def.m_vsChoices.push_back( sChoice );
|
||||
}
|
||||
for( int col = 0; col < NumCols; ++col )
|
||||
{
|
||||
GameCommand mc;
|
||||
@@ -223,13 +217,14 @@ public:
|
||||
mc.m_sName = sParam;
|
||||
if( mc.m_sName == "" )
|
||||
{
|
||||
LuaHelpers::ReportScriptErrorFmt("List \"%s\", col %i has no name.", sParam.c_str(), col);
|
||||
LuaHelpers::ReportScriptErrorFmt("List \"%s\", choice %i has no name.", sParam.c_str(), col+1);
|
||||
mc.m_sName= "";
|
||||
}
|
||||
|
||||
if( !mc.IsPlayable() )
|
||||
RString why;
|
||||
if( !mc.IsPlayable(&why) )
|
||||
{
|
||||
LuaHelpers::ReportScriptErrorFmt("\"%s\" is not playable.", sParam.c_str());
|
||||
LuaHelpers::ReportScriptErrorFmt("\"%s\" choice %d is not playable: %s", sParam.c_str(), col, why.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -249,6 +244,7 @@ public:
|
||||
m_Def.m_iDefault = e;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void ImportOption( OptionRow *pRow, const vector<PlayerNumber> &vpns, vector<bool> vbSelectedOut[NUM_PLAYERS] ) const
|
||||
{
|
||||
@@ -388,7 +384,7 @@ static void SortNoteSkins( vector<RString> &asSkinNames )
|
||||
|
||||
class OptionRowHandlerListNoteSkins : public OptionRowHandlerList
|
||||
{
|
||||
virtual void LoadInternal( const Commands & )
|
||||
virtual bool LoadInternal( const Commands & )
|
||||
{
|
||||
m_Def.m_sName = "NoteSkins";
|
||||
m_Def.m_bOneChoiceForAllPlayers = false;
|
||||
@@ -408,13 +404,14 @@ class OptionRowHandlerListNoteSkins : public OptionRowHandlerList
|
||||
m_aListEntries.push_back( mc );
|
||||
m_Def.m_vsChoices.push_back( arraySkinNames[skin] );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// XXX: very similar to OptionRowHandlerSteps
|
||||
class OptionRowHandlerListSteps : public OptionRowHandlerList
|
||||
{
|
||||
virtual void LoadInternal( const Commands & )
|
||||
virtual bool LoadInternal( const Commands & )
|
||||
{
|
||||
m_Def.m_sName = "Steps";
|
||||
m_Def.m_bAllowThemeItems = false; // we theme the text ourself
|
||||
@@ -423,6 +420,7 @@ class OptionRowHandlerListSteps : public OptionRowHandlerList
|
||||
|
||||
// don't call default
|
||||
// OptionRowHandlerList::LoadInternal( cmds );
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual ReloadChanged Reload()
|
||||
@@ -533,13 +531,12 @@ public:
|
||||
m_vDifficulties.clear();
|
||||
}
|
||||
|
||||
virtual void LoadInternal( const Commands &cmds )
|
||||
virtual bool LoadInternal( const Commands &cmds )
|
||||
{
|
||||
ASSERT( cmds.v.size() == 1 );
|
||||
const Command &command = cmds.v[0];
|
||||
RString sParam = command.GetArg(1).s;
|
||||
ASSERT( command.m_vsArgs.size() == 2 );
|
||||
ASSERT( sParam.size() != 0 );
|
||||
CHECK_WRONG_NUM_ARGS(2);
|
||||
CHECK_BLANK_ARG;
|
||||
|
||||
if( sParam == "EditSteps" )
|
||||
{
|
||||
@@ -558,7 +555,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
LuaHelpers::ReportScriptErrorFmt("Invalid StepsType param \"%s\".", sParam.c_str());
|
||||
ROW_INVALID_IF(true, "Invalid StepsType param \"" + sParam + "\".", false);
|
||||
}
|
||||
|
||||
m_Def.m_sName = sParam;
|
||||
@@ -620,6 +617,7 @@ public:
|
||||
if( m_pDifficultyToFill )
|
||||
m_pDifficultyToFill->Set( m_vDifficulties[0] );
|
||||
m_ppStepsToFill->Set( m_vSteps[0] );
|
||||
return true;
|
||||
}
|
||||
virtual void ImportOption( OptionRow *pRow, const vector<PlayerNumber> &vpns, vector<bool> vbSelectedOut[NUM_PLAYERS] ) const
|
||||
{
|
||||
@@ -679,7 +677,7 @@ public:
|
||||
|
||||
class OptionRowHandlerListCharacters: public OptionRowHandlerList
|
||||
{
|
||||
virtual void LoadInternal( const Commands & )
|
||||
virtual bool LoadInternal( const Commands & )
|
||||
{
|
||||
m_Def.m_bOneChoiceForAllPlayers = false;
|
||||
m_Def.m_bAllowThemeItems = false;
|
||||
@@ -707,12 +705,13 @@ class OptionRowHandlerListCharacters: public OptionRowHandlerList
|
||||
mc.m_pCharacter = pCharacter;
|
||||
m_aListEntries.push_back( mc );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class OptionRowHandlerListStyles: public OptionRowHandlerList
|
||||
{
|
||||
virtual void LoadInternal( const Commands & )
|
||||
virtual bool LoadInternal( const Commands & )
|
||||
{
|
||||
m_Def.m_bOneChoiceForAllPlayers = true;
|
||||
m_Def.m_sName = "Style";
|
||||
@@ -730,12 +729,13 @@ class OptionRowHandlerListStyles: public OptionRowHandlerList
|
||||
}
|
||||
|
||||
m_Default.m_pStyle = vStyles[0];
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class OptionRowHandlerListGroups: public OptionRowHandlerList
|
||||
{
|
||||
virtual void LoadInternal( const Commands & )
|
||||
virtual bool LoadInternal( const Commands & )
|
||||
{
|
||||
m_Def.m_bOneChoiceForAllPlayers = true;
|
||||
m_Def.m_bAllowThemeItems = false; // we theme the text ourself
|
||||
@@ -760,12 +760,13 @@ class OptionRowHandlerListGroups: public OptionRowHandlerList
|
||||
mc.m_sSongGroup = *g;
|
||||
m_aListEntries.push_back( mc );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class OptionRowHandlerListDifficulties: public OptionRowHandlerList
|
||||
{
|
||||
virtual void LoadInternal( const Commands & )
|
||||
virtual bool LoadInternal( const Commands & )
|
||||
{
|
||||
m_Def.m_bOneChoiceForAllPlayers = true;
|
||||
m_Def.m_sName = "Difficulty";
|
||||
@@ -790,13 +791,14 @@ class OptionRowHandlerListDifficulties: public OptionRowHandlerList
|
||||
mc.m_dc = *d;
|
||||
m_aListEntries.push_back( mc );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// XXX: very similar to OptionRowHandlerSongChoices
|
||||
class OptionRowHandlerListSongsInCurrentSongGroup: public OptionRowHandlerList
|
||||
{
|
||||
virtual void LoadInternal( const Commands & )
|
||||
virtual bool LoadInternal( const Commands & )
|
||||
{
|
||||
const vector<Song*> &vpSongs = SONGMAN->GetSongs( GAMESTATE->m_sPreferredSongGroup );
|
||||
|
||||
@@ -815,6 +817,7 @@ class OptionRowHandlerListSongsInCurrentSongGroup: public OptionRowHandlerList
|
||||
mc.m_pSong = *p;
|
||||
m_aListEntries.push_back( mc );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -995,45 +998,25 @@ public:
|
||||
LUA->Release(L);
|
||||
}
|
||||
|
||||
virtual void LoadInternal( const Commands &cmds )
|
||||
virtual bool LoadInternal( const Commands &cmds )
|
||||
{
|
||||
ASSERT( cmds.v.size() == 1 );
|
||||
const Command &command = cmds.v[0];
|
||||
ASSERT( command.m_vsArgs.size() == 2 );
|
||||
RString sLuaFunction = command.m_vsArgs[1];
|
||||
ASSERT( sLuaFunction.size() != 0 );
|
||||
RString sParam = command.GetArg(1).s;
|
||||
CHECK_WRONG_NUM_ARGS(2);
|
||||
CHECK_BLANK_ARG;
|
||||
|
||||
m_Def.m_bAllowThemeItems = false; // Lua options are always dynamic and can theme themselves.
|
||||
|
||||
Lua *L = LUA->Get();
|
||||
|
||||
// Run the Lua expression. It should return a table.
|
||||
m_pLuaTable->SetFromExpression( sLuaFunction );
|
||||
m_TableIsSane= SanityCheckTable(L, sLuaFunction);
|
||||
m_pLuaTable->SetFromExpression( sParam );
|
||||
m_TableIsSane= SanityCheckTable(L, sParam);
|
||||
if(!m_TableIsSane)
|
||||
{
|
||||
m_pLuaTable->PushSelf(L);
|
||||
lua_getfield(L, -1, "Name");
|
||||
const char *pStr = lua_tostring( L, -1 );
|
||||
if(pStr == NULL)
|
||||
{
|
||||
m_Def.m_sName = "Invalid";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Def.m_sName = pStr;
|
||||
}
|
||||
lua_pop( L, 1 );
|
||||
// Add a fake choice so that there won't be a crash.
|
||||
// This is so that a themer that makes a mistake doesn't have to
|
||||
// completely restart and can just reload scripts.
|
||||
m_Def.m_vsChoices.push_back("Error in row.");
|
||||
// Set m_selectType to SELECT_MULTIPLE so we won't hit the assert in
|
||||
// VerifySelected.
|
||||
m_Def.m_selectType= SELECT_MULTIPLE;
|
||||
lua_settop(L, 0); // Release has an assert that forces a clear stack.
|
||||
LUA->Release(L);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
m_pLuaTable->PushSelf(L);
|
||||
|
||||
@@ -1101,6 +1084,7 @@ public:
|
||||
ASSERT( lua_gettop(L) == 0 );
|
||||
|
||||
LUA->Release(L);
|
||||
return m_TableIsSane;
|
||||
}
|
||||
|
||||
virtual ReloadChanged Reload()
|
||||
@@ -1277,13 +1261,12 @@ public:
|
||||
OptionRowHandler::Init();
|
||||
m_pOpt = NULL;
|
||||
}
|
||||
virtual void LoadInternal( const Commands &cmds )
|
||||
virtual bool LoadInternal( const Commands &cmds )
|
||||
{
|
||||
ASSERT( cmds.v.size() == 1 );
|
||||
const Command &command = cmds.v[0];
|
||||
RString sParam = command.GetArg(1).s;
|
||||
ASSERT( command.m_vsArgs.size() == 2 );
|
||||
ASSERT( sParam.size() != 0 );
|
||||
CHECK_WRONG_NUM_ARGS(2);
|
||||
CHECK_BLANK_ARG;
|
||||
|
||||
Init();
|
||||
|
||||
@@ -1291,12 +1274,7 @@ public:
|
||||
m_Def.m_bOneChoiceForAllPlayers = true;
|
||||
|
||||
ConfOption *pConfOption = ConfOption::Find( sParam );
|
||||
if( pConfOption == NULL )
|
||||
{
|
||||
LuaHelpers::ReportScriptErrorFmt( "Invalid Conf type \"%s\"", sParam.c_str() );
|
||||
pConfOption = ConfOption::Find( "Invalid" );
|
||||
ASSERT_M( pConfOption != NULL, "ConfOption::Find(Invalid)" );
|
||||
}
|
||||
ROW_INVALID_IF(pConfOption == NULL, "Invalid Conf type \"" + sParam + "\".", false);
|
||||
|
||||
pConfOption->UpdateAvailableOptions();
|
||||
|
||||
@@ -1306,6 +1284,7 @@ public:
|
||||
m_Def.m_bAllowThemeItems = m_pOpt->m_bAllowThemeItems;
|
||||
|
||||
m_Def.m_sName = m_pOpt->name;
|
||||
return true;
|
||||
}
|
||||
virtual void ImportOption( OptionRow *, const vector<PlayerNumber> &vpns, vector<bool> vbSelectedOut[NUM_PLAYERS] ) const
|
||||
{
|
||||
@@ -1361,13 +1340,12 @@ public:
|
||||
m_vStepsTypesToShow.clear();
|
||||
}
|
||||
|
||||
virtual void LoadInternal( const Commands &cmds )
|
||||
virtual bool LoadInternal( const Commands &cmds )
|
||||
{
|
||||
ASSERT( cmds.v.size() == 1 );
|
||||
const Command &command = cmds.v[0];
|
||||
RString sParam = command.GetArg(1).s;
|
||||
ASSERT( command.m_vsArgs.size() == 2 );
|
||||
ASSERT( sParam.size() != 0 );
|
||||
CHECK_WRONG_NUM_ARGS(2);
|
||||
CHECK_BLANK_ARG;
|
||||
|
||||
if( sParam == "EditStepsType" )
|
||||
{
|
||||
@@ -1383,7 +1361,7 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
RageException::Throw( "Invalid StepsType param \"%s\".", sParam.c_str() );
|
||||
ROW_INVALID_IF(true, "Invalid StepsType param \"" + sParam + "\".", false);
|
||||
}
|
||||
|
||||
m_Def.m_sName = sParam;
|
||||
@@ -1404,6 +1382,7 @@ public:
|
||||
|
||||
if( *m_pstToFill == StepsType_Invalid )
|
||||
m_pstToFill->Set( m_vStepsTypesToShow[0] );
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void ImportOption( OptionRow *pRow, const vector<PlayerNumber> &vpns, vector<bool> vbSelectedOut[NUM_PLAYERS] ) const
|
||||
@@ -1455,19 +1434,20 @@ public:
|
||||
m_gc.Init();
|
||||
m_gc.ApplyCommitsScreens( false );
|
||||
}
|
||||
virtual void LoadInternal( const Commands &cmds )
|
||||
virtual bool LoadInternal( const Commands &cmds )
|
||||
{
|
||||
ASSERT( cmds.v.size() > 1 );
|
||||
ROW_INVALID_IF(cmds.v.size() <= 1, "No args to construct GameCommand.", false);
|
||||
|
||||
Commands temp = cmds;
|
||||
temp.v.erase( temp.v.begin() );
|
||||
m_gc.Load( 0, temp );
|
||||
ASSERT( !m_gc.m_sName.empty() );
|
||||
ROW_INVALID_IF(m_gc.m_sName.empty(), "GameCommand row has no name.", false);
|
||||
m_Def.m_sName = m_gc.m_sName;
|
||||
m_Def.m_bOneChoiceForAllPlayers = true;
|
||||
m_Def.m_layoutType = LAYOUT_SHOW_ONE_IN_ROW;
|
||||
m_Def.m_selectType = SELECT_NONE;
|
||||
m_Def.m_vsChoices.push_back( "" );
|
||||
return true;
|
||||
}
|
||||
virtual void ImportOption( OptionRow *pRow, const vector<PlayerNumber> &vpns, vector<bool> vbSelectedOut[NUM_PLAYERS] ) const
|
||||
{
|
||||
@@ -1501,20 +1481,21 @@ OptionRowHandler* OptionRowHandlerUtil::Make( const Commands &cmds )
|
||||
{
|
||||
OptionRowHandler* pHand = NULL;
|
||||
|
||||
if( cmds.v.size() == 0 )
|
||||
return NULL;
|
||||
|
||||
ROW_INVALID_IF(cmds.v.size() == 0, "No commands for constructing row.", NULL);
|
||||
const RString &name = cmds.v[0].GetName();
|
||||
ROW_INVALID_IF(name != "gamecommand" && cmds.v.size() != 1,
|
||||
"Row must be constructed from single command.", NULL);
|
||||
|
||||
#define MAKE( type ) { type *p = new type; p->Load( cmds ); pHand = p; }
|
||||
bool load_succeeded= false;
|
||||
#define MAKE( type ) { type *p = new type; load_succeeded= p->Load( cmds ); pHand = p; }
|
||||
|
||||
// XXX: merge these, and merge "Steps" and "list,Steps"
|
||||
if( name == "list" )
|
||||
{
|
||||
const Command &command = cmds.v[0];
|
||||
RString sParam = command.GetArg(1).s;
|
||||
if( command.m_vsArgs.size() != 2 || !sParam.size() )
|
||||
return NULL;
|
||||
ROW_INVALID_IF(command.m_vsArgs.size() != 2 || !sParam.size(),
|
||||
"list row command must be 'list,name' or 'list,type'.", NULL);
|
||||
|
||||
if( sParam.CompareNoCase("NoteSkins")==0 ) MAKE( OptionRowHandlerListNoteSkins )
|
||||
else if( sParam.CompareNoCase("Steps")==0 ) MAKE( OptionRowHandlerListSteps )
|
||||
@@ -1535,16 +1516,29 @@ OptionRowHandler* OptionRowHandlerUtil::Make( const Commands &cmds )
|
||||
else if( name == "stepstype" ) MAKE( OptionRowHandlerStepsType )
|
||||
else if( name == "steps" ) MAKE( OptionRowHandlerSteps )
|
||||
else if( name == "gamecommand" ) MAKE( OptionRowHandlerGameCommand )
|
||||
else
|
||||
{
|
||||
ROW_INVALID_IF(true, "Invalid row type.", NULL);
|
||||
}
|
||||
|
||||
return pHand;
|
||||
if(load_succeeded)
|
||||
{
|
||||
return pHand;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OptionRowHandler* OptionRowHandlerUtil::MakeNull()
|
||||
{
|
||||
OptionRowHandler* pHand = NULL;
|
||||
bool load_succeeded= false; // Part of the MAKE macro, but unused.
|
||||
Commands cmds;
|
||||
MAKE( OptionRowHandlerNull )
|
||||
return pHand;
|
||||
if(load_succeeded) // Just to get rid of the warning for not using it.
|
||||
{
|
||||
return pHand;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OptionRowHandler* OptionRowHandlerUtil::MakeSimple( const MenuRowDef &mr )
|
||||
|
||||
Reference in New Issue
Block a user