2004-06-03 20:38:14 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
#include "ObjectManager.h"
|
|
|
|
#include <algorithm>
|
2004-06-03 03:43:33 +02:00
|
|
|
#include "CLogger.h"
|
2004-07-08 16:44:04 +02:00
|
|
|
#include "lib/res/res.h"
|
2005-03-18 23:02:20 +01:00
|
|
|
#include "timer.h"
|
2005-03-19 12:55:27 +01:00
|
|
|
#include "VFSUtil.h"
|
2005-03-22 18:09:36 +01:00
|
|
|
#include "ObjectBase.h"
|
2005-03-23 00:31:30 +01:00
|
|
|
#include "ObjectEntry.h"
|
2005-03-30 07:43:22 +02:00
|
|
|
#include "Entity.h"
|
|
|
|
#include "EntityManager.h"
|
|
|
|
#include "BaseEntity.h"
|
|
|
|
#include "Game.h"
|
|
|
|
#include "Model.h"
|
|
|
|
#include "Unit.h"
|
|
|
|
#include "Matrix3D.h"
|
2006-03-17 04:59:49 +01:00
|
|
|
#include "ps/Profile.h"
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2004-08-15 22:57:31 +02:00
|
|
|
#define LOG_CATEGORY "graphics"
|
|
|
|
|
2005-03-22 18:09:36 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-03-30 07:43:22 +02:00
|
|
|
CObjectManager::CObjectManager() : m_SelectedThing(NULL)
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
|
|
|
m_ObjectTypes.reserve(32);
|
|
|
|
}
|
|
|
|
|
2005-05-21 03:40:32 +02:00
|
|
|
template<typename T, typename S> static void delete_pair_2nd(std::pair<T,S> v) { delete v.second; }
|
2005-03-19 12:55:27 +01:00
|
|
|
|
2004-05-30 02:46:58 +02:00
|
|
|
CObjectManager::~CObjectManager()
|
|
|
|
{
|
2005-11-06 06:05:07 +01:00
|
|
|
UnloadObjects();
|
2004-05-30 02:46:58 +02:00
|
|
|
}
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2005-03-19 12:55:27 +01:00
|
|
|
|
|
|
|
// TODO (PT): Work out what the object 'types' are for, since they're not
|
|
|
|
// doing anything obvious. (And if they're useless, remove them.)
|
|
|
|
|
2005-03-22 18:09:36 +01:00
|
|
|
CObjectBase* CObjectManager::FindObjectBase(const char* objectname)
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2006-05-31 07:27:02 +02:00
|
|
|
debug_assert(strcmp(objectname, "") != 0);
|
|
|
|
|
|
|
|
// See if the base type has been loaded yet:
|
2005-03-22 18:09:36 +01:00
|
|
|
|
2005-03-19 12:55:27 +01:00
|
|
|
for (uint k = 0; k < m_ObjectTypes.size(); k++)
|
|
|
|
{
|
2005-03-22 18:09:36 +01:00
|
|
|
std::map<CStr, CObjectBase*>::iterator it = m_ObjectTypes[k].m_ObjectBases.find(objectname);
|
|
|
|
if (it != m_ObjectTypes[k].m_ObjectBases.end())
|
2005-03-19 12:55:27 +01:00
|
|
|
return it->second;
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
2005-03-19 12:55:27 +01:00
|
|
|
// Not already loaded, so try to load it:
|
2005-03-18 23:30:23 +01:00
|
|
|
|
2005-03-29 22:50:04 +02:00
|
|
|
for (uint k = 0; k < m_ObjectTypes.size(); k++)
|
|
|
|
{
|
2005-03-26 00:04:36 +01:00
|
|
|
CObjectBase* obj = new CObjectBase();
|
2004-10-06 20:46:33 +02:00
|
|
|
|
2005-03-29 22:50:04 +02:00
|
|
|
if (obj->Load(objectname))
|
2005-03-26 00:04:36 +01:00
|
|
|
{
|
2005-03-22 18:09:36 +01:00
|
|
|
m_ObjectTypes[k].m_ObjectBases[objectname] = obj;
|
|
|
|
return obj;
|
2004-10-06 20:46:33 +02:00
|
|
|
}
|
2005-03-26 00:04:36 +01:00
|
|
|
else
|
|
|
|
delete obj;
|
2004-10-06 20:46:33 +02:00
|
|
|
}
|
|
|
|
|
2005-04-03 07:02:00 +02:00
|
|
|
LOG(ERROR, LOG_CATEGORY, "CObjectManager::FindObjectBase(): Cannot find object '%s'", objectname);
|
2005-03-19 12:55:27 +01:00
|
|
|
|
2004-10-06 20:46:33 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-03-22 18:09:36 +01:00
|
|
|
CObjectEntry* CObjectManager::FindObject(const char* objname)
|
|
|
|
{
|
2006-03-17 04:59:49 +01:00
|
|
|
std::vector<std::set<CStrW> > selections; // TODO - should this really be empty?
|
|
|
|
return FindObjectVariation(objname, selections);
|
2005-04-03 07:02:00 +02:00
|
|
|
}
|
|
|
|
|
2006-03-17 04:59:49 +01:00
|
|
|
CObjectEntry* CObjectManager::FindObjectVariation(const char* objname, const std::vector<std::set<CStrW> >& selections)
|
2005-04-03 07:02:00 +02:00
|
|
|
{
|
|
|
|
CObjectBase* base = FindObjectBase(objname);
|
|
|
|
|
|
|
|
if (! base)
|
|
|
|
return NULL;
|
|
|
|
|
2006-03-17 04:59:49 +01:00
|
|
|
return FindObjectVariation(base, selections);
|
2005-04-03 07:02:00 +02:00
|
|
|
}
|
|
|
|
|
2006-03-17 04:59:49 +01:00
|
|
|
CObjectEntry* CObjectManager::FindObjectVariation(CObjectBase* base, const std::vector<std::set<CStrW> >& selections)
|
2005-04-03 07:02:00 +02:00
|
|
|
{
|
2006-03-17 04:59:49 +01:00
|
|
|
PROFILE( "object variation loading" );
|
|
|
|
|
2005-03-22 18:09:36 +01:00
|
|
|
// Look to see whether this particular variation has already been loaded
|
|
|
|
|
2006-03-17 04:59:49 +01:00
|
|
|
std::vector<u8> choices = base->CalculateVariationKey(selections);
|
|
|
|
ObjectKey key (base->m_Name, choices);
|
2005-03-22 18:09:36 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2005-04-03 07:02:00 +02:00
|
|
|
CObjectEntry* obj = new CObjectEntry(0, base); // TODO: type ?
|
2005-03-22 18:09:36 +01:00
|
|
|
|
2006-04-14 05:14:43 +02:00
|
|
|
// TODO (for some efficiency): use the pre-calculated choices for this object,
|
|
|
|
// which has already worked out what to do for props, instead of passing the
|
|
|
|
// selections into BuildVariation and having it recalculate the props' choices.
|
|
|
|
|
|
|
|
if (! obj->BuildVariation(selections, choices))
|
2005-03-22 18:09:36 +01:00
|
|
|
{
|
|
|
|
DeleteObject(obj);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ObjectTypes[0].m_Objects[key] = obj;
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
void CObjectManager::AddObjectType(const char* name)
|
|
|
|
{
|
|
|
|
m_ObjectTypes.resize(m_ObjectTypes.size()+1);
|
|
|
|
SObjectType& type=m_ObjectTypes.back();
|
|
|
|
type.m_Name=name;
|
2004-06-03 02:20:20 +02:00
|
|
|
type.m_Index=(int)m_ObjectTypes.size()-1;
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
2005-03-22 18:09:36 +01:00
|
|
|
|
|
|
|
void CObjectManager::AddObject(ObjectKey& key, CObjectEntry* entry, int type)
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2005-06-28 06:06:25 +02:00
|
|
|
debug_assert((uint)type<m_ObjectTypes.size());
|
2005-03-22 18:09:36 +01:00
|
|
|
m_ObjectTypes[type].m_Objects.insert(std::make_pair(key, entry));
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CObjectManager::DeleteObject(CObjectEntry* entry)
|
|
|
|
{
|
2005-03-22 18:09:36 +01:00
|
|
|
std::map<ObjectKey, CObjectEntry*>& objects = m_ObjectTypes[entry->m_Type].m_Objects;
|
2005-03-19 12:55:27 +01:00
|
|
|
|
2005-03-22 18:09:36 +01:00
|
|
|
for (std::map<ObjectKey, CObjectEntry*>::iterator it = objects.begin(); it != objects.end(); )
|
2005-03-19 12:55:27 +01:00
|
|
|
if (it->second == entry)
|
|
|
|
objects.erase(it++);
|
|
|
|
else
|
|
|
|
++it;
|
2005-03-22 18:09:36 +01:00
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
delete entry;
|
|
|
|
}
|
|
|
|
|
2005-03-22 18:09:36 +01:00
|
|
|
|
2005-05-03 23:36:57 +02:00
|
|
|
int CObjectManager::LoadObjects()
|
2004-05-29 22:56:24 +02:00
|
|
|
{
|
2005-03-19 12:55:27 +01:00
|
|
|
AddObjectType("");
|
2005-05-03 23:36:57 +02:00
|
|
|
return 0;
|
2004-05-29 22:56:24 +02:00
|
|
|
}
|
2005-03-30 07:43:22 +02:00
|
|
|
|
2005-11-06 06:05:07 +01:00
|
|
|
void CObjectManager::UnloadObjects()
|
|
|
|
{
|
|
|
|
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<ObjectKey, CObjectEntry*>
|
|
|
|
);
|
|
|
|
std::for_each(
|
|
|
|
m_ObjectTypes[i].m_ObjectBases.begin(),
|
|
|
|
m_ObjectTypes[i].m_ObjectBases.end(),
|
|
|
|
delete_pair_2nd<CStr, CObjectBase*>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
m_ObjectTypes.clear();
|
|
|
|
|
|
|
|
delete m_SelectedThing;
|
|
|
|
m_SelectedThing = NULL;
|
|
|
|
}
|
|
|
|
|
2005-03-30 07:43:22 +02:00
|
|
|
|
2005-04-03 07:02:00 +02:00
|
|
|
|
2005-08-09 17:55:44 +02:00
|
|
|
static void GetObjectName_ThunkCb(const char* path, const DirEnt* UNUSED(ent), void* context)
|
2005-03-30 07:43:22 +02:00
|
|
|
{
|
|
|
|
std::vector<CStr>* names = (std::vector<CStr>*)context;
|
|
|
|
CStr name (path);
|
|
|
|
names->push_back(name.AfterFirst("actors/"));
|
|
|
|
}
|
2006-03-17 04:59:49 +01:00
|
|
|
|
2005-03-30 07:43:22 +02:00
|
|
|
void CObjectManager::GetAllObjectNames(std::vector<CStr>& names)
|
|
|
|
{
|
2006-04-14 08:32:05 +02:00
|
|
|
vfs_dir_enum("art/actors/", VFS_DIR_RECURSIVE, "*.xml",
|
2005-08-09 17:55:44 +02:00
|
|
|
GetObjectName_ThunkCb, &names);
|
2005-03-30 07:43:22 +02:00
|
|
|
}
|
2006-03-17 04:59:49 +01:00
|
|
|
|
2006-03-14 22:29:19 +01:00
|
|
|
void CObjectManager::GetPropObjectNames(std::vector<CStr>& names)
|
|
|
|
{
|
2006-04-14 08:32:05 +02:00
|
|
|
vfs_dir_enum("art/actors/props/", VFS_DIR_RECURSIVE, "*.xml",
|
2006-03-14 22:29:19 +01:00
|
|
|
GetObjectName_ThunkCb, &names);
|
|
|
|
}
|