forked from mirrors/0ad
# Hotloading of actor XML files.
Stop ignoring actor XML animation speeds. Add decentralised registration of hotloaders. Move player ID storage into CModel, to simplify CUnit. Remove obsolete unit ID allocation code. Remove some material junk. This was SVN commit r7605.
This commit is contained in:
@@ -76,7 +76,7 @@ public:
|
||||
CGameViewImpl(CGame* game)
|
||||
: Game(game),
|
||||
ColladaManager(), MeshManager(ColladaManager), SkeletonAnimManager(ColladaManager),
|
||||
ObjectManager(MeshManager, SkeletonAnimManager),
|
||||
ObjectManager(MeshManager, SkeletonAnimManager, *game->GetSimulation2()),
|
||||
ViewCamera(),
|
||||
CullCamera(),
|
||||
LockCullCamera(false),
|
||||
|
||||
@@ -103,10 +103,7 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
|
||||
|
||||
// delete all remaining non-entity units
|
||||
if (pUnitMan)
|
||||
{
|
||||
pUnitMan->DeleteAll();
|
||||
pUnitMan->SetNextID(0);
|
||||
}
|
||||
|
||||
// unpack the data
|
||||
if (!only_xml)
|
||||
@@ -968,26 +965,6 @@ int CXMLReader::ReadOldEntities(XMBElement parent, double end_time)
|
||||
{
|
||||
XMBElementList entities = parent.GetChildNodes();
|
||||
|
||||
// If this is the first time in ReadOldEntities, find the next free ID number
|
||||
// in case we need to allocate new ones in the future
|
||||
if (entity_idx == 0)
|
||||
{
|
||||
int maxUnitID = -1;
|
||||
|
||||
XERO_ITER_EL(parent, entity)
|
||||
{
|
||||
debug_assert(entity.GetNodeName() == el_entity);
|
||||
|
||||
XMBAttributeList attrs = entity.GetAttributes();
|
||||
utf16string uid = attrs.GetNamedItem(at_uid);
|
||||
int unitId = uid.empty() ? -1 : CStr(uid).ToInt();
|
||||
maxUnitID = std::max(maxUnitID, unitId);
|
||||
}
|
||||
|
||||
if (m_MapReader.pUnitMan)
|
||||
m_MapReader.pUnitMan->SetNextID(maxUnitID + 1);
|
||||
}
|
||||
|
||||
while (entity_idx < entities.Count)
|
||||
{
|
||||
// all new state at this scope and below doesn't need to be
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -34,16 +34,6 @@ static SMaterialColor IdentityEmissive(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
static SMaterialColor BrokenColor(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
|
||||
bool SMaterialColor::operator==(const SMaterialColor& color)
|
||||
{
|
||||
return (
|
||||
r == color.r &&
|
||||
g == color.g &&
|
||||
b == color.b &&
|
||||
a == color.a
|
||||
);
|
||||
}
|
||||
|
||||
CMaterial::CMaterial()
|
||||
: m_Diffuse(IdentityDiffuse),
|
||||
m_Ambient(IdentityAmbient),
|
||||
@@ -54,30 +44,6 @@ CMaterial::CMaterial()
|
||||
m_PlayerID(PLAYER_ID_NONE),
|
||||
m_TextureColor(BrokenColor)
|
||||
{
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
CMaterial::CMaterial(const CMaterial& material)
|
||||
{
|
||||
(*this) = material;
|
||||
}
|
||||
|
||||
CMaterial::~CMaterial()
|
||||
{
|
||||
}
|
||||
|
||||
void CMaterial::operator=(const CMaterial& material)
|
||||
{
|
||||
m_Diffuse = material.m_Diffuse;
|
||||
m_Ambient = material.m_Ambient;
|
||||
m_Specular = material.m_Specular;
|
||||
m_Emissive = material.m_Emissive;
|
||||
|
||||
m_SpecularPower = material.m_SpecularPower;
|
||||
m_Alpha = material.m_Alpha;
|
||||
m_PlayerID = material.m_PlayerID;
|
||||
m_TextureColor = material.m_TextureColor;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
bool CMaterial::operator==(const CMaterial& material)
|
||||
@@ -163,70 +129,47 @@ void CMaterial::SetPlayerColor(const CColor& colour)
|
||||
m_TextureColor = SMaterialColor(colour.r, colour.g, colour.b, colour.a);
|
||||
}
|
||||
|
||||
|
||||
void CMaterial::SetTexture(const CStr& texture)
|
||||
{
|
||||
m_Texture = texture;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
void CMaterial::SetVertexProgram(const CStr& prog)
|
||||
{
|
||||
m_VertexProgram = prog;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
void CMaterial::SetFragmentProgram(const CStr& prog)
|
||||
{
|
||||
m_FragmentProgram = prog;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
void CMaterial::SetDiffuse(const SMaterialColor& color)
|
||||
{
|
||||
m_Diffuse = color;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
void CMaterial::SetAmbient(const SMaterialColor& color)
|
||||
{
|
||||
m_Ambient = color;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
void CMaterial::SetSpecular(const SMaterialColor& color)
|
||||
{
|
||||
m_Specular = color;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
void CMaterial::SetEmissive(const SMaterialColor& color)
|
||||
{
|
||||
m_Emissive = color;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
void CMaterial::SetSpecularPower(float power)
|
||||
{
|
||||
m_SpecularPower = power;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
void CMaterial::SetUsesAlpha(bool flag)
|
||||
{
|
||||
m_Alpha = flag;
|
||||
ComputeHash();
|
||||
}
|
||||
|
||||
void CMaterial::ComputeHash()
|
||||
{
|
||||
m_Hash =
|
||||
m_Diffuse.Sum() +
|
||||
m_Ambient.Sum() +
|
||||
m_Specular.Sum() +
|
||||
m_Emissive.Sum() +
|
||||
m_SpecularPower +
|
||||
(float)m_Texture.GetHashCode() +
|
||||
(float)m_VertexProgram.GetHashCode() +
|
||||
(float)m_FragmentProgram.GetHashCode();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -38,26 +38,14 @@ public:
|
||||
b = _b;
|
||||
a = _a;
|
||||
}
|
||||
SMaterialColor(const SMaterialColor& color)
|
||||
bool operator==(const SMaterialColor& color)
|
||||
{
|
||||
r = color.r;
|
||||
g = color.g;
|
||||
b = color.b;
|
||||
a = color.a;
|
||||
}
|
||||
|
||||
void operator=(const SMaterialColor& color)
|
||||
{
|
||||
r = color.r;
|
||||
g = color.g;
|
||||
b = color.b;
|
||||
a = color.a;
|
||||
}
|
||||
bool operator==(const SMaterialColor& color);
|
||||
|
||||
float Sum()
|
||||
{
|
||||
return (r + g + b + a);
|
||||
return (
|
||||
r == color.r &&
|
||||
g == color.g &&
|
||||
b == color.b &&
|
||||
a == color.a
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -65,12 +53,9 @@ class CMaterial
|
||||
{
|
||||
public:
|
||||
CMaterial();
|
||||
CMaterial(const CMaterial& material);
|
||||
virtual ~CMaterial();
|
||||
|
||||
void Bind();
|
||||
void Unbind();
|
||||
float GetHash() { return m_Hash; }
|
||||
|
||||
const CStr& GetTexture() { return m_Texture; }
|
||||
const CStr& GetVertexProgram() { return m_VertexProgram; }
|
||||
@@ -105,13 +90,8 @@ public:
|
||||
void SetSpecularPower(float power);
|
||||
void SetUsesAlpha(bool flag);
|
||||
|
||||
void operator=(const CMaterial& material);
|
||||
bool operator==(const CMaterial& material);
|
||||
protected:
|
||||
void ComputeHash();
|
||||
|
||||
float m_Hash;
|
||||
|
||||
// Various reflective color properties
|
||||
SMaterialColor m_Diffuse;
|
||||
SMaterialColor m_Ambient;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -25,8 +25,6 @@
|
||||
#include "ps/FileIo.h" // to get access to its CError
|
||||
#include "ps/Profile.h"
|
||||
|
||||
#define LOG_CATEGORY L"mesh"
|
||||
|
||||
// TODO: should this cache models while they're not actively in the game?
|
||||
// (Currently they'll probably be deleted when the reference count drops to 0,
|
||||
// even if it's quite possible that they'll get reloaded very soon.)
|
||||
@@ -49,13 +47,13 @@ CModelDefPtr CMeshManager::GetMesh(const VfsPath& pathname)
|
||||
if (iter != m_MeshMap.end() && !iter->second.expired())
|
||||
return CModelDefPtr(iter->second);
|
||||
|
||||
PROFILE( "load mesh" );
|
||||
PROFILE("load mesh");
|
||||
|
||||
VfsPath pmdFilename = m_ColladaManager.GetLoadableFilename(name, CColladaManager::PMD);
|
||||
|
||||
if (pmdFilename.empty())
|
||||
{
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"Could not load mesh '%ls'", pathname.string().c_str());
|
||||
LOGERROR(L"Could not load mesh '%ls'", pathname.string().c_str());
|
||||
return CModelDefPtr();
|
||||
}
|
||||
|
||||
@@ -67,7 +65,7 @@ CModelDefPtr CMeshManager::GetMesh(const VfsPath& pathname)
|
||||
}
|
||||
catch (PSERROR_File&)
|
||||
{
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"Could not load mesh '%ls'", pathname.string().c_str());
|
||||
LOGERROR(L"Could not load mesh '%ls'", pathname.string().c_str());
|
||||
return CModelDefPtr();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
CModel::CModel(CSkeletonAnimManager& skeletonAnimManager)
|
||||
: m_Parent(NULL), m_Flags(0), m_Anim(NULL), m_AnimTime(0),
|
||||
m_BoneMatrices(NULL), m_InverseBindBoneMatrices(NULL),
|
||||
m_PositionValid(false), m_ShadingColor(1,1,1,1),
|
||||
m_PositionValid(false), m_ShadingColor(1,1,1,1), m_PlayerID((size_t)-1),
|
||||
m_SkeletonAnimManager(skeletonAnimManager)
|
||||
{
|
||||
}
|
||||
@@ -238,6 +238,8 @@ void CModel::Update(float time)
|
||||
{
|
||||
if (m_Anim && m_Anim->m_AnimDef && m_BoneMatrices)
|
||||
{
|
||||
time *= m_Anim->m_Speed;
|
||||
|
||||
float oldAnimTime = m_AnimTime;
|
||||
|
||||
// update animation time, but don't calculate bone matrices - do that (lazily) when
|
||||
@@ -288,7 +290,10 @@ bool CModel::NeedsNewAnim(float time) const
|
||||
|
||||
if (m_Anim && m_Anim->m_AnimDef && m_BoneMatrices)
|
||||
{
|
||||
time *= m_Anim->m_Speed;
|
||||
|
||||
float duration = m_Anim->m_AnimDef->GetDuration();
|
||||
|
||||
if (m_AnimTime + time > duration)
|
||||
return true;
|
||||
}
|
||||
@@ -300,6 +305,8 @@ void CModel::CheckActionTriggers(float time, bool& action, bool& action2) const
|
||||
{
|
||||
if (m_Anim && m_Anim->m_AnimDef && m_BoneMatrices)
|
||||
{
|
||||
time *= m_Anim->m_Speed;
|
||||
|
||||
if (m_AnimTime <= m_Anim->m_ActionPos && m_AnimTime + time > m_Anim->m_ActionPos)
|
||||
action = true;
|
||||
|
||||
@@ -498,19 +505,24 @@ 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)
|
||||
{
|
||||
// [TODO: uh, shouldn't this be doing something?]
|
||||
}
|
||||
}
|
||||
|
||||
void CModel::SetPlayerID(size_t id)
|
||||
{
|
||||
m_Material.SetPlayerColor(id);
|
||||
m_PlayerID = id;
|
||||
|
||||
if (id != (size_t)-1)
|
||||
m_Material.SetPlayerColor(id);
|
||||
|
||||
for (std::vector<Prop>::iterator it = m_Props.begin(); it != m_Props.end(); ++it)
|
||||
it->m_Model->SetPlayerID(id);
|
||||
}
|
||||
|
||||
size_t CModel::GetPlayerID()
|
||||
{
|
||||
return m_PlayerID;
|
||||
}
|
||||
|
||||
void CModel::SetPlayerColor(const CColor& colour)
|
||||
{
|
||||
m_Material.SetPlayerColor(colour);
|
||||
|
||||
@@ -84,9 +84,10 @@ public:
|
||||
void SetTexture(const CTexture& tex) { m_Texture=tex; }
|
||||
// set the model's material
|
||||
void SetMaterial(const CMaterial &material);
|
||||
// set the model's player ID, recursively through props. CUnit::SetPlayerID
|
||||
// should normally be used instead.
|
||||
// set the model's player ID, recursively through props
|
||||
void SetPlayerID(size_t id);
|
||||
// get the model's player ID, recursively through props; initial default is (size_t)-1
|
||||
size_t GetPlayerID();
|
||||
// set the model's player colour
|
||||
void SetPlayerColor(const CColor& colour);
|
||||
// set the models mod color
|
||||
@@ -227,6 +228,8 @@ private:
|
||||
// modulating color
|
||||
CColor m_ShadingColor;
|
||||
|
||||
size_t m_PlayerID;
|
||||
|
||||
// manager object which can load animations for us
|
||||
CSkeletonAnimManager& m_SkeletonAnimManager;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -39,19 +39,12 @@ CObjectBase::CObjectBase(CObjectManager& objectManager)
|
||||
m_Properties.m_FloatOnWater = false;
|
||||
}
|
||||
|
||||
bool CObjectBase::Load(const std::wstring& filename)
|
||||
bool CObjectBase::Load(const VfsPath& pathname)
|
||||
{
|
||||
m_VariantGroups.clear();
|
||||
|
||||
VfsPath pathname(VfsPath(L"art/actors/")/filename);
|
||||
|
||||
CXeromyces XeroFile;
|
||||
if (XeroFile.Load(pathname) != PSRETURN_OK)
|
||||
return false;
|
||||
|
||||
m_Name = filename;
|
||||
m_ShortName = fs::basename(pathname);
|
||||
|
||||
// Define all the elements used in the XML file
|
||||
#define EL(x) int el_##x = XeroFile.GetElementID(#x)
|
||||
#define AT(x) int at_##x = XeroFile.GetAttributeID(#x)
|
||||
@@ -88,6 +81,12 @@ bool CObjectBase::Load(const std::wstring& filename)
|
||||
}
|
||||
|
||||
|
||||
m_VariantGroups.clear();
|
||||
|
||||
m_Pathname = pathname;
|
||||
m_ShortName = fs::basename(pathname);
|
||||
|
||||
|
||||
// Set up the vector<vector<T>> m_Variants to contain the right number
|
||||
// of elements, to avoid wasteful copying/reallocation later.
|
||||
{
|
||||
@@ -206,7 +205,7 @@ bool CObjectBase::Load(const std::wstring& filename)
|
||||
|
||||
if (currentGroup->size() == 0)
|
||||
{
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"Actor group has zero variants ('%ls')", filename.c_str());
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"Actor group has zero variants ('%ls')", pathname.string().c_str());
|
||||
}
|
||||
|
||||
++currentGroup;
|
||||
@@ -228,6 +227,11 @@ bool CObjectBase::Load(const std::wstring& filename)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CObjectBase::Reload()
|
||||
{
|
||||
return Load(m_Pathname);
|
||||
}
|
||||
|
||||
std::vector<u8> CObjectBase::CalculateVariationKey(const std::vector<std::set<CStr> >& selections)
|
||||
{
|
||||
// (TODO: see CObjectManager::FindObjectVariation for an opportunity to
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -74,8 +74,8 @@ public:
|
||||
VfsPath texture;
|
||||
VfsPath model;
|
||||
CStr color;
|
||||
std::multimap<CStr, CObjectBase::Prop> props;
|
||||
std::multimap<CStr, CObjectBase::Anim> anims;
|
||||
std::multimap<CStr, Prop> props;
|
||||
std::multimap<CStr, Anim> anims;
|
||||
};
|
||||
|
||||
CObjectBase(CObjectManager& objectManager);
|
||||
@@ -97,10 +97,20 @@ public:
|
||||
// variant names.
|
||||
std::vector<std::vector<CStr> > GetVariantGroups() const;
|
||||
|
||||
bool Load(const std::wstring& filename);
|
||||
/**
|
||||
* Initialise this object by loading from the given file.
|
||||
* Returns false on error.
|
||||
*/
|
||||
bool Load(const VfsPath& pathname);
|
||||
|
||||
// object name
|
||||
CStrW m_Name;
|
||||
/**
|
||||
* Reload this object from the file that it was previously loaded from.
|
||||
* Returns false on error.
|
||||
*/
|
||||
bool Reload();
|
||||
|
||||
// filename that this was loaded from
|
||||
VfsPath m_Pathname;
|
||||
|
||||
// short human-readable name
|
||||
CStrW m_ShortName;
|
||||
|
||||
@@ -175,7 +175,7 @@ bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections
|
||||
m_AmmunitionModel = oe->m_Model;
|
||||
m_AmmunitionPoint = modeldef->FindPropPoint(ppn);
|
||||
if (! m_AmmunitionPoint)
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"Failed to find matching prop point called \"%hs\" in model \"%ls\" for actor \"%ls\"", ppn.c_str(), m_ModelName.string().c_str(), m_Base->m_Name.c_str());
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"Failed to find matching prop point called \"%hs\" in model \"%ls\" for actor \"%ls\"", ppn.c_str(), m_ModelName.string().c_str(), m_Base->m_ShortName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -187,7 +187,7 @@ bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections
|
||||
propmodel->SetAnimation(oe->GetRandomAnimation("idle"));
|
||||
}
|
||||
else
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"Failed to find matching prop point called \"%hs\" in model \"%ls\" for actor \"%ls\"", prop.m_PropPointName.c_str(), m_ModelName.string().c_str(), m_Base->m_Name.c_str());
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"Failed to find matching prop point called \"%hs\" in model \"%ls\" for actor \"%ls\"", prop.m_PropPointName.c_str(), m_ModelName.string().c_str(), m_Base->m_ShortName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -22,10 +22,11 @@
|
||||
#include "graphics/ObjectBase.h"
|
||||
#include "graphics/ObjectEntry.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/Game.h"
|
||||
#include "ps/Profile.h"
|
||||
#include "ps/Filesystem.h"
|
||||
|
||||
#define LOG_CATEGORY L"graphics"
|
||||
#include "simulation2/Simulation2.h"
|
||||
#include "simulation2/components/ICmpVisual.h"
|
||||
|
||||
template<typename T, typename S>
|
||||
static void delete_pair_2nd(std::pair<T,S> v)
|
||||
@@ -51,14 +52,22 @@ bool CObjectManager::ObjectKey::operator< (const CObjectManager::ObjectKey& a) c
|
||||
return ActorVariation < a.ActorVariation;
|
||||
}
|
||||
|
||||
CObjectManager::CObjectManager(CMeshManager& meshManager, CSkeletonAnimManager& skeletonAnimManager)
|
||||
: m_MeshManager(meshManager), m_SkeletonAnimManager(skeletonAnimManager)
|
||||
static LibError ReloadChangedFileCB(void* param, const VfsPath& path)
|
||||
{
|
||||
return static_cast<CObjectManager*>(param)->ReloadChangedFile(path);
|
||||
}
|
||||
|
||||
CObjectManager::CObjectManager(CMeshManager& meshManager, CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation)
|
||||
: m_MeshManager(meshManager), m_SkeletonAnimManager(skeletonAnimManager), m_Simulation(simulation)
|
||||
{
|
||||
RegisterFileReloadFunc(ReloadChangedFileCB, this);
|
||||
}
|
||||
|
||||
CObjectManager::~CObjectManager()
|
||||
{
|
||||
UnloadObjects();
|
||||
|
||||
UnregisterFileReloadFunc(ReloadChangedFileCB, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +85,9 @@ CObjectBase* CObjectManager::FindObjectBase(const wchar_t* objectname)
|
||||
|
||||
CObjectBase* obj = new CObjectBase(*this);
|
||||
|
||||
if (obj->Load(objectname))
|
||||
VfsPath pathname(VfsPath(L"art/actors/")/objectname);
|
||||
|
||||
if (obj->Load(pathname))
|
||||
{
|
||||
m_ObjectBases[objectname] = obj;
|
||||
return obj;
|
||||
@@ -84,7 +95,7 @@ CObjectBase* CObjectManager::FindObjectBase(const wchar_t* objectname)
|
||||
else
|
||||
delete obj;
|
||||
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"CObjectManager::FindObjectBase(): Cannot find object '%ls'", objectname);
|
||||
LOGERROR(L"CObjectManager::FindObjectBase(): Cannot find object '%ls'", objectname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -107,12 +118,12 @@ CObjectEntry* CObjectManager::FindObjectVariation(const wchar_t* objname, const
|
||||
|
||||
CObjectEntry* CObjectManager::FindObjectVariation(CObjectBase* base, const std::vector<std::set<CStr> >& selections)
|
||||
{
|
||||
PROFILE( "object variation loading" );
|
||||
PROFILE("object variation loading");
|
||||
|
||||
// Look to see whether this particular variation has already been loaded
|
||||
|
||||
std::vector<u8> choices = base->CalculateVariationKey(selections);
|
||||
ObjectKey key (base->m_Name, choices);
|
||||
ObjectKey key (base->m_Pathname.string(), choices);
|
||||
|
||||
std::map<ObjectKey, CObjectEntry*>::iterator it = m_Objects.find(key);
|
||||
if (it != m_Objects.end())
|
||||
@@ -165,22 +176,23 @@ void CObjectManager::UnloadObjects()
|
||||
m_ObjectBases.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static LibError GetObjectName_ThunkCb(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), uintptr_t cbData)
|
||||
LibError CObjectManager::ReloadChangedFile(const VfsPath& path)
|
||||
{
|
||||
std::vector<CStr>* names = (std::vector<CStr>*)cbData;
|
||||
CStr name(pathname.string());
|
||||
names->push_back(name.AfterFirst("actors/"));
|
||||
return INFO::CB_CONTINUE;
|
||||
}
|
||||
for (std::map<CStrW, CObjectBase*>::iterator it = m_ObjectBases.begin(); it != m_ObjectBases.end(); ++it)
|
||||
{
|
||||
if (it->second->m_Pathname == path)
|
||||
{
|
||||
it->second->Reload();
|
||||
|
||||
void CObjectManager::GetAllObjectNames(std::vector<CStr>& names)
|
||||
{
|
||||
(void)fs_util::ForEachFile(g_VFS, L"art/actors/", GetObjectName_ThunkCb, (uintptr_t)&names, L"*.xml", fs_util::DIR_RECURSIVE);
|
||||
}
|
||||
// Slightly ugly hack: The graphics system doesn't preserve enough information to regenerate the
|
||||
// object with all correct variations, and we don't want to waste space storing it just for the
|
||||
// rare occurrence of hotloading, so we'll tell the component (which does preserve the information)
|
||||
// to do the reloading itself
|
||||
const std::map<entity_id_t, IComponent*>& cmps = m_Simulation.GetEntitiesWithInterface(IID_Visual);
|
||||
for (std::map<entity_id_t, IComponent*>::const_iterator eit = cmps.begin(); eit != cmps.end(); ++eit)
|
||||
static_cast<ICmpVisual*>(eit->second)->Hotload(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void CObjectManager::GetPropObjectNames(std::vector<CStr>& names)
|
||||
{
|
||||
(void)fs_util::ForEachFile(g_VFS, L"art/actors/props/", GetObjectName_ThunkCb, (uintptr_t)&names, L"*.xml", fs_util::DIR_RECURSIVE);
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "ps/CStr.h"
|
||||
#include "lib/file/vfs/vfs_path.h"
|
||||
|
||||
class CEntityTemplate;
|
||||
class CMatrix3D;
|
||||
@@ -29,6 +31,7 @@ class CMeshManager;
|
||||
class CObjectBase;
|
||||
class CObjectEntry;
|
||||
class CSkeletonAnimManager;
|
||||
class CSimulation2;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// CObjectManager: manager class for all possible actor types
|
||||
@@ -36,21 +39,23 @@ class CObjectManager
|
||||
{
|
||||
NONCOPYABLE(CObjectManager);
|
||||
public:
|
||||
// Unique identifier of an actor variation
|
||||
struct ObjectKey
|
||||
{
|
||||
ObjectKey(const CStr& name, const std::vector<u8>& var)
|
||||
ObjectKey(const CStrW& name, const std::vector<u8>& var)
|
||||
: ActorName(name), ActorVariation(var) {}
|
||||
|
||||
CStr ActorName;
|
||||
std::vector<u8> ActorVariation;
|
||||
|
||||
bool operator< (const CObjectManager::ObjectKey& a) const;
|
||||
|
||||
private:
|
||||
CStrW ActorName;
|
||||
std::vector<u8> ActorVariation;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
// constructor, destructor
|
||||
CObjectManager(CMeshManager& meshManager, CSkeletonAnimManager& skeletonAnimManager);
|
||||
CObjectManager(CMeshManager& meshManager, CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation);
|
||||
~CObjectManager();
|
||||
|
||||
// Provide access to the manager classes for meshes and animations - they're
|
||||
@@ -69,13 +74,16 @@ public:
|
||||
CObjectEntry* FindObjectVariation(const wchar_t* objname, const std::vector<std::set<CStr> >& selections);
|
||||
CObjectEntry* FindObjectVariation(CObjectBase* base, const std::vector<std::set<CStr> >& selections);
|
||||
|
||||
// Get all names, quite slowly. (Intended only for Atlas.)
|
||||
static void GetAllObjectNames(std::vector<CStr>& names);
|
||||
static void GetPropObjectNames(std::vector<CStr>& names);
|
||||
/**
|
||||
* Reload any scripts that were loaded from the given filename.
|
||||
* (This is used to implement hotloading.)
|
||||
*/
|
||||
LibError ReloadChangedFile(const VfsPath& path);
|
||||
|
||||
private:
|
||||
CMeshManager& m_MeshManager;
|
||||
CSkeletonAnimManager& m_SkeletonAnimManager;
|
||||
CSimulation2& m_Simulation;
|
||||
|
||||
std::map<ObjectKey, CObjectEntry*> m_Objects;
|
||||
std::map<CStrW, CObjectBase*> m_ObjectBases;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
CUnit::CUnit(CObjectEntry* object, CEntity* entity, CObjectManager& objectManager,
|
||||
const std::set<CStr>& actorSelections)
|
||||
: m_Object(object), m_Model(object->m_Model->Clone()),
|
||||
m_ID(invalidUnitId), m_ActorSelections(actorSelections), m_PlayerID(invalidPlayerId),
|
||||
m_ID(invalidUnitId), m_ActorSelections(actorSelections),
|
||||
m_ObjectManager(objectManager)
|
||||
{
|
||||
m_Animation = new CUnitAnimation(*this);
|
||||
@@ -174,13 +174,6 @@ void CUnit::UpdateModel(float frameTime)
|
||||
m_Animation->Update(frameTime*1000.0f);
|
||||
}
|
||||
|
||||
|
||||
void CUnit::SetPlayerID(size_t id)
|
||||
{
|
||||
m_PlayerID = id;
|
||||
m_Model->SetPlayerID(m_PlayerID);
|
||||
}
|
||||
|
||||
void CUnit::SetEntitySelection(const CStr& selection)
|
||||
{
|
||||
CStr selection_lc = selection.LowerCase();
|
||||
@@ -218,8 +211,7 @@ void CUnit::ReloadObject()
|
||||
|
||||
// Copy the old instance-specific settings from the old model to the new instance
|
||||
newModel->SetTransform(m_Model->GetTransform());
|
||||
if (m_PlayerID != invalidPlayerId)
|
||||
newModel->SetPlayerID(m_PlayerID);
|
||||
newModel->SetPlayerID(m_Model->GetPlayerID());
|
||||
newModel->CopyAnimationFrom(m_Model);
|
||||
|
||||
delete m_Model;
|
||||
|
||||
@@ -90,12 +90,6 @@ public:
|
||||
// matching 'name'.
|
||||
bool IsPlayingAnimation(const CStr& name);
|
||||
|
||||
// Set player ID of this unit (and the attached entity and actor)
|
||||
void SetPlayerID(size_t id);
|
||||
|
||||
// Get player ID of this unit
|
||||
size_t GetPlayerID() { return m_PlayerID; }
|
||||
|
||||
// Most units have a hopefully-unique ID number, so they can be referred to
|
||||
// persistently despite saving/loading maps. Default for new units is -1; should
|
||||
// usually be set to CUnitManager::GetNewID() after creation.
|
||||
@@ -111,8 +105,6 @@ private:
|
||||
CObjectEntry* m_Object;
|
||||
// object model representation; never NULL
|
||||
CModel* m_Model;
|
||||
// player id of this unit (only read for graphical effects), or ~0 if unspecified
|
||||
size_t m_PlayerID;
|
||||
|
||||
CUnitAnimation* m_Animation;
|
||||
|
||||
|
||||
@@ -75,6 +75,10 @@ void CUnitAnimation::SetAnimationSync(float actionTime, float repeatTime)
|
||||
// Set the speed so it loops once in repeatTime
|
||||
float speed = duration / repeatTime;
|
||||
|
||||
// Compensate for the animation's scale factor
|
||||
if (model.m_Anim->m_Speed)
|
||||
speed /= model.m_Anim->m_Speed;
|
||||
|
||||
// Need to offset so that start+actionTime*speed = ActionPos
|
||||
float start = model.m_Anim->m_ActionPos - actionTime*speed;
|
||||
// Wrap it so that it's within the animation
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -36,7 +36,6 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CUnitManager constructor
|
||||
CUnitManager::CUnitManager()
|
||||
: m_NextID(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -135,18 +134,3 @@ CUnit* CUnitManager::CreateUnit(const CStrW& actorName, CEntity* entity, const s
|
||||
AddUnit(unit);
|
||||
return unit;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// FindByID
|
||||
// TODO: this is hopelessly inefficient
|
||||
CUnit* CUnitManager::FindByID(size_t id) const
|
||||
{
|
||||
if (id == invalidUnitId)
|
||||
return NULL;
|
||||
|
||||
for (size_t i = 0; i < m_Units.size(); ++i)
|
||||
if (m_Units[i]->GetID() == id)
|
||||
return m_Units[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -60,19 +60,11 @@ public:
|
||||
// return the closest unit, or null if everything missed
|
||||
CUnit* PickUnit(const CVector3D& origin, const CVector3D& dir, bool entitiesOnly) const;
|
||||
|
||||
CUnit* FindByID(size_t id) const;
|
||||
|
||||
size_t GetNewID() { return m_NextID++; }
|
||||
|
||||
void SetNextID(size_t n) { m_NextID = n; }
|
||||
|
||||
void SetObjectManager(CObjectManager& objectManager) { m_ObjectManager = &objectManager; }
|
||||
|
||||
private:
|
||||
// list of all known units
|
||||
std::vector<CUnit*> m_Units;
|
||||
// next ID number to be assigned to a unit created in the editor
|
||||
size_t m_NextID;
|
||||
// graphical object manager; may be NULL if not set up
|
||||
CObjectManager* m_ObjectManager;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -20,22 +20,29 @@
|
||||
|
||||
#include "gui/GUIManager.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/Game.h"
|
||||
#include "simulation2/Simulation2.h"
|
||||
|
||||
#include "lib/res/h_mgr.h" // h_reload
|
||||
#include "lib/sysdep/dir_watch.h"
|
||||
|
||||
#define LOG_CATEGORY L"file"
|
||||
|
||||
|
||||
PIVFS g_VFS;
|
||||
|
||||
static std::vector<std::pair<FileReloadFunc, void*> > g_ReloadFuncs;
|
||||
|
||||
bool FileExists(const VfsPath& pathname)
|
||||
{
|
||||
return g_VFS->GetFileInfo(pathname, 0) == INFO::OK;
|
||||
}
|
||||
|
||||
void RegisterFileReloadFunc(FileReloadFunc func, void* obj)
|
||||
{
|
||||
g_ReloadFuncs.push_back(std::make_pair(func, obj));
|
||||
}
|
||||
|
||||
void UnregisterFileReloadFunc(FileReloadFunc func, void* obj)
|
||||
{
|
||||
g_ReloadFuncs.erase(std::remove(g_ReloadFuncs.begin(), g_ReloadFuncs.end(), std::make_pair(func, obj)));
|
||||
}
|
||||
|
||||
// try to skip unnecessary work by ignoring uninteresting notifications.
|
||||
static bool CanIgnore(const DirWatchNotification& notification)
|
||||
@@ -69,9 +76,14 @@ LibError ReloadChangedFiles()
|
||||
VfsPath pathname;
|
||||
RETURN_ERR(g_VFS->GetVirtualPath(notifications[i].Pathname(), pathname));
|
||||
RETURN_ERR(g_VFS->Invalidate(pathname));
|
||||
|
||||
// Tell each hotloadable system about this file change:
|
||||
|
||||
RETURN_ERR(g_GUI->ReloadChangedFiles(pathname));
|
||||
if (g_Game && g_Game->GetSimulation2())
|
||||
RETURN_ERR(g_Game->GetSimulation2()->ReloadChangedFile(pathname));
|
||||
|
||||
for (size_t j = 0; j < g_ReloadFuncs.size(); ++j)
|
||||
g_ReloadFuncs[j].first(g_ReloadFuncs[j].second, pathname);
|
||||
|
||||
RETURN_ERR(h_reload(pathname));
|
||||
}
|
||||
}
|
||||
@@ -99,7 +111,7 @@ PSRETURN CVFSFile::Load(const VfsPath& filename)
|
||||
LibError ret = g_VFS->LoadFile(filename, m_Buffer, m_BufferSize);
|
||||
if (ret != INFO::OK)
|
||||
{
|
||||
LOG(CLogger::Error, LOG_CATEGORY, L"CVFSFile: file %ls couldn't be opened (vfs_load: %ld)", filename.string().c_str(), ret);
|
||||
LOGERROR(L"CVFSFile: file %ls couldn't be opened (vfs_load: %ld)", filename.string().c_str(), ret);
|
||||
return PSRETURN_CVFSFile_LoadFailed;
|
||||
}
|
||||
|
||||
|
||||
+17
-1
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -32,6 +32,22 @@ extern PIVFS g_VFS;
|
||||
|
||||
extern bool FileExists(const VfsPath& pathname);
|
||||
|
||||
/**
|
||||
* callback function type for file change notifications
|
||||
*/
|
||||
typedef LibError (*FileReloadFunc)(void* param, const VfsPath& path);
|
||||
|
||||
/**
|
||||
* register a callback function to be called by ReloadChangedFiles
|
||||
*/
|
||||
void RegisterFileReloadFunc(FileReloadFunc func, void* obj);
|
||||
|
||||
/**
|
||||
* delete a callback function registered with RegisterFileReloadFunc
|
||||
* (removes any with the same func and obj)
|
||||
*/
|
||||
void UnregisterFileReloadFunc(FileReloadFunc func, void* obj);
|
||||
|
||||
/**
|
||||
* poll for directory change notifications and reload all affected files.
|
||||
* must be called regularly (e.g. once a frame), else notifications
|
||||
|
||||
@@ -52,11 +52,18 @@ public:
|
||||
m_SimContext.m_Terrain = terrain;
|
||||
m_ComponentManager.LoadComponentTypes();
|
||||
|
||||
RegisterFileReloadFunc(ReloadChangedFileCB, this);
|
||||
|
||||
// m_EnableOOSLog = true; // TODO: this should be a command-line flag or similar
|
||||
|
||||
// (can't call ResetState here since the scripts haven't been loaded yet)
|
||||
}
|
||||
|
||||
~CSimulation2Impl()
|
||||
{
|
||||
UnregisterFileReloadFunc(ReloadChangedFileCB, this);
|
||||
}
|
||||
|
||||
CParamNode LoadXML(const std::wstring& name)
|
||||
{
|
||||
CParamNode ret;
|
||||
@@ -112,6 +119,11 @@ public:
|
||||
bool LoadScripts(const VfsPath& path);
|
||||
LibError ReloadChangedFile(const VfsPath& path);
|
||||
|
||||
static LibError ReloadChangedFileCB(void* param, const VfsPath& path)
|
||||
{
|
||||
return static_cast<CSimulation2Impl*>(param)->ReloadChangedFile(path);
|
||||
}
|
||||
|
||||
bool Update(int turnLength, const std::vector<SimulationCommand>& commands);
|
||||
void Interpolate(float frameLength, float frameOffset);
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ void CCmpProjectileManager::LaunchProjectile(entity_id_t source, CFixedVector3D
|
||||
std::wstring name = sourceVisual->GetProjectileActor();
|
||||
if (name.empty())
|
||||
{
|
||||
LOGERROR(L"Unit with actor '%ls' launched a projectile but has no actor on 'projectile' attachpoint", sourceVisual->GetActor().c_str());
|
||||
LOGERROR(L"Unit with actor '%ls' launched a projectile but has no actor on 'projectile' attachpoint", sourceVisual->GetActorShortName().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
|
||||
DEFAULT_COMPONENT_ALLOCATOR(VisualActor)
|
||||
|
||||
std::wstring m_ActorName;
|
||||
CUnit* m_Unit;
|
||||
|
||||
// Current animation state
|
||||
@@ -54,6 +55,9 @@ public:
|
||||
bool m_AnimOnce;
|
||||
float m_AnimSpeed;
|
||||
std::wstring m_SoundGroup;
|
||||
float m_AnimDesync;
|
||||
|
||||
float m_AnimSyncRepeatTime; // 0.0 if not synced
|
||||
|
||||
CCmpVisualActor() :
|
||||
m_Unit(NULL)
|
||||
@@ -93,23 +97,22 @@ public:
|
||||
|
||||
// TODO: we should do some fancy animation of under-construction buildings rising from the ground,
|
||||
// but for now we'll just use the foundation actor and ignore the normal one
|
||||
std::wstring name;
|
||||
if (paramNode.GetChild("Foundation").IsOk() && paramNode.GetChild("FoundationActor").IsOk())
|
||||
name = paramNode.GetChild("FoundationActor").ToString();
|
||||
m_ActorName = paramNode.GetChild("FoundationActor").ToString();
|
||||
else
|
||||
name = paramNode.GetChild("Actor").ToString();
|
||||
m_ActorName = paramNode.GetChild("Actor").ToString();
|
||||
|
||||
std::set<CStr> selections;
|
||||
m_Unit = context.GetUnitManager().CreateUnit(name, NULL, selections);
|
||||
m_Unit = context.GetUnitManager().CreateUnit(m_ActorName, NULL, selections);
|
||||
if (!m_Unit)
|
||||
{
|
||||
// The error will have already been logged
|
||||
return;
|
||||
}
|
||||
|
||||
SelectAnimation("idle", false, 0.f, L"");
|
||||
m_Unit->SetID(GetEntityId());
|
||||
|
||||
m_Unit->SetID(GetEntityId()); // TODO: is it safe to be using entity IDs for unit IDs?
|
||||
SelectAnimation("idle", false, 0.f, L"");
|
||||
}
|
||||
|
||||
virtual void Deinit(const CSimContext& context)
|
||||
@@ -127,10 +130,7 @@ public:
|
||||
|
||||
if (serialize.IsDebug())
|
||||
{
|
||||
if (m_Unit == NULL)
|
||||
serialize.StringASCII("actor", "[none]", 0, 256);
|
||||
else
|
||||
serialize.String("actor", m_Unit->GetObject().m_Base->m_Name, 0, 256);
|
||||
serialize.String("actor", m_ActorName, 0, 256);
|
||||
}
|
||||
|
||||
// TODO: store random variation. This ought to be synchronised across saved games
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
{
|
||||
const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg);
|
||||
if (m_Unit)
|
||||
m_Unit->SetPlayerID(msgData.to);
|
||||
m_Unit->GetModel().SetPlayerID(msgData.to);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -190,11 +190,11 @@ public:
|
||||
return m_Unit->GetModel().GetTransform().GetTranslation();
|
||||
}
|
||||
|
||||
virtual std::wstring GetActor()
|
||||
virtual std::wstring GetActorShortName()
|
||||
{
|
||||
if (!m_Unit)
|
||||
return L"";
|
||||
return m_Unit->GetObject().m_Base->m_Name;
|
||||
return m_Unit->GetObject().m_Base->m_ShortName;
|
||||
}
|
||||
|
||||
virtual std::wstring GetProjectileActor()
|
||||
@@ -212,14 +212,14 @@ public:
|
||||
if (!isfinite(speed) || speed < 0) // JS 'undefined' converts to NaN, which causes Bad Things
|
||||
speed = 1.f;
|
||||
|
||||
float desync = 0.05f; // TODO: make this an argument
|
||||
|
||||
m_AnimName = name;
|
||||
m_AnimOnce = once;
|
||||
m_AnimSpeed = speed;
|
||||
m_SoundGroup = soundgroup;
|
||||
m_AnimDesync = 0.05f; // TODO: make this an argument
|
||||
m_AnimSyncRepeatTime = 0.0f;
|
||||
|
||||
m_Unit->SetAnimationState(name, once, speed, desync, false, soundgroup.c_str());
|
||||
m_Unit->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed, m_AnimDesync, false, m_SoundGroup.c_str());
|
||||
}
|
||||
|
||||
virtual void SetAnimationSync(float actiontime, float repeattime)
|
||||
@@ -227,7 +227,9 @@ public:
|
||||
if (!m_Unit)
|
||||
return;
|
||||
|
||||
m_Unit->SetAnimationSync(actiontime, repeattime);
|
||||
m_AnimSyncRepeatTime = repeattime;
|
||||
|
||||
m_Unit->SetAnimationSync(actiontime, m_AnimSyncRepeatTime);
|
||||
}
|
||||
|
||||
virtual void SetShadingColour(fixed r, fixed g, fixed b, fixed a)
|
||||
@@ -238,6 +240,41 @@ public:
|
||||
m_Unit->GetModel().SetShadingColor(CColor(r.ToFloat(), g.ToFloat(), b.ToFloat(), a.ToFloat()));
|
||||
}
|
||||
|
||||
virtual void Hotload(const std::wstring& name)
|
||||
{
|
||||
if (!m_Unit)
|
||||
return;
|
||||
|
||||
if (name != m_ActorName)
|
||||
return;
|
||||
|
||||
std::set<CStr> selections;
|
||||
CUnit* newUnit = GetSimContext().GetUnitManager().CreateUnit(m_ActorName, NULL, selections);
|
||||
|
||||
if (!newUnit)
|
||||
return;
|
||||
|
||||
// Save some data from the old unit
|
||||
CColor shading = m_Unit->GetModel().GetShadingColor();
|
||||
size_t playerID = m_Unit->GetModel().GetPlayerID();
|
||||
|
||||
// Replace with the new unit
|
||||
GetSimContext().GetUnitManager().DeleteUnit(m_Unit);
|
||||
m_Unit = newUnit;
|
||||
|
||||
m_Unit->SetID(GetEntityId());
|
||||
|
||||
m_Unit->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed, m_AnimDesync, false, m_SoundGroup.c_str());
|
||||
|
||||
// We'll lose the exact synchronisation but we should at least make sure it's going at the correct rate
|
||||
if (m_AnimSyncRepeatTime != 0.0f)
|
||||
m_Unit->SetAnimationSync(0.0f, m_AnimSyncRepeatTime);
|
||||
|
||||
m_Unit->GetModel().SetShadingColor(shading);
|
||||
|
||||
m_Unit->GetModel().SetPlayerID(playerID);
|
||||
}
|
||||
|
||||
private:
|
||||
void Interpolate(const CSimContext& context, float frameTime, float frameOffset);
|
||||
void RenderSubmit(const CSimContext& context, SceneCollector& collector, const CFrustum& frustum, bool culling);
|
||||
|
||||
@@ -42,10 +42,10 @@ public:
|
||||
virtual CVector3D GetPosition() = 0;
|
||||
|
||||
/**
|
||||
* Return the filename of the actor that's being displayed, or the empty string on error.
|
||||
* Return the short name of the actor that's being displayed, or the empty string on error.
|
||||
* (Not safe for use in simulation code.)
|
||||
*/
|
||||
virtual std::wstring GetActor() = 0;
|
||||
virtual std::wstring GetActorShortName() = 0;
|
||||
|
||||
/**
|
||||
* Return the filename of the actor to be used for projectiles from this unit, or the empty string if none.
|
||||
@@ -84,6 +84,13 @@ public:
|
||||
*/
|
||||
virtual void SetShadingColour(fixed r, fixed g, fixed b, fixed a) = 0;
|
||||
|
||||
/**
|
||||
* Called when an actor file has been modified and reloaded dynamically.
|
||||
* If this component uses the named actor file, it should regenerate its actor
|
||||
* to pick up the new definitions.
|
||||
*/
|
||||
virtual void Hotload(const std::wstring& name) = 0;
|
||||
|
||||
DECLARE_INTERFACE_TYPE(Visual)
|
||||
};
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ struct ActorViewerImpl : public Scene
|
||||
public:
|
||||
ActorViewerImpl()
|
||||
: Entity(INVALID_ENTITY), Terrain(), ColladaManager(), MeshManager(ColladaManager), SkeletonAnimManager(ColladaManager),
|
||||
ObjectManager(MeshManager, SkeletonAnimManager), UnitManager(), Simulation2(&UnitManager, &Terrain)
|
||||
UnitManager(), Simulation2(&UnitManager, &Terrain), ObjectManager(MeshManager, SkeletonAnimManager, Simulation2)
|
||||
{
|
||||
UnitManager.SetObjectManager(ObjectManager);
|
||||
}
|
||||
|
||||
@@ -131,32 +131,21 @@ QUERYHANDLER(GetObjectSettings)
|
||||
{
|
||||
View* view = View::GetView(msg->view);
|
||||
CSimulation2* simulation = view->GetSimulation2();
|
||||
if (simulation)
|
||||
{
|
||||
sObjectSettings settings;
|
||||
settings.player = 0;
|
||||
|
||||
CmpPtr<ICmpOwnership> cmpOwner (*simulation, view->GetEntityId(msg->id));
|
||||
if (!cmpOwner.null())
|
||||
{
|
||||
int32_t player = cmpOwner->GetOwner();
|
||||
if (player != -1)
|
||||
settings.player = player;
|
||||
}
|
||||
|
||||
// TODO: selections
|
||||
|
||||
msg->settings = settings;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
CUnit* unit = view->GetUnit(msg->id);
|
||||
if (! unit) return;
|
||||
|
||||
sObjectSettings settings;
|
||||
settings.player = unit->GetPlayerID();
|
||||
settings.player = 0;
|
||||
|
||||
CmpPtr<ICmpOwnership> cmpOwner (*simulation, view->GetEntityId(msg->id));
|
||||
if (!cmpOwner.null())
|
||||
{
|
||||
int32_t player = cmpOwner->GetOwner();
|
||||
if (player != -1)
|
||||
settings.player = player;
|
||||
}
|
||||
|
||||
// TODO: selections
|
||||
|
||||
/*
|
||||
// Get the unit's possible variants and selected variants
|
||||
std::vector<std::vector<CStr> > groups = unit->GetObject().m_Base->GetVariantGroups();
|
||||
const std::set<CStr>& selections = unit->GetActorSelections();
|
||||
@@ -194,6 +183,8 @@ QUERYHANDLER(GetObjectSettings)
|
||||
|
||||
settings.variantgroups = variantgroups;
|
||||
settings.selections = std::vector<std::wstring> (selections_set.begin(), selections_set.end()); // convert set->vector
|
||||
*/
|
||||
|
||||
msg->settings = settings;
|
||||
}
|
||||
|
||||
@@ -208,27 +199,19 @@ BEGIN_COMMAND(SetObjectSettings)
|
||||
|
||||
View* view = View::GetView(msg->view);
|
||||
CSimulation2* simulation = view->GetSimulation2();
|
||||
if (simulation)
|
||||
{
|
||||
CmpPtr<ICmpOwnership> cmpOwner (*simulation, view->GetEntityId(msg->id));
|
||||
m_PlayerOld = 0;
|
||||
if (!cmpOwner.null())
|
||||
{
|
||||
int32_t player = cmpOwner->GetOwner();
|
||||
if (player != -1)
|
||||
m_PlayerOld = player;
|
||||
}
|
||||
|
||||
// TODO: selections
|
||||
}
|
||||
else
|
||||
CmpPtr<ICmpOwnership> cmpOwner (*simulation, view->GetEntityId(msg->id));
|
||||
m_PlayerOld = 0;
|
||||
if (!cmpOwner.null())
|
||||
{
|
||||
CUnit* unit = view->GetUnit(msg->id);
|
||||
if (! unit) return;
|
||||
m_PlayerOld = unit->GetPlayerID();
|
||||
m_SelectionsOld = unit->GetActorSelections();
|
||||
int32_t player = cmpOwner->GetOwner();
|
||||
if (player != -1)
|
||||
m_PlayerOld = player;
|
||||
}
|
||||
|
||||
// TODO: selections
|
||||
// m_SelectionsOld = unit->GetActorSelections();
|
||||
|
||||
m_PlayerNew = (size_t)settings.player;
|
||||
|
||||
std::vector<std::wstring> selections = *settings.selections;
|
||||
@@ -255,22 +238,13 @@ private:
|
||||
{
|
||||
View* view = View::GetView(msg->view);
|
||||
CSimulation2* simulation = view->GetSimulation2();
|
||||
if (simulation)
|
||||
{
|
||||
CmpPtr<ICmpOwnership> cmpOwner (*simulation, view->GetEntityId(msg->id));
|
||||
if (!cmpOwner.null())
|
||||
cmpOwner->SetOwner(player);
|
||||
// TODO: selections
|
||||
|
||||
return;
|
||||
}
|
||||
CmpPtr<ICmpOwnership> cmpOwner (*simulation, view->GetEntityId(msg->id));
|
||||
if (!cmpOwner.null())
|
||||
cmpOwner->SetOwner(player);
|
||||
|
||||
CUnit* unit = view->GetUnit(msg->id);
|
||||
if (! unit) return;
|
||||
|
||||
unit->SetPlayerID(player);
|
||||
|
||||
unit->SetActorSelections(selections);
|
||||
// TODO: selections
|
||||
// unit->SetActorSelections(selections);
|
||||
}
|
||||
};
|
||||
END_COMMAND(SetObjectSettings);
|
||||
|
||||
@@ -261,11 +261,6 @@ CCamera& ViewGame::GetCamera()
|
||||
return *g_Game->GetView()->GetCamera();
|
||||
}
|
||||
|
||||
CUnit* ViewGame::GetUnit(AtlasMessage::ObjectID id)
|
||||
{
|
||||
return g_Game->GetWorld()->GetUnitManager().FindByID(id);
|
||||
}
|
||||
|
||||
bool ViewGame::WantsHighFramerate()
|
||||
{
|
||||
if (g_Game->GetView()->GetCinema()->IsPlaying())
|
||||
|
||||
@@ -40,7 +40,6 @@ public:
|
||||
virtual CCamera& GetCamera() = 0;
|
||||
virtual CSimulation2* GetSimulation2() { return NULL; }
|
||||
virtual entity_id_t GetEntityId(AtlasMessage::ObjectID obj) { return (entity_id_t)obj; }
|
||||
virtual CUnit* GetUnit(AtlasMessage::ObjectID UNUSED(id)) { return NULL; }
|
||||
virtual bool WantsHighFramerate() { return false; }
|
||||
|
||||
virtual void SetParam(const std::wstring& name, bool value);
|
||||
@@ -77,7 +76,6 @@ public:
|
||||
virtual void Update(float frameLength);
|
||||
virtual void Render();
|
||||
virtual CCamera& GetCamera();
|
||||
virtual CUnit* GetUnit(AtlasMessage::ObjectID id);
|
||||
virtual CSimulation2* GetSimulation2();
|
||||
virtual bool WantsHighFramerate();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user