mirror of https://github.com/AxioDL/metaforce.git
Externally track MemoryRelays
This commit is contained in:
parent
0ed44f1cdc
commit
5b5f3318b0
|
@ -20,7 +20,7 @@ struct ISTRG : BigYAML
|
||||||
virtual hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const=0;
|
virtual hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const=0;
|
||||||
virtual int32_t lookupIdx(const std::string& name) const=0;
|
virtual int32_t lookupIdx(const std::string& name) const=0;
|
||||||
|
|
||||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const;
|
virtual void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const;
|
||||||
};
|
};
|
||||||
std::unique_ptr<ISTRG> LoadSTRG(athena::io::IStreamReader& reader);
|
std::unique_ptr<ISTRG> LoadSTRG(athena::io::IStreamReader& reader);
|
||||||
|
|
||||||
|
|
|
@ -13,36 +13,59 @@ namespace DataSpec
|
||||||
namespace DNAMP1
|
namespace DNAMP1
|
||||||
{
|
{
|
||||||
|
|
||||||
bool MLVL::Extract(const SpecBase& dataSpec,
|
bool MLVL::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||||
PAKEntryReadStream& rs,
|
PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, hecl::BlenderToken& btok,
|
||||||
const hecl::ProjectPath& outPath,
|
|
||||||
PAKRouter<PAKBridge>& pakRouter,
|
|
||||||
const PAK::Entry& entry,
|
|
||||||
bool force,
|
|
||||||
hecl::BlenderToken& btok,
|
|
||||||
std::function<void(const hecl::SystemChar*)> fileChanged)
|
std::function<void(const hecl::SystemChar*)> fileChanged)
|
||||||
{
|
{
|
||||||
MLVL mlvl;
|
MLVL mlvl;
|
||||||
mlvl.read(rs);
|
mlvl.read(rs);
|
||||||
|
const nod::Node* node;
|
||||||
|
const typename PAKRouter<PAKBridge>::EntryType* texEntry = pakRouter.lookupEntry(mlvl.saveWorldId, &node);
|
||||||
|
hecl::ProjectPath savwPath = pakRouter.getWorking(texEntry);
|
||||||
|
SAVW savw;
|
||||||
|
if (!savwPath.isNone())
|
||||||
|
{
|
||||||
|
savwPath.makeDirChain(false);
|
||||||
|
PAKEntryReadStream rs = texEntry->beginReadStream(*node);
|
||||||
|
savw.read(rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
atUint32 areaIdx = 0;
|
||||||
for (const MLVL::Area& area : mlvl.areas)
|
for (const MLVL::Area& area : mlvl.areas)
|
||||||
{
|
{
|
||||||
hecl::ProjectPath areaDir = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
hecl::ProjectPath areaDir = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
||||||
|
{
|
||||||
athena::io::FileWriter fw(hecl::ProjectPath(areaDir, _S("!memoryid.yaml")).getAbsolutePath());
|
athena::io::FileWriter fw(hecl::ProjectPath(areaDir, _S("!memoryid.yaml")).getAbsolutePath());
|
||||||
athena::io::YAMLDocWriter w(nullptr);
|
athena::io::YAMLDocWriter w(nullptr);
|
||||||
w.writeUint32("memoryid", area.areaId);
|
w.writeUint32("memoryid", area.areaId);
|
||||||
w.finish(&fw);
|
w.finish(&fw);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
athena::io::FileWriter fw(hecl::ProjectPath(areaDir, _S("!memoryrelays.yaml")).getAbsolutePath());
|
||||||
|
athena::io::YAMLDocWriter w(nullptr);
|
||||||
|
|
||||||
|
std::vector<atUint32> relayIds;
|
||||||
|
for (const atUint32& relay : savw.relays)
|
||||||
|
{
|
||||||
|
atUint16 aIdx = ((relay >> 16) & 0x3ff);
|
||||||
|
if (aIdx == areaIdx && std::find(relayIds.begin(), relayIds.end(), relay) == relayIds.end())
|
||||||
|
relayIds.push_back(relay);
|
||||||
|
}
|
||||||
|
|
||||||
|
w.enumerate<atUint32>("memrelays", relayIds);
|
||||||
|
w.finish(&fw);
|
||||||
|
}
|
||||||
|
areaIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
athena::io::FileWriter writer(outPath.getWithExtension(_S(".yaml"), true).getAbsolutePath());
|
athena::io::FileWriter writer(outPath.getWithExtension(_S(".yaml"), true).getAbsolutePath());
|
||||||
mlvl.toYAMLStream(writer, static_cast<YAMLWriteMemberFn>(&MLVL::writeMeta));
|
mlvl.toYAMLStream(writer, static_cast<YAMLWriteMemberFn>(&MLVL::writeMeta));
|
||||||
hecl::BlenderConnection& conn = btok.getBlenderConnection();
|
hecl::BlenderConnection& conn = btok.getBlenderConnection();
|
||||||
return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter,
|
return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter, entry, force, fileChanged);
|
||||||
entry, force, fileChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath,
|
bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const World& wld,
|
||||||
const World& wld, hecl::BlenderToken& btok)
|
hecl::BlenderToken& btok)
|
||||||
{
|
{
|
||||||
MLVL mlvl = {};
|
MLVL mlvl = {};
|
||||||
athena::io::FileReader reader(inPath.getWithExtension(_S(".yaml"), true).getAbsolutePath());
|
athena::io::FileReader reader(inPath.getWithExtension(_S(".yaml"), true).getAbsolutePath());
|
||||||
|
@ -77,8 +100,24 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
||||||
if (!areaPath.isFile())
|
if (!areaPath.isFile())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
hecl::DirectoryEnumerator dEnum(area.path.getAbsolutePath(),
|
hecl::ProjectPath memRelayPath(area.path, _S("/!memoryrelays.yaml"));
|
||||||
hecl::DirectoryEnumerator::Mode::DirsSorted);
|
|
||||||
|
std::vector<atUint32> memRelays;
|
||||||
|
|
||||||
|
if (memRelayPath.isFile())
|
||||||
|
{
|
||||||
|
athena::io::FileReader fr(memRelayPath.getAbsolutePath());
|
||||||
|
athena::io::YAMLDocReader r;
|
||||||
|
if (r.parse(&fr))
|
||||||
|
r.enumerate<atUint32>("memrelays", memRelays);
|
||||||
|
}
|
||||||
|
|
||||||
|
savw.relays.insert(savw.relays.end(), memRelays.begin(), memRelays.end());
|
||||||
|
|
||||||
|
/* Bare minimum we'll need exactly the same number of links as relays */
|
||||||
|
std::vector<MemRelayLink> memRelayLinks(memRelays.size());
|
||||||
|
|
||||||
|
hecl::DirectoryEnumerator dEnum(area.path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsSorted);
|
||||||
bool areaInit = false;
|
bool areaInit = false;
|
||||||
|
|
||||||
size_t layerIdx = 0;
|
size_t layerIdx = 0;
|
||||||
|
@ -201,6 +240,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
||||||
MLVL::Area& areaOut = mlvl.areas.back();
|
MLVL::Area& areaOut = mlvl.areas.back();
|
||||||
areaOut.depLayers.push_back(areaOut.deps.size());
|
areaOut.depLayers.push_back(areaOut.deps.size());
|
||||||
|
|
||||||
|
|
||||||
/* Gather memory relays, scans, and dependencies */
|
/* Gather memory relays, scans, and dependencies */
|
||||||
{
|
{
|
||||||
g_ThreadBlenderToken.reset(&btok);
|
g_ThreadBlenderToken.reset(&btok);
|
||||||
|
@ -213,14 +253,28 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
||||||
MemoryRelay& memRelay = static_cast<MemoryRelay&>(*obj);
|
MemoryRelay& memRelay = static_cast<MemoryRelay&>(*obj);
|
||||||
for (IScriptObject::Connection& conn : memRelay.connections)
|
for (IScriptObject::Connection& conn : memRelay.connections)
|
||||||
{
|
{
|
||||||
mlvl.memRelayLinks.emplace_back();
|
MemRelayLink linkOut;
|
||||||
MemRelayLink& linkOut = mlvl.memRelayLinks.back();
|
|
||||||
linkOut.memRelayId = memRelay.id;
|
linkOut.memRelayId = memRelay.id;
|
||||||
linkOut.targetId = conn.target;
|
linkOut.targetId = conn.target;
|
||||||
linkOut.msg = conn.msg;
|
linkOut.msg = conn.msg;
|
||||||
linkOut.active = memRelay.active;
|
linkOut.active = memRelay.active;
|
||||||
}
|
auto iter = std::find(memRelays.begin(), memRelays.end(), linkOut.memRelayId);
|
||||||
|
if (iter == memRelays.end())
|
||||||
|
{
|
||||||
|
/* We must have a new relay, let's track it */
|
||||||
|
memRelayLinks.push_back(linkOut);
|
||||||
savw.relays.push_back(memRelay.id);
|
savw.relays.push_back(memRelay.id);
|
||||||
|
memRelays.push_back(memRelay.id);
|
||||||
|
}
|
||||||
|
else /* Lets insert this in it's appropriate location, target order doesn't matter */
|
||||||
|
{
|
||||||
|
atUint32 idx = iter - memRelays.begin();
|
||||||
|
if (idx >= memRelayLinks.size())
|
||||||
|
memRelayLinks.push_back(linkOut);
|
||||||
|
else
|
||||||
|
memRelayLinks.insert(memRelayLinks.begin() + idx, linkOut);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (obj->type == int(urde::EScriptObjectType::SpecialFunction))
|
else if (obj->type == int(urde::EScriptObjectType::SpecialFunction))
|
||||||
{
|
{
|
||||||
|
@ -286,6 +340,9 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
||||||
++layerIdx;
|
++layerIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Append Memory Relays */
|
||||||
|
mlvl.memRelayLinks.insert(mlvl.memRelayLinks.end(), memRelayLinks.begin(), memRelayLinks.end());
|
||||||
|
|
||||||
/* Cull duplicate area paths and add typed hash to list */
|
/* Cull duplicate area paths and add typed hash to list */
|
||||||
auto& conn = btok.getBlenderConnection();
|
auto& conn = btok.getBlenderConnection();
|
||||||
if (conn.openBlend(areaPath))
|
if (conn.openBlend(areaPath))
|
||||||
|
@ -332,8 +389,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
||||||
|
|
||||||
/* Write out MAPW */
|
/* Write out MAPW */
|
||||||
{
|
{
|
||||||
hecl::ProjectPath mapwCooked =
|
hecl::ProjectPath mapwCooked = mapwPath.getCookedPath(*g_curSpec->overrideDataSpec(mapwPath, nullptr, btok));
|
||||||
mapwPath.getCookedPath(*g_curSpec->overrideDataSpec(mapwPath, nullptr, btok));
|
|
||||||
mapwCooked.makeDirChain(false);
|
mapwCooked.makeDirChain(false);
|
||||||
athena::io::FileWriter fo(mapwCooked.getAbsolutePath());
|
athena::io::FileWriter fo(mapwCooked.getAbsolutePath());
|
||||||
fo.writeUint32Big(0xDEADF00D);
|
fo.writeUint32Big(0xDEADF00D);
|
||||||
|
@ -352,8 +408,7 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
||||||
savw.doorCount = savw.doors.size();
|
savw.doorCount = savw.doors.size();
|
||||||
savw.scanCount = savw.scans.size();
|
savw.scanCount = savw.scans.size();
|
||||||
|
|
||||||
hecl::ProjectPath savwCooked =
|
hecl::ProjectPath savwCooked = savwPath.getCookedPath(*g_curSpec->overrideDataSpec(savwPath, nullptr, btok));
|
||||||
savwPath.getCookedPath(*g_curSpec->overrideDataSpec(savwPath, nullptr, btok));
|
|
||||||
savwCooked.makeDirChain(false);
|
savwCooked.makeDirChain(false);
|
||||||
athena::io::FileWriter fo(savwCooked.getAbsolutePath());
|
athena::io::FileWriter fo(savwCooked.getAbsolutePath());
|
||||||
savw.write(fo);
|
savw.write(fo);
|
||||||
|
@ -361,6 +416,5 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,11 +161,8 @@ struct SCAN : BigYAML
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath)
|
static bool Cook(const SCAN& scan, const hecl::ProjectPath& outPath)
|
||||||
{
|
{
|
||||||
SCAN scan;
|
|
||||||
athena::io::FileReader reader(inPath.getAbsolutePath());
|
|
||||||
scan.fromYAMLStream(reader);
|
|
||||||
athena::io::FileWriter ws(outPath.getAbsolutePath());
|
athena::io::FileWriter ws(outPath.getAbsolutePath());
|
||||||
scan.write(ws);
|
scan.write(ws);
|
||||||
return true;
|
return true;
|
||||||
|
@ -204,6 +201,12 @@ struct SCAN : BigYAML
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
g_curSpec->flattenDependencies(textures[i].texture, pathsOut);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,22 +6,14 @@ namespace DataSpec
|
||||||
namespace DNAMP1
|
namespace DNAMP1
|
||||||
{
|
{
|
||||||
|
|
||||||
const std::vector<FourCC> skLanguages =
|
const std::vector<FourCC> skLanguages = {FOURCC('ENGL'), FOURCC('FREN'), FOURCC('GERM'), FOURCC('SPAN'),
|
||||||
{
|
FOURCC('ITAL'), FOURCC('DUTC'), FOURCC('JAPN')};
|
||||||
FOURCC('ENGL'),
|
|
||||||
FOURCC('FREN'),
|
|
||||||
FOURCC('GERM'),
|
|
||||||
FOURCC('SPAN'),
|
|
||||||
FOURCC('ITAL'),
|
|
||||||
FOURCC('DUTC'),
|
|
||||||
FOURCC('JAPN')
|
|
||||||
};
|
|
||||||
|
|
||||||
static float u16stof(char16_t* str)
|
static float u16stof(char16_t* str)
|
||||||
{
|
{
|
||||||
char cstr[16];
|
char cstr[16];
|
||||||
int i;
|
int i;
|
||||||
for (i=0 ; i<15 && str[i] != u'\0' ; ++i)
|
for (i = 0; i < 15 && str[i] != u'\0'; ++i)
|
||||||
cstr[i] = str[i];
|
cstr[i] = str[i];
|
||||||
cstr[i] = '\0';
|
cstr[i] = '\0';
|
||||||
return strtof(cstr, nullptr);
|
return strtof(cstr, nullptr);
|
||||||
|
@ -31,18 +23,16 @@ static uint32_t ParseTag(const char16_t* str)
|
||||||
{
|
{
|
||||||
char parseStr[9];
|
char parseStr[9];
|
||||||
int i;
|
int i;
|
||||||
for (i=0 ; i<8 && str[i] ; ++i)
|
for (i = 0; i < 8 && str[i]; ++i)
|
||||||
parseStr[i] = str[i];
|
parseStr[i] = str[i];
|
||||||
parseStr[i] = '\0';
|
parseStr[i] = '\0';
|
||||||
return strtoul(parseStr, nullptr, 16);
|
return strtoul(parseStr, nullptr, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::u16string::const_iterator SkipCommas(std::u16string& ret,
|
static std::u16string::const_iterator SkipCommas(std::u16string& ret, const std::u16string& str,
|
||||||
const std::u16string& str,
|
std::u16string::const_iterator it, size_t count)
|
||||||
std::u16string::const_iterator it,
|
|
||||||
size_t count)
|
|
||||||
{
|
{
|
||||||
for (size_t i=0 ; i<count ; ++i)
|
for (size_t i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
auto cpos = str.find(u',', it - str.begin());
|
auto cpos = str.find(u',', it - str.begin());
|
||||||
if (cpos == std::u16string::npos)
|
if (cpos == std::u16string::npos)
|
||||||
|
@ -54,8 +44,7 @@ static std::u16string::const_iterator SkipCommas(std::u16string& ret,
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::u16string::const_iterator UncookTextureList(std::u16string& ret,
|
static std::u16string::const_iterator UncookTextureList(std::u16string& ret, const std::u16string& str,
|
||||||
const std::u16string& str,
|
|
||||||
std::u16string::const_iterator it)
|
std::u16string::const_iterator it)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -87,20 +76,17 @@ static std::u16string::const_iterator UncookTextureList(std::u16string& ret,
|
||||||
return str.begin() + scpos + 1;
|
return str.begin() + scpos + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::u16string::const_iterator CookTextureList(std::u16string& ret,
|
static std::u16string::const_iterator CookTextureList(std::u16string& ret, const std::u16string& str,
|
||||||
const std::u16string& str,
|
|
||||||
std::u16string::const_iterator it)
|
std::u16string::const_iterator it)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
auto end = str.find_first_of(u",;", it - str.begin());
|
auto end = str.find_first_of(u",;", it - str.begin());
|
||||||
if (end == std::u16string::npos)
|
if (end == std::u16string::npos)
|
||||||
Log.report(logvisor::Fatal,
|
Log.report(logvisor::Fatal, "Missing comma/semicolon token while pasing font tag");
|
||||||
"Missing comma/semicolon token while pasing font tag");
|
|
||||||
auto endIt = str.begin() + end;
|
auto endIt = str.begin() + end;
|
||||||
hecl::ProjectPath path =
|
hecl::ProjectPath path =
|
||||||
UniqueIDBridge::MakePathFromString<UniqueID32>(
|
UniqueIDBridge::MakePathFromString<UniqueID32>(hecl::Char16ToUTF8(std::u16string(it, endIt)));
|
||||||
hecl::Char16ToUTF8(std::u16string(it, endIt)));
|
|
||||||
ret.append(hecl::UTF8ToChar16(UniqueID32(path).toString()));
|
ret.append(hecl::UTF8ToChar16(UniqueID32(path).toString()));
|
||||||
it = endIt;
|
it = endIt;
|
||||||
if (*it == u';')
|
if (*it == u';')
|
||||||
|
@ -126,11 +112,47 @@ static std::u16string::const_iterator CookTextureList(std::u16string& ret,
|
||||||
return str.begin() + scpos + 1;
|
return str.begin() + scpos + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::u16string::const_iterator GatherTextureList(std::vector<hecl::ProjectPath>& pathsOut,
|
||||||
|
const std::u16string& str, std::u16string::const_iterator it)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto end = str.find_first_of(u",;", it - str.begin());
|
||||||
|
if (end == std::u16string::npos)
|
||||||
|
Log.report(logvisor::Fatal, "Missing comma/semicolon token while pasing font tag");
|
||||||
|
auto endIt = str.begin() + end;
|
||||||
|
hecl::ProjectPath path =
|
||||||
|
UniqueIDBridge::MakePathFromString<UniqueID32>(hecl::Char16ToUTF8(std::u16string(it, endIt)));
|
||||||
|
if (path)
|
||||||
|
pathsOut.push_back(path);
|
||||||
|
|
||||||
|
it = endIt;
|
||||||
|
if (*it == u';')
|
||||||
|
{
|
||||||
|
return it + 1;
|
||||||
|
}
|
||||||
|
else if (*it == u',')
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failsafe */
|
||||||
|
auto scpos = str.find(u';', it - str.begin());
|
||||||
|
if (scpos == std::u16string::npos)
|
||||||
|
return str.end();
|
||||||
|
return str.begin() + scpos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
static std::u16string UncookString(const std::u16string& str)
|
static std::u16string UncookString(const std::u16string& str)
|
||||||
{
|
{
|
||||||
std::u16string ret;
|
std::u16string ret;
|
||||||
ret.reserve(str.size());
|
ret.reserve(str.size());
|
||||||
for (auto it = str.begin() ; it != str.end() ;)
|
for (auto it = str.begin(); it != str.end();)
|
||||||
{
|
{
|
||||||
if (*it == u'&')
|
if (*it == u'&')
|
||||||
{
|
{
|
||||||
|
@ -202,7 +224,7 @@ static std::u16string CookString(const std::u16string& str)
|
||||||
{
|
{
|
||||||
std::u16string ret;
|
std::u16string ret;
|
||||||
ret.reserve(str.size());
|
ret.reserve(str.size());
|
||||||
for (auto it = str.begin() ; it != str.end() ;)
|
for (auto it = str.begin(); it != str.end();)
|
||||||
{
|
{
|
||||||
if (*it == u'&')
|
if (*it == u'&')
|
||||||
{
|
{
|
||||||
|
@ -238,8 +260,7 @@ static std::u16string CookString(const std::u16string& str)
|
||||||
auto scpos = str.find(u';', it - str.begin());
|
auto scpos = str.find(u';', it - str.begin());
|
||||||
if (scpos == std::u16string::npos)
|
if (scpos == std::u16string::npos)
|
||||||
Log.report(logvisor::Fatal, "Missing semicolon token while pasing font tag");
|
Log.report(logvisor::Fatal, "Missing semicolon token while pasing font tag");
|
||||||
hecl::ProjectPath path =
|
hecl::ProjectPath path = UniqueIDBridge::MakePathFromString<UniqueID32>(
|
||||||
UniqueIDBridge::MakePathFromString<UniqueID32>(
|
|
||||||
hecl::Char16ToUTF8(std::u16string(it, str.begin() + scpos)));
|
hecl::Char16ToUTF8(std::u16string(it, str.begin() + scpos)));
|
||||||
ret.append(hecl::UTF8ToChar16(UniqueID32(path).toString()));
|
ret.append(hecl::UTF8ToChar16(UniqueID32(path).toString()));
|
||||||
ret.push_back(u';');
|
ret.push_back(u';');
|
||||||
|
@ -269,6 +290,68 @@ static std::u16string CookString(const std::u16string& str)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void STRG::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const
|
||||||
|
{
|
||||||
|
std::u16string skip;
|
||||||
|
for (const auto& lang : langs)
|
||||||
|
{
|
||||||
|
for (const std::u16string& str : lang.second)
|
||||||
|
{
|
||||||
|
for (auto it = str.begin(); it != str.end();)
|
||||||
|
{
|
||||||
|
if (*it == u'&')
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
if (!str.compare(it - str.begin(), 5, u"image"))
|
||||||
|
{
|
||||||
|
it += 6;
|
||||||
|
if (!str.compare(it - str.begin(), 1, u"A"))
|
||||||
|
{
|
||||||
|
it = SkipCommas(skip, str, it, 2);
|
||||||
|
it = GatherTextureList(pathsOut, str, it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (!str.compare(it - str.begin(), 2, u"SA"))
|
||||||
|
{
|
||||||
|
it = SkipCommas(skip, str, it, 4);
|
||||||
|
it = GatherTextureList(pathsOut, str, it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (!str.compare(it - str.begin(), 2, u"SI"))
|
||||||
|
{
|
||||||
|
it = SkipCommas(skip, str, it, 3);
|
||||||
|
it = GatherTextureList(pathsOut, str, it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!str.compare(it - str.begin(), 4, u"font"))
|
||||||
|
{
|
||||||
|
it += 5;
|
||||||
|
auto scpos = str.find(u';', it - str.begin());
|
||||||
|
if (scpos == std::u16string::npos)
|
||||||
|
Log.report(logvisor::Fatal, "Missing semicolon token while pasing font tag");
|
||||||
|
hecl::ProjectPath path = UniqueIDBridge::MakePathFromString<UniqueID32>(
|
||||||
|
hecl::Char16ToUTF8(std::u16string(it, str.begin() + scpos)));
|
||||||
|
if (path)
|
||||||
|
pathsOut.push_back(path);
|
||||||
|
it = str.begin() + scpos + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto scpos = str.find(u';', it - str.begin());
|
||||||
|
if (scpos == std::u16string::npos)
|
||||||
|
it = str.end();
|
||||||
|
else
|
||||||
|
it = str.begin() + scpos + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void STRG::_read(athena::io::IStreamReader& reader)
|
void STRG::_read(athena::io::IStreamReader& reader)
|
||||||
{
|
{
|
||||||
atUint32 langCount = reader.readUint32Big();
|
atUint32 langCount = reader.readUint32Big();
|
||||||
|
@ -277,7 +360,7 @@ void STRG::_read(athena::io::IStreamReader& reader)
|
||||||
std::vector<std::pair<FourCC, atUint32>> readLangs;
|
std::vector<std::pair<FourCC, atUint32>> readLangs;
|
||||||
|
|
||||||
readLangs.reserve(langCount);
|
readLangs.reserve(langCount);
|
||||||
for (atUint32 l=0 ; l<langCount ; ++l)
|
for (atUint32 l = 0; l < langCount; ++l)
|
||||||
{
|
{
|
||||||
DNAFourCC lang;
|
DNAFourCC lang;
|
||||||
lang.read(reader);
|
lang.read(reader);
|
||||||
|
@ -294,7 +377,7 @@ void STRG::_read(athena::io::IStreamReader& reader)
|
||||||
reader.seek(tablesStart + lang.second, athena::SeekOrigin::Begin);
|
reader.seek(tablesStart + lang.second, athena::SeekOrigin::Begin);
|
||||||
reader.readUint32Big(); // table size
|
reader.readUint32Big(); // table size
|
||||||
atUint32 langStart = reader.position();
|
atUint32 langStart = reader.position();
|
||||||
for (atUint32 s=0 ; s<strCount ; ++s)
|
for (atUint32 s = 0; s < strCount; ++s)
|
||||||
{
|
{
|
||||||
atUint32 strOffset = reader.readUint32Big();
|
atUint32 strOffset = reader.readUint32Big();
|
||||||
atUint32 tmpOffset = reader.position();
|
atUint32 tmpOffset = reader.position();
|
||||||
|
@ -342,7 +425,7 @@ void STRG::write(athena::io::IStreamWriter& writer) const
|
||||||
writer.writeUint32Big(offset);
|
writer.writeUint32Big(offset);
|
||||||
offset += strCount * 4 + 4;
|
offset += strCount * 4 + 4;
|
||||||
atUint32 langStrCount = lang.second.size();
|
atUint32 langStrCount = lang.second.size();
|
||||||
for (atUint32 s=0 ; s<strCount ; ++s)
|
for (atUint32 s = 0; s < strCount; ++s)
|
||||||
{
|
{
|
||||||
std::u16string str = CookString(lang.second[s]);
|
std::u16string str = CookString(lang.second[s]);
|
||||||
atUint32 chCount = str.size();
|
atUint32 chCount = str.size();
|
||||||
|
@ -360,7 +443,7 @@ void STRG::write(athena::io::IStreamWriter& writer) const
|
||||||
atUint32 langStrCount = lang.second.size();
|
atUint32 langStrCount = lang.second.size();
|
||||||
atUint32 tableSz = strCount * 4;
|
atUint32 tableSz = strCount * 4;
|
||||||
auto strIt = langIt;
|
auto strIt = langIt;
|
||||||
for (atUint32 s=0 ; s<strCount ; ++s)
|
for (atUint32 s = 0; s < strCount; ++s)
|
||||||
{
|
{
|
||||||
if (s < langStrCount)
|
if (s < langStrCount)
|
||||||
tableSz += ((strIt++)->size() + 1) * 2;
|
tableSz += ((strIt++)->size() + 1) * 2;
|
||||||
|
@ -371,7 +454,7 @@ void STRG::write(athena::io::IStreamWriter& writer) const
|
||||||
|
|
||||||
offset = strCount * 4;
|
offset = strCount * 4;
|
||||||
strIt = langIt;
|
strIt = langIt;
|
||||||
for (atUint32 s=0 ; s<strCount ; ++s)
|
for (atUint32 s = 0; s < strCount; ++s)
|
||||||
{
|
{
|
||||||
writer.writeUint32Big(offset);
|
writer.writeUint32Big(offset);
|
||||||
if (s < langStrCount)
|
if (s < langStrCount)
|
||||||
|
@ -381,7 +464,7 @@ void STRG::write(athena::io::IStreamWriter& writer) const
|
||||||
}
|
}
|
||||||
|
|
||||||
strIt = langIt;
|
strIt = langIt;
|
||||||
for (atUint32 s=0 ; s<strCount ; ++s)
|
for (atUint32 s = 0; s < strCount; ++s)
|
||||||
{
|
{
|
||||||
if (s < langStrCount)
|
if (s < langStrCount)
|
||||||
writer.writeU16StringBig(*strIt++);
|
writer.writeU16StringBig(*strIt++);
|
||||||
|
@ -403,7 +486,7 @@ size_t STRG::binarySize(size_t __isz) const
|
||||||
for (const std::pair<FourCC, std::vector<std::u16string>>& lang : langs)
|
for (const std::pair<FourCC, std::vector<std::u16string>>& lang : langs)
|
||||||
{
|
{
|
||||||
atUint32 langStrCount = lang.second.size();
|
atUint32 langStrCount = lang.second.size();
|
||||||
for (atUint32 s=0 ; s<strCount ; ++s)
|
for (atUint32 s = 0; s < strCount; ++s)
|
||||||
{
|
{
|
||||||
if (s < langStrCount)
|
if (s < langStrCount)
|
||||||
__isz += (CookString(lang.second[s]).size() + 1) * 2;
|
__isz += (CookString(lang.second[s]).size() + 1) * 2;
|
||||||
|
@ -429,19 +512,22 @@ void STRG::read(athena::io::YAMLDocReader& reader)
|
||||||
|
|
||||||
if (lang.first.size() != 4)
|
if (lang.first.size() != 4)
|
||||||
{
|
{
|
||||||
Log.report(logvisor::Warning, "STRG language string '%s' must be exactly 4 characters; skipping", lang.first.c_str());
|
Log.report(logvisor::Warning, "STRG language string '%s' must be exactly 4 characters; skipping",
|
||||||
|
lang.first.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (lang.second->m_type != YAML_SEQUENCE_NODE)
|
if (lang.second->m_type != YAML_SEQUENCE_NODE)
|
||||||
{
|
{
|
||||||
Log.report(logvisor::Warning, "STRG language string '%s' must contain a sequence; skipping", lang.first.c_str());
|
Log.report(logvisor::Warning, "STRG language string '%s' must contain a sequence; skipping",
|
||||||
|
lang.first.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto& str : lang.second->m_seqChildren)
|
for (const auto& str : lang.second->m_seqChildren)
|
||||||
{
|
{
|
||||||
if (str->m_type != YAML_SCALAR_NODE)
|
if (str->m_type != YAML_SCALAR_NODE)
|
||||||
{
|
{
|
||||||
Log.report(logvisor::Warning, "STRG language '%s' must contain all scalars; skipping", lang.first.c_str());
|
Log.report(logvisor::Warning, "STRG language '%s' must contain all scalars; skipping",
|
||||||
|
lang.first.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -483,10 +569,6 @@ void STRG::write(athena::io::YAMLDocWriter& writer) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* STRG::DNAType()
|
const char* STRG::DNAType() { return "urde::DNAMP1::STRG"; }
|
||||||
{
|
|
||||||
return "urde::DNAMP1::STRG";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ struct STRG : ISTRG
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gatherDependencies(std::vector<hecl::ProjectPath> &pathsOut) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "DNAMP1/HINT.hpp"
|
#include "DNAMP1/HINT.hpp"
|
||||||
#include "DNAMP1/MLVL.hpp"
|
#include "DNAMP1/MLVL.hpp"
|
||||||
#include "DNAMP1/STRG.hpp"
|
#include "DNAMP1/STRG.hpp"
|
||||||
|
#include "DNAMP1/SCAN.hpp"
|
||||||
#include "DNAMP1/CMDL.hpp"
|
#include "DNAMP1/CMDL.hpp"
|
||||||
#include "DNAMP1/MREA.hpp"
|
#include "DNAMP1/MREA.hpp"
|
||||||
#include "DNAMP1/ANCS.hpp"
|
#include "DNAMP1/ANCS.hpp"
|
||||||
|
@ -50,12 +51,10 @@ extern hecl::Database::DataSpecEntry SpecEntMP1ORIG;
|
||||||
|
|
||||||
struct OriginalIDs
|
struct OriginalIDs
|
||||||
{
|
{
|
||||||
static void Generate(PAKRouter<DNAMP1::PAKBridge>& pakRouter,
|
static void Generate(PAKRouter<DNAMP1::PAKBridge>& pakRouter, hecl::Database::Project& project)
|
||||||
hecl::Database::Project& project)
|
|
||||||
{
|
{
|
||||||
std::vector<UniqueID32> originalIDs;
|
std::vector<UniqueID32> originalIDs;
|
||||||
pakRouter.enumerateResources([&](const DNAMP1::PAK::Entry* ent) -> bool
|
pakRouter.enumerateResources([&](const DNAMP1::PAK::Entry* ent) -> bool {
|
||||||
{
|
|
||||||
if (ent->type == FOURCC('MLVL') || ent->type == FOURCC('SCAN'))
|
if (ent->type == FOURCC('MLVL') || ent->type == FOURCC('SCAN'))
|
||||||
originalIDs.push_back(ent->id);
|
originalIDs.push_back(ent->id);
|
||||||
return true;
|
return true;
|
||||||
|
@ -91,14 +90,11 @@ struct OriginalIDs
|
||||||
if (end != node.first.c_str() + 8)
|
if (end != node.first.c_str() + 8)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
hecl::ProjectPath path(project.getProjectWorkingPath(),
|
hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str());
|
||||||
node.second->m_scalarString.c_str());
|
|
||||||
originalIDs.push_back(std::make_pair(id, path.hash().val32()));
|
originalIDs.push_back(std::make_pair(id, path.hash().val32()));
|
||||||
}
|
}
|
||||||
std::sort(originalIDs.begin(), originalIDs.end(),
|
std::sort(originalIDs.begin(), originalIDs.end(),
|
||||||
[](const std::pair<UniqueID32, UniqueID32>& a,
|
[](const std::pair<UniqueID32, UniqueID32>& a, const std::pair<UniqueID32, UniqueID32>& b) -> bool {
|
||||||
const std::pair<UniqueID32, UniqueID32>& b) -> bool
|
|
||||||
{
|
|
||||||
return a.first < b.first;
|
return a.first < b.first;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -111,9 +107,7 @@ struct OriginalIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(originalIDs.begin(), originalIDs.end(),
|
std::sort(originalIDs.begin(), originalIDs.end(),
|
||||||
[](const std::pair<UniqueID32, UniqueID32>& a,
|
[](const std::pair<UniqueID32, UniqueID32>& a, const std::pair<UniqueID32, UniqueID32>& b) -> bool {
|
||||||
const std::pair<UniqueID32, UniqueID32>& b) -> bool
|
|
||||||
{
|
|
||||||
return a.second < b.second;
|
return a.second < b.second;
|
||||||
});
|
});
|
||||||
for (const auto& idPair : originalIDs)
|
for (const auto& idPair : originalIDs)
|
||||||
|
@ -142,14 +136,14 @@ struct SpecMP1 : SpecBase
|
||||||
PAKRouter<DNAMP1::PAKBridge> m_pakRouter;
|
PAKRouter<DNAMP1::PAKBridge> m_pakRouter;
|
||||||
|
|
||||||
SpecMP1(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc)
|
SpecMP1(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc)
|
||||||
: SpecBase(specEntry, project, pc),
|
: SpecBase(specEntry, project, pc)
|
||||||
m_workPath(project.getProjectWorkingPath(), _S("MP1")),
|
, m_workPath(project.getProjectWorkingPath(), _S("MP1"))
|
||||||
m_cookPath(project.getProjectCookedPath(SpecEntMP1), _S("MP1")),
|
, m_cookPath(project.getProjectCookedPath(SpecEntMP1), _S("MP1"))
|
||||||
m_pakRouter(*this, m_workPath, m_cookPath) {}
|
, m_pakRouter(*this, m_workPath, m_cookPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void buildPaks(nod::Node& root,
|
void buildPaks(nod::Node& root, const std::vector<hecl::SystemString>& args, ExtractReport& rep)
|
||||||
const std::vector<hecl::SystemString>& args,
|
|
||||||
ExtractReport& rep)
|
|
||||||
{
|
{
|
||||||
m_nonPaks.clear();
|
m_nonPaks.clear();
|
||||||
m_paks.clear();
|
m_paks.clear();
|
||||||
|
@ -199,7 +193,6 @@ struct SpecMP1 : SpecBase
|
||||||
}
|
}
|
||||||
|
|
||||||
m_paks.emplace_back(m_project, child, good);
|
m_paks.emplace_back(m_project, child, good);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,10 +219,8 @@ struct SpecMP1 : SpecBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkFromStandaloneDisc(nod::DiscBase& disc,
|
bool checkFromStandaloneDisc(nod::DiscBase& disc, const hecl::SystemString& regstr,
|
||||||
const hecl::SystemString& regstr,
|
const std::vector<hecl::SystemString>& args, std::vector<ExtractReport>& reps)
|
||||||
const std::vector<hecl::SystemString>& args,
|
|
||||||
std::vector<ExtractReport>& reps)
|
|
||||||
{
|
{
|
||||||
nod::Partition* partition = disc.getDataPartition();
|
nod::Partition* partition = disc.getDataPartition();
|
||||||
std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf();
|
std::unique_ptr<uint8_t[]> dolBuf = partition->getDOLBuf();
|
||||||
|
@ -257,10 +248,8 @@ struct SpecMP1 : SpecBase
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkFromTrilogyDisc(nod::DiscBase& disc,
|
bool checkFromTrilogyDisc(nod::DiscBase& disc, const hecl::SystemString& regstr,
|
||||||
const hecl::SystemString& regstr,
|
const std::vector<hecl::SystemString>& args, std::vector<ExtractReport>& reps)
|
||||||
const std::vector<hecl::SystemString>& args,
|
|
||||||
std::vector<ExtractReport>& reps)
|
|
||||||
{
|
{
|
||||||
std::vector<hecl::SystemString> mp1args;
|
std::vector<hecl::SystemString> mp1args;
|
||||||
bool doExtract = false;
|
bool doExtract = false;
|
||||||
|
@ -328,10 +317,7 @@ struct SpecMP1 : SpecBase
|
||||||
m_workPath.makeDir();
|
m_workPath.makeDir();
|
||||||
|
|
||||||
progress(_S("Indexing PAKs"), _S(""), 2, 0.0);
|
progress(_S("Indexing PAKs"), _S(""), 2, 0.0);
|
||||||
m_pakRouter.build(m_paks, [&progress](float factor)
|
m_pakRouter.build(m_paks, [&progress](float factor) { progress(_S("Indexing PAKs"), _S(""), 2, factor); });
|
||||||
{
|
|
||||||
progress(_S("Indexing PAKs"), _S(""), 2, factor);
|
|
||||||
});
|
|
||||||
progress(_S("Indexing PAKs"), _S(""), 2, 1.0);
|
progress(_S("Indexing PAKs"), _S(""), 2, 1.0);
|
||||||
|
|
||||||
hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _S("out"));
|
hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _S("out"));
|
||||||
|
@ -388,11 +374,8 @@ struct SpecMP1 : SpecBase
|
||||||
progress(sysName.c_str(), _S(""), compIdx, 0.0);
|
progress(sysName.c_str(), _S(""), compIdx, 0.0);
|
||||||
}
|
}
|
||||||
hecl::SystemString pakName = sysName.sys_str();
|
hecl::SystemString pakName = sysName.sys_str();
|
||||||
process.addLambdaTransaction([&, pakName](hecl::BlenderToken& btok)
|
process.addLambdaTransaction([&, pakName](hecl::BlenderToken& btok) {
|
||||||
{
|
m_pakRouter.extractResources(pak, force, btok, [&](const hecl::SystemChar* substr, float factor) {
|
||||||
m_pakRouter.extractResources(pak, force, btok,
|
|
||||||
[&](const hecl::SystemChar* substr, float factor)
|
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lk(msgLock);
|
std::unique_lock<std::mutex> lk(msgLock);
|
||||||
progress(pakName.c_str(), substr, compIdx, factor);
|
progress(pakName.c_str(), substr, compIdx, factor);
|
||||||
});
|
});
|
||||||
|
@ -404,20 +387,11 @@ struct SpecMP1 : SpecBase
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hecl::Database::DataSpecEntry& getOriginalSpec() const
|
const hecl::Database::DataSpecEntry& getOriginalSpec() const { return SpecEntMP1; }
|
||||||
{
|
|
||||||
return SpecEntMP1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const
|
const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const { return SpecEntMP1ORIG; }
|
||||||
{
|
|
||||||
return SpecEntMP1ORIG;
|
|
||||||
}
|
|
||||||
|
|
||||||
hecl::ProjectPath getWorking(class UniqueID32& id)
|
hecl::ProjectPath getWorking(class UniqueID32& id) { return m_pakRouter.getWorking(id); }
|
||||||
{
|
|
||||||
return m_pakRouter.getWorking(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkPathPrefix(const hecl::ProjectPath& path) const
|
bool checkPathPrefix(const hecl::ProjectPath& path) const
|
||||||
{
|
{
|
||||||
|
@ -428,12 +402,13 @@ struct SpecMP1 : SpecBase
|
||||||
{
|
{
|
||||||
athena::io::YAMLDocReader reader;
|
athena::io::YAMLDocReader reader;
|
||||||
yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)athena::io::YAMLAthenaReader, &fp);
|
yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)athena::io::YAMLAthenaReader, &fp);
|
||||||
return reader.ClassTypeOperation([](const char* classType)
|
return reader.ClassTypeOperation([](const char* classType) {
|
||||||
{
|
|
||||||
if (!strcmp(classType, DNAMP1::MLVL::DNAType()))
|
if (!strcmp(classType, DNAMP1::MLVL::DNAType()))
|
||||||
return true;
|
return true;
|
||||||
else if (!strcmp(classType, DNAMP1::STRG::DNAType()))
|
else if (!strcmp(classType, DNAMP1::STRG::DNAType()))
|
||||||
return true;
|
return true;
|
||||||
|
else if (!strcmp(classType, DNAMP1::SCAN::DNAType()))
|
||||||
|
return true;
|
||||||
else if (!strcmp(classType, DNAParticle::GPSM<UniqueID32>::DNAType()))
|
else if (!strcmp(classType, DNAParticle::GPSM<UniqueID32>::DNAType()))
|
||||||
return true;
|
return true;
|
||||||
else if (!strcmp(classType, DNAParticle::SWSH<UniqueID32>::DNAType()))
|
else if (!strcmp(classType, DNAParticle::SWSH<UniqueID32>::DNAType()))
|
||||||
|
@ -575,8 +550,7 @@ struct SpecMP1 : SpecBase
|
||||||
yaml_parser_set_input_file(reader.getParser(), fp);
|
yaml_parser_set_input_file(reader.getParser(), fp);
|
||||||
|
|
||||||
urde::SObjectTag resTag;
|
urde::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');
|
resTag.type = SBIG('PART');
|
||||||
|
@ -627,6 +601,11 @@ struct SpecMP1 : SpecBase
|
||||||
resTag.type = SBIG('STRG');
|
resTag.type = SBIG('STRG');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(className, "urde::DNAMP1::SCAN"))
|
||||||
|
{
|
||||||
|
resTag.type = SBIG('SCAN');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else if (!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerRes") ||
|
else if (!strcmp(className, "DataSpec::DNAMP1::CTweakPlayerRes") ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakGunRes") ||
|
!strcmp(className, "DataSpec::DNAMP1::CTweakGunRes") ||
|
||||||
!strcmp(className, "DataSpec::DNAMP1::CTweakSlideShow") ||
|
!strcmp(className, "DataSpec::DNAMP1::CTweakSlideShow") ||
|
||||||
|
@ -673,15 +652,12 @@ struct SpecMP1 : SpecBase
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||||
BlendStream& ds, bool fast, hecl::BlenderToken& btok,
|
hecl::BlenderToken& btok, FCookProgress progress)
|
||||||
FCookProgress progress)
|
|
||||||
{
|
{
|
||||||
Mesh mesh = ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, m_pc ? 16 : -1,
|
Mesh mesh =
|
||||||
[&progress](int surfCount)
|
ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, m_pc ? 16 : -1,
|
||||||
{
|
[&progress](int surfCount) { progress(hecl::SysFormat(_S("%d"), surfCount).c_str()); });
|
||||||
progress(hecl::SysFormat(_S("%d"), surfCount).c_str());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (m_pc)
|
if (m_pc)
|
||||||
DNAMP1::CMDL::HMDLCook(out, in, mesh);
|
DNAMP1::CMDL::HMDLCook(out, in, mesh);
|
||||||
|
@ -689,14 +665,11 @@ struct SpecMP1 : SpecBase
|
||||||
DNAMP1::CMDL::Cook(out, in, mesh);
|
DNAMP1::CMDL::Cook(out, in, mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||||
BlendStream& ds, bool fast, hecl::BlenderToken& btok,
|
hecl::BlenderToken& btok, FCookProgress progress)
|
||||||
FCookProgress progress)
|
|
||||||
{
|
{
|
||||||
Actor actor = ds.compileActor();
|
Actor actor = ds.compileActor();
|
||||||
DNAMP1::ANCS::Cook(out, in, actor, ds, m_pc,
|
DNAMP1::ANCS::Cook(out, in, actor, ds, m_pc, [&](const hecl::ProjectPath& modelPath) -> bool {
|
||||||
[&](const hecl::ProjectPath& modelPath) -> bool
|
|
||||||
{
|
|
||||||
hecl::ProjectPath cooked;
|
hecl::ProjectPath cooked;
|
||||||
if (m_pc)
|
if (m_pc)
|
||||||
cooked = modelPath.getCookedPath(SpecEntMP1PC);
|
cooked = modelPath.getCookedPath(SpecEntMP1PC);
|
||||||
|
@ -707,9 +680,8 @@ struct SpecMP1 : SpecBase
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||||
BlendStream& ds, bool fast, hecl::BlenderToken& btok,
|
hecl::BlenderToken& btok, FCookProgress progress)
|
||||||
FCookProgress progress)
|
|
||||||
{
|
{
|
||||||
std::vector<std::string> meshes = ds.getMeshList();
|
std::vector<std::string> meshes = ds.getMeshList();
|
||||||
std::vector<Mesh> meshCompiles;
|
std::vector<Mesh> meshCompiles;
|
||||||
|
@ -726,11 +698,9 @@ struct SpecMP1 : SpecBase
|
||||||
progress(_S("Collision Mesh"));
|
progress(_S("Collision Mesh"));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
meshCompiles.push_back(ds.compileMesh(mesh, fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1,
|
meshCompiles.push_back(ds.compileMesh(
|
||||||
[&](int surfCount)
|
mesh, fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1,
|
||||||
{
|
[&](int surfCount) { progress(hecl::SysFormat(_S("%s %d"), meshSys.c_str(), surfCount).c_str()); }));
|
||||||
progress(hecl::SysFormat(_S("%s %d"), meshSys.c_str(), surfCount).c_str());
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!colMesh)
|
if (!colMesh)
|
||||||
|
@ -744,24 +714,22 @@ struct SpecMP1 : SpecBase
|
||||||
DNAMP1::MREA::Cook(out, in, meshCompiles, *colMesh, lights);
|
DNAMP1::MREA::Cook(out, in, meshCompiles, *colMesh, lights);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast,
|
||||||
BlendStream& ds, bool fast, hecl::BlenderToken& btok,
|
hecl::BlenderToken& btok, FCookProgress progress)
|
||||||
FCookProgress progress)
|
|
||||||
{
|
{
|
||||||
BlendStream::World world = ds.compileWorld();
|
BlendStream::World world = ds.compileWorld();
|
||||||
ds.close();
|
ds.close();
|
||||||
DNAMP1::MLVL::Cook(out, in, world, btok);
|
DNAMP1::MLVL::Cook(out, in, world, btok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds,
|
||||||
BlendStream& ds, hecl::BlenderToken& btok,
|
hecl::BlenderToken& btok, FCookProgress progress)
|
||||||
FCookProgress progress)
|
|
||||||
{
|
{
|
||||||
ds.compileGuiFrame(out.getAbsolutePathUTF8(), 0);
|
ds.compileGuiFrame(out.getAbsolutePathUTF8(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin,
|
||||||
athena::io::IStreamReader& fin, FCookProgress progress)
|
FCookProgress progress)
|
||||||
{
|
{
|
||||||
athena::io::YAMLDocReader reader;
|
athena::io::YAMLDocReader reader;
|
||||||
if (reader.parse(&fin))
|
if (reader.parse(&fin))
|
||||||
|
@ -776,6 +744,12 @@ struct SpecMP1 : SpecBase
|
||||||
strg.read(reader);
|
strg.read(reader);
|
||||||
DNAMP1::STRG::Cook(strg, out);
|
DNAMP1::STRG::Cook(strg, out);
|
||||||
}
|
}
|
||||||
|
else if (!classStr.compare(DNAMP1::SCAN::DNAType()))
|
||||||
|
{
|
||||||
|
DNAMP1::SCAN scan;
|
||||||
|
scan.read(reader);
|
||||||
|
DNAMP1::SCAN::Cook(scan, out);
|
||||||
|
}
|
||||||
else if (!classStr.compare(DNAParticle::GPSM<UniqueID32>::DNAType()))
|
else if (!classStr.compare(DNAParticle::GPSM<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
DNAParticle::GPSM<UniqueID32> gpsm;
|
DNAParticle::GPSM<UniqueID32> gpsm;
|
||||||
|
@ -945,6 +919,12 @@ struct SpecMP1 : SpecBase
|
||||||
strg.read(reader);
|
strg.read(reader);
|
||||||
strg.gatherDependencies(pathsOut);
|
strg.gatherDependencies(pathsOut);
|
||||||
}
|
}
|
||||||
|
if (!classStr.compare(DNAMP1::SCAN::DNAType()))
|
||||||
|
{
|
||||||
|
DNAMP1::SCAN scan;
|
||||||
|
scan.read(reader);
|
||||||
|
scan.gatherDependencies(pathsOut);
|
||||||
|
}
|
||||||
else if (!classStr.compare(DNAParticle::GPSM<UniqueID32>::DNAType()))
|
else if (!classStr.compare(DNAParticle::GPSM<UniqueID32>::DNAType()))
|
||||||
{
|
{
|
||||||
DNAParticle::GPSM<UniqueID32> gpsm;
|
DNAParticle::GPSM<UniqueID32> gpsm;
|
||||||
|
@ -990,49 +970,33 @@ struct SpecMP1 : SpecBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress)
|
||||||
FCookProgress progress)
|
|
||||||
{
|
{
|
||||||
DNAMP1::AGSC::Cook(in, out);
|
DNAMP1::AGSC::Cook(in, out);
|
||||||
progress(_S("Done"));
|
progress(_S("Done"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in,
|
void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress)
|
||||||
FCookProgress progress)
|
|
||||||
{
|
{
|
||||||
DNAMP1::CSNG::Cook(in, out);
|
DNAMP1::CSNG::Cook(in, out);
|
||||||
progress(_S("Done"));
|
progress(_S("Done"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
hecl::Database::DataSpecEntry SpecEntMP1 =
|
hecl::Database::DataSpecEntry SpecEntMP1 = {
|
||||||
{
|
_S("MP1"), _S("Data specification for original Metroid Prime engine"),
|
||||||
_S("MP1"),
|
[](hecl::Database::Project& project, hecl::Database::DataSpecTool) -> hecl::Database::IDataSpec* {
|
||||||
_S("Data specification for original Metroid Prime engine"),
|
return new struct SpecMP1(&SpecEntMP1, project, false);
|
||||||
[](hecl::Database::Project& project, hecl::Database::DataSpecTool)
|
}};
|
||||||
-> hecl::Database::IDataSpec* {return new struct SpecMP1(&SpecEntMP1, project, false);}
|
|
||||||
};
|
|
||||||
|
|
||||||
hecl::Database::DataSpecEntry SpecEntMP1PC =
|
hecl::Database::DataSpecEntry SpecEntMP1PC = {
|
||||||
{
|
_S("MP1-PC"), _S("Data specification for PC-optimized Metroid Prime engine"),
|
||||||
_S("MP1-PC"),
|
[](hecl::Database::Project& project, hecl::Database::DataSpecTool tool) -> hecl::Database::IDataSpec* {
|
||||||
_S("Data specification for PC-optimized Metroid Prime engine"),
|
|
||||||
[](hecl::Database::Project& project, hecl::Database::DataSpecTool tool)
|
|
||||||
-> hecl::Database::IDataSpec*
|
|
||||||
{
|
|
||||||
if (tool != hecl::Database::DataSpecTool::Extract)
|
if (tool != hecl::Database::DataSpecTool::Extract)
|
||||||
return new struct SpecMP1(&SpecEntMP1PC, project, true);
|
return new struct SpecMP1(&SpecEntMP1PC, project, true);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}};
|
||||||
};
|
|
||||||
|
|
||||||
hecl::Database::DataSpecEntry SpecEntMP1ORIG =
|
|
||||||
{
|
|
||||||
_S("MP1-ORIG"),
|
|
||||||
_S("Data specification for unmodified Metroid Prime resources"),
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
hecl::Database::DataSpecEntry SpecEntMP1ORIG = {
|
||||||
|
_S("MP1-ORIG"), _S("Data specification for unmodified Metroid Prime resources"), {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "Runtime/Collision/CCollidableOBBTreeGroup.hpp"
|
#include "Runtime/Collision/CCollidableOBBTreeGroup.hpp"
|
||||||
#include "Runtime/CSaveWorld.hpp"
|
#include "Runtime/CSaveWorld.hpp"
|
||||||
#include "Runtime/AutoMapper/CMapWorld.hpp"
|
#include "Runtime/AutoMapper/CMapWorld.hpp"
|
||||||
|
#include "Runtime/CScannableObjectInfo.hpp"
|
||||||
#include "Audio/CAudioGroupSet.hpp"
|
#include "Audio/CAudioGroupSet.hpp"
|
||||||
#include "Audio/CSfxManager.hpp"
|
#include "Audio/CSfxManager.hpp"
|
||||||
#include "Runtime/CDependencyGroup.hpp"
|
#include "Runtime/CDependencyGroup.hpp"
|
||||||
|
@ -108,6 +109,7 @@ ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& client
|
||||||
m_factoryMgr.AddFactory(FOURCC('SAVW'), FFactoryFunc(FSaveWorldFactory));
|
m_factoryMgr.AddFactory(FOURCC('SAVW'), FFactoryFunc(FSaveWorldFactory));
|
||||||
m_factoryMgr.AddFactory(FOURCC('MAPW'), FFactoryFunc(FMapWorldFactory));
|
m_factoryMgr.AddFactory(FOURCC('MAPW'), FFactoryFunc(FMapWorldFactory));
|
||||||
m_factoryMgr.AddFactory(FOURCC('OIDS'), FFactoryFunc(FMP1OriginalIDsFactory));
|
m_factoryMgr.AddFactory(FOURCC('OIDS'), FFactoryFunc(FMP1OriginalIDsFactory));
|
||||||
|
m_factoryMgr.AddFactory(FOURCC('SCAN'), FFactoryFunc(FScannableObjectInfoFactory));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj, CSimplePool& sp)
|
void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj, CSimplePool& sp)
|
||||||
|
|
|
@ -3,32 +3,19 @@
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
CScannableObjectInfo::CScannableObjectInfo(CInputStream& in, ResId resId)
|
CScannableObjectInfo::CScannableObjectInfo(CInputStream& in, ResId resId) : x0_scannableObjectId(resId)
|
||||||
: x0_scannableObjectId(resId)
|
|
||||||
{
|
{
|
||||||
u32 version = in.readUint32Big();
|
u32 version = in.readUint32Big();
|
||||||
Load(in, version);
|
Load(in, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResId CScannableObjectInfo::GetScannableObjectId() const
|
ResId CScannableObjectInfo::GetScannableObjectId() const { return x0_scannableObjectId; }
|
||||||
{
|
|
||||||
return x0_scannableObjectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
ResId CScannableObjectInfo::GetStringTableId() const
|
ResId CScannableObjectInfo::GetStringTableId() const { return x4_stringId; }
|
||||||
{
|
|
||||||
return x4_stringId;
|
|
||||||
}
|
|
||||||
|
|
||||||
float CScannableObjectInfo::GetTotalDownloadTime() const
|
float CScannableObjectInfo::GetTotalDownloadTime() const { return x8_totalDownloadTime; }
|
||||||
{
|
|
||||||
return x8_totalDownloadTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CScannableObjectInfo::SBucket& CScannableObjectInfo::GetBucket(s32 idx) const
|
const CScannableObjectInfo::SBucket& CScannableObjectInfo::GetBucket(s32 idx) const { return x14_buckets[idx]; }
|
||||||
{
|
|
||||||
return x14_buckets[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
void CScannableObjectInfo::Load(CInputStream& in, u32 version)
|
void CScannableObjectInfo::Load(CInputStream& in, u32 version)
|
||||||
{
|
{
|
||||||
|
@ -46,7 +33,7 @@ void CScannableObjectInfo::Load(CInputStream& in, u32 version)
|
||||||
if (version > 4)
|
if (version > 4)
|
||||||
x10_important = in.readBool();
|
x10_important = in.readBool();
|
||||||
|
|
||||||
for (u32 i = 0 ; i<4 ; i++)
|
for (u32 i = 0; i < 4; i++)
|
||||||
x14_buckets.emplace_back(in, version);
|
x14_buckets.emplace_back(in, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,9 +52,9 @@ CScannableObjectInfo::SBucket::SBucket(CInputStream& in, u32 version)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CFactoryFnReturn FScannableObjectInfoFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer &)
|
CFactoryFnReturn FScannableObjectInfoFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer&,
|
||||||
|
CObjectReference* selfRef)
|
||||||
{
|
{
|
||||||
return TToken<CScannableObjectInfo>::GetIObjObjectFor(std::make_unique<CScannableObjectInfo>(in, tag.id));
|
return TToken<CScannableObjectInfo>::GetIObjObjectFor(std::make_unique<CScannableObjectInfo>(in, tag.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ private:
|
||||||
u32 xc_category = 0;
|
u32 xc_category = 0;
|
||||||
bool x10_important = false;
|
bool x10_important = false;
|
||||||
rstl::reserved_vector<SBucket, 4> x14_buckets;
|
rstl::reserved_vector<SBucket, 4> x14_buckets;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CScannableObjectInfo(CInputStream&, ResId);
|
CScannableObjectInfo(CInputStream&, ResId);
|
||||||
ResId GetStringTableId() const;
|
ResId GetStringTableId() const;
|
||||||
|
@ -43,6 +44,7 @@ public:
|
||||||
bool IsImportant() const;
|
bool IsImportant() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
CFactoryFnReturn FScannableObjectInfoFactory(const SObjectTag&, CInputStream&, const CVParamTransfer&);
|
CFactoryFnReturn FScannableObjectInfoFactory(const SObjectTag&, CInputStream&, const CVParamTransfer&,
|
||||||
|
CObjectReference* selfRef);
|
||||||
}
|
}
|
||||||
#endif // __URDE_CSCANNABLEOBJECTINFO_HPP__
|
#endif // __URDE_CSCANNABLEOBJECTINFO_HPP__
|
||||||
|
|
|
@ -23,9 +23,7 @@ void CScriptGenerator::Accept(IVisitor& visitor) { visitor.Visit(this); }
|
||||||
|
|
||||||
void CScriptGenerator::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr)
|
void CScriptGenerator::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr)
|
||||||
{
|
{
|
||||||
if (msg == EScriptObjectMessage::SetToZero && GetActive())
|
if (msg == EScriptObjectMessage::SetToZero && GetActive() && !x20_conns.empty())
|
||||||
{
|
|
||||||
if (!x20_conns.empty())
|
|
||||||
{
|
{
|
||||||
std::vector<TUniqueId> follows;
|
std::vector<TUniqueId> follows;
|
||||||
follows.reserve(x20_conns.size());
|
follows.reserve(x20_conns.size());
|
||||||
|
@ -132,7 +130,6 @@ void CScriptGenerator::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CEntity::AcceptScriptMsg(msg, objId, stateMgr);
|
CEntity::AcceptScriptMsg(msg, objId, stateMgr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue