diff --git a/stepmania/src/ActorUtil.cpp b/stepmania/src/ActorUtil.cpp index 22f91eb182..8ed8873c4e 100644 --- a/stepmania/src/ActorUtil.cpp +++ b/stepmania/src/ActorUtil.cpp @@ -15,10 +15,36 @@ #include "XmlFile.h" #include "FontCharAliases.h" #include "LuaManager.h" +#include "MessageManager.h" #include "arch/Dialog/Dialog.h" +// Actor registration +static map *g_pmapRegistrees = NULL; + +void ActorUtil::Register( const CString& sClassName, CreateActorFn pfn ) +{ + if( g_pmapRegistrees == NULL ) + g_pmapRegistrees = new map; + + map::iterator iter = g_pmapRegistrees->find( sClassName ); + ASSERT_M( iter == g_pmapRegistrees->end(), ssprintf("Actor class '%s' already registered.", sClassName.c_str()) ); + + (*g_pmapRegistrees)[sClassName] = pfn; +} + +Actor* ActorUtil::Create( const CString& sClassName, const CString& sDir, const XNode* pNode ) +{ + map::iterator iter = g_pmapRegistrees->find( sClassName ); + ASSERT_M( iter != g_pmapRegistrees->end(), ssprintf("Actor '%s' is not registered.",sClassName.c_str()) ) + + CreateActorFn pfn = iter->second; + return pfn( sDir, pNode ); +} + + + Actor* ActorUtil::LoadFromActorFile( const CString& sAniDir, const XNode* pNode ) { ASSERT( pNode ); @@ -63,6 +89,10 @@ Actor* ActorUtil::LoadFromActorFile( const CString& sAniDir, const XNode* pNode p->LoadFromNode( sAniDir, pNode ); pActor = p; } + else if( sType == "GenreDisplay" ) + { + pActor = ActorUtil::Create( sType, sAniDir, pNode ); + } else if( sType == "ActorFrame" ) { ActorFrame *p = new ActorFrame; diff --git a/stepmania/src/ActorUtil.h b/stepmania/src/ActorUtil.h index 37157b8f6b..21f22636d7 100644 --- a/stepmania/src/ActorUtil.h +++ b/stepmania/src/ActorUtil.h @@ -1,4 +1,4 @@ -/* ActorScroller - ActorFrame that moves its children. */ +/* ActorUtil - Utility functions for creating and manipulating Actors. */ #ifndef ActorUtil_H #define ActorUtil_H @@ -8,9 +8,28 @@ struct XNode; +typedef Actor* (*CreateActorFn)(const CString& sDir, const XNode* pNode); + +// Each Actor class should have a REGISTER_ACTOR_CLASS in its CPP file. +#define REGISTER_ACTOR_CLASS( className ) \ + Actor* Create##className(const CString& sDir, const XNode* pNode) { \ + className *pRet = new className; \ + pRet->LoadFromNode(sDir, pNode); \ + return pRet; } \ + class Register##className { \ + public: \ + Register##className() { ActorUtil::Register(#className,Create##className); } \ + }; \ + static Register##className register##className; namespace ActorUtil { + // Every screen should register its class at program initialization. + void Register( const CString& sClassName, CreateActorFn pfn ); + Actor* Create( const CString& sClassName, const CString& sDir, const XNode* pNode ); + + + void SetXY( Actor& actor, const CString &sScreenName ); inline void SetXY( Actor* pActor, const CString &sScreenName ) { SetXY( *pActor, sScreenName ); } diff --git a/stepmania/src/AutoActor.h b/stepmania/src/AutoActor.h index d2406bf9cc..e12514bc94 100644 --- a/stepmania/src/AutoActor.h +++ b/stepmania/src/AutoActor.h @@ -1,4 +1,6 @@ -/* ActorScroller - ActorFrame that moves its children. */ +/* AutoActor - An Actor wrapper that creates the appropriate type of Actor. * + * from the supplied file name and automatically frees the Actor on + * destruction. */ #ifndef AutoActor_H #define AutoActor_H