2009-04-18 10:00:33 -07:00
|
|
|
/* Copyright (C) 2009 Wildfire Games.
|
|
|
|
|
* This file is part of 0 A.D.
|
|
|
|
|
*
|
|
|
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* 0 A.D. is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
2004-06-03 11:38:14 -07:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
|
2004-05-29 13:56:24 -07:00
|
|
|
#include "ObjectManager.h"
|
2007-02-04 06:56:38 -08:00
|
|
|
|
|
|
|
|
#include "graphics/ObjectBase.h"
|
|
|
|
|
#include "graphics/ObjectEntry.h"
|
2006-06-01 19:10:27 -07:00
|
|
|
#include "ps/CLogger.h"
|
2006-03-16 19:59:49 -08:00
|
|
|
#include "ps/Profile.h"
|
2007-12-20 12:21:45 -08:00
|
|
|
#include "ps/Filesystem.h"
|
2004-05-29 13:56:24 -07:00
|
|
|
|
2009-11-03 13:46:35 -08:00
|
|
|
#define LOG_CATEGORY L"graphics"
|
2004-08-15 13:57:31 -07:00
|
|
|
|
2006-09-22 10:43:00 -07:00
|
|
|
template<typename T, typename S>
|
|
|
|
|
static void delete_pair_2nd(std::pair<T,S> v)
|
|
|
|
|
{
|
|
|
|
|
delete v.second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
struct second_equals
|
|
|
|
|
{
|
|
|
|
|
T x;
|
|
|
|
|
second_equals(const T& x) : x(x) {}
|
|
|
|
|
template<typename S> bool operator()(const S& v) { return v.second == x; }
|
|
|
|
|
};
|
|
|
|
|
|
2008-01-17 15:07:26 -08:00
|
|
|
bool CObjectManager::ObjectKey::operator< (const CObjectManager::ObjectKey& a) const
|
2005-03-22 09:09:36 -08:00
|
|
|
{
|
2008-01-17 15:07:26 -08:00
|
|
|
if (ActorName < a.ActorName)
|
2005-03-22 09:09:36 -08:00
|
|
|
return true;
|
2008-01-17 15:07:26 -08:00
|
|
|
else if (ActorName > a.ActorName)
|
2005-03-22 09:09:36 -08:00
|
|
|
return false;
|
|
|
|
|
else
|
2008-01-17 15:07:26 -08:00
|
|
|
return ActorVariation < a.ActorVariation;
|
2005-03-22 09:09:36 -08:00
|
|
|
}
|
|
|
|
|
|
2007-03-01 10:52:53 -08:00
|
|
|
CObjectManager::CObjectManager(CMeshManager& meshManager, CSkeletonAnimManager& skeletonAnimManager)
|
|
|
|
|
: m_MeshManager(meshManager), m_SkeletonAnimManager(skeletonAnimManager)
|
2004-05-29 13:56:24 -07:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2004-05-29 17:46:58 -07:00
|
|
|
CObjectManager::~CObjectManager()
|
|
|
|
|
{
|
2005-11-05 21:05:07 -08:00
|
|
|
UnloadObjects();
|
2004-05-29 17:46:58 -07:00
|
|
|
}
|
2004-05-29 13:56:24 -07:00
|
|
|
|
2005-03-19 03:55:27 -08:00
|
|
|
|
2009-11-03 13:46:35 -08:00
|
|
|
CObjectBase* CObjectManager::FindObjectBase(const wchar_t* objectname)
|
2004-05-29 13:56:24 -07:00
|
|
|
{
|
2009-11-03 13:46:35 -08:00
|
|
|
debug_assert(objectname[0] != '\0');
|
2006-05-30 22:27:02 -07:00
|
|
|
|
|
|
|
|
// See if the base type has been loaded yet:
|
2005-03-22 09:09:36 -08:00
|
|
|
|
2009-11-03 13:46:35 -08:00
|
|
|
std::map<CStrW, CObjectBase*>::iterator it = m_ObjectBases.find(objectname);
|
2006-09-22 10:43:00 -07:00
|
|
|
if (it != m_ObjectBases.end())
|
|
|
|
|
return it->second;
|
2004-05-29 13:56:24 -07:00
|
|
|
|
2005-03-19 03:55:27 -08:00
|
|
|
// Not already loaded, so try to load it:
|
2005-03-18 14:30:23 -08:00
|
|
|
|
2007-01-07 17:56:46 -08:00
|
|
|
CObjectBase* obj = new CObjectBase(*this);
|
2006-09-22 10:43:00 -07:00
|
|
|
|
|
|
|
|
if (obj->Load(objectname))
|
2005-03-29 12:50:04 -08:00
|
|
|
{
|
2006-09-22 10:43:00 -07:00
|
|
|
m_ObjectBases[objectname] = obj;
|
|
|
|
|
return obj;
|
2004-10-06 11:46:33 -07:00
|
|
|
}
|
2006-09-22 10:43:00 -07:00
|
|
|
else
|
|
|
|
|
delete obj;
|
2004-10-06 11:46:33 -07:00
|
|
|
|
2009-11-03 13:46:35 -08:00
|
|
|
LOG(CLogger::Error, LOG_CATEGORY, L"CObjectManager::FindObjectBase(): Cannot find object '%ls'", objectname);
|
2005-03-19 03:55:27 -08:00
|
|
|
|
2004-10-06 11:46:33 -07:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-03 13:46:35 -08:00
|
|
|
CObjectEntry* CObjectManager::FindObject(const wchar_t* objname)
|
2005-03-22 09:09:36 -08:00
|
|
|
{
|
2006-09-22 10:43:00 -07:00
|
|
|
std::vector<std::set<CStr> > selections; // TODO - should this really be empty?
|
2006-03-16 19:59:49 -08:00
|
|
|
return FindObjectVariation(objname, selections);
|
2005-04-02 21:02:00 -08:00
|
|
|
}
|
|
|
|
|
|
2009-11-03 13:46:35 -08:00
|
|
|
CObjectEntry* CObjectManager::FindObjectVariation(const wchar_t* objname, const std::vector<std::set<CStr> >& selections)
|
2005-04-02 21:02:00 -08:00
|
|
|
{
|
|
|
|
|
CObjectBase* base = FindObjectBase(objname);
|
|
|
|
|
|
|
|
|
|
if (! base)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
2006-03-16 19:59:49 -08:00
|
|
|
return FindObjectVariation(base, selections);
|
2005-04-02 21:02:00 -08:00
|
|
|
}
|
|
|
|
|
|
2007-01-16 19:25:20 -08:00
|
|
|
CObjectEntry* CObjectManager::FindObjectVariation(CObjectBase* base, const std::vector<std::set<CStr> >& selections)
|
2005-04-02 21:02:00 -08:00
|
|
|
{
|
2006-03-16 19:59:49 -08:00
|
|
|
PROFILE( "object variation loading" );
|
|
|
|
|
|
2005-03-22 09:09:36 -08:00
|
|
|
// Look to see whether this particular variation has already been loaded
|
|
|
|
|
|
2006-03-16 19:59:49 -08:00
|
|
|
std::vector<u8> choices = base->CalculateVariationKey(selections);
|
|
|
|
|
ObjectKey key (base->m_Name, choices);
|
2005-03-22 09:09:36 -08:00
|
|
|
|
2006-09-22 10:43:00 -07:00
|
|
|
std::map<ObjectKey, CObjectEntry*>::iterator it = m_Objects.find(key);
|
|
|
|
|
if (it != m_Objects.end())
|
2005-03-22 09:09:36 -08:00
|
|
|
return it->second;
|
|
|
|
|
|
|
|
|
|
// If it hasn't been loaded, load it now
|
|
|
|
|
|
2006-09-22 10:43:00 -07:00
|
|
|
CObjectEntry* obj = new CObjectEntry(base); // TODO: type ?
|
2005-03-22 09:09:36 -08:00
|
|
|
|
2006-04-13 20:14:43 -07: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.
|
|
|
|
|
|
2007-01-07 17:56:46 -08:00
|
|
|
if (! obj->BuildVariation(selections, choices, *this))
|
2005-03-22 09:09:36 -08:00
|
|
|
{
|
|
|
|
|
DeleteObject(obj);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-22 10:43:00 -07:00
|
|
|
m_Objects[key] = obj;
|
2005-03-22 09:09:36 -08:00
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-05-29 13:56:24 -07:00
|
|
|
void CObjectManager::DeleteObject(CObjectEntry* entry)
|
|
|
|
|
{
|
2006-09-22 10:43:00 -07:00
|
|
|
std::map<ObjectKey, CObjectEntry*>::iterator it;
|
|
|
|
|
while (m_Objects.end() != (it = find_if(m_Objects.begin(), m_Objects.end(), second_equals<CObjectEntry*>(entry))))
|
|
|
|
|
m_Objects.erase(it);
|
2005-03-22 09:09:36 -08:00
|
|
|
|
2004-05-29 13:56:24 -07:00
|
|
|
delete entry;
|
|
|
|
|
}
|
|
|
|
|
|
2005-03-22 09:09:36 -08:00
|
|
|
|
2005-11-05 21:05:07 -08:00
|
|
|
void CObjectManager::UnloadObjects()
|
|
|
|
|
{
|
2006-09-22 10:43:00 -07:00
|
|
|
std::for_each(
|
|
|
|
|
m_Objects.begin(),
|
|
|
|
|
m_Objects.end(),
|
|
|
|
|
delete_pair_2nd<ObjectKey, CObjectEntry*>
|
|
|
|
|
);
|
|
|
|
|
m_Objects.clear();
|
|
|
|
|
|
|
|
|
|
std::for_each(
|
|
|
|
|
m_ObjectBases.begin(),
|
|
|
|
|
m_ObjectBases.end(),
|
|
|
|
|
delete_pair_2nd<CStr, CObjectBase*>
|
|
|
|
|
);
|
|
|
|
|
m_ObjectBases.clear();
|
2005-11-05 21:05:07 -08:00
|
|
|
}
|
|
|
|
|
|
2005-03-29 21:43:22 -08:00
|
|
|
|
2005-04-02 21:02:00 -08:00
|
|
|
|
2007-12-20 12:21:45 -08:00
|
|
|
static LibError GetObjectName_ThunkCb(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), uintptr_t cbData)
|
2005-03-29 21:43:22 -08:00
|
|
|
{
|
2007-09-25 02:39:20 -07:00
|
|
|
std::vector<CStr>* names = (std::vector<CStr>*)cbData;
|
2007-12-20 12:21:45 -08:00
|
|
|
CStr name(pathname.string());
|
2005-03-29 21:43:22 -08:00
|
|
|
names->push_back(name.AfterFirst("actors/"));
|
2007-12-20 12:21:45 -08:00
|
|
|
return INFO::CB_CONTINUE;
|
2005-03-29 21:43:22 -08:00
|
|
|
}
|
2006-03-16 19:59:49 -08:00
|
|
|
|
2005-03-29 21:43:22 -08:00
|
|
|
void CObjectManager::GetAllObjectNames(std::vector<CStr>& names)
|
|
|
|
|
{
|
2009-11-03 13:46:35 -08:00
|
|
|
(void)fs_util::ForEachFile(g_VFS, L"art/actors/", GetObjectName_ThunkCb, (uintptr_t)&names, L"*.xml", fs_util::DIR_RECURSIVE);
|
2005-03-29 21:43:22 -08:00
|
|
|
}
|
2006-03-16 19:59:49 -08:00
|
|
|
|
2006-03-14 13:29:19 -08:00
|
|
|
void CObjectManager::GetPropObjectNames(std::vector<CStr>& names)
|
|
|
|
|
{
|
2009-11-03 13:46:35 -08:00
|
|
|
(void)fs_util::ForEachFile(g_VFS, L"art/actors/props/", GetObjectName_ThunkCb, (uintptr_t)&names, L"*.xml", fs_util::DIR_RECURSIVE);
|
2006-03-14 13:29:19 -08:00
|
|
|
}
|