Fix LoadFallbackB for loading BGAs recursively. LoadFallbackB checking for either LuaThreadVariables or Lua globals is not very clean, but room for possible improvement.
This commit is contained in:
@@ -27,7 +27,7 @@ function ComboGraph( pn )
|
||||
end
|
||||
|
||||
|
||||
local t = THEME:GetPathB("ScreenWithMenuElements2", "decorations" );
|
||||
local t = LoadFallbackB();
|
||||
|
||||
t[#t+1] = GraphDisplay(PLAYER_1) .. {
|
||||
InitCommand = cmd(x,SCREEN_CENTER_X-222;y,SCREEN_CENTER_Y-16;draworder,1;);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
local t = LoadFallbackB( "decorations" );
|
||||
local t = LoadFallbackB();
|
||||
|
||||
t[#t+1] = LoadActor( THEME:GetPathB('','_standard decoration required'), "StageFrame", "StageFrame" );
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ local function OptionsArea(pn)
|
||||
end
|
||||
|
||||
|
||||
local t = LoadFallbackB( "decorations" );
|
||||
local t = LoadFallbackB();
|
||||
t[#t+1] = Def.ActorFrame {
|
||||
InitCommand=cmd(x,SCREEN_CENTER_X+140;y,SCREEN_CENTER_Y-10);
|
||||
OnCommand=cmd(addx,-SCREEN_WIDTH*0.6;bounceend,0.5;addx,SCREEN_WIDTH*0.6);
|
||||
|
||||
@@ -1,10 +1,32 @@
|
||||
function LoadFallbackB( element )
|
||||
-- TODO: This should fall back to the current lookup's fallback, and not LoadingScreen's fallback
|
||||
-- TODO: Remove element parameter and make it a LuaThreadVar
|
||||
local fallback_screen = THEME:GetMetric(Var 'LoadingScreen','Fallback');
|
||||
local fallback_path = THEME:GetPathB(fallback_screen,element);
|
||||
--Trace('fallback_path ' .. fallback_path );
|
||||
return LoadActor( fallback_path );
|
||||
local g_metrics_group = nil;
|
||||
local g_element = nil;
|
||||
|
||||
function LoadFallbackB()
|
||||
-- Load the fallback BGA for the element that is currently being loaded.
|
||||
-- The fallback metrics group and element name will come either from LuaThreadVars
|
||||
-- (loading from C++) or from the Lua globals above (loading from Lua).
|
||||
|
||||
--Warn( "g_element " .. (g_element or "") );
|
||||
--Warn( "MatchingElement " .. (Var 'MatchingElement' or "") );
|
||||
--Warn( "g_metrics_group " .. (g_metrics_group or "") );
|
||||
--Warn( "MatchingMetricsGroup " .. (Var 'MatchingMetricsGroup' or "") );
|
||||
|
||||
local metrics_group = g_metrics_group or Var 'MatchingMetricsGroup';
|
||||
local element = g_element or Var 'MatchingElement';
|
||||
local fallback = THEME:GetMetric(metrics_group,'Fallback');
|
||||
|
||||
local old_metrics_group = g_metrics_group;
|
||||
local old_element = g_element;
|
||||
|
||||
local path;
|
||||
path, g_metrics_group, g_element = THEME:GetPathInfoB(fallback,element);
|
||||
--Trace('path ' .. path );
|
||||
local t = LoadActor( path );
|
||||
|
||||
g_metrics_group = old_metrics_group;
|
||||
g_element = old_element;
|
||||
|
||||
return t;
|
||||
end
|
||||
|
||||
function FormatNumSongsPlayed( num )
|
||||
|
||||
@@ -45,6 +45,16 @@ void AutoActor::Load( const RString &sPath )
|
||||
m_pActor = new Actor;
|
||||
}
|
||||
|
||||
void AutoActor::LoadB( const RString &sMetricsGroup, const RString &sElement )
|
||||
{
|
||||
ThemeManager::PathInfo pi;
|
||||
bool b = THEME->GetPathInfo( pi, EC_BGANIMATIONS, sMetricsGroup, sElement );
|
||||
ASSERT( b );
|
||||
LuaThreadVariable var1( "MatchingMetricsGroup", pi.sMatchingMetricsGroup );
|
||||
LuaThreadVariable var2( "MatchingElement", pi.sMatchingElement );
|
||||
Load( pi.sResolvedPath );
|
||||
}
|
||||
|
||||
void AutoActor::LoadActorFromNode( const XNode* pNode, Actor *pParent )
|
||||
{
|
||||
Unload();
|
||||
|
||||
@@ -21,8 +21,9 @@ public:
|
||||
Actor *operator->() { return m_pActor; }
|
||||
void Unload();
|
||||
bool IsLoaded() const { return m_pActor != NULL; }
|
||||
void Load( Actor *pActor );
|
||||
void Load( Actor *pActor ); // transfer pointer
|
||||
void Load( const RString &sPath );
|
||||
void LoadB( const RString &sMetricsGroup, const RString &sElement ); // load a background and set up LuaThreadVariables for recursive loading
|
||||
void LoadActorFromNode( const XNode *pNode, Actor *pParent );
|
||||
void LoadAndSetName( const RString &sScreenName, const RString &sActorName );
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ void ScreenWithMenuElements::Init()
|
||||
/* Experimental: Load "decorations" and make them children of the screen. */
|
||||
{
|
||||
AutoActor decorations;
|
||||
decorations.Load( THEME->GetPathB(m_sName,"decorations") );
|
||||
decorations.LoadB( m_sName, "decorations" );
|
||||
ActorFrame *pFrame = dynamic_cast<ActorFrame*>((Actor*)decorations);
|
||||
if( pFrame )
|
||||
pFrame->TransferChildren( this );
|
||||
|
||||
@@ -114,7 +114,7 @@ void ThemeManager::Unsubscribe( IThemeMetric *p )
|
||||
|
||||
|
||||
/* We spend a lot of time doing redundant theme path lookups. Cache results. */
|
||||
static map<RString, RString> g_ThemePathCache[NUM_ElementCategory];
|
||||
static map<RString, ThemeManager::PathInfo> g_ThemePathCache[NUM_ElementCategory];
|
||||
void ThemeManager::ClearThemePathCache()
|
||||
{
|
||||
for( int i = 0; i < NUM_ElementCategory; ++i )
|
||||
@@ -503,10 +503,10 @@ void ThemeManager::FilterFileLanguages( vector<RString> &asPaths )
|
||||
asPaths.erase( it, asPaths.end() );
|
||||
}
|
||||
|
||||
RString ThemeManager::GetPathToRaw( const RString &sThemeName_, ElementCategory category, const RString &sMetricsGroup_, const RString &sElement_ )
|
||||
bool ThemeManager::GetPathInfoToRaw( PathInfo &out, const RString &sThemeName_, ElementCategory category, const RString &sMetricsGroup_, const RString &sElement_ )
|
||||
{
|
||||
/* Ugly: the parameters to this function may be a reference into g_vThemes, or something
|
||||
* else that might suddenly go away when we call ReloadMetrics. */
|
||||
* else that might suddenly go away when we call ReloadMetrics, so make a copy. */
|
||||
const RString sThemeName = sThemeName_;
|
||||
const RString sMetricsGroup = sMetricsGroup_;
|
||||
const RString sElement = sElement_;
|
||||
@@ -578,7 +578,7 @@ try_element_again:
|
||||
|
||||
|
||||
if( asElementPaths.size() == 0 )
|
||||
return RString(); // This isn't fatal.
|
||||
return false; // This isn't fatal.
|
||||
|
||||
FilterFileLanguages( asElementPaths );
|
||||
|
||||
@@ -613,7 +613,12 @@ try_element_again:
|
||||
bool bIsARedirect = GetExtension(sPath).CompareNoCase("redir")==0;
|
||||
|
||||
if( !bIsARedirect )
|
||||
return sPath;
|
||||
{
|
||||
out.sResolvedPath = sPath;
|
||||
out.sMatchingMetricsGroup = sMetricsGroup;
|
||||
out.sMatchingElement = sElement;
|
||||
return true;
|
||||
}
|
||||
|
||||
RString sNewFileName;
|
||||
GetFileContents( sPath, sNewFileName, true );
|
||||
@@ -629,10 +634,8 @@ try_element_again:
|
||||
* up resolving to the overridden background. */
|
||||
/* Use GetPathToOptional because we don't want report that there's an element
|
||||
* missing. Instead we want to report that the redirect is invalid. */
|
||||
RString sNewPath = GetPath(category, sNewClassName, sNewFile, true);
|
||||
|
||||
if( !sNewPath.empty() )
|
||||
return sNewPath;
|
||||
if( GetPathInfo(out,category,sNewClassName,sNewFile,true) )
|
||||
return true;
|
||||
|
||||
RString sMessage = ssprintf(
|
||||
"ThemeManager: The redirect '%s' points to the file '%s', which does not exist. "
|
||||
@@ -645,13 +648,14 @@ try_element_again:
|
||||
ReloadMetrics();
|
||||
goto try_element_again;
|
||||
case Dialog::ignore:
|
||||
return GetPath( category, "", "_missing" );
|
||||
GetPathInfo( out, category, "", "_missing" );
|
||||
return true;
|
||||
}
|
||||
|
||||
RageException::Throw( "%s", sMessage.c_str() );
|
||||
}
|
||||
|
||||
RString ThemeManager::GetPathToAndFallback( ElementCategory category, const RString &sMetricsGroup_, const RString &sElement )
|
||||
bool ThemeManager::GetPathInfoToAndFallback( PathInfo &out, ElementCategory category, const RString &sMetricsGroup_, const RString &sElement )
|
||||
{
|
||||
RString sMetricsGroup( sMetricsGroup_ );
|
||||
|
||||
@@ -661,18 +665,17 @@ RString ThemeManager::GetPathToAndFallback( ElementCategory category, const RStr
|
||||
FOREACHD_CONST( Theme, g_vThemes, iter )
|
||||
{
|
||||
// search with requested name
|
||||
RString sRet = GetPathToRaw( iter->sThemeName, category, sMetricsGroup, sElement );
|
||||
if( !sRet.empty() )
|
||||
return sRet;
|
||||
if( GetPathInfoToRaw( out, iter->sThemeName, category, sMetricsGroup, sElement ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
if( sMetricsGroup.empty() )
|
||||
return RString();
|
||||
return false;
|
||||
|
||||
// search fallback name (if any)
|
||||
sMetricsGroup = GetMetricsGroupFallback( sMetricsGroup );
|
||||
if( sMetricsGroup.empty() )
|
||||
return RString();
|
||||
return false;
|
||||
}
|
||||
|
||||
RageException::Throw( "Infinite recursion looking up theme element \"%s\"",
|
||||
@@ -682,7 +685,7 @@ RString ThemeManager::GetPathToAndFallback( ElementCategory category, const RStr
|
||||
while( true ) {}
|
||||
}
|
||||
|
||||
RString ThemeManager::GetPath( ElementCategory category, const RString &sMetricsGroup_, const RString &sElement_, bool bOptional )
|
||||
bool ThemeManager::GetPathInfo( PathInfo &out, ElementCategory category, const RString &sMetricsGroup_, const RString &sElement_, bool bOptional )
|
||||
{
|
||||
/* Ugly: the parameters to this function may be a reference into g_vThemes, or something
|
||||
* else that might suddenly go away when we call ReloadMetrics. */
|
||||
@@ -691,29 +694,31 @@ RString ThemeManager::GetPath( ElementCategory category, const RString &sMetrics
|
||||
|
||||
RString sFileName = MetricsGroupAndElementToFileName( sMetricsGroup, sElement );
|
||||
|
||||
map<RString, RString> &Cache = g_ThemePathCache[category];
|
||||
map<RString, PathInfo> &Cache = g_ThemePathCache[category];
|
||||
{
|
||||
map<RString, RString>::const_iterator i;
|
||||
map<RString, PathInfo>::const_iterator i;
|
||||
|
||||
i = Cache.find( sFileName );
|
||||
if( i != Cache.end() )
|
||||
return i->second;
|
||||
{
|
||||
out = i->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
try_element_again:
|
||||
|
||||
// search the current theme
|
||||
RString ret = GetPathToAndFallback( category, sMetricsGroup, sElement );
|
||||
if( !ret.empty() ) // we found something
|
||||
if( GetPathInfoToAndFallback( out, category, sMetricsGroup, sElement ) ) // we found something
|
||||
{
|
||||
Cache[sFileName] = ret;
|
||||
return ret;
|
||||
Cache[sFileName] = out;
|
||||
return true;
|
||||
}
|
||||
|
||||
if( bOptional )
|
||||
{
|
||||
Cache[sFileName] = "";
|
||||
return RString();
|
||||
Cache[sFileName] = PathInfo(); // clear cache entry
|
||||
return false;
|
||||
}
|
||||
|
||||
const RString &sCategory = ElementCategoryToString(category);
|
||||
@@ -740,8 +745,9 @@ try_element_again:
|
||||
if( sFileName == "_missing" )
|
||||
RageException::Throw( "\"_missing\" isn't present in \"%s%s\".", GetThemeDirFromName(SpecialFiles::BASE_THEME_NAME).c_str(), sCategory.c_str() );
|
||||
|
||||
Cache[sFileName] = GetPath( category, "", "_missing" );
|
||||
return Cache[sFileName];
|
||||
GetPathInfo( out, category, "", "_missing" );
|
||||
Cache[sFileName] = out;
|
||||
return true;
|
||||
case Dialog::abort:
|
||||
LOG->UserLog( "Theme element", sCategory + '/' + sFileName,
|
||||
"could not be found in \"%s\" or \"%s\".",
|
||||
@@ -757,6 +763,13 @@ try_element_again:
|
||||
FAIL_M( "" ); // Silence gcc 4.
|
||||
}
|
||||
|
||||
RString ThemeManager::GetPath( ElementCategory category, const RString &sMetricsGroup, const RString &sElement, bool bOptional )
|
||||
{
|
||||
PathInfo pi;
|
||||
GetPathInfo( pi, category, sMetricsGroup, sElement, bOptional );
|
||||
ASSERT( pi.sResolvedPath );
|
||||
return pi.sResolvedPath;
|
||||
}
|
||||
|
||||
RString ThemeManager::GetMetricsIniPath( const RString &sThemeName )
|
||||
{
|
||||
@@ -1123,6 +1136,15 @@ class LunaThemeManager: public Luna<ThemeManager>
|
||||
public:
|
||||
static int GetMetric( T* p, lua_State *L ) { p->PushMetric( L, SArg(1),SArg(2) ); return 1; }
|
||||
static int GetString( T* p, lua_State *L ) { lua_pushstring(L, p->GetString(SArg(1),SArg(2)) ); return 1; }
|
||||
static int GetPathInfoB( T* p, lua_State *L )
|
||||
{
|
||||
ThemeManager::PathInfo pi;
|
||||
p->GetPathInfo( pi, EC_BGANIMATIONS, SArg(1), SArg(2) );
|
||||
lua_pushstring(L, pi.sResolvedPath);
|
||||
lua_pushstring(L, pi.sMatchingMetricsGroup);
|
||||
lua_pushstring(L, pi.sMatchingElement);
|
||||
return 3;
|
||||
}
|
||||
static int GetPathF( T* p, lua_State *L ) { lua_pushstring(L, p->GetPathF(SArg(1),SArg(2)) ); return 1; }
|
||||
static int GetPathG( T* p, lua_State *L ) { lua_pushstring(L, p->GetPathG(SArg(1),SArg(2)) ); return 1; }
|
||||
static int GetPathB( T* p, lua_State *L ) { lua_pushstring(L, p->GetPathB(SArg(1),SArg(2)) ); return 1; }
|
||||
@@ -1133,6 +1155,7 @@ public:
|
||||
{
|
||||
ADD_METHOD( GetMetric );
|
||||
ADD_METHOD( GetString );
|
||||
ADD_METHOD( GetPathInfoB );
|
||||
ADD_METHOD( GetPathF );
|
||||
ADD_METHOD( GetPathG );
|
||||
ADD_METHOD( GetPathB );
|
||||
|
||||
@@ -55,9 +55,14 @@ public:
|
||||
|
||||
static void EvaluateString( RString &sText );
|
||||
|
||||
/* I renamed these for two reasons. The overload conflicts with the ones below:
|
||||
* GetPathToB( str, str ) was matching the ones below instead of these. It's also
|
||||
* easier to search for uses of obsolete functions if they have a different name. */
|
||||
struct PathInfo
|
||||
{
|
||||
RString sResolvedPath;
|
||||
RString sMatchingMetricsGroup;
|
||||
RString sMatchingElement;
|
||||
};
|
||||
|
||||
bool GetPathInfo( PathInfo &out, ElementCategory category, const RString &sMetricsGroup, const RString &sElement, bool bOptional=false );
|
||||
RString GetPath( ElementCategory category, const RString &sMetricsGroup, const RString &sElement, bool bOptional=false );
|
||||
RString GetPathB( const RString &sMetricsGroup, const RString &sElement, bool bOptional=false ) { return GetPath(EC_BGANIMATIONS,sMetricsGroup,sElement,bOptional); };
|
||||
RString GetPathF( const RString &sMetricsGroup, const RString &sElement, bool bOptional=false ) { return GetPath(EC_FONTS,sMetricsGroup,sElement,bOptional); };
|
||||
@@ -106,8 +111,9 @@ protected:
|
||||
void LoadThemeMetrics( const RString &sThemeName, const RString &sLanguage_ );
|
||||
RString GetMetricRaw( const IniFile &ini, const RString &sMetricsGroup, const RString &sValueName );
|
||||
bool GetMetricRawRecursive( const IniFile &ini, const RString &sMetricsGroup, const RString &sValueName, RString &sRet );
|
||||
RString GetPathToAndFallback( ElementCategory category, const RString &sMetricsGroup, const RString &sFile );
|
||||
RString GetPathToRaw( const RString &sThemeName, ElementCategory category, const RString &sMetricsGroup, const RString &sFile );
|
||||
|
||||
bool GetPathInfoToAndFallback( PathInfo &out, ElementCategory category, const RString &sMetricsGroup, const RString &sFile );
|
||||
bool GetPathInfoToRaw( PathInfo &out, const RString &sThemeName, ElementCategory category, const RString &sMetricsGroup, const RString &sFile );
|
||||
static RString GetThemeDirFromName( const RString &sThemeName );
|
||||
RString GetElementDir( const RString &sThemeName );
|
||||
static RString GetMetricsIniPath( const RString &sThemeName );
|
||||
|
||||
Reference in New Issue
Block a user