mirror of https://github.com/AxioDL/metaforce.git
New code style refactor
This commit is contained in:
parent
41ae32be31
commit
636c82a568
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
IndentWidth: 4
|
||||
BasedOnStyle: LLVM
|
||||
ColumnLimit: 120
|
||||
UseTab: Never
|
||||
---
|
||||
|
@ -8,7 +8,6 @@ DerivePointerAlignment: false
|
|||
PointerAlignment: Left
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
BreakBeforeBraces: Allman
|
||||
IndentCaseLabels: false
|
||||
AllowShortBlocksOnASingleLine: true
|
||||
AlignOperands: true
|
||||
|
@ -24,6 +23,6 @@ NamespaceIndentation: None
|
|||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
SortIncludes: false
|
||||
AccessModifierOffset: -4
|
||||
AccessModifierOffset: -2
|
||||
ConstructorInitializerIndentWidth: 0
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
<mapping directory="$PROJECT_DIR$/discord-rpc" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/hecl" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/hecl-gui" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/hecl-gui/quazip" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/hecl/extern/athena" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/hecl/extern/boo" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/hecl/extern/boo/glslang" vcs="Git" />
|
||||
|
|
|
@ -6,79 +6,70 @@ extern "C" const size_t ASSET_NAME_MP32_SZ;
|
|||
extern "C" const uint8_t ASSET_NAME_MP64[];
|
||||
extern "C" const size_t ASSET_NAME_MP64_SZ;
|
||||
|
||||
namespace DataSpec::AssetNameMap
|
||||
{
|
||||
namespace DataSpec::AssetNameMap {
|
||||
logvisor::Module Log("AssetNameMap");
|
||||
|
||||
struct SAsset
|
||||
{
|
||||
std::string name;
|
||||
std::string directory;
|
||||
hecl::FourCC type;
|
||||
SAsset() = default;
|
||||
SAsset(const hecl::FourCC& typeIn, athena::io::IStreamReader& in)
|
||||
: type(typeIn)
|
||||
{
|
||||
uint32_t nameLen = in.readUint32Big();
|
||||
name = in.readString(nameLen);
|
||||
uint32_t dirLen = in.readUint32Big();
|
||||
directory = in.readString(dirLen);
|
||||
}
|
||||
struct SAsset {
|
||||
std::string name;
|
||||
std::string directory;
|
||||
hecl::FourCC type;
|
||||
SAsset() = default;
|
||||
SAsset(const hecl::FourCC& typeIn, athena::io::IStreamReader& in) : type(typeIn) {
|
||||
uint32_t nameLen = in.readUint32Big();
|
||||
name = in.readString(nameLen);
|
||||
uint32_t dirLen = in.readUint32Big();
|
||||
directory = in.readString(dirLen);
|
||||
}
|
||||
};
|
||||
|
||||
static std::unordered_map<uint64_t, SAsset> g_AssetNameMap;
|
||||
static bool g_AssetNameMapInit = false;
|
||||
|
||||
void LoadAssetMap(athena::io::MemoryReader& ar)
|
||||
{
|
||||
if (!ar.hasError())
|
||||
{
|
||||
hecl::FourCC magic;
|
||||
if (ar.length() >= 4)
|
||||
ar.readBytesToBuf(&magic, 4);
|
||||
if (magic != FOURCC('AIDM'))
|
||||
Log.report(logvisor::Warning, _SYS_STR("Unable to load asset map; Assets will not have proper filenames for most files."));
|
||||
else
|
||||
{
|
||||
uint32_t assetCount = ar.readUint32Big();
|
||||
g_AssetNameMap.reserve(assetCount);
|
||||
for (uint32_t i = 0 ; i<assetCount ; ++i)
|
||||
{
|
||||
hecl::FourCC type;
|
||||
ar.readBytesToBuf(&type, 4);
|
||||
uint64_t id = ar.readUint64Big();
|
||||
g_AssetNameMap[id] = SAsset(type, ar);
|
||||
}
|
||||
}
|
||||
void LoadAssetMap(athena::io::MemoryReader& ar) {
|
||||
if (!ar.hasError()) {
|
||||
hecl::FourCC magic;
|
||||
if (ar.length() >= 4)
|
||||
ar.readBytesToBuf(&magic, 4);
|
||||
if (magic != FOURCC('AIDM'))
|
||||
Log.report(logvisor::Warning,
|
||||
_SYS_STR("Unable to load asset map; Assets will not have proper filenames for most files."));
|
||||
else {
|
||||
uint32_t assetCount = ar.readUint32Big();
|
||||
g_AssetNameMap.reserve(assetCount);
|
||||
for (uint32_t i = 0; i < assetCount; ++i) {
|
||||
hecl::FourCC type;
|
||||
ar.readBytesToBuf(&type, 4);
|
||||
uint64_t id = ar.readUint64Big();
|
||||
g_AssetNameMap[id] = SAsset(type, ar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitAssetNameMap()
|
||||
{
|
||||
if (g_AssetNameMapInit)
|
||||
return;
|
||||
void InitAssetNameMap() {
|
||||
if (g_AssetNameMapInit)
|
||||
return;
|
||||
|
||||
Log.report(logvisor::Info, "Initializing asset name database...");
|
||||
Log.report(logvisor::Info, "Initializing asset name database...");
|
||||
|
||||
/* First load the 32bit map for MP1/2 */
|
||||
{
|
||||
athena::io::MemoryReader ar(ASSET_NAME_MP32, ASSET_NAME_MP32_SZ);
|
||||
LoadAssetMap(ar);
|
||||
}
|
||||
/* Now load the 64bit map for MP3 */
|
||||
{
|
||||
athena::io::MemoryReader ar(ASSET_NAME_MP64, ASSET_NAME_MP64_SZ);
|
||||
LoadAssetMap(ar);
|
||||
}
|
||||
g_AssetNameMapInit = true;
|
||||
/* First load the 32bit map for MP1/2 */
|
||||
{
|
||||
athena::io::MemoryReader ar(ASSET_NAME_MP32, ASSET_NAME_MP32_SZ);
|
||||
LoadAssetMap(ar);
|
||||
}
|
||||
/* Now load the 64bit map for MP3 */
|
||||
{
|
||||
athena::io::MemoryReader ar(ASSET_NAME_MP64, ASSET_NAME_MP64_SZ);
|
||||
LoadAssetMap(ar);
|
||||
}
|
||||
g_AssetNameMapInit = true;
|
||||
}
|
||||
|
||||
const std::string* TranslateIdToName(const UniqueID32& id)
|
||||
{
|
||||
if (g_AssetNameMap.find(id.toUint64()) == g_AssetNameMap.end())
|
||||
return nullptr;
|
||||
const std::string* TranslateIdToName(const UniqueID32& id) {
|
||||
if (g_AssetNameMap.find(id.toUint64()) == g_AssetNameMap.end())
|
||||
return nullptr;
|
||||
|
||||
return &g_AssetNameMap[id.toUint64()].name;
|
||||
return &g_AssetNameMap[id.toUint64()].name;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::AssetNameMap
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
#include <string>
|
||||
#include "DNACommon/DNACommon.hpp"
|
||||
|
||||
namespace DataSpec::AssetNameMap
|
||||
{
|
||||
namespace DataSpec::AssetNameMap {
|
||||
void InitAssetNameMap();
|
||||
const std::string* TranslateIdToName(const UniqueID32&);
|
||||
const std::string* TranslateIdToName(const UniqueID64&);
|
||||
}
|
||||
} // namespace DataSpec::AssetNameMap
|
||||
|
|
|
@ -5,20 +5,18 @@
|
|||
extern "C" uint8_t RETRO_MASTER_SHADER[];
|
||||
extern "C" size_t RETRO_MASTER_SHADER_SZ;
|
||||
|
||||
namespace DataSpec::Blender
|
||||
{
|
||||
namespace DataSpec::Blender {
|
||||
|
||||
bool BuildMasterShader(const hecl::ProjectPath& path)
|
||||
{
|
||||
hecl::blender::Connection& conn = hecl::blender::Connection::SharedConnection();
|
||||
if (!conn.createBlend(path, hecl::blender::BlendType::None))
|
||||
return false;
|
||||
{
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os << RETRO_MASTER_SHADER;
|
||||
os << "make_master_shader_library()\n";
|
||||
}
|
||||
return conn.saveBlend();
|
||||
bool BuildMasterShader(const hecl::ProjectPath& path) {
|
||||
hecl::blender::Connection& conn = hecl::blender::Connection::SharedConnection();
|
||||
if (!conn.createBlend(path, hecl::blender::BlendType::None))
|
||||
return false;
|
||||
{
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os << RETRO_MASTER_SHADER;
|
||||
os << "make_master_shader_library()\n";
|
||||
}
|
||||
return conn.saveBlend();
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::Blender
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
#include <hecl/hecl.hpp>
|
||||
|
||||
namespace DataSpec::Blender
|
||||
{
|
||||
namespace DataSpec::Blender {
|
||||
|
||||
bool BuildMasterShader(const hecl::ProjectPath& path);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -7,302 +7,259 @@
|
|||
#include "DataSpec/DNAMP3/CHAR.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAANCS
|
||||
{
|
||||
namespace DataSpec::DNAANCS {
|
||||
|
||||
template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
|
||||
bool ReadANCSToBlender(hecl::blender::Connection& conn,
|
||||
const ANCSDNA& ancs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged,
|
||||
bool force)
|
||||
{
|
||||
/* Extract character CMDL/CSKR first */
|
||||
std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
|
||||
ancs.getCharacterResInfo(chResInfo);
|
||||
for (const auto& info : chResInfo)
|
||||
{
|
||||
const nod::Node* node;
|
||||
const typename PAKRouter::EntryType* cmdlE =
|
||||
pakRouter.lookupEntry(info.cmdl, &node, true, false);
|
||||
if (cmdlE)
|
||||
{
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
if (force || cmdlPath.isNone())
|
||||
{
|
||||
cmdlPath.makeDirChain(false);
|
||||
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
|
||||
return false;
|
||||
bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged, bool force) {
|
||||
/* Extract character CMDL/CSKR first */
|
||||
std::vector<CharacterResInfo<typename PAKRouter::IDType>> chResInfo;
|
||||
ancs.getCharacterResInfo(chResInfo);
|
||||
for (const auto& info : chResInfo) {
|
||||
const nod::Node* node;
|
||||
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node, true, false);
|
||||
if (cmdlE) {
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
if (force || cmdlPath.isNone()) {
|
||||
cmdlPath.makeDirChain(false);
|
||||
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
|
||||
return false;
|
||||
|
||||
std::string bestName = pakRouter.getBestEntryName(*cmdlE);
|
||||
hecl::SystemStringConv bestNameView(bestName);
|
||||
fileChanged(bestNameView.c_str());
|
||||
std::string bestName = pakRouter.getBestEntryName(*cmdlE);
|
||||
hecl::SystemStringConv bestNameView(bestName);
|
||||
fileChanged(bestNameView.c_str());
|
||||
|
||||
typename ANCSDNA::CSKRType cskr;
|
||||
pakRouter.lookupAndReadDNA(info.cskr, cskr);
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
||||
using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
|
||||
RigPair rigPair(&cskr, &cinf);
|
||||
typename ANCSDNA::CSKRType cskr;
|
||||
pakRouter.lookupAndReadDNA(info.cskr, cskr);
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
||||
using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
|
||||
RigPair rigPair(&cskr, &cinf);
|
||||
|
||||
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>
|
||||
(conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
|
||||
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>(
|
||||
conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
|
||||
|
||||
conn.saveBlend();
|
||||
}
|
||||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract attachment CMDL/CSKRs first */
|
||||
auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id);
|
||||
for (auto it = attRange.first; it != attRange.second; ++it) {
|
||||
auto cmdlid = it->second.first.second;
|
||||
|
||||
const nod::Node* node;
|
||||
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(cmdlid, &node, true, false);
|
||||
if (cmdlE) {
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
if (force || cmdlPath.isNone()) {
|
||||
cmdlPath.makeDirChain(false);
|
||||
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
|
||||
return false;
|
||||
|
||||
std::string bestName = pakRouter.getBestEntryName(*cmdlE);
|
||||
hecl::SystemStringConv bestNameView(bestName);
|
||||
fileChanged(bestNameView.c_str());
|
||||
|
||||
const auto* rp = pakRouter.lookupCMDLRigPair(cmdlid);
|
||||
typename ANCSDNA::CSKRType cskr;
|
||||
pakRouter.lookupAndReadDNA(rp->first, cskr);
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(rp->second, cinf);
|
||||
using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
|
||||
RigPair rigPair(&cskr, &cinf);
|
||||
|
||||
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>(
|
||||
conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
|
||||
|
||||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string bestName = pakRouter.getBestEntryName(entry);
|
||||
hecl::SystemStringConv bestNameView(bestName);
|
||||
fileChanged(bestNameView.c_str());
|
||||
|
||||
/* Establish ANCS blend */
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::Actor))
|
||||
return false;
|
||||
|
||||
std::string firstName;
|
||||
typename ANCSDNA::CINFType firstCinf;
|
||||
{
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
|
||||
os.format(
|
||||
"import bpy\n"
|
||||
"from mathutils import Vector\n"
|
||||
"bpy.context.scene.name = '%s'\n"
|
||||
"bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n"
|
||||
"\n"
|
||||
"# Using 'Blender Game'\n"
|
||||
"bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
|
||||
"\n"
|
||||
"# Clear Scene\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" if ob.type != 'LAMP' and ob.type != 'CAMERA':\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n"
|
||||
"\n"
|
||||
"actor_data = bpy.context.scene.hecl_sact_data\n"
|
||||
"arm_obj = None\n",
|
||||
pakRouter.getBestEntryName(entry).c_str());
|
||||
|
||||
std::unordered_set<typename PAKRouter::IDType> cinfsDone;
|
||||
for (const auto& info : chResInfo) {
|
||||
/* Provide data to add-on */
|
||||
os.format(
|
||||
"actor_subtype = actor_data.subtypes.add()\n"
|
||||
"actor_subtype.name = '%s'\n\n",
|
||||
info.name.c_str());
|
||||
|
||||
/* Build CINF if needed */
|
||||
if (cinfsDone.find(info.cinf) == cinfsDone.end()) {
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
||||
cinf.sendCINFToBlender(os, info.cinf);
|
||||
if (cinfsDone.empty()) {
|
||||
firstName = ANCSDNA::CINFType::GetCINFArmatureName(info.cinf);
|
||||
firstCinf = cinf;
|
||||
}
|
||||
cinfsDone.insert(info.cinf);
|
||||
} else
|
||||
os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str());
|
||||
os << "actor_subtype.linked_armature = arm_obj.name\n";
|
||||
|
||||
/* Link CMDL */
|
||||
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, nullptr, true, false);
|
||||
if (cmdlE) {
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true);
|
||||
|
||||
/* Attach CMDL to CINF */
|
||||
os << "if obj.name not in bpy.context.scene.objects:\n"
|
||||
" bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.parent = arm_obj\n"
|
||||
"obj.parent_type = 'ARMATURE'\n"
|
||||
"actor_subtype.linked_mesh = obj.name\n\n";
|
||||
}
|
||||
|
||||
/* Link overlays */
|
||||
for (const auto& overlay : info.overlays) {
|
||||
os << "overlay = actor_subtype.overlays.add()\n";
|
||||
os.format("overlay.name = '%s'\n", overlay.first.c_str());
|
||||
|
||||
/* Link CMDL */
|
||||
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(overlay.second.first, nullptr, true, false);
|
||||
if (cmdlE) {
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true);
|
||||
|
||||
/* Attach CMDL to CINF */
|
||||
os << "if obj.name not in bpy.context.scene.objects:\n"
|
||||
" bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.parent = arm_obj\n"
|
||||
"obj.parent_type = 'ARMATURE'\n"
|
||||
"overlay.linked_mesh = obj.name\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract attachment CMDL/CSKRs first */
|
||||
auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id);
|
||||
for (auto it = attRange.first; it != attRange.second; ++it)
|
||||
{
|
||||
auto cmdlid = it->second.first.second;
|
||||
/* Link attachments */
|
||||
for (auto it = attRange.first; it != attRange.second; ++it) {
|
||||
os << "attachment = actor_data.attachments.add()\n";
|
||||
os.format("attachment.name = '%s'\n", it->second.second.c_str());
|
||||
|
||||
const nod::Node* node;
|
||||
const typename PAKRouter::EntryType* cmdlE =
|
||||
pakRouter.lookupEntry(cmdlid, &node, true, false);
|
||||
if (cmdlE)
|
||||
{
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
if (force || cmdlPath.isNone())
|
||||
{
|
||||
cmdlPath.makeDirChain(false);
|
||||
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
|
||||
return false;
|
||||
auto cinfid = it->second.first.first;
|
||||
auto cmdlid = it->second.first.second;
|
||||
|
||||
std::string bestName = pakRouter.getBestEntryName(*cmdlE);
|
||||
hecl::SystemStringConv bestNameView(bestName);
|
||||
fileChanged(bestNameView.c_str());
|
||||
if (cinfid) {
|
||||
/* Build CINF if needed */
|
||||
if (cinfsDone.find(cinfid) == cinfsDone.end()) {
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(cinfid, cinf);
|
||||
cinf.sendCINFToBlender(os, cinfid);
|
||||
if (cinfsDone.empty()) {
|
||||
firstName = ANCSDNA::CINFType::GetCINFArmatureName(cinfid);
|
||||
firstCinf = cinf;
|
||||
}
|
||||
cinfsDone.insert(cinfid);
|
||||
} else
|
||||
os.format("arm_obj = bpy.data.objects['CINF_%s']\n", cinfid.toString().c_str());
|
||||
os << "attachment.linked_armature = arm_obj.name\n";
|
||||
}
|
||||
|
||||
const auto* rp = pakRouter.lookupCMDLRigPair(cmdlid);
|
||||
typename ANCSDNA::CSKRType cskr;
|
||||
pakRouter.lookupAndReadDNA(rp->first, cskr);
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(rp->second, cinf);
|
||||
using RigPair = std::pair<typename ANCSDNA::CSKRType*, typename ANCSDNA::CINFType*>;
|
||||
RigPair rigPair(&cskr, &cinf);
|
||||
/* Link CMDL */
|
||||
const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(cmdlid, nullptr, true, false);
|
||||
if (cmdlE) {
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true);
|
||||
|
||||
PAKEntryReadStream rs = cmdlE->beginReadStream(*node);
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter, MaterialSet, RigPair, SurfaceHeader, CMDLVersion>
|
||||
(conn, rs, pakRouter, *cmdlE, dataspec, rigPair);
|
||||
|
||||
conn.saveBlend();
|
||||
}
|
||||
}
|
||||
/* Attach CMDL to CINF */
|
||||
os << "if obj.name not in bpy.context.scene.objects:\n"
|
||||
" bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.parent = arm_obj\n"
|
||||
"obj.parent_type = 'ARMATURE'\n"
|
||||
"attachment.linked_mesh = obj.name\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string bestName = pakRouter.getBestEntryName(entry);
|
||||
hecl::SystemStringConv bestNameView(bestName);
|
||||
fileChanged(bestNameView.c_str());
|
||||
{
|
||||
hecl::blender::DataStream ds = conn.beginData();
|
||||
std::unordered_map<std::string, hecl::blender::Matrix3f> matrices = ds.getBoneMatrices(firstName);
|
||||
ds.close();
|
||||
DNAANIM::RigInverter<typename ANCSDNA::CINFType> inverter(firstCinf, matrices);
|
||||
|
||||
/* Establish ANCS blend */
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::Actor))
|
||||
return false;
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os << "import bpy\n"
|
||||
"actor_data = bpy.context.scene.hecl_sact_data\n";
|
||||
|
||||
std::string firstName;
|
||||
typename ANCSDNA::CINFType firstCinf;
|
||||
{
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
/* Get animation primitives */
|
||||
std::map<atUint32, AnimationResInfo<typename PAKRouter::IDType>> animResInfo;
|
||||
ancs.getAnimationResInfo(&pakRouter, animResInfo);
|
||||
for (const auto& id : animResInfo) {
|
||||
typename ANCSDNA::ANIMType anim;
|
||||
if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true)) {
|
||||
os.format(
|
||||
"act = bpy.data.actions.new('%s')\n"
|
||||
"act.use_fake_user = True\n",
|
||||
id.second.name.c_str());
|
||||
anim.sendANIMToBlender(os, inverter, id.second.additive);
|
||||
}
|
||||
|
||||
os.format("import bpy\n"
|
||||
"from mathutils import Vector\n"
|
||||
"bpy.context.scene.name = '%s'\n"
|
||||
"bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n"
|
||||
"\n"
|
||||
"# Using 'Blender Game'\n"
|
||||
"bpy.context.scene.render.engine = 'BLENDER_GAME'\n"
|
||||
"\n"
|
||||
"# Clear Scene\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" if ob.type != 'LAMP' and ob.type != 'CAMERA':\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n"
|
||||
"\n"
|
||||
"actor_data = bpy.context.scene.hecl_sact_data\n"
|
||||
"arm_obj = None\n",
|
||||
pakRouter.getBestEntryName(entry).c_str());
|
||||
os.format(
|
||||
"actor_action = actor_data.actions.add()\n"
|
||||
"actor_action.name = '%s'\n",
|
||||
id.second.name.c_str());
|
||||
|
||||
std::unordered_set<typename PAKRouter::IDType> cinfsDone;
|
||||
for (const auto& info : chResInfo)
|
||||
{
|
||||
/* Provide data to add-on */
|
||||
os.format("actor_subtype = actor_data.subtypes.add()\n"
|
||||
"actor_subtype.name = '%s'\n\n",
|
||||
info.name.c_str());
|
||||
|
||||
/* Build CINF if needed */
|
||||
if (cinfsDone.find(info.cinf) == cinfsDone.end())
|
||||
{
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(info.cinf, cinf);
|
||||
cinf.sendCINFToBlender(os, info.cinf);
|
||||
if (cinfsDone.empty())
|
||||
{
|
||||
firstName = ANCSDNA::CINFType::GetCINFArmatureName(info.cinf);
|
||||
firstCinf = cinf;
|
||||
}
|
||||
cinfsDone.insert(info.cinf);
|
||||
}
|
||||
else
|
||||
os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str());
|
||||
os << "actor_subtype.linked_armature = arm_obj.name\n";
|
||||
|
||||
/* Link CMDL */
|
||||
const typename PAKRouter::EntryType* cmdlE =
|
||||
pakRouter.lookupEntry(info.cmdl, nullptr, true, false);
|
||||
if (cmdlE)
|
||||
{
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(),
|
||||
pakRouter.getBestEntryName(*cmdlE).data(), true);
|
||||
|
||||
/* Attach CMDL to CINF */
|
||||
os << "if obj.name not in bpy.context.scene.objects:\n"
|
||||
" bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.parent = arm_obj\n"
|
||||
"obj.parent_type = 'ARMATURE'\n"
|
||||
"actor_subtype.linked_mesh = obj.name\n\n";
|
||||
}
|
||||
|
||||
/* Link overlays */
|
||||
for (const auto& overlay : info.overlays)
|
||||
{
|
||||
os << "overlay = actor_subtype.overlays.add()\n";
|
||||
os.format("overlay.name = '%s'\n", overlay.first.c_str());
|
||||
|
||||
/* Link CMDL */
|
||||
const typename PAKRouter::EntryType* cmdlE =
|
||||
pakRouter.lookupEntry(overlay.second.first, nullptr, true, false);
|
||||
if (cmdlE)
|
||||
{
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(),
|
||||
pakRouter.getBestEntryName(*cmdlE).data(), true);
|
||||
|
||||
/* Attach CMDL to CINF */
|
||||
os << "if obj.name not in bpy.context.scene.objects:\n"
|
||||
" bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.parent = arm_obj\n"
|
||||
"obj.parent_type = 'ARMATURE'\n"
|
||||
"overlay.linked_mesh = obj.name\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Link attachments */
|
||||
for (auto it = attRange.first; it != attRange.second; ++it)
|
||||
{
|
||||
os << "attachment = actor_data.attachments.add()\n";
|
||||
os.format("attachment.name = '%s'\n", it->second.second.c_str());
|
||||
|
||||
auto cinfid = it->second.first.first;
|
||||
auto cmdlid = it->second.first.second;
|
||||
|
||||
if (cinfid)
|
||||
{
|
||||
/* Build CINF if needed */
|
||||
if (cinfsDone.find(cinfid) == cinfsDone.end())
|
||||
{
|
||||
typename ANCSDNA::CINFType cinf;
|
||||
pakRouter.lookupAndReadDNA(cinfid, cinf);
|
||||
cinf.sendCINFToBlender(os, cinfid);
|
||||
if (cinfsDone.empty())
|
||||
{
|
||||
firstName = ANCSDNA::CINFType::GetCINFArmatureName(cinfid);
|
||||
firstCinf = cinf;
|
||||
}
|
||||
cinfsDone.insert(cinfid);
|
||||
}
|
||||
else
|
||||
os.format("arm_obj = bpy.data.objects['CINF_%s']\n", cinfid.toString().c_str());
|
||||
os << "attachment.linked_armature = arm_obj.name\n";
|
||||
}
|
||||
|
||||
/* Link CMDL */
|
||||
const typename PAKRouter::EntryType* cmdlE =
|
||||
pakRouter.lookupEntry(cmdlid, nullptr, true, false);
|
||||
if (cmdlE)
|
||||
{
|
||||
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
|
||||
os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(),
|
||||
pakRouter.getBestEntryName(*cmdlE).data(), true);
|
||||
|
||||
/* Attach CMDL to CINF */
|
||||
os << "if obj.name not in bpy.context.scene.objects:\n"
|
||||
" bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.parent = arm_obj\n"
|
||||
"obj.parent_type = 'ARMATURE'\n"
|
||||
"attachment.linked_mesh = obj.name\n\n";
|
||||
}
|
||||
}
|
||||
/* Extract EVNT if present */
|
||||
anim.extractEVNT(id.second, outPath, pakRouter, force);
|
||||
}
|
||||
|
||||
{
|
||||
hecl::blender::DataStream ds = conn.beginData();
|
||||
std::unordered_map<std::string,
|
||||
hecl::blender::Matrix3f> matrices = ds.getBoneMatrices(firstName);
|
||||
ds.close();
|
||||
DNAANIM::RigInverter<typename ANCSDNA::CINFType> inverter(firstCinf, matrices);
|
||||
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os << "import bpy\n"
|
||||
"actor_data = bpy.context.scene.hecl_sact_data\n";
|
||||
|
||||
/* Get animation primitives */
|
||||
std::map<atUint32, AnimationResInfo<typename PAKRouter::IDType>> animResInfo;
|
||||
ancs.getAnimationResInfo(&pakRouter, animResInfo);
|
||||
for (const auto& id : animResInfo)
|
||||
{
|
||||
typename ANCSDNA::ANIMType anim;
|
||||
if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true))
|
||||
{
|
||||
os.format("act = bpy.data.actions.new('%s')\n"
|
||||
"act.use_fake_user = True\n", id.second.name.c_str());
|
||||
anim.sendANIMToBlender(os, inverter, id.second.additive);
|
||||
}
|
||||
|
||||
os.format("actor_action = actor_data.actions.add()\n"
|
||||
"actor_action.name = '%s'\n", id.second.name.c_str());
|
||||
|
||||
/* Extract EVNT if present */
|
||||
anim.extractEVNT(id.second, outPath, pakRouter, force);
|
||||
}
|
||||
}
|
||||
conn.saveBlend();
|
||||
return true;
|
||||
}
|
||||
conn.saveBlend();
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool ReadANCSToBlender<PAKRouter<DNAMP1::PAKBridge>, DNAMP1::ANCS, DNAMP1::MaterialSet, DNACMDL::SurfaceHeader_1, 2>
|
||||
(hecl::blender::Connection& conn,
|
||||
const DNAMP1::ANCS& ancs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter,
|
||||
const typename PAKRouter<DNAMP1::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged,
|
||||
bool force);
|
||||
template bool ReadANCSToBlender<PAKRouter<DNAMP2::PAKBridge>, DNAMP2::ANCS, DNAMP2::MaterialSet, DNACMDL::SurfaceHeader_2, 4>
|
||||
(hecl::blender::Connection& conn,
|
||||
const DNAMP2::ANCS& ancs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter,
|
||||
const typename PAKRouter<DNAMP2::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged,
|
||||
bool force);
|
||||
template bool ReadANCSToBlender<PAKRouter<DNAMP3::PAKBridge>, DNAMP3::CHAR, DNAMP3::MaterialSet, DNACMDL::SurfaceHeader_3, 4>
|
||||
(hecl::blender::Connection& conn,
|
||||
const DNAMP3::CHAR& ancs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP3::PAKBridge>& pakRouter,
|
||||
const typename PAKRouter<DNAMP3::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged,
|
||||
bool force);
|
||||
template bool
|
||||
ReadANCSToBlender<PAKRouter<DNAMP1::PAKBridge>, DNAMP1::ANCS, DNAMP1::MaterialSet, DNACMDL::SurfaceHeader_1, 2>(
|
||||
hecl::blender::Connection& conn, const DNAMP1::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter, const typename PAKRouter<DNAMP1::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec, std::function<void(const hecl::SystemChar*)> fileChanged, bool force);
|
||||
template bool
|
||||
ReadANCSToBlender<PAKRouter<DNAMP2::PAKBridge>, DNAMP2::ANCS, DNAMP2::MaterialSet, DNACMDL::SurfaceHeader_2, 4>(
|
||||
hecl::blender::Connection& conn, const DNAMP2::ANCS& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter, const typename PAKRouter<DNAMP2::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec, std::function<void(const hecl::SystemChar*)> fileChanged, bool force);
|
||||
template bool
|
||||
ReadANCSToBlender<PAKRouter<DNAMP3::PAKBridge>, DNAMP3::CHAR, DNAMP3::MaterialSet, DNACMDL::SurfaceHeader_3, 4>(
|
||||
hecl::blender::Connection& conn, const DNAMP3::CHAR& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP3::PAKBridge>& pakRouter, const typename PAKRouter<DNAMP3::PAKBridge>::EntryType& entry,
|
||||
const SpecBase& dataspec, std::function<void(const hecl::SystemChar*)> fileChanged, bool force);
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAANCS
|
||||
|
|
|
@ -5,41 +5,32 @@
|
|||
#include "CMDL.hpp"
|
||||
#include "RigInverter.hpp"
|
||||
|
||||
namespace DataSpec::DNAANCS
|
||||
{
|
||||
namespace DataSpec::DNAANCS {
|
||||
|
||||
using Actor = hecl::blender::Actor;
|
||||
using Armature = hecl::blender::Armature;
|
||||
using Action = hecl::blender::Action;
|
||||
|
||||
template <typename IDTYPE>
|
||||
struct CharacterResInfo
|
||||
{
|
||||
std::string name;
|
||||
IDTYPE cmdl;
|
||||
IDTYPE cskr;
|
||||
IDTYPE cinf;
|
||||
std::vector<std::pair<std::string, std::pair<IDTYPE, IDTYPE>>> overlays;
|
||||
struct CharacterResInfo {
|
||||
std::string name;
|
||||
IDTYPE cmdl;
|
||||
IDTYPE cskr;
|
||||
IDTYPE cinf;
|
||||
std::vector<std::pair<std::string, std::pair<IDTYPE, IDTYPE>>> overlays;
|
||||
};
|
||||
|
||||
template <typename IDTYPE>
|
||||
struct AnimationResInfo
|
||||
{
|
||||
std::string name;
|
||||
IDTYPE animId;
|
||||
IDTYPE evntId;
|
||||
bool additive;
|
||||
struct AnimationResInfo {
|
||||
std::string name;
|
||||
IDTYPE animId;
|
||||
IDTYPE evntId;
|
||||
bool additive;
|
||||
};
|
||||
|
||||
template <class PAKRouter, class ANCSDNA, class MaterialSet, class SurfaceHeader, atUint32 CMDLVersion>
|
||||
bool ReadANCSToBlender(hecl::blender::Connection& conn,
|
||||
const ANCSDNA& ancs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged,
|
||||
bool force=false);
|
||||
|
||||
}
|
||||
bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged, bool force = false);
|
||||
|
||||
} // namespace DataSpec::DNAANCS
|
||||
|
|
|
@ -3,529 +3,439 @@
|
|||
|
||||
#define DUMP_KEYS 0
|
||||
|
||||
namespace DataSpec::DNAANIM
|
||||
{
|
||||
namespace DataSpec::DNAANIM {
|
||||
|
||||
size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& channels)
|
||||
{
|
||||
size_t bitsPerKeyFrame = 0;
|
||||
for (const Channel& chan : channels)
|
||||
{
|
||||
switch (chan.type)
|
||||
{
|
||||
case Channel::Type::Rotation:
|
||||
bitsPerKeyFrame += 1;
|
||||
case Channel::Type::Translation:
|
||||
case Channel::Type::Scale:
|
||||
bitsPerKeyFrame += chan.q[0];
|
||||
bitsPerKeyFrame += chan.q[1];
|
||||
bitsPerKeyFrame += chan.q[2];
|
||||
break;
|
||||
case Channel::Type::KfHead:
|
||||
bitsPerKeyFrame += 1;
|
||||
break;
|
||||
case Channel::Type::RotationMP3:
|
||||
bitsPerKeyFrame += chan.q[0];
|
||||
bitsPerKeyFrame += chan.q[1];
|
||||
bitsPerKeyFrame += chan.q[2];
|
||||
bitsPerKeyFrame += chan.q[3];
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& channels) {
|
||||
size_t bitsPerKeyFrame = 0;
|
||||
for (const Channel& chan : channels) {
|
||||
switch (chan.type) {
|
||||
case Channel::Type::Rotation:
|
||||
bitsPerKeyFrame += 1;
|
||||
case Channel::Type::Translation:
|
||||
case Channel::Type::Scale:
|
||||
bitsPerKeyFrame += chan.q[0];
|
||||
bitsPerKeyFrame += chan.q[1];
|
||||
bitsPerKeyFrame += chan.q[2];
|
||||
break;
|
||||
case Channel::Type::KfHead:
|
||||
bitsPerKeyFrame += 1;
|
||||
break;
|
||||
case Channel::Type::RotationMP3:
|
||||
bitsPerKeyFrame += chan.q[0];
|
||||
bitsPerKeyFrame += chan.q[1];
|
||||
bitsPerKeyFrame += chan.q[2];
|
||||
bitsPerKeyFrame += chan.q[3];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (bitsPerKeyFrame * keyFrameCount + 31) / 32 * 4;
|
||||
}
|
||||
return (bitsPerKeyFrame * keyFrameCount + 31) / 32 * 4;
|
||||
}
|
||||
|
||||
static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div)
|
||||
{
|
||||
float q = M_PIF / 2.0f / float(div);
|
||||
zeus::simd_floats f(quat.simd);
|
||||
return
|
||||
{
|
||||
{
|
||||
atInt32(std::asin(f[1]) / q),
|
||||
atInt32(std::asin(f[2]) / q),
|
||||
atInt32(std::asin(f[3]) / q),
|
||||
},
|
||||
(f[0] < 0.f)
|
||||
};
|
||||
static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div) {
|
||||
float q = M_PIF / 2.0f / float(div);
|
||||
zeus::simd_floats f(quat.simd);
|
||||
return {{
|
||||
atInt32(std::asin(f[1]) / q),
|
||||
atInt32(std::asin(f[2]) / q),
|
||||
atInt32(std::asin(f[3]) / q),
|
||||
},
|
||||
(f[0] < 0.f)};
|
||||
}
|
||||
|
||||
static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div)
|
||||
{
|
||||
float q = M_PIF / 2.0f / float(div);
|
||||
athena::simd_floats f = {
|
||||
0.0f,
|
||||
std::sin(v.v[0] * q),
|
||||
std::sin(v.v[1] * q),
|
||||
std::sin(v.v[2] * q),
|
||||
};
|
||||
f[0] = std::sqrt(std::max((1.0f -
|
||||
(f[1] * f[1] +
|
||||
f[2] * f[2] +
|
||||
f[3] * f[3])), 0.0f));
|
||||
f[0] = v.w ? -f[0] : f[0];
|
||||
Value retval;
|
||||
retval.simd.copy_from(f);
|
||||
return retval;
|
||||
static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div) {
|
||||
float q = M_PIF / 2.0f / float(div);
|
||||
athena::simd_floats f = {
|
||||
0.0f,
|
||||
std::sin(v.v[0] * q),
|
||||
std::sin(v.v[1] * q),
|
||||
std::sin(v.v[2] * q),
|
||||
};
|
||||
f[0] = std::sqrt(std::max((1.0f - (f[1] * f[1] + f[2] * f[2] + f[3] * f[3])), 0.0f));
|
||||
f[0] = v.w ? -f[0] : f[0];
|
||||
Value retval;
|
||||
retval.simd.copy_from(f);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline Value DequantizeRotation_3(const QuantizedRot& v, atUint32 div)
|
||||
{
|
||||
float q = 1.0f / float(div);
|
||||
athena::simd_floats f = {
|
||||
0.0f,
|
||||
v.v[0] * q,
|
||||
v.v[1] * q,
|
||||
v.v[2] * q,
|
||||
};
|
||||
f[0] = std::sqrt(std::max((1.0f -
|
||||
(f[1] * f[1] +
|
||||
f[2] * f[2] +
|
||||
f[3] * f[3])), 0.0f));
|
||||
f[0] = v.w ? -f[0] : f[0];
|
||||
Value retval;
|
||||
retval.simd.copy_from(f);
|
||||
return retval;
|
||||
static inline Value DequantizeRotation_3(const QuantizedRot& v, atUint32 div) {
|
||||
float q = 1.0f / float(div);
|
||||
athena::simd_floats f = {
|
||||
0.0f,
|
||||
v.v[0] * q,
|
||||
v.v[1] * q,
|
||||
v.v[2] * q,
|
||||
};
|
||||
f[0] = std::sqrt(std::max((1.0f - (f[1] * f[1] + f[2] * f[2] + f[3] * f[3])), 0.0f));
|
||||
f[0] = v.w ? -f[0] : f[0];
|
||||
Value retval;
|
||||
retval.simd.copy_from(f);
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool BitstreamReader::dequantizeBit(const atUint8* data)
|
||||
{
|
||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||
atUint32 bitRem = m_bitCur % 32;
|
||||
bool BitstreamReader::dequantizeBit(const atUint8* data) {
|
||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||
atUint32 bitRem = m_bitCur % 32;
|
||||
|
||||
/* Fill 32 bit buffer with region containing bits */
|
||||
/* Make them least significant */
|
||||
atUint32 tempBuf = hecl::SBig(*reinterpret_cast<const atUint32*>(data + byteCur)) >> bitRem;
|
||||
/* Fill 32 bit buffer with region containing bits */
|
||||
/* Make them least significant */
|
||||
atUint32 tempBuf = hecl::SBig(*reinterpret_cast<const atUint32*>(data + byteCur)) >> bitRem;
|
||||
|
||||
/* That's it */
|
||||
m_bitCur += 1;
|
||||
return tempBuf & 0x1;
|
||||
/* That's it */
|
||||
m_bitCur += 1;
|
||||
return tempBuf & 0x1;
|
||||
}
|
||||
|
||||
atInt32 BitstreamReader::dequantize(const atUint8* data, atUint8 q)
|
||||
{
|
||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||
atUint32 bitRem = m_bitCur % 32;
|
||||
atInt32 BitstreamReader::dequantize(const atUint8* data, atUint8 q) {
|
||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||
atUint32 bitRem = m_bitCur % 32;
|
||||
|
||||
/* Fill 32 bit buffer with region containing bits */
|
||||
/* Make them least significant */
|
||||
atUint32 tempBuf = hecl::SBig(*reinterpret_cast<const atUint32*>(data + byteCur)) >> bitRem;
|
||||
/* Fill 32 bit buffer with region containing bits */
|
||||
/* Make them least significant */
|
||||
atUint32 tempBuf = hecl::SBig(*reinterpret_cast<const atUint32*>(data + byteCur)) >> bitRem;
|
||||
|
||||
/* If this shift underflows the value, buffer the next 32 bits */
|
||||
/* And tack onto shifted buffer */
|
||||
if ((bitRem + q) > 32)
|
||||
{
|
||||
atUint32 tempBuf2 = hecl::SBig(*reinterpret_cast<const atUint32*>(data + byteCur + 4));
|
||||
tempBuf |= (tempBuf2 << (32 - bitRem));
|
||||
/* If this shift underflows the value, buffer the next 32 bits */
|
||||
/* And tack onto shifted buffer */
|
||||
if ((bitRem + q) > 32) {
|
||||
atUint32 tempBuf2 = hecl::SBig(*reinterpret_cast<const atUint32*>(data + byteCur + 4));
|
||||
tempBuf |= (tempBuf2 << (32 - bitRem));
|
||||
}
|
||||
|
||||
/* Mask it */
|
||||
atUint32 mask = (1 << q) - 1;
|
||||
tempBuf &= mask;
|
||||
|
||||
/* Sign extend */
|
||||
atUint32 sign = (tempBuf >> (q - 1)) & 0x1;
|
||||
if (sign)
|
||||
tempBuf |= ~0u << q;
|
||||
|
||||
/* Return delta value */
|
||||
m_bitCur += q;
|
||||
return atInt32(tempBuf);
|
||||
}
|
||||
|
||||
std::vector<std::vector<Value>> BitstreamReader::read(const atUint8* data, size_t keyFrameCount,
|
||||
const std::vector<Channel>& channels, atUint32 rotDiv,
|
||||
float transMult, float scaleMult) {
|
||||
m_bitCur = 0;
|
||||
std::vector<std::vector<Value>> chanKeys;
|
||||
std::vector<QuantizedValue> chanAccum;
|
||||
chanKeys.reserve(channels.size());
|
||||
chanAccum.reserve(channels.size());
|
||||
for (const Channel& chan : channels) {
|
||||
chanAccum.push_back(chan.i);
|
||||
|
||||
chanKeys.emplace_back();
|
||||
std::vector<Value>& keys = chanKeys.back();
|
||||
keys.reserve(keyFrameCount);
|
||||
switch (chan.type) {
|
||||
case Channel::Type::Rotation: {
|
||||
QuantizedRot qr = {{chan.i[0], chan.i[1], chan.i[2]}, false};
|
||||
keys.emplace_back(DequantizeRotation(qr, rotDiv));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Mask it */
|
||||
atUint32 mask = (1 << q) - 1;
|
||||
tempBuf &= mask;
|
||||
|
||||
/* Sign extend */
|
||||
atUint32 sign = (tempBuf >> (q - 1)) & 0x1;
|
||||
if (sign)
|
||||
tempBuf |= ~0u << q;
|
||||
|
||||
/* Return delta value */
|
||||
m_bitCur += q;
|
||||
return atInt32(tempBuf);
|
||||
}
|
||||
|
||||
std::vector<std::vector<Value>>
|
||||
BitstreamReader::read(const atUint8* data,
|
||||
size_t keyFrameCount,
|
||||
const std::vector<Channel>& channels,
|
||||
atUint32 rotDiv,
|
||||
float transMult,
|
||||
float scaleMult)
|
||||
{
|
||||
m_bitCur = 0;
|
||||
std::vector<std::vector<Value>> chanKeys;
|
||||
std::vector<QuantizedValue> chanAccum;
|
||||
chanKeys.reserve(channels.size());
|
||||
chanAccum.reserve(channels.size());
|
||||
for (const Channel& chan : channels)
|
||||
{
|
||||
chanAccum.push_back(chan.i);
|
||||
|
||||
chanKeys.emplace_back();
|
||||
std::vector<Value>& keys = chanKeys.back();
|
||||
keys.reserve(keyFrameCount);
|
||||
switch (chan.type)
|
||||
{
|
||||
case Channel::Type::Rotation:
|
||||
{
|
||||
QuantizedRot qr = {{chan.i[0], chan.i[1], chan.i[2]}, false};
|
||||
keys.emplace_back(DequantizeRotation(qr, rotDiv));
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Translation:
|
||||
{
|
||||
keys.push_back({chan.i[0] * transMult, chan.i[1] * transMult, chan.i[2] * transMult});
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale:
|
||||
{
|
||||
keys.push_back({chan.i[0] * scaleMult, chan.i[1] * scaleMult, chan.i[2] * scaleMult});
|
||||
break;
|
||||
}
|
||||
case Channel::Type::KfHead:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case Channel::Type::RotationMP3:
|
||||
{
|
||||
QuantizedRot qr = {{chan.i[1], chan.i[2], chan.i[3]}, bool(chan.i[0] & 0x1)};
|
||||
keys.emplace_back(DequantizeRotation_3(qr, rotDiv));
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
case Channel::Type::Translation: {
|
||||
keys.push_back({chan.i[0] * transMult, chan.i[1] * transMult, chan.i[2] * transMult});
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t f=0 ; f<keyFrameCount ; ++f)
|
||||
{
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "\nFRAME %" PRISize " %u %u\n", f, (m_bitCur / 32) * 4, m_bitCur % 32);
|
||||
int lastId = -1;
|
||||
#endif
|
||||
auto kit = chanKeys.begin();
|
||||
auto ait = chanAccum.begin();
|
||||
for (const Channel& chan : channels)
|
||||
{
|
||||
#if DUMP_KEYS
|
||||
if (chan.id != lastId)
|
||||
{
|
||||
lastId = chan.id;
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
QuantizedValue& p = *ait;
|
||||
switch (chan.type)
|
||||
{
|
||||
case Channel::Type::Rotation:
|
||||
{
|
||||
bool wBit = dequantizeBit(data);
|
||||
p[0] += dequantize(data, chan.q[0]);
|
||||
p[1] += dequantize(data, chan.q[1]);
|
||||
p[2] += dequantize(data, chan.q[2]);
|
||||
QuantizedRot qr = {{p[0], p[1], p[2]}, wBit};
|
||||
kit->emplace_back(DequantizeRotation(qr, rotDiv));
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "%d R: %d %d %d %d\t", chan.id, wBit, p[0], p[1], p[2]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Translation:
|
||||
{
|
||||
atInt32 val1 = dequantize(data, chan.q[0]);
|
||||
p[0] += val1;
|
||||
atInt32 val2 = dequantize(data, chan.q[1]);
|
||||
p[1] += val2;
|
||||
atInt32 val3 = dequantize(data, chan.q[2]);
|
||||
p[2] += val3;
|
||||
kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult});
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "%d T: %d %d %d\t", chan.id, p[0], p[1], p[2]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale:
|
||||
{
|
||||
p[0] += dequantize(data, chan.q[0]);
|
||||
p[1] += dequantize(data, chan.q[1]);
|
||||
p[2] += dequantize(data, chan.q[2]);
|
||||
kit->push_back({p[0] * scaleMult, p[1] * scaleMult, p[2] * scaleMult});
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "%d S: %d %d %d\t", chan.id, p[0], p[1], p[2]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Channel::Type::KfHead:
|
||||
{
|
||||
dequantizeBit(data);
|
||||
break;
|
||||
}
|
||||
case Channel::Type::RotationMP3:
|
||||
{
|
||||
atInt32 val1 = dequantize(data, chan.q[0]);
|
||||
p[0] += val1;
|
||||
atInt32 val2 = dequantize(data, chan.q[1]);
|
||||
p[1] += val2;
|
||||
atInt32 val3 = dequantize(data, chan.q[2]);
|
||||
p[2] += val3;
|
||||
atInt32 val4 = dequantize(data, chan.q[3]);
|
||||
p[3] += val4;
|
||||
QuantizedRot qr = {{p[1], p[2], p[3]}, bool(p[0] & 0x1)};
|
||||
kit->emplace_back(DequantizeRotation_3(qr, rotDiv));
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
++kit;
|
||||
++ait;
|
||||
}
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
case Channel::Type::Scale: {
|
||||
keys.push_back({chan.i[0] * scaleMult, chan.i[1] * scaleMult, chan.i[2] * scaleMult});
|
||||
break;
|
||||
}
|
||||
|
||||
return chanKeys;
|
||||
}
|
||||
|
||||
void BitstreamWriter::quantizeBit(atUint8* data, bool val)
|
||||
{
|
||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||
atUint32 bitRem = m_bitCur % 32;
|
||||
|
||||
/* Fill 32 bit buffer with region containing bits */
|
||||
/* Make them least significant */
|
||||
*(atUint32*)(data + byteCur) =
|
||||
hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur)) | (val << bitRem));
|
||||
|
||||
m_bitCur += 1;
|
||||
}
|
||||
|
||||
void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt32 val)
|
||||
{
|
||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||
atUint32 bitRem = m_bitCur % 32;
|
||||
|
||||
atUint32 masked = val & ((1 << q) - 1);
|
||||
|
||||
/* Fill 32 bit buffer with region containing bits */
|
||||
/* Make them least significant */
|
||||
*(atUint32*)(data + byteCur) =
|
||||
hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur)) | (masked << bitRem));
|
||||
|
||||
/* If this shift underflows the value, buffer the next 32 bits */
|
||||
/* And tack onto shifted buffer */
|
||||
if ((bitRem + q) > 32)
|
||||
{
|
||||
*(atUint32*)(data + byteCur + 4) =
|
||||
hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur + 4)) | (masked >> (32 - bitRem)));
|
||||
case Channel::Type::KfHead: {
|
||||
break;
|
||||
}
|
||||
case Channel::Type::RotationMP3: {
|
||||
QuantizedRot qr = {{chan.i[1], chan.i[2], chan.i[3]}, bool(chan.i[0] & 0x1)};
|
||||
keys.emplace_back(DequantizeRotation_3(qr, rotDiv));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_bitCur += q;
|
||||
}
|
||||
|
||||
std::unique_ptr<atUint8[]>
|
||||
BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys,
|
||||
size_t keyFrameCount, std::vector<Channel>& channels,
|
||||
atUint32 quantRange,
|
||||
atUint32& rotDivOut,
|
||||
float& transMultOut,
|
||||
float& scaleMultOut,
|
||||
size_t& sizeOut)
|
||||
{
|
||||
m_bitCur = 0;
|
||||
rotDivOut = quantRange; /* Normalized range of values */
|
||||
float quantRangeF = float(quantRange);
|
||||
|
||||
/* Pre-pass to calculate translation multiplier */
|
||||
float maxTransVal = 0.0f;
|
||||
float maxScaleVal = 0.0f;
|
||||
for (size_t f = 0; f < keyFrameCount; ++f) {
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "\nFRAME %" PRISize " %u %u\n", f, (m_bitCur / 32) * 4, m_bitCur % 32);
|
||||
int lastId = -1;
|
||||
#endif
|
||||
auto kit = chanKeys.begin();
|
||||
for (Channel& chan : channels)
|
||||
{
|
||||
switch (chan.type)
|
||||
{
|
||||
case Channel::Type::Translation:
|
||||
{
|
||||
for (auto it=kit->begin();
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
const Value* key = &*it;
|
||||
zeus::simd_floats f(key->simd);
|
||||
maxTransVal = std::max(maxTransVal, std::fabs(f[0]));
|
||||
maxTransVal = std::max(maxTransVal, std::fabs(f[1]));
|
||||
maxTransVal = std::max(maxTransVal, std::fabs(f[2]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale:
|
||||
{
|
||||
for (auto it=kit->begin();
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
const Value* key = &*it;
|
||||
zeus::simd_floats f(key->simd);
|
||||
maxScaleVal = std::max(maxScaleVal, std::fabs(f[0]));
|
||||
maxScaleVal = std::max(maxScaleVal, std::fabs(f[1]));
|
||||
maxScaleVal = std::max(maxScaleVal, std::fabs(f[2]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
++kit;
|
||||
auto ait = chanAccum.begin();
|
||||
for (const Channel& chan : channels) {
|
||||
#if DUMP_KEYS
|
||||
if (chan.id != lastId) {
|
||||
lastId = chan.id;
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
QuantizedValue& p = *ait;
|
||||
switch (chan.type) {
|
||||
case Channel::Type::Rotation: {
|
||||
bool wBit = dequantizeBit(data);
|
||||
p[0] += dequantize(data, chan.q[0]);
|
||||
p[1] += dequantize(data, chan.q[1]);
|
||||
p[2] += dequantize(data, chan.q[2]);
|
||||
QuantizedRot qr = {{p[0], p[1], p[2]}, wBit};
|
||||
kit->emplace_back(DequantizeRotation(qr, rotDiv));
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "%d R: %d %d %d %d\t", chan.id, wBit, p[0], p[1], p[2]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Translation: {
|
||||
atInt32 val1 = dequantize(data, chan.q[0]);
|
||||
p[0] += val1;
|
||||
atInt32 val2 = dequantize(data, chan.q[1]);
|
||||
p[1] += val2;
|
||||
atInt32 val3 = dequantize(data, chan.q[2]);
|
||||
p[2] += val3;
|
||||
kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult});
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "%d T: %d %d %d\t", chan.id, p[0], p[1], p[2]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale: {
|
||||
p[0] += dequantize(data, chan.q[0]);
|
||||
p[1] += dequantize(data, chan.q[1]);
|
||||
p[2] += dequantize(data, chan.q[2]);
|
||||
kit->push_back({p[0] * scaleMult, p[1] * scaleMult, p[2] * scaleMult});
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "%d S: %d %d %d\t", chan.id, p[0], p[1], p[2]);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Channel::Type::KfHead: {
|
||||
dequantizeBit(data);
|
||||
break;
|
||||
}
|
||||
case Channel::Type::RotationMP3: {
|
||||
atInt32 val1 = dequantize(data, chan.q[0]);
|
||||
p[0] += val1;
|
||||
atInt32 val2 = dequantize(data, chan.q[1]);
|
||||
p[1] += val2;
|
||||
atInt32 val3 = dequantize(data, chan.q[2]);
|
||||
p[2] += val3;
|
||||
atInt32 val4 = dequantize(data, chan.q[3]);
|
||||
p[3] += val4;
|
||||
QuantizedRot qr = {{p[1], p[2], p[3]}, bool(p[0] & 0x1)};
|
||||
kit->emplace_back(DequantizeRotation_3(qr, rotDiv));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++kit;
|
||||
++ait;
|
||||
}
|
||||
transMultOut = maxTransVal / quantRangeF;
|
||||
scaleMultOut = maxScaleVal / quantRangeF;
|
||||
#if DUMP_KEYS
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Output channel inits */
|
||||
std::vector<QuantizedValue> initVals;
|
||||
initVals.reserve(channels.size());
|
||||
kit = chanKeys.begin();
|
||||
for (Channel& chan : channels)
|
||||
{
|
||||
chan.q[0] = 1;
|
||||
chan.q[1] = 1;
|
||||
chan.q[2] = 1;
|
||||
switch (chan.type)
|
||||
{
|
||||
case Channel::Type::Rotation:
|
||||
{
|
||||
QuantizedRot qr = QuantizeRotation((*kit)[0], rotDivOut);
|
||||
chan.i = qr.v;
|
||||
initVals.push_back(chan.i);
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Translation:
|
||||
{
|
||||
zeus::simd_floats f((*kit)[0].simd);
|
||||
chan.i = {atInt32(f[0] / transMultOut),
|
||||
atInt32(f[1] / transMultOut),
|
||||
atInt32(f[2] / transMultOut)};
|
||||
initVals.push_back(chan.i);
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale:
|
||||
{
|
||||
zeus::simd_floats f((*kit)[0].simd);
|
||||
chan.i = {atInt32(f[0] / scaleMultOut),
|
||||
atInt32(f[1] / scaleMultOut),
|
||||
atInt32(f[2] / scaleMultOut)};
|
||||
initVals.push_back(chan.i);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
++kit;
|
||||
}
|
||||
|
||||
/* Pre-pass to analyze quantization factors for channels */
|
||||
std::vector<QuantizedValue> lastVals = initVals;
|
||||
kit = chanKeys.begin();
|
||||
auto vit = lastVals.begin();
|
||||
for (Channel& chan : channels)
|
||||
{
|
||||
QuantizedValue& last = *vit++;
|
||||
switch (chan.type)
|
||||
{
|
||||
case Channel::Type::Rotation:
|
||||
{
|
||||
for (auto it=kit->begin() + 1;
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
|
||||
chan.q[0] = std::max(chan.q[0], atUint8(qrCur.v.qFrom(last, 0)));
|
||||
chan.q[1] = std::max(chan.q[1], atUint8(qrCur.v.qFrom(last, 1)));
|
||||
chan.q[2] = std::max(chan.q[2], atUint8(qrCur.v.qFrom(last, 2)));
|
||||
last = qrCur.v;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Translation:
|
||||
{
|
||||
for (auto it=kit->begin() + 1;
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
zeus::simd_floats f(it->simd);
|
||||
QuantizedValue cur = {atInt32(f[0] / transMultOut),
|
||||
atInt32(f[1] / transMultOut),
|
||||
atInt32(f[2] / transMultOut)};
|
||||
chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0)));
|
||||
chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1)));
|
||||
chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2)));
|
||||
last = cur;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale:
|
||||
{
|
||||
for (auto it=kit->begin() + 1;
|
||||
it != kit->end();
|
||||
++it)
|
||||
{
|
||||
zeus::simd_floats f(it->simd);
|
||||
QuantizedValue cur = {atInt32(f[0] / scaleMultOut),
|
||||
atInt32(f[1] / scaleMultOut),
|
||||
atInt32(f[2] / scaleMultOut)};
|
||||
chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0)));
|
||||
chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1)));
|
||||
chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2)));
|
||||
last = cur;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
++kit;
|
||||
}
|
||||
|
||||
/* Generate Bitstream */
|
||||
sizeOut = ComputeBitstreamSize(keyFrameCount, channels);
|
||||
std::unique_ptr<atUint8[]> newData(new atUint8[sizeOut]);
|
||||
memset(newData.get(), 0, sizeOut);
|
||||
|
||||
lastVals = initVals;
|
||||
for (size_t f=0 ; f<keyFrameCount ; ++f)
|
||||
{
|
||||
kit = chanKeys.begin();
|
||||
vit = lastVals.begin();
|
||||
for (const Channel& chan : channels)
|
||||
{
|
||||
const Value& val = (*kit++)[f+1];
|
||||
QuantizedValue& last = *vit++;
|
||||
switch (chan.type)
|
||||
{
|
||||
case Channel::Type::Rotation:
|
||||
{
|
||||
QuantizedRot qrCur = QuantizeRotation(val, rotDivOut);
|
||||
quantizeBit(newData.get(), qrCur.w);
|
||||
quantize(newData.get(), chan.q[0], qrCur.v[0] - last.v[0]);
|
||||
quantize(newData.get(), chan.q[1], qrCur.v[1] - last.v[1]);
|
||||
quantize(newData.get(), chan.q[2], qrCur.v[2] - last.v[2]);
|
||||
last = qrCur.v;
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Translation:
|
||||
{
|
||||
zeus::simd_floats f(val.simd);
|
||||
QuantizedValue cur = {atInt32(f[0] / transMultOut),
|
||||
atInt32(f[1] / transMultOut),
|
||||
atInt32(f[2] / transMultOut)};
|
||||
quantize(newData.get(), chan.q[0], cur[0] - last[0]);
|
||||
quantize(newData.get(), chan.q[1], cur[1] - last[1]);
|
||||
quantize(newData.get(), chan.q[2], cur[2] - last[2]);
|
||||
last = cur;
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale:
|
||||
{
|
||||
zeus::simd_floats f(val.simd);
|
||||
QuantizedValue cur = {atInt32(f[0] / scaleMultOut),
|
||||
atInt32(f[1] / scaleMultOut),
|
||||
atInt32(f[2] / scaleMultOut)};
|
||||
quantize(newData.get(), chan.q[0], cur[0] - last[0]);
|
||||
quantize(newData.get(), chan.q[1], cur[1] - last[1]);
|
||||
quantize(newData.get(), chan.q[2], cur[2] - last[2]);
|
||||
last = cur;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newData;
|
||||
return chanKeys;
|
||||
}
|
||||
|
||||
void BitstreamWriter::quantizeBit(atUint8* data, bool val) {
|
||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||
atUint32 bitRem = m_bitCur % 32;
|
||||
|
||||
/* Fill 32 bit buffer with region containing bits */
|
||||
/* Make them least significant */
|
||||
*(atUint32*)(data + byteCur) = hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur)) | (val << bitRem));
|
||||
|
||||
m_bitCur += 1;
|
||||
}
|
||||
|
||||
void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt32 val) {
|
||||
atUint32 byteCur = (m_bitCur / 32) * 4;
|
||||
atUint32 bitRem = m_bitCur % 32;
|
||||
|
||||
atUint32 masked = val & ((1 << q) - 1);
|
||||
|
||||
/* Fill 32 bit buffer with region containing bits */
|
||||
/* Make them least significant */
|
||||
*(atUint32*)(data + byteCur) = hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur)) | (masked << bitRem));
|
||||
|
||||
/* If this shift underflows the value, buffer the next 32 bits */
|
||||
/* And tack onto shifted buffer */
|
||||
if ((bitRem + q) > 32) {
|
||||
*(atUint32*)(data + byteCur + 4) =
|
||||
hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur + 4)) | (masked >> (32 - bitRem)));
|
||||
}
|
||||
|
||||
m_bitCur += q;
|
||||
}
|
||||
|
||||
std::unique_ptr<atUint8[]> BitstreamWriter::write(const std::vector<std::vector<Value>>& chanKeys, size_t keyFrameCount,
|
||||
std::vector<Channel>& channels, atUint32 quantRange,
|
||||
atUint32& rotDivOut, float& transMultOut, float& scaleMultOut,
|
||||
size_t& sizeOut) {
|
||||
m_bitCur = 0;
|
||||
rotDivOut = quantRange; /* Normalized range of values */
|
||||
float quantRangeF = float(quantRange);
|
||||
|
||||
/* Pre-pass to calculate translation multiplier */
|
||||
float maxTransVal = 0.0f;
|
||||
float maxScaleVal = 0.0f;
|
||||
auto kit = chanKeys.begin();
|
||||
for (Channel& chan : channels) {
|
||||
switch (chan.type) {
|
||||
case Channel::Type::Translation: {
|
||||
for (auto it = kit->begin(); it != kit->end(); ++it) {
|
||||
const Value* key = &*it;
|
||||
zeus::simd_floats f(key->simd);
|
||||
maxTransVal = std::max(maxTransVal, std::fabs(f[0]));
|
||||
maxTransVal = std::max(maxTransVal, std::fabs(f[1]));
|
||||
maxTransVal = std::max(maxTransVal, std::fabs(f[2]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale: {
|
||||
for (auto it = kit->begin(); it != kit->end(); ++it) {
|
||||
const Value* key = &*it;
|
||||
zeus::simd_floats f(key->simd);
|
||||
maxScaleVal = std::max(maxScaleVal, std::fabs(f[0]));
|
||||
maxScaleVal = std::max(maxScaleVal, std::fabs(f[1]));
|
||||
maxScaleVal = std::max(maxScaleVal, std::fabs(f[2]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++kit;
|
||||
}
|
||||
transMultOut = maxTransVal / quantRangeF;
|
||||
scaleMultOut = maxScaleVal / quantRangeF;
|
||||
|
||||
/* Output channel inits */
|
||||
std::vector<QuantizedValue> initVals;
|
||||
initVals.reserve(channels.size());
|
||||
kit = chanKeys.begin();
|
||||
for (Channel& chan : channels) {
|
||||
chan.q[0] = 1;
|
||||
chan.q[1] = 1;
|
||||
chan.q[2] = 1;
|
||||
switch (chan.type) {
|
||||
case Channel::Type::Rotation: {
|
||||
QuantizedRot qr = QuantizeRotation((*kit)[0], rotDivOut);
|
||||
chan.i = qr.v;
|
||||
initVals.push_back(chan.i);
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Translation: {
|
||||
zeus::simd_floats f((*kit)[0].simd);
|
||||
chan.i = {atInt32(f[0] / transMultOut), atInt32(f[1] / transMultOut), atInt32(f[2] / transMultOut)};
|
||||
initVals.push_back(chan.i);
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale: {
|
||||
zeus::simd_floats f((*kit)[0].simd);
|
||||
chan.i = {atInt32(f[0] / scaleMultOut), atInt32(f[1] / scaleMultOut), atInt32(f[2] / scaleMultOut)};
|
||||
initVals.push_back(chan.i);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++kit;
|
||||
}
|
||||
|
||||
/* Pre-pass to analyze quantization factors for channels */
|
||||
std::vector<QuantizedValue> lastVals = initVals;
|
||||
kit = chanKeys.begin();
|
||||
auto vit = lastVals.begin();
|
||||
for (Channel& chan : channels) {
|
||||
QuantizedValue& last = *vit++;
|
||||
switch (chan.type) {
|
||||
case Channel::Type::Rotation: {
|
||||
for (auto it = kit->begin() + 1; it != kit->end(); ++it) {
|
||||
QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut);
|
||||
chan.q[0] = std::max(chan.q[0], atUint8(qrCur.v.qFrom(last, 0)));
|
||||
chan.q[1] = std::max(chan.q[1], atUint8(qrCur.v.qFrom(last, 1)));
|
||||
chan.q[2] = std::max(chan.q[2], atUint8(qrCur.v.qFrom(last, 2)));
|
||||
last = qrCur.v;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Translation: {
|
||||
for (auto it = kit->begin() + 1; it != kit->end(); ++it) {
|
||||
zeus::simd_floats f(it->simd);
|
||||
QuantizedValue cur = {atInt32(f[0] / transMultOut), atInt32(f[1] / transMultOut), atInt32(f[2] / transMultOut)};
|
||||
chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0)));
|
||||
chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1)));
|
||||
chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2)));
|
||||
last = cur;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale: {
|
||||
for (auto it = kit->begin() + 1; it != kit->end(); ++it) {
|
||||
zeus::simd_floats f(it->simd);
|
||||
QuantizedValue cur = {atInt32(f[0] / scaleMultOut), atInt32(f[1] / scaleMultOut), atInt32(f[2] / scaleMultOut)};
|
||||
chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0)));
|
||||
chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1)));
|
||||
chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2)));
|
||||
last = cur;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++kit;
|
||||
}
|
||||
|
||||
/* Generate Bitstream */
|
||||
sizeOut = ComputeBitstreamSize(keyFrameCount, channels);
|
||||
std::unique_ptr<atUint8[]> newData(new atUint8[sizeOut]);
|
||||
memset(newData.get(), 0, sizeOut);
|
||||
|
||||
lastVals = initVals;
|
||||
for (size_t f = 0; f < keyFrameCount; ++f) {
|
||||
kit = chanKeys.begin();
|
||||
vit = lastVals.begin();
|
||||
for (const Channel& chan : channels) {
|
||||
const Value& val = (*kit++)[f + 1];
|
||||
QuantizedValue& last = *vit++;
|
||||
switch (chan.type) {
|
||||
case Channel::Type::Rotation: {
|
||||
QuantizedRot qrCur = QuantizeRotation(val, rotDivOut);
|
||||
quantizeBit(newData.get(), qrCur.w);
|
||||
quantize(newData.get(), chan.q[0], qrCur.v[0] - last.v[0]);
|
||||
quantize(newData.get(), chan.q[1], qrCur.v[1] - last.v[1]);
|
||||
quantize(newData.get(), chan.q[2], qrCur.v[2] - last.v[2]);
|
||||
last = qrCur.v;
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Translation: {
|
||||
zeus::simd_floats f(val.simd);
|
||||
QuantizedValue cur = {atInt32(f[0] / transMultOut), atInt32(f[1] / transMultOut), atInt32(f[2] / transMultOut)};
|
||||
quantize(newData.get(), chan.q[0], cur[0] - last[0]);
|
||||
quantize(newData.get(), chan.q[1], cur[1] - last[1]);
|
||||
quantize(newData.get(), chan.q[2], cur[2] - last[2]);
|
||||
last = cur;
|
||||
break;
|
||||
}
|
||||
case Channel::Type::Scale: {
|
||||
zeus::simd_floats f(val.simd);
|
||||
QuantizedValue cur = {atInt32(f[0] / scaleMultOut), atInt32(f[1] / scaleMultOut), atInt32(f[2] / scaleMultOut)};
|
||||
quantize(newData.get(), chan.q[0], cur[0] - last[0]);
|
||||
quantize(newData.get(), chan.q[1], cur[1] - last[1]);
|
||||
quantize(newData.get(), chan.q[2], cur[2] - last[2]);
|
||||
last = cur;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newData;
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAANIM
|
||||
|
|
|
@ -3,87 +3,61 @@
|
|||
#include "DNACommon.hpp"
|
||||
#include <cmath>
|
||||
|
||||
namespace DataSpec::DNAANIM
|
||||
{
|
||||
namespace DataSpec::DNAANIM {
|
||||
|
||||
struct Value
|
||||
{
|
||||
athena::simd<float> simd;
|
||||
Value() = default;
|
||||
Value(const athena::simd<float>& s) : simd(s) {}
|
||||
Value(const atVec3f& v) : simd(v.simd) {}
|
||||
Value(const atVec4f& v) : simd(v.simd) {}
|
||||
Value(float x, float y, float z) : simd(x, y, z, 0.f) {}
|
||||
Value(float w, float x, float y, float z) : simd(w, x, y, z) {}
|
||||
struct Value {
|
||||
athena::simd<float> simd;
|
||||
Value() = default;
|
||||
Value(const athena::simd<float>& s) : simd(s) {}
|
||||
Value(const atVec3f& v) : simd(v.simd) {}
|
||||
Value(const atVec4f& v) : simd(v.simd) {}
|
||||
Value(float x, float y, float z) : simd(x, y, z, 0.f) {}
|
||||
Value(float w, float x, float y, float z) : simd(w, x, y, z) {}
|
||||
};
|
||||
struct QuantizedValue
|
||||
{
|
||||
atInt32 v[4];
|
||||
atInt32& operator[] (size_t idx)
|
||||
{return v[idx];}
|
||||
atInt32 operator[] (size_t idx) const
|
||||
{return v[idx];}
|
||||
struct QuantizedValue {
|
||||
atInt32 v[4];
|
||||
atInt32& operator[](size_t idx) { return v[idx]; }
|
||||
atInt32 operator[](size_t idx) const { return v[idx]; }
|
||||
|
||||
int qFrom(const QuantizedValue& other, size_t idx) const
|
||||
{
|
||||
atInt32 delta = std::abs(v[idx] - other.v[idx]);
|
||||
if (delta == 0)
|
||||
return 1;
|
||||
return int(std::ceil(std::log2(delta))) + 1;
|
||||
}
|
||||
int qFrom(const QuantizedValue& other, size_t idx) const {
|
||||
atInt32 delta = std::abs(v[idx] - other.v[idx]);
|
||||
if (delta == 0)
|
||||
return 1;
|
||||
return int(std::ceil(std::log2(delta))) + 1;
|
||||
}
|
||||
};
|
||||
struct QuantizedRot
|
||||
{
|
||||
QuantizedValue v;
|
||||
bool w;
|
||||
struct QuantizedRot {
|
||||
QuantizedValue v;
|
||||
bool w;
|
||||
};
|
||||
struct Channel
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
Rotation,
|
||||
Translation,
|
||||
Scale,
|
||||
KfHead,
|
||||
RotationMP3
|
||||
} type;
|
||||
atInt32 id = -1;
|
||||
QuantizedValue i = {};
|
||||
atUint8 q[4] = {};
|
||||
struct Channel {
|
||||
enum class Type { Rotation, Translation, Scale, KfHead, RotationMP3 } type;
|
||||
atInt32 id = -1;
|
||||
QuantizedValue i = {};
|
||||
atUint8 q[4] = {};
|
||||
};
|
||||
|
||||
size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& channels);
|
||||
|
||||
class BitstreamReader
|
||||
{
|
||||
size_t m_bitCur;
|
||||
atInt32 dequantize(const atUint8* data, atUint8 q);
|
||||
bool dequantizeBit(const atUint8* data);
|
||||
class BitstreamReader {
|
||||
size_t m_bitCur;
|
||||
atInt32 dequantize(const atUint8* data, atUint8 q);
|
||||
bool dequantizeBit(const atUint8* data);
|
||||
|
||||
public:
|
||||
std::vector<std::vector<Value>>
|
||||
read(const atUint8* data,
|
||||
size_t keyFrameCount,
|
||||
const std::vector<Channel>& channels,
|
||||
atUint32 rotDiv,
|
||||
float transMult,
|
||||
float scaleMult);
|
||||
std::vector<std::vector<Value>> read(const atUint8* data, size_t keyFrameCount, const std::vector<Channel>& channels,
|
||||
atUint32 rotDiv, float transMult, float scaleMult);
|
||||
};
|
||||
|
||||
class BitstreamWriter
|
||||
{
|
||||
size_t m_bitCur;
|
||||
void quantize(atUint8* data, atUint8 q, atInt32 val);
|
||||
void quantizeBit(atUint8* data, bool val);
|
||||
class BitstreamWriter {
|
||||
size_t m_bitCur;
|
||||
void quantize(atUint8* data, atUint8 q, atInt32 val);
|
||||
void quantizeBit(atUint8* data, bool val);
|
||||
|
||||
public:
|
||||
std::unique_ptr<atUint8[]>
|
||||
write(const std::vector<std::vector<Value>>& chanKeys,
|
||||
size_t keyFrameCount, std::vector<Channel>& channels,
|
||||
atUint32 quantRange,
|
||||
atUint32& rotDivOut,
|
||||
float& transMultOut,
|
||||
float& scaleMultOut,
|
||||
size_t& sizeOut);
|
||||
std::unique_ptr<atUint8[]> write(const std::vector<std::vector<Value>>& chanKeys, size_t keyFrameCount,
|
||||
std::vector<Channel>& channels, atUint32 quantRange, atUint32& rotDivOut,
|
||||
float& transMultOut, float& scaleMultOut, size_t& sizeOut);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAANIM
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
#include "hecl/Blender/Connection.hpp"
|
||||
#include "../DNAMP1/PATH.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
logvisor::Module Log("AROTBuilder");
|
||||
|
||||
#define AROT_MAX_LEVEL 10
|
||||
|
@ -12,505 +11,419 @@ logvisor::Module Log("AROTBuilder");
|
|||
#define COLLISION_MIN_NODE_TRIANGLES 8
|
||||
#define PATH_MIN_NODE_REGIONS 16
|
||||
|
||||
static zeus::CAABox SplitAABB(const zeus::CAABox& aabb, int i)
|
||||
{
|
||||
zeus::CAABox pos, neg;
|
||||
aabb.splitZ(neg, pos);
|
||||
if (i & 4)
|
||||
{
|
||||
zeus::CAABox(pos).splitY(neg, pos);
|
||||
if (i & 2)
|
||||
{
|
||||
zeus::CAABox(pos).splitX(neg, pos);
|
||||
if (i & 1)
|
||||
return pos;
|
||||
else
|
||||
return neg;
|
||||
}
|
||||
else
|
||||
{
|
||||
zeus::CAABox(neg).splitX(neg, pos);
|
||||
if (i & 1)
|
||||
return pos;
|
||||
else
|
||||
return neg;
|
||||
}
|
||||
static zeus::CAABox SplitAABB(const zeus::CAABox& aabb, int i) {
|
||||
zeus::CAABox pos, neg;
|
||||
aabb.splitZ(neg, pos);
|
||||
if (i & 4) {
|
||||
zeus::CAABox(pos).splitY(neg, pos);
|
||||
if (i & 2) {
|
||||
zeus::CAABox(pos).splitX(neg, pos);
|
||||
if (i & 1)
|
||||
return pos;
|
||||
else
|
||||
return neg;
|
||||
} else {
|
||||
zeus::CAABox(neg).splitX(neg, pos);
|
||||
if (i & 1)
|
||||
return pos;
|
||||
else
|
||||
return neg;
|
||||
}
|
||||
else
|
||||
{
|
||||
zeus::CAABox(neg).splitY(neg, pos);
|
||||
if (i & 2)
|
||||
{
|
||||
zeus::CAABox(pos).splitX(neg, pos);
|
||||
if (i & 1)
|
||||
return pos;
|
||||
else
|
||||
return neg;
|
||||
}
|
||||
else
|
||||
{
|
||||
zeus::CAABox(neg).splitX(neg, pos);
|
||||
if (i & 1)
|
||||
return pos;
|
||||
else
|
||||
return neg;
|
||||
}
|
||||
} else {
|
||||
zeus::CAABox(neg).splitY(neg, pos);
|
||||
if (i & 2) {
|
||||
zeus::CAABox(pos).splitX(neg, pos);
|
||||
if (i & 1)
|
||||
return pos;
|
||||
else
|
||||
return neg;
|
||||
} else {
|
||||
zeus::CAABox(neg).splitX(neg, pos);
|
||||
if (i & 1)
|
||||
return pos;
|
||||
else
|
||||
return neg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::mergeSets(int a, int b)
|
||||
{
|
||||
childNodes[a].childIndices.insert(childNodes[b].childIndices.cbegin(), childNodes[b].childIndices.cend());
|
||||
childNodes[b].childIndices = childNodes[a].childIndices;
|
||||
void AROTBuilder::Node::mergeSets(int a, int b) {
|
||||
childNodes[a].childIndices.insert(childNodes[b].childIndices.cbegin(), childNodes[b].childIndices.cend());
|
||||
childNodes[b].childIndices = childNodes[a].childIndices;
|
||||
}
|
||||
|
||||
bool AROTBuilder::Node::compareSets(int a, int b) const
|
||||
{
|
||||
return childNodes[a].childIndices != childNodes[b].childIndices;
|
||||
bool AROTBuilder::Node::compareSets(int a, int b) const {
|
||||
return childNodes[a].childIndices != childNodes[b].childIndices;
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::addChild(int level, int minChildren, const std::vector<zeus::CAABox>& triBoxes,
|
||||
const zeus::CAABox& curAABB, BspNodeType& typeOut)
|
||||
{
|
||||
/* Gather intersecting faces */
|
||||
for (int i=0 ; i<triBoxes.size() ; ++i)
|
||||
if (triBoxes[i].intersects(curAABB))
|
||||
childIndices.insert(i);
|
||||
const zeus::CAABox& curAABB, BspNodeType& typeOut) {
|
||||
/* Gather intersecting faces */
|
||||
for (int i = 0; i < triBoxes.size(); ++i)
|
||||
if (triBoxes[i].intersects(curAABB))
|
||||
childIndices.insert(i);
|
||||
|
||||
zeus::CVector3f extents = curAABB.extents();
|
||||
zeus::CVector3f extents = curAABB.extents();
|
||||
|
||||
/* Return early if empty, triangle intersection below performance threshold, or at max level */
|
||||
if (childIndices.empty())
|
||||
{
|
||||
typeOut = BspNodeType::Invalid;
|
||||
return;
|
||||
}
|
||||
else if (childIndices.size() < minChildren || level == AROT_MAX_LEVEL ||
|
||||
std::max(extents.x(), std::max(extents.y(), extents.z())) < AROT_MIN_SUBDIV)
|
||||
{
|
||||
typeOut = BspNodeType::Leaf;
|
||||
return;
|
||||
}
|
||||
/* Return early if empty, triangle intersection below performance threshold, or at max level */
|
||||
if (childIndices.empty()) {
|
||||
typeOut = BspNodeType::Invalid;
|
||||
return;
|
||||
} else if (childIndices.size() < minChildren || level == AROT_MAX_LEVEL ||
|
||||
std::max(extents.x(), std::max(extents.y(), extents.z())) < AROT_MIN_SUBDIV) {
|
||||
typeOut = BspNodeType::Leaf;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Subdivide */
|
||||
typeOut = BspNodeType::Branch;
|
||||
childNodes.resize(8);
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
{
|
||||
BspNodeType chType;
|
||||
childNodes[i].addChild(level + 1, minChildren, triBoxes, SplitAABB(curAABB, i), chType);
|
||||
flags |= int(chType) << (i * 2);
|
||||
}
|
||||
/* Subdivide */
|
||||
typeOut = BspNodeType::Branch;
|
||||
childNodes.resize(8);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
BspNodeType chType;
|
||||
childNodes[i].addChild(level + 1, minChildren, triBoxes, SplitAABB(curAABB, i), chType);
|
||||
flags |= int(chType) << (i * 2);
|
||||
}
|
||||
|
||||
/* Unsubdivide minimum axis dimensions */
|
||||
if (extents.x() < AROT_MIN_SUBDIV)
|
||||
{
|
||||
mergeSets(0, 1);
|
||||
mergeSets(4, 5);
|
||||
mergeSets(2, 3);
|
||||
mergeSets(6, 7);
|
||||
}
|
||||
if (extents.y() < AROT_MIN_SUBDIV)
|
||||
{
|
||||
mergeSets(0, 2);
|
||||
mergeSets(1, 3);
|
||||
mergeSets(4, 6);
|
||||
mergeSets(5, 7);
|
||||
}
|
||||
if (extents.z() < AROT_MIN_SUBDIV)
|
||||
{
|
||||
mergeSets(0, 4);
|
||||
mergeSets(1, 5);
|
||||
mergeSets(2, 6);
|
||||
mergeSets(3, 7);
|
||||
}
|
||||
/* Unsubdivide minimum axis dimensions */
|
||||
if (extents.x() < AROT_MIN_SUBDIV) {
|
||||
mergeSets(0, 1);
|
||||
mergeSets(4, 5);
|
||||
mergeSets(2, 3);
|
||||
mergeSets(6, 7);
|
||||
}
|
||||
if (extents.y() < AROT_MIN_SUBDIV) {
|
||||
mergeSets(0, 2);
|
||||
mergeSets(1, 3);
|
||||
mergeSets(4, 6);
|
||||
mergeSets(5, 7);
|
||||
}
|
||||
if (extents.z() < AROT_MIN_SUBDIV) {
|
||||
mergeSets(0, 4);
|
||||
mergeSets(1, 5);
|
||||
mergeSets(2, 6);
|
||||
mergeSets(3, 7);
|
||||
}
|
||||
|
||||
/* Unsubdivide */
|
||||
compSubdivs = 0;
|
||||
if (compareSets(0, 1) ||
|
||||
compareSets(4, 5) ||
|
||||
compareSets(2, 3) ||
|
||||
compareSets(6, 7))
|
||||
compSubdivs |= 0x1;
|
||||
if (compareSets(0, 2) ||
|
||||
compareSets(1, 3) ||
|
||||
compareSets(4, 6) ||
|
||||
compareSets(5, 7))
|
||||
compSubdivs |= 0x2;
|
||||
if (compareSets(0, 4) ||
|
||||
compareSets(1, 5) ||
|
||||
compareSets(2, 6) ||
|
||||
compareSets(3, 7))
|
||||
compSubdivs |= 0x4;
|
||||
/* Unsubdivide */
|
||||
compSubdivs = 0;
|
||||
if (compareSets(0, 1) || compareSets(4, 5) || compareSets(2, 3) || compareSets(6, 7))
|
||||
compSubdivs |= 0x1;
|
||||
if (compareSets(0, 2) || compareSets(1, 3) || compareSets(4, 6) || compareSets(5, 7))
|
||||
compSubdivs |= 0x2;
|
||||
if (compareSets(0, 4) || compareSets(1, 5) || compareSets(2, 6) || compareSets(3, 7))
|
||||
compSubdivs |= 0x4;
|
||||
|
||||
if (!compSubdivs)
|
||||
{
|
||||
typeOut = BspNodeType::Leaf;
|
||||
childNodes = std::vector<Node>();
|
||||
flags = 0;
|
||||
}
|
||||
if (!compSubdivs) {
|
||||
typeOut = BspNodeType::Leaf;
|
||||
childNodes = std::vector<Node>();
|
||||
flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t AROTBuilder::BitmapPool::addIndices(const std::set<int>& indices)
|
||||
{
|
||||
for (size_t i=0 ; i<m_pool.size() ; ++i)
|
||||
if (m_pool[i] == indices)
|
||||
return i;
|
||||
m_pool.push_back(indices);
|
||||
return m_pool.size() - 1;
|
||||
size_t AROTBuilder::BitmapPool::addIndices(const std::set<int>& indices) {
|
||||
for (size_t i = 0; i < m_pool.size(); ++i)
|
||||
if (m_pool[i] == indices)
|
||||
return i;
|
||||
m_pool.push_back(indices);
|
||||
return m_pool.size() - 1;
|
||||
}
|
||||
|
||||
static const uint32_t AROTChildCounts[] = { 0, 2, 2, 4, 2, 4, 4, 8 };
|
||||
static const uint32_t AROTChildCounts[] = {0, 2, 2, 4, 2, 4, 4, 8};
|
||||
|
||||
void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff)
|
||||
{
|
||||
sz += 1;
|
||||
poolIdx = bmpPool.addIndices(childIndices);
|
||||
if (poolIdx > 65535)
|
||||
Log.report(logvisor::Fatal, "AROT bitmap exceeds 16-bit node addressing; area too complex");
|
||||
void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff) {
|
||||
sz += 1;
|
||||
poolIdx = bmpPool.addIndices(childIndices);
|
||||
if (poolIdx > 65535)
|
||||
Log.report(logvisor::Fatal, "AROT bitmap exceeds 16-bit node addressing; area too complex");
|
||||
|
||||
uint32_t childCount = AROTChildCounts[compSubdivs];
|
||||
nodeOff = curOff;
|
||||
nodeSz = childCount * 2 + 4;
|
||||
curOff += nodeSz;
|
||||
if (childNodes.size())
|
||||
{
|
||||
for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
|
||||
{
|
||||
int idx = k*4 + j*2 + i;
|
||||
childNodes[idx].nodeCount(sz, idxRefs, bmpPool, curOff);
|
||||
}
|
||||
}
|
||||
uint32_t childCount = AROTChildCounts[compSubdivs];
|
||||
nodeOff = curOff;
|
||||
nodeSz = childCount * 2 + 4;
|
||||
curOff += nodeSz;
|
||||
if (childNodes.size()) {
|
||||
for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
|
||||
for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
|
||||
for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
|
||||
int idx = k * 4 + j * 2 + i;
|
||||
childNodes[idx].nodeCount(sz, idxRefs, bmpPool, curOff);
|
||||
}
|
||||
idxRefs += childCount;
|
||||
}
|
||||
}
|
||||
idxRefs += childCount;
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::writeIndirectionTable(athena::io::MemoryWriter& w)
|
||||
{
|
||||
w.writeUint32Big(nodeOff);
|
||||
if (childNodes.size())
|
||||
{
|
||||
for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
|
||||
{
|
||||
int idx = k*4 + j*2 + i;
|
||||
childNodes[idx].writeIndirectionTable(w);
|
||||
}
|
||||
}
|
||||
void AROTBuilder::Node::writeIndirectionTable(athena::io::MemoryWriter& w) {
|
||||
w.writeUint32Big(nodeOff);
|
||||
if (childNodes.size()) {
|
||||
for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
|
||||
for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
|
||||
for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
|
||||
int idx = k * 4 + j * 2 + i;
|
||||
childNodes[idx].writeIndirectionTable(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx)
|
||||
{
|
||||
w.writeUint16Big(poolIdx);
|
||||
w.writeUint16Big(compSubdivs);
|
||||
void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx) {
|
||||
w.writeUint16Big(poolIdx);
|
||||
w.writeUint16Big(compSubdivs);
|
||||
|
||||
if (childNodes.size())
|
||||
{
|
||||
int curIdx = nodeIdx + 1;
|
||||
if (curIdx > 65535)
|
||||
Log.report(logvisor::Fatal, "AROT node exceeds 16-bit node addressing; area too complex");
|
||||
if (childNodes.size()) {
|
||||
int curIdx = nodeIdx + 1;
|
||||
if (curIdx > 65535)
|
||||
Log.report(logvisor::Fatal, "AROT node exceeds 16-bit node addressing; area too complex");
|
||||
|
||||
int childIndices[8];
|
||||
int childIndices[8];
|
||||
|
||||
for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
|
||||
{
|
||||
int idx = k*4 + j*2 + i;
|
||||
w.writeUint16Big(curIdx);
|
||||
childIndices[idx] = curIdx;
|
||||
childNodes[idx].advanceIndex(curIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
|
||||
{
|
||||
int idx = k*4 + j*2 + i;
|
||||
childNodes[idx].writeNodes(w, childIndices[idx]);
|
||||
}
|
||||
}
|
||||
for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
|
||||
for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
|
||||
for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
|
||||
int idx = k * 4 + j * 2 + i;
|
||||
w.writeUint16Big(curIdx);
|
||||
childIndices[idx] = curIdx;
|
||||
childNodes[idx].advanceIndex(curIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
|
||||
for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
|
||||
for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
|
||||
int idx = k * 4 + j * 2 + i;
|
||||
childNodes[idx].writeNodes(w, childIndices[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::advanceIndex(int& nodeIdx)
|
||||
{
|
||||
++nodeIdx;
|
||||
if (childNodes.size())
|
||||
{
|
||||
for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k)
|
||||
{
|
||||
for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j)
|
||||
{
|
||||
for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i)
|
||||
{
|
||||
int idx = k*4 + j*2 + i;
|
||||
childNodes[idx].advanceIndex(nodeIdx);
|
||||
}
|
||||
}
|
||||
void AROTBuilder::Node::advanceIndex(int& nodeIdx) {
|
||||
++nodeIdx;
|
||||
if (childNodes.size()) {
|
||||
for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
|
||||
for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
|
||||
for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) {
|
||||
int idx = k * 4 + j * 2 + i;
|
||||
childNodes[idx].advanceIndex(nodeIdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::colSize(size_t& totalSz)
|
||||
{
|
||||
if (childIndices.size())
|
||||
{
|
||||
nodeOff = totalSz;
|
||||
if (childNodes.empty())
|
||||
{
|
||||
totalSz += 26 + childIndices.size() * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
totalSz += 36;
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
childNodes[i].colSize(totalSz);
|
||||
}
|
||||
void AROTBuilder::Node::colSize(size_t& totalSz) {
|
||||
if (childIndices.size()) {
|
||||
nodeOff = totalSz;
|
||||
if (childNodes.empty()) {
|
||||
totalSz += 26 + childIndices.size() * 2;
|
||||
} else {
|
||||
totalSz += 36;
|
||||
for (int i = 0; i < 8; ++i)
|
||||
childNodes[i].colSize(totalSz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB)
|
||||
{
|
||||
if (childIndices.size())
|
||||
{
|
||||
if (childNodes.empty())
|
||||
{
|
||||
float* aabbOut = reinterpret_cast<float*>(ptr);
|
||||
aabbOut[0] = hecl::SBig(curAABB.min[0]);
|
||||
aabbOut[1] = hecl::SBig(curAABB.min[1]);
|
||||
aabbOut[2] = hecl::SBig(curAABB.min[2]);
|
||||
aabbOut[3] = hecl::SBig(curAABB.max[0]);
|
||||
aabbOut[4] = hecl::SBig(curAABB.max[1]);
|
||||
aabbOut[5] = hecl::SBig(curAABB.max[2]);
|
||||
athena::io::MemoryWriter w(ptr + 24, INT32_MAX);
|
||||
w.writeUint16Big(childIndices.size());
|
||||
for (int idx : childIndices)
|
||||
w.writeUint16Big(idx);
|
||||
ptr += 26 + childIndices.size() * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t* pflags = reinterpret_cast<uint16_t*>(ptr);
|
||||
uint32_t* offsets = reinterpret_cast<uint32_t*>(ptr + 4);
|
||||
memset(pflags, 0, sizeof(uint32_t) * 9);
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
{
|
||||
const Node& chNode = childNodes[i];
|
||||
BspNodeType type = BspNodeType((flags >> (i * 2)) & 0x3);
|
||||
if (type != BspNodeType::Invalid)
|
||||
offsets[i] = hecl::SBig(uint32_t(chNode.nodeOff - nodeOff - 36));
|
||||
}
|
||||
void AROTBuilder::Node::writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB) {
|
||||
if (childIndices.size()) {
|
||||
if (childNodes.empty()) {
|
||||
float* aabbOut = reinterpret_cast<float*>(ptr);
|
||||
aabbOut[0] = hecl::SBig(curAABB.min[0]);
|
||||
aabbOut[1] = hecl::SBig(curAABB.min[1]);
|
||||
aabbOut[2] = hecl::SBig(curAABB.min[2]);
|
||||
aabbOut[3] = hecl::SBig(curAABB.max[0]);
|
||||
aabbOut[4] = hecl::SBig(curAABB.max[1]);
|
||||
aabbOut[5] = hecl::SBig(curAABB.max[2]);
|
||||
athena::io::MemoryWriter w(ptr + 24, INT32_MAX);
|
||||
w.writeUint16Big(childIndices.size());
|
||||
for (int idx : childIndices)
|
||||
w.writeUint16Big(idx);
|
||||
ptr += 26 + childIndices.size() * 2;
|
||||
} else {
|
||||
uint16_t* pflags = reinterpret_cast<uint16_t*>(ptr);
|
||||
uint32_t* offsets = reinterpret_cast<uint32_t*>(ptr + 4);
|
||||
memset(pflags, 0, sizeof(uint32_t) * 9);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
const Node& chNode = childNodes[i];
|
||||
BspNodeType type = BspNodeType((flags >> (i * 2)) & 0x3);
|
||||
if (type != BspNodeType::Invalid)
|
||||
offsets[i] = hecl::SBig(uint32_t(chNode.nodeOff - nodeOff - 36));
|
||||
}
|
||||
|
||||
*pflags = hecl::SBig(flags);
|
||||
ptr += 36;
|
||||
*pflags = hecl::SBig(flags);
|
||||
ptr += 36;
|
||||
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
childNodes[i].writeColNodes(ptr, SplitAABB(curAABB, i));
|
||||
}
|
||||
for (int i = 0; i < 8; ++i)
|
||||
childNodes[i].writeColNodes(ptr, SplitAABB(curAABB, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount)
|
||||
{
|
||||
++nodeCount;
|
||||
if (childNodes.empty())
|
||||
{
|
||||
lookupCount += childIndices.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
childNodes[i].pathCountNodesAndLookups(nodeCount, lookupCount);
|
||||
}
|
||||
void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount) {
|
||||
++nodeCount;
|
||||
if (childNodes.empty()) {
|
||||
lookupCount += childIndices.size();
|
||||
} else {
|
||||
for (int i = 0; i < 8; ++i)
|
||||
childNodes[i].pathCountNodesAndLookups(nodeCount, lookupCount);
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB)
|
||||
{
|
||||
if (childNodes.empty())
|
||||
{
|
||||
path.octree.emplace_back();
|
||||
DNAMP1::PATH::OctreeNode& n = path.octree.back();
|
||||
n.isLeaf = 1;
|
||||
n.aabb[0] = curAABB.min;
|
||||
n.aabb[1] = curAABB.max;
|
||||
n.centroid = curAABB.center();
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
n.children[i] = 0xffffffff;
|
||||
n.regionCount = childIndices.size();
|
||||
n.regionStart = path.octreeRegionLookup.size();
|
||||
for (int r : childIndices)
|
||||
path.octreeRegionLookup.push_back(r);
|
||||
void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB) {
|
||||
if (childNodes.empty()) {
|
||||
path.octree.emplace_back();
|
||||
DNAMP1::PATH::OctreeNode& n = path.octree.back();
|
||||
n.isLeaf = 1;
|
||||
n.aabb[0] = curAABB.min;
|
||||
n.aabb[1] = curAABB.max;
|
||||
n.centroid = curAABB.center();
|
||||
for (int i = 0; i < 8; ++i)
|
||||
n.children[i] = 0xffffffff;
|
||||
n.regionCount = childIndices.size();
|
||||
n.regionStart = path.octreeRegionLookup.size();
|
||||
for (int r : childIndices)
|
||||
path.octreeRegionLookup.push_back(r);
|
||||
} else {
|
||||
atUint32 children[8];
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
/* Head recursion (first node will be a leaf) */
|
||||
children[i] = path.octree.size();
|
||||
childNodes[i].pathWrite(path, SplitAABB(curAABB, i));
|
||||
}
|
||||
else
|
||||
{
|
||||
atUint32 children[8];
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
{
|
||||
/* Head recursion (first node will be a leaf) */
|
||||
children[i] = path.octree.size();
|
||||
childNodes[i].pathWrite(path, SplitAABB(curAABB, i));
|
||||
}
|
||||
|
||||
path.octree.emplace_back();
|
||||
DNAMP1::PATH::OctreeNode& n = path.octree.back();
|
||||
n.isLeaf = 0;
|
||||
n.aabb[0] = curAABB.min;
|
||||
n.aabb[1] = curAABB.max;
|
||||
n.centroid = curAABB.center();
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
n.children[i] = children[i];
|
||||
n.regionCount = 0;
|
||||
n.regionStart = 0;
|
||||
}
|
||||
path.octree.emplace_back();
|
||||
DNAMP1::PATH::OctreeNode& n = path.octree.back();
|
||||
n.isLeaf = 0;
|
||||
n.aabb[0] = curAABB.min;
|
||||
n.aabb[1] = curAABB.max;
|
||||
n.centroid = curAABB.center();
|
||||
for (int i = 0; i < 8; ++i)
|
||||
n.children[i] = children[i];
|
||||
n.regionCount = 0;
|
||||
n.regionStart = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void AROTBuilder::build(std::vector<std::vector<uint8_t>>& secs, const zeus::CAABox& fullAabb,
|
||||
const std::vector<zeus::CAABox>& meshAabbs, const std::vector<DNACMDL::Mesh>& meshes)
|
||||
{
|
||||
/* Recursively split */
|
||||
BspNodeType rootType;
|
||||
rootNode.addChild(0, AROT_MIN_MODELS, meshAabbs, fullAabb, rootType);
|
||||
const std::vector<zeus::CAABox>& meshAabbs, const std::vector<DNACMDL::Mesh>& meshes) {
|
||||
/* Recursively split */
|
||||
BspNodeType rootType;
|
||||
rootNode.addChild(0, AROT_MIN_MODELS, meshAabbs, fullAabb, rootType);
|
||||
|
||||
/* Calculate indexing metrics */
|
||||
size_t totalNodeCount = 0;
|
||||
size_t idxRefCount = 0;
|
||||
size_t curOff = 0;
|
||||
rootNode.nodeCount(totalNodeCount, idxRefCount, bmpPool, curOff);
|
||||
size_t bmpWordCount = ROUND_UP_32(meshes.size()) / 32;
|
||||
size_t arotSz = 64 + bmpWordCount * bmpPool.m_pool.size() * 4 + totalNodeCount * 8 + idxRefCount * 2;
|
||||
/* Calculate indexing metrics */
|
||||
size_t totalNodeCount = 0;
|
||||
size_t idxRefCount = 0;
|
||||
size_t curOff = 0;
|
||||
rootNode.nodeCount(totalNodeCount, idxRefCount, bmpPool, curOff);
|
||||
size_t bmpWordCount = ROUND_UP_32(meshes.size()) / 32;
|
||||
size_t arotSz = 64 + bmpWordCount * bmpPool.m_pool.size() * 4 + totalNodeCount * 8 + idxRefCount * 2;
|
||||
|
||||
/* Write header */
|
||||
secs.emplace_back(arotSz, 0);
|
||||
athena::io::MemoryWriter w(secs.back().data(), secs.back().size());
|
||||
w.writeUint32Big('AROT');
|
||||
w.writeUint32Big(1);
|
||||
w.writeUint32Big(bmpPool.m_pool.size());
|
||||
w.writeUint32Big(meshes.size());
|
||||
w.writeUint32Big(totalNodeCount);
|
||||
w.writeVec3fBig(fullAabb.min);
|
||||
w.writeVec3fBig(fullAabb.max);
|
||||
w.seekAlign32();
|
||||
/* Write header */
|
||||
secs.emplace_back(arotSz, 0);
|
||||
athena::io::MemoryWriter w(secs.back().data(), secs.back().size());
|
||||
w.writeUint32Big('AROT');
|
||||
w.writeUint32Big(1);
|
||||
w.writeUint32Big(bmpPool.m_pool.size());
|
||||
w.writeUint32Big(meshes.size());
|
||||
w.writeUint32Big(totalNodeCount);
|
||||
w.writeVec3fBig(fullAabb.min);
|
||||
w.writeVec3fBig(fullAabb.max);
|
||||
w.seekAlign32();
|
||||
|
||||
/* Write bitmap */
|
||||
std::vector<uint32_t> bmpWords;
|
||||
bmpWords.reserve(bmpWordCount);
|
||||
for (const std::set<int>& bmp : bmpPool.m_pool)
|
||||
{
|
||||
bmpWords.clear();
|
||||
bmpWords.resize(bmpWordCount);
|
||||
/* Write bitmap */
|
||||
std::vector<uint32_t> bmpWords;
|
||||
bmpWords.reserve(bmpWordCount);
|
||||
for (const std::set<int>& bmp : bmpPool.m_pool) {
|
||||
bmpWords.clear();
|
||||
bmpWords.resize(bmpWordCount);
|
||||
|
||||
auto bmpIt = bmp.cbegin();
|
||||
if (bmpIt != bmp.cend())
|
||||
{
|
||||
int curIdx = 0;
|
||||
for (int w=0 ; w<bmpWordCount ; ++w)
|
||||
{
|
||||
for (int b=0 ; b<32 ; ++b)
|
||||
{
|
||||
if (*bmpIt == curIdx)
|
||||
{
|
||||
bmpWords[w] |= 1 << b;
|
||||
++bmpIt;
|
||||
if (bmpIt == bmp.cend())
|
||||
break;
|
||||
}
|
||||
++curIdx;
|
||||
}
|
||||
if (bmpIt == bmp.cend())
|
||||
break;
|
||||
}
|
||||
auto bmpIt = bmp.cbegin();
|
||||
if (bmpIt != bmp.cend()) {
|
||||
int curIdx = 0;
|
||||
for (int w = 0; w < bmpWordCount; ++w) {
|
||||
for (int b = 0; b < 32; ++b) {
|
||||
if (*bmpIt == curIdx) {
|
||||
bmpWords[w] |= 1 << b;
|
||||
++bmpIt;
|
||||
if (bmpIt == bmp.cend())
|
||||
break;
|
||||
}
|
||||
++curIdx;
|
||||
}
|
||||
|
||||
for (uint32_t word : bmpWords)
|
||||
w.writeUint32Big(word);
|
||||
if (bmpIt == bmp.cend())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the rest */
|
||||
rootNode.writeIndirectionTable(w);
|
||||
rootNode.writeNodes(w, 0);
|
||||
for (uint32_t word : bmpWords)
|
||||
w.writeUint32Big(word);
|
||||
}
|
||||
|
||||
/* Write the rest */
|
||||
rootNode.writeIndirectionTable(w);
|
||||
rootNode.writeNodes(w, 0);
|
||||
}
|
||||
|
||||
std::pair<std::unique_ptr<uint8_t[]>, uint32_t> AROTBuilder::buildCol(const ColMesh& mesh, BspNodeType& rootOut)
|
||||
{
|
||||
/* Accumulate total AABB */
|
||||
zeus::CAABox fullAABB;
|
||||
for (const auto& vert : mesh.verts)
|
||||
fullAABB.accumulateBounds(zeus::CVector3f(vert));
|
||||
std::pair<std::unique_ptr<uint8_t[]>, uint32_t> AROTBuilder::buildCol(const ColMesh& mesh, BspNodeType& rootOut) {
|
||||
/* Accumulate total AABB */
|
||||
zeus::CAABox fullAABB;
|
||||
for (const auto& vert : mesh.verts)
|
||||
fullAABB.accumulateBounds(zeus::CVector3f(vert));
|
||||
|
||||
/* Predetermine triangle AABBs */
|
||||
std::vector<zeus::CAABox> triBoxes;
|
||||
triBoxes.reserve(mesh.trianges.size());
|
||||
for (const ColMesh::Triangle& tri : mesh.trianges)
|
||||
{
|
||||
triBoxes.emplace_back();
|
||||
zeus::CAABox& aabb = triBoxes.back();
|
||||
for (int e=0 ; e<3 ; ++e)
|
||||
{
|
||||
const ColMesh::Edge& edge = mesh.edges[tri.edges[e]];
|
||||
for (int v=0 ; v<2 ; ++v)
|
||||
{
|
||||
const auto& vert = mesh.verts[edge.verts[v]];
|
||||
aabb.accumulateBounds(zeus::CVector3f(vert));
|
||||
}
|
||||
}
|
||||
/* Predetermine triangle AABBs */
|
||||
std::vector<zeus::CAABox> triBoxes;
|
||||
triBoxes.reserve(mesh.trianges.size());
|
||||
for (const ColMesh::Triangle& tri : mesh.trianges) {
|
||||
triBoxes.emplace_back();
|
||||
zeus::CAABox& aabb = triBoxes.back();
|
||||
for (int e = 0; e < 3; ++e) {
|
||||
const ColMesh::Edge& edge = mesh.edges[tri.edges[e]];
|
||||
for (int v = 0; v < 2; ++v) {
|
||||
const auto& vert = mesh.verts[edge.verts[v]];
|
||||
aabb.accumulateBounds(zeus::CVector3f(vert));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Recursively split */
|
||||
rootNode.addChild(0, COLLISION_MIN_NODE_TRIANGLES, triBoxes, fullAABB, rootOut);
|
||||
/* Recursively split */
|
||||
rootNode.addChild(0, COLLISION_MIN_NODE_TRIANGLES, triBoxes, fullAABB, rootOut);
|
||||
|
||||
/* Calculate offsets and write out */
|
||||
size_t totalSize = 0;
|
||||
rootNode.colSize(totalSize);
|
||||
std::unique_ptr<uint8_t[]> ret(new uint8_t[totalSize]);
|
||||
uint8_t* ptr = ret.get();
|
||||
rootNode.writeColNodes(ptr, fullAABB);
|
||||
/* Calculate offsets and write out */
|
||||
size_t totalSize = 0;
|
||||
rootNode.colSize(totalSize);
|
||||
std::unique_ptr<uint8_t[]> ret(new uint8_t[totalSize]);
|
||||
uint8_t* ptr = ret.get();
|
||||
rootNode.writeColNodes(ptr, fullAABB);
|
||||
|
||||
return {std::move(ret), totalSize};
|
||||
return {std::move(ret), totalSize};
|
||||
}
|
||||
|
||||
void AROTBuilder::buildPath(DNAMP1::PATH& path)
|
||||
{
|
||||
/* Accumulate total AABB and gather region boxes */
|
||||
std::vector<zeus::CAABox> regionBoxes;
|
||||
regionBoxes.reserve(path.regions.size());
|
||||
zeus::CAABox fullAABB;
|
||||
for (const DNAMP1::PATH::Region& r : path.regions)
|
||||
{
|
||||
regionBoxes.emplace_back(r.aabb[0], r.aabb[1]);
|
||||
fullAABB.accumulateBounds(regionBoxes.back());
|
||||
}
|
||||
void AROTBuilder::buildPath(DNAMP1::PATH& path) {
|
||||
/* Accumulate total AABB and gather region boxes */
|
||||
std::vector<zeus::CAABox> regionBoxes;
|
||||
regionBoxes.reserve(path.regions.size());
|
||||
zeus::CAABox fullAABB;
|
||||
for (const DNAMP1::PATH::Region& r : path.regions) {
|
||||
regionBoxes.emplace_back(r.aabb[0], r.aabb[1]);
|
||||
fullAABB.accumulateBounds(regionBoxes.back());
|
||||
}
|
||||
|
||||
/* Recursively split */
|
||||
BspNodeType dontCare;
|
||||
rootNode.addChild(0, PATH_MIN_NODE_REGIONS, regionBoxes, fullAABB, dontCare);
|
||||
/* Recursively split */
|
||||
BspNodeType dontCare;
|
||||
rootNode.addChild(0, PATH_MIN_NODE_REGIONS, regionBoxes, fullAABB, dontCare);
|
||||
|
||||
/* Write out */
|
||||
size_t nodeCount = 0;
|
||||
size_t lookupCount = 0;
|
||||
rootNode.pathCountNodesAndLookups(nodeCount, lookupCount);
|
||||
path.octreeNodeCount = nodeCount;
|
||||
path.octree.reserve(nodeCount);
|
||||
path.octreeRegionLookupCount = lookupCount;
|
||||
path.octreeRegionLookup.reserve(lookupCount);
|
||||
rootNode.pathWrite(path, fullAABB);
|
||||
/* Write out */
|
||||
size_t nodeCount = 0;
|
||||
size_t lookupCount = 0;
|
||||
rootNode.pathCountNodesAndLookups(nodeCount, lookupCount);
|
||||
path.octreeNodeCount = nodeCount;
|
||||
path.octree.reserve(nodeCount);
|
||||
path.octreeRegionLookupCount = lookupCount;
|
||||
path.octreeRegionLookup.reserve(lookupCount);
|
||||
rootNode.pathWrite(path, fullAABB);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -6,55 +6,49 @@
|
|||
#include "CMDL.hpp"
|
||||
#include <set>
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DNAMP1
|
||||
{
|
||||
namespace DataSpec {
|
||||
namespace DNAMP1 {
|
||||
struct PATH;
|
||||
}
|
||||
|
||||
struct AROTBuilder
|
||||
{
|
||||
using ColMesh = hecl::blender::ColMesh;
|
||||
struct AROTBuilder {
|
||||
using ColMesh = hecl::blender::ColMesh;
|
||||
|
||||
struct BitmapPool
|
||||
{
|
||||
std::vector<std::set<int>> m_pool;
|
||||
size_t addIndices(const std::set<int>& indices);
|
||||
} bmpPool;
|
||||
struct BitmapPool {
|
||||
std::vector<std::set<int>> m_pool;
|
||||
size_t addIndices(const std::set<int>& indices);
|
||||
} bmpPool;
|
||||
|
||||
struct Node
|
||||
{
|
||||
std::vector<Node> childNodes;
|
||||
std::set<int> childIndices;
|
||||
size_t poolIdx = 0;
|
||||
uint16_t flags = 0;
|
||||
uint16_t compSubdivs = 0;
|
||||
struct Node {
|
||||
std::vector<Node> childNodes;
|
||||
std::set<int> childIndices;
|
||||
size_t poolIdx = 0;
|
||||
uint16_t flags = 0;
|
||||
uint16_t compSubdivs = 0;
|
||||
|
||||
size_t nodeOff = 0;
|
||||
size_t nodeSz = 4;
|
||||
size_t nodeOff = 0;
|
||||
size_t nodeSz = 4;
|
||||
|
||||
void addChild(int level, int minChildren, const std::vector<zeus::CAABox>& triBoxes,
|
||||
const zeus::CAABox& curAABB, BspNodeType& typeOut);
|
||||
void mergeSets(int a, int b);
|
||||
bool compareSets(int a, int b) const;
|
||||
void nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff);
|
||||
void writeIndirectionTable(athena::io::MemoryWriter& w);
|
||||
void writeNodes(athena::io::MemoryWriter& w, int nodeIdx);
|
||||
void advanceIndex(int& nodeIdx);
|
||||
void addChild(int level, int minChildren, const std::vector<zeus::CAABox>& triBoxes, const zeus::CAABox& curAABB,
|
||||
BspNodeType& typeOut);
|
||||
void mergeSets(int a, int b);
|
||||
bool compareSets(int a, int b) const;
|
||||
void nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff);
|
||||
void writeIndirectionTable(athena::io::MemoryWriter& w);
|
||||
void writeNodes(athena::io::MemoryWriter& w, int nodeIdx);
|
||||
void advanceIndex(int& nodeIdx);
|
||||
|
||||
void colSize(size_t& totalSz);
|
||||
void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB);
|
||||
void colSize(size_t& totalSz);
|
||||
void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB);
|
||||
|
||||
void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount);
|
||||
void pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB);
|
||||
} rootNode;
|
||||
void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount);
|
||||
void pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB);
|
||||
} rootNode;
|
||||
|
||||
void build(std::vector<std::vector<uint8_t>>& secs, const zeus::CAABox& fullAabb,
|
||||
const std::vector<zeus::CAABox>& meshAabbs, const std::vector<DNACMDL::Mesh>& meshes);
|
||||
std::pair<std::unique_ptr<uint8_t[]>, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut);
|
||||
void buildPath(DNAMP1::PATH& path);
|
||||
void build(std::vector<std::vector<uint8_t>>& secs, const zeus::CAABox& fullAabb,
|
||||
const std::vector<zeus::CAABox>& meshAabbs, const std::vector<DNACMDL::Mesh>& meshes);
|
||||
std::pair<std::unique_ptr<uint8_t[]>, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut);
|
||||
void buildPath(DNAMP1::PATH& path);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -1,61 +1,55 @@
|
|||
#include "ATBL.hpp"
|
||||
|
||||
namespace DataSpec::DNAAudio
|
||||
{
|
||||
namespace DataSpec::DNAAudio {
|
||||
|
||||
bool ATBL::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
uint32_t idxCount = rs.readUint32Big();
|
||||
athena::io::YAMLDocWriter w("ATBL");
|
||||
for (uint32_t i=0 ; i<idxCount ; ++i)
|
||||
{
|
||||
uint16_t idx = rs.readUint16Big();
|
||||
if (idx == 0xffff)
|
||||
continue;
|
||||
char iStr[16];
|
||||
snprintf(iStr, 16, "0x%04X", int(i));
|
||||
w.writeUint16(iStr, idx);
|
||||
}
|
||||
bool ATBL::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
uint32_t idxCount = rs.readUint32Big();
|
||||
athena::io::YAMLDocWriter w("ATBL");
|
||||
for (uint32_t i = 0; i < idxCount; ++i) {
|
||||
uint16_t idx = rs.readUint16Big();
|
||||
if (idx == 0xffff)
|
||||
continue;
|
||||
char iStr[16];
|
||||
snprintf(iStr, 16, "0x%04X", int(i));
|
||||
w.writeUint16(iStr, idx);
|
||||
}
|
||||
|
||||
athena::io::FileWriter fw(outPath.getAbsolutePath());
|
||||
w.finish(&fw);
|
||||
athena::io::FileWriter fw(outPath.getAbsolutePath());
|
||||
w.finish(&fw);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ATBL::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileReader r(inPath.getAbsolutePath());
|
||||
if (r.hasError())
|
||||
return false;
|
||||
bool ATBL::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileReader r(inPath.getAbsolutePath());
|
||||
if (r.hasError())
|
||||
return false;
|
||||
|
||||
athena::io::YAMLDocReader dr;
|
||||
if (!dr.parse(&r))
|
||||
return false;
|
||||
athena::io::YAMLDocReader dr;
|
||||
if (!dr.parse(&r))
|
||||
return false;
|
||||
|
||||
unsigned long maxI = 0;
|
||||
for (const auto& pair : dr.getRootNode()->m_mapChildren)
|
||||
{
|
||||
unsigned long i = strtoul(pair.first.c_str(), nullptr, 0);
|
||||
maxI = std::max(maxI, i);
|
||||
}
|
||||
unsigned long maxI = 0;
|
||||
for (const auto& pair : dr.getRootNode()->m_mapChildren) {
|
||||
unsigned long i = strtoul(pair.first.c_str(), nullptr, 0);
|
||||
maxI = std::max(maxI, i);
|
||||
}
|
||||
|
||||
std::vector<uint16_t> vecOut;
|
||||
vecOut.resize(maxI + 1, 0xffff);
|
||||
std::vector<uint16_t> vecOut;
|
||||
vecOut.resize(maxI + 1, 0xffff);
|
||||
|
||||
for (const auto& pair : dr.getRootNode()->m_mapChildren)
|
||||
{
|
||||
unsigned long i = strtoul(pair.first.c_str(), nullptr, 0);
|
||||
vecOut[i] = hecl::SBig(uint16_t(strtoul(pair.second->m_scalarString.c_str(), nullptr, 0)));
|
||||
}
|
||||
for (const auto& pair : dr.getRootNode()->m_mapChildren) {
|
||||
unsigned long i = strtoul(pair.first.c_str(), nullptr, 0);
|
||||
vecOut[i] = hecl::SBig(uint16_t(strtoul(pair.second->m_scalarString.c_str(), nullptr, 0)));
|
||||
}
|
||||
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
w.writeUint32Big(uint32_t(vecOut.size()));
|
||||
w.writeBytes(vecOut.data(), vecOut.size() * 2);
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
w.writeUint32Big(uint32_t(vecOut.size()));
|
||||
w.writeBytes(vecOut.data(), vecOut.size() * 2);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAAudio
|
||||
|
|
|
@ -3,15 +3,12 @@
|
|||
#include "DNACommon.hpp"
|
||||
#include "PAK.hpp"
|
||||
|
||||
namespace DataSpec::DNAAudio
|
||||
{
|
||||
namespace DataSpec::DNAAudio {
|
||||
|
||||
class ATBL
|
||||
{
|
||||
class ATBL {
|
||||
public:
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAAudio
|
||||
|
|
|
@ -4,163 +4,156 @@
|
|||
#include "zeus/CTransform.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
template<class BabeDeadLight>
|
||||
void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os,
|
||||
const BabeDeadLight& light, unsigned s, unsigned l)
|
||||
{
|
||||
switch (light.lightType)
|
||||
{
|
||||
case BabeDeadLight::LightType::LocalAmbient:
|
||||
case BabeDeadLight::LightType::LocalAmbient2:
|
||||
os.format("bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n"
|
||||
"bg_node.inputs[1].default_value = %f\n",
|
||||
light.color.simd[0], light.color.simd[1], light.color.simd[2],
|
||||
light.q / 8.f);
|
||||
return;
|
||||
case BabeDeadLight::LightType::Directional:
|
||||
os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SUN')\n"
|
||||
"lamp.color = (%f,%f,%f)\n"
|
||||
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
||||
"lamp_obj.rotation_mode = 'QUATERNION'\n"
|
||||
"lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
|
||||
"lamp.shadow_method = '%s'\n"
|
||||
"\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2],
|
||||
light.direction.simd[0], light.direction.simd[1], light.direction.simd[2],
|
||||
light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
|
||||
return;
|
||||
case BabeDeadLight::LightType::Custom:
|
||||
os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'POINT')\n"
|
||||
"lamp.color = (%f,%f,%f)\n"
|
||||
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
||||
"lamp.shadow_soft_size = 1.0\n"
|
||||
"lamp.shadow_method = '%s'\n"
|
||||
"\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2],
|
||||
light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
|
||||
break;
|
||||
case BabeDeadLight::LightType::Spot:
|
||||
case BabeDeadLight::LightType::Spot2:
|
||||
os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n"
|
||||
"lamp.color = (%f,%f,%f)\n"
|
||||
"lamp.spot_size = %.6g\n"
|
||||
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
||||
"lamp_obj.rotation_mode = 'QUATERNION'\n"
|
||||
"lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
|
||||
"lamp.shadow_soft_size = 0.5\n"
|
||||
"lamp.shadow_method = '%s'\n"
|
||||
"\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2],
|
||||
zeus::degToRad(light.spotCutoff),
|
||||
light.direction.simd[0], light.direction.simd[1], light.direction.simd[2],
|
||||
light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
template <class BabeDeadLight>
|
||||
void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLight& light, unsigned s, unsigned l) {
|
||||
switch (light.lightType) {
|
||||
case BabeDeadLight::LightType::LocalAmbient:
|
||||
case BabeDeadLight::LightType::LocalAmbient2:
|
||||
os.format(
|
||||
"bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n"
|
||||
"bg_node.inputs[1].default_value = %f\n",
|
||||
light.color.simd[0], light.color.simd[1], light.color.simd[2], light.q / 8.f);
|
||||
return;
|
||||
case BabeDeadLight::LightType::Directional:
|
||||
os.format(
|
||||
"lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SUN')\n"
|
||||
"lamp.color = (%f,%f,%f)\n"
|
||||
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
||||
"lamp_obj.rotation_mode = 'QUATERNION'\n"
|
||||
"lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
|
||||
"lamp.shadow_method = '%s'\n"
|
||||
"\n",
|
||||
s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], light.direction.simd[0],
|
||||
light.direction.simd[1], light.direction.simd[2], light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
|
||||
return;
|
||||
case BabeDeadLight::LightType::Custom:
|
||||
os.format(
|
||||
"lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'POINT')\n"
|
||||
"lamp.color = (%f,%f,%f)\n"
|
||||
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
||||
"lamp.shadow_soft_size = 1.0\n"
|
||||
"lamp.shadow_method = '%s'\n"
|
||||
"\n",
|
||||
s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2],
|
||||
light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
|
||||
break;
|
||||
case BabeDeadLight::LightType::Spot:
|
||||
case BabeDeadLight::LightType::Spot2:
|
||||
os.format(
|
||||
"lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n"
|
||||
"lamp.color = (%f,%f,%f)\n"
|
||||
"lamp.spot_size = %.6g\n"
|
||||
"lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n"
|
||||
"lamp_obj.rotation_mode = 'QUATERNION'\n"
|
||||
"lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n"
|
||||
"lamp.shadow_soft_size = 0.5\n"
|
||||
"lamp.shadow_method = '%s'\n"
|
||||
"\n",
|
||||
s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], zeus::degToRad(light.spotCutoff),
|
||||
light.direction.simd[0], light.direction.simd[1], light.direction.simd[2],
|
||||
light.castShadows ? "RAY_SHADOW" : "NOSHADOW");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
os.format("lamp.retro_layer = %u\n"
|
||||
"lamp.retro_origtype = %u\n"
|
||||
"lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n"
|
||||
"lamp.constant_coefficient = 0\n"
|
||||
"lamp.use_nodes = True\n"
|
||||
"falloff_node = lamp.node_tree.nodes.new('ShaderNodeLightFalloff')\n"
|
||||
"lamp.energy = 0.0\n"
|
||||
"falloff_node.inputs[0].default_value = %f\n"
|
||||
"hue_sat_node = lamp.node_tree.nodes.new('ShaderNodeHueSaturation')\n"
|
||||
"hue_sat_node.inputs[1].default_value = 1.25\n"
|
||||
"hue_sat_node.inputs[4].default_value = (%f,%f,%f,1.0)\n"
|
||||
"lamp.node_tree.links.new(hue_sat_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[0])\n"
|
||||
"lamp_obj.location = (%f,%f,%f)\n"
|
||||
"bpy.context.scene.objects.link(lamp_obj)\n"
|
||||
"\n", s, light.lightType, light.q / 8.f,
|
||||
light.color.simd[0], light.color.simd[1], light.color.simd[2],
|
||||
light.position.simd[0], light.position.simd[1], light.position.simd[2]);
|
||||
os.format(
|
||||
"lamp.retro_layer = %u\n"
|
||||
"lamp.retro_origtype = %u\n"
|
||||
"lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n"
|
||||
"lamp.constant_coefficient = 0\n"
|
||||
"lamp.use_nodes = True\n"
|
||||
"falloff_node = lamp.node_tree.nodes.new('ShaderNodeLightFalloff')\n"
|
||||
"lamp.energy = 0.0\n"
|
||||
"falloff_node.inputs[0].default_value = %f\n"
|
||||
"hue_sat_node = lamp.node_tree.nodes.new('ShaderNodeHueSaturation')\n"
|
||||
"hue_sat_node.inputs[1].default_value = 1.25\n"
|
||||
"hue_sat_node.inputs[4].default_value = (%f,%f,%f,1.0)\n"
|
||||
"lamp.node_tree.links.new(hue_sat_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[0])\n"
|
||||
"lamp_obj.location = (%f,%f,%f)\n"
|
||||
"bpy.context.scene.objects.link(lamp_obj)\n"
|
||||
"\n",
|
||||
s, light.lightType, light.q / 8.f, light.color.simd[0], light.color.simd[1], light.color.simd[2],
|
||||
light.position.simd[0], light.position.simd[1], light.position.simd[2]);
|
||||
|
||||
switch (light.falloff)
|
||||
{
|
||||
case BabeDeadLight::Falloff::Constant:
|
||||
os << "falloff_node.inputs[0].default_value *= 150.0\n"
|
||||
"lamp.node_tree.links.new(falloff_node.outputs[2], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
if (light.q > FLT_EPSILON)
|
||||
os.format("lamp.constant_coefficient = 2.0 / %f\n", light.q);
|
||||
break;
|
||||
case BabeDeadLight::Falloff::Linear:
|
||||
os << "lamp.node_tree.links.new(falloff_node.outputs[1], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
if (light.q > FLT_EPSILON)
|
||||
os.format("lamp.linear_coefficient = 250 / %f\n", light.q);
|
||||
break;
|
||||
case BabeDeadLight::Falloff::Quadratic:
|
||||
os << "lamp.node_tree.links.new(falloff_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
if (light.q > FLT_EPSILON)
|
||||
os.format("lamp.quadratic_coefficient = 25000 / %f\n", light.q);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
switch (light.falloff) {
|
||||
case BabeDeadLight::Falloff::Constant:
|
||||
os << "falloff_node.inputs[0].default_value *= 150.0\n"
|
||||
"lamp.node_tree.links.new(falloff_node.outputs[2], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
if (light.q > FLT_EPSILON)
|
||||
os.format("lamp.constant_coefficient = 2.0 / %f\n", light.q);
|
||||
break;
|
||||
case BabeDeadLight::Falloff::Linear:
|
||||
os << "lamp.node_tree.links.new(falloff_node.outputs[1], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
if (light.q > FLT_EPSILON)
|
||||
os.format("lamp.linear_coefficient = 250 / %f\n", light.q);
|
||||
break;
|
||||
case BabeDeadLight::Falloff::Quadratic:
|
||||
os << "lamp.node_tree.links.new(falloff_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[1])\n";
|
||||
if (light.q > FLT_EPSILON)
|
||||
os.format("lamp.quadratic_coefficient = 25000 / %f\n", light.q);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template void ReadBabeDeadLightToBlender<DNAMP1::MREA::BabeDeadLight>
|
||||
(hecl::blender::PyOutStream& os, const DNAMP1::MREA::BabeDeadLight& light, unsigned s, unsigned l);
|
||||
template void ReadBabeDeadLightToBlender<DNAMP3::MREA::BabeDeadLight>
|
||||
(hecl::blender::PyOutStream& os, const DNAMP3::MREA::BabeDeadLight& light, unsigned s, unsigned l);
|
||||
template void ReadBabeDeadLightToBlender<DNAMP1::MREA::BabeDeadLight>(hecl::blender::PyOutStream& os,
|
||||
const DNAMP1::MREA::BabeDeadLight& light,
|
||||
unsigned s, unsigned l);
|
||||
template void ReadBabeDeadLightToBlender<DNAMP3::MREA::BabeDeadLight>(hecl::blender::PyOutStream& os,
|
||||
const DNAMP3::MREA::BabeDeadLight& light,
|
||||
unsigned s, unsigned l);
|
||||
|
||||
template<class BabeDeadLight>
|
||||
void WriteBabeDeadLightFromBlender(BabeDeadLight& lightOut, const hecl::blender::Light& lightIn)
|
||||
{
|
||||
using InterType = hecl::blender::Light::Type;
|
||||
switch (lightIn.type)
|
||||
{
|
||||
case InterType::Ambient:
|
||||
lightOut.lightType = BabeDeadLight::LightType::LocalAmbient;
|
||||
break;
|
||||
case InterType::Directional:
|
||||
lightOut.lightType = BabeDeadLight::LightType::Directional;
|
||||
break;
|
||||
case InterType::Custom:
|
||||
default:
|
||||
lightOut.lightType = BabeDeadLight::LightType::Custom;
|
||||
break;
|
||||
case InterType::Spot:
|
||||
lightOut.lightType = BabeDeadLight::LightType::Spot;
|
||||
break;
|
||||
}
|
||||
template <class BabeDeadLight>
|
||||
void WriteBabeDeadLightFromBlender(BabeDeadLight& lightOut, const hecl::blender::Light& lightIn) {
|
||||
using InterType = hecl::blender::Light::Type;
|
||||
switch (lightIn.type) {
|
||||
case InterType::Ambient:
|
||||
lightOut.lightType = BabeDeadLight::LightType::LocalAmbient;
|
||||
break;
|
||||
case InterType::Directional:
|
||||
lightOut.lightType = BabeDeadLight::LightType::Directional;
|
||||
break;
|
||||
case InterType::Custom:
|
||||
default:
|
||||
lightOut.lightType = BabeDeadLight::LightType::Custom;
|
||||
break;
|
||||
case InterType::Spot:
|
||||
lightOut.lightType = BabeDeadLight::LightType::Spot;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lightIn.type == InterType::Ambient)
|
||||
{
|
||||
lightOut.falloff = BabeDeadLight::Falloff::Constant;
|
||||
lightOut.q = lightIn.energy * 8.f;
|
||||
}
|
||||
else if (lightIn.linear > lightIn.constant &&
|
||||
lightIn.linear > lightIn.quadratic)
|
||||
{
|
||||
lightOut.falloff = BabeDeadLight::Falloff::Linear;
|
||||
lightOut.q = 250.f / lightIn.linear;
|
||||
}
|
||||
else if (lightIn.quadratic > lightIn.constant &&
|
||||
lightIn.quadratic > lightIn.linear)
|
||||
{
|
||||
lightOut.falloff = BabeDeadLight::Falloff::Quadratic;
|
||||
lightOut.q = 25000.f / lightIn.quadratic;
|
||||
}
|
||||
else
|
||||
{
|
||||
lightOut.falloff = BabeDeadLight::Falloff::Constant;
|
||||
lightOut.q = 2.f / lightIn.constant;
|
||||
}
|
||||
if (lightIn.type == InterType::Ambient) {
|
||||
lightOut.falloff = BabeDeadLight::Falloff::Constant;
|
||||
lightOut.q = lightIn.energy * 8.f;
|
||||
} else if (lightIn.linear > lightIn.constant && lightIn.linear > lightIn.quadratic) {
|
||||
lightOut.falloff = BabeDeadLight::Falloff::Linear;
|
||||
lightOut.q = 250.f / lightIn.linear;
|
||||
} else if (lightIn.quadratic > lightIn.constant && lightIn.quadratic > lightIn.linear) {
|
||||
lightOut.falloff = BabeDeadLight::Falloff::Quadratic;
|
||||
lightOut.q = 25000.f / lightIn.quadratic;
|
||||
} else {
|
||||
lightOut.falloff = BabeDeadLight::Falloff::Constant;
|
||||
lightOut.q = 2.f / lightIn.constant;
|
||||
}
|
||||
|
||||
lightOut.color = lightIn.color;
|
||||
lightOut.spotCutoff = zeus::radToDeg(lightIn.spotCutoff);
|
||||
lightOut.castShadows = lightIn.shadow;
|
||||
lightOut.position.simd[0] = lightIn.sceneXf[0].simd[3];
|
||||
lightOut.position.simd[1] = lightIn.sceneXf[1].simd[3];
|
||||
lightOut.position.simd[2] = lightIn.sceneXf[2].simd[3];
|
||||
lightOut.color = lightIn.color;
|
||||
lightOut.spotCutoff = zeus::radToDeg(lightIn.spotCutoff);
|
||||
lightOut.castShadows = lightIn.shadow;
|
||||
lightOut.position.simd[0] = lightIn.sceneXf[0].simd[3];
|
||||
lightOut.position.simd[1] = lightIn.sceneXf[1].simd[3];
|
||||
lightOut.position.simd[2] = lightIn.sceneXf[2].simd[3];
|
||||
|
||||
zeus::CTransform lightXf(&lightIn.sceneXf[0]);
|
||||
lightOut.direction = (lightXf.basis.transposed() * zeus::CVector3f(0.f, 0.f, -1.f)).normalized();
|
||||
zeus::CTransform lightXf(&lightIn.sceneXf[0]);
|
||||
lightOut.direction = (lightXf.basis.transposed() * zeus::CVector3f(0.f, 0.f, -1.f)).normalized();
|
||||
}
|
||||
|
||||
template void WriteBabeDeadLightFromBlender<DNAMP1::MREA::BabeDeadLight>
|
||||
(DNAMP1::MREA::BabeDeadLight& lightOut, const hecl::blender::Light& lightIn);
|
||||
template void WriteBabeDeadLightFromBlender<DNAMP3::MREA::BabeDeadLight>
|
||||
(DNAMP3::MREA::BabeDeadLight& lightOut, const hecl::blender::Light& lightIn);
|
||||
template void WriteBabeDeadLightFromBlender<DNAMP1::MREA::BabeDeadLight>(DNAMP1::MREA::BabeDeadLight& lightOut,
|
||||
const hecl::blender::Light& lightIn);
|
||||
template void WriteBabeDeadLightFromBlender<DNAMP3::MREA::BabeDeadLight>(DNAMP3::MREA::BabeDeadLight& lightOut,
|
||||
const hecl::blender::Light& lightIn);
|
||||
|
||||
}
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -4,15 +4,12 @@
|
|||
#include "hecl/hecl.hpp"
|
||||
#include <cfloat>
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
template<class BabeDeadLight>
|
||||
void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os,
|
||||
const BabeDeadLight& light, unsigned s, unsigned l);
|
||||
template <class BabeDeadLight>
|
||||
void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLight& light, unsigned s, unsigned l);
|
||||
|
||||
template<class BabeDeadLight>
|
||||
template <class BabeDeadLight>
|
||||
void WriteBabeDeadLightFromBlender(BabeDeadLight& lightOut, const hecl::blender::Light& lightIn);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,165 +8,144 @@
|
|||
#include "TXTR.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
|
||||
namespace DataSpec::DNACMDL
|
||||
{
|
||||
namespace DataSpec::DNACMDL {
|
||||
|
||||
using Mesh = hecl::blender::Mesh;
|
||||
using Material = hecl::blender::Material;
|
||||
|
||||
struct Header : BigDNA
|
||||
{
|
||||
struct Header : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
struct Flags : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
struct Flags : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> flags = 0;
|
||||
bool skinned() const {return (flags & 0x1) != 0;}
|
||||
void setSkinned(bool val) {flags &= ~0x1; flags |= val;}
|
||||
bool shortNormals() const {return (flags & 0x2) != 0;}
|
||||
void setShortNormals(bool val) {flags &= ~0x2; flags |= val << 1;}
|
||||
bool shortUVs() const {return (flags & 0x4) != 0;}
|
||||
void setShortUVs(bool val) {flags &= ~0x4; flags |= val << 2;}
|
||||
} flags;
|
||||
Value<atVec3f> aabbMin;
|
||||
Value<atVec3f> aabbMax;
|
||||
Value<atUint32> secCount;
|
||||
Value<atUint32> matSetCount;
|
||||
Vector<atUint32, AT_DNA_COUNT(secCount)> secSizes;
|
||||
Align<32> align;
|
||||
Value<atUint32> flags = 0;
|
||||
bool skinned() const { return (flags & 0x1) != 0; }
|
||||
void setSkinned(bool val) {
|
||||
flags &= ~0x1;
|
||||
flags |= val;
|
||||
}
|
||||
bool shortNormals() const { return (flags & 0x2) != 0; }
|
||||
void setShortNormals(bool val) {
|
||||
flags &= ~0x2;
|
||||
flags |= val << 1;
|
||||
}
|
||||
bool shortUVs() const { return (flags & 0x4) != 0; }
|
||||
void setShortUVs(bool val) {
|
||||
flags &= ~0x4;
|
||||
flags |= val << 2;
|
||||
}
|
||||
} flags;
|
||||
Value<atVec3f> aabbMin;
|
||||
Value<atVec3f> aabbMax;
|
||||
Value<atUint32> secCount;
|
||||
Value<atUint32> matSetCount;
|
||||
Vector<atUint32, AT_DNA_COUNT(secCount)> secSizes;
|
||||
Align<32> align;
|
||||
};
|
||||
|
||||
struct SurfaceHeader_1 : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> matIdx = 0;
|
||||
Value<atUint32> dlSize = 0;
|
||||
Value<atUint32> idxStart = 0; /* Actually used by game to stash CCubeModel pointer */
|
||||
Value<atUint32> idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */
|
||||
Value<atUint32> aabbSz = 0;
|
||||
Value<atVec3f> reflectionNormal;
|
||||
Value<atVec3f> aabb[2];
|
||||
Align<32> align;
|
||||
struct SurfaceHeader_1 : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> matIdx = 0;
|
||||
Value<atUint32> dlSize = 0;
|
||||
Value<atUint32> idxStart = 0; /* Actually used by game to stash CCubeModel pointer */
|
||||
Value<atUint32> idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */
|
||||
Value<atUint32> aabbSz = 0;
|
||||
Value<atVec3f> reflectionNormal;
|
||||
Value<atVec3f> aabb[2];
|
||||
Align<32> align;
|
||||
|
||||
static constexpr bool UseMatrixSkinning() {return false;}
|
||||
static constexpr atInt16 skinMatrixBankIdx() {return -1;}
|
||||
static constexpr bool UseMatrixSkinning() { return false; }
|
||||
static constexpr atInt16 skinMatrixBankIdx() { return -1; }
|
||||
};
|
||||
|
||||
struct SurfaceHeader_2 : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> matIdx = 0;
|
||||
Value<atUint32> dlSize = 0;
|
||||
Value<atUint32> idxStart = 0; /* Actually used by game to stash CCubeModel pointer */
|
||||
Value<atUint32> idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */
|
||||
Value<atUint32> aabbSz = 0;
|
||||
Value<atVec3f> reflectionNormal;
|
||||
Value<atInt16> skinMtxBankIdx;
|
||||
Value<atUint16> surfaceGroup;
|
||||
Value<atVec3f> aabb[2];
|
||||
Align<32> align;
|
||||
struct SurfaceHeader_2 : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> matIdx = 0;
|
||||
Value<atUint32> dlSize = 0;
|
||||
Value<atUint32> idxStart = 0; /* Actually used by game to stash CCubeModel pointer */
|
||||
Value<atUint32> idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */
|
||||
Value<atUint32> aabbSz = 0;
|
||||
Value<atVec3f> reflectionNormal;
|
||||
Value<atInt16> skinMtxBankIdx;
|
||||
Value<atUint16> surfaceGroup;
|
||||
Value<atVec3f> aabb[2];
|
||||
Align<32> align;
|
||||
|
||||
static constexpr bool UseMatrixSkinning() {return false;}
|
||||
atInt16 skinMatrixBankIdx() const {return skinMtxBankIdx;}
|
||||
static constexpr bool UseMatrixSkinning() { return false; }
|
||||
atInt16 skinMatrixBankIdx() const { return skinMtxBankIdx; }
|
||||
};
|
||||
|
||||
struct SurfaceHeader_3 : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> matIdx = 0;
|
||||
Value<atUint32> dlSize = 0;
|
||||
Value<atUint32> idxStart = 0; /* Actually used by game to stash CCubeModel pointer */
|
||||
Value<atUint32> idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */
|
||||
Value<atUint32> aabbSz = 0;
|
||||
Value<atVec3f> reflectionNormal;
|
||||
Value<atInt16> skinMtxBankIdx;
|
||||
Value<atUint16> surfaceGroup;
|
||||
Value<atVec3f> aabb[2];
|
||||
Value<atUint8> unk3;
|
||||
Align<32> align;
|
||||
struct SurfaceHeader_3 : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> matIdx = 0;
|
||||
Value<atUint32> dlSize = 0;
|
||||
Value<atUint32> idxStart = 0; /* Actually used by game to stash CCubeModel pointer */
|
||||
Value<atUint32> idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */
|
||||
Value<atUint32> aabbSz = 0;
|
||||
Value<atVec3f> reflectionNormal;
|
||||
Value<atInt16> skinMtxBankIdx;
|
||||
Value<atUint16> surfaceGroup;
|
||||
Value<atVec3f> aabb[2];
|
||||
Value<atUint8> unk3;
|
||||
Align<32> align;
|
||||
|
||||
static constexpr bool UseMatrixSkinning() {return true;}
|
||||
atInt16 skinMatrixBankIdx() const {return skinMtxBankIdx;}
|
||||
static constexpr bool UseMatrixSkinning() { return true; }
|
||||
atInt16 skinMatrixBankIdx() const { return skinMtxBankIdx; }
|
||||
};
|
||||
|
||||
struct VertexAttributes
|
||||
{
|
||||
GX::AttrType pos = GX::NONE;
|
||||
GX::AttrType norm = GX::NONE;
|
||||
GX::AttrType color0 = GX::NONE;
|
||||
GX::AttrType color1 = GX::NONE;
|
||||
unsigned uvCount = 0;
|
||||
GX::AttrType uvs[7] = {GX::NONE};
|
||||
GX::AttrType pnMtxIdx = GX::NONE;
|
||||
unsigned texMtxIdxCount = 0;
|
||||
GX::AttrType texMtxIdx[7] = {GX::NONE};
|
||||
bool shortUVs;
|
||||
struct VertexAttributes {
|
||||
GX::AttrType pos = GX::NONE;
|
||||
GX::AttrType norm = GX::NONE;
|
||||
GX::AttrType color0 = GX::NONE;
|
||||
GX::AttrType color1 = GX::NONE;
|
||||
unsigned uvCount = 0;
|
||||
GX::AttrType uvs[7] = {GX::NONE};
|
||||
GX::AttrType pnMtxIdx = GX::NONE;
|
||||
unsigned texMtxIdxCount = 0;
|
||||
GX::AttrType texMtxIdx[7] = {GX::NONE};
|
||||
bool shortUVs;
|
||||
};
|
||||
|
||||
template <class MaterialSet>
|
||||
void GetVertexAttributes(const MaterialSet& matSet,
|
||||
std::vector<VertexAttributes>& attributesOut);
|
||||
void GetVertexAttributes(const MaterialSet& matSet, std::vector<VertexAttributes>& attributesOut);
|
||||
|
||||
template <class PAKRouter, class MaterialSet>
|
||||
void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os,
|
||||
const MaterialSet& matSet,
|
||||
const PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
unsigned setIdx);
|
||||
void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry, unsigned setIdx);
|
||||
|
||||
template <class PAKRouter, class MaterialSet>
|
||||
void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os,
|
||||
const MaterialSet& matSet,
|
||||
const PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
unsigned setIdx);
|
||||
void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry, unsigned setIdx);
|
||||
|
||||
void InitGeomBlenderContext(hecl::blender::PyOutStream& os,
|
||||
const hecl::ProjectPath& masterShaderPath,
|
||||
void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectPath& masterShaderPath,
|
||||
bool solidShading);
|
||||
void FinishBlenderMesh(hecl::blender::PyOutStream& os,
|
||||
unsigned matSetCount, int meshIdx);
|
||||
void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int meshIdx);
|
||||
|
||||
template <class PAKRouter, class MaterialSet, class RigPair, class SurfaceHeader>
|
||||
atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os,
|
||||
athena::io::IStreamReader& reader,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
const RigPair& rp,
|
||||
bool shortNormals,
|
||||
bool shortUVs,
|
||||
std::vector<VertexAttributes>& vertAttribs,
|
||||
int meshIdx,
|
||||
atUint32 secCount,
|
||||
atUint32 matSetCount,
|
||||
const atUint32* secSizes,
|
||||
atUint32 surfaceCount=0);
|
||||
atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::IStreamReader& reader,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const RigPair& rp,
|
||||
bool shortNormals, bool shortUVs, std::vector<VertexAttributes>& vertAttribs,
|
||||
int meshIdx, atUint32 secCount, atUint32 matSetCount, const atUint32* secSizes,
|
||||
atUint32 surfaceCount = 0);
|
||||
|
||||
template <class PAKRouter, class MaterialSet, class RigPair, class SurfaceHeader, atUint32 Version>
|
||||
bool ReadCMDLToBlender(hecl::blender::Connection& conn,
|
||||
athena::io::IStreamReader& reader,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
const SpecBase& dataspec,
|
||||
const RigPair& rp);
|
||||
bool ReadCMDLToBlender(hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, const RigPair& rp);
|
||||
|
||||
template <class PAKRouter, class MaterialSet>
|
||||
void NameCMDL(athena::io::IStreamReader& reader,
|
||||
PAKRouter& pakRouter,
|
||||
typename PAKRouter::EntryType& entry,
|
||||
void NameCMDL(athena::io::IStreamReader& reader, PAKRouter& pakRouter, typename PAKRouter::EntryType& entry,
|
||||
const SpecBase& dataspec);
|
||||
|
||||
template <class MaterialSet, class SurfaceHeader, atUint32 Version>
|
||||
bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh);
|
||||
|
||||
template <class MaterialSet, class SurfaceHeader, atUint32 Version>
|
||||
bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath,
|
||||
const Mesh& mesh, hecl::blender::PoolSkinIndex& poolSkinIndex);
|
||||
bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh,
|
||||
hecl::blender::PoolSkinIndex& poolSkinIndex);
|
||||
|
||||
template <class MaterialSet, class SurfaceHeader, class MeshHeader>
|
||||
bool WriteMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::ProjectPath& inPath,
|
||||
|
@ -176,5 +155,4 @@ template <class MaterialSet, class SurfaceHeader, class MeshHeader>
|
|||
bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::ProjectPath& inPath,
|
||||
const std::vector<Mesh>& meshes, zeus::CAABox& fullAABB, std::vector<zeus::CAABox>& meshAABBs);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNACMDL
|
||||
|
|
|
@ -1,341 +1,268 @@
|
|||
#include "CRSC.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle
|
||||
{
|
||||
static const std::vector<FourCC> GeneratorTypes =
|
||||
{
|
||||
SBIG('NODP'),SBIG('DEFS'),SBIG('CRTS'),SBIG('MTLS'),
|
||||
SBIG('GRAS'),SBIG('ICEE'),SBIG('GOOO'),SBIG('WODS'),
|
||||
SBIG('WATR'),SBIG('1MUD'),SBIG('1LAV'),SBIG('1SAN'),
|
||||
SBIG('1PRJ'),SBIG('DCHR'),SBIG('DCHS'),SBIG('DCSH'),
|
||||
SBIG('DENM'),SBIG('DESP'),SBIG('DESH'),SBIG('BTLE'),
|
||||
SBIG('WASP'),SBIG('TALP'),SBIG('PTGM'),SBIG('SPIR'),
|
||||
SBIG('FPIR'),SBIG('FFLE'),SBIG('PARA'),SBIG('BMON'),
|
||||
SBIG('BFLR'),SBIG('PBOS'),SBIG('IBOS'),SBIG('1SVA'),
|
||||
SBIG('1RPR'),SBIG('1MTR'),SBIG('1PDS'),SBIG('1FLB'),
|
||||
SBIG('1DRN'),SBIG('1MRE'),SBIG('CHOZ'),SBIG('JZAP'),
|
||||
SBIG('1ISE'),SBIG('1BSE'),SBIG('1ATB'),SBIG('1ATA'),
|
||||
SBIG('BTSP'),SBIG('WWSP'),SBIG('TASP'),SBIG('TGSP'),
|
||||
SBIG('SPSP'),SBIG('FPSP'),SBIG('FFSP'),SBIG('PSSP'),
|
||||
SBIG('BMSP'),SBIG('BFSP'),SBIG('PBSP'),SBIG('IBSP'),
|
||||
SBIG('2SVA'),SBIG('2RPR'),SBIG('2MTR'),SBIG('2PDS'),
|
||||
SBIG('2FLB'),SBIG('2DRN'),SBIG('2MRE'),SBIG('CHSP'),
|
||||
SBIG('JZSP'),SBIG('3ISE'),SBIG('3BSE'),SBIG('3ATB'),
|
||||
SBIG('3ATA'),SBIG('BTSH'),SBIG('WWSH'),SBIG('TASH'),
|
||||
SBIG('TGSH'),SBIG('SPSH'),SBIG('FPSH'),SBIG('FFSH'),
|
||||
SBIG('PSSH'),SBIG('BMSH'),SBIG('BFSH'),SBIG('PBSH'),
|
||||
SBIG('IBSH'),SBIG('3SVA'),SBIG('3RPR'),SBIG('3MTR'),
|
||||
SBIG('3PDS'),SBIG('3FLB'),SBIG('3DRN'),SBIG('3MRE'),
|
||||
SBIG('CHSH'),SBIG('JZSH'),SBIG('5ISE'),SBIG('5BSE'),
|
||||
SBIG('5ATB'),SBIG('5ATA')
|
||||
namespace DataSpec::DNAParticle {
|
||||
static const std::vector<FourCC> GeneratorTypes = {
|
||||
SBIG('NODP'), SBIG('DEFS'), SBIG('CRTS'), SBIG('MTLS'), SBIG('GRAS'), SBIG('ICEE'), SBIG('GOOO'), SBIG('WODS'),
|
||||
SBIG('WATR'), SBIG('1MUD'), SBIG('1LAV'), SBIG('1SAN'), SBIG('1PRJ'), SBIG('DCHR'), SBIG('DCHS'), SBIG('DCSH'),
|
||||
SBIG('DENM'), SBIG('DESP'), SBIG('DESH'), SBIG('BTLE'), SBIG('WASP'), SBIG('TALP'), SBIG('PTGM'), SBIG('SPIR'),
|
||||
SBIG('FPIR'), SBIG('FFLE'), SBIG('PARA'), SBIG('BMON'), SBIG('BFLR'), SBIG('PBOS'), SBIG('IBOS'), SBIG('1SVA'),
|
||||
SBIG('1RPR'), SBIG('1MTR'), SBIG('1PDS'), SBIG('1FLB'), SBIG('1DRN'), SBIG('1MRE'), SBIG('CHOZ'), SBIG('JZAP'),
|
||||
SBIG('1ISE'), SBIG('1BSE'), SBIG('1ATB'), SBIG('1ATA'), SBIG('BTSP'), SBIG('WWSP'), SBIG('TASP'), SBIG('TGSP'),
|
||||
SBIG('SPSP'), SBIG('FPSP'), SBIG('FFSP'), SBIG('PSSP'), SBIG('BMSP'), SBIG('BFSP'), SBIG('PBSP'), SBIG('IBSP'),
|
||||
SBIG('2SVA'), SBIG('2RPR'), SBIG('2MTR'), SBIG('2PDS'), SBIG('2FLB'), SBIG('2DRN'), SBIG('2MRE'), SBIG('CHSP'),
|
||||
SBIG('JZSP'), SBIG('3ISE'), SBIG('3BSE'), SBIG('3ATB'), SBIG('3ATA'), SBIG('BTSH'), SBIG('WWSH'), SBIG('TASH'),
|
||||
SBIG('TGSH'), SBIG('SPSH'), SBIG('FPSH'), SBIG('FFSH'), SBIG('PSSH'), SBIG('BMSH'), SBIG('BFSH'), SBIG('PBSH'),
|
||||
SBIG('IBSH'), SBIG('3SVA'), SBIG('3RPR'), SBIG('3MTR'), SBIG('3PDS'), SBIG('3FLB'), SBIG('3DRN'), SBIG('3MRE'),
|
||||
SBIG('CHSH'), SBIG('JZSH'), SBIG('5ISE'), SBIG('5BSE'), SBIG('5ATB'), SBIG('5ATA')};
|
||||
|
||||
static const std::vector<FourCC> SFXTypes = {
|
||||
SBIG('DSFX'), SBIG('CSFX'), SBIG('MSFX'), SBIG('GRFX'), SBIG('NSFX'), SBIG('DSFX'), SBIG('CSFX'), SBIG('MSFX'),
|
||||
SBIG('GRFX'), SBIG('ICFX'), SBIG('GOFX'), SBIG('WSFX'), SBIG('WTFX'), SBIG('2MUD'), SBIG('2LAV'), SBIG('2SAN'),
|
||||
SBIG('2PRJ'), SBIG('DCFX'), SBIG('DSFX'), SBIG('DSHX'), SBIG('DEFX'), SBIG('ESFX'), SBIG('SHFX'), SBIG('BEFX'),
|
||||
SBIG('WWFX'), SBIG('TAFX'), SBIG('GTFX'), SBIG('SPFX'), SBIG('FPFX'), SBIG('FFFX'), SBIG('PAFX'), SBIG('BMFX'),
|
||||
SBIG('BFFX'), SBIG('PBFX'), SBIG('IBFX'), SBIG('4SVA'), SBIG('4RPR'), SBIG('4MTR'), SBIG('4PDS'), SBIG('4FLB'),
|
||||
SBIG('4DRN'), SBIG('4MRE'), SBIG('CZFX'), SBIG('JZAS'), SBIG('2ISE'), SBIG('2BSE'), SBIG('2ATB'), SBIG('2ATA'),
|
||||
SBIG('BSFX'), SBIG('WSFX'), SBIG('TSFX'), SBIG('GSFX'), SBIG('SSFX'), SBIG('FSFX'), SBIG('SFFX'), SBIG('PSFX'),
|
||||
SBIG('MSFX'), SBIG('SBFX'), SBIG('PBSX'), SBIG('IBSX'), SBIG('5SVA'), SBIG('5RPR'), SBIG('5MTR'), SBIG('5PDS'),
|
||||
SBIG('5FLB'), SBIG('5DRN'), SBIG('5MRE'), SBIG('CSFX'), SBIG('JZPS'), SBIG('4ISE'), SBIG('4BSE'), SBIG('4ATB'),
|
||||
SBIG('4ATA'), SBIG('BHFX'), SBIG('WHFX'), SBIG('THFX'), SBIG('GHFX'), SBIG('SHFX'), SBIG('FHFX'), SBIG('HFFX'),
|
||||
SBIG('PHFX'), SBIG('MHFX'), SBIG('HBFX'), SBIG('PBHX'), SBIG('IBHX'), SBIG('6SVA'), SBIG('6RPR'), SBIG('6MTR'),
|
||||
SBIG('6PDS'), SBIG('6FLB'), SBIG('6DRN'), SBIG('6MRE'), SBIG('CHFX'), SBIG('JZHS'), SBIG('6ISE'), SBIG('6BSE'),
|
||||
SBIG('6ATB'), SBIG('6ATA'),
|
||||
};
|
||||
|
||||
static const std::vector<FourCC> SFXTypes =
|
||||
{
|
||||
SBIG('DSFX'),SBIG('CSFX'),SBIG('MSFX'),SBIG('GRFX'),
|
||||
SBIG('NSFX'),SBIG('DSFX'),SBIG('CSFX'),SBIG('MSFX'),
|
||||
SBIG('GRFX'),SBIG('ICFX'),SBIG('GOFX'),SBIG('WSFX'),
|
||||
SBIG('WTFX'),SBIG('2MUD'),SBIG('2LAV'),SBIG('2SAN'),
|
||||
SBIG('2PRJ'),SBIG('DCFX'),SBIG('DSFX'),SBIG('DSHX'),
|
||||
SBIG('DEFX'),SBIG('ESFX'),SBIG('SHFX'),SBIG('BEFX'),
|
||||
SBIG('WWFX'),SBIG('TAFX'),SBIG('GTFX'),SBIG('SPFX'),
|
||||
SBIG('FPFX'),SBIG('FFFX'),SBIG('PAFX'),SBIG('BMFX'),
|
||||
SBIG('BFFX'),SBIG('PBFX'),SBIG('IBFX'),SBIG('4SVA'),
|
||||
SBIG('4RPR'),SBIG('4MTR'),SBIG('4PDS'),SBIG('4FLB'),
|
||||
SBIG('4DRN'),SBIG('4MRE'),SBIG('CZFX'),SBIG('JZAS'),
|
||||
SBIG('2ISE'),SBIG('2BSE'),SBIG('2ATB'),SBIG('2ATA'),
|
||||
SBIG('BSFX'),SBIG('WSFX'),SBIG('TSFX'),SBIG('GSFX'),
|
||||
SBIG('SSFX'),SBIG('FSFX'),SBIG('SFFX'),SBIG('PSFX'),
|
||||
SBIG('MSFX'),SBIG('SBFX'),SBIG('PBSX'),SBIG('IBSX'),
|
||||
SBIG('5SVA'),SBIG('5RPR'),SBIG('5MTR'),SBIG('5PDS'),
|
||||
SBIG('5FLB'),SBIG('5DRN'),SBIG('5MRE'),SBIG('CSFX'),
|
||||
SBIG('JZPS'),SBIG('4ISE'),SBIG('4BSE'),SBIG('4ATB'),
|
||||
SBIG('4ATA'),SBIG('BHFX'),SBIG('WHFX'),SBIG('THFX'),
|
||||
SBIG('GHFX'),SBIG('SHFX'),SBIG('FHFX'),SBIG('HFFX'),
|
||||
SBIG('PHFX'),SBIG('MHFX'),SBIG('HBFX'),SBIG('PBHX'),
|
||||
SBIG('IBHX'),SBIG('6SVA'),SBIG('6RPR'),SBIG('6MTR'),
|
||||
SBIG('6PDS'),SBIG('6FLB'),SBIG('6DRN'),SBIG('6MRE'),
|
||||
SBIG('CHFX'),SBIG('JZHS'),SBIG('6ISE'),SBIG('6BSE'),
|
||||
SBIG('6ATB'),SBIG('6ATA'),
|
||||
};
|
||||
|
||||
static const std::vector<FourCC> DecalTypes =
|
||||
{
|
||||
SBIG('NCDL'),SBIG('DDCL'),SBIG('CODL'),SBIG('MEDL'),
|
||||
SBIG('GRDL'),SBIG('ICDL'),SBIG('GODL'),SBIG('WODL'),
|
||||
SBIG('WTDL'),SBIG('3MUD'),SBIG('3LAV'),SBIG('3SAN'),
|
||||
SBIG('CHDL'),SBIG('ENDL')
|
||||
};
|
||||
static const std::vector<FourCC> DecalTypes = {SBIG('NCDL'), SBIG('DDCL'), SBIG('CODL'), SBIG('MEDL'), SBIG('GRDL'),
|
||||
SBIG('ICDL'), SBIG('GODL'), SBIG('WODL'), SBIG('WTDL'), SBIG('3MUD'),
|
||||
SBIG('3LAV'), SBIG('3SAN'), SBIG('CHDL'), SBIG('ENDL')};
|
||||
|
||||
template <>
|
||||
const char* CRSM<UniqueID32>::DNAType() { return "CRSM<UniqueID32>"; }
|
||||
const char* CRSM<UniqueID32>::DNAType() {
|
||||
return "CRSM<UniqueID32>";
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* CRSM<UniqueID64>::DNAType() { return "CRSM<UniqueID64>"; }
|
||||
|
||||
template <class IDType>
|
||||
void CRSM<IDType>::_read(athena::io::YAMLDocReader& r)
|
||||
{
|
||||
for (const auto& elem : r.getCurNode()->m_mapChildren)
|
||||
{
|
||||
if (elem.first.size() < 4)
|
||||
{
|
||||
LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto rec = r.enterSubRecord(elem.first.c_str()))
|
||||
{
|
||||
FourCC clsId(elem.first.c_str());
|
||||
auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(), [&clsId](const FourCC& other) -> bool{
|
||||
return clsId == other;
|
||||
});
|
||||
if (gen != GeneratorTypes.end())
|
||||
{
|
||||
x0_generators[clsId].read(r);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(), [&clsId](const FourCC& other) -> bool{
|
||||
return clsId == other;
|
||||
});
|
||||
if (sfx != SFXTypes.end())
|
||||
{
|
||||
x10_sfx[clsId] = r.readInt32(clsId.toString().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(), [&clsId](const FourCC& other) -> bool{
|
||||
return clsId == other;
|
||||
});
|
||||
if (decal != DecalTypes.end())
|
||||
{
|
||||
x20_decals[clsId].read(r);
|
||||
continue;
|
||||
}
|
||||
if (clsId == SBIG('RNGE'))
|
||||
x30_RNGE = r.readFloat(nullptr);
|
||||
else if (clsId == SBIG('FOFF'))
|
||||
x34_FOFF = r.readFloat(nullptr);
|
||||
}
|
||||
}
|
||||
const char* CRSM<UniqueID64>::DNAType() {
|
||||
return "CRSM<UniqueID64>";
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void CRSM<IDType>::_write(athena::io::YAMLDocWriter& w) const
|
||||
{
|
||||
for (const auto& pair : x0_generators)
|
||||
if (pair.second)
|
||||
if (auto rec = w.enterSubRecord(pair.first.toString().c_str()))
|
||||
pair.second.write(w);
|
||||
void CRSM<IDType>::_read(athena::io::YAMLDocReader& r) {
|
||||
for (const auto& elem : r.getCurNode()->m_mapChildren) {
|
||||
if (elem.first.size() < 4) {
|
||||
LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& pair : x10_sfx)
|
||||
if (pair.second != ~0)
|
||||
w.writeUint32(pair.first.toString().c_str(), pair.second);
|
||||
if (auto rec = r.enterSubRecord(elem.first.c_str())) {
|
||||
FourCC clsId(elem.first.c_str());
|
||||
auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(),
|
||||
[&clsId](const FourCC& other) -> bool { return clsId == other; });
|
||||
if (gen != GeneratorTypes.end()) {
|
||||
x0_generators[clsId].read(r);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto& pair : x20_decals)
|
||||
if (pair.second)
|
||||
if (auto rec = w.enterSubRecord(pair.first.toString().c_str()))
|
||||
pair.second.write(w);
|
||||
auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(),
|
||||
[&clsId](const FourCC& other) -> bool { return clsId == other; });
|
||||
if (sfx != SFXTypes.end()) {
|
||||
x10_sfx[clsId] = r.readInt32(clsId.toString().c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (x30_RNGE != 50.f)
|
||||
w.writeFloat("RNGE", x30_RNGE);
|
||||
if (x34_FOFF != 0.2f)
|
||||
w.writeFloat("FOFF", x34_FOFF);
|
||||
auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(),
|
||||
[&clsId](const FourCC& other) -> bool { return clsId == other; });
|
||||
if (decal != DecalTypes.end()) {
|
||||
x20_decals[clsId].read(r);
|
||||
continue;
|
||||
}
|
||||
if (clsId == SBIG('RNGE'))
|
||||
x30_RNGE = r.readFloat(nullptr);
|
||||
else if (clsId == SBIG('FOFF'))
|
||||
x34_FOFF = r.readFloat(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void CRSM<IDType>::_binarySize(size_t& __isz) const
|
||||
{
|
||||
__isz += 4;
|
||||
for (const auto& pair : x0_generators)
|
||||
{
|
||||
if (pair.second)
|
||||
{
|
||||
__isz += 4;
|
||||
pair.second.binarySize(__isz);
|
||||
}
|
||||
}
|
||||
for (const auto& pair : x10_sfx)
|
||||
{
|
||||
if (pair.second != ~0)
|
||||
__isz += 12;
|
||||
}
|
||||
void CRSM<IDType>::_write(athena::io::YAMLDocWriter& w) const {
|
||||
for (const auto& pair : x0_generators)
|
||||
if (pair.second)
|
||||
if (auto rec = w.enterSubRecord(pair.first.toString().c_str()))
|
||||
pair.second.write(w);
|
||||
|
||||
for (const auto& pair : x20_decals)
|
||||
{
|
||||
if (pair.second)
|
||||
{
|
||||
__isz += 4;
|
||||
pair.second.binarySize(__isz);
|
||||
}
|
||||
}
|
||||
for (const auto& pair : x10_sfx)
|
||||
if (pair.second != ~0)
|
||||
w.writeUint32(pair.first.toString().c_str(), pair.second);
|
||||
|
||||
if (x30_RNGE != 50.f)
|
||||
__isz += 12;
|
||||
if (x34_FOFF != 0.2f)
|
||||
__isz += 12;
|
||||
for (const auto& pair : x20_decals)
|
||||
if (pair.second)
|
||||
if (auto rec = w.enterSubRecord(pair.first.toString().c_str()))
|
||||
pair.second.write(w);
|
||||
|
||||
if (x30_RNGE != 50.f)
|
||||
w.writeFloat("RNGE", x30_RNGE);
|
||||
if (x34_FOFF != 0.2f)
|
||||
w.writeFloat("FOFF", x34_FOFF);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void CRSM<IDType>::_read(athena::io::IStreamReader &r)
|
||||
{
|
||||
uint32_t clsId;
|
||||
void CRSM<IDType>::_binarySize(size_t& __isz) const {
|
||||
__isz += 4;
|
||||
for (const auto& pair : x0_generators) {
|
||||
if (pair.second) {
|
||||
__isz += 4;
|
||||
pair.second.binarySize(__isz);
|
||||
}
|
||||
}
|
||||
for (const auto& pair : x10_sfx) {
|
||||
if (pair.second != ~0)
|
||||
__isz += 12;
|
||||
}
|
||||
|
||||
for (const auto& pair : x20_decals) {
|
||||
if (pair.second) {
|
||||
__isz += 4;
|
||||
pair.second.binarySize(__isz);
|
||||
}
|
||||
}
|
||||
|
||||
if (x30_RNGE != 50.f)
|
||||
__isz += 12;
|
||||
if (x34_FOFF != 0.2f)
|
||||
__isz += 12;
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void CRSM<IDType>::_read(athena::io::IStreamReader& r) {
|
||||
uint32_t clsId;
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
if (clsId != SBIG('CRSM')) {
|
||||
LogModule.report(logvisor::Warning, "non CRSM provided to CRSM parser");
|
||||
return;
|
||||
}
|
||||
|
||||
while (clsId != SBIG('_END')) {
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
if (clsId != SBIG('CRSM'))
|
||||
{
|
||||
LogModule.report(logvisor::Warning, "non CRSM provided to CRSM parser");
|
||||
return;
|
||||
auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(),
|
||||
[&clsId](const FourCC& other) -> bool { return clsId == other; });
|
||||
if (gen != GeneratorTypes.end()) {
|
||||
x0_generators[clsId].read(r);
|
||||
continue;
|
||||
}
|
||||
|
||||
while (clsId != SBIG('_END'))
|
||||
{
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(), [&clsId](const FourCC& other) -> bool{
|
||||
return clsId == other;
|
||||
});
|
||||
if (gen != GeneratorTypes.end())
|
||||
{
|
||||
x0_generators[clsId].read(r);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(), [&clsId](const FourCC& other) -> bool{
|
||||
return clsId == other;
|
||||
});
|
||||
if (sfx != SFXTypes.end())
|
||||
{
|
||||
uint32_t fcc;
|
||||
r.readBytesToBuf(&fcc, 4);
|
||||
if (fcc != SBIG('NONE'))
|
||||
x10_sfx[clsId] = r.readInt32Big();
|
||||
else
|
||||
x10_sfx[clsId] = ~0;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(), [&clsId](const FourCC& other) -> bool{
|
||||
return clsId == other;
|
||||
});
|
||||
if (decal != DecalTypes.end())
|
||||
{
|
||||
x20_decals[clsId].read(r);
|
||||
continue;
|
||||
}
|
||||
if (clsId == SBIG('RNGE'))
|
||||
{
|
||||
r.readUint32();
|
||||
x30_RNGE = r.readFloatBig();
|
||||
continue;
|
||||
}
|
||||
if (clsId == SBIG('FOFF'))
|
||||
{
|
||||
r.readUint32();
|
||||
x34_FOFF = r.readFloatBig();
|
||||
continue;
|
||||
}
|
||||
if (clsId != SBIG('_END'))
|
||||
LogModule.report(logvisor::Fatal, "Unknown CRSM class %.4s @%" PRIi64, &clsId, r.position());
|
||||
auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(),
|
||||
[&clsId](const FourCC& other) -> bool { return clsId == other; });
|
||||
if (sfx != SFXTypes.end()) {
|
||||
uint32_t fcc;
|
||||
r.readBytesToBuf(&fcc, 4);
|
||||
if (fcc != SBIG('NONE'))
|
||||
x10_sfx[clsId] = r.readInt32Big();
|
||||
else
|
||||
x10_sfx[clsId] = ~0;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(),
|
||||
[&clsId](const FourCC& other) -> bool { return clsId == other; });
|
||||
if (decal != DecalTypes.end()) {
|
||||
x20_decals[clsId].read(r);
|
||||
continue;
|
||||
}
|
||||
if (clsId == SBIG('RNGE')) {
|
||||
r.readUint32();
|
||||
x30_RNGE = r.readFloatBig();
|
||||
continue;
|
||||
}
|
||||
if (clsId == SBIG('FOFF')) {
|
||||
r.readUint32();
|
||||
x34_FOFF = r.readFloatBig();
|
||||
continue;
|
||||
}
|
||||
if (clsId != SBIG('_END'))
|
||||
LogModule.report(logvisor::Fatal, "Unknown CRSM class %.4s @%" PRIi64, &clsId, r.position());
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void CRSM<IDType>::_write(athena::io::IStreamWriter& w) const
|
||||
{
|
||||
w.writeBytes("CRSM", 4);
|
||||
for (const auto& pair : x0_generators)
|
||||
{
|
||||
w.writeBytes(pair.first.getChars(), 4);
|
||||
pair.second.write(w);
|
||||
}
|
||||
void CRSM<IDType>::_write(athena::io::IStreamWriter& w) const {
|
||||
w.writeBytes("CRSM", 4);
|
||||
for (const auto& pair : x0_generators) {
|
||||
w.writeBytes(pair.first.getChars(), 4);
|
||||
pair.second.write(w);
|
||||
}
|
||||
|
||||
for (const auto& pair : x10_sfx)
|
||||
{
|
||||
w.writeBytes(pair.first.getChars(), 4);
|
||||
if (pair.second != ~0)
|
||||
{
|
||||
w.writeBytes("CNST", 4);
|
||||
w.writeUint32Big(pair.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
w.writeBytes("NONE", 4);
|
||||
}
|
||||
for (const auto& pair : x10_sfx) {
|
||||
w.writeBytes(pair.first.getChars(), 4);
|
||||
if (pair.second != ~0) {
|
||||
w.writeBytes("CNST", 4);
|
||||
w.writeUint32Big(pair.second);
|
||||
} else {
|
||||
w.writeBytes("NONE", 4);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& pair : x20_decals)
|
||||
{
|
||||
w.writeBytes(pair.first.getChars(), 4);
|
||||
pair.second.write(w);
|
||||
}
|
||||
for (const auto& pair : x20_decals) {
|
||||
w.writeBytes(pair.first.getChars(), 4);
|
||||
pair.second.write(w);
|
||||
}
|
||||
|
||||
if (x30_RNGE != 50.f)
|
||||
{
|
||||
w.writeBytes("RNGECNST", 8);
|
||||
w.writeFloatBig(x30_RNGE);
|
||||
}
|
||||
if (x34_FOFF != 0.2f)
|
||||
{
|
||||
w.writeBytes("FOFFCNST", 8);
|
||||
w.writeFloatBig(x34_FOFF);
|
||||
}
|
||||
w.writeBytes("_END", 4);
|
||||
if (x30_RNGE != 50.f) {
|
||||
w.writeBytes("RNGECNST", 8);
|
||||
w.writeFloatBig(x30_RNGE);
|
||||
}
|
||||
if (x34_FOFF != 0.2f) {
|
||||
w.writeBytes("FOFFCNST", 8);
|
||||
w.writeFloatBig(x34_FOFF);
|
||||
}
|
||||
w.writeBytes("_END", 4);
|
||||
}
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(CRSM<UniqueID32>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(CRSM<UniqueID64>)
|
||||
|
||||
template <class IDType>
|
||||
void CRSM<IDType>::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const
|
||||
{
|
||||
for (const auto& p : x0_generators)
|
||||
g_curSpec->flattenDependencies(p.second.id, pathsOut);
|
||||
for (const auto& p : x20_decals)
|
||||
g_curSpec->flattenDependencies(p.second.id, pathsOut);
|
||||
void CRSM<IDType>::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
||||
for (const auto& p : x0_generators)
|
||||
g_curSpec->flattenDependencies(p.second.id, pathsOut);
|
||||
for (const auto& p : x20_decals)
|
||||
g_curSpec->flattenDependencies(p.second.id, pathsOut);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
CRSM<IDType>::CRSM()
|
||||
: x30_RNGE(50.f),
|
||||
x34_FOFF(0.2f)
|
||||
{
|
||||
for (const auto& sfx : SFXTypes)
|
||||
x10_sfx[sfx] = ~0;
|
||||
CRSM<IDType>::CRSM() : x30_RNGE(50.f), x34_FOFF(0.2f) {
|
||||
for (const auto& sfx : SFXTypes)
|
||||
x10_sfx[sfx] = ~0;
|
||||
}
|
||||
|
||||
template struct CRSM<UniqueID32>;
|
||||
template struct CRSM<UniqueID64>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen())
|
||||
{
|
||||
CRSM<IDType> crsm;
|
||||
crsm.read(rs);
|
||||
athena::io::ToYAMLStream(crsm, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen()) {
|
||||
CRSM<IDType> crsm;
|
||||
crsm.read(rs);
|
||||
athena::io::ToYAMLStream(crsm, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template bool ExtractCRSM<UniqueID32>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
template bool ExtractCRSM<UniqueID64>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
||||
template <class IDType>
|
||||
bool WriteCRSM(const CRSM<IDType>& crsm, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
crsm.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
bool WriteCRSM(const CRSM<IDType>& crsm, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
crsm.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
template bool WriteCRSM<UniqueID32>(const CRSM<UniqueID32>& crsm, const hecl::ProjectPath& outPath);
|
||||
template bool WriteCRSM<UniqueID64>(const CRSM<UniqueID64>& crsm, const hecl::ProjectPath& outPath);
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
|
@ -5,26 +5,24 @@
|
|||
#include "athena/FileWriter.hpp"
|
||||
#include "optional.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle
|
||||
{
|
||||
namespace DataSpec::DNAParticle {
|
||||
template <class IDType>
|
||||
struct CRSM : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
std::unordered_map<FourCC, ChildResourceFactory<IDType>> x0_generators;
|
||||
std::unordered_map<FourCC, uint32_t> x10_sfx;
|
||||
std::unordered_map<FourCC, ChildResourceFactory<IDType>> x20_decals;
|
||||
float x30_RNGE;
|
||||
float x34_FOFF;
|
||||
struct CRSM : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
std::unordered_map<FourCC, ChildResourceFactory<IDType>> x0_generators;
|
||||
std::unordered_map<FourCC, uint32_t> x10_sfx;
|
||||
std::unordered_map<FourCC, ChildResourceFactory<IDType>> x20_decals;
|
||||
float x30_RNGE;
|
||||
float x34_FOFF;
|
||||
|
||||
CRSM();
|
||||
CRSM();
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
};
|
||||
template <class IDType>
|
||||
bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
||||
template <class IDType>
|
||||
bool WriteCRSM(const CRSM<IDType>& crsm, const hecl::ProjectPath& outPath);
|
||||
}
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
|
@ -3,39 +3,35 @@
|
|||
#include "athena/FileWriter.hpp"
|
||||
#include "DGRP.hpp"
|
||||
|
||||
namespace DataSpec::DNADGRP
|
||||
{
|
||||
namespace DataSpec::DNADGRP {
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractDGRP(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen())
|
||||
{
|
||||
DGRP<IDType> dgrp;
|
||||
dgrp.read(rs);
|
||||
athena::io::ToYAMLStream(dgrp, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool ExtractDGRP(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen()) {
|
||||
DGRP<IDType> dgrp;
|
||||
dgrp.read(rs);
|
||||
athena::io::ToYAMLStream(dgrp, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template bool ExtractDGRP<UniqueID32>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
template bool ExtractDGRP<UniqueID64>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
||||
template <class IDType>
|
||||
bool WriteDGRP(const DGRP<IDType>& dgrp, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
dgrp.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
bool WriteDGRP(const DGRP<IDType>& dgrp, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
dgrp.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
template bool WriteDGRP<UniqueID32>(const DGRP<UniqueID32>& dgrp, const hecl::ProjectPath& outPath);
|
||||
template bool WriteDGRP<UniqueID64>(const DGRP<UniqueID64>& dgrp, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNADGRP
|
||||
|
|
|
@ -3,41 +3,36 @@
|
|||
#include "DNACommon.hpp"
|
||||
#include "PAK.hpp"
|
||||
|
||||
namespace DataSpec::DNADGRP
|
||||
{
|
||||
namespace DataSpec::DNADGRP {
|
||||
|
||||
template <class IDType>
|
||||
struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) DGRP : BigDNA
|
||||
{
|
||||
struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) DGRP : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> dependCount;
|
||||
struct ObjectTag : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> dependCount;
|
||||
struct ObjectTag : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
DNAFourCC type;
|
||||
Value<IDType> id;
|
||||
DNAFourCC type;
|
||||
Value<IDType> id;
|
||||
|
||||
bool validate() const
|
||||
{
|
||||
if (!id.operator bool())
|
||||
return false;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id);
|
||||
return path && !path.isNone();
|
||||
}
|
||||
};
|
||||
|
||||
Vector<ObjectTag, AT_DNA_COUNT(dependCount)> depends;
|
||||
|
||||
void validateDeps()
|
||||
{
|
||||
std::vector<ObjectTag> newDeps;
|
||||
newDeps.reserve(depends.size());
|
||||
for (const ObjectTag& tag : depends)
|
||||
if (tag.validate())
|
||||
newDeps.push_back(tag);
|
||||
depends = std::move(newDeps);
|
||||
dependCount = atUint32(depends.size());
|
||||
bool validate() const {
|
||||
if (!id.operator bool())
|
||||
return false;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id);
|
||||
return path && !path.isNone();
|
||||
}
|
||||
};
|
||||
|
||||
Vector<ObjectTag, AT_DNA_COUNT(dependCount)> depends;
|
||||
|
||||
void validateDeps() {
|
||||
std::vector<ObjectTag> newDeps;
|
||||
newDeps.reserve(depends.size());
|
||||
for (const ObjectTag& tag : depends)
|
||||
if (tag.validate())
|
||||
newDeps.push_back(tag);
|
||||
depends = std::move(newDeps);
|
||||
dependCount = atUint32(depends.size());
|
||||
}
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
|
@ -45,5 +40,4 @@ bool ExtractDGRP(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
|||
template <class IDType>
|
||||
bool WriteDGRP(const DGRP<IDType>& dgrp, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNADGRP
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
#include "PAK.hpp"
|
||||
#include "boo/ThreadLocalPtr.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
logvisor::Module LogDNACommon("urde::DNACommon");
|
||||
ThreadLocalPtr<SpecBase> g_curSpec;
|
||||
|
@ -16,305 +15,270 @@ ThreadLocalPtr<IDRestorer<UniqueID128>> UniqueIDBridge::s_restorer128;
|
|||
UniqueID32 UniqueID32::kInvalidId;
|
||||
|
||||
template <class IDType>
|
||||
hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const IDType& id, bool silenceWarnings)
|
||||
{
|
||||
/* Try PAKRouter first (only available at extract) */
|
||||
PAKRouterBase* pakRouter = g_PakRouter.get();
|
||||
if (pakRouter)
|
||||
{
|
||||
hecl::ProjectPath path = pakRouter->getWorking(id, silenceWarnings);
|
||||
if (path)
|
||||
return path;
|
||||
}
|
||||
hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const IDType& id, bool silenceWarnings) {
|
||||
/* Try PAKRouter first (only available at extract) */
|
||||
PAKRouterBase* pakRouter = g_PakRouter.get();
|
||||
if (pakRouter) {
|
||||
hecl::ProjectPath path = pakRouter->getWorking(id, silenceWarnings);
|
||||
if (path)
|
||||
return path;
|
||||
}
|
||||
|
||||
/* Try project cache second (populated with paths read from YAML resources) */
|
||||
hecl::Database::Project* project = s_Project.get();
|
||||
if (!project)
|
||||
{
|
||||
if (pakRouter)
|
||||
{
|
||||
if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id)
|
||||
LogDNACommon.report(logvisor::Warning,
|
||||
"unable to translate %s to path", id.toString().c_str());
|
||||
return {};
|
||||
}
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
"g_PakRouter or s_Project must be set to non-null before "
|
||||
"calling UniqueIDBridge::TranslatePakIdToPath");
|
||||
return {};
|
||||
/* Try project cache second (populated with paths read from YAML resources) */
|
||||
hecl::Database::Project* project = s_Project.get();
|
||||
if (!project) {
|
||||
if (pakRouter) {
|
||||
if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id)
|
||||
LogDNACommon.report(logvisor::Warning, "unable to translate %s to path", id.toString().c_str());
|
||||
return {};
|
||||
}
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
"g_PakRouter or s_Project must be set to non-null before "
|
||||
"calling UniqueIDBridge::TranslatePakIdToPath");
|
||||
return {};
|
||||
}
|
||||
|
||||
const hecl::ProjectPath* search = project->lookupBridgePath(id.toUint64());
|
||||
if (!search)
|
||||
{
|
||||
if (IDRestorer<IDType>* restorer = GetIDRestorer<IDType>())
|
||||
if (IDType newId = restorer->originalToNew(id))
|
||||
if (const hecl::ProjectPath* newSearch = project->lookupBridgePath(newId.toUint64()))
|
||||
return *newSearch;
|
||||
if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id)
|
||||
LogDNACommon.report(logvisor::Warning,
|
||||
"unable to translate %s to path", id.toString().c_str());
|
||||
return {};
|
||||
}
|
||||
return *search;
|
||||
const hecl::ProjectPath* search = project->lookupBridgePath(id.toUint64());
|
||||
if (!search) {
|
||||
if (IDRestorer<IDType>* restorer = GetIDRestorer<IDType>())
|
||||
if (IDType newId = restorer->originalToNew(id))
|
||||
if (const hecl::ProjectPath* newSearch = project->lookupBridgePath(newId.toUint64()))
|
||||
return *newSearch;
|
||||
if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id)
|
||||
LogDNACommon.report(logvisor::Warning, "unable to translate %s to path", id.toString().c_str());
|
||||
return {};
|
||||
}
|
||||
return *search;
|
||||
}
|
||||
template
|
||||
hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID32& id, bool silenceWarnings);
|
||||
template
|
||||
hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID64& id, bool silenceWarnings);
|
||||
template
|
||||
hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID128& id, bool silenceWarnings);
|
||||
template hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID32& id, bool silenceWarnings);
|
||||
template hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID64& id, bool silenceWarnings);
|
||||
template hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID128& id, bool silenceWarnings);
|
||||
|
||||
template <class IDType>
|
||||
hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str)
|
||||
{
|
||||
if (str.empty())
|
||||
return {};
|
||||
hecl::Database::Project* project = s_Project.get();
|
||||
if (!project)
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
"UniqueIDBridge::setGlobalProject must be called before MakePathFromString");
|
||||
hecl::ProjectPath path = hecl::ProjectPath(*project, str);
|
||||
project->addBridgePathToCache(IDType(path).toUint64(), path);
|
||||
return path;
|
||||
hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str) {
|
||||
if (str.empty())
|
||||
return {};
|
||||
hecl::Database::Project* project = s_Project.get();
|
||||
if (!project)
|
||||
LogDNACommon.report(logvisor::Fatal, "UniqueIDBridge::setGlobalProject must be called before MakePathFromString");
|
||||
hecl::ProjectPath path = hecl::ProjectPath(*project, str);
|
||||
project->addBridgePathToCache(IDType(path).toUint64(), path);
|
||||
return path;
|
||||
}
|
||||
template
|
||||
hecl::ProjectPath UniqueIDBridge::MakePathFromString<UniqueID32>(std::string_view str);
|
||||
template
|
||||
hecl::ProjectPath UniqueIDBridge::MakePathFromString<UniqueID64>(std::string_view str);
|
||||
template hecl::ProjectPath UniqueIDBridge::MakePathFromString<UniqueID32>(std::string_view str);
|
||||
template hecl::ProjectPath UniqueIDBridge::MakePathFromString<UniqueID64>(std::string_view str);
|
||||
|
||||
template <class IDType>
|
||||
void UniqueIDBridge::TransformOldHashToNewHash(IDType& id)
|
||||
{
|
||||
id = TranslatePakIdToPath(id);
|
||||
void UniqueIDBridge::TransformOldHashToNewHash(IDType& id) {
|
||||
id = TranslatePakIdToPath(id);
|
||||
}
|
||||
template
|
||||
void UniqueIDBridge::TransformOldHashToNewHash(UniqueID32& id);
|
||||
template
|
||||
void UniqueIDBridge::TransformOldHashToNewHash(UniqueID64& id);
|
||||
template void UniqueIDBridge::TransformOldHashToNewHash(UniqueID32& id);
|
||||
template void UniqueIDBridge::TransformOldHashToNewHash(UniqueID64& id);
|
||||
|
||||
void UniqueIDBridge::SetThreadProject(hecl::Database::Project& project)
|
||||
{
|
||||
s_Project.reset(&project);
|
||||
}
|
||||
void UniqueIDBridge::SetThreadProject(hecl::Database::Project& project) { s_Project.reset(&project); }
|
||||
|
||||
/** PAK 32-bit Unique ID */
|
||||
void UniqueID32::assign(uint32_t id, bool noOriginal)
|
||||
{
|
||||
m_id = id ? id : 0xffffffff;
|
||||
if (!noOriginal)
|
||||
if (IDRestorer<UniqueID32>* restorer = UniqueIDBridge::GetIDRestorer<UniqueID32>())
|
||||
if (UniqueID32 origId = restorer->newToOriginal(*this))
|
||||
*this = origId;
|
||||
void UniqueID32::assign(uint32_t id, bool noOriginal) {
|
||||
m_id = id ? id : 0xffffffff;
|
||||
if (!noOriginal)
|
||||
if (IDRestorer<UniqueID32>* restorer = UniqueIDBridge::GetIDRestorer<UniqueID32>())
|
||||
if (UniqueID32 origId = restorer->newToOriginal(*this))
|
||||
*this = origId;
|
||||
}
|
||||
|
||||
template <>
|
||||
void UniqueID32::Enumerate<BigDNA::Read>(typename Read::StreamT& reader)
|
||||
{assign(reader.readUint32Big());}
|
||||
template <>
|
||||
void UniqueID32::Enumerate<BigDNA::Write>(typename Write::StreamT& writer)
|
||||
{writer.writeUint32Big(m_id);}
|
||||
template <>
|
||||
void UniqueID32::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader)
|
||||
{
|
||||
*this = UniqueIDBridge::MakePathFromString<UniqueID32>(reader.readString(nullptr));
|
||||
void UniqueID32::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
||||
assign(reader.readUint32Big());
|
||||
}
|
||||
template <>
|
||||
void UniqueID32::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer)
|
||||
{
|
||||
if (!operator bool())
|
||||
return;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this);
|
||||
if (!path)
|
||||
return;
|
||||
writer.writeString(nullptr, path.getAuxInfo().size() ?
|
||||
(std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) :
|
||||
path.getRelativePathUTF8());
|
||||
void UniqueID32::Enumerate<BigDNA::Write>(typename Write::StreamT& writer) {
|
||||
writer.writeUint32Big(m_id);
|
||||
}
|
||||
template <>
|
||||
void UniqueID32::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
|
||||
{s += 4;}
|
||||
void UniqueID32::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader) {
|
||||
*this = UniqueIDBridge::MakePathFromString<UniqueID32>(reader.readString(nullptr));
|
||||
}
|
||||
template <>
|
||||
void UniqueID32::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer) {
|
||||
if (!operator bool())
|
||||
return;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this);
|
||||
if (!path)
|
||||
return;
|
||||
writer.writeString(nullptr, path.getAuxInfo().size()
|
||||
? (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data())
|
||||
: path.getRelativePathUTF8());
|
||||
}
|
||||
template <>
|
||||
void UniqueID32::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) {
|
||||
s += 4;
|
||||
}
|
||||
|
||||
std::string UniqueID32::toString() const
|
||||
{
|
||||
char buf[9];
|
||||
snprintf(buf, 9, "%08X", m_id);
|
||||
return std::string(buf);
|
||||
std::string UniqueID32::toString() const {
|
||||
char buf[9];
|
||||
snprintf(buf, 9, "%08X", m_id);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
template <>
|
||||
void UniqueID32Zero::Enumerate<BigDNA::Read>(typename Read::StreamT& reader)
|
||||
{UniqueID32::Enumerate<BigDNA::Read>(reader);}
|
||||
void UniqueID32Zero::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
||||
UniqueID32::Enumerate<BigDNA::Read>(reader);
|
||||
}
|
||||
template <>
|
||||
void UniqueID32Zero::Enumerate<BigDNA::Write>(typename Write::StreamT& writer)
|
||||
{writer.writeUint32Big(*this ? m_id : 0);}
|
||||
void UniqueID32Zero::Enumerate<BigDNA::Write>(typename Write::StreamT& writer) {
|
||||
writer.writeUint32Big(*this ? m_id : 0);
|
||||
}
|
||||
template <>
|
||||
void UniqueID32Zero::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader)
|
||||
{UniqueID32::Enumerate<BigDNA::ReadYaml>(reader);}
|
||||
void UniqueID32Zero::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader) {
|
||||
UniqueID32::Enumerate<BigDNA::ReadYaml>(reader);
|
||||
}
|
||||
template <>
|
||||
void UniqueID32Zero::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer)
|
||||
{UniqueID32::Enumerate<BigDNA::WriteYaml>(writer);}
|
||||
void UniqueID32Zero::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer) {
|
||||
UniqueID32::Enumerate<BigDNA::WriteYaml>(writer);
|
||||
}
|
||||
template <>
|
||||
void UniqueID32Zero::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
|
||||
{UniqueID32::Enumerate<BigDNA::BinarySize>(s);}
|
||||
|
||||
AuxiliaryID32& AuxiliaryID32::operator=(const hecl::ProjectPath& path)
|
||||
{
|
||||
assign(path.ensureAuxInfo(m_auxStr).hash().val32());
|
||||
return *this;
|
||||
void UniqueID32Zero::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) {
|
||||
UniqueID32::Enumerate<BigDNA::BinarySize>(s);
|
||||
}
|
||||
|
||||
AuxiliaryID32& AuxiliaryID32::operator=(const UniqueID32& id)
|
||||
{
|
||||
m_baseId = id;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id);
|
||||
if (path)
|
||||
{
|
||||
if (m_addExtension)
|
||||
path = path.getWithExtension(m_addExtension);
|
||||
*this = path;
|
||||
}
|
||||
return *this;
|
||||
AuxiliaryID32& AuxiliaryID32::operator=(const hecl::ProjectPath& path) {
|
||||
assign(path.ensureAuxInfo(m_auxStr).hash().val32());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <>
|
||||
void AuxiliaryID32::Enumerate<BigDNA::Read>(typename Read::StreamT& reader)
|
||||
{
|
||||
assign(reader.readUint32Big());
|
||||
m_baseId = *this;
|
||||
}
|
||||
template <>
|
||||
void AuxiliaryID32::Enumerate<BigDNA::Write>(typename Write::StreamT& writer)
|
||||
{
|
||||
writer.writeUint32Big(m_id);
|
||||
}
|
||||
template <>
|
||||
void AuxiliaryID32::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader)
|
||||
{
|
||||
hecl::ProjectPath readPath = UniqueIDBridge::MakePathFromString<UniqueID32>(reader.readString(nullptr));
|
||||
*this = readPath.ensureAuxInfo(m_auxStr);
|
||||
}
|
||||
template <>
|
||||
void AuxiliaryID32::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer)
|
||||
{
|
||||
if (!operator bool())
|
||||
return;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath<UniqueID32>(*this, true);
|
||||
if (!path)
|
||||
path = UniqueIDBridge::TranslatePakIdToPath(m_baseId);
|
||||
if (!path)
|
||||
return;
|
||||
AuxiliaryID32& AuxiliaryID32::operator=(const UniqueID32& id) {
|
||||
m_baseId = id;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id);
|
||||
if (path) {
|
||||
if (m_addExtension)
|
||||
path = path.getWithExtension(m_addExtension);
|
||||
hecl::SystemUTF8Conv ufx8AuxStr(m_auxStr);
|
||||
writer.writeString(nullptr, std::string(path.getRelativePathUTF8()) + '|' + ufx8AuxStr);
|
||||
path = path.getWithExtension(m_addExtension);
|
||||
*this = path;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <>
|
||||
void AuxiliaryID32::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
||||
assign(reader.readUint32Big());
|
||||
m_baseId = *this;
|
||||
}
|
||||
template <>
|
||||
void AuxiliaryID32::Enumerate<BigDNA::Write>(typename Write::StreamT& writer) {
|
||||
writer.writeUint32Big(m_id);
|
||||
}
|
||||
template <>
|
||||
void AuxiliaryID32::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader) {
|
||||
hecl::ProjectPath readPath = UniqueIDBridge::MakePathFromString<UniqueID32>(reader.readString(nullptr));
|
||||
*this = readPath.ensureAuxInfo(m_auxStr);
|
||||
}
|
||||
template <>
|
||||
void AuxiliaryID32::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer) {
|
||||
if (!operator bool())
|
||||
return;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath<UniqueID32>(*this, true);
|
||||
if (!path)
|
||||
path = UniqueIDBridge::TranslatePakIdToPath(m_baseId);
|
||||
if (!path)
|
||||
return;
|
||||
if (m_addExtension)
|
||||
path = path.getWithExtension(m_addExtension);
|
||||
hecl::SystemUTF8Conv ufx8AuxStr(m_auxStr);
|
||||
writer.writeString(nullptr, std::string(path.getRelativePathUTF8()) + '|' + ufx8AuxStr);
|
||||
}
|
||||
|
||||
/** PAK 64-bit Unique ID */
|
||||
void UniqueID64::assign(uint64_t id, bool noOriginal)
|
||||
{
|
||||
m_id = id ? id : 0xffffffffffffffff;
|
||||
if (!noOriginal)
|
||||
if (IDRestorer<UniqueID64>* restorer = UniqueIDBridge::GetIDRestorer<UniqueID64>())
|
||||
if (UniqueID64 origId = restorer->newToOriginal(*this))
|
||||
*this = origId;
|
||||
void UniqueID64::assign(uint64_t id, bool noOriginal) {
|
||||
m_id = id ? id : 0xffffffffffffffff;
|
||||
if (!noOriginal)
|
||||
if (IDRestorer<UniqueID64>* restorer = UniqueIDBridge::GetIDRestorer<UniqueID64>())
|
||||
if (UniqueID64 origId = restorer->newToOriginal(*this))
|
||||
*this = origId;
|
||||
}
|
||||
|
||||
template <>
|
||||
void UniqueID64::Enumerate<BigDNA::Read>(typename Read::StreamT& reader)
|
||||
{assign(reader.readUint64Big());}
|
||||
template <>
|
||||
void UniqueID64::Enumerate<BigDNA::Write>(typename Write::StreamT& writer)
|
||||
{writer.writeUint64Big(m_id);}
|
||||
template <>
|
||||
void UniqueID64::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader)
|
||||
{
|
||||
*this = UniqueIDBridge::MakePathFromString<UniqueID64>(reader.readString(nullptr));
|
||||
void UniqueID64::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
||||
assign(reader.readUint64Big());
|
||||
}
|
||||
template <>
|
||||
void UniqueID64::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer)
|
||||
{
|
||||
if (!operator bool())
|
||||
return;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this);
|
||||
if (!path)
|
||||
return;
|
||||
writer.writeString(nullptr, path.getAuxInfo().size() ?
|
||||
(std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) :
|
||||
path.getRelativePathUTF8());
|
||||
void UniqueID64::Enumerate<BigDNA::Write>(typename Write::StreamT& writer) {
|
||||
writer.writeUint64Big(m_id);
|
||||
}
|
||||
template <>
|
||||
void UniqueID64::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
|
||||
{s += 8;}
|
||||
void UniqueID64::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader) {
|
||||
*this = UniqueIDBridge::MakePathFromString<UniqueID64>(reader.readString(nullptr));
|
||||
}
|
||||
template <>
|
||||
void UniqueID64::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer) {
|
||||
if (!operator bool())
|
||||
return;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this);
|
||||
if (!path)
|
||||
return;
|
||||
writer.writeString(nullptr, path.getAuxInfo().size()
|
||||
? (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data())
|
||||
: path.getRelativePathUTF8());
|
||||
}
|
||||
template <>
|
||||
void UniqueID64::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) {
|
||||
s += 8;
|
||||
}
|
||||
|
||||
std::string UniqueID64::toString() const
|
||||
{
|
||||
char buf[17];
|
||||
snprintf(buf, 17, "%016" PRIX64, m_id);
|
||||
return std::string(buf);
|
||||
std::string UniqueID64::toString() const {
|
||||
char buf[17];
|
||||
snprintf(buf, 17, "%016" PRIX64, m_id);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
/** PAK 128-bit Unique ID */
|
||||
template <>
|
||||
void UniqueID128::Enumerate<BigDNA::Read>(typename Read::StreamT& reader)
|
||||
{
|
||||
m_id.id[0] = reader.readUint64Big();
|
||||
m_id.id[1] = reader.readUint64Big();
|
||||
void UniqueID128::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
||||
m_id.id[0] = reader.readUint64Big();
|
||||
m_id.id[1] = reader.readUint64Big();
|
||||
}
|
||||
template <>
|
||||
void UniqueID128::Enumerate<BigDNA::Write>(typename Write::StreamT& writer)
|
||||
{
|
||||
writer.writeUint64Big(m_id.id[0]);
|
||||
writer.writeUint64Big(m_id.id[1]);
|
||||
void UniqueID128::Enumerate<BigDNA::Write>(typename Write::StreamT& writer) {
|
||||
writer.writeUint64Big(m_id.id[0]);
|
||||
writer.writeUint64Big(m_id.id[1]);
|
||||
}
|
||||
template <>
|
||||
void UniqueID128::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader)
|
||||
{
|
||||
*this = UniqueIDBridge::MakePathFromString<UniqueID128>(reader.readString(nullptr));
|
||||
void UniqueID128::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& reader) {
|
||||
*this = UniqueIDBridge::MakePathFromString<UniqueID128>(reader.readString(nullptr));
|
||||
}
|
||||
template <>
|
||||
void UniqueID128::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer)
|
||||
{
|
||||
if (!operator bool())
|
||||
return;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this);
|
||||
if (!path)
|
||||
return;
|
||||
writer.writeString(nullptr, path.getAuxInfo().size() ?
|
||||
(std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) :
|
||||
path.getRelativePathUTF8());
|
||||
void UniqueID128::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& writer) {
|
||||
if (!operator bool())
|
||||
return;
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this);
|
||||
if (!path)
|
||||
return;
|
||||
writer.writeString(nullptr, path.getAuxInfo().size()
|
||||
? (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data())
|
||||
: path.getRelativePathUTF8());
|
||||
}
|
||||
template <>
|
||||
void UniqueID128::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
|
||||
{s += 16;}
|
||||
|
||||
std::string UniqueID128::toString() const
|
||||
{
|
||||
char buf[33];
|
||||
snprintf(buf, 33, "%016" PRIX64 "%016" PRIX64, m_id.id[0], m_id.id[1]);
|
||||
return std::string(buf);
|
||||
void UniqueID128::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) {
|
||||
s += 16;
|
||||
}
|
||||
|
||||
std::string UniqueID128::toString() const {
|
||||
char buf[33];
|
||||
snprintf(buf, 33, "%016" PRIX64 "%016" PRIX64, m_id.id[0], m_id.id[1]);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
/** Word Bitmap reader/writer */
|
||||
void WordBitmap::read(athena::io::IStreamReader& reader, size_t bitCount)
|
||||
{
|
||||
m_bitCount = bitCount;
|
||||
size_t wordCount = (bitCount + 31) / 32;
|
||||
m_words.clear();
|
||||
m_words.reserve(wordCount);
|
||||
for (size_t w=0 ; w<wordCount ; ++w)
|
||||
m_words.push_back(reader.readUint32Big());
|
||||
void WordBitmap::read(athena::io::IStreamReader& reader, size_t bitCount) {
|
||||
m_bitCount = bitCount;
|
||||
size_t wordCount = (bitCount + 31) / 32;
|
||||
m_words.clear();
|
||||
m_words.reserve(wordCount);
|
||||
for (size_t w = 0; w < wordCount; ++w)
|
||||
m_words.push_back(reader.readUint32Big());
|
||||
}
|
||||
void WordBitmap::write(athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
for (atUint32 word : m_words)
|
||||
writer.writeUint32Big(word);
|
||||
}
|
||||
void WordBitmap::binarySize(size_t& __isz) const
|
||||
{
|
||||
__isz += m_words.size() * 4;
|
||||
void WordBitmap::write(athena::io::IStreamWriter& writer) const {
|
||||
for (atUint32 word : m_words)
|
||||
writer.writeUint32Big(word);
|
||||
}
|
||||
void WordBitmap::binarySize(size_t& __isz) const { __isz += m_words.size() * 4; }
|
||||
|
||||
}
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
#include "boo/ThreadLocalPtr.hpp"
|
||||
#include "zeus/CColor.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
struct SpecBase;
|
||||
|
||||
extern logvisor::Module LogDNACommon;
|
||||
|
@ -25,43 +24,46 @@ typedef athena::io::DNAVYaml<athena::Big> BigDNAVYaml;
|
|||
/** FourCC with DNA read/write */
|
||||
using DNAFourCC = hecl::DNAFourCC;
|
||||
|
||||
class DNAColor final : public BigDNA, public zeus::CColor
|
||||
{
|
||||
class DNAColor final : public BigDNA, public zeus::CColor {
|
||||
public:
|
||||
DNAColor() = default;
|
||||
DNAColor(const zeus::CColor& color) : zeus::CColor(color) {}
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
DNAColor() = default;
|
||||
DNAColor(const zeus::CColor& color) : zeus::CColor(color) {}
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
};
|
||||
template <> inline void DNAColor::Enumerate<BigDNA::Read>(typename Read::StreamT& _r)
|
||||
{ zeus::CColor::readRGBABig(_r); }
|
||||
template <> inline void DNAColor::Enumerate<BigDNA::Write>(typename Write::StreamT& _w)
|
||||
{ zeus::CColor::writeRGBABig(_w); }
|
||||
template <> inline void DNAColor::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& _r)
|
||||
{
|
||||
size_t count;
|
||||
if (auto v = _r.enterSubVector(nullptr, count))
|
||||
{
|
||||
zeus::simd_floats f;
|
||||
f[0] = (count >= 1) ? _r.readFloat(nullptr) : 0.f;
|
||||
f[1] = (count >= 2) ? _r.readFloat(nullptr) : 0.f;
|
||||
f[2] = (count >= 3) ? _r.readFloat(nullptr) : 0.f;
|
||||
f[3] = (count >= 4) ? _r.readFloat(nullptr) : 0.f;
|
||||
mSimd.copy_from(f);
|
||||
}
|
||||
template <>
|
||||
inline void DNAColor::Enumerate<BigDNA::Read>(typename Read::StreamT& _r) {
|
||||
zeus::CColor::readRGBABig(_r);
|
||||
}
|
||||
template <> inline void DNAColor::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& _w)
|
||||
{
|
||||
if (auto v = _w.enterSubVector(nullptr))
|
||||
{
|
||||
zeus::simd_floats f(mSimd);
|
||||
_w.writeFloat(nullptr, f[0]);
|
||||
_w.writeFloat(nullptr, f[1]);
|
||||
_w.writeFloat(nullptr, f[2]);
|
||||
_w.writeFloat(nullptr, f[3]);
|
||||
}
|
||||
template <>
|
||||
inline void DNAColor::Enumerate<BigDNA::Write>(typename Write::StreamT& _w) {
|
||||
zeus::CColor::writeRGBABig(_w);
|
||||
}
|
||||
template <>
|
||||
inline void DNAColor::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& _r) {
|
||||
size_t count;
|
||||
if (auto v = _r.enterSubVector(nullptr, count)) {
|
||||
zeus::simd_floats f;
|
||||
f[0] = (count >= 1) ? _r.readFloat(nullptr) : 0.f;
|
||||
f[1] = (count >= 2) ? _r.readFloat(nullptr) : 0.f;
|
||||
f[2] = (count >= 3) ? _r.readFloat(nullptr) : 0.f;
|
||||
f[3] = (count >= 4) ? _r.readFloat(nullptr) : 0.f;
|
||||
mSimd.copy_from(f);
|
||||
}
|
||||
}
|
||||
template <>
|
||||
inline void DNAColor::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& _w) {
|
||||
if (auto v = _w.enterSubVector(nullptr)) {
|
||||
zeus::simd_floats f(mSimd);
|
||||
_w.writeFloat(nullptr, f[0]);
|
||||
_w.writeFloat(nullptr, f[1]);
|
||||
_w.writeFloat(nullptr, f[2]);
|
||||
_w.writeFloat(nullptr, f[3]);
|
||||
}
|
||||
}
|
||||
template <>
|
||||
inline void DNAColor::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& _s) {
|
||||
_s += 16;
|
||||
}
|
||||
template <> inline void DNAColor::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& _s)
|
||||
{ _s += 16; }
|
||||
|
||||
using FourCC = hecl::FourCC;
|
||||
class UniqueID32;
|
||||
|
@ -69,277 +71,266 @@ class UniqueID64;
|
|||
class UniqueID128;
|
||||
|
||||
/** Common virtual interface for runtime ambiguity resolution */
|
||||
class PAKRouterBase
|
||||
{
|
||||
class PAKRouterBase {
|
||||
protected:
|
||||
const SpecBase& m_dataSpec;
|
||||
const SpecBase& m_dataSpec;
|
||||
|
||||
public:
|
||||
PAKRouterBase(const SpecBase& dataSpec) : m_dataSpec(dataSpec) {}
|
||||
hecl::Database::Project& getProject() const {return m_dataSpec.getProject();}
|
||||
virtual hecl::ProjectPath getWorking(const UniqueID32&, bool silenceWarnings=false) const
|
||||
{
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
"PAKRouter IDType mismatch; expected UniqueID32 specialization");
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
virtual hecl::ProjectPath getWorking(const UniqueID64&, bool silenceWarnings=false) const
|
||||
{
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
"PAKRouter IDType mismatch; expected UniqueID64 specialization");
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
virtual hecl::ProjectPath getWorking(const UniqueID128&, bool silenceWarnings=false) const
|
||||
{
|
||||
LogDNACommon.report(logvisor::Fatal,
|
||||
"PAKRouter IDType mismatch; expected UniqueID128 specialization");
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
PAKRouterBase(const SpecBase& dataSpec) : m_dataSpec(dataSpec) {}
|
||||
hecl::Database::Project& getProject() const { return m_dataSpec.getProject(); }
|
||||
virtual hecl::ProjectPath getWorking(const UniqueID32&, bool silenceWarnings = false) const {
|
||||
LogDNACommon.report(logvisor::Fatal, "PAKRouter IDType mismatch; expected UniqueID32 specialization");
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
virtual hecl::ProjectPath getWorking(const UniqueID64&, bool silenceWarnings = false) const {
|
||||
LogDNACommon.report(logvisor::Fatal, "PAKRouter IDType mismatch; expected UniqueID64 specialization");
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
virtual hecl::ProjectPath getWorking(const UniqueID128&, bool silenceWarnings = false) const {
|
||||
LogDNACommon.report(logvisor::Fatal, "PAKRouter IDType mismatch; expected UniqueID128 specialization");
|
||||
return hecl::ProjectPath();
|
||||
}
|
||||
};
|
||||
|
||||
/** Globally-accessed manager allowing UniqueID* classes to directly
|
||||
* lookup destination paths of resources */
|
||||
class UniqueIDBridge
|
||||
{
|
||||
friend class UniqueID32;
|
||||
friend class UniqueID64;
|
||||
class UniqueIDBridge {
|
||||
friend class UniqueID32;
|
||||
friend class UniqueID64;
|
||||
|
||||
static ThreadLocalPtr<hecl::Database::Project> s_Project;
|
||||
static ThreadLocalPtr<IDRestorer<UniqueID32>> s_restorer32;
|
||||
static ThreadLocalPtr<IDRestorer<UniqueID64>> s_restorer64;
|
||||
static ThreadLocalPtr<IDRestorer<UniqueID128>> s_restorer128;
|
||||
|
||||
static ThreadLocalPtr<hecl::Database::Project> s_Project;
|
||||
static ThreadLocalPtr<IDRestorer<UniqueID32>> s_restorer32;
|
||||
static ThreadLocalPtr<IDRestorer<UniqueID64>> s_restorer64;
|
||||
static ThreadLocalPtr<IDRestorer<UniqueID128>> s_restorer128;
|
||||
public:
|
||||
template <class IDType>
|
||||
static hecl::ProjectPath TranslatePakIdToPath(const IDType& id, bool silenceWarnings=false);
|
||||
template <class IDType>
|
||||
static hecl::ProjectPath MakePathFromString(std::string_view str);
|
||||
template <class IDType>
|
||||
static void TransformOldHashToNewHash(IDType& id);
|
||||
template <class IDType>
|
||||
static hecl::ProjectPath TranslatePakIdToPath(const IDType& id, bool silenceWarnings = false);
|
||||
template <class IDType>
|
||||
static hecl::ProjectPath MakePathFromString(std::string_view str);
|
||||
template <class IDType>
|
||||
static void TransformOldHashToNewHash(IDType& id);
|
||||
|
||||
static void SetThreadProject(hecl::Database::Project& project);
|
||||
static void SetThreadProject(hecl::Database::Project& project);
|
||||
|
||||
template <class IDType>
|
||||
static IDRestorer<IDType>* GetIDRestorer();
|
||||
template <class IDType>
|
||||
static void SetIDRestorer(IDRestorer<IDType>* restorer);
|
||||
template <class IDType>
|
||||
static IDRestorer<IDType>* GetIDRestorer();
|
||||
template <class IDType>
|
||||
static void SetIDRestorer(IDRestorer<IDType>* restorer);
|
||||
};
|
||||
|
||||
template <>
|
||||
inline IDRestorer<UniqueID32>* UniqueIDBridge::GetIDRestorer<UniqueID32>()
|
||||
{
|
||||
return s_restorer32.get();
|
||||
inline IDRestorer<UniqueID32>* UniqueIDBridge::GetIDRestorer<UniqueID32>() {
|
||||
return s_restorer32.get();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void UniqueIDBridge::SetIDRestorer<UniqueID32>(IDRestorer<UniqueID32>* restorer)
|
||||
{
|
||||
s_restorer32.reset(restorer);
|
||||
inline void UniqueIDBridge::SetIDRestorer<UniqueID32>(IDRestorer<UniqueID32>* restorer) {
|
||||
s_restorer32.reset(restorer);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline IDRestorer<UniqueID64>* UniqueIDBridge::GetIDRestorer<UniqueID64>()
|
||||
{
|
||||
return s_restorer64.get();
|
||||
inline IDRestorer<UniqueID64>* UniqueIDBridge::GetIDRestorer<UniqueID64>() {
|
||||
return s_restorer64.get();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void UniqueIDBridge::SetIDRestorer<UniqueID64>(IDRestorer<UniqueID64>* restorer)
|
||||
{
|
||||
s_restorer64.reset(restorer);
|
||||
inline void UniqueIDBridge::SetIDRestorer<UniqueID64>(IDRestorer<UniqueID64>* restorer) {
|
||||
s_restorer64.reset(restorer);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline IDRestorer<UniqueID128>* UniqueIDBridge::GetIDRestorer<UniqueID128>()
|
||||
{
|
||||
return s_restorer128.get();
|
||||
inline IDRestorer<UniqueID128>* UniqueIDBridge::GetIDRestorer<UniqueID128>() {
|
||||
return s_restorer128.get();
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void UniqueIDBridge::SetIDRestorer<UniqueID128>(IDRestorer<UniqueID128>* restorer)
|
||||
{
|
||||
s_restorer128.reset(restorer);
|
||||
inline void UniqueIDBridge::SetIDRestorer<UniqueID128>(IDRestorer<UniqueID128>* restorer) {
|
||||
s_restorer128.reset(restorer);
|
||||
}
|
||||
|
||||
/** PAK 32-bit Unique ID */
|
||||
class UniqueID32 : public BigDNA
|
||||
{
|
||||
class UniqueID32 : public BigDNA {
|
||||
protected:
|
||||
uint32_t m_id = 0xffffffff;
|
||||
uint32_t m_id = 0xffffffff;
|
||||
|
||||
public:
|
||||
using value_type = uint32_t;
|
||||
static UniqueID32 kInvalidId;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
operator bool() const {return m_id != 0xffffffff && m_id != 0;}
|
||||
void assign(uint32_t id, bool noOriginal = false);
|
||||
using value_type = uint32_t;
|
||||
static UniqueID32 kInvalidId;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
operator bool() const { return m_id != 0xffffffff && m_id != 0; }
|
||||
void assign(uint32_t id, bool noOriginal = false);
|
||||
|
||||
UniqueID32& operator=(const hecl::ProjectPath& path)
|
||||
{assign(path.hash().val32()); return *this;}
|
||||
UniqueID32& operator=(const hecl::ProjectPath& path) {
|
||||
assign(path.hash().val32());
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator!=(const UniqueID32& other) const {return m_id != other.m_id;}
|
||||
bool operator==(const UniqueID32& other) const {return m_id == other.m_id;}
|
||||
bool operator<(const UniqueID32& other) const {return m_id < other.m_id;}
|
||||
uint32_t toUint32() const {return m_id;}
|
||||
uint64_t toUint64() const {return m_id;}
|
||||
std::string toString() const;
|
||||
void clear() {m_id = 0xffffffff;}
|
||||
bool operator!=(const UniqueID32& other) const { return m_id != other.m_id; }
|
||||
bool operator==(const UniqueID32& other) const { return m_id == other.m_id; }
|
||||
bool operator<(const UniqueID32& other) const { return m_id < other.m_id; }
|
||||
uint32_t toUint32() const { return m_id; }
|
||||
uint64_t toUint64() const { return m_id; }
|
||||
std::string toString() const;
|
||||
void clear() { m_id = 0xffffffff; }
|
||||
|
||||
UniqueID32() = default;
|
||||
UniqueID32(uint32_t idin, bool noOriginal = false) {assign(idin, noOriginal);}
|
||||
UniqueID32(athena::io::IStreamReader& reader) {read(reader);}
|
||||
UniqueID32(const hecl::ProjectPath& path) {*this = path;}
|
||||
UniqueID32(const char* hexStr)
|
||||
{
|
||||
char copy[9];
|
||||
strncpy(copy, hexStr, 8);
|
||||
copy[8] = '\0';
|
||||
assign(strtoul(copy, nullptr, 16));
|
||||
}
|
||||
UniqueID32(const wchar_t* hexStr)
|
||||
{
|
||||
wchar_t copy[9];
|
||||
wcsncpy(copy, hexStr, 8);
|
||||
copy[8] = L'\0';
|
||||
assign(wcstoul(copy, nullptr, 16));
|
||||
}
|
||||
UniqueID32() = default;
|
||||
UniqueID32(uint32_t idin, bool noOriginal = false) { assign(idin, noOriginal); }
|
||||
UniqueID32(athena::io::IStreamReader& reader) { read(reader); }
|
||||
UniqueID32(const hecl::ProjectPath& path) { *this = path; }
|
||||
UniqueID32(const char* hexStr) {
|
||||
char copy[9];
|
||||
strncpy(copy, hexStr, 8);
|
||||
copy[8] = '\0';
|
||||
assign(strtoul(copy, nullptr, 16));
|
||||
}
|
||||
UniqueID32(const wchar_t* hexStr) {
|
||||
wchar_t copy[9];
|
||||
wcsncpy(copy, hexStr, 8);
|
||||
copy[8] = L'\0';
|
||||
assign(wcstoul(copy, nullptr, 16));
|
||||
}
|
||||
|
||||
static constexpr size_t BinarySize() {return 4;}
|
||||
static constexpr size_t BinarySize() { return 4; }
|
||||
};
|
||||
|
||||
/** PAK 32-bit Unique ID - writes zero when invalid */
|
||||
class UniqueID32Zero : public UniqueID32
|
||||
{
|
||||
class UniqueID32Zero : public UniqueID32 {
|
||||
public:
|
||||
AT_DECL_DNA_YAML
|
||||
Delete __d2;
|
||||
using UniqueID32::UniqueID32;
|
||||
AT_DECL_DNA_YAML
|
||||
Delete __d2;
|
||||
using UniqueID32::UniqueID32;
|
||||
};
|
||||
|
||||
class AuxiliaryID32 : public UniqueID32
|
||||
{
|
||||
const hecl::SystemChar* m_auxStr;
|
||||
const hecl::SystemChar* m_addExtension;
|
||||
UniqueID32 m_baseId;
|
||||
public:
|
||||
AT_DECL_DNA
|
||||
Delete __d2;
|
||||
AuxiliaryID32(const hecl::SystemChar* auxStr,
|
||||
const hecl::SystemChar* addExtension=nullptr)
|
||||
: m_auxStr(auxStr), m_addExtension(addExtension) {}
|
||||
class AuxiliaryID32 : public UniqueID32 {
|
||||
const hecl::SystemChar* m_auxStr;
|
||||
const hecl::SystemChar* m_addExtension;
|
||||
UniqueID32 m_baseId;
|
||||
|
||||
AuxiliaryID32& operator=(const hecl::ProjectPath& path);
|
||||
AuxiliaryID32& operator=(const UniqueID32& id);
|
||||
const UniqueID32& getBaseId() const {return m_baseId;}
|
||||
public:
|
||||
AT_DECL_DNA
|
||||
Delete __d2;
|
||||
AuxiliaryID32(const hecl::SystemChar* auxStr, const hecl::SystemChar* addExtension = nullptr)
|
||||
: m_auxStr(auxStr), m_addExtension(addExtension) {}
|
||||
|
||||
AuxiliaryID32& operator=(const hecl::ProjectPath& path);
|
||||
AuxiliaryID32& operator=(const UniqueID32& id);
|
||||
const UniqueID32& getBaseId() const { return m_baseId; }
|
||||
};
|
||||
|
||||
/** PAK 64-bit Unique ID */
|
||||
class UniqueID64 : public BigDNA
|
||||
{
|
||||
uint64_t m_id = 0xffffffffffffffff;
|
||||
class UniqueID64 : public BigDNA {
|
||||
uint64_t m_id = 0xffffffffffffffff;
|
||||
|
||||
public:
|
||||
using value_type = uint64_t;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
operator bool() const {return m_id != 0xffffffffffffffff && m_id != 0;}
|
||||
void assign(uint64_t id, bool noOriginal = false);
|
||||
using value_type = uint64_t;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
operator bool() const { return m_id != 0xffffffffffffffff && m_id != 0; }
|
||||
void assign(uint64_t id, bool noOriginal = false);
|
||||
|
||||
UniqueID64& operator=(const hecl::ProjectPath& path)
|
||||
{assign(path.hash().val64()); return *this;}
|
||||
UniqueID64& operator=(const hecl::ProjectPath& path) {
|
||||
assign(path.hash().val64());
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator!=(const UniqueID64& other) const {return m_id != other.m_id;}
|
||||
bool operator==(const UniqueID64& other) const {return m_id == other.m_id;}
|
||||
bool operator<(const UniqueID64& other) const {return m_id < other.m_id;}
|
||||
uint64_t toUint64() const {return m_id;}
|
||||
std::string toString() const;
|
||||
void clear() {m_id = 0xffffffffffffffff;}
|
||||
bool operator!=(const UniqueID64& other) const { return m_id != other.m_id; }
|
||||
bool operator==(const UniqueID64& other) const { return m_id == other.m_id; }
|
||||
bool operator<(const UniqueID64& other) const { return m_id < other.m_id; }
|
||||
uint64_t toUint64() const { return m_id; }
|
||||
std::string toString() const;
|
||||
void clear() { m_id = 0xffffffffffffffff; }
|
||||
|
||||
UniqueID64() = default;
|
||||
UniqueID64(uint64_t idin, bool noOriginal = false) {assign(idin, noOriginal);}
|
||||
UniqueID64(athena::io::IStreamReader& reader) {read(reader);}
|
||||
UniqueID64(const hecl::ProjectPath& path) {*this = path;}
|
||||
UniqueID64(const char* hexStr)
|
||||
{
|
||||
char copy[17];
|
||||
strncpy(copy, hexStr, 16);
|
||||
copy[16] = '\0';
|
||||
UniqueID64() = default;
|
||||
UniqueID64(uint64_t idin, bool noOriginal = false) { assign(idin, noOriginal); }
|
||||
UniqueID64(athena::io::IStreamReader& reader) { read(reader); }
|
||||
UniqueID64(const hecl::ProjectPath& path) { *this = path; }
|
||||
UniqueID64(const char* hexStr) {
|
||||
char copy[17];
|
||||
strncpy(copy, hexStr, 16);
|
||||
copy[16] = '\0';
|
||||
#if _WIN32
|
||||
assign(_strtoui64(copy, nullptr, 16));
|
||||
assign(_strtoui64(copy, nullptr, 16));
|
||||
#else
|
||||
assign(strtouq(copy, nullptr, 16));
|
||||
assign(strtouq(copy, nullptr, 16));
|
||||
#endif
|
||||
}
|
||||
UniqueID64(const wchar_t* hexStr)
|
||||
{
|
||||
wchar_t copy[17];
|
||||
wcsncpy(copy, hexStr, 16);
|
||||
copy[16] = L'\0';
|
||||
}
|
||||
UniqueID64(const wchar_t* hexStr) {
|
||||
wchar_t copy[17];
|
||||
wcsncpy(copy, hexStr, 16);
|
||||
copy[16] = L'\0';
|
||||
#if _WIN32
|
||||
assign(_wcstoui64(copy, nullptr, 16));
|
||||
assign(_wcstoui64(copy, nullptr, 16));
|
||||
#else
|
||||
assign(wcstoull(copy, nullptr, 16));
|
||||
assign(wcstoull(copy, nullptr, 16));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr size_t BinarySize() {return 8;}
|
||||
static constexpr size_t BinarySize() { return 8; }
|
||||
};
|
||||
|
||||
/** PAK 128-bit Unique ID */
|
||||
class UniqueID128 : public BigDNA
|
||||
{
|
||||
class UniqueID128 : public BigDNA {
|
||||
public:
|
||||
union Value
|
||||
{
|
||||
uint64_t id[2];
|
||||
union Value {
|
||||
uint64_t id[2];
|
||||
#if __SSE__
|
||||
__m128i id128;
|
||||
__m128i id128;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
private:
|
||||
Value m_id;
|
||||
Value m_id;
|
||||
|
||||
public:
|
||||
using value_type = uint64_t;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
UniqueID128() {m_id.id[0]=0xffffffffffffffff; m_id.id[1]=0xffffffffffffffff;}
|
||||
UniqueID128(uint64_t idin, bool noOriginal = false)
|
||||
{
|
||||
m_id.id[0] = idin;
|
||||
m_id.id[1] = 0;
|
||||
}
|
||||
operator bool() const
|
||||
{return m_id.id[0] != 0xffffffffffffffff && m_id.id[0] != 0 && m_id.id[1] != 0xffffffffffffffff && m_id.id[1] != 0;}
|
||||
using value_type = uint64_t;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
UniqueID128() {
|
||||
m_id.id[0] = 0xffffffffffffffff;
|
||||
m_id.id[1] = 0xffffffffffffffff;
|
||||
}
|
||||
UniqueID128(uint64_t idin, bool noOriginal = false) {
|
||||
m_id.id[0] = idin;
|
||||
m_id.id[1] = 0;
|
||||
}
|
||||
operator bool() const {
|
||||
return m_id.id[0] != 0xffffffffffffffff && m_id.id[0] != 0 && m_id.id[1] != 0xffffffffffffffff && m_id.id[1] != 0;
|
||||
}
|
||||
|
||||
UniqueID128& operator=(const hecl::ProjectPath& path)
|
||||
{
|
||||
m_id.id[0] = path.hash().val64();
|
||||
m_id.id[1] = 0;
|
||||
return *this;
|
||||
}
|
||||
UniqueID128(const hecl::ProjectPath& path) {*this = path;}
|
||||
UniqueID128& operator=(const hecl::ProjectPath& path) {
|
||||
m_id.id[0] = path.hash().val64();
|
||||
m_id.id[1] = 0;
|
||||
return *this;
|
||||
}
|
||||
UniqueID128(const hecl::ProjectPath& path) { *this = path; }
|
||||
|
||||
bool operator!=(const UniqueID128& other) const
|
||||
{
|
||||
bool operator!=(const UniqueID128& other) const {
|
||||
#if __SSE__
|
||||
__m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128);
|
||||
int vmask = _mm_movemask_epi8(vcmp);
|
||||
return vmask != 0xffff;
|
||||
__m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128);
|
||||
int vmask = _mm_movemask_epi8(vcmp);
|
||||
return vmask != 0xffff;
|
||||
#else
|
||||
return (m_id.id[0] != other.m_id.id[0]) || (m_id.id[1] != other.m_id.id[1]);
|
||||
return (m_id.id[0] != other.m_id.id[0]) || (m_id.id[1] != other.m_id.id[1]);
|
||||
#endif
|
||||
}
|
||||
bool operator==(const UniqueID128& other) const
|
||||
{
|
||||
}
|
||||
bool operator==(const UniqueID128& other) const {
|
||||
#if __SSE__
|
||||
__m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128);
|
||||
int vmask = _mm_movemask_epi8(vcmp);
|
||||
return vmask == 0xffff;
|
||||
__m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128);
|
||||
int vmask = _mm_movemask_epi8(vcmp);
|
||||
return vmask == 0xffff;
|
||||
#else
|
||||
return (m_id.id[0] == other.m_id.id[0]) && (m_id.id[1] == other.m_id.id[1]);
|
||||
return (m_id.id[0] == other.m_id.id[0]) && (m_id.id[1] == other.m_id.id[1]);
|
||||
#endif
|
||||
}
|
||||
void clear() {m_id.id[0] = 0xffffffffffffffff; m_id.id[1] = 0xffffffffffffffff;}
|
||||
uint64_t toUint64() const {return m_id.id[0];}
|
||||
uint64_t toHighUint64() const {return m_id.id[0];}
|
||||
uint64_t toLowUint64() const {return m_id.id[1];}
|
||||
std::string toString() const;
|
||||
}
|
||||
void clear() {
|
||||
m_id.id[0] = 0xffffffffffffffff;
|
||||
m_id.id[1] = 0xffffffffffffffff;
|
||||
}
|
||||
uint64_t toUint64() const { return m_id.id[0]; }
|
||||
uint64_t toHighUint64() const { return m_id.id[0]; }
|
||||
uint64_t toLowUint64() const { return m_id.id[1]; }
|
||||
std::string toString() const;
|
||||
|
||||
static constexpr size_t BinarySize() {return 16;}
|
||||
static constexpr size_t BinarySize() { return 16; }
|
||||
};
|
||||
|
||||
/** Casts ID type to its null-zero equivalent */
|
||||
|
@ -347,63 +338,66 @@ template <class T>
|
|||
using CastIDToZero = typename std::conditional_t<std::is_same_v<T, UniqueID32>, UniqueID32Zero, T>;
|
||||
|
||||
/** Word Bitmap reader/writer */
|
||||
class WordBitmap
|
||||
{
|
||||
std::vector<atUint32> m_words;
|
||||
size_t m_bitCount = 0;
|
||||
class WordBitmap {
|
||||
std::vector<atUint32> m_words;
|
||||
size_t m_bitCount = 0;
|
||||
|
||||
public:
|
||||
void read(athena::io::IStreamReader& reader, size_t bitCount);
|
||||
void write(athena::io::IStreamWriter& writer) const;
|
||||
void reserve(size_t bitCount) { m_words.reserve((bitCount + 31) / 32); }
|
||||
void binarySize(size_t& __isz) const;
|
||||
size_t getBitCount() const {return m_bitCount;}
|
||||
bool getBit(size_t idx) const
|
||||
{
|
||||
size_t wordIdx = idx / 32;
|
||||
if (wordIdx >= m_words.size())
|
||||
return false;
|
||||
size_t wordCur = idx % 32;
|
||||
return (m_words[wordIdx] >> wordCur) & 0x1;
|
||||
}
|
||||
void setBit(size_t idx)
|
||||
{
|
||||
size_t wordIdx = idx / 32;
|
||||
while (wordIdx >= m_words.size())
|
||||
m_words.push_back(0);
|
||||
size_t wordCur = idx % 32;
|
||||
m_words[wordIdx] |= (1 << wordCur);
|
||||
m_bitCount = std::max(m_bitCount, idx + 1);
|
||||
}
|
||||
void unsetBit(size_t idx)
|
||||
{
|
||||
size_t wordIdx = idx / 32;
|
||||
while (wordIdx >= m_words.size())
|
||||
m_words.push_back(0);
|
||||
size_t wordCur = idx % 32;
|
||||
m_words[wordIdx] &= ~(1 << wordCur);
|
||||
m_bitCount = std::max(m_bitCount, idx + 1);
|
||||
}
|
||||
void clear() { m_words.clear(); m_bitCount = 0; }
|
||||
void read(athena::io::IStreamReader& reader, size_t bitCount);
|
||||
void write(athena::io::IStreamWriter& writer) const;
|
||||
void reserve(size_t bitCount) { m_words.reserve((bitCount + 31) / 32); }
|
||||
void binarySize(size_t& __isz) const;
|
||||
size_t getBitCount() const { return m_bitCount; }
|
||||
bool getBit(size_t idx) const {
|
||||
size_t wordIdx = idx / 32;
|
||||
if (wordIdx >= m_words.size())
|
||||
return false;
|
||||
size_t wordCur = idx % 32;
|
||||
return (m_words[wordIdx] >> wordCur) & 0x1;
|
||||
}
|
||||
void setBit(size_t idx) {
|
||||
size_t wordIdx = idx / 32;
|
||||
while (wordIdx >= m_words.size())
|
||||
m_words.push_back(0);
|
||||
size_t wordCur = idx % 32;
|
||||
m_words[wordIdx] |= (1 << wordCur);
|
||||
m_bitCount = std::max(m_bitCount, idx + 1);
|
||||
}
|
||||
void unsetBit(size_t idx) {
|
||||
size_t wordIdx = idx / 32;
|
||||
while (wordIdx >= m_words.size())
|
||||
m_words.push_back(0);
|
||||
size_t wordCur = idx % 32;
|
||||
m_words[wordIdx] &= ~(1 << wordCur);
|
||||
m_bitCount = std::max(m_bitCount, idx + 1);
|
||||
}
|
||||
void clear() {
|
||||
m_words.clear();
|
||||
m_bitCount = 0;
|
||||
}
|
||||
|
||||
class Iterator
|
||||
{
|
||||
friend class WordBitmap;
|
||||
const WordBitmap& m_bmp;
|
||||
size_t m_idx = 0;
|
||||
Iterator(const WordBitmap& bmp, size_t idx) : m_bmp(bmp), m_idx(idx) {}
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = bool;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = bool*;
|
||||
using reference = bool&;
|
||||
class Iterator {
|
||||
friend class WordBitmap;
|
||||
const WordBitmap& m_bmp;
|
||||
size_t m_idx = 0;
|
||||
Iterator(const WordBitmap& bmp, size_t idx) : m_bmp(bmp), m_idx(idx) {}
|
||||
|
||||
Iterator& operator++() {++m_idx; return *this;}
|
||||
bool operator*() {return m_bmp.getBit(m_idx);}
|
||||
bool operator!=(const Iterator& other) const {return m_idx != other.m_idx;}
|
||||
};
|
||||
Iterator begin() const {return Iterator(*this, 0);}
|
||||
Iterator end() const {return Iterator(*this, m_bitCount);}
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = bool;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = bool*;
|
||||
using reference = bool&;
|
||||
|
||||
Iterator& operator++() {
|
||||
++m_idx;
|
||||
return *this;
|
||||
}
|
||||
bool operator*() { return m_bmp.getBit(m_idx); }
|
||||
bool operator!=(const Iterator& other) const { return m_idx != other.m_idx; }
|
||||
};
|
||||
Iterator begin() const { return Iterator(*this, 0); }
|
||||
Iterator end() const { return Iterator(*this, m_bitCount); }
|
||||
};
|
||||
|
||||
/** Resource cooker function */
|
||||
|
@ -411,60 +405,47 @@ typedef std::function<bool(const hecl::ProjectPath&, const hecl::ProjectPath&)>
|
|||
|
||||
/** Mappings of resources involved in extracting characters */
|
||||
template <class IDType>
|
||||
struct CharacterAssociations
|
||||
{
|
||||
using RigPair = std::pair<IDType, IDType>;
|
||||
/* CMDL -> (CSKR, CINF) */
|
||||
std::unordered_map<IDType, RigPair> m_cmdlRigs;
|
||||
/* (CSKR, CINF) -> ANCS */
|
||||
std::unordered_map<IDType, std::pair<IDType, std::string>> m_cskrCinfToCharacter;
|
||||
/* ANCS -> (CINF, CMDL) */
|
||||
std::unordered_multimap<IDType, std::pair<RigPair, std::string>> m_characterToAttachmentRigs;
|
||||
using MultimapIteratorPair = std::pair<
|
||||
typename std::unordered_multimap<IDType, std::pair<RigPair, std::string>>::const_iterator,
|
||||
typename std::unordered_multimap<IDType, std::pair<RigPair, std::string>>::const_iterator>;
|
||||
void addAttachmentRig(IDType character, IDType cinf, IDType cmdl, const char* name)
|
||||
{
|
||||
auto range = m_characterToAttachmentRigs.equal_range(character);
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
if (it->second.second == name)
|
||||
return;
|
||||
m_characterToAttachmentRigs.insert(
|
||||
std::make_pair(character, std::make_pair(std::make_pair(cinf, cmdl), name)));
|
||||
}
|
||||
struct CharacterAssociations {
|
||||
using RigPair = std::pair<IDType, IDType>;
|
||||
/* CMDL -> (CSKR, CINF) */
|
||||
std::unordered_map<IDType, RigPair> m_cmdlRigs;
|
||||
/* (CSKR, CINF) -> ANCS */
|
||||
std::unordered_map<IDType, std::pair<IDType, std::string>> m_cskrCinfToCharacter;
|
||||
/* ANCS -> (CINF, CMDL) */
|
||||
std::unordered_multimap<IDType, std::pair<RigPair, std::string>> m_characterToAttachmentRigs;
|
||||
using MultimapIteratorPair =
|
||||
std::pair<typename std::unordered_multimap<IDType, std::pair<RigPair, std::string>>::const_iterator,
|
||||
typename std::unordered_multimap<IDType, std::pair<RigPair, std::string>>::const_iterator>;
|
||||
void addAttachmentRig(IDType character, IDType cinf, IDType cmdl, const char* name) {
|
||||
auto range = m_characterToAttachmentRigs.equal_range(character);
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
if (it->second.second == name)
|
||||
return;
|
||||
m_characterToAttachmentRigs.insert(std::make_pair(character, std::make_pair(std::make_pair(cinf, cmdl), name)));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace DataSpec
|
||||
|
||||
/* Hash template-specializations for UniqueID types */
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<DataSpec::DNAFourCC>
|
||||
{
|
||||
size_t operator()(const DataSpec::DNAFourCC& fcc) const
|
||||
{return fcc.toUint32();}
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<DataSpec::DNAFourCC> {
|
||||
size_t operator()(const DataSpec::DNAFourCC& fcc) const { return fcc.toUint32(); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<DataSpec::UniqueID32>
|
||||
{
|
||||
size_t operator()(const DataSpec::UniqueID32& id) const
|
||||
{return id.toUint32();}
|
||||
template <>
|
||||
struct hash<DataSpec::UniqueID32> {
|
||||
size_t operator()(const DataSpec::UniqueID32& id) const { return id.toUint32(); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<DataSpec::UniqueID64>
|
||||
{
|
||||
size_t operator()(const DataSpec::UniqueID64& id) const
|
||||
{return id.toUint64();}
|
||||
template <>
|
||||
struct hash<DataSpec::UniqueID64> {
|
||||
size_t operator()(const DataSpec::UniqueID64& id) const { return id.toUint64(); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hash<DataSpec::UniqueID128>
|
||||
{
|
||||
size_t operator()(const DataSpec::UniqueID128& id) const
|
||||
{return id.toHighUint64() ^ id.toLowUint64();}
|
||||
template <>
|
||||
struct hash<DataSpec::UniqueID128> {
|
||||
size_t operator()(const DataSpec::UniqueID128& id) const { return id.toHighUint64() ^ id.toLowUint64(); }
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
|
|
|
@ -1,418 +1,377 @@
|
|||
#include "DPSC.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle
|
||||
{
|
||||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template <>
|
||||
const char* DPSM<UniqueID32>::DNAType() { return "DPSM<UniqueID32>"; }
|
||||
const char* DPSM<UniqueID32>::DNAType() {
|
||||
return "DPSM<UniqueID32>";
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* DPSM<UniqueID64>::DNAType() { return "DPSM<UniqueID64>"; }
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::_read(athena::io::YAMLDocReader& r)
|
||||
{
|
||||
for (const auto& elem : r.getCurNode()->m_mapChildren)
|
||||
{
|
||||
if (elem.first.size() < 4)
|
||||
{
|
||||
LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto rec = r.enterSubRecord(elem.first.c_str()))
|
||||
{
|
||||
bool loadFirstDesc = false;
|
||||
uint32_t clsId = *reinterpret_cast<const uint32_t*>(elem.first.c_str());
|
||||
switch(clsId)
|
||||
{
|
||||
case SBIG('1SZE'):
|
||||
case SBIG('1LFT'):
|
||||
case SBIG('1ROT'):
|
||||
case SBIG('1OFF'):
|
||||
case SBIG('1CLR'):
|
||||
case SBIG('1TEX'):
|
||||
case SBIG('1ADD'):
|
||||
loadFirstDesc = true;
|
||||
case SBIG('2SZE'):
|
||||
case SBIG('2LFT'):
|
||||
case SBIG('2ROT'):
|
||||
case SBIG('2OFF'):
|
||||
case SBIG('2CLR'):
|
||||
case SBIG('2TEX'):
|
||||
case SBIG('2ADD'):
|
||||
if (loadFirstDesc)
|
||||
readQuadDecalInfo(r, clsId, x0_quad);
|
||||
else
|
||||
readQuadDecalInfo(r, clsId, x1c_quad);
|
||||
break;
|
||||
case SBIG('DMDL'):
|
||||
x38_DMDL.read(r);
|
||||
break;
|
||||
case SBIG('DLFT'):
|
||||
x48_DLFT.read(r);
|
||||
break;
|
||||
case SBIG('DMOP'):
|
||||
x4c_DMOP.read(r);
|
||||
break;
|
||||
case SBIG('DMRT'):
|
||||
x50_DMRT.read(r);
|
||||
break;
|
||||
case SBIG('DMSC'):
|
||||
x54_DMSC.read(r);
|
||||
break;
|
||||
case SBIG('DMCL'):
|
||||
x58_DMCL.read(r);
|
||||
break;
|
||||
case SBIG('DMAB'):
|
||||
x5c_24_DMAB = r.readBool(nullptr);
|
||||
break;
|
||||
case SBIG('DMOO'):
|
||||
x5c_25_DMOO = r.readBool(nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const char* DPSM<UniqueID64>::DNAType() {
|
||||
return "DPSM<UniqueID64>";
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::_write(athena::io::YAMLDocWriter& w) const
|
||||
{
|
||||
writeQuadDecalInfo(w, x0_quad, true);
|
||||
writeQuadDecalInfo(w, x1c_quad, false);
|
||||
void DPSM<IDType>::_read(athena::io::YAMLDocReader& r) {
|
||||
for (const auto& elem : r.getCurNode()->m_mapChildren) {
|
||||
if (elem.first.size() < 4) {
|
||||
LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (x38_DMDL)
|
||||
if (auto rec = w.enterSubRecord("DMDL"))
|
||||
x38_DMDL.write(w);
|
||||
if (x48_DLFT)
|
||||
if (auto rec = w.enterSubRecord("DLFT"))
|
||||
x48_DLFT.write(w);
|
||||
if (x4c_DMOP)
|
||||
if (auto rec = w.enterSubRecord("DMOP"))
|
||||
x4c_DMOP.write(w);
|
||||
if (x50_DMRT)
|
||||
if (auto rec = w.enterSubRecord("DMRT"))
|
||||
x50_DMRT.write(w);
|
||||
if (x54_DMSC)
|
||||
if (auto rec = w.enterSubRecord("DMSC"))
|
||||
x54_DMSC.write(w);
|
||||
if (x58_DMCL)
|
||||
if (auto rec = w.enterSubRecord("DMCL"))
|
||||
x54_DMSC.write(w);
|
||||
if (auto rec = r.enterSubRecord(elem.first.c_str())) {
|
||||
bool loadFirstDesc = false;
|
||||
uint32_t clsId = *reinterpret_cast<const uint32_t*>(elem.first.c_str());
|
||||
switch (clsId) {
|
||||
case SBIG('1SZE'):
|
||||
case SBIG('1LFT'):
|
||||
case SBIG('1ROT'):
|
||||
case SBIG('1OFF'):
|
||||
case SBIG('1CLR'):
|
||||
case SBIG('1TEX'):
|
||||
case SBIG('1ADD'):
|
||||
loadFirstDesc = true;
|
||||
case SBIG('2SZE'):
|
||||
case SBIG('2LFT'):
|
||||
case SBIG('2ROT'):
|
||||
case SBIG('2OFF'):
|
||||
case SBIG('2CLR'):
|
||||
case SBIG('2TEX'):
|
||||
case SBIG('2ADD'):
|
||||
if (loadFirstDesc)
|
||||
readQuadDecalInfo(r, clsId, x0_quad);
|
||||
else
|
||||
readQuadDecalInfo(r, clsId, x1c_quad);
|
||||
break;
|
||||
case SBIG('DMDL'):
|
||||
x38_DMDL.read(r);
|
||||
break;
|
||||
case SBIG('DLFT'):
|
||||
x48_DLFT.read(r);
|
||||
break;
|
||||
case SBIG('DMOP'):
|
||||
x4c_DMOP.read(r);
|
||||
break;
|
||||
case SBIG('DMRT'):
|
||||
x50_DMRT.read(r);
|
||||
break;
|
||||
case SBIG('DMSC'):
|
||||
x54_DMSC.read(r);
|
||||
break;
|
||||
case SBIG('DMCL'):
|
||||
x58_DMCL.read(r);
|
||||
break;
|
||||
case SBIG('DMAB'):
|
||||
x5c_24_DMAB = r.readBool(nullptr);
|
||||
break;
|
||||
case SBIG('DMOO'):
|
||||
x5c_25_DMOO = r.readBool(nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (x5c_24_DMAB)
|
||||
w.writeBool("DMAB", x5c_24_DMAB);
|
||||
if (x5c_25_DMOO)
|
||||
w.writeBool("DMOO", x5c_25_DMOO);
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::_write(athena::io::YAMLDocWriter& w) const {
|
||||
writeQuadDecalInfo(w, x0_quad, true);
|
||||
writeQuadDecalInfo(w, x1c_quad, false);
|
||||
|
||||
if (x38_DMDL)
|
||||
if (auto rec = w.enterSubRecord("DMDL"))
|
||||
x38_DMDL.write(w);
|
||||
if (x48_DLFT)
|
||||
if (auto rec = w.enterSubRecord("DLFT"))
|
||||
x48_DLFT.write(w);
|
||||
if (x4c_DMOP)
|
||||
if (auto rec = w.enterSubRecord("DMOP"))
|
||||
x4c_DMOP.write(w);
|
||||
if (x50_DMRT)
|
||||
if (auto rec = w.enterSubRecord("DMRT"))
|
||||
x50_DMRT.write(w);
|
||||
if (x54_DMSC)
|
||||
if (auto rec = w.enterSubRecord("DMSC"))
|
||||
x54_DMSC.write(w);
|
||||
if (x58_DMCL)
|
||||
if (auto rec = w.enterSubRecord("DMCL"))
|
||||
x54_DMSC.write(w);
|
||||
|
||||
if (x5c_24_DMAB)
|
||||
w.writeBool("DMAB", x5c_24_DMAB);
|
||||
if (x5c_25_DMOO)
|
||||
w.writeBool("DMOO", x5c_25_DMOO);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
template <class Reader>
|
||||
void DPSM<IDType>::readQuadDecalInfo(Reader& r, uint32_t clsId, typename DPSM<IDType>::SQuadDescr& quad)
|
||||
{
|
||||
switch(clsId)
|
||||
{
|
||||
case SBIG('1LFT'):
|
||||
case SBIG('2LFT'):
|
||||
quad.x0_LFT.read(r);
|
||||
void DPSM<IDType>::readQuadDecalInfo(Reader& r, uint32_t clsId, typename DPSM<IDType>::SQuadDescr& quad) {
|
||||
switch (clsId) {
|
||||
case SBIG('1LFT'):
|
||||
case SBIG('2LFT'):
|
||||
quad.x0_LFT.read(r);
|
||||
break;
|
||||
case SBIG('1SZE'):
|
||||
case SBIG('2SZE'):
|
||||
quad.x4_SZE.read(r);
|
||||
case SBIG('1SZE'):
|
||||
case SBIG('2SZE'):
|
||||
quad.x4_SZE.read(r);
|
||||
break;
|
||||
case SBIG('1ROT'):
|
||||
case SBIG('2ROT'):
|
||||
quad.x8_ROT.read(r);
|
||||
case SBIG('1ROT'):
|
||||
case SBIG('2ROT'):
|
||||
quad.x8_ROT.read(r);
|
||||
break;
|
||||
case SBIG('1OFF'):
|
||||
case SBIG('2OFF'):
|
||||
quad.xc_OFF.read(r);
|
||||
case SBIG('1OFF'):
|
||||
case SBIG('2OFF'):
|
||||
quad.xc_OFF.read(r);
|
||||
break;
|
||||
case SBIG('1CLR'):
|
||||
case SBIG('2CLR'):
|
||||
quad.x10_CLR.read(r);
|
||||
case SBIG('1CLR'):
|
||||
case SBIG('2CLR'):
|
||||
quad.x10_CLR.read(r);
|
||||
break;
|
||||
case SBIG('1TEX'):
|
||||
case SBIG('2TEX'):
|
||||
quad.x14_TEX.read(r);
|
||||
case SBIG('1TEX'):
|
||||
case SBIG('2TEX'):
|
||||
quad.x14_TEX.read(r);
|
||||
break;
|
||||
case SBIG('1ADD'):
|
||||
case SBIG('2ADD'):
|
||||
quad.x18_ADD.read(r);
|
||||
case SBIG('1ADD'):
|
||||
case SBIG('2ADD'):
|
||||
quad.x18_ADD.read(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::writeQuadDecalInfo(athena::io::YAMLDocWriter& w,
|
||||
const typename DPSM<IDType>::SQuadDescr& quad, bool first) const
|
||||
{
|
||||
if (quad.x0_LFT)
|
||||
if (auto rec = w.enterSubRecord((first ? "1LFT" : "2LFT")))
|
||||
quad.x0_LFT.write(w);
|
||||
if (quad.x4_SZE)
|
||||
if (auto rec = w.enterSubRecord((first ? "1SZE" : "2SZE")))
|
||||
quad.x4_SZE.write(w);
|
||||
if (quad.x8_ROT)
|
||||
if (auto rec = w.enterSubRecord((first ? "1ROT" : "2ROT")))
|
||||
quad.x8_ROT.write(w);
|
||||
if (quad.xc_OFF)
|
||||
if (auto rec = w.enterSubRecord((first ? "1OFF" : "2OFF")))
|
||||
quad.xc_OFF.write(w);
|
||||
if (quad.x10_CLR)
|
||||
if (auto rec = w.enterSubRecord((first ? "1CLR" : "2CLR")))
|
||||
quad.x10_CLR.write(w);
|
||||
if (quad.x14_TEX)
|
||||
if (auto rec = w.enterSubRecord((first ? "1TEX" : "2TEX")))
|
||||
quad.x14_TEX.write(w);
|
||||
if (quad.x18_ADD)
|
||||
if (auto rec = w.enterSubRecord((first ? "1ADD" : "2ADD")))
|
||||
quad.x18_ADD.write(w);
|
||||
void DPSM<IDType>::writeQuadDecalInfo(athena::io::YAMLDocWriter& w, const typename DPSM<IDType>::SQuadDescr& quad,
|
||||
bool first) const {
|
||||
if (quad.x0_LFT)
|
||||
if (auto rec = w.enterSubRecord((first ? "1LFT" : "2LFT")))
|
||||
quad.x0_LFT.write(w);
|
||||
if (quad.x4_SZE)
|
||||
if (auto rec = w.enterSubRecord((first ? "1SZE" : "2SZE")))
|
||||
quad.x4_SZE.write(w);
|
||||
if (quad.x8_ROT)
|
||||
if (auto rec = w.enterSubRecord((first ? "1ROT" : "2ROT")))
|
||||
quad.x8_ROT.write(w);
|
||||
if (quad.xc_OFF)
|
||||
if (auto rec = w.enterSubRecord((first ? "1OFF" : "2OFF")))
|
||||
quad.xc_OFF.write(w);
|
||||
if (quad.x10_CLR)
|
||||
if (auto rec = w.enterSubRecord((first ? "1CLR" : "2CLR")))
|
||||
quad.x10_CLR.write(w);
|
||||
if (quad.x14_TEX)
|
||||
if (auto rec = w.enterSubRecord((first ? "1TEX" : "2TEX")))
|
||||
quad.x14_TEX.write(w);
|
||||
if (quad.x18_ADD)
|
||||
if (auto rec = w.enterSubRecord((first ? "1ADD" : "2ADD")))
|
||||
quad.x18_ADD.write(w);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::_binarySize(size_t& s) const
|
||||
{
|
||||
void DPSM<IDType>::_binarySize(size_t& s) const {
|
||||
s += 4;
|
||||
getQuadDecalBinarySize(s, x0_quad);
|
||||
getQuadDecalBinarySize(s, x1c_quad);
|
||||
if (x38_DMDL) {
|
||||
s += 4;
|
||||
getQuadDecalBinarySize(s, x0_quad);
|
||||
getQuadDecalBinarySize(s, x1c_quad);
|
||||
if (x38_DMDL)
|
||||
{
|
||||
s += 4;
|
||||
x38_DMDL.binarySize(s);
|
||||
}
|
||||
if (x48_DLFT)
|
||||
{
|
||||
s += 4;
|
||||
x48_DLFT.binarySize(s);
|
||||
}
|
||||
if (x4c_DMOP)
|
||||
{
|
||||
s += 4;
|
||||
x4c_DMOP.binarySize(s);
|
||||
}
|
||||
if (x50_DMRT)
|
||||
{
|
||||
s += 4;
|
||||
x50_DMRT.binarySize(s);
|
||||
}
|
||||
if (x54_DMSC)
|
||||
{
|
||||
s += 4;
|
||||
x54_DMSC.binarySize(s);
|
||||
}
|
||||
if (x58_DMCL)
|
||||
{
|
||||
x58_DMCL.binarySize(s);
|
||||
}
|
||||
if (x5c_24_DMAB)
|
||||
s += 9;
|
||||
if (x5c_25_DMOO)
|
||||
s += 9;
|
||||
x38_DMDL.binarySize(s);
|
||||
}
|
||||
if (x48_DLFT) {
|
||||
s += 4;
|
||||
x48_DLFT.binarySize(s);
|
||||
}
|
||||
if (x4c_DMOP) {
|
||||
s += 4;
|
||||
x4c_DMOP.binarySize(s);
|
||||
}
|
||||
if (x50_DMRT) {
|
||||
s += 4;
|
||||
x50_DMRT.binarySize(s);
|
||||
}
|
||||
if (x54_DMSC) {
|
||||
s += 4;
|
||||
x54_DMSC.binarySize(s);
|
||||
}
|
||||
if (x58_DMCL) {
|
||||
x58_DMCL.binarySize(s);
|
||||
}
|
||||
if (x5c_24_DMAB)
|
||||
s += 9;
|
||||
if (x5c_25_DMOO)
|
||||
s += 9;
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::getQuadDecalBinarySize(size_t& s, const typename DPSM<IDType>::SQuadDescr& quad) const
|
||||
{
|
||||
if (quad.x0_LFT)
|
||||
{
|
||||
s += 4;
|
||||
quad.x0_LFT.binarySize(s);
|
||||
}
|
||||
if (quad.x4_SZE)
|
||||
{
|
||||
s += 4;
|
||||
quad.x4_SZE.binarySize(s);
|
||||
}
|
||||
if (quad.x8_ROT)
|
||||
{
|
||||
s += 4;
|
||||
quad.x8_ROT.binarySize(s);
|
||||
}
|
||||
if (quad.xc_OFF)
|
||||
{
|
||||
s += 4;
|
||||
quad.xc_OFF.binarySize(s);
|
||||
}
|
||||
if (quad.x10_CLR)
|
||||
{
|
||||
s += 4;
|
||||
quad.x10_CLR.binarySize(s);
|
||||
}
|
||||
if (quad.x14_TEX)
|
||||
{
|
||||
s += 4;
|
||||
quad.x14_TEX.binarySize(s);
|
||||
}
|
||||
if (quad.x18_ADD)
|
||||
{
|
||||
s += 4;
|
||||
quad.x18_ADD.binarySize(s);
|
||||
}
|
||||
void DPSM<IDType>::getQuadDecalBinarySize(size_t& s, const typename DPSM<IDType>::SQuadDescr& quad) const {
|
||||
if (quad.x0_LFT) {
|
||||
s += 4;
|
||||
quad.x0_LFT.binarySize(s);
|
||||
}
|
||||
if (quad.x4_SZE) {
|
||||
s += 4;
|
||||
quad.x4_SZE.binarySize(s);
|
||||
}
|
||||
if (quad.x8_ROT) {
|
||||
s += 4;
|
||||
quad.x8_ROT.binarySize(s);
|
||||
}
|
||||
if (quad.xc_OFF) {
|
||||
s += 4;
|
||||
quad.xc_OFF.binarySize(s);
|
||||
}
|
||||
if (quad.x10_CLR) {
|
||||
s += 4;
|
||||
quad.x10_CLR.binarySize(s);
|
||||
}
|
||||
if (quad.x14_TEX) {
|
||||
s += 4;
|
||||
quad.x14_TEX.binarySize(s);
|
||||
}
|
||||
if (quad.x18_ADD) {
|
||||
s += 4;
|
||||
quad.x18_ADD.binarySize(s);
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::_read(athena::io::IStreamReader& r)
|
||||
{
|
||||
uint32_t clsId;
|
||||
void DPSM<IDType>::_read(athena::io::IStreamReader& r) {
|
||||
uint32_t clsId;
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
if (clsId != SBIG('DPSM')) {
|
||||
LogModule.report(logvisor::Warning, "non DPSM provided to DPSM parser");
|
||||
return;
|
||||
}
|
||||
bool loadFirstDesc = false;
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
while (clsId != SBIG('_END')) {
|
||||
switch (clsId) {
|
||||
case SBIG('1SZE'):
|
||||
case SBIG('1LFT'):
|
||||
case SBIG('1ROT'):
|
||||
case SBIG('1OFF'):
|
||||
case SBIG('1CLR'):
|
||||
case SBIG('1TEX'):
|
||||
case SBIG('1ADD'):
|
||||
loadFirstDesc = true;
|
||||
case SBIG('2SZE'):
|
||||
case SBIG('2LFT'):
|
||||
case SBIG('2ROT'):
|
||||
case SBIG('2OFF'):
|
||||
case SBIG('2CLR'):
|
||||
case SBIG('2TEX'):
|
||||
case SBIG('2ADD'):
|
||||
if (loadFirstDesc)
|
||||
readQuadDecalInfo(r, clsId, x0_quad);
|
||||
else
|
||||
readQuadDecalInfo(r, clsId, x1c_quad);
|
||||
break;
|
||||
case SBIG('DMDL'):
|
||||
x38_DMDL.read(r);
|
||||
break;
|
||||
case SBIG('DLFT'):
|
||||
x48_DLFT.read(r);
|
||||
break;
|
||||
case SBIG('DMOP'):
|
||||
x4c_DMOP.read(r);
|
||||
break;
|
||||
case SBIG('DMRT'):
|
||||
x50_DMRT.read(r);
|
||||
break;
|
||||
case SBIG('DMSC'):
|
||||
x54_DMSC.read(r);
|
||||
break;
|
||||
case SBIG('DMCL'):
|
||||
x58_DMCL.read(r);
|
||||
break;
|
||||
case SBIG('DMAB'):
|
||||
r.readUint32();
|
||||
x5c_24_DMAB = r.readBool();
|
||||
break;
|
||||
case SBIG('DMOO'):
|
||||
r.readUint32();
|
||||
x5c_25_DMOO = r.readBool();
|
||||
break;
|
||||
default:
|
||||
LogModule.report(logvisor::Fatal, "Unknown DPSM class %.4s @%" PRIi64, &clsId, r.position());
|
||||
break;
|
||||
}
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
if (clsId != SBIG('DPSM'))
|
||||
{
|
||||
LogModule.report(logvisor::Warning, "non DPSM provided to DPSM parser");
|
||||
return;
|
||||
}
|
||||
bool loadFirstDesc = false;
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
while (clsId != SBIG('_END'))
|
||||
{
|
||||
switch(clsId)
|
||||
{
|
||||
case SBIG('1SZE'):
|
||||
case SBIG('1LFT'):
|
||||
case SBIG('1ROT'):
|
||||
case SBIG('1OFF'):
|
||||
case SBIG('1CLR'):
|
||||
case SBIG('1TEX'):
|
||||
case SBIG('1ADD'):
|
||||
loadFirstDesc = true;
|
||||
case SBIG('2SZE'):
|
||||
case SBIG('2LFT'):
|
||||
case SBIG('2ROT'):
|
||||
case SBIG('2OFF'):
|
||||
case SBIG('2CLR'):
|
||||
case SBIG('2TEX'):
|
||||
case SBIG('2ADD'):
|
||||
if (loadFirstDesc)
|
||||
readQuadDecalInfo(r, clsId, x0_quad);
|
||||
else
|
||||
readQuadDecalInfo(r, clsId, x1c_quad);
|
||||
break;
|
||||
case SBIG('DMDL'):
|
||||
x38_DMDL.read(r);
|
||||
break;
|
||||
case SBIG('DLFT'):
|
||||
x48_DLFT.read(r);
|
||||
break;
|
||||
case SBIG('DMOP'):
|
||||
x4c_DMOP.read(r);
|
||||
break;
|
||||
case SBIG('DMRT'):
|
||||
x50_DMRT.read(r);
|
||||
break;
|
||||
case SBIG('DMSC'):
|
||||
x54_DMSC.read(r);
|
||||
break;
|
||||
case SBIG('DMCL'):
|
||||
x58_DMCL.read(r);
|
||||
break;
|
||||
case SBIG('DMAB'):
|
||||
r.readUint32();
|
||||
x5c_24_DMAB = r.readBool();
|
||||
break;
|
||||
case SBIG('DMOO'):
|
||||
r.readUint32();
|
||||
x5c_25_DMOO = r.readBool();
|
||||
break;
|
||||
default:
|
||||
LogModule.report(logvisor::Fatal, "Unknown DPSM class %.4s @%" PRIi64, &clsId, r.position());
|
||||
break;
|
||||
}
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::_write(athena::io::IStreamWriter& w) const
|
||||
{
|
||||
w.writeBytes("DPSM", 4);
|
||||
writeQuadDecalInfo(w, x0_quad, true);
|
||||
writeQuadDecalInfo(w, x1c_quad, false);
|
||||
if (x38_DMDL)
|
||||
{
|
||||
w.writeBytes("DMDL", 4);
|
||||
x38_DMDL.write(w);
|
||||
}
|
||||
if (x48_DLFT)
|
||||
{
|
||||
w.writeBytes("DLFT", 4);
|
||||
x48_DLFT.write(w);
|
||||
}
|
||||
if (x4c_DMOP)
|
||||
{
|
||||
w.writeBytes("DMOP", 4);
|
||||
x4c_DMOP.write(w);
|
||||
}
|
||||
if (x50_DMRT)
|
||||
{
|
||||
w.writeBytes("DMRT", 4);
|
||||
x50_DMRT.write(w);
|
||||
}
|
||||
if (x54_DMSC)
|
||||
{
|
||||
w.writeBytes("DMSC", 4);
|
||||
x54_DMSC.write(w);
|
||||
}
|
||||
if (x58_DMCL)
|
||||
{
|
||||
w.writeBytes("DMCL", 4);
|
||||
x58_DMCL.write(w);
|
||||
}
|
||||
if (x5c_24_DMAB)
|
||||
w.writeBytes("DMABCNST\x01", 9);
|
||||
if (x5c_25_DMOO)
|
||||
w.writeBytes("DMOOCNST\x01", 9);
|
||||
w.writeBytes("_END", 4);
|
||||
void DPSM<IDType>::_write(athena::io::IStreamWriter& w) const {
|
||||
w.writeBytes("DPSM", 4);
|
||||
writeQuadDecalInfo(w, x0_quad, true);
|
||||
writeQuadDecalInfo(w, x1c_quad, false);
|
||||
if (x38_DMDL) {
|
||||
w.writeBytes("DMDL", 4);
|
||||
x38_DMDL.write(w);
|
||||
}
|
||||
if (x48_DLFT) {
|
||||
w.writeBytes("DLFT", 4);
|
||||
x48_DLFT.write(w);
|
||||
}
|
||||
if (x4c_DMOP) {
|
||||
w.writeBytes("DMOP", 4);
|
||||
x4c_DMOP.write(w);
|
||||
}
|
||||
if (x50_DMRT) {
|
||||
w.writeBytes("DMRT", 4);
|
||||
x50_DMRT.write(w);
|
||||
}
|
||||
if (x54_DMSC) {
|
||||
w.writeBytes("DMSC", 4);
|
||||
x54_DMSC.write(w);
|
||||
}
|
||||
if (x58_DMCL) {
|
||||
w.writeBytes("DMCL", 4);
|
||||
x58_DMCL.write(w);
|
||||
}
|
||||
if (x5c_24_DMAB)
|
||||
w.writeBytes("DMABCNST\x01", 9);
|
||||
if (x5c_25_DMOO)
|
||||
w.writeBytes("DMOOCNST\x01", 9);
|
||||
w.writeBytes("_END", 4);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::writeQuadDecalInfo(athena::io::IStreamWriter& w,
|
||||
const typename DPSM<IDType>::SQuadDescr& quad, bool first) const
|
||||
{
|
||||
if (quad.x0_LFT)
|
||||
{
|
||||
w.writeBytes((first ? "1LFT" : "2LFT"), 4);
|
||||
quad.x0_LFT.write(w);
|
||||
}
|
||||
if (quad.x4_SZE)
|
||||
{
|
||||
w.writeBytes((first ? "1SZE" : "2SZE"), 4);
|
||||
quad.x4_SZE.write(w);
|
||||
}
|
||||
if (quad.x8_ROT)
|
||||
{
|
||||
w.writeBytes((first ? "1ROT" : "2ROT"), 4);
|
||||
quad.x8_ROT.write(w);
|
||||
}
|
||||
if (quad.xc_OFF)
|
||||
{
|
||||
w.writeBytes((first ? "1OFF" : "2OFF"), 4);
|
||||
quad.xc_OFF.write(w);
|
||||
}
|
||||
if (quad.x10_CLR)
|
||||
{
|
||||
w.writeBytes((first ? "1CLR" : "2CLR"), 4);
|
||||
quad.x10_CLR.write(w);
|
||||
}
|
||||
if (quad.x14_TEX)
|
||||
{
|
||||
w.writeBytes((first ? "1TEX" : "2TEX"), 4);
|
||||
quad.x14_TEX.write(w);
|
||||
}
|
||||
if (quad.x18_ADD)
|
||||
{
|
||||
w.writeBytes((first ? "1ADD" : "2ADD"), 4);
|
||||
quad.x18_ADD.write(w);
|
||||
}
|
||||
void DPSM<IDType>::writeQuadDecalInfo(athena::io::IStreamWriter& w, const typename DPSM<IDType>::SQuadDescr& quad,
|
||||
bool first) const {
|
||||
if (quad.x0_LFT) {
|
||||
w.writeBytes((first ? "1LFT" : "2LFT"), 4);
|
||||
quad.x0_LFT.write(w);
|
||||
}
|
||||
if (quad.x4_SZE) {
|
||||
w.writeBytes((first ? "1SZE" : "2SZE"), 4);
|
||||
quad.x4_SZE.write(w);
|
||||
}
|
||||
if (quad.x8_ROT) {
|
||||
w.writeBytes((first ? "1ROT" : "2ROT"), 4);
|
||||
quad.x8_ROT.write(w);
|
||||
}
|
||||
if (quad.xc_OFF) {
|
||||
w.writeBytes((first ? "1OFF" : "2OFF"), 4);
|
||||
quad.xc_OFF.write(w);
|
||||
}
|
||||
if (quad.x10_CLR) {
|
||||
w.writeBytes((first ? "1CLR" : "2CLR"), 4);
|
||||
quad.x10_CLR.write(w);
|
||||
}
|
||||
if (quad.x14_TEX) {
|
||||
w.writeBytes((first ? "1TEX" : "2TEX"), 4);
|
||||
quad.x14_TEX.write(w);
|
||||
}
|
||||
if (quad.x18_ADD) {
|
||||
w.writeBytes((first ? "1ADD" : "2ADD"), 4);
|
||||
quad.x18_ADD.write(w);
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const
|
||||
{
|
||||
if (x0_quad.x14_TEX.m_elem)
|
||||
x0_quad.x14_TEX.m_elem->gatherDependencies(pathsOut);
|
||||
if (x1c_quad.x14_TEX.m_elem)
|
||||
x1c_quad.x14_TEX.m_elem->gatherDependencies(pathsOut);
|
||||
g_curSpec->flattenDependencies(x38_DMDL.id, pathsOut);
|
||||
void DPSM<IDType>::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
||||
if (x0_quad.x14_TEX.m_elem)
|
||||
x0_quad.x14_TEX.m_elem->gatherDependencies(pathsOut);
|
||||
if (x1c_quad.x14_TEX.m_elem)
|
||||
x1c_quad.x14_TEX.m_elem->gatherDependencies(pathsOut);
|
||||
g_curSpec->flattenDependencies(x38_DMDL.id, pathsOut);
|
||||
}
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(DPSM<UniqueID32>)
|
||||
|
@ -421,36 +380,32 @@ template struct DPSM<UniqueID32>;
|
|||
template struct DPSM<UniqueID64>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractDPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen())
|
||||
{
|
||||
DPSM<IDType> dpsm;
|
||||
dpsm.read(rs);
|
||||
athena::io::ToYAMLStream(dpsm, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool ExtractDPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen()) {
|
||||
DPSM<IDType> dpsm;
|
||||
dpsm.read(rs);
|
||||
athena::io::ToYAMLStream(dpsm, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template bool ExtractDPSM<UniqueID32>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
template bool ExtractDPSM<UniqueID64>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
||||
template <class IDType>
|
||||
bool WriteDPSM(const DPSM<IDType>& dpsm, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
dpsm.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
bool WriteDPSM(const DPSM<IDType>& dpsm, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
dpsm.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
template bool WriteDPSM<UniqueID32>(const DPSM<UniqueID32>& dpsm, const hecl::ProjectPath& outPath);
|
||||
template bool WriteDPSM<UniqueID64>(const DPSM<UniqueID64>& dpsm, const hecl::ProjectPath& outPath);
|
||||
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
|
@ -4,46 +4,45 @@
|
|||
#include "PAK.hpp"
|
||||
#include "athena/FileWriter.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle
|
||||
{
|
||||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template <class IDType>
|
||||
struct DPSM : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
struct DPSM : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
|
||||
struct SQuadDescr
|
||||
{
|
||||
IntElementFactory x0_LFT;
|
||||
RealElementFactory x4_SZE;
|
||||
RealElementFactory x8_ROT;
|
||||
VectorElementFactory xc_OFF;
|
||||
ColorElementFactory x10_CLR;
|
||||
UVElementFactory<IDType> x14_TEX;
|
||||
BoolHelper x18_ADD;
|
||||
struct SQuadDescr {
|
||||
IntElementFactory x0_LFT;
|
||||
RealElementFactory x4_SZE;
|
||||
RealElementFactory x8_ROT;
|
||||
VectorElementFactory xc_OFF;
|
||||
ColorElementFactory x10_CLR;
|
||||
UVElementFactory<IDType> x14_TEX;
|
||||
BoolHelper x18_ADD;
|
||||
};
|
||||
|
||||
SQuadDescr x0_quad;
|
||||
SQuadDescr x1c_quad;
|
||||
ChildResourceFactory<IDType> x38_DMDL;
|
||||
IntElementFactory x48_DLFT;
|
||||
VectorElementFactory x4c_DMOP;
|
||||
VectorElementFactory x50_DMRT;
|
||||
VectorElementFactory x54_DMSC;
|
||||
ColorElementFactory x58_DMCL;
|
||||
union {
|
||||
struct {
|
||||
bool x5c_24_DMAB : 1;
|
||||
bool x5c_25_DMOO : 1;
|
||||
};
|
||||
uint8_t dummy;
|
||||
};
|
||||
template <class Reader>
|
||||
void readQuadDecalInfo(Reader& r, uint32_t clsId, SQuadDescr& quad);
|
||||
void writeQuadDecalInfo(athena::io::YAMLDocWriter& w, const SQuadDescr& quad, bool first) const;
|
||||
void getQuadDecalBinarySize(size_t& s, const SQuadDescr& desc) const;
|
||||
void writeQuadDecalInfo(athena::io::IStreamWriter& w, const SQuadDescr& quad, bool first) const;
|
||||
|
||||
SQuadDescr x0_quad;
|
||||
SQuadDescr x1c_quad;
|
||||
ChildResourceFactory<IDType> x38_DMDL;
|
||||
IntElementFactory x48_DLFT;
|
||||
VectorElementFactory x4c_DMOP;
|
||||
VectorElementFactory x50_DMRT;
|
||||
VectorElementFactory x54_DMSC;
|
||||
ColorElementFactory x58_DMCL;
|
||||
union
|
||||
{
|
||||
struct { bool x5c_24_DMAB : 1; bool x5c_25_DMOO : 1;};
|
||||
uint8_t dummy;
|
||||
};
|
||||
template <class Reader>
|
||||
void readQuadDecalInfo(Reader& r, uint32_t clsId, SQuadDescr& quad);
|
||||
void writeQuadDecalInfo(athena::io::YAMLDocWriter& w, const SQuadDescr& quad, bool first) const;
|
||||
void getQuadDecalBinarySize(size_t& s, const SQuadDescr& desc) const;
|
||||
void writeQuadDecalInfo(athena::io::IStreamWriter& w, const SQuadDescr& quad, bool first) const;
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
|
@ -52,5 +51,4 @@ bool ExtractDPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
|||
template <class IDType>
|
||||
bool WriteDPSM(const DPSM<IDType>& dpsm, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
|
@ -6,260 +6,246 @@
|
|||
#include "hecl/Blender/Connection.hpp"
|
||||
#include <cinttypes>
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
template<class DEAFBABE>
|
||||
void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, bool isDcln, atInt32 idx)
|
||||
{
|
||||
os << "material_index = []\n"
|
||||
"col_bm = bmesh.new()\n";
|
||||
for (const atVec3f& vert : db.verts)
|
||||
{
|
||||
zeus::simd_floats f(vert.simd);
|
||||
os.format("col_bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]);
|
||||
template <class DEAFBABE>
|
||||
void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, bool isDcln, atInt32 idx) {
|
||||
os << "material_index = []\n"
|
||||
"col_bm = bmesh.new()\n";
|
||||
for (const atVec3f& vert : db.verts) {
|
||||
zeus::simd_floats f(vert.simd);
|
||||
os.format("col_bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]);
|
||||
}
|
||||
|
||||
os << "col_bm.verts.ensure_lookup_table()\n";
|
||||
|
||||
int triIdx = 0;
|
||||
for (const typename DEAFBABE::Triangle& tri : db.triangleEdgeConnections) {
|
||||
const typename DEAFBABE::Material& triMat = db.materials[db.triMats[triIdx++]];
|
||||
const typename DEAFBABE::Edge& edge0 = db.edgeVertConnections[tri.edges[0]];
|
||||
const typename DEAFBABE::Edge& edge1 = db.edgeVertConnections[tri.edges[1]];
|
||||
const typename DEAFBABE::Edge& edge2 = db.edgeVertConnections[tri.edges[2]];
|
||||
if (!edge0.verts[0] && !edge1.verts[0] && !edge2.verts[0])
|
||||
break;
|
||||
|
||||
int vindices[3];
|
||||
vindices[2] =
|
||||
(edge1.verts[0] != edge0.verts[0] && edge1.verts[0] != edge0.verts[1]) ? edge1.verts[0] : edge1.verts[1];
|
||||
|
||||
if (triMat.flipFace()) {
|
||||
vindices[0] = edge0.verts[1];
|
||||
vindices[1] = edge0.verts[0];
|
||||
} else {
|
||||
vindices[0] = edge0.verts[0];
|
||||
vindices[1] = edge0.verts[1];
|
||||
}
|
||||
|
||||
os << "col_bm.verts.ensure_lookup_table()\n";
|
||||
os << "tri_verts = []\n";
|
||||
os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[0]);
|
||||
os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[1]);
|
||||
os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[2]);
|
||||
|
||||
int triIdx = 0;
|
||||
for (const typename DEAFBABE::Triangle& tri : db.triangleEdgeConnections)
|
||||
{
|
||||
const typename DEAFBABE::Material& triMat = db.materials[db.triMats[triIdx++]];
|
||||
const typename DEAFBABE::Edge& edge0 = db.edgeVertConnections[tri.edges[0]];
|
||||
const typename DEAFBABE::Edge& edge1 = db.edgeVertConnections[tri.edges[1]];
|
||||
const typename DEAFBABE::Edge& edge2 = db.edgeVertConnections[tri.edges[2]];
|
||||
if (!edge0.verts[0] && !edge1.verts[0] && !edge2.verts[0])
|
||||
break;
|
||||
os.format(
|
||||
"face = col_bm.faces.get(tri_verts)\n"
|
||||
"if face is None:\n"
|
||||
" face = col_bm.faces.new(tri_verts)\n"
|
||||
"else:\n"
|
||||
" face = face.copy()\n"
|
||||
" for i in range(3):\n"
|
||||
" face.verts[i].co = tri_verts[i].co\n"
|
||||
" col_bm.verts.ensure_lookup_table()\n"
|
||||
"face.material_index = select_material(0x%016" PRIX64
|
||||
")\n"
|
||||
"face.smooth = False\n"
|
||||
"\n",
|
||||
atUint64(triMat.material));
|
||||
}
|
||||
|
||||
int vindices[3];
|
||||
vindices[2] =
|
||||
(edge1.verts[0] != edge0.verts[0] && edge1.verts[0] != edge0.verts[1]) ?
|
||||
edge1.verts[0] : edge1.verts[1];
|
||||
db.insertNoClimb(os);
|
||||
|
||||
if (triMat.flipFace())
|
||||
{
|
||||
vindices[0] = edge0.verts[1];
|
||||
vindices[1] = edge0.verts[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
vindices[0] = edge0.verts[0];
|
||||
vindices[1] = edge0.verts[1];
|
||||
}
|
||||
if (isDcln)
|
||||
os.format("col_mesh = bpy.data.meshes.new('CMESH_%i')\n", idx);
|
||||
else
|
||||
os << "col_mesh = bpy.data.meshes.new('CMESH')\n";
|
||||
|
||||
os << "tri_verts = []\n";
|
||||
os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[0]);
|
||||
os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[1]);
|
||||
os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[2]);
|
||||
os << "col_bm.to_mesh(col_mesh)\n"
|
||||
"col_mesh_obj = bpy.data.objects.new(col_mesh.name, col_mesh)\n"
|
||||
"\n"
|
||||
"for mat_name in material_index:\n"
|
||||
" mat = material_dict[mat_name]\n"
|
||||
" col_mesh.materials.append(mat)\n"
|
||||
"\n"
|
||||
"bpy.context.scene.objects.link(col_mesh_obj)\n"
|
||||
"bpy.context.scene.objects.active = col_mesh_obj\n"
|
||||
"bpy.ops.object.mode_set(mode='EDIT')\n"
|
||||
"bpy.ops.mesh.tris_convert_to_quads()\n"
|
||||
"bpy.ops.object.mode_set(mode='OBJECT')\n"
|
||||
"bpy.context.scene.objects.active = None\n";
|
||||
if (!isDcln)
|
||||
os << "col_mesh_obj.layers[1] = True\n"
|
||||
"col_mesh_obj.layers[0] = False\n";
|
||||
|
||||
os.format("face = col_bm.faces.get(tri_verts)\n"
|
||||
"if face is None:\n"
|
||||
" face = col_bm.faces.new(tri_verts)\n"
|
||||
"else:\n"
|
||||
" face = face.copy()\n"
|
||||
" for i in range(3):\n"
|
||||
" face.verts[i].co = tri_verts[i].co\n"
|
||||
" col_bm.verts.ensure_lookup_table()\n"
|
||||
"face.material_index = select_material(0x%016" PRIX64 ")\n"
|
||||
"face.smooth = False\n"
|
||||
"\n",
|
||||
atUint64(triMat.material));
|
||||
}
|
||||
|
||||
db.insertNoClimb(os);
|
||||
|
||||
if (isDcln)
|
||||
os.format("col_mesh = bpy.data.meshes.new('CMESH_%i')\n", idx);
|
||||
else
|
||||
os << "col_mesh = bpy.data.meshes.new('CMESH')\n";
|
||||
|
||||
os << "col_bm.to_mesh(col_mesh)\n"
|
||||
"col_mesh_obj = bpy.data.objects.new(col_mesh.name, col_mesh)\n"
|
||||
"\n"
|
||||
"for mat_name in material_index:\n"
|
||||
" mat = material_dict[mat_name]\n"
|
||||
" col_mesh.materials.append(mat)\n"
|
||||
"\n"
|
||||
"bpy.context.scene.objects.link(col_mesh_obj)\n"
|
||||
"bpy.context.scene.objects.active = col_mesh_obj\n"
|
||||
"bpy.ops.object.mode_set(mode='EDIT')\n"
|
||||
"bpy.ops.mesh.tris_convert_to_quads()\n"
|
||||
"bpy.ops.object.mode_set(mode='OBJECT')\n"
|
||||
"bpy.context.scene.objects.active = None\n";
|
||||
if (!isDcln)
|
||||
os << "col_mesh_obj.layers[1] = True\n"
|
||||
"col_mesh_obj.layers[0] = False\n";
|
||||
|
||||
|
||||
os << "col_mesh_obj.draw_type = 'SOLID'\n"
|
||||
"col_mesh_obj.game.physics_type = 'STATIC'\n"
|
||||
"\n";
|
||||
os << "col_mesh_obj.draw_type = 'SOLID'\n"
|
||||
"col_mesh_obj.game.physics_type = 'STATIC'\n"
|
||||
"\n";
|
||||
}
|
||||
|
||||
template void DeafBabeSendToBlender<DNAMP1::DeafBabe>(hecl::blender::PyOutStream& os, const DNAMP1::DeafBabe& db, bool isDcln, atInt32 idx);
|
||||
template void DeafBabeSendToBlender<DNAMP2::DeafBabe>(hecl::blender::PyOutStream& os, const DNAMP2::DeafBabe& db, bool isDcln, atInt32 idx);
|
||||
template void DeafBabeSendToBlender<DNAMP1::DCLN::Collision>(hecl::blender::PyOutStream& os, const DNAMP1::DCLN::Collision& db, bool isDcln, atInt32 idx);
|
||||
template void DeafBabeSendToBlender<DNAMP1::DeafBabe>(hecl::blender::PyOutStream& os, const DNAMP1::DeafBabe& db,
|
||||
bool isDcln, atInt32 idx);
|
||||
template void DeafBabeSendToBlender<DNAMP2::DeafBabe>(hecl::blender::PyOutStream& os, const DNAMP2::DeafBabe& db,
|
||||
bool isDcln, atInt32 idx);
|
||||
template void DeafBabeSendToBlender<DNAMP1::DCLN::Collision>(hecl::blender::PyOutStream& os,
|
||||
const DNAMP1::DCLN::Collision& db, bool isDcln,
|
||||
atInt32 idx);
|
||||
|
||||
template<class DEAFBABE>
|
||||
static void PopulateAreaFields(DEAFBABE& db,
|
||||
const hecl::blender::ColMesh& colMesh,
|
||||
const zeus::CAABox& fullAABB,
|
||||
std::enable_if_t<std::is_same<DEAFBABE, DNAMP1::DeafBabe>::value ||
|
||||
std::is_same<DEAFBABE, DNAMP2::DeafBabe>::value, int>* = 0)
|
||||
{
|
||||
AROTBuilder builder;
|
||||
auto octree = builder.buildCol(colMesh, db.rootNodeType);
|
||||
static_cast<std::unique_ptr<atUint8[]>&>(db.bspTree) = std::move(octree.first);
|
||||
db.bspSize = octree.second;
|
||||
template <class DEAFBABE>
|
||||
static void PopulateAreaFields(
|
||||
DEAFBABE& db, const hecl::blender::ColMesh& colMesh, const zeus::CAABox& fullAABB,
|
||||
std::enable_if_t<std::is_same<DEAFBABE, DNAMP1::DeafBabe>::value || std::is_same<DEAFBABE, DNAMP2::DeafBabe>::value,
|
||||
int>* = 0) {
|
||||
AROTBuilder builder;
|
||||
auto octree = builder.buildCol(colMesh, db.rootNodeType);
|
||||
static_cast<std::unique_ptr<atUint8[]>&>(db.bspTree) = std::move(octree.first);
|
||||
db.bspSize = octree.second;
|
||||
|
||||
db.unk1 = 0x1000000;
|
||||
size_t dbSize = 0;
|
||||
db.binarySize(dbSize);
|
||||
db.length = dbSize - 8;
|
||||
db.magic = 0xDEAFBABE;
|
||||
db.version = 3;
|
||||
db.aabb[0] = fullAABB.min;
|
||||
db.aabb[1] = fullAABB.max;
|
||||
db.unk1 = 0x1000000;
|
||||
size_t dbSize = 0;
|
||||
db.binarySize(dbSize);
|
||||
db.length = dbSize - 8;
|
||||
db.magic = 0xDEAFBABE;
|
||||
db.version = 3;
|
||||
db.aabb[0] = fullAABB.min;
|
||||
db.aabb[1] = fullAABB.max;
|
||||
}
|
||||
|
||||
template<class DEAFBABE>
|
||||
static void PopulateAreaFields(DEAFBABE& db,
|
||||
const hecl::blender::ColMesh& colMesh,
|
||||
const zeus::CAABox& fullAABB,
|
||||
std::enable_if_t<std::is_same<DEAFBABE, DNAMP1::DCLN::Collision>::value, int>* = 0)
|
||||
{
|
||||
db.magic = 0xDEAFBABE;
|
||||
db.version = 2;
|
||||
db.memSize = 0;
|
||||
template <class DEAFBABE>
|
||||
static void PopulateAreaFields(DEAFBABE& db, const hecl::blender::ColMesh& colMesh, const zeus::CAABox& fullAABB,
|
||||
std::enable_if_t<std::is_same<DEAFBABE, DNAMP1::DCLN::Collision>::value, int>* = 0) {
|
||||
db.magic = 0xDEAFBABE;
|
||||
db.version = 2;
|
||||
db.memSize = 0;
|
||||
}
|
||||
|
||||
class MaterialPool
|
||||
{
|
||||
std::unordered_map<u64, int> m_materials;
|
||||
class MaterialPool {
|
||||
std::unordered_map<u64, int> m_materials;
|
||||
|
||||
public:
|
||||
template <class M, class V>
|
||||
int AddOrLookup(const M& mat, V& vec)
|
||||
{
|
||||
auto search = m_materials.find(mat.material);
|
||||
if (search != m_materials.end())
|
||||
return search->second;
|
||||
auto idx = int(vec.size());
|
||||
vec.push_back(mat);
|
||||
m_materials[mat.material] = idx;
|
||||
return idx;
|
||||
}
|
||||
template <class M, class V>
|
||||
int AddOrLookup(const M& mat, V& vec) {
|
||||
auto search = m_materials.find(mat.material);
|
||||
if (search != m_materials.end())
|
||||
return search->second;
|
||||
auto idx = int(vec.size());
|
||||
vec.push_back(mat);
|
||||
m_materials[mat.material] = idx;
|
||||
return idx;
|
||||
}
|
||||
};
|
||||
|
||||
template<class DEAFBABE>
|
||||
void DeafBabeBuildFromBlender(DEAFBABE& db, const hecl::blender::ColMesh& colMesh)
|
||||
{
|
||||
using BlendMat = hecl::blender::ColMesh::Material;
|
||||
template <class DEAFBABE>
|
||||
void DeafBabeBuildFromBlender(DEAFBABE& db, const hecl::blender::ColMesh& colMesh) {
|
||||
using BlendMat = hecl::blender::ColMesh::Material;
|
||||
|
||||
auto MakeMat = [](const BlendMat& mat, bool flipFace) -> typename DEAFBABE::Material
|
||||
{
|
||||
typename DEAFBABE::Material dbMat = {};
|
||||
dbMat.setUnknown(mat.unknown);
|
||||
dbMat.setSurfaceStone(mat.surfaceStone);
|
||||
dbMat.setSurfaceMetal(mat.surfaceMetal);
|
||||
dbMat.setSurfaceGrass(mat.surfaceGrass);
|
||||
dbMat.setSurfaceIce(mat.surfaceIce);
|
||||
dbMat.setPillar(mat.pillar);
|
||||
dbMat.setSurfaceMetalGrating(mat.surfaceMetalGrating);
|
||||
dbMat.setSurfacePhazon(mat.surfacePhazon);
|
||||
dbMat.setSurfaceDirt(mat.surfaceDirt);
|
||||
dbMat.setSurfaceLava(mat.surfaceLava);
|
||||
dbMat.setSurfaceSPMetal(mat.surfaceSPMetal);
|
||||
dbMat.setSurfaceLavaStone(mat.surfaceLavaStone);
|
||||
dbMat.setSurfaceSnow(mat.surfaceSnow);
|
||||
dbMat.setSurfaceMudSlow(mat.surfaceMudSlow);
|
||||
dbMat.setSurfaceFabric(mat.surfaceFabric);
|
||||
dbMat.setHalfPipe(mat.halfPipe);
|
||||
dbMat.setSurfaceMud(mat.surfaceMud);
|
||||
dbMat.setSurfaceGlass(mat.surfaceGlass);
|
||||
dbMat.setUnused3(mat.unused3);
|
||||
dbMat.setUnused4(mat.unused4);
|
||||
dbMat.setSurfaceShield(mat.surfaceShield);
|
||||
dbMat.setSurfaceSand(mat.surfaceSand);
|
||||
dbMat.setSurfaceMothOrSeedOrganics(mat.surfaceMothOrSeedOrganics);
|
||||
dbMat.setSurfaceWeb(mat.surfaceWeb);
|
||||
dbMat.setProjectilePassthrough(mat.projPassthrough);
|
||||
dbMat.setSolid(mat.solid);
|
||||
dbMat.setNoPlatformCollision(mat.noPlatformCollision);
|
||||
dbMat.setCameraPassthrough(mat.camPassthrough);
|
||||
dbMat.setSurfaceWood(mat.surfaceWood);
|
||||
dbMat.setSurfaceOrganic(mat.surfaceOrganic);
|
||||
dbMat.setNoEdgeCollision(mat.noEdgeCollision);
|
||||
dbMat.setSurfaceRubber(mat.surfaceRubber);
|
||||
dbMat.setSeeThrough(mat.seeThrough);
|
||||
dbMat.setScanPassthrough(mat.scanPassthrough);
|
||||
dbMat.setAiPassthrough(mat.aiPassthrough);
|
||||
dbMat.setCeiling(mat.ceiling);
|
||||
dbMat.setWall(mat.wall);
|
||||
dbMat.setFloor(mat.floor);
|
||||
dbMat.setAiBlock(mat.aiBlock);
|
||||
dbMat.setJumpNotAllowed(mat.jumpNotAllowed);
|
||||
dbMat.setSpiderBall(mat.spiderBall);
|
||||
dbMat.setScrewAttackWallJump(mat.screwAttackWallJump);
|
||||
dbMat.setFlipFace(flipFace);
|
||||
return dbMat;
|
||||
};
|
||||
auto MakeMat = [](const BlendMat& mat, bool flipFace) -> typename DEAFBABE::Material {
|
||||
typename DEAFBABE::Material dbMat = {};
|
||||
dbMat.setUnknown(mat.unknown);
|
||||
dbMat.setSurfaceStone(mat.surfaceStone);
|
||||
dbMat.setSurfaceMetal(mat.surfaceMetal);
|
||||
dbMat.setSurfaceGrass(mat.surfaceGrass);
|
||||
dbMat.setSurfaceIce(mat.surfaceIce);
|
||||
dbMat.setPillar(mat.pillar);
|
||||
dbMat.setSurfaceMetalGrating(mat.surfaceMetalGrating);
|
||||
dbMat.setSurfacePhazon(mat.surfacePhazon);
|
||||
dbMat.setSurfaceDirt(mat.surfaceDirt);
|
||||
dbMat.setSurfaceLava(mat.surfaceLava);
|
||||
dbMat.setSurfaceSPMetal(mat.surfaceSPMetal);
|
||||
dbMat.setSurfaceLavaStone(mat.surfaceLavaStone);
|
||||
dbMat.setSurfaceSnow(mat.surfaceSnow);
|
||||
dbMat.setSurfaceMudSlow(mat.surfaceMudSlow);
|
||||
dbMat.setSurfaceFabric(mat.surfaceFabric);
|
||||
dbMat.setHalfPipe(mat.halfPipe);
|
||||
dbMat.setSurfaceMud(mat.surfaceMud);
|
||||
dbMat.setSurfaceGlass(mat.surfaceGlass);
|
||||
dbMat.setUnused3(mat.unused3);
|
||||
dbMat.setUnused4(mat.unused4);
|
||||
dbMat.setSurfaceShield(mat.surfaceShield);
|
||||
dbMat.setSurfaceSand(mat.surfaceSand);
|
||||
dbMat.setSurfaceMothOrSeedOrganics(mat.surfaceMothOrSeedOrganics);
|
||||
dbMat.setSurfaceWeb(mat.surfaceWeb);
|
||||
dbMat.setProjectilePassthrough(mat.projPassthrough);
|
||||
dbMat.setSolid(mat.solid);
|
||||
dbMat.setNoPlatformCollision(mat.noPlatformCollision);
|
||||
dbMat.setCameraPassthrough(mat.camPassthrough);
|
||||
dbMat.setSurfaceWood(mat.surfaceWood);
|
||||
dbMat.setSurfaceOrganic(mat.surfaceOrganic);
|
||||
dbMat.setNoEdgeCollision(mat.noEdgeCollision);
|
||||
dbMat.setSurfaceRubber(mat.surfaceRubber);
|
||||
dbMat.setSeeThrough(mat.seeThrough);
|
||||
dbMat.setScanPassthrough(mat.scanPassthrough);
|
||||
dbMat.setAiPassthrough(mat.aiPassthrough);
|
||||
dbMat.setCeiling(mat.ceiling);
|
||||
dbMat.setWall(mat.wall);
|
||||
dbMat.setFloor(mat.floor);
|
||||
dbMat.setAiBlock(mat.aiBlock);
|
||||
dbMat.setJumpNotAllowed(mat.jumpNotAllowed);
|
||||
dbMat.setSpiderBall(mat.spiderBall);
|
||||
dbMat.setScrewAttackWallJump(mat.screwAttackWallJump);
|
||||
dbMat.setFlipFace(flipFace);
|
||||
return dbMat;
|
||||
};
|
||||
|
||||
MaterialPool matPool;
|
||||
db.materials.reserve(colMesh.materials.size() * 2);
|
||||
MaterialPool matPool;
|
||||
db.materials.reserve(colMesh.materials.size() * 2);
|
||||
|
||||
zeus::CAABox fullAABB;
|
||||
zeus::CAABox fullAABB;
|
||||
|
||||
db.verts.reserve(colMesh.verts.size());
|
||||
db.vertMats.resize(colMesh.verts.size());
|
||||
for (const auto& vert : colMesh.verts)
|
||||
{
|
||||
fullAABB.accumulateBounds(zeus::CVector3f(vert));
|
||||
db.verts.push_back(vert);
|
||||
db.verts.reserve(colMesh.verts.size());
|
||||
db.vertMats.resize(colMesh.verts.size());
|
||||
for (const auto& vert : colMesh.verts) {
|
||||
fullAABB.accumulateBounds(zeus::CVector3f(vert));
|
||||
db.verts.push_back(vert);
|
||||
}
|
||||
db.vertMatsCount = colMesh.verts.size();
|
||||
db.vertCount = colMesh.verts.size();
|
||||
|
||||
db.edgeVertConnections.reserve(colMesh.edges.size());
|
||||
db.edgeMats.resize(colMesh.edges.size());
|
||||
for (const auto& edge : colMesh.edges) {
|
||||
db.edgeVertConnections.emplace_back();
|
||||
db.edgeVertConnections.back().verts[0] = edge.verts[0];
|
||||
db.edgeVertConnections.back().verts[1] = edge.verts[1];
|
||||
}
|
||||
db.edgeMatsCount = colMesh.edges.size();
|
||||
db.edgeVertsCount = colMesh.edges.size();
|
||||
|
||||
db.triMats.reserve(colMesh.trianges.size());
|
||||
db.triangleEdgeConnections.reserve(colMesh.trianges.size());
|
||||
for (const auto& tri : colMesh.trianges) {
|
||||
int triMatIdx = matPool.AddOrLookup(MakeMat(colMesh.materials[tri.matIdx], tri.flip), db.materials);
|
||||
db.triMats.push_back(triMatIdx);
|
||||
|
||||
db.triangleEdgeConnections.emplace_back();
|
||||
db.triangleEdgeConnections.back().edges[0] = tri.edges[0];
|
||||
db.triangleEdgeConnections.back().edges[1] = tri.edges[1];
|
||||
db.triangleEdgeConnections.back().edges[2] = tri.edges[2];
|
||||
|
||||
for (int e = 0; e < 3; ++e) {
|
||||
db.edgeMats[tri.edges[e]] = triMatIdx;
|
||||
for (int v = 0; v < 2; ++v)
|
||||
db.vertMats[colMesh.edges[e].verts[v]] = triMatIdx;
|
||||
}
|
||||
db.vertMatsCount = colMesh.verts.size();
|
||||
db.vertCount = colMesh.verts.size();
|
||||
}
|
||||
db.triMatsCount = colMesh.trianges.size();
|
||||
db.triangleEdgesCount = colMesh.trianges.size() * 3;
|
||||
|
||||
db.edgeVertConnections.reserve(colMesh.edges.size());
|
||||
db.edgeMats.resize(colMesh.edges.size());
|
||||
for (const auto& edge : colMesh.edges)
|
||||
{
|
||||
db.edgeVertConnections.emplace_back();
|
||||
db.edgeVertConnections.back().verts[0] = edge.verts[0];
|
||||
db.edgeVertConnections.back().verts[1] = edge.verts[1];
|
||||
}
|
||||
db.edgeMatsCount = colMesh.edges.size();
|
||||
db.edgeVertsCount = colMesh.edges.size();
|
||||
db.materialCount = db.materials.size();
|
||||
|
||||
db.triMats.reserve(colMesh.trianges.size());
|
||||
db.triangleEdgeConnections.reserve(colMesh.trianges.size());
|
||||
for (const auto& tri : colMesh.trianges)
|
||||
{
|
||||
int triMatIdx = matPool.AddOrLookup(MakeMat(colMesh.materials[tri.matIdx], tri.flip), db.materials);
|
||||
db.triMats.push_back(triMatIdx);
|
||||
|
||||
db.triangleEdgeConnections.emplace_back();
|
||||
db.triangleEdgeConnections.back().edges[0] = tri.edges[0];
|
||||
db.triangleEdgeConnections.back().edges[1] = tri.edges[1];
|
||||
db.triangleEdgeConnections.back().edges[2] = tri.edges[2];
|
||||
|
||||
for (int e=0 ; e<3 ; ++e)
|
||||
{
|
||||
db.edgeMats[tri.edges[e]] = triMatIdx;
|
||||
for (int v=0 ; v<2 ; ++v)
|
||||
db.vertMats[colMesh.edges[e].verts[v]] = triMatIdx;
|
||||
}
|
||||
}
|
||||
db.triMatsCount = colMesh.trianges.size();
|
||||
db.triangleEdgesCount = colMesh.trianges.size() * 3;
|
||||
|
||||
db.materialCount = db.materials.size();
|
||||
|
||||
PopulateAreaFields(db, colMesh, fullAABB);
|
||||
PopulateAreaFields(db, colMesh, fullAABB);
|
||||
}
|
||||
|
||||
template void DeafBabeBuildFromBlender<DNAMP1::DeafBabe>(DNAMP1::DeafBabe& db, const hecl::blender::ColMesh& colMesh);
|
||||
template void DeafBabeBuildFromBlender<DNAMP2::DeafBabe>(DNAMP2::DeafBabe& db, const hecl::blender::ColMesh& colMesh);
|
||||
template void DeafBabeBuildFromBlender<DNAMP1::DCLN::Collision>(DNAMP1::DCLN::Collision& db, const hecl::blender::ColMesh& colMesh);
|
||||
template void DeafBabeBuildFromBlender<DNAMP1::DCLN::Collision>(DNAMP1::DCLN::Collision& db,
|
||||
const hecl::blender::ColMesh& colMesh);
|
||||
|
||||
}
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,21 +2,14 @@
|
|||
|
||||
#include "DNACommon.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
enum class BspNodeType : atUint32
|
||||
{
|
||||
Invalid,
|
||||
Branch,
|
||||
Leaf
|
||||
};
|
||||
enum class BspNodeType : atUint32 { Invalid, Branch, Leaf };
|
||||
|
||||
template<class DEAFBABE>
|
||||
template <class DEAFBABE>
|
||||
void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, bool isDcln = false, atInt32 idx = -1);
|
||||
|
||||
template<class DEAFBABE>
|
||||
template <class DEAFBABE>
|
||||
void DeafBabeBuildFromBlender(DEAFBABE& db, const hecl::blender::ColMesh& colMesh);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,20 +2,17 @@
|
|||
|
||||
#include "DNACommon.hpp"
|
||||
|
||||
namespace DataSpec::DNACommon
|
||||
{
|
||||
struct EGMC : public BigDNA
|
||||
{
|
||||
namespace DataSpec::DNACommon {
|
||||
struct EGMC : public BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> count;
|
||||
|
||||
struct Object : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> count;
|
||||
Value<atUint32> mesh;
|
||||
Value<atUint32> instanceId;
|
||||
};
|
||||
|
||||
struct Object : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> mesh;
|
||||
Value<atUint32> instanceId;
|
||||
};
|
||||
|
||||
Vector<Object, AT_DNA_COUNT(count)> objects;
|
||||
Vector<Object, AT_DNA_COUNT(count)> objects;
|
||||
};
|
||||
}
|
||||
} // namespace DataSpec::DNACommon
|
||||
|
|
|
@ -1,502 +1,449 @@
|
|||
#include "ELSC.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle
|
||||
{
|
||||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template <class IDType>
|
||||
void ELSM<IDType>::_read(athena::io::IStreamReader& r)
|
||||
{
|
||||
uint32_t clsId;
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
if (clsId != SBIG('ELSM'))
|
||||
{
|
||||
LogModule.report(logvisor::Warning, "non ELSM provided to ELSM parser");
|
||||
return;
|
||||
}
|
||||
void ELSM<IDType>::_read(athena::io::IStreamReader& r) {
|
||||
uint32_t clsId;
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
if (clsId != SBIG('ELSM')) {
|
||||
LogModule.report(logvisor::Warning, "non ELSM provided to ELSM parser");
|
||||
return;
|
||||
}
|
||||
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
while (clsId != SBIG('_END'))
|
||||
{
|
||||
switch(clsId)
|
||||
{
|
||||
case SBIG('LIFE'):
|
||||
x0_LIFE.read(r);
|
||||
break;
|
||||
case SBIG('SLIF'):
|
||||
x4_SLIF.read(r);
|
||||
break;
|
||||
case SBIG('GRAT'):
|
||||
x8_GRAT.read(r);
|
||||
break;
|
||||
case SBIG('SCNT'):
|
||||
xc_SCNT.read(r);
|
||||
break;
|
||||
case SBIG('SSEG'):
|
||||
x10_SSEG.read(r);
|
||||
break;
|
||||
case SBIG('COLR'):
|
||||
x14_COLR.read(r);
|
||||
break;
|
||||
case SBIG('IEMT'):
|
||||
x18_IEMT.read(r);
|
||||
break;
|
||||
case SBIG('FEMT'):
|
||||
x1c_FEMT.read(r);
|
||||
break;
|
||||
case SBIG('AMPL'):
|
||||
x20_AMPL.read(r);
|
||||
break;
|
||||
case SBIG('AMPD'):
|
||||
x24_AMPD.read(r);
|
||||
break;
|
||||
case SBIG('LWD1'):
|
||||
x28_LWD1.read(r);
|
||||
break;
|
||||
case SBIG('LWD2'):
|
||||
x2c_LWD2.read(r);
|
||||
break;
|
||||
case SBIG('LWD3'):
|
||||
x30_LWD3.read(r);
|
||||
break;
|
||||
case SBIG('LCL1'):
|
||||
x34_LCL1.read(r);
|
||||
break;
|
||||
case SBIG('LCL2'):
|
||||
x38_LCL2.read(r);
|
||||
break;
|
||||
case SBIG('LCL3'):
|
||||
x3c_LCL3.read(r);
|
||||
break;
|
||||
case SBIG('SSWH'):
|
||||
x40_SSWH.read(r);
|
||||
break;
|
||||
case SBIG('GPSM'):
|
||||
x50_GPSM.read(r);
|
||||
break;
|
||||
case SBIG('EPSM'):
|
||||
x60_EPSM.read(r);
|
||||
break;
|
||||
case SBIG('ZERY'):
|
||||
x70_ZERY.read(r);
|
||||
break;
|
||||
default:
|
||||
LogModule.report(logvisor::Fatal, "Unknown ELSM class %.4s @%" PRIi64, &clsId, r.position());
|
||||
break;
|
||||
}
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
while (clsId != SBIG('_END')) {
|
||||
switch (clsId) {
|
||||
case SBIG('LIFE'):
|
||||
x0_LIFE.read(r);
|
||||
break;
|
||||
case SBIG('SLIF'):
|
||||
x4_SLIF.read(r);
|
||||
break;
|
||||
case SBIG('GRAT'):
|
||||
x8_GRAT.read(r);
|
||||
break;
|
||||
case SBIG('SCNT'):
|
||||
xc_SCNT.read(r);
|
||||
break;
|
||||
case SBIG('SSEG'):
|
||||
x10_SSEG.read(r);
|
||||
break;
|
||||
case SBIG('COLR'):
|
||||
x14_COLR.read(r);
|
||||
break;
|
||||
case SBIG('IEMT'):
|
||||
x18_IEMT.read(r);
|
||||
break;
|
||||
case SBIG('FEMT'):
|
||||
x1c_FEMT.read(r);
|
||||
break;
|
||||
case SBIG('AMPL'):
|
||||
x20_AMPL.read(r);
|
||||
break;
|
||||
case SBIG('AMPD'):
|
||||
x24_AMPD.read(r);
|
||||
break;
|
||||
case SBIG('LWD1'):
|
||||
x28_LWD1.read(r);
|
||||
break;
|
||||
case SBIG('LWD2'):
|
||||
x2c_LWD2.read(r);
|
||||
break;
|
||||
case SBIG('LWD3'):
|
||||
x30_LWD3.read(r);
|
||||
break;
|
||||
case SBIG('LCL1'):
|
||||
x34_LCL1.read(r);
|
||||
break;
|
||||
case SBIG('LCL2'):
|
||||
x38_LCL2.read(r);
|
||||
break;
|
||||
case SBIG('LCL3'):
|
||||
x3c_LCL3.read(r);
|
||||
break;
|
||||
case SBIG('SSWH'):
|
||||
x40_SSWH.read(r);
|
||||
break;
|
||||
case SBIG('GPSM'):
|
||||
x50_GPSM.read(r);
|
||||
break;
|
||||
case SBIG('EPSM'):
|
||||
x60_EPSM.read(r);
|
||||
break;
|
||||
case SBIG('ZERY'):
|
||||
x70_ZERY.read(r);
|
||||
break;
|
||||
default:
|
||||
LogModule.report(logvisor::Fatal, "Unknown ELSM class %.4s @%" PRIi64, &clsId, r.position());
|
||||
break;
|
||||
}
|
||||
r.readBytesToBuf(&clsId, 4);
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void ELSM<IDType>::_write(athena::io::IStreamWriter& w) const
|
||||
{
|
||||
w.writeBytes((atInt8*)"ELSM", 4);
|
||||
if (x0_LIFE)
|
||||
{
|
||||
w.writeBytes((atInt8*)"LIFE", 4);
|
||||
x0_LIFE.write(w);
|
||||
}
|
||||
if (x4_SLIF)
|
||||
{
|
||||
w.writeBytes((atInt8*)"SLIF", 4);
|
||||
x4_SLIF.write(w);
|
||||
}
|
||||
if (x8_GRAT)
|
||||
{
|
||||
w.writeBytes((atInt8*)"GRAT", 4);
|
||||
x8_GRAT.write(w);
|
||||
}
|
||||
if (xc_SCNT)
|
||||
{
|
||||
w.writeBytes((atInt8*)"SCNT", 4);
|
||||
xc_SCNT.write(w);
|
||||
}
|
||||
if (x10_SSEG)
|
||||
{
|
||||
w.writeBytes((atInt8*)"SSEG", 4);
|
||||
x10_SSEG.write(w);
|
||||
}
|
||||
if (x14_COLR)
|
||||
{
|
||||
w.writeBytes((atInt8*)"COLR", 4);
|
||||
x14_COLR.write(w);
|
||||
}
|
||||
if (x18_IEMT)
|
||||
{
|
||||
w.writeBytes((atInt8*)"IEMT", 4);
|
||||
x18_IEMT.write(w);
|
||||
}
|
||||
if (x1c_FEMT)
|
||||
{
|
||||
w.writeBytes((atInt8*)"FEMT", 4);
|
||||
x1c_FEMT.write(w);
|
||||
}
|
||||
if (x20_AMPL)
|
||||
{
|
||||
w.writeBytes((atInt8*)"AMPL", 4);
|
||||
x20_AMPL.write(w);
|
||||
}
|
||||
if (x24_AMPD)
|
||||
{
|
||||
w.writeBytes((atInt8*)"AMPD", 4);
|
||||
x24_AMPD.write(w);
|
||||
}
|
||||
if (x28_LWD1)
|
||||
{
|
||||
w.writeBytes((atInt8*)"LWD1", 4);
|
||||
x28_LWD1.write(w);
|
||||
}
|
||||
if (x2c_LWD2)
|
||||
{
|
||||
w.writeBytes((atInt8*)"LWD2", 4);
|
||||
x2c_LWD2.write(w);
|
||||
}
|
||||
if (x30_LWD3)
|
||||
{
|
||||
w.writeBytes((atInt8*)"LWD3", 4);
|
||||
x30_LWD3.write(w);
|
||||
}
|
||||
if (x34_LCL1)
|
||||
{
|
||||
w.writeBytes((atInt8*)"LCL1", 4);
|
||||
x34_LCL1.write(w);
|
||||
}
|
||||
if (x38_LCL2)
|
||||
{
|
||||
w.writeBytes((atInt8*)"LCL2", 4);
|
||||
x38_LCL2.write(w);
|
||||
}
|
||||
if (x3c_LCL3)
|
||||
{
|
||||
w.writeBytes((atInt8*)"LCL3", 4);
|
||||
x3c_LCL3.write(w);
|
||||
}
|
||||
if (x40_SSWH)
|
||||
{
|
||||
w.writeBytes((atInt8*)"SSWH", 4);
|
||||
x40_SSWH.write(w);
|
||||
}
|
||||
if (x50_GPSM)
|
||||
{
|
||||
w.writeBytes((atInt8*)"GPSM", 4);
|
||||
x50_GPSM.write(w);
|
||||
}
|
||||
if (x60_EPSM)
|
||||
{
|
||||
w.writeBytes((atInt8*)"EPSM", 4);
|
||||
x60_EPSM.write(w);
|
||||
}
|
||||
if (x70_ZERY)
|
||||
{
|
||||
w.writeBytes((atInt8*)"ZERY", 4);
|
||||
x70_ZERY.write(w);
|
||||
}
|
||||
w.writeBytes("_END", 4);
|
||||
void ELSM<IDType>::_write(athena::io::IStreamWriter& w) const {
|
||||
w.writeBytes((atInt8*)"ELSM", 4);
|
||||
if (x0_LIFE) {
|
||||
w.writeBytes((atInt8*)"LIFE", 4);
|
||||
x0_LIFE.write(w);
|
||||
}
|
||||
if (x4_SLIF) {
|
||||
w.writeBytes((atInt8*)"SLIF", 4);
|
||||
x4_SLIF.write(w);
|
||||
}
|
||||
if (x8_GRAT) {
|
||||
w.writeBytes((atInt8*)"GRAT", 4);
|
||||
x8_GRAT.write(w);
|
||||
}
|
||||
if (xc_SCNT) {
|
||||
w.writeBytes((atInt8*)"SCNT", 4);
|
||||
xc_SCNT.write(w);
|
||||
}
|
||||
if (x10_SSEG) {
|
||||
w.writeBytes((atInt8*)"SSEG", 4);
|
||||
x10_SSEG.write(w);
|
||||
}
|
||||
if (x14_COLR) {
|
||||
w.writeBytes((atInt8*)"COLR", 4);
|
||||
x14_COLR.write(w);
|
||||
}
|
||||
if (x18_IEMT) {
|
||||
w.writeBytes((atInt8*)"IEMT", 4);
|
||||
x18_IEMT.write(w);
|
||||
}
|
||||
if (x1c_FEMT) {
|
||||
w.writeBytes((atInt8*)"FEMT", 4);
|
||||
x1c_FEMT.write(w);
|
||||
}
|
||||
if (x20_AMPL) {
|
||||
w.writeBytes((atInt8*)"AMPL", 4);
|
||||
x20_AMPL.write(w);
|
||||
}
|
||||
if (x24_AMPD) {
|
||||
w.writeBytes((atInt8*)"AMPD", 4);
|
||||
x24_AMPD.write(w);
|
||||
}
|
||||
if (x28_LWD1) {
|
||||
w.writeBytes((atInt8*)"LWD1", 4);
|
||||
x28_LWD1.write(w);
|
||||
}
|
||||
if (x2c_LWD2) {
|
||||
w.writeBytes((atInt8*)"LWD2", 4);
|
||||
x2c_LWD2.write(w);
|
||||
}
|
||||
if (x30_LWD3) {
|
||||
w.writeBytes((atInt8*)"LWD3", 4);
|
||||
x30_LWD3.write(w);
|
||||
}
|
||||
if (x34_LCL1) {
|
||||
w.writeBytes((atInt8*)"LCL1", 4);
|
||||
x34_LCL1.write(w);
|
||||
}
|
||||
if (x38_LCL2) {
|
||||
w.writeBytes((atInt8*)"LCL2", 4);
|
||||
x38_LCL2.write(w);
|
||||
}
|
||||
if (x3c_LCL3) {
|
||||
w.writeBytes((atInt8*)"LCL3", 4);
|
||||
x3c_LCL3.write(w);
|
||||
}
|
||||
if (x40_SSWH) {
|
||||
w.writeBytes((atInt8*)"SSWH", 4);
|
||||
x40_SSWH.write(w);
|
||||
}
|
||||
if (x50_GPSM) {
|
||||
w.writeBytes((atInt8*)"GPSM", 4);
|
||||
x50_GPSM.write(w);
|
||||
}
|
||||
if (x60_EPSM) {
|
||||
w.writeBytes((atInt8*)"EPSM", 4);
|
||||
x60_EPSM.write(w);
|
||||
}
|
||||
if (x70_ZERY) {
|
||||
w.writeBytes((atInt8*)"ZERY", 4);
|
||||
x70_ZERY.write(w);
|
||||
}
|
||||
w.writeBytes("_END", 4);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void ELSM<IDType>::_binarySize(size_t& s) const
|
||||
{
|
||||
void ELSM<IDType>::_binarySize(size_t& s) const {
|
||||
s += 4;
|
||||
if (x0_LIFE) {
|
||||
s += 4;
|
||||
if (x0_LIFE)
|
||||
{
|
||||
s += 4;
|
||||
x0_LIFE.binarySize(s);
|
||||
}
|
||||
if (x4_SLIF)
|
||||
{
|
||||
s += 4;
|
||||
x4_SLIF.binarySize(s);
|
||||
}
|
||||
if (x8_GRAT)
|
||||
{
|
||||
s += 4;
|
||||
x8_GRAT.binarySize(s);
|
||||
}
|
||||
if (xc_SCNT)
|
||||
{
|
||||
s += 4;
|
||||
xc_SCNT.binarySize(s);
|
||||
}
|
||||
if (x10_SSEG)
|
||||
{
|
||||
s += 4;
|
||||
x10_SSEG.binarySize(s);
|
||||
}
|
||||
if (x14_COLR)
|
||||
{
|
||||
s += 4;
|
||||
x14_COLR.binarySize(s);
|
||||
}
|
||||
if (x18_IEMT)
|
||||
{
|
||||
s += 4;
|
||||
x18_IEMT.binarySize(s);
|
||||
}
|
||||
if (x1c_FEMT)
|
||||
{
|
||||
s += 4;
|
||||
x1c_FEMT.binarySize(s);
|
||||
}
|
||||
if (x20_AMPL)
|
||||
{
|
||||
s += 4;
|
||||
x20_AMPL.binarySize(s);
|
||||
}
|
||||
if (x24_AMPD)
|
||||
{
|
||||
s += 4;
|
||||
x24_AMPD.binarySize(s);
|
||||
}
|
||||
if (x28_LWD1)
|
||||
{
|
||||
s += 4;
|
||||
x28_LWD1.binarySize(s);
|
||||
}
|
||||
if (x2c_LWD2)
|
||||
{
|
||||
s += 4;
|
||||
x2c_LWD2.binarySize(s);
|
||||
}
|
||||
if (x30_LWD3)
|
||||
{
|
||||
s += 4;
|
||||
x30_LWD3.binarySize(s);
|
||||
}
|
||||
if (x34_LCL1)
|
||||
{
|
||||
s += 4;
|
||||
x34_LCL1.binarySize(s);
|
||||
}
|
||||
if (x38_LCL2)
|
||||
{
|
||||
s += 4;
|
||||
x38_LCL2.binarySize(s);
|
||||
}
|
||||
if (x3c_LCL3)
|
||||
{
|
||||
s += 4;
|
||||
x3c_LCL3.binarySize(s);
|
||||
}
|
||||
if (x40_SSWH)
|
||||
{
|
||||
s += 4;
|
||||
x40_SSWH.binarySize(s);
|
||||
}
|
||||
if (x50_GPSM)
|
||||
{
|
||||
s += 4;
|
||||
x50_GPSM.binarySize(s);
|
||||
}
|
||||
if (x60_EPSM)
|
||||
{
|
||||
s += 4;
|
||||
x60_EPSM.binarySize(s);
|
||||
}
|
||||
if (x70_ZERY)
|
||||
{
|
||||
s += 4;
|
||||
x70_ZERY.binarySize(s);
|
||||
}
|
||||
x0_LIFE.binarySize(s);
|
||||
}
|
||||
if (x4_SLIF) {
|
||||
s += 4;
|
||||
x4_SLIF.binarySize(s);
|
||||
}
|
||||
if (x8_GRAT) {
|
||||
s += 4;
|
||||
x8_GRAT.binarySize(s);
|
||||
}
|
||||
if (xc_SCNT) {
|
||||
s += 4;
|
||||
xc_SCNT.binarySize(s);
|
||||
}
|
||||
if (x10_SSEG) {
|
||||
s += 4;
|
||||
x10_SSEG.binarySize(s);
|
||||
}
|
||||
if (x14_COLR) {
|
||||
s += 4;
|
||||
x14_COLR.binarySize(s);
|
||||
}
|
||||
if (x18_IEMT) {
|
||||
s += 4;
|
||||
x18_IEMT.binarySize(s);
|
||||
}
|
||||
if (x1c_FEMT) {
|
||||
s += 4;
|
||||
x1c_FEMT.binarySize(s);
|
||||
}
|
||||
if (x20_AMPL) {
|
||||
s += 4;
|
||||
x20_AMPL.binarySize(s);
|
||||
}
|
||||
if (x24_AMPD) {
|
||||
s += 4;
|
||||
x24_AMPD.binarySize(s);
|
||||
}
|
||||
if (x28_LWD1) {
|
||||
s += 4;
|
||||
x28_LWD1.binarySize(s);
|
||||
}
|
||||
if (x2c_LWD2) {
|
||||
s += 4;
|
||||
x2c_LWD2.binarySize(s);
|
||||
}
|
||||
if (x30_LWD3) {
|
||||
s += 4;
|
||||
x30_LWD3.binarySize(s);
|
||||
}
|
||||
if (x34_LCL1) {
|
||||
s += 4;
|
||||
x34_LCL1.binarySize(s);
|
||||
}
|
||||
if (x38_LCL2) {
|
||||
s += 4;
|
||||
x38_LCL2.binarySize(s);
|
||||
}
|
||||
if (x3c_LCL3) {
|
||||
s += 4;
|
||||
x3c_LCL3.binarySize(s);
|
||||
}
|
||||
if (x40_SSWH) {
|
||||
s += 4;
|
||||
x40_SSWH.binarySize(s);
|
||||
}
|
||||
if (x50_GPSM) {
|
||||
s += 4;
|
||||
x50_GPSM.binarySize(s);
|
||||
}
|
||||
if (x60_EPSM) {
|
||||
s += 4;
|
||||
x60_EPSM.binarySize(s);
|
||||
}
|
||||
if (x70_ZERY) {
|
||||
s += 4;
|
||||
x70_ZERY.binarySize(s);
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void ELSM<IDType>::_read(athena::io::YAMLDocReader& r)
|
||||
{
|
||||
for (const auto& elem : r.getCurNode()->m_mapChildren)
|
||||
{
|
||||
if (elem.first.size() < 4)
|
||||
{
|
||||
LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto rec = r.enterSubRecord(elem.first.c_str()))
|
||||
{
|
||||
switch (*reinterpret_cast<const uint32_t*>(elem.first.data()))
|
||||
{
|
||||
case SBIG('LIFE'):
|
||||
x0_LIFE.read(r);
|
||||
break;
|
||||
case SBIG('SLIF'):
|
||||
x4_SLIF.read(r);
|
||||
break;
|
||||
case SBIG('GRAT'):
|
||||
x8_GRAT.read(r);
|
||||
break;
|
||||
case SBIG('SCNT'):
|
||||
xc_SCNT.read(r);
|
||||
break;
|
||||
case SBIG('SSEG'):
|
||||
x10_SSEG.read(r);
|
||||
break;
|
||||
case SBIG('COLR'):
|
||||
x14_COLR.read(r);
|
||||
break;
|
||||
case SBIG('IEMT'):
|
||||
x18_IEMT.read(r);
|
||||
break;
|
||||
case SBIG('FEMT'):
|
||||
x1c_FEMT.read(r);
|
||||
break;
|
||||
case SBIG('AMPL'):
|
||||
x20_AMPL.read(r);
|
||||
break;
|
||||
case SBIG('AMPD'):
|
||||
x24_AMPD.read(r);
|
||||
break;
|
||||
case SBIG('LWD1'):
|
||||
x28_LWD1.read(r);
|
||||
break;
|
||||
case SBIG('LWD2'):
|
||||
x2c_LWD2.read(r);
|
||||
break;
|
||||
case SBIG('LWD3'):
|
||||
x30_LWD3.read(r);
|
||||
break;
|
||||
case SBIG('LCL1'):
|
||||
x34_LCL1.read(r);
|
||||
break;
|
||||
case SBIG('LCL2'):
|
||||
x38_LCL2.read(r);
|
||||
break;
|
||||
case SBIG('LCL3'):
|
||||
x3c_LCL3.read(r);
|
||||
break;
|
||||
case SBIG('SSWH'):
|
||||
x40_SSWH.read(r);
|
||||
break;
|
||||
case SBIG('GPSM'):
|
||||
x50_GPSM.read(r);
|
||||
break;
|
||||
case SBIG('EPSM'):
|
||||
x60_EPSM.read(r);
|
||||
break;
|
||||
case SBIG('ZERY'):
|
||||
x70_ZERY.read(r);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void ELSM<IDType>::_read(athena::io::YAMLDocReader& r) {
|
||||
for (const auto& elem : r.getCurNode()->m_mapChildren) {
|
||||
if (elem.first.size() < 4) {
|
||||
LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto rec = r.enterSubRecord(elem.first.c_str())) {
|
||||
switch (*reinterpret_cast<const uint32_t*>(elem.first.data())) {
|
||||
case SBIG('LIFE'):
|
||||
x0_LIFE.read(r);
|
||||
break;
|
||||
case SBIG('SLIF'):
|
||||
x4_SLIF.read(r);
|
||||
break;
|
||||
case SBIG('GRAT'):
|
||||
x8_GRAT.read(r);
|
||||
break;
|
||||
case SBIG('SCNT'):
|
||||
xc_SCNT.read(r);
|
||||
break;
|
||||
case SBIG('SSEG'):
|
||||
x10_SSEG.read(r);
|
||||
break;
|
||||
case SBIG('COLR'):
|
||||
x14_COLR.read(r);
|
||||
break;
|
||||
case SBIG('IEMT'):
|
||||
x18_IEMT.read(r);
|
||||
break;
|
||||
case SBIG('FEMT'):
|
||||
x1c_FEMT.read(r);
|
||||
break;
|
||||
case SBIG('AMPL'):
|
||||
x20_AMPL.read(r);
|
||||
break;
|
||||
case SBIG('AMPD'):
|
||||
x24_AMPD.read(r);
|
||||
break;
|
||||
case SBIG('LWD1'):
|
||||
x28_LWD1.read(r);
|
||||
break;
|
||||
case SBIG('LWD2'):
|
||||
x2c_LWD2.read(r);
|
||||
break;
|
||||
case SBIG('LWD3'):
|
||||
x30_LWD3.read(r);
|
||||
break;
|
||||
case SBIG('LCL1'):
|
||||
x34_LCL1.read(r);
|
||||
break;
|
||||
case SBIG('LCL2'):
|
||||
x38_LCL2.read(r);
|
||||
break;
|
||||
case SBIG('LCL3'):
|
||||
x3c_LCL3.read(r);
|
||||
break;
|
||||
case SBIG('SSWH'):
|
||||
x40_SSWH.read(r);
|
||||
break;
|
||||
case SBIG('GPSM'):
|
||||
x50_GPSM.read(r);
|
||||
break;
|
||||
case SBIG('EPSM'):
|
||||
x60_EPSM.read(r);
|
||||
break;
|
||||
case SBIG('ZERY'):
|
||||
x70_ZERY.read(r);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void ELSM<IDType>::_write(athena::io::YAMLDocWriter& w) const
|
||||
{
|
||||
if (x0_LIFE)
|
||||
if (auto rec = w.enterSubRecord("LIFE"))
|
||||
x0_LIFE.write(w);
|
||||
if (x4_SLIF)
|
||||
if (auto rec = w.enterSubRecord("SLIF"))
|
||||
x4_SLIF.write(w);
|
||||
if (x8_GRAT)
|
||||
if (auto rec = w.enterSubRecord("GRAT"))
|
||||
x8_GRAT.write(w);
|
||||
if (xc_SCNT)
|
||||
if (auto rec = w.enterSubRecord("SCNT"))
|
||||
xc_SCNT.write(w);
|
||||
if (x10_SSEG)
|
||||
if (auto rec = w.enterSubRecord("SSEG"))
|
||||
x10_SSEG.write(w);
|
||||
if (x14_COLR)
|
||||
if (auto rec = w.enterSubRecord("COLR"))
|
||||
x14_COLR.write(w);
|
||||
if (x18_IEMT)
|
||||
if (auto rec = w.enterSubRecord("IEMT"))
|
||||
x18_IEMT.write(w);
|
||||
if (x1c_FEMT)
|
||||
if (auto rec = w.enterSubRecord("FEMT"))
|
||||
x1c_FEMT.write(w);
|
||||
if (x20_AMPL)
|
||||
if (auto rec = w.enterSubRecord("AMPL"))
|
||||
x20_AMPL.write(w);
|
||||
if (x24_AMPD)
|
||||
if (auto rec = w.enterSubRecord("AMPD"))
|
||||
x24_AMPD.write(w);
|
||||
if (x28_LWD1)
|
||||
if (auto rec = w.enterSubRecord("LWD1"))
|
||||
x28_LWD1.write(w);
|
||||
if (x2c_LWD2)
|
||||
if (auto rec = w.enterSubRecord("LWD2"))
|
||||
x2c_LWD2.write(w);
|
||||
if (x30_LWD3)
|
||||
if (auto rec = w.enterSubRecord("LWD3"))
|
||||
x30_LWD3.write(w);
|
||||
if (x34_LCL1)
|
||||
if (auto rec = w.enterSubRecord("LCL1"))
|
||||
x34_LCL1.write(w);
|
||||
if (x38_LCL2)
|
||||
if (auto rec = w.enterSubRecord("LCL2"))
|
||||
x38_LCL2.write(w);
|
||||
if (x3c_LCL3)
|
||||
if (auto rec = w.enterSubRecord("LCL3"))
|
||||
x3c_LCL3.write(w);
|
||||
if (x40_SSWH)
|
||||
if (auto rec = w.enterSubRecord("SSWH"))
|
||||
x40_SSWH.write(w);
|
||||
if (x50_GPSM)
|
||||
if (auto rec = w.enterSubRecord("GPSM"))
|
||||
x50_GPSM.write(w);
|
||||
if (x60_EPSM)
|
||||
if (auto rec = w.enterSubRecord("EPSM"))
|
||||
x60_EPSM.write(w);
|
||||
if (x70_ZERY)
|
||||
if (auto rec = w.enterSubRecord("ZERY"))
|
||||
x70_ZERY.write(w);
|
||||
void ELSM<IDType>::_write(athena::io::YAMLDocWriter& w) const {
|
||||
if (x0_LIFE)
|
||||
if (auto rec = w.enterSubRecord("LIFE"))
|
||||
x0_LIFE.write(w);
|
||||
if (x4_SLIF)
|
||||
if (auto rec = w.enterSubRecord("SLIF"))
|
||||
x4_SLIF.write(w);
|
||||
if (x8_GRAT)
|
||||
if (auto rec = w.enterSubRecord("GRAT"))
|
||||
x8_GRAT.write(w);
|
||||
if (xc_SCNT)
|
||||
if (auto rec = w.enterSubRecord("SCNT"))
|
||||
xc_SCNT.write(w);
|
||||
if (x10_SSEG)
|
||||
if (auto rec = w.enterSubRecord("SSEG"))
|
||||
x10_SSEG.write(w);
|
||||
if (x14_COLR)
|
||||
if (auto rec = w.enterSubRecord("COLR"))
|
||||
x14_COLR.write(w);
|
||||
if (x18_IEMT)
|
||||
if (auto rec = w.enterSubRecord("IEMT"))
|
||||
x18_IEMT.write(w);
|
||||
if (x1c_FEMT)
|
||||
if (auto rec = w.enterSubRecord("FEMT"))
|
||||
x1c_FEMT.write(w);
|
||||
if (x20_AMPL)
|
||||
if (auto rec = w.enterSubRecord("AMPL"))
|
||||
x20_AMPL.write(w);
|
||||
if (x24_AMPD)
|
||||
if (auto rec = w.enterSubRecord("AMPD"))
|
||||
x24_AMPD.write(w);
|
||||
if (x28_LWD1)
|
||||
if (auto rec = w.enterSubRecord("LWD1"))
|
||||
x28_LWD1.write(w);
|
||||
if (x2c_LWD2)
|
||||
if (auto rec = w.enterSubRecord("LWD2"))
|
||||
x2c_LWD2.write(w);
|
||||
if (x30_LWD3)
|
||||
if (auto rec = w.enterSubRecord("LWD3"))
|
||||
x30_LWD3.write(w);
|
||||
if (x34_LCL1)
|
||||
if (auto rec = w.enterSubRecord("LCL1"))
|
||||
x34_LCL1.write(w);
|
||||
if (x38_LCL2)
|
||||
if (auto rec = w.enterSubRecord("LCL2"))
|
||||
x38_LCL2.write(w);
|
||||
if (x3c_LCL3)
|
||||
if (auto rec = w.enterSubRecord("LCL3"))
|
||||
x3c_LCL3.write(w);
|
||||
if (x40_SSWH)
|
||||
if (auto rec = w.enterSubRecord("SSWH"))
|
||||
x40_SSWH.write(w);
|
||||
if (x50_GPSM)
|
||||
if (auto rec = w.enterSubRecord("GPSM"))
|
||||
x50_GPSM.write(w);
|
||||
if (x60_EPSM)
|
||||
if (auto rec = w.enterSubRecord("EPSM"))
|
||||
x60_EPSM.write(w);
|
||||
if (x70_ZERY)
|
||||
if (auto rec = w.enterSubRecord("ZERY"))
|
||||
x70_ZERY.write(w);
|
||||
}
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(ELSM<UniqueID32>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(ELSM<UniqueID64>)
|
||||
|
||||
template <>
|
||||
const char* ELSM<UniqueID32>::DNAType() { return "urde::ELSM<UniqueID32>"; }
|
||||
const char* ELSM<UniqueID32>::DNAType() {
|
||||
return "urde::ELSM<UniqueID32>";
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* ELSM<UniqueID64>::DNAType() { return "urde::ELSM<UniqueID64>"; }
|
||||
const char* ELSM<UniqueID64>::DNAType() {
|
||||
return "urde::ELSM<UniqueID64>";
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void ELSM<IDType>::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const
|
||||
{
|
||||
g_curSpec->flattenDependencies(x40_SSWH.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x50_GPSM.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x60_EPSM.id, pathsOut);
|
||||
void ELSM<IDType>::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
||||
g_curSpec->flattenDependencies(x40_SSWH.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x50_GPSM.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x60_EPSM.id, pathsOut);
|
||||
}
|
||||
|
||||
template struct ELSM<UniqueID32>;
|
||||
template struct ELSM<UniqueID64>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractELSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen())
|
||||
{
|
||||
ELSM<IDType> elsm;
|
||||
elsm.read(rs);
|
||||
athena::io::ToYAMLStream(elsm, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool ExtractELSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen()) {
|
||||
ELSM<IDType> elsm;
|
||||
elsm.read(rs);
|
||||
athena::io::ToYAMLStream(elsm, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template bool ExtractELSM<UniqueID32>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
template bool ExtractELSM<UniqueID64>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
||||
template <class IDType>
|
||||
bool WriteELSM(const ELSM<IDType>& elsm, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
elsm.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
bool WriteELSM(const ELSM<IDType>& elsm, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
elsm.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
template bool WriteELSM<UniqueID32>(const ELSM<UniqueID32>& gpsm, const hecl::ProjectPath& outPath);
|
||||
template bool WriteELSM<UniqueID64>(const ELSM<UniqueID64>& gpsm, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
|
@ -4,35 +4,33 @@
|
|||
#include "PAK.hpp"
|
||||
#include "athena/FileWriter.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle
|
||||
{
|
||||
namespace DataSpec::DNAParticle {
|
||||
template <class IDType>
|
||||
struct ELSM : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
IntElementFactory x0_LIFE;
|
||||
IntElementFactory x4_SLIF;
|
||||
RealElementFactory x8_GRAT;
|
||||
IntElementFactory xc_SCNT;
|
||||
IntElementFactory x10_SSEG;
|
||||
ColorElementFactory x14_COLR;
|
||||
EmitterElementFactory x18_IEMT;
|
||||
EmitterElementFactory x1c_FEMT;
|
||||
RealElementFactory x20_AMPL;
|
||||
RealElementFactory x24_AMPD;
|
||||
RealElementFactory x28_LWD1;
|
||||
RealElementFactory x2c_LWD2;
|
||||
RealElementFactory x30_LWD3;
|
||||
ColorElementFactory x34_LCL1;
|
||||
ColorElementFactory x38_LCL2;
|
||||
ColorElementFactory x3c_LCL3;
|
||||
ChildResourceFactory<IDType> x40_SSWH;
|
||||
ChildResourceFactory<IDType> x50_GPSM;
|
||||
ChildResourceFactory<IDType> x60_EPSM;
|
||||
BoolHelper x70_ZERY;
|
||||
struct ELSM : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
IntElementFactory x0_LIFE;
|
||||
IntElementFactory x4_SLIF;
|
||||
RealElementFactory x8_GRAT;
|
||||
IntElementFactory xc_SCNT;
|
||||
IntElementFactory x10_SSEG;
|
||||
ColorElementFactory x14_COLR;
|
||||
EmitterElementFactory x18_IEMT;
|
||||
EmitterElementFactory x1c_FEMT;
|
||||
RealElementFactory x20_AMPL;
|
||||
RealElementFactory x24_AMPD;
|
||||
RealElementFactory x28_LWD1;
|
||||
RealElementFactory x2c_LWD2;
|
||||
RealElementFactory x30_LWD3;
|
||||
ColorElementFactory x34_LCL1;
|
||||
ColorElementFactory x38_LCL2;
|
||||
ColorElementFactory x3c_LCL3;
|
||||
ChildResourceFactory<IDType> x40_SSWH;
|
||||
ChildResourceFactory<IDType> x50_GPSM;
|
||||
ChildResourceFactory<IDType> x60_EPSM;
|
||||
BoolHelper x70_ZERY;
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
|
@ -41,4 +39,4 @@ bool ExtractELSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
|||
template <class IDType>
|
||||
bool WriteELSM(const ELSM<IDType>& elsm, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
|
@ -1,246 +1,231 @@
|
|||
#include "FONT.hpp"
|
||||
|
||||
namespace DataSpec::DNAFont
|
||||
{
|
||||
namespace DataSpec::DNAFont {
|
||||
logvisor::Module LogModule("urde::DNAFont");
|
||||
|
||||
template <class IDType>
|
||||
void FONT<IDType>::_read(athena::io::IStreamReader& __dna_reader)
|
||||
{
|
||||
/* magic */
|
||||
atUint32 magic;
|
||||
__dna_reader.readBytesToBuf(&magic, 4);
|
||||
if (magic != SBIG('FONT'))
|
||||
{
|
||||
LogModule.report(logvisor::Fatal, "Invalid FONT magic '%s'", &magic);
|
||||
return;
|
||||
}
|
||||
/* version */
|
||||
version = __dna_reader.readUint32Big();
|
||||
/* unknown1 */
|
||||
unknown1 = __dna_reader.readUint32Big();
|
||||
/* lineHeight */
|
||||
lineHeight = __dna_reader.readInt32Big();
|
||||
/* verticalOffset */
|
||||
verticalOffset = __dna_reader.readInt32Big();
|
||||
/* lineMargin */
|
||||
lineMargin = __dna_reader.readInt32Big();
|
||||
/* unknown2 */
|
||||
unknown2 = __dna_reader.readBool();
|
||||
/* unknown3 */
|
||||
unknown3 = __dna_reader.readBool();
|
||||
/* unknown4 */
|
||||
unknown4 = __dna_reader.readUint32Big();
|
||||
/* fontSize */
|
||||
fontSize = __dna_reader.readUint32Big();
|
||||
/* name */
|
||||
name = __dna_reader.readString(-1);
|
||||
/* textureId */
|
||||
textureId.read(__dna_reader);
|
||||
/* textureFormat */
|
||||
textureFormat = __dna_reader.readUint32Big();
|
||||
/* glyphCount */
|
||||
glyphCount = __dna_reader.readUint32Big();
|
||||
/* glyphs */
|
||||
for (atUint32 i = 0; i < glyphCount; i++)
|
||||
{
|
||||
if (version < 4)
|
||||
glyphs.emplace_back(new GlyphMP1);
|
||||
else
|
||||
glyphs.emplace_back(new GlyphMP2);
|
||||
glyphs.back()->read(__dna_reader);
|
||||
}
|
||||
/* kerningInfoCount */
|
||||
kerningInfoCount = __dna_reader.readUint32Big();
|
||||
/* kerningInfo */
|
||||
__dna_reader.enumerate(kerningInfo, kerningInfoCount);
|
||||
void FONT<IDType>::_read(athena::io::IStreamReader& __dna_reader) {
|
||||
/* magic */
|
||||
atUint32 magic;
|
||||
__dna_reader.readBytesToBuf(&magic, 4);
|
||||
if (magic != SBIG('FONT')) {
|
||||
LogModule.report(logvisor::Fatal, "Invalid FONT magic '%s'", &magic);
|
||||
return;
|
||||
}
|
||||
/* version */
|
||||
version = __dna_reader.readUint32Big();
|
||||
/* unknown1 */
|
||||
unknown1 = __dna_reader.readUint32Big();
|
||||
/* lineHeight */
|
||||
lineHeight = __dna_reader.readInt32Big();
|
||||
/* verticalOffset */
|
||||
verticalOffset = __dna_reader.readInt32Big();
|
||||
/* lineMargin */
|
||||
lineMargin = __dna_reader.readInt32Big();
|
||||
/* unknown2 */
|
||||
unknown2 = __dna_reader.readBool();
|
||||
/* unknown3 */
|
||||
unknown3 = __dna_reader.readBool();
|
||||
/* unknown4 */
|
||||
unknown4 = __dna_reader.readUint32Big();
|
||||
/* fontSize */
|
||||
fontSize = __dna_reader.readUint32Big();
|
||||
/* name */
|
||||
name = __dna_reader.readString(-1);
|
||||
/* textureId */
|
||||
textureId.read(__dna_reader);
|
||||
/* textureFormat */
|
||||
textureFormat = __dna_reader.readUint32Big();
|
||||
/* glyphCount */
|
||||
glyphCount = __dna_reader.readUint32Big();
|
||||
/* glyphs */
|
||||
for (atUint32 i = 0; i < glyphCount; i++) {
|
||||
if (version < 4)
|
||||
glyphs.emplace_back(new GlyphMP1);
|
||||
else
|
||||
glyphs.emplace_back(new GlyphMP2);
|
||||
glyphs.back()->read(__dna_reader);
|
||||
}
|
||||
/* kerningInfoCount */
|
||||
kerningInfoCount = __dna_reader.readUint32Big();
|
||||
/* kerningInfo */
|
||||
__dna_reader.enumerate(kerningInfo, kerningInfoCount);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void FONT<IDType>::_write(athena::io::IStreamWriter& __dna_writer) const
|
||||
{
|
||||
/* magic */
|
||||
__dna_writer.writeBytes((atInt8*)"FONT", 4);
|
||||
/* version */
|
||||
__dna_writer.writeUint32Big(version);
|
||||
/* unknown1 */
|
||||
__dna_writer.writeUint32Big(unknown1);
|
||||
/* lineHeight */
|
||||
__dna_writer.writeInt32Big(lineHeight);
|
||||
/* verticalOffset */
|
||||
__dna_writer.writeInt32Big(verticalOffset);
|
||||
/* lineMargin */
|
||||
__dna_writer.writeInt32Big(lineMargin);
|
||||
/* unknown2 */
|
||||
__dna_writer.writeBool(unknown2);
|
||||
/* unknown3 */
|
||||
__dna_writer.writeBool(unknown3);
|
||||
/* unknown4 */
|
||||
__dna_writer.writeUint32Big(unknown4);
|
||||
/* fontSize */
|
||||
__dna_writer.writeUint32Big(fontSize);
|
||||
/* name */
|
||||
__dna_writer.writeString(name, -1);
|
||||
/* textureId */
|
||||
textureId.write(__dna_writer);
|
||||
/* textureFormat */
|
||||
__dna_writer.writeUint32Big(textureFormat);
|
||||
/* glyphCount */
|
||||
__dna_writer.writeUint32Big(glyphCount);
|
||||
/* glyphs */
|
||||
void FONT<IDType>::_write(athena::io::IStreamWriter& __dna_writer) const {
|
||||
/* magic */
|
||||
__dna_writer.writeBytes((atInt8*)"FONT", 4);
|
||||
/* version */
|
||||
__dna_writer.writeUint32Big(version);
|
||||
/* unknown1 */
|
||||
__dna_writer.writeUint32Big(unknown1);
|
||||
/* lineHeight */
|
||||
__dna_writer.writeInt32Big(lineHeight);
|
||||
/* verticalOffset */
|
||||
__dna_writer.writeInt32Big(verticalOffset);
|
||||
/* lineMargin */
|
||||
__dna_writer.writeInt32Big(lineMargin);
|
||||
/* unknown2 */
|
||||
__dna_writer.writeBool(unknown2);
|
||||
/* unknown3 */
|
||||
__dna_writer.writeBool(unknown3);
|
||||
/* unknown4 */
|
||||
__dna_writer.writeUint32Big(unknown4);
|
||||
/* fontSize */
|
||||
__dna_writer.writeUint32Big(fontSize);
|
||||
/* name */
|
||||
__dna_writer.writeString(name, -1);
|
||||
/* textureId */
|
||||
textureId.write(__dna_writer);
|
||||
/* textureFormat */
|
||||
__dna_writer.writeUint32Big(textureFormat);
|
||||
/* glyphCount */
|
||||
__dna_writer.writeUint32Big(glyphCount);
|
||||
/* glyphs */
|
||||
for (const std::unique_ptr<IGlyph>& glyph : glyphs)
|
||||
glyph->write(__dna_writer);
|
||||
/* kerningInfoCount */
|
||||
__dna_writer.writeUint32Big(kerningInfoCount);
|
||||
/* kerningInfo */
|
||||
__dna_writer.enumerate(kerningInfo);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void FONT<IDType>::_read(athena::io::YAMLDocReader& __dna_docin) {
|
||||
/* version */
|
||||
version = __dna_docin.readUint32("version");
|
||||
/* unknown1 */
|
||||
unknown1 = __dna_docin.readUint32("unknown1");
|
||||
/* lineHeight */
|
||||
lineHeight = __dna_docin.readInt32("lineHeight");
|
||||
/* verticalOffset */
|
||||
verticalOffset = __dna_docin.readInt32("verticalOffset");
|
||||
/* lineMargin */
|
||||
lineMargin = __dna_docin.readInt32("lineMargin");
|
||||
/* unknown2 */
|
||||
unknown2 = __dna_docin.readBool("unknown2");
|
||||
/* unknown3 */
|
||||
unknown3 = __dna_docin.readBool("unknown3");
|
||||
/* unknown4 */
|
||||
unknown4 = __dna_docin.readUint32("unknown4");
|
||||
/* fontSize */
|
||||
fontSize = __dna_docin.readUint32("fontSize");
|
||||
/* name */
|
||||
name = __dna_docin.readString("name");
|
||||
/* textureId */
|
||||
__dna_docin.enumerate("textureId", textureId);
|
||||
/* textureFormat */
|
||||
textureFormat = __dna_docin.readUint32("textureFormat");
|
||||
/* glyphCount */
|
||||
/* glyphs */
|
||||
size_t count;
|
||||
if (auto v = __dna_docin.enterSubVector("glyphs", count)) {
|
||||
glyphCount = count;
|
||||
for (atUint32 i = 0; i < glyphCount; i++) {
|
||||
if (version < 4)
|
||||
glyphs.emplace_back(new GlyphMP1);
|
||||
else
|
||||
glyphs.emplace_back(new GlyphMP2);
|
||||
|
||||
if (auto rec = __dna_docin.enterSubRecord(nullptr))
|
||||
glyphs.back()->read(__dna_docin);
|
||||
}
|
||||
}
|
||||
/* kerningInfoCount squelched */
|
||||
/* kerningInfo */
|
||||
kerningInfoCount = __dna_docin.enumerate("kerningInfo", kerningInfo);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void FONT<IDType>::_write(athena::io::YAMLDocWriter& __dna_docout) const {
|
||||
/* version */
|
||||
__dna_docout.writeUint32("version", version);
|
||||
/* unknown1 */
|
||||
__dna_docout.writeUint32("unknown1", unknown1);
|
||||
/* lineHeight */
|
||||
__dna_docout.writeInt32("lineHeight", lineHeight);
|
||||
/* verticalOffset */
|
||||
__dna_docout.writeInt32("verticalOffset", verticalOffset);
|
||||
/* lineMargin */
|
||||
__dna_docout.writeInt32("lineMargin", lineMargin);
|
||||
/* unknown2 */
|
||||
__dna_docout.writeBool("unknown2", unknown2);
|
||||
/* unknown3 */
|
||||
__dna_docout.writeBool("unknown3", unknown3);
|
||||
/* unknown4 */
|
||||
__dna_docout.writeUint32("unknown4", unknown4);
|
||||
/* fontSize */
|
||||
__dna_docout.writeUint32("fontSize", fontSize);
|
||||
/* name */
|
||||
__dna_docout.writeString("name", name);
|
||||
/* textureId */
|
||||
__dna_docout.enumerate("textureId", textureId);
|
||||
/* textureFormat */
|
||||
__dna_docout.writeUint32("textureFormat", textureFormat);
|
||||
/* glyphCount squelched */
|
||||
/* glyphs */
|
||||
if (auto v = __dna_docout.enterSubVector("glyphs"))
|
||||
for (const std::unique_ptr<IGlyph>& glyph : glyphs)
|
||||
glyph->write(__dna_writer);
|
||||
/* kerningInfoCount */
|
||||
__dna_writer.writeUint32Big(kerningInfoCount);
|
||||
/* kerningInfo */
|
||||
__dna_writer.enumerate(kerningInfo);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void FONT<IDType>::_read(athena::io::YAMLDocReader& __dna_docin)
|
||||
{
|
||||
/* version */
|
||||
version = __dna_docin.readUint32("version");
|
||||
/* unknown1 */
|
||||
unknown1 = __dna_docin.readUint32("unknown1");
|
||||
/* lineHeight */
|
||||
lineHeight = __dna_docin.readInt32("lineHeight");
|
||||
/* verticalOffset */
|
||||
verticalOffset = __dna_docin.readInt32("verticalOffset");
|
||||
/* lineMargin */
|
||||
lineMargin = __dna_docin.readInt32("lineMargin");
|
||||
/* unknown2 */
|
||||
unknown2 = __dna_docin.readBool("unknown2");
|
||||
/* unknown3 */
|
||||
unknown3 = __dna_docin.readBool("unknown3");
|
||||
/* unknown4 */
|
||||
unknown4 = __dna_docin.readUint32("unknown4");
|
||||
/* fontSize */
|
||||
fontSize = __dna_docin.readUint32("fontSize");
|
||||
/* name */
|
||||
name = __dna_docin.readString("name");
|
||||
/* textureId */
|
||||
__dna_docin.enumerate("textureId", textureId);
|
||||
/* textureFormat */
|
||||
textureFormat = __dna_docin.readUint32("textureFormat");
|
||||
/* glyphCount */
|
||||
/* glyphs */
|
||||
size_t count;
|
||||
if (auto v = __dna_docin.enterSubVector("glyphs", count))
|
||||
{
|
||||
glyphCount = count;
|
||||
for (atUint32 i = 0; i < glyphCount; i++)
|
||||
{
|
||||
if (version < 4)
|
||||
glyphs.emplace_back(new GlyphMP1);
|
||||
else
|
||||
glyphs.emplace_back(new GlyphMP2);
|
||||
|
||||
if (auto rec = __dna_docin.enterSubRecord(nullptr))
|
||||
glyphs.back()->read(__dna_docin);
|
||||
}
|
||||
}
|
||||
/* kerningInfoCount squelched */
|
||||
/* kerningInfo */
|
||||
kerningInfoCount = __dna_docin.enumerate("kerningInfo", kerningInfo);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void FONT<IDType>::_write(athena::io::YAMLDocWriter& __dna_docout) const
|
||||
{
|
||||
/* version */
|
||||
__dna_docout.writeUint32("version", version);
|
||||
/* unknown1 */
|
||||
__dna_docout.writeUint32("unknown1", unknown1);
|
||||
/* lineHeight */
|
||||
__dna_docout.writeInt32("lineHeight", lineHeight);
|
||||
/* verticalOffset */
|
||||
__dna_docout.writeInt32("verticalOffset", verticalOffset);
|
||||
/* lineMargin */
|
||||
__dna_docout.writeInt32("lineMargin", lineMargin);
|
||||
/* unknown2 */
|
||||
__dna_docout.writeBool("unknown2", unknown2);
|
||||
/* unknown3 */
|
||||
__dna_docout.writeBool("unknown3", unknown3);
|
||||
/* unknown4 */
|
||||
__dna_docout.writeUint32("unknown4", unknown4);
|
||||
/* fontSize */
|
||||
__dna_docout.writeUint32("fontSize", fontSize);
|
||||
/* name */
|
||||
__dna_docout.writeString("name", name);
|
||||
/* textureId */
|
||||
__dna_docout.enumerate("textureId", textureId);
|
||||
/* textureFormat */
|
||||
__dna_docout.writeUint32("textureFormat", textureFormat);
|
||||
/* glyphCount squelched */
|
||||
/* glyphs */
|
||||
if (auto v = __dna_docout.enterSubVector("glyphs"))
|
||||
for (const std::unique_ptr<IGlyph>& glyph : glyphs)
|
||||
if (auto rec = __dna_docout.enterSubRecord(nullptr))
|
||||
glyph->write(__dna_docout);
|
||||
/* kerningInfoCount squelched */
|
||||
/* kerningInfo */
|
||||
__dna_docout.enumerate("kerningInfo", kerningInfo);
|
||||
if (auto rec = __dna_docout.enterSubRecord(nullptr))
|
||||
glyph->write(__dna_docout);
|
||||
/* kerningInfoCount squelched */
|
||||
/* kerningInfo */
|
||||
__dna_docout.enumerate("kerningInfo", kerningInfo);
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* FONT<UniqueID32>::DNAType()
|
||||
{
|
||||
return "FONT<UniqueID32>";
|
||||
const char* FONT<UniqueID32>::DNAType() {
|
||||
return "FONT<UniqueID32>";
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* FONT<UniqueID64>::DNAType()
|
||||
{
|
||||
return "FONT<UniqueID64>";
|
||||
const char* FONT<UniqueID64>::DNAType() {
|
||||
return "FONT<UniqueID64>";
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void FONT<IDType>::_binarySize(size_t& __isz) const
|
||||
{
|
||||
__isz += name.size() + 1;
|
||||
textureId.binarySize(__isz);
|
||||
for (const std::unique_ptr<IGlyph>& glyph : glyphs)
|
||||
glyph->binarySize(__isz);
|
||||
for (const KerningInfo& k : kerningInfo)
|
||||
k.binarySize(__isz);
|
||||
__isz += 46;
|
||||
void FONT<IDType>::_binarySize(size_t& __isz) const {
|
||||
__isz += name.size() + 1;
|
||||
textureId.binarySize(__isz);
|
||||
for (const std::unique_ptr<IGlyph>& glyph : glyphs)
|
||||
glyph->binarySize(__isz);
|
||||
for (const KerningInfo& k : kerningInfo)
|
||||
k.binarySize(__isz);
|
||||
__isz += 46;
|
||||
}
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(FONT<UniqueID32>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(FONT<UniqueID64>)
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractFONT(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen())
|
||||
{
|
||||
FONT<IDType> font;
|
||||
font.read(rs);
|
||||
athena::io::ToYAMLStream(font, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool ExtractFONT(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen()) {
|
||||
FONT<IDType> font;
|
||||
font.read(rs);
|
||||
athena::io::ToYAMLStream(font, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template bool ExtractFONT<UniqueID32>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
template bool ExtractFONT<UniqueID64>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
||||
template <class IDType>
|
||||
bool WriteFONT(const FONT<IDType>& font, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
font.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
bool WriteFONT(const FONT<IDType>& font, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
font.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
template bool WriteFONT<UniqueID32>(const FONT<UniqueID32>& font, const hecl::ProjectPath& outPath);
|
||||
template bool WriteFONT<UniqueID64>(const FONT<UniqueID64>& font, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAFont
|
||||
|
|
|
@ -3,117 +3,109 @@
|
|||
#include "PAK.hpp"
|
||||
#include "athena/FileWriter.hpp"
|
||||
|
||||
namespace DataSpec::DNAFont
|
||||
{
|
||||
struct GlyphRect : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<float> left;
|
||||
Value<float> top;
|
||||
Value<float> right;
|
||||
Value<float> bottom;
|
||||
namespace DataSpec::DNAFont {
|
||||
struct GlyphRect : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<float> left;
|
||||
Value<float> top;
|
||||
Value<float> right;
|
||||
Value<float> bottom;
|
||||
};
|
||||
struct IGlyph : BigDNAVYaml
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint16> m_character;
|
||||
GlyphRect m_glyphRect;
|
||||
struct IGlyph : BigDNAVYaml {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint16> m_character;
|
||||
GlyphRect m_glyphRect;
|
||||
|
||||
atUint16 character() const { return m_character; }
|
||||
float left() const { return m_glyphRect.left; }
|
||||
float top() const { return m_glyphRect.top; }
|
||||
float right() const { return m_glyphRect.right; }
|
||||
float bottom() const { return m_glyphRect.bottom; }
|
||||
GlyphRect rect() const { return m_glyphRect; }
|
||||
atUint16 character() const { return m_character; }
|
||||
float left() const { return m_glyphRect.left; }
|
||||
float top() const { return m_glyphRect.top; }
|
||||
float right() const { return m_glyphRect.right; }
|
||||
float bottom() const { return m_glyphRect.bottom; }
|
||||
GlyphRect rect() const { return m_glyphRect; }
|
||||
|
||||
virtual atInt32 layer() const { return 0; }
|
||||
virtual atInt32 leftPadding() const=0;
|
||||
virtual atInt32 advance() const =0;
|
||||
virtual atInt32 rightPadding() const=0;
|
||||
virtual atInt32 width() const=0;
|
||||
virtual atInt32 height() const=0;
|
||||
virtual atInt32 baseline() const=0;
|
||||
virtual atInt32 kerningIndex() const =0;
|
||||
virtual atInt32 layer() const { return 0; }
|
||||
virtual atInt32 leftPadding() const = 0;
|
||||
virtual atInt32 advance() const = 0;
|
||||
virtual atInt32 rightPadding() const = 0;
|
||||
virtual atInt32 width() const = 0;
|
||||
virtual atInt32 height() const = 0;
|
||||
virtual atInt32 baseline() const = 0;
|
||||
virtual atInt32 kerningIndex() const = 0;
|
||||
};
|
||||
|
||||
struct GlyphMP1 : IGlyph
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atInt32> m_leftPadding;
|
||||
Value<atInt32> m_advance;
|
||||
Value<atInt32> m_rightPadding;
|
||||
Value<atInt32> m_width;
|
||||
Value<atInt32> m_height;
|
||||
Value<atInt32> m_baseline;
|
||||
Value<atInt32> m_kerningIndex;
|
||||
struct GlyphMP1 : IGlyph {
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atInt32> m_leftPadding;
|
||||
Value<atInt32> m_advance;
|
||||
Value<atInt32> m_rightPadding;
|
||||
Value<atInt32> m_width;
|
||||
Value<atInt32> m_height;
|
||||
Value<atInt32> m_baseline;
|
||||
Value<atInt32> m_kerningIndex;
|
||||
|
||||
atInt32 leftPadding() const { return m_leftPadding; }
|
||||
atInt32 advance() const { return m_advance; }
|
||||
atInt32 rightPadding() const { return m_rightPadding; }
|
||||
atInt32 width() const { return m_width; }
|
||||
atInt32 height() const { return m_height; }
|
||||
atInt32 baseline() const { return m_baseline; }
|
||||
atInt32 kerningIndex() const { return m_kerningIndex; }
|
||||
atInt32 leftPadding() const { return m_leftPadding; }
|
||||
atInt32 advance() const { return m_advance; }
|
||||
atInt32 rightPadding() const { return m_rightPadding; }
|
||||
atInt32 width() const { return m_width; }
|
||||
atInt32 height() const { return m_height; }
|
||||
atInt32 baseline() const { return m_baseline; }
|
||||
atInt32 kerningIndex() const { return m_kerningIndex; }
|
||||
};
|
||||
|
||||
struct GlyphMP2 : IGlyph
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atInt8> m_layer;
|
||||
Value<atInt8> m_leftPadding;
|
||||
Value<atInt8> m_advance;
|
||||
Value<atInt8> m_rightPadding;
|
||||
Value<atInt8> m_width;
|
||||
Value<atInt8> m_height;
|
||||
Value<atInt8> m_baseline;
|
||||
Value<atInt16> m_kerningIndex;
|
||||
struct GlyphMP2 : IGlyph {
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atInt8> m_layer;
|
||||
Value<atInt8> m_leftPadding;
|
||||
Value<atInt8> m_advance;
|
||||
Value<atInt8> m_rightPadding;
|
||||
Value<atInt8> m_width;
|
||||
Value<atInt8> m_height;
|
||||
Value<atInt8> m_baseline;
|
||||
Value<atInt16> m_kerningIndex;
|
||||
|
||||
atInt32 layer() const { return m_layer; }
|
||||
atInt32 leftPadding() const { return m_leftPadding; }
|
||||
atInt32 advance() const { return m_advance; }
|
||||
atInt32 rightPadding() const { return m_rightPadding; }
|
||||
atInt32 width() const { return m_width; }
|
||||
atInt32 height() const { return m_height; }
|
||||
atInt32 baseline() const { return m_baseline; }
|
||||
atInt32 kerningIndex() const { return m_kerningIndex; }
|
||||
atInt32 layer() const { return m_layer; }
|
||||
atInt32 leftPadding() const { return m_leftPadding; }
|
||||
atInt32 advance() const { return m_advance; }
|
||||
atInt32 rightPadding() const { return m_rightPadding; }
|
||||
atInt32 width() const { return m_width; }
|
||||
atInt32 height() const { return m_height; }
|
||||
atInt32 baseline() const { return m_baseline; }
|
||||
atInt32 kerningIndex() const { return m_kerningIndex; }
|
||||
};
|
||||
|
||||
struct KerningInfo : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint16> thisChar;
|
||||
Value<atUint16> nextChar;
|
||||
Value<atInt32> adjust;
|
||||
struct KerningInfo : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint16> thisChar;
|
||||
Value<atUint16> nextChar;
|
||||
Value<atInt32> adjust;
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) FONT : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
Value<atUint32> version;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atInt32> lineHeight;
|
||||
Value<atInt32> verticalOffset;
|
||||
Value<atInt32> lineMargin;
|
||||
Value<bool> unknown2;
|
||||
Value<bool> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<atUint32> fontSize; // in points
|
||||
String<-1> name;
|
||||
Value<IDType> textureId;
|
||||
Value<atUint32> textureFormat;
|
||||
Value<atUint32> glyphCount;
|
||||
std::vector<std::unique_ptr<IGlyph>> glyphs;
|
||||
Value<atUint32> kerningInfoCount;
|
||||
Vector<KerningInfo, AT_DNA_COUNT(kerningInfoCount)> kerningInfo;
|
||||
struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) FONT : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
Value<atUint32> version;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atInt32> lineHeight;
|
||||
Value<atInt32> verticalOffset;
|
||||
Value<atInt32> lineMargin;
|
||||
Value<bool> unknown2;
|
||||
Value<bool> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<atUint32> fontSize; // in points
|
||||
String<-1> name;
|
||||
Value<IDType> textureId;
|
||||
Value<atUint32> textureFormat;
|
||||
Value<atUint32> glyphCount;
|
||||
std::vector<std::unique_ptr<IGlyph>> glyphs;
|
||||
Value<atUint32> kerningInfoCount;
|
||||
Vector<KerningInfo, AT_DNA_COUNT(kerningInfoCount)> kerningInfo;
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const
|
||||
{
|
||||
g_curSpec->flattenDependencies(textureId, pathsOut);
|
||||
}
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
||||
g_curSpec->flattenDependencies(textureId, pathsOut);
|
||||
}
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
|
@ -122,5 +114,4 @@ bool ExtractFONT(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
|||
template <class IDType>
|
||||
bool WriteFONT(const FONT<IDType>& font, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAFont
|
||||
|
|
|
@ -4,82 +4,75 @@
|
|||
|
||||
#include "FSM2.hpp"
|
||||
|
||||
namespace DataSpec::DNAFSM2
|
||||
{
|
||||
namespace DataSpec::DNAFSM2 {
|
||||
logvisor::Module LogDNAFSM2("urde::DNAFSM2");
|
||||
|
||||
template <class IDType>
|
||||
template <class Op>
|
||||
void FSM2<IDType>::Enumerate(typename Op::StreamT& s)
|
||||
{
|
||||
Do<Op>({"header"}, header, s);
|
||||
if (header.magic != SBIG('FSM2'))
|
||||
{
|
||||
LogDNAFSM2.report(logvisor::Fatal, "Invalid FSM2 magic '%.4s' expected 'FSM2'", header.magic.toString().c_str());
|
||||
return;
|
||||
}
|
||||
void FSM2<IDType>::Enumerate(typename Op::StreamT& s) {
|
||||
Do<Op>({"header"}, header, s);
|
||||
if (header.magic != SBIG('FSM2')) {
|
||||
LogDNAFSM2.report(logvisor::Fatal, "Invalid FSM2 magic '%.4s' expected 'FSM2'", header.magic.toString().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (header.version == 1)
|
||||
{
|
||||
if (!detail)
|
||||
detail.reset(new FSMV1);
|
||||
Do<Op>({"detail"}, static_cast<FSMV1&>(*detail), s);
|
||||
}
|
||||
else if (header.version == 2)
|
||||
{
|
||||
if (!detail)
|
||||
detail.reset(new FSMV2);
|
||||
Do<Op>({"detail"}, static_cast<FSMV2&>(*detail), s);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDNAFSM2.report(logvisor::Fatal, "Invalid FSM2 version '%i'", header.version);
|
||||
return;
|
||||
}
|
||||
if (header.version == 1) {
|
||||
if (!detail)
|
||||
detail.reset(new FSMV1);
|
||||
Do<Op>({"detail"}, static_cast<FSMV1&>(*detail), s);
|
||||
} else if (header.version == 2) {
|
||||
if (!detail)
|
||||
detail.reset(new FSMV2);
|
||||
Do<Op>({"detail"}, static_cast<FSMV2&>(*detail), s);
|
||||
} else {
|
||||
LogDNAFSM2.report(logvisor::Fatal, "Invalid FSM2 version '%i'", header.version);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
AT_SPECIALIZE_DNA(FSM2<UniqueID32>)
|
||||
AT_SPECIALIZE_DNA(FSM2<UniqueID64>)
|
||||
|
||||
template <>
|
||||
const char* FSM2<UniqueID32>::DNAType() { return "urde::FSM2<UniqueID32>"; }
|
||||
const char* FSM2<UniqueID32>::DNAType() {
|
||||
return "urde::FSM2<UniqueID32>";
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* FSM2<UniqueID64>::DNAType() { return "urde::FSM2<UniqueID64>"; }
|
||||
const char* FSM2<UniqueID64>::DNAType() {
|
||||
return "urde::FSM2<UniqueID64>";
|
||||
}
|
||||
|
||||
template struct FSM2<UniqueID32>;
|
||||
template struct FSM2<UniqueID64>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractFSM2(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen())
|
||||
{
|
||||
FSM2<IDType> fsm2;
|
||||
fsm2.read(rs);
|
||||
athena::io::ToYAMLStream(fsm2, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
bool ExtractFSM2(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen()) {
|
||||
FSM2<IDType> fsm2;
|
||||
fsm2.read(rs);
|
||||
athena::io::ToYAMLStream(fsm2, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
template bool ExtractFSM2<UniqueID32>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
template bool ExtractFSM2<UniqueID64>(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
||||
template <class IDType>
|
||||
bool WriteFSM2(const FSM2<IDType>& fsm2, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
fsm2.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
bool WriteFSM2(const FSM2<IDType>& fsm2, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
fsm2.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
template bool WriteFSM2<UniqueID32>(const FSM2<UniqueID32>& fsm2, const hecl::ProjectPath& outPath);
|
||||
template bool WriteFSM2<UniqueID64>(const FSM2<UniqueID64>& fsm2, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAFSM2
|
||||
|
|
|
@ -4,146 +4,131 @@
|
|||
#include "DNACommon.hpp"
|
||||
#include "athena/FileWriter.hpp"
|
||||
|
||||
namespace DataSpec::DNAFSM2
|
||||
{
|
||||
struct IFSM : BigDNAVYaml
|
||||
{
|
||||
Delete _d;
|
||||
namespace DataSpec::DNAFSM2 {
|
||||
struct IFSM : BigDNAVYaml {
|
||||
Delete _d;
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) FSM2 : BigDNA
|
||||
{
|
||||
struct Header : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
DNAFourCC magic = FOURCC('FSM2');
|
||||
Value<atUint32> version;
|
||||
} header;
|
||||
struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) FSM2 : BigDNA {
|
||||
struct Header : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
DNAFourCC magic = FOURCC('FSM2');
|
||||
Value<atUint32> version;
|
||||
} header;
|
||||
|
||||
struct CommonStruct : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown;
|
||||
struct CommonStruct : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown;
|
||||
};
|
||||
|
||||
struct FSMV1 : IFSM {
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> stateCount;
|
||||
Value<atUint32> unknown1Count;
|
||||
Value<atUint32> unknown2Count;
|
||||
Value<atUint32> unknown3Count;
|
||||
struct State : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknownCount;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknownCount)> unknown;
|
||||
};
|
||||
|
||||
struct FSMV1 : IFSM
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> stateCount;
|
||||
Value<atUint32> unknown1Count;
|
||||
Value<atUint32> unknown2Count;
|
||||
Value<atUint32> unknown3Count;
|
||||
struct State : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknownCount;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknownCount)> unknown;
|
||||
};
|
||||
|
||||
struct Unknown1 : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<float> unknown1;
|
||||
Value<atUint32> unknown2Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown2Count)> unknown2;
|
||||
Value<atUint8> unknown3;
|
||||
};
|
||||
|
||||
struct Unknown2 : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknownCount;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknownCount)> unknown;
|
||||
};
|
||||
|
||||
struct Unknown3 : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknownCount;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknownCount)> unknown;
|
||||
Value<IDType> fsmId;
|
||||
};
|
||||
|
||||
Vector<State, AT_DNA_COUNT(stateCount)> states;
|
||||
Vector<Unknown1, AT_DNA_COUNT(unknown1Count)> unknown1;
|
||||
Vector<Unknown2, AT_DNA_COUNT(unknown2Count)> unknown2;
|
||||
Vector<Unknown3, AT_DNA_COUNT(unknown3Count)> unknown3;
|
||||
struct Unknown1 : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<float> unknown1;
|
||||
Value<atUint32> unknown2Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown2Count)> unknown2;
|
||||
Value<atUint8> unknown3;
|
||||
};
|
||||
|
||||
struct FSMV2 : IFSM
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> stateCount;
|
||||
Value<atUint32> unknown1Count;
|
||||
Value<atUint32> unknown2Count;
|
||||
Value<atUint32> unknown3Count;
|
||||
struct State : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atUint32> unknown2;
|
||||
Value<atUint32> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<atUint32> unknown5Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown5Count)> unknown5;
|
||||
};
|
||||
|
||||
struct Unknown1 : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atUint32> unknown2;
|
||||
Value<atUint32> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<float> unknown5;
|
||||
Value<atUint32> unknown6Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown6Count)> unknown6;
|
||||
Value<atUint8> unknown7;
|
||||
};
|
||||
|
||||
struct Unknown2 : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atUint32> unknown2;
|
||||
Value<atUint32> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<atUint32> unknown5Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown5Count)> unknown5;
|
||||
};
|
||||
|
||||
struct Unknown3 : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atUint32> unknown2;
|
||||
Value<atUint32> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<atUint32> unknown5Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown5Count)> unknown5;
|
||||
Value<IDType> fsmId;
|
||||
};
|
||||
|
||||
Vector<State, AT_DNA_COUNT(stateCount)> states;
|
||||
Vector<Unknown1, AT_DNA_COUNT(unknown1Count)> unknown1;
|
||||
Vector<Unknown2, AT_DNA_COUNT(unknown2Count)> unknown2;
|
||||
Vector<Unknown3, AT_DNA_COUNT(unknown3Count)> unknown3;
|
||||
struct Unknown2 : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknownCount;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknownCount)> unknown;
|
||||
};
|
||||
|
||||
std::unique_ptr<IFSM> detail;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
struct Unknown3 : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknownCount;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknownCount)> unknown;
|
||||
Value<IDType> fsmId;
|
||||
};
|
||||
|
||||
Vector<State, AT_DNA_COUNT(stateCount)> states;
|
||||
Vector<Unknown1, AT_DNA_COUNT(unknown1Count)> unknown1;
|
||||
Vector<Unknown2, AT_DNA_COUNT(unknown2Count)> unknown2;
|
||||
Vector<Unknown3, AT_DNA_COUNT(unknown3Count)> unknown3;
|
||||
};
|
||||
|
||||
struct FSMV2 : IFSM {
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> stateCount;
|
||||
Value<atUint32> unknown1Count;
|
||||
Value<atUint32> unknown2Count;
|
||||
Value<atUint32> unknown3Count;
|
||||
struct State : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atUint32> unknown2;
|
||||
Value<atUint32> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<atUint32> unknown5Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown5Count)> unknown5;
|
||||
};
|
||||
|
||||
struct Unknown1 : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atUint32> unknown2;
|
||||
Value<atUint32> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<float> unknown5;
|
||||
Value<atUint32> unknown6Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown6Count)> unknown6;
|
||||
Value<atUint8> unknown7;
|
||||
};
|
||||
|
||||
struct Unknown2 : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atUint32> unknown2;
|
||||
Value<atUint32> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<atUint32> unknown5Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown5Count)> unknown5;
|
||||
};
|
||||
|
||||
struct Unknown3 : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atUint32> unknown2;
|
||||
Value<atUint32> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<atUint32> unknown5Count;
|
||||
Vector<CommonStruct, AT_DNA_COUNT(unknown5Count)> unknown5;
|
||||
Value<IDType> fsmId;
|
||||
};
|
||||
|
||||
Vector<State, AT_DNA_COUNT(stateCount)> states;
|
||||
Vector<Unknown1, AT_DNA_COUNT(unknown1Count)> unknown1;
|
||||
Vector<Unknown2, AT_DNA_COUNT(unknown2Count)> unknown2;
|
||||
Vector<Unknown3, AT_DNA_COUNT(unknown3Count)> unknown3;
|
||||
};
|
||||
|
||||
std::unique_ptr<IFSM> detail;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
|
@ -151,4 +136,4 @@ bool ExtractFSM2(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
|||
template <class IDType>
|
||||
bool WriteFSM2(const FSM2<IDType>& fsm2, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAFSM2
|
||||
|
|
|
@ -2,4 +2,3 @@
|
|||
|
||||
#include "hecl/Backend/GX.hpp"
|
||||
using GX = hecl::Backend::GX;
|
||||
|
||||
|
|
|
@ -9,487 +9,419 @@
|
|||
#include "zeus/CAABox.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAMAPA
|
||||
{
|
||||
namespace DataSpec::DNAMAPA {
|
||||
|
||||
static logvisor::Module Log("DNAMAPA");
|
||||
|
||||
template <>
|
||||
void MAPA::Enumerate<BigDNA::Read>(typename Read::StreamT& __dna_reader)
|
||||
{
|
||||
/* magic */
|
||||
magic = __dna_reader.readUint32Big();
|
||||
if (magic != 0xDEADD00D)
|
||||
{
|
||||
LogDNACommon.report(logvisor::Error, "invalid MAPA magic");
|
||||
return;
|
||||
}
|
||||
/* version */
|
||||
version = __dna_reader.readUint32Big();
|
||||
if (version == 2)
|
||||
header.reset(new HeaderMP1);
|
||||
else if (version == 3)
|
||||
header.reset(new HeaderMP2);
|
||||
else if (version == 5)
|
||||
header.reset(new HeaderMP3);
|
||||
void MAPA::Enumerate<BigDNA::Read>(typename Read::StreamT& __dna_reader) {
|
||||
/* magic */
|
||||
magic = __dna_reader.readUint32Big();
|
||||
if (magic != 0xDEADD00D) {
|
||||
LogDNACommon.report(logvisor::Error, "invalid MAPA magic");
|
||||
return;
|
||||
}
|
||||
/* version */
|
||||
version = __dna_reader.readUint32Big();
|
||||
if (version == 2)
|
||||
header.reset(new HeaderMP1);
|
||||
else if (version == 3)
|
||||
header.reset(new HeaderMP2);
|
||||
else if (version == 5)
|
||||
header.reset(new HeaderMP3);
|
||||
else {
|
||||
LogDNACommon.report(logvisor::Error, "invalid MAPA version");
|
||||
return;
|
||||
}
|
||||
|
||||
header->read(__dna_reader);
|
||||
|
||||
for (atUint32 i = 0; i < header->mappableObjectCount(); i++) {
|
||||
std::unique_ptr<IMappableObject> mo = nullptr;
|
||||
if (version != 5)
|
||||
mo.reset(new MappableObjectMP1_2);
|
||||
else
|
||||
{
|
||||
LogDNACommon.report(logvisor::Error, "invalid MAPA version");
|
||||
return;
|
||||
}
|
||||
mo.reset(new MappableObjectMP3);
|
||||
mo->read(__dna_reader);
|
||||
mappableObjects.push_back(std::move(mo));
|
||||
}
|
||||
|
||||
header->read(__dna_reader);
|
||||
|
||||
for (atUint32 i = 0; i < header->mappableObjectCount(); i++)
|
||||
{
|
||||
std::unique_ptr<IMappableObject> mo = nullptr;
|
||||
if (version != 5)
|
||||
mo.reset(new MappableObjectMP1_2);
|
||||
else
|
||||
mo.reset(new MappableObjectMP3);
|
||||
mo->read(__dna_reader);
|
||||
mappableObjects.push_back(std::move(mo));
|
||||
}
|
||||
|
||||
/* vertices */
|
||||
__dna_reader.enumerateBig(vertices, header->vertexCount());
|
||||
/* surfaceHeaders */
|
||||
__dna_reader.enumerate(surfaceHeaders, header->surfaceCount());
|
||||
/* surfaces */
|
||||
__dna_reader.enumerate(surfaces, header->surfaceCount());
|
||||
/* vertices */
|
||||
__dna_reader.enumerateBig(vertices, header->vertexCount());
|
||||
/* surfaceHeaders */
|
||||
__dna_reader.enumerate(surfaceHeaders, header->surfaceCount());
|
||||
/* surfaces */
|
||||
__dna_reader.enumerate(surfaces, header->surfaceCount());
|
||||
}
|
||||
|
||||
template <>
|
||||
void MAPA::Enumerate<BigDNA::Write>(typename Write::StreamT& __dna_writer)
|
||||
{
|
||||
/* magic */
|
||||
__dna_writer.writeUint32Big(magic);
|
||||
/* version */
|
||||
__dna_writer.writeUint32Big(version);
|
||||
header->write(__dna_writer);
|
||||
void MAPA::Enumerate<BigDNA::Write>(typename Write::StreamT& __dna_writer) {
|
||||
/* magic */
|
||||
__dna_writer.writeUint32Big(magic);
|
||||
/* version */
|
||||
__dna_writer.writeUint32Big(version);
|
||||
header->write(__dna_writer);
|
||||
|
||||
/* mappableObjects */
|
||||
for (const std::unique_ptr<IMappableObject>& mo : mappableObjects)
|
||||
mo->write(__dna_writer);
|
||||
/* vertices */
|
||||
__dna_writer.enumerateBig(vertices);
|
||||
/* surfaceHeaders */
|
||||
__dna_writer.enumerate(surfaceHeaders);
|
||||
/* surfaces */
|
||||
__dna_writer.enumerate(surfaces);
|
||||
/* mappableObjects */
|
||||
for (const std::unique_ptr<IMappableObject>& mo : mappableObjects)
|
||||
mo->write(__dna_writer);
|
||||
/* vertices */
|
||||
__dna_writer.enumerateBig(vertices);
|
||||
/* surfaceHeaders */
|
||||
__dna_writer.enumerate(surfaceHeaders);
|
||||
/* surfaces */
|
||||
__dna_writer.enumerate(surfaces);
|
||||
}
|
||||
|
||||
template <>
|
||||
void MAPA::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
|
||||
{
|
||||
header->binarySize(s);
|
||||
void MAPA::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) {
|
||||
header->binarySize(s);
|
||||
|
||||
for (const std::unique_ptr<IMappableObject>& mo : mappableObjects)
|
||||
mo->binarySize(s);
|
||||
for (const std::unique_ptr<IMappableObject>& mo : mappableObjects)
|
||||
mo->binarySize(s);
|
||||
|
||||
s += vertices.size() * 12;
|
||||
for (const SurfaceHeader& sh : surfaceHeaders)
|
||||
sh.binarySize(s);
|
||||
for (const Surface& su : surfaces)
|
||||
su.binarySize(s);
|
||||
s += 8;
|
||||
s += vertices.size() * 12;
|
||||
for (const SurfaceHeader& sh : surfaceHeaders)
|
||||
sh.binarySize(s);
|
||||
for (const Surface& su : surfaces)
|
||||
su.binarySize(s);
|
||||
s += 8;
|
||||
}
|
||||
|
||||
static const char* RetroMapVisModes[] =
|
||||
{
|
||||
"ALWAYS",
|
||||
"MAPSTATIONORVISIT",
|
||||
"VISIT",
|
||||
"NEVER"
|
||||
};
|
||||
static const char* RetroMapVisModes[] = {"ALWAYS", "MAPSTATIONORVISIT", "VISIT", "NEVER"};
|
||||
|
||||
static const char* RetroMapObjVisModes[] =
|
||||
{
|
||||
"ALWAYS",
|
||||
"MAPSTATIONORVISIT",
|
||||
"VISIT",
|
||||
"NEVER",
|
||||
"MAPSTATIONORVISIT2"
|
||||
};
|
||||
static const char* RetroMapObjVisModes[] = {"ALWAYS", "MAPSTATIONORVISIT", "VISIT", "NEVER", "MAPSTATIONORVISIT2"};
|
||||
|
||||
template <typename PAKRouter>
|
||||
bool ReadMAPAToBlender(hecl::blender::Connection& conn,
|
||||
const MAPA& mapa,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
bool force)
|
||||
{
|
||||
if (!force && outPath.isFile())
|
||||
return true;
|
||||
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::MapArea))
|
||||
return false;
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
|
||||
os << "import bpy, bmesh\n"
|
||||
"from mathutils import Matrix\n"
|
||||
"\n"
|
||||
"bpy.types.Object.retro_mappable_type = bpy.props.IntProperty(name='Retro: MAPA object type', default=-1)\n"
|
||||
"bpy.types.Object.retro_mappable_sclyid = bpy.props.StringProperty(name='Retro: MAPA object SCLY ID')\n"
|
||||
"bpy.types.Scene.retro_map_vis_mode = bpy.props.EnumProperty(items=[('ALWAYS', 'Always', 'Always Visible', 0),"
|
||||
"('MAPSTATIONORVISIT', 'Map Station or Visit', 'Visible after Map Station or Visit', 1),"
|
||||
"('VISIT', 'Visit', 'Visible after Visit', 2),"
|
||||
"('NEVER', 'Never', 'Never Visible', 3)],"
|
||||
"name='Retro: Map Visibility Mode')\n"
|
||||
"bpy.types.Object.retro_mapobj_vis_mode = bpy.props.EnumProperty(items=[('ALWAYS', 'Always', 'Always Visible', 0),"
|
||||
"('MAPSTATIONORVISIT', 'Map Station or Visit', 'Visible after Map Station or Visit', 1),"
|
||||
"('VISIT', 'Visit', 'Visible after Door Visit', 2),"
|
||||
"('NEVER', 'Never', 'Never Visible', 3),"
|
||||
"('MAPSTATIONORVISIT2', 'Map Station or Visit 2', 'Visible after Map Station or Visit', 4)],"
|
||||
"name='Retro: Map Object Visibility Mode')\n"
|
||||
"\n"
|
||||
"for ar in bpy.context.screen.areas:\n"
|
||||
" for sp in ar.spaces:\n"
|
||||
" if sp.type == 'VIEW_3D':\n"
|
||||
" sp.viewport_shade = 'SOLID'\n"
|
||||
"\n"
|
||||
"# Clear Scene\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" if ob.type != 'CAMERA':\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n"
|
||||
"\n"
|
||||
"def add_triangle(bm, verts):\n"
|
||||
" verts = [bm.verts[vi] for vi in verts]\n"
|
||||
" face = bm.faces.get(verts)\n"
|
||||
" if face:\n"
|
||||
" face = face.copy()\n"
|
||||
" bm.verts.ensure_lookup_table()\n"
|
||||
" face.normal_flip()\n"
|
||||
" else:\n"
|
||||
" bm.faces.new(verts)\n"
|
||||
"\n"
|
||||
"def add_border(bm, verts):\n"
|
||||
" verts = [bm.verts[vi] for vi in verts]\n"
|
||||
" edge = bm.edges.get(verts)\n"
|
||||
" if not edge:\n"
|
||||
" edge = bm.edges.new(verts)\n"
|
||||
" edge.seam = True\n"
|
||||
"\n";
|
||||
|
||||
os.format("bpy.context.scene.name = 'MAPA_%s'\n"
|
||||
"bpy.context.scene.retro_map_vis_mode = '%s'\n",
|
||||
entry.id.toString().c_str(),
|
||||
RetroMapVisModes[mapa.header->visMode()]);
|
||||
|
||||
/* Add empties representing MappableObjects */
|
||||
int moIdx = 0;
|
||||
for (const std::unique_ptr<MAPA::IMappableObject>& mo : mapa.mappableObjects)
|
||||
{
|
||||
if (mapa.version < 5)
|
||||
{
|
||||
const MAPA::MappableObjectMP1_2* moMP12 = static_cast<const MAPA::MappableObjectMP1_2*>(mo.get());
|
||||
zeus::simd_floats mtxF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
moMP12->transformMtx[i].simd.copy_to(mtxF[i]);
|
||||
os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.retro_mappable_type = %d\n"
|
||||
"obj.retro_mapobj_vis_mode = '%s'\n"
|
||||
"obj.retro_mappable_sclyid = '0x%08X'\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = mtxd[2]\n",
|
||||
moIdx, moMP12->type, RetroMapObjVisModes[moMP12->visMode], moMP12->sclyId,
|
||||
mtxF[0][0], mtxF[0][1], mtxF[0][2], mtxF[0][3],
|
||||
mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3],
|
||||
mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]);
|
||||
++moIdx;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const MAPA::MappableObjectMP3* moMP3 = static_cast<const MAPA::MappableObjectMP3*>(mo.get());
|
||||
zeus::simd_floats mtxF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
moMP3->transformMtx[i].simd.copy_to(mtxF[i]);
|
||||
os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.retro_mappable_type = %d\n"
|
||||
"obj.retro_mapobj_vis_mode = '%s'\n"
|
||||
"obj.retro_mappable_sclyid = '0x%08X'\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = mtxd[2]\n",
|
||||
moIdx, moMP3->type, RetroMapObjVisModes[moMP3->visMode], moMP3->sclyId,
|
||||
mtxF[0][0], mtxF[0][1], mtxF[0][2], mtxF[0][3],
|
||||
mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3],
|
||||
mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]);
|
||||
++moIdx;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
os << "# Begin bmesh\n"
|
||||
"bm = bmesh.new()\n"
|
||||
"\n";
|
||||
|
||||
/* Read in verts */
|
||||
for (const atVec3f& vert : mapa.vertices)
|
||||
{
|
||||
zeus::simd_floats f(vert.simd);
|
||||
os.format("bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]);
|
||||
}
|
||||
os << "bm.verts.ensure_lookup_table()\n";
|
||||
|
||||
/* Read in surfaces */
|
||||
for (const typename MAPA::Surface& surf : mapa.surfaces)
|
||||
{
|
||||
for (const typename MAPA::Surface::Primitive& prim : surf.primitives)
|
||||
{
|
||||
auto iit = prim.indices.cbegin();
|
||||
|
||||
/* 3 Prim Verts to start */
|
||||
int c = 0;
|
||||
unsigned int primVerts[3] =
|
||||
{
|
||||
*iit++,
|
||||
*iit++,
|
||||
*iit++
|
||||
};
|
||||
|
||||
if (GX::Primitive(prim.type) == GX::TRIANGLESTRIP)
|
||||
{
|
||||
atUint8 flip = 0;
|
||||
for (size_t v=0 ; v<prim.indexCount-2 ; ++v)
|
||||
{
|
||||
if (flip)
|
||||
{
|
||||
os.format("add_triangle(bm, (%u,%u,%u))\n",
|
||||
primVerts[c%3],
|
||||
primVerts[(c+2)%3],
|
||||
primVerts[(c+1)%3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
os.format("add_triangle(bm, (%u,%u,%u))\n",
|
||||
primVerts[c%3],
|
||||
primVerts[(c+1)%3],
|
||||
primVerts[(c+2)%3]);
|
||||
}
|
||||
flip ^= 1;
|
||||
|
||||
/* Break if done */
|
||||
if (iit == prim.indices.cend())
|
||||
break;
|
||||
|
||||
bool peek = (v >= prim.indexCount - 3);
|
||||
|
||||
/* Advance one prim vert */
|
||||
if (peek)
|
||||
primVerts[c%3] = *iit;
|
||||
else
|
||||
primVerts[c%3] = *iit++;
|
||||
++c;
|
||||
}
|
||||
}
|
||||
else if (GX::Primitive(prim.type) == GX::TRIANGLES)
|
||||
{
|
||||
for (size_t v=0 ; v<prim.indexCount ; v+=3)
|
||||
{
|
||||
os.format("add_triangle(bm, (%u,%u,%u))\n",
|
||||
primVerts[0],
|
||||
primVerts[1],
|
||||
primVerts[2]);
|
||||
|
||||
/* Break if done */
|
||||
if (v+3 >= prim.indexCount)
|
||||
break;
|
||||
|
||||
/* Advance 3 Prim Verts */
|
||||
for (int pv=0 ; pv<3 ; ++pv)
|
||||
primVerts[pv] = *iit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const typename MAPA::Surface::Border& border : surf.borders)
|
||||
{
|
||||
auto iit = border.indices.cbegin();
|
||||
for (size_t i=0 ; i<border.indexCount-1 ; ++i)
|
||||
{
|
||||
os.format("add_border(bm, (%u,%u))\n",
|
||||
*iit, *(iit+1));
|
||||
++iit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
os << "mesh = bpy.data.meshes.new('MAP')\n"
|
||||
"mesh.show_edge_seams = True\n"
|
||||
"obj = bpy.data.objects.new(mesh.name, mesh)\n"
|
||||
"bm.to_mesh(mesh)\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"bm.free()\n";
|
||||
|
||||
const zeus::CMatrix4f* tmpMtx = pakRouter.lookupMAPATransform(entry.id);
|
||||
const zeus::CMatrix4f& mtx = tmpMtx ? *tmpMtx : zeus::CMatrix4f::skIdentityMatrix4f;
|
||||
os.format("mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = mtxd[2]\n",
|
||||
mtx[0][0], mtx[1][0], mtx[2][0], mtx[3][0],
|
||||
mtx[0][1], mtx[1][1], mtx[2][1], mtx[3][1],
|
||||
mtx[0][2], mtx[1][2], mtx[2][2], mtx[3][2]);
|
||||
|
||||
/* World background */
|
||||
hecl::ProjectPath worldBlend(outPath.getParentPath().getParentPath(), "!world.blend");
|
||||
if (worldBlend.isFile())
|
||||
os.linkBackground("//../!world.blend", "World");
|
||||
|
||||
os.centerView();
|
||||
os.close();
|
||||
conn.saveBlend();
|
||||
bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force) {
|
||||
if (!force && outPath.isFile())
|
||||
return true;
|
||||
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::MapArea))
|
||||
return false;
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
|
||||
os << "import bpy, bmesh\n"
|
||||
"from mathutils import Matrix\n"
|
||||
"\n"
|
||||
"bpy.types.Object.retro_mappable_type = bpy.props.IntProperty(name='Retro: MAPA object type', default=-1)\n"
|
||||
"bpy.types.Object.retro_mappable_sclyid = bpy.props.StringProperty(name='Retro: MAPA object SCLY ID')\n"
|
||||
"bpy.types.Scene.retro_map_vis_mode = bpy.props.EnumProperty(items=[('ALWAYS', 'Always', 'Always Visible', 0),"
|
||||
"('MAPSTATIONORVISIT', 'Map Station or Visit', 'Visible after Map Station or Visit', 1),"
|
||||
"('VISIT', 'Visit', 'Visible after Visit', 2),"
|
||||
"('NEVER', 'Never', 'Never Visible', 3)],"
|
||||
"name='Retro: Map Visibility Mode')\n"
|
||||
"bpy.types.Object.retro_mapobj_vis_mode = bpy.props.EnumProperty(items=[('ALWAYS', 'Always', 'Always Visible', "
|
||||
"0),"
|
||||
"('MAPSTATIONORVISIT', 'Map Station or Visit', 'Visible after Map Station or Visit', 1),"
|
||||
"('VISIT', 'Visit', 'Visible after Door Visit', 2),"
|
||||
"('NEVER', 'Never', 'Never Visible', 3),"
|
||||
"('MAPSTATIONORVISIT2', 'Map Station or Visit 2', 'Visible after Map Station or Visit', 4)],"
|
||||
"name='Retro: Map Object Visibility Mode')\n"
|
||||
"\n"
|
||||
"for ar in bpy.context.screen.areas:\n"
|
||||
" for sp in ar.spaces:\n"
|
||||
" if sp.type == 'VIEW_3D':\n"
|
||||
" sp.viewport_shade = 'SOLID'\n"
|
||||
"\n"
|
||||
"# Clear Scene\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" if ob.type != 'CAMERA':\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n"
|
||||
"\n"
|
||||
"def add_triangle(bm, verts):\n"
|
||||
" verts = [bm.verts[vi] for vi in verts]\n"
|
||||
" face = bm.faces.get(verts)\n"
|
||||
" if face:\n"
|
||||
" face = face.copy()\n"
|
||||
" bm.verts.ensure_lookup_table()\n"
|
||||
" face.normal_flip()\n"
|
||||
" else:\n"
|
||||
" bm.faces.new(verts)\n"
|
||||
"\n"
|
||||
"def add_border(bm, verts):\n"
|
||||
" verts = [bm.verts[vi] for vi in verts]\n"
|
||||
" edge = bm.edges.get(verts)\n"
|
||||
" if not edge:\n"
|
||||
" edge = bm.edges.new(verts)\n"
|
||||
" edge.seam = True\n"
|
||||
"\n";
|
||||
|
||||
os.format(
|
||||
"bpy.context.scene.name = 'MAPA_%s'\n"
|
||||
"bpy.context.scene.retro_map_vis_mode = '%s'\n",
|
||||
entry.id.toString().c_str(), RetroMapVisModes[mapa.header->visMode()]);
|
||||
|
||||
/* Add empties representing MappableObjects */
|
||||
int moIdx = 0;
|
||||
for (const std::unique_ptr<MAPA::IMappableObject>& mo : mapa.mappableObjects) {
|
||||
if (mapa.version < 5) {
|
||||
const MAPA::MappableObjectMP1_2* moMP12 = static_cast<const MAPA::MappableObjectMP1_2*>(mo.get());
|
||||
zeus::simd_floats mtxF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
moMP12->transformMtx[i].simd.copy_to(mtxF[i]);
|
||||
os.format(
|
||||
"obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.retro_mappable_type = %d\n"
|
||||
"obj.retro_mapobj_vis_mode = '%s'\n"
|
||||
"obj.retro_mappable_sclyid = '0x%08X'\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = mtxd[2]\n",
|
||||
moIdx, moMP12->type, RetroMapObjVisModes[moMP12->visMode], moMP12->sclyId, mtxF[0][0], mtxF[0][1], mtxF[0][2],
|
||||
mtxF[0][3], mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3], mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]);
|
||||
++moIdx;
|
||||
continue;
|
||||
} else {
|
||||
const MAPA::MappableObjectMP3* moMP3 = static_cast<const MAPA::MappableObjectMP3*>(mo.get());
|
||||
zeus::simd_floats mtxF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
moMP3->transformMtx[i].simd.copy_to(mtxF[i]);
|
||||
os.format(
|
||||
"obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.retro_mappable_type = %d\n"
|
||||
"obj.retro_mapobj_vis_mode = '%s'\n"
|
||||
"obj.retro_mappable_sclyid = '0x%08X'\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = mtxd[2]\n",
|
||||
moIdx, moMP3->type, RetroMapObjVisModes[moMP3->visMode], moMP3->sclyId, mtxF[0][0], mtxF[0][1], mtxF[0][2],
|
||||
mtxF[0][3], mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3], mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]);
|
||||
++moIdx;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
os << "# Begin bmesh\n"
|
||||
"bm = bmesh.new()\n"
|
||||
"\n";
|
||||
|
||||
/* Read in verts */
|
||||
for (const atVec3f& vert : mapa.vertices) {
|
||||
zeus::simd_floats f(vert.simd);
|
||||
os.format("bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]);
|
||||
}
|
||||
os << "bm.verts.ensure_lookup_table()\n";
|
||||
|
||||
/* Read in surfaces */
|
||||
for (const typename MAPA::Surface& surf : mapa.surfaces) {
|
||||
for (const typename MAPA::Surface::Primitive& prim : surf.primitives) {
|
||||
auto iit = prim.indices.cbegin();
|
||||
|
||||
/* 3 Prim Verts to start */
|
||||
int c = 0;
|
||||
unsigned int primVerts[3] = {*iit++, *iit++, *iit++};
|
||||
|
||||
if (GX::Primitive(prim.type) == GX::TRIANGLESTRIP) {
|
||||
atUint8 flip = 0;
|
||||
for (size_t v = 0; v < prim.indexCount - 2; ++v) {
|
||||
if (flip) {
|
||||
os.format("add_triangle(bm, (%u,%u,%u))\n", primVerts[c % 3], primVerts[(c + 2) % 3],
|
||||
primVerts[(c + 1) % 3]);
|
||||
} else {
|
||||
os.format("add_triangle(bm, (%u,%u,%u))\n", primVerts[c % 3], primVerts[(c + 1) % 3],
|
||||
primVerts[(c + 2) % 3]);
|
||||
}
|
||||
flip ^= 1;
|
||||
|
||||
/* Break if done */
|
||||
if (iit == prim.indices.cend())
|
||||
break;
|
||||
|
||||
bool peek = (v >= prim.indexCount - 3);
|
||||
|
||||
/* Advance one prim vert */
|
||||
if (peek)
|
||||
primVerts[c % 3] = *iit;
|
||||
else
|
||||
primVerts[c % 3] = *iit++;
|
||||
++c;
|
||||
}
|
||||
} else if (GX::Primitive(prim.type) == GX::TRIANGLES) {
|
||||
for (size_t v = 0; v < prim.indexCount; v += 3) {
|
||||
os.format("add_triangle(bm, (%u,%u,%u))\n", primVerts[0], primVerts[1], primVerts[2]);
|
||||
|
||||
/* Break if done */
|
||||
if (v + 3 >= prim.indexCount)
|
||||
break;
|
||||
|
||||
/* Advance 3 Prim Verts */
|
||||
for (int pv = 0; pv < 3; ++pv)
|
||||
primVerts[pv] = *iit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const typename MAPA::Surface::Border& border : surf.borders) {
|
||||
auto iit = border.indices.cbegin();
|
||||
for (size_t i = 0; i < border.indexCount - 1; ++i) {
|
||||
os.format("add_border(bm, (%u,%u))\n", *iit, *(iit + 1));
|
||||
++iit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os << "mesh = bpy.data.meshes.new('MAP')\n"
|
||||
"mesh.show_edge_seams = True\n"
|
||||
"obj = bpy.data.objects.new(mesh.name, mesh)\n"
|
||||
"bm.to_mesh(mesh)\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"bm.free()\n";
|
||||
|
||||
const zeus::CMatrix4f* tmpMtx = pakRouter.lookupMAPATransform(entry.id);
|
||||
const zeus::CMatrix4f& mtx = tmpMtx ? *tmpMtx : zeus::CMatrix4f::skIdentityMatrix4f;
|
||||
os.format(
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = mtxd[2]\n",
|
||||
mtx[0][0], mtx[1][0], mtx[2][0], mtx[3][0], mtx[0][1], mtx[1][1], mtx[2][1], mtx[3][1], mtx[0][2], mtx[1][2],
|
||||
mtx[2][2], mtx[3][2]);
|
||||
|
||||
/* World background */
|
||||
hecl::ProjectPath worldBlend(outPath.getParentPath().getParentPath(), "!world.blend");
|
||||
if (worldBlend.isFile())
|
||||
os.linkBackground("//../!world.blend", "World");
|
||||
|
||||
os.centerView();
|
||||
os.close();
|
||||
conn.saveBlend();
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool ReadMAPAToBlender<PAKRouter<DNAMP1::PAKBridge>>
|
||||
(hecl::blender::Connection& conn,
|
||||
const MAPA& mapa,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP1::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
template bool ReadMAPAToBlender<PAKRouter<DNAMP1::PAKBridge>>(hecl::blender::Connection& conn, const MAPA& mapa,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP1::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
|
||||
template bool ReadMAPAToBlender<PAKRouter<DNAMP2::PAKBridge>>
|
||||
(hecl::blender::Connection& conn,
|
||||
const MAPA& mapa,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP2::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
template bool ReadMAPAToBlender<PAKRouter<DNAMP2::PAKBridge>>(hecl::blender::Connection& conn, const MAPA& mapa,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP2::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
|
||||
template bool ReadMAPAToBlender<PAKRouter<DNAMP3::PAKBridge>>
|
||||
(hecl::blender::Connection& conn,
|
||||
const MAPA& mapa,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP3::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP3::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
template bool ReadMAPAToBlender<PAKRouter<DNAMP3::PAKBridge>>(hecl::blender::Connection& conn, const MAPA& mapa,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP3::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP3::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
|
||||
template <typename MAPAType>
|
||||
bool Cook(const hecl::blender::MapArea& mapaIn, const hecl::ProjectPath& out)
|
||||
{
|
||||
if (mapaIn.verts.size() >= 256)
|
||||
{
|
||||
Log.report(logvisor::Error, _SYS_STR("MAPA %s vertex range exceeded [%d/%d]"),
|
||||
out.getRelativePath().data(), mapaIn.verts.size(), 255);
|
||||
return false;
|
||||
bool Cook(const hecl::blender::MapArea& mapaIn, const hecl::ProjectPath& out) {
|
||||
if (mapaIn.verts.size() >= 256) {
|
||||
Log.report(logvisor::Error, _SYS_STR("MAPA %s vertex range exceeded [%d/%d]"), out.getRelativePath().data(),
|
||||
mapaIn.verts.size(), 255);
|
||||
return false;
|
||||
}
|
||||
|
||||
MAPAType mapa;
|
||||
mapa.magic = 0xDEADD00D;
|
||||
mapa.version = MAPAType::Version();
|
||||
|
||||
zeus::CAABox aabb;
|
||||
for (const hecl::blender::Vector3f& vert : mapaIn.verts)
|
||||
aabb.accumulateBounds(vert.val);
|
||||
|
||||
mapa.header = std::make_unique<typename MAPAType::Header>();
|
||||
typename MAPAType::Header& header = static_cast<typename MAPAType::Header&>(*mapa.header);
|
||||
header.unknown1 = 0;
|
||||
header.mapVisMode = mapaIn.visType.val;
|
||||
header.boundingBox[0] = aabb.min;
|
||||
header.boundingBox[1] = aabb.max;
|
||||
header.moCount = mapaIn.pois.size();
|
||||
header.vtxCount = mapaIn.verts.size();
|
||||
header.surfCount = mapaIn.surfaces.size();
|
||||
|
||||
mapa.mappableObjects.reserve(mapaIn.pois.size());
|
||||
for (const hecl::blender::MapArea::POI& poi : mapaIn.pois) {
|
||||
mapa.mappableObjects.push_back(std::make_unique<typename MAPAType::MappableObject>());
|
||||
typename MAPAType::MappableObject& mobj =
|
||||
static_cast<typename MAPAType::MappableObject&>(*mapa.mappableObjects.back());
|
||||
mobj.type = MAPA::IMappableObject::Type(poi.type);
|
||||
mobj.visMode = poi.visMode;
|
||||
mobj.sclyId = poi.objid;
|
||||
mobj.transformMtx[0] = poi.xf.val[0];
|
||||
mobj.transformMtx[1] = poi.xf.val[1];
|
||||
mobj.transformMtx[2] = poi.xf.val[2];
|
||||
}
|
||||
|
||||
mapa.vertices.reserve(mapaIn.verts.size());
|
||||
for (const hecl::blender::Vector3f& vert : mapaIn.verts)
|
||||
mapa.vertices.push_back(vert.val);
|
||||
|
||||
size_t offsetCur = 0;
|
||||
for (const auto& mo : mapa.mappableObjects)
|
||||
mo->binarySize(offsetCur);
|
||||
offsetCur += mapa.vertices.size() * 12;
|
||||
offsetCur += mapaIn.surfaces.size() * 32;
|
||||
|
||||
mapa.surfaceHeaders.reserve(mapaIn.surfaces.size());
|
||||
mapa.surfaces.reserve(mapaIn.surfaces.size());
|
||||
for (const hecl::blender::MapArea::Surface& surfIn : mapaIn.surfaces) {
|
||||
mapa.surfaceHeaders.emplace_back();
|
||||
DNAMAPA::MAPA::SurfaceHeader& surfHead = mapa.surfaceHeaders.back();
|
||||
mapa.surfaces.emplace_back();
|
||||
DNAMAPA::MAPA::Surface& surf = mapa.surfaces.back();
|
||||
|
||||
surf.primitiveCount = 1;
|
||||
surf.primitives.emplace_back();
|
||||
DNAMAPA::MAPA::Surface::Primitive& prim = surf.primitives.back();
|
||||
prim.type = GX::TRIANGLESTRIP;
|
||||
prim.indexCount = surfIn.count;
|
||||
prim.indices.reserve(surfIn.count);
|
||||
auto itBegin = mapaIn.indices.begin() + surfIn.start.val;
|
||||
auto itEnd = itBegin + surfIn.count;
|
||||
for (auto it = itBegin; it != itEnd; ++it)
|
||||
prim.indices.push_back(it->val);
|
||||
|
||||
surf.borderCount = surfIn.borders.size();
|
||||
surf.borders.reserve(surfIn.borders.size());
|
||||
for (const auto& borderIn : surfIn.borders) {
|
||||
surf.borders.emplace_back();
|
||||
DNAMAPA::MAPA::Surface::Border& border = surf.borders.back();
|
||||
border.indexCount = borderIn.second.val;
|
||||
border.indices.reserve(borderIn.second.val);
|
||||
auto it2Begin = mapaIn.indices.begin() + borderIn.first.val;
|
||||
auto it2End = it2Begin + borderIn.second.val;
|
||||
for (auto it = it2Begin; it != it2End; ++it)
|
||||
border.indices.push_back(it->val);
|
||||
}
|
||||
|
||||
MAPAType mapa;
|
||||
mapa.magic = 0xDEADD00D;
|
||||
mapa.version = MAPAType::Version();
|
||||
surfHead.normal = surfIn.normal.val;
|
||||
surfHead.centroid = surfIn.centerOfMass;
|
||||
surfHead.polyOff = offsetCur;
|
||||
offsetCur += 4;
|
||||
prim.binarySize(offsetCur);
|
||||
surfHead.edgeOff = offsetCur;
|
||||
offsetCur += 4;
|
||||
for (const auto& border : surf.borders)
|
||||
border.binarySize(offsetCur);
|
||||
}
|
||||
|
||||
zeus::CAABox aabb;
|
||||
for (const hecl::blender::Vector3f& vert : mapaIn.verts)
|
||||
aabb.accumulateBounds(vert.val);
|
||||
|
||||
mapa.header = std::make_unique<typename MAPAType::Header>();
|
||||
typename MAPAType::Header& header = static_cast<typename MAPAType::Header&>(*mapa.header);
|
||||
header.unknown1 = 0;
|
||||
header.mapVisMode = mapaIn.visType.val;
|
||||
header.boundingBox[0] = aabb.min;
|
||||
header.boundingBox[1] = aabb.max;
|
||||
header.moCount = mapaIn.pois.size();
|
||||
header.vtxCount = mapaIn.verts.size();
|
||||
header.surfCount = mapaIn.surfaces.size();
|
||||
|
||||
mapa.mappableObjects.reserve(mapaIn.pois.size());
|
||||
for (const hecl::blender::MapArea::POI& poi : mapaIn.pois)
|
||||
{
|
||||
mapa.mappableObjects.push_back(std::make_unique<typename MAPAType::MappableObject>());
|
||||
typename MAPAType::MappableObject& mobj =
|
||||
static_cast<typename MAPAType::MappableObject&>(*mapa.mappableObjects.back());
|
||||
mobj.type = MAPA::IMappableObject::Type(poi.type);
|
||||
mobj.visMode = poi.visMode;
|
||||
mobj.sclyId = poi.objid;
|
||||
mobj.transformMtx[0] = poi.xf.val[0];
|
||||
mobj.transformMtx[1] = poi.xf.val[1];
|
||||
mobj.transformMtx[2] = poi.xf.val[2];
|
||||
}
|
||||
|
||||
mapa.vertices.reserve(mapaIn.verts.size());
|
||||
for (const hecl::blender::Vector3f& vert : mapaIn.verts)
|
||||
mapa.vertices.push_back(vert.val);
|
||||
|
||||
size_t offsetCur = 0;
|
||||
for (const auto& mo : mapa.mappableObjects)
|
||||
mo->binarySize(offsetCur);
|
||||
offsetCur += mapa.vertices.size() * 12;
|
||||
offsetCur += mapaIn.surfaces.size() * 32;
|
||||
|
||||
mapa.surfaceHeaders.reserve(mapaIn.surfaces.size());
|
||||
mapa.surfaces.reserve(mapaIn.surfaces.size());
|
||||
for (const hecl::blender::MapArea::Surface& surfIn : mapaIn.surfaces)
|
||||
{
|
||||
mapa.surfaceHeaders.emplace_back();
|
||||
DNAMAPA::MAPA::SurfaceHeader& surfHead = mapa.surfaceHeaders.back();
|
||||
mapa.surfaces.emplace_back();
|
||||
DNAMAPA::MAPA::Surface& surf = mapa.surfaces.back();
|
||||
|
||||
surf.primitiveCount = 1;
|
||||
surf.primitives.emplace_back();
|
||||
DNAMAPA::MAPA::Surface::Primitive& prim = surf.primitives.back();
|
||||
prim.type = GX::TRIANGLESTRIP;
|
||||
prim.indexCount = surfIn.count;
|
||||
prim.indices.reserve(surfIn.count);
|
||||
auto itBegin = mapaIn.indices.begin() + surfIn.start.val;
|
||||
auto itEnd = itBegin + surfIn.count;
|
||||
for (auto it = itBegin ; it != itEnd ; ++it)
|
||||
prim.indices.push_back(it->val);
|
||||
|
||||
surf.borderCount = surfIn.borders.size();
|
||||
surf.borders.reserve(surfIn.borders.size());
|
||||
for (const auto& borderIn : surfIn.borders)
|
||||
{
|
||||
surf.borders.emplace_back();
|
||||
DNAMAPA::MAPA::Surface::Border& border = surf.borders.back();
|
||||
border.indexCount = borderIn.second.val;
|
||||
border.indices.reserve(borderIn.second.val);
|
||||
auto it2Begin = mapaIn.indices.begin() + borderIn.first.val;
|
||||
auto it2End = it2Begin + borderIn.second.val;
|
||||
for (auto it = it2Begin ; it != it2End ; ++it)
|
||||
border.indices.push_back(it->val);
|
||||
}
|
||||
|
||||
surfHead.normal = surfIn.normal.val;
|
||||
surfHead.centroid = surfIn.centerOfMass;
|
||||
surfHead.polyOff = offsetCur;
|
||||
offsetCur += 4;
|
||||
prim.binarySize(offsetCur);
|
||||
surfHead.edgeOff = offsetCur;
|
||||
offsetCur += 4;
|
||||
for (const auto& border : surf.borders)
|
||||
border.binarySize(offsetCur);
|
||||
}
|
||||
|
||||
athena::io::FileWriter f(out.getAbsolutePath());
|
||||
mapa.write(f);
|
||||
int64_t rem = f.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
f.writeBytes((atInt8*)"\xff", 1);
|
||||
return true;
|
||||
athena::io::FileWriter f(out.getAbsolutePath());
|
||||
mapa.write(f);
|
||||
int64_t rem = f.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
f.writeBytes((atInt8*)"\xff", 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool Cook<DNAMP1::MAPA>(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out);
|
||||
template bool Cook<DNAMP2::MAPA>(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out);
|
||||
template bool Cook<DNAMP3::MAPA>(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out);
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMAPA
|
||||
|
|
|
@ -3,190 +3,169 @@
|
|||
#include "DNACommon.hpp"
|
||||
#include "GX.hpp"
|
||||
|
||||
namespace DataSpec::DNAMAPA {
|
||||
struct MAPA : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
struct IMAPAHeader : BigDNAV {
|
||||
Delete _d;
|
||||
virtual atUint32 visMode() const = 0;
|
||||
virtual atUint32 mappableObjectCount() const = 0;
|
||||
virtual atUint32 vertexCount() const = 0;
|
||||
virtual atUint32 surfaceCount() const = 0;
|
||||
};
|
||||
|
||||
namespace DataSpec::DNAMAPA
|
||||
{
|
||||
struct MAPA : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
struct IMAPAHeader : BigDNAV
|
||||
{
|
||||
Delete _d;
|
||||
virtual atUint32 visMode() const=0;
|
||||
virtual atUint32 mappableObjectCount() const=0;
|
||||
virtual atUint32 vertexCount() const=0;
|
||||
virtual atUint32 surfaceCount() const=0;
|
||||
struct HeaderMP1 : IMAPAHeader {
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> unknown1 = 0;
|
||||
Value<atUint32> mapVisMode = 0;
|
||||
Value<atVec3f> boundingBox[2] = {};
|
||||
Value<atUint32> moCount = 0;
|
||||
Value<atUint32> vtxCount = 0;
|
||||
Value<atUint32> surfCount = 0;
|
||||
atUint32 visMode() const { return mapVisMode; }
|
||||
atUint32 mappableObjectCount() const { return moCount; }
|
||||
atUint32 vertexCount() const { return vtxCount; }
|
||||
atUint32 surfaceCount() const { return surfCount; }
|
||||
};
|
||||
|
||||
struct HeaderMP2 : IMAPAHeader {
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> unknown1 = 0;
|
||||
Value<atUint32> mapVisMode = 0;
|
||||
Value<atVec3f> boundingBox[2] = {};
|
||||
Value<atUint32> unknown3 = 0;
|
||||
Value<atUint32> unknown4 = 0;
|
||||
Value<atUint32> unknown5 = 0;
|
||||
Value<atUint32> moCount = 0;
|
||||
Value<atUint32> vtxCount = 0;
|
||||
Value<atUint32> surfCount = 0;
|
||||
atUint32 visMode() const { return mapVisMode; }
|
||||
atUint32 mappableObjectCount() const { return moCount; }
|
||||
atUint32 vertexCount() const { return vtxCount; }
|
||||
atUint32 surfaceCount() const { return surfCount; }
|
||||
};
|
||||
|
||||
struct HeaderMP3 : IMAPAHeader {
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> unknown1 = 0;
|
||||
Value<atUint32> mapVisMode = 0;
|
||||
Value<atVec3f> boundingBox[2] = {};
|
||||
Value<atUint32> unknown3 = 0;
|
||||
Value<atUint32> unknown4 = 0;
|
||||
Value<atUint32> unknown5 = 0;
|
||||
Value<atUint32> unknown6 = 0;
|
||||
Value<atUint32> moCount = 0;
|
||||
Value<atUint32> vtxCount = 0;
|
||||
Value<atUint32> surfCount = 0;
|
||||
Value<atUint32> internalNameLength = 0;
|
||||
Value<atUint32> unknown7 = 0;
|
||||
String<AT_DNA_COUNT(internalNameLength)> internalName;
|
||||
atUint32 visMode() const { return mapVisMode; }
|
||||
atUint32 mappableObjectCount() const { return moCount; }
|
||||
atUint32 vertexCount() const { return vtxCount; }
|
||||
atUint32 surfaceCount() const { return surfCount; }
|
||||
};
|
||||
|
||||
std::unique_ptr<IMAPAHeader> header;
|
||||
|
||||
struct IMappableObject : BigDNAV {
|
||||
Delete _d;
|
||||
enum class Type : atUint32 {
|
||||
BlueDoor = 0,
|
||||
ShieldDoor = 1,
|
||||
IceDoor = 2,
|
||||
WaveDoor = 3,
|
||||
PlasmaDoor = 4,
|
||||
BigDoor1 = 5,
|
||||
BigDoor2 = 6,
|
||||
IceDoorCeiling = 7,
|
||||
IceDoorFloor = 8,
|
||||
WaveDoorCeiling = 9,
|
||||
WaveDoorFloor = 10,
|
||||
IceDoorFloor2 = 13,
|
||||
WaveDoorFloor2 = 14,
|
||||
DownArrowYellow = 27, /* Maintenance Tunnel */
|
||||
UpArrowYellow = 28, /* Phazon Processing Center */
|
||||
DownArrowGreen = 29, /* Elevator A */
|
||||
UpArrowGreen = 30, /* Elite Control Access */
|
||||
DownArrowRed = 31, /* Elevator B */
|
||||
UpArrowRed = 32, /* Fungal Hall Access */
|
||||
TransportLift = 33,
|
||||
SaveStation = 34,
|
||||
MissileStation = 37
|
||||
};
|
||||
};
|
||||
|
||||
struct HeaderMP1 : IMAPAHeader
|
||||
{
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> unknown1 = 0;
|
||||
Value<atUint32> mapVisMode = 0;
|
||||
Value<atVec3f> boundingBox[2] = {};
|
||||
Value<atUint32> moCount = 0;
|
||||
Value<atUint32> vtxCount = 0;
|
||||
Value<atUint32> surfCount = 0;
|
||||
atUint32 visMode() const { return mapVisMode; }
|
||||
atUint32 mappableObjectCount() const { return moCount;}
|
||||
atUint32 vertexCount() const { return vtxCount; }
|
||||
atUint32 surfaceCount() const { return surfCount; }
|
||||
struct MappableObjectMP1_2 : IMappableObject {
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<Type> type;
|
||||
Value<atUint32> visMode;
|
||||
Value<atUint32> sclyId;
|
||||
Value<atInt32> seek1 = -1;
|
||||
Value<atVec4f> transformMtx[3];
|
||||
Value<atInt32> seek2[4] = {-1, -1, -1, -1};
|
||||
};
|
||||
|
||||
struct MappableObjectMP3 : IMappableObject {
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<Type> type;
|
||||
Value<atUint32> visMode;
|
||||
Value<atUint32> sclyId;
|
||||
Buffer<AT_DNA_COUNT(0x10)> unknownHash;
|
||||
Value<atInt32> seek1 = -1;
|
||||
Value<atVec4f> transformMtx[3];
|
||||
Value<atInt32> seek2[4] = {-1, -1, -1, -1};
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<IMappableObject>> mappableObjects;
|
||||
Vector<atVec3f, AT_DNA_COUNT(header->vertexCount())> vertices;
|
||||
|
||||
struct SurfaceHeader : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atVec3f> normal;
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> polyOff;
|
||||
Value<atUint32> edgeOff;
|
||||
};
|
||||
|
||||
Vector<SurfaceHeader, AT_DNA_COUNT(header->surfaceCount())> surfaceHeaders;
|
||||
|
||||
struct Surface : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> primitiveCount;
|
||||
struct Primitive : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> type;
|
||||
Value<atUint32> indexCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(indexCount)> indices;
|
||||
Align<4> align;
|
||||
};
|
||||
|
||||
struct HeaderMP2 : IMAPAHeader
|
||||
{
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> unknown1 = 0;
|
||||
Value<atUint32> mapVisMode = 0;
|
||||
Value<atVec3f> boundingBox[2] = {};
|
||||
Value<atUint32> unknown3 = 0;
|
||||
Value<atUint32> unknown4 = 0;
|
||||
Value<atUint32> unknown5 = 0;
|
||||
Value<atUint32> moCount = 0;
|
||||
Value<atUint32> vtxCount = 0;
|
||||
Value<atUint32> surfCount = 0;
|
||||
atUint32 visMode() const { return mapVisMode; }
|
||||
atUint32 mappableObjectCount() const { return moCount;}
|
||||
atUint32 vertexCount() const { return vtxCount; }
|
||||
atUint32 surfaceCount() const { return surfCount; }
|
||||
Vector<Primitive, AT_DNA_COUNT(primitiveCount)> primitives;
|
||||
Value<atUint32> borderCount;
|
||||
struct Border : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> indexCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(indexCount)> indices;
|
||||
Align<4> align;
|
||||
};
|
||||
Vector<Border, AT_DNA_COUNT(borderCount)> borders;
|
||||
};
|
||||
|
||||
struct HeaderMP3 : IMAPAHeader
|
||||
{
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> unknown1 = 0;
|
||||
Value<atUint32> mapVisMode = 0;
|
||||
Value<atVec3f> boundingBox[2] = {};
|
||||
Value<atUint32> unknown3 = 0;
|
||||
Value<atUint32> unknown4 = 0;
|
||||
Value<atUint32> unknown5 = 0;
|
||||
Value<atUint32> unknown6 = 0;
|
||||
Value<atUint32> moCount = 0;
|
||||
Value<atUint32> vtxCount = 0;
|
||||
Value<atUint32> surfCount = 0;
|
||||
Value<atUint32> internalNameLength = 0;
|
||||
Value<atUint32> unknown7 = 0;
|
||||
String<AT_DNA_COUNT(internalNameLength)> internalName;
|
||||
atUint32 visMode() const { return mapVisMode; }
|
||||
atUint32 mappableObjectCount() const { return moCount;}
|
||||
atUint32 vertexCount() const { return vtxCount; }
|
||||
atUint32 surfaceCount() const { return surfCount; }
|
||||
};
|
||||
|
||||
|
||||
std::unique_ptr<IMAPAHeader> header;
|
||||
|
||||
struct IMappableObject : BigDNAV
|
||||
{
|
||||
Delete _d;
|
||||
enum class Type : atUint32
|
||||
{
|
||||
BlueDoor = 0,
|
||||
ShieldDoor = 1,
|
||||
IceDoor = 2,
|
||||
WaveDoor = 3,
|
||||
PlasmaDoor = 4,
|
||||
BigDoor1 = 5,
|
||||
BigDoor2 = 6,
|
||||
IceDoorCeiling = 7,
|
||||
IceDoorFloor = 8,
|
||||
WaveDoorCeiling = 9,
|
||||
WaveDoorFloor = 10,
|
||||
IceDoorFloor2 = 13,
|
||||
WaveDoorFloor2 = 14,
|
||||
DownArrowYellow = 27, /* Maintenance Tunnel */
|
||||
UpArrowYellow = 28, /* Phazon Processing Center */
|
||||
DownArrowGreen = 29, /* Elevator A */
|
||||
UpArrowGreen = 30, /* Elite Control Access */
|
||||
DownArrowRed = 31, /* Elevator B */
|
||||
UpArrowRed = 32, /* Fungal Hall Access */
|
||||
TransportLift = 33,
|
||||
SaveStation = 34,
|
||||
MissileStation = 37
|
||||
};
|
||||
};
|
||||
|
||||
struct MappableObjectMP1_2 : IMappableObject
|
||||
{
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<Type> type;
|
||||
Value<atUint32> visMode;
|
||||
Value<atUint32> sclyId;
|
||||
Value<atInt32> seek1 = -1;
|
||||
Value<atVec4f> transformMtx[3];
|
||||
Value<atInt32> seek2[4] = {-1, -1, -1, -1};
|
||||
};
|
||||
|
||||
struct MappableObjectMP3 : IMappableObject
|
||||
{
|
||||
AT_DECL_DNA
|
||||
AT_DECL_DNAV
|
||||
Value<Type> type;
|
||||
Value<atUint32> visMode;
|
||||
Value<atUint32> sclyId;
|
||||
Buffer<AT_DNA_COUNT(0x10)> unknownHash;
|
||||
Value<atInt32> seek1 = -1;
|
||||
Value<atVec4f> transformMtx[3];
|
||||
Value<atInt32> seek2[4] = {-1, -1, -1, -1};
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<IMappableObject>> mappableObjects;
|
||||
Vector<atVec3f, AT_DNA_COUNT(header->vertexCount())> vertices;
|
||||
|
||||
struct SurfaceHeader : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atVec3f> normal;
|
||||
Value<atVec3f> centroid;
|
||||
Value<atUint32> polyOff;
|
||||
Value<atUint32> edgeOff;
|
||||
};
|
||||
|
||||
Vector<SurfaceHeader, AT_DNA_COUNT(header->surfaceCount())> surfaceHeaders;
|
||||
|
||||
struct Surface : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> primitiveCount;
|
||||
struct Primitive : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> type;
|
||||
Value<atUint32> indexCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(indexCount)> indices;
|
||||
Align<4> align;
|
||||
};
|
||||
Vector<Primitive, AT_DNA_COUNT(primitiveCount)> primitives;
|
||||
Value<atUint32> borderCount;
|
||||
struct Border : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> indexCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(indexCount)> indices;
|
||||
Align<4> align;
|
||||
};
|
||||
Vector<Border, AT_DNA_COUNT(borderCount)> borders;
|
||||
};
|
||||
|
||||
Vector<Surface, AT_DNA_COUNT(header->surfaceCount())> surfaces;
|
||||
Vector<Surface, AT_DNA_COUNT(header->surfaceCount())> surfaces;
|
||||
};
|
||||
|
||||
template <typename PAKRouter>
|
||||
bool ReadMAPAToBlender(hecl::blender::Connection& conn,
|
||||
const MAPA& mapa,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
bool force);
|
||||
bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force);
|
||||
|
||||
template <typename MAPAType>
|
||||
bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMAPA
|
||||
|
|
|
@ -5,157 +5,139 @@
|
|||
#include "zeus/CTransform.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAMAPU
|
||||
{
|
||||
namespace DataSpec::DNAMAPU {
|
||||
|
||||
template <typename PAKRouter>
|
||||
bool ReadMAPUToBlender(hecl::blender::Connection& conn,
|
||||
const MAPU& mapu,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
bool force)
|
||||
{
|
||||
if (!force && outPath.isFile())
|
||||
return true;
|
||||
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::MapUniverse))
|
||||
return false;
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
|
||||
os << "import bpy\n"
|
||||
"from mathutils import Matrix\n"
|
||||
"\n"
|
||||
"# Clear Scene\n"
|
||||
"bpy.context.scene.camera = None\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n"
|
||||
"\n"
|
||||
"bpy.types.Object.retro_mapworld_color = bpy.props.FloatVectorProperty(name='Retro: MapWorld Color',"
|
||||
" description='Sets map world color', subtype='COLOR', size=4, min=0.0, max=1.0)\n"
|
||||
"bpy.types.Object.retro_mapworld_path = bpy.props.StringProperty(name='Retro: MapWorld Path',"
|
||||
" description='Sets path to World root')\n"
|
||||
"\n";
|
||||
|
||||
hecl::ProjectPath hexPath = pakRouter.getWorking(mapu.hexMapa);
|
||||
os.linkBlend(hexPath.getAbsolutePathUTF8().data(),
|
||||
pakRouter.getBestEntryName(mapu.hexMapa).data());
|
||||
os << "hexMesh = bpy.data.objects['MAP'].data\n";
|
||||
|
||||
for (const MAPU::World& wld : mapu.worlds)
|
||||
{
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(wld.mlvl);
|
||||
const MAPU::Transform& wldXf = wld.transform;
|
||||
zeus::simd_floats wldXfF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
wldXf.xf[i].simd.copy_to(wldXfF[i]);
|
||||
zeus::simd_floats hexColorF(wld.hexColor.mSimd);
|
||||
os.format("wldObj = bpy.data.objects.new('%s', None)\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"wldObj.rotation_mode = 'QUATERNION'\n"
|
||||
"wldObj.location = mtxd[0]\n"
|
||||
"wldObj.rotation_quaternion = mtxd[1]\n"
|
||||
"wldObj.scale = mtxd[2]\n"
|
||||
"wldObj.retro_mapworld_color = (%f, %f, %f, %f)\n"
|
||||
"wldObj.retro_mapworld_path = '''%s'''\n"
|
||||
"bpy.context.scene.objects.link(wldObj)\n", wld.name.c_str(),
|
||||
wldXfF[0][0], wldXfF[0][1], wldXfF[0][2], wldXfF[0][3],
|
||||
wldXfF[1][0], wldXfF[1][1], wldXfF[1][2], wldXfF[1][3],
|
||||
wldXfF[2][0], wldXfF[2][1], wldXfF[2][2], wldXfF[2][3],
|
||||
hexColorF[0], hexColorF[1], hexColorF[2], hexColorF[3],
|
||||
path.getParentPath().getRelativePathUTF8().data());
|
||||
int idx = 0;
|
||||
for (const MAPU::Transform& hexXf : wld.hexTransforms)
|
||||
{
|
||||
zeus::simd_floats hexXfF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
hexXf.xf[i].simd.copy_to(hexXfF[i]);
|
||||
os.format("obj = bpy.data.objects.new('%s_%d', hexMesh)\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = mtxd[2]\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.parent = wldObj\n",
|
||||
wld.name.c_str(), idx++,
|
||||
hexXfF[0][0], hexXfF[0][1], hexXfF[0][2], hexXfF[0][3],
|
||||
hexXfF[1][0], hexXfF[1][1], hexXfF[1][2], hexXfF[1][3],
|
||||
hexXfF[2][0], hexXfF[2][1], hexXfF[2][2], hexXfF[2][3]);
|
||||
}
|
||||
}
|
||||
|
||||
os << "for screen in bpy.data.screens:\n"
|
||||
" for area in screen.areas:\n"
|
||||
" for space in area.spaces:\n"
|
||||
" if space.type == 'VIEW_3D':\n"
|
||||
" space.viewport_shade = 'SOLID'\n"
|
||||
" space.clip_end = 8000.0\n";
|
||||
|
||||
os.centerView();
|
||||
os.close();
|
||||
conn.saveBlend();
|
||||
bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force) {
|
||||
if (!force && outPath.isFile())
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool ReadMAPUToBlender<PAKRouter<DNAMP1::PAKBridge>>
|
||||
(hecl::blender::Connection& conn,
|
||||
const MAPU& mapu,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP1::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::MapUniverse))
|
||||
return false;
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
|
||||
template bool ReadMAPUToBlender<PAKRouter<DNAMP2::PAKBridge>>
|
||||
(hecl::blender::Connection& conn,
|
||||
const MAPU& mapu,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP2::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
os << "import bpy\n"
|
||||
"from mathutils import Matrix\n"
|
||||
"\n"
|
||||
"# Clear Scene\n"
|
||||
"bpy.context.scene.camera = None\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n"
|
||||
"\n"
|
||||
"bpy.types.Object.retro_mapworld_color = bpy.props.FloatVectorProperty(name='Retro: MapWorld Color',"
|
||||
" description='Sets map world color', subtype='COLOR', size=4, min=0.0, max=1.0)\n"
|
||||
"bpy.types.Object.retro_mapworld_path = bpy.props.StringProperty(name='Retro: MapWorld Path',"
|
||||
" description='Sets path to World root')\n"
|
||||
"\n";
|
||||
|
||||
bool MAPU::Cook(const hecl::blender::MapUniverse& mapuIn, const hecl::ProjectPath& out)
|
||||
{
|
||||
MAPU mapu;
|
||||
hecl::ProjectPath hexPath = pakRouter.getWorking(mapu.hexMapa);
|
||||
os.linkBlend(hexPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(mapu.hexMapa).data());
|
||||
os << "hexMesh = bpy.data.objects['MAP'].data\n";
|
||||
|
||||
mapu.magic = 0xABCDEF01;
|
||||
mapu.version = 1;
|
||||
mapu.hexMapa = mapuIn.hexagonPath;
|
||||
|
||||
mapu.worldCount = mapuIn.worlds.size();
|
||||
mapu.worlds.reserve(mapuIn.worlds.size());
|
||||
for (const hecl::blender::MapUniverse::World& wld : mapuIn.worlds)
|
||||
{
|
||||
mapu.worlds.emplace_back();
|
||||
MAPU::World& wldOut = mapu.worlds.back();
|
||||
wldOut.name = wld.name;
|
||||
wldOut.mlvl = hecl::ProjectPath(wld.worldPath, _SYS_STR("!world.*"));
|
||||
wldOut.transform.xf[0] = wld.xf.val[0];
|
||||
wldOut.transform.xf[1] = wld.xf.val[1];
|
||||
wldOut.transform.xf[2] = wld.xf.val[2];
|
||||
wldOut.hexCount = wld.hexagons.size();
|
||||
wldOut.hexTransforms.reserve(wld.hexagons.size());
|
||||
for (const hecl::blender::Matrix4f& mtx : wld.hexagons)
|
||||
{
|
||||
wldOut.hexTransforms.emplace_back();
|
||||
MAPU::Transform& xf = wldOut.hexTransforms.back();
|
||||
xf.xf[0] = mtx.val[0];
|
||||
xf.xf[1] = mtx.val[1];
|
||||
xf.xf[2] = mtx.val[2];
|
||||
}
|
||||
wldOut.hexColor = zeus::CColor(wld.color.val);
|
||||
for (const MAPU::World& wld : mapu.worlds) {
|
||||
hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(wld.mlvl);
|
||||
const MAPU::Transform& wldXf = wld.transform;
|
||||
zeus::simd_floats wldXfF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
wldXf.xf[i].simd.copy_to(wldXfF[i]);
|
||||
zeus::simd_floats hexColorF(wld.hexColor.mSimd);
|
||||
os.format(
|
||||
"wldObj = bpy.data.objects.new('%s', None)\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"wldObj.rotation_mode = 'QUATERNION'\n"
|
||||
"wldObj.location = mtxd[0]\n"
|
||||
"wldObj.rotation_quaternion = mtxd[1]\n"
|
||||
"wldObj.scale = mtxd[2]\n"
|
||||
"wldObj.retro_mapworld_color = (%f, %f, %f, %f)\n"
|
||||
"wldObj.retro_mapworld_path = '''%s'''\n"
|
||||
"bpy.context.scene.objects.link(wldObj)\n",
|
||||
wld.name.c_str(), wldXfF[0][0], wldXfF[0][1], wldXfF[0][2], wldXfF[0][3], wldXfF[1][0], wldXfF[1][1],
|
||||
wldXfF[1][2], wldXfF[1][3], wldXfF[2][0], wldXfF[2][1], wldXfF[2][2], wldXfF[2][3], hexColorF[0], hexColorF[1],
|
||||
hexColorF[2], hexColorF[3], path.getParentPath().getRelativePathUTF8().data());
|
||||
int idx = 0;
|
||||
for (const MAPU::Transform& hexXf : wld.hexTransforms) {
|
||||
zeus::simd_floats hexXfF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
hexXf.xf[i].simd.copy_to(hexXfF[i]);
|
||||
os.format(
|
||||
"obj = bpy.data.objects.new('%s_%d', hexMesh)\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = mtxd[2]\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"obj.parent = wldObj\n",
|
||||
wld.name.c_str(), idx++, hexXfF[0][0], hexXfF[0][1], hexXfF[0][2], hexXfF[0][3], hexXfF[1][0], hexXfF[1][1],
|
||||
hexXfF[1][2], hexXfF[1][3], hexXfF[2][0], hexXfF[2][1], hexXfF[2][2], hexXfF[2][3]);
|
||||
}
|
||||
}
|
||||
|
||||
athena::io::FileWriter f(out.getAbsolutePath());
|
||||
mapu.write(f);
|
||||
int64_t rem = f.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
f.writeBytes((atInt8*)"\xff", 1);
|
||||
return true;
|
||||
os << "for screen in bpy.data.screens:\n"
|
||||
" for area in screen.areas:\n"
|
||||
" for space in area.spaces:\n"
|
||||
" if space.type == 'VIEW_3D':\n"
|
||||
" space.viewport_shade = 'SOLID'\n"
|
||||
" space.clip_end = 8000.0\n";
|
||||
|
||||
os.centerView();
|
||||
os.close();
|
||||
conn.saveBlend();
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool ReadMAPUToBlender<PAKRouter<DNAMP1::PAKBridge>>(hecl::blender::Connection& conn, const MAPU& mapu,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP1::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
|
||||
template bool ReadMAPUToBlender<PAKRouter<DNAMP2::PAKBridge>>(hecl::blender::Connection& conn, const MAPU& mapu,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP2::PAKBridge>::EntryType& entry,
|
||||
bool force);
|
||||
|
||||
bool MAPU::Cook(const hecl::blender::MapUniverse& mapuIn, const hecl::ProjectPath& out) {
|
||||
MAPU mapu;
|
||||
|
||||
mapu.magic = 0xABCDEF01;
|
||||
mapu.version = 1;
|
||||
mapu.hexMapa = mapuIn.hexagonPath;
|
||||
|
||||
mapu.worldCount = mapuIn.worlds.size();
|
||||
mapu.worlds.reserve(mapuIn.worlds.size());
|
||||
for (const hecl::blender::MapUniverse::World& wld : mapuIn.worlds) {
|
||||
mapu.worlds.emplace_back();
|
||||
MAPU::World& wldOut = mapu.worlds.back();
|
||||
wldOut.name = wld.name;
|
||||
wldOut.mlvl = hecl::ProjectPath(wld.worldPath, _SYS_STR("!world.*"));
|
||||
wldOut.transform.xf[0] = wld.xf.val[0];
|
||||
wldOut.transform.xf[1] = wld.xf.val[1];
|
||||
wldOut.transform.xf[2] = wld.xf.val[2];
|
||||
wldOut.hexCount = wld.hexagons.size();
|
||||
wldOut.hexTransforms.reserve(wld.hexagons.size());
|
||||
for (const hecl::blender::Matrix4f& mtx : wld.hexagons) {
|
||||
wldOut.hexTransforms.emplace_back();
|
||||
MAPU::Transform& xf = wldOut.hexTransforms.back();
|
||||
xf.xf[0] = mtx.val[0];
|
||||
xf.xf[1] = mtx.val[1];
|
||||
xf.xf[2] = mtx.val[2];
|
||||
}
|
||||
wldOut.hexColor = zeus::CColor(wld.color.val);
|
||||
}
|
||||
|
||||
athena::io::FileWriter f(out.getAbsolutePath());
|
||||
mapu.write(f);
|
||||
int64_t rem = f.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
f.writeBytes((atInt8*)"\xff", 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMAPU
|
||||
|
|
|
@ -2,42 +2,33 @@
|
|||
|
||||
#include "DNACommon.hpp"
|
||||
|
||||
namespace DataSpec::DNAMAPU
|
||||
{
|
||||
struct MAPU : BigDNA
|
||||
{
|
||||
namespace DataSpec::DNAMAPU {
|
||||
struct MAPU : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<uint32_t> magic;
|
||||
Value<uint32_t> version;
|
||||
UniqueID32 hexMapa;
|
||||
Value<uint32_t> worldCount;
|
||||
struct Transform : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<uint32_t> magic;
|
||||
Value<uint32_t> version;
|
||||
UniqueID32 hexMapa;
|
||||
Value<uint32_t> worldCount;
|
||||
struct Transform : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atVec4f> xf[3];
|
||||
};
|
||||
struct World : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
String<-1> name;
|
||||
UniqueID32 mlvl;
|
||||
Transform transform;
|
||||
Value<uint32_t> hexCount;
|
||||
Vector<Transform, AT_DNA_COUNT(hexCount)> hexTransforms;
|
||||
DNAColor hexColor;
|
||||
};
|
||||
Vector<World, AT_DNA_COUNT(worldCount)> worlds;
|
||||
Value<atVec4f> xf[3];
|
||||
};
|
||||
struct World : BigDNA {
|
||||
AT_DECL_DNA
|
||||
String<-1> name;
|
||||
UniqueID32 mlvl;
|
||||
Transform transform;
|
||||
Value<uint32_t> hexCount;
|
||||
Vector<Transform, AT_DNA_COUNT(hexCount)> hexTransforms;
|
||||
DNAColor hexColor;
|
||||
};
|
||||
Vector<World, AT_DNA_COUNT(worldCount)> worlds;
|
||||
|
||||
static bool Cook(const hecl::blender::MapUniverse& mapu, const hecl::ProjectPath& out);
|
||||
static bool Cook(const hecl::blender::MapUniverse& mapu, const hecl::ProjectPath& out);
|
||||
};
|
||||
|
||||
template <typename PAKRouter>
|
||||
bool ReadMAPUToBlender(hecl::blender::Connection& conn,
|
||||
const MAPU& mapu,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
bool force);
|
||||
|
||||
}
|
||||
bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force);
|
||||
|
||||
} // namespace DataSpec::DNAMAPU
|
||||
|
|
|
@ -4,130 +4,109 @@
|
|||
#include "../DNAMP3/MLVL.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAMLVL
|
||||
{
|
||||
namespace DataSpec::DNAMLVL {
|
||||
|
||||
template <class PAKRouter, typename MLVL>
|
||||
bool ReadMLVLToBlender(hecl::blender::Connection& conn,
|
||||
const MLVL& mlvl,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
bool force,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged)
|
||||
{
|
||||
hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true);
|
||||
if (!force && blendPath.isFile())
|
||||
return true;
|
||||
|
||||
/* Create World Blend */
|
||||
if (!conn.createBlend(blendPath, hecl::blender::BlendType::World))
|
||||
return false;
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os.format("import bpy\n"
|
||||
"import bmesh\n"
|
||||
"from mathutils import Matrix\n"
|
||||
"\n"
|
||||
"bpy.context.scene.name = 'World'\n"
|
||||
"\n"
|
||||
"# Clear Scene\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" if ob.type != 'CAMERA':\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n");
|
||||
|
||||
/* Insert area empties */
|
||||
int areaIdx = 0;
|
||||
for (const auto& area : mlvl.areas)
|
||||
{
|
||||
const typename PAKRouter::EntryType* mreaEntry = pakRouter.lookupEntry(area.areaMREAId);
|
||||
hecl::SystemUTF8Conv areaDirName(*mreaEntry->unique.m_areaName);
|
||||
|
||||
os.AABBToBMesh(area.aabb[0], area.aabb[1]);
|
||||
zeus::simd_floats xfMtxF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
area.transformMtx[i].simd.copy_to(xfMtxF[i]);
|
||||
os.format("box_mesh = bpy.data.meshes.new('''%s''')\n"
|
||||
"bm.to_mesh(box_mesh)\n"
|
||||
"bm.free()\n"
|
||||
"box = bpy.data.objects.new(box_mesh.name, box_mesh)\n"
|
||||
"bpy.context.scene.objects.link(box)\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"box.rotation_mode = 'QUATERNION'\n"
|
||||
"box.location = mtxd[0]\n"
|
||||
"box.rotation_quaternion = mtxd[1]\n"
|
||||
"box.scale = mtxd[2]\n",
|
||||
areaDirName.str().data(),
|
||||
xfMtxF[0][0], xfMtxF[0][1], xfMtxF[0][2], xfMtxF[0][3],
|
||||
xfMtxF[1][0], xfMtxF[1][1], xfMtxF[1][2], xfMtxF[1][3],
|
||||
xfMtxF[2][0], xfMtxF[2][1], xfMtxF[2][2], xfMtxF[2][3]);
|
||||
|
||||
/* Insert dock planes */
|
||||
int dockIdx = 0;
|
||||
for (const auto& dock : area.docks)
|
||||
{
|
||||
os << "bm = bmesh.new()\n";
|
||||
zeus::CVector3f pvAvg;
|
||||
for (const atVec3f& pv : dock.planeVerts)
|
||||
pvAvg += pv;
|
||||
pvAvg /= zeus::CVector3f(dock.planeVerts.size());
|
||||
int idx = 0;
|
||||
for (const atVec3f& pv : dock.planeVerts)
|
||||
{
|
||||
const zeus::CVector3f pvRel = zeus::CVector3f(pv) - pvAvg;
|
||||
os.format("bm.verts.new((%f,%f,%f))\n"
|
||||
"bm.verts.ensure_lookup_table()\n",
|
||||
pvRel[0], pvRel[1], pvRel[2]);
|
||||
if (idx)
|
||||
os << "bm.edges.new((bm.verts[-2], bm.verts[-1]))\n";
|
||||
++idx;
|
||||
}
|
||||
os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n";
|
||||
os.format("dockMesh = bpy.data.meshes.new('DOCK_%02d_%02d')\n", areaIdx, dockIdx);
|
||||
os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n"
|
||||
"bpy.context.scene.objects.link(dockObj)\n"
|
||||
"bm.to_mesh(dockMesh)\n"
|
||||
"bm.free()\n"
|
||||
"dockObj.parent = box\n";
|
||||
os.format("dockObj.location = (%f,%f,%f)\n",
|
||||
float(pvAvg[0]), float(pvAvg[1]), float(pvAvg[2]));
|
||||
++dockIdx;
|
||||
}
|
||||
++areaIdx;
|
||||
}
|
||||
|
||||
os.centerView();
|
||||
os.close();
|
||||
conn.saveBlend();
|
||||
bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged) {
|
||||
hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true);
|
||||
if (!force && blendPath.isFile())
|
||||
return true;
|
||||
|
||||
/* Create World Blend */
|
||||
if (!conn.createBlend(blendPath, hecl::blender::BlendType::World))
|
||||
return false;
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os.format(
|
||||
"import bpy\n"
|
||||
"import bmesh\n"
|
||||
"from mathutils import Matrix\n"
|
||||
"\n"
|
||||
"bpy.context.scene.name = 'World'\n"
|
||||
"\n"
|
||||
"# Clear Scene\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" if ob.type != 'CAMERA':\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n");
|
||||
|
||||
/* Insert area empties */
|
||||
int areaIdx = 0;
|
||||
for (const auto& area : mlvl.areas) {
|
||||
const typename PAKRouter::EntryType* mreaEntry = pakRouter.lookupEntry(area.areaMREAId);
|
||||
hecl::SystemUTF8Conv areaDirName(*mreaEntry->unique.m_areaName);
|
||||
|
||||
os.AABBToBMesh(area.aabb[0], area.aabb[1]);
|
||||
zeus::simd_floats xfMtxF[3];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
area.transformMtx[i].simd.copy_to(xfMtxF[i]);
|
||||
os.format(
|
||||
"box_mesh = bpy.data.meshes.new('''%s''')\n"
|
||||
"bm.to_mesh(box_mesh)\n"
|
||||
"bm.free()\n"
|
||||
"box = bpy.data.objects.new(box_mesh.name, box_mesh)\n"
|
||||
"bpy.context.scene.objects.link(box)\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"box.rotation_mode = 'QUATERNION'\n"
|
||||
"box.location = mtxd[0]\n"
|
||||
"box.rotation_quaternion = mtxd[1]\n"
|
||||
"box.scale = mtxd[2]\n",
|
||||
areaDirName.str().data(), xfMtxF[0][0], xfMtxF[0][1], xfMtxF[0][2], xfMtxF[0][3], xfMtxF[1][0], xfMtxF[1][1],
|
||||
xfMtxF[1][2], xfMtxF[1][3], xfMtxF[2][0], xfMtxF[2][1], xfMtxF[2][2], xfMtxF[2][3]);
|
||||
|
||||
/* Insert dock planes */
|
||||
int dockIdx = 0;
|
||||
for (const auto& dock : area.docks) {
|
||||
os << "bm = bmesh.new()\n";
|
||||
zeus::CVector3f pvAvg;
|
||||
for (const atVec3f& pv : dock.planeVerts)
|
||||
pvAvg += pv;
|
||||
pvAvg /= zeus::CVector3f(dock.planeVerts.size());
|
||||
int idx = 0;
|
||||
for (const atVec3f& pv : dock.planeVerts) {
|
||||
const zeus::CVector3f pvRel = zeus::CVector3f(pv) - pvAvg;
|
||||
os.format(
|
||||
"bm.verts.new((%f,%f,%f))\n"
|
||||
"bm.verts.ensure_lookup_table()\n",
|
||||
pvRel[0], pvRel[1], pvRel[2]);
|
||||
if (idx)
|
||||
os << "bm.edges.new((bm.verts[-2], bm.verts[-1]))\n";
|
||||
++idx;
|
||||
}
|
||||
os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n";
|
||||
os.format("dockMesh = bpy.data.meshes.new('DOCK_%02d_%02d')\n", areaIdx, dockIdx);
|
||||
os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n"
|
||||
"bpy.context.scene.objects.link(dockObj)\n"
|
||||
"bm.to_mesh(dockMesh)\n"
|
||||
"bm.free()\n"
|
||||
"dockObj.parent = box\n";
|
||||
os.format("dockObj.location = (%f,%f,%f)\n", float(pvAvg[0]), float(pvAvg[1]), float(pvAvg[2]));
|
||||
++dockIdx;
|
||||
}
|
||||
++areaIdx;
|
||||
}
|
||||
|
||||
os.centerView();
|
||||
os.close();
|
||||
conn.saveBlend();
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool ReadMLVLToBlender<PAKRouter<DNAMP1::PAKBridge>, DNAMP1::MLVL>
|
||||
(hecl::blender::Connection& conn,
|
||||
const DNAMP1::MLVL& mlvl,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP1::PAKBridge>::EntryType& entry,
|
||||
bool force,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
template bool ReadMLVLToBlender<PAKRouter<DNAMP1::PAKBridge>, DNAMP1::MLVL>(
|
||||
hecl::blender::Connection& conn, const DNAMP1::MLVL& mlvl, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP1::PAKBridge>& pakRouter, const PAKRouter<DNAMP1::PAKBridge>::EntryType& entry, bool force,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
template bool ReadMLVLToBlender<PAKRouter<DNAMP2::PAKBridge>, DNAMP2::MLVL>
|
||||
(hecl::blender::Connection& conn,
|
||||
const DNAMP2::MLVL& mlvl,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP2::PAKBridge>::EntryType& entry,
|
||||
bool force,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
template bool ReadMLVLToBlender<PAKRouter<DNAMP2::PAKBridge>, DNAMP2::MLVL>(
|
||||
hecl::blender::Connection& conn, const DNAMP2::MLVL& mlvl, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP2::PAKBridge>& pakRouter, const PAKRouter<DNAMP2::PAKBridge>::EntryType& entry, bool force,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
template bool ReadMLVLToBlender<PAKRouter<DNAMP3::PAKBridge>, DNAMP3::MLVL>
|
||||
(hecl::blender::Connection& conn,
|
||||
const DNAMP3::MLVL& mlvl,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP3::PAKBridge>& pakRouter,
|
||||
const PAKRouter<DNAMP3::PAKBridge>::EntryType& entry,
|
||||
bool force,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
template bool ReadMLVLToBlender<PAKRouter<DNAMP3::PAKBridge>, DNAMP3::MLVL>(
|
||||
hecl::blender::Connection& conn, const DNAMP3::MLVL& mlvl, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<DNAMP3::PAKBridge>& pakRouter, const PAKRouter<DNAMP3::PAKBridge>::EntryType& entry, bool force,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMLVL
|
||||
|
|
|
@ -3,17 +3,11 @@
|
|||
#include "DNACommon.hpp"
|
||||
#include "zeus/CVector3f.hpp"
|
||||
|
||||
namespace DataSpec::DNAMLVL
|
||||
{
|
||||
namespace DataSpec::DNAMLVL {
|
||||
|
||||
template <class PAKRouter, typename MLVL>
|
||||
bool ReadMLVLToBlender(hecl::blender::Connection& conn,
|
||||
const MLVL& mlvl,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter,
|
||||
const typename PAKRouter::EntryType& entry,
|
||||
bool force,
|
||||
bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const hecl::ProjectPath& outPath,
|
||||
PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -5,86 +5,80 @@
|
|||
#include "gmm/gmm.h"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
using ColMesh = hecl::blender::ColMesh;
|
||||
|
||||
struct FittedOBB
|
||||
{
|
||||
zeus::CTransform xf;
|
||||
zeus::CVector3f he;
|
||||
struct FittedOBB {
|
||||
zeus::CTransform xf;
|
||||
zeus::CVector3f he;
|
||||
};
|
||||
|
||||
static std::vector<int> MakeRootTriangleIndex(const ColMesh& mesh)
|
||||
{
|
||||
std::vector<int> ret;
|
||||
ret.reserve(mesh.trianges.size());
|
||||
for (int i = 0; i < mesh.trianges.size(); ++i)
|
||||
ret.push_back(i);
|
||||
return ret;
|
||||
static std::vector<int> MakeRootTriangleIndex(const ColMesh& mesh) {
|
||||
std::vector<int> ret;
|
||||
ret.reserve(mesh.trianges.size());
|
||||
for (int i = 0; i < mesh.trianges.size(); ++i)
|
||||
ret.push_back(i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::unordered_set<uint32_t> GetTriangleVerts(const ColMesh& mesh, int triIdx)
|
||||
{
|
||||
const ColMesh::Triangle& T = mesh.trianges[triIdx];
|
||||
std::unordered_set<uint32_t> verts;
|
||||
verts.insert(mesh.edges[T.edges[0]].verts[0]);
|
||||
verts.insert(mesh.edges[T.edges[0]].verts[1]);
|
||||
verts.insert(mesh.edges[T.edges[1]].verts[0]);
|
||||
verts.insert(mesh.edges[T.edges[1]].verts[1]);
|
||||
verts.insert(mesh.edges[T.edges[2]].verts[0]);
|
||||
verts.insert(mesh.edges[T.edges[2]].verts[1]);
|
||||
return verts;
|
||||
static std::unordered_set<uint32_t> GetTriangleVerts(const ColMesh& mesh, int triIdx) {
|
||||
const ColMesh::Triangle& T = mesh.trianges[triIdx];
|
||||
std::unordered_set<uint32_t> verts;
|
||||
verts.insert(mesh.edges[T.edges[0]].verts[0]);
|
||||
verts.insert(mesh.edges[T.edges[0]].verts[1]);
|
||||
verts.insert(mesh.edges[T.edges[1]].verts[0]);
|
||||
verts.insert(mesh.edges[T.edges[1]].verts[1]);
|
||||
verts.insert(mesh.edges[T.edges[2]].verts[0]);
|
||||
verts.insert(mesh.edges[T.edges[2]].verts[1]);
|
||||
return verts;
|
||||
}
|
||||
|
||||
// method to set the OBB parameters which produce a box oriented according to
|
||||
// the covariance matrix C, which just containts the points pnts
|
||||
static FittedOBB BuildFromCovarianceMatrix(gmm::dense_matrix<float>& C,
|
||||
const ColMesh& mesh, const std::vector<int>& index)
|
||||
{
|
||||
FittedOBB ret;
|
||||
static FittedOBB BuildFromCovarianceMatrix(gmm::dense_matrix<float>& C, const ColMesh& mesh,
|
||||
const std::vector<int>& index) {
|
||||
FittedOBB ret;
|
||||
|
||||
// extract the eigenvalues and eigenvectors from C
|
||||
gmm::dense_matrix<float> eigvec(3,3);
|
||||
std::vector<float> eigval(3);
|
||||
using namespace gmm;
|
||||
using MAT1 = gmm::dense_matrix<float>;
|
||||
gmm::symmetric_qr_algorithm(C, eigval, eigvec, default_tol_for_qr);
|
||||
// extract the eigenvalues and eigenvectors from C
|
||||
gmm::dense_matrix<float> eigvec(3, 3);
|
||||
std::vector<float> eigval(3);
|
||||
using namespace gmm;
|
||||
using MAT1 = gmm::dense_matrix<float>;
|
||||
gmm::symmetric_qr_algorithm(C, eigval, eigvec, default_tol_for_qr);
|
||||
|
||||
// find the right, up and forward vectors from the eigenvectors
|
||||
zeus::CVector3f r(eigvec(0,0), eigvec(1,0), eigvec(2,0));
|
||||
zeus::CVector3f u(eigvec(0,1), eigvec(1,1), eigvec(2,1));
|
||||
zeus::CVector3f f(eigvec(0,2), eigvec(1,2), eigvec(2,2));
|
||||
r.normalize(); u.normalize(), f.normalize();
|
||||
// find the right, up and forward vectors from the eigenvectors
|
||||
zeus::CVector3f r(eigvec(0, 0), eigvec(1, 0), eigvec(2, 0));
|
||||
zeus::CVector3f u(eigvec(0, 1), eigvec(1, 1), eigvec(2, 1));
|
||||
zeus::CVector3f f(eigvec(0, 2), eigvec(1, 2), eigvec(2, 2));
|
||||
r.normalize();
|
||||
u.normalize(), f.normalize();
|
||||
|
||||
// set the rotation matrix using the eigvenvectors
|
||||
ret.xf.basis[0] = r;
|
||||
ret.xf.basis[1] = u;
|
||||
ret.xf.basis[2] = f;
|
||||
// set the rotation matrix using the eigvenvectors
|
||||
ret.xf.basis[0] = r;
|
||||
ret.xf.basis[1] = u;
|
||||
ret.xf.basis[2] = f;
|
||||
|
||||
// now build the bounding box extents in the rotated frame
|
||||
zeus::CVector3f minim(1e10f, 1e10f, 1e10f), maxim(-1e10f, -1e10f, -1e10f);
|
||||
for (int triIdx : index)
|
||||
{
|
||||
std::unordered_set<uint32_t> verts = GetTriangleVerts(mesh, triIdx);
|
||||
for (uint32_t v : verts)
|
||||
{
|
||||
const zeus::CVector3f& p = mesh.verts[v].val;
|
||||
zeus::CVector3f p_prime(r.dot(p), u.dot(p), f.dot(p));
|
||||
minim = zeus::min(minim, p_prime);
|
||||
maxim = zeus::max(maxim, p_prime);
|
||||
}
|
||||
// now build the bounding box extents in the rotated frame
|
||||
zeus::CVector3f minim(1e10f, 1e10f, 1e10f), maxim(-1e10f, -1e10f, -1e10f);
|
||||
for (int triIdx : index) {
|
||||
std::unordered_set<uint32_t> verts = GetTriangleVerts(mesh, triIdx);
|
||||
for (uint32_t v : verts) {
|
||||
const zeus::CVector3f& p = mesh.verts[v].val;
|
||||
zeus::CVector3f p_prime(r.dot(p), u.dot(p), f.dot(p));
|
||||
minim = zeus::min(minim, p_prime);
|
||||
maxim = zeus::max(maxim, p_prime);
|
||||
}
|
||||
}
|
||||
|
||||
// set the center of the OBB to be the average of the
|
||||
// minimum and maximum, and the extents be half of the
|
||||
// difference between the minimum and maximum
|
||||
zeus::CVector3f center = (maxim + minim) * 0.5f;
|
||||
ret.xf.origin = ret.xf.basis * center;
|
||||
ret.he = (maxim - minim) * 0.5f;
|
||||
// set the center of the OBB to be the average of the
|
||||
// minimum and maximum, and the extents be half of the
|
||||
// difference between the minimum and maximum
|
||||
zeus::CVector3f center = (maxim + minim) * 0.5f;
|
||||
ret.xf.origin = ret.xf.basis * center;
|
||||
ret.he = (maxim - minim) * 0.5f;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// builds an OBB from triangles specified as an array of
|
||||
|
@ -93,166 +87,164 @@ static FittedOBB BuildFromCovarianceMatrix(gmm::dense_matrix<float>& C,
|
|||
// method build_from_covariance_matrix() method to fit
|
||||
// the box. ALL points will be fit in the box, regardless
|
||||
// of whether they are indexed by a triangle or not.
|
||||
static FittedOBB FitOBB(const ColMesh& mesh, const std::vector<int>& index)
|
||||
{
|
||||
float Ai, Am=0.0;
|
||||
zeus::CVector3f mu, mui;
|
||||
gmm::dense_matrix<float> C(3,3);
|
||||
float cxx=0.0, cxy=0.0, cxz=0.0, cyy=0.0, cyz=0.0, czz=0.0;
|
||||
static FittedOBB FitOBB(const ColMesh& mesh, const std::vector<int>& index) {
|
||||
float Ai, Am = 0.0;
|
||||
zeus::CVector3f mu, mui;
|
||||
gmm::dense_matrix<float> C(3, 3);
|
||||
float cxx = 0.0, cxy = 0.0, cxz = 0.0, cyy = 0.0, cyz = 0.0, czz = 0.0;
|
||||
|
||||
// loop over the triangles this time to find the
|
||||
// mean location
|
||||
for (int i : index)
|
||||
{
|
||||
std::unordered_set<uint32_t> verts = GetTriangleVerts(mesh, i);
|
||||
auto it = verts.begin();
|
||||
zeus::CVector3f p = mesh.verts[*it++].val;
|
||||
zeus::CVector3f q = mesh.verts[*it++].val;
|
||||
zeus::CVector3f r = mesh.verts[*it++].val;
|
||||
mui = (p+q+r)/3.f;
|
||||
Ai = (q-p).cross(r-p).magnitude() / 2.f;
|
||||
mu += mui*Ai;
|
||||
Am += Ai;
|
||||
// loop over the triangles this time to find the
|
||||
// mean location
|
||||
for (int i : index) {
|
||||
std::unordered_set<uint32_t> verts = GetTriangleVerts(mesh, i);
|
||||
auto it = verts.begin();
|
||||
zeus::CVector3f p = mesh.verts[*it++].val;
|
||||
zeus::CVector3f q = mesh.verts[*it++].val;
|
||||
zeus::CVector3f r = mesh.verts[*it++].val;
|
||||
mui = (p + q + r) / 3.f;
|
||||
Ai = (q - p).cross(r - p).magnitude() / 2.f;
|
||||
mu += mui * Ai;
|
||||
Am += Ai;
|
||||
|
||||
// these bits set the c terms to Am*E[xx], Am*E[xy], Am*E[xz]....
|
||||
cxx += ( 9.0*mui.x()*mui.x() + p.x()*p.x() + q.x()*q.x() + r.x()*r.x() )*(Ai/12.0);
|
||||
cxy += ( 9.0*mui.x()*mui.y() + p.x()*p.y() + q.x()*q.y() + r.x()*r.y() )*(Ai/12.0);
|
||||
cxz += ( 9.0*mui.x()*mui.z() + p.x()*p.z() + q.x()*q.z() + r.x()*r.z() )*(Ai/12.0);
|
||||
cyy += ( 9.0*mui.y()*mui.y() + p.y()*p.y() + q.y()*q.y() + r.y()*r.y() )*(Ai/12.0);
|
||||
cyz += ( 9.0*mui.y()*mui.z() + p.y()*p.z() + q.y()*q.z() + r.y()*r.z() )*(Ai/12.0);
|
||||
}
|
||||
// these bits set the c terms to Am*E[xx], Am*E[xy], Am*E[xz]....
|
||||
cxx += (9.0 * mui.x() * mui.x() + p.x() * p.x() + q.x() * q.x() + r.x() * r.x()) * (Ai / 12.0);
|
||||
cxy += (9.0 * mui.x() * mui.y() + p.x() * p.y() + q.x() * q.y() + r.x() * r.y()) * (Ai / 12.0);
|
||||
cxz += (9.0 * mui.x() * mui.z() + p.x() * p.z() + q.x() * q.z() + r.x() * r.z()) * (Ai / 12.0);
|
||||
cyy += (9.0 * mui.y() * mui.y() + p.y() * p.y() + q.y() * q.y() + r.y() * r.y()) * (Ai / 12.0);
|
||||
cyz += (9.0 * mui.y() * mui.z() + p.y() * p.z() + q.y() * q.z() + r.y() * r.z()) * (Ai / 12.0);
|
||||
}
|
||||
|
||||
if (zeus::close_enough(Am, 0.f))
|
||||
return {};
|
||||
if (zeus::close_enough(Am, 0.f))
|
||||
return {};
|
||||
|
||||
// divide out the Am fraction from the average position and
|
||||
// covariance terms
|
||||
mu = mu / Am;
|
||||
cxx /= Am; cxy /= Am; cxz /= Am; cyy /= Am; cyz /= Am; czz /= Am;
|
||||
// divide out the Am fraction from the average position and
|
||||
// covariance terms
|
||||
mu = mu / Am;
|
||||
cxx /= Am;
|
||||
cxy /= Am;
|
||||
cxz /= Am;
|
||||
cyy /= Am;
|
||||
cyz /= Am;
|
||||
czz /= Am;
|
||||
|
||||
// now subtract off the E[x]*E[x], E[x]*E[y], ... terms
|
||||
cxx -= mu.x()*mu.x(); cxy -= mu.x()*mu.y(); cxz -= mu.x()*mu.z();
|
||||
cyy -= mu.y()*mu.y(); cyz -= mu.y()*mu.z(); czz -= mu.z()*mu.z();
|
||||
// now subtract off the E[x]*E[x], E[x]*E[y], ... terms
|
||||
cxx -= mu.x() * mu.x();
|
||||
cxy -= mu.x() * mu.y();
|
||||
cxz -= mu.x() * mu.z();
|
||||
cyy -= mu.y() * mu.y();
|
||||
cyz -= mu.y() * mu.z();
|
||||
czz -= mu.z() * mu.z();
|
||||
|
||||
// now build the covariance matrix
|
||||
C(0,0)=cxx; C(0,1)=cxy; C(0,2)=cxz;
|
||||
C(1,0)=cxy; C(1,1)=cyy; C(1,2)=cyz;
|
||||
C(2,0)=cxz; C(2,1)=cyz; C(2,2)=czz;
|
||||
// now build the covariance matrix
|
||||
C(0, 0) = cxx;
|
||||
C(0, 1) = cxy;
|
||||
C(0, 2) = cxz;
|
||||
C(1, 0) = cxy;
|
||||
C(1, 1) = cyy;
|
||||
C(1, 2) = cyz;
|
||||
C(2, 0) = cxz;
|
||||
C(2, 1) = cyz;
|
||||
C(2, 2) = czz;
|
||||
|
||||
// set the obb parameters from the covariance matrix
|
||||
return BuildFromCovarianceMatrix(C, mesh, index);
|
||||
// set the obb parameters from the covariance matrix
|
||||
return BuildFromCovarianceMatrix(C, mesh, index);
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
static void MakeLeaf(const ColMesh& mesh, const std::vector<int>& index, Node& n)
|
||||
{
|
||||
n.left.reset();
|
||||
n.right.reset();
|
||||
n.isLeaf = true;
|
||||
n.leafData = std::make_unique<typename Node::LeafData>();
|
||||
n.leafData->triangleIndexCount = atUint32(index.size());
|
||||
n.leafData->triangleIndices.reserve(n.leafData->triangleIndexCount);
|
||||
for (int i : index)
|
||||
n.leafData->triangleIndices.push_back(i);
|
||||
static void MakeLeaf(const ColMesh& mesh, const std::vector<int>& index, Node& n) {
|
||||
n.left.reset();
|
||||
n.right.reset();
|
||||
n.isLeaf = true;
|
||||
n.leafData = std::make_unique<typename Node::LeafData>();
|
||||
n.leafData->triangleIndexCount = atUint32(index.size());
|
||||
n.leafData->triangleIndices.reserve(n.leafData->triangleIndexCount);
|
||||
for (int i : index)
|
||||
n.leafData->triangleIndices.push_back(i);
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
static std::unique_ptr<Node> RecursiveMakeNode(const ColMesh& mesh, const std::vector<int>& index)
|
||||
{
|
||||
// calculate root OBB
|
||||
FittedOBB obb = FitOBB(mesh, index);
|
||||
static std::unique_ptr<Node> RecursiveMakeNode(const ColMesh& mesh, const std::vector<int>& index) {
|
||||
// calculate root OBB
|
||||
FittedOBB obb = FitOBB(mesh, index);
|
||||
|
||||
// make results row-major and also invert the rotation basis
|
||||
obb.xf.basis.transpose();
|
||||
// make results row-major and also invert the rotation basis
|
||||
obb.xf.basis.transpose();
|
||||
|
||||
std::unique_ptr<Node> n = std::make_unique<Node>();
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
n->xf[i] = zeus::CVector4f{obb.xf.basis[i]};
|
||||
n->xf[i].simd[3] = float(obb.xf.origin[i]);
|
||||
}
|
||||
n->halfExtent = obb.he;
|
||||
|
||||
// terminate branch when volume < 1.0
|
||||
if (obb.he[0] * obb.he[1] * obb.he[2] < 1.f)
|
||||
{
|
||||
MakeLeaf(mesh, index, *n);
|
||||
return n;
|
||||
}
|
||||
|
||||
n->isLeaf = false;
|
||||
|
||||
std::vector<int> indexNeg[3];
|
||||
std::vector<int> indexPos[3];
|
||||
for (int c = 0; c < 3; ++c)
|
||||
{
|
||||
// subdivide negative side
|
||||
indexNeg[c].reserve(index.size());
|
||||
for (int i : index)
|
||||
{
|
||||
std::unordered_set<uint32_t> verts = GetTriangleVerts(mesh, i);
|
||||
for (uint32_t vtx : verts)
|
||||
{
|
||||
zeus::CVector3f v = mesh.verts[vtx].val;
|
||||
v = obb.xf.basis * (v - obb.xf.origin);
|
||||
if (v[c] < 0.f)
|
||||
{
|
||||
indexNeg[c].push_back(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// subdivide positive side
|
||||
indexPos[c].reserve(index.size());
|
||||
for (int i : index)
|
||||
{
|
||||
std::unordered_set<uint32_t> verts = GetTriangleVerts(mesh, i);
|
||||
for (uint32_t vtx : verts)
|
||||
{
|
||||
zeus::CVector3f v = mesh.verts[vtx].val;
|
||||
v = obb.xf.basis * (v - obb.xf.origin);
|
||||
if (v[c] >= 0.f)
|
||||
{
|
||||
indexPos[c].push_back(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t idxMin = index.size();
|
||||
int minComp = -1;
|
||||
for (int c = 0; c < 3; ++c)
|
||||
{
|
||||
size_t test = std::max(indexNeg[c].size(), indexPos[c].size());
|
||||
if (test < idxMin && test < index.size() * 3 / 4)
|
||||
{
|
||||
minComp = c;
|
||||
idxMin = test;
|
||||
}
|
||||
}
|
||||
|
||||
if (minComp == -1)
|
||||
{
|
||||
MakeLeaf(mesh, index, *n);
|
||||
return n;
|
||||
}
|
||||
|
||||
n->left = RecursiveMakeNode<Node>(mesh, indexNeg[minComp]);
|
||||
n->right = RecursiveMakeNode<Node>(mesh, indexPos[minComp]);
|
||||
std::unique_ptr<Node> n = std::make_unique<Node>();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
n->xf[i] = zeus::CVector4f{obb.xf.basis[i]};
|
||||
n->xf[i].simd[3] = float(obb.xf.origin[i]);
|
||||
}
|
||||
n->halfExtent = obb.he;
|
||||
|
||||
// terminate branch when volume < 1.0
|
||||
if (obb.he[0] * obb.he[1] * obb.he[2] < 1.f) {
|
||||
MakeLeaf(mesh, index, *n);
|
||||
return n;
|
||||
}
|
||||
|
||||
n->isLeaf = false;
|
||||
|
||||
std::vector<int> indexNeg[3];
|
||||
std::vector<int> indexPos[3];
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
// subdivide negative side
|
||||
indexNeg[c].reserve(index.size());
|
||||
for (int i : index) {
|
||||
std::unordered_set<uint32_t> verts = GetTriangleVerts(mesh, i);
|
||||
for (uint32_t vtx : verts) {
|
||||
zeus::CVector3f v = mesh.verts[vtx].val;
|
||||
v = obb.xf.basis * (v - obb.xf.origin);
|
||||
if (v[c] < 0.f) {
|
||||
indexNeg[c].push_back(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// subdivide positive side
|
||||
indexPos[c].reserve(index.size());
|
||||
for (int i : index) {
|
||||
std::unordered_set<uint32_t> verts = GetTriangleVerts(mesh, i);
|
||||
for (uint32_t vtx : verts) {
|
||||
zeus::CVector3f v = mesh.verts[vtx].val;
|
||||
v = obb.xf.basis * (v - obb.xf.origin);
|
||||
if (v[c] >= 0.f) {
|
||||
indexPos[c].push_back(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t idxMin = index.size();
|
||||
int minComp = -1;
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
size_t test = std::max(indexNeg[c].size(), indexPos[c].size());
|
||||
if (test < idxMin && test < index.size() * 3 / 4) {
|
||||
minComp = c;
|
||||
idxMin = test;
|
||||
}
|
||||
}
|
||||
|
||||
if (minComp == -1) {
|
||||
MakeLeaf(mesh, index, *n);
|
||||
return n;
|
||||
}
|
||||
|
||||
n->left = RecursiveMakeNode<Node>(mesh, indexNeg[minComp]);
|
||||
n->right = RecursiveMakeNode<Node>(mesh, indexPos[minComp]);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
template <typename Node>
|
||||
std::unique_ptr<Node> OBBTreeBuilder::buildCol(const ColMesh& mesh)
|
||||
{
|
||||
std::vector<int> root = MakeRootTriangleIndex(mesh);
|
||||
return RecursiveMakeNode<Node>(mesh, root);
|
||||
std::unique_ptr<Node> OBBTreeBuilder::buildCol(const ColMesh& mesh) {
|
||||
std::vector<int> root = MakeRootTriangleIndex(mesh);
|
||||
return RecursiveMakeNode<Node>(mesh, root);
|
||||
}
|
||||
|
||||
template std::unique_ptr<DNAMP1::DCLN::Collision::Node>
|
||||
OBBTreeBuilder::buildCol<DNAMP1::DCLN::Collision::Node>(const ColMesh& mesh);
|
||||
|
||||
}
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,15 +2,12 @@
|
|||
|
||||
#include "DNACommon.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
struct OBBTreeBuilder
|
||||
{
|
||||
using ColMesh = hecl::blender::ColMesh;
|
||||
template <typename Node>
|
||||
static std::unique_ptr<Node> buildCol(const ColMesh& mesh);
|
||||
struct OBBTreeBuilder {
|
||||
using ColMesh = hecl::blender::ColMesh;
|
||||
template <typename Node>
|
||||
static std::unique_ptr<Node> buildCol(const ColMesh& mesh);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,73 +5,61 @@
|
|||
#include <array>
|
||||
#include "zeus/CMatrix4f.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
/** PAK entry stream reader */
|
||||
class PAKEntryReadStream : public athena::io::IStreamReader
|
||||
{
|
||||
std::unique_ptr<atUint8[]> m_buf;
|
||||
atUint64 m_sz;
|
||||
atUint64 m_pos;
|
||||
class PAKEntryReadStream : public athena::io::IStreamReader {
|
||||
std::unique_ptr<atUint8[]> m_buf;
|
||||
atUint64 m_sz;
|
||||
atUint64 m_pos;
|
||||
|
||||
public:
|
||||
PAKEntryReadStream() {}
|
||||
operator bool() const {return m_buf.operator bool();}
|
||||
PAKEntryReadStream(const PAKEntryReadStream& other) = delete;
|
||||
PAKEntryReadStream(PAKEntryReadStream&& other) = default;
|
||||
PAKEntryReadStream& operator=(const PAKEntryReadStream& other) = delete;
|
||||
PAKEntryReadStream& operator=(PAKEntryReadStream&& other) = default;
|
||||
PAKEntryReadStream(std::unique_ptr<atUint8[]>&& buf, atUint64 sz, atUint64 pos)
|
||||
: m_buf(std::move(buf)), m_sz(sz), m_pos(pos)
|
||||
{
|
||||
if (m_pos >= m_sz)
|
||||
LogDNACommon.report(logvisor::Fatal, "PAK stream cursor overrun");
|
||||
}
|
||||
void seek(atInt64 pos, athena::SeekOrigin origin)
|
||||
{
|
||||
if (origin == athena::Begin)
|
||||
m_pos = pos;
|
||||
else if (origin == athena::Current)
|
||||
m_pos += pos;
|
||||
else if (origin == athena::End)
|
||||
m_pos = m_sz + pos;
|
||||
if (m_pos > m_sz)
|
||||
LogDNACommon.report(logvisor::Fatal, "PAK stream cursor overrun");
|
||||
}
|
||||
atUint64 position() const {return m_pos;}
|
||||
atUint64 length() const {return m_sz;}
|
||||
const atUint8* data() const {return m_buf.get();}
|
||||
atUint64 readUBytesToBuf(void* buf, atUint64 len)
|
||||
{
|
||||
atUint64 bufEnd = m_pos + len;
|
||||
if (bufEnd > m_sz)
|
||||
len -= bufEnd - m_sz;
|
||||
memmove(buf, m_buf.get() + m_pos, len);
|
||||
m_pos += len;
|
||||
return len;
|
||||
}
|
||||
PAKEntryReadStream() {}
|
||||
operator bool() const { return m_buf.operator bool(); }
|
||||
PAKEntryReadStream(const PAKEntryReadStream& other) = delete;
|
||||
PAKEntryReadStream(PAKEntryReadStream&& other) = default;
|
||||
PAKEntryReadStream& operator=(const PAKEntryReadStream& other) = delete;
|
||||
PAKEntryReadStream& operator=(PAKEntryReadStream&& other) = default;
|
||||
PAKEntryReadStream(std::unique_ptr<atUint8[]>&& buf, atUint64 sz, atUint64 pos)
|
||||
: m_buf(std::move(buf)), m_sz(sz), m_pos(pos) {
|
||||
if (m_pos >= m_sz)
|
||||
LogDNACommon.report(logvisor::Fatal, "PAK stream cursor overrun");
|
||||
}
|
||||
void seek(atInt64 pos, athena::SeekOrigin origin) {
|
||||
if (origin == athena::Begin)
|
||||
m_pos = pos;
|
||||
else if (origin == athena::Current)
|
||||
m_pos += pos;
|
||||
else if (origin == athena::End)
|
||||
m_pos = m_sz + pos;
|
||||
if (m_pos > m_sz)
|
||||
LogDNACommon.report(logvisor::Fatal, "PAK stream cursor overrun");
|
||||
}
|
||||
atUint64 position() const { return m_pos; }
|
||||
atUint64 length() const { return m_sz; }
|
||||
const atUint8* data() const { return m_buf.get(); }
|
||||
atUint64 readUBytesToBuf(void* buf, atUint64 len) {
|
||||
atUint64 bufEnd = m_pos + len;
|
||||
if (bufEnd > m_sz)
|
||||
len -= bufEnd - m_sz;
|
||||
memmove(buf, m_buf.get() + m_pos, len);
|
||||
m_pos += len;
|
||||
return len;
|
||||
}
|
||||
};
|
||||
|
||||
struct UniqueResult
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
NotFound,
|
||||
Pak,
|
||||
Level,
|
||||
Area,
|
||||
Layer
|
||||
} m_type = Type::NotFound;
|
||||
const hecl::SystemString* m_levelName = nullptr;
|
||||
const hecl::SystemString* m_areaName = nullptr;
|
||||
const hecl::SystemString* m_layerName = nullptr;
|
||||
UniqueResult() = default;
|
||||
UniqueResult(Type tp) : m_type(tp) {}
|
||||
struct UniqueResult {
|
||||
enum class Type { NotFound, Pak, Level, Area, Layer } m_type = Type::NotFound;
|
||||
const hecl::SystemString* m_levelName = nullptr;
|
||||
const hecl::SystemString* m_areaName = nullptr;
|
||||
const hecl::SystemString* m_layerName = nullptr;
|
||||
UniqueResult() = default;
|
||||
UniqueResult(Type tp) : m_type(tp) {}
|
||||
|
||||
template <class PAKBRIDGE>
|
||||
void checkEntry(const PAKBRIDGE& pakBridge, const typename PAKBRIDGE::PAKType::Entry& entry);
|
||||
template <class PAKBRIDGE>
|
||||
void checkEntry(const PAKBRIDGE& pakBridge, const typename PAKBRIDGE::PAKType::Entry& entry);
|
||||
|
||||
hecl::ProjectPath uniquePath(const hecl::ProjectPath& pakPath) const;
|
||||
hecl::ProjectPath uniquePath(const hecl::ProjectPath& pakPath) const;
|
||||
};
|
||||
|
||||
template <class BRIDGETYPE>
|
||||
|
@ -79,161 +67,154 @@ class PAKRouter;
|
|||
|
||||
/** Resource extractor type */
|
||||
template <class PAKBRIDGE>
|
||||
struct ResExtractor
|
||||
{
|
||||
std::function<bool(PAKEntryReadStream&, const hecl::ProjectPath&)> func_a;
|
||||
std::function<bool(const SpecBase&, PAKEntryReadStream&, const hecl::ProjectPath&, PAKRouter<PAKBRIDGE>&,
|
||||
const typename PAKBRIDGE::PAKType::Entry&, bool, hecl::blender::Token&,
|
||||
std::function<void(const hecl::SystemChar*)>)> func_b;
|
||||
std::array<const hecl::SystemChar*, 6> fileExts = {};
|
||||
unsigned weight = 0;
|
||||
std::function<void(const SpecBase&, PAKEntryReadStream&, PAKRouter<PAKBRIDGE>&,
|
||||
typename PAKBRIDGE::PAKType::Entry&)> func_name;
|
||||
struct ResExtractor {
|
||||
std::function<bool(PAKEntryReadStream&, const hecl::ProjectPath&)> func_a;
|
||||
std::function<bool(const SpecBase&, PAKEntryReadStream&, const hecl::ProjectPath&, PAKRouter<PAKBRIDGE>&,
|
||||
const typename PAKBRIDGE::PAKType::Entry&, bool, hecl::blender::Token&,
|
||||
std::function<void(const hecl::SystemChar*)>)>
|
||||
func_b;
|
||||
std::array<const hecl::SystemChar*, 6> fileExts = {};
|
||||
unsigned weight = 0;
|
||||
std::function<void(const SpecBase&, PAKEntryReadStream&, PAKRouter<PAKBRIDGE>&, typename PAKBRIDGE::PAKType::Entry&)>
|
||||
func_name;
|
||||
|
||||
ResExtractor() = default;
|
||||
ResExtractor() = default;
|
||||
|
||||
ResExtractor(std::function<bool(PAKEntryReadStream&, const hecl::ProjectPath&)> func,
|
||||
std::array<const hecl::SystemChar*, 6>&& fileExtsIn, unsigned weightin=0,
|
||||
std::function<void(const SpecBase&, PAKEntryReadStream&, PAKRouter<PAKBRIDGE>&,
|
||||
typename PAKBRIDGE::PAKType::Entry&)> nfunc={})
|
||||
: func_a(std::move(func)), fileExts(std::move(fileExtsIn)), weight(weightin), func_name(std::move(nfunc)) {}
|
||||
ResExtractor(std::function<bool(PAKEntryReadStream&, const hecl::ProjectPath&)> func,
|
||||
std::array<const hecl::SystemChar*, 6>&& fileExtsIn, unsigned weightin = 0,
|
||||
std::function<void(const SpecBase&, PAKEntryReadStream&, PAKRouter<PAKBRIDGE>&,
|
||||
typename PAKBRIDGE::PAKType::Entry&)>
|
||||
nfunc = {})
|
||||
: func_a(std::move(func)), fileExts(std::move(fileExtsIn)), weight(weightin), func_name(std::move(nfunc)) {}
|
||||
|
||||
ResExtractor(std::function<bool(const SpecBase&, PAKEntryReadStream&, const hecl::ProjectPath&, PAKRouter<PAKBRIDGE>&,
|
||||
const typename PAKBRIDGE::PAKType::Entry&, bool, hecl::blender::Token&,
|
||||
std::function<void(const hecl::SystemChar*)>)> func,
|
||||
std::array<const hecl::SystemChar*, 6>&& fileExtsIn, unsigned weightin=0,
|
||||
std::function<void(const SpecBase&, PAKEntryReadStream&, PAKRouter<PAKBRIDGE>&,
|
||||
typename PAKBRIDGE::PAKType::Entry&)> nfunc={})
|
||||
: func_b(std::move(func)), fileExts(std::move(fileExtsIn)), weight(weightin), func_name(std::move(nfunc)) {}
|
||||
ResExtractor(std::function<bool(const SpecBase&, PAKEntryReadStream&, const hecl::ProjectPath&, PAKRouter<PAKBRIDGE>&,
|
||||
const typename PAKBRIDGE::PAKType::Entry&, bool, hecl::blender::Token&,
|
||||
std::function<void(const hecl::SystemChar*)>)>
|
||||
func,
|
||||
std::array<const hecl::SystemChar*, 6>&& fileExtsIn, unsigned weightin = 0,
|
||||
std::function<void(const SpecBase&, PAKEntryReadStream&, PAKRouter<PAKBRIDGE>&,
|
||||
typename PAKBRIDGE::PAKType::Entry&)>
|
||||
nfunc = {})
|
||||
: func_b(std::move(func)), fileExts(std::move(fileExtsIn)), weight(weightin), func_name(std::move(nfunc)) {}
|
||||
|
||||
bool IsFullyExtracted(const hecl::ProjectPath& path) const
|
||||
{
|
||||
hecl::ProjectPath::Type tp = path.getPathType();
|
||||
if (tp == hecl::ProjectPath::Type::None)
|
||||
return false;
|
||||
else if (tp == hecl::ProjectPath::Type::Glob)
|
||||
{
|
||||
for (int i=0 ; i<6 ; ++i)
|
||||
{
|
||||
if (!fileExts[i])
|
||||
break;
|
||||
hecl::ProjectPath withExt = path.getWithExtension(fileExts[i], true);
|
||||
if (withExt.isNone())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
bool IsFullyExtracted(const hecl::ProjectPath& path) const {
|
||||
hecl::ProjectPath::Type tp = path.getPathType();
|
||||
if (tp == hecl::ProjectPath::Type::None)
|
||||
return false;
|
||||
else if (tp == hecl::ProjectPath::Type::Glob) {
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
if (!fileExts[i])
|
||||
break;
|
||||
hecl::ProjectPath withExt = path.getWithExtension(fileExts[i], true);
|
||||
if (withExt.isNone())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** Level hierarchy representation */
|
||||
template <class IDType>
|
||||
struct Level
|
||||
{
|
||||
struct Level {
|
||||
hecl::SystemString name;
|
||||
struct Area {
|
||||
hecl::SystemString name;
|
||||
struct Area
|
||||
{
|
||||
hecl::SystemString name;
|
||||
struct Layer
|
||||
{
|
||||
hecl::SystemString name;
|
||||
bool active;
|
||||
std::unordered_set<IDType> resources;
|
||||
};
|
||||
std::vector<Layer> layers;
|
||||
std::unordered_set<IDType> resources;
|
||||
struct Layer {
|
||||
hecl::SystemString name;
|
||||
bool active;
|
||||
std::unordered_set<IDType> resources;
|
||||
};
|
||||
std::unordered_map<IDType, Area> areas;
|
||||
std::vector<Layer> layers;
|
||||
std::unordered_set<IDType> resources;
|
||||
};
|
||||
std::unordered_map<IDType, Area> areas;
|
||||
};
|
||||
|
||||
/** PAKRouter (for detecting shared entry locations) */
|
||||
template <class BRIDGETYPE>
|
||||
class PAKRouter : public PAKRouterBase
|
||||
{
|
||||
class PAKRouter : public PAKRouterBase {
|
||||
public:
|
||||
using PAKType = typename BRIDGETYPE::PAKType;
|
||||
using IDType = typename PAKType::IDType;
|
||||
using EntryType = typename PAKType::Entry;
|
||||
using PAKType = typename BRIDGETYPE::PAKType;
|
||||
using IDType = typename PAKType::IDType;
|
||||
using EntryType = typename PAKType::Entry;
|
||||
|
||||
private:
|
||||
const std::vector<BRIDGETYPE>* m_bridges = nullptr;
|
||||
std::vector<std::pair<hecl::ProjectPath,hecl::ProjectPath>> m_bridgePaths;
|
||||
ThreadLocalPtr<void> m_curBridgeIdx;
|
||||
const hecl::ProjectPath& m_gameWorking;
|
||||
const hecl::ProjectPath& m_gameCooked;
|
||||
hecl::ProjectPath m_sharedWorking;
|
||||
hecl::ProjectPath m_sharedCooked;
|
||||
ThreadLocalPtr<const PAKType> m_pak;
|
||||
ThreadLocalPtr<const nod::Node> m_node;
|
||||
std::unordered_map<IDType, std::pair<size_t, const EntryType*>> m_uniqueEntries;
|
||||
std::unordered_map<IDType, std::pair<size_t, const EntryType*>> m_sharedEntries;
|
||||
std::unordered_map<IDType, hecl::ProjectPath> m_overrideEntries;
|
||||
CharacterAssociations<IDType> m_charAssoc;
|
||||
std::unordered_map<IDType, zeus::CMatrix4f> m_mapaTransforms;
|
||||
const std::vector<BRIDGETYPE>* m_bridges = nullptr;
|
||||
std::vector<std::pair<hecl::ProjectPath, hecl::ProjectPath>> m_bridgePaths;
|
||||
ThreadLocalPtr<void> m_curBridgeIdx;
|
||||
const hecl::ProjectPath& m_gameWorking;
|
||||
const hecl::ProjectPath& m_gameCooked;
|
||||
hecl::ProjectPath m_sharedWorking;
|
||||
hecl::ProjectPath m_sharedCooked;
|
||||
ThreadLocalPtr<const PAKType> m_pak;
|
||||
ThreadLocalPtr<const nod::Node> m_node;
|
||||
std::unordered_map<IDType, std::pair<size_t, const EntryType*>> m_uniqueEntries;
|
||||
std::unordered_map<IDType, std::pair<size_t, const EntryType*>> m_sharedEntries;
|
||||
std::unordered_map<IDType, hecl::ProjectPath> m_overrideEntries;
|
||||
CharacterAssociations<IDType> m_charAssoc;
|
||||
std::unordered_map<IDType, zeus::CMatrix4f> m_mapaTransforms;
|
||||
|
||||
hecl::ProjectPath getCharacterWorking(const EntryType* entry) const;
|
||||
hecl::ProjectPath getCharacterWorking(const EntryType* entry) const;
|
||||
|
||||
public:
|
||||
PAKRouter(const SpecBase& dataSpec, const hecl::ProjectPath& working, const hecl::ProjectPath& cooked)
|
||||
: PAKRouterBase(dataSpec),
|
||||
m_gameWorking(working), m_gameCooked(cooked),
|
||||
m_sharedWorking(working, "Shared"), m_sharedCooked(cooked, "Shared") {}
|
||||
PAKRouter(const SpecBase& dataSpec, const hecl::ProjectPath& working, const hecl::ProjectPath& cooked)
|
||||
: PAKRouterBase(dataSpec)
|
||||
, m_gameWorking(working)
|
||||
, m_gameCooked(cooked)
|
||||
, m_sharedWorking(working, "Shared")
|
||||
, m_sharedCooked(cooked, "Shared") {}
|
||||
|
||||
void build(std::vector<BRIDGETYPE>& bridges, std::function<void(float)> progress);
|
||||
void build(std::vector<BRIDGETYPE>& bridges, std::function<void(float)> progress);
|
||||
|
||||
void enterPAKBridge(const BRIDGETYPE& pakBridge);
|
||||
void enterPAKBridge(const BRIDGETYPE& pakBridge);
|
||||
|
||||
using PAKRouterBase::getWorking;
|
||||
hecl::ProjectPath getWorking(const EntryType* entry,
|
||||
const ResExtractor<BRIDGETYPE>& extractor) const;
|
||||
hecl::ProjectPath getWorking(const EntryType* entry) const;
|
||||
hecl::ProjectPath getWorking(const IDType& id, bool silenceWarnings=false) const;
|
||||
hecl::ProjectPath getCooked(const EntryType* entry) const;
|
||||
hecl::ProjectPath getCooked(const IDType& id, bool silenceWarnings=false) const;
|
||||
bool isShared() const
|
||||
{
|
||||
const PAKType* pak = m_pak.get();
|
||||
return pak ? !pak->m_noShare : false;
|
||||
}
|
||||
using PAKRouterBase::getWorking;
|
||||
hecl::ProjectPath getWorking(const EntryType* entry, const ResExtractor<BRIDGETYPE>& extractor) const;
|
||||
hecl::ProjectPath getWorking(const EntryType* entry) const;
|
||||
hecl::ProjectPath getWorking(const IDType& id, bool silenceWarnings = false) const;
|
||||
hecl::ProjectPath getCooked(const EntryType* entry) const;
|
||||
hecl::ProjectPath getCooked(const IDType& id, bool silenceWarnings = false) const;
|
||||
bool isShared() const {
|
||||
const PAKType* pak = m_pak.get();
|
||||
return pak ? !pak->m_noShare : false;
|
||||
}
|
||||
|
||||
hecl::SystemString getResourceRelativePath(const EntryType& a, const IDType& b) const;
|
||||
hecl::SystemString getResourceRelativePath(const EntryType& a, const IDType& b) const;
|
||||
|
||||
std::string getBestEntryName(const EntryType& entry, bool stdOverride=true) const;
|
||||
std::string getBestEntryName(const IDType& entry, bool stdOverride=true) const;
|
||||
std::string getBestEntryName(const EntryType& entry, bool stdOverride = true) const;
|
||||
std::string getBestEntryName(const IDType& entry, bool stdOverride = true) const;
|
||||
|
||||
bool extractResources(const BRIDGETYPE& pakBridge, bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*, float)> progress);
|
||||
bool extractResources(const BRIDGETYPE& pakBridge, bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*, float)> progress);
|
||||
|
||||
const typename BRIDGETYPE::PAKType::Entry* lookupEntry(const IDType& entry,
|
||||
const nod::Node** nodeOut=nullptr,
|
||||
bool silenceWarnings=false,
|
||||
bool currentPAK=false) const;
|
||||
const typename BRIDGETYPE::PAKType::Entry* lookupEntry(const IDType& entry, const nod::Node** nodeOut = nullptr,
|
||||
bool silenceWarnings = false, bool currentPAK = false) const;
|
||||
|
||||
template <typename DNA>
|
||||
bool lookupAndReadDNA(const IDType& id, DNA& out, bool silenceWarnings=false)
|
||||
{
|
||||
const nod::Node* node;
|
||||
const EntryType* entry = lookupEntry(id, &node, silenceWarnings);
|
||||
if (!entry)
|
||||
return false;
|
||||
PAKEntryReadStream rs = entry->beginReadStream(*node);
|
||||
out.read(rs);
|
||||
return true;
|
||||
}
|
||||
template <typename DNA>
|
||||
bool lookupAndReadDNA(const IDType& id, DNA& out, bool silenceWarnings = false) {
|
||||
const nod::Node* node;
|
||||
const EntryType* entry = lookupEntry(id, &node, silenceWarnings);
|
||||
if (!entry)
|
||||
return false;
|
||||
PAKEntryReadStream rs = entry->beginReadStream(*node);
|
||||
out.read(rs);
|
||||
return true;
|
||||
}
|
||||
|
||||
const typename CharacterAssociations<IDType>::RigPair* lookupCMDLRigPair(const IDType& id) const;
|
||||
const typename CharacterAssociations<IDType>::MultimapIteratorPair lookupCharacterAttachmentRigs(const IDType& id) const;
|
||||
const zeus::CMatrix4f* lookupMAPATransform(const IDType& mapaId) const;
|
||||
const typename CharacterAssociations<IDType>::RigPair* lookupCMDLRigPair(const IDType& id) const;
|
||||
const typename CharacterAssociations<IDType>::MultimapIteratorPair
|
||||
lookupCharacterAttachmentRigs(const IDType& id) const;
|
||||
const zeus::CMatrix4f* lookupMAPATransform(const IDType& mapaId) const;
|
||||
|
||||
hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx) const;
|
||||
hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx, bool& activeOut) const;
|
||||
hecl::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx) const;
|
||||
hecl::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx, bool& activeOut) const;
|
||||
hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx) const;
|
||||
hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx, bool& activeOut) const;
|
||||
hecl::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx) const;
|
||||
hecl::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx, bool& activeOut) const;
|
||||
|
||||
void enumerateResources(const std::function<bool(const EntryType*)>& func);
|
||||
void enumerateResources(const std::function<bool(const EntryType*)>& func);
|
||||
|
||||
bool mreaHasDupeResources(const IDType& id) const;
|
||||
bool mreaHasDupeResources(const IDType& id) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,106 +4,109 @@
|
|||
#include "PAK.hpp"
|
||||
#include "athena/FileWriter.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle
|
||||
{
|
||||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template <class IDType>
|
||||
struct GPSM : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
VectorElementFactory x0_PSIV;
|
||||
ModVectorElementFactory x4_PSVM;
|
||||
VectorElementFactory x8_PSOV;
|
||||
IntElementFactory xc_PSLT;
|
||||
IntElementFactory x10_PSWT;
|
||||
RealElementFactory x14_PSTS;
|
||||
VectorElementFactory x18_POFS;
|
||||
IntElementFactory x1c_SEED;
|
||||
RealElementFactory x20_LENG;
|
||||
RealElementFactory x24_WIDT;
|
||||
IntElementFactory x28_MAXP;
|
||||
RealElementFactory x2c_GRTE;
|
||||
ColorElementFactory x30_COLR;
|
||||
IntElementFactory x34_LTME;
|
||||
VectorElementFactory x38_ILOC;
|
||||
VectorElementFactory x3c_IVEC;
|
||||
EmitterElementFactory x40_EMTR;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool x44_28_SORT : 1; bool x44_30_MBLR : 1; bool x44_24_LINE : 1; bool x44_29_LIT_ : 1;
|
||||
bool x44_26_AAPH : 1; bool x44_27_ZBUF : 1; bool x44_25_FXLL : 1; bool x44_31_PMAB : 1;
|
||||
bool x45_29_VMD4 : 1; bool x45_28_VMD3 : 1; bool x45_27_VMD2 : 1; bool x45_26_VMD1 : 1;
|
||||
bool x45_31_OPTS : 1; bool x45_24_PMUS : 1; bool x45_25_PMOO : 1; bool x45_30_CIND : 1;
|
||||
};
|
||||
uint16_t dummy1 = 0;
|
||||
struct GPSM : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
VectorElementFactory x0_PSIV;
|
||||
ModVectorElementFactory x4_PSVM;
|
||||
VectorElementFactory x8_PSOV;
|
||||
IntElementFactory xc_PSLT;
|
||||
IntElementFactory x10_PSWT;
|
||||
RealElementFactory x14_PSTS;
|
||||
VectorElementFactory x18_POFS;
|
||||
IntElementFactory x1c_SEED;
|
||||
RealElementFactory x20_LENG;
|
||||
RealElementFactory x24_WIDT;
|
||||
IntElementFactory x28_MAXP;
|
||||
RealElementFactory x2c_GRTE;
|
||||
ColorElementFactory x30_COLR;
|
||||
IntElementFactory x34_LTME;
|
||||
VectorElementFactory x38_ILOC;
|
||||
VectorElementFactory x3c_IVEC;
|
||||
EmitterElementFactory x40_EMTR;
|
||||
union {
|
||||
struct {
|
||||
bool x44_28_SORT : 1;
|
||||
bool x44_30_MBLR : 1;
|
||||
bool x44_24_LINE : 1;
|
||||
bool x44_29_LIT_ : 1;
|
||||
bool x44_26_AAPH : 1;
|
||||
bool x44_27_ZBUF : 1;
|
||||
bool x44_25_FXLL : 1;
|
||||
bool x44_31_PMAB : 1;
|
||||
bool x45_29_VMD4 : 1;
|
||||
bool x45_28_VMD3 : 1;
|
||||
bool x45_27_VMD2 : 1;
|
||||
bool x45_26_VMD1 : 1;
|
||||
bool x45_31_OPTS : 1;
|
||||
bool x45_24_PMUS : 1;
|
||||
bool x45_25_PMOO : 1;
|
||||
bool x45_30_CIND : 1;
|
||||
};
|
||||
IntElementFactory x48_MBSP;
|
||||
RealElementFactory x4c_SIZE;
|
||||
RealElementFactory x50_ROTA;
|
||||
UVElementFactory<IDType> x54_TEXR;
|
||||
UVElementFactory<IDType> x58_TIND;
|
||||
ChildResourceFactory<IDType> x5c_PMDL;
|
||||
VectorElementFactory x6c_PMOP;
|
||||
VectorElementFactory x70_PMRT;
|
||||
VectorElementFactory x74_PMSC;
|
||||
ColorElementFactory x78_PMCL;
|
||||
ModVectorElementFactory x7c_VEL1;
|
||||
ModVectorElementFactory x80_VEL2;
|
||||
ModVectorElementFactory x84_VEL3;
|
||||
ModVectorElementFactory x88_VEL4;
|
||||
ChildResourceFactory<IDType> x8c_ICTS;
|
||||
IntElementFactory x9c_NCSY;
|
||||
IntElementFactory xa0_CSSD;
|
||||
ChildResourceFactory<IDType> xa4_IDTS;
|
||||
IntElementFactory xb4_NDSY;
|
||||
ChildResourceFactory<IDType> xb8_IITS;
|
||||
IntElementFactory xc8_PISY;
|
||||
IntElementFactory xcc_SISY;
|
||||
SpawnSystemKeyframeData<IDType> xd0_KSSM;
|
||||
ChildResourceFactory<IDType> xd4_SSWH;
|
||||
IntElementFactory xe4_SSSD;
|
||||
VectorElementFactory xe8_SSPO;
|
||||
IntElementFactory xf8_SESD;
|
||||
VectorElementFactory xfc_SEPO;
|
||||
ChildResourceFactory<IDType> xec_PMLC;
|
||||
IntElementFactory x100_LTYP;
|
||||
ColorElementFactory x104_LCLR;
|
||||
RealElementFactory x108_LINT;
|
||||
VectorElementFactory x10c_LOFF;
|
||||
VectorElementFactory x110_LDIR;
|
||||
IntElementFactory x114_LFOT;
|
||||
RealElementFactory x118_LFOR;
|
||||
RealElementFactory x11c_LSLA;
|
||||
uint16_t dummy1 = 0;
|
||||
};
|
||||
IntElementFactory x48_MBSP;
|
||||
RealElementFactory x4c_SIZE;
|
||||
RealElementFactory x50_ROTA;
|
||||
UVElementFactory<IDType> x54_TEXR;
|
||||
UVElementFactory<IDType> x58_TIND;
|
||||
ChildResourceFactory<IDType> x5c_PMDL;
|
||||
VectorElementFactory x6c_PMOP;
|
||||
VectorElementFactory x70_PMRT;
|
||||
VectorElementFactory x74_PMSC;
|
||||
ColorElementFactory x78_PMCL;
|
||||
ModVectorElementFactory x7c_VEL1;
|
||||
ModVectorElementFactory x80_VEL2;
|
||||
ModVectorElementFactory x84_VEL3;
|
||||
ModVectorElementFactory x88_VEL4;
|
||||
ChildResourceFactory<IDType> x8c_ICTS;
|
||||
IntElementFactory x9c_NCSY;
|
||||
IntElementFactory xa0_CSSD;
|
||||
ChildResourceFactory<IDType> xa4_IDTS;
|
||||
IntElementFactory xb4_NDSY;
|
||||
ChildResourceFactory<IDType> xb8_IITS;
|
||||
IntElementFactory xc8_PISY;
|
||||
IntElementFactory xcc_SISY;
|
||||
SpawnSystemKeyframeData<IDType> xd0_KSSM;
|
||||
ChildResourceFactory<IDType> xd4_SSWH;
|
||||
IntElementFactory xe4_SSSD;
|
||||
VectorElementFactory xe8_SSPO;
|
||||
IntElementFactory xf8_SESD;
|
||||
VectorElementFactory xfc_SEPO;
|
||||
ChildResourceFactory<IDType> xec_PMLC;
|
||||
IntElementFactory x100_LTYP;
|
||||
ColorElementFactory x104_LCLR;
|
||||
RealElementFactory x108_LINT;
|
||||
VectorElementFactory x10c_LOFF;
|
||||
VectorElementFactory x110_LDIR;
|
||||
IntElementFactory x114_LFOT;
|
||||
RealElementFactory x118_LFOR;
|
||||
RealElementFactory x11c_LSLA;
|
||||
|
||||
/* 0-00 additions */
|
||||
ChildResourceFactory<IDType> xd8_SELC;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool x30_30_ORNT : 1;
|
||||
bool x30_31_RSOP : 1;
|
||||
};
|
||||
uint16_t dummy2 = 0;
|
||||
/* 0-00 additions */
|
||||
ChildResourceFactory<IDType> xd8_SELC;
|
||||
union {
|
||||
struct {
|
||||
bool x30_30_ORNT : 1;
|
||||
bool x30_31_RSOP : 1;
|
||||
};
|
||||
RealElementFactory x10c_ADV1;
|
||||
RealElementFactory x110_ADV2;
|
||||
RealElementFactory x114_ADV3;
|
||||
RealElementFactory x118_ADV4;
|
||||
RealElementFactory x11c_ADV5;
|
||||
RealElementFactory x120_ADV6;
|
||||
RealElementFactory x124_ADV7;
|
||||
RealElementFactory x128_ADV8;
|
||||
uint16_t dummy2 = 0;
|
||||
};
|
||||
RealElementFactory x10c_ADV1;
|
||||
RealElementFactory x110_ADV2;
|
||||
RealElementFactory x114_ADV3;
|
||||
RealElementFactory x118_ADV4;
|
||||
RealElementFactory x11c_ADV5;
|
||||
RealElementFactory x120_ADV6;
|
||||
RealElementFactory x124_ADV7;
|
||||
RealElementFactory x128_ADV8;
|
||||
|
||||
GPSM()
|
||||
{
|
||||
x45_25_PMOO = true;
|
||||
}
|
||||
GPSM() { x45_25_PMOO = true; }
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
|
@ -112,5 +115,4 @@ bool ExtractGPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
|||
template <class IDType>
|
||||
bool WriteGPSM(const GPSM<IDType>& gpsm, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -4,177 +4,144 @@
|
|||
#include "DataSpec/DNAMP3/CINF.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAANIM
|
||||
{
|
||||
namespace DataSpec::DNAANIM {
|
||||
|
||||
template <class CINFType>
|
||||
RigInverter<CINFType>::Bone::Bone(const CINFType& cinf, const typename CINFType::Bone& origBone)
|
||||
: m_origBone(origBone)
|
||||
{
|
||||
atUint32 parentIdx = cinf.getInternalBoneIdxFromId(origBone.parentId);
|
||||
zeus::CVector3f boneOrigin(origBone.origin);
|
||||
zeus::CVector3f naturalTail = boneOrigin + zeus::CVector3f{0.f, 0.5f, 0.f};
|
||||
if (parentIdx != -1)
|
||||
{
|
||||
const typename CINFType::Bone& pBone = cinf.bones[parentIdx];
|
||||
m_parentDelta = boneOrigin - zeus::CVector3f(pBone.origin);
|
||||
: m_origBone(origBone) {
|
||||
atUint32 parentIdx = cinf.getInternalBoneIdxFromId(origBone.parentId);
|
||||
zeus::CVector3f boneOrigin(origBone.origin);
|
||||
zeus::CVector3f naturalTail = boneOrigin + zeus::CVector3f{0.f, 0.5f, 0.f};
|
||||
if (parentIdx != -1) {
|
||||
const typename CINFType::Bone& pBone = cinf.bones[parentIdx];
|
||||
m_parentDelta = boneOrigin - zeus::CVector3f(pBone.origin);
|
||||
}
|
||||
|
||||
size_t actualChildren = 0;
|
||||
for (atUint32 chId : origBone.linked) {
|
||||
if (chId == origBone.parentId)
|
||||
continue;
|
||||
atUint32 chIdx = cinf.getInternalBoneIdxFromId(chId);
|
||||
if (chIdx != -1)
|
||||
++actualChildren;
|
||||
}
|
||||
|
||||
const std::string* bName = cinf.getBoneNameFromId(origBone.id);
|
||||
bool isLCTR = false;
|
||||
if (bName)
|
||||
isLCTR = bName->find("_LCTR") != std::string::npos;
|
||||
|
||||
if (parentIdx == -1) {
|
||||
/* Root will always use +Y tail */
|
||||
m_tail = naturalTail;
|
||||
} else if (actualChildren) {
|
||||
/* Position tail to average of children */
|
||||
for (atUint32 chId : origBone.linked) {
|
||||
if (chId == origBone.parentId)
|
||||
continue;
|
||||
atUint32 chIdx = cinf.getInternalBoneIdxFromId(chId);
|
||||
if (chIdx != -1) {
|
||||
const typename CINFType::Bone& chBone = cinf.bones[chIdx];
|
||||
m_tail += chBone.origin;
|
||||
}
|
||||
}
|
||||
|
||||
size_t actualChildren = 0;
|
||||
for (atUint32 chId : origBone.linked)
|
||||
{
|
||||
if (chId == origBone.parentId)
|
||||
continue;
|
||||
atUint32 chIdx = cinf.getInternalBoneIdxFromId(chId);
|
||||
if (chIdx != -1)
|
||||
++actualChildren;
|
||||
m_tail /= zeus::CVector3f(float(actualChildren));
|
||||
if ((m_tail - boneOrigin).magSquared() < 0.001f)
|
||||
m_tail = naturalTail;
|
||||
else if (isLCTR)
|
||||
m_tail = boneOrigin + zeus::CVector3f{0.f, 1.0f, 0.f} * (m_tail - boneOrigin).magnitude();
|
||||
} else if (parentIdx != -1) {
|
||||
/* Extrapolate by delta with parent */
|
||||
m_tail = boneOrigin + m_parentDelta;
|
||||
float deltaMag = m_parentDelta.magnitude();
|
||||
if (deltaMag < 0.001f) {
|
||||
deltaMag = 0.5f;
|
||||
m_tail = naturalTail;
|
||||
} else if (deltaMag > 0.5f) {
|
||||
/* Extreme bones capped to +0.5 value */
|
||||
deltaMag = 0.5f;
|
||||
m_tail = boneOrigin + m_parentDelta.normalized() * 0.5f;
|
||||
}
|
||||
|
||||
const std::string* bName = cinf.getBoneNameFromId(origBone.id);
|
||||
bool isLCTR = false;
|
||||
if (bName)
|
||||
isLCTR = bName->find("_LCTR") != std::string::npos;
|
||||
|
||||
if (parentIdx == -1)
|
||||
{
|
||||
/* Root will always use +Y tail */
|
||||
m_tail = naturalTail;
|
||||
}
|
||||
else if (actualChildren)
|
||||
{
|
||||
/* Position tail to average of children */
|
||||
for (atUint32 chId : origBone.linked)
|
||||
{
|
||||
if (chId == origBone.parentId)
|
||||
continue;
|
||||
atUint32 chIdx = cinf.getInternalBoneIdxFromId(chId);
|
||||
if (chIdx != -1)
|
||||
{
|
||||
const typename CINFType::Bone& chBone = cinf.bones[chIdx];
|
||||
m_tail += chBone.origin;
|
||||
}
|
||||
}
|
||||
m_tail /= zeus::CVector3f(float(actualChildren));
|
||||
if ((m_tail - boneOrigin).magSquared() < 0.001f)
|
||||
m_tail = naturalTail;
|
||||
else if (isLCTR)
|
||||
m_tail = boneOrigin + zeus::CVector3f{0.f, 1.0f, 0.f} * (m_tail - boneOrigin).magnitude();
|
||||
}
|
||||
else if (parentIdx != -1)
|
||||
{
|
||||
/* Extrapolate by delta with parent */
|
||||
m_tail = boneOrigin + m_parentDelta;
|
||||
float deltaMag = m_parentDelta.magnitude();
|
||||
if (deltaMag < 0.001f)
|
||||
{
|
||||
deltaMag = 0.5f;
|
||||
m_tail = naturalTail;
|
||||
}
|
||||
else if (deltaMag > 0.5f)
|
||||
{
|
||||
/* Extreme bones capped to +0.5 value */
|
||||
deltaMag = 0.5f;
|
||||
m_tail = boneOrigin + m_parentDelta.normalized() * 0.5f;
|
||||
}
|
||||
|
||||
if (isLCTR)
|
||||
m_tail = boneOrigin + zeus::CVector3f{0.f, 1.0f, 0.f} * deltaMag;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fallback to +Y tail */
|
||||
m_tail = naturalTail;
|
||||
}
|
||||
if (isLCTR)
|
||||
m_tail = boneOrigin + zeus::CVector3f{0.f, 1.0f, 0.f} * deltaMag;
|
||||
} else {
|
||||
/* Fallback to +Y tail */
|
||||
m_tail = naturalTail;
|
||||
}
|
||||
}
|
||||
|
||||
template <class CINFType>
|
||||
RigInverter<CINFType>::RigInverter(const CINFType& cinf)
|
||||
: m_cinf(cinf)
|
||||
{
|
||||
m_bones.reserve(cinf.bones.size());
|
||||
for (const typename CINFType::Bone& b : cinf.bones)
|
||||
m_bones.emplace_back(cinf, b);
|
||||
RigInverter<CINFType>::RigInverter(const CINFType& cinf) : m_cinf(cinf) {
|
||||
m_bones.reserve(cinf.bones.size());
|
||||
for (const typename CINFType::Bone& b : cinf.bones)
|
||||
m_bones.emplace_back(cinf, b);
|
||||
}
|
||||
|
||||
template <class CINFType>
|
||||
RigInverter<CINFType>::RigInverter(const CINFType& cinf,
|
||||
const std::unordered_map<std::string,
|
||||
hecl::blender::Matrix3f>& matrices)
|
||||
: m_cinf(cinf)
|
||||
{
|
||||
m_bones.reserve(cinf.bones.size());
|
||||
for (const typename CINFType::Bone& b : cinf.bones)
|
||||
{
|
||||
m_bones.emplace_back(cinf, b);
|
||||
const std::unordered_map<std::string, hecl::blender::Matrix3f>& matrices)
|
||||
: m_cinf(cinf) {
|
||||
m_bones.reserve(cinf.bones.size());
|
||||
for (const typename CINFType::Bone& b : cinf.bones) {
|
||||
m_bones.emplace_back(cinf, b);
|
||||
|
||||
const std::string* name = cinf.getBoneNameFromId(b.id);
|
||||
if (name)
|
||||
{
|
||||
auto search = matrices.find(*name);
|
||||
if (search != matrices.cend())
|
||||
{
|
||||
zeus::CMatrix3f boneMtx(search->second[0],
|
||||
search->second[1],
|
||||
search->second[2]);
|
||||
m_bones.back().m_inverter = boneMtx.transposed();
|
||||
m_bones.back().m_restorer = boneMtx;
|
||||
}
|
||||
}
|
||||
const std::string* name = cinf.getBoneNameFromId(b.id);
|
||||
if (name) {
|
||||
auto search = matrices.find(*name);
|
||||
if (search != matrices.cend()) {
|
||||
zeus::CMatrix3f boneMtx(search->second[0], search->second[1], search->second[2]);
|
||||
m_bones.back().m_inverter = boneMtx.transposed();
|
||||
m_bones.back().m_restorer = boneMtx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class CINFType>
|
||||
zeus::CQuaternion
|
||||
RigInverter<CINFType>::invertRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const
|
||||
{
|
||||
for (const Bone& b : m_bones)
|
||||
if (b.m_origBone.id == boneId)
|
||||
return b.m_restorer * zeus::CMatrix3f(origRot) * b.m_inverter;
|
||||
return origRot;
|
||||
}
|
||||
|
||||
template <class CINFType>
|
||||
zeus::CVector3f
|
||||
RigInverter<CINFType>::invertPosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const
|
||||
{
|
||||
for (const Bone& b : m_bones)
|
||||
if (b.m_origBone.id == boneId)
|
||||
{
|
||||
zeus::CVector3f localPos = origPos;
|
||||
if (subDelta)
|
||||
localPos -= b.m_parentDelta;
|
||||
return b.m_restorer * localPos;
|
||||
}
|
||||
return origPos;
|
||||
zeus::CQuaternion RigInverter<CINFType>::invertRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const {
|
||||
for (const Bone& b : m_bones)
|
||||
if (b.m_origBone.id == boneId)
|
||||
return b.m_restorer * zeus::CMatrix3f(origRot) * b.m_inverter;
|
||||
return origRot;
|
||||
}
|
||||
|
||||
template <class CINFType>
|
||||
zeus::CQuaternion
|
||||
RigInverter<CINFType>::restoreRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const
|
||||
{
|
||||
for (const Bone& b : m_bones)
|
||||
if (b.m_origBone.id == boneId)
|
||||
return b.m_inverter * zeus::CMatrix3f(origRot) * b.m_restorer;
|
||||
return origRot;
|
||||
zeus::CVector3f RigInverter<CINFType>::invertPosition(atUint32 boneId, const zeus::CVector3f& origPos,
|
||||
bool subDelta) const {
|
||||
for (const Bone& b : m_bones)
|
||||
if (b.m_origBone.id == boneId) {
|
||||
zeus::CVector3f localPos = origPos;
|
||||
if (subDelta)
|
||||
localPos -= b.m_parentDelta;
|
||||
return b.m_restorer * localPos;
|
||||
}
|
||||
return origPos;
|
||||
}
|
||||
|
||||
template <class CINFType>
|
||||
zeus::CVector3f
|
||||
RigInverter<CINFType>::restorePosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const
|
||||
{
|
||||
for (const Bone& b : m_bones)
|
||||
if (b.m_origBone.id == boneId)
|
||||
{
|
||||
zeus::CVector3f localPos = b.m_inverter * origPos;
|
||||
if (subDelta)
|
||||
localPos += b.m_parentDelta;
|
||||
return localPos;
|
||||
}
|
||||
return origPos;
|
||||
zeus::CQuaternion RigInverter<CINFType>::restoreRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const {
|
||||
for (const Bone& b : m_bones)
|
||||
if (b.m_origBone.id == boneId)
|
||||
return b.m_inverter * zeus::CMatrix3f(origRot) * b.m_restorer;
|
||||
return origRot;
|
||||
}
|
||||
|
||||
template <class CINFType>
|
||||
zeus::CVector3f RigInverter<CINFType>::restorePosition(atUint32 boneId, const zeus::CVector3f& origPos,
|
||||
bool subDelta) const {
|
||||
for (const Bone& b : m_bones)
|
||||
if (b.m_origBone.id == boneId) {
|
||||
zeus::CVector3f localPos = b.m_inverter * origPos;
|
||||
if (subDelta)
|
||||
localPos += b.m_parentDelta;
|
||||
return localPos;
|
||||
}
|
||||
return origPos;
|
||||
}
|
||||
|
||||
template class RigInverter<DNAMP1::CINF>;
|
||||
template class RigInverter<DNAMP2::CINF>;
|
||||
template class RigInverter<DNAMP3::CINF>;
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAANIM
|
||||
|
|
|
@ -5,40 +5,37 @@
|
|||
#include "zeus/CQuaternion.hpp"
|
||||
#include "hecl/hecl.hpp"
|
||||
|
||||
namespace DataSpec::DNAANIM
|
||||
{
|
||||
namespace DataSpec::DNAANIM {
|
||||
|
||||
/** One-shot process to invert CINF armature into connected rig,
|
||||
* inverting rotations/translations of ANIM data to match */
|
||||
template <class CINFType>
|
||||
class RigInverter
|
||||
{
|
||||
class RigInverter {
|
||||
public:
|
||||
struct Bone
|
||||
{
|
||||
const typename CINFType::Bone& m_origBone;
|
||||
zeus::CMatrix3f m_inverter;
|
||||
zeus::CMatrix3f m_restorer;
|
||||
zeus::CVector3f m_tail;
|
||||
zeus::CVector3f m_parentDelta;
|
||||
Bone(const CINFType& cinf, const typename CINFType::Bone& origBone);
|
||||
};
|
||||
struct Bone {
|
||||
const typename CINFType::Bone& m_origBone;
|
||||
zeus::CMatrix3f m_inverter;
|
||||
zeus::CMatrix3f m_restorer;
|
||||
zeus::CVector3f m_tail;
|
||||
zeus::CVector3f m_parentDelta;
|
||||
Bone(const CINFType& cinf, const typename CINFType::Bone& origBone);
|
||||
};
|
||||
|
||||
private:
|
||||
const CINFType& m_cinf;
|
||||
std::vector<Bone> m_bones;
|
||||
const CINFType& m_cinf;
|
||||
std::vector<Bone> m_bones;
|
||||
|
||||
public:
|
||||
RigInverter(const CINFType& cinf);
|
||||
RigInverter(const CINFType& cinf,
|
||||
const std::unordered_map<std::string, hecl::blender::Matrix3f>& matrices);
|
||||
const CINFType& getCINF() const {return m_cinf;}
|
||||
const std::vector<Bone>& getBones() const {return m_bones;}
|
||||
RigInverter(const CINFType& cinf);
|
||||
RigInverter(const CINFType& cinf, const std::unordered_map<std::string, hecl::blender::Matrix3f>& matrices);
|
||||
const CINFType& getCINF() const { return m_cinf; }
|
||||
const std::vector<Bone>& getBones() const { return m_bones; }
|
||||
|
||||
zeus::CQuaternion invertRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const;
|
||||
zeus::CVector3f invertPosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const;
|
||||
zeus::CQuaternion invertRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const;
|
||||
zeus::CVector3f invertPosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const;
|
||||
|
||||
zeus::CQuaternion restoreRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const;
|
||||
zeus::CVector3f restorePosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const;
|
||||
zeus::CQuaternion restoreRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const;
|
||||
zeus::CVector3f restorePosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAANIM
|
||||
|
|
|
@ -2,51 +2,37 @@
|
|||
#include "DNACommon.hpp"
|
||||
#include "PAK.hpp"
|
||||
|
||||
namespace DataSpec::SAVWCommon
|
||||
{
|
||||
enum class EScanCategory
|
||||
{
|
||||
None,
|
||||
Data,
|
||||
Lore,
|
||||
Creature,
|
||||
Research,
|
||||
Artifact
|
||||
namespace DataSpec::SAVWCommon {
|
||||
enum class EScanCategory { None, Data, Lore, Creature, Research, Artifact };
|
||||
|
||||
struct Header : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
Value<atUint32> areaCount;
|
||||
};
|
||||
|
||||
struct Header : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
Value<atUint32> areaCount;
|
||||
struct EnvironmentVariable : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> unk2;
|
||||
Value<atUint32> unk3;
|
||||
};
|
||||
|
||||
struct EnvironmentVariable : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> unk2;
|
||||
Value<atUint32> unk3;
|
||||
};
|
||||
|
||||
struct Layer : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> areaId;
|
||||
Value<atUint32> layer;
|
||||
struct Layer : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> areaId;
|
||||
Value<atUint32> layer;
|
||||
};
|
||||
|
||||
template <class SAVW>
|
||||
static bool ExtractSAVW(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
SAVW savw;
|
||||
savw.read(rs);
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
athena::io::ToYAMLStream(savw, writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ExtractSAVW(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
SAVW savw;
|
||||
savw.read(rs);
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
athena::io::ToYAMLStream(savw, writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace DataSpec::SAVWCommon
|
||||
|
|
|
@ -3,46 +3,37 @@
|
|||
#include "../DNAMP2/STRG.hpp"
|
||||
#include "../DNAMP3/STRG.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
void ISTRG::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const
|
||||
{
|
||||
/* TODO: parse out resource tokens */
|
||||
}
|
||||
void ISTRG::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const { /* TODO: parse out resource tokens */ }
|
||||
|
||||
std::unique_ptr<ISTRG> LoadSTRG(athena::io::IStreamReader& reader)
|
||||
{
|
||||
uint32_t magic = reader.readUint32Big();
|
||||
if (magic != 0x87654321)
|
||||
{
|
||||
LogDNACommon.report(logvisor::Error, "invalid STRG magic");
|
||||
return std::unique_ptr<ISTRG>();
|
||||
}
|
||||
|
||||
uint32_t version = reader.readUint32Big();
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
DNAMP1::STRG* newStrg = new DNAMP1::STRG;
|
||||
newStrg->_read(reader);
|
||||
return std::unique_ptr<ISTRG>(newStrg);
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
DNAMP2::STRG* newStrg = new DNAMP2::STRG;
|
||||
newStrg->_read(reader);
|
||||
return std::unique_ptr<ISTRG>(newStrg);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
DNAMP3::STRG* newStrg = new DNAMP3::STRG;
|
||||
newStrg->_read(reader);
|
||||
return std::unique_ptr<ISTRG>(newStrg);
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
std::unique_ptr<ISTRG> LoadSTRG(athena::io::IStreamReader& reader) {
|
||||
uint32_t magic = reader.readUint32Big();
|
||||
if (magic != 0x87654321) {
|
||||
LogDNACommon.report(logvisor::Error, "invalid STRG magic");
|
||||
return std::unique_ptr<ISTRG>();
|
||||
}
|
||||
|
||||
uint32_t version = reader.readUint32Big();
|
||||
switch (version) {
|
||||
case 0: {
|
||||
DNAMP1::STRG* newStrg = new DNAMP1::STRG;
|
||||
newStrg->_read(reader);
|
||||
return std::unique_ptr<ISTRG>(newStrg);
|
||||
}
|
||||
case 1: {
|
||||
DNAMP2::STRG* newStrg = new DNAMP2::STRG;
|
||||
newStrg->_read(reader);
|
||||
return std::unique_ptr<ISTRG>(newStrg);
|
||||
}
|
||||
case 3: {
|
||||
DNAMP3::STRG* newStrg = new DNAMP3::STRG;
|
||||
newStrg->_read(reader);
|
||||
return std::unique_ptr<ISTRG>(newStrg);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return std::unique_ptr<ISTRG>();
|
||||
}
|
||||
}
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -7,21 +7,18 @@
|
|||
#include <athena/FileWriter.hpp>
|
||||
#include "DNACommon.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
struct ISTRG : BigDNAVYaml
|
||||
{
|
||||
virtual ~ISTRG() = default;
|
||||
namespace DataSpec {
|
||||
struct ISTRG : BigDNAVYaml {
|
||||
virtual ~ISTRG() = default;
|
||||
|
||||
virtual size_t count() const=0;
|
||||
virtual std::string getUTF8(const FourCC& lang, size_t idx) const=0;
|
||||
virtual std::u16string getUTF16(const FourCC& lang, size_t idx) const=0;
|
||||
virtual hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const=0;
|
||||
virtual int32_t lookupIdx(std::string_view name) const=0;
|
||||
virtual size_t count() const = 0;
|
||||
virtual std::string getUTF8(const FourCC& lang, size_t idx) const = 0;
|
||||
virtual std::u16string getUTF16(const FourCC& lang, size_t idx) const = 0;
|
||||
virtual hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const = 0;
|
||||
virtual int32_t lookupIdx(std::string_view name) const = 0;
|
||||
|
||||
virtual 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);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,49 +4,50 @@
|
|||
#include "PAK.hpp"
|
||||
#include "athena/FileWriter.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle
|
||||
{
|
||||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template <class IDType>
|
||||
struct SWSH : public BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
struct SWSH : public BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
|
||||
IntElementFactory x0_PSLT;
|
||||
RealElementFactory x4_TIME;
|
||||
RealElementFactory x8_LRAD;
|
||||
RealElementFactory xc_RRAD;
|
||||
IntElementFactory x10_LENG;
|
||||
ColorElementFactory x14_COLR;
|
||||
IntElementFactory x18_SIDE;
|
||||
RealElementFactory x1c_IROT;
|
||||
RealElementFactory x20_ROTM;
|
||||
VectorElementFactory x24_POFS;
|
||||
VectorElementFactory x28_IVEL;
|
||||
VectorElementFactory x2c_NPOS;
|
||||
ModVectorElementFactory x30_VELM;
|
||||
ModVectorElementFactory x34_VLM2;
|
||||
IntElementFactory x38_SPLN;
|
||||
UVElementFactory<IDType> x3c_TEXR;
|
||||
IntElementFactory x40_TSPN;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool x44_24_LLRD : 1; bool x44_25_CROS : 1; bool x44_26_VLS1 : 1; bool x44_27_VLS2 : 1;
|
||||
bool x44_28_SROT : 1; bool x44_29_WIRE : 1; bool x44_30_TEXW : 1; bool x44_31_AALP : 1;
|
||||
bool x45_24_ZBUF : 1; bool x45_25_ORNT : 1; bool x45_26_CRND : 1;
|
||||
};
|
||||
uint16_t dummy = 0;
|
||||
IntElementFactory x0_PSLT;
|
||||
RealElementFactory x4_TIME;
|
||||
RealElementFactory x8_LRAD;
|
||||
RealElementFactory xc_RRAD;
|
||||
IntElementFactory x10_LENG;
|
||||
ColorElementFactory x14_COLR;
|
||||
IntElementFactory x18_SIDE;
|
||||
RealElementFactory x1c_IROT;
|
||||
RealElementFactory x20_ROTM;
|
||||
VectorElementFactory x24_POFS;
|
||||
VectorElementFactory x28_IVEL;
|
||||
VectorElementFactory x2c_NPOS;
|
||||
ModVectorElementFactory x30_VELM;
|
||||
ModVectorElementFactory x34_VLM2;
|
||||
IntElementFactory x38_SPLN;
|
||||
UVElementFactory<IDType> x3c_TEXR;
|
||||
IntElementFactory x40_TSPN;
|
||||
union {
|
||||
struct {
|
||||
bool x44_24_LLRD : 1;
|
||||
bool x44_25_CROS : 1;
|
||||
bool x44_26_VLS1 : 1;
|
||||
bool x44_27_VLS2 : 1;
|
||||
bool x44_28_SROT : 1;
|
||||
bool x44_29_WIRE : 1;
|
||||
bool x44_30_TEXW : 1;
|
||||
bool x44_31_AALP : 1;
|
||||
bool x45_24_ZBUF : 1;
|
||||
bool x45_25_ORNT : 1;
|
||||
bool x45_26_CRND : 1;
|
||||
};
|
||||
uint16_t dummy = 0;
|
||||
};
|
||||
|
||||
SWSH()
|
||||
{
|
||||
x44_25_CROS = true;
|
||||
}
|
||||
SWSH() { x44_25_CROS = true; }
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
|
@ -54,4 +55,4 @@ bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
|||
|
||||
template <class IDType>
|
||||
bool WriteSWSH(const SWSH<IDType>& gpsm, const hecl::ProjectPath& outPath);
|
||||
}
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,16 +2,13 @@
|
|||
|
||||
#include "DNACommon.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
class PAKEntryReadStream;
|
||||
|
||||
struct TXTR
|
||||
{
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
static bool CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
struct TXTR {
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
static bool CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,16 +2,12 @@
|
|||
|
||||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
|
||||
namespace hecl
|
||||
{
|
||||
namespace hecl {
|
||||
class CVarManager;
|
||||
}
|
||||
namespace DataSpec
|
||||
{
|
||||
struct ITweak : BigDNA
|
||||
{
|
||||
namespace DataSpec {
|
||||
struct ITweak : BigDNA {
|
||||
|
||||
virtual void initCVars(hecl::CVarManager*) {}
|
||||
virtual void initCVars(hecl::CVarManager*) {}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,66 +2,62 @@
|
|||
|
||||
#include "ITweak.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
struct ITweakAutoMapper : public ITweak
|
||||
{
|
||||
virtual bool GetShowOneMiniMapArea() const=0;
|
||||
virtual bool GetScaleMoveSpeedWithCamDist() const=0;
|
||||
virtual float GetCamDist() const=0;
|
||||
virtual float GetMinCamDist() const=0;
|
||||
virtual float GetMaxCamDist() const=0;
|
||||
virtual float GetMinCamRotateX() const=0;
|
||||
virtual float GetMaxCamRotateX() const=0;
|
||||
virtual float GetCamAngle() const=0;
|
||||
virtual const zeus::CColor& GetAutomapperWidgetColor() const=0;
|
||||
virtual float GetMiniCamDist() const=0;
|
||||
virtual float GetMiniCamXAngle() const=0;
|
||||
virtual float GetMiniCamAngle() const=0;
|
||||
virtual const zeus::CColor& GetAutomapperWidgetMiniColor() const=0;
|
||||
virtual const zeus::CColor& GetSurfaceVisitedColor() const=0;
|
||||
virtual const zeus::CColor& GetOutlineVisitedColor() const=0;
|
||||
virtual const zeus::CColor& GetSurfaceUnvisitedColor() const=0;
|
||||
virtual const zeus::CColor& GetOutlineUnvisitedColor() const=0;
|
||||
virtual const zeus::CColor& GetSurfaceSelectVisitedColor() const=0;
|
||||
virtual const zeus::CColor& GetOutlineSelectVisitedColor() const=0;
|
||||
virtual float GetMapSurfaceNormColorLinear() const=0;
|
||||
virtual float GetMapSurfaceNormColorConstant() const=0;
|
||||
virtual float GetOpenMapScreenTime() const=0;
|
||||
virtual float GetCloseMapScreenTime() const=0;
|
||||
virtual float GetHintPanTime() const=0;
|
||||
virtual float GetCamZoomUnitsPerFrame() const=0;
|
||||
virtual float GetCamRotateDegreesPerFrame() const=0;
|
||||
virtual float GetBaseMapScreenCameraMoveSpeed() const=0;
|
||||
virtual const zeus::CColor& GetSurfaceSelectUnvisitedColor() const=0;
|
||||
virtual const zeus::CColor& GetOutlineSelectUnvisitedColor() const=0;
|
||||
virtual float GetMiniAlphaSurfaceVisited() const=0;
|
||||
virtual float GetAlphaSurfaceVisited() const=0;
|
||||
virtual float GetMiniAlphaOutlineVisited() const=0;
|
||||
virtual float GetAlphaOutlineVisited() const=0;
|
||||
virtual float GetMiniAlphaSurfaceUnvisited() const=0;
|
||||
virtual float GetAlphaSurfaceUnvisited() const=0;
|
||||
virtual float GetMiniAlphaOutlineUnvisited() const=0;
|
||||
virtual float GetAlphaOutlineUnvisited() const=0;
|
||||
virtual const zeus::CVector3f& GetDoorCenter() const=0;
|
||||
virtual float GetMiniMapViewportWidth() const=0;
|
||||
virtual float GetMiniMapViewportHeight() const=0;
|
||||
virtual float GetMiniMapCamDistScale() const=0;
|
||||
virtual float GetMapPlaneScaleX() const=0;
|
||||
virtual float GetMapPlaneScaleZ() const=0;
|
||||
virtual float GetUniverseCamDist() const=0;
|
||||
virtual float GetMinUniverseCamDist() const=0;
|
||||
virtual float GetMaxUniverseCamDist() const=0;
|
||||
virtual float GetSwitchToFromUniverseTime() const=0;
|
||||
virtual float GetCamPanUnitsPerFrame() const=0;
|
||||
virtual float GetAutomapperScaleX() const=0;
|
||||
virtual float GetAutomapperScaleZ() const=0;
|
||||
virtual float GetCamVerticalOffset() const=0;
|
||||
virtual const zeus::CColor& GetMiniMapSamusModColor() const=0;
|
||||
virtual const zeus::CColor& GetAreaFlashPulseColor() const=0;
|
||||
virtual const zeus::CColor& GetDoorColor(int idx) const=0;
|
||||
virtual const zeus::CColor& GetOpenDoorColor() const=0;
|
||||
namespace DataSpec {
|
||||
struct ITweakAutoMapper : public ITweak {
|
||||
virtual bool GetShowOneMiniMapArea() const = 0;
|
||||
virtual bool GetScaleMoveSpeedWithCamDist() const = 0;
|
||||
virtual float GetCamDist() const = 0;
|
||||
virtual float GetMinCamDist() const = 0;
|
||||
virtual float GetMaxCamDist() const = 0;
|
||||
virtual float GetMinCamRotateX() const = 0;
|
||||
virtual float GetMaxCamRotateX() const = 0;
|
||||
virtual float GetCamAngle() const = 0;
|
||||
virtual const zeus::CColor& GetAutomapperWidgetColor() const = 0;
|
||||
virtual float GetMiniCamDist() const = 0;
|
||||
virtual float GetMiniCamXAngle() const = 0;
|
||||
virtual float GetMiniCamAngle() const = 0;
|
||||
virtual const zeus::CColor& GetAutomapperWidgetMiniColor() const = 0;
|
||||
virtual const zeus::CColor& GetSurfaceVisitedColor() const = 0;
|
||||
virtual const zeus::CColor& GetOutlineVisitedColor() const = 0;
|
||||
virtual const zeus::CColor& GetSurfaceUnvisitedColor() const = 0;
|
||||
virtual const zeus::CColor& GetOutlineUnvisitedColor() const = 0;
|
||||
virtual const zeus::CColor& GetSurfaceSelectVisitedColor() const = 0;
|
||||
virtual const zeus::CColor& GetOutlineSelectVisitedColor() const = 0;
|
||||
virtual float GetMapSurfaceNormColorLinear() const = 0;
|
||||
virtual float GetMapSurfaceNormColorConstant() const = 0;
|
||||
virtual float GetOpenMapScreenTime() const = 0;
|
||||
virtual float GetCloseMapScreenTime() const = 0;
|
||||
virtual float GetHintPanTime() const = 0;
|
||||
virtual float GetCamZoomUnitsPerFrame() const = 0;
|
||||
virtual float GetCamRotateDegreesPerFrame() const = 0;
|
||||
virtual float GetBaseMapScreenCameraMoveSpeed() const = 0;
|
||||
virtual const zeus::CColor& GetSurfaceSelectUnvisitedColor() const = 0;
|
||||
virtual const zeus::CColor& GetOutlineSelectUnvisitedColor() const = 0;
|
||||
virtual float GetMiniAlphaSurfaceVisited() const = 0;
|
||||
virtual float GetAlphaSurfaceVisited() const = 0;
|
||||
virtual float GetMiniAlphaOutlineVisited() const = 0;
|
||||
virtual float GetAlphaOutlineVisited() const = 0;
|
||||
virtual float GetMiniAlphaSurfaceUnvisited() const = 0;
|
||||
virtual float GetAlphaSurfaceUnvisited() const = 0;
|
||||
virtual float GetMiniAlphaOutlineUnvisited() const = 0;
|
||||
virtual float GetAlphaOutlineUnvisited() const = 0;
|
||||
virtual const zeus::CVector3f& GetDoorCenter() const = 0;
|
||||
virtual float GetMiniMapViewportWidth() const = 0;
|
||||
virtual float GetMiniMapViewportHeight() const = 0;
|
||||
virtual float GetMiniMapCamDistScale() const = 0;
|
||||
virtual float GetMapPlaneScaleX() const = 0;
|
||||
virtual float GetMapPlaneScaleZ() const = 0;
|
||||
virtual float GetUniverseCamDist() const = 0;
|
||||
virtual float GetMinUniverseCamDist() const = 0;
|
||||
virtual float GetMaxUniverseCamDist() const = 0;
|
||||
virtual float GetSwitchToFromUniverseTime() const = 0;
|
||||
virtual float GetCamPanUnitsPerFrame() const = 0;
|
||||
virtual float GetAutomapperScaleX() const = 0;
|
||||
virtual float GetAutomapperScaleZ() const = 0;
|
||||
virtual float GetCamVerticalOffset() const = 0;
|
||||
virtual const zeus::CColor& GetMiniMapSamusModColor() const = 0;
|
||||
virtual const zeus::CColor& GetAreaFlashPulseColor() const = 0;
|
||||
virtual const zeus::CColor& GetDoorColor(int idx) const = 0;
|
||||
virtual const zeus::CColor& GetOpenDoorColor() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,71 +2,68 @@
|
|||
|
||||
#include "ITweak.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
struct ITweakBall : ITweak
|
||||
{
|
||||
virtual float GetMaxBallTranslationAcceleration(int s) const=0;
|
||||
virtual float GetBallTranslationFriction(int s) const=0;
|
||||
virtual float GetBallTranslationMaxSpeed(int s) const=0;
|
||||
virtual float GetBallCameraElevation() const=0;
|
||||
virtual float GetBallCameraAnglePerSecond() const=0;
|
||||
virtual const zeus::CVector3f& GetBallCameraOffset() const=0;
|
||||
virtual float GetBallCameraMinSpeedDistance() const=0;
|
||||
virtual float GetBallCameraMaxSpeedDistance() const=0;
|
||||
virtual float GetBallCameraBackwardsDistance() const=0;
|
||||
virtual float GetBallCameraSpringConstant() const=0;
|
||||
virtual float GetBallCameraSpringMax() const=0;
|
||||
virtual float GetBallCameraSpringTardis() const=0;
|
||||
virtual float GetBallCameraCentroidSpringConstant() const=0;
|
||||
virtual float GetBallCameraCentroidSpringMax() const=0;
|
||||
virtual float GetBallCameraCentroidSpringTardis() const=0;
|
||||
virtual float GetBallCameraCentroidDistanceSpringConstant() const=0;
|
||||
virtual float GetBallCameraCentroidDistanceSpringMax() const=0;
|
||||
virtual float GetBallCameraCentroidDistanceSpringTardis() const=0;
|
||||
virtual float GetBallCameraLookAtSpringConstant() const=0;
|
||||
virtual float GetBallCameraLookAtSpringMax() const=0;
|
||||
virtual float GetBallCameraLookAtSpringTardis() const=0;
|
||||
virtual float GetBallForwardBrakingAcceleration(int s) const=0;
|
||||
virtual float GetBallGravity() const=0;
|
||||
virtual float GetBallWaterGravity() const=0;
|
||||
virtual float GetBallSlipFactor(int s) const=0;
|
||||
virtual float GetConservativeDoorCameraDistance() const=0;
|
||||
virtual float GetBallCameraChaseElevation() const=0;
|
||||
virtual float GetBallCameraChaseDampenAngle() const=0;
|
||||
virtual float GetBallCameraChaseDistance() const=0;
|
||||
virtual float GetBallCameraChaseYawSpeed() const=0;
|
||||
virtual float GetBallCameraChaseAnglePerSecond() const=0;
|
||||
virtual const zeus::CVector3f& GetBallCameraChaseLookAtOffset() const=0;
|
||||
virtual float GetBallCameraChaseSpringConstant() const=0;
|
||||
virtual float GetBallCameraChaseSpringMax() const=0;
|
||||
virtual float GetBallCameraChaseSpringTardis() const=0;
|
||||
virtual float GetBallCameraBoostElevation() const=0;
|
||||
virtual float GetBallCameraBoostDampenAngle() const=0;
|
||||
virtual float GetBallCameraBoostDistance() const=0;
|
||||
virtual float GetBallCameraBoostYawSpeed() const=0;
|
||||
virtual float GetBallCameraBoostAnglePerSecond() const=0;
|
||||
virtual const zeus::CVector3f& GetBallCameraBoostLookAtOffset() const=0;
|
||||
virtual float GetBallCameraBoostSpringConstant() const=0;
|
||||
virtual float GetBallCameraBoostSpringMax() const=0;
|
||||
virtual float GetBallCameraBoostSpringTardis() const=0;
|
||||
virtual float GetMinimumAlignmentSpeed() const=0;
|
||||
virtual float GetTireness() const=0;
|
||||
virtual float GetMaxLeanAngle() const=0;
|
||||
virtual float GetTireToMarbleThresholdSpeed() const=0;
|
||||
virtual float GetMarbleToTireThresholdSpeed() const=0;
|
||||
virtual float GetForceToLeanGain() const=0;
|
||||
virtual float GetLeanTrackingGain() const=0;
|
||||
virtual float GetBallCameraControlDistance() const=0;
|
||||
virtual float GetLeftStickDivisor() const=0;
|
||||
virtual float GetRightStickDivisor() const=0;
|
||||
virtual float GetBallTouchRadius() const=0;
|
||||
virtual float GetBoostBallDrainTime() const=0;
|
||||
virtual float GetBoostBallMaxChargeTime() const=0;
|
||||
virtual float GetBoostBallMinChargeTime() const=0;
|
||||
virtual float GetBoostBallMinRelativeSpeedForDamage() const=0;
|
||||
virtual float GetBoostBallChargeTimeTable(int i) const=0;
|
||||
virtual float GetBoostBallIncrementalSpeedTable(int i) const=0;
|
||||
namespace DataSpec {
|
||||
struct ITweakBall : ITweak {
|
||||
virtual float GetMaxBallTranslationAcceleration(int s) const = 0;
|
||||
virtual float GetBallTranslationFriction(int s) const = 0;
|
||||
virtual float GetBallTranslationMaxSpeed(int s) const = 0;
|
||||
virtual float GetBallCameraElevation() const = 0;
|
||||
virtual float GetBallCameraAnglePerSecond() const = 0;
|
||||
virtual const zeus::CVector3f& GetBallCameraOffset() const = 0;
|
||||
virtual float GetBallCameraMinSpeedDistance() const = 0;
|
||||
virtual float GetBallCameraMaxSpeedDistance() const = 0;
|
||||
virtual float GetBallCameraBackwardsDistance() const = 0;
|
||||
virtual float GetBallCameraSpringConstant() const = 0;
|
||||
virtual float GetBallCameraSpringMax() const = 0;
|
||||
virtual float GetBallCameraSpringTardis() const = 0;
|
||||
virtual float GetBallCameraCentroidSpringConstant() const = 0;
|
||||
virtual float GetBallCameraCentroidSpringMax() const = 0;
|
||||
virtual float GetBallCameraCentroidSpringTardis() const = 0;
|
||||
virtual float GetBallCameraCentroidDistanceSpringConstant() const = 0;
|
||||
virtual float GetBallCameraCentroidDistanceSpringMax() const = 0;
|
||||
virtual float GetBallCameraCentroidDistanceSpringTardis() const = 0;
|
||||
virtual float GetBallCameraLookAtSpringConstant() const = 0;
|
||||
virtual float GetBallCameraLookAtSpringMax() const = 0;
|
||||
virtual float GetBallCameraLookAtSpringTardis() const = 0;
|
||||
virtual float GetBallForwardBrakingAcceleration(int s) const = 0;
|
||||
virtual float GetBallGravity() const = 0;
|
||||
virtual float GetBallWaterGravity() const = 0;
|
||||
virtual float GetBallSlipFactor(int s) const = 0;
|
||||
virtual float GetConservativeDoorCameraDistance() const = 0;
|
||||
virtual float GetBallCameraChaseElevation() const = 0;
|
||||
virtual float GetBallCameraChaseDampenAngle() const = 0;
|
||||
virtual float GetBallCameraChaseDistance() const = 0;
|
||||
virtual float GetBallCameraChaseYawSpeed() const = 0;
|
||||
virtual float GetBallCameraChaseAnglePerSecond() const = 0;
|
||||
virtual const zeus::CVector3f& GetBallCameraChaseLookAtOffset() const = 0;
|
||||
virtual float GetBallCameraChaseSpringConstant() const = 0;
|
||||
virtual float GetBallCameraChaseSpringMax() const = 0;
|
||||
virtual float GetBallCameraChaseSpringTardis() const = 0;
|
||||
virtual float GetBallCameraBoostElevation() const = 0;
|
||||
virtual float GetBallCameraBoostDampenAngle() const = 0;
|
||||
virtual float GetBallCameraBoostDistance() const = 0;
|
||||
virtual float GetBallCameraBoostYawSpeed() const = 0;
|
||||
virtual float GetBallCameraBoostAnglePerSecond() const = 0;
|
||||
virtual const zeus::CVector3f& GetBallCameraBoostLookAtOffset() const = 0;
|
||||
virtual float GetBallCameraBoostSpringConstant() const = 0;
|
||||
virtual float GetBallCameraBoostSpringMax() const = 0;
|
||||
virtual float GetBallCameraBoostSpringTardis() const = 0;
|
||||
virtual float GetMinimumAlignmentSpeed() const = 0;
|
||||
virtual float GetTireness() const = 0;
|
||||
virtual float GetMaxLeanAngle() const = 0;
|
||||
virtual float GetTireToMarbleThresholdSpeed() const = 0;
|
||||
virtual float GetMarbleToTireThresholdSpeed() const = 0;
|
||||
virtual float GetForceToLeanGain() const = 0;
|
||||
virtual float GetLeanTrackingGain() const = 0;
|
||||
virtual float GetBallCameraControlDistance() const = 0;
|
||||
virtual float GetLeftStickDivisor() const = 0;
|
||||
virtual float GetRightStickDivisor() const = 0;
|
||||
virtual float GetBallTouchRadius() const = 0;
|
||||
virtual float GetBoostBallDrainTime() const = 0;
|
||||
virtual float GetBoostBallMaxChargeTime() const = 0;
|
||||
virtual float GetBoostBallMinChargeTime() const = 0;
|
||||
virtual float GetBoostBallMinRelativeSpeedForDamage() const = 0;
|
||||
virtual float GetBoostBallChargeTimeTable(int i) const = 0;
|
||||
virtual float GetBoostBallIncrementalSpeedTable(int i) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,28 +2,25 @@
|
|||
|
||||
#include "ITweak.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
struct ITweakGame : ITweak
|
||||
{
|
||||
virtual std::string_view GetWorldPrefix() const = 0;
|
||||
virtual bool GetSplashScreensDisabled() const = 0;
|
||||
virtual float GetFirstPersonFOV() const = 0;
|
||||
virtual float GetPressStartDelay() const = 0;
|
||||
virtual float GetWavecapIntensityNormal() const = 0;
|
||||
virtual float GetWavecapIntensityPoison() const = 0;
|
||||
virtual float GetWavecapIntensityLava() const = 0;
|
||||
virtual float GetRippleIntensityNormal() const = 0;
|
||||
virtual float GetRippleIntensityPoison() const = 0;
|
||||
virtual float GetRippleIntensityLava() const = 0;
|
||||
virtual float GetFluidEnvBumpScale() const = 0;
|
||||
virtual float GetWaterFogDistanceBase() const = 0;
|
||||
virtual float GetWaterFogDistanceRange() const = 0;
|
||||
virtual float GetGravityWaterFogDistanceBase() const = 0;
|
||||
virtual float GetGravityWaterFogDistanceRange() const = 0;
|
||||
virtual float GetHardModeDamageMultiplier() const = 0;
|
||||
virtual float GetHardModeWeaponMultiplier() const = 0;
|
||||
struct ITweakGame : ITweak {
|
||||
virtual std::string_view GetWorldPrefix() const = 0;
|
||||
virtual bool GetSplashScreensDisabled() const = 0;
|
||||
virtual float GetFirstPersonFOV() const = 0;
|
||||
virtual float GetPressStartDelay() const = 0;
|
||||
virtual float GetWavecapIntensityNormal() const = 0;
|
||||
virtual float GetWavecapIntensityPoison() const = 0;
|
||||
virtual float GetWavecapIntensityLava() const = 0;
|
||||
virtual float GetRippleIntensityNormal() const = 0;
|
||||
virtual float GetRippleIntensityPoison() const = 0;
|
||||
virtual float GetRippleIntensityLava() const = 0;
|
||||
virtual float GetFluidEnvBumpScale() const = 0;
|
||||
virtual float GetWaterFogDistanceBase() const = 0;
|
||||
virtual float GetWaterFogDistanceRange() const = 0;
|
||||
virtual float GetGravityWaterFogDistanceBase() const = 0;
|
||||
virtual float GetGravityWaterFogDistanceRange() const = 0;
|
||||
virtual float GetHardModeDamageMultiplier() const = 0;
|
||||
virtual float GetHardModeWeaponMultiplier() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -3,151 +3,134 @@
|
|||
#include "ITweak.hpp"
|
||||
#include "zeus/CVector2f.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
struct ITweakGui : ITweak
|
||||
{
|
||||
enum class EHudVisMode : atUint32
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three
|
||||
};
|
||||
struct ITweakGui : ITweak {
|
||||
enum class EHudVisMode : atUint32 { Zero, One, Two, Three };
|
||||
|
||||
enum class EHelmetVisMode : atUint32
|
||||
{
|
||||
ReducedUpdate,
|
||||
NotVisible,
|
||||
Deco,
|
||||
HelmetDeco,
|
||||
GlowHelmetDeco,
|
||||
HelmetOnly
|
||||
};
|
||||
enum class EHelmetVisMode : atUint32 { ReducedUpdate, NotVisible, Deco, HelmetDeco, GlowHelmetDeco, HelmetOnly };
|
||||
|
||||
virtual float GetMapAlphaInterpolant() const=0;
|
||||
virtual float GetPauseBlurFactor() const=0;
|
||||
virtual float GetRadarXYRadius() const=0;
|
||||
virtual float GetRadarZRadius() const=0;
|
||||
virtual float GetRadarZCloseRadius() const=0;
|
||||
virtual float GetEnergyBarFilledSpeed() const=0;
|
||||
virtual float GetEnergyBarShadowSpeed() const=0;
|
||||
virtual float GetEnergyBarDrainDelay() const=0;
|
||||
virtual bool GetEnergyBarAlwaysResetDelay() const=0;
|
||||
virtual float GetHudDamagePracticalsGainConstant() const=0;
|
||||
virtual float GetHudDamagePracticalsGainLinear() const=0;
|
||||
virtual float GetHudDamagePracticalsInitConstant() const=0;
|
||||
virtual float GetHudDamagePracticalsInitLinear() const=0;
|
||||
virtual float GetHudDamageLightSpotAngle() const=0;
|
||||
virtual float GetDamageLightAngleC() const=0;
|
||||
virtual float GetDamageLightAngleL() const=0;
|
||||
virtual float GetDamageLightAngleQ() const=0;
|
||||
virtual atVec3f GetDamageLightPreTranslate() const=0;
|
||||
virtual atVec3f GetDamageLightCenterTranslate() const=0;
|
||||
virtual float GetDamageLightXfXAngle() const=0;
|
||||
virtual float GetDamageLightXfZAngle() const=0;
|
||||
virtual float GetHudDecoShakeTranslateVelConstant() const=0;
|
||||
virtual float GetHudDecoShakeTranslateVelLinear() const=0;
|
||||
virtual float GetMaxDecoDamageShakeTranslate() const=0;
|
||||
virtual float GetDecoDamageShakeDeceleration() const=0;
|
||||
virtual float GetDecoShakeGainConstant() const=0;
|
||||
virtual float GetDecoShakeGainLinear() const=0;
|
||||
virtual float GetDecoShakeInitConstant() const=0;
|
||||
virtual float GetDecoShakeInitLinear() const=0;
|
||||
virtual float GetMaxDecoDamageShakeRotate() const=0;
|
||||
virtual atUint32 GetHudCamFovTweak() const=0;
|
||||
virtual atUint32 GetHudCamYTweak() const=0;
|
||||
virtual atUint32 GetHudCamZTweak() const=0;
|
||||
virtual float GetBeamVisorMenuAnimTime() const=0;
|
||||
virtual float GetVisorBeamMenuItemActiveScale() const=0;
|
||||
virtual float GetVisorBeamMenuItemInactiveScale() const=0;
|
||||
virtual float GetVisorBeamMenuItemTranslate() const=0;
|
||||
virtual float GetThreatRange() const=0;
|
||||
virtual float GetRadarScopeCoordRadius() const=0;
|
||||
virtual float GetRadarPlayerPaintRadius() const=0;
|
||||
virtual float GetRadarEnemyPaintRadius() const=0;
|
||||
virtual float GetMissileArrowVisTime() const=0;
|
||||
virtual EHudVisMode GetHudVisMode() const=0;
|
||||
virtual EHelmetVisMode GetHelmetVisMode() const=0;
|
||||
virtual atUint32 GetEnableAutoMapper() const=0;
|
||||
virtual atUint32 GetEnableTargetingManager() const=0;
|
||||
virtual atUint32 GetEnablePlayerVisor() const=0;
|
||||
virtual float GetThreatWarningFraction() const=0;
|
||||
virtual float GetMissileWarningFraction() const=0;
|
||||
virtual float GetFreeLookFadeTime() const=0;
|
||||
virtual float GetFreeLookSfxPitchScale() const=0;
|
||||
virtual bool GetNoAbsoluteFreeLookSfxPitch() const=0;
|
||||
virtual float GetFaceReflectionOrthoWidth() const=0;
|
||||
virtual float GetFaceReflectionOrthoHeight() const=0;
|
||||
virtual float GetFaceReflectionDistance() const=0;
|
||||
virtual float GetFaceReflectionHeight() const=0;
|
||||
virtual float GetFaceReflectionAspect() const=0;
|
||||
virtual float GetMissileWarningPulseTime() const=0;
|
||||
virtual float GetExplosionLightFalloffMultConstant() const=0;
|
||||
virtual float GetExplosionLightFalloffMultLinear() const=0;
|
||||
virtual float GetExplosionLightFalloffMultQuadratic() const=0;
|
||||
virtual float GetHudDamagePeakFactor() const=0;
|
||||
virtual float GetHudDamageFilterGainConstant() const=0;
|
||||
virtual float GetHudDamageFilterGainLinear() const=0;
|
||||
virtual float GetHudDamageFilterInitConstant() const=0;
|
||||
virtual float GetHudDamageFilterInitLinear() const=0;
|
||||
virtual float GetEnergyDrainModPeriod() const=0;
|
||||
virtual bool GetEnergyDrainSinusoidalPulse() const=0;
|
||||
virtual bool GetEnergyDrainFilterAdditive() const=0;
|
||||
virtual float GetHudDamagePulseDuration() const=0;
|
||||
virtual float GetHudDamageColorGain() const=0;
|
||||
virtual float GetHudDecoShakeTranslateGain() const=0;
|
||||
virtual float GetHudLagOffsetScale() const=0;
|
||||
virtual float GetScanAppearanceDuration() const=0;
|
||||
virtual float GetScanPaneFlashFactor() const=0;
|
||||
virtual float GetScanPaneFadeInTime() const=0;
|
||||
virtual float GetScanPaneFadeOutTime() const=0;
|
||||
virtual float GetBallViewportYReduction() const=0;
|
||||
virtual float GetScanWindowIdleWidth() const=0;
|
||||
virtual float GetScanWindowIdleHeight() const=0;
|
||||
virtual float GetScanWindowActiveWidth() const=0;
|
||||
virtual float GetScanWindowActiveHeight() const=0;
|
||||
virtual float GetScanWindowMagnification() const=0;
|
||||
virtual float GetScanWindowScanningAspect() const=0;
|
||||
virtual float GetScanSpeed(int idx) const=0;
|
||||
virtual float GetXrayBlurScaleLinear() const=0;
|
||||
virtual float GetXrayBlurScaleQuadratic() const=0;
|
||||
virtual float GetScanSidesAngle() const=0;
|
||||
virtual float GetScanSidesXScale() const=0;
|
||||
virtual float GetScanSidesPositionEnd() const=0;
|
||||
virtual float GetScanSidesDuration() const=0;
|
||||
virtual float GetScanSidesStartTime() const=0;
|
||||
virtual float GetScanSidesEndTime() const=0;
|
||||
virtual float GetScanDataDotRadius() const=0;
|
||||
virtual float GetScanDataDotPosRandMagnitude() const=0;
|
||||
virtual float GetScanDataDotSeekDurationMin() const=0;
|
||||
virtual float GetScanDataDotSeekDurationMax() const=0;
|
||||
virtual float GetScanDataDotHoldDurationMin() const=0;
|
||||
virtual float GetScanDataDotHoldDurationMax() const=0;
|
||||
virtual float GetScanSidesPositionStart() const=0;
|
||||
virtual bool GetShowAutomapperInMorphball() const=0;
|
||||
virtual bool GetLatchArticleText() const=0;
|
||||
virtual float GetWorldTransManagerCharsPerSfx() const=0;
|
||||
virtual atUint32 GetXRayFogMode() const=0;
|
||||
virtual float GetXRayFogNearZ() const=0;
|
||||
virtual float GetXRayFogFarZ() const=0;
|
||||
virtual const zeus::CColor& GetXRayFogColor() const=0;
|
||||
virtual float GetThermalVisorLevel() const=0;
|
||||
virtual const zeus::CColor& GetThermalVisorColor() const=0;
|
||||
virtual const zeus::CColor& GetVisorHudLightAdd(int v) const=0;
|
||||
virtual const zeus::CColor& GetVisorHudLightMultiply(int v) const=0;
|
||||
virtual const zeus::CColor& GetHudReflectivityLightColor() const=0;
|
||||
virtual float GetHudLightAttMulConstant() const=0;
|
||||
virtual float GetHudLightAttMulLinear() const=0;
|
||||
virtual float GetHudLightAttMulQuadratic() const=0;
|
||||
virtual float GetMapAlphaInterpolant() const = 0;
|
||||
virtual float GetPauseBlurFactor() const = 0;
|
||||
virtual float GetRadarXYRadius() const = 0;
|
||||
virtual float GetRadarZRadius() const = 0;
|
||||
virtual float GetRadarZCloseRadius() const = 0;
|
||||
virtual float GetEnergyBarFilledSpeed() const = 0;
|
||||
virtual float GetEnergyBarShadowSpeed() const = 0;
|
||||
virtual float GetEnergyBarDrainDelay() const = 0;
|
||||
virtual bool GetEnergyBarAlwaysResetDelay() const = 0;
|
||||
virtual float GetHudDamagePracticalsGainConstant() const = 0;
|
||||
virtual float GetHudDamagePracticalsGainLinear() const = 0;
|
||||
virtual float GetHudDamagePracticalsInitConstant() const = 0;
|
||||
virtual float GetHudDamagePracticalsInitLinear() const = 0;
|
||||
virtual float GetHudDamageLightSpotAngle() const = 0;
|
||||
virtual float GetDamageLightAngleC() const = 0;
|
||||
virtual float GetDamageLightAngleL() const = 0;
|
||||
virtual float GetDamageLightAngleQ() const = 0;
|
||||
virtual atVec3f GetDamageLightPreTranslate() const = 0;
|
||||
virtual atVec3f GetDamageLightCenterTranslate() const = 0;
|
||||
virtual float GetDamageLightXfXAngle() const = 0;
|
||||
virtual float GetDamageLightXfZAngle() const = 0;
|
||||
virtual float GetHudDecoShakeTranslateVelConstant() const = 0;
|
||||
virtual float GetHudDecoShakeTranslateVelLinear() const = 0;
|
||||
virtual float GetMaxDecoDamageShakeTranslate() const = 0;
|
||||
virtual float GetDecoDamageShakeDeceleration() const = 0;
|
||||
virtual float GetDecoShakeGainConstant() const = 0;
|
||||
virtual float GetDecoShakeGainLinear() const = 0;
|
||||
virtual float GetDecoShakeInitConstant() const = 0;
|
||||
virtual float GetDecoShakeInitLinear() const = 0;
|
||||
virtual float GetMaxDecoDamageShakeRotate() const = 0;
|
||||
virtual atUint32 GetHudCamFovTweak() const = 0;
|
||||
virtual atUint32 GetHudCamYTweak() const = 0;
|
||||
virtual atUint32 GetHudCamZTweak() const = 0;
|
||||
virtual float GetBeamVisorMenuAnimTime() const = 0;
|
||||
virtual float GetVisorBeamMenuItemActiveScale() const = 0;
|
||||
virtual float GetVisorBeamMenuItemInactiveScale() const = 0;
|
||||
virtual float GetVisorBeamMenuItemTranslate() const = 0;
|
||||
virtual float GetThreatRange() const = 0;
|
||||
virtual float GetRadarScopeCoordRadius() const = 0;
|
||||
virtual float GetRadarPlayerPaintRadius() const = 0;
|
||||
virtual float GetRadarEnemyPaintRadius() const = 0;
|
||||
virtual float GetMissileArrowVisTime() const = 0;
|
||||
virtual EHudVisMode GetHudVisMode() const = 0;
|
||||
virtual EHelmetVisMode GetHelmetVisMode() const = 0;
|
||||
virtual atUint32 GetEnableAutoMapper() const = 0;
|
||||
virtual atUint32 GetEnableTargetingManager() const = 0;
|
||||
virtual atUint32 GetEnablePlayerVisor() const = 0;
|
||||
virtual float GetThreatWarningFraction() const = 0;
|
||||
virtual float GetMissileWarningFraction() const = 0;
|
||||
virtual float GetFreeLookFadeTime() const = 0;
|
||||
virtual float GetFreeLookSfxPitchScale() const = 0;
|
||||
virtual bool GetNoAbsoluteFreeLookSfxPitch() const = 0;
|
||||
virtual float GetFaceReflectionOrthoWidth() const = 0;
|
||||
virtual float GetFaceReflectionOrthoHeight() const = 0;
|
||||
virtual float GetFaceReflectionDistance() const = 0;
|
||||
virtual float GetFaceReflectionHeight() const = 0;
|
||||
virtual float GetFaceReflectionAspect() const = 0;
|
||||
virtual float GetMissileWarningPulseTime() const = 0;
|
||||
virtual float GetExplosionLightFalloffMultConstant() const = 0;
|
||||
virtual float GetExplosionLightFalloffMultLinear() const = 0;
|
||||
virtual float GetExplosionLightFalloffMultQuadratic() const = 0;
|
||||
virtual float GetHudDamagePeakFactor() const = 0;
|
||||
virtual float GetHudDamageFilterGainConstant() const = 0;
|
||||
virtual float GetHudDamageFilterGainLinear() const = 0;
|
||||
virtual float GetHudDamageFilterInitConstant() const = 0;
|
||||
virtual float GetHudDamageFilterInitLinear() const = 0;
|
||||
virtual float GetEnergyDrainModPeriod() const = 0;
|
||||
virtual bool GetEnergyDrainSinusoidalPulse() const = 0;
|
||||
virtual bool GetEnergyDrainFilterAdditive() const = 0;
|
||||
virtual float GetHudDamagePulseDuration() const = 0;
|
||||
virtual float GetHudDamageColorGain() const = 0;
|
||||
virtual float GetHudDecoShakeTranslateGain() const = 0;
|
||||
virtual float GetHudLagOffsetScale() const = 0;
|
||||
virtual float GetScanAppearanceDuration() const = 0;
|
||||
virtual float GetScanPaneFlashFactor() const = 0;
|
||||
virtual float GetScanPaneFadeInTime() const = 0;
|
||||
virtual float GetScanPaneFadeOutTime() const = 0;
|
||||
virtual float GetBallViewportYReduction() const = 0;
|
||||
virtual float GetScanWindowIdleWidth() const = 0;
|
||||
virtual float GetScanWindowIdleHeight() const = 0;
|
||||
virtual float GetScanWindowActiveWidth() const = 0;
|
||||
virtual float GetScanWindowActiveHeight() const = 0;
|
||||
virtual float GetScanWindowMagnification() const = 0;
|
||||
virtual float GetScanWindowScanningAspect() const = 0;
|
||||
virtual float GetScanSpeed(int idx) const = 0;
|
||||
virtual float GetXrayBlurScaleLinear() const = 0;
|
||||
virtual float GetXrayBlurScaleQuadratic() const = 0;
|
||||
virtual float GetScanSidesAngle() const = 0;
|
||||
virtual float GetScanSidesXScale() const = 0;
|
||||
virtual float GetScanSidesPositionEnd() const = 0;
|
||||
virtual float GetScanSidesDuration() const = 0;
|
||||
virtual float GetScanSidesStartTime() const = 0;
|
||||
virtual float GetScanSidesEndTime() const = 0;
|
||||
virtual float GetScanDataDotRadius() const = 0;
|
||||
virtual float GetScanDataDotPosRandMagnitude() const = 0;
|
||||
virtual float GetScanDataDotSeekDurationMin() const = 0;
|
||||
virtual float GetScanDataDotSeekDurationMax() const = 0;
|
||||
virtual float GetScanDataDotHoldDurationMin() const = 0;
|
||||
virtual float GetScanDataDotHoldDurationMax() const = 0;
|
||||
virtual float GetScanSidesPositionStart() const = 0;
|
||||
virtual bool GetShowAutomapperInMorphball() const = 0;
|
||||
virtual bool GetLatchArticleText() const = 0;
|
||||
virtual float GetWorldTransManagerCharsPerSfx() const = 0;
|
||||
virtual atUint32 GetXRayFogMode() const = 0;
|
||||
virtual float GetXRayFogNearZ() const = 0;
|
||||
virtual float GetXRayFogFarZ() const = 0;
|
||||
virtual const zeus::CColor& GetXRayFogColor() const = 0;
|
||||
virtual float GetThermalVisorLevel() const = 0;
|
||||
virtual const zeus::CColor& GetThermalVisorColor() const = 0;
|
||||
virtual const zeus::CColor& GetVisorHudLightAdd(int v) const = 0;
|
||||
virtual const zeus::CColor& GetVisorHudLightMultiply(int v) const = 0;
|
||||
virtual const zeus::CColor& GetHudReflectivityLightColor() const = 0;
|
||||
virtual float GetHudLightAttMulConstant() const = 0;
|
||||
virtual float GetHudLightAttMulLinear() const = 0;
|
||||
virtual float GetHudLightAttMulQuadratic() const = 0;
|
||||
|
||||
static float FaceReflectionDistanceDebugValueToActualValue(float v) { return 0.015f * v + 0.2f; }
|
||||
static float FaceReflectionHeightDebugValueToActualValue(float v) { return 0.005f * v - 0.05f; }
|
||||
static float FaceReflectionAspectDebugValueToActualValue(float v) { return 0.05f * v + 1.f; }
|
||||
static float FaceReflectionOrthoWidthDebugValueToActualValue(float v) { return 0.007f * v + 0.02f; }
|
||||
static float FaceReflectionOrthoHeightDebugValueToActualValue(float v) { return 0.007f * v + 0.02f; }
|
||||
static float FaceReflectionDistanceDebugValueToActualValue(float v) { return 0.015f * v + 0.2f; }
|
||||
static float FaceReflectionHeightDebugValueToActualValue(float v) { return 0.005f * v - 0.05f; }
|
||||
static float FaceReflectionAspectDebugValueToActualValue(float v) { return 0.05f * v + 1.f; }
|
||||
static float FaceReflectionOrthoWidthDebugValueToActualValue(float v) { return 0.007f * v + 0.02f; }
|
||||
static float FaceReflectionOrthoHeightDebugValueToActualValue(float v) { return 0.007f * v + 0.02f; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,106 +2,101 @@
|
|||
|
||||
#include "ITweak.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
struct ITweakGuiColors : ITweak
|
||||
{
|
||||
struct VisorEnergyInitColors
|
||||
{
|
||||
const zeus::CColor& tankFilled;
|
||||
const zeus::CColor& tankEmpty;
|
||||
const zeus::CColor& digitsFont;
|
||||
const zeus::CColor& digitsOutline;
|
||||
};
|
||||
namespace DataSpec {
|
||||
struct ITweakGuiColors : ITweak {
|
||||
struct VisorEnergyInitColors {
|
||||
const zeus::CColor& tankFilled;
|
||||
const zeus::CColor& tankEmpty;
|
||||
const zeus::CColor& digitsFont;
|
||||
const zeus::CColor& digitsOutline;
|
||||
};
|
||||
|
||||
struct VisorEnergyBarColors
|
||||
{
|
||||
const zeus::CColor& filled;
|
||||
const zeus::CColor& empty;
|
||||
const zeus::CColor& shadow;
|
||||
};
|
||||
struct VisorEnergyBarColors {
|
||||
const zeus::CColor& filled;
|
||||
const zeus::CColor& empty;
|
||||
const zeus::CColor& shadow;
|
||||
};
|
||||
|
||||
virtual const zeus::CColor& GetPauseBlurFilterColor() const=0;
|
||||
virtual const zeus::CColor& GetRadarStuffColor() const=0;
|
||||
virtual const zeus::CColor& GetRadarPlayerPaintColor() const=0;
|
||||
virtual const zeus::CColor& GetRadarEnemyPaintColor() const=0;
|
||||
virtual const zeus::CColor& GetHudMessageFill() const=0;
|
||||
virtual const zeus::CColor& GetHudMessageOutline() const=0;
|
||||
virtual const zeus::CColor& GetHudFrameColor() const=0;
|
||||
virtual const zeus::CColor& GetMissileIconColorActive() const=0;
|
||||
virtual const zeus::CColor& GetVisorBeamMenuItemActive() const=0;
|
||||
virtual const zeus::CColor& GetVisorBeamMenuItemInactive() const=0;
|
||||
virtual const zeus::CColor& GetEnergyBarFilledLowEnergy() const=0;
|
||||
virtual const zeus::CColor& GetEnergyBarShadowLowEnergy() const=0;
|
||||
virtual const zeus::CColor& GetEnergyBarEmptyLowEnergy() const=0;
|
||||
virtual const zeus::CColor& GetHudDamageLightColor() const=0;
|
||||
virtual const zeus::CColor& GetVisorMenuTextFont() const=0;
|
||||
virtual const zeus::CColor& GetVisorMenuTextOutline() const=0;
|
||||
virtual const zeus::CColor& GetBeamMenuTextFont() const=0;
|
||||
virtual const zeus::CColor& GetBeamMenuTextOutline() const=0;
|
||||
virtual const zeus::CColor& GetEnergyWarningFont() const=0;
|
||||
virtual const zeus::CColor& GetThreatWarningFont() const=0;
|
||||
virtual const zeus::CColor& GetMissileWarningFont() const=0;
|
||||
virtual const zeus::CColor& GetThreatBarFilled() const=0;
|
||||
virtual const zeus::CColor& GetThreatBarShadow() const=0;
|
||||
virtual const zeus::CColor& GetThreatBarEmpty() const=0;
|
||||
virtual const zeus::CColor& GetMissileBarFilled() const=0;
|
||||
virtual const zeus::CColor& GetMissileBarShadow() const=0;
|
||||
virtual const zeus::CColor& GetMissileBarEmpty() const=0;
|
||||
virtual const zeus::CColor& GetThreatIconColor() const=0;
|
||||
virtual const zeus::CColor& GetTickDecoColor() const=0;
|
||||
virtual const zeus::CColor& GetHelmetLightColor() const=0;
|
||||
virtual const zeus::CColor& GetThreatIconSafeColor() const=0;
|
||||
virtual const zeus::CColor& GetMissileIconColorInactive() const=0;
|
||||
virtual const zeus::CColor& GetMissileIconColorChargedCanAlt() const=0;
|
||||
virtual const zeus::CColor& GetMissileIconColorChargedNoAlt() const=0;
|
||||
virtual const zeus::CColor& GetMissileIconColorDepleteAlt() const=0;
|
||||
virtual const zeus::CColor& GetVisorBeamMenuLozColor() const=0;
|
||||
virtual const zeus::CColor& GetEnergyWarningOutline() const=0;
|
||||
virtual const zeus::CColor& GetThreatWarningOutline() const=0;
|
||||
virtual const zeus::CColor& GetMissileWarningOutline() const=0;
|
||||
virtual const zeus::CColor& GetDamageAmbientColor() const=0;
|
||||
virtual const zeus::CColor& GetScanFrameInactiveColor() const=0;
|
||||
virtual const zeus::CColor& GetScanFrameActiveColor() const=0;
|
||||
virtual const zeus::CColor& GetScanFrameImpulseColor() const=0;
|
||||
virtual const zeus::CColor& GetScanVisorHudLightMultiply() const=0;
|
||||
virtual const zeus::CColor& GetScanVisorScreenDimColor() const=0;
|
||||
virtual const zeus::CColor& GetThermalVisorHudLightMultiply() const=0;
|
||||
virtual const zeus::CColor& GetEnergyDrainFilterColor() const=0;
|
||||
virtual const zeus::CColor& GetDamageAmbientPulseColor() const=0;
|
||||
virtual const zeus::CColor& GetEnergyBarFlashColor() const=0;
|
||||
virtual const zeus::CColor& GetXRayEnergyDecoColor() const=0;
|
||||
virtual const zeus::CColor& GetScanDataDotColor() const=0;
|
||||
virtual const zeus::CColor& GetPowerBombDigitAvailableFont() const=0;
|
||||
virtual const zeus::CColor& GetPowerBombDigitAvailableOutline() const=0;
|
||||
virtual const zeus::CColor& GetBallBombFilledColor() const=0;
|
||||
virtual const zeus::CColor& GetBallBombEmptyColor() const=0;
|
||||
virtual const zeus::CColor& GetPowerBombIconAvailableColor() const=0;
|
||||
virtual const zeus::CColor& GetBallBombEnergyColor() const=0;
|
||||
virtual const zeus::CColor& GetBallBombDecoColor() const=0;
|
||||
virtual const zeus::CColor& GetPowerBombDigitDelpetedFont() const=0;
|
||||
virtual const zeus::CColor& GetPowerBombDigitDelpetedOutline() const=0;
|
||||
virtual const zeus::CColor& GetPowerBombIconDepletedColor() const=0;
|
||||
virtual const zeus::CColor& GetScanDisplayImagePaneColor() const=0;
|
||||
virtual const zeus::CColor& GetThreatIconWarningColor() const=0;
|
||||
virtual const zeus::CColor& GetHudCounterFill() const=0;
|
||||
virtual const zeus::CColor& GetHudCounterOutline() const=0;
|
||||
virtual const zeus::CColor& GetScanIconCriticalColor() const=0;
|
||||
virtual const zeus::CColor& GetScanIconCriticalDimColor() const=0;
|
||||
virtual const zeus::CColor& GetScanIconNoncriticalColor() const=0;
|
||||
virtual const zeus::CColor& GetScanIconNoncriticalDimColor() const=0;
|
||||
virtual const zeus::CColor& GetScanReticuleColor() const=0;
|
||||
virtual const zeus::CColor& GetThreatDigitsFont() const=0;
|
||||
virtual const zeus::CColor& GetThreatDigitsOutline() const=0;
|
||||
virtual const zeus::CColor& GetMissileDigitsFont() const=0;
|
||||
virtual const zeus::CColor& GetMissileDigitsOutline() const=0;
|
||||
virtual const zeus::CColor& GetThermalDecoColor() const=0;
|
||||
virtual const zeus::CColor& GetThermalOutlinesColor() const=0;
|
||||
virtual const zeus::CColor& GetThermalLockColor() const=0;
|
||||
virtual const zeus::CColor& GetPauseItemAmberColor() const=0;
|
||||
virtual const zeus::CColor& GetPauseItemBlueColor() const=0;
|
||||
virtual VisorEnergyInitColors GetVisorEnergyInitColors(int idx) const=0;
|
||||
virtual VisorEnergyBarColors GetVisorEnergyBarColors(int idx) const=0;
|
||||
virtual const zeus::CColor& GetPauseBlurFilterColor() const = 0;
|
||||
virtual const zeus::CColor& GetRadarStuffColor() const = 0;
|
||||
virtual const zeus::CColor& GetRadarPlayerPaintColor() const = 0;
|
||||
virtual const zeus::CColor& GetRadarEnemyPaintColor() const = 0;
|
||||
virtual const zeus::CColor& GetHudMessageFill() const = 0;
|
||||
virtual const zeus::CColor& GetHudMessageOutline() const = 0;
|
||||
virtual const zeus::CColor& GetHudFrameColor() const = 0;
|
||||
virtual const zeus::CColor& GetMissileIconColorActive() const = 0;
|
||||
virtual const zeus::CColor& GetVisorBeamMenuItemActive() const = 0;
|
||||
virtual const zeus::CColor& GetVisorBeamMenuItemInactive() const = 0;
|
||||
virtual const zeus::CColor& GetEnergyBarFilledLowEnergy() const = 0;
|
||||
virtual const zeus::CColor& GetEnergyBarShadowLowEnergy() const = 0;
|
||||
virtual const zeus::CColor& GetEnergyBarEmptyLowEnergy() const = 0;
|
||||
virtual const zeus::CColor& GetHudDamageLightColor() const = 0;
|
||||
virtual const zeus::CColor& GetVisorMenuTextFont() const = 0;
|
||||
virtual const zeus::CColor& GetVisorMenuTextOutline() const = 0;
|
||||
virtual const zeus::CColor& GetBeamMenuTextFont() const = 0;
|
||||
virtual const zeus::CColor& GetBeamMenuTextOutline() const = 0;
|
||||
virtual const zeus::CColor& GetEnergyWarningFont() const = 0;
|
||||
virtual const zeus::CColor& GetThreatWarningFont() const = 0;
|
||||
virtual const zeus::CColor& GetMissileWarningFont() const = 0;
|
||||
virtual const zeus::CColor& GetThreatBarFilled() const = 0;
|
||||
virtual const zeus::CColor& GetThreatBarShadow() const = 0;
|
||||
virtual const zeus::CColor& GetThreatBarEmpty() const = 0;
|
||||
virtual const zeus::CColor& GetMissileBarFilled() const = 0;
|
||||
virtual const zeus::CColor& GetMissileBarShadow() const = 0;
|
||||
virtual const zeus::CColor& GetMissileBarEmpty() const = 0;
|
||||
virtual const zeus::CColor& GetThreatIconColor() const = 0;
|
||||
virtual const zeus::CColor& GetTickDecoColor() const = 0;
|
||||
virtual const zeus::CColor& GetHelmetLightColor() const = 0;
|
||||
virtual const zeus::CColor& GetThreatIconSafeColor() const = 0;
|
||||
virtual const zeus::CColor& GetMissileIconColorInactive() const = 0;
|
||||
virtual const zeus::CColor& GetMissileIconColorChargedCanAlt() const = 0;
|
||||
virtual const zeus::CColor& GetMissileIconColorChargedNoAlt() const = 0;
|
||||
virtual const zeus::CColor& GetMissileIconColorDepleteAlt() const = 0;
|
||||
virtual const zeus::CColor& GetVisorBeamMenuLozColor() const = 0;
|
||||
virtual const zeus::CColor& GetEnergyWarningOutline() const = 0;
|
||||
virtual const zeus::CColor& GetThreatWarningOutline() const = 0;
|
||||
virtual const zeus::CColor& GetMissileWarningOutline() const = 0;
|
||||
virtual const zeus::CColor& GetDamageAmbientColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanFrameInactiveColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanFrameActiveColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanFrameImpulseColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanVisorHudLightMultiply() const = 0;
|
||||
virtual const zeus::CColor& GetScanVisorScreenDimColor() const = 0;
|
||||
virtual const zeus::CColor& GetThermalVisorHudLightMultiply() const = 0;
|
||||
virtual const zeus::CColor& GetEnergyDrainFilterColor() const = 0;
|
||||
virtual const zeus::CColor& GetDamageAmbientPulseColor() const = 0;
|
||||
virtual const zeus::CColor& GetEnergyBarFlashColor() const = 0;
|
||||
virtual const zeus::CColor& GetXRayEnergyDecoColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanDataDotColor() const = 0;
|
||||
virtual const zeus::CColor& GetPowerBombDigitAvailableFont() const = 0;
|
||||
virtual const zeus::CColor& GetPowerBombDigitAvailableOutline() const = 0;
|
||||
virtual const zeus::CColor& GetBallBombFilledColor() const = 0;
|
||||
virtual const zeus::CColor& GetBallBombEmptyColor() const = 0;
|
||||
virtual const zeus::CColor& GetPowerBombIconAvailableColor() const = 0;
|
||||
virtual const zeus::CColor& GetBallBombEnergyColor() const = 0;
|
||||
virtual const zeus::CColor& GetBallBombDecoColor() const = 0;
|
||||
virtual const zeus::CColor& GetPowerBombDigitDelpetedFont() const = 0;
|
||||
virtual const zeus::CColor& GetPowerBombDigitDelpetedOutline() const = 0;
|
||||
virtual const zeus::CColor& GetPowerBombIconDepletedColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanDisplayImagePaneColor() const = 0;
|
||||
virtual const zeus::CColor& GetThreatIconWarningColor() const = 0;
|
||||
virtual const zeus::CColor& GetHudCounterFill() const = 0;
|
||||
virtual const zeus::CColor& GetHudCounterOutline() const = 0;
|
||||
virtual const zeus::CColor& GetScanIconCriticalColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanIconCriticalDimColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanIconNoncriticalColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanIconNoncriticalDimColor() const = 0;
|
||||
virtual const zeus::CColor& GetScanReticuleColor() const = 0;
|
||||
virtual const zeus::CColor& GetThreatDigitsFont() const = 0;
|
||||
virtual const zeus::CColor& GetThreatDigitsOutline() const = 0;
|
||||
virtual const zeus::CColor& GetMissileDigitsFont() const = 0;
|
||||
virtual const zeus::CColor& GetMissileDigitsOutline() const = 0;
|
||||
virtual const zeus::CColor& GetThermalDecoColor() const = 0;
|
||||
virtual const zeus::CColor& GetThermalOutlinesColor() const = 0;
|
||||
virtual const zeus::CColor& GetThermalLockColor() const = 0;
|
||||
virtual const zeus::CColor& GetPauseItemAmberColor() const = 0;
|
||||
virtual const zeus::CColor& GetPauseItemBlueColor() const = 0;
|
||||
virtual VisorEnergyInitColors GetVisorEnergyInitColors(int idx) const = 0;
|
||||
virtual VisorEnergyBarColors GetVisorEnergyBarColors(int idx) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -4,137 +4,130 @@
|
|||
#include "Runtime/IFactory.hpp"
|
||||
#include "Runtime/CPlayerState.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
struct ITweakGunRes : ITweak
|
||||
{
|
||||
using ResId = urde::CAssetId;
|
||||
using EBeamId = urde::CPlayerState::EBeamId;
|
||||
struct ITweakGunRes : ITweak {
|
||||
using ResId = urde::CAssetId;
|
||||
using EBeamId = urde::CPlayerState::EBeamId;
|
||||
|
||||
ResId x4_gunMotion;
|
||||
ResId x8_grappleArm;
|
||||
ResId xc_rightHand;
|
||||
ResId x4_gunMotion;
|
||||
ResId x8_grappleArm;
|
||||
ResId xc_rightHand;
|
||||
|
||||
ResId x10_powerBeam;
|
||||
ResId x14_iceBeam;
|
||||
ResId x18_waveBeam;
|
||||
ResId x1c_plasmaBeam;
|
||||
ResId x20_phazonBeam;
|
||||
ResId x10_powerBeam;
|
||||
ResId x14_iceBeam;
|
||||
ResId x18_waveBeam;
|
||||
ResId x1c_plasmaBeam;
|
||||
ResId x20_phazonBeam;
|
||||
|
||||
ResId x24_holoTransition;
|
||||
ResId x24_holoTransition;
|
||||
|
||||
ResId x28_bombSet;
|
||||
ResId x2c_bombExplode;
|
||||
ResId x30_powerBombExplode;
|
||||
ResId x28_bombSet;
|
||||
ResId x2c_bombExplode;
|
||||
ResId x30_powerBombExplode;
|
||||
|
||||
/* Power, Ice, Wave, Plasma, Phazon / Beam, Ball */
|
||||
ResId x34_weapons[5][2];
|
||||
ResId x84_muzzle[5];
|
||||
ResId x94_charge[5];
|
||||
ResId xa4_auxMuzzle[5];
|
||||
/* Power, Ice, Wave, Plasma, Phazon / Beam, Ball */
|
||||
ResId x34_weapons[5][2];
|
||||
ResId x84_muzzle[5];
|
||||
ResId x94_charge[5];
|
||||
ResId xa4_auxMuzzle[5];
|
||||
|
||||
ResId xb4_grappleSegment;
|
||||
ResId xb8_grappleClaw;
|
||||
ResId xbc_grappleHit;
|
||||
ResId xc0_grappleMuzzle;
|
||||
ResId xc4_grappleSwoosh;
|
||||
ResId xb4_grappleSegment;
|
||||
ResId xb8_grappleClaw;
|
||||
ResId xbc_grappleHit;
|
||||
ResId xc0_grappleMuzzle;
|
||||
ResId xc4_grappleSwoosh;
|
||||
|
||||
ResId GetBeamModel(EBeamId beam) const
|
||||
{
|
||||
auto b = int(beam);
|
||||
if (b < 0 || b > 4)
|
||||
b = 0;
|
||||
switch (EBeamId(b))
|
||||
{
|
||||
default:
|
||||
case EBeamId::Power:
|
||||
return x10_powerBeam;
|
||||
case EBeamId::Ice:
|
||||
return x14_iceBeam;
|
||||
case EBeamId::Wave:
|
||||
return x18_waveBeam;
|
||||
case EBeamId::Plasma:
|
||||
return x1c_plasmaBeam;
|
||||
case EBeamId::Phazon:
|
||||
return x20_phazonBeam;
|
||||
}
|
||||
ResId GetBeamModel(EBeamId beam) const {
|
||||
auto b = int(beam);
|
||||
if (b < 0 || b > 4)
|
||||
b = 0;
|
||||
switch (EBeamId(b)) {
|
||||
default:
|
||||
case EBeamId::Power:
|
||||
return x10_powerBeam;
|
||||
case EBeamId::Ice:
|
||||
return x14_iceBeam;
|
||||
case EBeamId::Wave:
|
||||
return x18_waveBeam;
|
||||
case EBeamId::Plasma:
|
||||
return x1c_plasmaBeam;
|
||||
case EBeamId::Phazon:
|
||||
return x20_phazonBeam;
|
||||
}
|
||||
}
|
||||
|
||||
const ResId* GetWeaponPair(EBeamId beam) const
|
||||
{
|
||||
auto b = int(beam);
|
||||
if (b < 0 || b > 4)
|
||||
return x34_weapons[0];
|
||||
return x34_weapons[b];
|
||||
}
|
||||
const ResId* GetWeaponPair(EBeamId beam) const {
|
||||
auto b = int(beam);
|
||||
if (b < 0 || b > 4)
|
||||
return x34_weapons[0];
|
||||
return x34_weapons[b];
|
||||
}
|
||||
|
||||
void ResolveResources(const urde::IFactory& factory)
|
||||
{
|
||||
x4_gunMotion = factory.GetResourceIdByName(GetGunMotion().c_str())->id;
|
||||
x8_grappleArm = factory.GetResourceIdByName(GetGrappleArm().c_str())->id;
|
||||
xc_rightHand = factory.GetResourceIdByName(GetRightHand().c_str())->id;
|
||||
void ResolveResources(const urde::IFactory& factory) {
|
||||
x4_gunMotion = factory.GetResourceIdByName(GetGunMotion().c_str())->id;
|
||||
x8_grappleArm = factory.GetResourceIdByName(GetGrappleArm().c_str())->id;
|
||||
xc_rightHand = factory.GetResourceIdByName(GetRightHand().c_str())->id;
|
||||
|
||||
x10_powerBeam = factory.GetResourceIdByName(GetPowerBeam().c_str())->id;
|
||||
x14_iceBeam = factory.GetResourceIdByName(GetIceBeam().c_str())->id;
|
||||
x18_waveBeam = factory.GetResourceIdByName(GetWaveBeam().c_str())->id;
|
||||
x1c_plasmaBeam = factory.GetResourceIdByName(GetPlasmaBeam().c_str())->id;
|
||||
x20_phazonBeam = factory.GetResourceIdByName(GetPhazonBeam().c_str())->id;
|
||||
x10_powerBeam = factory.GetResourceIdByName(GetPowerBeam().c_str())->id;
|
||||
x14_iceBeam = factory.GetResourceIdByName(GetIceBeam().c_str())->id;
|
||||
x18_waveBeam = factory.GetResourceIdByName(GetWaveBeam().c_str())->id;
|
||||
x1c_plasmaBeam = factory.GetResourceIdByName(GetPlasmaBeam().c_str())->id;
|
||||
x20_phazonBeam = factory.GetResourceIdByName(GetPhazonBeam().c_str())->id;
|
||||
|
||||
x24_holoTransition = factory.GetResourceIdByName(GetHoloTransition().c_str())->id;
|
||||
x24_holoTransition = factory.GetResourceIdByName(GetHoloTransition().c_str())->id;
|
||||
|
||||
x28_bombSet = factory.GetResourceIdByName(GetBombSet().c_str())->id;
|
||||
x2c_bombExplode = factory.GetResourceIdByName(GetBombExplode().c_str())->id;
|
||||
x30_powerBombExplode = factory.GetResourceIdByName(GetPowerBombExplode().c_str())->id;
|
||||
x28_bombSet = factory.GetResourceIdByName(GetBombSet().c_str())->id;
|
||||
x2c_bombExplode = factory.GetResourceIdByName(GetBombExplode().c_str())->id;
|
||||
x30_powerBombExplode = factory.GetResourceIdByName(GetPowerBombExplode().c_str())->id;
|
||||
|
||||
for (int i=0 ; i<5 ; ++i)
|
||||
for (int j=0 ; j<2 ; ++j)
|
||||
x34_weapons[i][j] = factory.GetResourceIdByName(GetWeapon(i, j).c_str())->id;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
for (int j = 0; j < 2; ++j)
|
||||
x34_weapons[i][j] = factory.GetResourceIdByName(GetWeapon(i, j).c_str())->id;
|
||||
|
||||
for (int i=0 ; i<5 ; ++i)
|
||||
x84_muzzle[i] = factory.GetResourceIdByName(GetMuzzleParticle(i).c_str())->id;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
x84_muzzle[i] = factory.GetResourceIdByName(GetMuzzleParticle(i).c_str())->id;
|
||||
|
||||
for (int i=0 ; i<5 ; ++i)
|
||||
x94_charge[i] = factory.GetResourceIdByName(GetChargeParticle(i).c_str())->id;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
x94_charge[i] = factory.GetResourceIdByName(GetChargeParticle(i).c_str())->id;
|
||||
|
||||
for (int i=0 ; i<5 ; ++i)
|
||||
xa4_auxMuzzle[i] = factory.GetResourceIdByName(GetAuxMuzzleParticle(i).c_str())->id;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
xa4_auxMuzzle[i] = factory.GetResourceIdByName(GetAuxMuzzleParticle(i).c_str())->id;
|
||||
|
||||
xb4_grappleSegment = factory.GetResourceIdByName(GetGrappleSegmentParticle().c_str())->id;
|
||||
xb8_grappleClaw = factory.GetResourceIdByName(GetGrappleClawParticle().c_str())->id;
|
||||
xbc_grappleHit = factory.GetResourceIdByName(GetGrappleHitParticle().c_str())->id;
|
||||
xc0_grappleMuzzle = factory.GetResourceIdByName(GetGrappleMuzzleParticle().c_str())->id;
|
||||
xc4_grappleSwoosh = factory.GetResourceIdByName(GetGrappleSwooshParticle().c_str())->id;
|
||||
}
|
||||
xb4_grappleSegment = factory.GetResourceIdByName(GetGrappleSegmentParticle().c_str())->id;
|
||||
xb8_grappleClaw = factory.GetResourceIdByName(GetGrappleClawParticle().c_str())->id;
|
||||
xbc_grappleHit = factory.GetResourceIdByName(GetGrappleHitParticle().c_str())->id;
|
||||
xc0_grappleMuzzle = factory.GetResourceIdByName(GetGrappleMuzzleParticle().c_str())->id;
|
||||
xc4_grappleSwoosh = factory.GetResourceIdByName(GetGrappleSwooshParticle().c_str())->id;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual const std::string& GetGunMotion() const=0;
|
||||
virtual const std::string& GetGrappleArm() const=0;
|
||||
virtual const std::string& GetRightHand() const=0;
|
||||
virtual const std::string& GetGunMotion() const = 0;
|
||||
virtual const std::string& GetGrappleArm() const = 0;
|
||||
virtual const std::string& GetRightHand() const = 0;
|
||||
|
||||
virtual const std::string& GetPowerBeam() const=0;
|
||||
virtual const std::string& GetIceBeam() const=0;
|
||||
virtual const std::string& GetWaveBeam() const=0;
|
||||
virtual const std::string& GetPlasmaBeam() const=0;
|
||||
virtual const std::string& GetPhazonBeam() const=0;
|
||||
virtual const std::string& GetPowerBeam() const = 0;
|
||||
virtual const std::string& GetIceBeam() const = 0;
|
||||
virtual const std::string& GetWaveBeam() const = 0;
|
||||
virtual const std::string& GetPlasmaBeam() const = 0;
|
||||
virtual const std::string& GetPhazonBeam() const = 0;
|
||||
|
||||
virtual const std::string& GetHoloTransition() const=0;
|
||||
virtual const std::string& GetHoloTransition() const = 0;
|
||||
|
||||
virtual const std::string& GetBombSet() const=0;
|
||||
virtual const std::string& GetBombExplode() const=0;
|
||||
virtual const std::string& GetPowerBombExplode() const=0;
|
||||
virtual const std::string& GetBombSet() const = 0;
|
||||
virtual const std::string& GetBombExplode() const = 0;
|
||||
virtual const std::string& GetPowerBombExplode() const = 0;
|
||||
|
||||
virtual const std::string& GetWeapon(size_t idx, bool ball) const=0;
|
||||
virtual const std::string& GetMuzzleParticle(size_t idx) const=0;
|
||||
virtual const std::string& GetChargeParticle(size_t idx) const=0;
|
||||
virtual const std::string& GetAuxMuzzleParticle(size_t idx) const=0;
|
||||
virtual const std::string& GetWeapon(size_t idx, bool ball) const = 0;
|
||||
virtual const std::string& GetMuzzleParticle(size_t idx) const = 0;
|
||||
virtual const std::string& GetChargeParticle(size_t idx) const = 0;
|
||||
virtual const std::string& GetAuxMuzzleParticle(size_t idx) const = 0;
|
||||
|
||||
virtual const std::string& GetGrappleSegmentParticle() const=0;
|
||||
virtual const std::string& GetGrappleClawParticle() const=0;
|
||||
virtual const std::string& GetGrappleHitParticle() const=0;
|
||||
virtual const std::string& GetGrappleMuzzleParticle() const=0;
|
||||
virtual const std::string& GetGrappleSwooshParticle() const=0;
|
||||
virtual const std::string& GetGrappleSegmentParticle() const = 0;
|
||||
virtual const std::string& GetGrappleClawParticle() const = 0;
|
||||
virtual const std::string& GetGrappleHitParticle() const = 0;
|
||||
virtual const std::string& GetGrappleMuzzleParticle() const = 0;
|
||||
virtual const std::string& GetGrappleSwooshParticle() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,12 +2,8 @@
|
|||
|
||||
#include "ITweak.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
struct ITweakParticle : ITweak
|
||||
{
|
||||
};
|
||||
|
||||
}
|
||||
struct ITweakParticle : ITweak {};
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -3,145 +3,142 @@
|
|||
#include "ITweak.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
struct ITweakPlayer : ITweak
|
||||
{
|
||||
virtual float GetMaxTranslationalAcceleration(int s) const=0;
|
||||
virtual float GetMaxRotationalAcceleration(int s) const=0;
|
||||
virtual float GetPlayerTranslationFriction(int s) const=0;
|
||||
virtual float GetPlayerRotationFriction(int s) const=0;
|
||||
virtual float GetPlayerRotationMaxSpeed(int s) const=0;
|
||||
virtual float GetPlayerTranslationMaxSpeed(int s) const=0;
|
||||
virtual float GetNormalGravAccel() const=0;
|
||||
virtual float GetFluidGravAccel() const=0;
|
||||
virtual float GetVerticalJumpAccel() const=0;
|
||||
virtual float GetHorizontalJumpAccel() const=0;
|
||||
virtual float GetVerticalDoubleJumpAccel() const=0;
|
||||
virtual float GetHorizontalDoubleJumpAccel() const=0;
|
||||
virtual float GetWaterJumpFactor() const=0;
|
||||
virtual float GetWaterBallJumpFactor() const=0;
|
||||
virtual float GetLavaJumpFactor() const=0;
|
||||
virtual float GetLavaBallJumpFactor() const=0;
|
||||
virtual float GetPhazonJumpFactor() const=0;
|
||||
virtual float GetPhazonBallJumpFactor() const=0;
|
||||
virtual float GetAllowedJumpTime() const=0;
|
||||
virtual float GetAllowedDoubleJumpTime() const=0;
|
||||
virtual float GetMinDoubleJumpWindow() const=0;
|
||||
virtual float GetMaxDoubleJumpWindow() const=0;
|
||||
virtual float GetMinJumpTime() const=0;
|
||||
virtual float GetMinDoubleJumpTime() const=0;
|
||||
virtual float GetAllowedLedgeTime() const=0;
|
||||
virtual float GetDoubleJumpImpulse() const=0;
|
||||
virtual float GetBackwardsForceMultiplier() const=0;
|
||||
virtual float GetBombJumpRadius() const=0;
|
||||
virtual float GetBombJumpHeight() const=0;
|
||||
virtual float GetEyeOffset() const=0;
|
||||
virtual float GetTurnSpeedMultiplier() const=0;
|
||||
virtual float GetFreeLookTurnSpeedMultiplier() const=0;
|
||||
virtual float GetFreeLookSpeed() const=0;
|
||||
virtual float GetFreeLookSnapSpeed() const=0;
|
||||
virtual float GetFreeLookCenteredThresholdAngle() const=0;
|
||||
virtual float GetFreeLookCenteredTime() const=0;
|
||||
virtual float GetOrbitModeTimer() const=0;
|
||||
virtual float GetOrbitUpperAngle() const=0;
|
||||
virtual float GetOrbitLowerAngle() const=0;
|
||||
virtual float GetOrbitHorizAngle() const=0;
|
||||
virtual float GetOrbitMaxTargetDistance() const=0;
|
||||
virtual float GetOrbitMaxLockDistance() const=0;
|
||||
virtual float GetOrbitDistanceThreshold() const=0;
|
||||
virtual uint32_t GetOrbitScreenBoxHalfExtentX(int zone) const=0;
|
||||
virtual uint32_t GetOrbitScreenBoxHalfExtentY(int zone) const=0;
|
||||
virtual uint32_t GetOrbitScreenBoxCenterX(int zone) const=0;
|
||||
virtual uint32_t GetOrbitScreenBoxCenterY(int zone) const=0;
|
||||
virtual uint32_t GetOrbitZoneIdealX(int zone) const=0;
|
||||
virtual uint32_t GetOrbitZoneIdealY(int zone) const=0;
|
||||
virtual float GetOrbitNearX() const=0;
|
||||
virtual float GetOrbitNearZ() const=0;
|
||||
virtual float GetOrbitFixedOffsetZDiff() const=0;
|
||||
virtual float GetOrbitZRange() const=0;
|
||||
virtual bool GetDashEnabled() const=0;
|
||||
virtual bool GetDashOnButtonRelease() const=0;
|
||||
virtual float GetDashButtonHoldCancelTime() const=0;
|
||||
virtual float GetDashStrafeInputThreshold() const=0;
|
||||
virtual float GetSidewaysDoubleJumpImpulse() const=0;
|
||||
virtual float GetSidewaysVerticalDoubleJumpAccel() const=0;
|
||||
virtual float GetSidewaysHorizontalDoubleJumpAccel() const=0;
|
||||
virtual float GetScanningRange() const=0; // x218
|
||||
virtual bool GetScanRetention() const=0;
|
||||
virtual bool GetScanFreezesGame() const=0; // x21c_25
|
||||
virtual bool GetOrbitWhileScanning() const=0;
|
||||
virtual bool GetFallingDoubleJump() const=0;
|
||||
virtual bool GetImpulseDoubleJump() const=0;
|
||||
virtual bool GetFiringCancelsCameraPitch() const=0;
|
||||
virtual bool GetAssistedAimingIgnoreHorizontal() const=0;
|
||||
virtual bool GetAssistedAimingIgnoreVertical() const=0;
|
||||
virtual float GetAimMaxDistance() const=0;
|
||||
virtual float GetAimThresholdDistance() const=0;
|
||||
virtual float GetAimBoxWidth() const=0;
|
||||
virtual float GetAimBoxHeight() const=0;
|
||||
virtual float GetAimTargetTimer() const=0;
|
||||
virtual float GetAimAssistHorizontalAngle() const=0;
|
||||
virtual float GetAimAssistVerticalAngle() const=0;
|
||||
virtual float GetScanMaxTargetDistance() const=0;
|
||||
virtual float GetScanMaxLockDistance() const=0;
|
||||
virtual bool GetMoveDuringFreeLook() const=0;
|
||||
virtual bool GetHoldButtonsForFreeLook() const=0;
|
||||
virtual bool GetTwoButtonsForFreeLook() const=0;
|
||||
virtual bool GetAimWhenOrbitingPoint() const=0;
|
||||
virtual bool GetStayInFreeLookWhileFiring() const=0;
|
||||
virtual bool GetOrbitFixedOffset() const=0;
|
||||
virtual bool GetGunButtonTogglesHolster() const=0;
|
||||
virtual bool GetGunNotFiringHolstersGun() const=0;
|
||||
virtual float GetPlayerHeight() const=0; // x26c
|
||||
virtual float GetPlayerXYHalfExtent() const=0; // x270
|
||||
virtual bool GetFreeLookTurnsPlayer() const=0; // x228_24
|
||||
virtual float GetStepUpHeight() const=0; // x274
|
||||
virtual float GetStepDownHeight() const=0; // x278
|
||||
virtual float GetPlayerBallHalfExtent() const=0; // x27c
|
||||
virtual float GetOrbitDistanceMax() const=0;
|
||||
virtual float GetGrappleSwingLength() const=0;
|
||||
virtual float GetGrappleSwingPeriod() const=0;
|
||||
virtual float GetGrapplePullSpeedMin() const=0;
|
||||
virtual float GetMaxGrappleLockedTurnAlignDistance() const=0;
|
||||
virtual float GetGrapplePullSpeedProportion() const=0;
|
||||
virtual float GetGrapplePullSpeedMax() const=0;
|
||||
virtual float GetGrappleLookCenterSpeed() const=0;
|
||||
virtual float GetMaxGrappleTurnSpeed() const=0;
|
||||
virtual float GetGrappleJumpForce() const=0;
|
||||
virtual float GetGrappleReleaseTime() const=0;
|
||||
virtual uint32_t GetGrappleJumpMode() const=0;
|
||||
virtual bool GetOrbitReleaseBreaksGrapple() const=0;
|
||||
virtual bool GetInvertGrappleTurn() const=0;
|
||||
virtual float GetGrappleBeamSpeed() const=0;
|
||||
virtual float GetGrappleBeamXWaveAmplitude() const=0;
|
||||
virtual float GetGrappleBeamZWaveAmplitude() const=0;
|
||||
virtual float GetGrappleBeamAnglePhaseDelta() const=0;
|
||||
virtual float GetHorizontalFreeLookAngleVel() const=0;
|
||||
virtual float GetVerticalFreeLookAngleVel() const=0; // x134
|
||||
virtual float GetOrbitCameraSpeed() const=0; // x184
|
||||
virtual float GetOrbitPreventionTime() const=0;
|
||||
virtual float GetJumpCameraPitchDownStart() const=0; // x288
|
||||
virtual float GetJumpCameraPitchDownFull() const=0; // x28c
|
||||
virtual float GetJumpCameraPitchDownAngle() const=0; // x290
|
||||
virtual float GetFallCameraPitchDownStart() const=0; // x294
|
||||
virtual float GetFallCameraPitchDownFull() const=0; // x298
|
||||
virtual float GetFallCameraPitchDownAngle() const=0; // x29c
|
||||
virtual float GetFirstPersonCameraSpeed() const=0; // x280
|
||||
virtual float GetGrappleCameraSpeed() const=0; // x2b0
|
||||
virtual float GetFreeLookDampenFactor() const=0; // x14c
|
||||
virtual float GetLeftLogicalThreshold() const=0;
|
||||
virtual float GetRightLogicalThreshold() const=0;
|
||||
virtual float GetOrbitMinDistance(int type) const=0;
|
||||
virtual float GetOrbitNormalDistance(int type) const=0;
|
||||
virtual float GetOrbitMaxDistance(int type) const=0;
|
||||
virtual float GetFrozenTimeout() const=0;
|
||||
virtual uint32_t GetIceBreakJumpCount() const=0;
|
||||
virtual float GetVariaDamageReduction() const=0;
|
||||
virtual float GetGravityDamageReduction() const=0;
|
||||
virtual float GetPhazonDamageReduction() const=0;
|
||||
struct ITweakPlayer : ITweak {
|
||||
virtual float GetMaxTranslationalAcceleration(int s) const = 0;
|
||||
virtual float GetMaxRotationalAcceleration(int s) const = 0;
|
||||
virtual float GetPlayerTranslationFriction(int s) const = 0;
|
||||
virtual float GetPlayerRotationFriction(int s) const = 0;
|
||||
virtual float GetPlayerRotationMaxSpeed(int s) const = 0;
|
||||
virtual float GetPlayerTranslationMaxSpeed(int s) const = 0;
|
||||
virtual float GetNormalGravAccel() const = 0;
|
||||
virtual float GetFluidGravAccel() const = 0;
|
||||
virtual float GetVerticalJumpAccel() const = 0;
|
||||
virtual float GetHorizontalJumpAccel() const = 0;
|
||||
virtual float GetVerticalDoubleJumpAccel() const = 0;
|
||||
virtual float GetHorizontalDoubleJumpAccel() const = 0;
|
||||
virtual float GetWaterJumpFactor() const = 0;
|
||||
virtual float GetWaterBallJumpFactor() const = 0;
|
||||
virtual float GetLavaJumpFactor() const = 0;
|
||||
virtual float GetLavaBallJumpFactor() const = 0;
|
||||
virtual float GetPhazonJumpFactor() const = 0;
|
||||
virtual float GetPhazonBallJumpFactor() const = 0;
|
||||
virtual float GetAllowedJumpTime() const = 0;
|
||||
virtual float GetAllowedDoubleJumpTime() const = 0;
|
||||
virtual float GetMinDoubleJumpWindow() const = 0;
|
||||
virtual float GetMaxDoubleJumpWindow() const = 0;
|
||||
virtual float GetMinJumpTime() const = 0;
|
||||
virtual float GetMinDoubleJumpTime() const = 0;
|
||||
virtual float GetAllowedLedgeTime() const = 0;
|
||||
virtual float GetDoubleJumpImpulse() const = 0;
|
||||
virtual float GetBackwardsForceMultiplier() const = 0;
|
||||
virtual float GetBombJumpRadius() const = 0;
|
||||
virtual float GetBombJumpHeight() const = 0;
|
||||
virtual float GetEyeOffset() const = 0;
|
||||
virtual float GetTurnSpeedMultiplier() const = 0;
|
||||
virtual float GetFreeLookTurnSpeedMultiplier() const = 0;
|
||||
virtual float GetFreeLookSpeed() const = 0;
|
||||
virtual float GetFreeLookSnapSpeed() const = 0;
|
||||
virtual float GetFreeLookCenteredThresholdAngle() const = 0;
|
||||
virtual float GetFreeLookCenteredTime() const = 0;
|
||||
virtual float GetOrbitModeTimer() const = 0;
|
||||
virtual float GetOrbitUpperAngle() const = 0;
|
||||
virtual float GetOrbitLowerAngle() const = 0;
|
||||
virtual float GetOrbitHorizAngle() const = 0;
|
||||
virtual float GetOrbitMaxTargetDistance() const = 0;
|
||||
virtual float GetOrbitMaxLockDistance() const = 0;
|
||||
virtual float GetOrbitDistanceThreshold() const = 0;
|
||||
virtual uint32_t GetOrbitScreenBoxHalfExtentX(int zone) const = 0;
|
||||
virtual uint32_t GetOrbitScreenBoxHalfExtentY(int zone) const = 0;
|
||||
virtual uint32_t GetOrbitScreenBoxCenterX(int zone) const = 0;
|
||||
virtual uint32_t GetOrbitScreenBoxCenterY(int zone) const = 0;
|
||||
virtual uint32_t GetOrbitZoneIdealX(int zone) const = 0;
|
||||
virtual uint32_t GetOrbitZoneIdealY(int zone) const = 0;
|
||||
virtual float GetOrbitNearX() const = 0;
|
||||
virtual float GetOrbitNearZ() const = 0;
|
||||
virtual float GetOrbitFixedOffsetZDiff() const = 0;
|
||||
virtual float GetOrbitZRange() const = 0;
|
||||
virtual bool GetDashEnabled() const = 0;
|
||||
virtual bool GetDashOnButtonRelease() const = 0;
|
||||
virtual float GetDashButtonHoldCancelTime() const = 0;
|
||||
virtual float GetDashStrafeInputThreshold() const = 0;
|
||||
virtual float GetSidewaysDoubleJumpImpulse() const = 0;
|
||||
virtual float GetSidewaysVerticalDoubleJumpAccel() const = 0;
|
||||
virtual float GetSidewaysHorizontalDoubleJumpAccel() const = 0;
|
||||
virtual float GetScanningRange() const = 0; // x218
|
||||
virtual bool GetScanRetention() const = 0;
|
||||
virtual bool GetScanFreezesGame() const = 0; // x21c_25
|
||||
virtual bool GetOrbitWhileScanning() const = 0;
|
||||
virtual bool GetFallingDoubleJump() const = 0;
|
||||
virtual bool GetImpulseDoubleJump() const = 0;
|
||||
virtual bool GetFiringCancelsCameraPitch() const = 0;
|
||||
virtual bool GetAssistedAimingIgnoreHorizontal() const = 0;
|
||||
virtual bool GetAssistedAimingIgnoreVertical() const = 0;
|
||||
virtual float GetAimMaxDistance() const = 0;
|
||||
virtual float GetAimThresholdDistance() const = 0;
|
||||
virtual float GetAimBoxWidth() const = 0;
|
||||
virtual float GetAimBoxHeight() const = 0;
|
||||
virtual float GetAimTargetTimer() const = 0;
|
||||
virtual float GetAimAssistHorizontalAngle() const = 0;
|
||||
virtual float GetAimAssistVerticalAngle() const = 0;
|
||||
virtual float GetScanMaxTargetDistance() const = 0;
|
||||
virtual float GetScanMaxLockDistance() const = 0;
|
||||
virtual bool GetMoveDuringFreeLook() const = 0;
|
||||
virtual bool GetHoldButtonsForFreeLook() const = 0;
|
||||
virtual bool GetTwoButtonsForFreeLook() const = 0;
|
||||
virtual bool GetAimWhenOrbitingPoint() const = 0;
|
||||
virtual bool GetStayInFreeLookWhileFiring() const = 0;
|
||||
virtual bool GetOrbitFixedOffset() const = 0;
|
||||
virtual bool GetGunButtonTogglesHolster() const = 0;
|
||||
virtual bool GetGunNotFiringHolstersGun() const = 0;
|
||||
virtual float GetPlayerHeight() const = 0; // x26c
|
||||
virtual float GetPlayerXYHalfExtent() const = 0; // x270
|
||||
virtual bool GetFreeLookTurnsPlayer() const = 0; // x228_24
|
||||
virtual float GetStepUpHeight() const = 0; // x274
|
||||
virtual float GetStepDownHeight() const = 0; // x278
|
||||
virtual float GetPlayerBallHalfExtent() const = 0; // x27c
|
||||
virtual float GetOrbitDistanceMax() const = 0;
|
||||
virtual float GetGrappleSwingLength() const = 0;
|
||||
virtual float GetGrappleSwingPeriod() const = 0;
|
||||
virtual float GetGrapplePullSpeedMin() const = 0;
|
||||
virtual float GetMaxGrappleLockedTurnAlignDistance() const = 0;
|
||||
virtual float GetGrapplePullSpeedProportion() const = 0;
|
||||
virtual float GetGrapplePullSpeedMax() const = 0;
|
||||
virtual float GetGrappleLookCenterSpeed() const = 0;
|
||||
virtual float GetMaxGrappleTurnSpeed() const = 0;
|
||||
virtual float GetGrappleJumpForce() const = 0;
|
||||
virtual float GetGrappleReleaseTime() const = 0;
|
||||
virtual uint32_t GetGrappleJumpMode() const = 0;
|
||||
virtual bool GetOrbitReleaseBreaksGrapple() const = 0;
|
||||
virtual bool GetInvertGrappleTurn() const = 0;
|
||||
virtual float GetGrappleBeamSpeed() const = 0;
|
||||
virtual float GetGrappleBeamXWaveAmplitude() const = 0;
|
||||
virtual float GetGrappleBeamZWaveAmplitude() const = 0;
|
||||
virtual float GetGrappleBeamAnglePhaseDelta() const = 0;
|
||||
virtual float GetHorizontalFreeLookAngleVel() const = 0;
|
||||
virtual float GetVerticalFreeLookAngleVel() const = 0; // x134
|
||||
virtual float GetOrbitCameraSpeed() const = 0; // x184
|
||||
virtual float GetOrbitPreventionTime() const = 0;
|
||||
virtual float GetJumpCameraPitchDownStart() const = 0; // x288
|
||||
virtual float GetJumpCameraPitchDownFull() const = 0; // x28c
|
||||
virtual float GetJumpCameraPitchDownAngle() const = 0; // x290
|
||||
virtual float GetFallCameraPitchDownStart() const = 0; // x294
|
||||
virtual float GetFallCameraPitchDownFull() const = 0; // x298
|
||||
virtual float GetFallCameraPitchDownAngle() const = 0; // x29c
|
||||
virtual float GetFirstPersonCameraSpeed() const = 0; // x280
|
||||
virtual float GetGrappleCameraSpeed() const = 0; // x2b0
|
||||
virtual float GetFreeLookDampenFactor() const = 0; // x14c
|
||||
virtual float GetLeftLogicalThreshold() const = 0;
|
||||
virtual float GetRightLogicalThreshold() const = 0;
|
||||
virtual float GetOrbitMinDistance(int type) const = 0;
|
||||
virtual float GetOrbitNormalDistance(int type) const = 0;
|
||||
virtual float GetOrbitMaxDistance(int type) const = 0;
|
||||
virtual float GetFrozenTimeout() const = 0;
|
||||
virtual uint32_t GetIceBreakJumpCount() const = 0;
|
||||
virtual float GetVariaDamageReduction() const = 0;
|
||||
virtual float GetGravityDamageReduction() const = 0;
|
||||
virtual float GetPhazonDamageReduction() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,13 +2,10 @@
|
|||
|
||||
#include "ITweak.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
struct ITweakPlayerControl : ITweak
|
||||
{
|
||||
virtual atUint32 GetMapping(atUint32) const=0;
|
||||
struct ITweakPlayerControl : ITweak {
|
||||
virtual atUint32 GetMapping(atUint32) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -3,72 +3,70 @@
|
|||
#include "ITweak.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
/* Same as CDamageInfo */
|
||||
struct SShotParam : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atInt32> weaponType = -1;
|
||||
bool charged : 1;
|
||||
bool combo : 1;
|
||||
bool instaKill : 1;
|
||||
Value<float> damage = 0.f;
|
||||
Value<float> radiusDamage = 0.f;
|
||||
Value<float> radius = 0.f;
|
||||
Value<float> knockback = 0.f;
|
||||
bool noImmunity : 1;
|
||||
SShotParam() { charged = false; combo = false; instaKill = false; noImmunity = false; }
|
||||
struct SShotParam : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atInt32> weaponType = -1;
|
||||
bool charged : 1;
|
||||
bool combo : 1;
|
||||
bool instaKill : 1;
|
||||
Value<float> damage = 0.f;
|
||||
Value<float> radiusDamage = 0.f;
|
||||
Value<float> radius = 0.f;
|
||||
Value<float> knockback = 0.f;
|
||||
bool noImmunity : 1;
|
||||
SShotParam() {
|
||||
charged = false;
|
||||
combo = false;
|
||||
instaKill = false;
|
||||
noImmunity = false;
|
||||
}
|
||||
};
|
||||
|
||||
struct SComboShotParam : SShotParam
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
SComboShotParam() { combo = true; }
|
||||
struct SComboShotParam : SShotParam {
|
||||
AT_DECL_DNA_YAML
|
||||
SComboShotParam() { combo = true; }
|
||||
};
|
||||
|
||||
struct SChargedShotParam : SShotParam
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
SChargedShotParam() { charged = true; }
|
||||
struct SChargedShotParam : SShotParam {
|
||||
AT_DECL_DNA_YAML
|
||||
SChargedShotParam() { charged = true; }
|
||||
};
|
||||
|
||||
struct SWeaponInfo : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<float> x0_coolDown = 0.1f;
|
||||
SShotParam x4_normal;
|
||||
SChargedShotParam x20_charged;
|
||||
struct SWeaponInfo : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<float> x0_coolDown = 0.1f;
|
||||
SShotParam x4_normal;
|
||||
SChargedShotParam x20_charged;
|
||||
};
|
||||
|
||||
struct ITweakPlayerGun : ITweak
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
virtual float GetUpLookAngle() const = 0;
|
||||
virtual float GetDownLookAngle() const = 0;
|
||||
virtual float GetVerticalSpread() const = 0;
|
||||
virtual float GetHorizontalSpread() const = 0;
|
||||
virtual float GetHighVerticalSpread() const = 0;
|
||||
virtual float GetHighHorizontalSpread() const = 0;
|
||||
virtual float GetLowVerticalSpread() const = 0;
|
||||
virtual float GetLowHorizontalSpread() const = 0;
|
||||
virtual float GetAimVerticalSpeed() const = 0; // x24
|
||||
virtual float GetAimHorizontalSpeed() const = 0; // x28
|
||||
virtual float GetBombFuseTime() const = 0; // x2c
|
||||
virtual float GetBombDropDelayTime() const = 0; // x30
|
||||
virtual float GetHoloHoldTime() const = 0; // x34
|
||||
virtual float GetGunTransformTime() const = 0; // x38
|
||||
virtual float GetGunHolsterTime() const = 0;
|
||||
virtual float GetGunNotFiringTime() const = 0;
|
||||
virtual float GetFixedVerticalAim() const = 0;
|
||||
virtual float GetGunExtendDistance() const = 0;
|
||||
virtual const zeus::CVector3f& GetGunPosition() const = 0;
|
||||
virtual const zeus::CVector3f& GetGrapplingArmPosition() const = 0;
|
||||
virtual float GetRichochetDamage(atUint32) const = 0;
|
||||
virtual const SWeaponInfo& GetBeamInfo(atInt32 beam) const = 0;
|
||||
virtual const SComboShotParam& GetComboShotInfo(atInt32 beam) const = 0;
|
||||
virtual const SShotParam& GetBombInfo() const=0;
|
||||
virtual const SShotParam& GetPowerBombInfo() const=0;
|
||||
struct ITweakPlayerGun : ITweak {
|
||||
AT_DECL_DNA_YAML
|
||||
virtual float GetUpLookAngle() const = 0;
|
||||
virtual float GetDownLookAngle() const = 0;
|
||||
virtual float GetVerticalSpread() const = 0;
|
||||
virtual float GetHorizontalSpread() const = 0;
|
||||
virtual float GetHighVerticalSpread() const = 0;
|
||||
virtual float GetHighHorizontalSpread() const = 0;
|
||||
virtual float GetLowVerticalSpread() const = 0;
|
||||
virtual float GetLowHorizontalSpread() const = 0;
|
||||
virtual float GetAimVerticalSpeed() const = 0; // x24
|
||||
virtual float GetAimHorizontalSpeed() const = 0; // x28
|
||||
virtual float GetBombFuseTime() const = 0; // x2c
|
||||
virtual float GetBombDropDelayTime() const = 0; // x30
|
||||
virtual float GetHoloHoldTime() const = 0; // x34
|
||||
virtual float GetGunTransformTime() const = 0; // x38
|
||||
virtual float GetGunHolsterTime() const = 0;
|
||||
virtual float GetGunNotFiringTime() const = 0;
|
||||
virtual float GetFixedVerticalAim() const = 0;
|
||||
virtual float GetGunExtendDistance() const = 0;
|
||||
virtual const zeus::CVector3f& GetGunPosition() const = 0;
|
||||
virtual const zeus::CVector3f& GetGrapplingArmPosition() const = 0;
|
||||
virtual float GetRichochetDamage(atUint32) const = 0;
|
||||
virtual const SWeaponInfo& GetBeamInfo(atInt32 beam) const = 0;
|
||||
virtual const SComboShotParam& GetComboShotInfo(atInt32 beam) const = 0;
|
||||
virtual const SShotParam& GetBombInfo() const = 0;
|
||||
virtual const SShotParam& GetPowerBombInfo() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -4,163 +4,155 @@
|
|||
#include "Runtime/IFactory.hpp"
|
||||
#include "Runtime/CPlayerState.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
struct ITweakPlayerRes : ITweak
|
||||
{
|
||||
using ResId = urde::CAssetId;
|
||||
using EBeamId = urde::CPlayerState::EBeamId;
|
||||
struct ITweakPlayerRes : ITweak {
|
||||
using ResId = urde::CAssetId;
|
||||
using EBeamId = urde::CPlayerState::EBeamId;
|
||||
|
||||
ResId x4_saveStationIcon;
|
||||
ResId x8_missileStationIcon;
|
||||
ResId xc_elevatorIcon;
|
||||
ResId x4_saveStationIcon;
|
||||
ResId x8_missileStationIcon;
|
||||
ResId xc_elevatorIcon;
|
||||
|
||||
ResId x10_minesBreakFirstTopIcon;
|
||||
ResId x14_minesBreakFirstBottomIcon;
|
||||
ResId x18_minesBreakSecondTopIcon;
|
||||
ResId x1c_minesBreakSecondBottomIcon;
|
||||
ResId x10_minesBreakFirstTopIcon;
|
||||
ResId x14_minesBreakFirstBottomIcon;
|
||||
ResId x18_minesBreakSecondTopIcon;
|
||||
ResId x1c_minesBreakSecondBottomIcon;
|
||||
|
||||
/* N, U, UL, L, DL, D, DR, R, UR */
|
||||
ResId x24_lStick[9];
|
||||
ResId x4c_cStick[9];
|
||||
/* N, U, UL, L, DL, D, DR, R, UR */
|
||||
ResId x24_lStick[9];
|
||||
ResId x4c_cStick[9];
|
||||
|
||||
/* Out, In */
|
||||
ResId x74_lTrigger[2];
|
||||
ResId x80_rTrigger[2];
|
||||
ResId x8c_startButton[2];
|
||||
ResId x98_aButton[2];
|
||||
ResId xa4_bButton[2];
|
||||
ResId xb0_xButton[2];
|
||||
ResId xbc_yButton[2];
|
||||
/* Out, In */
|
||||
ResId x74_lTrigger[2];
|
||||
ResId x80_rTrigger[2];
|
||||
ResId x8c_startButton[2];
|
||||
ResId x98_aButton[2];
|
||||
ResId xa4_bButton[2];
|
||||
ResId xb0_xButton[2];
|
||||
ResId xbc_yButton[2];
|
||||
|
||||
ResId xc4_ballTransitionsANCS;
|
||||
ResId xc4_ballTransitionsANCS;
|
||||
|
||||
/* Power, Ice, Wave, Plasma, Phazon */
|
||||
ResId xc8_ballTransitions[5];
|
||||
ResId xc8_cineGun[5];
|
||||
/* Power, Ice, Wave, Plasma, Phazon */
|
||||
ResId xc8_ballTransitions[5];
|
||||
ResId xc8_cineGun[5];
|
||||
|
||||
float xf0_cinematicMoveOutofIntoPlayerDistance;
|
||||
float xf0_cinematicMoveOutofIntoPlayerDistance;
|
||||
|
||||
ResId GetBeamBallTransitionModel(EBeamId beam) const
|
||||
{
|
||||
int b = int(beam);
|
||||
if (b < 0 || b > 4)
|
||||
b = 0;
|
||||
switch (EBeamId(b))
|
||||
{
|
||||
case EBeamId::Power:
|
||||
default:
|
||||
return xc8_ballTransitions[0];
|
||||
case EBeamId::Ice:
|
||||
return xc8_ballTransitions[1];
|
||||
case EBeamId::Wave:
|
||||
return xc8_ballTransitions[2];
|
||||
case EBeamId::Plasma:
|
||||
return xc8_ballTransitions[3];
|
||||
case EBeamId::Phazon:
|
||||
return xc8_ballTransitions[4];
|
||||
}
|
||||
ResId GetBeamBallTransitionModel(EBeamId beam) const {
|
||||
int b = int(beam);
|
||||
if (b < 0 || b > 4)
|
||||
b = 0;
|
||||
switch (EBeamId(b)) {
|
||||
case EBeamId::Power:
|
||||
default:
|
||||
return xc8_ballTransitions[0];
|
||||
case EBeamId::Ice:
|
||||
return xc8_ballTransitions[1];
|
||||
case EBeamId::Wave:
|
||||
return xc8_ballTransitions[2];
|
||||
case EBeamId::Plasma:
|
||||
return xc8_ballTransitions[3];
|
||||
case EBeamId::Phazon:
|
||||
return xc8_ballTransitions[4];
|
||||
}
|
||||
}
|
||||
|
||||
ResId GetBeamCineModel(EBeamId beam) const
|
||||
{
|
||||
int b = int(beam);
|
||||
if (b < 0 || b > 4)
|
||||
b = 0;
|
||||
switch (EBeamId(b))
|
||||
{
|
||||
case EBeamId::Power:
|
||||
default:
|
||||
return xc8_cineGun[0];
|
||||
case EBeamId::Ice:
|
||||
return xc8_cineGun[1];
|
||||
case EBeamId::Wave:
|
||||
return xc8_cineGun[2];
|
||||
case EBeamId::Plasma:
|
||||
return xc8_cineGun[3];
|
||||
case EBeamId::Phazon:
|
||||
return xc8_cineGun[4];
|
||||
}
|
||||
ResId GetBeamCineModel(EBeamId beam) const {
|
||||
int b = int(beam);
|
||||
if (b < 0 || b > 4)
|
||||
b = 0;
|
||||
switch (EBeamId(b)) {
|
||||
case EBeamId::Power:
|
||||
default:
|
||||
return xc8_cineGun[0];
|
||||
case EBeamId::Ice:
|
||||
return xc8_cineGun[1];
|
||||
case EBeamId::Wave:
|
||||
return xc8_cineGun[2];
|
||||
case EBeamId::Plasma:
|
||||
return xc8_cineGun[3];
|
||||
case EBeamId::Phazon:
|
||||
return xc8_cineGun[4];
|
||||
}
|
||||
}
|
||||
|
||||
void ResolveResources(const urde::IFactory& factory)
|
||||
{
|
||||
x4_saveStationIcon = factory.GetResourceIdByName(_GetSaveStationIcon().data())->id;
|
||||
x8_missileStationIcon = factory.GetResourceIdByName(_GetMissileStationIcon().data())->id;
|
||||
xc_elevatorIcon = factory.GetResourceIdByName(_GetElevatorIcon().data())->id;
|
||||
void ResolveResources(const urde::IFactory& factory) {
|
||||
x4_saveStationIcon = factory.GetResourceIdByName(_GetSaveStationIcon().data())->id;
|
||||
x8_missileStationIcon = factory.GetResourceIdByName(_GetMissileStationIcon().data())->id;
|
||||
xc_elevatorIcon = factory.GetResourceIdByName(_GetElevatorIcon().data())->id;
|
||||
|
||||
x10_minesBreakFirstTopIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id;
|
||||
x14_minesBreakFirstBottomIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id;
|
||||
x18_minesBreakSecondTopIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id;
|
||||
x1c_minesBreakSecondBottomIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id;
|
||||
x10_minesBreakFirstTopIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id;
|
||||
x14_minesBreakFirstBottomIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id;
|
||||
x18_minesBreakSecondTopIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id;
|
||||
x1c_minesBreakSecondBottomIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id;
|
||||
|
||||
for (int i=0 ; i<9 ; ++i)
|
||||
x24_lStick[i] = factory.GetResourceIdByName(_GetLStick(i).data())->id;
|
||||
for (int i = 0; i < 9; ++i)
|
||||
x24_lStick[i] = factory.GetResourceIdByName(_GetLStick(i).data())->id;
|
||||
|
||||
for (int i=0 ; i<9 ; ++i)
|
||||
x4c_cStick[i] = factory.GetResourceIdByName(_GetCStick(i).data())->id;
|
||||
for (int i = 0; i < 9; ++i)
|
||||
x4c_cStick[i] = factory.GetResourceIdByName(_GetCStick(i).data())->id;
|
||||
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
x74_lTrigger[i] = factory.GetResourceIdByName(_GetLTrigger(i).data())->id;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
x74_lTrigger[i] = factory.GetResourceIdByName(_GetLTrigger(i).data())->id;
|
||||
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
x80_rTrigger[i] = factory.GetResourceIdByName(_GetRTrigger(i).data())->id;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
x80_rTrigger[i] = factory.GetResourceIdByName(_GetRTrigger(i).data())->id;
|
||||
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
x8c_startButton[i] = factory.GetResourceIdByName(_GetStartButton(i).data())->id;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
x8c_startButton[i] = factory.GetResourceIdByName(_GetStartButton(i).data())->id;
|
||||
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
x98_aButton[i] = factory.GetResourceIdByName(_GetAButton(i).data())->id;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
x98_aButton[i] = factory.GetResourceIdByName(_GetAButton(i).data())->id;
|
||||
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
xa4_bButton[i] = factory.GetResourceIdByName(_GetBButton(i).data())->id;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
xa4_bButton[i] = factory.GetResourceIdByName(_GetBButton(i).data())->id;
|
||||
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
xb0_xButton[i] = factory.GetResourceIdByName(_GetXButton(i).data())->id;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
xb0_xButton[i] = factory.GetResourceIdByName(_GetXButton(i).data())->id;
|
||||
|
||||
for (int i=0 ; i<2 ; ++i)
|
||||
xbc_yButton[i] = factory.GetResourceIdByName(_GetYButton(i).data())->id;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
xbc_yButton[i] = factory.GetResourceIdByName(_GetYButton(i).data())->id;
|
||||
|
||||
xc4_ballTransitionsANCS = factory.GetResourceIdByName(_GetBallTransitionsANCS().data())->id;
|
||||
xc4_ballTransitionsANCS = factory.GetResourceIdByName(_GetBallTransitionsANCS().data())->id;
|
||||
|
||||
for (int i=0 ; i<5 ; ++i)
|
||||
xc8_ballTransitions[i] = factory.GetResourceIdByName(_GetBallTransitionBeamRes(i).data())->id;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
xc8_ballTransitions[i] = factory.GetResourceIdByName(_GetBallTransitionBeamRes(i).data())->id;
|
||||
|
||||
for (int i=0 ; i<5 ; ++i)
|
||||
xc8_cineGun[i] = factory.GetResourceIdByName(_GetBeamCineModel(i).data())->id;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
xc8_cineGun[i] = factory.GetResourceIdByName(_GetBeamCineModel(i).data())->id;
|
||||
|
||||
xf0_cinematicMoveOutofIntoPlayerDistance = _GetCinematicMoveOutofIntoPlayerDistance();
|
||||
}
|
||||
xf0_cinematicMoveOutofIntoPlayerDistance = _GetCinematicMoveOutofIntoPlayerDistance();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual std::string_view _GetSaveStationIcon() const=0;
|
||||
virtual std::string_view _GetMissileStationIcon() const=0;
|
||||
virtual std::string_view _GetElevatorIcon() const=0;
|
||||
virtual std::string_view _GetSaveStationIcon() const = 0;
|
||||
virtual std::string_view _GetMissileStationIcon() const = 0;
|
||||
virtual std::string_view _GetElevatorIcon() const = 0;
|
||||
|
||||
virtual std::string_view _GetMinesBreakFirstTopIcon() const=0;
|
||||
virtual std::string_view _GetMinesBreakFirstBottomIcon() const=0;
|
||||
virtual std::string_view _GetMinesBreakSecondTopIcon() const=0;
|
||||
virtual std::string_view _GetMinesBreakSecondBottomIcon() const=0;
|
||||
virtual std::string_view _GetMinesBreakFirstTopIcon() const = 0;
|
||||
virtual std::string_view _GetMinesBreakFirstBottomIcon() const = 0;
|
||||
virtual std::string_view _GetMinesBreakSecondTopIcon() const = 0;
|
||||
virtual std::string_view _GetMinesBreakSecondBottomIcon() const = 0;
|
||||
|
||||
virtual std::string_view _GetLStick(size_t idx) const=0;
|
||||
virtual std::string_view _GetCStick(size_t idx) const=0;
|
||||
virtual std::string_view _GetLStick(size_t idx) const = 0;
|
||||
virtual std::string_view _GetCStick(size_t idx) const = 0;
|
||||
|
||||
virtual std::string_view _GetLTrigger(size_t idx) const=0;
|
||||
virtual std::string_view _GetRTrigger(size_t idx) const=0;
|
||||
virtual std::string_view _GetStartButton(size_t idx) const=0;
|
||||
virtual std::string_view _GetAButton(size_t idx) const=0;
|
||||
virtual std::string_view _GetBButton(size_t idx) const=0;
|
||||
virtual std::string_view _GetXButton(size_t idx) const=0;
|
||||
virtual std::string_view _GetYButton(size_t idx) const=0;
|
||||
virtual std::string_view _GetLTrigger(size_t idx) const = 0;
|
||||
virtual std::string_view _GetRTrigger(size_t idx) const = 0;
|
||||
virtual std::string_view _GetStartButton(size_t idx) const = 0;
|
||||
virtual std::string_view _GetAButton(size_t idx) const = 0;
|
||||
virtual std::string_view _GetBButton(size_t idx) const = 0;
|
||||
virtual std::string_view _GetXButton(size_t idx) const = 0;
|
||||
virtual std::string_view _GetYButton(size_t idx) const = 0;
|
||||
|
||||
virtual std::string_view _GetBallTransitionsANCS() const=0;
|
||||
virtual std::string_view _GetBallTransitionsANCS() const = 0;
|
||||
|
||||
virtual std::string_view _GetBallTransitionBeamRes(size_t idx) const=0;
|
||||
virtual std::string_view _GetBeamCineModel(size_t idx) const=0;
|
||||
virtual std::string_view _GetBallTransitionBeamRes(size_t idx) const = 0;
|
||||
virtual std::string_view _GetBeamCineModel(size_t idx) const = 0;
|
||||
|
||||
virtual float _GetCinematicMoveOutofIntoPlayerDistance() const=0;
|
||||
virtual float _GetCinematicMoveOutofIntoPlayerDistance() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,17 +2,14 @@
|
|||
|
||||
#include "ITweak.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
struct ITweakSlideShow : ITweak
|
||||
{
|
||||
virtual std::string_view GetFont() const=0;
|
||||
virtual const zeus::CColor& GetFontColor() const=0;
|
||||
virtual const zeus::CColor& GetOutlineColor() const=0;
|
||||
virtual float GetScanPercentInterval() const=0;
|
||||
virtual float GetX54() const=0;
|
||||
struct ITweakSlideShow : ITweak {
|
||||
virtual std::string_view GetFont() const = 0;
|
||||
virtual const zeus::CColor& GetFontColor() const = 0;
|
||||
virtual const zeus::CColor& GetOutlineColor() const = 0;
|
||||
virtual float GetScanPercentInterval() const = 0;
|
||||
virtual float GetX54() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -1,98 +1,95 @@
|
|||
#pragma once
|
||||
|
||||
#include "ITweak.hpp"
|
||||
namespace DataSpec
|
||||
{
|
||||
struct ITweakTargeting : public ITweak
|
||||
{
|
||||
virtual atUint32 GetTargetRadiusMode() const=0;
|
||||
virtual float GetCurrLockOnExitDuration() const=0;
|
||||
virtual float GetCurrLockOnEnterDuration() const=0;
|
||||
virtual float GetCurrLockOnSwitchDuration() const=0;
|
||||
virtual float GetLockConfirmScale() const=0;
|
||||
virtual float GetNextLockOnEnterDuration() const=0;
|
||||
virtual float GetNextLockOnExitDuration() const=0;
|
||||
virtual float GetNextLockOnSwitchDuration() const=0;
|
||||
virtual float GetSeekerScale() const=0;
|
||||
virtual float GetSeekerAngleSpeed() const=0;
|
||||
virtual float GetXRayRetAngleSpeed() const=0;
|
||||
virtual float GetOrbitPointZOffset() const=0;
|
||||
virtual float GetOrbitPointInTime() const=0;
|
||||
virtual float GetOrbitPointOutTime() const=0;
|
||||
virtual const zeus::CColor& GetThermalReticuleColor() const=0;
|
||||
virtual float GetTargetFlowerScale() const=0;
|
||||
virtual const zeus::CColor& GetTargetFlowerColor() const=0;
|
||||
virtual float GetMissileBracketDuration() const=0;
|
||||
virtual float GetMissileBracketScaleStart() const=0;
|
||||
virtual float GetMissileBracketScaleEnd() const=0;
|
||||
virtual float GetMissileBracketScaleDuration() const=0;
|
||||
virtual const zeus::CColor& GetMissileBracketColor() const=0;
|
||||
virtual float GetChargeGaugeOvershootOffset() const=0;
|
||||
virtual float GetChargeGaugeOvershootDuration() const=0;
|
||||
virtual float GetOuterBeamSquaresScale() const=0;
|
||||
virtual const zeus::CColor& GetOuterBeamSquareColor() const=0;
|
||||
virtual float GetLockonDuration() const=0;
|
||||
virtual float GetInnerBeamScale() const=0;
|
||||
virtual const zeus::CColor& GetInnerBeamColorPower() const=0;
|
||||
virtual const zeus::CColor& GetInnerBeamColorIce() const=0;
|
||||
virtual const zeus::CColor& GetInnerBeamColorWave() const=0;
|
||||
virtual const zeus::CColor& GetInnerBeamColorPlasma() const=0;
|
||||
virtual const float* GetOuterBeamSquareAngles(int i) const=0;
|
||||
virtual float GetChargeGaugeAngle(int i) const=0;
|
||||
virtual float GetChargeGaugeScale() const=0;
|
||||
virtual const zeus::CColor& GetChargeGaugeNonFullColor() const=0;
|
||||
virtual atUint32 GetChargeTickCount() const=0;
|
||||
virtual float GetChargeTickAnglePitch() const=0;
|
||||
virtual float GetLockFireScale() const=0;
|
||||
virtual float GetLockFireDuration() const=0;
|
||||
virtual const zeus::CColor& GetLockFireColor() const=0;
|
||||
virtual float GetLockDaggerScaleStart() const=0;
|
||||
virtual float GetLockDaggerScaleEnd() const=0;
|
||||
virtual const zeus::CColor& GetLockDaggerColor() const=0;
|
||||
virtual float GetLockDaggerAngle0() const=0;
|
||||
virtual float GetLockDaggerAngle1() const=0;
|
||||
virtual float GetLockDaggerAngle2() const=0;
|
||||
virtual const zeus::CColor& GetLockConfirmColor() const=0;
|
||||
virtual const zeus::CColor& GetSeekerColor() const=0;
|
||||
virtual float GetLockConfirmClampMin() const=0;
|
||||
virtual float GetLockConfirmClampMax() const=0;
|
||||
virtual float GetTargetFlowerClampMin() const=0;
|
||||
virtual float GetTargetFlowerClampMax() const=0;
|
||||
virtual float GetSeekerClampMin() const=0;
|
||||
virtual float GetSeekerClampMax() const=0;
|
||||
virtual float GetMissileBracketClampMin() const=0;
|
||||
virtual float GetMissileBracketClampMax() const=0;
|
||||
virtual float GetInnerBeamClampMin() const=0;
|
||||
virtual float GetInnerBeamClampMax() const=0;
|
||||
virtual float GetChargeGaugeClampMin() const=0;
|
||||
virtual float GetChargeGaugeClampMax() const=0;
|
||||
virtual float GetLockFireClampMin() const=0;
|
||||
virtual float GetLockFireClampMax() const=0;
|
||||
virtual float GetLockDaggerClampMin() const=0;
|
||||
virtual float GetLockDaggerClampMax() const=0;
|
||||
virtual float GetGrappleSelectScale() const=0;
|
||||
virtual float GetGrappleScale() const=0;
|
||||
virtual float GetGrappleClampMin() const=0;
|
||||
virtual float GetGrappleClampMax() const=0;
|
||||
virtual const zeus::CColor& GetGrapplePointSelectColor() const=0;
|
||||
virtual const zeus::CColor& GetGrapplePointColor() const=0;
|
||||
virtual const zeus::CColor& GetLockedGrapplePointSelectColor() const=0;
|
||||
virtual float GetGrappleMinClampScale() const=0;
|
||||
virtual const zeus::CColor& GetChargeGaugePulseColorHigh() const=0;
|
||||
virtual float GetFullChargeFadeDuration() const=0;
|
||||
virtual const zeus::CColor& GetOrbitPointColor() const=0;
|
||||
virtual const zeus::CColor& GetCrosshairsColor() const=0;
|
||||
virtual float GetCrosshairsScaleDuration() const=0;
|
||||
virtual bool DrawOrbitPoint() const=0;
|
||||
virtual const zeus::CColor& GetChargeGaugePulseColorLow() const=0;
|
||||
virtual float GetChargeGaugePulsePeriod() const=0;
|
||||
virtual float GetReticuleClampMin() const=0;
|
||||
virtual float GetReticuleClampMax() const=0;
|
||||
virtual const zeus::CColor& GetXRayRetRingColor() const=0;
|
||||
virtual float GetReticuleScale() const=0;
|
||||
virtual float GetScanTargetClampMin() const=0;
|
||||
virtual float GetScanTargetClampMax() const=0;
|
||||
virtual float GetAngularLagSpeed() const=0;
|
||||
namespace DataSpec {
|
||||
struct ITweakTargeting : public ITweak {
|
||||
virtual atUint32 GetTargetRadiusMode() const = 0;
|
||||
virtual float GetCurrLockOnExitDuration() const = 0;
|
||||
virtual float GetCurrLockOnEnterDuration() const = 0;
|
||||
virtual float GetCurrLockOnSwitchDuration() const = 0;
|
||||
virtual float GetLockConfirmScale() const = 0;
|
||||
virtual float GetNextLockOnEnterDuration() const = 0;
|
||||
virtual float GetNextLockOnExitDuration() const = 0;
|
||||
virtual float GetNextLockOnSwitchDuration() const = 0;
|
||||
virtual float GetSeekerScale() const = 0;
|
||||
virtual float GetSeekerAngleSpeed() const = 0;
|
||||
virtual float GetXRayRetAngleSpeed() const = 0;
|
||||
virtual float GetOrbitPointZOffset() const = 0;
|
||||
virtual float GetOrbitPointInTime() const = 0;
|
||||
virtual float GetOrbitPointOutTime() const = 0;
|
||||
virtual const zeus::CColor& GetThermalReticuleColor() const = 0;
|
||||
virtual float GetTargetFlowerScale() const = 0;
|
||||
virtual const zeus::CColor& GetTargetFlowerColor() const = 0;
|
||||
virtual float GetMissileBracketDuration() const = 0;
|
||||
virtual float GetMissileBracketScaleStart() const = 0;
|
||||
virtual float GetMissileBracketScaleEnd() const = 0;
|
||||
virtual float GetMissileBracketScaleDuration() const = 0;
|
||||
virtual const zeus::CColor& GetMissileBracketColor() const = 0;
|
||||
virtual float GetChargeGaugeOvershootOffset() const = 0;
|
||||
virtual float GetChargeGaugeOvershootDuration() const = 0;
|
||||
virtual float GetOuterBeamSquaresScale() const = 0;
|
||||
virtual const zeus::CColor& GetOuterBeamSquareColor() const = 0;
|
||||
virtual float GetLockonDuration() const = 0;
|
||||
virtual float GetInnerBeamScale() const = 0;
|
||||
virtual const zeus::CColor& GetInnerBeamColorPower() const = 0;
|
||||
virtual const zeus::CColor& GetInnerBeamColorIce() const = 0;
|
||||
virtual const zeus::CColor& GetInnerBeamColorWave() const = 0;
|
||||
virtual const zeus::CColor& GetInnerBeamColorPlasma() const = 0;
|
||||
virtual const float* GetOuterBeamSquareAngles(int i) const = 0;
|
||||
virtual float GetChargeGaugeAngle(int i) const = 0;
|
||||
virtual float GetChargeGaugeScale() const = 0;
|
||||
virtual const zeus::CColor& GetChargeGaugeNonFullColor() const = 0;
|
||||
virtual atUint32 GetChargeTickCount() const = 0;
|
||||
virtual float GetChargeTickAnglePitch() const = 0;
|
||||
virtual float GetLockFireScale() const = 0;
|
||||
virtual float GetLockFireDuration() const = 0;
|
||||
virtual const zeus::CColor& GetLockFireColor() const = 0;
|
||||
virtual float GetLockDaggerScaleStart() const = 0;
|
||||
virtual float GetLockDaggerScaleEnd() const = 0;
|
||||
virtual const zeus::CColor& GetLockDaggerColor() const = 0;
|
||||
virtual float GetLockDaggerAngle0() const = 0;
|
||||
virtual float GetLockDaggerAngle1() const = 0;
|
||||
virtual float GetLockDaggerAngle2() const = 0;
|
||||
virtual const zeus::CColor& GetLockConfirmColor() const = 0;
|
||||
virtual const zeus::CColor& GetSeekerColor() const = 0;
|
||||
virtual float GetLockConfirmClampMin() const = 0;
|
||||
virtual float GetLockConfirmClampMax() const = 0;
|
||||
virtual float GetTargetFlowerClampMin() const = 0;
|
||||
virtual float GetTargetFlowerClampMax() const = 0;
|
||||
virtual float GetSeekerClampMin() const = 0;
|
||||
virtual float GetSeekerClampMax() const = 0;
|
||||
virtual float GetMissileBracketClampMin() const = 0;
|
||||
virtual float GetMissileBracketClampMax() const = 0;
|
||||
virtual float GetInnerBeamClampMin() const = 0;
|
||||
virtual float GetInnerBeamClampMax() const = 0;
|
||||
virtual float GetChargeGaugeClampMin() const = 0;
|
||||
virtual float GetChargeGaugeClampMax() const = 0;
|
||||
virtual float GetLockFireClampMin() const = 0;
|
||||
virtual float GetLockFireClampMax() const = 0;
|
||||
virtual float GetLockDaggerClampMin() const = 0;
|
||||
virtual float GetLockDaggerClampMax() const = 0;
|
||||
virtual float GetGrappleSelectScale() const = 0;
|
||||
virtual float GetGrappleScale() const = 0;
|
||||
virtual float GetGrappleClampMin() const = 0;
|
||||
virtual float GetGrappleClampMax() const = 0;
|
||||
virtual const zeus::CColor& GetGrapplePointSelectColor() const = 0;
|
||||
virtual const zeus::CColor& GetGrapplePointColor() const = 0;
|
||||
virtual const zeus::CColor& GetLockedGrapplePointSelectColor() const = 0;
|
||||
virtual float GetGrappleMinClampScale() const = 0;
|
||||
virtual const zeus::CColor& GetChargeGaugePulseColorHigh() const = 0;
|
||||
virtual float GetFullChargeFadeDuration() const = 0;
|
||||
virtual const zeus::CColor& GetOrbitPointColor() const = 0;
|
||||
virtual const zeus::CColor& GetCrosshairsColor() const = 0;
|
||||
virtual float GetCrosshairsScaleDuration() const = 0;
|
||||
virtual bool DrawOrbitPoint() const = 0;
|
||||
virtual const zeus::CColor& GetChargeGaugePulseColorLow() const = 0;
|
||||
virtual float GetChargeGaugePulsePeriod() const = 0;
|
||||
virtual float GetReticuleClampMin() const = 0;
|
||||
virtual float GetReticuleClampMax() const = 0;
|
||||
virtual const zeus::CColor& GetXRayRetRingColor() const = 0;
|
||||
virtual float GetReticuleScale() const = 0;
|
||||
virtual float GetScanTargetClampMin() const = 0;
|
||||
virtual float GetScanTargetClampMax() const = 0;
|
||||
virtual float GetAngularLagSpeed() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
|
@ -2,36 +2,31 @@
|
|||
|
||||
#include "../PAK.hpp"
|
||||
|
||||
namespace DataSpec
|
||||
{
|
||||
namespace DataSpec {
|
||||
|
||||
template <class T>
|
||||
bool WriteTweak(const T& tweak, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
tweak.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool ExtractTweak(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen())
|
||||
{
|
||||
T tweak;
|
||||
tweak.read(rs);
|
||||
athena::io::ToYAMLStream(tweak, writer);
|
||||
return true;
|
||||
}
|
||||
bool WriteTweak(const T& tweak, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath(), true, false);
|
||||
if (w.hasError())
|
||||
return false;
|
||||
tweak.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool ExtractTweak(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
if (writer.isOpen()) {
|
||||
T tweak;
|
||||
tweak.read(rs);
|
||||
athena::io::ToYAMLStream(tweak, writer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace DataSpec
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,54 +4,53 @@
|
|||
#include "PAK.hpp"
|
||||
#include "athena/FileWriter.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle
|
||||
{
|
||||
namespace DataSpec::DNAParticle {
|
||||
template <class IDType>
|
||||
struct WPSM : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
VectorElementFactory x0_IORN;
|
||||
VectorElementFactory x4_IVEC;
|
||||
VectorElementFactory x8_PSOV;
|
||||
ModVectorElementFactory xc_PSVM;
|
||||
BoolHelper x10_VMD2;
|
||||
IntElementFactory x14_PSLT;
|
||||
VectorElementFactory x18_PSCL;
|
||||
ColorElementFactory x1c_PCOL;
|
||||
VectorElementFactory x20_POFS;
|
||||
VectorElementFactory x24_OFST;
|
||||
BoolHelper x28_APSO;
|
||||
BoolHelper x29_HOMG;
|
||||
BoolHelper x2a_AP11;
|
||||
BoolHelper x2b_AP21;
|
||||
BoolHelper x2c_AS11;
|
||||
BoolHelper x2d_AS12;
|
||||
BoolHelper x2e_AS13;
|
||||
RealElementFactory x30_TRAT;
|
||||
ChildResourceFactory<IDType> x34_APSM;
|
||||
ChildResourceFactory<IDType> x44_APS2;
|
||||
ChildResourceFactory<IDType> x54_ASW1;
|
||||
ChildResourceFactory<IDType> x64_ASW2;
|
||||
ChildResourceFactory<IDType> x74_ASW3;
|
||||
ChildResourceFactory<IDType> x84_OHEF;
|
||||
ChildResourceFactory<IDType> x94_COLR;
|
||||
BoolHelper xa4_EWTR;
|
||||
BoolHelper xa5_LWTR;
|
||||
BoolHelper xa6_SWTR;
|
||||
uint32_t xa8_PJFX = ~0;
|
||||
RealElementFactory xac_RNGE;
|
||||
RealElementFactory xb0_FOFF;
|
||||
BoolHelper xunk_FC60;
|
||||
BoolHelper xunk_SPS1;
|
||||
BoolHelper xunk_SPS2;
|
||||
struct WPSM : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
VectorElementFactory x0_IORN;
|
||||
VectorElementFactory x4_IVEC;
|
||||
VectorElementFactory x8_PSOV;
|
||||
ModVectorElementFactory xc_PSVM;
|
||||
BoolHelper x10_VMD2;
|
||||
IntElementFactory x14_PSLT;
|
||||
VectorElementFactory x18_PSCL;
|
||||
ColorElementFactory x1c_PCOL;
|
||||
VectorElementFactory x20_POFS;
|
||||
VectorElementFactory x24_OFST;
|
||||
BoolHelper x28_APSO;
|
||||
BoolHelper x29_HOMG;
|
||||
BoolHelper x2a_AP11;
|
||||
BoolHelper x2b_AP21;
|
||||
BoolHelper x2c_AS11;
|
||||
BoolHelper x2d_AS12;
|
||||
BoolHelper x2e_AS13;
|
||||
RealElementFactory x30_TRAT;
|
||||
ChildResourceFactory<IDType> x34_APSM;
|
||||
ChildResourceFactory<IDType> x44_APS2;
|
||||
ChildResourceFactory<IDType> x54_ASW1;
|
||||
ChildResourceFactory<IDType> x64_ASW2;
|
||||
ChildResourceFactory<IDType> x74_ASW3;
|
||||
ChildResourceFactory<IDType> x84_OHEF;
|
||||
ChildResourceFactory<IDType> x94_COLR;
|
||||
BoolHelper xa4_EWTR;
|
||||
BoolHelper xa5_LWTR;
|
||||
BoolHelper xa6_SWTR;
|
||||
uint32_t xa8_PJFX = ~0;
|
||||
RealElementFactory xac_RNGE;
|
||||
RealElementFactory xb0_FOFF;
|
||||
BoolHelper xunk_FC60;
|
||||
BoolHelper xunk_SPS1;
|
||||
BoolHelper xunk_SPS2;
|
||||
|
||||
WPSM()
|
||||
{
|
||||
xa4_EWTR = true; xa5_LWTR = true; xa6_SWTR = true;
|
||||
}
|
||||
WPSM() {
|
||||
xa4_EWTR = true;
|
||||
xa5_LWTR = true;
|
||||
xa6_SWTR = true;
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
|
@ -60,5 +59,4 @@ bool ExtractWPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
|||
template <class IDType>
|
||||
bool WriteWPSM(const WPSM<IDType>& wpsm, const hecl::ProjectPath& outPath);
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
|
@ -1,127 +1,104 @@
|
|||
#include "AFSM.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::Read>(typename Read::StreamT& r)
|
||||
{
|
||||
triggerCount = r.readUint32Big();
|
||||
int i = 0;
|
||||
r.enumerate<Trigger>(triggers, triggerCount,
|
||||
[&](athena::io::IStreamReader& in, Trigger& tr){
|
||||
tr.first = i == 0;
|
||||
tr.read(in);
|
||||
i++;
|
||||
});
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::Read>(typename Read::StreamT& r) {
|
||||
triggerCount = r.readUint32Big();
|
||||
int i = 0;
|
||||
r.enumerate<Trigger>(triggers, triggerCount, [&](athena::io::IStreamReader& in, Trigger& tr) {
|
||||
tr.first = i == 0;
|
||||
tr.read(in);
|
||||
i++;
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::Write>(typename Write::StreamT& w)
|
||||
{
|
||||
w.writeInt32Big(triggerCount);
|
||||
w.enumerate(triggers);
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::Write>(typename Write::StreamT& w) {
|
||||
w.writeInt32Big(triggerCount);
|
||||
w.enumerate(triggers);
|
||||
}
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& r)
|
||||
{
|
||||
int i = 0;
|
||||
/* triggers */
|
||||
triggerCount = r.enumerate<Trigger>("triggers", triggers,
|
||||
[&](athena::io::YAMLDocReader& in, Trigger& tr){
|
||||
tr.first = i == 0;
|
||||
tr.read(in);
|
||||
i++;
|
||||
});
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& r) {
|
||||
int i = 0;
|
||||
/* triggers */
|
||||
triggerCount = r.enumerate<Trigger>("triggers", triggers, [&](athena::io::YAMLDocReader& in, Trigger& tr) {
|
||||
tr.first = i == 0;
|
||||
tr.read(in);
|
||||
i++;
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& w)
|
||||
{
|
||||
/* triggers */
|
||||
w.enumerate("triggers", triggers);
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& w) {
|
||||
/* triggers */
|
||||
w.enumerate("triggers", triggers);
|
||||
}
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
|
||||
{
|
||||
s += 4;
|
||||
for (const Trigger& trig : triggers)
|
||||
trig.binarySize(s);
|
||||
void AFSM::State::Transition::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) {
|
||||
s += 4;
|
||||
for (const Trigger& trig : triggers)
|
||||
trig.binarySize(s);
|
||||
}
|
||||
|
||||
const char* AFSM::State::Transition::DNAType()
|
||||
{
|
||||
return "urde::DNAMP1::AFSM::Transition";
|
||||
const char* AFSM::State::Transition::DNAType() { return "urde::DNAMP1::AFSM::Transition"; }
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::Read>(athena::io::IStreamReader& __dna_reader) {
|
||||
/* name */
|
||||
name = __dna_reader.readString(-1);
|
||||
/* parameter */
|
||||
parameter = __dna_reader.readFloatBig();
|
||||
if (first) {
|
||||
/* targetState */
|
||||
targetState = __dna_reader.readUint32Big();
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::Read>(athena::io::IStreamReader& __dna_reader)
|
||||
{
|
||||
/* name */
|
||||
name = __dna_reader.readString(-1);
|
||||
/* parameter */
|
||||
parameter = __dna_reader.readFloatBig();
|
||||
if (first)
|
||||
{
|
||||
/* targetState */
|
||||
targetState = __dna_reader.readUint32Big();
|
||||
}
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& __dna_writer) {
|
||||
/* name */
|
||||
__dna_writer.writeString(name, -1);
|
||||
/* parameter */
|
||||
__dna_writer.writeFloatBig(parameter);
|
||||
if (first) {
|
||||
/* targetState */
|
||||
__dna_writer.writeUint32Big(targetState);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& __dna_writer)
|
||||
{
|
||||
/* name */
|
||||
__dna_writer.writeString(name, -1);
|
||||
/* parameter */
|
||||
__dna_writer.writeFloatBig(parameter);
|
||||
if (first)
|
||||
{
|
||||
/* targetState */
|
||||
__dna_writer.writeUint32Big(targetState);
|
||||
}
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& __dna_docin) {
|
||||
/* name */
|
||||
name = __dna_docin.readString("name");
|
||||
/* parameter */
|
||||
parameter = __dna_docin.readFloat("parameter");
|
||||
if (first) {
|
||||
/* targetState */
|
||||
targetState = __dna_docin.readUint32("targetState");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::ReadYaml>(athena::io::YAMLDocReader& __dna_docin)
|
||||
{
|
||||
/* name */
|
||||
name = __dna_docin.readString("name");
|
||||
/* parameter */
|
||||
parameter = __dna_docin.readFloat("parameter");
|
||||
if (first)
|
||||
{
|
||||
/* targetState */
|
||||
targetState = __dna_docin.readUint32("targetState");
|
||||
}
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& __dna_docout) {
|
||||
/* name */
|
||||
__dna_docout.writeString("name", name);
|
||||
/* parameter */
|
||||
__dna_docout.writeFloat("parameter", parameter);
|
||||
if (first) {
|
||||
/* targetState */
|
||||
__dna_docout.writeUint32("targetState", targetState);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::WriteYaml>(athena::io::YAMLDocWriter& __dna_docout)
|
||||
{
|
||||
/* name */
|
||||
__dna_docout.writeString("name", name);
|
||||
/* parameter */
|
||||
__dna_docout.writeFloat("parameter", parameter);
|
||||
if (first)
|
||||
{
|
||||
/* targetState */
|
||||
__dna_docout.writeUint32("targetState", targetState);
|
||||
}
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::BinarySize>(size_t& __isz) {
|
||||
__isz += name.size() + 1;
|
||||
__isz += (first ? 8 : 4);
|
||||
}
|
||||
|
||||
template <>
|
||||
void AFSM::State::Transition::Trigger::Enumerate<BigDNA::BinarySize>(size_t& __isz)
|
||||
{
|
||||
__isz += name.size() + 1;
|
||||
__isz += (first ? 8 : 4);
|
||||
}
|
||||
const char* AFSM::State::Transition::Trigger::DNAType() { return "urde::DNAMP1::AFSM::State::Transition::Trigger"; }
|
||||
|
||||
const char* AFSM::State::Transition::Trigger::DNAType()
|
||||
{
|
||||
return "urde::DNAMP1::AFSM::State::Transition::Trigger";
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -4,56 +4,48 @@
|
|||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
struct AFSM : public BigDNA
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
struct AFSM : public BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> stateCount;
|
||||
Vector<String<-1>, AT_DNA_COUNT(stateCount)> stateNames;
|
||||
Value<atUint32> triggerCount;
|
||||
|
||||
struct State : public BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> stateCount;
|
||||
Vector<String<-1>, AT_DNA_COUNT(stateCount)> stateNames;
|
||||
Value<atUint32> triggerCount;
|
||||
Value<atUint32> transitionCount;
|
||||
struct Transition : public BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
Value<atUint32> triggerCount;
|
||||
|
||||
struct State : public BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> transitionCount;
|
||||
struct Transition : public BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
Value<atUint32> triggerCount;
|
||||
|
||||
struct Trigger : public BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
bool first = false;
|
||||
String<-1> name;
|
||||
Value<float> parameter;
|
||||
Value<atUint32> targetState;
|
||||
};
|
||||
Vector<Trigger, AT_DNA_COUNT(triggerCount)> triggers;
|
||||
};
|
||||
Vector<Transition, AT_DNA_COUNT(transitionCount)> transitions;
|
||||
struct Trigger : public BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
bool first = false;
|
||||
String<-1> name;
|
||||
Value<float> parameter;
|
||||
Value<atUint32> targetState;
|
||||
};
|
||||
Vector<Trigger, AT_DNA_COUNT(triggerCount)> triggers;
|
||||
};
|
||||
Vector<State, AT_DNA_COUNT(stateCount)> states;
|
||||
Vector<Transition, AT_DNA_COUNT(transitionCount)> transitions;
|
||||
};
|
||||
Vector<State, AT_DNA_COUNT(stateCount)> states;
|
||||
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
AFSM afsm;
|
||||
afsm.read(rs);
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
athena::io::ToYAMLStream(afsm, writer);
|
||||
return true;
|
||||
}
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
AFSM afsm;
|
||||
afsm.read(rs);
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
athena::io::ToYAMLStream(afsm, writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
AFSM afsm;
|
||||
athena::io::FileReader reader(inPath.getAbsolutePath());
|
||||
athena::io::FromYAMLStream(afsm, reader);
|
||||
athena::io::FileWriter ws(outPath.getAbsolutePath());
|
||||
afsm.write(ws);
|
||||
return true;
|
||||
}
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||
AFSM afsm;
|
||||
athena::io::FileReader reader(inPath.getAbsolutePath());
|
||||
athena::io::FromYAMLStream(afsm, reader);
|
||||
athena::io::FileWriter ws(outPath.getAbsolutePath());
|
||||
afsm.write(ws);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -74,176 +74,170 @@ extern "C" const uint8_t Zoomer_H[];
|
|||
extern "C" const uint8_t lumigek_H[];
|
||||
extern "C" const uint8_t test_H[];
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
static const std::pair<std::string_view, const uint8_t*> Headers[] =
|
||||
{
|
||||
{"Atomic"sv, Atomic_H},
|
||||
{"BetaBeetle"sv, BetaBeetle_H},
|
||||
{"Bird"sv, Bird_H},
|
||||
{"BloodFlower"sv, BloodFlower_H},
|
||||
{"Burrower"sv, Burrower_H},
|
||||
{"ChozoGhost"sv, ChozoGhost_H},
|
||||
{"ChubbWeed"sv, ChubbWeed_H},
|
||||
{"CineBoots"sv, CineBoots_H},
|
||||
{"CineGeneral"sv, CineGeneral_H},
|
||||
{"CineGun"sv, CineGun_H},
|
||||
{"CineMorphball"sv, CineMorphball_H},
|
||||
{"CineSuit"sv, CineSuit_H},
|
||||
{"CineVisor"sv, CineVisor_H},
|
||||
{"Crater"sv, Crater_H},
|
||||
{"Crystallite"sv, Crystallite_H},
|
||||
{"Drones"sv, Drones_H},
|
||||
{"EliteSpacePirate"sv, EliteSpacePirate_H},
|
||||
{"FireFlea"sv, FireFlea_H},
|
||||
{"Flaaghra"sv, Flaaghra_H},
|
||||
{"FlickerBat"sv, FlickerBat_H},
|
||||
{"FlyingPirate"sv, FlyingPirate_H},
|
||||
{"FrontEnd"sv, FrontEnd_H},
|
||||
{"GagantuanBeatle"sv, GagantuanBeatle_H},
|
||||
{"Gnats"sv, Gnats_H},
|
||||
{"Gryzbee"sv, Gryzbee_H},
|
||||
{"IceCrack"sv, IceCrack_H},
|
||||
{"IceWorld"sv, IceWorld_H},
|
||||
{"InjuredPirates"sv, InjuredPirates_H},
|
||||
{"IntroBoss"sv, IntroBoss_H},
|
||||
{"IntroWorld"sv, IntroWorld_H},
|
||||
{"JellyZap"sv, JellyZap_H},
|
||||
{"LavaWorld"sv, LavaWorld_H},
|
||||
{"Magdolite"sv, Magdolite_H},
|
||||
{"Metaree"sv, Metaree_H},
|
||||
{"MetroidPrime"sv, MetroidPrime_H},
|
||||
{"Metroid"sv, Metroid_H},
|
||||
{"MinesWorld"sv, MinesWorld_H},
|
||||
{"MiscSamus"sv, MiscSamus_H},
|
||||
{"Misc"sv, Misc_H},
|
||||
{"OmegaPirate"sv, OmegaPirate_H},
|
||||
{"OverWorld"sv, OverWorld_H},
|
||||
{"Parasite"sv, Parasite_H},
|
||||
{"PhazonGun"sv, PhazonGun_H},
|
||||
{"Phazon"sv, Phazon_H},
|
||||
{"PuddleSpore"sv, PuddleSpore_H},
|
||||
{"PuddleToad"sv, PuddleToad_H},
|
||||
{"Puffer"sv, Puffer_H},
|
||||
{"ReactorDoor"sv, ReactorDoor_H},
|
||||
{"Ridley"sv, Ridley_H},
|
||||
{"Ripper"sv, Ripper_H},
|
||||
{"RuinsWorld"sv, RuinsWorld_H},
|
||||
{"SamusShip"sv, SamusShip_H},
|
||||
{"Scarab"sv, Scarab_H},
|
||||
{"Seedling"sv, Seedling_H},
|
||||
{"SheeGoth"sv, SheeGoth_H},
|
||||
{"SnakeWeed"sv, SnakeWeed_H},
|
||||
{"Sova"sv, Sova_H},
|
||||
{"SpacePirate"sv, SpacePirate_H},
|
||||
{"SpankWeed"sv, SpankWeed_H},
|
||||
{"Thardus"sv, Thardus_H},
|
||||
{"TheEnd"sv, TheEnd_H},
|
||||
{"Torobyte"sv, Torobyte_H},
|
||||
{"Triclops"sv, Triclops_H},
|
||||
{"Turret"sv, Turret_H},
|
||||
{"UI"sv, UI_H},
|
||||
{"WarWasp"sv, WarWasp_H},
|
||||
{"Weapons"sv, Weapons_H},
|
||||
{"ZZZ"sv, ZZZ_H},
|
||||
{"Zoomer"sv, Zoomer_H},
|
||||
{"lumigek"sv, lumigek_H},
|
||||
{"test"sv, test_H}
|
||||
};
|
||||
static const std::pair<std::string_view, const uint8_t*> Headers[] = {{"Atomic"sv, Atomic_H},
|
||||
{"BetaBeetle"sv, BetaBeetle_H},
|
||||
{"Bird"sv, Bird_H},
|
||||
{"BloodFlower"sv, BloodFlower_H},
|
||||
{"Burrower"sv, Burrower_H},
|
||||
{"ChozoGhost"sv, ChozoGhost_H},
|
||||
{"ChubbWeed"sv, ChubbWeed_H},
|
||||
{"CineBoots"sv, CineBoots_H},
|
||||
{"CineGeneral"sv, CineGeneral_H},
|
||||
{"CineGun"sv, CineGun_H},
|
||||
{"CineMorphball"sv, CineMorphball_H},
|
||||
{"CineSuit"sv, CineSuit_H},
|
||||
{"CineVisor"sv, CineVisor_H},
|
||||
{"Crater"sv, Crater_H},
|
||||
{"Crystallite"sv, Crystallite_H},
|
||||
{"Drones"sv, Drones_H},
|
||||
{"EliteSpacePirate"sv, EliteSpacePirate_H},
|
||||
{"FireFlea"sv, FireFlea_H},
|
||||
{"Flaaghra"sv, Flaaghra_H},
|
||||
{"FlickerBat"sv, FlickerBat_H},
|
||||
{"FlyingPirate"sv, FlyingPirate_H},
|
||||
{"FrontEnd"sv, FrontEnd_H},
|
||||
{"GagantuanBeatle"sv, GagantuanBeatle_H},
|
||||
{"Gnats"sv, Gnats_H},
|
||||
{"Gryzbee"sv, Gryzbee_H},
|
||||
{"IceCrack"sv, IceCrack_H},
|
||||
{"IceWorld"sv, IceWorld_H},
|
||||
{"InjuredPirates"sv, InjuredPirates_H},
|
||||
{"IntroBoss"sv, IntroBoss_H},
|
||||
{"IntroWorld"sv, IntroWorld_H},
|
||||
{"JellyZap"sv, JellyZap_H},
|
||||
{"LavaWorld"sv, LavaWorld_H},
|
||||
{"Magdolite"sv, Magdolite_H},
|
||||
{"Metaree"sv, Metaree_H},
|
||||
{"MetroidPrime"sv, MetroidPrime_H},
|
||||
{"Metroid"sv, Metroid_H},
|
||||
{"MinesWorld"sv, MinesWorld_H},
|
||||
{"MiscSamus"sv, MiscSamus_H},
|
||||
{"Misc"sv, Misc_H},
|
||||
{"OmegaPirate"sv, OmegaPirate_H},
|
||||
{"OverWorld"sv, OverWorld_H},
|
||||
{"Parasite"sv, Parasite_H},
|
||||
{"PhazonGun"sv, PhazonGun_H},
|
||||
{"Phazon"sv, Phazon_H},
|
||||
{"PuddleSpore"sv, PuddleSpore_H},
|
||||
{"PuddleToad"sv, PuddleToad_H},
|
||||
{"Puffer"sv, Puffer_H},
|
||||
{"ReactorDoor"sv, ReactorDoor_H},
|
||||
{"Ridley"sv, Ridley_H},
|
||||
{"Ripper"sv, Ripper_H},
|
||||
{"RuinsWorld"sv, RuinsWorld_H},
|
||||
{"SamusShip"sv, SamusShip_H},
|
||||
{"Scarab"sv, Scarab_H},
|
||||
{"Seedling"sv, Seedling_H},
|
||||
{"SheeGoth"sv, SheeGoth_H},
|
||||
{"SnakeWeed"sv, SnakeWeed_H},
|
||||
{"Sova"sv, Sova_H},
|
||||
{"SpacePirate"sv, SpacePirate_H},
|
||||
{"SpankWeed"sv, SpankWeed_H},
|
||||
{"Thardus"sv, Thardus_H},
|
||||
{"TheEnd"sv, TheEnd_H},
|
||||
{"Torobyte"sv, Torobyte_H},
|
||||
{"Triclops"sv, Triclops_H},
|
||||
{"Turret"sv, Turret_H},
|
||||
{"UI"sv, UI_H},
|
||||
{"WarWasp"sv, WarWasp_H},
|
||||
{"Weapons"sv, Weapons_H},
|
||||
{"ZZZ"sv, ZZZ_H},
|
||||
{"Zoomer"sv, Zoomer_H},
|
||||
{"lumigek"sv, lumigek_H},
|
||||
{"test"sv, test_H}};
|
||||
|
||||
bool AGSC::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& dir)
|
||||
{
|
||||
dir.makeDirChain(true);
|
||||
bool AGSC::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& dir) {
|
||||
dir.makeDirChain(true);
|
||||
|
||||
Header head;
|
||||
head.read(rs);
|
||||
Header head;
|
||||
head.read(rs);
|
||||
|
||||
uint32_t poolLen = rs.readUint32Big();
|
||||
auto pool = rs.readUBytes(poolLen);
|
||||
uint32_t poolLen = rs.readUint32Big();
|
||||
auto pool = rs.readUBytes(poolLen);
|
||||
|
||||
uint32_t projLen = rs.readUint32Big();
|
||||
auto proj = rs.readUBytes(projLen);
|
||||
uint32_t projLen = rs.readUint32Big();
|
||||
auto proj = rs.readUBytes(projLen);
|
||||
|
||||
uint32_t sampLen = rs.readUint32Big();
|
||||
auto samp = rs.readUBytes(sampLen);
|
||||
uint32_t sampLen = rs.readUint32Big();
|
||||
auto samp = rs.readUBytes(sampLen);
|
||||
|
||||
uint32_t sdirLen = rs.readUint32Big();
|
||||
auto sdir = rs.readUBytes(sdirLen);
|
||||
uint32_t sdirLen = rs.readUint32Big();
|
||||
auto sdir = rs.readUBytes(sdirLen);
|
||||
|
||||
amuse::AudioGroupData data(proj.get(), projLen, pool.get(), poolLen,
|
||||
sdir.get(), sdirLen, samp.get(), sampLen, amuse::GCNDataTag{});
|
||||
amuse::AudioGroupData data(proj.get(), projLen, pool.get(), poolLen, sdir.get(), sdirLen, samp.get(), sampLen,
|
||||
amuse::GCNDataTag{});
|
||||
|
||||
/* Load into amuse representation */
|
||||
amuse::ProjectDatabase projDb;
|
||||
projDb.setIdDatabases();
|
||||
amuse::AudioGroupDatabase group(data);
|
||||
group.setGroupPath(dir.getAbsolutePath());
|
||||
/* Load into amuse representation */
|
||||
amuse::ProjectDatabase projDb;
|
||||
projDb.setIdDatabases();
|
||||
amuse::AudioGroupDatabase group(data);
|
||||
group.setGroupPath(dir.getAbsolutePath());
|
||||
|
||||
/* Extract samples */
|
||||
group.getSdir().extractAllCompressed(dir.getAbsolutePath(), data.getSamp());
|
||||
/* Extract samples */
|
||||
group.getSdir().extractAllCompressed(dir.getAbsolutePath(), data.getSamp());
|
||||
|
||||
/* Import C headers */
|
||||
auto lastComp = dir.getLastComponentUTF8();
|
||||
auto search = std::lower_bound(std::cbegin(Headers), std::cend(Headers), lastComp,
|
||||
[](const auto& a, const auto& b) { return a.first < b; });
|
||||
if (search != std::cend(Headers) && search->first == lastComp)
|
||||
group.importCHeader((char*)search->second);
|
||||
/* Import C headers */
|
||||
auto lastComp = dir.getLastComponentUTF8();
|
||||
auto search = std::lower_bound(std::cbegin(Headers), std::cend(Headers), lastComp,
|
||||
[](const auto& a, const auto& b) { return a.first < b; });
|
||||
if (search != std::cend(Headers) && search->first == lastComp)
|
||||
group.importCHeader((char*)search->second);
|
||||
|
||||
/* Write out project/pool */
|
||||
{
|
||||
auto projd = group.getProj().toYAML();
|
||||
athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!project.yaml")).getAbsolutePath());
|
||||
if (fo.hasError())
|
||||
return false;
|
||||
fo.writeUBytes(projd.data(), projd.size());
|
||||
}
|
||||
/* Write out project/pool */
|
||||
{
|
||||
auto projd = group.getProj().toYAML();
|
||||
athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!project.yaml")).getAbsolutePath());
|
||||
if (fo.hasError())
|
||||
return false;
|
||||
fo.writeUBytes(projd.data(), projd.size());
|
||||
}
|
||||
|
||||
{
|
||||
auto poold = group.getPool().toYAML();
|
||||
athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!pool.yaml")).getAbsolutePath());
|
||||
if (fo.hasError())
|
||||
return false;
|
||||
fo.writeUBytes(poold.data(), poold.size());
|
||||
}
|
||||
{
|
||||
auto poold = group.getPool().toYAML();
|
||||
athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!pool.yaml")).getAbsolutePath());
|
||||
if (fo.hasError())
|
||||
return false;
|
||||
fo.writeUBytes(poold.data(), poold.size());
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AGSC::Cook(const hecl::ProjectPath& dir, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
bool AGSC::Cook(const hecl::ProjectPath& dir, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
|
||||
Header head;
|
||||
head.audioDir = "Audio/"sv;
|
||||
head.groupName = dir.getLastComponentUTF8();
|
||||
head.write(w);
|
||||
Header head;
|
||||
head.audioDir = "Audio/"sv;
|
||||
head.groupName = dir.getLastComponentUTF8();
|
||||
head.write(w);
|
||||
|
||||
amuse::ProjectDatabase projDb;
|
||||
projDb.setIdDatabases();
|
||||
amuse::AudioGroupDatabase group(dir.getAbsolutePath());
|
||||
amuse::ProjectDatabase projDb;
|
||||
projDb.setIdDatabases();
|
||||
amuse::AudioGroupDatabase group(dir.getAbsolutePath());
|
||||
|
||||
auto proj = group.getProj().toGCNData(group.getPool(), group.getSdir());
|
||||
auto pool = group.getPool().toData<athena::Big>();
|
||||
auto sdirSamp = group.getSdir().toGCNData(group);
|
||||
auto proj = group.getProj().toGCNData(group.getPool(), group.getSdir());
|
||||
auto pool = group.getPool().toData<athena::Big>();
|
||||
auto sdirSamp = group.getSdir().toGCNData(group);
|
||||
|
||||
w.writeUint32Big(pool.size());
|
||||
w.writeUBytes(pool.data(), pool.size());
|
||||
w.writeUint32Big(pool.size());
|
||||
w.writeUBytes(pool.data(), pool.size());
|
||||
|
||||
w.writeUint32Big(proj.size());
|
||||
w.writeUBytes(proj.data(), proj.size());
|
||||
w.writeUint32Big(proj.size());
|
||||
w.writeUBytes(proj.data(), proj.size());
|
||||
|
||||
w.writeUint32Big(sdirSamp.second.size());
|
||||
w.writeUBytes(sdirSamp.second.data(), sdirSamp.second.size());
|
||||
w.writeUint32Big(sdirSamp.second.size());
|
||||
w.writeUBytes(sdirSamp.second.data(), sdirSamp.second.size());
|
||||
|
||||
w.writeUint32Big(sdirSamp.first.size());
|
||||
w.writeUBytes(sdirSamp.first.data(), sdirSamp.first.size());
|
||||
w.writeUint32Big(sdirSamp.first.size());
|
||||
w.writeUBytes(sdirSamp.first.data(), sdirSamp.first.size());
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -3,21 +3,17 @@
|
|||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
class AGSC
|
||||
{
|
||||
class AGSC {
|
||||
public:
|
||||
struct Header : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
String<-1> audioDir;
|
||||
String<-1> groupName;
|
||||
};
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
struct Header : BigDNA {
|
||||
AT_DECL_DNA
|
||||
String<-1> audioDir;
|
||||
String<-1> groupName;
|
||||
};
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,510 +10,419 @@
|
|||
#include "EVNT.hpp"
|
||||
#include "athena/FileReader.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
struct ANCS : BigDNA
|
||||
{
|
||||
using CINFType = CINF;
|
||||
using CSKRType = CSKR;
|
||||
using ANIMType = ANIM;
|
||||
struct ANCS : BigDNA {
|
||||
using CINFType = CINF;
|
||||
using CSKRType = CSKR;
|
||||
using ANIMType = ANIM;
|
||||
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint16> version;
|
||||
|
||||
struct CharacterSet : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint16> version;
|
||||
Value<atUint32> characterCount;
|
||||
struct CharacterInfo : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
|
||||
struct CharacterSet : BigDNA
|
||||
{
|
||||
atUint32 idx;
|
||||
std::string name;
|
||||
UniqueID32 cmdl;
|
||||
UniqueID32 cskr;
|
||||
UniqueID32 cinf;
|
||||
|
||||
struct Animation : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint16> version;
|
||||
Value<atUint32> characterCount;
|
||||
struct CharacterInfo : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
Value<atUint32> animIdx;
|
||||
String<-1> strA;
|
||||
String<-1> strB;
|
||||
};
|
||||
std::vector<Animation> animations;
|
||||
|
||||
atUint32 idx;
|
||||
std::string name;
|
||||
UniqueID32 cmdl;
|
||||
UniqueID32 cskr;
|
||||
UniqueID32 cinf;
|
||||
|
||||
struct Animation : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> animIdx;
|
||||
String<-1> strA;
|
||||
String<-1> strB;
|
||||
};
|
||||
std::vector<Animation> animations;
|
||||
|
||||
struct PASDatabase : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> animStateCount;
|
||||
Value<atUint32> defaultState;
|
||||
struct AnimState : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
atUint32 id;
|
||||
|
||||
struct ParmInfo : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
enum class DataType
|
||||
{
|
||||
Int32 = 0,
|
||||
UInt32 = 1,
|
||||
Float = 2,
|
||||
Bool = 3,
|
||||
Enum = 4
|
||||
};
|
||||
union Parm
|
||||
{
|
||||
atInt32 int32;
|
||||
atUint32 uint32;
|
||||
float float32;
|
||||
bool bool1;
|
||||
Parm() : int32(0) {}
|
||||
Parm(atInt32 val) : int32(val) {}
|
||||
Parm(atUint32 val) : uint32(val) {}
|
||||
Parm(float val) : float32(val) {}
|
||||
Parm(bool val) : bool1(val) {}
|
||||
};
|
||||
|
||||
atUint32 parmType;
|
||||
atUint32 weightFunction;
|
||||
float weight;
|
||||
Parm range[2];
|
||||
};
|
||||
std::vector<ParmInfo> parmInfos;
|
||||
|
||||
struct AnimInfo
|
||||
{
|
||||
atUint32 id;
|
||||
std::vector<ParmInfo::Parm> parmVals;
|
||||
};
|
||||
std::vector<AnimInfo> animInfos;
|
||||
};
|
||||
Vector<AnimState, AT_DNA_COUNT(animStateCount)> animStates;
|
||||
} pasDatabase;
|
||||
|
||||
struct ParticleResData
|
||||
{
|
||||
std::vector<UniqueID32> part;
|
||||
std::vector<UniqueID32> swhc;
|
||||
std::vector<UniqueID32> unk;
|
||||
std::vector<UniqueID32> elsc;
|
||||
} partResData;
|
||||
|
||||
atUint32 unk1 = 0;
|
||||
|
||||
struct ActionAABB : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atVec3f> aabb[2];
|
||||
};
|
||||
std::vector<ActionAABB> animAABBs;
|
||||
|
||||
struct Effect : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> compCount;
|
||||
struct EffectComponent : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
DNAFourCC type;
|
||||
UniqueID32 id;
|
||||
String<-1> locator;
|
||||
Value<float> scale;
|
||||
Value<atUint32> parentMode;
|
||||
Value<atUint32> flags;
|
||||
};
|
||||
Vector<EffectComponent, AT_DNA_COUNT(compCount)> comps;
|
||||
};
|
||||
std::vector<Effect> effects;
|
||||
|
||||
UniqueID32Zero cmdlIce;
|
||||
UniqueID32Zero cskrIce;
|
||||
|
||||
std::vector<atUint32> animIdxs;
|
||||
};
|
||||
Vector<CharacterInfo, AT_DNA_COUNT(characterCount)> characters;
|
||||
} characterSet;
|
||||
|
||||
struct AnimationSet : BigDNA
|
||||
{
|
||||
struct PASDatabase : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> animStateCount;
|
||||
Value<atUint32> defaultState;
|
||||
struct AnimState : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
atUint32 id;
|
||||
|
||||
struct MetaAnimPrimitive;
|
||||
struct IMetaAnim : BigDNAVYaml
|
||||
{
|
||||
struct ParmInfo : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
enum class Type
|
||||
{
|
||||
Primitive = 0,
|
||||
Blend = 1,
|
||||
PhaseBlend = 2,
|
||||
Random = 3,
|
||||
Sequence = 4
|
||||
} m_type;
|
||||
const char* m_typeStr;
|
||||
IMetaAnim(Type type, const char* typeStr)
|
||||
: m_type(type), m_typeStr(typeStr) {}
|
||||
virtual void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)=0;
|
||||
virtual bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func)=0;
|
||||
};
|
||||
struct MetaAnimFactory : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
std::unique_ptr<IMetaAnim> m_anim;
|
||||
};
|
||||
struct MetaAnimPrimitive : IMetaAnim
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
MetaAnimPrimitive() : IMetaAnim(Type::Primitive, "Primitive") {}
|
||||
|
||||
UniqueID32 animId;
|
||||
Value<atUint32> animIdx;
|
||||
String<-1> animName;
|
||||
Value<float> unk1;
|
||||
Value<atUint32> unk2;
|
||||
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out);
|
||||
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func)
|
||||
{
|
||||
return func(*this);
|
||||
}
|
||||
};
|
||||
struct MetaAnimBlend : IMetaAnim
|
||||
{
|
||||
MetaAnimBlend()
|
||||
: IMetaAnim(Type::Blend, "Blend") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
MetaAnimFactory animA;
|
||||
MetaAnimFactory animB;
|
||||
Value<float> unkFloat;
|
||||
Value<atUint8> unk;
|
||||
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
|
||||
{
|
||||
animA.m_anim->gatherPrimitives(pakRouter, out);
|
||||
animB.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func)
|
||||
{
|
||||
if (!animA.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
if (!animB.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct MetaAnimPhaseBlend : IMetaAnim
|
||||
{
|
||||
MetaAnimPhaseBlend()
|
||||
: IMetaAnim(Type::PhaseBlend, "PhaseBlend") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
MetaAnimFactory animA;
|
||||
MetaAnimFactory animB;
|
||||
Value<float> unkFloat;
|
||||
Value<atUint8> unk;
|
||||
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
|
||||
{
|
||||
animA.m_anim->gatherPrimitives(pakRouter, out);
|
||||
animB.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func)
|
||||
{
|
||||
if (!animA.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
if (!animB.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct MetaAnimRandom : IMetaAnim
|
||||
{
|
||||
MetaAnimRandom() : IMetaAnim(Type::Random, "Random") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> animCount;
|
||||
struct Child : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
MetaAnimFactory anim;
|
||||
Value<atUint32> probability;
|
||||
enum class DataType { Int32 = 0, UInt32 = 1, Float = 2, Bool = 3, Enum = 4 };
|
||||
union Parm {
|
||||
atInt32 int32;
|
||||
atUint32 uint32;
|
||||
float float32;
|
||||
bool bool1;
|
||||
Parm() : int32(0) {}
|
||||
Parm(atInt32 val) : int32(val) {}
|
||||
Parm(atUint32 val) : uint32(val) {}
|
||||
Parm(float val) : float32(val) {}
|
||||
Parm(bool val) : bool1(val) {}
|
||||
};
|
||||
Vector<Child, AT_DNA_COUNT(animCount)> children;
|
||||
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
|
||||
{
|
||||
for (const auto& child : children)
|
||||
child.anim.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
atUint32 parmType;
|
||||
atUint32 weightFunction;
|
||||
float weight;
|
||||
Parm range[2];
|
||||
};
|
||||
std::vector<ParmInfo> parmInfos;
|
||||
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func)
|
||||
{
|
||||
for (auto& child : children)
|
||||
if (!child.anim.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
struct AnimInfo {
|
||||
atUint32 id;
|
||||
std::vector<ParmInfo::Parm> parmVals;
|
||||
};
|
||||
std::vector<AnimInfo> animInfos;
|
||||
};
|
||||
struct MetaAnimSequence : IMetaAnim
|
||||
{
|
||||
MetaAnimSequence() : IMetaAnim(Type::Sequence, "Sequence") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> animCount;
|
||||
Vector<MetaAnimFactory, AT_DNA_COUNT(animCount)> children;
|
||||
Vector<AnimState, AT_DNA_COUNT(animStateCount)> animStates;
|
||||
} pasDatabase;
|
||||
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
|
||||
{
|
||||
for (const auto& child : children)
|
||||
child.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
struct ParticleResData {
|
||||
std::vector<UniqueID32> part;
|
||||
std::vector<UniqueID32> swhc;
|
||||
std::vector<UniqueID32> unk;
|
||||
std::vector<UniqueID32> elsc;
|
||||
} partResData;
|
||||
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func)
|
||||
{
|
||||
for (auto& child : children)
|
||||
if (!child.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
atUint32 unk1 = 0;
|
||||
|
||||
struct ActionAABB : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atVec3f> aabb[2];
|
||||
};
|
||||
std::vector<ActionAABB> animAABBs;
|
||||
|
||||
struct Effect : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
Value<atUint32> compCount;
|
||||
struct EffectComponent : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
DNAFourCC type;
|
||||
UniqueID32 id;
|
||||
String<-1> locator;
|
||||
Value<float> scale;
|
||||
Value<atUint32> parentMode;
|
||||
Value<atUint32> flags;
|
||||
};
|
||||
Vector<EffectComponent, AT_DNA_COUNT(compCount)> comps;
|
||||
};
|
||||
std::vector<Effect> effects;
|
||||
|
||||
struct Animation : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
MetaAnimFactory metaAnim;
|
||||
};
|
||||
std::vector<Animation> animations;
|
||||
UniqueID32Zero cmdlIce;
|
||||
UniqueID32Zero cskrIce;
|
||||
|
||||
struct IMetaTrans : BigDNAVYaml
|
||||
{
|
||||
Delete expl;
|
||||
enum class Type
|
||||
{
|
||||
MetaAnim = 0,
|
||||
Trans = 1,
|
||||
PhaseTrans = 2,
|
||||
NoTrans = 3,
|
||||
} m_type;
|
||||
const char* m_typeStr;
|
||||
IMetaTrans(Type type, const char* typeStr)
|
||||
: m_type(type), m_typeStr(typeStr) {}
|
||||
virtual void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) {}
|
||||
virtual bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func) {return true;}
|
||||
};
|
||||
struct MetaTransFactory : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
std::unique_ptr<IMetaTrans> m_trans;
|
||||
};
|
||||
struct MetaTransMetaAnim : IMetaTrans
|
||||
{
|
||||
MetaTransMetaAnim()
|
||||
: IMetaTrans(Type::MetaAnim, "MetaAnim") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
MetaAnimFactory anim;
|
||||
std::vector<atUint32> animIdxs;
|
||||
};
|
||||
Vector<CharacterInfo, AT_DNA_COUNT(characterCount)> characters;
|
||||
} characterSet;
|
||||
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out)
|
||||
{
|
||||
anim.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
struct AnimationSet : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func)
|
||||
{
|
||||
return anim.m_anim->enumeratePrimitives(func);
|
||||
}
|
||||
};
|
||||
struct MetaTransTrans : IMetaTrans
|
||||
{
|
||||
MetaTransTrans()
|
||||
: IMetaTrans(Type::Trans, "Trans") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<float> transDurTime;
|
||||
Value<atUint32> transDurTimeMode;
|
||||
Value<bool> unk2;
|
||||
Value<bool> runA;
|
||||
Value<atUint32> flags;
|
||||
};
|
||||
struct MetaTransPhaseTrans : IMetaTrans
|
||||
{
|
||||
MetaTransPhaseTrans()
|
||||
: IMetaTrans(Type::PhaseTrans, "PhaseTrans") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<float> transDurTime;
|
||||
Value<atUint32> transDurTimeMode;
|
||||
Value<bool> unk2;
|
||||
Value<bool> runA;
|
||||
Value<atUint32> flags;
|
||||
};
|
||||
struct MetaAnimPrimitive;
|
||||
struct IMetaAnim : BigDNAVYaml {
|
||||
Delete expl;
|
||||
enum class Type { Primitive = 0, Blend = 1, PhaseBlend = 2, Random = 3, Sequence = 4 } m_type;
|
||||
const char* m_typeStr;
|
||||
IMetaAnim(Type type, const char* typeStr) : m_type(type), m_typeStr(typeStr) {}
|
||||
virtual void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) = 0;
|
||||
virtual bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func) = 0;
|
||||
};
|
||||
struct MetaAnimFactory : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
std::unique_ptr<IMetaAnim> m_anim;
|
||||
};
|
||||
struct MetaAnimPrimitive : IMetaAnim {
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
MetaAnimPrimitive() : IMetaAnim(Type::Primitive, "Primitive") {}
|
||||
|
||||
struct Transition : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> unk;
|
||||
Value<atUint32> animIdxA;
|
||||
Value<atUint32> animIdxB;
|
||||
MetaTransFactory metaTrans;
|
||||
};
|
||||
std::vector<Transition> transitions;
|
||||
MetaTransFactory defaultTransition;
|
||||
UniqueID32 animId;
|
||||
Value<atUint32> animIdx;
|
||||
String<-1> animName;
|
||||
Value<float> unk1;
|
||||
Value<atUint32> unk2;
|
||||
|
||||
struct AdditiveAnimationInfo : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> animIdx;
|
||||
Value<float> unk1;
|
||||
Value<float> unk2;
|
||||
};
|
||||
std::vector<AdditiveAnimationInfo> additiveAnims;
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out);
|
||||
|
||||
float floatA = 0.0;
|
||||
float floatB = 0.0;
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func) { return func(*this); }
|
||||
};
|
||||
struct MetaAnimBlend : IMetaAnim {
|
||||
MetaAnimBlend() : IMetaAnim(Type::Blend, "Blend") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
MetaAnimFactory animA;
|
||||
MetaAnimFactory animB;
|
||||
Value<float> unkFloat;
|
||||
Value<atUint8> unk;
|
||||
|
||||
struct HalfTransition : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> animIdx;
|
||||
MetaTransFactory metaTrans;
|
||||
};
|
||||
std::vector<HalfTransition> halfTransitions;
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) {
|
||||
animA.m_anim->gatherPrimitives(pakRouter, out);
|
||||
animB.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
|
||||
struct AnimationResources : BigDNA
|
||||
{
|
||||
AT_DECL_DNA_YAML
|
||||
UniqueID32 animId;
|
||||
UniqueID32 evntId;
|
||||
};
|
||||
std::vector<AnimationResources> animResources;
|
||||
} animationSet;
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func) {
|
||||
if (!animA.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
if (!animB.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct MetaAnimPhaseBlend : IMetaAnim {
|
||||
MetaAnimPhaseBlend() : IMetaAnim(Type::PhaseBlend, "PhaseBlend") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
MetaAnimFactory animA;
|
||||
MetaAnimFactory animB;
|
||||
Value<float> unkFloat;
|
||||
Value<atUint8> unk;
|
||||
|
||||
void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID32>>& out) const
|
||||
{
|
||||
out.clear();
|
||||
out.reserve(characterSet.characters.size());
|
||||
for (const CharacterSet::CharacterInfo& ci : characterSet.characters)
|
||||
{
|
||||
out.emplace_back();
|
||||
DNAANCS::CharacterResInfo<UniqueID32>& chOut = out.back();
|
||||
chOut.name = ci.name;
|
||||
chOut.cmdl = ci.cmdl;
|
||||
chOut.cskr = ci.cskr;
|
||||
chOut.cinf = ci.cinf;
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) {
|
||||
animA.m_anim->gatherPrimitives(pakRouter, out);
|
||||
animB.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
|
||||
if (ci.cmdlIce)
|
||||
chOut.overlays.emplace_back("ICE", std::make_pair(ci.cmdlIce, ci.cskrIce));
|
||||
}
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func) {
|
||||
if (!animA.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
if (!animB.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct MetaAnimRandom : IMetaAnim {
|
||||
MetaAnimRandom() : IMetaAnim(Type::Random, "Random") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> animCount;
|
||||
struct Child : BigDNA {
|
||||
AT_DECL_DNA
|
||||
MetaAnimFactory anim;
|
||||
Value<atUint32> probability;
|
||||
};
|
||||
Vector<Child, AT_DNA_COUNT(animCount)> children;
|
||||
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) {
|
||||
for (const auto& child : children)
|
||||
child.anim.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func) {
|
||||
for (auto& child : children)
|
||||
if (!child.anim.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
struct MetaAnimSequence : IMetaAnim {
|
||||
MetaAnimSequence() : IMetaAnim(Type::Sequence, "Sequence") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<atUint32> animCount;
|
||||
Vector<MetaAnimFactory, AT_DNA_COUNT(animCount)> children;
|
||||
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) {
|
||||
for (const auto& child : children)
|
||||
child.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func) {
|
||||
for (auto& child : children)
|
||||
if (!child.m_anim->enumeratePrimitives(func))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct Animation : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
String<-1> name;
|
||||
MetaAnimFactory metaAnim;
|
||||
};
|
||||
std::vector<Animation> animations;
|
||||
|
||||
struct IMetaTrans : BigDNAVYaml {
|
||||
Delete expl;
|
||||
enum class Type {
|
||||
MetaAnim = 0,
|
||||
Trans = 1,
|
||||
PhaseTrans = 2,
|
||||
NoTrans = 3,
|
||||
} m_type;
|
||||
const char* m_typeStr;
|
||||
IMetaTrans(Type type, const char* typeStr) : m_type(type), m_typeStr(typeStr) {}
|
||||
virtual void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) {}
|
||||
virtual bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func) { return true; }
|
||||
};
|
||||
struct MetaTransFactory : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Delete expl;
|
||||
std::unique_ptr<IMetaTrans> m_trans;
|
||||
};
|
||||
struct MetaTransMetaAnim : IMetaTrans {
|
||||
MetaTransMetaAnim() : IMetaTrans(Type::MetaAnim, "MetaAnim") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
MetaAnimFactory anim;
|
||||
|
||||
void gatherPrimitives(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) {
|
||||
anim.m_anim->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
|
||||
bool enumeratePrimitives(const std::function<bool(MetaAnimPrimitive& prim)>& func) {
|
||||
return anim.m_anim->enumeratePrimitives(func);
|
||||
}
|
||||
};
|
||||
struct MetaTransTrans : IMetaTrans {
|
||||
MetaTransTrans() : IMetaTrans(Type::Trans, "Trans") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<float> transDurTime;
|
||||
Value<atUint32> transDurTimeMode;
|
||||
Value<bool> unk2;
|
||||
Value<bool> runA;
|
||||
Value<atUint32> flags;
|
||||
};
|
||||
struct MetaTransPhaseTrans : IMetaTrans {
|
||||
MetaTransPhaseTrans() : IMetaTrans(Type::PhaseTrans, "PhaseTrans") {}
|
||||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
Value<float> transDurTime;
|
||||
Value<atUint32> transDurTimeMode;
|
||||
Value<bool> unk2;
|
||||
Value<bool> runA;
|
||||
Value<atUint32> flags;
|
||||
};
|
||||
|
||||
struct Transition : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> unk;
|
||||
Value<atUint32> animIdxA;
|
||||
Value<atUint32> animIdxB;
|
||||
MetaTransFactory metaTrans;
|
||||
};
|
||||
std::vector<Transition> transitions;
|
||||
MetaTransFactory defaultTransition;
|
||||
|
||||
struct AdditiveAnimationInfo : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> animIdx;
|
||||
Value<float> unk1;
|
||||
Value<float> unk2;
|
||||
};
|
||||
std::vector<AdditiveAnimationInfo> additiveAnims;
|
||||
|
||||
float floatA = 0.0;
|
||||
float floatB = 0.0;
|
||||
|
||||
struct HalfTransition : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
Value<atUint32> animIdx;
|
||||
MetaTransFactory metaTrans;
|
||||
};
|
||||
std::vector<HalfTransition> halfTransitions;
|
||||
|
||||
struct AnimationResources : BigDNA {
|
||||
AT_DECL_DNA_YAML
|
||||
UniqueID32 animId;
|
||||
UniqueID32 evntId;
|
||||
};
|
||||
std::vector<AnimationResources> animResources;
|
||||
} animationSet;
|
||||
|
||||
void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID32>>& out) const {
|
||||
out.clear();
|
||||
out.reserve(characterSet.characters.size());
|
||||
for (const CharacterSet::CharacterInfo& ci : characterSet.characters) {
|
||||
out.emplace_back();
|
||||
DNAANCS::CharacterResInfo<UniqueID32>& chOut = out.back();
|
||||
chOut.name = ci.name;
|
||||
chOut.cmdl = ci.cmdl;
|
||||
chOut.cskr = ci.cskr;
|
||||
chOut.cinf = ci.cinf;
|
||||
|
||||
if (ci.cmdlIce)
|
||||
chOut.overlays.emplace_back("ICE", std::make_pair(ci.cmdlIce, ci.cskrIce));
|
||||
}
|
||||
}
|
||||
|
||||
void getAnimationResInfo(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) const
|
||||
{
|
||||
out.clear();
|
||||
for (const AnimationSet::Animation& ai : animationSet.animations)
|
||||
if (AnimationSet::IMetaAnim* anim = ai.metaAnim.m_anim.get())
|
||||
anim->gatherPrimitives(pakRouter, out);
|
||||
for (const AnimationSet::Transition& ti : animationSet.transitions)
|
||||
if (AnimationSet::IMetaTrans* trans = ti.metaTrans.m_trans.get())
|
||||
trans->gatherPrimitives(pakRouter, out);
|
||||
if (AnimationSet::IMetaTrans* trans = animationSet.defaultTransition.m_trans.get())
|
||||
trans->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
void getAnimationResInfo(PAKRouter<PAKBridge>* pakRouter,
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>>& out) const {
|
||||
out.clear();
|
||||
for (const AnimationSet::Animation& ai : animationSet.animations)
|
||||
if (AnimationSet::IMetaAnim* anim = ai.metaAnim.m_anim.get())
|
||||
anim->gatherPrimitives(pakRouter, out);
|
||||
for (const AnimationSet::Transition& ti : animationSet.transitions)
|
||||
if (AnimationSet::IMetaTrans* trans = ti.metaTrans.m_trans.get())
|
||||
trans->gatherPrimitives(pakRouter, out);
|
||||
if (AnimationSet::IMetaTrans* trans = animationSet.defaultTransition.m_trans.get())
|
||||
trans->gatherPrimitives(pakRouter, out);
|
||||
}
|
||||
|
||||
void enumeratePrimitives(const std::function<bool(AnimationSet::MetaAnimPrimitive& prim)>& func)
|
||||
{
|
||||
for (const AnimationSet::Animation& ai : animationSet.animations)
|
||||
if (AnimationSet::IMetaAnim* anim = ai.metaAnim.m_anim.get())
|
||||
anim->enumeratePrimitives(func);
|
||||
for (const AnimationSet::Transition& ti : animationSet.transitions)
|
||||
if (AnimationSet::IMetaTrans* trans = ti.metaTrans.m_trans.get())
|
||||
trans->enumeratePrimitives(func);
|
||||
if (AnimationSet::IMetaTrans* trans = animationSet.defaultTransition.m_trans.get())
|
||||
trans->enumeratePrimitives(func);
|
||||
}
|
||||
void enumeratePrimitives(const std::function<bool(AnimationSet::MetaAnimPrimitive& prim)>& func) {
|
||||
for (const AnimationSet::Animation& ai : animationSet.animations)
|
||||
if (AnimationSet::IMetaAnim* anim = ai.metaAnim.m_anim.get())
|
||||
anim->enumeratePrimitives(func);
|
||||
for (const AnimationSet::Transition& ti : animationSet.transitions)
|
||||
if (AnimationSet::IMetaTrans* trans = ti.metaTrans.m_trans.get())
|
||||
trans->enumeratePrimitives(func);
|
||||
if (AnimationSet::IMetaTrans* trans = animationSet.defaultTransition.m_trans.get())
|
||||
trans->enumeratePrimitives(func);
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut, int charIdx) const
|
||||
{
|
||||
auto doCi = [&](const CharacterSet::CharacterInfo& ci)
|
||||
{
|
||||
for (const auto& id : ci.partResData.part)
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
for (const auto& id : ci.partResData.swhc)
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
for (const auto& id : ci.partResData.unk)
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
for (const auto& id : ci.partResData.elsc)
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
};
|
||||
if (charIdx < 0)
|
||||
for (const CharacterSet::CharacterInfo& ci : characterSet.characters)
|
||||
doCi(ci);
|
||||
else if (charIdx < characterSet.characters.size())
|
||||
doCi(characterSet.characters[charIdx]);
|
||||
}
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut, int charIdx) const {
|
||||
auto doCi = [&](const CharacterSet::CharacterInfo& ci) {
|
||||
for (const auto& id : ci.partResData.part)
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
for (const auto& id : ci.partResData.swhc)
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
for (const auto& id : ci.partResData.unk)
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
for (const auto& id : ci.partResData.elsc)
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
};
|
||||
if (charIdx < 0)
|
||||
for (const CharacterSet::CharacterInfo& ci : characterSet.characters)
|
||||
doCi(ci);
|
||||
else if (charIdx < characterSet.characters.size())
|
||||
doCi(characterSet.characters[charIdx]);
|
||||
}
|
||||
|
||||
static bool Extract(const SpecBase& dataSpec,
|
||||
PAKEntryReadStream& rs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry,
|
||||
bool force,
|
||||
hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor);
|
||||
static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor);
|
||||
|
||||
static bool CookCINF(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor);
|
||||
static bool CookCINF(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor);
|
||||
|
||||
static bool CookCSKR(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor,
|
||||
static bool CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor,
|
||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
|
||||
static bool CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor,
|
||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
|
||||
static bool CookCSKRPC(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor,
|
||||
const std::function<bool(const hecl::ProjectPath& modelPath)>& modelCookFunc);
|
||||
|
||||
static bool CookANIM(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNAANCS::Actor& actor,
|
||||
hecl::blender::DataStream& ds,
|
||||
bool pc);
|
||||
static bool CookANIM(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor,
|
||||
hecl::blender::DataStream& ds, bool pc);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,240 +7,211 @@
|
|||
#include "EVNT.hpp"
|
||||
#include "DataSpec/DNACommon/ANCS.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
struct ANIM : BigDNA
|
||||
{
|
||||
struct ANIM : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
|
||||
static UniqueID32 GetEVNTId(athena::io::IStreamReader& r);
|
||||
|
||||
struct IANIM : BigDNAV {
|
||||
Delete expl;
|
||||
atUint32 m_version;
|
||||
IANIM(atUint32 version) : m_version(version) {}
|
||||
|
||||
std::vector<std::pair<atUint32, bool>> bones;
|
||||
std::vector<atUint32> frames;
|
||||
std::vector<DNAANIM::Channel> channels;
|
||||
std::vector<std::vector<DNAANIM::Value>> chanKeys;
|
||||
float mainInterval = 0.0;
|
||||
UniqueID32Zero evnt;
|
||||
bool looping = false;
|
||||
|
||||
void sendANIMToBlender(hecl::blender::PyOutStream&, const DNAANIM::RigInverter<CINF>& rig) const;
|
||||
};
|
||||
|
||||
struct ANIM0 : IANIM {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
AT_DECL_DNAV
|
||||
ANIM0() : IANIM(0) {}
|
||||
|
||||
static UniqueID32 GetEVNTId(athena::io::IStreamReader& r);
|
||||
struct Header : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<float> duration;
|
||||
Value<atUint32> unk0;
|
||||
Value<float> interval;
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> keyCount;
|
||||
Value<atUint32> unk2;
|
||||
Value<atUint32> boneSlotCount;
|
||||
};
|
||||
};
|
||||
|
||||
struct IANIM : BigDNAV
|
||||
{
|
||||
Delete expl;
|
||||
atUint32 m_version;
|
||||
IANIM(atUint32 version) : m_version(version) {}
|
||||
struct ANIM2 : IANIM {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
AT_DECL_DNAV
|
||||
ANIM2(bool pc) : IANIM(pc ? 3 : 2) {}
|
||||
|
||||
std::vector<std::pair<atUint32, bool>> bones;
|
||||
std::vector<atUint32> frames;
|
||||
std::vector<DNAANIM::Channel> channels;
|
||||
std::vector<std::vector<DNAANIM::Value>> chanKeys;
|
||||
float mainInterval = 0.0;
|
||||
UniqueID32Zero evnt;
|
||||
bool looping = false;
|
||||
|
||||
void sendANIMToBlender(hecl::blender::PyOutStream&, const DNAANIM::RigInverter<CINF>& rig) const;
|
||||
struct Header : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> scratchSize;
|
||||
UniqueID32Zero evnt;
|
||||
Value<atUint32> unk0 = 1;
|
||||
Value<float> duration;
|
||||
Value<float> interval;
|
||||
Value<atUint32> rootBoneId = 3;
|
||||
Value<atUint32> looping = 0;
|
||||
Value<atUint32> rotDiv;
|
||||
Value<float> translationMult;
|
||||
Value<atUint32> boneChannelCount;
|
||||
Value<atUint32> unk3;
|
||||
Value<atUint32> keyBitmapBitCount;
|
||||
};
|
||||
|
||||
struct ANIM0 : IANIM
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
AT_DECL_DNAV
|
||||
ANIM0() : IANIM(0) {}
|
||||
struct ChannelDesc : BigDNA {
|
||||
Delete expl;
|
||||
Value<atUint32> id = 0;
|
||||
Value<atUint16> keyCount1 = 0;
|
||||
Value<atInt16> initRX = 0;
|
||||
Value<atUint8> qRX = 0;
|
||||
Value<atInt16> initRY = 0;
|
||||
Value<atUint8> qRY = 0;
|
||||
Value<atInt16> initRZ = 0;
|
||||
Value<atUint8> qRZ = 0;
|
||||
Value<atUint16> keyCount2 = 0;
|
||||
Value<atInt16> initTX = 0;
|
||||
Value<atUint8> qTX = 0;
|
||||
Value<atInt16> initTY = 0;
|
||||
Value<atUint8> qTY = 0;
|
||||
Value<atInt16> initTZ = 0;
|
||||
Value<atUint8> qTZ = 0;
|
||||
|
||||
struct Header : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<float> duration;
|
||||
Value<atUint32> unk0;
|
||||
Value<float> interval;
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> keyCount;
|
||||
Value<atUint32> unk2;
|
||||
Value<atUint32> boneSlotCount;
|
||||
};
|
||||
};
|
||||
|
||||
struct ANIM2 : IANIM
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
AT_DECL_DNAV
|
||||
ANIM2(bool pc) : IANIM(pc ? 3 : 2) {}
|
||||
|
||||
struct Header : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> scratchSize;
|
||||
UniqueID32Zero evnt;
|
||||
Value<atUint32> unk0 = 1;
|
||||
Value<float> duration;
|
||||
Value<float> interval;
|
||||
Value<atUint32> rootBoneId = 3;
|
||||
Value<atUint32> looping = 0;
|
||||
Value<atUint32> rotDiv;
|
||||
Value<float> translationMult;
|
||||
Value<atUint32> boneChannelCount;
|
||||
Value<atUint32> unk3;
|
||||
Value<atUint32> keyBitmapBitCount;
|
||||
};
|
||||
|
||||
struct ChannelDesc : BigDNA
|
||||
{
|
||||
Delete expl;
|
||||
Value<atUint32> id = 0;
|
||||
Value<atUint16> keyCount1 = 0;
|
||||
Value<atInt16> initRX = 0;
|
||||
Value<atUint8> qRX = 0;
|
||||
Value<atInt16> initRY = 0;
|
||||
Value<atUint8> qRY = 0;
|
||||
Value<atInt16> initRZ = 0;
|
||||
Value<atUint8> qRZ = 0;
|
||||
Value<atUint16> keyCount2 = 0;
|
||||
Value<atInt16> initTX = 0;
|
||||
Value<atUint8> qTX = 0;
|
||||
Value<atInt16> initTY = 0;
|
||||
Value<atUint8> qTY = 0;
|
||||
Value<atInt16> initTZ = 0;
|
||||
Value<atUint8> qTZ = 0;
|
||||
|
||||
void read(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint32Big();
|
||||
keyCount1 = reader.readUint16Big();
|
||||
initRX = reader.readInt16Big();
|
||||
qRX = reader.readUByte();
|
||||
initRY = reader.readInt16Big();
|
||||
qRY = reader.readUByte();
|
||||
initRZ = reader.readInt16Big();
|
||||
qRZ = reader.readUByte();
|
||||
keyCount2 = reader.readUint16Big();
|
||||
if (keyCount2)
|
||||
{
|
||||
initTX = reader.readInt16Big();
|
||||
qTX = reader.readUByte();
|
||||
initTY = reader.readInt16Big();
|
||||
qTY = reader.readUByte();
|
||||
initTZ = reader.readInt16Big();
|
||||
qTZ = reader.readUByte();
|
||||
}
|
||||
}
|
||||
void write(athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
writer.writeUint32Big(id);
|
||||
writer.writeUint16Big(keyCount1);
|
||||
writer.writeInt16Big(initRX);
|
||||
writer.writeUByte(qRX);
|
||||
writer.writeInt16Big(initRY);
|
||||
writer.writeUByte(qRY);
|
||||
writer.writeInt16Big(initRZ);
|
||||
writer.writeUByte(qRZ);
|
||||
writer.writeUint16Big(keyCount2);
|
||||
if (keyCount2)
|
||||
{
|
||||
writer.writeInt16Big(initTX);
|
||||
writer.writeUByte(qTX);
|
||||
writer.writeInt16Big(initTY);
|
||||
writer.writeUByte(qTY);
|
||||
writer.writeInt16Big(initTZ);
|
||||
writer.writeUByte(qTZ);
|
||||
}
|
||||
}
|
||||
void binarySize(size_t& __isz) const
|
||||
{
|
||||
__isz += 17;
|
||||
if (keyCount2)
|
||||
__isz += 9;
|
||||
}
|
||||
};
|
||||
|
||||
struct ChannelDescPC : BigDNA
|
||||
{
|
||||
Delete expl;
|
||||
Value<atUint32> id = 0;
|
||||
Value<atUint32> keyCount1 = 0;
|
||||
Value<atUint32> QinitRX = 0;
|
||||
Value<atUint32> QinitRY = 0;
|
||||
Value<atUint32> QinitRZ = 0;
|
||||
Value<atUint32> keyCount2 = 0;
|
||||
Value<atUint32> QinitTX = 0;
|
||||
Value<atUint32> QinitTY = 0;
|
||||
Value<atUint32> QinitTZ = 0;
|
||||
|
||||
void read(athena::io::IStreamReader& reader)
|
||||
{
|
||||
id = reader.readUint32Big();
|
||||
keyCount1 = reader.readUint32Big();
|
||||
QinitRX = reader.readUint32Big();
|
||||
QinitRY = reader.readUint32Big();
|
||||
QinitRZ = reader.readUint32Big();
|
||||
keyCount2 = reader.readUint32Big();
|
||||
if (keyCount2)
|
||||
{
|
||||
QinitTX = reader.readUint32Big();
|
||||
QinitTY = reader.readUint32Big();
|
||||
QinitTZ = reader.readUint32Big();
|
||||
}
|
||||
}
|
||||
void write(athena::io::IStreamWriter& writer) const
|
||||
{
|
||||
writer.writeUint32Big(id);
|
||||
writer.writeUint32Big(keyCount1);
|
||||
writer.writeUint32Big(QinitRX);
|
||||
writer.writeUint32Big(QinitRY);
|
||||
writer.writeUint32Big(QinitRZ);
|
||||
writer.writeUint32Big(keyCount2);
|
||||
if (keyCount2)
|
||||
{
|
||||
writer.writeUint32Big(QinitTX);
|
||||
writer.writeUint32Big(QinitTY);
|
||||
writer.writeUint32Big(QinitTZ);
|
||||
}
|
||||
}
|
||||
void binarySize(size_t& __isz) const
|
||||
{
|
||||
__isz += 24;
|
||||
if (keyCount2)
|
||||
__isz += 12;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
std::unique_ptr<IANIM> m_anim;
|
||||
|
||||
void sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig, bool) const
|
||||
{
|
||||
m_anim->sendANIMToBlender(os, rig);
|
||||
}
|
||||
|
||||
bool isLooping() const
|
||||
{
|
||||
if (!m_anim)
|
||||
return false;
|
||||
return m_anim->looping;
|
||||
}
|
||||
|
||||
void extractEVNT(const DNAANCS::AnimationResInfo<UniqueID32>& animInfo,
|
||||
const hecl::ProjectPath& outPath, PAKRouter<PAKBridge>& pakRouter, bool force) const
|
||||
{
|
||||
if (m_anim->evnt)
|
||||
{
|
||||
hecl::SystemStringConv sysStr(animInfo.name);
|
||||
hecl::ProjectPath evntYamlPath = outPath.getWithExtension((hecl::SystemString(_SYS_STR(".")) +
|
||||
sysStr.c_str() +
|
||||
_SYS_STR(".evnt.yaml")).c_str(), true);
|
||||
hecl::ProjectPath::Type evntYamlType = evntYamlPath.getPathType();
|
||||
|
||||
if (force || evntYamlType == hecl::ProjectPath::Type::None)
|
||||
{
|
||||
EVNT evnt;
|
||||
if (pakRouter.lookupAndReadDNA(m_anim->evnt, evnt, true))
|
||||
{
|
||||
athena::io::FileWriter writer(evntYamlPath.getAbsolutePath());
|
||||
athena::io::ToYAMLStream(evnt, writer);
|
||||
}
|
||||
}
|
||||
void read(athena::io::IStreamReader& reader) {
|
||||
id = reader.readUint32Big();
|
||||
keyCount1 = reader.readUint16Big();
|
||||
initRX = reader.readInt16Big();
|
||||
qRX = reader.readUByte();
|
||||
initRY = reader.readInt16Big();
|
||||
qRY = reader.readUByte();
|
||||
initRZ = reader.readInt16Big();
|
||||
qRZ = reader.readUByte();
|
||||
keyCount2 = reader.readUint16Big();
|
||||
if (keyCount2) {
|
||||
initTX = reader.readInt16Big();
|
||||
qTX = reader.readUByte();
|
||||
initTY = reader.readInt16Big();
|
||||
qTY = reader.readUByte();
|
||||
initTZ = reader.readInt16Big();
|
||||
qTZ = reader.readUByte();
|
||||
}
|
||||
}
|
||||
void write(athena::io::IStreamWriter& writer) const {
|
||||
writer.writeUint32Big(id);
|
||||
writer.writeUint16Big(keyCount1);
|
||||
writer.writeInt16Big(initRX);
|
||||
writer.writeUByte(qRX);
|
||||
writer.writeInt16Big(initRY);
|
||||
writer.writeUByte(qRY);
|
||||
writer.writeInt16Big(initRZ);
|
||||
writer.writeUByte(qRZ);
|
||||
writer.writeUint16Big(keyCount2);
|
||||
if (keyCount2) {
|
||||
writer.writeInt16Big(initTX);
|
||||
writer.writeUByte(qTX);
|
||||
writer.writeInt16Big(initTY);
|
||||
writer.writeUByte(qTY);
|
||||
writer.writeInt16Big(initTZ);
|
||||
writer.writeUByte(qTZ);
|
||||
}
|
||||
}
|
||||
void binarySize(size_t& __isz) const {
|
||||
__isz += 17;
|
||||
if (keyCount2)
|
||||
__isz += 9;
|
||||
}
|
||||
};
|
||||
|
||||
struct ChannelDescPC : BigDNA {
|
||||
Delete expl;
|
||||
Value<atUint32> id = 0;
|
||||
Value<atUint32> keyCount1 = 0;
|
||||
Value<atUint32> QinitRX = 0;
|
||||
Value<atUint32> QinitRY = 0;
|
||||
Value<atUint32> QinitRZ = 0;
|
||||
Value<atUint32> keyCount2 = 0;
|
||||
Value<atUint32> QinitTX = 0;
|
||||
Value<atUint32> QinitTY = 0;
|
||||
Value<atUint32> QinitTZ = 0;
|
||||
|
||||
void read(athena::io::IStreamReader& reader) {
|
||||
id = reader.readUint32Big();
|
||||
keyCount1 = reader.readUint32Big();
|
||||
QinitRX = reader.readUint32Big();
|
||||
QinitRY = reader.readUint32Big();
|
||||
QinitRZ = reader.readUint32Big();
|
||||
keyCount2 = reader.readUint32Big();
|
||||
if (keyCount2) {
|
||||
QinitTX = reader.readUint32Big();
|
||||
QinitTY = reader.readUint32Big();
|
||||
QinitTZ = reader.readUint32Big();
|
||||
}
|
||||
}
|
||||
void write(athena::io::IStreamWriter& writer) const {
|
||||
writer.writeUint32Big(id);
|
||||
writer.writeUint32Big(keyCount1);
|
||||
writer.writeUint32Big(QinitRX);
|
||||
writer.writeUint32Big(QinitRY);
|
||||
writer.writeUint32Big(QinitRZ);
|
||||
writer.writeUint32Big(keyCount2);
|
||||
if (keyCount2) {
|
||||
writer.writeUint32Big(QinitTX);
|
||||
writer.writeUint32Big(QinitTY);
|
||||
writer.writeUint32Big(QinitTZ);
|
||||
}
|
||||
}
|
||||
void binarySize(size_t& __isz) const {
|
||||
__isz += 24;
|
||||
if (keyCount2)
|
||||
__isz += 12;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
std::unique_ptr<IANIM> m_anim;
|
||||
|
||||
void sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter<CINF>& rig, bool) const {
|
||||
m_anim->sendANIMToBlender(os, rig);
|
||||
}
|
||||
|
||||
bool isLooping() const {
|
||||
if (!m_anim)
|
||||
return false;
|
||||
return m_anim->looping;
|
||||
}
|
||||
|
||||
void extractEVNT(const DNAANCS::AnimationResInfo<UniqueID32>& animInfo, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, bool force) const {
|
||||
if (m_anim->evnt) {
|
||||
hecl::SystemStringConv sysStr(animInfo.name);
|
||||
hecl::ProjectPath evntYamlPath = outPath.getWithExtension(
|
||||
(hecl::SystemString(_SYS_STR(".")) + sysStr.c_str() + _SYS_STR(".evnt.yaml")).c_str(), true);
|
||||
hecl::ProjectPath::Type evntYamlType = evntYamlPath.getPathType();
|
||||
|
||||
if (force || evntYamlType == hecl::ProjectPath::Type::None) {
|
||||
EVNT evnt;
|
||||
if (pakRouter.lookupAndReadDNA(m_anim->evnt, evnt, true)) {
|
||||
athena::io::FileWriter writer(evntYamlPath.getAbsolutePath());
|
||||
athena::io::ToYAMLStream(evnt, writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using BlenderAction = hecl::blender::Action;
|
||||
using BlenderAction = hecl::blender::Action;
|
||||
|
||||
ANIM() = default;
|
||||
ANIM(const BlenderAction& act,
|
||||
const std::unordered_map<std::string, atInt32>& idMap,
|
||||
const DNAANIM::RigInverter<CINF>& rig,
|
||||
bool pc);
|
||||
ANIM() = default;
|
||||
ANIM(const BlenderAction& act, const std::unordered_map<std::string, atInt32>& idMap,
|
||||
const DNAANIM::RigInverter<CINF>& rig, bool pc);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -1,184 +1,160 @@
|
|||
#include "CINF.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
atUint32 CINF::getInternalBoneIdxFromId(atUint32 id) const
|
||||
{
|
||||
atUint32 idx = 0;
|
||||
for (const Bone& b : bones)
|
||||
{
|
||||
if (b.id == id)
|
||||
return idx;
|
||||
++idx;
|
||||
atUint32 CINF::getInternalBoneIdxFromId(atUint32 id) const {
|
||||
atUint32 idx = 0;
|
||||
for (const Bone& b : bones) {
|
||||
if (b.id == id)
|
||||
return idx;
|
||||
++idx;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
atUint32 CINF::getBoneIdxFromId(atUint32 id) const {
|
||||
atUint32 idx = 0;
|
||||
for (atUint32 bid : boneIds) {
|
||||
if (bid == id)
|
||||
return idx;
|
||||
++idx;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string* CINF::getBoneNameFromId(atUint32 id) const {
|
||||
for (const Name& name : names)
|
||||
if (id == name.boneId)
|
||||
return &name.name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const {
|
||||
for (atUint32 bid : boneIds) {
|
||||
for (const Name& name : names) {
|
||||
if (name.boneId == bid) {
|
||||
os.format("obj.vertex_groups.new('%s')\n", name.name.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
atUint32 CINF::getBoneIdxFromId(atUint32 id) const
|
||||
{
|
||||
atUint32 idx = 0;
|
||||
for (atUint32 bid : boneIds)
|
||||
{
|
||||
if (bid == id)
|
||||
return idx;
|
||||
++idx;
|
||||
}
|
||||
return 0;
|
||||
void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const {
|
||||
DNAANIM::RigInverter<CINF> inverter(*this);
|
||||
|
||||
os.format(
|
||||
"arm = bpy.data.armatures.new('CINF_%08X')\n"
|
||||
"arm_obj = bpy.data.objects.new(arm.name, arm)\n"
|
||||
"bpy.context.scene.objects.link(arm_obj)\n"
|
||||
"bpy.context.scene.objects.active = arm_obj\n"
|
||||
"bpy.ops.object.mode_set(mode='EDIT')\n"
|
||||
"arm_bone_table = {}\n",
|
||||
cinfId.toUint32());
|
||||
|
||||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones()) {
|
||||
zeus::simd_floats originF(bone.m_origBone.origin.simd);
|
||||
zeus::simd_floats tailF(bone.m_tail.mSimd);
|
||||
os.format(
|
||||
"bone = arm.edit_bones.new('%s')\n"
|
||||
"bone.head = (%f,%f,%f)\n"
|
||||
"bone.tail = (%f,%f,%f)\n"
|
||||
"bone.use_inherit_scale = False\n"
|
||||
"arm_bone_table[%u] = bone\n",
|
||||
getBoneNameFromId(bone.m_origBone.id)->c_str(), originF[0], originF[1], originF[2], tailF[0], tailF[1],
|
||||
tailF[2], bone.m_origBone.id);
|
||||
}
|
||||
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != 2)
|
||||
os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
|
||||
|
||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||
|
||||
const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION";
|
||||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones())
|
||||
os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", getBoneNameFromId(bone.m_origBone.id)->c_str(),
|
||||
rotMode);
|
||||
}
|
||||
|
||||
const std::string* CINF::getBoneNameFromId(atUint32 id) const
|
||||
{
|
||||
for (const Name& name : names)
|
||||
if (id == name.boneId)
|
||||
return &name.name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const
|
||||
{
|
||||
for (atUint32 bid : boneIds)
|
||||
{
|
||||
for (const Name& name : names)
|
||||
{
|
||||
if (name.boneId == bid)
|
||||
{
|
||||
os.format("obj.vertex_groups.new('%s')\n", name.name.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const
|
||||
{
|
||||
DNAANIM::RigInverter<CINF> inverter(*this);
|
||||
|
||||
os.format("arm = bpy.data.armatures.new('CINF_%08X')\n"
|
||||
"arm_obj = bpy.data.objects.new(arm.name, arm)\n"
|
||||
"bpy.context.scene.objects.link(arm_obj)\n"
|
||||
"bpy.context.scene.objects.active = arm_obj\n"
|
||||
"bpy.ops.object.mode_set(mode='EDIT')\n"
|
||||
"arm_bone_table = {}\n",
|
||||
cinfId.toUint32());
|
||||
|
||||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones())
|
||||
{
|
||||
zeus::simd_floats originF(bone.m_origBone.origin.simd);
|
||||
zeus::simd_floats tailF(bone.m_tail.mSimd);
|
||||
os.format("bone = arm.edit_bones.new('%s')\n"
|
||||
"bone.head = (%f,%f,%f)\n"
|
||||
"bone.tail = (%f,%f,%f)\n"
|
||||
"bone.use_inherit_scale = False\n"
|
||||
"arm_bone_table[%u] = bone\n",
|
||||
getBoneNameFromId(bone.m_origBone.id)->c_str(),
|
||||
originF[0], originF[1], originF[2],
|
||||
tailF[0], tailF[1], tailF[2],
|
||||
bone.m_origBone.id);
|
||||
}
|
||||
|
||||
for (const Bone& bone : bones)
|
||||
if (bone.parentId != 2)
|
||||
os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId);
|
||||
|
||||
os << "bpy.ops.object.mode_set(mode='OBJECT')\n";
|
||||
|
||||
const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION";
|
||||
for (const DNAANIM::RigInverter<CINF>::Bone& bone : inverter.getBones())
|
||||
os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n",
|
||||
getBoneNameFromId(bone.m_origBone.id)->c_str(), rotMode);
|
||||
}
|
||||
|
||||
std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId)
|
||||
{
|
||||
return hecl::Format("CINF_%08X", cinfId.toUint32());
|
||||
}
|
||||
std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return hecl::Format("CINF_%08X", cinfId.toUint32()); }
|
||||
|
||||
int CINF::RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId,
|
||||
std::unordered_map<std::string, atInt32>& idMap, std::map<std::string, int>& nameMap)
|
||||
{
|
||||
int selId;
|
||||
auto search = idMap.find(bone->name);
|
||||
if (search == idMap.end())
|
||||
{
|
||||
selId = curId++;
|
||||
idMap.emplace(std::make_pair(bone->name, selId));
|
||||
std::unordered_map<std::string, atInt32>& idMap,
|
||||
std::map<std::string, int>& nameMap) {
|
||||
int selId;
|
||||
auto search = idMap.find(bone->name);
|
||||
if (search == idMap.end()) {
|
||||
selId = curId++;
|
||||
idMap.emplace(std::make_pair(bone->name, selId));
|
||||
} else
|
||||
selId = search->second;
|
||||
|
||||
bones.emplace_back();
|
||||
Bone& boneOut = bones.back();
|
||||
nameMap[bone->name] = selId;
|
||||
boneOut.id = selId;
|
||||
boneOut.parentId = parent;
|
||||
boneOut.origin = bone->origin;
|
||||
boneOut.linkedCount = bone->children.size() + 1;
|
||||
boneOut.linked.reserve(boneOut.linkedCount);
|
||||
|
||||
const BlenderBone* child;
|
||||
boneOut.linked.push_back(parent);
|
||||
for (size_t i = 0; (child = armature.getChild(bone, i)); ++i)
|
||||
boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, curId, idMap, nameMap));
|
||||
|
||||
return boneOut.id;
|
||||
}
|
||||
|
||||
CINF::CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& idMap) {
|
||||
idMap.reserve(armature.bones.size());
|
||||
bones.reserve(armature.bones.size());
|
||||
|
||||
std::map<std::string, int> nameMap;
|
||||
|
||||
const BlenderBone* bone = armature.getRoot();
|
||||
if (bone) {
|
||||
if (bone->children.size()) {
|
||||
int curId = 4;
|
||||
const BlenderBone* child;
|
||||
for (size_t i = 0; (child = armature.getChild(bone, i)); ++i)
|
||||
RecursiveAddArmatureBone(armature, child, 3, curId, idMap, nameMap);
|
||||
}
|
||||
else
|
||||
selId = search->second;
|
||||
|
||||
bones.emplace_back();
|
||||
Bone& boneOut = bones.back();
|
||||
nameMap[bone->name] = selId;
|
||||
boneOut.id = selId;
|
||||
boneOut.parentId = parent;
|
||||
nameMap[bone->name] = 3;
|
||||
boneOut.id = 3;
|
||||
boneOut.parentId = 2;
|
||||
boneOut.origin = bone->origin;
|
||||
boneOut.linkedCount = bone->children.size() + 1;
|
||||
boneOut.linked.reserve(boneOut.linkedCount);
|
||||
idMap.emplace(std::make_pair(bone->name, 3));
|
||||
|
||||
const BlenderBone* child;
|
||||
boneOut.linked.push_back(parent);
|
||||
for (size_t i=0 ; (child = armature.getChild(bone, i)) ; ++i)
|
||||
boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, curId, idMap, nameMap));
|
||||
|
||||
return boneOut.id;
|
||||
}
|
||||
|
||||
CINF::CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& idMap)
|
||||
{
|
||||
idMap.reserve(armature.bones.size());
|
||||
bones.reserve(armature.bones.size());
|
||||
|
||||
std::map<std::string, int> nameMap;
|
||||
|
||||
const BlenderBone* bone = armature.getRoot();
|
||||
if (bone)
|
||||
{
|
||||
if (bone->children.size())
|
||||
{
|
||||
int curId = 4;
|
||||
const BlenderBone* child;
|
||||
for (size_t i=0 ; (child = armature.getChild(bone, i)) ; ++i)
|
||||
RecursiveAddArmatureBone(armature, child, 3, curId, idMap, nameMap);
|
||||
}
|
||||
|
||||
bones.emplace_back();
|
||||
Bone& boneOut = bones.back();
|
||||
nameMap[bone->name] = 3;
|
||||
boneOut.id = 3;
|
||||
boneOut.parentId = 2;
|
||||
boneOut.origin = bone->origin;
|
||||
idMap.emplace(std::make_pair(bone->name, 3));
|
||||
|
||||
if (bone->children.size())
|
||||
{
|
||||
boneOut.linkedCount = 2;
|
||||
boneOut.linked = {2, 4};
|
||||
}
|
||||
else
|
||||
{
|
||||
boneOut.linkedCount = 1;
|
||||
boneOut.linked = {2};
|
||||
}
|
||||
if (bone->children.size()) {
|
||||
boneOut.linkedCount = 2;
|
||||
boneOut.linked = {2, 4};
|
||||
} else {
|
||||
boneOut.linkedCount = 1;
|
||||
boneOut.linked = {2};
|
||||
}
|
||||
}
|
||||
|
||||
boneCount = bones.size();
|
||||
boneCount = bones.size();
|
||||
|
||||
names.reserve(nameMap.size());
|
||||
nameCount = nameMap.size();
|
||||
for (const auto& name : nameMap)
|
||||
{
|
||||
names.emplace_back();
|
||||
Name& nameOut = names.back();
|
||||
nameOut.name = name.first;
|
||||
nameOut.boneId = name.second;
|
||||
}
|
||||
names.reserve(nameMap.size());
|
||||
nameCount = nameMap.size();
|
||||
for (const auto& name : nameMap) {
|
||||
names.emplace_back();
|
||||
Name& nameOut = names.back();
|
||||
nameOut.name = name.first;
|
||||
nameOut.boneId = name.second;
|
||||
}
|
||||
|
||||
boneIdCount = boneCount;
|
||||
boneIds.reserve(boneIdCount);
|
||||
for (auto it=bones.crbegin() ; it != bones.crend() ; ++it)
|
||||
boneIds.push_back(it->id);
|
||||
boneIdCount = boneCount;
|
||||
boneIds.reserve(boneIdCount);
|
||||
for (auto it = bones.crbegin(); it != bones.crend(); ++it)
|
||||
boneIds.push_back(it->id);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -3,52 +3,47 @@
|
|||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "DataSpec/DNACommon/RigInverter.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
struct CINF : BigDNA
|
||||
{
|
||||
struct CINF : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> boneCount;
|
||||
struct Bone : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> boneCount;
|
||||
struct Bone : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> id;
|
||||
Value<atUint32> parentId;
|
||||
Value<atVec3f> origin;
|
||||
Value<atUint32> linkedCount;
|
||||
Vector<atUint32, AT_DNA_COUNT(linkedCount)> linked;
|
||||
};
|
||||
Vector<Bone, AT_DNA_COUNT(boneCount)> bones;
|
||||
Value<atUint32> id;
|
||||
Value<atUint32> parentId;
|
||||
Value<atVec3f> origin;
|
||||
Value<atUint32> linkedCount;
|
||||
Vector<atUint32, AT_DNA_COUNT(linkedCount)> linked;
|
||||
};
|
||||
Vector<Bone, AT_DNA_COUNT(boneCount)> bones;
|
||||
|
||||
Value<atUint32> boneIdCount;
|
||||
Vector<atUint32, AT_DNA_COUNT(boneIdCount)> boneIds;
|
||||
Value<atUint32> boneIdCount;
|
||||
Vector<atUint32, AT_DNA_COUNT(boneIdCount)> boneIds;
|
||||
|
||||
Value<atUint32> nameCount;
|
||||
struct Name : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
String<-1> name;
|
||||
Value<atUint32> boneId;
|
||||
};
|
||||
Vector<Name, AT_DNA_COUNT(nameCount)> names;
|
||||
Value<atUint32> nameCount;
|
||||
struct Name : BigDNA {
|
||||
AT_DECL_DNA
|
||||
String<-1> name;
|
||||
Value<atUint32> boneId;
|
||||
};
|
||||
Vector<Name, AT_DNA_COUNT(nameCount)> names;
|
||||
|
||||
atUint32 getInternalBoneIdxFromId(atUint32 id) const;
|
||||
atUint32 getBoneIdxFromId(atUint32 id) const;
|
||||
const std::string* getBoneNameFromId(atUint32 id) const;
|
||||
void sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const;
|
||||
void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const;
|
||||
static std::string GetCINFArmatureName(const UniqueID32& cinfId);
|
||||
atUint32 getInternalBoneIdxFromId(atUint32 id) const;
|
||||
atUint32 getBoneIdxFromId(atUint32 id) const;
|
||||
const std::string* getBoneNameFromId(atUint32 id) const;
|
||||
void sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const;
|
||||
void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const;
|
||||
static std::string GetCINFArmatureName(const UniqueID32& cinfId);
|
||||
|
||||
CINF() = default;
|
||||
using Armature = hecl::blender::Armature;
|
||||
using BlenderBone = hecl::blender::Bone;
|
||||
CINF() = default;
|
||||
using Armature = hecl::blender::Armature;
|
||||
using BlenderBone = hecl::blender::Bone;
|
||||
|
||||
int RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId,
|
||||
std::unordered_map<std::string, atInt32>& idMap, std::map<std::string, int>& nameMap);
|
||||
int RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId,
|
||||
std::unordered_map<std::string, atInt32>& idMap, std::map<std::string, int>& nameMap);
|
||||
|
||||
CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& idMap);
|
||||
CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& idMap);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -1,38 +1,30 @@
|
|||
#include "CMDL.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
bool CMDL::Extract(const SpecBase& dataSpec,
|
||||
PAKEntryReadStream& rs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry,
|
||||
bool force,
|
||||
hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged)
|
||||
{
|
||||
/* Check for RigPair */
|
||||
const typename CharacterAssociations<UniqueID32>::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id);
|
||||
CINF cinf;
|
||||
CSKR cskr;
|
||||
std::pair<CSKR*,CINF*> loadRp(nullptr, nullptr);
|
||||
if (rp)
|
||||
{
|
||||
pakRouter.lookupAndReadDNA(rp->first, cskr);
|
||||
pakRouter.lookupAndReadDNA(rp->second, cinf);
|
||||
loadRp.first = &cskr;
|
||||
loadRp.second = &cinf;
|
||||
}
|
||||
bool CMDL::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged) {
|
||||
/* Check for RigPair */
|
||||
const typename CharacterAssociations<UniqueID32>::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id);
|
||||
CINF cinf;
|
||||
CSKR cskr;
|
||||
std::pair<CSKR*, CINF*> loadRp(nullptr, nullptr);
|
||||
if (rp) {
|
||||
pakRouter.lookupAndReadDNA(rp->first, cskr);
|
||||
pakRouter.lookupAndReadDNA(rp->second, cinf);
|
||||
loadRp.first = &cskr;
|
||||
loadRp.second = &cinf;
|
||||
}
|
||||
|
||||
/* Do extract */
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::Mesh))
|
||||
return false;
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*,CINF*>, DNACMDL::SurfaceHeader_1, 2>
|
||||
(conn, rs, pakRouter, entry, dataSpec, loadRp);
|
||||
conn.saveBlend();
|
||||
/* Do extract */
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::Mesh))
|
||||
return false;
|
||||
DNACMDL::ReadCMDLToBlender<PAKRouter<PAKBridge>, MaterialSet, std::pair<CSKR*, CINF*>, DNACMDL::SurfaceHeader_1, 2>(
|
||||
conn, rs, pakRouter, entry, dataSpec, loadRp);
|
||||
conn.saveBlend();
|
||||
|
||||
#if 0
|
||||
/* Cook and re-extract test */
|
||||
|
@ -50,98 +42,82 @@ bool CMDL::Extract(const SpecBase& dataSpec,
|
|||
(conn, reader, pakRouter, entry, dataSpec, loadRp);
|
||||
return conn.saveBlend();
|
||||
#elif 0
|
||||
/* HMDL cook test */
|
||||
hecl::ProjectPath tempOut = outPath.getWithExtension(_SYS_STR(".recook"), true);
|
||||
hecl::blender::Connection::DataStream ds = conn.beginData();
|
||||
DNACMDL::Mesh mesh = ds.compileMesh(hecl::HMDLTopology::TriStrips, 16);
|
||||
ds.close();
|
||||
DNACMDL::WriteHMDLCMDL<HMDLMaterialSet, DNACMDL::SurfaceHeader_1, 2>(tempOut, outPath, mesh);
|
||||
/* HMDL cook test */
|
||||
hecl::ProjectPath tempOut = outPath.getWithExtension(_SYS_STR(".recook"), true);
|
||||
hecl::blender::Connection::DataStream ds = conn.beginData();
|
||||
DNACMDL::Mesh mesh = ds.compileMesh(hecl::HMDLTopology::TriStrips, 16);
|
||||
ds.close();
|
||||
DNACMDL::WriteHMDLCMDL<HMDLMaterialSet, DNACMDL::SurfaceHeader_1, 2>(tempOut, outPath, mesh);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMDL::Cook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNACMDL::Mesh& mesh)
|
||||
{
|
||||
if (!mesh.skins.empty())
|
||||
{
|
||||
DNACMDL::Mesh skinMesh = mesh.getContiguousSkinningVersion();
|
||||
if (!DNACMDL::WriteCMDL<MaterialSet, DNACMDL::SurfaceHeader_1, 2>(outPath, inPath, skinMesh))
|
||||
return false;
|
||||
bool CMDL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNACMDL::Mesh& mesh) {
|
||||
if (!mesh.skins.empty()) {
|
||||
DNACMDL::Mesh skinMesh = mesh.getContiguousSkinningVersion();
|
||||
if (!DNACMDL::WriteCMDL<MaterialSet, DNACMDL::SurfaceHeader_1, 2>(outPath, inPath, skinMesh))
|
||||
return false;
|
||||
|
||||
/* Output skinning intermediate */
|
||||
auto vertCountIt = skinMesh.contiguousSkinVertCounts.cbegin();
|
||||
athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".skinint")).getAbsolutePath());
|
||||
writer.writeUint32Big(skinMesh.boneNames.size());
|
||||
for (const std::string& boneName : skinMesh.boneNames)
|
||||
writer.writeString(boneName);
|
||||
/* Output skinning intermediate */
|
||||
auto vertCountIt = skinMesh.contiguousSkinVertCounts.cbegin();
|
||||
athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".skinint")).getAbsolutePath());
|
||||
writer.writeUint32Big(skinMesh.boneNames.size());
|
||||
for (const std::string& boneName : skinMesh.boneNames)
|
||||
writer.writeString(boneName);
|
||||
|
||||
writer.writeUint32Big(skinMesh.skins.size());
|
||||
for (const std::vector<DNACMDL::Mesh::SkinBind> skin : skinMesh.skins)
|
||||
{
|
||||
writer.writeUint32Big(skin.size());
|
||||
for (const DNACMDL::Mesh::SkinBind& bind : skin)
|
||||
{
|
||||
writer.writeUint32Big(bind.boneIdx);
|
||||
writer.writeFloatBig(bind.weight);
|
||||
}
|
||||
writer.writeUint32Big(*vertCountIt++);
|
||||
}
|
||||
writer.writeUint32Big(skinMesh.pos.size());
|
||||
writer.writeUint32Big(skinMesh.norm.size());
|
||||
writer.writeUint32Big(skinMesh.skins.size());
|
||||
for (const std::vector<DNACMDL::Mesh::SkinBind> skin : skinMesh.skins) {
|
||||
writer.writeUint32Big(skin.size());
|
||||
for (const DNACMDL::Mesh::SkinBind& bind : skin) {
|
||||
writer.writeUint32Big(bind.boneIdx);
|
||||
writer.writeFloatBig(bind.weight);
|
||||
}
|
||||
writer.writeUint32Big(*vertCountIt++);
|
||||
}
|
||||
else if (!DNACMDL::WriteCMDL<MaterialSet, DNACMDL::SurfaceHeader_1, 2>(outPath, inPath, mesh))
|
||||
return false;
|
||||
return true;
|
||||
writer.writeUint32Big(skinMesh.pos.size());
|
||||
writer.writeUint32Big(skinMesh.norm.size());
|
||||
} else if (!DNACMDL::WriteCMDL<MaterialSet, DNACMDL::SurfaceHeader_1, 2>(outPath, inPath, mesh))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMDL::HMDLCook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNACMDL::Mesh& mesh)
|
||||
{
|
||||
hecl::blender::PoolSkinIndex poolSkinIndex;
|
||||
if (mesh.skins.size())
|
||||
{
|
||||
if (!DNACMDL::WriteHMDLCMDL<HMDLMaterialSet, DNACMDL::SurfaceHeader_2, 2>(
|
||||
outPath, inPath, mesh, poolSkinIndex))
|
||||
return false;
|
||||
bool CMDL::HMDLCook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNACMDL::Mesh& mesh) {
|
||||
hecl::blender::PoolSkinIndex poolSkinIndex;
|
||||
if (mesh.skins.size()) {
|
||||
if (!DNACMDL::WriteHMDLCMDL<HMDLMaterialSet, DNACMDL::SurfaceHeader_2, 2>(outPath, inPath, mesh, poolSkinIndex))
|
||||
return false;
|
||||
|
||||
/* Output skinning intermediate */
|
||||
athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".skinint")).getAbsolutePath());
|
||||
writer.writeUint32Big(mesh.skinBanks.banks.size());
|
||||
for (const DNACMDL::Mesh::SkinBanks::Bank& sb : mesh.skinBanks.banks)
|
||||
{
|
||||
writer.writeUint32Big(sb.m_boneIdxs.size());
|
||||
for (uint32_t bind : sb.m_boneIdxs)
|
||||
writer.writeUint32Big(bind);
|
||||
}
|
||||
writer.writeUint32Big(mesh.boneNames.size());
|
||||
for (const std::string& boneName : mesh.boneNames)
|
||||
writer.writeString(boneName);
|
||||
|
||||
/* CVirtualBone structure just like original (for CPU skinning) */
|
||||
writer.writeUint32Big(mesh.skins.size());
|
||||
for (auto& s : mesh.skins)
|
||||
{
|
||||
writer.writeUint32Big(s.size());
|
||||
for (auto& b : s)
|
||||
{
|
||||
writer.writeUint32Big(b.boneIdx);
|
||||
writer.writeFloatBig(b.weight);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write indirection table mapping pool verts to CVirtualBones */
|
||||
writer.writeUint32Big(poolSkinIndex.m_poolSz);
|
||||
for (uint32_t i=0 ; i<poolSkinIndex.m_poolSz ; ++i)
|
||||
writer.writeUint32Big(poolSkinIndex.m_poolToSkinIndex[i]);
|
||||
/* Output skinning intermediate */
|
||||
athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".skinint")).getAbsolutePath());
|
||||
writer.writeUint32Big(mesh.skinBanks.banks.size());
|
||||
for (const DNACMDL::Mesh::SkinBanks::Bank& sb : mesh.skinBanks.banks) {
|
||||
writer.writeUint32Big(sb.m_boneIdxs.size());
|
||||
for (uint32_t bind : sb.m_boneIdxs)
|
||||
writer.writeUint32Big(bind);
|
||||
}
|
||||
else if (!DNACMDL::WriteHMDLCMDL<HMDLMaterialSet, DNACMDL::SurfaceHeader_2, 2>(
|
||||
outPath, inPath, mesh, poolSkinIndex))
|
||||
return false;
|
||||
return true;
|
||||
writer.writeUint32Big(mesh.boneNames.size());
|
||||
for (const std::string& boneName : mesh.boneNames)
|
||||
writer.writeString(boneName);
|
||||
|
||||
/* CVirtualBone structure just like original (for CPU skinning) */
|
||||
writer.writeUint32Big(mesh.skins.size());
|
||||
for (auto& s : mesh.skins) {
|
||||
writer.writeUint32Big(s.size());
|
||||
for (auto& b : s) {
|
||||
writer.writeUint32Big(b.boneIdx);
|
||||
writer.writeFloatBig(b.weight);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write indirection table mapping pool verts to CVirtualBones */
|
||||
writer.writeUint32Big(poolSkinIndex.m_poolSz);
|
||||
for (uint32_t i = 0; i < poolSkinIndex.m_poolSz; ++i)
|
||||
writer.writeUint32Big(poolSkinIndex.m_poolToSkinIndex[i]);
|
||||
} else if (!DNACMDL::WriteHMDLCMDL<HMDLMaterialSet, DNACMDL::SurfaceHeader_2, 2>(outPath, inPath, mesh,
|
||||
poolSkinIndex))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -9,36 +9,21 @@
|
|||
|
||||
#include <athena/FileReader.hpp>
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
struct CMDL
|
||||
{
|
||||
static bool Extract(const SpecBase& dataSpec,
|
||||
PAKEntryReadStream& rs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry,
|
||||
bool force,
|
||||
hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
struct CMDL {
|
||||
static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
static void Name(const SpecBase& dataSpec,
|
||||
PAKEntryReadStream& rs,
|
||||
PAKRouter<PAKBridge>& pakRouter,
|
||||
PAK::Entry& entry)
|
||||
{
|
||||
DNACMDL::NameCMDL<PAKRouter<PAKBridge>, MaterialSet>(rs, pakRouter, entry, dataSpec);
|
||||
}
|
||||
static void Name(const SpecBase& dataSpec, PAKEntryReadStream& rs, PAKRouter<PAKBridge>& pakRouter,
|
||||
PAK::Entry& entry) {
|
||||
DNACMDL::NameCMDL<PAKRouter<PAKBridge>, MaterialSet>(rs, pakRouter, entry, dataSpec);
|
||||
}
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNACMDL::Mesh& mesh);
|
||||
static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNACMDL::Mesh& mesh);
|
||||
|
||||
static bool HMDLCook(const hecl::ProjectPath& outPath,
|
||||
const hecl::ProjectPath& inPath,
|
||||
const DNACMDL::Mesh& mesh);
|
||||
static bool HMDLCook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNACMDL::Mesh& mesh);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,411 +5,551 @@
|
|||
#include "DataSpec/DNACommon/CMDL.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
struct MaterialSet : BigDNA
|
||||
{
|
||||
static constexpr bool OneSection() {return false;}
|
||||
struct MaterialSet : BigDNA {
|
||||
static constexpr bool OneSection() { return false; }
|
||||
|
||||
AT_DECL_DNA
|
||||
struct MaterialSetHead : BigDNA {
|
||||
AT_DECL_DNA
|
||||
struct MaterialSetHead : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> textureCount = 0;
|
||||
Vector<UniqueID32, AT_DNA_COUNT(textureCount)> textureIDs;
|
||||
Value<atUint32> materialCount = 0;
|
||||
Vector<atUint32, AT_DNA_COUNT(materialCount)> materialEndOffs;
|
||||
Value<atUint32> textureCount = 0;
|
||||
Vector<UniqueID32, AT_DNA_COUNT(textureCount)> textureIDs;
|
||||
Value<atUint32> materialCount = 0;
|
||||
Vector<atUint32, AT_DNA_COUNT(materialCount)> materialEndOffs;
|
||||
|
||||
void addTexture(const UniqueID32& id) {textureIDs.push_back(id); ++textureCount;}
|
||||
void addMaterialEndOff(atUint32 off) {materialEndOffs.push_back(off); ++materialCount;}
|
||||
void addTexture(const UniqueID32& id) {
|
||||
textureIDs.push_back(id);
|
||||
++textureCount;
|
||||
}
|
||||
void addMaterialEndOff(atUint32 off) {
|
||||
materialEndOffs.push_back(off);
|
||||
++materialCount;
|
||||
}
|
||||
|
||||
template <class PAKBRIDGE>
|
||||
void ensureTexturesExtracted(PAKRouter<PAKBRIDGE>& pakRouter) const
|
||||
{
|
||||
for (const auto& id : textureIDs)
|
||||
{
|
||||
const nod::Node* node;
|
||||
const PAK::Entry* texEntry = pakRouter.lookupEntry(id, &node);
|
||||
if (!texEntry)
|
||||
continue;
|
||||
hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry);
|
||||
if (txtrPath.isNone())
|
||||
{
|
||||
txtrPath.makeDirChain(false);
|
||||
PAKEntryReadStream rs = texEntry->beginReadStream(*node);
|
||||
TXTR::Extract(rs, txtrPath);
|
||||
}
|
||||
}
|
||||
template <class PAKBRIDGE>
|
||||
void ensureTexturesExtracted(PAKRouter<PAKBRIDGE>& pakRouter) const {
|
||||
for (const auto& id : textureIDs) {
|
||||
const nod::Node* node;
|
||||
const PAK::Entry* texEntry = pakRouter.lookupEntry(id, &node);
|
||||
if (!texEntry)
|
||||
continue;
|
||||
hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry);
|
||||
if (txtrPath.isNone()) {
|
||||
txtrPath.makeDirChain(false);
|
||||
PAKEntryReadStream rs = texEntry->beginReadStream(*node);
|
||||
TXTR::Extract(rs, txtrPath);
|
||||
}
|
||||
} head;
|
||||
}
|
||||
}
|
||||
} head;
|
||||
|
||||
struct Material : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
struct Flags : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> flags = 0;
|
||||
bool konstValuesEnabled() const {return (flags & 0x8) != 0;}
|
||||
void setKonstValuesEnabled(bool enabled) {flags &= ~0x8; flags |= atUint32(enabled) << 3;}
|
||||
bool depthSorting() const {return (flags & 0x10) != 0;}
|
||||
void setDepthSorting(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;}
|
||||
bool alphaTest() const {return (flags & 0x20) != 0;}
|
||||
void setPunchthroughAlpha(bool enabled) {flags &= ~0x20; flags |= atUint32(enabled) << 5;}
|
||||
bool samusReflection() const {return (flags & 0x40) != 0;}
|
||||
void setSamusReflection(bool enabled) {flags &= ~0x40; flags |= atUint32(enabled) << 6;}
|
||||
bool depthWrite() const {return (flags & 0x80) != 0;}
|
||||
void setDepthWrite(bool enabled) {flags &= ~0x80; flags |= atUint32(enabled) << 7;}
|
||||
bool samusReflectionSurfaceEye() const {return (flags & 0x100) != 0;}
|
||||
void setSamusReflectionSurfaceEye(bool enabled) {flags &= ~0x100; flags |= atUint32(enabled) << 8;}
|
||||
bool shadowOccluderMesh() const {return (flags & 0x200) != 0;}
|
||||
void setShadowOccluderMesh(bool enabled) {flags &= ~0x200; flags |= atUint32(enabled) << 9;}
|
||||
bool samusReflectionIndirectTexture() const {return (flags & 0x400) != 0;}
|
||||
void setSamusReflectionIndirectTexture(bool enabled) {flags &= ~0x400; flags |= atUint32(enabled) << 10;}
|
||||
bool lightmap() const {return (flags & 0x800) != 0;}
|
||||
void setLightmap(bool enabled) {flags &= ~0x800; flags |= atUint32(enabled) << 11;}
|
||||
bool lightmapUVArray() const {return (flags & 0x2000) != 0;}
|
||||
void setLightmapUVArray(bool enabled) {flags &= ~0x2000; flags |= atUint32(enabled) << 13;}
|
||||
atUint16 textureSlots() const {return (flags >> 16) != 0;}
|
||||
void setTextureSlots(atUint16 texslots) {flags &= ~0xffff0000; flags |= atUint32(texslots) << 16;}
|
||||
} flags;
|
||||
const Flags& getFlags() const {return flags;}
|
||||
struct Material : BigDNA {
|
||||
AT_DECL_DNA
|
||||
struct Flags : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> flags = 0;
|
||||
bool konstValuesEnabled() const { return (flags & 0x8) != 0; }
|
||||
void setKonstValuesEnabled(bool enabled) {
|
||||
flags &= ~0x8;
|
||||
flags |= atUint32(enabled) << 3;
|
||||
}
|
||||
bool depthSorting() const { return (flags & 0x10) != 0; }
|
||||
void setDepthSorting(bool enabled) {
|
||||
flags &= ~0x10;
|
||||
flags |= atUint32(enabled) << 4;
|
||||
}
|
||||
bool alphaTest() const { return (flags & 0x20) != 0; }
|
||||
void setPunchthroughAlpha(bool enabled) {
|
||||
flags &= ~0x20;
|
||||
flags |= atUint32(enabled) << 5;
|
||||
}
|
||||
bool samusReflection() const { return (flags & 0x40) != 0; }
|
||||
void setSamusReflection(bool enabled) {
|
||||
flags &= ~0x40;
|
||||
flags |= atUint32(enabled) << 6;
|
||||
}
|
||||
bool depthWrite() const { return (flags & 0x80) != 0; }
|
||||
void setDepthWrite(bool enabled) {
|
||||
flags &= ~0x80;
|
||||
flags |= atUint32(enabled) << 7;
|
||||
}
|
||||
bool samusReflectionSurfaceEye() const { return (flags & 0x100) != 0; }
|
||||
void setSamusReflectionSurfaceEye(bool enabled) {
|
||||
flags &= ~0x100;
|
||||
flags |= atUint32(enabled) << 8;
|
||||
}
|
||||
bool shadowOccluderMesh() const { return (flags & 0x200) != 0; }
|
||||
void setShadowOccluderMesh(bool enabled) {
|
||||
flags &= ~0x200;
|
||||
flags |= atUint32(enabled) << 9;
|
||||
}
|
||||
bool samusReflectionIndirectTexture() const { return (flags & 0x400) != 0; }
|
||||
void setSamusReflectionIndirectTexture(bool enabled) {
|
||||
flags &= ~0x400;
|
||||
flags |= atUint32(enabled) << 10;
|
||||
}
|
||||
bool lightmap() const { return (flags & 0x800) != 0; }
|
||||
void setLightmap(bool enabled) {
|
||||
flags &= ~0x800;
|
||||
flags |= atUint32(enabled) << 11;
|
||||
}
|
||||
bool lightmapUVArray() const { return (flags & 0x2000) != 0; }
|
||||
void setLightmapUVArray(bool enabled) {
|
||||
flags &= ~0x2000;
|
||||
flags |= atUint32(enabled) << 13;
|
||||
}
|
||||
atUint16 textureSlots() const { return (flags >> 16) != 0; }
|
||||
void setTextureSlots(atUint16 texslots) {
|
||||
flags &= ~0xffff0000;
|
||||
flags |= atUint32(texslots) << 16;
|
||||
}
|
||||
} flags;
|
||||
const Flags& getFlags() const { return flags; }
|
||||
|
||||
Value<atUint32> textureCount = 0;
|
||||
Vector<atUint32, AT_DNA_COUNT(textureCount)> textureIdxs;
|
||||
struct VAFlags : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> vaFlags = 0;
|
||||
GX::AttrType position() const {return GX::AttrType(vaFlags & 0x3);}
|
||||
void setPosition(GX::AttrType val) {vaFlags &= ~0x3; vaFlags |= atUint32(val);}
|
||||
GX::AttrType normal() const {return GX::AttrType(vaFlags >> 2 & 0x3);}
|
||||
void setNormal(GX::AttrType val) {vaFlags &= ~0xC; vaFlags |= atUint32(val) << 2;}
|
||||
GX::AttrType color0() const {return GX::AttrType(vaFlags >> 4 & 0x3);}
|
||||
void setColor0(GX::AttrType val) {vaFlags &= ~0x30; vaFlags |= atUint32(val) << 4;}
|
||||
GX::AttrType color1() const {return GX::AttrType(vaFlags >> 6 & 0x3);}
|
||||
void setColor1(GX::AttrType val) {vaFlags &= ~0xC0; vaFlags |= atUint32(val) << 6;}
|
||||
GX::AttrType tex0() const {return GX::AttrType(vaFlags >> 8 & 0x3);}
|
||||
void setTex0(GX::AttrType val) {vaFlags &= ~0x300; vaFlags |= atUint32(val) << 8;}
|
||||
GX::AttrType tex1() const {return GX::AttrType(vaFlags >> 10 & 0x3);}
|
||||
void setTex1(GX::AttrType val) {vaFlags &= ~0xC00; vaFlags |= atUint32(val) << 10;}
|
||||
GX::AttrType tex2() const {return GX::AttrType(vaFlags >> 12 & 0x3);}
|
||||
void setTex2(GX::AttrType val) {vaFlags &= ~0x3000; vaFlags |= atUint32(val) << 12;}
|
||||
GX::AttrType tex3() const {return GX::AttrType(vaFlags >> 14 & 0x3);}
|
||||
void setTex3(GX::AttrType val) {vaFlags &= ~0xC000; vaFlags |= atUint32(val) << 14;}
|
||||
GX::AttrType tex4() const {return GX::AttrType(vaFlags >> 16 & 0x3);}
|
||||
void setTex4(GX::AttrType val) {vaFlags &= ~0x30000; vaFlags |= atUint32(val) << 16;}
|
||||
GX::AttrType tex5() const {return GX::AttrType(vaFlags >> 18 & 0x3);}
|
||||
void setTex5(GX::AttrType val) {vaFlags &= ~0xC0000; vaFlags |= atUint32(val) << 18;}
|
||||
GX::AttrType tex6() const {return GX::AttrType(vaFlags >> 20 & 0x3);}
|
||||
void setTex6(GX::AttrType val) {vaFlags &= ~0x300000; vaFlags |= atUint32(val) << 20;}
|
||||
GX::AttrType pnMatIdx() const {return GX::AttrType(vaFlags >> 24 & 0x1);}
|
||||
void setPnMatIdx(GX::AttrType val) {vaFlags &= ~0x1000000; vaFlags |= atUint32(val & 0x1) << 24;}
|
||||
GX::AttrType tex0MatIdx() const {return GX::AttrType(vaFlags >> 25 & 0x1);}
|
||||
void setTex0MatIdx(GX::AttrType val) {vaFlags &= ~0x2000000; vaFlags |= atUint32(val & 0x1) << 25;}
|
||||
GX::AttrType tex1MatIdx() const {return GX::AttrType(vaFlags >> 26 & 0x1);}
|
||||
void setTex1MatIdx(GX::AttrType val) {vaFlags &= ~0x4000000; vaFlags |= atUint32(val & 0x1) << 26;}
|
||||
GX::AttrType tex2MatIdx() const {return GX::AttrType(vaFlags >> 27 & 0x1);}
|
||||
void setTex2MatIdx(GX::AttrType val) {vaFlags &= ~0x8000000; vaFlags |= atUint32(val & 0x1) << 27;}
|
||||
GX::AttrType tex3MatIdx() const {return GX::AttrType(vaFlags >> 28 & 0x1);}
|
||||
void setTex3MatIdx(GX::AttrType val) {vaFlags &= ~0x10000000; vaFlags |= atUint32(val & 0x1) << 28;}
|
||||
GX::AttrType tex4MatIdx() const {return GX::AttrType(vaFlags >> 29 & 0x1);}
|
||||
void setTex4MatIdx(GX::AttrType val) {vaFlags &= ~0x20000000; vaFlags |= atUint32(val & 0x1) << 29;}
|
||||
GX::AttrType tex5MatIdx() const {return GX::AttrType(vaFlags >> 30 & 0x1);}
|
||||
void setTex5MatIdx(GX::AttrType val) {vaFlags &= ~0x40000000; vaFlags |= atUint32(val & 0x1) << 30;}
|
||||
GX::AttrType tex6MatIdx() const {return GX::AttrType(vaFlags >> 31 & 0x1);}
|
||||
void setTex6MatIdx(GX::AttrType val) {vaFlags &= ~0x80000000; vaFlags |= atUint32(val & 0x1) << 31;}
|
||||
Value<atUint32> textureCount = 0;
|
||||
Vector<atUint32, AT_DNA_COUNT(textureCount)> textureIdxs;
|
||||
struct VAFlags : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> vaFlags = 0;
|
||||
GX::AttrType position() const { return GX::AttrType(vaFlags & 0x3); }
|
||||
void setPosition(GX::AttrType val) {
|
||||
vaFlags &= ~0x3;
|
||||
vaFlags |= atUint32(val);
|
||||
}
|
||||
GX::AttrType normal() const { return GX::AttrType(vaFlags >> 2 & 0x3); }
|
||||
void setNormal(GX::AttrType val) {
|
||||
vaFlags &= ~0xC;
|
||||
vaFlags |= atUint32(val) << 2;
|
||||
}
|
||||
GX::AttrType color0() const { return GX::AttrType(vaFlags >> 4 & 0x3); }
|
||||
void setColor0(GX::AttrType val) {
|
||||
vaFlags &= ~0x30;
|
||||
vaFlags |= atUint32(val) << 4;
|
||||
}
|
||||
GX::AttrType color1() const { return GX::AttrType(vaFlags >> 6 & 0x3); }
|
||||
void setColor1(GX::AttrType val) {
|
||||
vaFlags &= ~0xC0;
|
||||
vaFlags |= atUint32(val) << 6;
|
||||
}
|
||||
GX::AttrType tex0() const { return GX::AttrType(vaFlags >> 8 & 0x3); }
|
||||
void setTex0(GX::AttrType val) {
|
||||
vaFlags &= ~0x300;
|
||||
vaFlags |= atUint32(val) << 8;
|
||||
}
|
||||
GX::AttrType tex1() const { return GX::AttrType(vaFlags >> 10 & 0x3); }
|
||||
void setTex1(GX::AttrType val) {
|
||||
vaFlags &= ~0xC00;
|
||||
vaFlags |= atUint32(val) << 10;
|
||||
}
|
||||
GX::AttrType tex2() const { return GX::AttrType(vaFlags >> 12 & 0x3); }
|
||||
void setTex2(GX::AttrType val) {
|
||||
vaFlags &= ~0x3000;
|
||||
vaFlags |= atUint32(val) << 12;
|
||||
}
|
||||
GX::AttrType tex3() const { return GX::AttrType(vaFlags >> 14 & 0x3); }
|
||||
void setTex3(GX::AttrType val) {
|
||||
vaFlags &= ~0xC000;
|
||||
vaFlags |= atUint32(val) << 14;
|
||||
}
|
||||
GX::AttrType tex4() const { return GX::AttrType(vaFlags >> 16 & 0x3); }
|
||||
void setTex4(GX::AttrType val) {
|
||||
vaFlags &= ~0x30000;
|
||||
vaFlags |= atUint32(val) << 16;
|
||||
}
|
||||
GX::AttrType tex5() const { return GX::AttrType(vaFlags >> 18 & 0x3); }
|
||||
void setTex5(GX::AttrType val) {
|
||||
vaFlags &= ~0xC0000;
|
||||
vaFlags |= atUint32(val) << 18;
|
||||
}
|
||||
GX::AttrType tex6() const { return GX::AttrType(vaFlags >> 20 & 0x3); }
|
||||
void setTex6(GX::AttrType val) {
|
||||
vaFlags &= ~0x300000;
|
||||
vaFlags |= atUint32(val) << 20;
|
||||
}
|
||||
GX::AttrType pnMatIdx() const { return GX::AttrType(vaFlags >> 24 & 0x1); }
|
||||
void setPnMatIdx(GX::AttrType val) {
|
||||
vaFlags &= ~0x1000000;
|
||||
vaFlags |= atUint32(val & 0x1) << 24;
|
||||
}
|
||||
GX::AttrType tex0MatIdx() const { return GX::AttrType(vaFlags >> 25 & 0x1); }
|
||||
void setTex0MatIdx(GX::AttrType val) {
|
||||
vaFlags &= ~0x2000000;
|
||||
vaFlags |= atUint32(val & 0x1) << 25;
|
||||
}
|
||||
GX::AttrType tex1MatIdx() const { return GX::AttrType(vaFlags >> 26 & 0x1); }
|
||||
void setTex1MatIdx(GX::AttrType val) {
|
||||
vaFlags &= ~0x4000000;
|
||||
vaFlags |= atUint32(val & 0x1) << 26;
|
||||
}
|
||||
GX::AttrType tex2MatIdx() const { return GX::AttrType(vaFlags >> 27 & 0x1); }
|
||||
void setTex2MatIdx(GX::AttrType val) {
|
||||
vaFlags &= ~0x8000000;
|
||||
vaFlags |= atUint32(val & 0x1) << 27;
|
||||
}
|
||||
GX::AttrType tex3MatIdx() const { return GX::AttrType(vaFlags >> 28 & 0x1); }
|
||||
void setTex3MatIdx(GX::AttrType val) {
|
||||
vaFlags &= ~0x10000000;
|
||||
vaFlags |= atUint32(val & 0x1) << 28;
|
||||
}
|
||||
GX::AttrType tex4MatIdx() const { return GX::AttrType(vaFlags >> 29 & 0x1); }
|
||||
void setTex4MatIdx(GX::AttrType val) {
|
||||
vaFlags &= ~0x20000000;
|
||||
vaFlags |= atUint32(val & 0x1) << 29;
|
||||
}
|
||||
GX::AttrType tex5MatIdx() const { return GX::AttrType(vaFlags >> 30 & 0x1); }
|
||||
void setTex5MatIdx(GX::AttrType val) {
|
||||
vaFlags &= ~0x40000000;
|
||||
vaFlags |= atUint32(val & 0x1) << 30;
|
||||
}
|
||||
GX::AttrType tex6MatIdx() const { return GX::AttrType(vaFlags >> 31 & 0x1); }
|
||||
void setTex6MatIdx(GX::AttrType val) {
|
||||
vaFlags &= ~0x80000000;
|
||||
vaFlags |= atUint32(val & 0x1) << 31;
|
||||
}
|
||||
|
||||
size_t vertDLSize() const
|
||||
{
|
||||
static size_t ATTR_SZ[] = {0,1,1,2};
|
||||
size_t ret = 0;
|
||||
ret += ATTR_SZ[position()];
|
||||
ret += ATTR_SZ[normal()];
|
||||
ret += ATTR_SZ[color0()];
|
||||
ret += ATTR_SZ[color1()];
|
||||
ret += ATTR_SZ[tex0()];
|
||||
ret += ATTR_SZ[tex1()];
|
||||
ret += ATTR_SZ[tex2()];
|
||||
ret += ATTR_SZ[tex3()];
|
||||
ret += ATTR_SZ[tex4()];
|
||||
ret += ATTR_SZ[tex5()];
|
||||
ret += ATTR_SZ[tex6()];
|
||||
ret += ATTR_SZ[pnMatIdx()];
|
||||
ret += ATTR_SZ[tex0MatIdx()];
|
||||
ret += ATTR_SZ[tex1MatIdx()];
|
||||
ret += ATTR_SZ[tex2MatIdx()];
|
||||
ret += ATTR_SZ[tex3MatIdx()];
|
||||
ret += ATTR_SZ[tex4MatIdx()];
|
||||
ret += ATTR_SZ[tex5MatIdx()];
|
||||
ret += ATTR_SZ[tex6MatIdx()];
|
||||
return ret;
|
||||
}
|
||||
} vaFlags;
|
||||
const VAFlags& getVAFlags() const {return vaFlags;}
|
||||
Value<atUint32> uniqueIdx;
|
||||
size_t vertDLSize() const {
|
||||
static size_t ATTR_SZ[] = {0, 1, 1, 2};
|
||||
size_t ret = 0;
|
||||
ret += ATTR_SZ[position()];
|
||||
ret += ATTR_SZ[normal()];
|
||||
ret += ATTR_SZ[color0()];
|
||||
ret += ATTR_SZ[color1()];
|
||||
ret += ATTR_SZ[tex0()];
|
||||
ret += ATTR_SZ[tex1()];
|
||||
ret += ATTR_SZ[tex2()];
|
||||
ret += ATTR_SZ[tex3()];
|
||||
ret += ATTR_SZ[tex4()];
|
||||
ret += ATTR_SZ[tex5()];
|
||||
ret += ATTR_SZ[tex6()];
|
||||
ret += ATTR_SZ[pnMatIdx()];
|
||||
ret += ATTR_SZ[tex0MatIdx()];
|
||||
ret += ATTR_SZ[tex1MatIdx()];
|
||||
ret += ATTR_SZ[tex2MatIdx()];
|
||||
ret += ATTR_SZ[tex3MatIdx()];
|
||||
ret += ATTR_SZ[tex4MatIdx()];
|
||||
ret += ATTR_SZ[tex5MatIdx()];
|
||||
ret += ATTR_SZ[tex6MatIdx()];
|
||||
return ret;
|
||||
}
|
||||
} vaFlags;
|
||||
const VAFlags& getVAFlags() const { return vaFlags; }
|
||||
Value<atUint32> uniqueIdx;
|
||||
|
||||
Vector<atUint32, AT_DNA_COUNT(flags.konstValuesEnabled())> konstCount;
|
||||
Vector<GX::Color, AT_DNA_COUNT(flags.konstValuesEnabled() ? konstCount[0] : 0)> konstColors;
|
||||
Vector<atUint32, AT_DNA_COUNT(flags.konstValuesEnabled())> konstCount;
|
||||
Vector<GX::Color, AT_DNA_COUNT(flags.konstValuesEnabled() ? konstCount[0] : 0)> konstColors;
|
||||
|
||||
using BlendFactor = GX::BlendFactor;
|
||||
Value<BlendFactor> blendDstFac;
|
||||
Value<BlendFactor> blendSrcFac;
|
||||
Vector<atUint32, AT_DNA_COUNT(flags.samusReflectionIndirectTexture())> indTexSlot;
|
||||
using BlendFactor = GX::BlendFactor;
|
||||
Value<BlendFactor> blendDstFac;
|
||||
Value<BlendFactor> blendSrcFac;
|
||||
Vector<atUint32, AT_DNA_COUNT(flags.samusReflectionIndirectTexture())> indTexSlot;
|
||||
|
||||
Value<atUint32> colorChannelCount = 0;
|
||||
struct ColorChannel : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> flags = 0;
|
||||
bool lighting() const {return (flags & 0x1) != 0;}
|
||||
void setLighting(bool enabled) {flags &= ~0x1; flags |= atUint32(enabled);}
|
||||
bool useAmbient() const {return (flags & 0x2) != 0;}
|
||||
void setUseAmbient(bool enabled) {flags &= ~0x2; flags |= atUint32(enabled) << 1;}
|
||||
bool useMaterial() const {return (flags & 0x4) != 0;}
|
||||
void setUseMaterial(bool enabled) {flags &= ~0x4; flags |= atUint32(enabled) << 2;}
|
||||
atUint8 lightmask() const {return atUint8(flags >> 3 & 0xff);}
|
||||
void setLightmask(atUint8 mask) {flags &= ~0x7f8; flags |= atUint32(mask) << 3;}
|
||||
GX::DiffuseFn diffuseFn() const {return GX::DiffuseFn(flags >> 11 & 0x3);}
|
||||
void setDiffuseFn(GX::DiffuseFn fn) {flags &= ~0x1800; flags |= atUint32(fn) << 11;}
|
||||
GX::AttnFn attenuationFn() const {return GX::AttnFn(flags >> 13 & 0x3);}
|
||||
void setAttenuationFn(GX::AttnFn fn) {flags &= ~0x6000; flags |= atUint32(fn) << 13;}
|
||||
};
|
||||
Vector<ColorChannel, AT_DNA_COUNT(colorChannelCount)> colorChannels;
|
||||
|
||||
Value<atUint32> tevStageCount = 0;
|
||||
struct TEVStage : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> ciFlags = 0;
|
||||
Value<atUint32> aiFlags = 0;
|
||||
Value<atUint32> ccFlags = 0;
|
||||
Value<atUint32> acFlags = 0;
|
||||
Value<atUint8> pad = 0;
|
||||
Value<atUint8> kaInput = 0;
|
||||
Value<atUint8> kcInput = 0;
|
||||
Value<atUint8> rascInput = 0;
|
||||
|
||||
GX::TevColorArg colorInA() const {return GX::TevColorArg(ciFlags & 0xf);}
|
||||
void setColorInA(GX::TevColorArg val) {ciFlags &= ~0x1f; ciFlags |= atUint32(val);}
|
||||
GX::TevColorArg colorInB() const {return GX::TevColorArg(ciFlags >> 5 & 0xf);}
|
||||
void setColorInB(GX::TevColorArg val) {ciFlags &= ~0x3e0; ciFlags |= atUint32(val) << 5;}
|
||||
GX::TevColorArg colorInC() const {return GX::TevColorArg(ciFlags >> 10 & 0xf);}
|
||||
void setColorInC(GX::TevColorArg val) {ciFlags &= ~0x7c00; ciFlags |= atUint32(val) << 10;}
|
||||
GX::TevColorArg colorInD() const {return GX::TevColorArg(ciFlags >> 15 & 0xf);}
|
||||
void setColorInD(GX::TevColorArg val) {ciFlags &= ~0xf8000; ciFlags |= atUint32(val) << 15;}
|
||||
|
||||
GX::TevAlphaArg alphaInA() const {return GX::TevAlphaArg(aiFlags & 0x7);}
|
||||
void setAlphaInA(GX::TevAlphaArg val) {aiFlags &= ~0x1f; aiFlags |= atUint32(val);}
|
||||
GX::TevAlphaArg alphaInB() const {return GX::TevAlphaArg(aiFlags >> 5 & 0x7);}
|
||||
void setAlphaInB(GX::TevAlphaArg val) {aiFlags &= ~0x3e0; aiFlags |= atUint32(val) << 5;}
|
||||
GX::TevAlphaArg alphaInC() const {return GX::TevAlphaArg(aiFlags >> 10 & 0x7);}
|
||||
void setAlphaInC(GX::TevAlphaArg val) {aiFlags &= ~0x7c00; aiFlags |= atUint32(val) << 10;}
|
||||
GX::TevAlphaArg alphaInD() const {return GX::TevAlphaArg(aiFlags >> 15 & 0x7);}
|
||||
void setAlphaInD(GX::TevAlphaArg val) {aiFlags &= ~0xf8000; aiFlags |= atUint32(val) << 15;}
|
||||
|
||||
GX::TevOp colorOp() const {return GX::TevOp(ccFlags & 0xf);}
|
||||
void setColorOp(GX::TevOp val) {ccFlags &= ~0x1; ccFlags |= atUint32(val);}
|
||||
GX::TevBias colorOpBias() const {return GX::TevBias(ccFlags >> 4 & 0x3);}
|
||||
void setColorOpBias(GX::TevBias val) {ccFlags &= ~0x30; ccFlags |= atUint32(val) << 4;}
|
||||
GX::TevScale colorOpScale() const {return GX::TevScale(ccFlags >> 6 & 0x3);}
|
||||
void setColorOpScale(GX::TevScale val) {ccFlags &= ~0xc0; ccFlags |= atUint32(val) << 6;}
|
||||
bool colorOpClamp() const {return ccFlags >> 8 & 0x1;}
|
||||
void setColorOpClamp(bool val) {ccFlags &= ~0x100; ccFlags |= atUint32(val) << 8;}
|
||||
GX::TevRegID colorOpOutReg() const {return GX::TevRegID(ccFlags >> 9 & 0x3);}
|
||||
void setColorOpOutReg(GX::TevRegID val) {ccFlags &= ~0x600; ccFlags |= atUint32(val) << 9;}
|
||||
|
||||
GX::TevOp alphaOp() const {return GX::TevOp(acFlags & 0xf);}
|
||||
void setAlphaOp(GX::TevOp val) {acFlags &= ~0x1; acFlags |= atUint32(val);}
|
||||
GX::TevBias alphaOpBias() const {return GX::TevBias(acFlags >> 4 & 0x3);}
|
||||
void setAlphaOpBias(GX::TevBias val) {acFlags &= ~0x30; acFlags |= atUint32(val) << 4;}
|
||||
GX::TevScale alphaOpScale() const {return GX::TevScale(acFlags >> 6 & 0x3);}
|
||||
void setAlphaOpScale(GX::TevScale val) {acFlags &= ~0xc0; acFlags |= atUint32(val) << 6;}
|
||||
bool alphaOpClamp() const {return acFlags >> 8 & 0x1;}
|
||||
void setAlphaOpClamp(bool val) {acFlags &= ~0x100; acFlags |= atUint32(val) << 8;}
|
||||
GX::TevRegID alphaOpOutReg() const {return GX::TevRegID(acFlags >> 9 & 0x3);}
|
||||
void setAlphaOpOutReg(GX::TevRegID val) {acFlags &= ~0x600; acFlags |= atUint32(val) << 9;}
|
||||
|
||||
GX::TevKColorSel kColorIn() const {return GX::TevKColorSel(kcInput);}
|
||||
void setKColorIn(GX::TevKColorSel val) {kcInput = val;}
|
||||
GX::TevKAlphaSel kAlphaIn() const {return GX::TevKAlphaSel(kaInput);}
|
||||
void setKAlphaIn(GX::TevKAlphaSel val) {kaInput = val;}
|
||||
|
||||
GX::ChannelID rasIn() const {return GX::ChannelID(rascInput);}
|
||||
void setRASIn(GX::ChannelID id) {rascInput = id;}
|
||||
};
|
||||
Vector<TEVStage, AT_DNA_COUNT(tevStageCount)> tevStages;
|
||||
struct TEVStageTexInfo : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint16> pad = 0;
|
||||
Value<atUint8> texSlot = 0xff;
|
||||
Value<atUint8> tcgSlot = 0xff;
|
||||
};
|
||||
Vector<TEVStageTexInfo, AT_DNA_COUNT(tevStageCount)> tevStageTexInfo;
|
||||
|
||||
Value<atUint32> tcgCount = 0;
|
||||
struct TexCoordGen : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> flags = 0;
|
||||
|
||||
GX::TexGenType type() const {return GX::TexGenType(flags & 0xf);}
|
||||
void setType(GX::TexGenType val) {flags &= ~0xf; flags |= atUint32(val);}
|
||||
GX::TexGenSrc source() const {return GX::TexGenSrc(flags >> 4 & 0x1f);}
|
||||
void setSource(GX::TexGenSrc val) {flags &= ~0x1f0; flags |= atUint32(val) << 4;}
|
||||
GX::TexMtx mtx() const {return GX::TexMtx((flags >> 9 & 0x1f) + 30);}
|
||||
void setMtx(GX::TexMtx val) {flags &= ~0x3e00; flags |= (atUint32(val)-30) << 9;}
|
||||
bool normalize() const {return flags >> 14 & 0x1;}
|
||||
void setNormalize(bool val) {flags &= ~0x4000; flags |= atUint32(val) << 14;}
|
||||
GX::PTTexMtx postMtx() const {return GX::PTTexMtx((flags >> 15 & 0x3f) + 64);}
|
||||
void setPostMtx(GX::PTTexMtx val) {flags &= ~0x1f8000; flags |= (atUint32(val)-64) << 15;}
|
||||
};
|
||||
Vector<TexCoordGen, AT_DNA_COUNT(tcgCount)> tcgs;
|
||||
|
||||
Value<atUint32> uvAnimsSize = 4;
|
||||
Value<atUint32> uvAnimsCount = 0;
|
||||
struct UVAnimation : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
enum class Mode
|
||||
{
|
||||
MvInvNoTranslation,
|
||||
MvInv,
|
||||
Scroll,
|
||||
Rotation,
|
||||
HStrip,
|
||||
VStrip,
|
||||
Model,
|
||||
CylinderEnvironment,
|
||||
Eight
|
||||
} mode;
|
||||
float vals[9];
|
||||
|
||||
UVAnimation() = default;
|
||||
UVAnimation(const std::string& gameFunction,
|
||||
const std::vector<atVec4f>& gameArgs);
|
||||
};
|
||||
Vector<UVAnimation, AT_DNA_COUNT(uvAnimsCount)> uvAnims;
|
||||
|
||||
static void AddTexture(hecl::blender::PyOutStream& out,
|
||||
GX::TexGenSrc type, int mtxIdx, uint32_t texIdx);
|
||||
static void AddTextureAnim(hecl::blender::PyOutStream& out,
|
||||
MaterialSet::Material::UVAnimation::Mode type,
|
||||
unsigned idx, const float* vals);
|
||||
static void AddKcolor(hecl::blender::PyOutStream& out,
|
||||
const GX::Color& col, unsigned idx);
|
||||
static void AddDynamicColor(hecl::blender::PyOutStream& out, unsigned idx);
|
||||
static void AddDynamicAlpha(hecl::blender::PyOutStream& out, unsigned idx);
|
||||
|
||||
Material() = default;
|
||||
Material(const hecl::Backend::GX& gx,
|
||||
const std::unordered_map<std::string, int32_t>& iprops,
|
||||
const std::vector<hecl::ProjectPath>& texPathsIn,
|
||||
std::vector<hecl::ProjectPath>& texPathsOut,
|
||||
int colorCount,
|
||||
bool lightmapUVs,
|
||||
bool matrixSkinning);
|
||||
Value<atUint32> colorChannelCount = 0;
|
||||
struct ColorChannel : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> flags = 0;
|
||||
bool lighting() const { return (flags & 0x1) != 0; }
|
||||
void setLighting(bool enabled) {
|
||||
flags &= ~0x1;
|
||||
flags |= atUint32(enabled);
|
||||
}
|
||||
bool useAmbient() const { return (flags & 0x2) != 0; }
|
||||
void setUseAmbient(bool enabled) {
|
||||
flags &= ~0x2;
|
||||
flags |= atUint32(enabled) << 1;
|
||||
}
|
||||
bool useMaterial() const { return (flags & 0x4) != 0; }
|
||||
void setUseMaterial(bool enabled) {
|
||||
flags &= ~0x4;
|
||||
flags |= atUint32(enabled) << 2;
|
||||
}
|
||||
atUint8 lightmask() const { return atUint8(flags >> 3 & 0xff); }
|
||||
void setLightmask(atUint8 mask) {
|
||||
flags &= ~0x7f8;
|
||||
flags |= atUint32(mask) << 3;
|
||||
}
|
||||
GX::DiffuseFn diffuseFn() const { return GX::DiffuseFn(flags >> 11 & 0x3); }
|
||||
void setDiffuseFn(GX::DiffuseFn fn) {
|
||||
flags &= ~0x1800;
|
||||
flags |= atUint32(fn) << 11;
|
||||
}
|
||||
GX::AttnFn attenuationFn() const { return GX::AttnFn(flags >> 13 & 0x3); }
|
||||
void setAttenuationFn(GX::AttnFn fn) {
|
||||
flags &= ~0x6000;
|
||||
flags |= atUint32(fn) << 13;
|
||||
}
|
||||
};
|
||||
Vector<Material, AT_DNA_COUNT(head.materialCount)> materials;
|
||||
Vector<ColorChannel, AT_DNA_COUNT(colorChannelCount)> colorChannels;
|
||||
|
||||
static void RegisterMaterialProps(hecl::blender::PyOutStream& out);
|
||||
static void ConstructMaterial(hecl::blender::PyOutStream& out,
|
||||
const MaterialSet::Material& material,
|
||||
unsigned groupIdx, unsigned matIdx);
|
||||
Value<atUint32> tevStageCount = 0;
|
||||
struct TEVStage : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> ciFlags = 0;
|
||||
Value<atUint32> aiFlags = 0;
|
||||
Value<atUint32> ccFlags = 0;
|
||||
Value<atUint32> acFlags = 0;
|
||||
Value<atUint8> pad = 0;
|
||||
Value<atUint8> kaInput = 0;
|
||||
Value<atUint8> kcInput = 0;
|
||||
Value<atUint8> rascInput = 0;
|
||||
|
||||
void readToBlender(hecl::blender::PyOutStream& os,
|
||||
const PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAKRouter<PAKBridge>::EntryType& entry,
|
||||
unsigned setIdx)
|
||||
{
|
||||
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx);
|
||||
}
|
||||
GX::TevColorArg colorInA() const { return GX::TevColorArg(ciFlags & 0xf); }
|
||||
void setColorInA(GX::TevColorArg val) {
|
||||
ciFlags &= ~0x1f;
|
||||
ciFlags |= atUint32(val);
|
||||
}
|
||||
GX::TevColorArg colorInB() const { return GX::TevColorArg(ciFlags >> 5 & 0xf); }
|
||||
void setColorInB(GX::TevColorArg val) {
|
||||
ciFlags &= ~0x3e0;
|
||||
ciFlags |= atUint32(val) << 5;
|
||||
}
|
||||
GX::TevColorArg colorInC() const { return GX::TevColorArg(ciFlags >> 10 & 0xf); }
|
||||
void setColorInC(GX::TevColorArg val) {
|
||||
ciFlags &= ~0x7c00;
|
||||
ciFlags |= atUint32(val) << 10;
|
||||
}
|
||||
GX::TevColorArg colorInD() const { return GX::TevColorArg(ciFlags >> 15 & 0xf); }
|
||||
void setColorInD(GX::TevColorArg val) {
|
||||
ciFlags &= ~0xf8000;
|
||||
ciFlags |= atUint32(val) << 15;
|
||||
}
|
||||
|
||||
template <class PAKRouter>
|
||||
void nameTextures(PAKRouter& pakRouter, const char* prefix, int setIdx) const
|
||||
{
|
||||
int matIdx = 0;
|
||||
for (const Material& mat : materials)
|
||||
{
|
||||
int stageIdx = 0;
|
||||
for (const Material::TEVStage& stage : mat.tevStages)
|
||||
{
|
||||
(void)stage;
|
||||
const Material::TEVStageTexInfo& texInfo = mat.tevStageTexInfo[stageIdx];
|
||||
if (texInfo.texSlot == 0xff)
|
||||
{
|
||||
++stageIdx;
|
||||
continue;
|
||||
}
|
||||
const nod::Node* node;
|
||||
typename PAKRouter::EntryType* texEntry = (typename PAKRouter::EntryType*)
|
||||
pakRouter.lookupEntry(head.textureIDs[mat.textureIdxs[texInfo.texSlot]], &node);
|
||||
if (texEntry->name.size())
|
||||
{
|
||||
if (texEntry->name.size() < 5 || texEntry->name.compare(0, 5, "mult_"))
|
||||
texEntry->name = "mult_" + texEntry->name;
|
||||
++stageIdx;
|
||||
continue;
|
||||
}
|
||||
if (setIdx < 0)
|
||||
texEntry->name = hecl::Format("%s_%d_%d", prefix, matIdx, stageIdx);
|
||||
else
|
||||
texEntry->name = hecl::Format("%s_%d_%d_%d", prefix, setIdx, matIdx, stageIdx);
|
||||
GX::TevAlphaArg alphaInA() const { return GX::TevAlphaArg(aiFlags & 0x7); }
|
||||
void setAlphaInA(GX::TevAlphaArg val) {
|
||||
aiFlags &= ~0x1f;
|
||||
aiFlags |= atUint32(val);
|
||||
}
|
||||
GX::TevAlphaArg alphaInB() const { return GX::TevAlphaArg(aiFlags >> 5 & 0x7); }
|
||||
void setAlphaInB(GX::TevAlphaArg val) {
|
||||
aiFlags &= ~0x3e0;
|
||||
aiFlags |= atUint32(val) << 5;
|
||||
}
|
||||
GX::TevAlphaArg alphaInC() const { return GX::TevAlphaArg(aiFlags >> 10 & 0x7); }
|
||||
void setAlphaInC(GX::TevAlphaArg val) {
|
||||
aiFlags &= ~0x7c00;
|
||||
aiFlags |= atUint32(val) << 10;
|
||||
}
|
||||
GX::TevAlphaArg alphaInD() const { return GX::TevAlphaArg(aiFlags >> 15 & 0x7); }
|
||||
void setAlphaInD(GX::TevAlphaArg val) {
|
||||
aiFlags &= ~0xf8000;
|
||||
aiFlags |= atUint32(val) << 15;
|
||||
}
|
||||
|
||||
if (mat.flags.lightmap() && stageIdx == 0)
|
||||
{
|
||||
texEntry->name += "light";
|
||||
++stageIdx;
|
||||
continue;
|
||||
}
|
||||
GX::TevOp colorOp() const { return GX::TevOp(ccFlags & 0xf); }
|
||||
void setColorOp(GX::TevOp val) {
|
||||
ccFlags &= ~0x1;
|
||||
ccFlags |= atUint32(val);
|
||||
}
|
||||
GX::TevBias colorOpBias() const { return GX::TevBias(ccFlags >> 4 & 0x3); }
|
||||
void setColorOpBias(GX::TevBias val) {
|
||||
ccFlags &= ~0x30;
|
||||
ccFlags |= atUint32(val) << 4;
|
||||
}
|
||||
GX::TevScale colorOpScale() const { return GX::TevScale(ccFlags >> 6 & 0x3); }
|
||||
void setColorOpScale(GX::TevScale val) {
|
||||
ccFlags &= ~0xc0;
|
||||
ccFlags |= atUint32(val) << 6;
|
||||
}
|
||||
bool colorOpClamp() const { return ccFlags >> 8 & 0x1; }
|
||||
void setColorOpClamp(bool val) {
|
||||
ccFlags &= ~0x100;
|
||||
ccFlags |= atUint32(val) << 8;
|
||||
}
|
||||
GX::TevRegID colorOpOutReg() const { return GX::TevRegID(ccFlags >> 9 & 0x3); }
|
||||
void setColorOpOutReg(GX::TevRegID val) {
|
||||
ccFlags &= ~0x600;
|
||||
ccFlags |= atUint32(val) << 9;
|
||||
}
|
||||
|
||||
++stageIdx;
|
||||
}
|
||||
++matIdx;
|
||||
GX::TevOp alphaOp() const { return GX::TevOp(acFlags & 0xf); }
|
||||
void setAlphaOp(GX::TevOp val) {
|
||||
acFlags &= ~0x1;
|
||||
acFlags |= atUint32(val);
|
||||
}
|
||||
GX::TevBias alphaOpBias() const { return GX::TevBias(acFlags >> 4 & 0x3); }
|
||||
void setAlphaOpBias(GX::TevBias val) {
|
||||
acFlags &= ~0x30;
|
||||
acFlags |= atUint32(val) << 4;
|
||||
}
|
||||
GX::TevScale alphaOpScale() const { return GX::TevScale(acFlags >> 6 & 0x3); }
|
||||
void setAlphaOpScale(GX::TevScale val) {
|
||||
acFlags &= ~0xc0;
|
||||
acFlags |= atUint32(val) << 6;
|
||||
}
|
||||
bool alphaOpClamp() const { return acFlags >> 8 & 0x1; }
|
||||
void setAlphaOpClamp(bool val) {
|
||||
acFlags &= ~0x100;
|
||||
acFlags |= atUint32(val) << 8;
|
||||
}
|
||||
GX::TevRegID alphaOpOutReg() const { return GX::TevRegID(acFlags >> 9 & 0x3); }
|
||||
void setAlphaOpOutReg(GX::TevRegID val) {
|
||||
acFlags &= ~0x600;
|
||||
acFlags |= atUint32(val) << 9;
|
||||
}
|
||||
|
||||
GX::TevKColorSel kColorIn() const { return GX::TevKColorSel(kcInput); }
|
||||
void setKColorIn(GX::TevKColorSel val) { kcInput = val; }
|
||||
GX::TevKAlphaSel kAlphaIn() const { return GX::TevKAlphaSel(kaInput); }
|
||||
void setKAlphaIn(GX::TevKAlphaSel val) { kaInput = val; }
|
||||
|
||||
GX::ChannelID rasIn() const { return GX::ChannelID(rascInput); }
|
||||
void setRASIn(GX::ChannelID id) { rascInput = id; }
|
||||
};
|
||||
Vector<TEVStage, AT_DNA_COUNT(tevStageCount)> tevStages;
|
||||
struct TEVStageTexInfo : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint16> pad = 0;
|
||||
Value<atUint8> texSlot = 0xff;
|
||||
Value<atUint8> tcgSlot = 0xff;
|
||||
};
|
||||
Vector<TEVStageTexInfo, AT_DNA_COUNT(tevStageCount)> tevStageTexInfo;
|
||||
|
||||
Value<atUint32> tcgCount = 0;
|
||||
struct TexCoordGen : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> flags = 0;
|
||||
|
||||
GX::TexGenType type() const { return GX::TexGenType(flags & 0xf); }
|
||||
void setType(GX::TexGenType val) {
|
||||
flags &= ~0xf;
|
||||
flags |= atUint32(val);
|
||||
}
|
||||
GX::TexGenSrc source() const { return GX::TexGenSrc(flags >> 4 & 0x1f); }
|
||||
void setSource(GX::TexGenSrc val) {
|
||||
flags &= ~0x1f0;
|
||||
flags |= atUint32(val) << 4;
|
||||
}
|
||||
GX::TexMtx mtx() const { return GX::TexMtx((flags >> 9 & 0x1f) + 30); }
|
||||
void setMtx(GX::TexMtx val) {
|
||||
flags &= ~0x3e00;
|
||||
flags |= (atUint32(val) - 30) << 9;
|
||||
}
|
||||
bool normalize() const { return flags >> 14 & 0x1; }
|
||||
void setNormalize(bool val) {
|
||||
flags &= ~0x4000;
|
||||
flags |= atUint32(val) << 14;
|
||||
}
|
||||
GX::PTTexMtx postMtx() const { return GX::PTTexMtx((flags >> 15 & 0x3f) + 64); }
|
||||
void setPostMtx(GX::PTTexMtx val) {
|
||||
flags &= ~0x1f8000;
|
||||
flags |= (atUint32(val) - 64) << 15;
|
||||
}
|
||||
};
|
||||
Vector<TexCoordGen, AT_DNA_COUNT(tcgCount)> tcgs;
|
||||
|
||||
Value<atUint32> uvAnimsSize = 4;
|
||||
Value<atUint32> uvAnimsCount = 0;
|
||||
struct UVAnimation : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
enum class Mode {
|
||||
MvInvNoTranslation,
|
||||
MvInv,
|
||||
Scroll,
|
||||
Rotation,
|
||||
HStrip,
|
||||
VStrip,
|
||||
Model,
|
||||
CylinderEnvironment,
|
||||
Eight
|
||||
} mode;
|
||||
float vals[9];
|
||||
|
||||
UVAnimation() = default;
|
||||
UVAnimation(const std::string& gameFunction, const std::vector<atVec4f>& gameArgs);
|
||||
};
|
||||
Vector<UVAnimation, AT_DNA_COUNT(uvAnimsCount)> uvAnims;
|
||||
|
||||
static void AddTexture(hecl::blender::PyOutStream& out, GX::TexGenSrc type, int mtxIdx, uint32_t texIdx);
|
||||
static void AddTextureAnim(hecl::blender::PyOutStream& out, MaterialSet::Material::UVAnimation::Mode type,
|
||||
unsigned idx, const float* vals);
|
||||
static void AddKcolor(hecl::blender::PyOutStream& out, const GX::Color& col, unsigned idx);
|
||||
static void AddDynamicColor(hecl::blender::PyOutStream& out, unsigned idx);
|
||||
static void AddDynamicAlpha(hecl::blender::PyOutStream& out, unsigned idx);
|
||||
|
||||
Material() = default;
|
||||
Material(const hecl::Backend::GX& gx, const std::unordered_map<std::string, int32_t>& iprops,
|
||||
const std::vector<hecl::ProjectPath>& texPathsIn, std::vector<hecl::ProjectPath>& texPathsOut,
|
||||
int colorCount, bool lightmapUVs, bool matrixSkinning);
|
||||
};
|
||||
Vector<Material, AT_DNA_COUNT(head.materialCount)> materials;
|
||||
|
||||
static void RegisterMaterialProps(hecl::blender::PyOutStream& out);
|
||||
static void ConstructMaterial(hecl::blender::PyOutStream& out, const MaterialSet::Material& material,
|
||||
unsigned groupIdx, unsigned matIdx);
|
||||
|
||||
void readToBlender(hecl::blender::PyOutStream& os, const PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAKRouter<PAKBridge>::EntryType& entry, unsigned setIdx) {
|
||||
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx);
|
||||
}
|
||||
|
||||
template <class PAKRouter>
|
||||
void nameTextures(PAKRouter& pakRouter, const char* prefix, int setIdx) const {
|
||||
int matIdx = 0;
|
||||
for (const Material& mat : materials) {
|
||||
int stageIdx = 0;
|
||||
for (const Material::TEVStage& stage : mat.tevStages) {
|
||||
(void)stage;
|
||||
const Material::TEVStageTexInfo& texInfo = mat.tevStageTexInfo[stageIdx];
|
||||
if (texInfo.texSlot == 0xff) {
|
||||
++stageIdx;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const nod::Node* node;
|
||||
typename PAKRouter::EntryType* texEntry = (typename PAKRouter::EntryType*)pakRouter.lookupEntry(
|
||||
head.textureIDs[mat.textureIdxs[texInfo.texSlot]], &node);
|
||||
if (texEntry->name.size()) {
|
||||
if (texEntry->name.size() < 5 || texEntry->name.compare(0, 5, "mult_"))
|
||||
texEntry->name = "mult_" + texEntry->name;
|
||||
++stageIdx;
|
||||
continue;
|
||||
}
|
||||
if (setIdx < 0)
|
||||
texEntry->name = hecl::Format("%s_%d_%d", prefix, matIdx, stageIdx);
|
||||
else
|
||||
texEntry->name = hecl::Format("%s_%d_%d_%d", prefix, setIdx, matIdx, stageIdx);
|
||||
|
||||
void ensureTexturesExtracted(PAKRouter<PAKBridge>& pakRouter) const
|
||||
{
|
||||
head.ensureTexturesExtracted(pakRouter);
|
||||
if (mat.flags.lightmap() && stageIdx == 0) {
|
||||
texEntry->name += "light";
|
||||
++stageIdx;
|
||||
continue;
|
||||
}
|
||||
|
||||
++stageIdx;
|
||||
}
|
||||
++matIdx;
|
||||
}
|
||||
}
|
||||
|
||||
void ensureTexturesExtracted(PAKRouter<PAKBridge>& pakRouter) const { head.ensureTexturesExtracted(pakRouter); }
|
||||
};
|
||||
|
||||
struct HMDLMaterialSet : BigDNA
|
||||
{
|
||||
static constexpr bool OneSection() {return false;}
|
||||
struct HMDLMaterialSet : BigDNA {
|
||||
static constexpr bool OneSection() { return false; }
|
||||
|
||||
AT_DECL_DNA
|
||||
MaterialSet::MaterialSetHead head;
|
||||
|
||||
struct Material : BigDNA {
|
||||
AT_DECL_DNA
|
||||
MaterialSet::MaterialSetHead head;
|
||||
MaterialSet::Material::Flags flags;
|
||||
|
||||
struct Material : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
MaterialSet::Material::Flags flags;
|
||||
Value<atUint32> textureCount = 0;
|
||||
Vector<atUint32, AT_DNA_COUNT(textureCount)> textureIdxs;
|
||||
|
||||
Value<atUint32> textureCount = 0;
|
||||
Vector<atUint32, AT_DNA_COUNT(textureCount)> textureIdxs;
|
||||
Vector<atUint32, AT_DNA_COUNT(flags.samusReflectionIndirectTexture())> indTexSlot;
|
||||
|
||||
Vector<atUint32, AT_DNA_COUNT(flags.samusReflectionIndirectTexture())> indTexSlot;
|
||||
Value<atUint32> uvAnimsSize = 4;
|
||||
Value<atUint32> uvAnimsCount = 0;
|
||||
Vector<MaterialSet::Material::UVAnimation, AT_DNA_COUNT(uvAnimsCount)> uvAnims;
|
||||
|
||||
Value<atUint32> uvAnimsSize = 4;
|
||||
Value<atUint32> uvAnimsCount = 0;
|
||||
Vector<MaterialSet::Material::UVAnimation, AT_DNA_COUNT(uvAnimsCount)> uvAnims;
|
||||
String<-1> heclSource;
|
||||
hecl::Frontend::IR heclIr;
|
||||
|
||||
String<-1> heclSource;
|
||||
hecl::Frontend::IR heclIr;
|
||||
|
||||
Material() = default;
|
||||
Material(hecl::Frontend::Frontend& FE,
|
||||
const std::string& diagName,
|
||||
const hecl::blender::Material& mat,
|
||||
const std::unordered_map<std::string, int32_t>& iprops,
|
||||
const std::vector<hecl::ProjectPath>& texPaths);
|
||||
};
|
||||
Vector<Material, AT_DNA_COUNT(head.materialCount)> materials;
|
||||
Material() = default;
|
||||
Material(hecl::Frontend::Frontend& FE, const std::string& diagName, const hecl::blender::Material& mat,
|
||||
const std::unordered_map<std::string, int32_t>& iprops, const std::vector<hecl::ProjectPath>& texPaths);
|
||||
};
|
||||
Vector<Material, AT_DNA_COUNT(head.materialCount)> materials;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -1,21 +1,16 @@
|
|||
#include "CSKR.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const
|
||||
{
|
||||
atUint32 accum = 0;
|
||||
for (const SkinningRule& rule : skinningRules)
|
||||
{
|
||||
if (idx >= accum && idx < accum + rule.vertCount)
|
||||
for (const SkinningRule::Weight& weight : rule.weights)
|
||||
os.format("vert[dvert_lay][%u] = %f\n",
|
||||
cinf.getBoneIdxFromId(weight.boneId),
|
||||
weight.weight);
|
||||
accum += rule.vertCount;
|
||||
}
|
||||
void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const {
|
||||
atUint32 accum = 0;
|
||||
for (const SkinningRule& rule : skinningRules) {
|
||||
if (idx >= accum && idx < accum + rule.vertCount)
|
||||
for (const SkinningRule::Weight& weight : rule.weights)
|
||||
os.format("vert[dvert_lay][%u] = %f\n", cinf.getBoneIdxFromId(weight.boneId), weight.weight);
|
||||
accum += rule.vertCount;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -3,35 +3,27 @@
|
|||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "CINF.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
struct CSKR : BigDNA
|
||||
{
|
||||
struct CSKR : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> skinningRuleCount;
|
||||
struct SkinningRule : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> skinningRuleCount;
|
||||
struct SkinningRule : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> weightCount;
|
||||
struct Weight : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> boneId;
|
||||
Value<float> weight;
|
||||
};
|
||||
Vector<Weight, AT_DNA_COUNT(weightCount)> weights;
|
||||
Value<atUint32> vertCount;
|
||||
Value<atUint32> weightCount;
|
||||
struct Weight : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> boneId;
|
||||
Value<float> weight;
|
||||
};
|
||||
Vector<SkinningRule, AT_DNA_COUNT(skinningRuleCount)> skinningRules;
|
||||
Vector<Weight, AT_DNA_COUNT(weightCount)> weights;
|
||||
Value<atUint32> vertCount;
|
||||
};
|
||||
Vector<SkinningRule, AT_DNA_COUNT(skinningRuleCount)> skinningRules;
|
||||
|
||||
const atInt16* getMatrixBank(size_t) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const atInt16* getMatrixBank(size_t) const { return nullptr; }
|
||||
|
||||
void weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const;
|
||||
void weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -1,102 +1,99 @@
|
|||
#include "CSNG.hpp"
|
||||
#include "amuse/SongConverter.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
bool CSNG::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
hecl::ProjectPath midPath = outPath.getWithExtension(_SYS_STR(".mid"), true);
|
||||
hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true);
|
||||
bool CSNG::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
hecl::ProjectPath midPath = outPath.getWithExtension(_SYS_STR(".mid"), true);
|
||||
hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true);
|
||||
|
||||
Header head;
|
||||
head.read(rs);
|
||||
|
||||
{
|
||||
athena::io::YAMLDocWriter dw("CSNG");
|
||||
dw.writeUint32("midiSetupId", head.midiSetupId);
|
||||
dw.writeUint32("songGroupId", head.songGroupId);
|
||||
if (auto rec = dw.enterSubRecord("agscId"))
|
||||
head.agscId.write(dw);
|
||||
|
||||
athena::io::FileWriter w(yamlPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
dw.finish(&w);
|
||||
}
|
||||
|
||||
{
|
||||
auto sng = rs.readUBytes(head.sngLength);
|
||||
int version;
|
||||
bool isBig;
|
||||
auto midi = amuse::SongConverter::SongToMIDI(sng.get(), version, isBig);
|
||||
|
||||
athena::io::FileWriter w(midPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
w.writeUBytes(midi.data(), midi.size());
|
||||
}
|
||||
|
||||
/* Update !songs.yaml for Amuse editor */
|
||||
hecl::ProjectPath audGrp(outPath.getParentPath().getParentPath(), _SYS_STR("AudioGrp"));
|
||||
audGrp.makeDirChain(true);
|
||||
hecl::ProjectPath songsPath(audGrp, _SYS_STR("!songs.yaml"));
|
||||
std::experimental::optional<athena::io::FileReader> r;
|
||||
if (songsPath.isFile())
|
||||
r.emplace(songsPath.getAbsolutePath());
|
||||
athena::io::YAMLDocWriter ydw("amuse::Songs", r ? &*r : nullptr);
|
||||
r = std::experimental::nullopt;
|
||||
char id[16];
|
||||
snprintf(id, 16, "%04X", head.midiSetupId);
|
||||
ydw.writeString(id, hecl::Format("../MidiData/%s", midPath.getLastComponentUTF8().data()));
|
||||
athena::io::FileWriter w(songsPath.getAbsolutePath());
|
||||
ydw.finish(&w);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSNG::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) {
|
||||
hecl::ProjectPath midPath = inPath.getWithExtension(_SYS_STR(".mid"), true);
|
||||
hecl::ProjectPath yamlPath = inPath.getWithExtension(_SYS_STR(".yaml"), true);
|
||||
|
||||
std::vector<uint8_t> sngData;
|
||||
{
|
||||
athena::io::FileReader midR(midPath.getAbsolutePath());
|
||||
if (midR.hasError())
|
||||
return false;
|
||||
|
||||
uint32_t midLen = midR.length();
|
||||
std::vector<uint8_t> midData;
|
||||
midData.resize(midLen);
|
||||
midR.readUBytesToBuf(midData.data(), midLen);
|
||||
sngData = amuse::SongConverter::MIDIToSong(midData, 1, true);
|
||||
}
|
||||
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
|
||||
{
|
||||
athena::io::FileReader yamlR(yamlPath.getAbsolutePath());
|
||||
if (yamlR.hasError())
|
||||
return false;
|
||||
athena::io::YAMLDocReader dr;
|
||||
if (!dr.parse(&yamlR))
|
||||
return false;
|
||||
|
||||
Header head;
|
||||
head.read(rs);
|
||||
head.midiSetupId = dr.readUint32("midiSetupId");
|
||||
head.songGroupId = dr.readUint32("songGroupId");
|
||||
if (auto rec = dr.enterSubRecord("agscId"))
|
||||
head.agscId.read(dr);
|
||||
head.sngLength = sngData.size();
|
||||
head.write(w);
|
||||
}
|
||||
|
||||
{
|
||||
athena::io::YAMLDocWriter dw("CSNG");
|
||||
dw.writeUint32("midiSetupId", head.midiSetupId);
|
||||
dw.writeUint32("songGroupId", head.songGroupId);
|
||||
if (auto rec = dw.enterSubRecord("agscId"))
|
||||
head.agscId.write(dw);
|
||||
w.writeUBytes(sngData.data(), sngData.size());
|
||||
|
||||
athena::io::FileWriter w(yamlPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
dw.finish(&w);
|
||||
}
|
||||
|
||||
{
|
||||
auto sng = rs.readUBytes(head.sngLength);
|
||||
int version;
|
||||
bool isBig;
|
||||
auto midi = amuse::SongConverter::SongToMIDI(sng.get(), version, isBig);
|
||||
|
||||
athena::io::FileWriter w(midPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
w.writeUBytes(midi.data(), midi.size());
|
||||
}
|
||||
|
||||
/* Update !songs.yaml for Amuse editor */
|
||||
hecl::ProjectPath audGrp(outPath.getParentPath().getParentPath(), _SYS_STR("AudioGrp"));
|
||||
audGrp.makeDirChain(true);
|
||||
hecl::ProjectPath songsPath(audGrp, _SYS_STR("!songs.yaml"));
|
||||
std::experimental::optional<athena::io::FileReader> r;
|
||||
if (songsPath.isFile())
|
||||
r.emplace(songsPath.getAbsolutePath());
|
||||
athena::io::YAMLDocWriter ydw("amuse::Songs", r ? &*r : nullptr);
|
||||
r = std::experimental::nullopt;
|
||||
char id[16];
|
||||
snprintf(id, 16, "%04X", head.midiSetupId);
|
||||
ydw.writeString(id, hecl::Format("../MidiData/%s", midPath.getLastComponentUTF8().data()));
|
||||
athena::io::FileWriter w(songsPath.getAbsolutePath());
|
||||
ydw.finish(&w);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSNG::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath)
|
||||
{
|
||||
hecl::ProjectPath midPath = inPath.getWithExtension(_SYS_STR(".mid"), true);
|
||||
hecl::ProjectPath yamlPath = inPath.getWithExtension(_SYS_STR(".yaml"), true);
|
||||
|
||||
std::vector<uint8_t> sngData;
|
||||
{
|
||||
athena::io::FileReader midR(midPath.getAbsolutePath());
|
||||
if (midR.hasError())
|
||||
return false;
|
||||
|
||||
uint32_t midLen = midR.length();
|
||||
std::vector<uint8_t> midData;
|
||||
midData.resize(midLen);
|
||||
midR.readUBytesToBuf(midData.data(), midLen);
|
||||
sngData = amuse::SongConverter::MIDIToSong(midData, 1, true);
|
||||
}
|
||||
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
if (w.hasError())
|
||||
return false;
|
||||
|
||||
{
|
||||
athena::io::FileReader yamlR(yamlPath.getAbsolutePath());
|
||||
if (yamlR.hasError())
|
||||
return false;
|
||||
athena::io::YAMLDocReader dr;
|
||||
if (!dr.parse(&yamlR))
|
||||
return false;
|
||||
|
||||
Header head;
|
||||
head.midiSetupId = dr.readUint32("midiSetupId");
|
||||
head.songGroupId = dr.readUint32("songGroupId");
|
||||
if (auto rec = dr.enterSubRecord("agscId"))
|
||||
head.agscId.read(dr);
|
||||
head.sngLength = sngData.size();
|
||||
head.write(w);
|
||||
}
|
||||
|
||||
w.writeUBytes(sngData.data(), sngData.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -3,24 +3,21 @@
|
|||
#include "DataSpec/DNACommon/DNACommon.hpp"
|
||||
#include "DNAMP1.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
class CSNG {
|
||||
struct Header : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> magic = 0x2;
|
||||
Value<atUint32> midiSetupId;
|
||||
Value<atUint32> songGroupId;
|
||||
UniqueID32 agscId;
|
||||
Value<atUint32> sngLength;
|
||||
};
|
||||
|
||||
class CSNG
|
||||
{
|
||||
struct Header : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> magic = 0x2;
|
||||
Value<atUint32> midiSetupId;
|
||||
Value<atUint32> songGroupId;
|
||||
UniqueID32 agscId;
|
||||
Value<atUint32> sngLength;
|
||||
};
|
||||
public:
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -1,138 +1,121 @@
|
|||
#include "DCLN.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
#if DCLN_DUMP_OBB
|
||||
void DCLN::Collision::Node::sendToBlender(hecl::blender::PyOutStream& os) const
|
||||
{
|
||||
os.format("obj = bpy.data.objects.new('%s', None)\n"
|
||||
"obj.empty_draw_type = 'CUBE'\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = (%f,%f,%f)\n", isLeaf ? "leaf" : "branch",
|
||||
xf[0].vec[0], xf[0].vec[1], xf[0].vec[2], xf[0].vec[3],
|
||||
xf[1].vec[0], xf[1].vec[1], xf[1].vec[2], xf[1].vec[3],
|
||||
xf[2].vec[0], xf[2].vec[1], xf[2].vec[2], xf[2].vec[3],
|
||||
halfExtent.vec[0], halfExtent.vec[1], halfExtent.vec[2]);
|
||||
if (isLeaf)
|
||||
os << "obj.show_name = True\n";
|
||||
if (!isLeaf)
|
||||
{
|
||||
left->sendToBlender(os);
|
||||
right->sendToBlender(os);
|
||||
}
|
||||
void DCLN::Collision::Node::sendToBlender(hecl::blender::PyOutStream& os) const {
|
||||
os.format(
|
||||
"obj = bpy.data.objects.new('%s', None)\n"
|
||||
"obj.empty_draw_type = 'CUBE'\n"
|
||||
"bpy.context.scene.objects.link(obj)\n"
|
||||
"mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n"
|
||||
"mtxd = mtx.decompose()\n"
|
||||
"obj.rotation_mode = 'QUATERNION'\n"
|
||||
"obj.location = mtxd[0]\n"
|
||||
"obj.rotation_quaternion = mtxd[1]\n"
|
||||
"obj.scale = (%f,%f,%f)\n",
|
||||
isLeaf ? "leaf" : "branch", xf[0].vec[0], xf[0].vec[1], xf[0].vec[2], xf[0].vec[3], xf[1].vec[0], xf[1].vec[1],
|
||||
xf[1].vec[2], xf[1].vec[3], xf[2].vec[0], xf[2].vec[1], xf[2].vec[2], xf[2].vec[3], halfExtent.vec[0],
|
||||
halfExtent.vec[1], halfExtent.vec[2]);
|
||||
if (isLeaf)
|
||||
os << "obj.show_name = True\n";
|
||||
if (!isLeaf) {
|
||||
left->sendToBlender(os);
|
||||
right->sendToBlender(os);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Op>
|
||||
void DCLN::Collision::Node::Enumerate(typename Op::StreamT& s)
|
||||
{
|
||||
Do<Op>({"xf[0]"}, xf[0], s);
|
||||
Do<Op>({"xf[1]"}, xf[1], s);
|
||||
Do<Op>({"xf[2]"}, xf[2], s);
|
||||
Do<Op>({"halfExtent"}, halfExtent, s);
|
||||
Do<Op>({"isLeaf"}, isLeaf, s);
|
||||
if (isLeaf)
|
||||
{
|
||||
if (!leafData)
|
||||
leafData.reset(new LeafData);
|
||||
Do<Op>({"leafData"}, *leafData, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!left)
|
||||
left.reset(new Node);
|
||||
Do<Op>({"left"}, *left, s);
|
||||
if (!right)
|
||||
right.reset(new Node);
|
||||
Do<Op>({"right"}, *right, s);
|
||||
}
|
||||
void DCLN::Collision::Node::Enumerate(typename Op::StreamT& s) {
|
||||
Do<Op>({"xf[0]"}, xf[0], s);
|
||||
Do<Op>({"xf[1]"}, xf[1], s);
|
||||
Do<Op>({"xf[2]"}, xf[2], s);
|
||||
Do<Op>({"halfExtent"}, halfExtent, s);
|
||||
Do<Op>({"isLeaf"}, isLeaf, s);
|
||||
if (isLeaf) {
|
||||
if (!leafData)
|
||||
leafData.reset(new LeafData);
|
||||
Do<Op>({"leafData"}, *leafData, s);
|
||||
} else {
|
||||
if (!left)
|
||||
left.reset(new Node);
|
||||
Do<Op>({"left"}, *left, s);
|
||||
if (!right)
|
||||
right.reset(new Node);
|
||||
Do<Op>({"right"}, *right, s);
|
||||
}
|
||||
}
|
||||
|
||||
AT_SPECIALIZE_DNA(DCLN::Collision::Node)
|
||||
|
||||
void DCLN::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName)
|
||||
{
|
||||
/* Open Py Stream and read sections */
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os.format("import bpy\n"
|
||||
"import bmesh\n"
|
||||
"from mathutils import Vector, Matrix\n"
|
||||
"\n"
|
||||
"bpy.context.scene.name = '%s'\n"
|
||||
"# Clear Scene\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" if ob.type != 'CAMERA':\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n",
|
||||
entryName.data());
|
||||
void DCLN::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName) {
|
||||
/* Open Py Stream and read sections */
|
||||
hecl::blender::PyOutStream os = conn.beginPythonOut(true);
|
||||
os.format(
|
||||
"import bpy\n"
|
||||
"import bmesh\n"
|
||||
"from mathutils import Vector, Matrix\n"
|
||||
"\n"
|
||||
"bpy.context.scene.name = '%s'\n"
|
||||
"# Clear Scene\n"
|
||||
"for ob in bpy.data.objects:\n"
|
||||
" if ob.type != 'CAMERA':\n"
|
||||
" bpy.context.scene.objects.unlink(ob)\n"
|
||||
" bpy.data.objects.remove(ob)\n",
|
||||
entryName.data());
|
||||
|
||||
DeafBabe::BlenderInit(os);
|
||||
atInt32 idx = 0;
|
||||
for (const Collision& col : collision)
|
||||
{
|
||||
DeafBabeSendToBlender(os, col, true, idx++);
|
||||
DeafBabe::BlenderInit(os);
|
||||
atInt32 idx = 0;
|
||||
for (const Collision& col : collision) {
|
||||
DeafBabeSendToBlender(os, col, true, idx++);
|
||||
#if DCLN_DUMP_OBB
|
||||
col.root.sendToBlender(os);
|
||||
col.root.sendToBlender(os);
|
||||
#endif
|
||||
}
|
||||
os.centerView();
|
||||
os.close();
|
||||
}
|
||||
os.centerView();
|
||||
os.close();
|
||||
}
|
||||
|
||||
bool DCLN::Extract(const SpecBase& dataSpec,
|
||||
PAKEntryReadStream& rs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry,
|
||||
bool force,
|
||||
hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged)
|
||||
{
|
||||
DCLN dcln;
|
||||
dcln.read(rs);
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::ColMesh))
|
||||
return false;
|
||||
bool DCLN::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged) {
|
||||
DCLN dcln;
|
||||
dcln.read(rs);
|
||||
hecl::blender::Connection& conn = btok.getBlenderConnection();
|
||||
if (!conn.createBlend(outPath, hecl::blender::BlendType::ColMesh))
|
||||
return false;
|
||||
|
||||
dcln.sendToBlender(conn, pakRouter.getBestEntryName(entry, false));
|
||||
return conn.saveBlend();
|
||||
dcln.sendToBlender(conn, pakRouter.getBestEntryName(entry, false));
|
||||
return conn.saveBlend();
|
||||
}
|
||||
|
||||
bool DCLN::Cook(const hecl::ProjectPath& outPath,
|
||||
const std::vector<Mesh>& meshes)
|
||||
{
|
||||
DCLN dcln;
|
||||
dcln.colCount = atUint32(meshes.size());
|
||||
for (const Mesh& mesh : meshes)
|
||||
{
|
||||
dcln.collision.emplace_back();
|
||||
Collision& colOut = dcln.collision.back();
|
||||
DeafBabeBuildFromBlender(colOut, mesh);
|
||||
colOut.root = std::move(*OBBTreeBuilder::buildCol<Collision::Node>(mesh));
|
||||
colOut.memSize = atUint32(colOut.root.getMemoryUsage());
|
||||
}
|
||||
bool DCLN::Cook(const hecl::ProjectPath& outPath, const std::vector<Mesh>& meshes) {
|
||||
DCLN dcln;
|
||||
dcln.colCount = atUint32(meshes.size());
|
||||
for (const Mesh& mesh : meshes) {
|
||||
dcln.collision.emplace_back();
|
||||
Collision& colOut = dcln.collision.back();
|
||||
DeafBabeBuildFromBlender(colOut, mesh);
|
||||
colOut.root = std::move(*OBBTreeBuilder::buildCol<Collision::Node>(mesh));
|
||||
colOut.memSize = atUint32(colOut.root.getMemoryUsage());
|
||||
}
|
||||
|
||||
#if DCLN_DUMP_OBB
|
||||
hecl::blender::Connection& conn = hecl::blender::SharedBlenderToken.getBlenderConnection();
|
||||
conn.createBlend(outPath.getWithExtension(_SYS_STR(".blend")), hecl::blender::BlendType::ColMesh);
|
||||
dcln.sendToBlender(conn, "BLAH");
|
||||
conn.saveBlend();
|
||||
hecl::blender::Connection& conn = hecl::blender::SharedBlenderToken.getBlenderConnection();
|
||||
conn.createBlend(outPath.getWithExtension(_SYS_STR(".blend")), hecl::blender::BlendType::ColMesh);
|
||||
dcln.sendToBlender(conn, "BLAH");
|
||||
conn.saveBlend();
|
||||
#endif
|
||||
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
dcln.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
athena::io::FileWriter w(outPath.getAbsolutePath());
|
||||
dcln.write(w);
|
||||
int64_t rem = w.position() % 32;
|
||||
if (rem)
|
||||
for (int64_t i = 0; i < 32 - rem; ++i)
|
||||
w.writeUByte(0xff);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -9,103 +9,86 @@
|
|||
|
||||
#define DCLN_DUMP_OBB 0
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
struct DCLN : BigDNA
|
||||
{
|
||||
using Mesh = hecl::blender::ColMesh;
|
||||
struct DCLN : BigDNA {
|
||||
using Mesh = hecl::blender::ColMesh;
|
||||
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> colCount;
|
||||
struct Collision : BigDNA {
|
||||
using Material = DeafBabe::Material;
|
||||
using Edge = DeafBabe::Edge;
|
||||
using Triangle = DeafBabe::Triangle;
|
||||
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> colCount;
|
||||
struct Collision : BigDNA
|
||||
{
|
||||
using Material = DeafBabe::Material;
|
||||
using Edge = DeafBabe::Edge;
|
||||
using Triangle = DeafBabe::Triangle;
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
Value<atUint32> memSize;
|
||||
Value<atUint32> materialCount;
|
||||
Vector<Material, AT_DNA_COUNT(materialCount)> materials;
|
||||
Value<atUint32> vertMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(vertMatsCount)> vertMats;
|
||||
Value<atUint32> edgeMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(edgeMatsCount)> edgeMats;
|
||||
Value<atUint32> triMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(triMatsCount)> triMats;
|
||||
Value<atUint32> edgeVertsCount;
|
||||
Vector<Edge, AT_DNA_COUNT(edgeVertsCount)> edgeVertConnections;
|
||||
Value<atUint32> triangleEdgesCount;
|
||||
Vector<Triangle, AT_DNA_COUNT(triangleEdgesCount / 3)> triangleEdgeConnections;
|
||||
Value<atUint32> vertCount;
|
||||
Vector<atVec3f, AT_DNA_COUNT(vertCount)> verts;
|
||||
|
||||
struct Node : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
|
||||
struct LeafData : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
Value<atUint32> memSize;
|
||||
Value<atUint32> materialCount;
|
||||
Vector<Material, AT_DNA_COUNT(materialCount)> materials;
|
||||
Value<atUint32> vertMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(vertMatsCount)> vertMats;
|
||||
Value<atUint32> edgeMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(edgeMatsCount)> edgeMats;
|
||||
Value<atUint32> triMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(triMatsCount)> triMats;
|
||||
Value<atUint32> edgeVertsCount;
|
||||
Vector<Edge, AT_DNA_COUNT(edgeVertsCount)> edgeVertConnections;
|
||||
Value<atUint32> triangleEdgesCount;
|
||||
Vector<Triangle, AT_DNA_COUNT(triangleEdgesCount / 3)> triangleEdgeConnections;
|
||||
Value<atUint32> vertCount;
|
||||
Vector<atVec3f, AT_DNA_COUNT(vertCount)> verts;
|
||||
Value<atUint32> triangleIndexCount;
|
||||
Vector<atUint16, AT_DNA_COUNT(triangleIndexCount)> triangleIndices;
|
||||
size_t getMemoryUsage() const { return (((triangleIndices.size() * 2) + 16) + 3) & ~3; }
|
||||
};
|
||||
|
||||
struct Node : BigDNA
|
||||
{
|
||||
AT_DECL_EXPLICIT_DNA
|
||||
Value<atVec4f> xf[3];
|
||||
Value<atVec3f> halfExtent;
|
||||
Value<bool> isLeaf;
|
||||
std::unique_ptr<LeafData> leafData;
|
||||
std::unique_ptr<Node> left;
|
||||
std::unique_ptr<Node> right;
|
||||
|
||||
struct LeafData : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> triangleIndexCount;
|
||||
Vector<atUint16, AT_DNA_COUNT(triangleIndexCount)> triangleIndices;
|
||||
size_t getMemoryUsage() const { return (((triangleIndices.size() * 2) + 16) + 3) & ~3; }
|
||||
};
|
||||
|
||||
Value<atVec4f> xf[3];
|
||||
Value<atVec3f> halfExtent;
|
||||
Value<bool> isLeaf;
|
||||
std::unique_ptr<LeafData> leafData;
|
||||
std::unique_ptr<Node> left;
|
||||
std::unique_ptr<Node> right;
|
||||
|
||||
size_t getMemoryUsage() const
|
||||
{
|
||||
size_t ret = 80;
|
||||
if (isLeaf)
|
||||
ret += leafData->getMemoryUsage();
|
||||
else
|
||||
{
|
||||
ret += left->getMemoryUsage();
|
||||
ret += right->getMemoryUsage();
|
||||
}
|
||||
|
||||
return (ret + 3) & ~3;
|
||||
}
|
||||
|
||||
#if DCLN_DUMP_OBB
|
||||
void sendToBlender(hecl::blender::PyOutStream& os) const;
|
||||
#endif
|
||||
};
|
||||
Node root;
|
||||
size_t getMemoryUsage()
|
||||
{
|
||||
return root.getMemoryUsage();
|
||||
size_t getMemoryUsage() const {
|
||||
size_t ret = 80;
|
||||
if (isLeaf)
|
||||
ret += leafData->getMemoryUsage();
|
||||
else {
|
||||
ret += left->getMemoryUsage();
|
||||
ret += right->getMemoryUsage();
|
||||
}
|
||||
|
||||
/* Dummy MP2 member */
|
||||
void insertNoClimb(hecl::blender::PyOutStream&) const {}
|
||||
return (ret + 3) & ~3;
|
||||
}
|
||||
|
||||
#if DCLN_DUMP_OBB
|
||||
void sendToBlender(hecl::blender::PyOutStream& os) const;
|
||||
#endif
|
||||
};
|
||||
Node root;
|
||||
size_t getMemoryUsage() { return root.getMemoryUsage(); }
|
||||
|
||||
/* Dummy MP2 member */
|
||||
void insertNoClimb(hecl::blender::PyOutStream&) const {}
|
||||
};
|
||||
|
||||
Vector<Collision, AT_DNA_COUNT(colCount)> collision;
|
||||
Vector<Collision, AT_DNA_COUNT(colCount)> collision;
|
||||
|
||||
void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName);
|
||||
void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName);
|
||||
|
||||
static bool Extract(const SpecBase& dataSpec,
|
||||
PAKEntryReadStream& rs,
|
||||
const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter,
|
||||
const PAK::Entry& entry,
|
||||
bool force,
|
||||
hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath,
|
||||
PAKRouter<PAKBridge>& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok,
|
||||
std::function<void(const hecl::SystemChar*)> fileChanged);
|
||||
|
||||
static bool Cook(const hecl::ProjectPath& outPath,
|
||||
const std::vector<Mesh>& meshes);
|
||||
static bool Cook(const hecl::ProjectPath& outPath, const std::vector<Mesh>& meshes);
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -47,419 +47,373 @@
|
|||
#include "MazeSeeds.hpp"
|
||||
#include "SnowForces.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
logvisor::Module Log("urde::DNAMP1");
|
||||
|
||||
static bool GetNoShare(std::string_view name)
|
||||
{
|
||||
std::string lowerName(name);
|
||||
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
|
||||
if (!lowerName.compare(0, 7, "metroid"))
|
||||
return false;
|
||||
return true;
|
||||
static bool GetNoShare(std::string_view name) {
|
||||
std::string lowerName(name);
|
||||
std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
|
||||
if (!lowerName.compare(0, 7, "metroid"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
PAKBridge::PAKBridge(const nod::Node& node, bool doExtract)
|
||||
: m_node(node), m_pak(false, GetNoShare(node.getName())), m_doExtract(doExtract)
|
||||
{
|
||||
nod::AthenaPartReadStream rs(node.beginReadStream());
|
||||
m_pak.read(rs);
|
||||
: m_node(node), m_pak(false, GetNoShare(node.getName())), m_doExtract(doExtract) {
|
||||
nod::AthenaPartReadStream rs(node.beginReadStream());
|
||||
m_pak.read(rs);
|
||||
|
||||
/* Append Level String */
|
||||
for (auto& ent : m_pak.m_entries)
|
||||
{
|
||||
PAK::Entry& entry = ent.second;
|
||||
if (entry.type == FOURCC('MLVL'))
|
||||
{
|
||||
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
||||
MLVL mlvl;
|
||||
mlvl.read(rs);
|
||||
PAK::Entry* nameEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldNameId);
|
||||
if (nameEnt)
|
||||
{
|
||||
nameEnt->name = entry.name + "_name";
|
||||
PAKEntryReadStream rs = nameEnt->beginReadStream(m_node);
|
||||
STRG mlvlName;
|
||||
mlvlName.read(rs);
|
||||
if (m_levelString.size())
|
||||
m_levelString += _SYS_STR(", ");
|
||||
m_levelString += mlvlName.getSystemString(FOURCC('ENGL'), 0);
|
||||
}
|
||||
}
|
||||
/* Append Level String */
|
||||
for (auto& ent : m_pak.m_entries) {
|
||||
PAK::Entry& entry = ent.second;
|
||||
if (entry.type == FOURCC('MLVL')) {
|
||||
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
||||
MLVL mlvl;
|
||||
mlvl.read(rs);
|
||||
PAK::Entry* nameEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldNameId);
|
||||
if (nameEnt) {
|
||||
nameEnt->name = entry.name + "_name";
|
||||
PAKEntryReadStream rs = nameEnt->beginReadStream(m_node);
|
||||
STRG mlvlName;
|
||||
mlvlName.read(rs);
|
||||
if (m_levelString.size())
|
||||
m_levelString += _SYS_STR(", ");
|
||||
m_levelString += mlvlName.getSystemString(FOURCC('ENGL'), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static hecl::SystemString LayerName(std::string_view name)
|
||||
{
|
||||
hecl::SystemString ret(hecl::SystemStringConv(name).sys_str());
|
||||
for (auto& ch : ret)
|
||||
if (ch == _SYS_STR('/') || ch == _SYS_STR('\\'))
|
||||
ch = _SYS_STR('-');
|
||||
return ret;
|
||||
static hecl::SystemString LayerName(std::string_view name) {
|
||||
hecl::SystemString ret(hecl::SystemStringConv(name).sys_str());
|
||||
for (auto& ch : ret)
|
||||
if (ch == _SYS_STR('/') || ch == _SYS_STR('\\'))
|
||||
ch = _SYS_STR('-');
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PAKBridge::build()
|
||||
{
|
||||
/* First pass: build per-area/per-layer dependency map */
|
||||
for (const auto& ent : m_pak.m_entries)
|
||||
{
|
||||
const PAK::Entry& entry = ent.second;
|
||||
if (entry.type == FOURCC('MLVL'))
|
||||
{
|
||||
Level& level = m_levelDeps[entry.id];
|
||||
void PAKBridge::build() {
|
||||
/* First pass: build per-area/per-layer dependency map */
|
||||
for (const auto& ent : m_pak.m_entries) {
|
||||
const PAK::Entry& entry = ent.second;
|
||||
if (entry.type == FOURCC('MLVL')) {
|
||||
Level& level = m_levelDeps[entry.id];
|
||||
|
||||
MLVL mlvl;
|
||||
{
|
||||
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
||||
mlvl.read(rs);
|
||||
}
|
||||
bool named;
|
||||
std::string bestName = m_pak.bestEntryName(m_node, entry, named);
|
||||
level.name = hecl::SystemStringConv(bestName).sys_str();
|
||||
level.areas.reserve(mlvl.areaCount);
|
||||
unsigned layerIdx = 0;
|
||||
MLVL mlvl;
|
||||
{
|
||||
PAKEntryReadStream rs = entry.beginReadStream(m_node);
|
||||
mlvl.read(rs);
|
||||
}
|
||||
bool named;
|
||||
std::string bestName = m_pak.bestEntryName(m_node, entry, named);
|
||||
level.name = hecl::SystemStringConv(bestName).sys_str();
|
||||
level.areas.reserve(mlvl.areaCount);
|
||||
unsigned layerIdx = 0;
|
||||
|
||||
/* Make MAPW available to lookup MAPAs */
|
||||
PAK::Entry* worldMapEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldMap);
|
||||
std::vector<UniqueID32> mapw;
|
||||
if (worldMapEnt)
|
||||
{
|
||||
worldMapEnt->name = entry.name + "_mapw";
|
||||
PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node);
|
||||
rs.seek(8, athena::Current);
|
||||
atUint32 areaCount = rs.readUint32Big();
|
||||
mapw.reserve(areaCount);
|
||||
for (atUint32 i=0 ; i<areaCount ; ++i)
|
||||
mapw.emplace_back(rs);
|
||||
}
|
||||
/* Make MAPW available to lookup MAPAs */
|
||||
PAK::Entry* worldMapEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldMap);
|
||||
std::vector<UniqueID32> mapw;
|
||||
if (worldMapEnt) {
|
||||
worldMapEnt->name = entry.name + "_mapw";
|
||||
PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node);
|
||||
rs.seek(8, athena::Current);
|
||||
atUint32 areaCount = rs.readUint32Big();
|
||||
mapw.reserve(areaCount);
|
||||
for (atUint32 i = 0; i < areaCount; ++i)
|
||||
mapw.emplace_back(rs);
|
||||
}
|
||||
|
||||
PAK::Entry* savwEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.saveWorldId);
|
||||
if (savwEnt)
|
||||
savwEnt->name = entry.name + "_savw";
|
||||
PAK::Entry* savwEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.saveWorldId);
|
||||
if (savwEnt)
|
||||
savwEnt->name = entry.name + "_savw";
|
||||
|
||||
PAK::Entry* skyEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldSkyboxId);
|
||||
if (skyEnt)
|
||||
skyEnt->name = entry.name + "_skybox";
|
||||
PAK::Entry* skyEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldSkyboxId);
|
||||
if (skyEnt)
|
||||
skyEnt->name = entry.name + "_skybox";
|
||||
|
||||
/* Index areas */
|
||||
unsigned ai = 0;
|
||||
for (const MLVL::Area& area : mlvl.areas)
|
||||
{
|
||||
Level::Area& areaDeps = level.areas[area.areaMREAId];
|
||||
MLVL::LayerFlags& layerFlags = mlvl.layerFlags[ai];
|
||||
PAK::Entry* areaNameEnt = (PAK::Entry*)m_pak.lookupEntry(area.areaNameId);
|
||||
if (areaNameEnt)
|
||||
{
|
||||
STRG areaName;
|
||||
{
|
||||
PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node);
|
||||
areaName.read(rs);
|
||||
}
|
||||
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
||||
areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name);
|
||||
}
|
||||
if (areaDeps.name.empty())
|
||||
{
|
||||
std::string idStr = area.areaMREAId.toString();
|
||||
areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str();
|
||||
}
|
||||
hecl::SystemChar num[16];
|
||||
hecl::SNPrintf(num, 16, _SYS_STR("%02u "), ai);
|
||||
areaDeps.name = num + areaDeps.name;
|
||||
|
||||
std::string lowerName(hecl::SystemUTF8Conv(areaDeps.name).str());
|
||||
for (char& ch : lowerName)
|
||||
{
|
||||
ch = tolower(ch);
|
||||
if (ch == ' ')
|
||||
ch = '_';
|
||||
}
|
||||
if (areaNameEnt)
|
||||
areaNameEnt->name = lowerName + "_name";
|
||||
PAK::Entry* areaEnt = (PAK::Entry*)m_pak.lookupEntry(area.areaMREAId);
|
||||
if (areaEnt)
|
||||
areaEnt->name = lowerName;
|
||||
|
||||
areaDeps.layers.reserve(area.depLayerCount-1);
|
||||
unsigned r=0;
|
||||
for (unsigned l=1 ; l<area.depLayerCount ; ++l)
|
||||
{
|
||||
areaDeps.layers.emplace_back();
|
||||
Level::Area::Layer& layer = areaDeps.layers.back();
|
||||
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
||||
layer.active = layerFlags.flags >> (l-1) & 0x1;
|
||||
layer.name = hecl::StringUtils::TrimWhitespace(layer.name);
|
||||
|
||||
hecl::SNPrintf(num, 16, _SYS_STR("%02u "), l-1);
|
||||
layer.name = num + layer.name;
|
||||
|
||||
layer.resources.reserve(area.depLayers[l] - r);
|
||||
for (; r<area.depLayers[l] ; ++r)
|
||||
layer.resources.emplace(area.deps[r].id);
|
||||
}
|
||||
areaDeps.resources.reserve(area.depCount - r + 2);
|
||||
for (; r<area.depCount ; ++r)
|
||||
areaDeps.resources.emplace(area.deps[r].id);
|
||||
areaDeps.resources.emplace(area.areaMREAId);
|
||||
if (mapw.size() > ai)
|
||||
areaDeps.resources.emplace(mapw[ai]);
|
||||
++ai;
|
||||
}
|
||||
/* Index areas */
|
||||
unsigned ai = 0;
|
||||
for (const MLVL::Area& area : mlvl.areas) {
|
||||
Level::Area& areaDeps = level.areas[area.areaMREAId];
|
||||
MLVL::LayerFlags& layerFlags = mlvl.layerFlags[ai];
|
||||
PAK::Entry* areaNameEnt = (PAK::Entry*)m_pak.lookupEntry(area.areaNameId);
|
||||
if (areaNameEnt) {
|
||||
STRG areaName;
|
||||
{
|
||||
PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node);
|
||||
areaName.read(rs);
|
||||
}
|
||||
areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
|
||||
areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name);
|
||||
}
|
||||
}
|
||||
if (areaDeps.name.empty()) {
|
||||
std::string idStr = area.areaMREAId.toString();
|
||||
areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str();
|
||||
}
|
||||
hecl::SystemChar num[16];
|
||||
hecl::SNPrintf(num, 16, _SYS_STR("%02u "), ai);
|
||||
areaDeps.name = num + areaDeps.name;
|
||||
|
||||
/* Second pass: cross-compare uniqueness */
|
||||
for (auto& entry : m_pak.m_entries)
|
||||
{
|
||||
entry.second.unique.checkEntry(*this, entry.second);
|
||||
std::string lowerName(hecl::SystemUTF8Conv(areaDeps.name).str());
|
||||
for (char& ch : lowerName) {
|
||||
ch = tolower(ch);
|
||||
if (ch == ' ')
|
||||
ch = '_';
|
||||
}
|
||||
if (areaNameEnt)
|
||||
areaNameEnt->name = lowerName + "_name";
|
||||
PAK::Entry* areaEnt = (PAK::Entry*)m_pak.lookupEntry(area.areaMREAId);
|
||||
if (areaEnt)
|
||||
areaEnt->name = lowerName;
|
||||
|
||||
areaDeps.layers.reserve(area.depLayerCount - 1);
|
||||
unsigned r = 0;
|
||||
for (unsigned l = 1; l < area.depLayerCount; ++l) {
|
||||
areaDeps.layers.emplace_back();
|
||||
Level::Area::Layer& layer = areaDeps.layers.back();
|
||||
layer.name = LayerName(mlvl.layerNames[layerIdx++]);
|
||||
layer.active = layerFlags.flags >> (l - 1) & 0x1;
|
||||
layer.name = hecl::StringUtils::TrimWhitespace(layer.name);
|
||||
|
||||
hecl::SNPrintf(num, 16, _SYS_STR("%02u "), l - 1);
|
||||
layer.name = num + layer.name;
|
||||
|
||||
layer.resources.reserve(area.depLayers[l] - r);
|
||||
for (; r < area.depLayers[l]; ++r)
|
||||
layer.resources.emplace(area.deps[r].id);
|
||||
}
|
||||
areaDeps.resources.reserve(area.depCount - r + 2);
|
||||
for (; r < area.depCount; ++r)
|
||||
areaDeps.resources.emplace(area.deps[r].id);
|
||||
areaDeps.resources.emplace(area.areaMREAId);
|
||||
if (mapw.size() > ai)
|
||||
areaDeps.resources.emplace(mapw[ai]);
|
||||
++ai;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Second pass: cross-compare uniqueness */
|
||||
for (auto& entry : m_pak.m_entries) {
|
||||
entry.second.unique.checkEntry(*this, entry.second);
|
||||
}
|
||||
}
|
||||
|
||||
void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const
|
||||
{
|
||||
for (const std::pair<UniqueID32, PAK::Entry>& entry : m_pak.m_entries)
|
||||
{
|
||||
if (entry.second.type == FOURCC('ANCS'))
|
||||
{
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
ANCS ancs;
|
||||
ancs.read(rs);
|
||||
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters)
|
||||
{
|
||||
charAssoc.m_cmdlRigs[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
|
||||
charAssoc.m_cskrCinfToCharacter[ci.cskr] =
|
||||
std::make_pair(entry.second.id, hecl::Format("%s.CSKR", ci.name.c_str()));
|
||||
charAssoc.m_cskrCinfToCharacter[ci.cinf] =
|
||||
std::make_pair(entry.second.id, hecl::Format("CINF_%08X.CINF", ci.cinf.toUint32()));
|
||||
PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdl);
|
||||
PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskr);
|
||||
PAK::Entry* cinfEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cinf);
|
||||
cmdlEnt->name = hecl::Format("ANCS_%08X_%s_model", entry.first.toUint32(), ci.name.c_str());
|
||||
cskrEnt->name = hecl::Format("ANCS_%08X_%s_skin", entry.first.toUint32(), ci.name.c_str());
|
||||
cinfEnt->name = hecl::Format("ANCS_%08X_%s_skel", entry.first.toUint32(), ci.name.c_str());
|
||||
if (ci.cmdlIce && ci.cskrIce)
|
||||
{
|
||||
charAssoc.m_cmdlRigs[ci.cmdlIce] = std::make_pair(ci.cskrIce, ci.cinf);
|
||||
charAssoc.m_cskrCinfToCharacter[ci.cskrIce] =
|
||||
std::make_pair(entry.second.id, hecl::Format("%s.ICE.CSKR", ci.name.c_str()));
|
||||
PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdlIce);
|
||||
PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskrIce);
|
||||
cmdlEnt->name = hecl::Format("ANCS_%08X_%s_icemodel", entry.first.toUint32(), ci.name.c_str());
|
||||
cskrEnt->name = hecl::Format("ANCS_%08X_%s_iceskin", entry.first.toUint32(), ci.name.c_str());
|
||||
}
|
||||
}
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>> animInfo;
|
||||
ancs.getAnimationResInfo(&pakRouter, animInfo);
|
||||
for (auto& ae : animInfo)
|
||||
{
|
||||
PAK::Entry* animEnt = (PAK::Entry*)m_pak.lookupEntry(ae.second.animId);
|
||||
animEnt->name = hecl::Format("ANCS_%08X_%s", entry.first.toUint32(), ae.second.name.c_str());
|
||||
charAssoc.m_cskrCinfToCharacter[ae.second.animId] =
|
||||
std::make_pair(entry.second.id, hecl::Format("%s.ANIM", ae.second.name.c_str()));
|
||||
if (ae.second.evntId)
|
||||
{
|
||||
PAK::Entry* evntEnt = (PAK::Entry*)m_pak.lookupEntry(ae.second.evntId);
|
||||
evntEnt->name = hecl::Format("ANCS_%08X_%s_evnt", entry.first.toUint32(), ae.second.name.c_str());
|
||||
charAssoc.m_cskrCinfToCharacter[ae.second.evntId] =
|
||||
std::make_pair(entry.second.id, hecl::Format("%s.evnt.yaml", ae.second.name.c_str()));
|
||||
}
|
||||
}
|
||||
void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const {
|
||||
for (const std::pair<UniqueID32, PAK::Entry>& entry : m_pak.m_entries) {
|
||||
if (entry.second.type == FOURCC('ANCS')) {
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
ANCS ancs;
|
||||
ancs.read(rs);
|
||||
for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) {
|
||||
charAssoc.m_cmdlRigs[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf);
|
||||
charAssoc.m_cskrCinfToCharacter[ci.cskr] =
|
||||
std::make_pair(entry.second.id, hecl::Format("%s.CSKR", ci.name.c_str()));
|
||||
charAssoc.m_cskrCinfToCharacter[ci.cinf] =
|
||||
std::make_pair(entry.second.id, hecl::Format("CINF_%08X.CINF", ci.cinf.toUint32()));
|
||||
PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdl);
|
||||
PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskr);
|
||||
PAK::Entry* cinfEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cinf);
|
||||
cmdlEnt->name = hecl::Format("ANCS_%08X_%s_model", entry.first.toUint32(), ci.name.c_str());
|
||||
cskrEnt->name = hecl::Format("ANCS_%08X_%s_skin", entry.first.toUint32(), ci.name.c_str());
|
||||
cinfEnt->name = hecl::Format("ANCS_%08X_%s_skel", entry.first.toUint32(), ci.name.c_str());
|
||||
if (ci.cmdlIce && ci.cskrIce) {
|
||||
charAssoc.m_cmdlRigs[ci.cmdlIce] = std::make_pair(ci.cskrIce, ci.cinf);
|
||||
charAssoc.m_cskrCinfToCharacter[ci.cskrIce] =
|
||||
std::make_pair(entry.second.id, hecl::Format("%s.ICE.CSKR", ci.name.c_str()));
|
||||
PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdlIce);
|
||||
PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskrIce);
|
||||
cmdlEnt->name = hecl::Format("ANCS_%08X_%s_icemodel", entry.first.toUint32(), ci.name.c_str());
|
||||
cskrEnt->name = hecl::Format("ANCS_%08X_%s_iceskin", entry.first.toUint32(), ci.name.c_str());
|
||||
}
|
||||
else if (entry.second.type == FOURCC('MREA'))
|
||||
{
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
MREA::AddCMDLRigPairs(rs, pakRouter, charAssoc);
|
||||
}
|
||||
std::map<atUint32, DNAANCS::AnimationResInfo<UniqueID32>> animInfo;
|
||||
ancs.getAnimationResInfo(&pakRouter, animInfo);
|
||||
for (auto& ae : animInfo) {
|
||||
PAK::Entry* animEnt = (PAK::Entry*)m_pak.lookupEntry(ae.second.animId);
|
||||
animEnt->name = hecl::Format("ANCS_%08X_%s", entry.first.toUint32(), ae.second.name.c_str());
|
||||
charAssoc.m_cskrCinfToCharacter[ae.second.animId] =
|
||||
std::make_pair(entry.second.id, hecl::Format("%s.ANIM", ae.second.name.c_str()));
|
||||
if (ae.second.evntId) {
|
||||
PAK::Entry* evntEnt = (PAK::Entry*)m_pak.lookupEntry(ae.second.evntId);
|
||||
evntEnt->name = hecl::Format("ANCS_%08X_%s_evnt", entry.first.toUint32(), ae.second.name.c_str());
|
||||
charAssoc.m_cskrCinfToCharacter[ae.second.evntId] =
|
||||
std::make_pair(entry.second.id, hecl::Format("%s.evnt.yaml", ae.second.name.c_str()));
|
||||
}
|
||||
}
|
||||
} else if (entry.second.type == FOURCC('MREA')) {
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
MREA::AddCMDLRigPairs(rs, pakRouter, charAssoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PAKBridge::addPATHToMREA(PAKRouter<PAKBridge>& pakRouter,
|
||||
std::unordered_map<UniqueID32, UniqueID32>& pathToMrea) const
|
||||
{
|
||||
for (const std::pair<UniqueID32, PAK::Entry>& entry : m_pak.m_entries)
|
||||
{
|
||||
if (entry.second.type == FOURCC('MREA'))
|
||||
{
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
UniqueID32 pathID = MREA::GetPATHId(rs);
|
||||
if (pathID)
|
||||
pathToMrea[pathID] = entry.first;
|
||||
}
|
||||
std::unordered_map<UniqueID32, UniqueID32>& pathToMrea) const {
|
||||
for (const std::pair<UniqueID32, PAK::Entry>& entry : m_pak.m_entries) {
|
||||
if (entry.second.type == FOURCC('MREA')) {
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
UniqueID32 pathID = MREA::GetPATHId(rs);
|
||||
if (pathID)
|
||||
pathToMrea[pathID] = entry.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}};
|
||||
|
||||
void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||
std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
|
||||
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const
|
||||
{
|
||||
for (const std::pair<UniqueID32, PAK::Entry>& entry : m_pak.m_entries)
|
||||
{
|
||||
if (entry.second.type == FOURCC('MLVL'))
|
||||
std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
|
||||
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const {
|
||||
for (const std::pair<UniqueID32, PAK::Entry>& entry : m_pak.m_entries) {
|
||||
if (entry.second.type == FOURCC('MLVL')) {
|
||||
MLVL mlvl;
|
||||
{
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
mlvl.read(rs);
|
||||
}
|
||||
hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath();
|
||||
|
||||
if (mlvl.worldNameId)
|
||||
pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _SYS_STR("!name.yaml"));
|
||||
|
||||
for (const MLVL::Area& area : mlvl.areas) {
|
||||
{
|
||||
MLVL mlvl;
|
||||
{
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
mlvl.read(rs);
|
||||
}
|
||||
hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath();
|
||||
|
||||
if (mlvl.worldNameId)
|
||||
pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _SYS_STR("!name.yaml"));
|
||||
|
||||
for (const MLVL::Area& area : mlvl.areas)
|
||||
{
|
||||
{
|
||||
/* Get PATH transform */
|
||||
const nod::Node* areaNode;
|
||||
const PAK::Entry* areaEntry = pakRouter.lookupEntry(area.areaMREAId, &areaNode);
|
||||
PAKEntryReadStream rs = areaEntry->beginReadStream(*areaNode);
|
||||
UniqueID32 pathId = MREA::GetPATHId(rs);
|
||||
if (pathId)
|
||||
addTo[pathId] = zeus::CMatrix4f(
|
||||
area.transformMtx[0],
|
||||
area.transformMtx[1],
|
||||
area.transformMtx[2],
|
||||
BottomRow).transposed();
|
||||
}
|
||||
|
||||
hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
||||
if (area.areaNameId)
|
||||
pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _SYS_STR("!name.yaml"));
|
||||
}
|
||||
|
||||
if (mlvl.worldMap)
|
||||
{
|
||||
const nod::Node* mapNode;
|
||||
const PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode);
|
||||
if (mapEntry)
|
||||
{
|
||||
PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode);
|
||||
u32 magic = rs.readUint32Big();
|
||||
if (magic == 0xDEADF00D)
|
||||
{
|
||||
rs.readUint32Big();
|
||||
u32 count = rs.readUint32Big();
|
||||
for (u32 i=0 ; i<count && i<mlvl.areas.size() ; ++i)
|
||||
{
|
||||
MLVL::Area& areaData = mlvl.areas[i];
|
||||
UniqueID32 mapaId;
|
||||
mapaId.read(rs);
|
||||
addTo[mapaId] = zeus::CMatrix4f(
|
||||
areaData.transformMtx[0],
|
||||
areaData.transformMtx[1],
|
||||
areaData.transformMtx[2],
|
||||
BottomRow).transposed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Get PATH transform */
|
||||
const nod::Node* areaNode;
|
||||
const PAK::Entry* areaEntry = pakRouter.lookupEntry(area.areaMREAId, &areaNode);
|
||||
PAKEntryReadStream rs = areaEntry->beginReadStream(*areaNode);
|
||||
UniqueID32 pathId = MREA::GetPATHId(rs);
|
||||
if (pathId)
|
||||
addTo[pathId] = zeus::CMatrix4f(area.transformMtx[0], area.transformMtx[1], area.transformMtx[2], BottomRow)
|
||||
.transposed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry)
|
||||
{
|
||||
switch (entry.type)
|
||||
{
|
||||
case SBIG('STRG'):
|
||||
return {STRG::Extract, {_SYS_STR(".yaml")}};
|
||||
case SBIG('SCAN'):
|
||||
return {SCAN::Extract, {_SYS_STR(".yaml")}, 0, SCAN::Name};
|
||||
case SBIG('HINT'):
|
||||
return {HINT::Extract, {_SYS_STR(".yaml")}};
|
||||
case SBIG('SAVW'):
|
||||
return {SAVWCommon::ExtractSAVW<SAVW>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('TXTR'):
|
||||
return {TXTR::Extract, {_SYS_STR(".png")}};
|
||||
case SBIG('AFSM'):
|
||||
return {AFSM::Extract, {_SYS_STR(".yaml")}};
|
||||
case SBIG('FRME'):
|
||||
return {FRME::Extract, {_SYS_STR(".blend")}, 2};
|
||||
case SBIG('CMDL'):
|
||||
return {CMDL::Extract, {_SYS_STR(".blend")}, 1, CMDL::Name};
|
||||
case SBIG('DCLN'):
|
||||
return {DCLN::Extract, {_SYS_STR(".blend")}};
|
||||
case SBIG('ANCS'):
|
||||
return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2};
|
||||
case SBIG('MLVL'):
|
||||
return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3};
|
||||
case SBIG('MREA'):
|
||||
return {MREA::Extract, {_SYS_STR(".blend")}, 4, MREA::Name};
|
||||
case SBIG('MAPA'):
|
||||
return {MAPA::Extract, {_SYS_STR(".blend")}, 4};
|
||||
case SBIG('MAPU'):
|
||||
return {MAPU::Extract, {_SYS_STR(".blend")}, 5};
|
||||
case SBIG('PATH'):
|
||||
return {PATH::Extract, {_SYS_STR(".blend")}, 5};
|
||||
case SBIG('PART'):
|
||||
return {DNAParticle::ExtractGPSM<UniqueID32>, {_SYS_STR(".gpsm.yaml")}};
|
||||
case SBIG('ELSC'):
|
||||
return {DNAParticle::ExtractELSM<UniqueID32>, {_SYS_STR(".elsm.yaml")}};
|
||||
case SBIG('SWHC'):
|
||||
return {DNAParticle::ExtractSWSH<UniqueID32>, {_SYS_STR(".swsh.yaml")}};
|
||||
case SBIG('CRSC'):
|
||||
return {DNAParticle::ExtractCRSM<UniqueID32>, {_SYS_STR(".crsm.yaml")}};
|
||||
case SBIG('WPSC'):
|
||||
return {DNAParticle::ExtractWPSM<UniqueID32>, {_SYS_STR(".wpsm.yaml")}};
|
||||
case SBIG('DPSC'):
|
||||
return {DNAParticle::ExtractDPSM<UniqueID32>, {_SYS_STR(".dpsm.yaml")}};
|
||||
case SBIG('FONT'):
|
||||
return {DNAFont::ExtractFONT<UniqueID32>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('DGRP'):
|
||||
return {DNADGRP::ExtractDGRP<UniqueID32>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('AGSC'):
|
||||
return {AGSC::Extract, {}};
|
||||
case SBIG('CSNG'):
|
||||
return {CSNG::Extract, {_SYS_STR(".mid"), _SYS_STR(".yaml")}};
|
||||
case SBIG('ATBL'):
|
||||
return {DNAAudio::ATBL::Extract, {_SYS_STR(".yaml")}};
|
||||
case SBIG('CTWK'):
|
||||
case SBIG('DUMB'):
|
||||
{
|
||||
bool named;
|
||||
std::string name = pak.bestEntryName(pakNode, entry, named);
|
||||
if (named)
|
||||
{
|
||||
if (!name.compare("PlayerRes"))
|
||||
return {ExtractTweak<CTweakPlayerRes>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("GunRes"))
|
||||
return {ExtractTweak<CTweakGunRes>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Player"))
|
||||
return {ExtractTweak<CTweakPlayer>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("CameraBob"))
|
||||
return {ExtractTweak<CTweakCameraBob>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("SlideShow"))
|
||||
return {ExtractTweak<CTweakSlideShow>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Game"))
|
||||
return {ExtractTweak<CTweakGame>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Targeting"))
|
||||
return {ExtractTweak<CTweakTargeting>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Gui"))
|
||||
return {ExtractTweak<CTweakGui>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("AutoMapper"))
|
||||
return {ExtractTweak<CTweakAutoMapper>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("PlayerControls") || !name.compare("PlayerControls2"))
|
||||
return {ExtractTweak<CTweakPlayerControl>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Ball"))
|
||||
return {ExtractTweak<CTweakBall>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Particle"))
|
||||
return {ExtractTweak<CTweakParticle>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("GuiColors"))
|
||||
return {ExtractTweak<CTweakGuiColors>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("PlayerGun"))
|
||||
return {ExtractTweak<CTweakPlayerGun>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("DUMB_MazeSeeds"))
|
||||
return {ExtractTweak<MazeSeeds>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("DUMB_SnowForces"))
|
||||
return {ExtractTweak<SnowForces>, {_SYS_STR(".yaml")}};
|
||||
hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
|
||||
if (area.areaNameId)
|
||||
pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _SYS_STR("!name.yaml"));
|
||||
}
|
||||
|
||||
if (mlvl.worldMap) {
|
||||
const nod::Node* mapNode;
|
||||
const PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode);
|
||||
if (mapEntry) {
|
||||
PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode);
|
||||
u32 magic = rs.readUint32Big();
|
||||
if (magic == 0xDEADF00D) {
|
||||
rs.readUint32Big();
|
||||
u32 count = rs.readUint32Big();
|
||||
for (u32 i = 0; i < count && i < mlvl.areas.size(); ++i) {
|
||||
MLVL::Area& areaData = mlvl.areas[i];
|
||||
UniqueID32 mapaId;
|
||||
mapaId.read(rs);
|
||||
addTo[mapaId] = zeus::CMatrix4f(areaData.transformMtx[0], areaData.transformMtx[1],
|
||||
areaData.transformMtx[2], BottomRow)
|
||||
.transposed();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry) {
|
||||
switch (entry.type) {
|
||||
case SBIG('STRG'):
|
||||
return {STRG::Extract, {_SYS_STR(".yaml")}};
|
||||
case SBIG('SCAN'):
|
||||
return {SCAN::Extract, {_SYS_STR(".yaml")}, 0, SCAN::Name};
|
||||
case SBIG('HINT'):
|
||||
return {HINT::Extract, {_SYS_STR(".yaml")}};
|
||||
case SBIG('SAVW'):
|
||||
return {SAVWCommon::ExtractSAVW<SAVW>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('TXTR'):
|
||||
return {TXTR::Extract, {_SYS_STR(".png")}};
|
||||
case SBIG('AFSM'):
|
||||
return {AFSM::Extract, {_SYS_STR(".yaml")}};
|
||||
case SBIG('FRME'):
|
||||
return {FRME::Extract, {_SYS_STR(".blend")}, 2};
|
||||
case SBIG('CMDL'):
|
||||
return {CMDL::Extract, {_SYS_STR(".blend")}, 1, CMDL::Name};
|
||||
case SBIG('DCLN'):
|
||||
return {DCLN::Extract, {_SYS_STR(".blend")}};
|
||||
case SBIG('ANCS'):
|
||||
return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2};
|
||||
case SBIG('MLVL'):
|
||||
return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3};
|
||||
case SBIG('MREA'):
|
||||
return {MREA::Extract, {_SYS_STR(".blend")}, 4, MREA::Name};
|
||||
case SBIG('MAPA'):
|
||||
return {MAPA::Extract, {_SYS_STR(".blend")}, 4};
|
||||
case SBIG('MAPU'):
|
||||
return {MAPU::Extract, {_SYS_STR(".blend")}, 5};
|
||||
case SBIG('PATH'):
|
||||
return {PATH::Extract, {_SYS_STR(".blend")}, 5};
|
||||
case SBIG('PART'):
|
||||
return {DNAParticle::ExtractGPSM<UniqueID32>, {_SYS_STR(".gpsm.yaml")}};
|
||||
case SBIG('ELSC'):
|
||||
return {DNAParticle::ExtractELSM<UniqueID32>, {_SYS_STR(".elsm.yaml")}};
|
||||
case SBIG('SWHC'):
|
||||
return {DNAParticle::ExtractSWSH<UniqueID32>, {_SYS_STR(".swsh.yaml")}};
|
||||
case SBIG('CRSC'):
|
||||
return {DNAParticle::ExtractCRSM<UniqueID32>, {_SYS_STR(".crsm.yaml")}};
|
||||
case SBIG('WPSC'):
|
||||
return {DNAParticle::ExtractWPSM<UniqueID32>, {_SYS_STR(".wpsm.yaml")}};
|
||||
case SBIG('DPSC'):
|
||||
return {DNAParticle::ExtractDPSM<UniqueID32>, {_SYS_STR(".dpsm.yaml")}};
|
||||
case SBIG('FONT'):
|
||||
return {DNAFont::ExtractFONT<UniqueID32>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('DGRP'):
|
||||
return {DNADGRP::ExtractDGRP<UniqueID32>, {_SYS_STR(".yaml")}};
|
||||
case SBIG('AGSC'):
|
||||
return {AGSC::Extract, {}};
|
||||
case SBIG('CSNG'):
|
||||
return {CSNG::Extract, {_SYS_STR(".mid"), _SYS_STR(".yaml")}};
|
||||
case SBIG('ATBL'):
|
||||
return {DNAAudio::ATBL::Extract, {_SYS_STR(".yaml")}};
|
||||
case SBIG('CTWK'):
|
||||
case SBIG('DUMB'): {
|
||||
bool named;
|
||||
std::string name = pak.bestEntryName(pakNode, entry, named);
|
||||
if (named) {
|
||||
if (!name.compare("PlayerRes"))
|
||||
return {ExtractTweak<CTweakPlayerRes>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("GunRes"))
|
||||
return {ExtractTweak<CTweakGunRes>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Player"))
|
||||
return {ExtractTweak<CTweakPlayer>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("CameraBob"))
|
||||
return {ExtractTweak<CTweakCameraBob>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("SlideShow"))
|
||||
return {ExtractTweak<CTweakSlideShow>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Game"))
|
||||
return {ExtractTweak<CTweakGame>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Targeting"))
|
||||
return {ExtractTweak<CTweakTargeting>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Gui"))
|
||||
return {ExtractTweak<CTweakGui>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("AutoMapper"))
|
||||
return {ExtractTweak<CTweakAutoMapper>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("PlayerControls") || !name.compare("PlayerControls2"))
|
||||
return {ExtractTweak<CTweakPlayerControl>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Ball"))
|
||||
return {ExtractTweak<CTweakBall>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("Particle"))
|
||||
return {ExtractTweak<CTweakParticle>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("GuiColors"))
|
||||
return {ExtractTweak<CTweakGuiColors>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("PlayerGun"))
|
||||
return {ExtractTweak<CTweakPlayerGun>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("DUMB_MazeSeeds"))
|
||||
return {ExtractTweak<MazeSeeds>, {_SYS_STR(".yaml")}};
|
||||
if (!name.compare("DUMB_SnowForces"))
|
||||
return {ExtractTweak<SnowForces>, {_SYS_STR(".yaml")}};
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -4,40 +4,36 @@
|
|||
#include "PAK.hpp"
|
||||
#include "zeus/CMatrix4f.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
extern logvisor::Module Log;
|
||||
|
||||
/* MP1-specific, one-shot PAK traversal/extraction class */
|
||||
class PAKBridge
|
||||
{
|
||||
const nod::Node& m_node;
|
||||
PAK m_pak;
|
||||
class PAKBridge {
|
||||
const nod::Node& m_node;
|
||||
PAK m_pak;
|
||||
|
||||
public:
|
||||
bool m_doExtract;
|
||||
using Level = DataSpec::Level<UniqueID32>;
|
||||
std::unordered_map<UniqueID32, Level> m_levelDeps;
|
||||
hecl::SystemString m_levelString;
|
||||
bool m_doExtract;
|
||||
using Level = DataSpec::Level<UniqueID32>;
|
||||
std::unordered_map<UniqueID32, Level> m_levelDeps;
|
||||
hecl::SystemString m_levelString;
|
||||
|
||||
PAKBridge(const nod::Node& node, bool doExtract=true);
|
||||
void build();
|
||||
static ResExtractor<PAKBridge> LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry);
|
||||
std::string_view getName() const {return m_node.getName();}
|
||||
hecl::SystemStringView getLevelString() const {return m_levelString;}
|
||||
using PAKType = PAK;
|
||||
const PAKType& getPAK() const {return m_pak;}
|
||||
const nod::Node& getNode() const {return m_node;}
|
||||
PAKBridge(const nod::Node& node, bool doExtract = true);
|
||||
void build();
|
||||
static ResExtractor<PAKBridge> LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry);
|
||||
std::string_view getName() const { return m_node.getName(); }
|
||||
hecl::SystemStringView getLevelString() const { return m_levelString; }
|
||||
using PAKType = PAK;
|
||||
const PAKType& getPAK() const { return m_pak; }
|
||||
const nod::Node& getNode() const { return m_node; }
|
||||
|
||||
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const;
|
||||
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const;
|
||||
|
||||
void addPATHToMREA(PAKRouter<PAKBridge>& pakRouter,
|
||||
std::unordered_map<UniqueID32, UniqueID32>& pathToMrea) const;
|
||||
void addPATHToMREA(PAKRouter<PAKBridge>& pakRouter, std::unordered_map<UniqueID32, UniqueID32>& pathToMrea) const;
|
||||
|
||||
void addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||
std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
|
||||
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const;
|
||||
void addMAPATransforms(PAKRouter<PAKBridge>& pakRouter, std::unordered_map<UniqueID32, zeus::CMatrix4f>& addTo,
|
||||
std::unordered_map<UniqueID32, hecl::ProjectPath>& pathOverrides) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -1,233 +1,232 @@
|
|||
#include "DeafBabe.hpp"
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os)
|
||||
{
|
||||
os << "TYPE_COLORS = {'NoSFX':(0.0, 0.0, 0.0),\n"
|
||||
" 'Stone':(1.0, 0.43, 0.15),\n"
|
||||
" 'Metal':(0.5, 0.5, 0.5),\n"
|
||||
" 'Grass':(0.0, 0.42, 0.01),"
|
||||
" 'Ice':(0.0, 0.1, 0.1),\n"
|
||||
" 'Metal Grating':(0.09, 0.09, 0.09),\n"
|
||||
" 'Phazon':(0.24, 0.0, 0.21),\n"
|
||||
" 'Dirt':(0.1, 0.07, 0.05),\n"
|
||||
" 'Stone':(0.12, 0.12, 0.12),\n"
|
||||
" 'Lava':(0.8, 0.15, 0.0),\n"
|
||||
" 'Stone/Rock':(0.06, 0.05, 0.03),\n"
|
||||
" 'Snow':(0.9, 1.0, 1.0),\n"
|
||||
" 'Mud (Slow)':(0.12, 0.06, 0.02),\n"
|
||||
" 'Mud':(0.12, 0.06, 0.02),\n"
|
||||
" 'Glass':(0.27, 0.38, 0.9),\n"
|
||||
" 'Shield':(1.0, 0.6, 0.0),\n"
|
||||
" 'Sand':(0.53, 0.44, 0.21),\n"
|
||||
" 'Wood':(0.30, 0.15, 0.03),\n"
|
||||
" 'Organic':(0.19, 0.45, 0.2)}\n"
|
||||
"\n"
|
||||
"# Diffuse Color Maker\n"
|
||||
"def make_color(index, mat_type, name):\n"
|
||||
" new_mat = bpy.data.materials.new(name)\n"
|
||||
" if mat_type in TYPE_COLORS:\n"
|
||||
" new_mat.diffuse_color = TYPE_COLORS[mat_type]\n"
|
||||
" else:\n"
|
||||
" new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n"
|
||||
" return new_mat\n"
|
||||
"\n"
|
||||
"bpy.types.Material.retro_unknown = bpy.props.BoolProperty(name='Retro: Unknown (U)')\n"
|
||||
"bpy.types.Material.retro_surface_stone = bpy.props.BoolProperty(name='Retro Surface: Stone')\n"
|
||||
"bpy.types.Material.retro_surface_metal = bpy.props.BoolProperty(name='Retro Surface: Metal')\n"
|
||||
"bpy.types.Material.retro_surface_grass = bpy.props.BoolProperty(name='Retro Surface: Grass')\n"
|
||||
"bpy.types.Material.retro_surface_ice = bpy.props.BoolProperty(name='Retro Surface: Ice')\n"
|
||||
"bpy.types.Material.retro_pillar = bpy.props.BoolProperty(name='Retro Pillar (I)')\n"
|
||||
"bpy.types.Material.retro_surface_metal_grating = bpy.props.BoolProperty(name='Retro Surface: Metal Grating')\n"
|
||||
"bpy.types.Material.retro_surface_phazon = bpy.props.BoolProperty(name='Retro Surface: Phazon')\n"
|
||||
"bpy.types.Material.retro_surface_dirt = bpy.props.BoolProperty(name='Retro Surface: Rock')\n"
|
||||
"bpy.types.Material.retro_surface_lava = bpy.props.BoolProperty(name='Retro Surface: Lava')\n"
|
||||
"bpy.types.Material.retro_surface_lava_stone = bpy.props.BoolProperty(name='Retro Surface: Lava Stone')\n"
|
||||
"bpy.types.Material.retro_surface_snow = bpy.props.BoolProperty(name='Retro Surface: Snow')\n"
|
||||
"bpy.types.Material.retro_surface_mud_slow = bpy.props.BoolProperty(name='Retro Surface: Mud (Slow)')\n"
|
||||
"bpy.types.Material.retro_half_pipe = bpy.props.BoolProperty(name='Retro: Half Pipe (H)')\n"
|
||||
"bpy.types.Material.retro_surface_mud = bpy.props.BoolProperty(name='Retro Surface: Mud')\n"
|
||||
"bpy.types.Material.retro_surface_glass = bpy.props.BoolProperty(name='Retro Surface: Glass')\n"
|
||||
"bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(name='Retro Surface: Shield')\n"
|
||||
"bpy.types.Material.retro_surface_sand = bpy.props.BoolProperty(name='Retro Surface: Sand')\n"
|
||||
"bpy.types.Material.retro_projectile_passthrough = bpy.props.BoolProperty(name='Retro: Projectile Passthrough (P)')\n"
|
||||
"bpy.types.Material.retro_solid = bpy.props.BoolProperty(name='Retro: Solid (K)')\n"
|
||||
"bpy.types.Material.retro_no_platform_collision = bpy.props.BoolProperty(name='Retro: No Platform Collision')\n"
|
||||
"bpy.types.Material.retro_camera_passthrough = bpy.props.BoolProperty(name='Retro: Camera Passthrough (O)')\n"
|
||||
"bpy.types.Material.retro_surface_wood = bpy.props.BoolProperty(name='Retro Surface: Wood')\n"
|
||||
"bpy.types.Material.retro_surface_organic = bpy.props.BoolProperty(name='Retro Surface: Organic')\n"
|
||||
"bpy.types.Material.retro_no_edge_collision = bpy.props.BoolProperty(name='Retro: No Edge Collision')\n"
|
||||
"bpy.types.Material.retro_see_through = bpy.props.BoolProperty(name='Retro: See Through')\n"
|
||||
"bpy.types.Material.retro_scan_passthrough = bpy.props.BoolProperty(name='Retro: Scan Passthrough (S)')\n"
|
||||
"bpy.types.Material.retro_ai_passthrough = bpy.props.BoolProperty(name='Retro: AI Passthrough (A)')\n"
|
||||
"bpy.types.Material.retro_ceiling = bpy.props.BoolProperty(name='Retro: Ceiling (C)')\n"
|
||||
"bpy.types.Material.retro_wall = bpy.props.BoolProperty(name='Retro: Wall (W)')\n"
|
||||
"bpy.types.Material.retro_floor = bpy.props.BoolProperty(name='Retro: Floor (F)')\n"
|
||||
"\n"
|
||||
"material_dict = {}\n"
|
||||
"material_index = []\n"
|
||||
"def get_type_id(data):\n"
|
||||
"\n"
|
||||
" ret = 0\n"
|
||||
" for i in range(1, 24):\n"
|
||||
" if i == 5 or i == 13 or i in range(18, 22):\n"
|
||||
" continue\n"
|
||||
" if ((data >> i) & 1):\n"
|
||||
" ret = i\n"
|
||||
" return ret\n"
|
||||
"\n"
|
||||
"def select_material(data):\n"
|
||||
"\n"
|
||||
" type_id = get_type_id(data)\n"
|
||||
" mat_type = str(type_id)\n"
|
||||
" if type_id == 0:\n"
|
||||
" mat_type = 'NoSFX'\n"
|
||||
" if type_id == 1:\n"
|
||||
" mat_type = 'Stone'\n"
|
||||
" elif type_id == 2:\n"
|
||||
" mat_type = 'Metal'\n"
|
||||
" elif type_id == 3:\n"
|
||||
" mat_type = 'Grass'\n"
|
||||
" elif type_id == 4:\n"
|
||||
" mat_type = 'Ice'\n"
|
||||
" elif type_id == 6:\n"
|
||||
" mat_type = 'Metal Grating'\n"
|
||||
" elif type_id == 7:\n"
|
||||
" mat_type = 'Phazon'\n"
|
||||
" elif type_id == 8:\n"
|
||||
" mat_type = 'Dirt'\n"
|
||||
" elif type_id == 9:\n"
|
||||
" mat_type = 'Lava'\n"
|
||||
" elif type_id == 10:\n"
|
||||
" mat_type = 'Stone/Rock'\n"
|
||||
" elif type_id == 11:\n"
|
||||
" mat_type = 'Snow'\n"
|
||||
" elif type_id == 12:\n"
|
||||
" mat_type = 'Mud (Slow)'\n"
|
||||
" elif type_id == 14:\n"
|
||||
" mat_type = 'Mud'\n"
|
||||
" elif type_id == 15:\n"
|
||||
" mat_type = 'Glass'\n"
|
||||
" elif type_id == 16:\n"
|
||||
" mat_type = 'Shield'\n"
|
||||
" elif type_id == 17:\n"
|
||||
" mat_type = 'Sand'\n"
|
||||
" elif type_id == 22:\n"
|
||||
" mat_type = 'Wood'\n"
|
||||
" elif type_id == 23:\n"
|
||||
" mat_type = 'Organic'\n"
|
||||
"\n"
|
||||
" mat_flags = ''\n"
|
||||
" if ((data >> 0) & 1):\n"
|
||||
" mat_flags += 'U'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 5) & 1):\n"
|
||||
" mat_flags += 'I'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 13) & 1):\n"
|
||||
" mat_flags += 'H'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 18) & 1):\n"
|
||||
" mat_flags += 'P'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 19) & 1):\n"
|
||||
" mat_flags += 'K'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 20) & 1):\n"
|
||||
" mat_flags += 'u'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 21) & 1):\n"
|
||||
" mat_flags += 'O'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 24) & 1):\n"
|
||||
" mat_flags += 'u'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 26) & 1):\n"
|
||||
" mat_flags += 'T'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 27) & 1):\n"
|
||||
" mat_flags += 'S'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 28) & 1):\n"
|
||||
" mat_flags += 'A'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 29) & 1):\n"
|
||||
" mat_flags += 'C'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 30) & 1):\n"
|
||||
" mat_flags += 'W'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 31) & 1):\n"
|
||||
" mat_flags += 'F'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
"\n"
|
||||
" if len(mat_flags) > 0:\n"
|
||||
" mat_flags = ' ' + mat_flags\n"
|
||||
"\n"
|
||||
" mat_name = mat_type + mat_flags\n"
|
||||
"\n"
|
||||
" if mat_name in material_index:\n"
|
||||
" return material_index.index(mat_name)\n"
|
||||
" elif mat_name in material_dict:\n"
|
||||
" material_index.append(mat_name)\n"
|
||||
" return len(material_index)-1\n"
|
||||
" else:\n"
|
||||
" mat = make_color(len(material_dict), mat_type, mat_name)\n"
|
||||
" mat.diffuse_intensity = 1.0\n"
|
||||
" mat.specular_intensity = 0.0\n"
|
||||
" mat.retro_unknown = ((data >> 0) & 1)\n"
|
||||
" mat.retro_surface_stone = ((data >> 1) & 1)\n"
|
||||
" mat.retro_surface_metal = ((data >> 2) & 1)\n"
|
||||
" mat.retro_surface_grass = ((data >> 3) & 1) \n"
|
||||
" mat.retro_surface_ice = ((data >> 4) & 1)\n"
|
||||
" mat.retro_pillar = ((data >> 5) & 1)\n"
|
||||
" mat.retro_surface_metal_grating = ((data >> 6) & 1)\n"
|
||||
" mat.retro_surface_phazon = ((data >> 7) & 1)\n"
|
||||
" mat.retro_surface_dirt = ((data >> 8) & 1)\n"
|
||||
" mat.retro_surface_lava = ((data >> 9) & 1)\n"
|
||||
" mat.retro_surface_lava_stone = ((data >> 10) & 1)\n"
|
||||
" mat.retro_surface_snow = ((data >> 11) & 1)\n"
|
||||
" mat.retro_surface_mud_slow = ((data >> 12) & 1)\n"
|
||||
" mat.retro_half_pipe = ((data >> 13) & 1)\n"
|
||||
" mat.retro_surface_mud = ((data >> 14) & 1)\n"
|
||||
" mat.retro_surface_glass = ((data >> 15) & 1)\n"
|
||||
" mat.retro_surface_shield = ((data >> 16) & 1)\n"
|
||||
" mat.retro_surface_sand = ((data >> 17) & 1)\n"
|
||||
" mat.retro_projectile_passthrough = ((data >> 18) & 1)\n"
|
||||
" mat.retro_solid = ((data >> 19) & 1)\n"
|
||||
" mat.retro_no_platform_collision = ((data >> 20) & 1)\n"
|
||||
" mat.retro_camera_passthrough = ((data >> 21) & 1)\n"
|
||||
" mat.retro_surface_wood = ((data >> 22) & 1)\n"
|
||||
" mat.retro_surface_organic = ((data >> 23) & 1)\n"
|
||||
" mat.retro_no_edge_collision = ((data >> 24) & 1)\n"
|
||||
" mat.retro_see_through = ((data >> 26) & 1)\n"
|
||||
" mat.retro_scan_passthrough = ((data >> 27) & 1)\n"
|
||||
" mat.retro_ai_passthrough = ((data >> 28) & 1)\n"
|
||||
" mat.retro_ceiling = ((data >> 29) & 1)\n"
|
||||
" mat.retro_wall= ((data >> 30) & 1)\n"
|
||||
" mat.retro_floor = ((data >> 31) & 1)\n"
|
||||
" material_dict[mat_name] = mat\n"
|
||||
" material_index.append(mat_name)\n"
|
||||
" return len(material_index)-1\n"
|
||||
"\n"
|
||||
"\n";
|
||||
void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) {
|
||||
os << "TYPE_COLORS = {'NoSFX':(0.0, 0.0, 0.0),\n"
|
||||
" 'Stone':(1.0, 0.43, 0.15),\n"
|
||||
" 'Metal':(0.5, 0.5, 0.5),\n"
|
||||
" 'Grass':(0.0, 0.42, 0.01),"
|
||||
" 'Ice':(0.0, 0.1, 0.1),\n"
|
||||
" 'Metal Grating':(0.09, 0.09, 0.09),\n"
|
||||
" 'Phazon':(0.24, 0.0, 0.21),\n"
|
||||
" 'Dirt':(0.1, 0.07, 0.05),\n"
|
||||
" 'Stone':(0.12, 0.12, 0.12),\n"
|
||||
" 'Lava':(0.8, 0.15, 0.0),\n"
|
||||
" 'Stone/Rock':(0.06, 0.05, 0.03),\n"
|
||||
" 'Snow':(0.9, 1.0, 1.0),\n"
|
||||
" 'Mud (Slow)':(0.12, 0.06, 0.02),\n"
|
||||
" 'Mud':(0.12, 0.06, 0.02),\n"
|
||||
" 'Glass':(0.27, 0.38, 0.9),\n"
|
||||
" 'Shield':(1.0, 0.6, 0.0),\n"
|
||||
" 'Sand':(0.53, 0.44, 0.21),\n"
|
||||
" 'Wood':(0.30, 0.15, 0.03),\n"
|
||||
" 'Organic':(0.19, 0.45, 0.2)}\n"
|
||||
"\n"
|
||||
"# Diffuse Color Maker\n"
|
||||
"def make_color(index, mat_type, name):\n"
|
||||
" new_mat = bpy.data.materials.new(name)\n"
|
||||
" if mat_type in TYPE_COLORS:\n"
|
||||
" new_mat.diffuse_color = TYPE_COLORS[mat_type]\n"
|
||||
" else:\n"
|
||||
" new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n"
|
||||
" return new_mat\n"
|
||||
"\n"
|
||||
"bpy.types.Material.retro_unknown = bpy.props.BoolProperty(name='Retro: Unknown (U)')\n"
|
||||
"bpy.types.Material.retro_surface_stone = bpy.props.BoolProperty(name='Retro Surface: Stone')\n"
|
||||
"bpy.types.Material.retro_surface_metal = bpy.props.BoolProperty(name='Retro Surface: Metal')\n"
|
||||
"bpy.types.Material.retro_surface_grass = bpy.props.BoolProperty(name='Retro Surface: Grass')\n"
|
||||
"bpy.types.Material.retro_surface_ice = bpy.props.BoolProperty(name='Retro Surface: Ice')\n"
|
||||
"bpy.types.Material.retro_pillar = bpy.props.BoolProperty(name='Retro Pillar (I)')\n"
|
||||
"bpy.types.Material.retro_surface_metal_grating = bpy.props.BoolProperty(name='Retro Surface: Metal Grating')\n"
|
||||
"bpy.types.Material.retro_surface_phazon = bpy.props.BoolProperty(name='Retro Surface: Phazon')\n"
|
||||
"bpy.types.Material.retro_surface_dirt = bpy.props.BoolProperty(name='Retro Surface: Rock')\n"
|
||||
"bpy.types.Material.retro_surface_lava = bpy.props.BoolProperty(name='Retro Surface: Lava')\n"
|
||||
"bpy.types.Material.retro_surface_lava_stone = bpy.props.BoolProperty(name='Retro Surface: Lava Stone')\n"
|
||||
"bpy.types.Material.retro_surface_snow = bpy.props.BoolProperty(name='Retro Surface: Snow')\n"
|
||||
"bpy.types.Material.retro_surface_mud_slow = bpy.props.BoolProperty(name='Retro Surface: Mud (Slow)')\n"
|
||||
"bpy.types.Material.retro_half_pipe = bpy.props.BoolProperty(name='Retro: Half Pipe (H)')\n"
|
||||
"bpy.types.Material.retro_surface_mud = bpy.props.BoolProperty(name='Retro Surface: Mud')\n"
|
||||
"bpy.types.Material.retro_surface_glass = bpy.props.BoolProperty(name='Retro Surface: Glass')\n"
|
||||
"bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(name='Retro Surface: Shield')\n"
|
||||
"bpy.types.Material.retro_surface_sand = bpy.props.BoolProperty(name='Retro Surface: Sand')\n"
|
||||
"bpy.types.Material.retro_projectile_passthrough = bpy.props.BoolProperty(name='Retro: Projectile Passthrough "
|
||||
"(P)')\n"
|
||||
"bpy.types.Material.retro_solid = bpy.props.BoolProperty(name='Retro: Solid (K)')\n"
|
||||
"bpy.types.Material.retro_no_platform_collision = bpy.props.BoolProperty(name='Retro: No Platform Collision')\n"
|
||||
"bpy.types.Material.retro_camera_passthrough = bpy.props.BoolProperty(name='Retro: Camera Passthrough (O)')\n"
|
||||
"bpy.types.Material.retro_surface_wood = bpy.props.BoolProperty(name='Retro Surface: Wood')\n"
|
||||
"bpy.types.Material.retro_surface_organic = bpy.props.BoolProperty(name='Retro Surface: Organic')\n"
|
||||
"bpy.types.Material.retro_no_edge_collision = bpy.props.BoolProperty(name='Retro: No Edge Collision')\n"
|
||||
"bpy.types.Material.retro_see_through = bpy.props.BoolProperty(name='Retro: See Through')\n"
|
||||
"bpy.types.Material.retro_scan_passthrough = bpy.props.BoolProperty(name='Retro: Scan Passthrough (S)')\n"
|
||||
"bpy.types.Material.retro_ai_passthrough = bpy.props.BoolProperty(name='Retro: AI Passthrough (A)')\n"
|
||||
"bpy.types.Material.retro_ceiling = bpy.props.BoolProperty(name='Retro: Ceiling (C)')\n"
|
||||
"bpy.types.Material.retro_wall = bpy.props.BoolProperty(name='Retro: Wall (W)')\n"
|
||||
"bpy.types.Material.retro_floor = bpy.props.BoolProperty(name='Retro: Floor (F)')\n"
|
||||
"\n"
|
||||
"material_dict = {}\n"
|
||||
"material_index = []\n"
|
||||
"def get_type_id(data):\n"
|
||||
"\n"
|
||||
" ret = 0\n"
|
||||
" for i in range(1, 24):\n"
|
||||
" if i == 5 or i == 13 or i in range(18, 22):\n"
|
||||
" continue\n"
|
||||
" if ((data >> i) & 1):\n"
|
||||
" ret = i\n"
|
||||
" return ret\n"
|
||||
"\n"
|
||||
"def select_material(data):\n"
|
||||
"\n"
|
||||
" type_id = get_type_id(data)\n"
|
||||
" mat_type = str(type_id)\n"
|
||||
" if type_id == 0:\n"
|
||||
" mat_type = 'NoSFX'\n"
|
||||
" if type_id == 1:\n"
|
||||
" mat_type = 'Stone'\n"
|
||||
" elif type_id == 2:\n"
|
||||
" mat_type = 'Metal'\n"
|
||||
" elif type_id == 3:\n"
|
||||
" mat_type = 'Grass'\n"
|
||||
" elif type_id == 4:\n"
|
||||
" mat_type = 'Ice'\n"
|
||||
" elif type_id == 6:\n"
|
||||
" mat_type = 'Metal Grating'\n"
|
||||
" elif type_id == 7:\n"
|
||||
" mat_type = 'Phazon'\n"
|
||||
" elif type_id == 8:\n"
|
||||
" mat_type = 'Dirt'\n"
|
||||
" elif type_id == 9:\n"
|
||||
" mat_type = 'Lava'\n"
|
||||
" elif type_id == 10:\n"
|
||||
" mat_type = 'Stone/Rock'\n"
|
||||
" elif type_id == 11:\n"
|
||||
" mat_type = 'Snow'\n"
|
||||
" elif type_id == 12:\n"
|
||||
" mat_type = 'Mud (Slow)'\n"
|
||||
" elif type_id == 14:\n"
|
||||
" mat_type = 'Mud'\n"
|
||||
" elif type_id == 15:\n"
|
||||
" mat_type = 'Glass'\n"
|
||||
" elif type_id == 16:\n"
|
||||
" mat_type = 'Shield'\n"
|
||||
" elif type_id == 17:\n"
|
||||
" mat_type = 'Sand'\n"
|
||||
" elif type_id == 22:\n"
|
||||
" mat_type = 'Wood'\n"
|
||||
" elif type_id == 23:\n"
|
||||
" mat_type = 'Organic'\n"
|
||||
"\n"
|
||||
" mat_flags = ''\n"
|
||||
" if ((data >> 0) & 1):\n"
|
||||
" mat_flags += 'U'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 5) & 1):\n"
|
||||
" mat_flags += 'I'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 13) & 1):\n"
|
||||
" mat_flags += 'H'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 18) & 1):\n"
|
||||
" mat_flags += 'P'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 19) & 1):\n"
|
||||
" mat_flags += 'K'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 20) & 1):\n"
|
||||
" mat_flags += 'u'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 21) & 1):\n"
|
||||
" mat_flags += 'O'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 24) & 1):\n"
|
||||
" mat_flags += 'u'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 26) & 1):\n"
|
||||
" mat_flags += 'T'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 27) & 1):\n"
|
||||
" mat_flags += 'S'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 28) & 1):\n"
|
||||
" mat_flags += 'A'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 29) & 1):\n"
|
||||
" mat_flags += 'C'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 30) & 1):\n"
|
||||
" mat_flags += 'W'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
" if ((data >> 31) & 1):\n"
|
||||
" mat_flags += 'F'\n"
|
||||
" else:\n"
|
||||
" mat_flags += 'x'\n"
|
||||
"\n"
|
||||
" if len(mat_flags) > 0:\n"
|
||||
" mat_flags = ' ' + mat_flags\n"
|
||||
"\n"
|
||||
" mat_name = mat_type + mat_flags\n"
|
||||
"\n"
|
||||
" if mat_name in material_index:\n"
|
||||
" return material_index.index(mat_name)\n"
|
||||
" elif mat_name in material_dict:\n"
|
||||
" material_index.append(mat_name)\n"
|
||||
" return len(material_index)-1\n"
|
||||
" else:\n"
|
||||
" mat = make_color(len(material_dict), mat_type, mat_name)\n"
|
||||
" mat.diffuse_intensity = 1.0\n"
|
||||
" mat.specular_intensity = 0.0\n"
|
||||
" mat.retro_unknown = ((data >> 0) & 1)\n"
|
||||
" mat.retro_surface_stone = ((data >> 1) & 1)\n"
|
||||
" mat.retro_surface_metal = ((data >> 2) & 1)\n"
|
||||
" mat.retro_surface_grass = ((data >> 3) & 1) \n"
|
||||
" mat.retro_surface_ice = ((data >> 4) & 1)\n"
|
||||
" mat.retro_pillar = ((data >> 5) & 1)\n"
|
||||
" mat.retro_surface_metal_grating = ((data >> 6) & 1)\n"
|
||||
" mat.retro_surface_phazon = ((data >> 7) & 1)\n"
|
||||
" mat.retro_surface_dirt = ((data >> 8) & 1)\n"
|
||||
" mat.retro_surface_lava = ((data >> 9) & 1)\n"
|
||||
" mat.retro_surface_lava_stone = ((data >> 10) & 1)\n"
|
||||
" mat.retro_surface_snow = ((data >> 11) & 1)\n"
|
||||
" mat.retro_surface_mud_slow = ((data >> 12) & 1)\n"
|
||||
" mat.retro_half_pipe = ((data >> 13) & 1)\n"
|
||||
" mat.retro_surface_mud = ((data >> 14) & 1)\n"
|
||||
" mat.retro_surface_glass = ((data >> 15) & 1)\n"
|
||||
" mat.retro_surface_shield = ((data >> 16) & 1)\n"
|
||||
" mat.retro_surface_sand = ((data >> 17) & 1)\n"
|
||||
" mat.retro_projectile_passthrough = ((data >> 18) & 1)\n"
|
||||
" mat.retro_solid = ((data >> 19) & 1)\n"
|
||||
" mat.retro_no_platform_collision = ((data >> 20) & 1)\n"
|
||||
" mat.retro_camera_passthrough = ((data >> 21) & 1)\n"
|
||||
" mat.retro_surface_wood = ((data >> 22) & 1)\n"
|
||||
" mat.retro_surface_organic = ((data >> 23) & 1)\n"
|
||||
" mat.retro_no_edge_collision = ((data >> 24) & 1)\n"
|
||||
" mat.retro_see_through = ((data >> 26) & 1)\n"
|
||||
" mat.retro_scan_passthrough = ((data >> 27) & 1)\n"
|
||||
" mat.retro_ai_passthrough = ((data >> 28) & 1)\n"
|
||||
" mat.retro_ceiling = ((data >> 29) & 1)\n"
|
||||
" mat.retro_wall= ((data >> 30) & 1)\n"
|
||||
" mat.retro_floor = ((data >> 31) & 1)\n"
|
||||
" material_dict[mat_name] = mat\n"
|
||||
" material_index.append(mat_name)\n"
|
||||
" return len(material_index)-1\n"
|
||||
"\n"
|
||||
"\n";
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
|
@ -2,152 +2,239 @@
|
|||
|
||||
#include "DataSpec/DNACommon/DeafBabe.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1
|
||||
{
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
struct DeafBabe : BigDNA
|
||||
{
|
||||
struct DeafBabe : BigDNA {
|
||||
AT_DECL_DNA
|
||||
using BspNodeType = DataSpec::BspNodeType;
|
||||
|
||||
struct Material : BigDNA {
|
||||
AT_DECL_DNA
|
||||
using BspNodeType = DataSpec::BspNodeType;
|
||||
|
||||
struct Material : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint32> material = 0;
|
||||
bool unknown() const { return material & 1; }
|
||||
void setUnknown(bool v) { material &= ~1; material |= int(v); }
|
||||
bool surfaceStone() const { return (material >> 1) & 1; }
|
||||
void setSurfaceStone(bool v) { material &= ~(1ull << 1); material |= (v << 1); }
|
||||
bool surfaceMetal() const { return (material >> 2) & 1; }
|
||||
void setSurfaceMetal(bool v) { material &= ~(1ull << 2); material |= (v << 2); }
|
||||
bool surfaceGrass() const { return (material >> 3) & 1; }
|
||||
void setSurfaceGrass(bool v) { material &= ~(1ull << 3); material |= (v << 3); }
|
||||
bool surfaceIce() const { return (material >> 4) & 1; }
|
||||
void setSurfaceIce(bool v) { material &= ~(1ull << 4); material |= (v << 4); }
|
||||
bool pillar() const { return (material >> 5) & 1; }
|
||||
void setPillar(bool v) { material &= ~(1ull << 5); material |= (v << 5); }
|
||||
bool surfaceMetalGrating() const { return (material >> 6) & 1; }
|
||||
void setSurfaceMetalGrating(bool v) { material &= ~(1ull << 6); material |= (v << 6); }
|
||||
bool surfacePhazon() const { return (material >> 7) & 1; }
|
||||
void setSurfacePhazon(bool v) { material &= ~(1ull << 7); material |= (v << 7); }
|
||||
bool surfaceDirt() const { return (material >> 8) & 1; }
|
||||
void setSurfaceDirt(bool v) { material &= ~(1ull << 8); material |= (v << 8); }
|
||||
bool surfaceLava() const {return (material >> 9) & 1; }
|
||||
void setSurfaceLava(bool v) { material &= ~(1ull << 9); material |= (v << 9); }
|
||||
bool surfaceStoneRock() const { return (material >> 10) & 1; }
|
||||
void setSurfaceLavaStone(bool v) { material &= ~(1ull << 10); material |= (v << 10); }
|
||||
bool surfaceSnow() const { return (material >> 11) & 1; }
|
||||
void setSurfaceSnow(bool v) { material &= ~(1ull << 11); material |= (v << 11); }
|
||||
bool surfaceMudSlow() const { return (material >> 12) & 1; }
|
||||
void setSurfaceMudSlow(bool v) { material &= ~(1ull << 12); material |= (v << 12); }
|
||||
bool halfPipe() const { return (material >> 13) & 1; }
|
||||
void setHalfPipe(bool v) { material &= ~(1ull << 13); material |= (v << 13); }
|
||||
bool surfaceMud() const { return (material >> 14) & 1; }
|
||||
void setSurfaceMud(bool v) { material &= ~(1ull << 14); material |= (v << 14); }
|
||||
bool surfaceGlass() const { return (material >> 15) & 1; }
|
||||
void setSurfaceGlass(bool v) { material &= ~(1ull << 15); material |= (v << 15); }
|
||||
bool surfaceShield() const { return (material >> 16) & 1; }
|
||||
void setSurfaceShield(bool v) { material &= ~(1ull << 16); material |= (v << 16); }
|
||||
bool surfaceSand() const { return (material >> 17) & 1; }
|
||||
void setSurfaceSand(bool v) { material &= ~(1ull << 17); material |= (v << 17); }
|
||||
bool projectilePassthrough() const { return (material >> 18) & 1; }
|
||||
void setProjectilePassthrough(bool v) { material &= ~(1ull << 18); material |= (v << 18); }
|
||||
bool solid() const { return (material >> 19) & 1; }
|
||||
void setSolid(bool v) { material &= ~(1ull << 19); material |= (v << 19); }
|
||||
bool noPlatformCollision() const { return (material >> 20) & 1; }
|
||||
void setNoPlatformCollision(bool v) { material &= ~(1ull << 20); material |= (v << 20); }
|
||||
bool cameraPassthrough() const { return (material >> 21) & 1; }
|
||||
void setCameraPassthrough(bool v) { material &= ~(1ull << 21); material |= (v << 21); }
|
||||
bool surfaceWood() const { return (material >> 22) & 1; }
|
||||
void setSurfaceWood(bool v) { material &= ~(1ull << 22); material |= (v << 22); }
|
||||
bool surfaceOrganic() const { return (material >> 23) & 1; }
|
||||
void setSurfaceOrganic(bool v) { material &= ~(1ull << 23); material |= (v << 23); }
|
||||
bool noEdgeCollision() const { return (material >> 24) & 1; }
|
||||
void setNoEdgeCollision(bool v) { material &= ~(1ull << 24); material |= (v << 24); }
|
||||
bool flipFace() const { return (material >> 25) & 1; }
|
||||
void setFlipFace(bool v) { material &= ~(1ull << 25); material |= (v << 25); }
|
||||
bool seeThrough() const { return (material >> 26) & 1; }
|
||||
void setSeeThrough(bool v) { material &= ~(1ull << 26); material |= (v << 26); }
|
||||
bool scanPassthrough() const { return (material >> 27) & 1; }
|
||||
void setScanPassthrough(bool v) { material &= ~(1ull << 27); material |= (v << 27); }
|
||||
bool aiPassthrough() const { return (material >> 28) & 1; }
|
||||
void setAiPassthrough(bool v) { material &= ~(1ull << 28); material |= (v << 28); }
|
||||
bool ceiling() const { return (material >> 29) & 1; }
|
||||
void setCeiling(bool v) { material &= ~(1ull << 29); material |= (v << 29); }
|
||||
bool wall() const { return (material >> 30) & 1; }
|
||||
void setWall(bool v) { material &= ~(1ull << 30); material |= (v << 30); }
|
||||
bool floor() const { return (material >> 31) & 1; }
|
||||
void setFloor(bool v) { material &= ~(1ull << 31); material |= (v << 31); }
|
||||
|
||||
/* Dummies for later games */
|
||||
bool surfaceSPMetal() const { return false; }
|
||||
void setSurfaceSPMetal(bool v) { }
|
||||
bool surfaceFabric() const { return false; }
|
||||
void setSurfaceFabric(bool v) { }
|
||||
bool surfaceRubber() const { return false; }
|
||||
void setSurfaceRubber(bool v) { }
|
||||
bool surfaceMothOrSeedOrganics() const { return false; }
|
||||
void setSurfaceMothOrSeedOrganics(bool v) { }
|
||||
bool surfaceWeb() const { return false; }
|
||||
void setSurfaceWeb(bool v) { }
|
||||
bool unused3() const { return false; }
|
||||
void setUnused3(bool v) {}
|
||||
bool unused4() const { return false; }
|
||||
void setUnused4(bool v) {}
|
||||
bool aiBlock() const { return false; }
|
||||
void setAiBlock(bool v) { }
|
||||
bool jumpNotAllowed() const { return false; }
|
||||
void setJumpNotAllowed(bool v) { }
|
||||
bool spiderBall() const { return false; }
|
||||
void setSpiderBall(bool v) { }
|
||||
bool screwAttackWallJump() const { return false; }
|
||||
void setScrewAttackWallJump(bool v) { }
|
||||
};
|
||||
|
||||
struct Edge : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint16> verts[2];
|
||||
};
|
||||
|
||||
struct Triangle : BigDNA
|
||||
{
|
||||
AT_DECL_DNA
|
||||
Value<atUint16> edges[3];
|
||||
};
|
||||
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> length;
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
Value<atVec3f> aabb[2];
|
||||
Value<BspNodeType> rootNodeType;
|
||||
Value<atUint32> bspSize;
|
||||
Buffer<AT_DNA_COUNT(bspSize)> bspTree;
|
||||
Value<atUint32> materialCount;
|
||||
Vector<Material, AT_DNA_COUNT(materialCount)> materials;
|
||||
Value<atUint32> vertMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(vertMatsCount)> vertMats;
|
||||
Value<atUint32> edgeMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(edgeMatsCount)> edgeMats;
|
||||
Value<atUint32> triMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(triMatsCount)> triMats;
|
||||
Value<atUint32> edgeVertsCount;
|
||||
Vector<Edge, AT_DNA_COUNT(edgeVertsCount)> edgeVertConnections;
|
||||
Value<atUint32> triangleEdgesCount;
|
||||
Vector<Triangle, AT_DNA_COUNT(triangleEdgesCount / 3)> triangleEdgeConnections;
|
||||
Value<atUint32> vertCount;
|
||||
Vector<atVec3f, AT_DNA_COUNT(vertCount)> verts;
|
||||
|
||||
/* Dummy MP2 member */
|
||||
void insertNoClimb(hecl::blender::PyOutStream&) const {}
|
||||
|
||||
static void BlenderInit(hecl::blender::PyOutStream& os);
|
||||
void sendToBlender(hecl::blender::PyOutStream& os) const
|
||||
{
|
||||
DeafBabeSendToBlender(os, *this);
|
||||
Value<atUint32> material = 0;
|
||||
bool unknown() const { return material & 1; }
|
||||
void setUnknown(bool v) {
|
||||
material &= ~1;
|
||||
material |= int(v);
|
||||
}
|
||||
bool surfaceStone() const { return (material >> 1) & 1; }
|
||||
void setSurfaceStone(bool v) {
|
||||
material &= ~(1ull << 1);
|
||||
material |= (v << 1);
|
||||
}
|
||||
bool surfaceMetal() const { return (material >> 2) & 1; }
|
||||
void setSurfaceMetal(bool v) {
|
||||
material &= ~(1ull << 2);
|
||||
material |= (v << 2);
|
||||
}
|
||||
bool surfaceGrass() const { return (material >> 3) & 1; }
|
||||
void setSurfaceGrass(bool v) {
|
||||
material &= ~(1ull << 3);
|
||||
material |= (v << 3);
|
||||
}
|
||||
bool surfaceIce() const { return (material >> 4) & 1; }
|
||||
void setSurfaceIce(bool v) {
|
||||
material &= ~(1ull << 4);
|
||||
material |= (v << 4);
|
||||
}
|
||||
bool pillar() const { return (material >> 5) & 1; }
|
||||
void setPillar(bool v) {
|
||||
material &= ~(1ull << 5);
|
||||
material |= (v << 5);
|
||||
}
|
||||
bool surfaceMetalGrating() const { return (material >> 6) & 1; }
|
||||
void setSurfaceMetalGrating(bool v) {
|
||||
material &= ~(1ull << 6);
|
||||
material |= (v << 6);
|
||||
}
|
||||
bool surfacePhazon() const { return (material >> 7) & 1; }
|
||||
void setSurfacePhazon(bool v) {
|
||||
material &= ~(1ull << 7);
|
||||
material |= (v << 7);
|
||||
}
|
||||
bool surfaceDirt() const { return (material >> 8) & 1; }
|
||||
void setSurfaceDirt(bool v) {
|
||||
material &= ~(1ull << 8);
|
||||
material |= (v << 8);
|
||||
}
|
||||
bool surfaceLava() const { return (material >> 9) & 1; }
|
||||
void setSurfaceLava(bool v) {
|
||||
material &= ~(1ull << 9);
|
||||
material |= (v << 9);
|
||||
}
|
||||
bool surfaceStoneRock() const { return (material >> 10) & 1; }
|
||||
void setSurfaceLavaStone(bool v) {
|
||||
material &= ~(1ull << 10);
|
||||
material |= (v << 10);
|
||||
}
|
||||
bool surfaceSnow() const { return (material >> 11) & 1; }
|
||||
void setSurfaceSnow(bool v) {
|
||||
material &= ~(1ull << 11);
|
||||
material |= (v << 11);
|
||||
}
|
||||
bool surfaceMudSlow() const { return (material >> 12) & 1; }
|
||||
void setSurfaceMudSlow(bool v) {
|
||||
material &= ~(1ull << 12);
|
||||
material |= (v << 12);
|
||||
}
|
||||
bool halfPipe() const { return (material >> 13) & 1; }
|
||||
void setHalfPipe(bool v) {
|
||||
material &= ~(1ull << 13);
|
||||
material |= (v << 13);
|
||||
}
|
||||
bool surfaceMud() const { return (material >> 14) & 1; }
|
||||
void setSurfaceMud(bool v) {
|
||||
material &= ~(1ull << 14);
|
||||
material |= (v << 14);
|
||||
}
|
||||
bool surfaceGlass() const { return (material >> 15) & 1; }
|
||||
void setSurfaceGlass(bool v) {
|
||||
material &= ~(1ull << 15);
|
||||
material |= (v << 15);
|
||||
}
|
||||
bool surfaceShield() const { return (material >> 16) & 1; }
|
||||
void setSurfaceShield(bool v) {
|
||||
material &= ~(1ull << 16);
|
||||
material |= (v << 16);
|
||||
}
|
||||
bool surfaceSand() const { return (material >> 17) & 1; }
|
||||
void setSurfaceSand(bool v) {
|
||||
material &= ~(1ull << 17);
|
||||
material |= (v << 17);
|
||||
}
|
||||
bool projectilePassthrough() const { return (material >> 18) & 1; }
|
||||
void setProjectilePassthrough(bool v) {
|
||||
material &= ~(1ull << 18);
|
||||
material |= (v << 18);
|
||||
}
|
||||
bool solid() const { return (material >> 19) & 1; }
|
||||
void setSolid(bool v) {
|
||||
material &= ~(1ull << 19);
|
||||
material |= (v << 19);
|
||||
}
|
||||
bool noPlatformCollision() const { return (material >> 20) & 1; }
|
||||
void setNoPlatformCollision(bool v) {
|
||||
material &= ~(1ull << 20);
|
||||
material |= (v << 20);
|
||||
}
|
||||
bool cameraPassthrough() const { return (material >> 21) & 1; }
|
||||
void setCameraPassthrough(bool v) {
|
||||
material &= ~(1ull << 21);
|
||||
material |= (v << 21);
|
||||
}
|
||||
bool surfaceWood() const { return (material >> 22) & 1; }
|
||||
void setSurfaceWood(bool v) {
|
||||
material &= ~(1ull << 22);
|
||||
material |= (v << 22);
|
||||
}
|
||||
bool surfaceOrganic() const { return (material >> 23) & 1; }
|
||||
void setSurfaceOrganic(bool v) {
|
||||
material &= ~(1ull << 23);
|
||||
material |= (v << 23);
|
||||
}
|
||||
bool noEdgeCollision() const { return (material >> 24) & 1; }
|
||||
void setNoEdgeCollision(bool v) {
|
||||
material &= ~(1ull << 24);
|
||||
material |= (v << 24);
|
||||
}
|
||||
bool flipFace() const { return (material >> 25) & 1; }
|
||||
void setFlipFace(bool v) {
|
||||
material &= ~(1ull << 25);
|
||||
material |= (v << 25);
|
||||
}
|
||||
bool seeThrough() const { return (material >> 26) & 1; }
|
||||
void setSeeThrough(bool v) {
|
||||
material &= ~(1ull << 26);
|
||||
material |= (v << 26);
|
||||
}
|
||||
bool scanPassthrough() const { return (material >> 27) & 1; }
|
||||
void setScanPassthrough(bool v) {
|
||||
material &= ~(1ull << 27);
|
||||
material |= (v << 27);
|
||||
}
|
||||
bool aiPassthrough() const { return (material >> 28) & 1; }
|
||||
void setAiPassthrough(bool v) {
|
||||
material &= ~(1ull << 28);
|
||||
material |= (v << 28);
|
||||
}
|
||||
bool ceiling() const { return (material >> 29) & 1; }
|
||||
void setCeiling(bool v) {
|
||||
material &= ~(1ull << 29);
|
||||
material |= (v << 29);
|
||||
}
|
||||
bool wall() const { return (material >> 30) & 1; }
|
||||
void setWall(bool v) {
|
||||
material &= ~(1ull << 30);
|
||||
material |= (v << 30);
|
||||
}
|
||||
bool floor() const { return (material >> 31) & 1; }
|
||||
void setFloor(bool v) {
|
||||
material &= ~(1ull << 31);
|
||||
material |= (v << 31);
|
||||
}
|
||||
|
||||
/* Dummies for later games */
|
||||
bool surfaceSPMetal() const { return false; }
|
||||
void setSurfaceSPMetal(bool v) {}
|
||||
bool surfaceFabric() const { return false; }
|
||||
void setSurfaceFabric(bool v) {}
|
||||
bool surfaceRubber() const { return false; }
|
||||
void setSurfaceRubber(bool v) {}
|
||||
bool surfaceMothOrSeedOrganics() const { return false; }
|
||||
void setSurfaceMothOrSeedOrganics(bool v) {}
|
||||
bool surfaceWeb() const { return false; }
|
||||
void setSurfaceWeb(bool v) {}
|
||||
bool unused3() const { return false; }
|
||||
void setUnused3(bool v) {}
|
||||
bool unused4() const { return false; }
|
||||
void setUnused4(bool v) {}
|
||||
bool aiBlock() const { return false; }
|
||||
void setAiBlock(bool v) {}
|
||||
bool jumpNotAllowed() const { return false; }
|
||||
void setJumpNotAllowed(bool v) {}
|
||||
bool spiderBall() const { return false; }
|
||||
void setSpiderBall(bool v) {}
|
||||
bool screwAttackWallJump() const { return false; }
|
||||
void setScrewAttackWallJump(bool v) {}
|
||||
};
|
||||
|
||||
struct Edge : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint16> verts[2];
|
||||
};
|
||||
|
||||
struct Triangle : BigDNA {
|
||||
AT_DECL_DNA
|
||||
Value<atUint16> edges[3];
|
||||
};
|
||||
|
||||
Value<atUint32> unk1;
|
||||
Value<atUint32> length;
|
||||
Value<atUint32> magic;
|
||||
Value<atUint32> version;
|
||||
Value<atVec3f> aabb[2];
|
||||
Value<BspNodeType> rootNodeType;
|
||||
Value<atUint32> bspSize;
|
||||
Buffer<AT_DNA_COUNT(bspSize)> bspTree;
|
||||
Value<atUint32> materialCount;
|
||||
Vector<Material, AT_DNA_COUNT(materialCount)> materials;
|
||||
Value<atUint32> vertMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(vertMatsCount)> vertMats;
|
||||
Value<atUint32> edgeMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(edgeMatsCount)> edgeMats;
|
||||
Value<atUint32> triMatsCount;
|
||||
Vector<atUint8, AT_DNA_COUNT(triMatsCount)> triMats;
|
||||
Value<atUint32> edgeVertsCount;
|
||||
Vector<Edge, AT_DNA_COUNT(edgeVertsCount)> edgeVertConnections;
|
||||
Value<atUint32> triangleEdgesCount;
|
||||
Vector<Triangle, AT_DNA_COUNT(triangleEdgesCount / 3)> triangleEdgeConnections;
|
||||
Value<atUint32> vertCount;
|
||||
Vector<atVec3f, AT_DNA_COUNT(vertCount)> verts;
|
||||
|
||||
/* Dummy MP2 member */
|
||||
void insertNoClimb(hecl::blender::PyOutStream&) const {}
|
||||
|
||||
static void BlenderInit(hecl::blender::PyOutStream& os);
|
||||
void sendToBlender(hecl::blender::PyOutStream& os) const { DeafBabeSendToBlender(os, *this); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // namespace DataSpec::DNAMP1
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue