CGameObject* CFactory::InstantiatePrototype(const string &AProtoName, const string &AName /*= ""*/) { CXMLNode *xml = GetPrototypeXML(AProtoName); if (!xml) { Log("ERROR", "Can't create prototype instance: no such prototype: '%s'", AProtoName.c_str()); return NULL; } CGameObject *result = New<CGameObject>(AName); if (AName.empty()) result->SetName(AProtoName + itos(result->GetID())); result->Prototype = true; result->Deserialize(xml); SetRecursionLimit(AProtoName, from_string<int>(xml->SafeGetAttribute("RecursionLimit", "-1"))); TraversePrototypeNode(xml, result, result); result->FinalizeCreation(); Log("INFO", "Prototype INSTANTIATED: '%s', instance name: '%s'", AProtoName.c_str(), result->GetName().c_str()); return result; }
void CFactory::TraversePrototypeNode(CXMLNode *ANode, CGameObject *AObject, CGameObject *CurrentProto) { CGameObject *child; string NodeName; string ChildName; string LocalChildName; for (CXMLChildrenList::Iterator it = ANode->Children.Begin(); it != ANode->Children.End(); ++it) { if ((*it)->GetType() != CXMLNode::XML_NODE_TYPE_NORMAL) continue; NodeName = (*it)->GetName(); int recursionsLeft = GetRecursionsLeft(NodeName); if (recursionsLeft < 1) { if (recursionsLeft == -1) Log("ERROR", "Unlimited recursive reference of prototype '%s'", NodeName.c_str()); continue; } IncreaseUsedCount(NodeName); ChildName = (*it)->SafeGetAttribute("Name"); LocalChildName = (*it)->SafeGetAttribute("LocalName"); child = CreateGameObject(NodeName, ChildName, false); if (!child) { Log("ERROR", "Can't create object of class '%s' from prototype", NodeName.c_str()); continue; } CurrentProto->AddLocalName(LocalChildName, child); child->Deserialize(*it); AObject->Attach(child); if (!child->IsPrototype()) child->FinalizeCreation(); TraversePrototypeNode(*it, child, CurrentProto); DecreaseUsedCount(NodeName); } }
CGameObject* CFactory::CreateComponent(const string &AClassName, const string &AName /*= ""*/, bool AFinalizeCreation /*= true*/) { ComponentsContainer::iterator it = Components.find(AClassName); if (it == Components.end()) { Log("ERROR", "Can't create component: no such component class: '%s'", AClassName.c_str()); return NULL; } CGameObject *result = dynamic_cast<CGameObject *>((this->*(it->second))(AName)); if (AFinalizeCreation) result->FinalizeCreation(); return result; }
CGameObject* CGameObject::CloneTree(const string &ACloneName /*= ""*/, AlreadyClonedContainer *AlreadyCloned /*= NULL*/) const { CGameObject *result = Clone(ACloneName); map<CGameObject *, CGameObject *> *FirstAlreadyCloned = NULL; if (!AlreadyCloned) AlreadyCloned = FirstAlreadyCloned = new AlreadyClonedContainer; CGameObject *obj = NULL; for (LNOMType::const_iterator it = LocalNameObjectMapping.begin(); it != LocalNameObjectMapping.end(); ++it) { obj = it->second->CloneTree("", AlreadyCloned); result->LocalNameObjectMapping[it->first] = obj; (*AlreadyCloned)[it->second] = obj; } for (ChildrenConstIterator it = Children.begin(); it != Children.end(); ++it) { if (AlreadyCloned->count(*it)) obj = (*AlreadyCloned)[*it]; else obj = (*it)->CloneTree("", AlreadyCloned); result->Attach(obj); } if (IsPrototype()) result->FinalizeCreation(); if (FirstAlreadyCloned) delete FirstAlreadyCloned; return result; }