#include "precompiled.h" #include "ObjectEntry.h" #include "ObjectManager.h" #include "ObjectBase.h" #include "Model.h" #include "ModelDef.h" #include "CLogger.h" #include "MaterialManager.h" #include "MeshManager.h" #include "UnitManager.h" #include "Unit.h" #include "ps/Xeromyces.h" #include "ps/XMLWriter.h" #include "lib/res/vfs.h" #define LOG_CATEGORY "graphics" CObjectEntry::CObjectEntry(int type, CObjectBase* base) : m_Model(0), m_Type(type), m_Base(base) { m_IdleAnim=0; m_WalkAnim=0; m_DeathAnim=0; m_CorpseAnim=0; m_MeleeAnim=0; m_RangedAnim=0; } CObjectEntry::~CObjectEntry() { for (size_t i=0;iGetModelDef() : CModelDefPtr(); const char* modelfilename = m_ModelName.c_str(); // try and create a model CModelDefPtr modeldef (g_MeshManager.GetMesh(modelfilename)); if (!modeldef) { LOG(ERROR, LOG_CATEGORY, "CObjectEntry::BuildModel(): Model %s failed to load", modelfilename); return false; } // delete old model, create new delete m_Model; m_Model=new CModel; m_Model->SetTexture((const char*) m_TextureName); m_Model->SetMaterial(g_MaterialManager.LoadMaterial(m_Base->m_Material)); 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) { const char* animfilename = m_Animations[t].m_FileName.c_str(); m_Animations[t].m_AnimData = m_Model->BuildAnimation(animfilename,m_Animations[t].m_Speed); CStr AnimNameLC = m_Animations[t].m_AnimName.LowerCase(); if (AnimNameLC == "idle") m_IdleAnim = m_Animations[t].m_AnimData; else if (AnimNameLC == "walk") m_WalkAnim = m_Animations[t].m_AnimData; else if (AnimNameLC == "attack") m_MeleeAnim = m_Animations[t].m_AnimData; else if (AnimNameLC == "death") m_DeathAnim = m_Animations[t].m_AnimData; else if (AnimNameLC == "decay") m_CorpseAnim = m_Animations[t].m_AnimData; //else // debug_out("Invalid animation name '%s'\n", (const char*)AnimNameLC); } else { // FIXME, RC - don't store invalid animations (possible?) m_Animations[t].m_AnimData=0; } } // start up idling if (! m_Model->SetAnimation(m_IdleAnim)) LOG(ERROR, LOG_CATEGORY, "Failed to set idle animation in model \"%s\"", modelfilename); // 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); } else { LOG(ERROR, LOG_CATEGORY, "Failed to build prop model \"%s\" on actor \"%s\"",(const char*) m_Base->m_Name,(const char*) prop.m_ModelName); } } } else { LOG(ERROR, LOG_CATEGORY, "Failed to matching prop point called \"%s\" in model \"%s\"", (const char*)prop.m_PropPointName, modelfilename); } } // setup flags if (m_Base->m_Properties.m_CastShadows) { m_Model->SetFlags(m_Model->GetFlags()|MODELFLAG_CASTSHADOWS); } // replace any units using old model to now use new model; also reprop models, if necessary // FIXME, RC - ugh, doesn't recurse correctly through props const std::vector& units=g_UnitMan.GetUnits(); for (uint i=0;iGetModel(); if (unitmodel->GetModelDef()==oldmodeldef) { unitmodel->InitModel(m_Model->GetModelDef()); unitmodel->SetFlags(m_Model->GetFlags()); const std::vector& newprops=m_Model->GetProps(); for (uint j=0;jAddProp(newprops[j].m_Point,newprops[j].m_Model->Clone()); } } std::vector& mdlprops=unitmodel->GetProps(); for (uint j=0;jGetModelDef()==oldmodeldef) { delete prop.m_Model; prop.m_Model=m_Model->Clone(); } } } } return true; } void CObjectEntry::ApplyRandomVariant(CObjectBase::variation_key& vars) { CStr chosenTexture; CStr chosenModel; std::map chosenProps; std::map chosenAnims; CObjectBase::variation_key::const_iterator vars_it = vars.begin(); for (std::vector >::iterator grp = m_Base->m_Variants.begin(); grp != m_Base->m_Variants.end(); ++grp) { CObjectBase::Variant& var (grp->at(*(vars_it++))); if (var.m_TextureFilename.Length()) chosenTexture = var.m_TextureFilename; if (var.m_ModelFilename.Length()) chosenModel = var.m_ModelFilename; for (std::vector::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it) chosenProps[it->m_PropPointName] = *it; for (std::vector::iterator it = var.m_Anims.begin(); it != var.m_Anims.end(); ++it) chosenAnims[it->m_AnimName] = *it; } m_TextureName = chosenTexture; m_ModelName = chosenModel; for (std::map::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it) m_Props.push_back(it->second); for (std::map::iterator it = chosenAnims.begin(); it != chosenAnims.end(); ++it) m_Animations.push_back(it->second); } 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 ); } CObjectBase::Prop* CObjectEntry::FindProp(const char* proppointname) { for (size_t i=0;i