Created GameLoop::ChangeGame analogous to GameLoop::ChangeTheme. Changed ChangeTheme to use the AfterThemeChangeScreen metric instead of a passed in screen name from the theme being changed away from. ChangeGame uses the AfterGameChangeScreen and AfterGameAndThemeChangeScreen metrics to pick the screen to load after the change. New metrics are optional and default to InitialScreen. Changed ScreenManager::ThemeChanged to not duplicate the code in ReloadOverlayScreens. Fixed ScreenManager::IsScreenNameValid to check with HasMetric before using GetMetric. Changed game ConfOption logic to set the preference and work in a similar way to the theme ConfOption. Added THEME:SetTheme lua function.

This commit is contained in:
Kyzentun
2014-07-20 20:59:12 -06:00
parent 35ce025a1c
commit c3fb210291
13 changed files with 173 additions and 80 deletions
+1
View File
@@ -1661,6 +1661,7 @@
<Function name='IsThemeSelectable'/>
<Function name='ReloadMetrics'/>
<Function name='RunLuaScripts'/>
<Function name='SetTheme'/>
</Class>
<Class name='TimingData'>
<Function name='GetActualBPM'/>
+9 -1
View File
@@ -2181,7 +2181,10 @@ save yourself some time, copy this for undocumented things:
Returns a table of all selectable games.
</Function>
<Function name='SetGame' return='void' arguments='string Game, string Theme' >
Sets the current game to <code>Game</code>. The second argument is optional, and if provided will determine which theme is loaded when the game changes. If Stepmania was run with a commandline argument setting the theme, that will override the second argument of this function.
Sets the current game to <code>Game</code>. The second argument is optional, and if provided will determine which theme is loaded when the game changes. If the second argument is not provided, the default theme from the preferences for the new game type will be loaded.<br />
If only the game changes, the screen specified by the Common::AfterGameChangeScreen metric will be loaded.<br />
If the game and the theme both change, the screen specified by the Common::AfterGameAndThemeChangeScreen metric will be loaded.<br />
The Common::InitialScreen metric will be used if the appropriate metric for the change is blank or invalid.
</Function>
</Class>
<Class name='GameSoundManager'>
@@ -4678,6 +4681,11 @@ save yourself some time, copy this for undocumented things:
<Function name='RunLuaScripts' return='void' arguments='string sMask'>
</Function>
<Function name='SetTheme' return='void' arguments='string theme'>
Changes the current theme.<br />
After the theme changes, the screen specified by the Common::AfterThemeChangeScreen metric will be loaded.<br />
The Common::InitialScreen metric will be used if Common::AfterThemeChangeScreen is blank or invalid.
</Function>
</Class>
<Class name='TimingData'>
<Function name='GetActualBPM' return='{float}' arguments=''>
+107 -16
View File
@@ -114,17 +114,24 @@ static void CheckFocus()
}
// On the next update, change themes, and load sNewScreen.
static RString g_sNewTheme;
static RString g_sNewScreen;
static RString g_NewTheme;
static bool g_bForceThemeReload;
void GameLoop::ChangeTheme( const RString &sNewTheme, const RString &sNewScreen, bool bForced )
static RString g_NewGame;
void GameLoop::ChangeTheme( const RString &sNewTheme, bool bForced )
{
g_sNewTheme = sNewTheme;
g_sNewScreen = sNewScreen;
g_NewTheme = sNewTheme;
g_bForceThemeReload = bForced;
}
void GameLoop::ChangeGame(const RString& new_game, const RString& new_theme)
{
g_NewGame= new_game;
g_NewTheme= new_theme;
}
#include "StepMania.h" // XXX
#include "GameManager.h"
#include "Game.h"
namespace
{
void DoChangeTheme()
@@ -135,8 +142,8 @@ namespace
// In case the previous theme overloaded class bindings, reinitialize them.
LUA->RegisterTypes();
THEME->SwitchThemeAndLanguage( g_sNewTheme, THEME->GetCurLanguage(), PREFSMAN->m_bPseudoLocalize, g_bForceThemeReload );
PREFSMAN->m_sTheme.Set( g_sNewTheme );
THEME->SwitchThemeAndLanguage( g_NewTheme, THEME->GetCurLanguage(), PREFSMAN->m_bPseudoLocalize, g_bForceThemeReload );
PREFSMAN->m_sTheme.Set( g_NewTheme );
// Apply the new window title, icon and aspect ratio.
StepMania::ApplyGraphicOptions();
@@ -145,19 +152,97 @@ namespace
StepMania::ResetGame();
SCREENMAN->ThemeChanged();
// Not all themes use the same screen names! Check whether the new
// screen is valid in the new theme before setting it. Use the
// InitialScreen metric if it's not.
if(!SCREENMAN->IsScreenNameValid(g_sNewScreen))
// The previous system for changing the theme fetched the "NextScreen"
// metric from the current theme, then changed the theme, then tried to
// set the new screen to the name that had been fetched.
// If the new screen didn't exist in the new theme, there would be a
// crash.
// So now the correct thing to do is for a theme to specify its entry
// point after a theme change, ensuring that we are going to a valid
// screen and not crashing. -Kyz
RString new_screen= THEME->GetMetric("Common", "InitialScreen");
if(THEME->HasMetric("Common", "AfterThemeChangeScreen"))
{
g_sNewScreen= THEME->GetMetric("Common", "InitialScreen");
RString after_screen= THEME->GetMetric("Common", "AfterThemeChangeScreen");
if(SCREENMAN->IsScreenNameValid(after_screen))
{
new_screen= after_screen;
}
}
SCREENMAN->SetNewScreen( g_sNewScreen );
SCREENMAN->SetNewScreen(new_screen);
g_sNewTheme = RString();
g_sNewScreen = RString();
g_NewTheme = RString();
}
void DoChangeGame()
{
const Game* g= GAMEMAN->StringToGame(g_NewGame);
ASSERT(g != NULL);
GAMESTATE->SetCurGame(g);
bool theme_changing= false;
// The prefs allow specifying a different default theme to use for each
// game type. So if a theme name isn't passed in, fetch from the prefs.
if(g_NewTheme.empty())
{
g_NewTheme= PREFSMAN->m_sTheme;
}
if(g_NewTheme != THEME->GetCurThemeName() && THEME->IsThemeSelectable(g_NewTheme))
{
theme_changing= true;
}
if(theme_changing)
{
SAFE_DELETE(SCREENMAN);
TEXTUREMAN->DoDelayedDelete();
LUA->RegisterTypes();
THEME->SwitchThemeAndLanguage(g_NewTheme, THEME->GetCurLanguage(),
PREFSMAN->m_bPseudoLocalize);
PREFSMAN->m_sTheme.Set(g_NewTheme);
StepMania::ApplyGraphicOptions();
SCREENMAN= new ScreenManager();
}
StepMania::ResetGame();
RString new_screen= THEME->GetMetric("Common", "InitialScreen");
RString after_screen;
if(theme_changing)
{
SCREENMAN->ThemeChanged();
if(THEME->HasMetric("Common", "AfterGameAndThemeChangeScreen"))
{
after_screen= THEME->GetMetric("Common", "AfterGameAndThemeChangeScreen");
}
}
else
{
if(THEME->HasMetric("Common", "AfterGameChangeScreen"))
{
after_screen= THEME->GetMetric("Common", "AfterGameChangeScreen");
}
}
if(SCREENMAN->IsScreenNameValid(after_screen))
{
new_screen= after_screen;
}
SCREENMAN->SetNewScreen(new_screen);
// Set the input scheme for the new game, and load keymaps.
if( INPUTMAPPER )
{
INPUTMAPPER->SetInputScheme(&g->m_InputScheme);
INPUTMAPPER->ReadMappingsFromDisk();
}
// aj's comment transplanted from ScreenOptionsMasterPrefs.cpp:GameSel. -Kyz
/* Reload metrics to force a refresh of CommonMetrics::DIFFICULTIES_TO_SHOW,
* mainly if we're not switching themes. I'm not sure if this was the
* case going from theme to theme, but if it was, it should be fixed
* now. There's probably be a better way to do it, but I'm not sure
* what it'd be. -aj */
THEME->ReloadMetrics();
g_NewGame= RString();
g_NewTheme= RString();
}
}
void GameLoop::RunGameLoop()
@@ -169,8 +254,14 @@ void GameLoop::RunGameLoop()
while( !ArchHooks::UserQuit() )
{
if( !g_sNewTheme.empty() )
if(!g_NewGame.empty())
{
DoChangeGame();
}
if(!g_NewTheme.empty())
{
DoChangeTheme();
}
// Update
float fDeltaTime = g_GameplayTimer.GetDeltaTime();
+2 -1
View File
@@ -5,7 +5,8 @@ namespace GameLoop
{
void RunGameLoop();
void SetUpdateRate( float fUpdateRate );
void ChangeTheme( const RString &sNewTheme, const RString &sNewScreen, bool bForced = false );
void ChangeTheme( const RString &sNewTheme, bool bForced = false );
void ChangeGame(const RString& new_game, const RString& new_theme= "");
void StartConcurrentRendering();
void FinishConcurrentRendering();
};
+15 -14
View File
@@ -1,9 +1,10 @@
#include "global.h"
#include "Stepmania.h"
#include "StepMania.h"
#include "arch/Dialog/Dialog.h"
#include "GameManager.h"
#include "GameConstantsAndTypes.h"
#include "GameInput.h" // for GameButton constants
#include "GameLoop.h" // for ChangeGame
#include "RageLog.h"
#include "RageUtil.h"
#include "NoteSkinManager.h"
@@ -3176,22 +3177,22 @@ public:
static int SetGame( T* p, lua_State *L )
{
const Game *pGame = p->StringToGame(SArg(1));
RString sTheme;
RString game_name= SArg(1);
const Game *pGame = p->StringToGame(game_name);
if(!pGame)
{
luaL_error(L, "SetGame: Invalid Game: '%s'", game_name.c_str());
}
RString theme;
if( lua_gettop(L) >= 2 && !lua_isnil(L, 2) )
{
sTheme = SArg(2);
}
if( pGame )
{
StepMania::ChangeCurrentGame( pGame, sTheme );
THEME->ReloadMetrics();
}
else
{
LOG->Warn( "SetGame: Invalid Game, %s", pGame->m_szName );
Dialog::OK( "SetGame: Invalid Game, %s", pGame->m_szName );
theme = SArg(2);
if(!THEME->IsThemeSelectable(theme))
{
luaL_error(L, "SetGame: Invalid Theme: '%s'", theme.c_str());
}
}
GameLoop::ChangeGame(game_name, theme);
return 0;
}
+7 -23
View File
@@ -282,34 +282,14 @@ void ScreenManager::ThemeChanged()
m_soundInvalid.Load( THEME->GetPathS("Common","invalid") );
m_soundScreenshot.Load( THEME->GetPathS("Common","screenshot") );
// unload overlay screens
for( unsigned i=0; i<g_OverlayScreens.size(); i++ )
SAFE_DELETE( g_OverlayScreens[i] );
g_OverlayScreens.clear();
// reload overlay screens
RString sOverlays = THEME->GetMetric( "Common","OverlayScreens" );
vector<RString> asOverlays;
split( sOverlays, ",", asOverlays );
for( unsigned i=0; i<asOverlays.size(); i++ )
{
Screen *pScreen = MakeNewScreen( asOverlays[i] );
if(pScreen)
{
LuaThreadVariable var2( "LoadingScreen", pScreen->GetName() );
pScreen->BeginScreen();
g_OverlayScreens.push_back( pScreen );
}
}
// reload song manager colors (to avoid crashes) -aj
SONGMAN->ResetGroupColors();
ReloadOverlayScreens();
// force recreate of new BGA
SAFE_DELETE( g_pSharedBGA );
g_pSharedBGA = new Actor;
this->RefreshCreditsMessages();
}
void ScreenManager::ReloadOverlayScreens()
@@ -369,7 +349,11 @@ bool ScreenManager::AllowOperatorMenuButton() const
bool ScreenManager::IsScreenNameValid(RString const& name) const
{
RString ClassName = THEME->GetMetric(name,"Class");
if(name.empty() || !THEME->HasMetric(name, "Class"))
{
return false;
}
RString ClassName = THEME->GetMetric(name, "Class");
return g_pmapRegistrees->find(ClassName) != g_pmapRegistrees->end();
}
+4 -5
View File
@@ -4,6 +4,7 @@
#include "RageUtil.h"
#include "RageLog.h"
#include "ThemeManager.h"
#include "GameManager.h"
#include "GameState.h"
#include "ScreenManager.h"
#include "SongManager.h"
@@ -127,8 +128,7 @@ void ScreenOptionsMaster::HandleScreenMessage( const ScreenMessage SM )
* Otherwise, only reload it if it changed. */
RString sNewTheme = PREFSMAN->m_sTheme.Get();
bool bForceThemeReload = !!(m_iChangeMask & OPT_APPLY_ASPECT_RATIO) || !!(m_iChangeMask & OPT_APPLY_GRAPHICS);
GameLoop::ChangeTheme( sNewTheme, this->GetNextScreenName(), bForceThemeReload );
StepMania::ApplyGraphicOptions();
GameLoop::ChangeTheme( sNewTheme, bForceThemeReload );
}
if( m_iChangeMask & OPT_SAVE_PREFERENCES )
@@ -138,10 +138,9 @@ void ScreenOptionsMaster::HandleScreenMessage( const ScreenMessage SM )
PREFSMAN->SavePrefsToDisk();
}
if( m_iChangeMask & OPT_RESET_GAME )
if( m_iChangeMask & OPT_CHANGE_GAME )
{
StepMania::ResetGame();
m_sNextScreen = StepMania::GetInitialScreen();
GameLoop::ChangeGame(PREFSMAN->GetCurrentGame());
}
if( m_iChangeMask & OPT_APPLY_SOUND )
+3 -9
View File
@@ -177,7 +177,7 @@ static void GameSel( int &sel, bool ToSel, const ConfOption *pConfOption )
if( ToSel )
{
const RString sCurGameName = GAMESTATE->m_pCurGame->m_szName;
const RString sCurGameName = PREFSMAN->GetCurrentGame();
sel = 0;
for(unsigned i = 0; i < choices.size(); ++i)
@@ -186,13 +186,7 @@ static void GameSel( int &sel, bool ToSel, const ConfOption *pConfOption )
} else {
vector<const Game*> aGames;
GAMEMAN->GetEnabledGames( aGames );
StepMania::ChangeCurrentGame( aGames[sel] );
/* Reload metrics to force a refresh of CommonMetrics::DIFFICULTIES_TO_SHOW,
* mainly if we're not switching themes. I'm not sure if this was the
* case going from theme to theme, but if it was, it should be fixed
* now. There's probably be a better way to do it, but I'm not sure
* what it'd be. -aj */
THEME->ReloadMetrics();
PREFSMAN->SetCurrentGame(aGames[sel]->m_szName);
}
}
@@ -663,7 +657,7 @@ static void InitializeConfOptions()
#define ADD(x) g_ConfOptions.push_back( x )
// Select game
ADD( ConfOption( "Game", GameSel, GameChoices ) );
g_ConfOptions.back().m_iEffects = OPT_RESET_GAME;
g_ConfOptions.back().m_iEffects = OPT_CHANGE_GAME;
// Appearance options
ADD( ConfOption( "Language", Language, LanguageChoices ) );
+1 -1
View File
@@ -5,7 +5,7 @@ static const int MAX_OPTIONS=16;
#define OPT_SAVE_PREFERENCES (1<<0)
#define OPT_APPLY_GRAPHICS (1<<1)
#define OPT_APPLY_THEME (1<<2)
#define OPT_RESET_GAME (1<<3)
#define OPT_CHANGE_GAME (1<<3)
#define OPT_APPLY_SOUND (1<<4)
#define OPT_APPLY_SONG (1<<5)
#define OPT_APPLY_ASPECT_RATIO (1<<6)
+3 -1
View File
@@ -54,10 +54,12 @@ bool ScreenTitleMenu::Input( const InputEventPlus &input )
if( input.type == IET_FIRST_PRESS )
{
// detect codes
// Theme changing pad codes are marked as deprecated in _fallback's
// metrics.ini, remove them after SM5? -Kyz
if( CodeDetector::EnteredCode(input.GameI.controller,CODE_NEXT_THEME) ||
CodeDetector::EnteredCode(input.GameI.controller,CODE_NEXT_THEME2) )
{
GameLoop::ChangeTheme( THEME->GetNextSelectableTheme(), m_sName );
GameLoop::ChangeTheme(THEME->GetNextSelectableTheme());
bHandled = true;
}
if( CodeDetector::EnteredCode(input.GameI.controller,CODE_NEXT_ANNOUNCER) ||
+7 -8
View File
@@ -805,10 +805,11 @@ static void SwitchToLastPlayedGame()
ASSERT( GAMEMAN->IsGameEnabled(pGame) );
StepMania::ChangeCurrentGame( pGame );
StepMania::InitializeCurrentGame( pGame );
}
void StepMania::ChangeCurrentGame( const Game* g, RString Theme )
// This function is meant to only be called during start up.
void StepMania::InitializeCurrentGame( const Game* g )
{
ASSERT( g != NULL );
ASSERT( GAMESTATE != NULL );
@@ -823,11 +824,9 @@ void StepMania::ChangeCurrentGame( const Game* g, RString Theme )
if( sAnnouncer.empty() )
sAnnouncer = GAMESTATE->GetCurrentGame()->m_szName;
if( sTheme.empty() )
sTheme = GAMESTATE->GetCurrentGame()->m_szName;
if( Theme.size() )
sTheme = Theme;
// It doesn't matter if sTheme is blank or invalid, THEME->STAL will set
// a selectable theme for us. -Kyz
// process theme and language command line arguments;
// these change the preferences in order for transparent loading -aj
RString argTheme;
@@ -1115,7 +1114,7 @@ int main(int argc, char* argv[])
INPUTFILTER = new InputFilter;
INPUTMAPPER = new InputMapper;
StepMania::ChangeCurrentGame( GAMESTATE->GetCurrentGame() );
StepMania::InitializeCurrentGame( GAMESTATE->GetCurrentGame() );
INPUTQUEUE = new InputQueue;
SONGINDEX = new SongCacheIndex;
+1 -1
View File
@@ -15,7 +15,7 @@ namespace StepMania
void ResetGame();
RString GetInitialScreen();
RString GetSelectMusicScreen();
void ChangeCurrentGame( const Game* g, RString Theme = "" );
void InitializeCurrentGame(const Game* g);
// If successful, return filename of screenshot in sDir, else return ""
RString SaveScreenshot( RString Dir, bool SaveCompressed, bool MakeSignature, RString NamePrefix, RString NameSuffix );
+13
View File
@@ -17,6 +17,7 @@
#include "ActorUtil.h"
#endif
#include "Foreach.h"
#include "GameLoop.h" // For ChangeTheme
#include "ThemeMetric.h"
#include "SubscriptionManager.h"
#include "LuaManager.h"
@@ -1341,6 +1342,17 @@ public:
return 1;
}
static int SetTheme(T* p, lua_State* L)
{
RString theme_name= SArg(1);
if(!p->IsThemeSelectable(theme_name))
{
luaL_error(L, "SetTheme: Invalid Theme: '%s'", theme_name.c_str());
}
GameLoop::ChangeTheme(theme_name);
return 0;
}
LunaThemeManager()
{
ADD_METHOD( ReloadMetrics );
@@ -1367,6 +1379,7 @@ public:
ADD_METHOD( HasString );
ADD_METHOD( GetMetricNamesInGroup );
ADD_METHOD( GetStringNamesInGroup );
ADD_METHOD( SetTheme );
}
};