dtCore::LibraryManager 类是个单利,在创建LibraryManager实例的时候,会自动加载系统内部的三个角色插件:dtActors、dtAudio、dtAnim。
如下:
static const std::string ACTOR_LIBRARY("dtActors");
static const std::string AUDIO_ACTOR_LIBRARY("dtAudio");
static const std::string ANIM_ACTOR_LIBRARY("dtAnim");
LibraryManager::LibraryManager()
{
mLogger = &dtUtil::Log::GetInstance("librarymanager.cpp");
mLogger->LogMessage(dtUtil::Log::LOG_INFO, __FUNCTION__, __LINE__, "Initializing actor library manager.");
LoadActorRegistry(ACTOR_LIBRARY);
//try to load some optional actor libraries that depend on optional
//external dependencies. If the file isn't found, don't try to load it.
LoadOptionalActorRegistry(AUDIO_ACTOR_LIBRARY);
LoadOptionalActorRegistry(ANIM_ACTOR_LIBRARY);
}
在 LibraryManager中含有 typedef std::map<dtCore::RefPtr<const ActorType>, ActorPluginRegistry*, ActorType::RefPtrComp> ActorTypeMap;的一个容器。记录着所有actors类型和其对应创建actor的ActorPluginRegistry
在void MapContentHandler::EndLibraryElement()函数中会调用
if (LibraryManager::GetInstance().GetRegistry(mLibName) == NULL)
{
LibraryManager::GetInstance().LoadActorRegistry(mLibName);//mLibName 比如是TutorialLibrary
}
dtUtil::LibrarySharingManager& lsm = dtUtil::LibrarySharingManager::GetInstance();
RegistryEntry newEntry;
try
{
newEntry.lib = lsm.LoadSharedLibrary(libName);
}
dtUtil::LibrarySharingManager::LibraryHandle::SYMBOL_ADDRESS createFn;
dtUtil::LibrarySharingManager::LibraryHandle::SYMBOL_ADDRESS destroyFn;
createFn = newEntry.lib->FindSymbol("CreatePluginRegistry");//就是在你兵力插件中的入口函数。
destroyFn = newEntry.lib->FindSymbol("DestroyPluginRegistry");
//Well we made it here so that means the plugin was loaded
//successfully and the create and destroy functions were found.
newEntry.createFn = (CreatePluginRegistryFn)createFn;
newEntry.destroyFn = (DestroyPluginRegistryFun)destroyFn;
newEntry.registry = newEntry.createFn();
if (!AddRegistryEntry(libName,newEntry))
{
msg.clear();
msg.str("");
msg << "Can't add Registry Entry: " << libName << " to Registry. " <<
"Possibly it might have been added already.";
throw dtCore::ProjectResourceErrorException( msg.str(), __FILE__, __LINE__);
}
bool LibraryManager::AddRegistryEntry(const std::string& libName, const RegistryEntry& entry)
{
//Finally we can actually add the new registry to the library manager.
//The map key is the system independent library name.
bool inserted = mRegistries.insert(std::make_pair(libName,entry)).second;
if (!inserted)
{
return false;
}
//Used to format log messages.
std::ostringstream msg;
//Second we map actor type to the registry that owns it.
std::vector<dtCore::RefPtr<const ActorType> > actorTypes;
entry.registry->RegisterActorTypes();//注册你的actorproxy到dtUtil::ObjectFactory中的objectTypeMap里面
entry.registry->GetSupportedActorTypes(actorTypes);从dtUtil::ObjectFactory中的objectTypeMap里面取出
dtCore::ActorPluginRegistry::ActorTypeReplacements replacements;
entry.registry->GetReplacementActorTypes(replacements);//主要提供一些向后兼容的能力
mReplacementActors.insert(mReplacementActors.end(), replacements.begin(), replacements.end());
int numUniqueActors = 0;
for (unsigned int i = 0; i < actorTypes.size(); ++i)
{
ActorTypeMapItor itor = mActors.find(dtCore::RefPtr<const ActorType>(actorTypes[i].get()));
if (itor != mActors.end())
{
msg.clear();
msg.str("");
msg << "Duplicate actor type " << *actorTypes[i] << " found. Will not be added.";
LOG_ERROR(msg.str());
}
else
{//把actortype 和 对应ActorPluginRegistry 绑定到一起
mActors.insert(std::make_pair(dtCore::RefPtr<const ActorType>(actorTypes[i].get()),entry.registry));
++numUniqueActors;
}
}
msg.clear();
msg.str("");
msg << "Loaded actor plugin registry. (Name: " << libName <<
", Number of Actors: " << numUniqueActors << ")";
LOG_INFO(msg.str());
return true;
}
------------------------------------------------------上面创建actor的准备工作完毕--------------------------------------------------------------------------------------
当读取map文件时,在函数 void MapContentHandler::ActorCharacters(const XMLCh* const chars)中
else if (topEl == MapXMLConstants::ACTOR_TYPE_ELEMENT)
{
mBaseActorObject = LibraryManager::GetInstance().CreateActor(*actorType).get();
}
dtCore::RefPtr<BaseActorObject> LibraryManager::CreateActor(const ActorType& actorType)
{
ActorPluginRegistry* apr = GetRegistryForType(actorType);//在上面的mActors中找到对应的actorPluginRegistry
if (mLogger->IsLevelEnabled(dtUtil::Log::LOG_DEBUG))
{
mLogger->LogMessage(dtUtil::Log::LOG_DEBUG, __FUNCTION__, __LINE__,
"Creating actor proxy of type \"%s\".",
actorType.GetFullName().c_str());
}
//Now we know which registry to use, so tell the registry to
//create the proxy object and return it.
dtCore::RefPtr<BaseActorObject> proxy = apr->CreateActor(actorType).get();//创建actor
return proxy;
}
然后转到 ActorPluginRegistry::CreateActor(const ActorType& type)中
dtCore::RefPtr<BaseActorObject> ActorPluginRegistry::CreateActor(const ActorType& type)
{
dtCore::RefPtr<BaseActorObject> proxy = mActorFactory->CreateObject(dtCore::RefPtr<const ActorType>(&type));
proxy->Init(type);
proxy->InitDefaults();
return proxy;
}
OK,到此为止,我们看到,当创建一个兵力的时候,在外部会调用其内部的Init,和InitDefaults()两个方法。
void GameActorProxy::Init(const dtCore::ActorType& actorType)
{
BaseClass::Init(actorType);
BuildInvokables();//创建可调用体
BuildActorComponents();
// The actor components are stored on the game actor, unlike the other stuff
GameActor &ga = GetGameActor();
ga.BuildActorComponents();
}
而在 BaseClass::Init(actorType);函数中
void BaseActorObject::Init(const dtCore::ActorType& actorType)
{
SetActorType(actorType);//设置角色类型
CreateDrawable();//创建角色
// These are called to make it validate that they aren't Null
// before proceeding.
GetActorType();
GetDrawable();
BuildPropertyMap();//创建属性(暴露外边的属性)
}