#include "precompiled.h" #include "ObjectEntry.h" #include "ObjectManager.h" #include "Model.h" #include "ModelDef.h" #include "CLogger.h" #include "UnitManager.h" #include "XML.h" // automatically use namespace .. XERCES_CPP_NAMESPACE_USE CObjectEntry::CObjectEntry(int type) : m_Model(0), m_Type(type) { m_IdleAnim=0; m_WalkAnim=0; m_DeathAnim=0; m_MeleeAnim=0; m_RangedAnim=0; } CObjectEntry::~CObjectEntry() { for (size_t i=0;iGetModelDef() : 0; // build filename CStr modelfilename("mods/official/"); modelfilename+=m_ModelName; // try and create a model CModelDef* modeldef; try { modeldef=CModelDef::Load((const char*) modelfilename); } catch (...) { LOG(ERROR, "CObjectEntry::BuildModel(): Model %s failed to load\n", modelfilename.c_str()); return false; } // create new Model m_Model=new CModel; m_Model->SetTexture((const char*) m_TextureName); m_Model->InitModel(modeldef); // calculate initial object space bounds, based on vertex positions m_Model->CalcObjectBounds(); // load animations for( uint t = 0; t < m_Animations.size(); t++ ) { if( m_Animations[t].m_FileName.Length() > 0 ) { CStr animfilename( "mods/official/" ); animfilename += m_Animations[t].m_FileName; m_Animations[t].m_AnimData = m_Model->BuildAnimation((const char*) animfilename,m_Animations[t].m_Speed); if( m_Animations[t].m_AnimName.LowerCase() == CStr( "idle" ) ) m_IdleAnim = m_Animations[t].m_AnimData; if( m_Animations[t].m_AnimName.LowerCase() == CStr( "walk" ) ) m_WalkAnim = m_Animations[t].m_AnimData; } else { // FIXME, RC - don't store invalid animations m_Animations[t].m_AnimData=0; } } // start up idling m_Model->SetAnimation( m_IdleAnim ); // build props - TODO, RC - need to fix up bounds here for (uint p=0;pFindPropPoint((const char*) prop.m_PropPointName); if (proppoint) { CObjectEntry* oe=g_ObjMan.FindObject(prop.m_ModelName); if (oe) { // try and build model if we haven't already got it if (!oe->m_Model) oe->BuildModel(); if (oe->m_Model) { CModel* propmodel=oe->m_Model->Clone(); m_Model->AddProp(proppoint,propmodel); if (oe->m_WalkAnim) propmodel->SetAnimation(oe->m_WalkAnim); } } } } // build world space bounds m_Model->CalcBounds(); // replace any units using old model to now use new model; also reprop models, if necessary const std::vector& units=g_UnitMan.GetUnits(); for (uint i=0;iGetModel(); if (unitmodel->GetModelDef()==oldmodel) { unitmodel->InitModel(m_Model->GetModelDef()); const std::vector& newprops=m_Model->GetProps(); for (uint j=0;jAddProp(newprops[j].m_Point,newprops[j].m_Model->Clone()); } } } // and were done with the old model .. delete oldmodel; return true; } CSkeletonAnim* CObjectEntry::GetNamedAnimation( CStr animationName ) { for( uint t = 0; t < m_Animations.size(); t++ ) { if( m_Animations[t].m_AnimName == animationName ) return( m_Animations[t].m_AnimData ); } return( NULL ); } bool CObjectEntry::Load(const char* filename) { bool parseOK = false; // Initialize XML library XMLPlatformUtils::Initialize(); { XMLCh* attachpointtext=XMLString::transcode("attachpoint"); XMLCh* modeltext=XMLString::transcode("model"); XMLCh* nametext=XMLString::transcode("name"); XMLCh* filetext=XMLString::transcode("file"); XMLCh* speedtext=XMLString::transcode("speed"); // Create parser instance XercesDOMParser *parser = new XercesDOMParser(); // Setup parser parser->setValidationScheme(XercesDOMParser::Val_Auto); parser->setDoNamespaces(false); parser->setDoSchema(false); parser->setCreateEntityReferenceNodes(false); // Set customized error handler CXercesErrorHandler *errorHandler = new CXercesErrorHandler(); parser->setErrorHandler(errorHandler); CVFSEntityResolver *entityResolver = new CVFSEntityResolver(filename); parser->setEntityResolver(entityResolver); // Push the CLogger to mark it's reading this file. // Get main node CVFSInputSource source; parseOK = source.OpenFile(filename) == 0; if (parseOK) { // Parse file parser->parse(source); // Check how many errors parseOK = parser->getErrorCount() == 0; } if (parseOK) { // parsed successfully - grab our data DOMDocument *doc = parser->getDocument(); DOMElement *element = doc->getDocumentElement(); // root_name should be Object CStr root_name = XMLTranscode( element->getNodeName() ); // should have at least 3 children - Name, ModelName and TextureName DOMNodeList *children = element->getChildNodes(); int numChildren=children->getLength(); for (int i=0; iitem(i); // A child element if (child->getNodeType() == DOMNode::ELEMENT_NODE) { // First get element and not node DOMElement *child_element = (DOMElement*)child; CStr element_name = XMLTranscode( child_element->getNodeName() ); DOMNode *value_node= child_element->getChildNodes()->item(0); CStr element_value=value_node ? XMLTranscode(value_node->getNodeValue()) : ""; if (element_name==CStr("Name")) { m_Name=element_value; } else if (element_name==CStr("ModelName")) { m_ModelName=element_value; } else if (element_name==CStr("TextureName")) { m_TextureName=element_value; } else if (element_name==CStr("Animations")) { DOMNodeList* animations=(DOMNodeList*) child_element->getChildNodes(); for (uint j=0; jgetLength(); ++j) { DOMElement *anim_element = (DOMElement*) animations->item(j); CStr element_name = XMLTranscode( anim_element->getNodeName() ); DOMNamedNodeMap* attributes=anim_element->getAttributes(); if (attributes) { Anim anim; DOMNode *nameattr=attributes->getNamedItem(nametext); anim.m_AnimName=XMLTranscode(nameattr->getChildNodes()->item(0)->getNodeValue()); DOMNode *fileattr=attributes->getNamedItem(filetext); anim.m_FileName=XMLTranscode(fileattr->getChildNodes()->item(0)->getNodeValue()); DOMNode *speedattr=attributes->getNamedItem(speedtext); CStr speedstr=XMLTranscode(speedattr->getChildNodes()->item(0)->getNodeValue()); anim.m_Speed=float(atoi((const char*) speedstr))/100.0f; if (anim.m_Speed<=0) anim.m_Speed=1.0f; m_Animations.push_back(anim); } } } else if (element_name==CStr("Props")) { DOMNodeList* props=(DOMNodeList*) child_element->getChildNodes(); for (uint j=0; jgetLength(); ++j) { DOMElement *prop_element = (DOMElement*) props->item(j); CStr element_name = XMLTranscode( prop_element->getNodeName() ); DOMNamedNodeMap* attributes=prop_element->getAttributes(); if (attributes) { Prop prop; DOMNode *nameattr=attributes->getNamedItem(attachpointtext); prop.m_PropPointName=XMLTranscode(nameattr->getChildNodes()->item(0)->getNodeValue()); DOMNode *modelattr=attributes->getNamedItem(modeltext); prop.m_ModelName=XMLString::transcode(modelattr->getChildNodes()->item(0)->getNodeValue()); m_Props.push_back(prop); } } } } } } XMLString::release(&attachpointtext); XMLString::release(&modeltext); XMLString::release(&nametext); XMLString::release(&filetext); XMLString::release(&speedtext); delete parser; delete errorHandler; delete entityResolver; } XMLPlatformUtils::Terminate(); return parseOK; } bool CObjectEntry::Save(const char* filename) { FILE* fp=fopen(filename,"w"); if (!fp) return false; // write XML header fprintf(fp,"\n\n"); fprintf(fp,"\n\n"); // write the object itself fprintf(fp,"\n"); fprintf(fp,"\n"); fprintf(fp,"\t%s\n",(const char*) m_Name); fprintf(fp,"\t%s\n",(const char*) m_ModelName); fprintf(fp,"\t%s\n",(const char*) m_TextureName); if (m_Animations.size()>0) { fprintf(fp,"\t\n"); for (uint i=0;i \n",(const char*) m_Animations[i].m_AnimName,(const char*) m_Animations[i].m_FileName); } fprintf(fp,"\t\n"); } fprintf(fp,"\n"); fclose(fp); return true; }