Mostly complete support for random actors
This was SVN commit r2021.
This commit is contained in:
parent
1019dffdc3
commit
9e8d3d6518
@ -5,6 +5,7 @@
|
||||
#include "UnitManager.h"
|
||||
#include "Unit.h"
|
||||
#include "ObjectManager.h"
|
||||
#include "ObjectBase.h"
|
||||
#include "Model.h"
|
||||
#include "Terrain.h"
|
||||
#include "LightEnv.h"
|
||||
@ -155,7 +156,7 @@ void CMapWriter::EnumObjects(CUnitManager *pUnitMan,
|
||||
|
||||
// now build outgoing objectTypes array
|
||||
for (uint i=0;i<(uint)objectsInUse.size();i++) {
|
||||
objectTypes.push_back(objectsInUse[i]->m_Name);
|
||||
objectTypes.push_back(objectsInUse[i]->m_Base->m_Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,7 +366,7 @@ CModel* CModel::Clone() const
|
||||
clone->m_ObjectBounds=m_ObjectBounds;
|
||||
clone->InitModel(m_pModelDef);
|
||||
clone->SetTexture(m_Texture);
|
||||
clone->SetMaterial(m_Material);
|
||||
clone->SetMaterial(m_Material);
|
||||
clone->SetAnimation(m_Anim);
|
||||
clone->SetPlayerID(m_PlayerID);
|
||||
clone->SetFlags(m_Flags);
|
||||
@ -404,8 +404,8 @@ void CModel::SetTransform(const CMatrix3D& transform)
|
||||
|
||||
void CModel::SetMaterial(const CMaterial &material)
|
||||
{
|
||||
m_Material = material;
|
||||
if(m_Material.GetTexture().Trim(PS_TRIM_BOTH).Length() > 0)
|
||||
{
|
||||
}
|
||||
m_Material = material;
|
||||
if(m_Material.GetTexture().Trim(PS_TRIM_BOTH).Length() > 0)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ObjectEntry.h"
|
||||
#include "ObjectManager.h"
|
||||
#include "ObjectBase.h"
|
||||
#include "Model.h"
|
||||
#include "ModelDef.h"
|
||||
#include "CLogger.h"
|
||||
@ -19,22 +20,8 @@
|
||||
#define LOG_CATEGORY "graphics"
|
||||
|
||||
|
||||
|
||||
|
||||
struct Variant
|
||||
{
|
||||
CStr m_VariantName;
|
||||
int m_Frequency;
|
||||
CStr m_ModelFilename;
|
||||
CStr m_TextureFilename;
|
||||
|
||||
std::vector<CObjectEntry::Anim> m_Anims;
|
||||
std::vector<CObjectEntry::Prop> m_Props;
|
||||
};
|
||||
|
||||
|
||||
|
||||
CObjectEntry::CObjectEntry(int type) : m_Model(0), m_Type(type)
|
||||
CObjectEntry::CObjectEntry(int type, CObjectBase* base)
|
||||
: m_Model(0), m_Type(type), m_Base(base)
|
||||
{
|
||||
m_IdleAnim=0;
|
||||
m_WalkAnim=0;
|
||||
@ -42,8 +29,6 @@ CObjectEntry::CObjectEntry(int type) : m_Model(0), m_Type(type)
|
||||
m_CorpseAnim=0;
|
||||
m_MeleeAnim=0;
|
||||
m_RangedAnim=0;
|
||||
m_Properties.m_CastShadows=true;
|
||||
m_Properties.m_AutoFlatten=false;
|
||||
}
|
||||
|
||||
CObjectEntry::~CObjectEntry()
|
||||
@ -82,7 +67,7 @@ bool CObjectEntry::BuildModel()
|
||||
delete m_Model;
|
||||
m_Model=new CModel;
|
||||
m_Model->SetTexture((const char*) m_TextureName);
|
||||
m_Model->SetMaterial(g_MaterialManager.LoadMaterial((const char *)m_Material));
|
||||
m_Model->SetMaterial(g_MaterialManager.LoadMaterial(m_Base->m_Material));
|
||||
m_Model->InitModel(modeldef);
|
||||
|
||||
// calculate initial object space bounds, based on vertex positions
|
||||
@ -127,7 +112,7 @@ bool CObjectEntry::BuildModel()
|
||||
|
||||
// build props - TODO, RC - need to fix up bounds here
|
||||
for (uint p=0;p<m_Props.size();p++) {
|
||||
const Prop& prop=m_Props[p];
|
||||
const CObjectBase::Prop& prop=m_Props[p];
|
||||
SPropPoint* proppoint=modeldef->FindPropPoint((const char*) prop.m_PropPointName);
|
||||
if (proppoint) {
|
||||
CObjectEntry* oe=g_ObjMan.FindObject(prop.m_ModelName);
|
||||
@ -139,7 +124,7 @@ bool CObjectEntry::BuildModel()
|
||||
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_Name,(const char*) prop.m_ModelName);
|
||||
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 {
|
||||
@ -148,7 +133,7 @@ bool CObjectEntry::BuildModel()
|
||||
}
|
||||
|
||||
// setup flags
|
||||
if (m_Properties.m_CastShadows) {
|
||||
if (m_Base->m_Properties.m_CastShadows) {
|
||||
m_Model->SetFlags(m_Model->GetFlags()|MODELFLAG_CASTSHADOWS);
|
||||
}
|
||||
|
||||
@ -182,6 +167,45 @@ bool CObjectEntry::BuildModel()
|
||||
return true;
|
||||
}
|
||||
|
||||
void CObjectEntry::ApplyRandomVariant(CObjectBase::variation_key& vars)
|
||||
{
|
||||
CStr chosenTexture;
|
||||
CStr chosenModel;
|
||||
std::map<CStr, CObjectBase::Prop> chosenProps;
|
||||
std::map<CStr, CObjectBase::Anim> chosenAnims;
|
||||
|
||||
CObjectBase::variation_key::const_iterator vars_it = vars.begin();
|
||||
|
||||
for (std::vector<std::vector<CObjectBase::Variant> >::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<CObjectBase::Prop>::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it)
|
||||
chosenProps[it->m_PropPointName] = *it;
|
||||
|
||||
for (std::vector<CObjectBase::Anim>::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<CStr, CObjectBase::Prop>::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it)
|
||||
m_Props.push_back(it->second);
|
||||
|
||||
for (std::map<CStr, CObjectBase::Anim>::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++ )
|
||||
@ -192,350 +216,8 @@ CSkeletonAnim* CObjectEntry::GetNamedAnimation( CStr animationName )
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
bool CObjectEntry::Load(const char* filename)
|
||||
{
|
||||
//static int x=0; debug_out("load %s %d\n", filename, ++x);
|
||||
|
||||
CXeromyces XeroFile;
|
||||
if (XeroFile.Load(filename) != PSRETURN_OK)
|
||||
return false;
|
||||
|
||||
XMBElement root = XeroFile.getRoot();
|
||||
|
||||
if (root.getNodeName() == XeroFile.getElementID("object"))
|
||||
{
|
||||
//// Old-format actor file ////
|
||||
|
||||
// Define all the elements and attributes used in the XML file
|
||||
#define EL(x) int el_##x = XeroFile.getElementID(#x)
|
||||
#define AT(x) int at_##x = XeroFile.getAttributeID(#x)
|
||||
EL(name);
|
||||
EL(modelname);
|
||||
EL(texturename);
|
||||
EL(material);
|
||||
EL(animations);
|
||||
EL(props);
|
||||
EL(properties);
|
||||
AT(attachpoint);
|
||||
AT(model);
|
||||
AT(name);
|
||||
AT(file);
|
||||
AT(speed);
|
||||
AT(autoflatten);
|
||||
AT(castshadows);
|
||||
#undef AT
|
||||
#undef EL
|
||||
|
||||
XERO_ITER_EL(root, child)
|
||||
{
|
||||
int element_name = child.getNodeName();
|
||||
CStr element_value (child.getText());
|
||||
|
||||
if (element_name == el_name)
|
||||
m_Name=element_value;
|
||||
|
||||
else if (element_name == el_modelname)
|
||||
m_ModelName=element_value;
|
||||
|
||||
else if (element_name == el_texturename)
|
||||
m_TextureName=element_value;
|
||||
|
||||
else if(element_name == el_material)
|
||||
m_Material = element_value;
|
||||
|
||||
else if (element_name == el_properties)
|
||||
{
|
||||
|
||||
XERO_ITER_ATTR(child, attrib)
|
||||
{
|
||||
int attrib_name = attrib.Name;
|
||||
|
||||
if (attrib_name == at_autoflatten)
|
||||
{
|
||||
CStr str (attrib.Value);
|
||||
m_Properties.m_AutoFlatten=str.ToInt() ? true : false;
|
||||
}
|
||||
else if (attrib_name == at_castshadows)
|
||||
{
|
||||
CStr str = (attrib.Value);
|
||||
m_Properties.m_CastShadows=str.ToInt() ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (element_name == el_animations)
|
||||
{
|
||||
XERO_ITER_EL(child, anim_element)
|
||||
{
|
||||
XMBAttributeList attributes = anim_element.getAttributes();
|
||||
|
||||
if (attributes.Count)
|
||||
{
|
||||
Anim anim;
|
||||
|
||||
anim.m_AnimName = attributes.getNamedItem(at_name);
|
||||
anim.m_FileName = attributes.getNamedItem(at_file);
|
||||
CStr speedstr = attributes.getNamedItem(at_speed);
|
||||
|
||||
anim.m_Speed=float(speedstr.ToInt())/100.0f;
|
||||
if (anim.m_Speed<=0.0) anim.m_Speed=1.0f;
|
||||
|
||||
m_Animations.push_back(anim);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element_name == el_props)
|
||||
{
|
||||
XERO_ITER_EL(child, prop_element)
|
||||
{
|
||||
|
||||
XMBAttributeList attributes = prop_element.getAttributes();
|
||||
if (attributes.Count)
|
||||
{
|
||||
Prop prop;
|
||||
|
||||
prop.m_PropPointName = attributes.getNamedItem(at_attachpoint);
|
||||
prop.m_ModelName = attributes.getNamedItem(at_model);
|
||||
|
||||
m_Props.push_back(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (root.getNodeName() == XeroFile.getElementID("actor"))
|
||||
{
|
||||
//// New-format actor file ////
|
||||
|
||||
// Use the filename for the model's name
|
||||
m_Name = CStr(filename).AfterLast("/").BeforeLast(".xml");
|
||||
|
||||
// Define all the elements used in the XML file
|
||||
#define EL(x) int el_##x = XeroFile.getElementID(#x)
|
||||
EL(castshadow);
|
||||
EL(material);
|
||||
EL(group);
|
||||
EL(variant);
|
||||
EL(animations);
|
||||
EL(animation);
|
||||
EL(file);
|
||||
EL(name);
|
||||
EL(speed);
|
||||
EL(props);
|
||||
EL(prop);
|
||||
EL(attachpoint);
|
||||
EL(model);
|
||||
EL(frequency);
|
||||
EL(mesh);
|
||||
EL(texture);
|
||||
#undef EL
|
||||
|
||||
std::vector< std::vector<Variant> > actorVariants;
|
||||
|
||||
// (This code is rather worryingly verbose...)
|
||||
|
||||
XERO_ITER_EL(root, child)
|
||||
{
|
||||
int element_name = child.getNodeName();
|
||||
CStr element_value (child.getText());
|
||||
|
||||
if (element_name == el_group)
|
||||
{
|
||||
actorVariants.resize(actorVariants.size()+1);
|
||||
|
||||
XERO_ITER_EL(child, variant)
|
||||
{
|
||||
actorVariants.back().resize(actorVariants.back().size()+1);
|
||||
|
||||
XERO_ITER_EL(variant, option)
|
||||
{
|
||||
int option_name = option.getNodeName();
|
||||
|
||||
if (option_name == el_name)
|
||||
actorVariants.back().back().m_VariantName = option.getText();
|
||||
|
||||
else if (option_name == el_frequency)
|
||||
actorVariants.back().back().m_Frequency = CStr(option.getText()).ToInt();
|
||||
|
||||
else if (option_name == el_mesh)
|
||||
actorVariants.back().back().m_ModelFilename = option.getText();
|
||||
|
||||
else if (option_name == el_texture)
|
||||
actorVariants.back().back().m_TextureFilename = option.getText();
|
||||
|
||||
else if (option_name == el_animations)
|
||||
{
|
||||
XERO_ITER_EL(option, anim_element)
|
||||
{
|
||||
Anim anim;
|
||||
|
||||
XERO_ITER_EL(anim_element, ae)
|
||||
{
|
||||
int ae_name = ae.getNodeName();
|
||||
if (ae_name == el_name)
|
||||
anim.m_AnimName = ae.getText();
|
||||
else if (ae_name == el_file)
|
||||
anim.m_FileName = ae.getText();
|
||||
else if (ae_name == el_speed)
|
||||
{
|
||||
anim.m_Speed = CStr(ae.getText()).ToInt() / 100.f;
|
||||
if (anim.m_Speed <= 0.0) anim.m_Speed = 1.0f;
|
||||
}
|
||||
else
|
||||
; // unrecognised element
|
||||
}
|
||||
actorVariants.back().back().m_Anims.push_back(anim);
|
||||
}
|
||||
|
||||
}
|
||||
else if (option_name == el_props)
|
||||
{
|
||||
XERO_ITER_EL(option, prop_element)
|
||||
{
|
||||
Prop prop;
|
||||
|
||||
XERO_ITER_EL(prop_element, pe)
|
||||
{
|
||||
int pe_name = pe.getNodeName();
|
||||
if (pe_name == el_attachpoint)
|
||||
prop.m_PropPointName = pe.getText();
|
||||
else if (pe_name == el_model)
|
||||
prop.m_ModelName = pe.getText();
|
||||
else
|
||||
; // unrecognised element
|
||||
}
|
||||
actorVariants.back().back().m_Props.push_back(prop);
|
||||
}
|
||||
}
|
||||
else
|
||||
; // unrecognised element
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element_name == el_material)
|
||||
{
|
||||
m_Material = child.getText();
|
||||
}
|
||||
else
|
||||
; // unrecognised element
|
||||
}
|
||||
|
||||
// Fill in this actor with the appropriate variant choices:
|
||||
|
||||
CStr chosenTexture;
|
||||
CStr chosenModel;
|
||||
std::map<CStr, Prop> chosenProps;
|
||||
std::map<CStr, Anim> chosenAnims;
|
||||
|
||||
for (std::vector<std::vector<Variant> >::iterator grp = actorVariants.begin();
|
||||
grp != actorVariants.end();
|
||||
++grp)
|
||||
{
|
||||
// TODO: choose correctly
|
||||
Variant& var ((*grp)[0]);
|
||||
|
||||
if (var.m_TextureFilename.Length())
|
||||
chosenTexture = var.m_TextureFilename;
|
||||
|
||||
if (var.m_ModelFilename.Length())
|
||||
chosenModel = var.m_ModelFilename;
|
||||
|
||||
for (std::vector<Prop>::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it)
|
||||
chosenProps[it->m_PropPointName] = *it;
|
||||
|
||||
for (std::vector<Anim>::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<CStr, Prop>::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it)
|
||||
m_Props.push_back(it->second);
|
||||
|
||||
for (std::map<CStr, Anim>::iterator it = chosenAnims.begin(); it != chosenAnims.end(); ++it)
|
||||
m_Animations.push_back(it->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(ERROR, LOG_CATEGORY, "Invalid actor format (unrecognised root element '%s')", XeroFile.getElementString(root.getNodeName()));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool CObjectEntry::Save(const char* filename)
|
||||
{
|
||||
Handle h = vfs_open(filename, FILE_WRITE|FILE_NO_AIO);
|
||||
if (h <= 0)
|
||||
{
|
||||
debug_warn("actor open failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
XML_Start("iso-8859-1");
|
||||
XML_Doctype("Object", "/art/actors/object.dtd");
|
||||
|
||||
XML_Comment("File automatically generated by ScEd");
|
||||
|
||||
{
|
||||
XML_Element("Object");
|
||||
|
||||
XML_Setting("Name", m_Name);
|
||||
XML_Setting("ModelName", m_ModelName);
|
||||
XML_Setting("TextureName", m_TextureName);
|
||||
|
||||
if(m_Material.Trim(PS_TRIM_BOTH).Length())
|
||||
XML_Setting("Material", m_Material);
|
||||
|
||||
{
|
||||
XML_Element("Properties");
|
||||
XML_Attribute("autoflatten", m_Properties.m_AutoFlatten ? 1 : 0);
|
||||
XML_Attribute("castshadows", m_Properties.m_CastShadows ? 1 : 0);
|
||||
}
|
||||
|
||||
if (m_Animations.size()>0)
|
||||
{
|
||||
XML_Element("Animations");
|
||||
|
||||
for (uint i=0;i<m_Animations.size();i++)
|
||||
{
|
||||
XML_Element("Animation");
|
||||
XML_Attribute("name", m_Animations[i].m_AnimName);
|
||||
XML_Attribute("file", m_Animations[i].m_FileName);
|
||||
XML_Attribute("speed", int(m_Animations[i].m_Speed*100));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Props.size()>0)
|
||||
{
|
||||
XML_Element("Props");
|
||||
|
||||
for (uint i=0;i<m_Props.size();i++)
|
||||
{
|
||||
XML_Element("Prop");
|
||||
XML_Attribute("attachpoint", m_Props[i].m_PropPointName);
|
||||
XML_Attribute("model", m_Props[i].m_ModelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! XML_StoreVFS(h))
|
||||
{
|
||||
// Error occurred while saving data
|
||||
debug_warn("actor save failed");
|
||||
vfs_close(h);
|
||||
return false;
|
||||
}
|
||||
|
||||
vfs_close(h);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
CObjectEntry::Prop* CObjectEntry::FindProp(const char* proppointname)
|
||||
CObjectBase::Prop* CObjectEntry::FindProp(const char* proppointname)
|
||||
{
|
||||
for (size_t i=0;i<m_Props.size();i++) {
|
||||
if (strcmp(proppointname,m_Props[i].m_PropPointName)==0) return &m_Props[i];
|
||||
@ -543,47 +225,3 @@ CObjectEntry::Prop* CObjectEntry::FindProp(const char* proppointname)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Remove this, once all the actors are renamed properly
|
||||
bool CObjectEntry::LoadName(const CStr& filename, CStr& out)
|
||||
{
|
||||
CXeromyces XeroFile;
|
||||
if (XeroFile.Load(filename) != PSRETURN_OK)
|
||||
return false;
|
||||
|
||||
XMBElement root = XeroFile.getRoot();
|
||||
|
||||
if (root.getNodeName() == XeroFile.getElementID("object"))
|
||||
{
|
||||
//// Old-format actor file ////
|
||||
|
||||
#define EL(x) int el_##x = XeroFile.getElementID(#x)
|
||||
EL(name);
|
||||
#undef EL
|
||||
|
||||
XERO_ITER_EL(root, child)
|
||||
{
|
||||
if (child.getNodeName() == el_name)
|
||||
{
|
||||
out = child.getText();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
LOG(ERROR, LOG_CATEGORY, "Invalid actor format (couldn't find 'name')");
|
||||
return false;
|
||||
}
|
||||
else if (root.getNodeName() == XeroFile.getElementID("actor"))
|
||||
{
|
||||
//// New-format actor file ////
|
||||
|
||||
// Use the filename for the model's name
|
||||
out = CStr(filename).AfterLast("/").BeforeLast(".xml");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(ERROR, LOG_CATEGORY, "Invalid actor format (unrecognised root element '%s')", XeroFile.getElementString(root.getNodeName()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -6,55 +6,30 @@ class CSkeletonAnim;
|
||||
|
||||
#include <vector>
|
||||
#include "CStr.h"
|
||||
#include "ObjectBase.h"
|
||||
|
||||
class CObjectEntry
|
||||
{
|
||||
public:
|
||||
struct Anim {
|
||||
// constructor
|
||||
Anim() : m_Speed(1), m_AnimData(0) {}
|
||||
|
||||
// name of the animation - "Idle", "Run", etc
|
||||
CStr m_AnimName;
|
||||
// filename of the animation - manidle.psa, manrun.psa, etc
|
||||
CStr m_FileName;
|
||||
// animation speed, as specified in XML actor file
|
||||
float m_Speed;
|
||||
// the animation data, specific to the this model
|
||||
CSkeletonAnim* m_AnimData;
|
||||
};
|
||||
|
||||
struct Prop {
|
||||
// name of the prop point to attach to - "Prop01", "Prop02", "Head", "LeftHand", etc ..
|
||||
CStr m_PropPointName;
|
||||
// name of the model file - art/actors/props/sword.xml or whatever
|
||||
CStr m_ModelName;
|
||||
};
|
||||
|
||||
public:
|
||||
CObjectEntry(int type);
|
||||
CObjectEntry(int type, CObjectBase* base);
|
||||
~CObjectEntry();
|
||||
|
||||
bool BuildModel();
|
||||
|
||||
bool Load(const char* filename);
|
||||
bool Save(const char* filename);
|
||||
void ApplyRandomVariant(CObjectBase::variation_key& var);
|
||||
|
||||
// TODO: Remove this, once all the actors are renamed properly
|
||||
static bool LoadName(const CStr& filename, CStr& out);
|
||||
// base actor. Contains all the things that don't change between
|
||||
// different variations of the actor.
|
||||
CObjectBase* m_Base;
|
||||
|
||||
Prop* FindProp(const char* proppointname);
|
||||
CObjectBase::Prop* FindProp(const char* proppointname);
|
||||
|
||||
// object name
|
||||
CStr m_Name;
|
||||
// file name
|
||||
CStr m_FileName;
|
||||
// texture name
|
||||
CStr m_TextureName;
|
||||
// model name
|
||||
CStr m_ModelName;
|
||||
// list of valid animations for this object
|
||||
std::vector<Anim> m_Animations;
|
||||
std::vector<CObjectBase::Anim> m_Animations;
|
||||
CSkeletonAnim* m_IdleAnim;
|
||||
CSkeletonAnim* m_WalkAnim;
|
||||
CSkeletonAnim* m_DeathAnim;
|
||||
@ -64,19 +39,11 @@ public:
|
||||
|
||||
CSkeletonAnim* GetNamedAnimation( CStr animationName );
|
||||
// list of props attached to object
|
||||
std::vector<Prop> m_Props;
|
||||
struct {
|
||||
// automatically flatten terrain when applying object
|
||||
bool m_AutoFlatten;
|
||||
// cast shadows from this object
|
||||
bool m_CastShadows;
|
||||
} m_Properties;
|
||||
std::vector<CObjectBase::Prop> m_Props;
|
||||
// corresponding model
|
||||
CModel* m_Model;
|
||||
// type of object; index into object managers types array
|
||||
int m_Type;
|
||||
// the material file
|
||||
CStr m_Material;
|
||||
};
|
||||
|
||||
|
||||
|
@ -6,9 +6,20 @@
|
||||
#include "lib/res/res.h"
|
||||
#include "timer.h"
|
||||
#include "VFSUtil.h"
|
||||
#include "ObjectBase.h"
|
||||
|
||||
#define LOG_CATEGORY "graphics"
|
||||
|
||||
bool operator< (const CObjectManager::ObjectKey& a, const CObjectManager::ObjectKey& b)
|
||||
{
|
||||
if (a.ActorName < b.ActorName)
|
||||
return true;
|
||||
else if (a.ActorName > b.ActorName)
|
||||
return false;
|
||||
else
|
||||
return a.ActorVariation < b.ActorVariation;
|
||||
}
|
||||
|
||||
CObjectManager::CObjectManager() : m_SelectedObject(0)
|
||||
{
|
||||
m_ObjectTypes.reserve(32);
|
||||
@ -18,12 +29,18 @@ template<typename T, typename S> void delete_pair_2nd(std::pair<T,S> v) { delete
|
||||
|
||||
CObjectManager::~CObjectManager()
|
||||
{
|
||||
m_SelectedObject=0;
|
||||
for (size_t i=0;i<m_ObjectTypes.size();i++) {
|
||||
m_SelectedObject = NULL;
|
||||
|
||||
for (size_t i = 0; i < m_ObjectTypes.size(); i++) {
|
||||
std::for_each(
|
||||
m_ObjectTypes[i].m_Objects.begin(),
|
||||
m_ObjectTypes[i].m_Objects.end(),
|
||||
delete_pair_2nd<const CStr8, CObjectEntry *>
|
||||
delete_pair_2nd<ObjectKey, CObjectEntry*>
|
||||
);
|
||||
std::for_each(
|
||||
m_ObjectTypes[i].m_ObjectBases.begin(),
|
||||
m_ObjectTypes[i].m_ObjectBases.end(),
|
||||
delete_pair_2nd<CStr, CObjectBase*>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -32,12 +49,14 @@ CObjectManager::~CObjectManager()
|
||||
// TODO (PT): Work out what the object 'types' are for, since they're not
|
||||
// doing anything obvious. (And if they're useless, remove them.)
|
||||
|
||||
CObjectEntry* CObjectManager::FindObject(const char* objectname)
|
||||
CObjectBase* CObjectManager::FindObjectBase(const char* objectname)
|
||||
{
|
||||
// See if the base type has been loaded yet
|
||||
|
||||
for (uint k = 0; k < m_ObjectTypes.size(); k++)
|
||||
{
|
||||
std::map<CStr, CObjectEntry*>::iterator it = m_ObjectTypes[k].m_Objects.find(objectname);
|
||||
if (it != m_ObjectTypes[k].m_Objects.end())
|
||||
std::map<CStr, CObjectBase*>::iterator it = m_ObjectTypes[k].m_ObjectBases.find(objectname);
|
||||
if (it != m_ObjectTypes[k].m_ObjectBases.end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@ -48,19 +67,11 @@ CObjectEntry* CObjectManager::FindObject(const char* objectname)
|
||||
std::map<CStr, CStr>::iterator it = m_ObjectTypes[k].m_ObjectNameToFilename.find(objectname);
|
||||
if (it != m_ObjectTypes[k].m_ObjectNameToFilename.end())
|
||||
{
|
||||
CObjectEntry* obj = new CObjectEntry(0); // TODO: correct type??
|
||||
CObjectBase* obj = new CObjectBase();
|
||||
|
||||
obj->Load(it->second);
|
||||
|
||||
if (! obj->BuildModel())
|
||||
{
|
||||
DeleteObject(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ObjectTypes[k].m_Objects[objectname] = obj;
|
||||
return obj;
|
||||
}
|
||||
m_ObjectTypes[k].m_ObjectBases[objectname] = obj;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +80,46 @@ CObjectEntry* CObjectManager::FindObject(const char* objectname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
CObjectEntry* CObjectManager::FindObject(const char* objname)
|
||||
{
|
||||
CObjectBase* base = FindObjectBase(objname);
|
||||
|
||||
if (! base)
|
||||
return NULL;
|
||||
|
||||
std::set<CStr> choices;
|
||||
// TODO: Fill in these choices from somewhere, e.g.:
|
||||
//choices.insert("whatever");
|
||||
|
||||
CObjectBase::variation_key var;
|
||||
base->CalculateVariation(choices, var);
|
||||
|
||||
// Look to see whether this particular variation has already been loaded
|
||||
|
||||
ObjectKey key (CStr(objname), var);
|
||||
|
||||
std::map<ObjectKey, CObjectEntry*>::iterator it = m_ObjectTypes[0].m_Objects.find(key);
|
||||
if (it != m_ObjectTypes[0].m_Objects.end())
|
||||
return it->second;
|
||||
|
||||
// If it hasn't been loaded, load it now
|
||||
|
||||
CObjectEntry* obj = new CObjectEntry(0, base); // TODO: type ???
|
||||
|
||||
obj->ApplyRandomVariant(var);
|
||||
|
||||
if (! obj->BuildModel())
|
||||
{
|
||||
DeleteObject(obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_ObjectTypes[0].m_Objects[key] = obj;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
void CObjectManager::AddObjectType(const char* name)
|
||||
{
|
||||
m_ObjectTypes.resize(m_ObjectTypes.size()+1);
|
||||
@ -77,28 +128,46 @@ void CObjectManager::AddObjectType(const char* name)
|
||||
type.m_Index=(int)m_ObjectTypes.size()-1;
|
||||
}
|
||||
|
||||
void CObjectManager::AddObject(CObjectEntry* object,int type)
|
||||
|
||||
void CObjectManager::AddObject(ObjectKey& key, CObjectEntry* entry, int type)
|
||||
{
|
||||
assert((uint)type<m_ObjectTypes.size());
|
||||
m_ObjectTypes[type].m_Objects.insert(make_pair((CStr)object->m_FileName, object));
|
||||
m_ObjectTypes[type].m_Objects.insert(std::make_pair(key, entry));
|
||||
}
|
||||
|
||||
void CObjectManager::DeleteObject(CObjectEntry* entry)
|
||||
{
|
||||
std::map<CStr, CObjectEntry*>& objects = m_ObjectTypes[entry->m_Type].m_Objects;
|
||||
std::map<ObjectKey, CObjectEntry*>& objects = m_ObjectTypes[entry->m_Type].m_Objects;
|
||||
|
||||
std::map<CStr, CObjectEntry*>::iterator it;
|
||||
|
||||
for (it = objects.begin(); it != objects.end(); )
|
||||
{
|
||||
for (std::map<ObjectKey, CObjectEntry*>::iterator it = objects.begin(); it != objects.end(); )
|
||||
if (it->second == entry)
|
||||
objects.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
delete entry;
|
||||
}
|
||||
|
||||
|
||||
void CObjectManager::AddObjectBase(CObjectBase* base)
|
||||
{
|
||||
m_ObjectTypes[0].m_ObjectBases.insert(make_pair(base->m_FileName, base));
|
||||
}
|
||||
|
||||
void CObjectManager::DeleteObjectBase(CObjectBase* base)
|
||||
{
|
||||
std::map<CStr, CObjectBase*>& objects = m_ObjectTypes[0].m_ObjectBases;
|
||||
|
||||
for (std::map<CStr, CObjectBase*>::iterator it = objects.begin(); it != objects.end(); )
|
||||
if (it->second == base)
|
||||
objects.erase(it++);
|
||||
else
|
||||
++it;
|
||||
|
||||
delete base;
|
||||
}
|
||||
|
||||
|
||||
void CObjectManager::LoadObjects()
|
||||
{
|
||||
TIMER(__CObjectManager__LoadObjects);
|
||||
@ -127,7 +196,7 @@ void CObjectManager::LoadObjectsIn(CStr& pathname)
|
||||
for (it = files.begin(); it != files.end(); ++it)
|
||||
{
|
||||
CStr objectName;
|
||||
if (! CObjectEntry::LoadName(*it, objectName))
|
||||
if (! CObjectBase::LoadName(*it, objectName))
|
||||
LOG(ERROR, LOG_CATEGORY, "CObjectManager::LoadObjects(): %s: XML Load failed", it->c_str());
|
||||
else
|
||||
{
|
||||
|
@ -13,6 +13,16 @@
|
||||
class CObjectManager : public Singleton<CObjectManager>
|
||||
{
|
||||
public:
|
||||
struct ObjectKey
|
||||
{
|
||||
ObjectKey(CStr& name, CObjectBase::variation_key& var)
|
||||
: ActorName(name), ActorVariation(var) {}
|
||||
|
||||
CStr ActorName;
|
||||
CObjectBase::variation_key ActorVariation;
|
||||
|
||||
};
|
||||
|
||||
struct SObjectType
|
||||
{
|
||||
// name of this object type (derived from directory name)
|
||||
@ -20,7 +30,8 @@ public:
|
||||
// index in parent array
|
||||
int m_Index;
|
||||
// list of objects of this type (found from the objects directory)
|
||||
std::map<CStr, CObjectEntry*> m_Objects;
|
||||
std::map<ObjectKey, CObjectEntry*> m_Objects;
|
||||
std::map<CStr, CObjectBase*> m_ObjectBases;
|
||||
|
||||
std::map<CStr, CStr> m_ObjectNameToFilename;
|
||||
};
|
||||
@ -35,8 +46,12 @@ public:
|
||||
void AddObjectType(const char* name);
|
||||
|
||||
CObjectEntry* FindObject(const char* objname);
|
||||
void AddObject(CObjectEntry* entry,int type);
|
||||
void AddObject(ObjectKey& key, CObjectEntry* entry, int type);
|
||||
void DeleteObject(CObjectEntry* entry);
|
||||
|
||||
CObjectBase* FindObjectBase(const char* objname);
|
||||
void AddObjectBase(CObjectBase* base);
|
||||
void DeleteObjectBase(CObjectBase* base);
|
||||
|
||||
CObjectEntry* GetSelectedObject() const { return m_SelectedObject; }
|
||||
void SetSelectedObject(CObjectEntry* obj) { m_SelectedObject=obj; }
|
||||
@ -50,4 +65,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
// Global comparison operator
|
||||
bool operator< (const CObjectManager::ObjectKey& a, const CObjectManager::ObjectKey& b);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user