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); } }