EterGrnLib/Thing.cpp
#include "StdAfx.h"
#include "../eterbase/Debug.h"
#include "Thing.h"
#include "ThingInstance.h"
struct SThingModelCache
{
CGrannyModel* models;
int modelCount;
int refCount;
bool deviceObjectsCreated;
};
static std::unordered_map<std::string, SThingModelCache> g_ThingModelCache;
bool LoadThingModelsCached(const std::string& fileName, granny_file_info* pInfo, CGrannyModel*& outModels)
{
auto it = g_ThingModelCache.find(fileName);
if (it != g_ThingModelCache.end())
{
it->second.refCount++;
outModels = it->second.models;
return true;
}
int modelCount = pInfo->ModelCount;
CGrannyModel* models = new CGrannyModel[modelCount];
for (int m = 0; m < modelCount; ++m)
{
if (!models[m].CreateFromGrannyModelPointer(pInfo->Models[m]))
{
delete[] models;
return false;
}
}
g_ThingModelCache[fileName] = { models, modelCount, 1, false };
outModels = models;
return true;
}
void ReleaseThingModelsCached(const std::string& fileName)
{
auto it = g_ThingModelCache.find(fileName);
if (it == g_ThingModelCache.end())
return;
it->second.refCount--;
if (it->second.refCount <= 0)
{
if (it->second.deviceObjectsCreated)
{
for (int m = 0; m < it->second.modelCount; ++m)
it->second.models[m].DestroyDeviceObjects();
}
delete[] it->second.models;
g_ThingModelCache.erase(it);
}
}
struct SThingMotionCache
{
CGrannyMotion* motions;
int motionCount;
int refCount;
};
static std::unordered_map<std::string, SThingMotionCache> g_ThingMotionCache;
bool LoadThingMotionsCached(const std::string& fileName, granny_file_info* pInfo, CGrannyMotion*& outMotions)
{
auto it = g_ThingMotionCache.find(fileName);
if (it != g_ThingMotionCache.end())
{
it->second.refCount++;
outMotions = it->second.motions;
return true;
}
int motionCount = pInfo->AnimationCount;
CGrannyMotion* motions = new CGrannyMotion[motionCount];
for (int m = 0; m < motionCount; ++m)
{
if (!motions[m].BindGrannyAnimation(pInfo->Animations[m]))
{
delete[] motions;
return false;
}
}
g_ThingMotionCache[fileName] = { motions, motionCount, 1 };
outMotions = motions;
return true;
}
void ReleaseThingMotionsCached(const std::string& fileName)
{
auto it = g_ThingMotionCache.find(fileName);
if (it == g_ThingMotionCache.end())
return;
it->second.refCount--;
if (it->second.refCount <= 0)
{
delete[] it->second.motions;
g_ThingMotionCache.erase(it);
}
}
CGraphicThing::CGraphicThing(const char* c_szFileName) : CResource(c_szFileName)
{
Initialize();
}
CGraphicThing::~CGraphicThing()
{
Clear();
}
void CGraphicThing::Initialize()
{
m_pgrnFile = NULL;
m_pgrnFileInfo = NULL;
m_pgrnAni = NULL;
m_models = NULL;
m_motions = NULL;
}
void CGraphicThing::OnClear()
{
if (m_motions)
{
ReleaseThingMotionsCached(GetFileNameString());
m_motions = nullptr;
}
if (m_models)
{
ReleaseThingModelsCached(GetFileNameString());
m_models = nullptr;
}
if (m_pgrnFile)
{
GrannyFreeFile(m_pgrnFile);
m_pgrnFile = nullptr;
}
m_pgrnFileInfo = nullptr;
m_pgrnAni = nullptr;
}
CGraphicThing::TType CGraphicThing::Type()
{
static TType s_type = StringToType("CGraphicThing");
return s_type;
}
bool CGraphicThing::OnIsEmpty() const
{
return m_pgrnFile ? false : true;
}
bool CGraphicThing::OnIsType(TType type)
{
if (CGraphicThing::Type() == type)
return true;
return CResource::OnIsType(type);
}
bool CGraphicThing::CreateDeviceObjects()
{
if (!m_pgrnFileInfo || !m_models)
return true;
auto it = g_ThingModelCache.find(GetFileNameString());
if (it == g_ThingModelCache.end())
return true;
if (it->second.deviceObjectsCreated)
return true;
for (int m = 0; m < it->second.modelCount; ++m)
it->second.models[m].CreateDeviceObjects();
it->second.deviceObjectsCreated = true;
return true;
}
void CGraphicThing::DestroyDeviceObjects()
{
//if (!m_pgrnFileInfo)
// return;
//for (int m = 0; m < m_pgrnFileInfo->ModelCount; ++m)
//{
// CGrannyModel& rModel = m_models[m];
// rModel.DestroyDeviceObjects();
//}
}
bool CGraphicThing::CheckModelIndex(int iModel) const
{
if (!m_pgrnFileInfo)
{
Tracef("m_pgrnFileInfo == NULL: %s\n", GetFileName());
return false;
}
assert(m_pgrnFileInfo != NULL);
if (iModel < 0)
return false;
if (iModel >= m_pgrnFileInfo->ModelCount)
return false;
return true;
}
bool CGraphicThing::CheckMotionIndex(int iMotion) const
{
// Temporary
if (!m_pgrnFileInfo)
return false;
// Temporary
assert(m_pgrnFileInfo != NULL);
if (iMotion < 0)
return false;
if (iMotion >= m_pgrnFileInfo->AnimationCount)
return false;
return true;
}
CGrannyModel* CGraphicThing::GetModelPointer(int iModel)
{
assert(CheckModelIndex(iModel));
assert(m_models != NULL);
return m_models + iModel;
}
CGrannyMotion* CGraphicThing::GetMotionPointer(int iMotion)
{
assert(CheckMotionIndex(iMotion));
if (iMotion >= m_pgrnFileInfo->AnimationCount)
return NULL;
assert(m_motions != NULL);
return (m_motions + iMotion);
}
int CGraphicThing::GetModelCount() const
{
if (!m_pgrnFileInfo)
return 0;
return (m_pgrnFileInfo->ModelCount);
}
int CGraphicThing::GetMotionCount() const
{
if (!m_pgrnFileInfo)
return 0;
return (m_pgrnFileInfo->AnimationCount);
}
bool CGraphicThing::OnLoad(int iSize, const void* c_pvBuf)
{
if (!c_pvBuf)
return false;
m_pgrnFile = GrannyReadEntireFileFromMemory(iSize, (void*)c_pvBuf);
if (!m_pgrnFile)
return false;
m_pgrnFileInfo = GrannyGetFileInfo(m_pgrnFile);
if (!m_pgrnFileInfo)
return false;
LoadModels();
LoadMotions();
return true;
}
// SUPPORT_LOCAL_TEXTURE
static std::string gs_modelLocalPath;
const std::string& GetModelLocalPath()
{
return gs_modelLocalPath;
}
// END_OF_SUPPORT_LOCAL_TEXTURE
bool CGraphicThing::LoadModels()
{
assert(m_pgrnFile != NULL);
assert(m_models == NULL);
if (m_pgrnFileInfo->ModelCount <= 0)
return false;
const std::string& fileName = GetFileNameString();
if (!LoadThingModelsCached(fileName, m_pgrnFileInfo, m_models))
return false;
GrannyFreeFileSection(m_pgrnFile, GrannyStandardRigidVertexSection);
GrannyFreeFileSection(m_pgrnFile, GrannyStandardRigidIndexSection);
GrannyFreeFileSection(m_pgrnFile, GrannyStandardDeformableIndexSection);
GrannyFreeFileSection(m_pgrnFile, GrannyStandardTextureSection);
return true;
}
bool CGraphicThing::LoadMotions()
{
assert(m_pgrnFile != NULL);
assert(m_motions == NULL);
if (m_pgrnFileInfo->AnimationCount <= 0)
return false;
const std::string& fileName = GetFileNameString();
if (!LoadThingMotionsCached(fileName, m_pgrnFileInfo, m_motions))
return false;
return true;
}


