mirror of https://github.com/AxioDL/metaforce.git
Several resource management bug fixes
This commit is contained in:
parent
d440c0ff43
commit
c8d44d181b
|
@ -60,12 +60,18 @@ void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPat
|
||||||
const athena::io::YAMLNode* root = reader.getRootNode();
|
const athena::io::YAMLNode* root = reader.getRootNode();
|
||||||
for (const auto& p : root->m_mapChildren)
|
for (const auto& p : root->m_mapChildren)
|
||||||
{
|
{
|
||||||
|
/* Hash as lowercase since lookup is case-insensitive */
|
||||||
|
std::string pLower = p.first;
|
||||||
|
std::transform(pLower.cbegin(), pLower.cend(), pLower.begin(), tolower);
|
||||||
|
|
||||||
/* Avoid redundant filesystem access for re-caches */
|
/* Avoid redundant filesystem access for re-caches */
|
||||||
if (m_catalogNameToTag.find(p.first) != m_catalogNameToTag.cend())
|
if (m_catalogNameToTag.find(pLower) != m_catalogNameToTag.cend())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
athena::io::YAMLNode& node = *p.second;
|
athena::io::YAMLNode& node = *p.second;
|
||||||
hecl::ProjectPath path(m_proj->getProjectWorkingPath(), node.m_scalarString);
|
hecl::ProjectPath path(m_proj->getProjectWorkingPath(), node.m_scalarString);
|
||||||
|
if (node.m_scalarString == "MP1/SamGunFx/PowerBeam.wpsm.yaml")
|
||||||
|
printf("");
|
||||||
if (node.m_type == YAML_SCALAR_NODE)
|
if (node.m_type == YAML_SCALAR_NODE)
|
||||||
{
|
{
|
||||||
path = hecl::ProjectPath(m_proj->getProjectWorkingPath(), node.m_scalarString);
|
path = hecl::ProjectPath(m_proj->getProjectWorkingPath(), node.m_scalarString);
|
||||||
|
@ -84,7 +90,7 @@ void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPat
|
||||||
if (pathTag)
|
if (pathTag)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
||||||
m_catalogNameToTag[p.first] = pathTag;
|
m_catalogNameToTag[pLower] = pathTag;
|
||||||
WriteNameTag(nameWriter, pathTag, p.first);
|
WriteNameTag(nameWriter, pathTag, p.first);
|
||||||
#if 0
|
#if 0
|
||||||
fprintf(stderr, "%s %s %08X\n",
|
fprintf(stderr, "%s %s %08X\n",
|
||||||
|
@ -144,25 +150,29 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path,
|
||||||
if (m_pathToTag.find(path.hash()) != m_pathToTag.cend())
|
if (m_pathToTag.find(path.hash()) != m_pathToTag.cend())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/* Try as glob */
|
||||||
|
hecl::ProjectPath asGlob = path.getWithExtension(_S(".*"), true);
|
||||||
|
if (m_pathToTag.find(asGlob.hash()) != m_pathToTag.cend())
|
||||||
|
return true;
|
||||||
|
|
||||||
/* Classify intermediate into tag */
|
/* Classify intermediate into tag */
|
||||||
SObjectTag pathTag = BuildTagFromPath(path, m_backgroundBlender);
|
SObjectTag pathTag = BuildTagFromPath(path, m_backgroundBlender);
|
||||||
if (pathTag)
|
if (pathTag)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
||||||
m_tagToPath[pathTag] = path;
|
bool useGlob = false;
|
||||||
m_pathToTag[path.hash()] = pathTag;
|
|
||||||
WriteTag(cacheWriter, pathTag, path);
|
|
||||||
#if DUMP_CACHE_FILL
|
|
||||||
DumpCacheAdd(pathTag, path);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Special multi-resource intermediates */
|
/* Special multi-resource intermediates */
|
||||||
if (pathTag.type == SBIG('ANCS'))
|
if (pathTag.type == SBIG('ANCS'))
|
||||||
{
|
{
|
||||||
hecl::BlenderConnection& conn = m_backgroundBlender.getBlenderConnection();
|
hecl::BlenderConnection& conn = m_backgroundBlender.getBlenderConnection();
|
||||||
if (!conn.openBlend(path) || conn.getBlendType() != hecl::BlenderConnection::BlendType::Actor)
|
if (!conn.openBlend(path) || conn.getBlendType() != hecl::BlenderConnection::BlendType::Actor)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* Transform tag to glob */
|
||||||
|
pathTag = {SBIG('ANCS'), asGlob.hash().val32()};
|
||||||
|
useGlob = true;
|
||||||
|
|
||||||
hecl::BlenderConnection::DataStream ds = conn.beginData();
|
hecl::BlenderConnection::DataStream ds = conn.beginData();
|
||||||
std::vector<std::string> armatureNames = ds.getArmatureNames();
|
std::vector<std::string> armatureNames = ds.getArmatureNames();
|
||||||
std::vector<std::string> subtypeNames = ds.getSubtypeNames();
|
std::vector<std::string> subtypeNames = ds.getSubtypeNames();
|
||||||
|
@ -171,7 +181,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path,
|
||||||
for (const std::string& arm : armatureNames)
|
for (const std::string& arm : armatureNames)
|
||||||
{
|
{
|
||||||
hecl::SystemStringView sysStr(arm);
|
hecl::SystemStringView sysStr(arm);
|
||||||
hecl::ProjectPath subPath = path.ensureAuxInfo(sysStr.sys_str() + _S(".CINF"));
|
hecl::ProjectPath subPath = asGlob.ensureAuxInfo(sysStr.sys_str() + _S(".CINF"));
|
||||||
SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender);
|
SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender);
|
||||||
m_tagToPath[pathTag] = subPath;
|
m_tagToPath[pathTag] = subPath;
|
||||||
m_pathToTag[subPath.hash()] = pathTag;
|
m_pathToTag[subPath.hash()] = pathTag;
|
||||||
|
@ -184,7 +194,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path,
|
||||||
for (const std::string& sub : subtypeNames)
|
for (const std::string& sub : subtypeNames)
|
||||||
{
|
{
|
||||||
hecl::SystemStringView sysStr(sub);
|
hecl::SystemStringView sysStr(sub);
|
||||||
hecl::ProjectPath subPath = path.ensureAuxInfo(sysStr.sys_str() + _S(".CSKR"));
|
hecl::ProjectPath subPath = asGlob.ensureAuxInfo(sysStr.sys_str() + _S(".CSKR"));
|
||||||
SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender);
|
SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender);
|
||||||
m_tagToPath[pathTag] = subPath;
|
m_tagToPath[pathTag] = subPath;
|
||||||
m_pathToTag[subPath.hash()] = pathTag;
|
m_pathToTag[subPath.hash()] = pathTag;
|
||||||
|
@ -197,7 +207,7 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path,
|
||||||
for (const std::string& act : actionNames)
|
for (const std::string& act : actionNames)
|
||||||
{
|
{
|
||||||
hecl::SystemStringView sysStr(act);
|
hecl::SystemStringView sysStr(act);
|
||||||
hecl::ProjectPath subPath = path.ensureAuxInfo(sysStr.sys_str() + _S(".ANIM"));
|
hecl::ProjectPath subPath = asGlob.ensureAuxInfo(sysStr.sys_str() + _S(".ANIM"));
|
||||||
SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender);
|
SObjectTag pathTag = BuildTagFromPath(subPath, m_backgroundBlender);
|
||||||
m_tagToPath[pathTag] = subPath;
|
m_tagToPath[pathTag] = subPath;
|
||||||
m_pathToTag[subPath.hash()] = pathTag;
|
m_pathToTag[subPath.hash()] = pathTag;
|
||||||
|
@ -207,6 +217,15 @@ bool ProjectResourceFactoryBase::AddFileToIndex(const hecl::ProjectPath& path,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cache in-memory */
|
||||||
|
const hecl::ProjectPath& usePath = useGlob ? asGlob : path;
|
||||||
|
m_tagToPath[pathTag] = usePath;
|
||||||
|
m_pathToTag[usePath.hash()] = pathTag;
|
||||||
|
WriteTag(cacheWriter, pathTag, usePath);
|
||||||
|
#if DUMP_CACHE_FILL
|
||||||
|
DumpCacheAdd(pathTag, usePath);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -239,6 +258,7 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Index the regular file */
|
||||||
AddFileToIndex(path, cacheWriter);
|
AddFileToIndex(path, cacheWriter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +306,7 @@ void ProjectResourceFactoryBase::BackgroundIndexProc()
|
||||||
path = path.ensureAuxInfo(sys.sys_str());
|
path = path.ensureAuxInfo(sys.sys_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.isFile())
|
if (path.isFileOrGlob())
|
||||||
{
|
{
|
||||||
SObjectTag pathTag(type, id);
|
SObjectTag pathTag(type, id);
|
||||||
m_tagToPath[pathTag] = path;
|
m_tagToPath[pathTag] = path;
|
||||||
|
@ -317,8 +337,10 @@ void ProjectResourceFactoryBase::BackgroundIndexProc()
|
||||||
auto search = m_tagToPath.find(SObjectTag(FourCC(), uint32_t(id)));
|
auto search = m_tagToPath.find(SObjectTag(FourCC(), uint32_t(id)));
|
||||||
if (search != m_tagToPath.cend())
|
if (search != m_tagToPath.cend())
|
||||||
{
|
{
|
||||||
m_catalogNameToTag[child.first] = search->first;
|
std::string chLower = child.first;
|
||||||
WriteNameTag(nameWriter, search->first, child.first);
|
std::transform(chLower.cbegin(), chLower.cend(), chLower.begin(), tolower);
|
||||||
|
m_catalogNameToTag[chLower] = search->first;
|
||||||
|
WriteNameTag(nameWriter, search->first, chLower);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,7 +434,7 @@ void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& t
|
||||||
m_workingPath = path;
|
m_workingPath = path;
|
||||||
|
|
||||||
/* Ensure requested resource is on the filesystem */
|
/* Ensure requested resource is on the filesystem */
|
||||||
if (!path.isFile())
|
if (!path.isFileOrGlob())
|
||||||
{
|
{
|
||||||
Log.report(logvisor::Error, _S("unable to find resource path '%s'"),
|
Log.report(logvisor::Error, _S("unable to find resource path '%s'"),
|
||||||
path.getRelativePath().c_str());
|
path.getRelativePath().c_str());
|
||||||
|
@ -523,7 +545,7 @@ ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag,
|
||||||
std::experimental::optional<athena::io::FileReader>& fr)
|
std::experimental::optional<athena::io::FileReader>& fr)
|
||||||
{
|
{
|
||||||
/* Ensure requested resource is on the filesystem */
|
/* Ensure requested resource is on the filesystem */
|
||||||
if (!path.isFile())
|
if (!path.isFileOrGlob())
|
||||||
{
|
{
|
||||||
Log.report(logvisor::Error, _S("unable to find resource path '%s'"),
|
Log.report(logvisor::Error, _S("unable to find resource path '%s'"),
|
||||||
path.getAbsolutePath().c_str());
|
path.getAbsolutePath().c_str());
|
||||||
|
@ -724,8 +746,11 @@ bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag)
|
||||||
|
|
||||||
const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(const char* name) const
|
const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(const char* name) const
|
||||||
{
|
{
|
||||||
|
std::string lower = name;
|
||||||
|
std::transform(lower.cbegin(), lower.cend(), lower.begin(), tolower);
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lk(const_cast<ProjectResourceFactoryBase*>(this)->m_backgroundIndexMutex);
|
std::unique_lock<std::mutex> lk(const_cast<ProjectResourceFactoryBase*>(this)->m_backgroundIndexMutex);
|
||||||
auto search = m_catalogNameToTag.find(name);
|
auto search = m_catalogNameToTag.find(lower);
|
||||||
if (search == m_catalogNameToTag.end())
|
if (search == m_catalogNameToTag.end())
|
||||||
{
|
{
|
||||||
if (m_backgroundRunning)
|
if (m_backgroundRunning)
|
||||||
|
@ -734,7 +759,7 @@ const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(const ch
|
||||||
{
|
{
|
||||||
lk.unlock();
|
lk.unlock();
|
||||||
lk.lock();
|
lk.lock();
|
||||||
search = m_catalogNameToTag.find(name);
|
search = m_catalogNameToTag.find(lower);
|
||||||
if (search != m_catalogNameToTag.end())
|
if (search != m_catalogNameToTag.end())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,10 +64,16 @@ SObjectTag ProjectResourceFactoryMP1::BuildTagFromPath(const hecl::ProjectPath&
|
||||||
else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S(".ANIM")))
|
else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _S(".ANIM")))
|
||||||
return SObjectTag(SBIG('ANIM'), path.hash().val32());
|
return SObjectTag(SBIG('ANIM'), path.hash().val32());
|
||||||
|
|
||||||
if (hecl::IsPathBlend(path))
|
hecl::ProjectPath asBlend;
|
||||||
|
if (path.getPathType() == hecl::ProjectPath::Type::Glob)
|
||||||
|
asBlend = path.getWithExtension(_S(".blend"), true);
|
||||||
|
else
|
||||||
|
asBlend = path;
|
||||||
|
|
||||||
|
if (hecl::IsPathBlend(asBlend))
|
||||||
{
|
{
|
||||||
hecl::BlenderConnection& conn = btok.getBlenderConnection();
|
hecl::BlenderConnection& conn = btok.getBlenderConnection();
|
||||||
if (!conn.openBlend(path))
|
if (!conn.openBlend(asBlend))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
switch (conn.getBlendType())
|
switch (conn.getBlendType())
|
||||||
|
@ -113,49 +119,75 @@ SObjectTag ProjectResourceFactoryMP1::BuildTagFromPath(const hecl::ProjectPath&
|
||||||
yaml_parser_set_input_file(reader.getParser(), fp);
|
yaml_parser_set_input_file(reader.getParser(), fp);
|
||||||
|
|
||||||
SObjectTag resTag;
|
SObjectTag resTag;
|
||||||
if (reader.ClassTypeOperation([&](const char* className) -> bool {
|
if (reader.ClassTypeOperation([&](const char* className) -> bool
|
||||||
if (!strcmp(className, "GPSM"))
|
{
|
||||||
{
|
if (!strcmp(className, "GPSM"))
|
||||||
resTag.type = SBIG('PART');
|
{
|
||||||
return true;
|
resTag.type = SBIG('PART');
|
||||||
}
|
return true;
|
||||||
else if (!strcmp(className, "FONT"))
|
}
|
||||||
{
|
if (!strcmp(className, "SWSH"))
|
||||||
resTag.type = SBIG('FONT');
|
{
|
||||||
return true;
|
resTag.type = SBIG('SWHC');
|
||||||
}
|
return true;
|
||||||
else if (!strcmp(className, "urde::DNAMP1::EVNT"))
|
}
|
||||||
{
|
if (!strcmp(className, "ELSM"))
|
||||||
resTag.type = SBIG('EVNT');
|
{
|
||||||
return true;
|
resTag.type = SBIG('ELSC');
|
||||||
}
|
return true;
|
||||||
else if (!strcmp(className, "urde::DGRP"))
|
}
|
||||||
{
|
if (!strcmp(className, "WPSM"))
|
||||||
resTag.type = SBIG('DGRP');
|
{
|
||||||
return true;
|
resTag.type = SBIG('WPSC');
|
||||||
}
|
return true;
|
||||||
else if (!strcmp(className, "urde::DNAMP1::STRG"))
|
}
|
||||||
{
|
if (!strcmp(className, "CRSM"))
|
||||||
resTag.type = SBIG('STRG');
|
{
|
||||||
return true;
|
resTag.type = SBIG('CRSC');
|
||||||
}
|
return true;
|
||||||
else if (!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerRes") ||
|
}
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGunRes") ||
|
if (!strcmp(className, "DPSM"))
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakSlideShow") ||
|
{
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakPlayer") ||
|
resTag.type = SBIG('DPSC');
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakCameraBob"))
|
return true;
|
||||||
{
|
}
|
||||||
resTag.type = SBIG('CTWK');
|
else if (!strcmp(className, "FONT"))
|
||||||
return true;
|
{
|
||||||
}
|
resTag.type = SBIG('FONT');
|
||||||
else if (!strcmp(className, "DataSpec::DNAMP1::HINT"))
|
return true;
|
||||||
{
|
}
|
||||||
resTag.type = SBIG('HINT');
|
else if (!strcmp(className, "urde::DNAMP1::EVNT"))
|
||||||
return true;
|
{
|
||||||
}
|
resTag.type = SBIG('EVNT');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(className, "urde::DGRP"))
|
||||||
|
{
|
||||||
|
resTag.type = SBIG('DGRP');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(className, "urde::DNAMP1::STRG"))
|
||||||
|
{
|
||||||
|
resTag.type = SBIG('STRG');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerRes") ||
|
||||||
|
!strcmp(className, "DataSpec::DNAMP1::CTweakGunRes") ||
|
||||||
|
!strcmp(className, "DataSpec::DNAMP1::CTweakSlideShow") ||
|
||||||
|
!strcmp(className, "DataSpec::DNAMP1::CTweakPlayer") ||
|
||||||
|
!strcmp(className, "DataSpec::DNAMP1::CTweakCameraBob"))
|
||||||
|
{
|
||||||
|
resTag.type = SBIG('CTWK');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(className, "DataSpec::DNAMP1::HINT"))
|
||||||
|
{
|
||||||
|
resTag.type = SBIG('HINT');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
resTag.id = path.hash().val32();
|
resTag.id = path.hash().val32();
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
|
@ -29,7 +29,7 @@ void ViewManager::BuildTestPART(urde::IObjectStore& objStore)
|
||||||
m_modelTest = objStore.GetObj("MP1/Shared/CMDL_B2B41738.blend");
|
m_modelTest = objStore.GetObj("MP1/Shared/CMDL_B2B41738.blend");
|
||||||
CModel* ridley = m_modelTest.GetObj();
|
CModel* ridley = m_modelTest.GetObj();
|
||||||
#if 1
|
#if 1
|
||||||
SObjectTag samusCharSet = m_projManager.TagFromPath(_S("MP1/Shared/ANCS_77289A4A.blend"));
|
SObjectTag samusCharSet = m_projManager.TagFromPath(_S("MP1/Shared/ANCS_77289A4A.*"));
|
||||||
SObjectTag platModel = m_projManager.TagFromPath(_S("MP1/Shared/CMDL_6FA561D0.blend"));
|
SObjectTag platModel = m_projManager.TagFromPath(_S("MP1/Shared/CMDL_6FA561D0.blend"));
|
||||||
SObjectTag bgModel = m_projManager.TagFromPath(_S("MP1/Shared/CMDL_BC34D54C.blend"));
|
SObjectTag bgModel = m_projManager.TagFromPath(_S("MP1/Shared/CMDL_BC34D54C.blend"));
|
||||||
CAnimRes samusAnimRes(samusCharSet.id, 2, zeus::CVector3f{2.f, 2.f, 2.f}, 1, true);
|
CAnimRes samusAnimRes(samusCharSet.id, 2, zeus::CVector3f{2.f, 2.f, 2.f}, 1, true);
|
||||||
|
|
|
@ -85,7 +85,7 @@ add_library(RuntimeCommon
|
||||||
IObj.hpp
|
IObj.hpp
|
||||||
IVParamObj.hpp
|
IVParamObj.hpp
|
||||||
CTimeProvider.hpp CTimeProvider.cpp
|
CTimeProvider.hpp CTimeProvider.cpp
|
||||||
CToken.hpp
|
CToken.hpp CToken.cpp
|
||||||
CFactoryMgr.hpp CFactoryMgr.cpp
|
CFactoryMgr.hpp CFactoryMgr.cpp
|
||||||
CPakFile.hpp CPakFile.cpp
|
CPakFile.hpp CPakFile.cpp
|
||||||
CStringExtras.hpp
|
CStringExtras.hpp
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
#include "CToken.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
u16 CObjectReference::RemoveReference()
|
||||||
|
{
|
||||||
|
--x0_refCount;
|
||||||
|
if (x0_refCount == 0)
|
||||||
|
{
|
||||||
|
if (x10_object)
|
||||||
|
Unload();
|
||||||
|
if (IsLoading())
|
||||||
|
CancelLoad();
|
||||||
|
if (xC_objectStore)
|
||||||
|
xC_objectStore->ObjectUnreferenced(x4_objTag);
|
||||||
|
}
|
||||||
|
return x0_refCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
CObjectReference::CObjectReference(IObjectStore& objStore, std::unique_ptr<IObj>&& obj,
|
||||||
|
const SObjectTag& objTag, CVParamTransfer buildParams)
|
||||||
|
: x4_objTag(objTag), xC_objectStore(&objStore),
|
||||||
|
x10_object(obj.release()), x14_params(buildParams) {}
|
||||||
|
CObjectReference::CObjectReference(std::unique_ptr<IObj>&& obj)
|
||||||
|
: x10_object(obj.release()) {}
|
||||||
|
|
||||||
|
void CObjectReference::Unlock()
|
||||||
|
{
|
||||||
|
--x2_lockCount;
|
||||||
|
if (x2_lockCount)
|
||||||
|
return;
|
||||||
|
if (x10_object && xC_objectStore)
|
||||||
|
Unload();
|
||||||
|
else if (IsLoading())
|
||||||
|
CancelLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CObjectReference::Lock()
|
||||||
|
{
|
||||||
|
++x2_lockCount;
|
||||||
|
if (!x10_object && !x3_loading)
|
||||||
|
{
|
||||||
|
IFactory& fac = xC_objectStore->GetFactory();
|
||||||
|
fac.BuildAsync(x4_objTag, x14_params, &x10_object, this);
|
||||||
|
x3_loading = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CObjectReference::CancelLoad()
|
||||||
|
{
|
||||||
|
if (xC_objectStore && IsLoading())
|
||||||
|
{
|
||||||
|
xC_objectStore->GetFactory().CancelBuild(x4_objTag);
|
||||||
|
x3_loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CObjectReference::Unload()
|
||||||
|
{
|
||||||
|
std::default_delete<IObj>()(x10_object);
|
||||||
|
x10_object = nullptr;
|
||||||
|
x3_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IObj* CObjectReference::GetObject()
|
||||||
|
{
|
||||||
|
if (!x10_object)
|
||||||
|
{
|
||||||
|
IFactory& factory = xC_objectStore->GetFactory();
|
||||||
|
x10_object = factory.Build(x4_objTag, x14_params, this).release();
|
||||||
|
}
|
||||||
|
x3_loading = false;
|
||||||
|
return x10_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
CObjectReference::~CObjectReference()
|
||||||
|
{
|
||||||
|
if (x10_object)
|
||||||
|
std::default_delete<IObj>()(x10_object);
|
||||||
|
else if (x3_loading)
|
||||||
|
xC_objectStore->GetFactory().CancelBuild(x4_objTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CToken::RemoveRef()
|
||||||
|
{
|
||||||
|
if (x0_objRef && x0_objRef->RemoveReference() == 0)
|
||||||
|
{
|
||||||
|
std::default_delete<CObjectReference>()(x0_objRef);
|
||||||
|
x0_objRef = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CToken::CToken(CObjectReference* obj)
|
||||||
|
{
|
||||||
|
x0_objRef = obj;
|
||||||
|
++x0_objRef->x0_refCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CToken::Unlock()
|
||||||
|
{
|
||||||
|
if (x0_objRef && x4_lockHeld)
|
||||||
|
{
|
||||||
|
x0_objRef->Unlock();
|
||||||
|
x4_lockHeld = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void CToken::Lock()
|
||||||
|
{
|
||||||
|
if (x0_objRef && !x4_lockHeld)
|
||||||
|
{
|
||||||
|
x0_objRef->Lock();
|
||||||
|
x4_lockHeld = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool CToken::IsLoaded() const
|
||||||
|
{
|
||||||
|
if (!x0_objRef)
|
||||||
|
return false;
|
||||||
|
return x0_objRef->IsLoaded();
|
||||||
|
}
|
||||||
|
IObj* CToken::GetObj()
|
||||||
|
{
|
||||||
|
if (!x0_objRef)
|
||||||
|
return nullptr;
|
||||||
|
Lock();
|
||||||
|
return x0_objRef->GetObject();
|
||||||
|
}
|
||||||
|
CToken& CToken::operator=(const CToken& other)
|
||||||
|
{
|
||||||
|
Unlock();
|
||||||
|
RemoveRef();
|
||||||
|
x0_objRef = other.x0_objRef;
|
||||||
|
if (x0_objRef)
|
||||||
|
{
|
||||||
|
++x0_objRef->x0_refCount;
|
||||||
|
if (other.x4_lockHeld)
|
||||||
|
Lock();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
CToken& CToken::operator=(CToken&& other)
|
||||||
|
{
|
||||||
|
Unlock();
|
||||||
|
RemoveRef();
|
||||||
|
x0_objRef = other.x0_objRef;
|
||||||
|
other.x0_objRef = nullptr;
|
||||||
|
x4_lockHeld = other.x4_lockHeld;
|
||||||
|
other.x4_lockHeld = false;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
CToken::CToken(const CToken& other)
|
||||||
|
: x0_objRef(other.x0_objRef)
|
||||||
|
{
|
||||||
|
if (x0_objRef)
|
||||||
|
++x0_objRef->x0_refCount;
|
||||||
|
}
|
||||||
|
CToken::CToken(CToken&& other)
|
||||||
|
: x0_objRef(other.x0_objRef), x4_lockHeld(other.x4_lockHeld)
|
||||||
|
{
|
||||||
|
other.x0_objRef = nullptr;
|
||||||
|
other.x4_lockHeld = false;
|
||||||
|
}
|
||||||
|
CToken::CToken(IObj* obj)
|
||||||
|
{
|
||||||
|
x0_objRef = new CObjectReference(std::unique_ptr<IObj>(obj));
|
||||||
|
++x0_objRef->x0_refCount;
|
||||||
|
Lock();
|
||||||
|
}
|
||||||
|
CToken::CToken(std::unique_ptr<IObj>&& obj)
|
||||||
|
{
|
||||||
|
x0_objRef = new CObjectReference(std::move(obj));
|
||||||
|
++x0_objRef->x0_refCount;
|
||||||
|
Lock();
|
||||||
|
}
|
||||||
|
const SObjectTag* CToken::GetObjectTag() const
|
||||||
|
{
|
||||||
|
if (!x0_objRef)
|
||||||
|
return nullptr;
|
||||||
|
return &x0_objRef->GetObjectTag();
|
||||||
|
}
|
||||||
|
CToken::~CToken()
|
||||||
|
{
|
||||||
|
if (x0_objRef)
|
||||||
|
{
|
||||||
|
if (x4_lockHeld)
|
||||||
|
x0_objRef->Unlock();
|
||||||
|
RemoveRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,27 +27,11 @@ class CObjectReference
|
||||||
|
|
||||||
/** Mechanism by which CToken decrements 1st ref-count, indicating CToken invalidation or reset.
|
/** Mechanism by which CToken decrements 1st ref-count, indicating CToken invalidation or reset.
|
||||||
* Reaching 0 indicates the CToken should delete the CObjectReference */
|
* Reaching 0 indicates the CToken should delete the CObjectReference */
|
||||||
u16 RemoveReference()
|
u16 RemoveReference();
|
||||||
{
|
|
||||||
--x0_refCount;
|
|
||||||
if (x0_refCount == 0)
|
|
||||||
{
|
|
||||||
if (x10_object)
|
|
||||||
Unload();
|
|
||||||
if (IsLoading())
|
|
||||||
CancelLoad();
|
|
||||||
if (xC_objectStore)
|
|
||||||
xC_objectStore->ObjectUnreferenced(x4_objTag);
|
|
||||||
}
|
|
||||||
return x0_refCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
CObjectReference(IObjectStore& objStore, std::unique_ptr<IObj>&& obj,
|
CObjectReference(IObjectStore& objStore, std::unique_ptr<IObj>&& obj,
|
||||||
const SObjectTag& objTag, CVParamTransfer buildParams)
|
const SObjectTag& objTag, CVParamTransfer buildParams);
|
||||||
: x4_objTag(objTag), xC_objectStore(&objStore),
|
CObjectReference(std::unique_ptr<IObj>&& obj);
|
||||||
x10_object(obj.release()), x14_params(buildParams) {}
|
|
||||||
CObjectReference(std::unique_ptr<IObj>&& obj)
|
|
||||||
: x10_object(obj.release()) {}
|
|
||||||
|
|
||||||
/** Indicates an asynchronous load transaction has been submitted and is not yet finished */
|
/** Indicates an asynchronous load transaction has been submitted and is not yet finished */
|
||||||
bool IsLoading() const {return x3_loading;}
|
bool IsLoading() const {return x3_loading;}
|
||||||
|
@ -56,70 +40,26 @@ class CObjectReference
|
||||||
bool IsLoaded() const {return x10_object != nullptr;}
|
bool IsLoaded() const {return x10_object != nullptr;}
|
||||||
|
|
||||||
/** Decrements 2nd ref-count, performing unload or async-load-cancel if 0 reached */
|
/** Decrements 2nd ref-count, performing unload or async-load-cancel if 0 reached */
|
||||||
void Unlock()
|
void Unlock();
|
||||||
{
|
|
||||||
--x2_lockCount;
|
|
||||||
if (x2_lockCount)
|
|
||||||
return;
|
|
||||||
if (x10_object && xC_objectStore)
|
|
||||||
Unload();
|
|
||||||
else if (IsLoading())
|
|
||||||
CancelLoad();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Increments 2nd ref-count, performing async-factory-load if needed */
|
/** Increments 2nd ref-count, performing async-factory-load if needed */
|
||||||
void Lock()
|
void Lock();
|
||||||
{
|
|
||||||
++x2_lockCount;
|
|
||||||
if (!x10_object && !x3_loading)
|
|
||||||
{
|
|
||||||
IFactory& fac = xC_objectStore->GetFactory();
|
|
||||||
fac.BuildAsync(x4_objTag, x14_params, &x10_object, this);
|
|
||||||
x3_loading = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CancelLoad()
|
void CancelLoad();
|
||||||
{
|
|
||||||
if (xC_objectStore && IsLoading())
|
|
||||||
{
|
|
||||||
xC_objectStore->GetFactory().CancelBuild(x4_objTag);
|
|
||||||
x3_loading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Pointer-synchronized object-destructor, another building Lock cycle may be performed after */
|
/** Pointer-synchronized object-destructor, another building Lock cycle may be performed after */
|
||||||
void Unload()
|
void Unload();
|
||||||
{
|
|
||||||
std::default_delete<IObj>()(x10_object);
|
|
||||||
x10_object = nullptr;
|
|
||||||
x3_loading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Synchronous object-fetch, guaranteed to return complete object on-demand, blocking build if not ready */
|
/** Synchronous object-fetch, guaranteed to return complete object on-demand, blocking build if not ready */
|
||||||
IObj* GetObject()
|
IObj* GetObject();
|
||||||
{
|
|
||||||
if (!x10_object)
|
|
||||||
{
|
|
||||||
IFactory& factory = xC_objectStore->GetFactory();
|
|
||||||
x10_object = factory.Build(x4_objTag, x14_params, this).release();
|
|
||||||
}
|
|
||||||
x3_loading = false;
|
|
||||||
return x10_object;
|
|
||||||
}
|
|
||||||
const SObjectTag& GetObjectTag() const
|
const SObjectTag& GetObjectTag() const
|
||||||
{
|
{
|
||||||
return x4_objTag;
|
return x4_objTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~CObjectReference()
|
~CObjectReference();
|
||||||
{
|
|
||||||
if (x10_object)
|
|
||||||
std::default_delete<IObj>()(x10_object);
|
|
||||||
else if (x3_loading)
|
|
||||||
xC_objectStore->GetFactory().CancelBuild(x4_objTag);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Counted meta-object, reference-counting against a shared CObjectReference
|
/** Counted meta-object, reference-counting against a shared CObjectReference
|
||||||
|
@ -132,121 +72,31 @@ class CToken
|
||||||
CObjectReference* x0_objRef = nullptr;
|
CObjectReference* x0_objRef = nullptr;
|
||||||
bool x4_lockHeld = false;
|
bool x4_lockHeld = false;
|
||||||
|
|
||||||
void RemoveRef()
|
void RemoveRef();
|
||||||
{
|
|
||||||
if (x0_objRef && x0_objRef->RemoveReference() == 0)
|
|
||||||
{
|
|
||||||
std::default_delete<CObjectReference>()(x0_objRef);
|
|
||||||
x0_objRef = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CToken(CObjectReference* obj)
|
CToken(CObjectReference* obj);
|
||||||
{
|
|
||||||
x0_objRef = obj;
|
|
||||||
++x0_objRef->x0_refCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Added to test for non-null state */
|
/* Added to test for non-null state */
|
||||||
operator bool() const {return x0_objRef != nullptr;}
|
operator bool() const {return x0_objRef != nullptr;}
|
||||||
void Unlock()
|
void Unlock();
|
||||||
{
|
void Lock();
|
||||||
if (x0_objRef && x4_lockHeld)
|
|
||||||
{
|
|
||||||
x0_objRef->Unlock();
|
|
||||||
x4_lockHeld = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void Lock()
|
|
||||||
{
|
|
||||||
if (x0_objRef && !x4_lockHeld)
|
|
||||||
{
|
|
||||||
x0_objRef->Lock();
|
|
||||||
x4_lockHeld = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool IsLocked() const {return x4_lockHeld;}
|
bool IsLocked() const {return x4_lockHeld;}
|
||||||
bool IsLoaded() const
|
bool IsLoaded() const;
|
||||||
{
|
IObj* GetObj();
|
||||||
if (!x0_objRef)
|
|
||||||
return false;
|
|
||||||
return x0_objRef->IsLoaded();
|
|
||||||
}
|
|
||||||
IObj* GetObj()
|
|
||||||
{
|
|
||||||
if (!x0_objRef)
|
|
||||||
return nullptr;
|
|
||||||
Lock();
|
|
||||||
return x0_objRef->GetObject();
|
|
||||||
}
|
|
||||||
const IObj* GetObj() const
|
const IObj* GetObj() const
|
||||||
{
|
{
|
||||||
return const_cast<CToken*>(this)->GetObj();
|
return const_cast<CToken*>(this)->GetObj();
|
||||||
}
|
}
|
||||||
CToken& operator=(const CToken& other)
|
CToken& operator=(const CToken& other);
|
||||||
{
|
CToken& operator=(CToken&& other);
|
||||||
Unlock();
|
|
||||||
RemoveRef();
|
|
||||||
x0_objRef = other.x0_objRef;
|
|
||||||
if (x0_objRef)
|
|
||||||
{
|
|
||||||
++x0_objRef->x0_refCount;
|
|
||||||
if (other.x4_lockHeld)
|
|
||||||
Lock();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
CToken& operator=(CToken&& other)
|
|
||||||
{
|
|
||||||
Unlock();
|
|
||||||
RemoveRef();
|
|
||||||
x0_objRef = other.x0_objRef;
|
|
||||||
other.x0_objRef = nullptr;
|
|
||||||
x4_lockHeld = other.x4_lockHeld;
|
|
||||||
other.x4_lockHeld = false;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
CToken() = default;
|
CToken() = default;
|
||||||
CToken(const CToken& other)
|
CToken(const CToken& other);
|
||||||
: x0_objRef(other.x0_objRef)
|
CToken(CToken&& other);
|
||||||
{
|
CToken(IObj* obj);
|
||||||
if (x0_objRef)
|
CToken(std::unique_ptr<IObj>&& obj);
|
||||||
++x0_objRef->x0_refCount;
|
const SObjectTag* GetObjectTag() const;
|
||||||
}
|
~CToken();
|
||||||
CToken(CToken&& other)
|
|
||||||
: x0_objRef(other.x0_objRef), x4_lockHeld(other.x4_lockHeld)
|
|
||||||
{
|
|
||||||
other.x0_objRef = nullptr;
|
|
||||||
other.x4_lockHeld = false;
|
|
||||||
}
|
|
||||||
CToken(IObj* obj)
|
|
||||||
{
|
|
||||||
x0_objRef = new CObjectReference(std::unique_ptr<IObj>(obj));
|
|
||||||
++x0_objRef->x0_refCount;
|
|
||||||
Lock();
|
|
||||||
}
|
|
||||||
CToken(std::unique_ptr<IObj>&& obj)
|
|
||||||
{
|
|
||||||
x0_objRef = new CObjectReference(std::move(obj));
|
|
||||||
++x0_objRef->x0_refCount;
|
|
||||||
Lock();
|
|
||||||
}
|
|
||||||
const SObjectTag* GetObjectTag() const
|
|
||||||
{
|
|
||||||
if (!x0_objRef)
|
|
||||||
return nullptr;
|
|
||||||
return &x0_objRef->GetObjectTag();
|
|
||||||
}
|
|
||||||
~CToken()
|
|
||||||
{
|
|
||||||
if (x0_objRef)
|
|
||||||
{
|
|
||||||
if (x4_lockHeld)
|
|
||||||
x0_objRef->Unlock();
|
|
||||||
RemoveRef();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
||||||
Subproject commit 3a5bdade6f3e26b82eded9bee1bdcec2856fb0df
|
Subproject commit 1326eacf98fdc94d7fd692d248d54de9a09a2fb8
|
Loading…
Reference in New Issue