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); }
在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;
}
当读取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();//创建属性(暴露外边的属性) }