mirror of https://github.com/AxioDL/metaforce.git
Merge branch 'master' of ssh://git.axiodl.com:6431/AxioDL/urde into mp2-fixes
This commit is contained in:
commit
e858c929e3
|
@ -0,0 +1 @@
|
|||
Checks: '*,-misc-unused-parameters,-modernize-use-trailing-return-type,-readability-named-parameter,-readability-convert-member-functions-to-static,-readability-uppercase-literal-suffix,-readability-magic-numbers,-hicpp-uppercase-literal-suffix,-hicpp-signed-bitwise,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-non-private-member-variables-in-classes,-fuchsia-*,-google-runtime-references'
|
|
@ -36,8 +36,15 @@ endif()
|
|||
|
||||
project(urde VERSION 0.1.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
# MSVC has a "latest" flag, which always uses the newest standard
|
||||
# when available. GCC and Clang posess no such flag, and must be
|
||||
# manually enforced. CMake, curiously, also doesn't have a "latest"
|
||||
# standard flag either.
|
||||
if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Force shared libs off" FORCE)
|
||||
set(BUILD_STATIC_LIBS ON CACHE BOOL "Force static libs on" FORCE)
|
||||
|
||||
|
@ -84,10 +91,17 @@ if(MSVC)
|
|||
set(HAVE_WORDS_BIGENDIAN_EXITCODE 0)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
|
||||
add_compile_options(/EHsc)
|
||||
|
||||
# Link-time Code Generation for Release builds (excluding clang-cl)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
add_compile_options(
|
||||
/std:c++latest # Use latest C++ standard.
|
||||
/permissive- # Enforce various standards compliance features.
|
||||
/Zc:externConstexpr # Allow extern constexpr variables according to the standard.
|
||||
/Zc:throwingNew # Assume new throws, allowing for better code generation.
|
||||
)
|
||||
|
||||
# Link-time Code Generation for Release builds (excluding clang-cl)
|
||||
set(CMAKE_C_FLAGS_RELEASE "/DNDEBUG /O2 /Oy /GL /Gy /MD")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "/DNDEBUG /Zi /O2 /Oy- /GL /Gy /MD")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "/LTCG")
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
#include "AROTBuilder.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
#include "hecl/Blender/Connection.hpp"
|
||||
#include "PATH.hpp"
|
||||
|
||||
namespace DataSpec {
|
||||
logvisor::Module Log("AROTBuilder");
|
||||
|
||||
#define AROT_MAX_LEVEL 10
|
||||
#define AROT_MIN_SUBDIV 10.f
|
||||
#define AROT_MIN_MODELS 8
|
||||
#define COLLISION_MIN_NODE_TRIANGLES 8
|
||||
#define PATH_MIN_NODE_REGIONS 16
|
||||
constexpr s32 AROT_MAX_LEVEL = 10;
|
||||
constexpr s32 AROT_MIN_MODELS = 8;
|
||||
constexpr s32 COLLISION_MIN_NODE_TRIANGLES = 8;
|
||||
constexpr s32 PATH_MIN_NODE_REGIONS = 16;
|
||||
constexpr float AROT_MIN_SUBDIV = 10.f;
|
||||
|
||||
static zeus::CAABox SplitAABB(const zeus::CAABox& aabb, int i) {
|
||||
zeus::CAABox pos, neg;
|
||||
|
@ -128,7 +132,9 @@ size_t AROTBuilder::BitmapPool::addIndices(const std::set<int>& indices) {
|
|||
return m_pool.size() - 1;
|
||||
}
|
||||
|
||||
static const uint32_t AROTChildCounts[] = {0, 2, 2, 4, 2, 4, 4, 8};
|
||||
constexpr std::array<uint32_t, 8> 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;
|
||||
|
@ -176,7 +182,7 @@ void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx) {
|
|||
if (curIdx > 65535)
|
||||
Log.report(logvisor::Fatal, fmt("AROT node exceeds 16-bit node addressing; area too complex"));
|
||||
|
||||
int childIndices[8];
|
||||
std::array<int, 8> childIndices;
|
||||
|
||||
for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) {
|
||||
for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) {
|
||||
|
@ -280,17 +286,16 @@ void AROTBuilder::Node::pathWrite(DNAPATH::PATH<PAKBridge>& path, const zeus::CA
|
|||
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;
|
||||
std::fill(std::begin(n.children), std::end(n.children), 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) {
|
||||
std::array<atUint32, 8> children;
|
||||
for (size_t i = 0; i < children.size(); ++i) {
|
||||
/* Head recursion (first node will be a leaf) */
|
||||
childNodes[i].pathWrite(path, SplitAABB(curAABB, i));
|
||||
childNodes[i].pathWrite(path, SplitAABB(curAABB, static_cast<int>(i)));
|
||||
children[i] = path.octree.size() - 1;
|
||||
}
|
||||
|
||||
|
@ -299,8 +304,7 @@ void AROTBuilder::Node::pathWrite(DNAPATH::PATH<PAKBridge>& path, const zeus::CA
|
|||
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];
|
||||
std::copy(children.cbegin(), children.cend(), std::begin(n.children));
|
||||
n.regionCount = 0;
|
||||
n.regionStart = 0;
|
||||
}
|
||||
|
@ -346,18 +350,20 @@ void AROTBuilder::build(std::vector<std::vector<uint8_t>>& secs, const zeus::CAA
|
|||
auto bmpIt = bmp.cbegin();
|
||||
if (bmpIt != bmp.cend()) {
|
||||
int curIdx = 0;
|
||||
for (size_t w = 0; w < bmpWordCount; ++w) {
|
||||
for (int b = 0; b < 32; ++b) {
|
||||
for (size_t word = 0; word < bmpWordCount; ++word) {
|
||||
for (u32 b = 0; b < 32; ++b) {
|
||||
if (*bmpIt == curIdx) {
|
||||
bmpWords[w] |= 1 << b;
|
||||
bmpWords[word] |= 1U << b;
|
||||
++bmpIt;
|
||||
if (bmpIt == bmp.cend())
|
||||
if (bmpIt == bmp.cend()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
++curIdx;
|
||||
}
|
||||
if (bmpIt == bmp.cend())
|
||||
if (bmpIt == bmp.cend()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -381,10 +387,10 @@ std::pair<std::unique_ptr<uint8_t[]>, uint32_t> AROTBuilder::buildCol(const ColM
|
|||
triBoxes.reserve(mesh.trianges.size());
|
||||
for (const ColMesh::Triangle& tri : mesh.trianges) {
|
||||
zeus::CAABox& aabb = triBoxes.emplace_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]];
|
||||
for (const u32 edgeIdx : tri.edges) {
|
||||
const ColMesh::Edge& edge = mesh.edges[edgeIdx];
|
||||
for (const u32 vertIdx : edge.verts) {
|
||||
const auto& vert = mesh.verts[vertIdx];
|
||||
aabb.accumulateBounds(zeus::CVector3f(vert));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,9 +48,7 @@ bool ATBL::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
maxI = std::max(maxI, i);
|
||||
}
|
||||
|
||||
std::vector<uint16_t> vecOut;
|
||||
vecOut.resize(maxI + 1, 0xffff);
|
||||
|
||||
std::vector<uint16_t> vecOut(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)));
|
||||
|
|
|
@ -1,248 +1,24 @@
|
|||
#include "DataSpec/DNACommon/CRSC.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "DataSpec/DNACommon/PAK.hpp"
|
||||
|
||||
#include <logvisor/logvisor.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')};
|
||||
|
||||
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'),
|
||||
};
|
||||
template struct PPImpl<_CRSM<UniqueID32>>;
|
||||
template struct PPImpl<_CRSM<UniqueID64>>;
|
||||
|
||||
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')};
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_CRSM<UniqueID32>>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_CRSM<UniqueID64>>)
|
||||
|
||||
template <>
|
||||
std::string_view CRSM<UniqueID32>::DNAType() {
|
||||
return "CRSM<UniqueID32>"sv;
|
||||
std::string_view PPImpl<_CRSM<UniqueID32>>::DNAType() {
|
||||
return "urde::CRSM<UniqueID32>"sv;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string_view CRSM<UniqueID64>::DNAType() {
|
||||
return "CRSM<UniqueID64>"sv;
|
||||
std::string_view PPImpl<_CRSM<UniqueID64>>::DNAType() {
|
||||
return "urde::CRSM<UniqueID64>"sv;
|
||||
}
|
||||
|
||||
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, fmt("short FourCC in element '{}'"), elem.first);
|
||||
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) { 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) { return clsId == other; });
|
||||
if (sfx != SFXTypes.end()) {
|
||||
x10_sfx[clsId] = r.readInt32(clsId.toString());
|
||||
continue;
|
||||
}
|
||||
|
||||
auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(),
|
||||
[&clsId](const FourCC& other) { return clsId == other; });
|
||||
if (decal != DecalTypes.end()) {
|
||||
x20_decals[clsId].read(r);
|
||||
continue;
|
||||
}
|
||||
if (clsId == SBIG('RNGE'))
|
||||
x30_RNGE = r.readFloat();
|
||||
else if (clsId == SBIG('FOFF'))
|
||||
x34_FOFF = r.readFloat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()))
|
||||
pair.second.write(w);
|
||||
|
||||
for (const auto& pair : x10_sfx)
|
||||
if (pair.second != UINT32_MAX)
|
||||
w.writeUint32(pair.first.toString(), pair.second);
|
||||
|
||||
for (const auto& pair : x20_decals)
|
||||
if (pair.second)
|
||||
if (auto rec = w.enterSubRecord(pair.first.toString()))
|
||||
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>::_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 != UINT32_MAX)
|
||||
__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) {
|
||||
DNAFourCC clsId;
|
||||
clsId.read(r);
|
||||
if (clsId != SBIG('CRSM')) {
|
||||
LogModule.report(logvisor::Warning, fmt("non CRSM provided to CRSM parser"));
|
||||
return;
|
||||
}
|
||||
|
||||
while (clsId != SBIG('_END')) {
|
||||
clsId.read(r);
|
||||
auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(),
|
||||
[&clsId](const FourCC& other) { 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) { return clsId == other; });
|
||||
if (sfx != SFXTypes.end()) {
|
||||
DNAFourCC fcc;
|
||||
fcc.read(r);
|
||||
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) { 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, fmt("Unknown CRSM class {} @{}"), 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);
|
||||
}
|
||||
|
||||
for (const auto& pair : x10_sfx) {
|
||||
w.writeBytes(pair.first.getChars(), 4);
|
||||
if (pair.second != UINT32_MAX) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
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());
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
#ifndef ENTRY
|
||||
#define ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef RES_ENTRY
|
||||
#define RES_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef U32_ENTRY
|
||||
#define U32_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef FLOAT_ENTRY
|
||||
#define FLOAT_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
RES_ENTRY('NODP', NODP)
|
||||
RES_ENTRY('DEFS', DEFS)
|
||||
RES_ENTRY('CRTS', CRTS)
|
||||
RES_ENTRY('MTLS', MTLS)
|
||||
RES_ENTRY('GRAS', GRAS)
|
||||
RES_ENTRY('ICEE', ICEE)
|
||||
RES_ENTRY('GOOO', GOOO)
|
||||
RES_ENTRY('WODS', WODS)
|
||||
RES_ENTRY('WATR', WATR)
|
||||
RES_ENTRY('1MUD', _1MUD)
|
||||
RES_ENTRY('1LAV', _1LAV)
|
||||
RES_ENTRY('1SAN', _1SAN)
|
||||
RES_ENTRY('1PRJ', _1PRJ)
|
||||
RES_ENTRY('DCHR', DCHR)
|
||||
RES_ENTRY('DCHS', DCHS)
|
||||
RES_ENTRY('DCSH', DCSH)
|
||||
RES_ENTRY('DENM', DENM)
|
||||
RES_ENTRY('DESP', DESP)
|
||||
RES_ENTRY('DESH', DESH)
|
||||
RES_ENTRY('BTLE', BTLE)
|
||||
RES_ENTRY('WASP', WASP)
|
||||
RES_ENTRY('TALP', TALP)
|
||||
RES_ENTRY('PTGM', PTGM)
|
||||
RES_ENTRY('SPIR', SPIR)
|
||||
RES_ENTRY('FPIR', FPIR)
|
||||
RES_ENTRY('FFLE', FFLE)
|
||||
RES_ENTRY('PARA', PARA)
|
||||
RES_ENTRY('BMON', BMON)
|
||||
RES_ENTRY('BFLR', BFLR)
|
||||
RES_ENTRY('PBOS', PBOS)
|
||||
RES_ENTRY('IBOS', IBOS)
|
||||
RES_ENTRY('1SVA', _1SVA)
|
||||
RES_ENTRY('1RPR', _1RPR)
|
||||
RES_ENTRY('1MTR', _1MTR)
|
||||
RES_ENTRY('1PDS', _1PDS)
|
||||
RES_ENTRY('1FLB', _1FLB)
|
||||
RES_ENTRY('1DRN', _1DRN)
|
||||
RES_ENTRY('1MRE', _1MRE)
|
||||
RES_ENTRY('CHOZ', CHOZ)
|
||||
RES_ENTRY('JZAP', JZAP)
|
||||
RES_ENTRY('1ISE', _1ISE)
|
||||
RES_ENTRY('1BSE', _1BSE)
|
||||
RES_ENTRY('1ATB', _1ATB)
|
||||
RES_ENTRY('1ATA', _1ATA)
|
||||
RES_ENTRY('BTSP', BTSP)
|
||||
RES_ENTRY('WWSP', WWSP)
|
||||
RES_ENTRY('TASP', TASP)
|
||||
RES_ENTRY('TGSP', TGSP)
|
||||
RES_ENTRY('SPSP', SPSP)
|
||||
RES_ENTRY('FPSP', FPSP)
|
||||
RES_ENTRY('FFSP', FFSP)
|
||||
RES_ENTRY('PSSP', PSSP)
|
||||
RES_ENTRY('BMSP', BMSP)
|
||||
RES_ENTRY('BFSP', BFSP)
|
||||
RES_ENTRY('PBSP', PBSP)
|
||||
RES_ENTRY('IBSP', IBSP)
|
||||
RES_ENTRY('2SVA', _2SVA)
|
||||
RES_ENTRY('2RPR', _2RPR)
|
||||
RES_ENTRY('2MTR', _2MTR)
|
||||
RES_ENTRY('2PDS', _2PDS)
|
||||
RES_ENTRY('2FLB', _2FLB)
|
||||
RES_ENTRY('2DRN', _2DRN)
|
||||
RES_ENTRY('2MRE', _2MRE)
|
||||
RES_ENTRY('CHSP', CHSP)
|
||||
RES_ENTRY('JZSP', JZSP)
|
||||
RES_ENTRY('3ISE', _3ISE)
|
||||
RES_ENTRY('3BSE', _3BSE)
|
||||
RES_ENTRY('3ATB', _3ATB)
|
||||
RES_ENTRY('3ATA', _3ATA)
|
||||
RES_ENTRY('BTSH', BTSH)
|
||||
RES_ENTRY('WWSH', WWSH)
|
||||
RES_ENTRY('TASH', TASH)
|
||||
RES_ENTRY('TGSH', TGSH)
|
||||
RES_ENTRY('SPSH', SPSH)
|
||||
RES_ENTRY('FPSH', FPSH)
|
||||
RES_ENTRY('FFSH', FFSH)
|
||||
RES_ENTRY('PSSH', PSSH)
|
||||
RES_ENTRY('BMSH', BMSH)
|
||||
RES_ENTRY('BFSH', BFSH)
|
||||
RES_ENTRY('PBSH', PBSH)
|
||||
RES_ENTRY('IBSH', IBSH)
|
||||
RES_ENTRY('3SVA', _3SVA)
|
||||
RES_ENTRY('3RPR', _3RPR)
|
||||
RES_ENTRY('3MTR', _3MTR)
|
||||
RES_ENTRY('3PDS', _3PDS)
|
||||
RES_ENTRY('3FLB', _3FLB)
|
||||
RES_ENTRY('3DRN', _3DRN)
|
||||
RES_ENTRY('3MRE', _3MRE)
|
||||
RES_ENTRY('CHSH', CHSH)
|
||||
RES_ENTRY('JZSH', JZSH)
|
||||
RES_ENTRY('5ISE', _5ISE)
|
||||
RES_ENTRY('5BSE', _5BSE)
|
||||
RES_ENTRY('5ATB', _5ATB)
|
||||
RES_ENTRY('5ATA', _5ATA)
|
||||
RES_ENTRY('NCDL', NCDL)
|
||||
RES_ENTRY('DDCL', DDCL)
|
||||
RES_ENTRY('CODL', CODL)
|
||||
RES_ENTRY('MEDL', MEDL)
|
||||
RES_ENTRY('GRDL', GRDL)
|
||||
RES_ENTRY('ICDL', ICDL)
|
||||
RES_ENTRY('GODL', GODL)
|
||||
RES_ENTRY('WODL', WODL)
|
||||
RES_ENTRY('WTDL', WTDL)
|
||||
RES_ENTRY('3MUD', _3MUD)
|
||||
RES_ENTRY('3LAV', _3LAV)
|
||||
RES_ENTRY('3SAN', _3SAN)
|
||||
RES_ENTRY('CHDL', CHDL)
|
||||
RES_ENTRY('ENDL', ENDL)
|
||||
|
||||
U32_ENTRY('NSFX', NSFX)
|
||||
U32_ENTRY('DSFX', DSFX)
|
||||
U32_ENTRY('CSFX', CSFX)
|
||||
U32_ENTRY('MSFX', MSFX)
|
||||
U32_ENTRY('GRFX', GRFX)
|
||||
U32_ENTRY('ICFX', ICFX)
|
||||
U32_ENTRY('GOFX', GOFX)
|
||||
U32_ENTRY('WSFX', WSFX)
|
||||
U32_ENTRY('WTFX', WTFX)
|
||||
U32_ENTRY('2MUD', _2MUD)
|
||||
U32_ENTRY('2LAV', _2LAV)
|
||||
U32_ENTRY('2SAN', _2SAN)
|
||||
U32_ENTRY('2PRJ', _2PRJ)
|
||||
U32_ENTRY('DCFX', DCFX)
|
||||
U32_ENTRY('DSHX', DSHX)
|
||||
U32_ENTRY('DEFX', DEFX)
|
||||
U32_ENTRY('ESFX', ESFX)
|
||||
U32_ENTRY('SHFX', SHFX)
|
||||
U32_ENTRY('BEFX', BEFX)
|
||||
U32_ENTRY('WWFX', WWFX)
|
||||
U32_ENTRY('TAFX', TAFX)
|
||||
U32_ENTRY('GTFX', GTFX)
|
||||
U32_ENTRY('SPFX', SPFX)
|
||||
U32_ENTRY('FPFX', FPFX)
|
||||
U32_ENTRY('FFFX', FFFX)
|
||||
U32_ENTRY('PAFX', PAFX)
|
||||
U32_ENTRY('BMFX', BMFX)
|
||||
U32_ENTRY('BFFX', BFFX)
|
||||
U32_ENTRY('PBFX', PBFX)
|
||||
U32_ENTRY('IBFX', IBFX)
|
||||
U32_ENTRY('4SVA', _4SVA)
|
||||
U32_ENTRY('4RPR', _4RPR)
|
||||
U32_ENTRY('4MTR', _4MTR)
|
||||
U32_ENTRY('4PDS', _4PDS)
|
||||
U32_ENTRY('4FLB', _4FLB)
|
||||
U32_ENTRY('4DRN', _4DRN)
|
||||
U32_ENTRY('4MRE', _4MRE)
|
||||
U32_ENTRY('CZFX', CZFX)
|
||||
U32_ENTRY('JZAS', JZAS)
|
||||
U32_ENTRY('2ISE', _2ISE)
|
||||
U32_ENTRY('2BSE', _2BSE)
|
||||
U32_ENTRY('2ATB', _2ATB)
|
||||
U32_ENTRY('2ATA', _2ATA)
|
||||
U32_ENTRY('BSFX', BSFX)
|
||||
U32_ENTRY('TSFX', TSFX)
|
||||
U32_ENTRY('GSFX', GSFX)
|
||||
U32_ENTRY('SSFX', SSFX)
|
||||
U32_ENTRY('FSFX', FSFX)
|
||||
U32_ENTRY('SFFX', SFFX)
|
||||
U32_ENTRY('PSFX', PSFX)
|
||||
U32_ENTRY('SBFX', SBFX)
|
||||
U32_ENTRY('PBSX', PBSX)
|
||||
U32_ENTRY('IBSX', IBSX)
|
||||
U32_ENTRY('5SVA', _5SVA)
|
||||
U32_ENTRY('5RPR', _5RPR)
|
||||
U32_ENTRY('5MTR', _5MTR)
|
||||
U32_ENTRY('5PDS', _5PDS)
|
||||
U32_ENTRY('5FLB', _5FLB)
|
||||
U32_ENTRY('5DRN', _5DRN)
|
||||
U32_ENTRY('5MRE', _5MRE)
|
||||
U32_ENTRY('JZPS', JZPS)
|
||||
U32_ENTRY('4ISE', _4ISE)
|
||||
U32_ENTRY('4BSE', _4BSE)
|
||||
U32_ENTRY('4ATB', _4ATB)
|
||||
U32_ENTRY('4ATA', _4ATA)
|
||||
U32_ENTRY('BHFX', BHFX)
|
||||
U32_ENTRY('WHFX', WHFX)
|
||||
U32_ENTRY('THFX', THFX)
|
||||
U32_ENTRY('GHFX', GHFX)
|
||||
U32_ENTRY('FHFX', FHFX)
|
||||
U32_ENTRY('HFFX', HFFX)
|
||||
U32_ENTRY('PHFX', PHFX)
|
||||
U32_ENTRY('MHFX', MHFX)
|
||||
U32_ENTRY('HBFX', HBFX)
|
||||
U32_ENTRY('PBHX', PBHX)
|
||||
U32_ENTRY('IBHX', IBHX)
|
||||
U32_ENTRY('6SVA', _6SVA)
|
||||
U32_ENTRY('6RPR', _6RPR)
|
||||
U32_ENTRY('6MTR', _6MTR)
|
||||
U32_ENTRY('6PDS', _6PDS)
|
||||
U32_ENTRY('6FLB', _6FLB)
|
||||
U32_ENTRY('6DRN', _6DRN)
|
||||
U32_ENTRY('6MRE', _6MRE)
|
||||
U32_ENTRY('CHFX', CHFX)
|
||||
U32_ENTRY('JZHS', JZHS)
|
||||
U32_ENTRY('6ISE', _6ISE)
|
||||
U32_ENTRY('6BSE', _6BSE)
|
||||
U32_ENTRY('6ATB', _6ATB)
|
||||
U32_ENTRY('6ATA', _6ATA)
|
||||
|
||||
FLOAT_ENTRY('RNGE', x30_RNGE)
|
||||
FLOAT_ENTRY('FOFF', x34_FOFF)
|
||||
|
||||
#undef ENTRY
|
||||
#undef RES_ENTRY
|
||||
#undef U32_ENTRY
|
||||
#undef FLOAT_ENTRY
|
|
@ -18,20 +18,33 @@ class ProjectPath;
|
|||
}
|
||||
|
||||
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 {
|
||||
static constexpr ParticleType Type = ParticleType::CRSM;
|
||||
#define RES_ENTRY(name, identifier) ChildResourceFactory<IDType> identifier;
|
||||
#define U32_ENTRY(name, identifier) uint32_t identifier = ~0;
|
||||
#define FLOAT_ENTRY(name, identifier) float identifier = 0.f;
|
||||
#include "CRSC.def"
|
||||
|
||||
CRSM();
|
||||
template<typename _Func>
|
||||
void constexpr Enumerate(_Func f) {
|
||||
#define ENTRY(name, identifier) f(FOURCC(name), identifier);
|
||||
#include "CRSC.def"
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
template<typename _Func>
|
||||
bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
#define ENTRY(name, identifier) case SBIG(name): f(identifier); return true;
|
||||
#include "CRSC.def"
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class IDType>
|
||||
using CRSM = PPImpl<_CRSM<IDType>>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
||||
|
|
|
@ -118,40 +118,40 @@ public:
|
|||
using value_type = uint32_t;
|
||||
static UniqueID32 kInvalidId;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
bool isValid() const { return m_id != 0xffffffff && m_id != 0; }
|
||||
void assign(uint32_t id) { m_id = id ? id : 0xffffffff; }
|
||||
bool isValid() const noexcept { return m_id != 0xffffffff && m_id != 0; }
|
||||
void assign(uint32_t id) noexcept { m_id = id ? id : 0xffffffff; }
|
||||
|
||||
UniqueID32& operator=(const hecl::ProjectPath& path) {
|
||||
UniqueID32& operator=(const hecl::ProjectPath& path) noexcept {
|
||||
assign(path.parsedHash32());
|
||||
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; }
|
||||
bool operator!=(const UniqueID32& other) const noexcept { return m_id != other.m_id; }
|
||||
bool operator==(const UniqueID32& other) const noexcept { return m_id == other.m_id; }
|
||||
bool operator<(const UniqueID32& other) const noexcept { return m_id < other.m_id; }
|
||||
uint32_t toUint32() const noexcept { return m_id; }
|
||||
uint64_t toUint64() const noexcept { return m_id; }
|
||||
std::string toString() const;
|
||||
void clear() { m_id = 0xffffffff; }
|
||||
void clear() noexcept { m_id = 0xffffffff; }
|
||||
|
||||
UniqueID32() = default;
|
||||
UniqueID32(uint32_t idin) { assign(idin); }
|
||||
UniqueID32() noexcept = default;
|
||||
UniqueID32(uint32_t idin) noexcept { assign(idin); }
|
||||
UniqueID32(athena::io::IStreamReader& reader) { read(reader); }
|
||||
UniqueID32(const hecl::ProjectPath& path) { *this = path; }
|
||||
UniqueID32(const char* hexStr) {
|
||||
UniqueID32(const hecl::ProjectPath& path) noexcept { *this = path; }
|
||||
UniqueID32(const char* hexStr) noexcept {
|
||||
char copy[9];
|
||||
strncpy(copy, hexStr, 8);
|
||||
copy[8] = '\0';
|
||||
assign(strtoul(copy, nullptr, 16));
|
||||
}
|
||||
UniqueID32(const wchar_t* hexStr) {
|
||||
UniqueID32(const wchar_t* hexStr) noexcept{
|
||||
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() noexcept { return 4; }
|
||||
};
|
||||
|
||||
/** PAK 32-bit Unique ID - writes zero when invalid */
|
||||
|
@ -169,39 +169,39 @@ class UniqueID64 : public BigDNA {
|
|||
public:
|
||||
using value_type = uint64_t;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
bool isValid() const { return m_id != 0xffffffffffffffff && m_id != 0; }
|
||||
void assign(uint64_t id) { m_id = id ? id : 0xffffffffffffffff; }
|
||||
bool isValid() const noexcept { return m_id != 0xffffffffffffffff && m_id != 0; }
|
||||
void assign(uint64_t id) noexcept { m_id = id ? id : 0xffffffffffffffff; }
|
||||
|
||||
UniqueID64& operator=(const hecl::ProjectPath& path) {
|
||||
UniqueID64& operator=(const hecl::ProjectPath& path) noexcept {
|
||||
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; }
|
||||
bool operator!=(const UniqueID64& other) const noexcept { return m_id != other.m_id; }
|
||||
bool operator==(const UniqueID64& other) const noexcept { return m_id == other.m_id; }
|
||||
bool operator<(const UniqueID64& other) const noexcept { return m_id < other.m_id; }
|
||||
uint64_t toUint64() const noexcept { return m_id; }
|
||||
std::string toString() const;
|
||||
void clear() { m_id = 0xffffffffffffffff; }
|
||||
void clear() noexcept { m_id = 0xffffffffffffffff; }
|
||||
|
||||
UniqueID64() = default;
|
||||
UniqueID64(uint64_t idin) { assign(idin); }
|
||||
UniqueID64() noexcept = default;
|
||||
UniqueID64(uint64_t idin) noexcept { assign(idin); }
|
||||
UniqueID64(athena::io::IStreamReader& reader) { read(reader); }
|
||||
UniqueID64(const hecl::ProjectPath& path) { *this = path; }
|
||||
UniqueID64(const char* hexStr) {
|
||||
UniqueID64(const hecl::ProjectPath& path) noexcept { *this = path; }
|
||||
UniqueID64(const char* hexStr) noexcept {
|
||||
char copy[17];
|
||||
std::strncpy(copy, hexStr, 16);
|
||||
copy[16] = '\0';
|
||||
assign(std::strtoull(copy, nullptr, 16));
|
||||
}
|
||||
UniqueID64(const wchar_t* hexStr) {
|
||||
UniqueID64(const wchar_t* hexStr) noexcept {
|
||||
wchar_t copy[17];
|
||||
std::wcsncpy(copy, hexStr, 16);
|
||||
copy[16] = L'\0';
|
||||
assign(std::wcstoull(copy, nullptr, 16));
|
||||
}
|
||||
|
||||
static constexpr size_t BinarySize() { return 8; }
|
||||
static constexpr size_t BinarySize() noexcept { return 8; }
|
||||
};
|
||||
|
||||
/** PAK 128-bit Unique ID */
|
||||
|
@ -220,26 +220,26 @@ private:
|
|||
public:
|
||||
using value_type = uint64_t;
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
UniqueID128() {
|
||||
UniqueID128() noexcept {
|
||||
m_id.id[0] = 0xffffffffffffffff;
|
||||
m_id.id[1] = 0xffffffffffffffff;
|
||||
}
|
||||
UniqueID128(uint64_t idin) {
|
||||
UniqueID128(uint64_t idin) noexcept {
|
||||
m_id.id[0] = idin;
|
||||
m_id.id[1] = 0;
|
||||
}
|
||||
bool isValid() const {
|
||||
bool isValid() const noexcept {
|
||||
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) {
|
||||
UniqueID128& operator=(const hecl::ProjectPath& path) noexcept {
|
||||
m_id.id[0] = path.hash().val64();
|
||||
m_id.id[1] = 0;
|
||||
return *this;
|
||||
}
|
||||
UniqueID128(const hecl::ProjectPath& path) { *this = path; }
|
||||
UniqueID128(const hecl::ProjectPath& path) noexcept { *this = path; }
|
||||
|
||||
bool operator!=(const UniqueID128& other) const {
|
||||
bool operator!=(const UniqueID128& other) const noexcept {
|
||||
#if __SSE__
|
||||
__m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128);
|
||||
int vmask = _mm_movemask_epi8(vcmp);
|
||||
|
@ -248,7 +248,7 @@ public:
|
|||
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 noexcept {
|
||||
#if __SSE__
|
||||
__m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128);
|
||||
int vmask = _mm_movemask_epi8(vcmp);
|
||||
|
@ -257,19 +257,19 @@ public:
|
|||
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 noexcept {
|
||||
return m_id.id[0] < other.m_id.id[0] || (m_id.id[0] == other.m_id.id[0] && m_id.id[1] < other.m_id.id[1]);
|
||||
}
|
||||
void clear() {
|
||||
void clear() noexcept {
|
||||
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]; }
|
||||
uint64_t toUint64() const noexcept { return m_id.id[0]; }
|
||||
uint64_t toHighUint64() const noexcept { return m_id.id[0]; }
|
||||
uint64_t toLowUint64() const noexcept { return m_id.id[1]; }
|
||||
std::string toString() const;
|
||||
|
||||
static constexpr size_t BinarySize() { return 16; }
|
||||
static constexpr size_t BinarySize() noexcept { return 16; }
|
||||
};
|
||||
|
||||
/** Casts ID type to its null-zero equivalent */
|
||||
|
@ -340,7 +340,7 @@ public:
|
|||
};
|
||||
|
||||
/** Resource cooker function */
|
||||
typedef std::function<bool(const hecl::ProjectPath&, const hecl::ProjectPath&)> ResCooker;
|
||||
using ResCooker = std::function<bool(const hecl::ProjectPath&, const hecl::ProjectPath&)>;
|
||||
|
||||
/** Mappings of resources involved in extracting characters */
|
||||
template <class IDType>
|
||||
|
@ -377,22 +377,22 @@ inline hecl::ProjectPath GetPathBeginsWith(const hecl::ProjectPath& parentPath,
|
|||
namespace std {
|
||||
template <>
|
||||
struct hash<DataSpec::DNAFourCC> {
|
||||
size_t operator()(const DataSpec::DNAFourCC& fcc) const { return fcc.toUint32(); }
|
||||
size_t operator()(const DataSpec::DNAFourCC& fcc) const noexcept{ return fcc.toUint32(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<DataSpec::UniqueID32> {
|
||||
size_t operator()(const DataSpec::UniqueID32& id) const { return id.toUint32(); }
|
||||
size_t operator()(const DataSpec::UniqueID32& id) const noexcept{ return id.toUint32(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<DataSpec::UniqueID64> {
|
||||
size_t operator()(const DataSpec::UniqueID64& id) const { return id.toUint64(); }
|
||||
size_t operator()(const DataSpec::UniqueID64& id) const noexcept{ return id.toUint64(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<DataSpec::UniqueID128> {
|
||||
size_t operator()(const DataSpec::UniqueID128& id) const { return id.toHighUint64() ^ id.toLowUint64(); }
|
||||
size_t operator()(const DataSpec::UniqueID128& id) const noexcept { return id.toHighUint64() ^ id.toLowUint64(); }
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
|
|
|
@ -1,391 +1,24 @@
|
|||
#include "DataSpec/DNACommon/DPSC.hpp"
|
||||
|
||||
#include "DataSpec/DNACommon/PAK.hpp"
|
||||
|
||||
#include <athena/DNAYaml.hpp>
|
||||
#include <logvisor/logvisor.hpp>
|
||||
|
||||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template struct PPImpl<_DPSM<UniqueID32>>;
|
||||
template struct PPImpl<_DPSM<UniqueID64>>;
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_DPSM<UniqueID32>>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_DPSM<UniqueID64>>)
|
||||
|
||||
template <>
|
||||
std::string_view DPSM<UniqueID32>::DNAType() {
|
||||
std::string_view PPImpl<_DPSM<UniqueID32>>::DNAType() {
|
||||
return "DPSM<UniqueID32>"sv;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string_view DPSM<UniqueID64>::DNAType() {
|
||||
std::string_view PPImpl<_DPSM<UniqueID64>>::DNAType() {
|
||||
return "DPSM<UniqueID64>"sv;
|
||||
}
|
||||
|
||||
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, fmt("short FourCC in element '{}'"), elem.first);
|
||||
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;
|
||||
[[fallthrough]];
|
||||
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();
|
||||
break;
|
||||
case SBIG('DMOO'):
|
||||
x5c_25_DMOO = r.readBool();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, FourCC clsId, typename DPSM<IDType>::SQuadDescr& quad) {
|
||||
switch (clsId.toUint32()) {
|
||||
case SBIG('1LFT'):
|
||||
case SBIG('2LFT'):
|
||||
quad.x0_LFT.read(r);
|
||||
break;
|
||||
case SBIG('1SZE'):
|
||||
case SBIG('2SZE'):
|
||||
quad.x4_SZE.read(r);
|
||||
break;
|
||||
case SBIG('1ROT'):
|
||||
case SBIG('2ROT'):
|
||||
quad.x8_ROT.read(r);
|
||||
break;
|
||||
case SBIG('1OFF'):
|
||||
case SBIG('2OFF'):
|
||||
quad.xc_OFF.read(r);
|
||||
break;
|
||||
case SBIG('1CLR'):
|
||||
case SBIG('2CLR'):
|
||||
quad.x10_CLR.read(r);
|
||||
break;
|
||||
case SBIG('1TEX'):
|
||||
case SBIG('2TEX'):
|
||||
quad.x14_TEX.read(r);
|
||||
break;
|
||||
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);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::_binarySize(size_t& s) const {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void DPSM<IDType>::_read(athena::io::IStreamReader& r) {
|
||||
DNAFourCC clsId;
|
||||
clsId.read(r);
|
||||
if (clsId != SBIG('DPSM')) {
|
||||
LogModule.report(logvisor::Warning, fmt("non DPSM provided to DPSM parser"));
|
||||
return;
|
||||
}
|
||||
bool loadFirstDesc = false;
|
||||
clsId.read(r);
|
||||
while (clsId != SBIG('_END')) {
|
||||
switch (clsId.toUint32()) {
|
||||
case SBIG('1SZE'):
|
||||
case SBIG('1LFT'):
|
||||
case SBIG('1ROT'):
|
||||
case SBIG('1OFF'):
|
||||
case SBIG('1CLR'):
|
||||
case SBIG('1TEX'):
|
||||
case SBIG('1ADD'):
|
||||
loadFirstDesc = true;
|
||||
[[fallthrough]];
|
||||
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, fmt("Unknown DPSM class {} @{}"), clsId, r.position());
|
||||
break;
|
||||
}
|
||||
clsId.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(DPSM<UniqueID32>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(DPSM<UniqueID64>)
|
||||
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());
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef ENTRY
|
||||
#define ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
ENTRY('1LFT', x0_quad.x0_LFT)
|
||||
ENTRY('1SZE', x0_quad.x4_SZE)
|
||||
ENTRY('1ROT', x0_quad.x8_ROT)
|
||||
ENTRY('1OFF', x0_quad.xc_OFF)
|
||||
ENTRY('1CLR', x0_quad.x10_CLR)
|
||||
ENTRY('1TEX', x0_quad.x14_TEX)
|
||||
ENTRY('1ADD', x0_quad.x18_ADD)
|
||||
ENTRY('2LFT', x1c_quad.x0_LFT)
|
||||
ENTRY('2SZE', x1c_quad.x4_SZE)
|
||||
ENTRY('2ROT', x1c_quad.x8_ROT)
|
||||
ENTRY('2OFF', x1c_quad.xc_OFF)
|
||||
ENTRY('2CLR', x1c_quad.x10_CLR)
|
||||
ENTRY('2TEX', x1c_quad.x14_TEX)
|
||||
ENTRY('2ADD', x1c_quad.x18_ADD)
|
||||
ENTRY('DMDL', x38_DMDL)
|
||||
ENTRY('DLFT', x48_DLFT)
|
||||
ENTRY('DMOP', x4c_DMOP)
|
||||
ENTRY('DMRT', x50_DMRT)
|
||||
ENTRY('DMSC', x54_DMSC)
|
||||
ENTRY('DMCL', x58_DMCL)
|
||||
ENTRY('DMAB', x5c_24_DMAB)
|
||||
ENTRY('DMOO', x5c_25_DMOO)
|
||||
|
||||
#undef ENTRY
|
|
@ -20,9 +20,8 @@ class ProjectPath;
|
|||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template <class IDType>
|
||||
struct DPSM : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
struct _DPSM {
|
||||
static constexpr ParticleType Type = ParticleType::DPSM;
|
||||
|
||||
struct SQuadDescr {
|
||||
IntElementFactory x0_LFT;
|
||||
|
@ -31,7 +30,7 @@ struct DPSM : BigDNA {
|
|||
VectorElementFactory xc_OFF;
|
||||
ColorElementFactory x10_CLR;
|
||||
UVElementFactory<IDType> x14_TEX;
|
||||
BoolHelper x18_ADD;
|
||||
bool x18_ADD = false;
|
||||
};
|
||||
|
||||
SQuadDescr x0_quad;
|
||||
|
@ -42,21 +41,27 @@ struct DPSM : BigDNA {
|
|||
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, FourCC 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;
|
||||
bool x5c_24_DMAB = false;
|
||||
bool x5c_25_DMOO = false;
|
||||
|
||||
template<typename _Func>
|
||||
void constexpr Enumerate(_Func f) {
|
||||
#define ENTRY(name, identifier) f(FOURCC(name), identifier);
|
||||
#include "DPSC.def"
|
||||
}
|
||||
|
||||
template<typename _Func>
|
||||
bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
#define ENTRY(name, identifier) case SBIG(name): f(identifier); return true;
|
||||
#include "DPSC.def"
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class IDType>
|
||||
using DPSM = PPImpl<_DPSM<IDType>>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractDPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
|
|
@ -1,403 +1,13 @@
|
|||
#include "DataSpec/DNACommon/ELSC.hpp"
|
||||
|
||||
#include <logvisor/logvisor.hpp>
|
||||
#include "DataSpec/DNACommon/PAK.hpp"
|
||||
|
||||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template <class IDType>
|
||||
void ELSM<IDType>::_read(athena::io::IStreamReader& r) {
|
||||
DNAFourCC clsId;
|
||||
clsId.read(r);
|
||||
if (clsId != SBIG('ELSM')) {
|
||||
LogModule.report(logvisor::Warning, fmt("non ELSM provided to ELSM parser"));
|
||||
return;
|
||||
}
|
||||
template struct PPImpl<_ELSM<UniqueID32>>;
|
||||
template struct PPImpl<_ELSM<UniqueID64>>;
|
||||
|
||||
clsId.read(r);
|
||||
while (clsId != SBIG('_END')) {
|
||||
switch (clsId.toUint32()) {
|
||||
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, fmt("Unknown ELSM class {} @{}"), clsId, r.position());
|
||||
break;
|
||||
}
|
||||
clsId.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void ELSM<IDType>::_binarySize(size_t& s) const {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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, fmt("short FourCC in element '{}'"), elem.first);
|
||||
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);
|
||||
}
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(ELSM<UniqueID32>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(ELSM<UniqueID64>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_ELSM<UniqueID32>>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_ELSM<UniqueID64>>)
|
||||
|
||||
template <>
|
||||
std::string_view ELSM<UniqueID32>::DNAType() {
|
||||
|
@ -409,16 +19,6 @@ std::string_view ELSM<UniqueID64>::DNAType() {
|
|||
return "urde::ELSM<UniqueID64>"sv;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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());
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
#ifndef ENTRY
|
||||
#define ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef INT_ENTRY
|
||||
#define INT_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef REAL_ENTRY
|
||||
#define REAL_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef COLOR_ENTRY
|
||||
#define COLOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef EMITTER_ENTRY
|
||||
#define EMITTER_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef RES_ENTRY
|
||||
#define RES_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef BOOL_ENTRY
|
||||
#define BOOL_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
INT_ENTRY('LIFE', x0_LIFE)
|
||||
INT_ENTRY('SLIF', x4_SLIF)
|
||||
REAL_ENTRY('GRAT', x8_GRAT)
|
||||
INT_ENTRY('SCNT', xc_SCNT)
|
||||
INT_ENTRY('SSEG', x10_SSEG)
|
||||
COLOR_ENTRY('COLR', x14_COLR)
|
||||
EMITTER_ENTRY('IEMT', x18_IEMT)
|
||||
EMITTER_ENTRY('FEMT', x1c_FEMT)
|
||||
REAL_ENTRY('AMPL', x20_AMPL)
|
||||
REAL_ENTRY('AMPD', x24_AMPD)
|
||||
REAL_ENTRY('LWD1', x28_LWD1)
|
||||
REAL_ENTRY('LWD2', x2c_LWD2)
|
||||
REAL_ENTRY('LWD3', x30_LWD3)
|
||||
COLOR_ENTRY('LCL1', x34_LCL1)
|
||||
COLOR_ENTRY('LCL2', x38_LCL2)
|
||||
COLOR_ENTRY('LCL3', x3c_LCL3)
|
||||
RES_ENTRY('SSWH', x40_SSWH)
|
||||
RES_ENTRY('GPSM', x50_GPSM)
|
||||
RES_ENTRY('EPSM', x60_EPSM)
|
||||
BOOL_ENTRY('ZERY', x70_ZERY)
|
||||
|
||||
#undef ENTRY
|
||||
#undef INT_ENTRY
|
||||
#undef REAL_ENTRY
|
||||
#undef COLOR_ENTRY
|
||||
#undef EMITTER_ENTRY
|
||||
#undef RES_ENTRY
|
||||
#undef BOOL_ENTRY
|
|
@ -12,33 +12,36 @@ class ProjectPath;
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
template <class IDType>
|
||||
struct _ELSM {
|
||||
static constexpr ParticleType Type = ParticleType::ELSM;
|
||||
|
||||
#define INT_ENTRY(name, identifier) IntElementFactory identifier;
|
||||
#define REAL_ENTRY(name, identifier) RealElementFactory identifier;
|
||||
#define COLOR_ENTRY(name, identifier) ColorElementFactory identifier;
|
||||
#define EMITTER_ENTRY(name, identifier) EmitterElementFactory identifier;
|
||||
#define RES_ENTRY(name, identifier) ChildResourceFactory<IDType> identifier;
|
||||
#define BOOL_ENTRY(name, identifier) bool identifier = false;
|
||||
#include "ELSC.def"
|
||||
|
||||
template<typename _Func>
|
||||
void constexpr Enumerate(_Func f) {
|
||||
#define ENTRY(name, identifier) f(FOURCC(name), identifier);
|
||||
#include "ELSC.def"
|
||||
}
|
||||
|
||||
template<typename _Func>
|
||||
bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
#define ENTRY(name, identifier) case SBIG(name): f(identifier); return true;
|
||||
#include "ELSC.def"
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class IDType>
|
||||
using ELSM = PPImpl<_ELSM<IDType>>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractELSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
|
|
@ -27,11 +27,11 @@ void MAPA::Enumerate<BigDNA::Read>(typename Read::StreamT& __dna_reader) {
|
|||
/* version */
|
||||
version = __dna_reader.readUint32Big();
|
||||
if (version == 2)
|
||||
header.reset(new HeaderMP1);
|
||||
header = std::make_unique<HeaderMP1>();
|
||||
else if (version == 3)
|
||||
header.reset(new HeaderMP2);
|
||||
header = std::make_unique<HeaderMP2>();
|
||||
else if (version == 5)
|
||||
header.reset(new HeaderMP3);
|
||||
header = std::make_unique<HeaderMP3>();
|
||||
else {
|
||||
LogDNACommon.report(logvisor::Error, fmt("invalid MAPA version"));
|
||||
return;
|
||||
|
@ -41,10 +41,11 @@ void MAPA::Enumerate<BigDNA::Read>(typename Read::StreamT& __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);
|
||||
if (version != 5) {
|
||||
mo = std::make_unique<MappableObjectMP1_2>();
|
||||
} else {
|
||||
mo = std::make_unique<MappableObjectMP3>();
|
||||
}
|
||||
mo->read(__dna_reader);
|
||||
mappableObjects.push_back(std::move(mo));
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,141 @@
|
|||
#ifndef ENTRY
|
||||
#define ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef INT_ENTRY
|
||||
#define INT_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef REAL_ENTRY
|
||||
#define REAL_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef VECTOR_ENTRY
|
||||
#define VECTOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef MOD_VECTOR_ENTRY
|
||||
#define MOD_VECTOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef COLOR_ENTRY
|
||||
#define COLOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef EMITTER_ENTRY
|
||||
#define EMITTER_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef UV_ENTRY
|
||||
#define UV_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef RES_ENTRY
|
||||
#define RES_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef KSSM_ENTRY
|
||||
#define KSSM_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef BOOL_ENTRY
|
||||
#define BOOL_ENTRY(name, identifier, def) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
VECTOR_ENTRY('PSIV', x0_PSIV)
|
||||
MOD_VECTOR_ENTRY('PSVM', x4_PSVM)
|
||||
VECTOR_ENTRY('PSOV', x8_PSOV)
|
||||
INT_ENTRY('PSLT', xc_PSLT)
|
||||
INT_ENTRY('PSWT', x10_PSWT)
|
||||
REAL_ENTRY('PSTS', x14_PSTS)
|
||||
VECTOR_ENTRY('POFS', x18_POFS)
|
||||
INT_ENTRY('SEED', x1c_SEED)
|
||||
REAL_ENTRY('LENG', x20_LENG)
|
||||
REAL_ENTRY('WIDT', x24_WIDT)
|
||||
INT_ENTRY('MAXP', x28_MAXP)
|
||||
REAL_ENTRY('GRTE', x2c_GRTE)
|
||||
COLOR_ENTRY('COLR', x30_COLR)
|
||||
INT_ENTRY('LTME', x34_LTME)
|
||||
VECTOR_ENTRY('ILOC', x38_ILOC)
|
||||
VECTOR_ENTRY('IVEC', x3c_IVEC)
|
||||
EMITTER_ENTRY('EMTR', x40_EMTR)
|
||||
INT_ENTRY('MBSP', x48_MBSP)
|
||||
REAL_ENTRY('SIZE', x4c_SIZE)
|
||||
REAL_ENTRY('ROTA', x50_ROTA)
|
||||
UV_ENTRY('TEXR', x54_TEXR)
|
||||
UV_ENTRY('TIND', x58_TIND)
|
||||
RES_ENTRY('PMDL', x5c_PMDL)
|
||||
VECTOR_ENTRY('PMOP', x6c_PMOP)
|
||||
VECTOR_ENTRY('PMRT', x70_PMRT)
|
||||
VECTOR_ENTRY('PMSC', x74_PMSC)
|
||||
COLOR_ENTRY('PMCL', x78_PMCL)
|
||||
MOD_VECTOR_ENTRY('VEL1', x7c_VEL1)
|
||||
MOD_VECTOR_ENTRY('VEL2', x80_VEL2)
|
||||
MOD_VECTOR_ENTRY('VEL3', x84_VEL3)
|
||||
MOD_VECTOR_ENTRY('VEL4', x88_VEL4)
|
||||
RES_ENTRY('ICTS', x8c_ICTS)
|
||||
INT_ENTRY('NCSY', x9c_NCSY)
|
||||
INT_ENTRY('CSSD', xa0_CSSD)
|
||||
RES_ENTRY('IDTS', xa4_IDTS)
|
||||
INT_ENTRY('NDSY', xb4_NDSY)
|
||||
RES_ENTRY('IITS', xb8_IITS)
|
||||
INT_ENTRY('PISY', xc8_PISY)
|
||||
INT_ENTRY('SISY', xcc_SISY)
|
||||
KSSM_ENTRY('KSSM', xd0_KSSM)
|
||||
RES_ENTRY('SSWH', xd4_SSWH)
|
||||
INT_ENTRY('SSSD', xe4_SSSD)
|
||||
VECTOR_ENTRY('SSPO', xe8_SSPO)
|
||||
INT_ENTRY('SESD', xf8_SESD)
|
||||
VECTOR_ENTRY('SEPO', xfc_SEPO)
|
||||
RES_ENTRY('PMLC', xec_PMLC)
|
||||
INT_ENTRY('LTYP', x100_LTYP)
|
||||
COLOR_ENTRY('LCLR', x104_LCLR)
|
||||
REAL_ENTRY('LINT', x108_LINT)
|
||||
VECTOR_ENTRY('LOFF', x10c_LOFF)
|
||||
VECTOR_ENTRY('LDIR', x110_LDIR)
|
||||
INT_ENTRY('LFOT', x114_LFOT)
|
||||
REAL_ENTRY('LFOR', x118_LFOR)
|
||||
REAL_ENTRY('LSLA', x11c_LSLA)
|
||||
|
||||
/* 0-00 additions */
|
||||
RES_ENTRY('SELC', xd8_SELC)
|
||||
REAL_ENTRY('ADV1', x10c_ADV1)
|
||||
REAL_ENTRY('ADV2', x110_ADV2)
|
||||
REAL_ENTRY('ADV3', x114_ADV3)
|
||||
REAL_ENTRY('ADV4', x118_ADV4)
|
||||
REAL_ENTRY('ADV5', x11c_ADV5)
|
||||
REAL_ENTRY('ADV6', x120_ADV6)
|
||||
REAL_ENTRY('ADV7', x124_ADV7)
|
||||
REAL_ENTRY('ADV8', x128_ADV8)
|
||||
|
||||
BOOL_ENTRY('SORT', x44_28_SORT, false)
|
||||
BOOL_ENTRY('MBLR', x44_30_MBLR, false)
|
||||
BOOL_ENTRY('LINE', x44_24_LINE, false)
|
||||
BOOL_ENTRY('LIT_', x44_29_LIT_, false)
|
||||
BOOL_ENTRY('AAPH', x44_26_AAPH, false)
|
||||
BOOL_ENTRY('ZBUF', x44_27_ZBUF, false)
|
||||
BOOL_ENTRY('FXLL', x44_25_FXLL, false)
|
||||
BOOL_ENTRY('PMAB', x44_31_PMAB, false)
|
||||
BOOL_ENTRY('VMD4', x45_29_VMD4, false)
|
||||
BOOL_ENTRY('VMD3', x45_28_VMD3, false)
|
||||
BOOL_ENTRY('VMD2', x45_27_VMD2, false)
|
||||
BOOL_ENTRY('VMD1', x45_26_VMD1, false)
|
||||
BOOL_ENTRY('OPTS', x45_31_OPTS, false)
|
||||
BOOL_ENTRY('PMUS', x45_24_PMUS, false)
|
||||
BOOL_ENTRY('PMOO', x45_25_PMOO, true)
|
||||
BOOL_ENTRY('CIND', x45_30_CIND, false)
|
||||
|
||||
BOOL_ENTRY('ORNT', x30_30_ORNT, false)
|
||||
BOOL_ENTRY('RSOP', x30_31_RSOP, false)
|
||||
|
||||
#undef ENTRY
|
||||
#undef INT_ENTRY
|
||||
#undef REAL_ENTRY
|
||||
#undef VECTOR_ENTRY
|
||||
#undef MOD_VECTOR_ENTRY
|
||||
#undef COLOR_ENTRY
|
||||
#undef EMITTER_ENTRY
|
||||
#undef UV_ENTRY
|
||||
#undef RES_ENTRY
|
||||
#undef KSSM_ENTRY
|
||||
#undef BOOL_ENTRY
|
|
@ -17,107 +17,39 @@ class ProjectPath;
|
|||
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;
|
||||
};
|
||||
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;
|
||||
struct _GPSM {
|
||||
static constexpr ParticleType Type = ParticleType::GPSM;
|
||||
|
||||
/* 0-00 additions */
|
||||
ChildResourceFactory<IDType> xd8_SELC;
|
||||
union {
|
||||
struct {
|
||||
bool x30_30_ORNT : 1;
|
||||
bool x30_31_RSOP : 1;
|
||||
};
|
||||
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;
|
||||
#define INT_ENTRY(name, identifier) IntElementFactory identifier;
|
||||
#define REAL_ENTRY(name, identifier) RealElementFactory identifier;
|
||||
#define VECTOR_ENTRY(name, identifier) VectorElementFactory identifier;
|
||||
#define MOD_VECTOR_ENTRY(name, identifier) ModVectorElementFactory identifier;
|
||||
#define COLOR_ENTRY(name, identifier) ColorElementFactory identifier;
|
||||
#define EMITTER_ENTRY(name, identifier) EmitterElementFactory identifier;
|
||||
#define UV_ENTRY(name, identifier) UVElementFactory<IDType> identifier;
|
||||
#define RES_ENTRY(name, identifier) ChildResourceFactory<IDType> identifier;
|
||||
#define KSSM_ENTRY(name, identifier) SpawnSystemKeyframeData<IDType> identifier;
|
||||
#define BOOL_ENTRY(name, identifier, def) bool identifier = def;
|
||||
#include "PART.def"
|
||||
|
||||
GPSM() { x45_25_PMOO = true; }
|
||||
template<typename _Func>
|
||||
void constexpr Enumerate(_Func f) {
|
||||
#define ENTRY(name, identifier) f(FOURCC(name), identifier);
|
||||
#define BOOL_ENTRY(name, identifier, def) f(FOURCC(name), identifier, def);
|
||||
#include "PART.def"
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
template<typename _Func>
|
||||
bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
#define ENTRY(name, identifier) case SBIG(name): f(identifier); return true;
|
||||
#include "PART.def"
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class IDType>
|
||||
using GPSM = PPImpl<_GPSM<IDType>>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractGPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,6 +10,257 @@
|
|||
namespace DataSpec::DNAParticle {
|
||||
extern logvisor::Module LogModule;
|
||||
|
||||
enum class ParticleType {
|
||||
GPSM = SBIG('GPSM'),
|
||||
SWSH = SBIG('SWSH'),
|
||||
ELSM = SBIG('ELSM'),
|
||||
DPSM = SBIG('DPSM'),
|
||||
CRSM = SBIG('CRSM'),
|
||||
WPSM = SBIG('WPSM')
|
||||
};
|
||||
|
||||
/*
|
||||
* The particle property (PP) metaclass system provides common compile-time utilities
|
||||
* for storing, enumerating, and streaming particle scripts.
|
||||
*/
|
||||
|
||||
template <class _Basis>
|
||||
struct PPImpl : BigDNA, _Basis {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
|
||||
template<typename T>
|
||||
static constexpr bool _shouldStore(T& p, bool defaultBool) {
|
||||
if constexpr (std::is_same_v<T, bool>) {
|
||||
return p != defaultBool;
|
||||
} else if constexpr (std::is_same_v<T, uint32_t>) {
|
||||
return p != 0xffffffff;
|
||||
} else if constexpr (std::is_same_v<T, float>) {
|
||||
return true;
|
||||
} else {
|
||||
return p.operator bool();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void _read(athena::io::IStreamReader& r) {
|
||||
constexpr FourCC RefType = uint32_t(_Basis::Type);
|
||||
DNAFourCC clsId(r);
|
||||
if (clsId != RefType) {
|
||||
LogModule.report(logvisor::Warning, fmt("non {} provided to {} parser"), RefType, RefType);
|
||||
return;
|
||||
}
|
||||
clsId.read(r);
|
||||
while (clsId != SBIG('_END')) {
|
||||
if (!_Basis::Lookup(clsId, [&](auto& p) {
|
||||
using Tp = std::decay_t<decltype(p)>;
|
||||
if constexpr (std::is_same_v<Tp, bool>) {
|
||||
DNAFourCC tp(r);
|
||||
if (tp == SBIG('CNST'))
|
||||
p = r.readBool();
|
||||
} else if constexpr (std::is_same_v<Tp, uint32_t>) {
|
||||
DNAFourCC tp(r);
|
||||
if (tp == SBIG('CNST'))
|
||||
p = r.readUint32Big();
|
||||
} else if constexpr (std::is_same_v<Tp, float>) {
|
||||
DNAFourCC tp(r);
|
||||
if (tp == SBIG('CNST'))
|
||||
p = r.readFloatBig();
|
||||
} else {
|
||||
p.read(r);
|
||||
}
|
||||
})) {
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown {} class {} @{}"), RefType, clsId, r.position());
|
||||
}
|
||||
clsId.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void _write(athena::io::IStreamWriter& w) {
|
||||
constexpr DNAFourCC RefType = uint32_t(_Basis::Type);
|
||||
RefType.write(w);
|
||||
_Basis::Enumerate([&](FourCC fcc, auto& p, bool defaultBool = false) {
|
||||
if (_shouldStore(p, defaultBool)) {
|
||||
using Tp = std::decay_t<decltype(p)>;
|
||||
DNAFourCC(fcc).write(w);
|
||||
if constexpr (std::is_same_v<Tp, bool>) {
|
||||
w.writeBytes("CNST", 4);
|
||||
w.writeBool(p);
|
||||
} else if constexpr (std::is_same_v<Tp, uint32_t>) {
|
||||
w.writeBytes("CNST", 4);
|
||||
w.writeUint32Big(p);
|
||||
} else if constexpr (std::is_same_v<Tp, float>) {
|
||||
w.writeBytes("CNST", 4);
|
||||
w.writeFloatBig(p);
|
||||
} else {
|
||||
p.write(w);
|
||||
}
|
||||
}
|
||||
});
|
||||
w.writeBytes("_END", 4);
|
||||
}
|
||||
|
||||
constexpr void _binarySize(std::size_t& s) {
|
||||
constexpr DNAFourCC RefType = uint32_t(_Basis::Type);
|
||||
RefType.binarySize(s);
|
||||
_Basis::Enumerate([&](FourCC fcc, auto& p, bool defaultBool = false) {
|
||||
if (_shouldStore(p, defaultBool)) {
|
||||
using Tp = std::decay_t<decltype(p)>;
|
||||
DNAFourCC(fcc).binarySize(s);
|
||||
if constexpr (std::is_same_v<Tp, bool>) {
|
||||
s += 5;
|
||||
} else if constexpr (std::is_same_v<Tp, uint32_t> || std::is_same_v<Tp, float>) {
|
||||
s += 8;
|
||||
} else {
|
||||
p.binarySize(s);
|
||||
}
|
||||
}
|
||||
});
|
||||
s += 4;
|
||||
}
|
||||
|
||||
void _read(athena::io::YAMLDocReader& r) {
|
||||
constexpr DNAFourCC RefType = uint32_t(_Basis::Type);
|
||||
|
||||
for (const auto& [key, value] : r.getCurNode()->m_mapChildren) {
|
||||
if (key == "DNAType"sv)
|
||||
continue;
|
||||
if (key.size() < 4) {
|
||||
LogModule.report(logvisor::Warning, fmt("short FourCC in element '{}'"), key);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto rec = r.enterSubRecord(key)) {
|
||||
const DNAFourCC clsId = key.c_str();
|
||||
if (!_Basis::Lookup(clsId, [&](auto& p) {
|
||||
using Tp = std::decay_t<decltype(p)>;
|
||||
if constexpr (std::is_same_v<Tp, bool>) {
|
||||
p = r.readBool();
|
||||
} else if constexpr (std::is_same_v<Tp, uint32_t>) {
|
||||
p = r.readUint32();
|
||||
} else if constexpr (std::is_same_v<Tp, float>) {
|
||||
p = r.readFloat();
|
||||
} else {
|
||||
p.read(r);
|
||||
}
|
||||
})) {
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown {} class {}"), RefType, clsId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void _write(athena::io::YAMLDocWriter& w) {
|
||||
_Basis::Enumerate([&](FourCC fcc, auto& p, bool defaultBool = false) {
|
||||
if (_shouldStore(p, defaultBool)) {
|
||||
using Tp = std::decay_t<decltype(p)>;
|
||||
if (auto rec = w.enterSubRecord(fcc.toStringView())) {
|
||||
if constexpr (std::is_same_v<Tp, bool>) {
|
||||
w.writeBool(p);
|
||||
} else if constexpr (std::is_same_v<Tp, uint32_t>) {
|
||||
w.writeUint32(p);
|
||||
} else if constexpr (std::is_same_v<Tp, float>) {
|
||||
w.writeFloat(p);
|
||||
} else {
|
||||
p.write(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& deps) {
|
||||
_Basis::Enumerate([&](FourCC fcc, auto& p, bool defaultBool = false) {
|
||||
using Tp = std::decay_t<decltype(p)>;
|
||||
if constexpr (!std::is_same_v<Tp, bool> && !std::is_same_v<Tp, uint32_t> && !std::is_same_v<Tp, float>)
|
||||
p.gatherDependencies(deps);
|
||||
});
|
||||
}
|
||||
|
||||
constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& deps) const {
|
||||
const_cast<PPImpl&>(*this).gatherDependencies(deps);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename _Type>
|
||||
struct PEType {
|
||||
using Type = _Type;
|
||||
};
|
||||
|
||||
template <class _Basis>
|
||||
struct PEImpl : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
using _PtrType = typename _Basis::PtrType;
|
||||
|
||||
void _read(athena::io::IStreamReader& r) {
|
||||
DNAFourCC clsId(r);
|
||||
if (clsId == FOURCC('NONE')) {
|
||||
m_elem.reset();
|
||||
return;
|
||||
}
|
||||
if (!_Basis::Lookup(clsId, [&](auto&& p) {
|
||||
using Tp = std::decay_t<decltype(p)>;
|
||||
m_elem = std::make_unique<typename Tp::Type>();
|
||||
m_elem->read(r);
|
||||
})) {
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown {} class {} @{}"), _PtrType::TypeName, clsId, r.position());
|
||||
}
|
||||
}
|
||||
|
||||
void _write(athena::io::IStreamWriter& w) {
|
||||
if (m_elem) {
|
||||
w.writeBytes(m_elem->ClassID().data(), 4);
|
||||
m_elem->write(w);
|
||||
} else {
|
||||
w.writeBytes("NONE", 4);
|
||||
}
|
||||
}
|
||||
|
||||
void _binarySize(std::size_t& s) {
|
||||
if (m_elem)
|
||||
m_elem->binarySize(s);
|
||||
s += 4;
|
||||
}
|
||||
|
||||
void _read(athena::io::YAMLDocReader& r) {
|
||||
const auto& mapChildren = r.getCurNode()->m_mapChildren;
|
||||
if (mapChildren.empty()) {
|
||||
m_elem.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& [key, value] = mapChildren[0];
|
||||
if (key.size() < 4)
|
||||
LogModule.report(logvisor::Fatal, fmt("short FourCC in element '{}'"), key);
|
||||
|
||||
if (auto rec = r.enterSubRecord(key)) {
|
||||
const DNAFourCC clsId = key.c_str();
|
||||
if (!_Basis::Lookup(clsId, [&](auto&& p) {
|
||||
using Tp = std::decay_t<decltype(p)>;
|
||||
m_elem = std::make_unique<typename Tp::Type>();
|
||||
m_elem->read(r);
|
||||
})) {
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown {} class {}"), _PtrType::TypeName, clsId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _write(athena::io::YAMLDocWriter& w) {
|
||||
if (m_elem)
|
||||
if (auto rec = w.enterSubRecord(m_elem->ClassID()))
|
||||
m_elem->write(w);
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& deps) const {
|
||||
_Basis::gatherDependencies(deps, m_elem);
|
||||
}
|
||||
|
||||
operator bool() const { return m_elem.operator bool(); }
|
||||
auto* get() const { return m_elem.get(); }
|
||||
auto* operator->() const { return get(); }
|
||||
void reset() { m_elem.reset(); }
|
||||
private:
|
||||
std::unique_ptr<_PtrType> m_elem;
|
||||
};
|
||||
|
||||
struct IElement : BigDNAVYaml {
|
||||
Delete _d;
|
||||
~IElement() override = default;
|
||||
|
@ -19,61 +270,296 @@ struct IElement : BigDNAVYaml {
|
|||
|
||||
struct IRealElement : IElement {
|
||||
Delete _d2;
|
||||
static constexpr std::string_view TypeName = "RealElement"sv;
|
||||
};
|
||||
struct RealElementFactory : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
std::unique_ptr<IRealElement> m_elem;
|
||||
operator bool() const { return m_elem.operator bool(); }
|
||||
struct RELifetimeTween;
|
||||
struct REConstant;
|
||||
struct RETimeChain;
|
||||
struct REAdd;
|
||||
struct REClamp;
|
||||
struct REKeyframeEmitter;
|
||||
struct REKeyframeEmitter;
|
||||
struct REInitialRandom;
|
||||
struct RERandom;
|
||||
struct REMultiply;
|
||||
struct REPulse;
|
||||
struct RETimeScale;
|
||||
struct RELifetimePercent;
|
||||
struct RESineWave;
|
||||
struct REInitialSwitch;
|
||||
struct RECompareLessThan;
|
||||
struct RECompareEquals;
|
||||
struct REParticleAdvanceParam1;
|
||||
struct REParticleAdvanceParam2;
|
||||
struct REParticleAdvanceParam3;
|
||||
struct REParticleAdvanceParam4;
|
||||
struct REParticleAdvanceParam5;
|
||||
struct REParticleAdvanceParam6;
|
||||
struct REParticleAdvanceParam7;
|
||||
struct REParticleAdvanceParam8;
|
||||
struct REParticleSizeOrLineLength;
|
||||
struct REParticleRotationOrLineWidth;
|
||||
struct RESubtract;
|
||||
struct REVectorMagnitude;
|
||||
struct REVectorXToReal;
|
||||
struct REVectorYToReal;
|
||||
struct REVectorZToReal;
|
||||
struct RECEXT;
|
||||
struct REIntTimesReal;
|
||||
struct _RealElementFactory {
|
||||
using PtrType = IRealElement;
|
||||
template<typename _Func>
|
||||
static bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
case SBIG('LFTW'): f(PEType<RELifetimeTween>{}); return true;
|
||||
case SBIG('CNST'): f(PEType<REConstant>{}); return true;
|
||||
case SBIG('CHAN'): f(PEType<RETimeChain>{}); return true;
|
||||
case SBIG('ADD_'): f(PEType<REAdd>{}); return true;
|
||||
case SBIG('CLMP'): f(PEType<REClamp>{}); return true;
|
||||
case SBIG('KEYE'): f(PEType<REKeyframeEmitter>{}); return true;
|
||||
case SBIG('KEYP'): f(PEType<REKeyframeEmitter>{}); return true;
|
||||
case SBIG('IRND'): f(PEType<REInitialRandom>{}); return true;
|
||||
case SBIG('RAND'): f(PEType<RERandom>{}); return true;
|
||||
case SBIG('MULT'): f(PEType<REMultiply>{}); return true;
|
||||
case SBIG('PULS'): f(PEType<REPulse>{}); return true;
|
||||
case SBIG('SCAL'): f(PEType<RETimeScale>{}); return true;
|
||||
case SBIG('RLPT'): f(PEType<RELifetimePercent>{}); return true;
|
||||
case SBIG('SINE'): f(PEType<RESineWave>{}); return true;
|
||||
case SBIG('ISWT'): f(PEType<REInitialSwitch>{}); return true;
|
||||
case SBIG('CLTN'): f(PEType<RECompareLessThan>{}); return true;
|
||||
case SBIG('CEQL'): f(PEType<RECompareEquals>{}); return true;
|
||||
case SBIG('PAP1'): f(PEType<REParticleAdvanceParam1>{}); return true;
|
||||
case SBIG('PAP2'): f(PEType<REParticleAdvanceParam2>{}); return true;
|
||||
case SBIG('PAP3'): f(PEType<REParticleAdvanceParam3>{}); return true;
|
||||
case SBIG('PAP4'): f(PEType<REParticleAdvanceParam4>{}); return true;
|
||||
case SBIG('PAP5'): f(PEType<REParticleAdvanceParam5>{}); return true;
|
||||
case SBIG('PAP6'): f(PEType<REParticleAdvanceParam6>{}); return true;
|
||||
case SBIG('PAP7'): f(PEType<REParticleAdvanceParam7>{}); return true;
|
||||
case SBIG('PAP8'): f(PEType<REParticleAdvanceParam8>{}); return true;
|
||||
case SBIG('PSLL'): f(PEType<REParticleSizeOrLineLength>{}); return true;
|
||||
case SBIG('PRLW'): f(PEType<REParticleRotationOrLineWidth>{}); return true;
|
||||
case SBIG('SUB_'): f(PEType<RESubtract>{}); return true;
|
||||
case SBIG('VMAG'): f(PEType<REVectorMagnitude>{}); return true;
|
||||
case SBIG('VXTR'): f(PEType<REVectorXToReal>{}); return true;
|
||||
case SBIG('VYTR'): f(PEType<REVectorYToReal>{}); return true;
|
||||
case SBIG('VZTR'): f(PEType<REVectorZToReal>{}); return true;
|
||||
case SBIG('CEXT'): f(PEType<RECEXT>{}); return true;
|
||||
case SBIG('ITRL'): f(PEType<REIntTimesReal>{}); return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
static constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut,
|
||||
const std::unique_ptr<IRealElement>& elemPtr) {}
|
||||
};
|
||||
using RealElementFactory = PEImpl<_RealElementFactory>;
|
||||
|
||||
struct IIntElement : IElement {
|
||||
Delete _d2;
|
||||
static constexpr std::string_view TypeName = "IntElement"sv;
|
||||
};
|
||||
struct IntElementFactory : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
std::unique_ptr<IIntElement> m_elem;
|
||||
operator bool() const { return m_elem.operator bool(); }
|
||||
struct IEKeyframeEmitter;
|
||||
struct IEKeyframeEmitter;
|
||||
struct IEDeath;
|
||||
struct IEClamp;
|
||||
struct IETimeChain;
|
||||
struct IEAdd;
|
||||
struct IEConstant;
|
||||
struct IEImpulse;
|
||||
struct IELifetimePercent;
|
||||
struct IEInitialRandom;
|
||||
struct IEPulse;
|
||||
struct IEMultiply;
|
||||
struct IESampleAndHold;
|
||||
struct IERandom;
|
||||
struct IETimeScale;
|
||||
struct IEGTCP;
|
||||
struct IEModulo;
|
||||
struct IESubtract;
|
||||
struct _IntElementFactory {
|
||||
using PtrType = IIntElement;
|
||||
template<typename _Func>
|
||||
static bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
case SBIG('KEYE'): f(PEType<IEKeyframeEmitter>{}); return true;
|
||||
case SBIG('KEYP'): f(PEType<IEKeyframeEmitter>{}); return true;
|
||||
case SBIG('DETH'): f(PEType<IEDeath>{}); return true;
|
||||
case SBIG('CLMP'): f(PEType<IEClamp>{}); return true;
|
||||
case SBIG('CHAN'): f(PEType<IETimeChain>{}); return true;
|
||||
case SBIG('ADD_'): f(PEType<IEAdd>{}); return true;
|
||||
case SBIG('CNST'): f(PEType<IEConstant>{}); return true;
|
||||
case SBIG('IMPL'): f(PEType<IEImpulse>{}); return true;
|
||||
case SBIG('ILPT'): f(PEType<IELifetimePercent>{}); return true;
|
||||
case SBIG('IRND'): f(PEType<IEInitialRandom>{}); return true;
|
||||
case SBIG('PULS'): f(PEType<IEPulse>{}); return true;
|
||||
case SBIG('MULT'): f(PEType<IEMultiply>{}); return true;
|
||||
case SBIG('SPAH'): f(PEType<IESampleAndHold>{}); return true;
|
||||
case SBIG('RAND'): f(PEType<IERandom>{}); return true;
|
||||
case SBIG('TSCL'): f(PEType<IETimeScale>{}); return true;
|
||||
case SBIG('GTCP'): f(PEType<IEGTCP>{}); return true;
|
||||
case SBIG('MODU'): f(PEType<IEModulo>{}); return true;
|
||||
case SBIG('SUB_'): f(PEType<IESubtract>{}); return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
static constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut,
|
||||
const std::unique_ptr<IIntElement>& elemPtr) {}
|
||||
};
|
||||
using IntElementFactory = PEImpl<_IntElementFactory>;
|
||||
|
||||
struct IVectorElement : IElement {
|
||||
Delete _d2;
|
||||
static constexpr std::string_view TypeName = "VectorElement"sv;
|
||||
};
|
||||
struct VectorElementFactory : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
std::unique_ptr<IVectorElement> m_elem;
|
||||
operator bool() const { return m_elem.operator bool(); }
|
||||
struct VECone;
|
||||
struct VETimeChain;
|
||||
struct VEAngleCone;
|
||||
struct VEAdd;
|
||||
struct VECircleCluster;
|
||||
struct VEConstant;
|
||||
struct VECircle;
|
||||
struct VEKeyframeEmitter;
|
||||
struct VEKeyframeEmitter;
|
||||
struct VEMultiply;
|
||||
struct VERealToVector;
|
||||
struct VEPulse;
|
||||
struct VEParticleVelocity;
|
||||
struct VESPOS;
|
||||
struct VEPLCO;
|
||||
struct VEPLOC;
|
||||
struct VEPSOR;
|
||||
struct VEPSOF;
|
||||
struct _VectorElementFactory {
|
||||
using PtrType = IVectorElement;
|
||||
template<typename _Func>
|
||||
static bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
case SBIG('CONE'): f(PEType<VECone>{}); return true;
|
||||
case SBIG('CHAN'): f(PEType<VETimeChain>{}); return true;
|
||||
case SBIG('ANGC'): f(PEType<VEAngleCone>{}); return true;
|
||||
case SBIG('ADD_'): f(PEType<VEAdd>{}); return true;
|
||||
case SBIG('CCLU'): f(PEType<VECircleCluster>{}); return true;
|
||||
case SBIG('CNST'): f(PEType<VEConstant>{}); return true;
|
||||
case SBIG('CIRC'): f(PEType<VECircle>{}); return true;
|
||||
case SBIG('KEYE'): f(PEType<VEKeyframeEmitter>{}); return true;
|
||||
case SBIG('KEYP'): f(PEType<VEKeyframeEmitter>{}); return true;
|
||||
case SBIG('MULT'): f(PEType<VEMultiply>{}); return true;
|
||||
case SBIG('RTOV'): f(PEType<VERealToVector>{}); return true;
|
||||
case SBIG('PULS'): f(PEType<VEPulse>{}); return true;
|
||||
case SBIG('PVEL'): f(PEType<VEParticleVelocity>{}); return true;
|
||||
case SBIG('SPOS'): f(PEType<VESPOS>{}); return true;
|
||||
case SBIG('PLCO'): f(PEType<VEPLCO>{}); return true;
|
||||
case SBIG('PLOC'): f(PEType<VEPLOC>{}); return true;
|
||||
case SBIG('PSOR'): f(PEType<VEPSOR>{}); return true;
|
||||
case SBIG('PSOF'): f(PEType<VEPSOF>{}); return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
static constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut,
|
||||
const std::unique_ptr<IVectorElement>& elemPtr) {}
|
||||
};
|
||||
using VectorElementFactory = PEImpl<_VectorElementFactory>;
|
||||
|
||||
struct IColorElement : IElement {
|
||||
Delete _d2;
|
||||
static constexpr std::string_view TypeName = "ColorElement"sv;
|
||||
};
|
||||
struct ColorElementFactory : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
std::unique_ptr<IColorElement> m_elem;
|
||||
operator bool() const { return m_elem.operator bool(); }
|
||||
struct CEKeyframeEmitter;
|
||||
struct CEKeyframeEmitter;
|
||||
struct CEConstant;
|
||||
struct CETimeChain;
|
||||
struct CEFadeEnd;
|
||||
struct CEFade;
|
||||
struct CEPulse;
|
||||
struct _ColorElementFactory {
|
||||
using PtrType = IColorElement;
|
||||
template<typename _Func>
|
||||
static bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
case SBIG('KEYE'): f(PEType<CEKeyframeEmitter>{}); return true;
|
||||
case SBIG('KEYP'): f(PEType<CEKeyframeEmitter>{}); return true;
|
||||
case SBIG('CNST'): f(PEType<CEConstant>{}); return true;
|
||||
case SBIG('CHAN'): f(PEType<CETimeChain>{}); return true;
|
||||
case SBIG('CFDE'): f(PEType<CEFadeEnd>{}); return true;
|
||||
case SBIG('FADE'): f(PEType<CEFade>{}); return true;
|
||||
case SBIG('PULS'): f(PEType<CEPulse>{}); return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
static constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut,
|
||||
const std::unique_ptr<IColorElement>& elemPtr) {}
|
||||
};
|
||||
using ColorElementFactory = PEImpl<_ColorElementFactory>;
|
||||
|
||||
struct IModVectorElement : IElement {
|
||||
Delete _d2;
|
||||
static constexpr std::string_view TypeName = "ModVectorElement"sv;
|
||||
};
|
||||
struct ModVectorElementFactory : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
std::unique_ptr<IModVectorElement> m_elem;
|
||||
operator bool() const { return m_elem.operator bool(); }
|
||||
struct MVEImplosion;
|
||||
struct MVEExponentialImplosion;
|
||||
struct MVETimeChain;
|
||||
struct MVEBounce;
|
||||
struct MVEConstant;
|
||||
struct MVEGravity;
|
||||
struct MVEExplode;
|
||||
struct MVESetPosition;
|
||||
struct MVELinearImplosion;
|
||||
struct MVEPulse;
|
||||
struct MVEWind;
|
||||
struct MVESwirl;
|
||||
struct _ModVectorElementFactory {
|
||||
using PtrType = IModVectorElement;
|
||||
template<typename _Func>
|
||||
static bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
case SBIG('IMPL'): f(PEType<MVEImplosion>{}); return true;
|
||||
case SBIG('EMPL'): f(PEType<MVEExponentialImplosion>{}); return true;
|
||||
case SBIG('CHAN'): f(PEType<MVETimeChain>{}); return true;
|
||||
case SBIG('BNCE'): f(PEType<MVEBounce>{}); return true;
|
||||
case SBIG('CNST'): f(PEType<MVEConstant>{}); return true;
|
||||
case SBIG('GRAV'): f(PEType<MVEGravity>{}); return true;
|
||||
case SBIG('EXPL'): f(PEType<MVEExplode>{}); return true;
|
||||
case SBIG('SPOS'): f(PEType<MVESetPosition>{}); return true;
|
||||
case SBIG('LMPL'): f(PEType<MVELinearImplosion>{}); return true;
|
||||
case SBIG('PULS'): f(PEType<MVEPulse>{}); return true;
|
||||
case SBIG('WIND'): f(PEType<MVEWind>{}); return true;
|
||||
case SBIG('SWRL'): f(PEType<MVESwirl>{}); return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
static constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut,
|
||||
const std::unique_ptr<IModVectorElement>& elemPtr) {}
|
||||
};
|
||||
using ModVectorElementFactory = PEImpl<_ModVectorElementFactory>;
|
||||
|
||||
struct IEmitterElement : IElement {
|
||||
Delete _d2;
|
||||
static constexpr std::string_view TypeName = "EmitterElement"sv;
|
||||
};
|
||||
struct EmitterElementFactory : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
std::unique_ptr<IEmitterElement> m_elem;
|
||||
operator bool() const { return m_elem.operator bool(); }
|
||||
struct EESimpleEmitterTR;
|
||||
struct EESimpleEmitter;
|
||||
struct VESphere;
|
||||
struct VEAngleSphere;
|
||||
struct _EmitterElementFactory {
|
||||
using PtrType = IEmitterElement;
|
||||
template<typename _Func>
|
||||
static bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
case SBIG('SETR'): f(PEType<EESimpleEmitterTR>{}); return true;
|
||||
case SBIG('SEMR'): f(PEType<EESimpleEmitter>{}); return true;
|
||||
case SBIG('SPHE'): f(PEType<VESphere>{}); return true;
|
||||
case SBIG('ASPH'): f(PEType<VEAngleSphere>{}); return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
static constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut,
|
||||
const std::unique_ptr<IEmitterElement>& elemPtr) {}
|
||||
};
|
||||
using EmitterElementFactory = PEImpl<_EmitterElementFactory>;
|
||||
|
||||
struct IUVElement : IElement {
|
||||
Delete _d2;
|
||||
virtual void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const = 0;
|
||||
static constexpr std::string_view TypeName = "UVElement"sv;
|
||||
};
|
||||
|
||||
struct BoolHelper : IElement {
|
||||
|
@ -87,6 +573,46 @@ struct BoolHelper : IElement {
|
|||
std::string_view ClassID() const override { return "BoolHelper"sv; }
|
||||
};
|
||||
|
||||
template <typename Tp>
|
||||
struct ValueHelper : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
|
||||
void _read(athena::io::IStreamReader& r) {
|
||||
hecl::DNAFourCC ValueType;
|
||||
ValueType.read(r);
|
||||
if (ValueType == FOURCC('CNST'))
|
||||
athena::io::Read<athena::io::PropType::None>::Do<Tp, athena::Endian::Big>({}, value.emplace(), r);
|
||||
else
|
||||
value = std::nullopt;
|
||||
}
|
||||
void _write(athena::io::IStreamWriter& w) {
|
||||
if (value) {
|
||||
w.writeBytes("CNST", 4);
|
||||
athena::io::Write<athena::io::PropType::None>::Do<Tp, athena::Endian::Big>({}, *value, w);
|
||||
} else {
|
||||
w.writeBytes("NONE", 4);
|
||||
}
|
||||
}
|
||||
void _binarySize(std::size_t& s) {
|
||||
s += 4;
|
||||
if (value)
|
||||
athena::io::BinarySize<athena::io::PropType::None>::Do<Tp, athena::Endian::Big>({}, *value, s);
|
||||
}
|
||||
void _read(athena::io::YAMLDocReader& r) {
|
||||
athena::io::ReadYaml<athena::io::PropType::None>::Do<Tp, athena::Endian::Big>({}, value.emplace(), r);
|
||||
}
|
||||
void _write(athena::io::YAMLDocWriter& w) {
|
||||
athena::io::WriteYaml<athena::io::PropType::None>::Do<Tp, athena::Endian::Big>({}, *value, w);
|
||||
}
|
||||
|
||||
static constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) {}
|
||||
|
||||
std::optional<Tp> value = {};
|
||||
void emplace(Tp val) { value.emplace(val); }
|
||||
Tp operator*() const { return *value; }
|
||||
operator bool() const { return value.operator bool(); }
|
||||
};
|
||||
|
||||
struct RELifetimeTween : IRealElement {
|
||||
AT_DECL_DNA_YAMLV_NO_TYPE
|
||||
RealElementFactory a;
|
||||
|
@ -743,7 +1269,8 @@ struct UVEConstant : IUVElement {
|
|||
std::string_view ClassID() const override { return "CNST"sv; }
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const override {
|
||||
g_curSpec->flattenDependencies(tex, pathsOut);
|
||||
if (tex.isValid())
|
||||
g_curSpec->flattenDependencies(tex, pathsOut);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -761,18 +1288,30 @@ struct UVEAnimTexture : IUVElement {
|
|||
std::string_view ClassID() const override { return "ATEX"sv; }
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const override {
|
||||
g_curSpec->flattenDependencies(tex, pathsOut);
|
||||
if (tex.isValid())
|
||||
g_curSpec->flattenDependencies(tex, pathsOut);
|
||||
}
|
||||
};
|
||||
|
||||
template <class IDType>
|
||||
struct UVElementFactory : BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
DNAFourCC m_type;
|
||||
std::unique_ptr<IUVElement> m_elem;
|
||||
operator bool() const { return m_elem.operator bool(); }
|
||||
struct _UVElementFactory {
|
||||
using PtrType = IUVElement;
|
||||
template<typename _Func>
|
||||
static bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
case SBIG('CNST'): f(PEType<UVEConstant<IDType>>{}); return true;
|
||||
case SBIG('ATEX'): f(PEType<UVEAnimTexture<IDType>>{}); return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
static constexpr void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut,
|
||||
const std::unique_ptr<IUVElement>& elemPtr) {
|
||||
if (elemPtr)
|
||||
elemPtr->gatherDependencies(pathsOut);
|
||||
}
|
||||
};
|
||||
template <class IDType>
|
||||
using UVElementFactory = PEImpl<_UVElementFactory<IDType>>;
|
||||
|
||||
template <class IDType>
|
||||
struct SpawnSystemKeyframeData : BigDNA {
|
||||
|
@ -809,6 +1348,10 @@ struct ChildResourceFactory : BigDNA {
|
|||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
operator bool() const { return id.isValid(); }
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
||||
if (id.isValid())
|
||||
g_curSpec->flattenDependencies(id, pathsOut);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace DataSpec::DNAParticle
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#include "DataSpec/DNACommon/SWHC.hpp"
|
||||
|
||||
#include "DataSpec/DNACommon/PAK.hpp"
|
||||
|
||||
#include <logvisor/logvisor.hpp>
|
||||
|
||||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template struct PPImpl<_SWSH<UniqueID32>>;
|
||||
template struct PPImpl<_SWSH<UniqueID64>>;
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_SWSH<UniqueID32>>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_SWSH<UniqueID64>>)
|
||||
|
||||
template <>
|
||||
std::string_view SWSH<UniqueID32>::DNAType() {
|
||||
return "SWSH<UniqueID32>"sv;
|
||||
|
@ -16,504 +19,6 @@ std::string_view SWSH<UniqueID64>::DNAType() {
|
|||
return "SWSH<UniqueID64>"sv;
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void SWSH<IDType>::_read(typename BigDNA::ReadYaml::StreamT& r) {
|
||||
for (const auto& elem : r.getCurNode()->m_mapChildren) {
|
||||
if (elem.first.size() < 4) {
|
||||
LogModule.report(logvisor::Warning, fmt("short FourCC in element '{}'"), elem.first);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto rec = r.enterSubRecord(elem.first.c_str())) {
|
||||
switch (*reinterpret_cast<const uint32_t*>(elem.first.data())) {
|
||||
case SBIG('PSLT'):
|
||||
x0_PSLT.read(r);
|
||||
break;
|
||||
case SBIG('TIME'):
|
||||
x4_TIME.read(r);
|
||||
break;
|
||||
case SBIG('LRAD'):
|
||||
x8_LRAD.read(r);
|
||||
break;
|
||||
case SBIG('RRAD'):
|
||||
xc_RRAD.read(r);
|
||||
break;
|
||||
case SBIG('LENG'):
|
||||
x10_LENG.read(r);
|
||||
break;
|
||||
case SBIG('COLR'):
|
||||
x14_COLR.read(r);
|
||||
break;
|
||||
case SBIG('SIDE'):
|
||||
x18_SIDE.read(r);
|
||||
break;
|
||||
case SBIG('IROT'):
|
||||
x1c_IROT.read(r);
|
||||
break;
|
||||
case SBIG('ROTM'):
|
||||
x20_ROTM.read(r);
|
||||
break;
|
||||
case SBIG('POFS'):
|
||||
x24_POFS.read(r);
|
||||
break;
|
||||
case SBIG('IVEL'):
|
||||
x28_IVEL.read(r);
|
||||
break;
|
||||
case SBIG('NPOS'):
|
||||
x2c_NPOS.read(r);
|
||||
break;
|
||||
case SBIG('VELM'):
|
||||
x30_VELM.read(r);
|
||||
break;
|
||||
case SBIG('VLM2'):
|
||||
x34_VLM2.read(r);
|
||||
break;
|
||||
case SBIG('SPLN'):
|
||||
x38_SPLN.read(r);
|
||||
break;
|
||||
case SBIG('TEXR'):
|
||||
x3c_TEXR.read(r);
|
||||
break;
|
||||
case SBIG('TSPN'):
|
||||
x40_TSPN.read(r);
|
||||
break;
|
||||
case SBIG('LLRD'):
|
||||
x44_24_LLRD = r.readBool();
|
||||
break;
|
||||
case SBIG('CROS'):
|
||||
x44_25_CROS = r.readBool();
|
||||
break;
|
||||
case SBIG('VLS1'):
|
||||
x44_26_VLS1 = r.readBool();
|
||||
break;
|
||||
case SBIG('VLS2'):
|
||||
x44_27_VLS2 = r.readBool();
|
||||
break;
|
||||
case SBIG('SROT'):
|
||||
x44_28_SROT = r.readBool();
|
||||
break;
|
||||
case SBIG('WIRE'):
|
||||
x44_29_WIRE = r.readBool();
|
||||
break;
|
||||
case SBIG('TEXW'):
|
||||
x44_30_TEXW = r.readBool();
|
||||
break;
|
||||
case SBIG('AALP'):
|
||||
x44_31_AALP = r.readBool();
|
||||
break;
|
||||
case SBIG('ZBUF'):
|
||||
x45_24_ZBUF = r.readBool();
|
||||
break;
|
||||
case SBIG('ORNT'):
|
||||
x45_25_ORNT = r.readBool();
|
||||
break;
|
||||
case SBIG('CRND'):
|
||||
x45_26_CRND = r.readBool();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void SWSH<IDType>::_write(typename BigDNA::WriteYaml::StreamT& w) const {
|
||||
if (x0_PSLT)
|
||||
if (auto rec = w.enterSubRecord("PSLT"))
|
||||
x0_PSLT.write(w);
|
||||
if (x4_TIME)
|
||||
if (auto rec = w.enterSubRecord("TIME"))
|
||||
x4_TIME.write(w);
|
||||
if (x8_LRAD)
|
||||
if (auto rec = w.enterSubRecord("LRAD"))
|
||||
x8_LRAD.write(w);
|
||||
if (xc_RRAD)
|
||||
if (auto rec = w.enterSubRecord("RRAD"))
|
||||
xc_RRAD.write(w);
|
||||
if (x10_LENG)
|
||||
if (auto rec = w.enterSubRecord("LENG"))
|
||||
x10_LENG.write(w);
|
||||
if (x14_COLR)
|
||||
if (auto rec = w.enterSubRecord("COLR"))
|
||||
x14_COLR.write(w);
|
||||
if (x18_SIDE)
|
||||
if (auto rec = w.enterSubRecord("SIDE"))
|
||||
x18_SIDE.write(w);
|
||||
if (x1c_IROT)
|
||||
if (auto rec = w.enterSubRecord("IROT"))
|
||||
x1c_IROT.write(w);
|
||||
if (x20_ROTM)
|
||||
if (auto rec = w.enterSubRecord("ROTM"))
|
||||
x20_ROTM.write(w);
|
||||
if (x24_POFS)
|
||||
if (auto rec = w.enterSubRecord("POFS"))
|
||||
x24_POFS.write(w);
|
||||
if (x28_IVEL)
|
||||
if (auto rec = w.enterSubRecord("IVEL"))
|
||||
x28_IVEL.write(w);
|
||||
if (x2c_NPOS)
|
||||
if (auto rec = w.enterSubRecord("NPOS"))
|
||||
x2c_NPOS.write(w);
|
||||
if (x30_VELM)
|
||||
if (auto rec = w.enterSubRecord("VELM"))
|
||||
x30_VELM.write(w);
|
||||
if (x34_VLM2)
|
||||
if (auto rec = w.enterSubRecord("VLM2"))
|
||||
x34_VLM2.write(w);
|
||||
if (x38_SPLN)
|
||||
if (auto rec = w.enterSubRecord("SPLN"))
|
||||
x38_SPLN.write(w);
|
||||
if (x3c_TEXR)
|
||||
if (auto rec = w.enterSubRecord("TEXR"))
|
||||
x3c_TEXR.write(w);
|
||||
if (x40_TSPN)
|
||||
if (auto rec = w.enterSubRecord("TSPN"))
|
||||
x40_TSPN.write(w);
|
||||
|
||||
if (x44_24_LLRD)
|
||||
w.writeBool("LLRD", true);
|
||||
if (!x44_25_CROS)
|
||||
w.writeBool("CROS", false);
|
||||
if (x44_26_VLS1)
|
||||
w.writeBool("VLS1", true);
|
||||
if (x44_27_VLS2)
|
||||
w.writeBool("VLS2", true);
|
||||
if (x44_28_SROT)
|
||||
w.writeBool("SROT", true);
|
||||
if (x44_29_WIRE)
|
||||
w.writeBool("WIRE", true);
|
||||
if (x44_30_TEXW)
|
||||
w.writeBool("TEXW", true);
|
||||
if (x44_31_AALP)
|
||||
w.writeBool("AALP", true);
|
||||
if (x45_24_ZBUF)
|
||||
w.writeBool("ZBUF", true);
|
||||
if (x45_25_ORNT)
|
||||
w.writeBool("ORNT", true);
|
||||
if (x45_26_CRND)
|
||||
w.writeBool("CRND", true);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void SWSH<IDType>::_binarySize(typename BigDNA::BinarySize::StreamT& s) const {
|
||||
s += 4;
|
||||
if (x0_PSLT) {
|
||||
s += 4;
|
||||
x0_PSLT.binarySize(s);
|
||||
}
|
||||
if (x4_TIME) {
|
||||
s += 4;
|
||||
x4_TIME.binarySize(s);
|
||||
}
|
||||
if (x8_LRAD) {
|
||||
s += 4;
|
||||
x8_LRAD.binarySize(s);
|
||||
}
|
||||
if (xc_RRAD) {
|
||||
s += 4;
|
||||
xc_RRAD.binarySize(s);
|
||||
}
|
||||
if (x10_LENG) {
|
||||
s += 4;
|
||||
x10_LENG.binarySize(s);
|
||||
}
|
||||
if (x14_COLR) {
|
||||
s += 4;
|
||||
x14_COLR.binarySize(s);
|
||||
}
|
||||
if (x18_SIDE) {
|
||||
s += 4;
|
||||
x18_SIDE.binarySize(s);
|
||||
}
|
||||
if (x1c_IROT) {
|
||||
s += 4;
|
||||
x1c_IROT.binarySize(s);
|
||||
}
|
||||
if (x20_ROTM) {
|
||||
s += 4;
|
||||
x20_ROTM.binarySize(s);
|
||||
}
|
||||
if (x24_POFS) {
|
||||
s += 4;
|
||||
x24_POFS.binarySize(s);
|
||||
}
|
||||
if (x28_IVEL) {
|
||||
s += 4;
|
||||
x28_IVEL.binarySize(s);
|
||||
}
|
||||
if (x2c_NPOS) {
|
||||
s += 4;
|
||||
x2c_NPOS.binarySize(s);
|
||||
}
|
||||
if (x30_VELM) {
|
||||
s += 4;
|
||||
x30_VELM.binarySize(s);
|
||||
}
|
||||
if (x34_VLM2) {
|
||||
s += 4;
|
||||
x34_VLM2.binarySize(s);
|
||||
}
|
||||
if (x38_SPLN) {
|
||||
s += 4;
|
||||
x38_SPLN.binarySize(s);
|
||||
}
|
||||
if (x3c_TEXR) {
|
||||
s += 4;
|
||||
x3c_TEXR.binarySize(s);
|
||||
}
|
||||
if (x40_TSPN) {
|
||||
s += 4;
|
||||
x40_TSPN.binarySize(s);
|
||||
}
|
||||
if (x44_24_LLRD)
|
||||
s += 9;
|
||||
if (!x44_25_CROS)
|
||||
s += 9;
|
||||
if (x44_26_VLS1)
|
||||
s += 9;
|
||||
if (x44_27_VLS2)
|
||||
s += 9;
|
||||
if (x44_28_SROT)
|
||||
s += 9;
|
||||
if (x44_29_WIRE)
|
||||
s += 9;
|
||||
if (x44_30_TEXW)
|
||||
s += 9;
|
||||
if (x44_31_AALP)
|
||||
s += 9;
|
||||
if (x45_24_ZBUF)
|
||||
s += 9;
|
||||
if (x45_25_ORNT)
|
||||
s += 9;
|
||||
if (x45_26_CRND)
|
||||
s += 9;
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void SWSH<IDType>::_read(typename BigDNA::Read::StreamT& r) {
|
||||
DNAFourCC clsId;
|
||||
clsId.read(r);
|
||||
if (clsId != SBIG('SWSH')) {
|
||||
LogModule.report(logvisor::Warning, fmt("non SWSH provided to SWSH parser"));
|
||||
return;
|
||||
}
|
||||
|
||||
clsId.read(r);
|
||||
while (clsId != SBIG('_END')) {
|
||||
switch (clsId.toUint32()) {
|
||||
case SBIG('PSLT'):
|
||||
x0_PSLT.read(r);
|
||||
break;
|
||||
case SBIG('TIME'):
|
||||
x4_TIME.read(r);
|
||||
break;
|
||||
case SBIG('LRAD'):
|
||||
x8_LRAD.read(r);
|
||||
break;
|
||||
case SBIG('RRAD'):
|
||||
xc_RRAD.read(r);
|
||||
break;
|
||||
case SBIG('LENG'):
|
||||
x10_LENG.read(r);
|
||||
break;
|
||||
case SBIG('COLR'):
|
||||
x14_COLR.read(r);
|
||||
break;
|
||||
case SBIG('SIDE'):
|
||||
x18_SIDE.read(r);
|
||||
break;
|
||||
case SBIG('IROT'):
|
||||
x1c_IROT.read(r);
|
||||
break;
|
||||
case SBIG('ROTM'):
|
||||
x20_ROTM.read(r);
|
||||
break;
|
||||
case SBIG('POFS'):
|
||||
x24_POFS.read(r);
|
||||
break;
|
||||
case SBIG('IVEL'):
|
||||
x28_IVEL.read(r);
|
||||
break;
|
||||
case SBIG('NPOS'):
|
||||
x2c_NPOS.read(r);
|
||||
break;
|
||||
case SBIG('VELM'):
|
||||
x30_VELM.read(r);
|
||||
break;
|
||||
case SBIG('VLM2'):
|
||||
x34_VLM2.read(r);
|
||||
break;
|
||||
case SBIG('SPLN'):
|
||||
x38_SPLN.read(r);
|
||||
break;
|
||||
case SBIG('TEXR'):
|
||||
x3c_TEXR.read(r);
|
||||
break;
|
||||
case SBIG('TSPN'):
|
||||
x40_TSPN.read(r);
|
||||
break;
|
||||
case SBIG('LLRD'):
|
||||
r.readUint32Big();
|
||||
x44_24_LLRD = r.readBool();
|
||||
break;
|
||||
case SBIG('CROS'):
|
||||
r.readUint32Big();
|
||||
x44_25_CROS = r.readBool();
|
||||
break;
|
||||
case SBIG('VLS1'):
|
||||
r.readUint32Big();
|
||||
x44_26_VLS1 = r.readBool();
|
||||
break;
|
||||
case SBIG('VLS2'):
|
||||
r.readUint32Big();
|
||||
x44_27_VLS2 = r.readBool();
|
||||
break;
|
||||
case SBIG('SROT'):
|
||||
r.readUint32Big();
|
||||
x44_28_SROT = r.readBool();
|
||||
break;
|
||||
case SBIG('WIRE'):
|
||||
r.readUint32Big();
|
||||
x44_29_WIRE = r.readBool();
|
||||
break;
|
||||
case SBIG('TEXW'):
|
||||
r.readUint32Big();
|
||||
x44_30_TEXW = r.readBool();
|
||||
break;
|
||||
case SBIG('AALP'):
|
||||
r.readUint32Big();
|
||||
x44_31_AALP = r.readBool();
|
||||
break;
|
||||
case SBIG('ZBUF'):
|
||||
r.readUint32Big();
|
||||
x45_24_ZBUF = r.readBool();
|
||||
break;
|
||||
case SBIG('ORNT'):
|
||||
r.readUint32Big();
|
||||
x45_25_ORNT = r.readBool();
|
||||
break;
|
||||
case SBIG('CRND'):
|
||||
r.readUint32Big();
|
||||
x45_26_CRND = r.readBool();
|
||||
break;
|
||||
default:
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown SWSH class {} @{}"), clsId, r.position());
|
||||
break;
|
||||
}
|
||||
clsId.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void SWSH<IDType>::_write(typename BigDNA::Write::StreamT& w) const {
|
||||
w.writeBytes((atInt8*)"SWSH", 4);
|
||||
if (x0_PSLT) {
|
||||
w.writeBytes((atInt8*)"PSLT", 4);
|
||||
x0_PSLT.write(w);
|
||||
}
|
||||
if (x4_TIME) {
|
||||
w.writeBytes((atInt8*)"TIME", 4);
|
||||
x4_TIME.write(w);
|
||||
}
|
||||
if (x8_LRAD) {
|
||||
w.writeBytes((atInt8*)"LRAD", 4);
|
||||
x8_LRAD.write(w);
|
||||
}
|
||||
if (xc_RRAD) {
|
||||
w.writeBytes((atInt8*)"RRAD", 4);
|
||||
xc_RRAD.write(w);
|
||||
}
|
||||
if (x10_LENG) {
|
||||
w.writeBytes((atInt8*)"LENG", 4);
|
||||
x10_LENG.write(w);
|
||||
}
|
||||
if (x14_COLR) {
|
||||
w.writeBytes((atInt8*)"COLR", 4);
|
||||
x14_COLR.write(w);
|
||||
}
|
||||
if (x18_SIDE) {
|
||||
w.writeBytes((atInt8*)"SIDE", 4);
|
||||
x18_SIDE.write(w);
|
||||
}
|
||||
if (x1c_IROT) {
|
||||
w.writeBytes((atInt8*)"IROT", 4);
|
||||
x1c_IROT.write(w);
|
||||
}
|
||||
if (x20_ROTM) {
|
||||
w.writeBytes((atInt8*)"ROTM", 4);
|
||||
x20_ROTM.write(w);
|
||||
}
|
||||
if (x24_POFS) {
|
||||
w.writeBytes((atInt8*)"POFS", 4);
|
||||
x24_POFS.write(w);
|
||||
}
|
||||
if (x28_IVEL) {
|
||||
w.writeBytes((atInt8*)"IVEL", 4);
|
||||
x28_IVEL.write(w);
|
||||
}
|
||||
if (x2c_NPOS) {
|
||||
w.writeBytes((atInt8*)"NPOS", 4);
|
||||
x2c_NPOS.write(w);
|
||||
}
|
||||
if (x30_VELM) {
|
||||
w.writeBytes((atInt8*)"VELM", 4);
|
||||
x30_VELM.write(w);
|
||||
}
|
||||
if (x34_VLM2) {
|
||||
w.writeBytes((atInt8*)"VLM2", 4);
|
||||
x34_VLM2.write(w);
|
||||
}
|
||||
if (x38_SPLN) {
|
||||
w.writeBytes((atInt8*)"SPLN", 4);
|
||||
x38_SPLN.write(w);
|
||||
}
|
||||
if (x3c_TEXR) {
|
||||
w.writeBytes((atInt8*)"TEXR", 4);
|
||||
x3c_TEXR.write(w);
|
||||
}
|
||||
if (x40_TSPN) {
|
||||
w.writeBytes((atInt8*)"TSPN", 4);
|
||||
x40_TSPN.write(w);
|
||||
}
|
||||
|
||||
if (x44_24_LLRD)
|
||||
w.writeBytes("LLRDCNST\x01", 9);
|
||||
if (!x44_25_CROS)
|
||||
w.writeBytes("CROSCNST\x00", 9);
|
||||
if (x44_26_VLS1)
|
||||
w.writeBytes("VLS1CNST\x01", 9);
|
||||
if (x44_27_VLS2)
|
||||
w.writeBytes("VLS2CNST\x01", 9);
|
||||
if (x44_28_SROT)
|
||||
w.writeBytes("SROTCNST\x01", 9);
|
||||
if (x44_29_WIRE)
|
||||
w.writeBytes("WIRECNST\x01", 9);
|
||||
if (x44_30_TEXW)
|
||||
w.writeBytes("TEXWCNST\x01", 9);
|
||||
if (x44_31_AALP)
|
||||
w.writeBytes("AALPCNST\x01", 9);
|
||||
if (x45_24_ZBUF)
|
||||
w.writeBytes("ZBUFCNST\x01", 9);
|
||||
if (x45_25_ORNT)
|
||||
w.writeBytes("ORNTCNST\x01", 9);
|
||||
if (x45_26_CRND)
|
||||
w.writeBytes("CRNDCNST\x01", 9);
|
||||
w.writeBytes("_END", 4);
|
||||
}
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(SWSH<UniqueID32>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(SWSH<UniqueID64>)
|
||||
|
||||
template <class IDType>
|
||||
void SWSH<IDType>::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
||||
if (x3c_TEXR.m_elem)
|
||||
x3c_TEXR.m_elem->gatherDependencies(pathsOut);
|
||||
}
|
||||
|
||||
template struct SWSH<UniqueID32>;
|
||||
template struct SWSH<UniqueID64>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#ifndef ENTRY
|
||||
#define ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef INT_ENTRY
|
||||
#define INT_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef REAL_ENTRY
|
||||
#define REAL_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef VECTOR_ENTRY
|
||||
#define VECTOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef MOD_VECTOR_ENTRY
|
||||
#define MOD_VECTOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef COLOR_ENTRY
|
||||
#define COLOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef UV_ENTRY
|
||||
#define UV_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef BOOL_ENTRY
|
||||
#define BOOL_ENTRY(name, identifier, def) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
INT_ENTRY('PSLT', x0_PSLT)
|
||||
REAL_ENTRY('TIME', x4_TIME)
|
||||
REAL_ENTRY('LRAD', x8_LRAD)
|
||||
REAL_ENTRY('RRAD', xc_RRAD)
|
||||
INT_ENTRY('LENG', x10_LENG)
|
||||
COLOR_ENTRY('COLR', x14_COLR)
|
||||
INT_ENTRY('SIDE', x18_SIDE)
|
||||
REAL_ENTRY('IROT', x1c_IROT)
|
||||
REAL_ENTRY('ROTM', x20_ROTM)
|
||||
VECTOR_ENTRY('POFS', x24_POFS)
|
||||
VECTOR_ENTRY('IVEL', x28_IVEL)
|
||||
VECTOR_ENTRY('NPOS', x2c_NPOS)
|
||||
MOD_VECTOR_ENTRY('VELM', x30_VELM)
|
||||
MOD_VECTOR_ENTRY('VLM2', x34_VLM2)
|
||||
INT_ENTRY('SPLN', x38_SPLN)
|
||||
UV_ENTRY('TEXR', x3c_TEXR)
|
||||
INT_ENTRY('TSPN', x40_TSPN)
|
||||
BOOL_ENTRY('LLRD', x44_24_LLRD, false)
|
||||
BOOL_ENTRY('CROS', x44_25_CROS, true)
|
||||
BOOL_ENTRY('VLS1', x44_26_VLS1, false)
|
||||
BOOL_ENTRY('VLS2', x44_27_VLS2, false)
|
||||
BOOL_ENTRY('SROT', x44_28_SROT, false)
|
||||
BOOL_ENTRY('WIRE', x44_29_WIRE, false)
|
||||
BOOL_ENTRY('TEXW', x44_30_TEXW, false)
|
||||
BOOL_ENTRY('AALP', x44_31_AALP, false)
|
||||
BOOL_ENTRY('ZBUF', x45_24_ZBUF, false)
|
||||
BOOL_ENTRY('ORNT', x45_25_ORNT, false)
|
||||
BOOL_ENTRY('CRND', x45_26_CRND, false)
|
||||
|
||||
#undef ENTRY
|
||||
#undef INT_ENTRY
|
||||
#undef REAL_ENTRY
|
||||
#undef VECTOR_ENTRY
|
||||
#undef MOD_VECTOR_ENTRY
|
||||
#undef COLOR_ENTRY
|
||||
#undef UV_ENTRY
|
||||
#undef BOOL_ENTRY
|
|
@ -16,48 +16,36 @@ class ProjectPath;
|
|||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template <class IDType>
|
||||
struct SWSH : public BigDNA {
|
||||
AT_DECL_EXPLICIT_DNA_YAML
|
||||
AT_SUBDECL_DNA
|
||||
struct _SWSH {
|
||||
static constexpr ParticleType Type = ParticleType::SWSH;
|
||||
|
||||
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;
|
||||
};
|
||||
#define INT_ENTRY(name, identifier) IntElementFactory identifier;
|
||||
#define REAL_ENTRY(name, identifier) RealElementFactory identifier;
|
||||
#define VECTOR_ENTRY(name, identifier) VectorElementFactory identifier;
|
||||
#define MOD_VECTOR_ENTRY(name, identifier) ModVectorElementFactory identifier;
|
||||
#define COLOR_ENTRY(name, identifier) ColorElementFactory identifier;
|
||||
#define UV_ENTRY(name, identifier) UVElementFactory<IDType> identifier;
|
||||
#define BOOL_ENTRY(name, identifier, def) bool identifier = def;
|
||||
#include "SWHC.def"
|
||||
|
||||
SWSH() { x44_25_CROS = true; }
|
||||
template<typename _Func>
|
||||
void constexpr Enumerate(_Func f) {
|
||||
#define ENTRY(name, identifier) f(FOURCC(name), identifier);
|
||||
#define BOOL_ENTRY(name, identifier, def) f(FOURCC(name), identifier, def);
|
||||
#include "SWHC.def"
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
template<typename _Func>
|
||||
bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
#define ENTRY(name, identifier) case SBIG(name): f(identifier); return true;
|
||||
#include "SWHC.def"
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class IDType>
|
||||
using SWSH = PPImpl<_SWSH<IDType>>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
|
|
@ -17,9 +17,11 @@ static logvisor::Module Log("libpng");
|
|||
|
||||
static int CountBits(uint32_t n) {
|
||||
int ret = 0;
|
||||
for (int i = 0; i < 32; ++i)
|
||||
if (((n >> i) & 1) != 0)
|
||||
for (int i = 0; i < 32; ++i) {
|
||||
if (((n >> i) & 1) != 0) {
|
||||
++ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -28,27 +30,29 @@ static void BoxFilter(const uint8_t* input, unsigned chanCount, unsigned inWidth
|
|||
bool dxt1) {
|
||||
unsigned mipWidth = 1;
|
||||
unsigned mipHeight = 1;
|
||||
if (inWidth > 1)
|
||||
if (inWidth > 1) {
|
||||
mipWidth = inWidth / 2;
|
||||
if (inHeight > 1)
|
||||
}
|
||||
if (inHeight > 1) {
|
||||
mipHeight = inHeight / 2;
|
||||
}
|
||||
|
||||
unsigned y, x, c;
|
||||
for (y = 0; y < mipHeight; ++y) {
|
||||
unsigned miplineBase = mipWidth * y;
|
||||
unsigned in1LineBase = inWidth * (y * 2);
|
||||
unsigned in2LineBase = inWidth * (y * 2 + 1);
|
||||
for (x = 0; x < mipWidth; ++x) {
|
||||
for (unsigned y = 0; y < mipHeight; ++y) {
|
||||
const unsigned miplineBase = mipWidth * y;
|
||||
const unsigned in1LineBase = inWidth * (y * 2);
|
||||
const unsigned in2LineBase = inWidth * (y * 2 + 1);
|
||||
for (unsigned x = 0; x < mipWidth; ++x) {
|
||||
uint8_t* out = &output[(miplineBase + x) * chanCount];
|
||||
for (c = 0; c < chanCount; ++c) {
|
||||
for (unsigned c = 0; c < chanCount; ++c) {
|
||||
uint32_t tmp = 0;
|
||||
tmp += input[(in1LineBase + (x * 2)) * chanCount + c];
|
||||
tmp += input[(in1LineBase + (x * 2 + 1)) * chanCount + c];
|
||||
tmp += input[(in2LineBase + (x * 2)) * chanCount + c];
|
||||
tmp += input[(in2LineBase + (x * 2 + 1)) * chanCount + c];
|
||||
out[c] = uint8_t(tmp / 4);
|
||||
if (c == 3 && dxt1)
|
||||
if (c == 3 && dxt1) {
|
||||
out[c] = uint8_t(out[c] ? 0xff : 0x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,52 +69,52 @@ static size_t ComputeMippedTexelCount(unsigned inWidth, unsigned inHeight) {
|
|||
}
|
||||
|
||||
/* GX uses this upsampling technique to extract full 8-bit range */
|
||||
constexpr uint8_t Convert3To8(uint8_t v) {
|
||||
static constexpr uint8_t Convert3To8(uint8_t v) {
|
||||
/* Swizzle bits: 00000123 -> 12312312 */
|
||||
return (v << 5) | (v << 2) | (v >> 1);
|
||||
}
|
||||
|
||||
constexpr uint8_t Convert8To3(uint8_t v) { return v >> 5; }
|
||||
static constexpr uint8_t Convert8To3(uint8_t v) { return v >> 5; }
|
||||
|
||||
constexpr uint8_t Convert4To8(uint8_t v) {
|
||||
static constexpr uint8_t Convert4To8(uint8_t v) {
|
||||
/* Swizzle bits: 00001234 -> 12341234 */
|
||||
return (v << 4) | v;
|
||||
}
|
||||
|
||||
constexpr uint8_t Convert8To4(uint8_t v) { return v >> 4; }
|
||||
static constexpr uint8_t Convert8To4(uint8_t v) { return v >> 4; }
|
||||
|
||||
constexpr uint8_t Convert5To8(uint8_t v) {
|
||||
static constexpr uint8_t Convert5To8(uint8_t v) {
|
||||
/* Swizzle bits: 00012345 -> 12345123 */
|
||||
return (v << 3) | (v >> 2);
|
||||
}
|
||||
|
||||
constexpr uint8_t Convert8To5(uint8_t v) { return v >> 3; }
|
||||
static constexpr uint8_t Convert8To5(uint8_t v) { return v >> 3; }
|
||||
|
||||
constexpr uint8_t Convert6To8(uint8_t v) {
|
||||
static constexpr uint8_t Convert6To8(uint8_t v) {
|
||||
/* Swizzle bits: 00123456 -> 12345612 */
|
||||
return (v << 2) | (v >> 4);
|
||||
}
|
||||
|
||||
constexpr uint8_t Convert8To6(uint8_t v) { return v >> 2; }
|
||||
static constexpr uint8_t Convert8To6(uint8_t v) { return v >> 2; }
|
||||
|
||||
static uint8_t Lookup4BPP(const uint8_t* texels, int width, int x, int y) {
|
||||
int bwidth = (width + 7) / 8;
|
||||
int bx = x / 8;
|
||||
int by = y / 8;
|
||||
int rx = x % 8;
|
||||
int ry = y % 8;
|
||||
int bidx = by * bwidth + bx;
|
||||
const int bwidth = (width + 7) / 8;
|
||||
const int bx = x / 8;
|
||||
const int by = y / 8;
|
||||
const int rx = x % 8;
|
||||
const int ry = y % 8;
|
||||
const int bidx = by * bwidth + bx;
|
||||
const uint8_t* btexels = &texels[32 * bidx];
|
||||
return btexels[ry * 4 + rx / 2] >> ((rx & 1) ? 0 : 4) & 0xf;
|
||||
}
|
||||
|
||||
static void Set4BPP(uint8_t* texels, int width, int x, int y, uint8_t val) {
|
||||
int bwidth = (width + 7) / 8;
|
||||
int bx = x / 8;
|
||||
int by = y / 8;
|
||||
int rx = x % 8;
|
||||
int ry = y % 8;
|
||||
int bidx = by * bwidth + bx;
|
||||
const int bwidth = (width + 7) / 8;
|
||||
const int bx = x / 8;
|
||||
const int by = y / 8;
|
||||
const int rx = x % 8;
|
||||
const int ry = y % 8;
|
||||
const int bidx = by * bwidth + bx;
|
||||
uint8_t* btexels = &texels[32 * bidx];
|
||||
btexels[ry * 4 + rx / 2] |= (val & 0xf) << ((rx & 1) ? 0 : 4);
|
||||
}
|
||||
|
@ -127,68 +131,68 @@ static uint8_t Lookup8BPP(const uint8_t* texels, int width, int x, int y) {
|
|||
}
|
||||
|
||||
static void Set8BPP(uint8_t* texels, int width, int x, int y, uint8_t val) {
|
||||
int bwidth = (width + 7) / 8;
|
||||
int bx = x / 8;
|
||||
int by = y / 4;
|
||||
int rx = x % 8;
|
||||
int ry = y % 4;
|
||||
int bidx = by * bwidth + bx;
|
||||
const int bwidth = (width + 7) / 8;
|
||||
const int bx = x / 8;
|
||||
const int by = y / 4;
|
||||
const int rx = x % 8;
|
||||
const int ry = y % 4;
|
||||
const int bidx = by * bwidth + bx;
|
||||
uint8_t* btexels = &texels[32 * bidx];
|
||||
btexels[ry * 8 + rx] = val;
|
||||
}
|
||||
|
||||
static uint16_t Lookup16BPP(const uint8_t* texels, int width, int x, int y) {
|
||||
int bwidth = (width + 3) / 4;
|
||||
int bx = x / 4;
|
||||
int by = y / 4;
|
||||
int rx = x % 4;
|
||||
int ry = y % 4;
|
||||
const int bwidth = (width + 3) / 4;
|
||||
const int bx = x / 4;
|
||||
const int by = y / 4;
|
||||
const int rx = x % 4;
|
||||
const int ry = y % 4;
|
||||
int bidx = by * bwidth + bx;
|
||||
const uint16_t* btexels = (uint16_t*)&texels[32 * bidx];
|
||||
const uint16_t* btexels = reinterpret_cast<const uint16_t*>(&texels[32 * bidx]);
|
||||
return btexels[ry * 4 + rx];
|
||||
}
|
||||
|
||||
static void Set16BPP(uint8_t* texels, int width, int x, int y, uint16_t val) {
|
||||
int bwidth = (width + 3) / 4;
|
||||
int bx = x / 4;
|
||||
int by = y / 4;
|
||||
int rx = x % 4;
|
||||
int ry = y % 4;
|
||||
int bidx = by * bwidth + bx;
|
||||
uint16_t* btexels = (uint16_t*)&texels[32 * bidx];
|
||||
const int bwidth = (width + 3) / 4;
|
||||
const int bx = x / 4;
|
||||
const int by = y / 4;
|
||||
const int rx = x % 4;
|
||||
const int ry = y % 4;
|
||||
const int bidx = by * bwidth + bx;
|
||||
auto* btexels = reinterpret_cast<uint16_t*>(&texels[32 * bidx]);
|
||||
btexels[ry * 4 + rx] = val;
|
||||
}
|
||||
|
||||
static void LookupRGBA8(const uint8_t* texels, int width, int x, int y, uint8_t* r, uint8_t* g, uint8_t* b,
|
||||
uint8_t* a) {
|
||||
int bwidth = (width + 3) / 4;
|
||||
int bx = x / 4;
|
||||
int by = y / 4;
|
||||
int rx = x % 4;
|
||||
int ry = y % 4;
|
||||
int bidx = (by * bwidth + bx) * 2;
|
||||
const uint16_t* artexels = (uint16_t*)&texels[32 * bidx];
|
||||
const uint16_t* gbtexels = (uint16_t*)&texels[32 * (bidx + 1)];
|
||||
uint16_t ar = hecl::SBig(artexels[ry * 4 + rx]);
|
||||
const int bwidth = (width + 3) / 4;
|
||||
const int bx = x / 4;
|
||||
const int by = y / 4;
|
||||
const int rx = x % 4;
|
||||
const int ry = y % 4;
|
||||
const int bidx = (by * bwidth + bx) * 2;
|
||||
const auto* artexels = reinterpret_cast<const uint16_t*>(&texels[32 * bidx]);
|
||||
const auto* gbtexels = reinterpret_cast<const uint16_t*>(&texels[32 * (bidx + 1)]);
|
||||
const uint16_t ar = hecl::SBig(artexels[ry * 4 + rx]);
|
||||
*a = ar >> 8 & 0xff;
|
||||
*r = ar & 0xff;
|
||||
uint16_t gb = hecl::SBig(gbtexels[ry * 4 + rx]);
|
||||
const uint16_t gb = hecl::SBig(gbtexels[ry * 4 + rx]);
|
||||
*g = gb >> 8 & 0xff;
|
||||
*b = gb & 0xff;
|
||||
}
|
||||
|
||||
static void SetRGBA8(uint8_t* texels, int width, int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
int bwidth = (width + 3) / 4;
|
||||
int bx = x / 4;
|
||||
int by = y / 4;
|
||||
int rx = x % 4;
|
||||
int ry = y % 4;
|
||||
int bidx = (by * bwidth + bx) * 2;
|
||||
uint16_t* artexels = (uint16_t*)&texels[32 * bidx];
|
||||
uint16_t* gbtexels = (uint16_t*)&texels[32 * (bidx + 1)];
|
||||
uint16_t ar = (a << 8) | r;
|
||||
const int bwidth = (width + 3) / 4;
|
||||
const int bx = x / 4;
|
||||
const int by = y / 4;
|
||||
const int rx = x % 4;
|
||||
const int ry = y % 4;
|
||||
const int bidx = (by * bwidth + bx) * 2;
|
||||
uint16_t* artexels = reinterpret_cast<uint16_t*>(&texels[32 * bidx]);
|
||||
uint16_t* gbtexels = reinterpret_cast<uint16_t*>(&texels[32 * (bidx + 1)]);
|
||||
const uint16_t ar = (a << 8) | r;
|
||||
artexels[ry * 4 + rx] = hecl::SBig(ar);
|
||||
uint16_t gb = (g << 8) | b;
|
||||
const uint16_t gb = (g << 8) | b;
|
||||
gbtexels[ry * 4 + rx] = hecl::SBig(gb);
|
||||
}
|
||||
|
||||
|
@ -199,8 +203,9 @@ static void DecodeI4(png_structp png, png_infop info, const uint8_t* texels, int
|
|||
std::unique_ptr<uint8_t[]> buf(new uint8_t[width]);
|
||||
// memset(buf.get(), 0, width);
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
buf[x] = Convert4To8(Lookup4BPP(texels, width, x, y));
|
||||
}
|
||||
png_write_row(png, buf.get());
|
||||
}
|
||||
}
|
||||
|
@ -223,16 +228,18 @@ static void DecodeI8(png_structp png, png_infop info, const uint8_t* texels, int
|
|||
png_write_info(png, info);
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[width]);
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
buf[x] = Lookup8BPP(texels, width, x, y);
|
||||
}
|
||||
png_write_row(png, buf.get());
|
||||
}
|
||||
}
|
||||
|
||||
static void EncodeI8(const uint8_t* rgbaIn, uint8_t* texels, int width, int height) {
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
Set8BPP(texels, width, x, y, rgbaIn[x]);
|
||||
}
|
||||
rgbaIn += width;
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +251,7 @@ static void DecodeIA4(png_structp png, png_infop info, const uint8_t* texels, in
|
|||
std::unique_ptr<uint8_t[]> buf(new uint8_t[width * 2]);
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
uint8_t texel = Lookup8BPP(texels, width, x, y);
|
||||
const uint8_t texel = Lookup8BPP(texels, width, x, y);
|
||||
buf[x * 2 ] = Convert4To8(texel & 0xf);
|
||||
buf[x * 2 + 1] = Convert4To8(texel >> 4 & 0xf);
|
||||
}
|
||||
|
@ -274,22 +281,24 @@ static void DecodeIA8(png_structp png, png_infop info, const uint8_t* texels, in
|
|||
png_write_info(png, info);
|
||||
std::unique_ptr<uint16_t[]> buf(new uint16_t[width]);
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
buf[x] = hecl::SBig(Lookup16BPP(texels, width, x, y));
|
||||
png_write_row(png, (png_bytep)buf.get());
|
||||
}
|
||||
png_write_row(png, reinterpret_cast<png_bytep>(buf.get()));
|
||||
}
|
||||
}
|
||||
|
||||
static void EncodeIA8(const uint8_t* rgbaIn, uint8_t* texels, int width, int height) {
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
Set16BPP(texels, width, x, y, hecl::SBig(((uint16_t*)rgbaIn)[x]));
|
||||
for (int x = 0; x < width; ++x) {
|
||||
Set16BPP(texels, width, x, y, hecl::SBig(reinterpret_cast<const uint16_t*>(rgbaIn)[x]));
|
||||
}
|
||||
rgbaIn += width * 2;
|
||||
}
|
||||
}
|
||||
|
||||
static const uint8_t* DecodePalette(png_structp png, png_infop info, int numEntries, const uint8_t* data) {
|
||||
uint32_t format = hecl::SBig(*(uint32_t*)data);
|
||||
const auto format = hecl::SBig(*reinterpret_cast<const uint32_t*>(data));
|
||||
data += 8;
|
||||
png_color cEntries[256];
|
||||
png_byte aEntries[256];
|
||||
|
@ -306,9 +315,9 @@ static const uint8_t* DecodePalette(png_structp png, png_infop info, int numEntr
|
|||
}
|
||||
case 1: {
|
||||
/* RGB565 */
|
||||
const uint16_t* data16 = (uint16_t*)data;
|
||||
const auto* data16 = reinterpret_cast<const uint16_t*>(data);
|
||||
for (int e = 0; e < numEntries; ++e) {
|
||||
uint16_t texel = hecl::SBig(data16[e]);
|
||||
const uint16_t texel = hecl::SBig(data16[e]);
|
||||
cEntries[e].red = Convert5To8(texel >> 11 & 0x1f);
|
||||
cEntries[e].green = Convert6To8(texel >> 5 & 0x3f);
|
||||
cEntries[e].blue = Convert5To8(texel & 0x1f);
|
||||
|
@ -317,9 +326,9 @@ static const uint8_t* DecodePalette(png_structp png, png_infop info, int numEntr
|
|||
}
|
||||
case 2: {
|
||||
/* RGB5A3 */
|
||||
const uint16_t* data16 = (uint16_t*)data;
|
||||
const auto* data16 = reinterpret_cast<const uint16_t*>(data);
|
||||
for (int e = 0; e < numEntries; ++e) {
|
||||
uint16_t texel = hecl::SBig(data16[e]);
|
||||
const uint16_t texel = hecl::SBig(data16[e]);
|
||||
if (texel & 0x8000) {
|
||||
cEntries[e].red = Convert5To8(texel >> 10 & 0x1f);
|
||||
cEntries[e].green = Convert5To8(texel >> 5 & 0x1f);
|
||||
|
@ -336,8 +345,9 @@ static const uint8_t* DecodePalette(png_structp png, png_infop info, int numEntr
|
|||
}
|
||||
}
|
||||
png_set_PLTE(png, info, cEntries, numEntries);
|
||||
if (format == 0 || format == 2)
|
||||
if (format == 0 || format == 2) {
|
||||
png_set_tRNS(png, info, aEntries, numEntries, nullptr);
|
||||
}
|
||||
data += numEntries * 2;
|
||||
return data;
|
||||
}
|
||||
|
@ -360,20 +370,21 @@ static uint8_t* EncodePalette(png_structp png, png_infop info, int numEntries, u
|
|||
|
||||
uint32_t format = 0; /* Default IA8 */
|
||||
for (int e = 0; e < pngNumEntries; ++e) {
|
||||
png_colorp ent = &cEntries[e];
|
||||
const png_const_colorp ent = &cEntries[e];
|
||||
if (ent->red != ent->green || ent->red != ent->blue) {
|
||||
if (pngNumAEntries)
|
||||
if (pngNumAEntries) {
|
||||
format = 2; /* RGB565 if not greyscale and has alpha */
|
||||
else
|
||||
} else {
|
||||
format = 1; /* RGB565 if not greyscale */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
((uint32_t*)data)[0] = hecl::SBig(format);
|
||||
reinterpret_cast<uint32_t*>(data)[0] = hecl::SBig(format);
|
||||
data += 4;
|
||||
((uint16_t*)data)[0] = hecl::SBig(uint16_t(numEntries));
|
||||
((uint16_t*)data)[1] = hecl::SBig(uint16_t(1));
|
||||
reinterpret_cast<uint16_t*>(data)[0] = hecl::SBig(uint16_t(numEntries));
|
||||
reinterpret_cast<uint16_t*>(data)[1] = hecl::SBig(uint16_t(1));
|
||||
data += 4;
|
||||
|
||||
switch (format) {
|
||||
|
@ -393,7 +404,7 @@ static uint8_t* EncodePalette(png_structp png, png_infop info, int numEntries, u
|
|||
}
|
||||
case 1: {
|
||||
/* RGB565 */
|
||||
uint16_t* data16 = (uint16_t*)data;
|
||||
uint16_t* data16 = reinterpret_cast<uint16_t*>(data);
|
||||
for (int e = 0; e < numEntries; ++e) {
|
||||
if (e < pngNumEntries) {
|
||||
uint16_t texel = Convert8To5(cEntries[e].red) << 11;
|
||||
|
@ -408,11 +419,12 @@ static uint8_t* EncodePalette(png_structp png, png_infop info, int numEntries, u
|
|||
}
|
||||
case 2: {
|
||||
/* RGB5A3 */
|
||||
uint16_t* data16 = (uint16_t*)data;
|
||||
auto* data16 = reinterpret_cast<uint16_t*>(data);
|
||||
for (int e = 0; e < numEntries; ++e) {
|
||||
uint8_t alpha = 0;
|
||||
if (e < pngNumAEntries)
|
||||
if (e < pngNumAEntries) {
|
||||
alpha = aEntries[e];
|
||||
}
|
||||
|
||||
uint16_t texel = 0;
|
||||
if (alpha == 0xff) {
|
||||
|
@ -440,7 +452,7 @@ static uint8_t* EncodePalette(png_structp png, png_infop info, int numEntries, u
|
|||
}
|
||||
|
||||
static const uint8_t* DecodePaletteSPLT(png_structp png, png_infop info, int numEntries, const uint8_t* data) {
|
||||
uint32_t format = hecl::SBig(*(uint32_t*)data);
|
||||
const auto format = hecl::SBig(*reinterpret_cast<const uint32_t*>(data));
|
||||
data += 8;
|
||||
png_sPLT_entry entries[256] = {};
|
||||
png_sPLT_t GXEntry = {(char*)"GXPalette", 8, entries, numEntries};
|
||||
|
@ -459,9 +471,9 @@ static const uint8_t* DecodePaletteSPLT(png_structp png, png_infop info, int num
|
|||
case 1: {
|
||||
/* RGB565 */
|
||||
GXEntry.name = (char*)"GX_RGB565";
|
||||
const uint16_t* data16 = (uint16_t*)data;
|
||||
const auto* data16 = reinterpret_cast<const uint16_t*>(data);
|
||||
for (int e = 0; e < numEntries; ++e) {
|
||||
uint16_t texel = hecl::SBig(data16[e]);
|
||||
const uint16_t texel = hecl::SBig(data16[e]);
|
||||
entries[e].red = Convert5To8(texel >> 11 & 0x1f);
|
||||
entries[e].green = Convert6To8(texel >> 5 & 0x3f);
|
||||
entries[e].blue = Convert5To8(texel & 0x1f);
|
||||
|
@ -472,9 +484,9 @@ static const uint8_t* DecodePaletteSPLT(png_structp png, png_infop info, int num
|
|||
case 2: {
|
||||
/* RGB5A3 */
|
||||
GXEntry.name = (char*)"GX_RGB5A3";
|
||||
const uint16_t* data16 = (uint16_t*)data;
|
||||
const auto* data16 = reinterpret_cast<const uint16_t*>(data);
|
||||
for (int e = 0; e < numEntries; ++e) {
|
||||
uint16_t texel = hecl::SBig(data16[e]);
|
||||
const uint16_t texel = hecl::SBig(data16[e]);
|
||||
if (texel & 0x8000) {
|
||||
entries[e].red = Convert5To8(texel >> 10 & 0x1f);
|
||||
entries[e].green = Convert5To8(texel >> 5 & 0x1f);
|
||||
|
@ -497,12 +509,12 @@ static const uint8_t* DecodePaletteSPLT(png_structp png, png_infop info, int num
|
|||
|
||||
static uint8_t* EncodePaletteSPLT(png_structp png, png_infop info, int numEntries, uint8_t* data) {
|
||||
png_sPLT_tp palettes;
|
||||
int pngNumPalettes = png_get_sPLT(png, info, &palettes);
|
||||
const int pngNumPalettes = png_get_sPLT(png, info, &palettes);
|
||||
int pngNumEntries = 0;
|
||||
png_sPLT_entryp cEntries = nullptr;
|
||||
for (int i = 0; i < pngNumPalettes; ++i) {
|
||||
png_sPLT_tp palette = &palettes[i];
|
||||
if (!strncmp(palette->name, "GX_", 3)) {
|
||||
const png_const_sPLT_tp palette = &palettes[i];
|
||||
if (strncmp(palette->name, "GX_", 3) == 0) {
|
||||
pngNumEntries = palette->nentries;
|
||||
cEntries = palette->entries;
|
||||
break;
|
||||
|
@ -511,20 +523,21 @@ static uint8_t* EncodePaletteSPLT(png_structp png, png_infop info, int numEntrie
|
|||
|
||||
uint32_t format = 2; /* Default RGB5A3 */
|
||||
for (int e = 0; e < pngNumEntries; ++e) {
|
||||
png_sPLT_entryp ent = &cEntries[e];
|
||||
const png_const_sPLT_entryp ent = &cEntries[e];
|
||||
if (ent->red != ent->green || ent->red != ent->blue) {
|
||||
if (ent->alpha) {
|
||||
format = 2;
|
||||
break;
|
||||
} else
|
||||
} else {
|
||||
format = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
((uint32_t*)data)[0] = hecl::SBig(format);
|
||||
reinterpret_cast<uint32_t*>(data)[0] = hecl::SBig(format);
|
||||
data += 4;
|
||||
((uint16_t*)data)[0] = hecl::SBig(uint16_t(1));
|
||||
((uint16_t*)data)[1] = hecl::SBig(uint16_t(numEntries));
|
||||
reinterpret_cast<uint16_t*>(data)[0] = hecl::SBig(uint16_t(1));
|
||||
reinterpret_cast<uint16_t*>(data)[1] = hecl::SBig(uint16_t(numEntries));
|
||||
data += 4;
|
||||
|
||||
switch (format) {
|
||||
|
@ -543,7 +556,7 @@ static uint8_t* EncodePaletteSPLT(png_structp png, png_infop info, int numEntrie
|
|||
}
|
||||
case 1: {
|
||||
/* RGB565 */
|
||||
uint16_t* data16 = (uint16_t*)data;
|
||||
auto* data16 = reinterpret_cast<uint16_t*>(data);
|
||||
for (int e = 0; e < numEntries; ++e) {
|
||||
if (e < pngNumEntries) {
|
||||
uint16_t texel = Convert8To5(cEntries[e].red) << 11;
|
||||
|
@ -558,7 +571,7 @@ static uint8_t* EncodePaletteSPLT(png_structp png, png_infop info, int numEntrie
|
|||
}
|
||||
case 2: {
|
||||
/* RGB5A3 */
|
||||
uint16_t* data16 = (uint16_t*)data;
|
||||
auto* data16 = reinterpret_cast<uint16_t*>(data);
|
||||
for (int e = 0; e < numEntries; ++e) {
|
||||
uint16_t texel = 0;
|
||||
if (cEntries && cEntries[e].alpha == 0xff) {
|
||||
|
@ -599,8 +612,9 @@ static void DecodeC4(png_structp png, png_infop info, const uint8_t* data, int w
|
|||
png_write_info(png, info);
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[width]);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
buf[x] = Lookup4BPP(texels, width, x, y);
|
||||
}
|
||||
png_write_row(png, buf.get());
|
||||
}
|
||||
}
|
||||
|
@ -608,8 +622,9 @@ static void DecodeC4(png_structp png, png_infop info, const uint8_t* data, int w
|
|||
static void EncodeC4(png_structp png, png_infop info, const uint8_t* rgbaIn, uint8_t* data, int width, int height) {
|
||||
uint8_t* texels = EncodePaletteSPLT(png, info, 16, data);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
Set4BPP(texels, width, x, y, rgbaIn[x]);
|
||||
}
|
||||
rgbaIn += width;
|
||||
}
|
||||
}
|
||||
|
@ -621,8 +636,9 @@ static void DecodeC8(png_structp png, png_infop info, const uint8_t* data, int w
|
|||
png_write_info(png, info);
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[width]);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
buf[x] = Lookup8BPP(texels, width, x, y);
|
||||
}
|
||||
png_write_row(png, buf.get());
|
||||
}
|
||||
}
|
||||
|
@ -630,8 +646,9 @@ static void DecodeC8(png_structp png, png_infop info, const uint8_t* data, int w
|
|||
static void EncodeC8(png_structp png, png_infop info, const uint8_t* rgbaIn, uint8_t* data, int width, int height) {
|
||||
uint8_t* texels = EncodePalette(png, info, 256, data);
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
Set8BPP(texels, width, x, y, rgbaIn[x]);
|
||||
}
|
||||
rgbaIn += width;
|
||||
}
|
||||
}
|
||||
|
@ -643,7 +660,7 @@ static void DecodeRGB565(png_structp png, png_infop info, const uint8_t* texels,
|
|||
std::unique_ptr<uint8_t[]> buf(new uint8_t[width * 3]);
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
uint16_t texel = hecl::SBig(Lookup16BPP(texels, width, x, y));
|
||||
const uint16_t texel = hecl::SBig(Lookup16BPP(texels, width, x, y));
|
||||
buf[x * 3] = Convert5To8(texel >> 11 & 0x1f);
|
||||
buf[x * 3 + 1] = Convert6To8(texel >> 5 & 0x3f);
|
||||
buf[x * 3 + 2] = Convert5To8(texel & 0x1f);
|
||||
|
@ -676,7 +693,7 @@ static void DecodeRGB5A3(png_structp png, png_infop info, const uint8_t* texels,
|
|||
std::unique_ptr<uint8_t[]> buf(new uint8_t[width * 4]);
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
uint16_t texel = hecl::SBig(Lookup16BPP(texels, width, x, y));
|
||||
const uint16_t texel = hecl::SBig(Lookup16BPP(texels, width, x, y));
|
||||
if (texel & 0x8000) {
|
||||
buf[x * 4] = Convert5To8(texel >> 10 & 0x1f);
|
||||
buf[x * 4 + 1] = Convert5To8(texel >> 5 & 0x1f);
|
||||
|
@ -728,16 +745,18 @@ static void DecodeRGBA8(png_structp png, png_infop info, const uint8_t* texels,
|
|||
png_write_info(png, info);
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[width * 4]);
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
LookupRGBA8(texels, width, x, y, &buf[x * 4], &buf[x * 4 + 1], &buf[x * 4 + 2], &buf[x * 4 + 3]);
|
||||
}
|
||||
png_write_row(png, buf.get());
|
||||
}
|
||||
}
|
||||
|
||||
static void EncodeRGBA8(const uint8_t* rgbaIn, uint8_t* texels, int width, int height) {
|
||||
for (int y = height - 1; y >= 0; --y) {
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int x = 0; x < width; ++x) {
|
||||
SetRGBA8(texels, width, x, y, rgbaIn[x * 4], rgbaIn[x * 4 + 1], rgbaIn[x * 4 + 2], rgbaIn[x * 4 + 3]);
|
||||
}
|
||||
rgbaIn += width * 4;
|
||||
}
|
||||
}
|
||||
|
@ -754,50 +773,55 @@ static void DecodeCMPR(png_structp png, png_infop info, const uint8_t* texels, i
|
|||
png_write_info(png, info);
|
||||
|
||||
/* Decode 8 rows at a time */
|
||||
int bwidth = (width + 7) / 8;
|
||||
int bpwidth = bwidth * 8;
|
||||
const int bwidth = (width + 7) / 8;
|
||||
const int bpwidth = bwidth * 8;
|
||||
std::unique_ptr<uint32_t[]> buf(new uint32_t[bpwidth * 8]);
|
||||
uint32_t* bTargets[4] = {buf.get(), buf.get() + 4, buf.get() + 4 * width, buf.get() + 4 * width + 4};
|
||||
for (int y = height / 8 - 1; y >= 0; --y) {
|
||||
const DXTBlock* blks = (DXTBlock*)(texels + 32 * bwidth * y);
|
||||
const auto* blks = reinterpret_cast<const DXTBlock*>(texels + 32 * bwidth * y);
|
||||
for (int x = 0; x < width; x += 8) {
|
||||
uint32_t blkOut[4][4][4];
|
||||
squish::Decompress((uint8_t*)blkOut[0][0], blks++, squish::kDxt1GCN);
|
||||
squish::Decompress((uint8_t*)blkOut[1][0], blks++, squish::kDxt1GCN);
|
||||
squish::Decompress((uint8_t*)blkOut[2][0], blks++, squish::kDxt1GCN);
|
||||
squish::Decompress((uint8_t*)blkOut[3][0], blks++, squish::kDxt1GCN);
|
||||
squish::Decompress(reinterpret_cast<uint8_t*>(blkOut[0][0]), blks++, squish::kDxt1GCN);
|
||||
squish::Decompress(reinterpret_cast<uint8_t*>(blkOut[1][0]), blks++, squish::kDxt1GCN);
|
||||
squish::Decompress(reinterpret_cast<uint8_t*>(blkOut[2][0]), blks++, squish::kDxt1GCN);
|
||||
squish::Decompress(reinterpret_cast<uint8_t*>(blkOut[3][0]), blks++, squish::kDxt1GCN);
|
||||
|
||||
for (int bt = 0; bt < 4; ++bt)
|
||||
for (int by = 0; by < 4; ++by)
|
||||
memcpy(bTargets[bt] + x + width * by, blkOut[bt][by], 16);
|
||||
for (int bt = 0; bt < 4; ++bt) {
|
||||
for (int by = 0; by < 4; ++by) {
|
||||
std::memcpy(bTargets[bt] + x + width * by, blkOut[bt][by], 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int r = 7; r >= 0; --r) {
|
||||
png_write_row(png, reinterpret_cast<png_bytep>(bTargets[0] + width * r));
|
||||
}
|
||||
for (int r = 7; r >= 0; --r)
|
||||
png_write_row(png, (png_bytep)(bTargets[0] + width * r));
|
||||
}
|
||||
}
|
||||
|
||||
static void EncodeCMPR(const uint8_t* rgbaIn, uint8_t* texels, int width, int height) {
|
||||
/* Encode 8 rows at a time */
|
||||
int bwidth = (width + 7) / 8;
|
||||
int bpwidth = bwidth * 8;
|
||||
const int bwidth = (width + 7) / 8;
|
||||
const int bpwidth = bwidth * 8;
|
||||
std::unique_ptr<uint32_t[]> buf(new uint32_t[bpwidth * 8]);
|
||||
uint32_t* bTargets[4] = {buf.get(), buf.get() + 4, buf.get() + 4 * width, buf.get() + 4 * width + 4};
|
||||
for (int y = height / 8 - 1; y >= 0; --y) {
|
||||
for (int r = 7; r >= 0; --r) {
|
||||
memcpy(bTargets[0] + width * r, rgbaIn, width * 4);
|
||||
std::memcpy(bTargets[0] + width * r, rgbaIn, width * 4);
|
||||
rgbaIn += width * 4;
|
||||
}
|
||||
DXTBlock* blks = (DXTBlock*)(texels + 32 * bwidth * y);
|
||||
auto* blks = reinterpret_cast<DXTBlock*>(texels + 32 * bwidth * y);
|
||||
for (int x = 0; x < width; x += 8) {
|
||||
uint32_t blkIn[4][4][4];
|
||||
for (int bt = 0; bt < 4; ++bt)
|
||||
for (int by = 0; by < 4; ++by)
|
||||
memcpy(blkIn[bt][by], bTargets[bt] + x + width * by, 16);
|
||||
for (int bt = 0; bt < 4; ++bt) {
|
||||
for (int by = 0; by < 4; ++by) {
|
||||
std::memcpy(blkIn[bt][by], bTargets[bt] + x + width * by, 16);
|
||||
}
|
||||
}
|
||||
|
||||
squish::Compress((uint8_t*)blkIn[0][0], blks++, squish::kDxt1GCN);
|
||||
squish::Compress((uint8_t*)blkIn[1][0], blks++, squish::kDxt1GCN);
|
||||
squish::Compress((uint8_t*)blkIn[2][0], blks++, squish::kDxt1GCN);
|
||||
squish::Compress((uint8_t*)blkIn[3][0], blks++, squish::kDxt1GCN);
|
||||
squish::Compress(reinterpret_cast<uint8_t*>(blkIn[0][0]), blks++, squish::kDxt1GCN);
|
||||
squish::Compress(reinterpret_cast<uint8_t*>(blkIn[1][0]), blks++, squish::kDxt1GCN);
|
||||
squish::Compress(reinterpret_cast<uint8_t*>(blkIn[2][0]), blks++, squish::kDxt1GCN);
|
||||
squish::Compress(reinterpret_cast<uint8_t*>(blkIn[3][0]), blks++, squish::kDxt1GCN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -807,10 +831,10 @@ static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::
|
|||
static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, fmt("{}"), msg); }
|
||||
|
||||
bool TXTR::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
uint32_t format = rs.readUint32Big();
|
||||
uint16_t width = rs.readUint16Big();
|
||||
uint16_t height = rs.readUint16Big();
|
||||
uint32_t numMips = rs.readUint32Big();
|
||||
const uint32_t format = rs.readUint32Big();
|
||||
const uint16_t width = rs.readUint16Big();
|
||||
const uint16_t height = rs.readUint16Big();
|
||||
const uint32_t numMips = rs.readUint32Big();
|
||||
|
||||
auto fp = hecl::FopenUnique(outPath.getAbsolutePath().data(), _SYS_STR("wb"));
|
||||
if (fp == nullptr) {
|
||||
|
@ -869,11 +893,11 @@ bool TXTR::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
|||
static std::unique_ptr<uint8_t[]> ReadPalette(png_structp png, png_infop info, size_t& szOut) {
|
||||
std::unique_ptr<uint8_t[]> ret;
|
||||
png_sPLT_tp palettes;
|
||||
int paletteCount = png_get_sPLT(png, info, &palettes);
|
||||
if (paletteCount) {
|
||||
const int paletteCount = png_get_sPLT(png, info, &palettes);
|
||||
if (paletteCount != 0) {
|
||||
for (int i = 0; i < paletteCount; ++i) {
|
||||
png_sPLT_tp palette = &palettes[i];
|
||||
if (!strncmp(palette->name, "GX_", 3)) {
|
||||
const png_const_sPLT_tp palette = &palettes[i];
|
||||
if (strncmp(palette->name, "GX_", 3) == 0) {
|
||||
if (palette->nentries > 16) {
|
||||
/* This is a C8 palette */
|
||||
ret.reset(new uint8_t[4 * 257]);
|
||||
|
@ -882,7 +906,7 @@ static std::unique_ptr<uint8_t[]> ReadPalette(png_structp png, png_infop info, s
|
|||
uint8_t* cur = ret.get() + 4;
|
||||
for (int j = 0; j < 256; ++j) {
|
||||
if (j < palette->nentries) {
|
||||
png_sPLT_entryp entry = &palette->entries[j];
|
||||
const png_const_sPLT_entryp entry = &palette->entries[j];
|
||||
if (palette->depth == 16) {
|
||||
*cur++ = entry->red >> 8;
|
||||
*cur++ = entry->green >> 8;
|
||||
|
@ -909,7 +933,7 @@ static std::unique_ptr<uint8_t[]> ReadPalette(png_structp png, png_infop info, s
|
|||
uint8_t* cur = ret.get() + 4;
|
||||
for (int j = 0; j < 16; ++j) {
|
||||
if (j < palette->nentries) {
|
||||
png_sPLT_entryp entry = &palette->entries[j];
|
||||
const png_const_sPLT_entryp entry = &palette->entries[j];
|
||||
if (palette->depth == 16) {
|
||||
*cur++ = entry->red >> 8;
|
||||
*cur++ = entry->green >> 8;
|
||||
|
@ -933,9 +957,9 @@ static std::unique_ptr<uint8_t[]> ReadPalette(png_structp png, png_infop info, s
|
|||
}
|
||||
}
|
||||
} else {
|
||||
png_colorp palettes;
|
||||
png_colorp palettes2;
|
||||
int colorCount;
|
||||
if (png_get_PLTE(png, info, &palettes, &colorCount) == PNG_INFO_PLTE) {
|
||||
if (png_get_PLTE(png, info, &palettes2, &colorCount) == PNG_INFO_PLTE) {
|
||||
if (colorCount > 16) {
|
||||
/* This is a C8 palette */
|
||||
ret.reset(new uint8_t[4 * 257]);
|
||||
|
@ -944,7 +968,7 @@ static std::unique_ptr<uint8_t[]> ReadPalette(png_structp png, png_infop info, s
|
|||
uint8_t* cur = ret.get() + 4;
|
||||
for (int j = 0; j < 256; ++j) {
|
||||
if (j < colorCount) {
|
||||
png_colorp entry = &palettes[j];
|
||||
const png_const_colorp entry = &palettes2[j];
|
||||
*cur++ = entry->red;
|
||||
*cur++ = entry->green;
|
||||
*cur++ = entry->blue;
|
||||
|
@ -964,7 +988,7 @@ static std::unique_ptr<uint8_t[]> ReadPalette(png_structp png, png_infop info, s
|
|||
uint8_t* cur = ret.get() + 4;
|
||||
for (int j = 0; j < 16; ++j) {
|
||||
if (j < colorCount) {
|
||||
png_colorp entry = &palettes[j];
|
||||
const png_const_colorp entry = &palettes2[j];
|
||||
*cur++ = entry->red;
|
||||
*cur++ = entry->green;
|
||||
*cur++ = entry->blue;
|
||||
|
@ -984,11 +1008,11 @@ static std::unique_ptr<uint8_t[]> ReadPalette(png_structp png, png_infop info, s
|
|||
|
||||
static int GetNumPaletteEntriesForGCN(png_structp png, png_infop info) {
|
||||
png_sPLT_tp palettes;
|
||||
int paletteCount = png_get_sPLT(png, info, &palettes);
|
||||
if (paletteCount) {
|
||||
const int paletteCount = png_get_sPLT(png, info, &palettes);
|
||||
if (paletteCount != 0) {
|
||||
for (int i = 0; i < paletteCount; ++i) {
|
||||
png_sPLT_tp palette = &palettes[i];
|
||||
if (!strncmp(palette->name, "GX_", 3)) {
|
||||
const png_const_sPLT_tp palette = &palettes[i];
|
||||
if (strncmp(palette->name, "GX_", 3) == 0) {
|
||||
if (palette->nentries > 16) {
|
||||
/* This is a C8 palette */
|
||||
return 256;
|
||||
|
@ -996,13 +1020,12 @@ static int GetNumPaletteEntriesForGCN(png_structp png, png_infop info) {
|
|||
/* This is a C4 palette */
|
||||
return 16;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
png_colorp palettes;
|
||||
png_colorp palletes2;
|
||||
int colorCount;
|
||||
if (png_get_PLTE(png, info, &palettes, &colorCount) == PNG_INFO_PLTE) {
|
||||
if (png_get_PLTE(png, info, &palletes2, &colorCount) == PNG_INFO_PLTE) {
|
||||
if (colorCount > 16) {
|
||||
/* This is a C8 palette */
|
||||
return 256;
|
||||
|
@ -1054,10 +1077,10 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
|
||||
png_read_info(pngRead, info);
|
||||
|
||||
png_uint_32 width = png_get_image_width(pngRead, info);
|
||||
png_uint_32 height = png_get_image_height(pngRead, info);
|
||||
png_byte colorType = png_get_color_type(pngRead, info);
|
||||
png_byte bitDepth = png_get_bit_depth(pngRead, info);
|
||||
const png_uint_32 width = png_get_image_width(pngRead, info);
|
||||
const png_uint_32 height = png_get_image_height(pngRead, info);
|
||||
const png_byte colorType = png_get_color_type(pngRead, info);
|
||||
const png_byte bitDepth = png_get_bit_depth(pngRead, info);
|
||||
|
||||
if (width < 4 || height < 4) {
|
||||
Log.report(logvisor::Error, fmt("image must be 4x4 or larger"));
|
||||
|
@ -1070,18 +1093,22 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
png_text* textStruct;
|
||||
int numText;
|
||||
png_get_text(pngRead, info, &textStruct, &numText);
|
||||
for (int i = 0; i < numText; ++i)
|
||||
if (!strcmp(textStruct[i].key, "urde_nomip"))
|
||||
for (int i = 0; i < numText; ++i) {
|
||||
if (std::strcmp(textStruct[i].key, "urde_nomip") == 0) {
|
||||
mipmap = false;
|
||||
if (colorType == PNG_COLOR_TYPE_PALETTE)
|
||||
}
|
||||
}
|
||||
if (colorType == PNG_COLOR_TYPE_PALETTE) {
|
||||
mipmap = false;
|
||||
}
|
||||
|
||||
/* Compute mipmap levels */
|
||||
size_t numMips = 1;
|
||||
if (mipmap && CountBits(width) == 1 && CountBits(height) == 1) {
|
||||
size_t index = std::min(width, height);
|
||||
while (index >>= 1)
|
||||
while (index >>= 1) {
|
||||
++numMips;
|
||||
}
|
||||
}
|
||||
|
||||
if (bitDepth != 8) {
|
||||
|
@ -1149,8 +1176,8 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
if (colorType == PNG_COLOR_TYPE_RGB) {
|
||||
png_read_row(pngRead, rowBuf.get(), nullptr);
|
||||
for (unsigned i = 0; i < width; ++i) {
|
||||
size_t inbase = i * 3;
|
||||
size_t outbase = (r * width + i) * 4;
|
||||
const size_t inbase = i * 3;
|
||||
const size_t outbase = (r * width + i) * 4;
|
||||
bufOut[outbase] = rowBuf[inbase];
|
||||
bufOut[outbase + 1] = rowBuf[inbase + 1];
|
||||
bufOut[outbase + 2] = rowBuf[inbase + 2];
|
||||
|
@ -1160,9 +1187,10 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
png_read_row(pngRead, &bufOut[(r * width) * nComps], nullptr);
|
||||
if (colorType == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
for (unsigned i = 0; i < width; ++i) {
|
||||
size_t outbase = (r * width + i) * nComps;
|
||||
if (bufOut[outbase + 3] != 0 && bufOut[outbase + 3] != 255)
|
||||
const size_t outbase = (r * width + i) * nComps;
|
||||
if (bufOut[outbase + 3] != 0 && bufOut[outbase + 3] != 255) {
|
||||
doDXT1 = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1253,9 +1281,9 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
filterHeight = height;
|
||||
const uint8_t* rgbaIn = bufOut.get();
|
||||
uint8_t* blocksOut = compOut.get();
|
||||
memset(blocksOut, 0, compLen);
|
||||
std::memset(blocksOut, 0, compLen);
|
||||
for (size_t i = 0; i < numMips; ++i) {
|
||||
int thisLen = squish::GetStorageRequirements(filterWidth, filterHeight, squish::kDxt1);
|
||||
const int thisLen = squish::GetStorageRequirements(filterWidth, filterHeight, squish::kDxt1);
|
||||
EncodeCMPR(rgbaIn, blocksOut, filterWidth, filterHeight);
|
||||
rgbaIn += filterWidth * filterHeight * nComps;
|
||||
blocksOut += thisLen;
|
||||
|
@ -1269,14 +1297,15 @@ bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPat
|
|||
int filterHeight = height;
|
||||
compLen = bufLen;
|
||||
if (colorType == PNG_COLOR_TYPE_PALETTE) {
|
||||
if (nPaletteEntries == 16)
|
||||
if (nPaletteEntries == 16) {
|
||||
compLen /= 2;
|
||||
}
|
||||
compLen += 8 + nPaletteEntries * 2;
|
||||
}
|
||||
compOut.reset(new uint8_t[compLen]);
|
||||
const uint8_t* rgbaIn = bufOut.get();
|
||||
uint8_t* dataOut = compOut.get();
|
||||
memset(dataOut, 0, compLen);
|
||||
std::memset(dataOut, 0, compLen);
|
||||
for (size_t i = 0; i < numMips; ++i) {
|
||||
switch (colorType) {
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
|
@ -1367,28 +1396,32 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
|
||||
png_read_info(pngRead, info);
|
||||
|
||||
png_uint_32 width = png_get_image_width(pngRead, info);
|
||||
png_uint_32 height = png_get_image_height(pngRead, info);
|
||||
png_byte colorType = png_get_color_type(pngRead, info);
|
||||
png_byte bitDepth = png_get_bit_depth(pngRead, info);
|
||||
const png_uint_32 width = png_get_image_width(pngRead, info);
|
||||
const png_uint_32 height = png_get_image_height(pngRead, info);
|
||||
const png_byte colorType = png_get_color_type(pngRead, info);
|
||||
const png_byte bitDepth = png_get_bit_depth(pngRead, info);
|
||||
|
||||
/* Disable mipmapping if urde_nomip embedded */
|
||||
bool mipmap = true;
|
||||
png_text* textStruct;
|
||||
int numText;
|
||||
png_get_text(pngRead, info, &textStruct, &numText);
|
||||
for (int i = 0; i < numText; ++i)
|
||||
if (!strcmp(textStruct[i].key, "urde_nomip"))
|
||||
for (int i = 0; i < numText; ++i) {
|
||||
if (std::strcmp(textStruct[i].key, "urde_nomip") == 0) {
|
||||
mipmap = false;
|
||||
if (colorType == PNG_COLOR_TYPE_PALETTE)
|
||||
}
|
||||
}
|
||||
if (colorType == PNG_COLOR_TYPE_PALETTE) {
|
||||
mipmap = false;
|
||||
}
|
||||
|
||||
/* Compute mipmap levels */
|
||||
size_t numMips = 1;
|
||||
if (mipmap && CountBits(width) == 1 && CountBits(height) == 1) {
|
||||
size_t index = std::min(width, height);
|
||||
while (index >>= 1)
|
||||
while (index >>= 1) {
|
||||
++numMips;
|
||||
}
|
||||
}
|
||||
|
||||
if (bitDepth != 8) {
|
||||
|
@ -1454,7 +1487,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
switch (colorType) {
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
for (unsigned i = 0; i < width; ++i) {
|
||||
size_t outbase = (r * width + i) * 4;
|
||||
const size_t outbase = (r * width + i) * 4;
|
||||
bufOut[outbase] = rowBuf[i];
|
||||
bufOut[outbase + 1] = rowBuf[i];
|
||||
bufOut[outbase + 2] = rowBuf[i];
|
||||
|
@ -1463,8 +1496,8 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
break;
|
||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||
for (unsigned i = 0; i < width; ++i) {
|
||||
size_t inbase = i * 2;
|
||||
size_t outbase = (r * width + i) * 4;
|
||||
const size_t inbase = i * 2;
|
||||
const size_t outbase = (r * width + i) * 4;
|
||||
bufOut[outbase] = rowBuf[inbase];
|
||||
bufOut[outbase + 1] = rowBuf[inbase];
|
||||
bufOut[outbase + 2] = rowBuf[inbase];
|
||||
|
@ -1473,8 +1506,8 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
break;
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
for (unsigned i = 0; i < width; ++i) {
|
||||
size_t inbase = i * 3;
|
||||
size_t outbase = (r * width + i) * 4;
|
||||
const size_t inbase = i * 3;
|
||||
const size_t outbase = (r * width + i) * 4;
|
||||
bufOut[outbase] = rowBuf[inbase];
|
||||
bufOut[outbase + 1] = rowBuf[inbase + 1];
|
||||
bufOut[outbase + 2] = rowBuf[inbase + 2];
|
||||
|
@ -1483,8 +1516,8 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
break;
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
for (unsigned i = 0; i < width; ++i) {
|
||||
size_t inbase = i * 4;
|
||||
size_t outbase = (r * width + i) * 4;
|
||||
const size_t inbase = i * 4;
|
||||
const size_t outbase = (r * width + i) * 4;
|
||||
bufOut[outbase] = rowBuf[inbase];
|
||||
bufOut[outbase + 1] = rowBuf[inbase + 1];
|
||||
bufOut[outbase + 2] = rowBuf[inbase + 2];
|
||||
|
@ -1548,7 +1581,7 @@ bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outP
|
|||
const uint8_t* rgbaIn = bufOut.get();
|
||||
uint8_t* blocksOut = compOut.get();
|
||||
for (i = 0; i < numMips; ++i) {
|
||||
int thisLen = squish::GetStorageRequirements(filterWidth, filterHeight, compFlags);
|
||||
const int thisLen = squish::GetStorageRequirements(filterWidth, filterHeight, compFlags);
|
||||
squish::CompressImage(rgbaIn, filterWidth, filterHeight, blocksOut, compFlags);
|
||||
rgbaIn += filterWidth * filterHeight * nComps;
|
||||
blocksOut += thisLen;
|
||||
|
@ -1621,8 +1654,8 @@ static const atInt32 RetroToDol[11] {
|
|||
};
|
||||
|
||||
TXTR::Meta TXTR::GetMetaData(DataSpec::PAKEntryReadStream& rs) {
|
||||
atUint32 retroFormat = rs.readUint32Big();
|
||||
atUint32 format = RetroToDol[retroFormat];
|
||||
const atUint32 retroFormat = rs.readUint32Big();
|
||||
const atUint32 format = RetroToDol[retroFormat];
|
||||
if (format == UINT32_MAX)
|
||||
return {};
|
||||
|
||||
|
@ -1636,10 +1669,10 @@ TXTR::Meta TXTR::GetMetaData(DataSpec::PAKEntryReadStream& rs) {
|
|||
meta.hasPalette = true;
|
||||
PaletteMeta& palMeta = meta.palette;
|
||||
palMeta.format = rs.readUint32Big();
|
||||
atUint16 palWidth = rs.readUint16Big();
|
||||
atUint16 palHeight = rs.readUint16Big();
|
||||
const atUint16 palWidth = rs.readUint16Big();
|
||||
const atUint16 palHeight = rs.readUint16Big();
|
||||
palMeta.elementCount = palWidth * palHeight;
|
||||
atUint32 palSize = atUint32(palWidth * palHeight * 2);
|
||||
const atUint32 palSize = atUint32(palWidth * palHeight * 2);
|
||||
if (format == 8)
|
||||
textureSize /= 2;
|
||||
std::unique_ptr<u8[]> palData(new u8[palSize]);
|
||||
|
|
|
@ -1,645 +1,13 @@
|
|||
#include "DataSpec/DNACommon/WPSC.hpp"
|
||||
|
||||
#include "DataSpec/DNACommon/PAK.hpp"
|
||||
|
||||
#include <logvisor/logvisor.hpp>
|
||||
|
||||
namespace DataSpec::DNAParticle {
|
||||
|
||||
template <class IDType>
|
||||
void WPSM<IDType>::_read(athena::io::YAMLDocReader& r) {
|
||||
for (const auto& elem : r.getCurNode()->m_mapChildren) {
|
||||
if (elem.first.size() < 4) {
|
||||
LogModule.report(logvisor::Warning, fmt("short FourCC in element '{}'"), elem.first);
|
||||
continue;
|
||||
}
|
||||
template struct PPImpl<_WPSM<UniqueID32>>;
|
||||
template struct PPImpl<_WPSM<UniqueID64>>;
|
||||
|
||||
if (auto rec = r.enterSubRecord(elem.first.c_str())) {
|
||||
switch (*reinterpret_cast<const uint32_t*>(elem.first.data())) {
|
||||
case SBIG('IORN'):
|
||||
x0_IORN.read(r);
|
||||
break;
|
||||
case SBIG('IVEC'):
|
||||
x4_IVEC.read(r);
|
||||
break;
|
||||
case SBIG('PSOV'):
|
||||
x8_PSOV.read(r);
|
||||
break;
|
||||
case SBIG('PSVM'):
|
||||
xc_PSVM.read(r);
|
||||
break;
|
||||
case SBIG('VMD2'):
|
||||
x10_VMD2.read(r);
|
||||
break;
|
||||
case SBIG('PSLT'):
|
||||
x14_PSLT.read(r);
|
||||
break;
|
||||
case SBIG('PSCL'):
|
||||
x18_PSCL.read(r);
|
||||
break;
|
||||
case SBIG('PCOL'):
|
||||
x1c_PCOL.read(r);
|
||||
break;
|
||||
case SBIG('POFS'):
|
||||
x20_POFS.read(r);
|
||||
break;
|
||||
case SBIG('OFST'):
|
||||
x24_OFST.read(r);
|
||||
break;
|
||||
case SBIG('APSO'):
|
||||
x28_APSO.read(r);
|
||||
break;
|
||||
case SBIG('HOMG'):
|
||||
x29_HOMG.read(r);
|
||||
break;
|
||||
case SBIG('AP11'):
|
||||
x2a_AP11.read(r);
|
||||
break;
|
||||
case SBIG('AP21'):
|
||||
x2b_AP21.read(r);
|
||||
break;
|
||||
case SBIG('AS11'):
|
||||
x2c_AS11.read(r);
|
||||
break;
|
||||
case SBIG('AS12'):
|
||||
x2d_AS12.read(r);
|
||||
break;
|
||||
case SBIG('AS13'):
|
||||
x2e_AS13.read(r);
|
||||
break;
|
||||
case SBIG('TRAT'):
|
||||
x30_TRAT.read(r);
|
||||
break;
|
||||
case SBIG('APSM'):
|
||||
x34_APSM.read(r);
|
||||
break;
|
||||
case SBIG('APS2'):
|
||||
x44_APS2.read(r);
|
||||
break;
|
||||
case SBIG('ASW1'):
|
||||
x54_ASW1.read(r);
|
||||
break;
|
||||
case SBIG('ASW2'):
|
||||
x64_ASW2.read(r);
|
||||
break;
|
||||
case SBIG('ASW3'):
|
||||
x74_ASW3.read(r);
|
||||
break;
|
||||
case SBIG('OHEF'):
|
||||
x84_OHEF.read(r);
|
||||
break;
|
||||
case SBIG('COLR'):
|
||||
x94_COLR.read(r);
|
||||
break;
|
||||
case SBIG('EWTR'):
|
||||
xa4_EWTR.read(r);
|
||||
break;
|
||||
case SBIG('LWTR'):
|
||||
xa5_LWTR.read(r);
|
||||
break;
|
||||
case SBIG('SWTR'):
|
||||
xa6_SWTR.read(r);
|
||||
break;
|
||||
case SBIG('PJFX'):
|
||||
xa8_PJFX = r.readUint32();
|
||||
break;
|
||||
case SBIG('RNGE'):
|
||||
xac_RNGE.read(r);
|
||||
break;
|
||||
case SBIG('FOFF'):
|
||||
xb0_FOFF.read(r);
|
||||
break;
|
||||
case SBIG('FC60'):
|
||||
xunk_FC60.read(r);
|
||||
break;
|
||||
case SBIG('SPS1'):
|
||||
xunk_SPS1.read(r);
|
||||
break;
|
||||
case SBIG('SPS2'):
|
||||
xunk_SPS2.read(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void WPSM<IDType>::_write(athena::io::YAMLDocWriter& w) const {
|
||||
if (x0_IORN)
|
||||
if (auto rec = w.enterSubRecord("IORN"))
|
||||
x0_IORN.write(w);
|
||||
if (x4_IVEC)
|
||||
if (auto rec = w.enterSubRecord("IVEC"))
|
||||
x4_IVEC.write(w);
|
||||
if (x8_PSOV)
|
||||
if (auto rec = w.enterSubRecord("PSOV"))
|
||||
x8_PSOV.write(w);
|
||||
if (xc_PSVM)
|
||||
if (auto rec = w.enterSubRecord("PSVM"))
|
||||
xc_PSVM.write(w);
|
||||
if (x10_VMD2)
|
||||
if (auto rec = w.enterSubRecord("VMD2"))
|
||||
x10_VMD2.write(w);
|
||||
if (x14_PSLT)
|
||||
if (auto rec = w.enterSubRecord("PSLT"))
|
||||
x14_PSLT.write(w);
|
||||
if (x18_PSCL)
|
||||
if (auto rec = w.enterSubRecord("PSCL"))
|
||||
x18_PSCL.write(w);
|
||||
if (x1c_PCOL)
|
||||
if (auto rec = w.enterSubRecord("PCOL"))
|
||||
x1c_PCOL.write(w);
|
||||
if (x20_POFS)
|
||||
if (auto rec = w.enterSubRecord("POFS"))
|
||||
x20_POFS.write(w);
|
||||
if (x24_OFST)
|
||||
if (auto rec = w.enterSubRecord("OFST"))
|
||||
x24_OFST.write(w);
|
||||
if (x28_APSO)
|
||||
if (auto rec = w.enterSubRecord("APSO"))
|
||||
x28_APSO.write(w);
|
||||
if (x29_HOMG)
|
||||
if (auto rec = w.enterSubRecord("HOMG"))
|
||||
x29_HOMG.write(w);
|
||||
if (x2a_AP11)
|
||||
if (auto rec = w.enterSubRecord("AP11"))
|
||||
x2a_AP11.write(w);
|
||||
if (x2b_AP21)
|
||||
if (auto rec = w.enterSubRecord("AP21"))
|
||||
x2b_AP21.write(w);
|
||||
if (x2c_AS11)
|
||||
if (auto rec = w.enterSubRecord("AS11"))
|
||||
x2c_AS11.write(w);
|
||||
if (x2d_AS12)
|
||||
if (auto rec = w.enterSubRecord("AS12"))
|
||||
x2d_AS12.write(w);
|
||||
if (x2e_AS13)
|
||||
if (auto rec = w.enterSubRecord("AS13"))
|
||||
x2e_AS13.write(w);
|
||||
if (x30_TRAT)
|
||||
if (auto rec = w.enterSubRecord("TRAT"))
|
||||
x30_TRAT.write(w);
|
||||
if (x34_APSM)
|
||||
if (auto rec = w.enterSubRecord("APSM"))
|
||||
x34_APSM.write(w);
|
||||
if (x44_APS2)
|
||||
if (auto rec = w.enterSubRecord("APS2"))
|
||||
x44_APS2.write(w);
|
||||
if (x54_ASW1)
|
||||
if (auto rec = w.enterSubRecord("ASW1"))
|
||||
x54_ASW1.write(w);
|
||||
if (x64_ASW2)
|
||||
if (auto rec = w.enterSubRecord("ASW2"))
|
||||
x64_ASW2.write(w);
|
||||
if (x74_ASW3)
|
||||
if (auto rec = w.enterSubRecord("ASW3"))
|
||||
x74_ASW3.write(w);
|
||||
if (x84_OHEF)
|
||||
if (auto rec = w.enterSubRecord("OHEF"))
|
||||
x84_OHEF.write(w);
|
||||
if (x94_COLR)
|
||||
if (auto rec = w.enterSubRecord("COLR"))
|
||||
x94_COLR.write(w);
|
||||
if (!xa4_EWTR)
|
||||
if (auto rec = w.enterSubRecord("EWTR"))
|
||||
xa4_EWTR.write(w);
|
||||
if (!xa5_LWTR)
|
||||
if (auto rec = w.enterSubRecord("LWTR"))
|
||||
xa5_LWTR.write(w);
|
||||
if (!xa6_SWTR)
|
||||
if (auto rec = w.enterSubRecord("SWTR"))
|
||||
xa6_SWTR.write(w);
|
||||
if (xa8_PJFX != UINT32_MAX)
|
||||
w.writeUint32("PJFX", xa8_PJFX);
|
||||
if (xac_RNGE)
|
||||
if (auto rec = w.enterSubRecord("RNGE"))
|
||||
xac_RNGE.write(w);
|
||||
if (xb0_FOFF)
|
||||
if (auto rec = w.enterSubRecord("FOFF"))
|
||||
xb0_FOFF.write(w);
|
||||
if (xunk_FC60)
|
||||
if (auto rec = w.enterSubRecord("FC60"))
|
||||
xunk_FC60.write(w);
|
||||
if (xunk_SPS1)
|
||||
if (auto rec = w.enterSubRecord("SPS1"))
|
||||
xunk_SPS1.write(w);
|
||||
if (xunk_SPS1)
|
||||
if (auto rec = w.enterSubRecord("SPS2"))
|
||||
xunk_SPS2.write(w);
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void WPSM<IDType>::_binarySize(size_t& __isz) const {
|
||||
__isz += 4;
|
||||
if (x0_IORN) {
|
||||
__isz += 4;
|
||||
x0_IORN.binarySize(__isz);
|
||||
}
|
||||
if (x4_IVEC) {
|
||||
__isz += 4;
|
||||
x4_IVEC.binarySize(__isz);
|
||||
}
|
||||
if (x8_PSOV) {
|
||||
__isz += 4;
|
||||
x8_PSOV.binarySize(__isz);
|
||||
}
|
||||
if (xc_PSVM) {
|
||||
__isz += 4;
|
||||
xc_PSVM.binarySize(__isz);
|
||||
}
|
||||
if (x10_VMD2) {
|
||||
__isz += 4;
|
||||
x10_VMD2.binarySize(__isz);
|
||||
}
|
||||
if (x14_PSLT) {
|
||||
__isz += 4;
|
||||
x14_PSLT.binarySize(__isz);
|
||||
}
|
||||
if (x18_PSCL) {
|
||||
__isz += 4;
|
||||
x18_PSCL.binarySize(__isz);
|
||||
}
|
||||
if (x1c_PCOL) {
|
||||
__isz += 4;
|
||||
x1c_PCOL.binarySize(__isz);
|
||||
}
|
||||
if (x20_POFS) {
|
||||
__isz += 4;
|
||||
x20_POFS.binarySize(__isz);
|
||||
}
|
||||
if (x24_OFST) {
|
||||
__isz += 4;
|
||||
x24_OFST.binarySize(__isz);
|
||||
}
|
||||
if (x28_APSO) {
|
||||
__isz += 4;
|
||||
x28_APSO.binarySize(__isz);
|
||||
}
|
||||
if (x29_HOMG) {
|
||||
__isz += 4;
|
||||
x29_HOMG.binarySize(__isz);
|
||||
}
|
||||
if (x2a_AP11) {
|
||||
__isz += 4;
|
||||
x2a_AP11.binarySize(__isz);
|
||||
}
|
||||
if (x2b_AP21) {
|
||||
__isz += 4;
|
||||
x2b_AP21.binarySize(__isz);
|
||||
}
|
||||
if (x2c_AS11) {
|
||||
__isz += 4;
|
||||
x2c_AS11.binarySize(__isz);
|
||||
}
|
||||
if (x2d_AS12) {
|
||||
__isz += 4;
|
||||
x2d_AS12.binarySize(__isz);
|
||||
}
|
||||
if (x2e_AS13) {
|
||||
__isz += 4;
|
||||
x2e_AS13.binarySize(__isz);
|
||||
}
|
||||
if (x30_TRAT) {
|
||||
__isz += 4;
|
||||
x30_TRAT.binarySize(__isz);
|
||||
}
|
||||
if (x34_APSM) {
|
||||
__isz += 4;
|
||||
x34_APSM.binarySize(__isz);
|
||||
}
|
||||
if (x44_APS2) {
|
||||
__isz += 4;
|
||||
x44_APS2.binarySize(__isz);
|
||||
}
|
||||
if (x54_ASW1) {
|
||||
__isz += 4;
|
||||
x54_ASW1.binarySize(__isz);
|
||||
}
|
||||
if (x64_ASW2) {
|
||||
__isz += 4;
|
||||
x64_ASW2.binarySize(__isz);
|
||||
}
|
||||
if (x74_ASW3) {
|
||||
__isz += 4;
|
||||
x74_ASW3.binarySize(__isz);
|
||||
}
|
||||
if (x84_OHEF) {
|
||||
__isz += 4;
|
||||
x84_OHEF.binarySize(__isz);
|
||||
}
|
||||
if (x94_COLR) {
|
||||
__isz += 4;
|
||||
x94_COLR.binarySize(__isz);
|
||||
}
|
||||
if (!xa4_EWTR) {
|
||||
__isz += 4;
|
||||
xa4_EWTR.binarySize(__isz);
|
||||
}
|
||||
if (!xa5_LWTR) {
|
||||
__isz += 4;
|
||||
xa5_LWTR.binarySize(__isz);
|
||||
}
|
||||
if (!xa6_SWTR) {
|
||||
__isz += 4;
|
||||
xa6_SWTR.binarySize(__isz);
|
||||
}
|
||||
if (xa8_PJFX != UINT32_MAX)
|
||||
__isz += 12;
|
||||
if (xac_RNGE) {
|
||||
__isz += 4;
|
||||
xac_RNGE.binarySize(__isz);
|
||||
}
|
||||
if (xb0_FOFF) {
|
||||
__isz += 4;
|
||||
xb0_FOFF.binarySize(__isz);
|
||||
}
|
||||
if (xunk_FC60) {
|
||||
__isz += 4;
|
||||
xunk_FC60.binarySize(__isz);
|
||||
}
|
||||
if (xunk_SPS1) {
|
||||
__isz += 4;
|
||||
xunk_SPS1.binarySize(__isz);
|
||||
}
|
||||
if (xunk_SPS2) {
|
||||
__isz += 4;
|
||||
xunk_SPS2.binarySize(__isz);
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void WPSM<IDType>::_read(athena::io::IStreamReader& r) {
|
||||
DNAFourCC clsId;
|
||||
clsId.read(r);
|
||||
if (clsId != SBIG('WPSM')) {
|
||||
LogModule.report(logvisor::Warning, fmt("non WPSM provided to WPSM parser"));
|
||||
return;
|
||||
}
|
||||
clsId.read(r);
|
||||
while (clsId != SBIG('_END')) {
|
||||
switch (clsId.toUint32()) {
|
||||
case SBIG('IORN'):
|
||||
x0_IORN.read(r);
|
||||
break;
|
||||
case SBIG('IVEC'):
|
||||
x4_IVEC.read(r);
|
||||
break;
|
||||
case SBIG('PSOV'):
|
||||
x8_PSOV.read(r);
|
||||
break;
|
||||
case SBIG('PSVM'):
|
||||
xc_PSVM.read(r);
|
||||
break;
|
||||
case SBIG('VMD2'):
|
||||
x10_VMD2.read(r);
|
||||
break;
|
||||
case SBIG('PSLT'):
|
||||
x14_PSLT.read(r);
|
||||
break;
|
||||
case SBIG('PSCL'):
|
||||
x18_PSCL.read(r);
|
||||
break;
|
||||
case SBIG('PCOL'):
|
||||
x1c_PCOL.read(r);
|
||||
break;
|
||||
case SBIG('POFS'):
|
||||
x20_POFS.read(r);
|
||||
break;
|
||||
case SBIG('OFST'):
|
||||
x24_OFST.read(r);
|
||||
break;
|
||||
case SBIG('APSO'):
|
||||
r.readUint32();
|
||||
x28_APSO = r.readBool();
|
||||
break;
|
||||
case SBIG('HOMG'):
|
||||
x29_HOMG.read(r);
|
||||
break;
|
||||
case SBIG('AP11'):
|
||||
x2a_AP11.read(r);
|
||||
break;
|
||||
case SBIG('AP21'):
|
||||
x2b_AP21.read(r);
|
||||
break;
|
||||
case SBIG('AS11'):
|
||||
x2c_AS11.read(r);
|
||||
break;
|
||||
case SBIG('AS12'):
|
||||
x2d_AS12.read(r);
|
||||
break;
|
||||
case SBIG('AS13'):
|
||||
x2e_AS13.read(r);
|
||||
break;
|
||||
case SBIG('TRAT'):
|
||||
x30_TRAT.read(r);
|
||||
break;
|
||||
case SBIG('APSM'):
|
||||
x34_APSM.read(r);
|
||||
break;
|
||||
case SBIG('APS2'):
|
||||
x44_APS2.read(r);
|
||||
break;
|
||||
case SBIG('ASW1'):
|
||||
x54_ASW1.read(r);
|
||||
break;
|
||||
case SBIG('ASW2'):
|
||||
x64_ASW2.read(r);
|
||||
break;
|
||||
case SBIG('ASW3'):
|
||||
x74_ASW3.read(r);
|
||||
break;
|
||||
case SBIG('OHEF'):
|
||||
x84_OHEF.read(r);
|
||||
break;
|
||||
case SBIG('COLR'):
|
||||
x94_COLR.read(r);
|
||||
break;
|
||||
case SBIG('EWTR'):
|
||||
r.readUint32();
|
||||
xa4_EWTR = r.readBool();
|
||||
break;
|
||||
case SBIG('LWTR'):
|
||||
r.readUint32();
|
||||
xa5_LWTR = r.readBool();
|
||||
break;
|
||||
case SBIG('SWTR'):
|
||||
r.readUint32();
|
||||
xa6_SWTR = r.readBool();
|
||||
break;
|
||||
case SBIG('PJFX'): {
|
||||
uint32_t fcc;
|
||||
r.readBytesToBuf(&fcc, 4);
|
||||
if (fcc != SBIG('NONE'))
|
||||
xa8_PJFX = r.readUint32Big();
|
||||
} break;
|
||||
case SBIG('RNGE'):
|
||||
xac_RNGE.read(r);
|
||||
break;
|
||||
case SBIG('FOFF'):
|
||||
xb0_FOFF.read(r);
|
||||
break;
|
||||
case SBIG('FC60'):
|
||||
xunk_FC60.read(r);
|
||||
break;
|
||||
case SBIG('SPS1'):
|
||||
xunk_SPS1.read(r);
|
||||
break;
|
||||
case SBIG('SPS2'):
|
||||
xunk_SPS2.read(r);
|
||||
break;
|
||||
default:
|
||||
LogModule.report(logvisor::Fatal, fmt("Unknown WPSM class {} @{}"), clsId, r.position());
|
||||
break;
|
||||
}
|
||||
clsId.read(r);
|
||||
}
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void WPSM<IDType>::_write(athena::io::IStreamWriter& w) const {
|
||||
w.writeBytes("WPSM", 4);
|
||||
if (x0_IORN) {
|
||||
w.writeBytes("IORN", 4);
|
||||
x0_IORN.write(w);
|
||||
}
|
||||
if (x4_IVEC) {
|
||||
w.writeBytes("IVEC", 4);
|
||||
x4_IVEC.write(w);
|
||||
}
|
||||
if (x8_PSOV) {
|
||||
w.writeBytes("PSOV", 4);
|
||||
x8_PSOV.write(w);
|
||||
}
|
||||
if (xc_PSVM) {
|
||||
w.writeBytes("PSVM", 4);
|
||||
xc_PSVM.write(w);
|
||||
}
|
||||
if (x10_VMD2) {
|
||||
w.writeBytes("VMD2", 4);
|
||||
x10_VMD2.write(w);
|
||||
}
|
||||
if (x14_PSLT) {
|
||||
w.writeBytes("PSLT", 4);
|
||||
x14_PSLT.write(w);
|
||||
}
|
||||
if (x18_PSCL) {
|
||||
w.writeBytes("PSCL", 4);
|
||||
x18_PSCL.write(w);
|
||||
}
|
||||
if (x1c_PCOL) {
|
||||
w.writeBytes("PCOL", 4);
|
||||
x1c_PCOL.write(w);
|
||||
}
|
||||
if (x20_POFS) {
|
||||
w.writeBytes("POFS", 4);
|
||||
x20_POFS.write(w);
|
||||
}
|
||||
if (x24_OFST) {
|
||||
w.writeBytes("OFST", 4);
|
||||
x24_OFST.write(w);
|
||||
}
|
||||
if (x28_APSO) {
|
||||
w.writeBytes("APSO", 4);
|
||||
x28_APSO.write(w);
|
||||
}
|
||||
if (x29_HOMG) {
|
||||
w.writeBytes("HOMG", 4);
|
||||
x29_HOMG.write(w);
|
||||
}
|
||||
if (x2a_AP11) {
|
||||
w.writeBytes("AP11", 4);
|
||||
x2a_AP11.write(w);
|
||||
}
|
||||
if (x2b_AP21) {
|
||||
w.writeBytes("AP21", 4);
|
||||
x2b_AP21.write(w);
|
||||
}
|
||||
if (x2c_AS11) {
|
||||
w.writeBytes("AS11", 4);
|
||||
x2c_AS11.write(w);
|
||||
}
|
||||
if (x2d_AS12) {
|
||||
w.writeBytes("AS12", 4);
|
||||
x2d_AS12.write(w);
|
||||
}
|
||||
if (x2e_AS13) {
|
||||
w.writeBytes("AS13", 4);
|
||||
x2e_AS13.write(w);
|
||||
}
|
||||
if (x30_TRAT) {
|
||||
w.writeBytes("TRAT", 4);
|
||||
x30_TRAT.write(w);
|
||||
}
|
||||
if (x34_APSM) {
|
||||
w.writeBytes("APSM", 4);
|
||||
x34_APSM.write(w);
|
||||
}
|
||||
if (x44_APS2) {
|
||||
w.writeBytes("APS2", 4);
|
||||
x44_APS2.write(w);
|
||||
}
|
||||
if (x54_ASW1) {
|
||||
w.writeBytes("ASW1", 4);
|
||||
x54_ASW1.write(w);
|
||||
}
|
||||
if (x64_ASW2) {
|
||||
w.writeBytes("ASW2", 4);
|
||||
x64_ASW2.write(w);
|
||||
}
|
||||
if (x74_ASW3) {
|
||||
w.writeBytes("ASW3", 4);
|
||||
x74_ASW3.write(w);
|
||||
}
|
||||
if (x84_OHEF) {
|
||||
w.writeBytes("OHEF", 4);
|
||||
x84_OHEF.write(w);
|
||||
}
|
||||
if (x94_COLR) {
|
||||
w.writeBytes("COLR", 4);
|
||||
x94_COLR.write(w);
|
||||
}
|
||||
if (!xa4_EWTR) {
|
||||
w.writeBytes("EWTR", 4);
|
||||
xa4_EWTR.write(w);
|
||||
}
|
||||
if (!xa5_LWTR) {
|
||||
w.writeBytes("LWTR", 4);
|
||||
xa5_LWTR.write(w);
|
||||
}
|
||||
if (!xa6_SWTR) {
|
||||
w.writeBytes("SWTR", 4);
|
||||
xa6_SWTR.write(w);
|
||||
}
|
||||
if (xa8_PJFX != UINT32_MAX) {
|
||||
w.writeBytes("PJFXCNST", 8);
|
||||
w.writeUint32(xa8_PJFX);
|
||||
}
|
||||
if (xac_RNGE) {
|
||||
w.writeBytes("RNGE", 4);
|
||||
xac_RNGE.write(w);
|
||||
}
|
||||
if (xb0_FOFF) {
|
||||
w.writeBytes("FOFF", 4);
|
||||
xb0_FOFF.write(w);
|
||||
}
|
||||
if (xunk_FC60) {
|
||||
w.writeBytes("FC60", 4);
|
||||
xunk_FC60.write(w);
|
||||
}
|
||||
if (xunk_SPS1) {
|
||||
w.writeBytes("SPS1", 4);
|
||||
xunk_SPS1.write(w);
|
||||
}
|
||||
if (xunk_SPS2) {
|
||||
w.writeBytes("SPS2", 4);
|
||||
xunk_SPS2.write(w);
|
||||
}
|
||||
|
||||
w.writeBytes("_END", 4);
|
||||
}
|
||||
|
||||
AT_SUBSPECIALIZE_DNA_YAML(WPSM<UniqueID32>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(WPSM<UniqueID64>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_WPSM<UniqueID32>>)
|
||||
AT_SUBSPECIALIZE_DNA_YAML(PPImpl<_WPSM<UniqueID64>>)
|
||||
|
||||
template <>
|
||||
std::string_view WPSM<UniqueID32>::DNAType() {
|
||||
|
@ -651,20 +19,6 @@ std::string_view WPSM<UniqueID64>::DNAType() {
|
|||
return "WPSM<UniqueID64>"sv;
|
||||
}
|
||||
|
||||
template <class IDType>
|
||||
void WPSM<IDType>::gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const {
|
||||
g_curSpec->flattenDependencies(x34_APSM.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x44_APS2.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x54_ASW1.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x64_ASW2.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x74_ASW3.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x84_OHEF.id, pathsOut);
|
||||
g_curSpec->flattenDependencies(x94_COLR.id, pathsOut);
|
||||
}
|
||||
|
||||
template struct WPSM<UniqueID32>;
|
||||
template struct WPSM<UniqueID64>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractWPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) {
|
||||
athena::io::FileWriter writer(outPath.getAbsolutePath());
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef ENTRY
|
||||
#define ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef INT_ENTRY
|
||||
#define INT_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef U32_ENTRY
|
||||
#define U32_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef REAL_ENTRY
|
||||
#define REAL_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef VECTOR_ENTRY
|
||||
#define VECTOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef MOD_VECTOR_ENTRY
|
||||
#define MOD_VECTOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef COLOR_ENTRY
|
||||
#define COLOR_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef UV_ENTRY
|
||||
#define UV_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef RES_ENTRY
|
||||
#define RES_ENTRY(name, identifier) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
#ifndef BOOL_ENTRY
|
||||
#define BOOL_ENTRY(name, identifier, def) ENTRY(name, identifier)
|
||||
#endif
|
||||
|
||||
VECTOR_ENTRY('IORN', x0_IORN)
|
||||
VECTOR_ENTRY('IVEC', x4_IVEC)
|
||||
VECTOR_ENTRY('PSOV', x8_PSOV)
|
||||
MOD_VECTOR_ENTRY('PSVM', xc_PSVM)
|
||||
INT_ENTRY('PSLT', x14_PSLT)
|
||||
VECTOR_ENTRY('PSCL', x18_PSCL)
|
||||
COLOR_ENTRY('PCOL', x1c_PCOL)
|
||||
VECTOR_ENTRY('POFS', x20_POFS)
|
||||
VECTOR_ENTRY('OFST', x24_OFST)
|
||||
|
||||
REAL_ENTRY('TRAT', x30_TRAT)
|
||||
RES_ENTRY('APSM', x34_APSM)
|
||||
RES_ENTRY('APS2', x44_APS2)
|
||||
RES_ENTRY('ASW1', x54_ASW1)
|
||||
RES_ENTRY('ASW2', x64_ASW2)
|
||||
RES_ENTRY('ASW3', x74_ASW3)
|
||||
RES_ENTRY('OHEF', x84_OHEF)
|
||||
RES_ENTRY('COLR', x94_COLR)
|
||||
U32_ENTRY('PJFX', xa8_PJFX)
|
||||
REAL_ENTRY('RNGE', xac_RNGE)
|
||||
REAL_ENTRY('FOFF', xb0_FOFF)
|
||||
|
||||
BOOL_ENTRY('VMD2', x10_VMD2, false)
|
||||
BOOL_ENTRY('APSO', x28_APSO, false)
|
||||
BOOL_ENTRY('HOMG', x29_HOMG, false)
|
||||
BOOL_ENTRY('AP11', x2a_AP11, false)
|
||||
BOOL_ENTRY('AP21', x2b_AP21, false)
|
||||
BOOL_ENTRY('AS11', x2c_AS11, false)
|
||||
BOOL_ENTRY('AS12', x2d_AS12, false)
|
||||
BOOL_ENTRY('AS13', x2e_AS13, false)
|
||||
BOOL_ENTRY('EWTR', xa4_EWTR, true)
|
||||
BOOL_ENTRY('LWTR', xa5_LWTR, true)
|
||||
BOOL_ENTRY('SWTR', xa6_SWTR, true)
|
||||
BOOL_ENTRY('FC60', xunk_FC60, false)
|
||||
BOOL_ENTRY('SPS1', xunk_SPS1, false)
|
||||
BOOL_ENTRY('SPS2', xunk_SPS2, false)
|
||||
|
||||
#undef ENTRY
|
||||
#undef INT_ENTRY
|
||||
#undef U32_ENTRY
|
||||
#undef REAL_ENTRY
|
||||
#undef VECTOR_ENTRY
|
||||
#undef MOD_VECTOR_ENTRY
|
||||
#undef COLOR_ENTRY
|
||||
#undef UV_ENTRY
|
||||
#undef RES_ENTRY
|
||||
#undef BOOL_ENTRY
|
|
@ -12,53 +12,40 @@ class ProjectPath;
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
WPSM() {
|
||||
xa4_EWTR = true;
|
||||
xa5_LWTR = true;
|
||||
xa6_SWTR = true;
|
||||
template <class IDType>
|
||||
struct _WPSM {
|
||||
static constexpr ParticleType Type = ParticleType::WPSM;
|
||||
|
||||
#define INT_ENTRY(name, identifier) IntElementFactory identifier;
|
||||
#define U32_ENTRY(name, identifier) uint32_t identifier = ~0;
|
||||
#define REAL_ENTRY(name, identifier) RealElementFactory identifier;
|
||||
#define VECTOR_ENTRY(name, identifier) VectorElementFactory identifier;
|
||||
#define MOD_VECTOR_ENTRY(name, identifier) ModVectorElementFactory identifier;
|
||||
#define COLOR_ENTRY(name, identifier) ColorElementFactory identifier;
|
||||
#define UV_ENTRY(name, identifier) UVElementFactory<IDType> identifier;
|
||||
#define RES_ENTRY(name, identifier) ChildResourceFactory<IDType> identifier;
|
||||
#define BOOL_ENTRY(name, identifier, def) bool identifier = def;
|
||||
#include "WPSC.def"
|
||||
|
||||
template<typename _Func>
|
||||
void constexpr Enumerate(_Func f) {
|
||||
#define ENTRY(name, identifier) f(FOURCC(name), identifier);
|
||||
#define BOOL_ENTRY(name, identifier, def) f(FOURCC(name), identifier, def);
|
||||
#include "WPSC.def"
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>&) const;
|
||||
template<typename _Func>
|
||||
bool constexpr Lookup(FourCC fcc, _Func f) {
|
||||
switch (fcc.toUint32()) {
|
||||
#define ENTRY(name, identifier) case SBIG(name): f(identifier); return true;
|
||||
#include "WPSC.def"
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
template <class IDType>
|
||||
using WPSM = PPImpl<_WPSM<IDType>>;
|
||||
|
||||
template <class IDType>
|
||||
bool ExtractWPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath);
|
||||
|
|
|
@ -611,30 +611,30 @@ std::string_view ANCS::CharacterSet::CharacterInfo::DNAType() {
|
|||
|
||||
template <>
|
||||
void ANCS::AnimationSet::MetaAnimFactory::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
|
||||
IMetaAnim::Type type(IMetaAnim::Type(reader.readUint32Big()));
|
||||
const auto type = IMetaAnim::Type(reader.readUint32Big());
|
||||
switch (type) {
|
||||
case IMetaAnim::Type::Primitive:
|
||||
m_anim.reset(new struct MetaAnimPrimitive);
|
||||
m_anim = std::make_unique<MetaAnimPrimitive>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case IMetaAnim::Type::Blend:
|
||||
m_anim.reset(new struct MetaAnimBlend);
|
||||
m_anim = std::make_unique<MetaAnimBlend>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case IMetaAnim::Type::PhaseBlend:
|
||||
m_anim.reset(new struct MetaAnimPhaseBlend);
|
||||
m_anim = std::make_unique<MetaAnimPhaseBlend>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case IMetaAnim::Type::Random:
|
||||
m_anim.reset(new struct MetaAnimRandom);
|
||||
m_anim = std::make_unique<MetaAnimRandom>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case IMetaAnim::Type::Sequence:
|
||||
m_anim.reset(new struct MetaAnimSequence);
|
||||
m_anim = std::make_unique<MetaAnimSequence>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
default:
|
||||
m_anim.reset(nullptr);
|
||||
m_anim.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -660,22 +660,22 @@ void ANCS::AnimationSet::MetaAnimFactory::Enumerate<BigDNA::ReadYaml>(athena::io
|
|||
std::string type = reader.readString("type");
|
||||
std::transform(type.begin(), type.end(), type.begin(), tolower);
|
||||
if (type == "primitive") {
|
||||
m_anim.reset(new struct MetaAnimPrimitive);
|
||||
m_anim = std::make_unique<MetaAnimPrimitive>();
|
||||
m_anim->read(reader);
|
||||
} else if (type == "blend") {
|
||||
m_anim.reset(new struct MetaAnimBlend);
|
||||
m_anim = std::make_unique<MetaAnimBlend>();
|
||||
m_anim->read(reader);
|
||||
} else if (type == "phaseblend") {
|
||||
m_anim.reset(new struct MetaAnimPhaseBlend);
|
||||
m_anim = std::make_unique<MetaAnimPhaseBlend>();
|
||||
m_anim->read(reader);
|
||||
} else if (type == "random") {
|
||||
m_anim.reset(new struct MetaAnimRandom);
|
||||
m_anim = std::make_unique<MetaAnimRandom>();
|
||||
m_anim->read(reader);
|
||||
} else if (type == "sequence") {
|
||||
m_anim.reset(new struct MetaAnimSequence);
|
||||
m_anim = std::make_unique<MetaAnimSequence>();
|
||||
m_anim->read(reader);
|
||||
} else {
|
||||
m_anim.reset(nullptr);
|
||||
m_anim.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -696,20 +696,20 @@ void ANCS::AnimationSet::MetaTransFactory::Enumerate<BigDNA::Read>(athena::io::I
|
|||
IMetaTrans::Type type(IMetaTrans::Type(reader.readUint32Big()));
|
||||
switch (type) {
|
||||
case IMetaTrans::Type::MetaAnim:
|
||||
m_trans.reset(new struct MetaTransMetaAnim);
|
||||
m_trans = std::make_unique<MetaTransMetaAnim>();
|
||||
m_trans->read(reader);
|
||||
break;
|
||||
case IMetaTrans::Type::Trans:
|
||||
m_trans.reset(new struct MetaTransTrans);
|
||||
m_trans = std::make_unique<MetaTransTrans>();
|
||||
m_trans->read(reader);
|
||||
break;
|
||||
case IMetaTrans::Type::PhaseTrans:
|
||||
m_trans.reset(new struct MetaTransPhaseTrans);
|
||||
m_trans = std::make_unique<MetaTransPhaseTrans>();
|
||||
m_trans->read(reader);
|
||||
break;
|
||||
case IMetaTrans::Type::NoTrans:
|
||||
default:
|
||||
m_trans.reset(nullptr);
|
||||
m_trans.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -737,16 +737,16 @@ void ANCS::AnimationSet::MetaTransFactory::Enumerate<BigDNA::ReadYaml>(athena::i
|
|||
std::string type = reader.readString("type");
|
||||
std::transform(type.begin(), type.end(), type.begin(), tolower);
|
||||
if (type == "metaanim") {
|
||||
m_trans.reset(new struct MetaTransMetaAnim);
|
||||
m_trans = std::make_unique<MetaTransMetaAnim>();
|
||||
m_trans->read(reader);
|
||||
} else if (type == "trans") {
|
||||
m_trans.reset(new struct MetaTransTrans);
|
||||
m_trans = std::make_unique<MetaTransTrans>();
|
||||
m_trans->read(reader);
|
||||
} else if (type == "phasetrans") {
|
||||
m_trans.reset(new struct MetaTransPhaseTrans);
|
||||
m_trans = std::make_unique<MetaTransPhaseTrans>();
|
||||
m_trans->read(reader);
|
||||
} else {
|
||||
m_trans.reset(nullptr);
|
||||
m_trans.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,15 +122,15 @@ void ANIM::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
|||
atUint32 version = reader.readUint32Big();
|
||||
switch (version) {
|
||||
case 0:
|
||||
m_anim.reset(new struct ANIM0);
|
||||
m_anim = std::make_unique<ANIM0>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case 2:
|
||||
m_anim.reset(new struct ANIM2(false));
|
||||
m_anim = std::make_unique<ANIM2>(false);
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case 3:
|
||||
m_anim.reset(new struct ANIM2(true));
|
||||
m_anim = std::make_unique<ANIM2>(true);
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
default:
|
||||
|
@ -548,7 +548,7 @@ void ANIM::ANIM2::Enumerate<BigDNA::BinarySize>(size_t& __isz) {
|
|||
|
||||
ANIM::ANIM(const BlenderAction& act, const std::unordered_map<std::string, atInt32>& idMap,
|
||||
const DNAANIM::RigInverter<CINF>& rig, bool pc) {
|
||||
m_anim.reset(new struct ANIM2(pc));
|
||||
m_anim = std::make_unique<ANIM2>(pc);
|
||||
IANIM& newAnim = *m_anim;
|
||||
newAnim.looping = act.looping;
|
||||
|
||||
|
|
|
@ -99,15 +99,18 @@ void DCLN::Collision::Node::Enumerate(typename Op::StreamT& s) {
|
|||
Do<Op>(athena::io::PropId{"halfExtent"}, halfExtent, s);
|
||||
Do<Op>(athena::io::PropId{"isLeaf"}, isLeaf, s);
|
||||
if (isLeaf) {
|
||||
if (!leafData)
|
||||
leafData.reset(new LeafData);
|
||||
if (!leafData) {
|
||||
leafData = std::make_unique<LeafData>();
|
||||
}
|
||||
Do<Op>(athena::io::PropId{"leafData"}, *leafData, s);
|
||||
} else {
|
||||
if (!left)
|
||||
left.reset(new Node);
|
||||
if (!left) {
|
||||
left = std::make_unique<Node>();
|
||||
}
|
||||
Do<Op>(athena::io::PropId{"left"}, *left, s);
|
||||
if (!right)
|
||||
right.reset(new Node);
|
||||
if (!right) {
|
||||
right = std::make_unique<Node>();
|
||||
}
|
||||
Do<Op>(athena::io::PropId{"right"}, *right, s);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,43 +54,43 @@ void FRME::Widget::Enumerate<BigDNA::Read>(athena::io::IStreamReader& __dna_read
|
|||
header.read(__dna_reader);
|
||||
switch (type.toUint32()) {
|
||||
case SBIG('BWIG'):
|
||||
widgetInfo.reset(new BWIGInfo);
|
||||
widgetInfo = std::make_unique<BWIGInfo>();
|
||||
break;
|
||||
case SBIG('HWIG'):
|
||||
widgetInfo.reset(new HWIGInfo);
|
||||
widgetInfo = std::make_unique<HWIGInfo>();
|
||||
break;
|
||||
case SBIG('CAMR'):
|
||||
widgetInfo.reset(new CAMRInfo);
|
||||
widgetInfo = std::make_unique<CAMRInfo>();
|
||||
break;
|
||||
case SBIG('LITE'):
|
||||
widgetInfo.reset(new LITEInfo);
|
||||
widgetInfo = std::make_unique<LITEInfo>();
|
||||
break;
|
||||
case SBIG('ENRG'):
|
||||
widgetInfo.reset(new ENRGInfo);
|
||||
widgetInfo = std::make_unique<ENRGInfo>();
|
||||
break;
|
||||
case SBIG('MODL'):
|
||||
widgetInfo.reset(new MODLInfo);
|
||||
widgetInfo = std::make_unique<MODLInfo>();
|
||||
break;
|
||||
case SBIG('METR'):
|
||||
widgetInfo.reset(new METRInfo);
|
||||
widgetInfo = std::make_unique<METRInfo>();
|
||||
break;
|
||||
case SBIG('GRUP'):
|
||||
widgetInfo.reset(new GRUPInfo);
|
||||
widgetInfo = std::make_unique<GRUPInfo>();
|
||||
break;
|
||||
case SBIG('PANE'):
|
||||
widgetInfo.reset(new PANEInfo);
|
||||
widgetInfo = std::make_unique<PANEInfo>();
|
||||
break;
|
||||
case SBIG('TXPN'):
|
||||
widgetInfo.reset(new TXPNInfo(owner->version));
|
||||
widgetInfo = std::make_unique<TXPNInfo>(owner->version);
|
||||
break;
|
||||
case SBIG('IMGP'):
|
||||
widgetInfo.reset(new IMGPInfo);
|
||||
widgetInfo = std::make_unique<IMGPInfo>();
|
||||
break;
|
||||
case SBIG('TBGP'):
|
||||
widgetInfo.reset(new TBGPInfo);
|
||||
widgetInfo = std::make_unique<TBGPInfo>();
|
||||
break;
|
||||
case SBIG('SLGP'):
|
||||
widgetInfo.reset(new SLGPInfo);
|
||||
widgetInfo = std::make_unique<SLGPInfo>();
|
||||
break;
|
||||
default:
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Unsupported FRME widget type {}")), type);
|
||||
|
@ -169,12 +169,13 @@ void FRME::Widget::Enumerate<BigDNA::BinarySize>(size_t& __isz) {
|
|||
template <>
|
||||
void FRME::Widget::CAMRInfo::Enumerate<BigDNA::Read>(athena::io::IStreamReader& __dna_reader) {
|
||||
projectionType = ProjectionType(__dna_reader.readUint32Big());
|
||||
if (projectionType == ProjectionType::Perspective)
|
||||
projection.reset(new PerspectiveProjection);
|
||||
else if (projectionType == ProjectionType::Orthographic)
|
||||
projection.reset(new OrthographicProjection);
|
||||
else
|
||||
if (projectionType == ProjectionType::Perspective) {
|
||||
projection = std::make_unique<PerspectiveProjection>();
|
||||
} else if (projectionType == ProjectionType::Orthographic) {
|
||||
projection = std::make_unique<OrthographicProjection>();
|
||||
} else {
|
||||
Log.report(logvisor::Fatal, fmt(_SYS_STR("Invalid CAMR projection mode! {}")), int(projectionType));
|
||||
}
|
||||
|
||||
projection->read(__dna_reader);
|
||||
}
|
||||
|
|
|
@ -97,8 +97,8 @@ std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const nod::Node& pak, atUint64&
|
|||
atUint32 decompSz;
|
||||
strm->read(&decompSz, 4);
|
||||
decompSz = hecl::SBig(decompSz);
|
||||
atUint8* buf = new atUint8[decompSz];
|
||||
atUint8* bufCur = buf;
|
||||
std::unique_ptr<atUint8[]> buf{new atUint8[decompSz]};
|
||||
atUint8* bufCur = buf.get();
|
||||
|
||||
atUint8 compBuf[0x8000];
|
||||
if (compressed == 1) {
|
||||
|
@ -106,7 +106,7 @@ std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const nod::Node& pak, atUint64&
|
|||
z_stream zs = {};
|
||||
inflateInit(&zs);
|
||||
zs.avail_out = decompSz;
|
||||
zs.next_out = buf;
|
||||
zs.next_out = buf.get();
|
||||
while (zs.avail_out) {
|
||||
atUint64 readSz = strm->read(compBuf, std::min(compRem, atUint32(0x8000)));
|
||||
compRem -= readSz;
|
||||
|
@ -130,12 +130,12 @@ std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const nod::Node& pak, atUint64&
|
|||
}
|
||||
|
||||
szOut = decompSz;
|
||||
return std::unique_ptr<atUint8[]>(buf);
|
||||
return buf;
|
||||
} else {
|
||||
atUint8* buf = new atUint8[size];
|
||||
pak.beginReadStream(offset)->read(buf, size);
|
||||
std::unique_ptr<atUint8[]> buf{new atUint8[size]};
|
||||
pak.beginReadStream(offset)->read(buf.get(), size);
|
||||
szOut = size;
|
||||
return std::unique_ptr<atUint8[]>(buf);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
#include "SCAN.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
static const std::vector<std::string> PaneNames = {
|
||||
"imagepane_pane0", "imagepane_pane1", "imagepane_pane2", "imagepane_pane3", "imagepane_pane01",
|
||||
"imagepane_pane12", "imagepane_pane23", "imagepane_pane012", "imagepane_pane123", "imagepane_pane0123",
|
||||
"imagepane_pane4", "imagepane_pane5", "imagepane_pane6", "imagepane_pane7", "imagepane_pane45",
|
||||
"imagepane_pane56", "imagepane_pane67", "imagepane_pane456", "imagepane_pane567", "imagepane_pane4567"};
|
||||
constexpr std::array PaneNames{
|
||||
"imagepane_pane0"sv, "imagepane_pane1"sv, "imagepane_pane2"sv, "imagepane_pane3"sv, "imagepane_pane01"sv,
|
||||
"imagepane_pane12"sv, "imagepane_pane23"sv, "imagepane_pane012"sv, "imagepane_pane123"sv, "imagepane_pane0123"sv,
|
||||
"imagepane_pane4"sv, "imagepane_pane5"sv, "imagepane_pane6"sv, "imagepane_pane7"sv, "imagepane_pane45"sv,
|
||||
"imagepane_pane56"sv, "imagepane_pane67"sv, "imagepane_pane456"sv, "imagepane_pane567"sv, "imagepane_pane4567"sv,
|
||||
};
|
||||
|
||||
template <>
|
||||
void SCAN::Texture::Enumerate<BigDNA::Read>(typename Read::StreamT& r) {
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
#include "STRG.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "DNAMP1.hpp"
|
||||
|
||||
namespace DataSpec::DNAMP1 {
|
||||
|
||||
const std::vector<FourCC> skLanguages = {FOURCC('ENGL'), FOURCC('FREN'), FOURCC('GERM'), FOURCC('SPAN'),
|
||||
FOURCC('ITAL'), FOURCC('DUTC'), FOURCC('JAPN')};
|
||||
constexpr std::array skLanguages{
|
||||
FOURCC('ENGL'), FOURCC('FREN'), FOURCC('GERM'), FOURCC('SPAN'), FOURCC('ITAL'), FOURCC('DUTC'), FOURCC('JAPN'),
|
||||
};
|
||||
|
||||
static uint32_t ParseTag(const char16_t* str) {
|
||||
char parseStr[9];
|
||||
|
|
|
@ -126,11 +126,11 @@ void ANIM::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
|||
atUint32 version = reader.readUint32Big();
|
||||
switch (version) {
|
||||
case 0:
|
||||
m_anim.reset(new struct ANIM0);
|
||||
m_anim = std::make_unique<ANIM0>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case 2:
|
||||
m_anim.reset(new struct ANIM2);
|
||||
m_anim = std::make_unique<ANIM2>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -153,7 +153,7 @@ void PAKBridge::build() {
|
|||
}
|
||||
|
||||
void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const {
|
||||
for (const std::pair<UniqueID32, DNAMP2::PAK::Entry>& entry : m_pak.m_entries) {
|
||||
for (const auto& entry : m_pak.m_entries) {
|
||||
if (entry.second.type == FOURCC('ANCS')) {
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
ANCS ancs;
|
||||
|
@ -189,7 +189,7 @@ 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, DNAMP2::PAK::Entry>& entry : m_pak.m_entries) {
|
||||
for (const auto& entry : m_pak.m_entries) {
|
||||
if (entry.second.type == FOURCC('MLVL')) {
|
||||
MLVL mlvl;
|
||||
{
|
||||
|
|
|
@ -67,8 +67,8 @@ void STRG::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) {
|
|||
writer.writeUint32Big(strCount);
|
||||
|
||||
atUint32 offset = 0;
|
||||
for (const std::pair<DNAFourCC, std::vector<std::u16string>>& lang : langs) {
|
||||
lang.first.write(writer);
|
||||
for (const auto& lang : langs) {
|
||||
DNAFourCC{lang.first}.write(writer);
|
||||
writer.writeUint32Big(offset);
|
||||
offset += strCount * 4 + 4;
|
||||
atUint32 langStrCount = lang.second.size();
|
||||
|
@ -87,20 +87,22 @@ void STRG::Enumerate<BigDNA::Write>(athena::io::IStreamWriter& writer) {
|
|||
}
|
||||
|
||||
atUint32 nameTableSz = names.size() * 8;
|
||||
for (const std::pair<std::string, int32_t>& name : names)
|
||||
for (const auto& name : names) {
|
||||
nameTableSz += name.first.size() + 1;
|
||||
}
|
||||
writer.writeUint32Big(names.size());
|
||||
writer.writeUint32Big(nameTableSz);
|
||||
offset = names.size() * 8;
|
||||
for (const std::pair<std::string, int32_t>& name : names) {
|
||||
for (const auto& name : names) {
|
||||
writer.writeUint32Big(offset);
|
||||
writer.writeInt32Big(name.second);
|
||||
offset += name.first.size() + 1;
|
||||
}
|
||||
for (const std::pair<std::string, int32_t>& name : names)
|
||||
for (const auto& name : names) {
|
||||
writer.writeString(name.first);
|
||||
}
|
||||
|
||||
for (const std::pair<DNAFourCC, std::vector<std::u16string>>& lang : langs) {
|
||||
for (const auto& lang : langs) {
|
||||
offset = strCount * 4;
|
||||
atUint32 langStrCount = lang.second.size();
|
||||
for (atUint32 s = 0; s < strCount; ++s) {
|
||||
|
@ -128,11 +130,12 @@ void STRG::Enumerate<BigDNA::BinarySize>(size_t& __isz) {
|
|||
|
||||
__isz += 8;
|
||||
__isz += names.size() * 8;
|
||||
for (const std::pair<std::string, int32_t>& name : names)
|
||||
for (const auto& name : names) {
|
||||
__isz += name.first.size() + 1;
|
||||
}
|
||||
|
||||
size_t strCount = STRG::count();
|
||||
for (const std::pair<DNAFourCC, std::vector<std::u16string>>& lang : langs) {
|
||||
for (const auto& lang : langs) {
|
||||
atUint32 langStrCount = lang.second.size();
|
||||
__isz += strCount * 4;
|
||||
|
||||
|
|
|
@ -130,11 +130,11 @@ void ANIM::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
|
|||
atUint32 version = reader.readUint32Big();
|
||||
switch (version) {
|
||||
case 0:
|
||||
m_anim.reset(new struct ANIM0);
|
||||
m_anim = std::make_unique<ANIM0>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case 1:
|
||||
m_anim.reset(new struct ANIM1);
|
||||
m_anim = std::make_unique<ANIM1>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -74,30 +74,30 @@ std::string_view CHAR::AnimationInfo::EVNT::SFXEvent::DNAType() {
|
|||
|
||||
template <>
|
||||
void CHAR::AnimationInfo::MetaAnimFactory::Enumerate<BigDNA::Read>(athena::io::IStreamReader& reader) {
|
||||
IMetaAnim::Type type(IMetaAnim::Type(reader.readUint32Big()));
|
||||
const auto type = IMetaAnim::Type(reader.readUint32Big());
|
||||
switch (type) {
|
||||
case IMetaAnim::Type::Primitive:
|
||||
m_anim.reset(new struct MetaAnimPrimitive);
|
||||
m_anim = std::make_unique<MetaAnimPrimitive>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case IMetaAnim::Type::Blend:
|
||||
m_anim.reset(new struct MetaAnimBlend);
|
||||
m_anim = std::make_unique<MetaAnimBlend>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case IMetaAnim::Type::PhaseBlend:
|
||||
m_anim.reset(new struct MetaAnimPhaseBlend);
|
||||
m_anim = std::make_unique<MetaAnimPhaseBlend>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case IMetaAnim::Type::Random:
|
||||
m_anim.reset(new struct MetaAnimRandom);
|
||||
m_anim = std::make_unique<MetaAnimRandom>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
case IMetaAnim::Type::Sequence:
|
||||
m_anim.reset(new struct MetaAnimSequence);
|
||||
m_anim = std::make_unique<MetaAnimSequence>();
|
||||
m_anim->read(reader);
|
||||
break;
|
||||
default:
|
||||
m_anim.reset(nullptr);
|
||||
m_anim.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -123,22 +123,22 @@ void CHAR::AnimationInfo::MetaAnimFactory::Enumerate<BigDNA::ReadYaml>(athena::i
|
|||
std::string type = reader.readString("type");
|
||||
std::transform(type.begin(), type.end(), type.begin(), tolower);
|
||||
if (type == "primitive") {
|
||||
m_anim.reset(new struct MetaAnimPrimitive);
|
||||
m_anim = std::make_unique<MetaAnimPrimitive>();
|
||||
m_anim->read(reader);
|
||||
} else if (type == "blend") {
|
||||
m_anim.reset(new struct MetaAnimBlend);
|
||||
m_anim = std::make_unique<MetaAnimBlend>();
|
||||
m_anim->read(reader);
|
||||
} else if (type == "phaseblend") {
|
||||
m_anim.reset(new struct MetaAnimPhaseBlend);
|
||||
m_anim = std::make_unique<MetaAnimPhaseBlend>();
|
||||
m_anim->read(reader);
|
||||
} else if (type == "random") {
|
||||
m_anim.reset(new struct MetaAnimRandom);
|
||||
m_anim = std::make_unique<MetaAnimRandom>();
|
||||
m_anim->read(reader);
|
||||
} else if (type == "sequence") {
|
||||
m_anim.reset(new struct MetaAnimSequence);
|
||||
m_anim = std::make_unique<MetaAnimSequence>();
|
||||
m_anim->read(reader);
|
||||
} else {
|
||||
m_anim.reset(nullptr);
|
||||
m_anim.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,19 +12,19 @@ void MaterialSet::Material::SectionFactory::Enumerate<BigDNA::Read>(typename Rea
|
|||
type.read(reader);
|
||||
switch (ISection::Type(type.toUint32())) {
|
||||
case ISection::Type::PASS:
|
||||
section.reset(new struct SectionPASS);
|
||||
section = std::make_unique<SectionPASS>();
|
||||
section->read(reader);
|
||||
break;
|
||||
case ISection::Type::CLR:
|
||||
section.reset(new struct SectionCLR);
|
||||
section = std::make_unique<SectionCLR>();
|
||||
section->read(reader);
|
||||
break;
|
||||
case ISection::Type::INT:
|
||||
section.reset(new struct SectionINT);
|
||||
section = std::make_unique<SectionINT>();
|
||||
section->read(reader);
|
||||
break;
|
||||
default:
|
||||
section.reset(nullptr);
|
||||
section.reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ void PAKBridge::build() {
|
|||
}
|
||||
|
||||
void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID64>& charAssoc) const {
|
||||
for (const std::pair<UniqueID64, PAK::Entry>& entry : m_pak.m_entries) {
|
||||
for (const auto& entry : m_pak.m_entries) {
|
||||
if (entry.second.type == FOURCC('CHAR')) {
|
||||
PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
|
||||
CHAR aChar;
|
||||
|
@ -180,7 +180,7 @@ static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}};
|
|||
void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
|
||||
std::unordered_map<UniqueID64, zeus::CMatrix4f>& addTo,
|
||||
std::unordered_map<UniqueID64, hecl::ProjectPath>& pathOverrides) const {
|
||||
for (const std::pair<UniqueID64, PAK::Entry>& entry : m_pak.m_entries) {
|
||||
for (const auto& entry : m_pak.m_entries) {
|
||||
if (entry.second.type == FOURCC('MLVL')) {
|
||||
MLVL mlvl;
|
||||
{
|
||||
|
|
|
@ -142,7 +142,7 @@ std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const nod::Node& pak, atUint64&
|
|||
strm->read(&head, 8);
|
||||
if (head.magic != CMPD) {
|
||||
Log.report(logvisor::Error, fmt("invalid CMPD block"));
|
||||
return std::unique_ptr<atUint8[]>();
|
||||
return nullptr;
|
||||
}
|
||||
head.blockCount = hecl::SBig(head.blockCount);
|
||||
|
||||
|
@ -165,8 +165,8 @@ std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const nod::Node& pak, atUint64&
|
|||
}
|
||||
|
||||
std::unique_ptr<atUint8[]> compBuf(new atUint8[maxBlockSz]);
|
||||
atUint8* buf = new atUint8[totalDecompSz];
|
||||
atUint8* bufCur = buf;
|
||||
std::unique_ptr<atUint8[]> buf{new atUint8[totalDecompSz]};
|
||||
atUint8* bufCur = buf.get();
|
||||
for (atUint32 b = 0; b < head.blockCount; ++b) {
|
||||
Block& block = blocks[b];
|
||||
atUint8* compBufCur = compBuf.get();
|
||||
|
@ -189,12 +189,12 @@ std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const nod::Node& pak, atUint64&
|
|||
}
|
||||
|
||||
szOut = totalDecompSz;
|
||||
return std::unique_ptr<atUint8[]>(buf);
|
||||
return buf;
|
||||
} else {
|
||||
atUint8* buf = new atUint8[size];
|
||||
pak.beginReadStream(offset)->read(buf, size);
|
||||
std::unique_ptr<atUint8[]> buf{new atUint8[size]};
|
||||
pak.beginReadStream(offset)->read(buf.get(), size);
|
||||
szOut = size;
|
||||
return std::unique_ptr<atUint8[]>(buf);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ struct PAK : BigDNA {
|
|||
|
||||
bool mreaHasDupeResources(const UniqueID64& id) const { return m_dupeMREAs.find(id) != m_dupeMREAs.cend(); }
|
||||
|
||||
typedef UniqueID64 IDType;
|
||||
using IDType = UniqueID64;
|
||||
};
|
||||
|
||||
} // namespace DataSpec::DNAMP3
|
||||
|
|
|
@ -108,7 +108,7 @@ struct TextureCache {
|
|||
auto rec = r.enterSubRecord(node.first.c_str());
|
||||
TXTR::Meta meta;
|
||||
meta.read(r);
|
||||
metaPairs.push_back(std::make_pair(projectPath.parsedHash32(), meta));
|
||||
metaPairs.emplace_back(projectPath.parsedHash32(), meta);
|
||||
}
|
||||
|
||||
std::sort(metaPairs.begin(), metaPairs.end(), [](const auto& a, const auto& b) -> bool {
|
||||
|
@ -201,11 +201,12 @@ struct SpecMP1 : SpecBase {
|
|||
|
||||
/* Assemble extract report */
|
||||
rep.childOpts.reserve(m_orderedPaks.size());
|
||||
for (const std::pair<std::string, DNAMP1::PAKBridge*>& item : m_orderedPaks) {
|
||||
if (!item.second->m_doExtract)
|
||||
for (const auto& item : m_orderedPaks) {
|
||||
if (!item.second->m_doExtract) {
|
||||
continue;
|
||||
rep.childOpts.emplace_back();
|
||||
ExtractReport& childRep = rep.childOpts.back();
|
||||
}
|
||||
|
||||
ExtractReport& childRep = rep.childOpts.emplace_back();
|
||||
hecl::SystemStringConv nameView(item.first);
|
||||
childRep.name = nameView.sys_str();
|
||||
childRep.desc = item.second->getLevelString();
|
||||
|
@ -222,8 +223,7 @@ struct SpecMP1 : SpecBase {
|
|||
return false;
|
||||
|
||||
/* Root Report */
|
||||
reps.emplace_back();
|
||||
ExtractReport& rep = reps.back();
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP1");
|
||||
rep.desc = _SYS_STR("Metroid Prime ") + regstr;
|
||||
if (buildInfo) {
|
||||
|
@ -277,8 +277,7 @@ struct SpecMP1 : SpecBase {
|
|||
const char* buildInfo = (char*)memmem(m_dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19;
|
||||
|
||||
/* Root Report */
|
||||
reps.emplace_back();
|
||||
ExtractReport& rep = reps.back();
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP1");
|
||||
rep.desc = _SYS_STR("Metroid Prime ") + regstr;
|
||||
if (buildInfo) {
|
||||
|
@ -1023,7 +1022,7 @@ struct SpecMP1 : SpecBase {
|
|||
for (const auto& dep : area.deps) {
|
||||
urde::CAssetId newId = dep.id.toUint64();
|
||||
if (dupeRes || addedTags.find(newId) == addedTags.end()) {
|
||||
listOut.push_back({dep.type, newId});
|
||||
listOut.emplace_back(dep.type, newId);
|
||||
addedTags.insert(newId);
|
||||
}
|
||||
}
|
||||
|
@ -1083,7 +1082,7 @@ struct SpecMP1 : SpecBase {
|
|||
for (atUint32 i = 0; i < mapaCount; ++i) {
|
||||
UniqueID32 id;
|
||||
id.read(r);
|
||||
listOut.push_back({FOURCC('MAPA'), id.toUint64()});
|
||||
listOut.emplace_back(FOURCC('MAPA'), id.toUint64());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,11 +103,12 @@ struct SpecMP2 : SpecBase {
|
|||
m_orderedPaks[std::string(dpak.getName())] = &dpak;
|
||||
|
||||
/* Assemble extract report */
|
||||
for (const std::pair<std::string, DNAMP2::PAKBridge*>& item : m_orderedPaks) {
|
||||
if (!item.second->m_doExtract)
|
||||
for (const auto& item : m_orderedPaks) {
|
||||
if (!item.second->m_doExtract) {
|
||||
continue;
|
||||
rep.childOpts.emplace_back();
|
||||
ExtractReport& childRep = rep.childOpts.back();
|
||||
}
|
||||
|
||||
ExtractReport& childRep = rep.childOpts.emplace_back();
|
||||
hecl::SystemStringConv nameView(item.first);
|
||||
childRep.name = hecl::SystemString(nameView.sys_str());
|
||||
childRep.desc = item.second->getLevelString();
|
||||
|
@ -123,8 +124,7 @@ struct SpecMP2 : SpecBase {
|
|||
return false;
|
||||
|
||||
/* Root Report */
|
||||
reps.emplace_back();
|
||||
ExtractReport& rep = reps.back();
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP2");
|
||||
rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr;
|
||||
std::string buildStr(buildInfo);
|
||||
|
@ -176,8 +176,7 @@ struct SpecMP2 : SpecBase {
|
|||
const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19;
|
||||
|
||||
/* Root Report */
|
||||
reps.emplace_back();
|
||||
ExtractReport& rep = reps.back();
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP2");
|
||||
rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr;
|
||||
if (buildInfo) {
|
||||
|
|
|
@ -132,11 +132,11 @@ struct SpecMP3 : SpecBase {
|
|||
}
|
||||
|
||||
/* Assemble extract report */
|
||||
for (const std::pair<std::string, DNAMP3::PAKBridge*>& item : fe ? m_feOrderedPaks : m_orderedPaks) {
|
||||
for (const auto& item : fe ? m_feOrderedPaks : m_orderedPaks) {
|
||||
if (!item.second->m_doExtract)
|
||||
continue;
|
||||
rep.childOpts.emplace_back();
|
||||
ExtractReport& childRep = rep.childOpts.back();
|
||||
|
||||
ExtractReport& childRep = rep.childOpts.emplace_back();
|
||||
hecl::SystemStringConv nameView(item.first);
|
||||
childRep.name = hecl::SystemString(nameView.sys_str());
|
||||
if (item.first == "Worlds.pak")
|
||||
|
@ -168,8 +168,7 @@ struct SpecMP3 : SpecBase {
|
|||
return false;
|
||||
|
||||
/* Root Report */
|
||||
reps.emplace_back();
|
||||
ExtractReport& rep = reps.back();
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP3");
|
||||
rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr;
|
||||
std::string buildStr(buildInfo);
|
||||
|
@ -250,8 +249,7 @@ struct SpecMP3 : SpecBase {
|
|||
}
|
||||
|
||||
/* Root Report */
|
||||
reps.emplace_back();
|
||||
ExtractReport& rep = reps.back();
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("MP3");
|
||||
rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr;
|
||||
|
||||
|
@ -281,8 +279,7 @@ struct SpecMP3 : SpecBase {
|
|||
const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19;
|
||||
|
||||
/* Root Report */
|
||||
reps.emplace_back();
|
||||
ExtractReport& rep = reps.back();
|
||||
ExtractReport& rep = reps.emplace_back();
|
||||
rep.name = _SYS_STR("fe");
|
||||
rep.desc = _SYS_STR("Metroid Prime Trilogy Frontend ") + regstr;
|
||||
if (buildInfo) {
|
||||
|
@ -305,7 +302,7 @@ struct SpecMP3 : SpecBase {
|
|||
}
|
||||
|
||||
bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) override {
|
||||
hecl::SystemString currentTarget = _SYS_STR("");
|
||||
hecl::SystemString currentTarget;
|
||||
size_t nodeCount = 0;
|
||||
int prog = 0;
|
||||
nod::ExtractionContext ctx = {force, [&](std::string_view name, float) {
|
||||
|
@ -394,7 +391,7 @@ struct SpecMP3 : SpecBase {
|
|||
progress.startNewLine();
|
||||
|
||||
hecl::ClientProcess process;
|
||||
for (std::pair<std::string, DNAMP3::PAKBridge*> pair : m_feOrderedPaks) {
|
||||
for (auto& pair : m_feOrderedPaks) {
|
||||
DNAMP3::PAKBridge& pak = *pair.second;
|
||||
if (!pak.m_doExtract)
|
||||
continue;
|
||||
|
|
|
@ -1,23 +1,31 @@
|
|||
#include "Runtime/Audio/CAudioGroupSet.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace urde {
|
||||
|
||||
amuse::AudioGroupData CAudioGroupSet::LoadData() {
|
||||
const auto readU32 = [](const u8* ptr) {
|
||||
uint32_t value;
|
||||
std::memcpy(&value, ptr, sizeof(value));
|
||||
return hecl::SBig(value);
|
||||
};
|
||||
|
||||
athena::io::MemoryReader r(m_buffer.get(), INT32_MAX);
|
||||
x10_baseName = r.readString();
|
||||
x20_name = r.readString();
|
||||
|
||||
u8* buf = m_buffer.get() + r.position();
|
||||
uint32_t poolLen = hecl::SBig(*reinterpret_cast<uint32_t*>(buf));
|
||||
const uint32_t poolLen = readU32(buf);
|
||||
unsigned char* pool = buf + 4;
|
||||
buf += poolLen + 4;
|
||||
uint32_t projLen = hecl::SBig(*reinterpret_cast<uint32_t*>(buf));
|
||||
const uint32_t projLen = readU32(buf);
|
||||
unsigned char* proj = buf + 4;
|
||||
buf += projLen + 4;
|
||||
uint32_t sampLen = hecl::SBig(*reinterpret_cast<uint32_t*>(buf));
|
||||
const uint32_t sampLen = readU32(buf);
|
||||
unsigned char* samp = buf + 4;
|
||||
buf += sampLen + 4;
|
||||
uint32_t sdirLen = hecl::SBig(*reinterpret_cast<uint32_t*>(buf));
|
||||
const uint32_t sdirLen = readU32(buf);
|
||||
unsigned char* sdir = buf + 4;
|
||||
|
||||
return {proj, projLen, pool, poolLen, sdir, sdirLen, samp, sampLen, amuse::GCNDataTag{}};
|
||||
|
|
|
@ -21,7 +21,7 @@ class CAudioGroupSet {
|
|||
amuse::AudioGroupData LoadData();
|
||||
|
||||
public:
|
||||
CAudioGroupSet(std::unique_ptr<u8[]>&& in);
|
||||
explicit CAudioGroupSet(std::unique_ptr<u8[]>&& in);
|
||||
const amuse::AudioGroupData& GetAudioGroupData() const { return m_data; }
|
||||
std::string_view GetName() const { return x20_name; }
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@ public:
|
|||
u16 GetGroupId() const { return x2_groupId; }
|
||||
CAssetId GetAGSCAssetId() const { return x4_agscId; }
|
||||
const u8* GetArrData() const { return x8_arrData.get(); }
|
||||
CMidiData(CInputStream& in);
|
||||
explicit CMidiData(CInputStream& in);
|
||||
};
|
||||
|
||||
class CMidiWrapper {
|
||||
|
|
|
@ -26,7 +26,7 @@ CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStre
|
|||
return TToken<std::vector<u16>>::GetIObjObjectFor(std::move(obj));
|
||||
}
|
||||
|
||||
CSfxManager::CSfxChannel CSfxManager::m_channels[4];
|
||||
std::array<CSfxManager::CSfxChannel, 4> CSfxManager::m_channels;
|
||||
CSfxManager::ESfxChannels CSfxManager::m_currentChannel = CSfxManager::ESfxChannels::Default;
|
||||
bool CSfxManager::m_doUpdate;
|
||||
void* CSfxManager::m_usedSounds;
|
||||
|
@ -186,7 +186,7 @@ void CSfxManager::SetChannel(ESfxChannels chan) {
|
|||
}
|
||||
|
||||
void CSfxManager::KillAll(ESfxChannels chan) {
|
||||
CSfxChannel& chanObj = m_channels[int(chan)];
|
||||
CSfxChannel& chanObj = m_channels[size_t(chan)];
|
||||
for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) {
|
||||
const CSfxHandle& handle = *it;
|
||||
handle->Stop();
|
||||
|
@ -197,7 +197,7 @@ void CSfxManager::KillAll(ESfxChannels chan) {
|
|||
}
|
||||
|
||||
void CSfxManager::TurnOnChannel(ESfxChannels chan) {
|
||||
CSfxChannel& chanObj = m_channels[int(chan)];
|
||||
CSfxChannel& chanObj = m_channels[size_t(chan)];
|
||||
m_currentChannel = chan;
|
||||
m_doUpdate = true;
|
||||
if (chanObj.x44_listenerActive) {
|
||||
|
@ -208,7 +208,7 @@ void CSfxManager::TurnOnChannel(ESfxChannels chan) {
|
|||
}
|
||||
|
||||
void CSfxManager::TurnOffChannel(ESfxChannels chan) {
|
||||
CSfxChannel& chanObj = m_channels[int(chan)];
|
||||
CSfxChannel& chanObj = m_channels[size_t(chan)];
|
||||
for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) {
|
||||
const CSfxHandle& handle = *it;
|
||||
if (handle->IsLooped()) {
|
||||
|
@ -260,24 +260,29 @@ void CSfxManager::UpdateListener(const zeus::CVector3f& pos, const zeus::CVector
|
|||
}
|
||||
|
||||
s16 CSfxManager::GetRank(CBaseSfxWrapper* sfx) {
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
if (!sfx->IsInArea())
|
||||
const CSfxChannel& chanObj = m_channels[size_t(m_currentChannel)];
|
||||
if (!sfx->IsInArea()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s16 rank = sfx->GetPriority() / 4;
|
||||
if (sfx->IsPlaying())
|
||||
if (sfx->IsPlaying()) {
|
||||
++rank;
|
||||
}
|
||||
|
||||
if (sfx->IsLooped())
|
||||
if (sfx->IsLooped()) {
|
||||
rank -= 2;
|
||||
}
|
||||
|
||||
if (sfx->Ready() && !sfx->IsPlaying())
|
||||
if (sfx->Ready() && !sfx->IsPlaying()) {
|
||||
rank += 3;
|
||||
}
|
||||
|
||||
if (chanObj.x44_listenerActive) {
|
||||
ESfxAudibility aud = sfx->GetAudible(chanObj.x0_pos);
|
||||
if (aud == ESfxAudibility::Aud0)
|
||||
const ESfxAudibility aud = sfx->GetAudible(chanObj.x0_pos);
|
||||
if (aud == ESfxAudibility::Aud0) {
|
||||
return 0;
|
||||
}
|
||||
rank += int(aud) / 2;
|
||||
}
|
||||
|
||||
|
@ -285,7 +290,7 @@ s16 CSfxManager::GetRank(CBaseSfxWrapper* sfx) {
|
|||
}
|
||||
|
||||
void CSfxManager::ApplyReverb() {
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
const CSfxChannel& chanObj = m_channels[size_t(m_currentChannel)];
|
||||
for (const CSfxHandle& handle : chanObj.x48_handles) {
|
||||
handle->SetReverb(m_reverbAmount);
|
||||
}
|
||||
|
@ -344,7 +349,7 @@ void CSfxManager::StopSound(const CSfxHandle& handle) {
|
|||
m_doUpdate = true;
|
||||
handle->Stop();
|
||||
handle->Release();
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
CSfxChannel& chanObj = m_channels[size_t(m_currentChannel)];
|
||||
handle->Close();
|
||||
chanObj.x48_handles.erase(handle);
|
||||
}
|
||||
|
@ -357,7 +362,7 @@ CSfxHandle CSfxManager::SfxStart(u16 id, float vol, float pan, bool useAcoustics
|
|||
|
||||
m_doUpdate = true;
|
||||
CSfxHandle wrapper = std::make_shared<CSfxWrapper>(looped, prio, id, vol, pan, useAcoustics, areaId);
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
CSfxChannel& chanObj = m_channels[size_t(m_currentChannel)];
|
||||
chanObj.x48_handles.insert(wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
@ -428,14 +433,13 @@ CSfxHandle CSfxManager::AddEmitter(const CAudioSys::C3DEmitterParmData& parmData
|
|||
data.x20_flags |= 0x6; // Pausable/restartable when inaudible
|
||||
m_doUpdate = true;
|
||||
CSfxHandle wrapper = std::make_shared<CSfxEmitterWrapper>(looped, prio, data, useAcoustics, areaId);
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
CSfxChannel& chanObj = m_channels[size_t(m_currentChannel)];
|
||||
chanObj.x48_handles.insert(wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
void CSfxManager::StopAndRemoveAllEmitters() {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
CSfxChannel& chanObj = m_channels[i];
|
||||
for (auto& chanObj : m_channels) {
|
||||
for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) {
|
||||
const CSfxHandle& handle = *it;
|
||||
handle->Stop();
|
||||
|
@ -538,15 +542,15 @@ void CSfxManager::DisableAuxProcessing() {
|
|||
}
|
||||
|
||||
void CSfxManager::SetActiveAreas(const rstl::reserved_vector<TAreaId, 10>& areas) {
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
const CSfxChannel& chanObj = m_channels[size_t(m_currentChannel)];
|
||||
|
||||
for (const CSfxHandle& hnd : chanObj.x48_handles) {
|
||||
TAreaId sndArea = hnd->GetArea();
|
||||
const TAreaId sndArea = hnd->GetArea();
|
||||
if (sndArea == kInvalidAreaId) {
|
||||
hnd->SetInArea(true);
|
||||
} else {
|
||||
bool inArea = false;
|
||||
for (TAreaId id : areas) {
|
||||
for (const TAreaId id : areas) {
|
||||
if (sndArea == id) {
|
||||
inArea = true;
|
||||
break;
|
||||
|
@ -559,7 +563,7 @@ void CSfxManager::SetActiveAreas(const rstl::reserved_vector<TAreaId, 10>& areas
|
|||
}
|
||||
|
||||
void CSfxManager::Update(float dt) {
|
||||
CSfxChannel& chanObj = m_channels[int(m_currentChannel)];
|
||||
CSfxChannel& chanObj = m_channels[size_t(m_currentChannel)];
|
||||
|
||||
for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) {
|
||||
const CSfxHandle& handle = *it;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
@ -109,8 +110,7 @@ public:
|
|||
void SetTimeRemaining(float t) { x4_timeRemaining = t; }
|
||||
|
||||
CBaseSfxWrapper(bool looped, s16 prio, /*const CSfxHandle& handle,*/ bool useAcoustics, TAreaId area)
|
||||
: x8_rank(0)
|
||||
, xa_prio(prio)
|
||||
: xa_prio(prio)
|
||||
, /*xc_handle(handle),*/ x10_area(area)
|
||||
, x14_24_isActive(true)
|
||||
, x14_25_isPlaying(false)
|
||||
|
@ -118,15 +118,16 @@ public:
|
|||
, x14_27_inArea(true)
|
||||
, x14_28_isReleased(false)
|
||||
, x14_29_useAcoustics(useAcoustics)
|
||||
, m_isEmitter(false)
|
||||
, m_isClosed(false) {}
|
||||
};
|
||||
|
||||
class CSfxEmitterWrapper : public CBaseSfxWrapper {
|
||||
float x1a_reverb;
|
||||
float x1a_reverb = 0.0f;
|
||||
CAudioSys::C3DEmitterParmData x24_parmData;
|
||||
amuse::ObjToken<amuse::Emitter> x50_emitterHandle;
|
||||
bool x54_ready = true;
|
||||
float x55_cachedMaxVol;
|
||||
float x55_cachedMaxVol = 0.0f;
|
||||
|
||||
public:
|
||||
bool IsPlaying() const override;
|
||||
|
@ -177,7 +178,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
static CSfxChannel m_channels[4];
|
||||
static std::array<CSfxChannel, 4> m_channels;
|
||||
static ESfxChannels m_currentChannel;
|
||||
static bool m_doUpdate;
|
||||
static void* m_usedSounds;
|
||||
|
|
|
@ -53,7 +53,7 @@ class CStaticAudioPlayer {
|
|||
memset(data, 0, 4 * frames);
|
||||
return frames;
|
||||
}
|
||||
AudioVoiceCallback(CStaticAudioPlayer& p) : m_parent(p) {}
|
||||
explicit AudioVoiceCallback(CStaticAudioPlayer& p) : m_parent(p) {}
|
||||
} m_voiceCallback;
|
||||
boo::ObjToken<boo::IAudioVoice> m_voice;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Runtime/CStringExtras.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
@ -36,7 +37,7 @@ struct dspadpcm_header {
|
|||
s16 x44_loop_ps;
|
||||
s16 x46_loop_hist1;
|
||||
s16 x48_loop_hist2;
|
||||
u16 x4a_pad[11];
|
||||
std::array<u16, 11> x4a_pad;
|
||||
};
|
||||
|
||||
struct SDSPStreamInfo {
|
||||
|
@ -50,7 +51,7 @@ struct SDSPStreamInfo {
|
|||
s16 x1c_coef[8][2];
|
||||
|
||||
SDSPStreamInfo() = default;
|
||||
SDSPStreamInfo(const CDSPStreamManager& stream);
|
||||
explicit SDSPStreamInfo(const CDSPStreamManager& stream);
|
||||
};
|
||||
|
||||
struct SDSPStream : boo::IAudioVoiceCallback {
|
||||
|
@ -74,7 +75,7 @@ struct SDSPStream : boo::IAudioVoiceCallback {
|
|||
u8 xec_readState = 0; // 0: NoRead 1: Read 2: ReadWrap
|
||||
|
||||
std::optional<CDvdFile> m_file;
|
||||
std::shared_ptr<IDvdRequest> m_readReqs[2];
|
||||
std::array<std::shared_ptr<IDvdRequest>, 2> m_readReqs;
|
||||
|
||||
void ReadBuffer(int buf) {
|
||||
u32 halfSize = xd8_ringBytes / 2;
|
||||
|
@ -242,7 +243,7 @@ struct SDSPStream : boo::IAudioVoiceCallback {
|
|||
}
|
||||
|
||||
static void Initialize() {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (size_t i = 0; i < g_Streams.size(); ++i) {
|
||||
SDSPStream& stream = g_Streams[i];
|
||||
stream.x0_active = false;
|
||||
stream.xd4_ringBuffer.reset();
|
||||
|
@ -258,29 +259,30 @@ struct SDSPStream : boo::IAudioVoiceCallback {
|
|||
}
|
||||
|
||||
static void FreeAllStreams() {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
SDSPStream& stream = g_Streams[i];
|
||||
for (auto& stream : g_Streams) {
|
||||
stream.m_booVoice.reset();
|
||||
stream.x0_active = false;
|
||||
for (int j = 0; j < 2; ++j)
|
||||
if (stream.m_readReqs[j]) {
|
||||
stream.m_readReqs[j]->PostCancelRequest();
|
||||
stream.m_readReqs[j].reset();
|
||||
for (auto& request : stream.m_readReqs) {
|
||||
if (request) {
|
||||
request->PostCancelRequest();
|
||||
request.reset();
|
||||
}
|
||||
}
|
||||
stream.xd4_ringBuffer.reset();
|
||||
stream.m_file = std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
static s32 PickFreeStream(SDSPStream*& streamOut, bool oneshot) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
SDSPStream& stream = g_Streams[i];
|
||||
if (stream.x0_active || stream.x1_oneshot != oneshot)
|
||||
for (auto& stream : g_Streams) {
|
||||
if (stream.x0_active || stream.x1_oneshot != oneshot) {
|
||||
continue;
|
||||
}
|
||||
stream.x0_active = true;
|
||||
stream.x4_ownerId = ++s_HandleCounter2;
|
||||
if (stream.x4_ownerId == -1)
|
||||
if (stream.x4_ownerId == -1) {
|
||||
stream.x4_ownerId = ++s_HandleCounter2;
|
||||
}
|
||||
stream.x8_stereoLeft = nullptr;
|
||||
stream.xc_companionRight = nullptr;
|
||||
streamOut = &stream;
|
||||
|
@ -290,22 +292,24 @@ struct SDSPStream : boo::IAudioVoiceCallback {
|
|||
}
|
||||
|
||||
static s32 FindStreamIdx(s32 id) {
|
||||
for (s32 i = 0; i < 4; ++i) {
|
||||
SDSPStream& stream = g_Streams[i];
|
||||
if (stream.x4_ownerId == id)
|
||||
return i;
|
||||
for (size_t i = 0; i < g_Streams.size(); ++i) {
|
||||
const SDSPStream& stream = g_Streams[i];
|
||||
if (stream.x4_ownerId == id) {
|
||||
return s32(i);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void UpdateStreamVolume(float vol) {
|
||||
x4c_vol = vol;
|
||||
if (!x0_active || xe8_silent)
|
||||
if (!x0_active || xe8_silent) {
|
||||
return;
|
||||
float coefs[8] = {};
|
||||
coefs[int(boo::AudioChannel::FrontLeft)] = m_leftgain * vol;
|
||||
coefs[int(boo::AudioChannel::FrontRight)] = m_rightgain * vol;
|
||||
m_booVoice->setMonoChannelLevels(nullptr, coefs, true);
|
||||
}
|
||||
std::array<float, 8> coefs{};
|
||||
coefs[size_t(boo::AudioChannel::FrontLeft)] = m_leftgain * vol;
|
||||
coefs[size_t(boo::AudioChannel::FrontRight)] = m_rightgain * vol;
|
||||
m_booVoice->setMonoChannelLevels(nullptr, coefs.data(), true);
|
||||
}
|
||||
|
||||
static void UpdateVolume(s32 id, float vol) {
|
||||
|
@ -322,10 +326,11 @@ struct SDSPStream : boo::IAudioVoiceCallback {
|
|||
}
|
||||
|
||||
void SilenceStream() {
|
||||
if (!x0_active || xe8_silent)
|
||||
if (!x0_active || xe8_silent) {
|
||||
return;
|
||||
float coefs[8] = {};
|
||||
m_booVoice->setMonoChannelLevels(nullptr, coefs, true);
|
||||
}
|
||||
constexpr std::array<float, 8> coefs{};
|
||||
m_booVoice->setMonoChannelLevels(nullptr, coefs.data(), true);
|
||||
xe8_silent = true;
|
||||
x0_active = false;
|
||||
}
|
||||
|
@ -399,13 +404,15 @@ struct SDSPStream : boo::IAudioVoiceCallback {
|
|||
void AllocateStream(const SDSPStreamInfo& info, float vol, float left, float right) {
|
||||
x10_info = info;
|
||||
m_file.emplace(x10_info.x0_fileName);
|
||||
if (!xd4_ringBuffer)
|
||||
if (!xd4_ringBuffer) {
|
||||
DoAllocateStream();
|
||||
for (int j = 0; j < 2; ++j)
|
||||
if (m_readReqs[j]) {
|
||||
m_readReqs[j]->PostCancelRequest();
|
||||
m_readReqs[j].reset();
|
||||
}
|
||||
for (auto& request : m_readReqs) {
|
||||
if (request) {
|
||||
request->PostCancelRequest();
|
||||
request.reset();
|
||||
}
|
||||
}
|
||||
x4c_vol = vol;
|
||||
m_leftgain = left;
|
||||
m_rightgain = right;
|
||||
|
@ -425,10 +432,10 @@ struct SDSPStream : boo::IAudioVoiceCallback {
|
|||
UpdateStreamVolume(vol);
|
||||
}
|
||||
|
||||
static SDSPStream g_Streams[4];
|
||||
static std::array<SDSPStream, 4> g_Streams;
|
||||
};
|
||||
|
||||
SDSPStream SDSPStream::g_Streams[4] = {};
|
||||
std::array<SDSPStream, 4> SDSPStream::g_Streams{};
|
||||
|
||||
class CDSPStreamManager {
|
||||
friend struct SDSPStreamInfo;
|
||||
|
@ -450,12 +457,12 @@ private:
|
|||
s8 x71_companionRight = -1;
|
||||
s8 x72_companionLeft = -1;
|
||||
float x73_volume = 0.f;
|
||||
bool x74_oneshot;
|
||||
bool x74_oneshot = false;
|
||||
s32 x78_handleId = -1; // arg2
|
||||
s32 x7c_streamId = -1;
|
||||
std::shared_ptr<IDvdRequest> m_dvdReq;
|
||||
// DVDFileInfo x80_dvdHandle;
|
||||
static CDSPStreamManager g_Streams[4];
|
||||
static std::array<CDSPStreamManager, 4> g_Streams;
|
||||
|
||||
public:
|
||||
CDSPStreamManager() { x70_24_unclaimed = true; }
|
||||
|
@ -467,22 +474,23 @@ public:
|
|||
}
|
||||
|
||||
static s32 FindUnclaimedStreamIdx() {
|
||||
for (s32 i = 0; i < 4; ++i) {
|
||||
CDSPStreamManager& stream = g_Streams[i];
|
||||
if (stream.x70_24_unclaimed)
|
||||
return i;
|
||||
for (size_t i = 0; i < g_Streams.size(); ++i) {
|
||||
const CDSPStreamManager& stream = g_Streams[i];
|
||||
if (stream.x70_24_unclaimed) {
|
||||
return s32(i);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static bool FindUnclaimedStereoPair(s32& left, s32& right) {
|
||||
s32 idx = FindUnclaimedStreamIdx();
|
||||
const s32 idx = FindUnclaimedStreamIdx();
|
||||
|
||||
for (s32 i = 0; i < 4; ++i) {
|
||||
for (size_t i = 0; i < g_Streams.size(); ++i) {
|
||||
CDSPStreamManager& stream = g_Streams[i];
|
||||
if (stream.x70_24_unclaimed && idx != i) {
|
||||
if (stream.x70_24_unclaimed && idx != s32(i)) {
|
||||
left = idx;
|
||||
right = i;
|
||||
right = s32(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -491,10 +499,11 @@ public:
|
|||
}
|
||||
|
||||
static s32 FindClaimedStreamIdx(s32 handle) {
|
||||
for (s32 i = 0; i < 4; ++i) {
|
||||
CDSPStreamManager& stream = g_Streams[i];
|
||||
if (!stream.x70_24_unclaimed && stream.x78_handleId == handle)
|
||||
for (size_t i = 0; i < g_Streams.size(); ++i) {
|
||||
const CDSPStreamManager& stream = g_Streams[i];
|
||||
if (!stream.x70_24_unclaimed && stream.x78_handleId == handle) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
@ -510,8 +519,7 @@ public:
|
|||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
CDSPStreamManager& stream = g_Streams[i];
|
||||
for (auto& stream : g_Streams) {
|
||||
if (!stream.x70_24_unclaimed && stream.x78_handleId == handle) {
|
||||
good = false;
|
||||
break;
|
||||
|
@ -595,9 +603,9 @@ public:
|
|||
|
||||
void HeaderReadComplete() {
|
||||
s32 selfIdx = -1;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (size_t i = 0; i < g_Streams.size(); ++i) {
|
||||
if (this == &g_Streams[i]) {
|
||||
selfIdx = i;
|
||||
selfIdx = s32(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -641,8 +649,7 @@ public:
|
|||
}
|
||||
|
||||
static void PollHeaderReadCompletions() {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
CDSPStreamManager& stream = g_Streams[i];
|
||||
for (auto& stream : g_Streams) {
|
||||
if (stream.m_dvdReq && stream.m_dvdReq->IsComplete()) {
|
||||
stream.m_dvdReq.reset();
|
||||
stream.HeaderReadComplete();
|
||||
|
@ -790,22 +797,20 @@ public:
|
|||
|
||||
static void Initialize() {
|
||||
SDSPStream::Initialize();
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
CDSPStreamManager& stream = g_Streams[i];
|
||||
for (auto& stream : g_Streams) {
|
||||
stream = CDSPStreamManager();
|
||||
}
|
||||
}
|
||||
|
||||
static void Shutdown() {
|
||||
SDSPStream::FreeAllStreams();
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
CDSPStreamManager& stream = g_Streams[i];
|
||||
for (auto& stream : g_Streams) {
|
||||
stream = CDSPStreamManager();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CDSPStreamManager CDSPStreamManager::g_Streams[4] = {};
|
||||
std::array<CDSPStreamManager, 4> CDSPStreamManager::g_Streams{};
|
||||
|
||||
SDSPStreamInfo::SDSPStreamInfo(const CDSPStreamManager& stream) {
|
||||
x0_fileName = stream.x60_fileName.c_str();
|
||||
|
@ -853,8 +858,10 @@ struct SDSPPlayer {
|
|||
, x20_internalHandle(handle)
|
||||
, x28_music(music) {}
|
||||
};
|
||||
static SDSPPlayer s_Players[2]; // looping, oneshot
|
||||
static SDSPPlayer s_QueuedPlayers[2]; // looping, oneshot
|
||||
|
||||
using PlayerArray = std::array<SDSPPlayer, 2>;
|
||||
static PlayerArray s_Players; // looping, oneshot
|
||||
static PlayerArray s_QueuedPlayers; // looping, oneshot
|
||||
|
||||
float CStreamAudioManager::GetTargetDSPVolume(float fileVol, bool music) {
|
||||
if (music)
|
||||
|
@ -1000,7 +1007,7 @@ void CStreamAudioManager::UpdateDSPStreamers(float dt) {
|
|||
}
|
||||
|
||||
void CStreamAudioManager::StopAllStreams() {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (size_t i = 0; i < s_Players.size(); ++i) {
|
||||
StopStreaming(bool(i));
|
||||
SDSPPlayer& p = s_Players[i];
|
||||
SDSPPlayer& qp = s_QueuedPlayers[i];
|
||||
|
|
|
@ -158,7 +158,7 @@ bool CAutoMapper::CanLeaveMapScreenInternal(const CStateManager& mgr) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
void CAutoMapper::LeaveMapScreen(const CStateManager& mgr) {
|
||||
void CAutoMapper::LeaveMapScreen(CStateManager& mgr) {
|
||||
if (x1c0_nextState == EAutoMapperState::MapScreenUniverse) {
|
||||
xa8_renderStates[1].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth();
|
||||
xa8_renderStates[1].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth();
|
||||
|
@ -180,9 +180,9 @@ void CAutoMapper::LeaveMapScreen(const CStateManager& mgr) {
|
|||
}
|
||||
}
|
||||
|
||||
void CAutoMapper::SetupMiniMapWorld(const CStateManager& mgr) {
|
||||
const CWorld& wld = *mgr.GetWorld();
|
||||
const_cast<CMapWorld*>(wld.GetMapWorld())->SetWhichMapAreasLoaded(wld, wld.GetCurrentAreaId(), 3);
|
||||
void CAutoMapper::SetupMiniMapWorld(CStateManager& mgr) {
|
||||
CWorld& wld = *mgr.GetWorld();
|
||||
wld.GetMapWorld()->SetWhichMapAreasLoaded(wld, wld.GetCurrentAreaId(), 3);
|
||||
x328_ = 3;
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ bool CAutoMapper::HasCurrentMapUniverseWorld() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CAutoMapper::CheckDummyWorldLoad(const CStateManager& mgr) {
|
||||
bool CAutoMapper::CheckDummyWorldLoad(CStateManager& mgr) {
|
||||
const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx);
|
||||
auto& dummyWorld = x14_dummyWorlds[x9c_worldIdx];
|
||||
if (!dummyWorld) {
|
||||
|
@ -216,13 +216,13 @@ bool CAutoMapper::CheckDummyWorldLoad(const CStateManager& mgr) {
|
|||
}
|
||||
xa0_curAreaId = aid;
|
||||
|
||||
dummyWorld->IMapWorld()->RecalculateWorldSphere(mwInfo, *dummyWorld);
|
||||
dummyWorld->IGetMapWorld()->RecalculateWorldSphere(mwInfo, *dummyWorld);
|
||||
BeginMapperStateTransition(EAutoMapperState::MapScreen, mgr);
|
||||
x32c_loadingDummyWorld = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAutoMapper::UpdateHintNavigation(float dt, const CStateManager& mgr) {
|
||||
void CAutoMapper::UpdateHintNavigation(float dt, CStateManager& mgr) {
|
||||
SAutoMapperHintStep& nextStep = x1e0_hintSteps.front();
|
||||
bool oldProcessing = nextStep.x8_processing;
|
||||
nextStep.x8_processing = true;
|
||||
|
@ -321,7 +321,7 @@ void CAutoMapper::SetCurWorldAssetId(CAssetId mlvlId) {
|
|||
}
|
||||
}
|
||||
|
||||
void CAutoMapper::BeginMapperStateTransition(EAutoMapperState state, const CStateManager& mgr) {
|
||||
void CAutoMapper::BeginMapperStateTransition(EAutoMapperState state, CStateManager& mgr) {
|
||||
if (state == x1c0_nextState)
|
||||
return;
|
||||
if ((state == EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) ||
|
||||
|
@ -372,7 +372,7 @@ void CAutoMapper::BeginMapperStateTransition(EAutoMapperState state, const CStat
|
|||
}
|
||||
}
|
||||
|
||||
void CAutoMapper::CompleteMapperStateTransition(const CStateManager& mgr) {
|
||||
void CAutoMapper::CompleteMapperStateTransition(CStateManager& mgr) {
|
||||
if (x1bc_state == EAutoMapperState::MapScreenUniverse)
|
||||
TransformRenderStatesUniverseToWorld();
|
||||
|
||||
|
@ -407,8 +407,8 @@ void CAutoMapper::CompleteMapperStateTransition(const CStateManager& mgr) {
|
|||
x1bc_state = x1c0_nextState;
|
||||
}
|
||||
|
||||
void CAutoMapper::ResetInterpolationTimer(float t) {
|
||||
x1c4_interpDur = t;
|
||||
void CAutoMapper::ResetInterpolationTimer(float duration) {
|
||||
x1c4_interpDur = duration;
|
||||
x1c8_interpTime = 0.f;
|
||||
}
|
||||
|
||||
|
@ -754,8 +754,8 @@ void CAutoMapper::ProcessMapPanInput(const CFinalInput& input, const CStateManag
|
|||
}
|
||||
}
|
||||
|
||||
void CAutoMapper::SetShouldPanningSoundBePlaying(bool b) {
|
||||
if (b) {
|
||||
void CAutoMapper::SetShouldPanningSoundBePlaying(bool shouldBePlaying) {
|
||||
if (shouldBePlaying) {
|
||||
if (!x1cc_panningSfx)
|
||||
x1cc_panningSfx = CSfxManager::SfxStart(SFXui_map_pan, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId);
|
||||
} else {
|
||||
|
@ -764,8 +764,8 @@ void CAutoMapper::SetShouldPanningSoundBePlaying(bool b) {
|
|||
}
|
||||
}
|
||||
|
||||
void CAutoMapper::SetShouldZoomingSoundBePlaying(bool b) {
|
||||
if (b) {
|
||||
void CAutoMapper::SetShouldZoomingSoundBePlaying(bool shouldBePlaying) {
|
||||
if (shouldBePlaying) {
|
||||
if (!x1d4_zoomingSfx)
|
||||
x1d4_zoomingSfx = CSfxManager::SfxStart(SFXui_map_zoom, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId);
|
||||
} else {
|
||||
|
@ -774,8 +774,8 @@ void CAutoMapper::SetShouldZoomingSoundBePlaying(bool b) {
|
|||
}
|
||||
}
|
||||
|
||||
void CAutoMapper::SetShouldRotatingSoundBePlaying(bool b) {
|
||||
if (b) {
|
||||
void CAutoMapper::SetShouldRotatingSoundBePlaying(bool shouldBePlaying) {
|
||||
if (shouldBePlaying) {
|
||||
if (!x1d0_rotatingSfx)
|
||||
x1d0_rotatingSfx = CSfxManager::SfxStart(SFXui_map_rotate, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId);
|
||||
} else {
|
||||
|
@ -784,7 +784,7 @@ void CAutoMapper::SetShouldRotatingSoundBePlaying(bool b) {
|
|||
}
|
||||
}
|
||||
|
||||
void CAutoMapper::ProcessMapScreenInput(const CFinalInput& input, const CStateManager& mgr) {
|
||||
void CAutoMapper::ProcessMapScreenInput(const CFinalInput& input, CStateManager& mgr) {
|
||||
zeus::CMatrix3f camRot = xa8_renderStates[0].x8_camOrientation.toTransform().buildMatrix3f();
|
||||
if (x1bc_state == EAutoMapperState::MapScreen) {
|
||||
if ((input.PA() || input.PSpecialKey(boo::ESpecialKey::Enter)) && x328_ == 0 && HasCurrentMapUniverseWorld())
|
||||
|
@ -968,10 +968,11 @@ float CAutoMapper::GetDesiredMiniMapCameraDistance(const CStateManager& mgr) con
|
|||
std::tan(M_PIF / 2.f - 0.5f * 2.f * M_PIF * (xa8_renderStates[0].x1c_camAngle / 360.f));
|
||||
}
|
||||
|
||||
float CAutoMapper::GetClampedMapScreenCameraDistance(float v) const {
|
||||
if (x1bc_state == EAutoMapperState::MapScreenUniverse)
|
||||
return zeus::clamp(g_tweakAutoMapper->GetMinUniverseCamDist(), v, g_tweakAutoMapper->GetMaxUniverseCamDist());
|
||||
return zeus::clamp(g_tweakAutoMapper->GetMinCamDist(), v, g_tweakAutoMapper->GetMaxCamDist());
|
||||
float CAutoMapper::GetClampedMapScreenCameraDistance(float value) const {
|
||||
if (x1bc_state == EAutoMapperState::MapScreenUniverse) {
|
||||
return zeus::clamp(g_tweakAutoMapper->GetMinUniverseCamDist(), value, g_tweakAutoMapper->GetMaxUniverseCamDist());
|
||||
}
|
||||
return zeus::clamp(g_tweakAutoMapper->GetMinCamDist(), value, g_tweakAutoMapper->GetMaxCamDist());
|
||||
}
|
||||
|
||||
void CAutoMapper::MuteAllLoopedSounds() {
|
||||
|
@ -1092,7 +1093,7 @@ void CAutoMapper::ProcessControllerInput(const CFinalInput& input, CStateManager
|
|||
}
|
||||
}
|
||||
|
||||
void CAutoMapper::Update(float dt, const CStateManager& mgr) {
|
||||
void CAutoMapper::Update(float dt, CStateManager& mgr) {
|
||||
if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) {
|
||||
x1d8_flashTimer = std::fmod(x1d8_flashTimer + dt, 0.75f);
|
||||
x1dc_playerFlashPulse = x1d8_flashTimer < 0.375f ? x1d8_flashTimer / 0.375f : (0.75f - x1d8_flashTimer) / 0.375f;
|
||||
|
@ -1288,7 +1289,7 @@ void CAutoMapper::Update(float dt, const CStateManager& mgr) {
|
|||
wld->ICheckWorldComplete();
|
||||
}
|
||||
|
||||
void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, float alpha) const {
|
||||
void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, float alpha) {
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP("CAutoMapper::Draw", zeus::skPurple);
|
||||
alpha *= g_GameState->GameOptions().GetHUDAlpha() / 255.f;
|
||||
// Blend mode alpha
|
||||
|
@ -1341,7 +1342,7 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
|
|||
if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) {
|
||||
if (universeInterp < 1.f && x24_world) {
|
||||
const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo();
|
||||
const CMapWorld* mw = x24_world->IGetMapWorld();
|
||||
CMapWorld* mw = x24_world->IGetMapWorld();
|
||||
float hintFlash = 0.f;
|
||||
if (x1e0_hintSteps.size() && x1e0_hintSteps.front().x0_type == SAutoMapperHintStep::Type::ShowBeacon) {
|
||||
if (xa0_curAreaId == mgr.GetNextAreaId() && x24_world == mgr.GetWorld()) {
|
||||
|
@ -1360,35 +1361,37 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
|
|||
}
|
||||
}
|
||||
}
|
||||
zeus::CTransform modelXf = planeXf * preXf;
|
||||
CMapWorld::CMapWorldDrawParms parms(xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp,
|
||||
xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp,
|
||||
xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp,
|
||||
xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, mapAlpha, 2.f,
|
||||
mgr, modelXf, camXf, *x24_world, mwInfo, x1dc_playerFlashPulse, hintFlash,
|
||||
objectScale, true);
|
||||
const zeus::CTransform modelXf = planeXf * preXf;
|
||||
const CMapWorld::CMapWorldDrawParms parms(xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp,
|
||||
xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp,
|
||||
xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp,
|
||||
xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, mapAlpha,
|
||||
2.f, mgr, modelXf, camXf, *x24_world, mwInfo, x1dc_playerFlashPulse,
|
||||
hintFlash, objectScale, true);
|
||||
mw->Draw(parms, xa0_curAreaId, xa0_curAreaId, xa8_renderStates[0].x2c_drawDepth1,
|
||||
xa8_renderStates[0].x30_drawDepth2, true);
|
||||
}
|
||||
} else if (IsInMapperState(EAutoMapperState::MiniMap)) {
|
||||
const CMapWorld* mw = x24_world->IGetMapWorld();
|
||||
CMapWorld* mw = x24_world->IGetMapWorld();
|
||||
const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo();
|
||||
CMapWorld::CMapWorldDrawParms parms(xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp,
|
||||
xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp,
|
||||
xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp,
|
||||
xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, mapAlpha, 1.f, mgr,
|
||||
planeXf, camXf, *x24_world, mwInfo, 0.f, 0.f, objectScale, false);
|
||||
const CMapWorld::CMapWorldDrawParms parms(xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp,
|
||||
xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp,
|
||||
xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp,
|
||||
xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, mapAlpha,
|
||||
1.f, mgr, planeXf, camXf, *x24_world, mwInfo, 0.f, 0.f, objectScale,
|
||||
false);
|
||||
mw->Draw(parms, xa0_curAreaId, xa4_otherAreaId, xa8_renderStates[0].x2c_drawDepth1,
|
||||
xa8_renderStates[0].x30_drawDepth2, false);
|
||||
} else {
|
||||
const CMapWorld* mw = x24_world->IGetMapWorld();
|
||||
CMapWorld* mw = x24_world->IGetMapWorld();
|
||||
const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo();
|
||||
zeus::CTransform modelXf = planeXf * preXf;
|
||||
CMapWorld::CMapWorldDrawParms parms(xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp,
|
||||
xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp,
|
||||
xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp,
|
||||
xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, mapAlpha, 2.f, mgr,
|
||||
modelXf, camXf, *x24_world, mwInfo, 0.f, 0.f, objectScale, true);
|
||||
const CMapWorld::CMapWorldDrawParms parms(xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp,
|
||||
xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp,
|
||||
xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp,
|
||||
xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, mapAlpha,
|
||||
2.f, mgr, modelXf, camXf, *x24_world, mwInfo, 0.f, 0.f, objectScale,
|
||||
true);
|
||||
mw->Draw(parms, xa0_curAreaId, xa0_curAreaId, xa8_renderStates[0].x2c_drawDepth1,
|
||||
xa8_renderStates[0].x30_drawDepth2, false);
|
||||
}
|
||||
|
@ -1410,8 +1413,8 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
|
|||
}
|
||||
}
|
||||
|
||||
CMapUniverse::CMapUniverseDrawParms parms(universeInterp, x9c_worldIdx, g_GameState->CurrentWorldAssetId(), hexIdx,
|
||||
x1dc_playerFlashPulse, mgr, planeXf, camXf);
|
||||
const CMapUniverse::CMapUniverseDrawParms parms(universeInterp, x9c_worldIdx, g_GameState->CurrentWorldAssetId(),
|
||||
hexIdx, x1dc_playerFlashPulse, mgr, planeXf, camXf);
|
||||
x8_mapu->Draw(parms, zeus::skZero3f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
|
@ -1444,7 +1447,7 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
|
|||
if (IsInMapperState(EAutoMapperState::MapScreen)) {
|
||||
CAssetId wldMlvl = x24_world->IGetWorldAssetId();
|
||||
const CMapWorld* mw = x24_world->IGetMapWorld();
|
||||
std::vector<CTexturedQuadFilter>& hintBeaconFilters = const_cast<CAutoMapper&>(*this).m_hintBeaconFilters;
|
||||
std::vector<CTexturedQuadFilter>& hintBeaconFilters = m_hintBeaconFilters;
|
||||
if (hintBeaconFilters.size() < x1f8_hintLocations.size()) {
|
||||
hintBeaconFilters.reserve(x1f8_hintLocations.size());
|
||||
for (u32 i = hintBeaconFilters.size(); i < x1f8_hintLocations.size(); ++i)
|
||||
|
@ -1601,11 +1604,11 @@ CAssetId CAutoMapper::GetAreaHintDescriptionString(CAssetId mreaId) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void CAutoMapper::OnNewInGameGuiState(EInGameGuiState state, const CStateManager& mgr) {
|
||||
void CAutoMapper::OnNewInGameGuiState(EInGameGuiState state, CStateManager& mgr) {
|
||||
if (state == EInGameGuiState::MapScreen) {
|
||||
MP1::CMain::EnsureWorldPaksReady();
|
||||
const CWorld& wld = *mgr.GetWorld();
|
||||
const_cast<CMapWorld*>(wld.GetMapWorld())->SetWhichMapAreasLoaded(wld, 0, 9999);
|
||||
CWorld& wld = *mgr.GetWorld();
|
||||
wld.GetMapWorld()->SetWhichMapAreasLoaded(wld, 0, 9999);
|
||||
SetupHintNavigation();
|
||||
BeginMapperStateTransition(EAutoMapperState::MapScreen, mgr);
|
||||
x28_frmeMapScreen = g_SimplePool->GetObj("FRME_MapScreen");
|
||||
|
|
|
@ -128,7 +128,7 @@ private:
|
|||
ELoadPhase x4_loadPhase = ELoadPhase::LoadResources;
|
||||
TLockedToken<CMapUniverse> x8_mapu;
|
||||
std::vector<std::unique_ptr<IWorld>> x14_dummyWorlds;
|
||||
const CWorld* x24_world;
|
||||
CWorld* x24_world;
|
||||
TLockedToken<CGuiFrame> x28_frmeMapScreen; // Used to be ptr
|
||||
bool m_frmeInitialized = false;
|
||||
TLockedToken<CModel> x30_miniMapSamus;
|
||||
|
@ -194,29 +194,29 @@ private:
|
|||
}
|
||||
bool NotHintNavigating() const;
|
||||
bool CanLeaveMapScreenInternal(const CStateManager& mgr) const;
|
||||
void LeaveMapScreen(const CStateManager& mgr);
|
||||
void SetupMiniMapWorld(const CStateManager& mgr);
|
||||
void LeaveMapScreen(CStateManager& mgr);
|
||||
void SetupMiniMapWorld(CStateManager& mgr);
|
||||
bool HasCurrentMapUniverseWorld() const;
|
||||
bool CheckDummyWorldLoad(const CStateManager& mgr);
|
||||
void UpdateHintNavigation(float dt, const CStateManager& mgr);
|
||||
bool CheckDummyWorldLoad(CStateManager& mgr);
|
||||
void UpdateHintNavigation(float dt, CStateManager& mgr);
|
||||
static zeus::CVector2i GetMiniMapViewportSize();
|
||||
static zeus::CVector2i GetMapScreenViewportSize();
|
||||
static float GetMapAreaMiniMapDrawDepth() { return 2.f; }
|
||||
float GetMapAreaMaxDrawDepth(const CStateManager&, TAreaId) const;
|
||||
static float GetMapAreaMiniMapDrawAlphaSurfaceVisited(const CStateManager&);
|
||||
static float GetMapAreaMiniMapDrawAlphaOutlineVisited(const CStateManager&);
|
||||
static float GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(const CStateManager&);
|
||||
static float GetMapAreaMiniMapDrawAlphaOutlineUnvisited(const CStateManager&);
|
||||
float GetDesiredMiniMapCameraDistance(const CStateManager&) const;
|
||||
float GetMapAreaMaxDrawDepth(const CStateManager& mgr, TAreaId aid) const;
|
||||
static float GetMapAreaMiniMapDrawAlphaSurfaceVisited(const CStateManager& mgr);
|
||||
static float GetMapAreaMiniMapDrawAlphaOutlineVisited(const CStateManager& mgr);
|
||||
static float GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(const CStateManager& mgr);
|
||||
static float GetMapAreaMiniMapDrawAlphaOutlineUnvisited(const CStateManager& mgr);
|
||||
float GetDesiredMiniMapCameraDistance(const CStateManager& mgr) const;
|
||||
static float GetBaseMapScreenCameraMoveSpeed();
|
||||
float GetClampedMapScreenCameraDistance(float) const;
|
||||
float GetClampedMapScreenCameraDistance(float value) const;
|
||||
float GetFinalMapScreenCameraMoveSpeed() const;
|
||||
void ProcessMapRotateInput(const CFinalInput& input, const CStateManager& mgr);
|
||||
void ProcessMapZoomInput(const CFinalInput& input, const CStateManager& mgr);
|
||||
void ProcessMapPanInput(const CFinalInput& input, const CStateManager& mgr);
|
||||
void SetShouldPanningSoundBePlaying(bool);
|
||||
void SetShouldZoomingSoundBePlaying(bool);
|
||||
void SetShouldRotatingSoundBePlaying(bool);
|
||||
void SetShouldPanningSoundBePlaying(bool shouldBePlaying);
|
||||
void SetShouldZoomingSoundBePlaying(bool shouldBePlaying);
|
||||
void SetShouldRotatingSoundBePlaying(bool shouldBePlaying);
|
||||
void TransformRenderStatesWorldToUniverse();
|
||||
void TransformRenderStatesUniverseToWorld();
|
||||
void TransformRenderStateWorldToUniverse(SAutoMapperRenderState&);
|
||||
|
@ -224,9 +224,9 @@ private:
|
|||
CAssetId GetAreaHintDescriptionString(CAssetId mreaId);
|
||||
|
||||
public:
|
||||
CAutoMapper(CStateManager& stateMgr);
|
||||
explicit CAutoMapper(CStateManager& stateMgr);
|
||||
bool CheckLoadComplete();
|
||||
bool CanLeaveMapScreen(const CStateManager&) const;
|
||||
bool CanLeaveMapScreen(const CStateManager& mgr) const;
|
||||
float GetMapRotationX() const { return xa8_renderStates[0].x1c_camAngle; }
|
||||
float GetMapRotationZ() const { return xa8_renderStates[0].x8_camOrientation.yaw(); }
|
||||
TAreaId GetFocusAreaIndex() const { return xa0_curAreaId; }
|
||||
|
@ -234,29 +234,30 @@ public:
|
|||
void SetCurWorldAssetId(CAssetId mlvlId);
|
||||
void MuteAllLoopedSounds();
|
||||
void UnmuteAllLoopedSounds();
|
||||
void ProcessControllerInput(const CFinalInput&, CStateManager&);
|
||||
void ProcessControllerInput(const CFinalInput& input, CStateManager& mgr);
|
||||
bool IsInPlayerControlState() const {
|
||||
return IsInMapperState(EAutoMapperState::MapScreen) || IsInMapperState(EAutoMapperState::MapScreenUniverse);
|
||||
}
|
||||
void Update(float dt, const CStateManager& mgr);
|
||||
void Draw(const CStateManager&, const zeus::CTransform&, float) const;
|
||||
void Update(float dt, CStateManager& mgr);
|
||||
void Draw(const CStateManager& mgr, const zeus::CTransform& xf, float alpha);
|
||||
float GetTimeIntoInterpolation() const { return x1c8_interpTime; }
|
||||
void BeginMapperStateTransition(EAutoMapperState, const CStateManager&);
|
||||
void CompleteMapperStateTransition(const CStateManager&);
|
||||
void ResetInterpolationTimer(float);
|
||||
SAutoMapperRenderState BuildMiniMapWorldRenderState(const CStateManager&, const zeus::CQuaternion&, TAreaId) const;
|
||||
SAutoMapperRenderState BuildMapScreenWorldRenderState(const CStateManager&, const zeus::CQuaternion&, TAreaId,
|
||||
bool) const;
|
||||
SAutoMapperRenderState BuildMapScreenUniverseRenderState(const CStateManager&, const zeus::CQuaternion&,
|
||||
TAreaId) const;
|
||||
void BeginMapperStateTransition(EAutoMapperState state, CStateManager& mgr);
|
||||
void CompleteMapperStateTransition(CStateManager& mgr);
|
||||
void ResetInterpolationTimer(float duration);
|
||||
SAutoMapperRenderState BuildMiniMapWorldRenderState(const CStateManager& stateMgr, const zeus::CQuaternion& rot,
|
||||
TAreaId area) const;
|
||||
SAutoMapperRenderState BuildMapScreenWorldRenderState(const CStateManager& mgr, const zeus::CQuaternion& rot,
|
||||
TAreaId area, bool doingHint) const;
|
||||
SAutoMapperRenderState BuildMapScreenUniverseRenderState(const CStateManager& mgr, const zeus::CQuaternion& rot,
|
||||
TAreaId area) const;
|
||||
void LeaveMapScreenState();
|
||||
void ProcessMapScreenInput(const CFinalInput& input, const CStateManager& mgr);
|
||||
zeus::CQuaternion GetMiniMapCameraOrientation(const CStateManager&) const;
|
||||
zeus::CVector3f GetAreaPointOfInterest(const CStateManager&, TAreaId) const;
|
||||
TAreaId FindClosestVisibleArea(const zeus::CVector3f&, const zeus::CUnitVector3f&, const CStateManager&,
|
||||
const IWorld&, const CMapWorldInfo&) const;
|
||||
std::pair<int, int> FindClosestVisibleWorld(const zeus::CVector3f&, const zeus::CUnitVector3f&,
|
||||
const CStateManager&) const;
|
||||
void ProcessMapScreenInput(const CFinalInput& input, CStateManager& mgr);
|
||||
zeus::CQuaternion GetMiniMapCameraOrientation(const CStateManager& stateMgr) const;
|
||||
zeus::CVector3f GetAreaPointOfInterest(const CStateManager& mgr, TAreaId aid) const;
|
||||
TAreaId FindClosestVisibleArea(const zeus::CVector3f& point, const zeus::CUnitVector3f& camDir,
|
||||
const CStateManager& mgr, const IWorld& wld, const CMapWorldInfo& mwInfo) const;
|
||||
std::pair<int, int> FindClosestVisibleWorld(const zeus::CVector3f& point, const zeus::CUnitVector3f& camDir,
|
||||
const CStateManager& mgr) const;
|
||||
|
||||
EAutoMapperState GetNextState() const { return x1c0_nextState; }
|
||||
bool IsInMapperState(EAutoMapperState state) const { return state == x1bc_state && state == x1c0_nextState; }
|
||||
|
@ -267,7 +268,7 @@ public:
|
|||
bool IsFullyOutOfMiniMapState() const {
|
||||
return x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap;
|
||||
}
|
||||
void OnNewInGameGuiState(EInGameGuiState, const CStateManager&);
|
||||
void OnNewInGameGuiState(EInGameGuiState state, CStateManager& mgr);
|
||||
float GetInterp() const {
|
||||
if (x1c4_interpDur > 0.f)
|
||||
return x1c8_interpTime / x1c4_interpDur;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "Runtime/AutoMapper/CMapArea.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
#include "Runtime/CResFactory.hpp"
|
||||
#include "Runtime/CToken.hpp"
|
||||
#include "Runtime/GameGlobalObjects.hpp"
|
||||
|
@ -8,101 +11,13 @@
|
|||
#include "Runtime/World/CWorld.hpp"
|
||||
|
||||
namespace urde {
|
||||
CMapArea::CMapArea(CInputStream& in, u32 size)
|
||||
: x0_magic(in.readUint32())
|
||||
, x4_version(in.readUint32Big())
|
||||
, x8_(in.readUint32Big())
|
||||
, xc_visibilityMode(EVisMode(in.readUint32Big()))
|
||||
, x10_box(zeus::CAABox::ReadBoundingBoxBig(in))
|
||||
, x28_mappableObjCount(in.readUint32Big())
|
||||
, x2c_vertexCount(in.readUint32Big())
|
||||
, x30_surfaceCount(in.readUint32Big())
|
||||
, x34_size(size - 52) {
|
||||
x44_buf.reset(new u8[x34_size]);
|
||||
in.readUBytesToBuf(x44_buf.get(), x34_size);
|
||||
PostConstruct();
|
||||
}
|
||||
constexpr std::array<zeus::CVector3f, 3> MinesPostTransforms{{
|
||||
{0.f, 0.f, 200.f},
|
||||
{0.f, 0.f, 0.f},
|
||||
{0.f, 0.f, -200.f},
|
||||
}};
|
||||
|
||||
void CMapArea::PostConstruct() {
|
||||
x38_moStart = x44_buf.get();
|
||||
x3c_vertexStart = x38_moStart + (x28_mappableObjCount * 0x50);
|
||||
x40_surfaceStart = x3c_vertexStart + (x2c_vertexCount * 12);
|
||||
|
||||
m_mappableObjects.reserve(x28_mappableObjCount);
|
||||
for (u32 i = 0, j = 0; i < x28_mappableObjCount; ++i, j += 0x50) {
|
||||
m_mappableObjects.emplace_back(x38_moStart + j).PostConstruct(x44_buf.get());
|
||||
}
|
||||
|
||||
u8* tmp = x3c_vertexStart;
|
||||
m_verts.reserve(x2c_vertexCount);
|
||||
for (u32 i = 0; i < x2c_vertexCount; ++i) {
|
||||
float* fl = reinterpret_cast<float*>(tmp);
|
||||
m_verts.emplace_back(hecl::SBig(fl[0]), hecl::SBig(fl[1]), hecl::SBig(fl[2]));
|
||||
tmp += 12;
|
||||
}
|
||||
|
||||
std::vector<u32> index;
|
||||
m_surfaces.reserve(x30_surfaceCount);
|
||||
for (u32 i = 0, j = 0; i < x30_surfaceCount; ++i, j += 32) {
|
||||
m_surfaces.emplace_back(x40_surfaceStart + j).PostConstruct(x44_buf.get(), index);
|
||||
}
|
||||
|
||||
CGraphics::CommitResources([this, &index](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, m_verts.data(), 16, m_verts.size());
|
||||
m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, index.data(), 4, index.size());
|
||||
|
||||
/* Only the map universe specifies Always; it draws a maximum of 1016 instances */
|
||||
size_t instCount = (xc_visibilityMode == EVisMode::Always) ? 1024 : 1;
|
||||
|
||||
for (u32 i = 0; i < x30_surfaceCount; ++i) {
|
||||
CMapAreaSurface& surf = m_surfaces[i];
|
||||
surf.m_instances.reserve(instCount);
|
||||
for (u32 inst = 0; inst < instCount; ++inst) {
|
||||
CMapAreaSurface::Instance& instance = surf.m_instances.emplace_back(ctx, m_vbo, m_ibo);
|
||||
|
||||
athena::io::MemoryReader r(surf.x1c_outlineOffset, INT_MAX);
|
||||
u32 outlineCount = r.readUint32Big();
|
||||
|
||||
std::vector<CLineRenderer>& linePrims = instance.m_linePrims;
|
||||
linePrims.reserve(outlineCount * 2);
|
||||
for (u32 j = 0; j < 2; ++j) {
|
||||
r.seek(4, athena::SeekOrigin::Begin);
|
||||
for (u32 i = 0; i < outlineCount; ++i) {
|
||||
u32 count = r.readUint32Big();
|
||||
r.seek(count);
|
||||
r.seekAlign4();
|
||||
linePrims.emplace_back(ctx, CLineRenderer::EPrimitiveMode::LineStrip, count, nullptr, false, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < x28_mappableObjCount; ++i) {
|
||||
CMappableObject& mapObj = m_mappableObjects[i];
|
||||
if (CMappableObject::IsDoorType(mapObj.GetType()))
|
||||
mapObj.CreateDoorSurface(ctx);
|
||||
}
|
||||
return true;
|
||||
} BooTrace);
|
||||
}
|
||||
|
||||
bool CMapArea::GetIsVisibleToAutoMapper(bool worldVis, bool areaVis) const {
|
||||
switch (xc_visibilityMode) {
|
||||
case EVisMode::Always:
|
||||
return true;
|
||||
case EVisMode::MapStationOrVisit:
|
||||
return worldVis || areaVis;
|
||||
case EVisMode::Visit:
|
||||
return areaVis;
|
||||
case EVisMode::Never:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static const zeus::CVector3f MinesPostTransforms[3] = {{0.f, 0.f, 200.f}, {0.f, 0.f, 0.f}, {0.f, 0.f, -200.f}};
|
||||
static const u8 MinesPostTransformIndices[] = {
|
||||
constexpr std::array<u8, 42> MinesPostTransformIndices{
|
||||
0, // 00 Transport to Tallon Overworld South
|
||||
0, // 01 Quarry Access
|
||||
0, // 02 Main Quarry
|
||||
|
@ -147,6 +62,105 @@ static const u8 MinesPostTransformIndices[] = {
|
|||
2, // 41 Fungal Hall A
|
||||
};
|
||||
|
||||
CMapArea::CMapArea(CInputStream& in, u32 size)
|
||||
: x0_magic(in.readUint32())
|
||||
, x4_version(in.readUint32Big())
|
||||
, x8_(in.readUint32Big())
|
||||
, xc_visibilityMode(EVisMode(in.readUint32Big()))
|
||||
, x10_box(zeus::CAABox::ReadBoundingBoxBig(in))
|
||||
, x28_mappableObjCount(in.readUint32Big())
|
||||
, x2c_vertexCount(in.readUint32Big())
|
||||
, x30_surfaceCount(in.readUint32Big())
|
||||
, x34_size(size - 52) {
|
||||
x44_buf.reset(new u8[x34_size]);
|
||||
in.readUBytesToBuf(x44_buf.get(), x34_size);
|
||||
PostConstruct();
|
||||
}
|
||||
|
||||
void CMapArea::PostConstruct() {
|
||||
x38_moStart = x44_buf.get();
|
||||
x3c_vertexStart = x38_moStart + (x28_mappableObjCount * 0x50);
|
||||
x40_surfaceStart = x3c_vertexStart + (x2c_vertexCount * 12);
|
||||
|
||||
m_mappableObjects.reserve(x28_mappableObjCount);
|
||||
for (u32 i = 0, j = 0; i < x28_mappableObjCount; ++i, j += 0x50) {
|
||||
m_mappableObjects.emplace_back(x38_moStart + j).PostConstruct(x44_buf.get());
|
||||
}
|
||||
|
||||
u8* tmp = x3c_vertexStart;
|
||||
m_verts.reserve(x2c_vertexCount);
|
||||
for (u32 i = 0; i < x2c_vertexCount; ++i) {
|
||||
float x;
|
||||
std::memcpy(&x, tmp, sizeof(float));
|
||||
float y;
|
||||
std::memcpy(&y, tmp + 4, sizeof(float));
|
||||
float z;
|
||||
std::memcpy(&z, tmp + 8, sizeof(float));
|
||||
|
||||
m_verts.emplace_back(hecl::SBig(x), hecl::SBig(y), hecl::SBig(z));
|
||||
tmp += 12;
|
||||
}
|
||||
|
||||
std::vector<u32> index;
|
||||
m_surfaces.reserve(x30_surfaceCount);
|
||||
for (u32 i = 0, j = 0; i < x30_surfaceCount; ++i, j += 32) {
|
||||
m_surfaces.emplace_back(x40_surfaceStart + j).PostConstruct(x44_buf.get(), index);
|
||||
}
|
||||
|
||||
CGraphics::CommitResources([this, &index](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, m_verts.data(), 16, m_verts.size());
|
||||
m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, index.data(), 4, index.size());
|
||||
|
||||
/* Only the map universe specifies Always; it draws a maximum of 1016 instances */
|
||||
size_t instCount = (xc_visibilityMode == EVisMode::Always) ? 1024 : 1;
|
||||
|
||||
for (u32 i = 0; i < x30_surfaceCount; ++i) {
|
||||
CMapAreaSurface& surf = m_surfaces[i];
|
||||
surf.m_instances.reserve(instCount);
|
||||
for (u32 inst = 0; inst < instCount; ++inst) {
|
||||
CMapAreaSurface::Instance& instance = surf.m_instances.emplace_back(ctx, m_vbo, m_ibo);
|
||||
|
||||
athena::io::MemoryReader r(surf.x1c_outlineOffset, INT_MAX);
|
||||
u32 outlineCount = r.readUint32Big();
|
||||
|
||||
std::vector<CLineRenderer>& linePrims = instance.m_linePrims;
|
||||
linePrims.reserve(outlineCount * 2);
|
||||
for (u32 j = 0; j < 2; ++j) {
|
||||
r.seek(4, athena::SeekOrigin::Begin);
|
||||
for (u32 k = 0; k < outlineCount; ++k) {
|
||||
const u32 count = r.readUint32Big();
|
||||
r.seek(count);
|
||||
r.seekAlign4();
|
||||
linePrims.emplace_back(ctx, CLineRenderer::EPrimitiveMode::LineStrip, count, nullptr, false, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < x28_mappableObjCount; ++i) {
|
||||
CMappableObject& mapObj = m_mappableObjects[i];
|
||||
if (CMappableObject::IsDoorType(mapObj.GetType()))
|
||||
mapObj.CreateDoorSurface(ctx);
|
||||
}
|
||||
return true;
|
||||
} BooTrace);
|
||||
}
|
||||
|
||||
bool CMapArea::GetIsVisibleToAutoMapper(bool worldVis, bool areaVis) const {
|
||||
switch (xc_visibilityMode) {
|
||||
case EVisMode::Always:
|
||||
return true;
|
||||
case EVisMode::MapStationOrVisit:
|
||||
return worldVis || areaVis;
|
||||
case EVisMode::Visit:
|
||||
return areaVis;
|
||||
case EVisMode::Never:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
zeus::CTransform CMapArea::GetAreaPostTransform(const IWorld& world, TAreaId aid) const {
|
||||
if (world.IGetWorldAssetId() == 0xB1AC4D65) // Phazon Mines
|
||||
{
|
||||
|
@ -243,15 +257,16 @@ void CMapArea::CMapAreaSurface::PostConstruct(const u8* buf, std::vector<u32>& i
|
|||
}
|
||||
|
||||
void CMapArea::CMapAreaSurface::Draw(const zeus::CVector3f* verts, const zeus::CColor& surfColor,
|
||||
const zeus::CColor& lineColor, float lineWidth, size_t instIdx) const {
|
||||
const zeus::CColor& lineColor, float lineWidth, size_t instIdx) {
|
||||
if (instIdx >= m_instances.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Instance& instance = const_cast<Instance&>(m_instances[instIdx]);
|
||||
Instance& instance = m_instances[instIdx];
|
||||
|
||||
if (surfColor.a())
|
||||
if (surfColor.a()) {
|
||||
instance.m_surfacePrims.draw(surfColor, m_primStart, m_primCount);
|
||||
}
|
||||
|
||||
if (lineColor.a()) {
|
||||
bool draw2 = lineWidth > 1.f;
|
||||
|
|
|
@ -38,11 +38,11 @@ public:
|
|||
std::vector<Instance> m_instances;
|
||||
|
||||
public:
|
||||
CMapAreaSurface(const void* surfBuf);
|
||||
explicit CMapAreaSurface(const void* surfBuf);
|
||||
CMapAreaSurface(CMapAreaSurface&&) = default;
|
||||
void PostConstruct(const u8* buf, std::vector<u32>& index);
|
||||
void Draw(const zeus::CVector3f* verts, const zeus::CColor& surfColor, const zeus::CColor& lineColor,
|
||||
float lineWidth, size_t instIdx = 0) const;
|
||||
float lineWidth, size_t instIdx = 0);
|
||||
const zeus::CVector3f& GetNormal() const { return x0_normal; }
|
||||
const zeus::CVector3f& GetCenterPosition() const { return xc_centroid; }
|
||||
};
|
||||
|
@ -69,12 +69,14 @@ private:
|
|||
boo::ObjToken<boo::IGraphicsBufferS> m_ibo;
|
||||
|
||||
public:
|
||||
CMapArea(CInputStream& in, u32 size);
|
||||
explicit CMapArea(CInputStream& in, u32 size);
|
||||
void PostConstruct();
|
||||
bool GetIsVisibleToAutoMapper(bool worldVis, bool areaVis) const;
|
||||
zeus::CVector3f GetAreaCenterPoint() const { return x10_box.center(); }
|
||||
const zeus::CAABox& GetBoundingBox() const { return x10_box; }
|
||||
CMappableObject& GetMappableObject(int idx) { return m_mappableObjects[idx]; }
|
||||
const CMappableObject& GetMappableObject(int idx) const { return m_mappableObjects[idx]; }
|
||||
CMapAreaSurface& GetSurface(int idx) { return m_surfaces[idx]; }
|
||||
const CMapAreaSurface& GetSurface(int idx) const { return m_surfaces[idx]; }
|
||||
u32 GetNumMappableObjects() const { return m_mappableObjects.size(); }
|
||||
u32 GetNumSurfaces() const { return m_surfaces.size(); }
|
||||
|
|
|
@ -38,9 +38,10 @@ CMapUniverse::CMapWorldData::CMapWorldData(CInputStream& in, u32 version)
|
|||
x64_centerPoint *= zeus::CVector3f(1.0f / float(x44_hexagonXfs.size()));
|
||||
}
|
||||
|
||||
void CMapUniverse::Draw(const CMapUniverseDrawParms& parms, const zeus::CVector3f&, float, float) const {
|
||||
if (!x4_hexagonToken.IsLoaded())
|
||||
void CMapUniverse::Draw(const CMapUniverseDrawParms& parms, const zeus::CVector3f&, float, float) {
|
||||
if (!x4_hexagonToken.IsLoaded()) {
|
||||
return;
|
||||
}
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP("CMapUniverse::Draw", zeus::skBlue);
|
||||
|
||||
u32 totalSurfaceCount = 0;
|
||||
|
@ -100,7 +101,7 @@ void CMapUniverse::Draw(const CMapUniverseDrawParms& parms, const zeus::CVector3
|
|||
|
||||
zeus::CTransform hexXf = mwData.GetMapAreaData(info.GetAreaIndex());
|
||||
hexXf.orthonormalize();
|
||||
const CMapArea::CMapAreaSurface& surf = x4_hexagonToken->GetSurface(info.GetObjectIndex());
|
||||
CMapArea::CMapAreaSurface& surf = x4_hexagonToken->GetSurface(info.GetObjectIndex());
|
||||
zeus::CColor color(std::max(0.f, (-parms.GetCameraTransform().basis[1]).dot(hexXf.rotate(surf.GetNormal()))) *
|
||||
g_tweakAutoMapper->GetMapSurfaceNormColorLinear() +
|
||||
g_tweakAutoMapper->GetMapSurfaceNormColorConstant());
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
zeus::CVector3f x64_centerPoint = zeus::skZero3f;
|
||||
|
||||
public:
|
||||
CMapWorldData(CInputStream& in, u32 version);
|
||||
explicit CMapWorldData(CInputStream& in, u32 version);
|
||||
CAssetId GetWorldAssetId() const { return x10_worldAssetId; }
|
||||
const zeus::CVector3f& GetWorldCenterPoint() const { return x64_centerPoint; }
|
||||
std::string_view GetWorldLabel() const { return x0_label; }
|
||||
|
@ -105,7 +105,7 @@ private:
|
|||
float x2c_universeRadius = 1600.f;
|
||||
|
||||
public:
|
||||
CMapUniverse(CInputStream&, u32);
|
||||
explicit CMapUniverse(CInputStream&, u32);
|
||||
const CMapWorldData& GetMapWorldData(s32 idx) const { return x10_worldDatas[idx]; }
|
||||
const CMapWorldData& GetMapWorldDataByWorldId(CAssetId id) const {
|
||||
for (const CMapWorldData& data : x10_worldDatas)
|
||||
|
@ -116,7 +116,7 @@ public:
|
|||
u32 GetNumMapWorldDatas() const { return x10_worldDatas.size(); }
|
||||
float GetMapUniverseRadius() const { return x2c_universeRadius; }
|
||||
const zeus::CVector3f& GetMapUniverseCenterPoint() const { return x20_universeCenter; }
|
||||
void Draw(const CMapUniverseDrawParms&, const zeus::CVector3f&, float, float) const;
|
||||
void Draw(const CMapUniverseDrawParms&, const zeus::CVector3f&, float, float);
|
||||
std::vector<CMapWorldData>::const_iterator begin() const { return x10_worldDatas.cbegin(); }
|
||||
std::vector<CMapWorldData>::const_iterator end() const { return x10_worldDatas.cend(); }
|
||||
};
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "Runtime/AutoMapper/CMapWorld.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
#include "Runtime/CSimplePool.hpp"
|
||||
#include "Runtime/CStateManager.hpp"
|
||||
#include "Runtime/GameGlobalObjects.hpp"
|
||||
|
@ -7,6 +10,254 @@
|
|||
#include "Runtime/World/CWorld.hpp"
|
||||
|
||||
namespace urde {
|
||||
namespace {
|
||||
struct Support {
|
||||
int x0_;
|
||||
std::array<int, 3> x4_;
|
||||
};
|
||||
|
||||
struct Circle2 {
|
||||
zeus::CVector2f x0_point;
|
||||
float x8_radiusSq;
|
||||
};
|
||||
|
||||
struct Circle {
|
||||
zeus::CVector2f x0_point;
|
||||
float x8_radius;
|
||||
Circle(const Circle2& circ2) : x0_point(circ2.x0_point), x8_radius(std::sqrt(circ2.x8_radiusSq)) {}
|
||||
};
|
||||
|
||||
Circle2 ExactCircle1(const zeus::CVector2f* a) { return {*a, 0.f}; }
|
||||
|
||||
Circle2 ExactCircle2(const zeus::CVector2f* a, const zeus::CVector2f* b) {
|
||||
Circle2 ret = {};
|
||||
ret.x0_point = 0.5f * (*a + *b);
|
||||
ret.x8_radiusSq = (*b - *a).magSquared() * 0.25f;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Circle2 ExactCircle3(const zeus::CVector2f* a, const zeus::CVector2f* b, const zeus::CVector2f* c) {
|
||||
Circle2 ret = {};
|
||||
zeus::CVector2f d1 = *b - *a;
|
||||
zeus::CVector2f d2 = *c - *a;
|
||||
float cross = d1.cross(d2);
|
||||
zeus::CVector2f magVec(d1.magSquared() * 0.5f, d2.magSquared() * 0.5f);
|
||||
if (std::fabs(cross) > 0.01f) {
|
||||
zeus::CVector2f tmp((d2.y() * magVec.x() - d1.y() * magVec.y()) / cross,
|
||||
(d1.x() * magVec.y() - d2.x() * magVec.x()) / cross);
|
||||
ret.x0_point = *a + tmp;
|
||||
ret.x8_radiusSq = tmp.magSquared();
|
||||
} else {
|
||||
ret.x8_radiusSq = FLT_MAX;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PointInsideCircle(const zeus::CVector2f& point, const Circle2& circ, float& intersect) {
|
||||
intersect = (point - circ.x0_point).magSquared() - circ.x8_radiusSq;
|
||||
return intersect <= 0.f;
|
||||
}
|
||||
|
||||
Circle2 UpdateSupport1(int idx, const zeus::CVector2f** list, Support& support) {
|
||||
Circle2 ret = ExactCircle2(list[support.x4_[0]], list[idx]);
|
||||
support.x0_ = 2;
|
||||
support.x4_[1] = idx;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Circle2 UpdateSupport2(int idx, const zeus::CVector2f** list, Support& support) {
|
||||
std::array<Circle2, 3> circs{};
|
||||
float intersect;
|
||||
int circIdx = -1;
|
||||
float minRad = FLT_MAX;
|
||||
|
||||
circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]);
|
||||
if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) {
|
||||
minRad = circs[0].x8_radiusSq;
|
||||
circIdx = 0;
|
||||
}
|
||||
|
||||
circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]);
|
||||
if (circs[1].x8_radiusSq < minRad && PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) {
|
||||
circIdx = 1;
|
||||
}
|
||||
|
||||
Circle2 ret;
|
||||
if (circIdx != -1) {
|
||||
ret = circs[circIdx];
|
||||
support.x4_[1 - circIdx] = idx;
|
||||
} else {
|
||||
ret = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]);
|
||||
support.x0_ = 3;
|
||||
support.x4_[2] = idx;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Circle2 UpdateSupport3(int idx, const zeus::CVector2f** list, Support& support) {
|
||||
std::array<Circle2, 6> circs{};
|
||||
float intersect;
|
||||
int circIdxA = -1;
|
||||
int circIdxB = -1;
|
||||
float minRadA = FLT_MAX;
|
||||
float minRadB = FLT_MAX;
|
||||
|
||||
circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]);
|
||||
if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) {
|
||||
if (PointInsideCircle(*list[support.x4_[2]], circs[0], intersect)) {
|
||||
minRadA = circs[0].x8_radiusSq;
|
||||
circIdxA = 0;
|
||||
} else {
|
||||
minRadB = intersect;
|
||||
circIdxB = 0;
|
||||
}
|
||||
} else {
|
||||
minRadB = intersect;
|
||||
circIdxB = 0;
|
||||
}
|
||||
|
||||
circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]);
|
||||
if (circs[1].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) {
|
||||
if (PointInsideCircle(*list[support.x4_[2]], circs[1], intersect)) {
|
||||
minRadA = circs[1].x8_radiusSq;
|
||||
circIdxA = 1;
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 1;
|
||||
}
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 1;
|
||||
}
|
||||
}
|
||||
|
||||
circs[2] = ExactCircle2(list[support.x4_[2]], list[idx]);
|
||||
if (circs[2].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[0]], circs[2], intersect)) {
|
||||
if (PointInsideCircle(*list[support.x4_[1]], circs[2], intersect)) {
|
||||
minRadA = circs[2].x8_radiusSq;
|
||||
circIdxA = 2;
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 2;
|
||||
}
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 2;
|
||||
}
|
||||
}
|
||||
|
||||
circs[3] = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]);
|
||||
if (circs[3].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[2]], circs[3], intersect)) {
|
||||
minRadA = circs[3].x8_radiusSq;
|
||||
circIdxA = 3;
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 3;
|
||||
}
|
||||
}
|
||||
|
||||
circs[4] = ExactCircle3(list[support.x4_[0]], list[support.x4_[2]], list[idx]);
|
||||
if (circs[4].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[1]], circs[4], intersect)) {
|
||||
minRadA = circs[4].x8_radiusSq;
|
||||
circIdxA = 4;
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 4;
|
||||
}
|
||||
}
|
||||
|
||||
circs[5] = ExactCircle3(list[support.x4_[1]], list[support.x4_[2]], list[idx]);
|
||||
if (circs[5].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[0]], circs[5], intersect)) {
|
||||
circIdxA = 5;
|
||||
} else if (intersect < minRadB) {
|
||||
circIdxB = 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (circIdxA == -1)
|
||||
circIdxA = circIdxB;
|
||||
|
||||
switch (circIdxA) {
|
||||
case 0:
|
||||
support.x0_ = 2;
|
||||
support.x4_[1] = idx;
|
||||
break;
|
||||
case 1:
|
||||
support.x0_ = 2;
|
||||
support.x4_[0] = idx;
|
||||
break;
|
||||
case 2:
|
||||
support.x0_ = 2;
|
||||
support.x4_[0] = support.x4_[2];
|
||||
support.x4_[1] = idx;
|
||||
break;
|
||||
case 3:
|
||||
support.x4_[2] = idx;
|
||||
break;
|
||||
case 4:
|
||||
support.x4_[1] = idx;
|
||||
break;
|
||||
case 5:
|
||||
support.x4_[0] = idx;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return circs[circIdxA];
|
||||
}
|
||||
|
||||
using FSupport = Circle2 (*)(int idx, const zeus::CVector2f** list, Support& support);
|
||||
constexpr std::array<FSupport, 4> SupportFuncs{
|
||||
nullptr,
|
||||
UpdateSupport1,
|
||||
UpdateSupport2,
|
||||
UpdateSupport3,
|
||||
};
|
||||
|
||||
Circle MinCircle(const std::vector<zeus::CVector2f>& coords) {
|
||||
Circle2 ret = {};
|
||||
if (coords.size() >= 1) {
|
||||
std::unique_ptr<const zeus::CVector2f*[]> randArr(new const zeus::CVector2f*[coords.size()]);
|
||||
for (size_t i = 0; i < coords.size(); ++i)
|
||||
randArr[i] = &coords[i];
|
||||
for (int i = coords.size() - 1; i >= 0; --i) {
|
||||
int shuf = rand() % (i + 1);
|
||||
if (shuf != i)
|
||||
std::swap(randArr[i], randArr[shuf]);
|
||||
}
|
||||
ret = ExactCircle1(randArr[0]);
|
||||
|
||||
Support support = {};
|
||||
support.x0_ = 1;
|
||||
for (size_t i = 1; i < coords.size();) {
|
||||
bool broke = false;
|
||||
for (int j = 0; j < support.x0_; ++j) {
|
||||
if ((*randArr[i] - *randArr[support.x4_[j]]).magSquared() < 0.01f) {
|
||||
broke = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
float intersect;
|
||||
if (!broke && !PointInsideCircle(*randArr[i], ret, intersect)) {
|
||||
Circle2 circ = SupportFuncs[support.x0_](i, randArr.get(), support);
|
||||
if (circ.x8_radiusSq > ret.x8_radiusSq) {
|
||||
i = 0;
|
||||
ret = circ;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
CMapWorld::CMapAreaData::CMapAreaData(CAssetId areaRes, EMapAreaList list, CMapAreaData* next)
|
||||
: x0_area(g_SimplePool->GetObj(SObjectTag{FOURCC('MAPA'), areaRes})), x10_list(list), x14_next(next) {}
|
||||
|
@ -60,13 +311,13 @@ void CMapWorld::SetWhichMapAreasLoaded(const IWorld& wld, int start, int count)
|
|||
}
|
||||
}
|
||||
|
||||
bool CMapWorld::IsMapAreasStreaming() const {
|
||||
bool CMapWorld::IsMapAreasStreaming() {
|
||||
bool ret = false;
|
||||
CMapAreaData* data = x10_listHeads[1];
|
||||
while (data != nullptr) {
|
||||
if (data->IsLoaded()) {
|
||||
CMapAreaData* next = data->GetNextMapAreaData();
|
||||
const_cast<CMapWorld*>(this)->MoveMapAreaToList(data, EMapAreaList::Loaded);
|
||||
MoveMapAreaToList(data, EMapAreaList::Loaded);
|
||||
data = next;
|
||||
} else {
|
||||
data = data->GetNextMapAreaData();
|
||||
|
@ -93,7 +344,7 @@ void CMapWorld::MoveMapAreaToList(CMapWorld::CMapAreaData* data, CMapWorld::EMap
|
|||
x10_listHeads[int(list)] = data;
|
||||
}
|
||||
|
||||
s32 CMapWorld::GetCurrentMapAreaDepth(const IWorld& wld, TAreaId aid) const {
|
||||
s32 CMapWorld::GetCurrentMapAreaDepth(const IWorld& wld, TAreaId aid) {
|
||||
ClearTraversedFlags();
|
||||
std::vector<CMapAreaBFSInfo> info;
|
||||
info.reserve(x0_areas.size());
|
||||
|
@ -118,8 +369,8 @@ std::vector<int> CMapWorld::GetVisibleAreas(const IWorld& wld, const CMapWorldIn
|
|||
return ret;
|
||||
}
|
||||
|
||||
void CMapWorld::Draw(const CMapWorld::CMapWorldDrawParms& parms, int curArea, int otherArea, float depth1, float depth2,
|
||||
bool inMapScreen) const {
|
||||
void CMapWorld::Draw(const CMapWorldDrawParms& parms, int curArea, int otherArea, float depth1, float depth2,
|
||||
bool inMapScreen) {
|
||||
if (depth1 == 0.f && depth2 == 0.f)
|
||||
return;
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP("CMapWorld::Draw", zeus::skBlue);
|
||||
|
@ -130,7 +381,7 @@ void CMapWorld::Draw(const CMapWorld::CMapWorldDrawParms& parms, int curArea, in
|
|||
std::vector<CMapAreaBFSInfo> bfsInfos;
|
||||
bfsInfos.reserve(x0_areas.size());
|
||||
if (curArea != otherArea) {
|
||||
const_cast<CMapWorld*>(this)->x20_traversed[otherArea] = true;
|
||||
x20_traversed[otherArea] = true;
|
||||
DoBFS(parms.GetWorld(), curArea, areaDepth, depth1, depth2, true, bfsInfos);
|
||||
|
||||
float lowD1 = std::ceil(depth1 - 1.f);
|
||||
|
@ -150,7 +401,7 @@ void CMapWorld::Draw(const CMapWorld::CMapWorldDrawParms& parms, int curArea, in
|
|||
|
||||
int otherDepth = std::ceil(std::max(newD1, newD2));
|
||||
if (parms.GetWorld().IGetAreaAlways(otherArea)->IIsActive()) {
|
||||
const_cast<CMapWorld*>(this)->x20_traversed[otherArea] = false;
|
||||
x20_traversed[otherArea] = false;
|
||||
DoBFS(parms.GetWorld(), otherArea, otherDepth, newD1, newD2, true, bfsInfos);
|
||||
}
|
||||
} else {
|
||||
|
@ -161,13 +412,13 @@ void CMapWorld::Draw(const CMapWorld::CMapWorldDrawParms& parms, int curArea, in
|
|||
}
|
||||
|
||||
void CMapWorld::DoBFS(const IWorld& wld, int startArea, int areaCount, float surfDepth, float outlineDepth,
|
||||
bool checkLoad, std::vector<CMapAreaBFSInfo>& bfsInfos) const {
|
||||
bool checkLoad, std::vector<CMapAreaBFSInfo>& bfsInfos) {
|
||||
if (areaCount <= 0 || !IsMapAreaValid(wld, startArea, checkLoad))
|
||||
return;
|
||||
|
||||
size_t size = bfsInfos.size();
|
||||
bfsInfos.emplace_back(startArea, 1, surfDepth, outlineDepth);
|
||||
const_cast<CMapWorld*>(this)->x20_traversed[startArea] = true;
|
||||
x20_traversed[startArea] = true;
|
||||
|
||||
for (; size != bfsInfos.size(); ++size) {
|
||||
CMapAreaBFSInfo& testInfo = bfsInfos[size];
|
||||
|
@ -182,7 +433,7 @@ void CMapWorld::DoBFS(const IWorld& wld, int startArea, int areaCount, float sur
|
|||
TAreaId attId = area->IGetAttachedAreaId(i);
|
||||
if (IsMapAreaValid(wld, attId, checkLoad) && !x20_traversed[attId]) {
|
||||
bfsInfos.emplace_back(attId, testInfo.GetDepth() + 1, surfDepth, outlineDepth);
|
||||
const_cast<CMapWorld*>(this)->x20_traversed[attId] = true;
|
||||
x20_traversed[attId] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -197,8 +448,8 @@ bool CMapWorld::IsMapAreaValid(const IWorld& wld, int areaIdx, bool checkLoad) c
|
|||
return true;
|
||||
}
|
||||
|
||||
void CMapWorld::DrawAreas(const CMapWorld::CMapWorldDrawParms& parms, int selArea,
|
||||
const std::vector<CMapAreaBFSInfo>& bfsInfos, bool inMapScreen) const {
|
||||
void CMapWorld::DrawAreas(const CMapWorldDrawParms& parms, int selArea, const std::vector<CMapAreaBFSInfo>& bfsInfos,
|
||||
bool inMapScreen) {
|
||||
// Alpha blend
|
||||
// Line width 1
|
||||
|
||||
|
@ -328,17 +579,18 @@ void CMapWorld::DrawAreas(const CMapWorld::CMapWorldDrawParms& parms, int selAre
|
|||
u32 lastAreaIdx = UINT32_MAX;
|
||||
CMapObjectSortInfo::EObjectCode lastType = CMapObjectSortInfo::EObjectCode::Invalid;
|
||||
for (const CMapObjectSortInfo& info : sortInfos) {
|
||||
const CMapArea* mapa = GetMapArea(info.GetAreaIndex());
|
||||
CMapArea* mapa = GetMapArea(info.GetAreaIndex());
|
||||
zeus::CTransform areaPostXf = mapa->GetAreaPostTransform(parms.GetWorld(), info.GetAreaIndex());
|
||||
if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Surface) {
|
||||
const CMapArea::CMapAreaSurface& surf = mapa->GetSurface(info.GetLocalObjectIndex());
|
||||
CMapArea::CMapAreaSurface& surf = mapa->GetSurface(info.GetLocalObjectIndex());
|
||||
zeus::CColor color(
|
||||
std::max(0.f, (-parms.GetCameraTransform().basis[1]).dot(areaPostXf.rotate(surf.GetNormal()))) *
|
||||
g_tweakAutoMapper->GetMapSurfaceNormColorLinear() +
|
||||
g_tweakAutoMapper->GetMapSurfaceNormColorConstant());
|
||||
color *= info.GetSurfaceColor();
|
||||
if (lastAreaIdx != info.GetAreaIndex() || lastType != CMapObjectSortInfo::EObjectCode::Surface)
|
||||
if (lastAreaIdx != info.GetAreaIndex() || lastType != CMapObjectSortInfo::EObjectCode::Surface) {
|
||||
CGraphics::SetModelMatrix(parms.GetPlaneProjectionTransform() * areaPostXf);
|
||||
}
|
||||
surf.Draw(mapa->GetVertices(), color, info.GetOutlineColor(), parms.GetOutlineWidthScale());
|
||||
|
||||
lastAreaIdx = info.GetAreaIndex();
|
||||
|
@ -346,11 +598,11 @@ void CMapWorld::DrawAreas(const CMapWorld::CMapWorldDrawParms& parms, int selAre
|
|||
}
|
||||
}
|
||||
for (const CMapObjectSortInfo& info : sortInfos) {
|
||||
const CMapArea* mapa = GetMapArea(info.GetAreaIndex());
|
||||
CMapArea* mapa = GetMapArea(info.GetAreaIndex());
|
||||
if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Door ||
|
||||
info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Object) {
|
||||
const CMappableObject& mapObj = mapa->GetMappableObject(info.GetLocalObjectIndex());
|
||||
zeus::CTransform objXf =
|
||||
CMappableObject& mapObj = mapa->GetMappableObject(info.GetLocalObjectIndex());
|
||||
const zeus::CTransform objXf =
|
||||
zeus::CTransform::Translate(CMapArea::GetAreaPostTranslate(parms.GetWorld(), info.GetAreaIndex())) *
|
||||
mapObj.GetTransform();
|
||||
if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Door) {
|
||||
|
@ -363,8 +615,8 @@ void CMapWorld::DrawAreas(const CMapWorld::CMapWorldDrawParms& parms, int selAre
|
|||
mapObj.Draw(selArea, mwInfo, parms.GetAlpha(), lastType != info.GetObjectCode());
|
||||
lastType = info.GetObjectCode();
|
||||
} else if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::DoorSurface) {
|
||||
const CMappableObject& mapObj = mapa->GetMappableObject(info.GetLocalObjectIndex() / 6);
|
||||
zeus::CTransform objXf =
|
||||
CMappableObject& mapObj = mapa->GetMappableObject(info.GetLocalObjectIndex() / 6);
|
||||
const zeus::CTransform objXf =
|
||||
parms.GetPlaneProjectionTransform() *
|
||||
zeus::CTransform::Translate(CMapArea::GetAreaPostTranslate(parms.GetWorld(), info.GetAreaIndex())) *
|
||||
mapObj.GetTransform();
|
||||
|
@ -376,249 +628,7 @@ void CMapWorld::DrawAreas(const CMapWorld::CMapWorldDrawParms& parms, int selAre
|
|||
}
|
||||
}
|
||||
|
||||
struct Support {
|
||||
int x0_;
|
||||
int x4_[3];
|
||||
};
|
||||
|
||||
struct Circle2 {
|
||||
zeus::CVector2f x0_point;
|
||||
float x8_radiusSq;
|
||||
};
|
||||
|
||||
struct Circle {
|
||||
zeus::CVector2f x0_point;
|
||||
float x8_radius;
|
||||
Circle(const Circle2& circ2) : x0_point(circ2.x0_point), x8_radius(std::sqrt(circ2.x8_radiusSq)) {}
|
||||
};
|
||||
|
||||
static Circle2 ExactCircle1(const zeus::CVector2f* a) { return {*a, 0.f}; }
|
||||
|
||||
static Circle2 ExactCircle2(const zeus::CVector2f* a, const zeus::CVector2f* b) {
|
||||
Circle2 ret = {};
|
||||
ret.x0_point = 0.5f * (*a + *b);
|
||||
ret.x8_radiusSq = (*b - *a).magSquared() * 0.25f;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Circle2 ExactCircle3(const zeus::CVector2f* a, const zeus::CVector2f* b, const zeus::CVector2f* c) {
|
||||
Circle2 ret = {};
|
||||
zeus::CVector2f d1 = *b - *a;
|
||||
zeus::CVector2f d2 = *c - *a;
|
||||
float cross = d1.cross(d2);
|
||||
zeus::CVector2f magVec(d1.magSquared() * 0.5f, d2.magSquared() * 0.5f);
|
||||
if (std::fabs(cross) > 0.01f) {
|
||||
zeus::CVector2f tmp((d2.y() * magVec.x() - d1.y() * magVec.y()) / cross,
|
||||
(d1.x() * magVec.y() - d2.x() * magVec.x()) / cross);
|
||||
ret.x0_point = *a + tmp;
|
||||
ret.x8_radiusSq = tmp.magSquared();
|
||||
} else {
|
||||
ret.x8_radiusSq = FLT_MAX;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool PointInsideCircle(const zeus::CVector2f& point, const Circle2& circ, float& intersect) {
|
||||
intersect = (point - circ.x0_point).magSquared() - circ.x8_radiusSq;
|
||||
return intersect <= 0.f;
|
||||
}
|
||||
|
||||
static Circle2 UpdateSupport1(int idx, const zeus::CVector2f** list, Support& support) {
|
||||
Circle2 ret = ExactCircle2(list[support.x4_[0]], list[idx]);
|
||||
support.x0_ = 2;
|
||||
support.x4_[1] = idx;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Circle2 UpdateSupport2(int idx, const zeus::CVector2f** list, Support& support) {
|
||||
Circle2 circs[3] = {};
|
||||
float intersect;
|
||||
int circIdx = -1;
|
||||
float minRad = FLT_MAX;
|
||||
|
||||
circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]);
|
||||
if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) {
|
||||
minRad = circs[0].x8_radiusSq;
|
||||
circIdx = 0;
|
||||
}
|
||||
|
||||
circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]);
|
||||
if (circs[1].x8_radiusSq < minRad && PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) {
|
||||
circIdx = 1;
|
||||
}
|
||||
|
||||
Circle2 ret;
|
||||
if (circIdx != -1) {
|
||||
ret = circs[circIdx];
|
||||
support.x4_[1 - circIdx] = idx;
|
||||
} else {
|
||||
ret = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]);
|
||||
support.x0_ = 3;
|
||||
support.x4_[2] = idx;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Circle2 UpdateSupport3(int idx, const zeus::CVector2f** list, Support& support) {
|
||||
Circle2 circs[6] = {};
|
||||
float intersect;
|
||||
int circIdxA = -1;
|
||||
int circIdxB = -1;
|
||||
float minRadA = FLT_MAX;
|
||||
float minRadB = FLT_MAX;
|
||||
|
||||
circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]);
|
||||
if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) {
|
||||
if (PointInsideCircle(*list[support.x4_[2]], circs[0], intersect)) {
|
||||
minRadA = circs[0].x8_radiusSq;
|
||||
circIdxA = 0;
|
||||
} else {
|
||||
minRadB = intersect;
|
||||
circIdxB = 0;
|
||||
}
|
||||
} else {
|
||||
minRadB = intersect;
|
||||
circIdxB = 0;
|
||||
}
|
||||
|
||||
circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]);
|
||||
if (circs[1].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) {
|
||||
if (PointInsideCircle(*list[support.x4_[2]], circs[1], intersect)) {
|
||||
minRadA = circs[1].x8_radiusSq;
|
||||
circIdxA = 1;
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 1;
|
||||
}
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 1;
|
||||
}
|
||||
}
|
||||
|
||||
circs[2] = ExactCircle2(list[support.x4_[2]], list[idx]);
|
||||
if (circs[2].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[0]], circs[2], intersect)) {
|
||||
if (PointInsideCircle(*list[support.x4_[1]], circs[2], intersect)) {
|
||||
minRadA = circs[2].x8_radiusSq;
|
||||
circIdxA = 2;
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 2;
|
||||
}
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 2;
|
||||
}
|
||||
}
|
||||
|
||||
circs[3] = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]);
|
||||
if (circs[3].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[2]], circs[3], intersect)) {
|
||||
minRadA = circs[3].x8_radiusSq;
|
||||
circIdxA = 3;
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 3;
|
||||
}
|
||||
}
|
||||
|
||||
circs[4] = ExactCircle3(list[support.x4_[0]], list[support.x4_[2]], list[idx]);
|
||||
if (circs[4].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[1]], circs[4], intersect)) {
|
||||
minRadA = circs[4].x8_radiusSq;
|
||||
circIdxA = 4;
|
||||
} else if (intersect < minRadB) {
|
||||
minRadB = intersect;
|
||||
circIdxB = 4;
|
||||
}
|
||||
}
|
||||
|
||||
circs[5] = ExactCircle3(list[support.x4_[1]], list[support.x4_[2]], list[idx]);
|
||||
if (circs[5].x8_radiusSq < minRadA) {
|
||||
if (PointInsideCircle(*list[support.x4_[0]], circs[5], intersect)) {
|
||||
circIdxA = 5;
|
||||
} else if (intersect < minRadB) {
|
||||
circIdxB = 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (circIdxA == -1)
|
||||
circIdxA = circIdxB;
|
||||
|
||||
switch (circIdxA) {
|
||||
case 0:
|
||||
support.x0_ = 2;
|
||||
support.x4_[1] = idx;
|
||||
break;
|
||||
case 1:
|
||||
support.x0_ = 2;
|
||||
support.x4_[0] = idx;
|
||||
break;
|
||||
case 2:
|
||||
support.x0_ = 2;
|
||||
support.x4_[0] = support.x4_[2];
|
||||
support.x4_[1] = idx;
|
||||
break;
|
||||
case 3:
|
||||
support.x4_[2] = idx;
|
||||
break;
|
||||
case 4:
|
||||
support.x4_[1] = idx;
|
||||
break;
|
||||
case 5:
|
||||
support.x4_[0] = idx;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return circs[circIdxA];
|
||||
}
|
||||
|
||||
typedef Circle2 (*FSupport)(int idx, const zeus::CVector2f** list, Support& support);
|
||||
static const FSupport SupportFuncs[] = {nullptr, UpdateSupport1, UpdateSupport2, UpdateSupport3};
|
||||
|
||||
static Circle MinCircle(const std::vector<zeus::CVector2f>& coords) {
|
||||
Circle2 ret = {};
|
||||
if (coords.size() >= 1) {
|
||||
std::unique_ptr<const zeus::CVector2f*[]> randArr(new const zeus::CVector2f*[coords.size()]);
|
||||
for (size_t i = 0; i < coords.size(); ++i)
|
||||
randArr[i] = &coords[i];
|
||||
for (int i = coords.size() - 1; i >= 0; --i) {
|
||||
int shuf = rand() % (i + 1);
|
||||
if (shuf != i)
|
||||
std::swap(randArr[i], randArr[shuf]);
|
||||
}
|
||||
ret = ExactCircle1(randArr[0]);
|
||||
|
||||
Support support = {};
|
||||
support.x0_ = 1;
|
||||
for (size_t i = 1; i < coords.size();) {
|
||||
bool broke = false;
|
||||
for (int j = 0; j < support.x0_; ++j) {
|
||||
if ((*randArr[i] - *randArr[support.x4_[j]]).magSquared() < 0.01f) {
|
||||
broke = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
float intersect;
|
||||
if (!broke && !PointInsideCircle(*randArr[i], ret, intersect)) {
|
||||
Circle2 circ = SupportFuncs[support.x0_](i, randArr.get(), support);
|
||||
if (circ.x8_radiusSq > ret.x8_radiusSq) {
|
||||
i = 0;
|
||||
ret = circ;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CMapWorld::RecalculateWorldSphere(const CMapWorldInfo& mwInfo, const IWorld& wld) const {
|
||||
void CMapWorld::RecalculateWorldSphere(const CMapWorldInfo& mwInfo, const IWorld& wld) {
|
||||
std::vector<zeus::CVector2f> coords;
|
||||
coords.reserve(x0_areas.size() * 8);
|
||||
float zMin = FLT_MAX;
|
||||
|
@ -638,11 +648,10 @@ void CMapWorld::RecalculateWorldSphere(const CMapWorldInfo& mwInfo, const IWorld
|
|||
}
|
||||
}
|
||||
|
||||
Circle circle = MinCircle(coords);
|
||||
const_cast<CMapWorld*>(this)->x3c_worldSphereRadius = circle.x8_radius;
|
||||
const_cast<CMapWorld*>(this)->x30_worldSpherePoint =
|
||||
zeus::CVector3f(circle.x0_point.x(), circle.x0_point.y(), (zMin + zMax) * 0.5f);
|
||||
const_cast<CMapWorld*>(this)->x40_worldSphereHalfDepth = (zMax - zMin) * 0.5f;
|
||||
const Circle circle = MinCircle(coords);
|
||||
x3c_worldSphereRadius = circle.x8_radius;
|
||||
x30_worldSpherePoint = zeus::CVector3f(circle.x0_point.x(), circle.x0_point.y(), (zMin + zMax) * 0.5f);
|
||||
x40_worldSphereHalfDepth = (zMax - zMin) * 0.5f;
|
||||
}
|
||||
|
||||
zeus::CVector3f CMapWorld::ConstrainToWorldVolume(const zeus::CVector3f& point, const zeus::CVector3f& lookVec) const {
|
||||
|
@ -670,10 +679,8 @@ zeus::CVector3f CMapWorld::ConstrainToWorldVolume(const zeus::CVector3f& point,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void CMapWorld::ClearTraversedFlags() const {
|
||||
std::vector<bool>& flags = const_cast<CMapWorld*>(this)->x20_traversed;
|
||||
for (size_t i = 0; i < flags.size(); ++i)
|
||||
flags[i] = false;
|
||||
void CMapWorld::ClearTraversedFlags() {
|
||||
std::fill(x20_traversed.begin(), x20_traversed.end(), false);
|
||||
}
|
||||
|
||||
CFactoryFnReturn FMapWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param,
|
||||
|
|
|
@ -71,6 +71,7 @@ public:
|
|||
void Lock() { x0_area.Lock(); }
|
||||
void Unlock() { x0_area.Unlock(); }
|
||||
bool IsLoaded() const { return x0_area.IsLoaded(); }
|
||||
CMapArea* GetMapArea() { return x0_area.GetObj(); }
|
||||
const CMapArea* GetMapArea() const { return x0_area.GetObj(); }
|
||||
CMapAreaData* GetNextMapAreaData() { return x14_next; }
|
||||
const CMapAreaData* GetNextMapAreaData() const { return x14_next; }
|
||||
|
@ -142,22 +143,25 @@ private:
|
|||
float x40_worldSphereHalfDepth = 0.f;
|
||||
|
||||
public:
|
||||
CMapWorld(CInputStream&);
|
||||
explicit CMapWorld(CInputStream& in);
|
||||
u32 GetNumAreas() const { return x0_areas.size(); }
|
||||
CMapArea* GetMapArea(int aid) { return x0_areas[aid].GetMapArea(); }
|
||||
const CMapArea* GetMapArea(int aid) const { return x0_areas[aid].GetMapArea(); }
|
||||
bool IsMapAreaInBFSInfoVector(const CMapAreaData*, const std::vector<CMapAreaBFSInfo>&) const;
|
||||
void SetWhichMapAreasLoaded(const IWorld&, int start, int count);
|
||||
bool IsMapAreasStreaming() const;
|
||||
void MoveMapAreaToList(CMapAreaData*, EMapAreaList);
|
||||
s32 GetCurrentMapAreaDepth(const IWorld&, int areaIdx) const;
|
||||
std::vector<int> GetVisibleAreas(const IWorld&, const CMapWorldInfo&) const;
|
||||
void Draw(const CMapWorldDrawParms&, int, int, float, float, bool) const;
|
||||
void DoBFS(const IWorld&, int, int, float, float, bool, std::vector<CMapAreaBFSInfo>&) const;
|
||||
bool IsMapAreaValid(const IWorld&, int, bool) const;
|
||||
void DrawAreas(const CMapWorldDrawParms&, int, const std::vector<CMapAreaBFSInfo>&, bool) const;
|
||||
void RecalculateWorldSphere(const CMapWorldInfo&, const IWorld&) const;
|
||||
zeus::CVector3f ConstrainToWorldVolume(const zeus::CVector3f&, const zeus::CVector3f&) const;
|
||||
void ClearTraversedFlags() const;
|
||||
bool IsMapAreaInBFSInfoVector(const CMapAreaData* area, const std::vector<CMapAreaBFSInfo>& vec) const;
|
||||
void SetWhichMapAreasLoaded(const IWorld& wld, int start, int count);
|
||||
bool IsMapAreasStreaming();
|
||||
void MoveMapAreaToList(CMapAreaData* data, EMapAreaList list);
|
||||
s32 GetCurrentMapAreaDepth(const IWorld& wld, TAreaId aid);
|
||||
std::vector<int> GetVisibleAreas(const IWorld& wld, const CMapWorldInfo& mwInfo) const;
|
||||
void Draw(const CMapWorldDrawParms& parms, int curArea, int otherArea, float depth1, float depth2, bool inMapScreen);
|
||||
void DoBFS(const IWorld& wld, int startArea, int areaCount, float surfDepth, float outlineDepth, bool checkLoad,
|
||||
std::vector<CMapAreaBFSInfo>& bfsInfos);
|
||||
bool IsMapAreaValid(const IWorld& wld, int areaIdx, bool checkLoad) const;
|
||||
void DrawAreas(const CMapWorldDrawParms& parms, int selArea, const std::vector<CMapAreaBFSInfo>& bfsInfos,
|
||||
bool inMapScreen);
|
||||
void RecalculateWorldSphere(const CMapWorldInfo& mwInfo, const IWorld& wld);
|
||||
zeus::CVector3f ConstrainToWorldVolume(const zeus::CVector3f& point, const zeus::CVector3f& lookVec) const;
|
||||
void ClearTraversedFlags();
|
||||
};
|
||||
|
||||
CFactoryFnReturn FMapWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param,
|
||||
|
|
|
@ -10,43 +10,47 @@ CMapWorldInfo::CMapWorldInfo(CBitStreamReader& reader, const CSaveWorld& savw, C
|
|||
|
||||
x4_visitedAreas.reserve((worldMem.GetAreaCount() + 31) / 32);
|
||||
for (u32 i = 0; i < worldMem.GetAreaCount(); ++i) {
|
||||
bool visited = reader.ReadEncoded(1);
|
||||
const bool visited = reader.ReadEncoded(1) != 0;
|
||||
SetAreaVisited(i, visited);
|
||||
}
|
||||
|
||||
x18_mappedAreas.reserve((worldMem.GetAreaCount() + 31) / 32);
|
||||
for (u32 i = 0; i < worldMem.GetAreaCount(); ++i) {
|
||||
bool mapped = reader.ReadEncoded(1);
|
||||
const bool mapped = reader.ReadEncoded(1) != 0;
|
||||
SetIsMapped(i, mapped);
|
||||
}
|
||||
|
||||
for (TEditorId doorId : savw.GetDoors())
|
||||
SetDoorVisited(doorId, reader.ReadEncoded(1));
|
||||
for (const TEditorId doorId : savw.GetDoors()) {
|
||||
SetDoorVisited(doorId, reader.ReadEncoded(1) != 0);
|
||||
}
|
||||
|
||||
x38_mapStationUsed = reader.ReadEncoded(1);
|
||||
x38_mapStationUsed = reader.ReadEncoded(1) != 0;
|
||||
}
|
||||
|
||||
void CMapWorldInfo::PutTo(CBitStreamWriter& writer, const CSaveWorld& savw, CAssetId mlvlId) const {
|
||||
const CSaveWorldMemory& worldMem = g_MemoryCardSys->GetSaveWorldMemory(mlvlId);
|
||||
|
||||
for (u32 i = 0; i < worldMem.GetAreaCount(); ++i) {
|
||||
if (i < x0_visitedAreasAllocated)
|
||||
writer.WriteEncoded(IsAreaVisited(i), 1);
|
||||
else
|
||||
if (i < x0_visitedAreasAllocated) {
|
||||
writer.WriteEncoded(u32(IsAreaVisited(i)), 1);
|
||||
} else {
|
||||
writer.WriteEncoded(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < worldMem.GetAreaCount(); ++i) {
|
||||
if (i < x14_mappedAreasAllocated)
|
||||
writer.WriteEncoded(IsMapped(i), 1);
|
||||
else
|
||||
if (i < x14_mappedAreasAllocated) {
|
||||
writer.WriteEncoded(u32(IsMapped(i)), 1);
|
||||
} else {
|
||||
writer.WriteEncoded(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (TEditorId doorId : savw.GetDoors())
|
||||
writer.WriteEncoded(IsDoorVisited(doorId), 1);
|
||||
for (const TEditorId doorId : savw.GetDoors()) {
|
||||
writer.WriteEncoded(u32(IsDoorVisited(doorId)), 1);
|
||||
}
|
||||
|
||||
writer.WriteEncoded(x38_mapStationUsed, 1);
|
||||
writer.WriteEncoded(u32(x38_mapStationUsed), 1);
|
||||
}
|
||||
|
||||
void CMapWorldInfo::SetDoorVisited(TEditorId eid, bool visited) { x28_visitedDoors[eid] = visited; }
|
||||
|
@ -55,40 +59,44 @@ bool CMapWorldInfo::IsDoorVisited(TEditorId eid) const { return x28_visitedDoors
|
|||
|
||||
bool CMapWorldInfo::IsAreaVisited(TAreaId aid) const {
|
||||
if (u32(aid) + 1 > x0_visitedAreasAllocated) {
|
||||
const_cast<CMapWorldInfo&>(*this).x4_visitedAreas.resize((aid + 32) / 32);
|
||||
const_cast<CMapWorldInfo&>(*this).x0_visitedAreasAllocated = aid + 1;
|
||||
x4_visitedAreas.resize((u32(aid) + 32) / 32);
|
||||
x0_visitedAreasAllocated = u32(aid) + 1;
|
||||
}
|
||||
return (x4_visitedAreas[aid / 32] >> (aid % 32)) & 0x1;
|
||||
return ((x4_visitedAreas[aid / 32] >> (aid % 32)) & 1) != 0;
|
||||
}
|
||||
|
||||
void CMapWorldInfo::SetAreaVisited(TAreaId aid, bool visited) {
|
||||
if (u32(aid) + 1 > x0_visitedAreasAllocated) {
|
||||
x4_visitedAreas.resize((aid + 32) / 32);
|
||||
x0_visitedAreasAllocated = aid + 1;
|
||||
x4_visitedAreas.resize((u32(aid) + 32) / 32);
|
||||
x0_visitedAreasAllocated = u32(aid) + 1;
|
||||
}
|
||||
|
||||
if (visited) {
|
||||
x4_visitedAreas[aid / 32] |= 1U << (aid % 32);
|
||||
} else {
|
||||
x4_visitedAreas[aid / 32] &= ~(1U << (aid % 32));
|
||||
}
|
||||
if (visited)
|
||||
x4_visitedAreas[aid / 32] |= 1 << (aid % 32);
|
||||
else
|
||||
x4_visitedAreas[aid / 32] &= ~(1 << (aid % 32));
|
||||
}
|
||||
|
||||
bool CMapWorldInfo::IsMapped(TAreaId aid) const {
|
||||
if (u32(aid) + 1 > x14_mappedAreasAllocated) {
|
||||
const_cast<CMapWorldInfo&>(*this).x18_mappedAreas.resize((aid + 32) / 32);
|
||||
const_cast<CMapWorldInfo&>(*this).x14_mappedAreasAllocated = aid + 1;
|
||||
x18_mappedAreas.resize((u32(aid) + 32) / 32);
|
||||
x14_mappedAreasAllocated = u32(aid) + 1;
|
||||
}
|
||||
return (x18_mappedAreas[aid / 32] >> (aid % 32)) & 0x1;
|
||||
return ((x18_mappedAreas[aid / 32] >> (aid % 32)) & 1) != 0;
|
||||
}
|
||||
|
||||
void CMapWorldInfo::SetIsMapped(TAreaId aid, bool mapped) {
|
||||
if (u32(aid) + 1 > x14_mappedAreasAllocated) {
|
||||
x18_mappedAreas.resize((aid + 32) / 32);
|
||||
x14_mappedAreasAllocated = aid + 1;
|
||||
x18_mappedAreas.resize((u32(aid) + 32) / 32);
|
||||
x14_mappedAreasAllocated = u32(aid) + 1;
|
||||
}
|
||||
|
||||
if (mapped) {
|
||||
x18_mappedAreas[aid / 32] |= 1U << (aid % 32);
|
||||
} else {
|
||||
x18_mappedAreas[aid / 32] &= ~(1U << (aid % 32));
|
||||
}
|
||||
if (mapped)
|
||||
x18_mappedAreas[aid / 32] |= 1 << (aid % 32);
|
||||
else
|
||||
x18_mappedAreas[aid / 32] &= ~(1 << (aid % 32));
|
||||
}
|
||||
|
||||
bool CMapWorldInfo::IsWorldVisible(TAreaId aid) const { return x38_mapStationUsed || IsMapped(aid); }
|
||||
|
@ -96,12 +104,16 @@ bool CMapWorldInfo::IsWorldVisible(TAreaId aid) const { return x38_mapStationUse
|
|||
bool CMapWorldInfo::IsAreaVisible(TAreaId aid) const { return IsAreaVisited(aid) || IsMapped(aid); }
|
||||
|
||||
bool CMapWorldInfo::IsAnythingSet() const {
|
||||
for (u32 i = 0; i < x0_visitedAreasAllocated; ++i)
|
||||
if (x4_visitedAreas[i / 32] & (1 << (i % 32)))
|
||||
for (u32 i = 0; i < x0_visitedAreasAllocated; ++i) {
|
||||
if ((x4_visitedAreas[i / 32] & (1U << (i % 32))) != 0) {
|
||||
return true;
|
||||
for (u32 i = 0; i < x14_mappedAreasAllocated; ++i)
|
||||
if (x18_mappedAreas[i / 32] & (1 << (i % 32)))
|
||||
}
|
||||
}
|
||||
for (u32 i = 0; i < x14_mappedAreasAllocated; ++i) {
|
||||
if ((x18_mappedAreas[i / 32] & (1U << (i % 32))) != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return x38_mapStationUsed;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,16 +9,16 @@ namespace urde {
|
|||
class CSaveWorld;
|
||||
|
||||
class CMapWorldInfo {
|
||||
u32 x0_visitedAreasAllocated = 0;
|
||||
std::vector<u32> x4_visitedAreas;
|
||||
u32 x14_mappedAreasAllocated = 0;
|
||||
std::vector<u32> x18_mappedAreas;
|
||||
mutable u32 x0_visitedAreasAllocated = 0;
|
||||
mutable std::vector<u32> x4_visitedAreas;
|
||||
mutable u32 x14_mappedAreasAllocated = 0;
|
||||
mutable std::vector<u32> x18_mappedAreas;
|
||||
std::map<TEditorId, bool> x28_visitedDoors;
|
||||
bool x38_mapStationUsed = false;
|
||||
|
||||
public:
|
||||
CMapWorldInfo() = default;
|
||||
CMapWorldInfo(CBitStreamReader&, const CSaveWorld& saveWorld, CAssetId mlvlId);
|
||||
explicit CMapWorldInfo(CBitStreamReader&, const CSaveWorld& saveWorld, CAssetId mlvlId);
|
||||
void PutTo(CBitStreamWriter& writer, const CSaveWorld& savw, CAssetId mlvlId) const;
|
||||
bool IsMapped(TAreaId) const;
|
||||
void SetIsMapped(TAreaId, bool);
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
#include "Runtime/Graphics/CTexture.hpp"
|
||||
|
||||
namespace urde {
|
||||
zeus::CVector3f CMappableObject::skDoorVerts[8] = {};
|
||||
std::array<zeus::CVector3f, 8> CMappableObject::skDoorVerts{};
|
||||
|
||||
static const u32 DoorIndices[] = {6, 4, 2, 0, 3, 1, 7, 5, 1, 0, 5, 4, 7, 6, 3, 2, 3, 2, 1, 0, 5, 4, 7, 6};
|
||||
constexpr std::array<u32, 24> DoorIndices{
|
||||
6, 4, 2, 0, 3, 1, 7, 5, 1, 0, 5, 4, 7, 6, 3, 2, 3, 2, 1, 0, 5, 4, 7, 6,
|
||||
};
|
||||
|
||||
CMappableObject::CMappableObject(const void* buf) {
|
||||
athena::io::MemoryReader r(buf, 64);
|
||||
|
@ -106,12 +108,12 @@ std::pair<zeus::CColor, zeus::CColor> CMappableObject::GetDoorColors(int curArea
|
|||
|
||||
void CMappableObject::PostConstruct(const void*) { x10_transform = AdjustTransformForType(); }
|
||||
|
||||
void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo, float alpha, bool needsVtxLoad) const {
|
||||
void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo, float alpha, bool needsVtxLoad) {
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP("CMappableObject::Draw", zeus::skCyan);
|
||||
if (IsDoorType(x0_type)) {
|
||||
std::pair<zeus::CColor, zeus::CColor> colors = GetDoorColors(curArea, mwInfo, alpha);
|
||||
for (int s = 0; s < 6; ++s) {
|
||||
DoorSurface& ds = const_cast<DoorSurface&>(*m_doorSurface);
|
||||
DoorSurface& ds = *m_doorSurface;
|
||||
ds.m_surface.draw(colors.first, s * 4, 4);
|
||||
CLineRenderer& line = ds.m_outline;
|
||||
const u32* baseIdx = &DoorIndices[s * 4];
|
||||
|
@ -164,22 +166,24 @@ void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo, float alpha
|
|||
iconColor.a() *= alpha;
|
||||
|
||||
TLockedToken<CTexture> tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), iconRes});
|
||||
if (!m_texQuadFilter || m_texQuadFilter->GetTex().GetObj() != tex.GetObj())
|
||||
const_cast<CMappableObject*>(this)->m_texQuadFilter.emplace(EFilterType::Add, tex,
|
||||
CTexturedQuadFilter::ZTest::GEqual);
|
||||
if (!m_texQuadFilter || m_texQuadFilter->GetTex().GetObj() != tex.GetObj()) {
|
||||
m_texQuadFilter.emplace(EFilterType::Add, tex, CTexturedQuadFilter::ZTest::GEqual);
|
||||
}
|
||||
|
||||
CTexturedQuadFilter::Vert verts[4] = {{{-2.6f, 0.f, 2.6f}, {0.f, 1.f}},
|
||||
{{-2.6f, 0.f, -2.6f}, {0.f, 0.f}},
|
||||
{{2.6f, 0.f, 2.6f}, {1.f, 1.f}},
|
||||
{{2.6f, 0.f, -2.6f}, {1.f, 0.f}}};
|
||||
const_cast<CMappableObject*>(this)->m_texQuadFilter->drawVerts(iconColor, verts);
|
||||
const std::array<CTexturedQuadFilter::Vert, 4> verts{{
|
||||
{{-2.6f, 0.f, 2.6f}, {0.f, 1.f}},
|
||||
{{-2.6f, 0.f, -2.6f}, {0.f, 0.f}},
|
||||
{{2.6f, 0.f, 2.6f}, {1.f, 1.f}},
|
||||
{{2.6f, 0.f, -2.6f}, {1.f, 0.f}},
|
||||
}};
|
||||
m_texQuadFilter->drawVerts(iconColor, verts.data());
|
||||
}
|
||||
}
|
||||
|
||||
void CMappableObject::DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo, float alpha, int surfIdx,
|
||||
bool needsVtxLoad) const {
|
||||
bool needsVtxLoad) {
|
||||
std::pair<zeus::CColor, zeus::CColor> colors = GetDoorColors(curArea, mwInfo, alpha);
|
||||
DoorSurface& ds = const_cast<DoorSurface&>(*m_doorSurface);
|
||||
DoorSurface& ds = *m_doorSurface;
|
||||
ds.m_surface.draw(colors.first, surfIdx * 4, 4);
|
||||
CLineRenderer& line = ds.m_outline;
|
||||
const u32* baseIdx = &DoorIndices[surfIdx * 4];
|
||||
|
@ -237,9 +241,10 @@ boo::ObjToken<boo::IGraphicsBufferS> CMappableObject::g_doorIbo;
|
|||
|
||||
void CMappableObject::ReadAutoMapperTweaks(const ITweakAutoMapper& tweaks) {
|
||||
const zeus::CVector3f& center = tweaks.GetDoorCenter();
|
||||
zeus::simd_floats centerF(center.mSimd);
|
||||
zeus::CVector3f* doorVerts = CMappableObject::skDoorVerts;
|
||||
/* Wrap door verts around -Z to build surface */
|
||||
const zeus::simd_floats centerF(center.mSimd);
|
||||
|
||||
// Wrap door verts around -Z to build surface
|
||||
auto& doorVerts = skDoorVerts;
|
||||
doorVerts[0].assign(-centerF[2], -centerF[1], 0.f);
|
||||
doorVerts[1].assign(-centerF[2], -centerF[1], 2.f * centerF[0]);
|
||||
doorVerts[2].assign(-centerF[2], centerF[1], 0.f);
|
||||
|
@ -250,8 +255,8 @@ void CMappableObject::ReadAutoMapperTweaks(const ITweakAutoMapper& tweaks) {
|
|||
doorVerts[7].assign(.2f * -centerF[2], centerF[1], 2.f * centerF[0]);
|
||||
|
||||
CGraphics::CommitResources([](boo::IGraphicsDataFactory::Context& ctx) {
|
||||
g_doorVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, skDoorVerts, 16, 8);
|
||||
g_doorIbo = ctx.newStaticBuffer(boo::BufferUse::Index, DoorIndices, 4, 24);
|
||||
g_doorVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, skDoorVerts.data(), 16, skDoorVerts.size());
|
||||
g_doorIbo = ctx.newStaticBuffer(boo::BufferUse::Index, DoorIndices.data(), 4, DoorIndices.size());
|
||||
return true;
|
||||
} BooTrace);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
|
@ -52,7 +53,7 @@ public:
|
|||
enum class EVisMode { Always, MapStationOrVisit, Visit, Never, MapStationOrVisit2 };
|
||||
|
||||
private:
|
||||
static zeus::CVector3f skDoorVerts[8];
|
||||
static std::array<zeus::CVector3f, 8> skDoorVerts;
|
||||
|
||||
EMappableObjectType x0_type;
|
||||
EVisMode x4_visibilityMode;
|
||||
|
@ -63,7 +64,7 @@ private:
|
|||
struct DoorSurface {
|
||||
CMapSurfaceShader m_surface;
|
||||
CLineRenderer m_outline;
|
||||
DoorSurface(boo::IGraphicsDataFactory::Context& ctx)
|
||||
explicit DoorSurface(boo::IGraphicsDataFactory::Context& ctx)
|
||||
: m_surface(ctx, g_doorVbo, g_doorIbo)
|
||||
, m_outline(ctx, CLineRenderer::EPrimitiveMode::LineLoop, 5, nullptr, false, false, true) {}
|
||||
};
|
||||
|
@ -74,13 +75,13 @@ private:
|
|||
std::pair<zeus::CColor, zeus::CColor> GetDoorColors(int idx, const CMapWorldInfo& mwInfo, float alpha) const;
|
||||
|
||||
public:
|
||||
CMappableObject(const void* buf);
|
||||
explicit CMappableObject(const void* buf);
|
||||
CMappableObject(CMappableObject&&) = default;
|
||||
void PostConstruct(const void*);
|
||||
const zeus::CTransform& GetTransform() const { return x10_transform; }
|
||||
EMappableObjectType GetType() const { return x0_type; }
|
||||
void Draw(int, const CMapWorldInfo&, float, bool) const;
|
||||
void DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo, float alpha, int surfIdx, bool needsVtxLoad) const;
|
||||
void Draw(int, const CMapWorldInfo&, float, bool);
|
||||
void DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo, float alpha, int surfIdx, bool needsVtxLoad);
|
||||
zeus::CVector3f BuildSurfaceCenterPoint(int surfIdx) const;
|
||||
bool IsDoorConnectedToArea(int idx, const CStateManager&) const;
|
||||
bool IsDoorConnectedToVisitedArea(const CStateManager&) const;
|
||||
|
|
|
@ -16,7 +16,7 @@ public:
|
|||
return msg;
|
||||
}
|
||||
void Clear() { m_list.clear(); }
|
||||
operator bool() const { return m_list.size() != 0; }
|
||||
explicit operator bool() const { return !m_list.empty(); }
|
||||
};
|
||||
|
||||
} // namespace urde
|
||||
|
|
|
@ -8,7 +8,7 @@ class CDependencyGroup {
|
|||
std::vector<SObjectTag> x0_objectTags;
|
||||
|
||||
public:
|
||||
CDependencyGroup(CInputStream& in);
|
||||
explicit CDependencyGroup(CInputStream& in);
|
||||
void ReadFromStream(CInputStream& in);
|
||||
const std::vector<SObjectTag>& GetObjectTagVector() const { return x0_objectTags; }
|
||||
};
|
||||
|
|
|
@ -31,15 +31,15 @@ CGameHintInfo::SHintLocation::SHintLocation(CInputStream& in, s32)
|
|||
, x8_areaId(in.readUint32Big())
|
||||
, xc_stringId(in.readUint32Big()) {}
|
||||
|
||||
int CGameHintInfo::FindHintIndex(const char* str) {
|
||||
int CGameHintInfo::FindHintIndex(std::string_view str) {
|
||||
const std::vector<CGameHint>& gameHints = g_MemoryCardSys->GetHints();
|
||||
const auto& it = std::find_if(gameHints.begin(), gameHints.end(),
|
||||
[&str](const CGameHint& gh) -> bool { return gh.GetName() == str; });
|
||||
const auto it =
|
||||
std::find_if(gameHints.cbegin(), gameHints.cend(), [&str](const CGameHint& gh) { return gh.GetName() == str; });
|
||||
|
||||
return (it != gameHints.end() ? it - gameHints.begin() : -1);
|
||||
return it != gameHints.cend() ? it - gameHints.cbegin() : -1;
|
||||
}
|
||||
|
||||
CFactoryFnReturn FHintFactory(const SObjectTag&, CInputStream& in, const CVParamTransfer, CObjectReference*) {
|
||||
CFactoryFnReturn FHintFactory(const SObjectTag&, CInputStream& in, const CVParamTransfer&, CObjectReference*) {
|
||||
in.readUint32Big();
|
||||
s32 version = in.readInt32Big();
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ private:
|
|||
public:
|
||||
CGameHintInfo(CInputStream&, s32);
|
||||
const std::vector<CGameHint>& GetHints() const { return x0_hints; }
|
||||
static int FindHintIndex(const char* str);
|
||||
static int FindHintIndex(std::string_view str);
|
||||
};
|
||||
|
||||
CFactoryFnReturn FHintFactory(const SObjectTag&, CInputStream&, const CVParamTransfer, CObjectReference*);
|
||||
CFactoryFnReturn FHintFactory(const SObjectTag&, CInputStream&, const CVParamTransfer&, CObjectReference*);
|
||||
} // namespace urde
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "Runtime/CGameOptions.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "Runtime/CGameHintInfo.hpp"
|
||||
#include "Runtime/CGameState.hpp"
|
||||
#include "Runtime/CMemoryCardSys.hpp"
|
||||
|
@ -522,18 +524,20 @@ CHintOptions::CHintOptions(CBitStreamReader& stream) {
|
|||
x0_hintStates.reserve(hints.size());
|
||||
|
||||
u32 hintIdx = 0;
|
||||
for (const auto& hint : hints) {
|
||||
(void)hint;
|
||||
EHintState state = EHintState(stream.ReadEncoded(2));
|
||||
union { s32 i; float f; } timeBits = {stream.ReadEncoded(32)};
|
||||
float time = timeBits.f;
|
||||
if (state == EHintState::Zero)
|
||||
for ([[maybe_unused]] const auto& hint : hints) {
|
||||
const auto state = EHintState(stream.ReadEncoded(2));
|
||||
const s32 timeBits = stream.ReadEncoded(32);
|
||||
float time;
|
||||
std::memcpy(&time, &timeBits, sizeof(s32));
|
||||
if (state == EHintState::Zero) {
|
||||
time = 0.f;
|
||||
}
|
||||
|
||||
x0_hintStates.emplace_back(state, time, false);
|
||||
|
||||
if (x10_nextHintIdx == -1 && state == EHintState::Displaying)
|
||||
if (x10_nextHintIdx == -1 && state == EHintState::Displaying) {
|
||||
x10_nextHintIdx = hintIdx;
|
||||
}
|
||||
++hintIdx;
|
||||
}
|
||||
}
|
||||
|
@ -541,8 +545,11 @@ CHintOptions::CHintOptions(CBitStreamReader& stream) {
|
|||
void CHintOptions::PutTo(CBitStreamWriter& writer) const {
|
||||
for (const SHintState& hint : x0_hintStates) {
|
||||
writer.WriteEncoded(u32(hint.x0_state), 2);
|
||||
union { float f; u32 i; } timeBits = {hint.x4_time};
|
||||
writer.WriteEncoded(timeBits.i, 32);
|
||||
|
||||
u32 timeBits;
|
||||
std::memcpy(&timeBits, &hint.x4_time, sizeof(timeBits));
|
||||
|
||||
writer.WriteEncoded(timeBits, 32);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -578,43 +585,51 @@ const CHintOptions::SHintState* CHintOptions::GetCurrentDisplayedHint() const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void CHintOptions::DelayHint(const char* name) {
|
||||
int idx = CGameHintInfo::FindHintIndex(name);
|
||||
if (idx == -1)
|
||||
void CHintOptions::DelayHint(std::string_view name) {
|
||||
const int idx = CGameHintInfo::FindHintIndex(name);
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (x10_nextHintIdx == idx)
|
||||
for (SHintState& state : x0_hintStates)
|
||||
if (x10_nextHintIdx == idx) {
|
||||
for (SHintState& state : x0_hintStates) {
|
||||
state.x4_time += 60.f;
|
||||
}
|
||||
}
|
||||
|
||||
x0_hintStates[idx].x0_state = EHintState::Delayed;
|
||||
}
|
||||
|
||||
void CHintOptions::ActivateImmediateHintTimer(const char* name) {
|
||||
int idx = CGameHintInfo::FindHintIndex(name);
|
||||
if (idx == -1)
|
||||
void CHintOptions::ActivateImmediateHintTimer(std::string_view name) {
|
||||
const int idx = CGameHintInfo::FindHintIndex(name);
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
SHintState& hintState = x0_hintStates[idx];
|
||||
const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[idx];
|
||||
if (hintState.x0_state != EHintState::Zero)
|
||||
if (hintState.x0_state != EHintState::Zero) {
|
||||
return;
|
||||
}
|
||||
|
||||
hintState.x0_state = EHintState::Waiting;
|
||||
hintState.x4_time = hint.GetImmediateTime();
|
||||
}
|
||||
|
||||
void CHintOptions::ActivateContinueDelayHintTimer(const char* name) {
|
||||
void CHintOptions::ActivateContinueDelayHintTimer(std::string_view name) {
|
||||
int idx = x10_nextHintIdx;
|
||||
if (idx != 0)
|
||||
if (idx != 0) {
|
||||
idx = CGameHintInfo::FindHintIndex(name);
|
||||
if (idx == -1)
|
||||
}
|
||||
if (idx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
SHintState& hintState = x0_hintStates[idx];
|
||||
const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[idx];
|
||||
if (hintState.x0_state != EHintState::Displaying)
|
||||
if (hintState.x0_state != EHintState::Displaying) {
|
||||
return;
|
||||
}
|
||||
|
||||
hintState.x4_time = hint.GetTextTime();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "Runtime/CSaveWorld.hpp"
|
||||
|
@ -70,7 +71,7 @@ class CPersistentOptions {
|
|||
|
||||
public:
|
||||
CPersistentOptions() = default;
|
||||
CPersistentOptions(CBitStreamReader& stream);
|
||||
explicit CPersistentOptions(CBitStreamReader& stream);
|
||||
|
||||
bool GetCinematicState(CAssetId mlvlId, TEditorId cineId) const;
|
||||
void SetCinematicState(CAssetId mlvlId, TEditorId cineId, bool state);
|
||||
|
@ -133,7 +134,7 @@ class CGameOptions {
|
|||
|
||||
public:
|
||||
CGameOptions();
|
||||
CGameOptions(CBitStreamReader& stream);
|
||||
explicit CGameOptions(CBitStreamReader& stream);
|
||||
void ResetToDefaults();
|
||||
void InitSoundMode();
|
||||
void EnsureSettings();
|
||||
|
@ -200,14 +201,14 @@ private:
|
|||
|
||||
public:
|
||||
CHintOptions() = default;
|
||||
CHintOptions(CBitStreamReader& stream);
|
||||
explicit CHintOptions(CBitStreamReader& stream);
|
||||
void PutTo(CBitStreamWriter& writer) const;
|
||||
void SetNextHintTime();
|
||||
void InitializeMemoryState();
|
||||
const SHintState* GetCurrentDisplayedHint() const;
|
||||
void DelayHint(const char* name);
|
||||
void ActivateImmediateHintTimer(const char* name);
|
||||
void ActivateContinueDelayHintTimer(const char* name);
|
||||
void DelayHint(std::string_view name);
|
||||
void ActivateImmediateHintTimer(std::string_view name);
|
||||
void ActivateContinueDelayHintTimer(std::string_view name);
|
||||
void DismissDisplayedHint();
|
||||
u32 GetNextHintIdx() const;
|
||||
const std::vector<SHintState>& GetHintStates() const { return x0_hintStates; }
|
||||
|
|
|
@ -38,15 +38,17 @@ CWorldLayerState::CWorldLayerState(CBitStreamReader& reader, const CSaveWorld& s
|
|||
|
||||
void CWorldLayerState::PutTo(CBitStreamWriter& writer) const {
|
||||
u32 totalLayerCount = 0;
|
||||
for (int i = 0; i < x0_areaLayers.size(); ++i)
|
||||
totalLayerCount += GetAreaLayerCount(i) - 1;
|
||||
for (size_t i = 0; i < x0_areaLayers.size(); ++i) {
|
||||
totalLayerCount += GetAreaLayerCount(s32(i)) - 1;
|
||||
}
|
||||
|
||||
writer.WriteEncoded(totalLayerCount, 10);
|
||||
|
||||
for (int i = 0; i < x0_areaLayers.size(); ++i) {
|
||||
u32 count = GetAreaLayerCount(i);
|
||||
for (u32 l = 1; l < count; ++l)
|
||||
writer.WriteEncoded(IsLayerActive(i, l), 1);
|
||||
for (size_t i = 0; i < x0_areaLayers.size(); ++i) {
|
||||
const u32 count = GetAreaLayerCount(s32(i));
|
||||
for (u32 l = 1; l < count; ++l) {
|
||||
writer.WriteEncoded(IsLayerActive(s32(i), s32(l)), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,8 +97,9 @@ CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data) {
|
|||
CBitStreamReader stream(data, 4096);
|
||||
GameFileStateInfo ret;
|
||||
|
||||
for (u32 i = 0; i < 128; i++)
|
||||
for (u32 i = 0; i < 128; i++) {
|
||||
stream.ReadEncoded(8);
|
||||
}
|
||||
ret.x14_timestamp = stream.ReadEncoded(32);
|
||||
|
||||
ret.x20_hardMode = stream.ReadEncoded(1);
|
||||
|
@ -111,6 +114,7 @@ CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data) {
|
|||
|
||||
CPlayerState playerState(stream);
|
||||
ret.x10_energyTanks = playerState.GetItemCapacity(CPlayerState::EItemType::EnergyTanks);
|
||||
ret.xc_health = playerState.GetHealthInfo().GetHP();
|
||||
|
||||
u32 itemPercent;
|
||||
if (origMLVL == 0x158EFE17)
|
||||
|
@ -142,8 +146,9 @@ CGameState::CGameState(CBitStreamReader& stream, u32 saveIdx) : x20c_saveFileIdx
|
|||
x9c_transManager = std::make_shared<CWorldTransManager>();
|
||||
x228_25_initPowerupsAtFirstSpawn = true;
|
||||
|
||||
for (u32 i = 0; i < 128; i++)
|
||||
x0_[i] = stream.ReadEncoded(8);
|
||||
for (bool& value : x0_) {
|
||||
value = stream.ReadEncoded(8) != 0;
|
||||
}
|
||||
stream.ReadEncoded(32);
|
||||
|
||||
x228_24_hardMode = stream.ReadEncoded(1);
|
||||
|
@ -204,9 +209,10 @@ void CGameState::WriteBackupBuf() {
|
|||
PutTo(w);
|
||||
}
|
||||
|
||||
void CGameState::PutTo(CBitStreamWriter& writer) const {
|
||||
for (u32 i = 0; i < 128; i++)
|
||||
writer.WriteEncoded(x0_[i], 8);
|
||||
void CGameState::PutTo(CBitStreamWriter& writer) {
|
||||
for (const bool value : x0_) {
|
||||
writer.WriteEncoded(u32(value), 8);
|
||||
}
|
||||
|
||||
writer.WriteEncoded(CBasics::ToWiiTime(std::chrono::system_clock::now()) / CBasics::TICKS_PER_SECOND, 32);
|
||||
writer.WriteEncoded(x228_24_hardMode, 1);
|
||||
|
@ -226,7 +232,7 @@ void CGameState::PutTo(CBitStreamWriter& writer) const {
|
|||
for (const auto& memWorld : memWorlds) {
|
||||
TLockedToken<CSaveWorld> saveWorld =
|
||||
g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), memWorld.second.GetSaveWorldAssetId()});
|
||||
const CWorldState& wld = const_cast<CGameState&>(*this).StateForWorld(memWorld.first);
|
||||
const CWorldState& wld = StateForWorld(memWorld.first);
|
||||
wld.PutTo(writer, *saveWorld);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
|
@ -67,7 +68,7 @@ public:
|
|||
class CGameState {
|
||||
friend class CStateManager;
|
||||
|
||||
bool x0_[128] = {};
|
||||
std::array<bool, 128> x0_{};
|
||||
u32 x80_;
|
||||
CAssetId x84_mlvlId;
|
||||
std::vector<CWorldState> x88_worldStates;
|
||||
|
@ -116,7 +117,7 @@ public:
|
|||
void SetFileIdx(u32 idx) { x20c_saveFileIdx = idx; }
|
||||
void SetCardSerial(u64 serial) { x210_cardSerial = serial; }
|
||||
u64 GetCardSerial() const { return x210_cardSerial; }
|
||||
void PutTo(CBitStreamWriter& writer) const;
|
||||
void PutTo(CBitStreamWriter& writer);
|
||||
float GetHardModeDamageMultiplier() const;
|
||||
float GetHardModeWeaponMultiplier() const;
|
||||
void InitializeMemoryWorlds();
|
||||
|
|
|
@ -16,13 +16,13 @@ class CIOWin {
|
|||
|
||||
public:
|
||||
enum class EMessageReturn { Normal = 0, Exit = 1, RemoveIOWinAndExit = 2, RemoveIOWin = 3 };
|
||||
CIOWin(std::string_view name) : x4_name(name) { m_nameHash = std::hash<std::string_view>()(name); }
|
||||
explicit CIOWin(std::string_view name) : x4_name(name) { m_nameHash = std::hash<std::string_view>()(name); }
|
||||
|
||||
virtual ~CIOWin() = default;
|
||||
virtual EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&) = 0;
|
||||
virtual bool GetIsContinueDraw() const { return true; }
|
||||
virtual void Draw() const {}
|
||||
virtual void PreDraw() const {}
|
||||
virtual void Draw() {}
|
||||
virtual void PreDraw() {}
|
||||
|
||||
std::string_view GetName() const { return x4_name; }
|
||||
size_t GetNameHash() const { return m_nameHash; }
|
||||
|
|
|
@ -6,12 +6,12 @@ namespace urde {
|
|||
|
||||
class CMFGameBase : public CIOWin {
|
||||
public:
|
||||
CMFGameBase(const char* name) : CIOWin(name) {}
|
||||
explicit CMFGameBase(const char* name) : CIOWin(name) {}
|
||||
};
|
||||
|
||||
class CMFGameLoaderBase : public CIOWin {
|
||||
public:
|
||||
CMFGameLoaderBase(const char* name) : CIOWin(name) {}
|
||||
explicit CMFGameLoaderBase(const char* name) : CIOWin(name) {}
|
||||
};
|
||||
|
||||
} // namespace urde
|
||||
|
|
|
@ -11,7 +11,7 @@ protected:
|
|||
EClientFlowStates x14_gameState = EClientFlowStates::Unspecified;
|
||||
|
||||
public:
|
||||
CMainFlowBase(const char* name) : CIOWin(name) {}
|
||||
explicit CMainFlowBase(const char* name) : CIOWin(name) {}
|
||||
EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) override;
|
||||
virtual void AdvanceGameState(CArchitectureQueue& queue) = 0;
|
||||
virtual void SetGameState(EClientFlowStates state, CArchitectureQueue& queue) = 0;
|
||||
|
|
|
@ -30,12 +30,12 @@ bool CSaveWorldIntermediate::InitializePump() {
|
|||
|
||||
x4_strgId = wld.IGetStringTableAssetId();
|
||||
x8_savwId = wld.IGetSaveWorldAssetId();
|
||||
u32 areaCount = wld.IGetAreaCount();
|
||||
const u32 areaCount = wld.IGetAreaCount();
|
||||
|
||||
xc_areaIds.reserve(areaCount);
|
||||
for (u32 i = 0; i < areaCount; ++i) {
|
||||
const IGameArea* area = wld.IGetAreaAlways(i);
|
||||
xc_areaIds.push_back(area->IGetAreaId());
|
||||
xc_areaIds.emplace_back(area->IGetAreaId());
|
||||
}
|
||||
|
||||
CAssetId mlvlId = wld.IGetWorldAssetId();
|
||||
|
|
|
@ -76,7 +76,7 @@ public:
|
|||
ECardResult result;
|
||||
CardResult(ECardResult res) : result(res) {}
|
||||
operator ECardResult() const { return result; }
|
||||
operator bool() const { return result != ECardResult::READY; }
|
||||
explicit operator bool() const { return result != ECardResult::READY; }
|
||||
};
|
||||
|
||||
struct CardFileHandle {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "Runtime/RetroTypes.hpp"
|
||||
#include "Runtime/World/CEntity.hpp"
|
||||
|
||||
|
@ -25,7 +27,7 @@ class CObjectList {
|
|||
s16 next = -1;
|
||||
s16 prev = -1;
|
||||
};
|
||||
SObjectListEntry x0_list[1024]; // was an rstl::prereserved_vector
|
||||
std::array<SObjectListEntry, 1024> x0_list; // was an rstl::prereserved_vector
|
||||
EGameObjectList x2004_listEnum;
|
||||
s16 x2008_firstId = -1;
|
||||
u16 x200a_count = 0;
|
||||
|
|
|
@ -11,7 +11,7 @@ class CPlayMovieBase : public CIOWin {
|
|||
public:
|
||||
CPlayMovieBase(const char* iowName, const char* path) : CIOWin(iowName), x18_moviePlayer(path, 0.0, false, false) {}
|
||||
EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&) override { return EMessageReturn::Normal; }
|
||||
void Draw() const override {}
|
||||
void Draw() override {}
|
||||
};
|
||||
|
||||
} // namespace urde
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
|
||||
#include "Runtime/CMemoryCardSys.hpp"
|
||||
#include "Runtime/CStateManager.hpp"
|
||||
|
@ -81,12 +82,12 @@ CPlayerState::CPlayerState() : x188_staticIntf(5) {
|
|||
CPlayerState::CPlayerState(CBitStreamReader& stream) : x188_staticIntf(5) {
|
||||
x0_24_alive = true;
|
||||
x4_enabledItems = u32(stream.ReadEncoded(32));
|
||||
union {
|
||||
float fHP;
|
||||
u32 iHP;
|
||||
} hp;
|
||||
hp.iHP = u32(stream.ReadEncoded(32));
|
||||
xc_health.SetHP(hp.fHP);
|
||||
|
||||
const u32 integralHP = u32(stream.ReadEncoded(32));
|
||||
float realHP;
|
||||
std::memcpy(&realHP, &integralHP, sizeof(float));
|
||||
|
||||
xc_health.SetHP(realHP);
|
||||
x8_currentBeam = EBeamId(stream.ReadEncoded(CBitStreamReader::GetBitCount(5)));
|
||||
x20_currentSuit = EPlayerSuit(stream.ReadEncoded(CBitStreamReader::GetBitCount(4)));
|
||||
x24_powerups.resize(41);
|
||||
|
@ -113,12 +114,12 @@ CPlayerState::CPlayerState(CBitStreamReader& stream) : x188_staticIntf(5) {
|
|||
|
||||
void CPlayerState::PutTo(CBitStreamWriter& stream) {
|
||||
stream.WriteEncoded(x4_enabledItems, 32);
|
||||
union {
|
||||
float fHP;
|
||||
u32 iHP;
|
||||
} hp;
|
||||
hp.fHP = xc_health.GetHP();
|
||||
stream.WriteEncoded(hp.iHP, 32);
|
||||
|
||||
const float realHP = xc_health.GetHP();
|
||||
u32 integralHP;
|
||||
std::memcpy(&integralHP, &realHP, sizeof(u32));
|
||||
|
||||
stream.WriteEncoded(integralHP, 32);
|
||||
stream.WriteEncoded(u32(x8_currentBeam), CBitStreamWriter::GetBitCount(5));
|
||||
stream.WriteEncoded(u32(x20_currentSuit), CBitStreamWriter::GetBitCount(4));
|
||||
for (size_t i = 0; i < x24_powerups.size(); ++i) {
|
||||
|
@ -181,7 +182,7 @@ u32 CPlayerState::CalculateItemCollectionRate() const {
|
|||
return total + GetItemCapacity(EItemType::Wavebuster);
|
||||
}
|
||||
|
||||
CHealthInfo& CPlayerState::HealthInfo() { return xc_health; }
|
||||
CHealthInfo& CPlayerState::GetHealthInfo() { return xc_health; }
|
||||
|
||||
const CHealthInfo& CPlayerState::GetHealthInfo() const { return xc_health; }
|
||||
|
||||
|
@ -389,62 +390,66 @@ void CPlayerState::InitializeScanTimes() {
|
|||
|
||||
u32 CPlayerState::GetPowerUpMaxValue(EItemType type) { return PowerUpMaxValues[size_t(type)]; }
|
||||
|
||||
const std::unordered_map<std::string_view, CPlayerState::EItemType> CPlayerState::g_TypeNameMap = {
|
||||
{"powerbeam"sv, EItemType::PowerBeam},
|
||||
{"icebeam"sv, EItemType::IceBeam},
|
||||
{"wavebeam"sv, EItemType::WaveBeam},
|
||||
{"plasmabeam"sv, EItemType::PlasmaBeam},
|
||||
{"missiles"sv, EItemType::Missiles},
|
||||
{"scanvisor"sv, EItemType::ScanVisor},
|
||||
{"bombs"sv, EItemType::MorphBallBombs},
|
||||
{"ballbombs"sv, EItemType::MorphBallBombs},
|
||||
{"morphballbombs"sv, EItemType::MorphBallBombs},
|
||||
{"powerbombs"sv, EItemType::PowerBombs},
|
||||
{"flamethrower"sv, EItemType::Flamethrower},
|
||||
{"thermalvisor"sv, EItemType::ThermalVisor},
|
||||
{"chargebeam"sv, EItemType::ChargeBeam},
|
||||
{"supermissile"sv, EItemType::SuperMissile},
|
||||
{"grapple"sv, EItemType::GrappleBeam},
|
||||
{"grapplebeam"sv, EItemType::GrappleBeam},
|
||||
{"xrayvisor"sv, EItemType::XRayVisor},
|
||||
{"icespreader"sv, EItemType::IceSpreader},
|
||||
{"spacejump"sv, EItemType::SpaceJumpBoots},
|
||||
{"spacejumpboots"sv, EItemType::SpaceJumpBoots},
|
||||
{"morphball"sv, EItemType::MorphBall},
|
||||
{"combatvisor"sv, EItemType::CombatVisor},
|
||||
{"boostball"sv, EItemType::BoostBall},
|
||||
{"spiderball"sv, EItemType::SpiderBall},
|
||||
{"powersuit"sv, EItemType::PowerSuit},
|
||||
{"gravitysuit"sv, EItemType::GravitySuit},
|
||||
{"variasuit"sv, EItemType::VariaSuit},
|
||||
{"phazonsuit"sv, EItemType::PhazonSuit},
|
||||
{"energytanks"sv, EItemType::EnergyTanks},
|
||||
{"unknownitem1"sv, EItemType::UnknownItem1},
|
||||
{"healthrefill"sv, EItemType::HealthRefill},
|
||||
{"health"sv, EItemType::HealthRefill},
|
||||
{"unknownitem2"sv, EItemType::UnknownItem2},
|
||||
{"wavebuster"sv, EItemType::Wavebuster},
|
||||
{"truth"sv, EItemType::Truth},
|
||||
{"strength"sv, EItemType::Strength},
|
||||
{"elder"sv, EItemType::Elder},
|
||||
{"wild"sv, EItemType::Wild},
|
||||
{"lifegiver"sv, EItemType::Lifegiver},
|
||||
{"warrior"sv, EItemType::Warrior},
|
||||
{"chozo"sv, EItemType::Chozo},
|
||||
{"nature"sv, EItemType::Nature},
|
||||
{"sun"sv, EItemType::Sun},
|
||||
{"world"sv, EItemType::World},
|
||||
{"spirit"sv, EItemType::Spirit},
|
||||
{"newborn"sv, EItemType::Newborn},
|
||||
};
|
||||
|
||||
CPlayerState::EItemType CPlayerState::ItemNameToType(std::string_view name) {
|
||||
std::string lowName = name.data();
|
||||
athena::utility::tolower(lowName);
|
||||
if (g_TypeNameMap.find(lowName) == g_TypeNameMap.end())
|
||||
return EItemType::Invalid;
|
||||
static constexpr std::array<std::pair<std::string_view, EItemType>, 46> typeNameMap{{
|
||||
{"powerbeam"sv, EItemType::PowerBeam},
|
||||
{"icebeam"sv, EItemType::IceBeam},
|
||||
{"wavebeam"sv, EItemType::WaveBeam},
|
||||
{"plasmabeam"sv, EItemType::PlasmaBeam},
|
||||
{"missiles"sv, EItemType::Missiles},
|
||||
{"scanvisor"sv, EItemType::ScanVisor},
|
||||
{"bombs"sv, EItemType::MorphBallBombs},
|
||||
{"ballbombs"sv, EItemType::MorphBallBombs},
|
||||
{"morphballbombs"sv, EItemType::MorphBallBombs},
|
||||
{"powerbombs"sv, EItemType::PowerBombs},
|
||||
{"flamethrower"sv, EItemType::Flamethrower},
|
||||
{"thermalvisor"sv, EItemType::ThermalVisor},
|
||||
{"chargebeam"sv, EItemType::ChargeBeam},
|
||||
{"supermissile"sv, EItemType::SuperMissile},
|
||||
{"grapple"sv, EItemType::GrappleBeam},
|
||||
{"grapplebeam"sv, EItemType::GrappleBeam},
|
||||
{"xrayvisor"sv, EItemType::XRayVisor},
|
||||
{"icespreader"sv, EItemType::IceSpreader},
|
||||
{"spacejump"sv, EItemType::SpaceJumpBoots},
|
||||
{"spacejumpboots"sv, EItemType::SpaceJumpBoots},
|
||||
{"morphball"sv, EItemType::MorphBall},
|
||||
{"combatvisor"sv, EItemType::CombatVisor},
|
||||
{"boostball"sv, EItemType::BoostBall},
|
||||
{"spiderball"sv, EItemType::SpiderBall},
|
||||
{"powersuit"sv, EItemType::PowerSuit},
|
||||
{"gravitysuit"sv, EItemType::GravitySuit},
|
||||
{"variasuit"sv, EItemType::VariaSuit},
|
||||
{"phazonsuit"sv, EItemType::PhazonSuit},
|
||||
{"energytanks"sv, EItemType::EnergyTanks},
|
||||
{"unknownitem1"sv, EItemType::UnknownItem1},
|
||||
{"healthrefill"sv, EItemType::HealthRefill},
|
||||
{"health"sv, EItemType::HealthRefill},
|
||||
{"unknownitem2"sv, EItemType::UnknownItem2},
|
||||
{"wavebuster"sv, EItemType::Wavebuster},
|
||||
{"truth"sv, EItemType::Truth},
|
||||
{"strength"sv, EItemType::Strength},
|
||||
{"elder"sv, EItemType::Elder},
|
||||
{"wild"sv, EItemType::Wild},
|
||||
{"lifegiver"sv, EItemType::Lifegiver},
|
||||
{"warrior"sv, EItemType::Warrior},
|
||||
{"chozo"sv, EItemType::Chozo},
|
||||
{"nature"sv, EItemType::Nature},
|
||||
{"sun"sv, EItemType::Sun},
|
||||
{"world"sv, EItemType::World},
|
||||
{"spirit"sv, EItemType::Spirit},
|
||||
{"newborn"sv, EItemType::Newborn},
|
||||
}};
|
||||
|
||||
return g_TypeNameMap.find(lowName)->second;
|
||||
std::string lowName{name};
|
||||
athena::utility::tolower(lowName);
|
||||
|
||||
const auto iter = std::find_if(typeNameMap.cbegin(), typeNameMap.cend(),
|
||||
[&lowName](const auto& entry) { return entry.first == lowName; });
|
||||
if (iter == typeNameMap.cend()) {
|
||||
return EItemType::Invalid;
|
||||
}
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
} // namespace urde
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "Runtime/CStaticInterference.hpp"
|
||||
|
@ -89,12 +88,11 @@ public:
|
|||
enum class EBeamId : s32 { Invalid = -1, Power, Ice, Wave, Plasma, Phazon, Phazon2 = 27 };
|
||||
|
||||
private:
|
||||
static const std::unordered_map<std::string_view, EItemType> g_TypeNameMap;
|
||||
struct CPowerUp {
|
||||
u32 x0_amount = 0;
|
||||
u32 x4_capacity = 0;
|
||||
CPowerUp() {}
|
||||
CPowerUp(u32 amount, u32 capacity) : x0_amount(amount), x4_capacity(capacity) {}
|
||||
constexpr CPowerUp() = default;
|
||||
constexpr CPowerUp(u32 amount, u32 capacity) : x0_amount(amount), x4_capacity(capacity) {}
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
|
@ -125,7 +123,7 @@ public:
|
|||
static constexpr float GetMissileComboChargeFactor() { return 1.8f; }
|
||||
u32 CalculateItemCollectionRate() const;
|
||||
|
||||
CHealthInfo& HealthInfo();
|
||||
CHealthInfo& GetHealthInfo();
|
||||
const CHealthInfo& GetHealthInfo() const;
|
||||
u32 GetPickupTotal() { return 99; }
|
||||
void SetIsFusionEnabled(bool val) { x0_26_fusion = val; }
|
||||
|
@ -172,7 +170,7 @@ public:
|
|||
CStaticInterference& GetStaticInterference() { return x188_staticIntf; }
|
||||
const std::vector<std::pair<CAssetId, float>>& GetScanTimes() const { return x170_scanTimes; }
|
||||
CPlayerState();
|
||||
CPlayerState(CBitStreamReader& stream);
|
||||
explicit CPlayerState(CBitStreamReader& stream);
|
||||
void PutTo(CBitStreamWriter& stream);
|
||||
static u32 GetPowerUpMaxValue(EItemType type);
|
||||
static EItemType ItemNameToType(std::string_view name);
|
||||
|
|
|
@ -8,33 +8,41 @@
|
|||
|
||||
namespace urde {
|
||||
|
||||
CRelayTracker::CRelayTracker(CBitStreamReader& in, const CSaveWorld& saveworld) {
|
||||
u32 relayCount = saveworld.GetRelayCount();
|
||||
if (saveworld.GetRelayCount()) {
|
||||
std::vector<bool> relayStates(saveworld.GetRelayCount());
|
||||
for (u32 i = 0; i < relayCount; ++i)
|
||||
CRelayTracker::CRelayTracker(CBitStreamReader& in, const CSaveWorld& saveWorld) {
|
||||
const u32 relayCount = saveWorld.GetRelayCount();
|
||||
if (saveWorld.GetRelayCount()) {
|
||||
std::vector<bool> relayStates(saveWorld.GetRelayCount());
|
||||
for (u32 i = 0; i < relayCount; ++i) {
|
||||
relayStates[i] = in.ReadEncoded(1);
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < relayCount; ++i) {
|
||||
if (!relayStates[i])
|
||||
if (!relayStates[i]) {
|
||||
continue;
|
||||
x0_relayStates.push_back(saveworld.GetRelayEditorId(i));
|
||||
}
|
||||
x0_relayStates.push_back(saveWorld.GetRelayEditorId(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CRelayTracker::HasRelay(TEditorId id) {
|
||||
return std::find(x0_relayStates.begin(), x0_relayStates.end(), id) != x0_relayStates.end();
|
||||
bool CRelayTracker::HasRelay(TEditorId id) const {
|
||||
return std::find(x0_relayStates.cbegin(), x0_relayStates.cend(), id) != x0_relayStates.cend();
|
||||
}
|
||||
|
||||
void CRelayTracker::AddRelay(TEditorId id) {
|
||||
if (std::find(x0_relayStates.begin(), x0_relayStates.end(), id) == x0_relayStates.end())
|
||||
x0_relayStates.push_back(id);
|
||||
if (HasRelay(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
x0_relayStates.push_back(id);
|
||||
}
|
||||
|
||||
void CRelayTracker::RemoveRelay(TEditorId id) {
|
||||
if (std::find(x0_relayStates.begin(), x0_relayStates.end(), id) != x0_relayStates.end())
|
||||
x0_relayStates.erase(std::remove(x0_relayStates.begin(), x0_relayStates.end(), id), x0_relayStates.end());
|
||||
if (!HasRelay(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
x0_relayStates.erase(std::remove(x0_relayStates.begin(), x0_relayStates.end(), id), x0_relayStates.end());
|
||||
}
|
||||
|
||||
void CRelayTracker::SendMsgs(TAreaId areaId, CStateManager& stateMgr) {
|
||||
|
@ -71,18 +79,20 @@ void CRelayTracker::SendMsgs(TAreaId areaId, CStateManager& stateMgr) {
|
|||
}
|
||||
}
|
||||
|
||||
void CRelayTracker::PutTo(CBitStreamWriter& out, const CSaveWorld& saveworld) {
|
||||
u32 relayCount = saveworld.GetRelayCount();
|
||||
void CRelayTracker::PutTo(CBitStreamWriter& out, const CSaveWorld& saveWorld) {
|
||||
const u32 relayCount = saveWorld.GetRelayCount();
|
||||
std::vector<bool> relays(relayCount);
|
||||
|
||||
for (const TEditorId& id : x0_relayStates) {
|
||||
s32 idx = saveworld.GetRelayIndex(id);
|
||||
if (idx >= 0)
|
||||
const s32 idx = saveWorld.GetRelayIndex(id);
|
||||
if (idx >= 0) {
|
||||
relays[idx] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < relayCount; ++i)
|
||||
for (u32 i = 0; i < relayCount; ++i) {
|
||||
out.WriteEncoded(u32(relays[i]), 1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace urde
|
||||
|
|
|
@ -29,13 +29,13 @@ class CRelayTracker {
|
|||
|
||||
public:
|
||||
CRelayTracker() = default;
|
||||
CRelayTracker(CBitStreamReader&, const CSaveWorld&);
|
||||
CRelayTracker(CBitStreamReader& in, const CSaveWorld& saveWorld);
|
||||
|
||||
bool HasRelay(TEditorId);
|
||||
void AddRelay(TEditorId);
|
||||
void RemoveRelay(TEditorId);
|
||||
void SendMsgs(TAreaId, CStateManager&);
|
||||
void PutTo(CBitStreamWriter&, const CSaveWorld&);
|
||||
bool HasRelay(TEditorId id) const;
|
||||
void AddRelay(TEditorId id);
|
||||
void RemoveRelay(TEditorId id);
|
||||
void SendMsgs(TAreaId areaId, CStateManager& stateMgr);
|
||||
void PutTo(CBitStreamWriter& out, const CSaveWorld& saveWorld);
|
||||
};
|
||||
|
||||
} // namespace urde
|
||||
|
|
|
@ -14,13 +14,13 @@ CSaveWorld::CSaveWorld(CInputStream& in) {
|
|||
const u32 cinematicCount = in.readUint32Big();
|
||||
x4_cinematics.reserve(cinematicCount);
|
||||
for (u32 i = 0; i < cinematicCount; ++i) {
|
||||
x4_cinematics.push_back(in.readUint32Big());
|
||||
x4_cinematics.emplace_back(in.readUint32Big());
|
||||
}
|
||||
|
||||
const u32 relayCount = in.readUint32Big();
|
||||
x14_relays.reserve(relayCount);
|
||||
for (u32 i = 0; i < relayCount; ++i) {
|
||||
x14_relays.push_back(in.readUint32Big());
|
||||
x14_relays.emplace_back(in.readUint32Big());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ CSaveWorld::CSaveWorld(CInputStream& in) {
|
|||
const u32 doorCount = in.readUint32Big();
|
||||
x34_doors.reserve(doorCount);
|
||||
for (u32 i = 0; i < doorCount; ++i) {
|
||||
x34_doors.push_back(in.readUint32Big());
|
||||
x34_doors.emplace_back(in.readUint32Big());
|
||||
}
|
||||
|
||||
if (version <= 0) {
|
||||
|
|
|
@ -31,7 +31,7 @@ private:
|
|||
std::vector<SScanState> x44_scans;
|
||||
|
||||
public:
|
||||
CSaveWorld(CInputStream& in);
|
||||
explicit CSaveWorld(CInputStream& in);
|
||||
u32 GetAreaCount() const;
|
||||
u32 GetCinematicCount() const;
|
||||
s32 GetCinematicIndex(const TEditorId& id) const;
|
||||
|
|
|
@ -30,17 +30,19 @@ void CSortedListManager::Reset() {
|
|||
}
|
||||
}
|
||||
|
||||
void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) const {
|
||||
void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) {
|
||||
if (headId == -1) {
|
||||
const_cast<SNode&>(AccessElement(x0_nodes, nodeId)).x28_next = headId;
|
||||
AccessElement(x0_nodes, nodeId).x28_next = headId;
|
||||
headId = nodeId;
|
||||
tailId = nodeId;
|
||||
} else {
|
||||
if (AccessElement(x0_nodes, nodeId).x28_next != -1)
|
||||
if (AccessElement(x0_nodes, nodeId).x28_next != -1) {
|
||||
return;
|
||||
if (tailId == nodeId)
|
||||
}
|
||||
if (tailId == nodeId) {
|
||||
return;
|
||||
const_cast<SNode&>(AccessElement(x0_nodes, nodeId)).x28_next = headId;
|
||||
}
|
||||
AccessElement(x0_nodes, nodeId).x28_next = headId;
|
||||
headId = nodeId;
|
||||
}
|
||||
}
|
||||
|
@ -114,19 +116,19 @@ void CSortedListManager::InsertInList(ESortedList list, SNode& node) {
|
|||
++sl.x800_size;
|
||||
}
|
||||
|
||||
s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const {
|
||||
s16 CSortedListManager::FindInListUpper(ESortedList list, float value) const {
|
||||
const auto listIndex = static_cast<size_t>(list);
|
||||
const SSortedList& sl = xb000_sortedLists[listIndex];
|
||||
int idx = 0;
|
||||
|
||||
for (int i = sl.x800_size; i > 0;) {
|
||||
/* Binary search cycle to find index */
|
||||
if (!(val < AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[listIndex])) {
|
||||
/* Upper */
|
||||
// Binary search cycle to find index
|
||||
if (!(value < AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[listIndex])) {
|
||||
// Upper
|
||||
idx = idx + i / 2 + 1;
|
||||
i = i - i / 2 - 1;
|
||||
} else {
|
||||
/* Lower */
|
||||
// Lower
|
||||
i /= 2;
|
||||
}
|
||||
}
|
||||
|
@ -134,19 +136,19 @@ s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const {
|
|||
return idx;
|
||||
}
|
||||
|
||||
s16 CSortedListManager::FindInListLower(ESortedList list, float val) const {
|
||||
s16 CSortedListManager::FindInListLower(ESortedList list, float value) const {
|
||||
const auto listIndex = static_cast<size_t>(list);
|
||||
const SSortedList& sl = xb000_sortedLists[listIndex];
|
||||
int idx = 0;
|
||||
|
||||
for (int i = sl.x800_size; i > 0;) {
|
||||
/* Binary search cycle to find index */
|
||||
if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[listIndex] < val) {
|
||||
/* Upper */
|
||||
// Binary search cycle to find index
|
||||
if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[listIndex] < value) {
|
||||
// Upper
|
||||
idx = idx + i / 2 + 1;
|
||||
i = i - i / 2 - 1;
|
||||
} else {
|
||||
/* Lower */
|
||||
// Lower
|
||||
i /= 2;
|
||||
}
|
||||
}
|
||||
|
@ -233,48 +235,52 @@ s16 CSortedListManager::CalculateIntersections(ESortedList la, ESortedList lb, s
|
|||
|
||||
void CSortedListManager::BuildNearList(rstl::reserved_vector<TUniqueId, 1024>& out, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter,
|
||||
const CActor* actor) const {
|
||||
if (mag == 0.f)
|
||||
const CActor* actor) {
|
||||
if (mag == 0.f) {
|
||||
mag = 8000.f;
|
||||
}
|
||||
const zeus::CVector3f ray = dir * mag;
|
||||
const zeus::CVector3f sum = ray + pos;
|
||||
zeus::CVector3f maxs(std::max(pos.x(), sum.x()), std::max(pos.y(), sum.y()), std::max(pos.z(), sum.z()));
|
||||
zeus::CVector3f mins(std::min(sum.x(), pos.x()), std::min(sum.y(), pos.y()), std::min(sum.z(), pos.z()));
|
||||
const zeus::CVector3f maxs(std::max(pos.x(), sum.x()), std::max(pos.y(), sum.y()), std::max(pos.z(), sum.z()));
|
||||
const zeus::CVector3f mins(std::min(sum.x(), pos.x()), std::min(sum.y(), pos.y()), std::min(sum.z(), pos.z()));
|
||||
BuildNearList(out, zeus::CAABox(mins, maxs), filter, actor);
|
||||
}
|
||||
|
||||
void CSortedListManager::BuildNearList(rstl::reserved_vector<TUniqueId, 1024>& out, const CActor& actor,
|
||||
const zeus::CAABox& aabb) const {
|
||||
const zeus::CAABox& aabb) {
|
||||
const CMaterialFilter& filter = actor.GetMaterialFilter();
|
||||
s16 id = const_cast<CSortedListManager&>(*this).ConstructIntersectionArray(aabb);
|
||||
s16 id = ConstructIntersectionArray(aabb);
|
||||
while (id != -1) {
|
||||
const SNode& node = AccessElement(x0_nodes, id);
|
||||
SNode& node = AccessElement(x0_nodes, id);
|
||||
if (&actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList()) &&
|
||||
node.x0_actor->GetMaterialFilter().Passes(actor.GetMaterialList()))
|
||||
node.x0_actor->GetMaterialFilter().Passes(actor.GetMaterialList())) {
|
||||
out.push_back(node.x0_actor->GetUniqueId());
|
||||
}
|
||||
|
||||
id = node.x28_next;
|
||||
const_cast<SNode&>(node).x28_next = -1;
|
||||
node.x28_next = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void CSortedListManager::BuildNearList(rstl::reserved_vector<TUniqueId, 1024>& out, const zeus::CAABox& aabb,
|
||||
const CMaterialFilter& filter, const CActor* actor) const {
|
||||
s16 id = const_cast<CSortedListManager&>(*this).ConstructIntersectionArray(aabb);
|
||||
const CMaterialFilter& filter, const CActor* actor) {
|
||||
s16 id = ConstructIntersectionArray(aabb);
|
||||
while (id != -1) {
|
||||
const SNode& node = AccessElement(x0_nodes, id);
|
||||
if (actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList()))
|
||||
SNode& node = AccessElement(x0_nodes, id);
|
||||
if (actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList())) {
|
||||
out.push_back(node.x0_actor->GetUniqueId());
|
||||
}
|
||||
|
||||
id = node.x28_next;
|
||||
const_cast<SNode&>(node).x28_next = -1;
|
||||
node.x28_next = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void CSortedListManager::Remove(const CActor* act) {
|
||||
SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value());
|
||||
if (!node.x2a_populated)
|
||||
void CSortedListManager::Remove(const CActor* actor) {
|
||||
SNode& node = AccessElement(x0_nodes, actor->GetUniqueId().Value());
|
||||
if (!node.x2a_populated) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveFromList(ESortedList::MinX, node.x1c_selfIdxs[0]);
|
||||
RemoveFromList(ESortedList::MaxX, node.x1c_selfIdxs[3]);
|
||||
|
@ -285,8 +291,8 @@ void CSortedListManager::Remove(const CActor* act) {
|
|||
node.x2a_populated = false;
|
||||
}
|
||||
|
||||
void CSortedListManager::Move(const CActor* act, const zeus::CAABox& aabb) {
|
||||
SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value());
|
||||
void CSortedListManager::Move(const CActor* actor, const zeus::CAABox& aabb) {
|
||||
SNode& node = AccessElement(x0_nodes, actor->GetUniqueId().Value());
|
||||
node.x4_box = aabb;
|
||||
|
||||
MoveInList(ESortedList::MinX, node.x1c_selfIdxs[0]);
|
||||
|
@ -297,14 +303,14 @@ void CSortedListManager::Move(const CActor* act, const zeus::CAABox& aabb) {
|
|||
MoveInList(ESortedList::MaxZ, node.x1c_selfIdxs[5]);
|
||||
}
|
||||
|
||||
void CSortedListManager::Insert(const CActor* act, const zeus::CAABox& aabb) {
|
||||
SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value());
|
||||
void CSortedListManager::Insert(const CActor* actor, const zeus::CAABox& aabb) {
|
||||
SNode& node = AccessElement(x0_nodes, actor->GetUniqueId().Value());
|
||||
if (node.x2a_populated) {
|
||||
Move(act, aabb);
|
||||
Move(actor, aabb);
|
||||
return;
|
||||
}
|
||||
|
||||
SNode newNode(act, aabb);
|
||||
SNode newNode(actor, aabb);
|
||||
InsertInList(ESortedList::MinX, newNode);
|
||||
InsertInList(ESortedList::MaxX, newNode);
|
||||
InsertInList(ESortedList::MinY, newNode);
|
||||
|
@ -314,10 +320,11 @@ void CSortedListManager::Insert(const CActor* act, const zeus::CAABox& aabb) {
|
|||
node = newNode;
|
||||
}
|
||||
|
||||
bool CSortedListManager::ActorInLists(const CActor* act) const {
|
||||
if (!act)
|
||||
bool CSortedListManager::ActorInLists(const CActor* actor) const {
|
||||
if (!actor) {
|
||||
return false;
|
||||
const SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value());
|
||||
}
|
||||
const SNode& node = AccessElement(x0_nodes, actor->GetUniqueId().Value());
|
||||
return node.x2a_populated;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,27 +31,27 @@ class CSortedListManager {
|
|||
std::array<SNode, 1024> x0_nodes;
|
||||
std::array<SSortedList, 6> xb000_sortedLists;
|
||||
void Reset();
|
||||
void AddToLinkedList(s16 a, s16& b, s16& c) const;
|
||||
void RemoveFromList(ESortedList, s16);
|
||||
void MoveInList(ESortedList, s16);
|
||||
void InsertInList(ESortedList, SNode& node);
|
||||
s16 FindInListUpper(ESortedList, float) const;
|
||||
s16 FindInListLower(ESortedList, float) const;
|
||||
s16 ConstructIntersectionArray(const zeus::CAABox&);
|
||||
s16 CalculateIntersections(ESortedList, ESortedList, s16, s16, s16, s16, ESortedList, ESortedList, ESortedList,
|
||||
ESortedList, const zeus::CAABox&);
|
||||
void AddToLinkedList(s16 nodeId, s16& headId, s16& tailId);
|
||||
void RemoveFromList(ESortedList list, s16 idx);
|
||||
void MoveInList(ESortedList list, s16 idx);
|
||||
void InsertInList(ESortedList list, SNode& node);
|
||||
s16 FindInListUpper(ESortedList list, float value) const;
|
||||
s16 FindInListLower(ESortedList list, float value) const;
|
||||
s16 ConstructIntersectionArray(const zeus::CAABox& aabb);
|
||||
s16 CalculateIntersections(ESortedList la, ESortedList lb, s16 a, s16 b, s16 c, s16 d, ESortedList slA,
|
||||
ESortedList slB, ESortedList slC, ESortedList slD, const zeus::CAABox& aabb);
|
||||
|
||||
public:
|
||||
CSortedListManager();
|
||||
void BuildNearList(rstl::reserved_vector<TUniqueId, 1024>&, const zeus::CVector3f&, const zeus::CVector3f&, float,
|
||||
const CMaterialFilter&, const CActor*) const;
|
||||
void BuildNearList(rstl::reserved_vector<TUniqueId, 1024>&, const CActor&, const zeus::CAABox&) const;
|
||||
void BuildNearList(rstl::reserved_vector<TUniqueId, 1024>&, const zeus::CAABox&, const CMaterialFilter&,
|
||||
const CActor*) const;
|
||||
void Remove(const CActor*);
|
||||
void Move(const CActor* act, const zeus::CAABox& aabb);
|
||||
void Insert(const CActor* act, const zeus::CAABox& aabb);
|
||||
bool ActorInLists(const CActor* act) const;
|
||||
void BuildNearList(rstl::reserved_vector<TUniqueId, 1024>& out, const zeus::CVector3f& pos,
|
||||
const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter, const CActor* actor);
|
||||
void BuildNearList(rstl::reserved_vector<TUniqueId, 1024>& out, const CActor& actor, const zeus::CAABox& aabb);
|
||||
void BuildNearList(rstl::reserved_vector<TUniqueId, 1024>& out, const zeus::CAABox& aabb,
|
||||
const CMaterialFilter& filter, const CActor* actor);
|
||||
void Remove(const CActor* actor);
|
||||
void Move(const CActor* actor, const zeus::CAABox& aabb);
|
||||
void Insert(const CActor* actor, const zeus::CAABox& aabb);
|
||||
bool ActorInLists(const CActor* actor) const;
|
||||
};
|
||||
|
||||
} // namespace urde
|
||||
|
|
|
@ -74,133 +74,133 @@ CStateManager::CStateManager(const std::weak_ptr<CRelayTracker>& relayTracker,
|
|||
|
||||
g_Renderer->SetDrawableCallback(&CStateManager::RendererDrawCallback, this);
|
||||
x908_loaderCount = int(EScriptObjectType::ScriptObjectTypeMAX);
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Actor)] = ScriptLoader::LoadActor;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Waypoint)] = ScriptLoader::LoadWaypoint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Door)] = ScriptLoader::LoadDoor;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Trigger)] = ScriptLoader::LoadTrigger;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Timer)] = ScriptLoader::LoadTimer;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Counter)] = ScriptLoader::LoadCounter;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Effect)] = ScriptLoader::LoadEffect;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Platform)] = ScriptLoader::LoadPlatform;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Sound)] = ScriptLoader::LoadSound;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Generator)] = ScriptLoader::LoadGenerator;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Dock)] = ScriptLoader::LoadDock;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Camera)] = ScriptLoader::LoadCamera;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::CameraWaypoint)] = ScriptLoader::LoadCameraWaypoint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::NewIntroBoss)] = ScriptLoader::LoadNewIntroBoss;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::SpawnPoint)] = ScriptLoader::LoadSpawnPoint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::CameraHint)] = ScriptLoader::LoadCameraHint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Pickup)] = ScriptLoader::LoadPickup;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::MemoryRelay)] = ScriptLoader::LoadMemoryRelay;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::RandomRelay)] = ScriptLoader::LoadRandomRelay;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Relay)] = ScriptLoader::LoadRelay;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Beetle)] = ScriptLoader::LoadBeetle;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::HUDMemo)] = ScriptLoader::LoadHUDMemo;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::CameraFilterKeyframe)] = ScriptLoader::LoadCameraFilterKeyframe;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::CameraBlurKeyframe)] = ScriptLoader::LoadCameraBlurKeyframe;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::DamageableTrigger)] = ScriptLoader::LoadDamageableTrigger;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Debris)] = ScriptLoader::LoadDebris;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::CameraShaker)] = ScriptLoader::LoadCameraShaker;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ActorKeyframe)] = ScriptLoader::LoadActorKeyframe;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Water)] = ScriptLoader::LoadWater;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Warwasp)] = ScriptLoader::LoadWarWasp;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::SpacePirate)] = ScriptLoader::LoadSpacePirate;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::FlyingPirate)] = ScriptLoader::LoadFlyingPirate;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ElitePirate)] = ScriptLoader::LoadElitePirate;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::MetroidBeta)] = ScriptLoader::LoadMetroidBeta;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ChozoGhost)] = ScriptLoader::LoadChozoGhost;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::CoverPoint)] = ScriptLoader::LoadCoverPoint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::SpiderBallWaypoint)] = ScriptLoader::LoadSpiderBallWaypoint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::BloodFlower)] = ScriptLoader::LoadBloodFlower;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::FlickerBat)] = ScriptLoader::LoadFlickerBat;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PathCamera)] = ScriptLoader::LoadPathCamera;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::GrapplePoint)] = ScriptLoader::LoadGrapplePoint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PuddleSpore)] = ScriptLoader::LoadPuddleSpore;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::DebugCameraWaypoint)] = ScriptLoader::LoadDebugCameraWaypoint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::SpiderBallAttractionSurface)] = ScriptLoader::LoadSpiderBallAttractionSurface;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PuddleToadGamma)] = ScriptLoader::LoadPuddleToadGamma;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::DistanceFog)] = ScriptLoader::LoadDistanceFog;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::FireFlea)] = ScriptLoader::LoadFireFlea;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Metaree)] = ScriptLoader::LoadMetaree;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::DockAreaChange)] = ScriptLoader::LoadDockAreaChange;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ActorRotate)] = ScriptLoader::LoadActorRotate;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::SpecialFunction)] = ScriptLoader::LoadSpecialFunction;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::SpankWeed)] = ScriptLoader::LoadSpankWeed;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Parasite)] = ScriptLoader::LoadParasite;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PlayerHint)] = ScriptLoader::LoadPlayerHint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Ripper)] = ScriptLoader::LoadRipper;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PickupGenerator)] = ScriptLoader::LoadPickupGenerator;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::AIKeyframe)] = ScriptLoader::LoadAIKeyframe;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PointOfInterest)] = ScriptLoader::LoadPointOfInterest;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Drone)] = ScriptLoader::LoadDrone;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Metroid)] = ScriptLoader::LoadMetroid;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::DebrisExtended)] = ScriptLoader::LoadDebrisExtended;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Steam)] = ScriptLoader::LoadSteam;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Ripple)] = ScriptLoader::LoadRipple;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::BallTrigger)] = ScriptLoader::LoadBallTrigger;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::TargetingPoint)] = ScriptLoader::LoadTargetingPoint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::EMPulse)] = ScriptLoader::LoadEMPulse;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::IceSheegoth)] = ScriptLoader::LoadIceSheegoth;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PlayerActor)] = ScriptLoader::LoadPlayerActor;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Flaahgra)] = ScriptLoader::LoadFlaahgra;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::AreaAttributes)] = ScriptLoader::LoadAreaAttributes;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::FishCloud)] = ScriptLoader::LoadFishCloud;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::FishCloudModifier)] = ScriptLoader::LoadFishCloudModifier;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::VisorFlare)] = ScriptLoader::LoadVisorFlare;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::WorldTeleporter)] = ScriptLoader::LoadWorldTeleporter;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::VisorGoo)] = ScriptLoader::LoadVisorGoo;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::JellyZap)] = ScriptLoader::LoadJellyZap;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ControllerAction)] = ScriptLoader::LoadControllerAction;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Switch)] = ScriptLoader::LoadSwitch;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PlayerStateChange)] = ScriptLoader::LoadPlayerStateChange;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Thardus)] = ScriptLoader::LoadThardus;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::WallCrawlerSwarm)] = ScriptLoader::LoadWallCrawlerSwarm;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::AIJumpPoint)] = ScriptLoader::LoadAiJumpPoint;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::FlaahgraTentacle)] = ScriptLoader::LoadFlaahgraTentacle;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::RoomAcoustics)] = ScriptLoader::LoadRoomAcoustics;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ColorModulate)] = ScriptLoader::LoadColorModulate;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ThardusRockProjectile)] = ScriptLoader::LoadThardusRockProjectile;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Midi)] = ScriptLoader::LoadMidi;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::StreamedAudio)] = ScriptLoader::LoadStreamedAudio;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::WorldTeleporterToo)] = ScriptLoader::LoadWorldTeleporter;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Repulsor)] = ScriptLoader::LoadRepulsor;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::GunTurret)] = ScriptLoader::LoadGunTurret;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::FogVolume)] = ScriptLoader::LoadFogVolume;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Babygoth)] = ScriptLoader::LoadBabygoth;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Eyeball)] = ScriptLoader::LoadEyeball;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::RadialDamage)] = ScriptLoader::LoadRadialDamage;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::CameraPitchVolume)] = ScriptLoader::LoadCameraPitchVolume;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::EnvFxDensityController)] = ScriptLoader::LoadEnvFxDensityController;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Magdolite)] = ScriptLoader::LoadMagdolite;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::TeamAIMgr)] = ScriptLoader::LoadTeamAIMgr;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::SnakeWeedSwarm)] = ScriptLoader::LoadSnakeWeedSwarm;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ActorContraption)] = ScriptLoader::LoadActorContraption;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Oculus)] = ScriptLoader::LoadOculus;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Geemer)] = ScriptLoader::LoadGeemer;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::SpindleCamera)] = ScriptLoader::LoadSpindleCamera;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::AtomicAlpha)] = ScriptLoader::LoadAtomicAlpha;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::CameraHintTrigger)] = ScriptLoader::LoadCameraHintTrigger;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::RumbleEffect)] = ScriptLoader::LoadRumbleEffect;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::AmbientAI)] = ScriptLoader::LoadAmbientAI;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::AtomicBeta)] = ScriptLoader::LoadAtomicBeta;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::IceZoomer)] = ScriptLoader::LoadIceZoomer;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Puffer)] = ScriptLoader::LoadPuffer;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Tryclops)] = ScriptLoader::LoadTryclops;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Ridley)] = ScriptLoader::LoadRidley;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Seedling)] = ScriptLoader::LoadSeedling;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ThermalHeatFader)] = ScriptLoader::LoadThermalHeatFader;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::Burrower)] = ScriptLoader::LoadBurrower;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ScriptBeam)] = ScriptLoader::LoadBeam;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::WorldLightFader)] = ScriptLoader::LoadWorldLightFader;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::MetroidPrimeStage2)] = ScriptLoader::LoadMetroidPrimeStage2;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::MetroidPrimeStage1)] = ScriptLoader::LoadMetroidPrimeStage1;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::MazeNode)] = ScriptLoader::LoadMazeNode;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::OmegaPirate)] = ScriptLoader::LoadOmegaPirate;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PhazonPool)] = ScriptLoader::LoadPhazonPool;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::PhazonHealingNodule)] = ScriptLoader::LoadPhazonHealingNodule;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::NewCameraShaker)] = ScriptLoader::LoadNewCameraShaker;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::ShadowProjector)] = ScriptLoader::LoadShadowProjector;
|
||||
x90c_loaderFuncs[int(EScriptObjectType::EnergyBall)] = ScriptLoader::LoadEnergyBall;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Actor)] = ScriptLoader::LoadActor;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Waypoint)] = ScriptLoader::LoadWaypoint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Door)] = ScriptLoader::LoadDoor;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Trigger)] = ScriptLoader::LoadTrigger;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Timer)] = ScriptLoader::LoadTimer;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Counter)] = ScriptLoader::LoadCounter;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Effect)] = ScriptLoader::LoadEffect;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Platform)] = ScriptLoader::LoadPlatform;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Sound)] = ScriptLoader::LoadSound;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Generator)] = ScriptLoader::LoadGenerator;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Dock)] = ScriptLoader::LoadDock;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Camera)] = ScriptLoader::LoadCamera;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::CameraWaypoint)] = ScriptLoader::LoadCameraWaypoint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::NewIntroBoss)] = ScriptLoader::LoadNewIntroBoss;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::SpawnPoint)] = ScriptLoader::LoadSpawnPoint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::CameraHint)] = ScriptLoader::LoadCameraHint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Pickup)] = ScriptLoader::LoadPickup;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::MemoryRelay)] = ScriptLoader::LoadMemoryRelay;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::RandomRelay)] = ScriptLoader::LoadRandomRelay;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Relay)] = ScriptLoader::LoadRelay;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Beetle)] = ScriptLoader::LoadBeetle;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::HUDMemo)] = ScriptLoader::LoadHUDMemo;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::CameraFilterKeyframe)] = ScriptLoader::LoadCameraFilterKeyframe;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::CameraBlurKeyframe)] = ScriptLoader::LoadCameraBlurKeyframe;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::DamageableTrigger)] = ScriptLoader::LoadDamageableTrigger;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Debris)] = ScriptLoader::LoadDebris;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::CameraShaker)] = ScriptLoader::LoadCameraShaker;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ActorKeyframe)] = ScriptLoader::LoadActorKeyframe;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Water)] = ScriptLoader::LoadWater;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Warwasp)] = ScriptLoader::LoadWarWasp;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::SpacePirate)] = ScriptLoader::LoadSpacePirate;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::FlyingPirate)] = ScriptLoader::LoadFlyingPirate;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ElitePirate)] = ScriptLoader::LoadElitePirate;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::MetroidBeta)] = ScriptLoader::LoadMetroidBeta;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ChozoGhost)] = ScriptLoader::LoadChozoGhost;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::CoverPoint)] = ScriptLoader::LoadCoverPoint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::SpiderBallWaypoint)] = ScriptLoader::LoadSpiderBallWaypoint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::BloodFlower)] = ScriptLoader::LoadBloodFlower;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::FlickerBat)] = ScriptLoader::LoadFlickerBat;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PathCamera)] = ScriptLoader::LoadPathCamera;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::GrapplePoint)] = ScriptLoader::LoadGrapplePoint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PuddleSpore)] = ScriptLoader::LoadPuddleSpore;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::DebugCameraWaypoint)] = ScriptLoader::LoadDebugCameraWaypoint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::SpiderBallAttractionSurface)] = ScriptLoader::LoadSpiderBallAttractionSurface;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PuddleToadGamma)] = ScriptLoader::LoadPuddleToadGamma;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::DistanceFog)] = ScriptLoader::LoadDistanceFog;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::FireFlea)] = ScriptLoader::LoadFireFlea;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Metaree)] = ScriptLoader::LoadMetaree;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::DockAreaChange)] = ScriptLoader::LoadDockAreaChange;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ActorRotate)] = ScriptLoader::LoadActorRotate;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::SpecialFunction)] = ScriptLoader::LoadSpecialFunction;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::SpankWeed)] = ScriptLoader::LoadSpankWeed;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Parasite)] = ScriptLoader::LoadParasite;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PlayerHint)] = ScriptLoader::LoadPlayerHint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Ripper)] = ScriptLoader::LoadRipper;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PickupGenerator)] = ScriptLoader::LoadPickupGenerator;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::AIKeyframe)] = ScriptLoader::LoadAIKeyframe;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PointOfInterest)] = ScriptLoader::LoadPointOfInterest;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Drone)] = ScriptLoader::LoadDrone;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Metroid)] = ScriptLoader::LoadMetroid;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::DebrisExtended)] = ScriptLoader::LoadDebrisExtended;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Steam)] = ScriptLoader::LoadSteam;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Ripple)] = ScriptLoader::LoadRipple;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::BallTrigger)] = ScriptLoader::LoadBallTrigger;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::TargetingPoint)] = ScriptLoader::LoadTargetingPoint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::EMPulse)] = ScriptLoader::LoadEMPulse;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::IceSheegoth)] = ScriptLoader::LoadIceSheegoth;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PlayerActor)] = ScriptLoader::LoadPlayerActor;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Flaahgra)] = ScriptLoader::LoadFlaahgra;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::AreaAttributes)] = ScriptLoader::LoadAreaAttributes;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::FishCloud)] = ScriptLoader::LoadFishCloud;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::FishCloudModifier)] = ScriptLoader::LoadFishCloudModifier;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::VisorFlare)] = ScriptLoader::LoadVisorFlare;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::WorldTeleporter)] = ScriptLoader::LoadWorldTeleporter;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::VisorGoo)] = ScriptLoader::LoadVisorGoo;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::JellyZap)] = ScriptLoader::LoadJellyZap;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ControllerAction)] = ScriptLoader::LoadControllerAction;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Switch)] = ScriptLoader::LoadSwitch;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PlayerStateChange)] = ScriptLoader::LoadPlayerStateChange;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Thardus)] = ScriptLoader::LoadThardus;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::WallCrawlerSwarm)] = ScriptLoader::LoadWallCrawlerSwarm;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::AIJumpPoint)] = ScriptLoader::LoadAiJumpPoint;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::FlaahgraTentacle)] = ScriptLoader::LoadFlaahgraTentacle;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::RoomAcoustics)] = ScriptLoader::LoadRoomAcoustics;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ColorModulate)] = ScriptLoader::LoadColorModulate;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ThardusRockProjectile)] = ScriptLoader::LoadThardusRockProjectile;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Midi)] = ScriptLoader::LoadMidi;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::StreamedAudio)] = ScriptLoader::LoadStreamedAudio;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::WorldTeleporterToo)] = ScriptLoader::LoadWorldTeleporter;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Repulsor)] = ScriptLoader::LoadRepulsor;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::GunTurret)] = ScriptLoader::LoadGunTurret;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::FogVolume)] = ScriptLoader::LoadFogVolume;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Babygoth)] = ScriptLoader::LoadBabygoth;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Eyeball)] = ScriptLoader::LoadEyeball;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::RadialDamage)] = ScriptLoader::LoadRadialDamage;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::CameraPitchVolume)] = ScriptLoader::LoadCameraPitchVolume;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::EnvFxDensityController)] = ScriptLoader::LoadEnvFxDensityController;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Magdolite)] = ScriptLoader::LoadMagdolite;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::TeamAIMgr)] = ScriptLoader::LoadTeamAIMgr;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::SnakeWeedSwarm)] = ScriptLoader::LoadSnakeWeedSwarm;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ActorContraption)] = ScriptLoader::LoadActorContraption;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Oculus)] = ScriptLoader::LoadOculus;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Geemer)] = ScriptLoader::LoadGeemer;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::SpindleCamera)] = ScriptLoader::LoadSpindleCamera;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::AtomicAlpha)] = ScriptLoader::LoadAtomicAlpha;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::CameraHintTrigger)] = ScriptLoader::LoadCameraHintTrigger;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::RumbleEffect)] = ScriptLoader::LoadRumbleEffect;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::AmbientAI)] = ScriptLoader::LoadAmbientAI;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::AtomicBeta)] = ScriptLoader::LoadAtomicBeta;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::IceZoomer)] = ScriptLoader::LoadIceZoomer;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Puffer)] = ScriptLoader::LoadPuffer;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Tryclops)] = ScriptLoader::LoadTryclops;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Ridley)] = ScriptLoader::LoadRidley;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Seedling)] = ScriptLoader::LoadSeedling;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ThermalHeatFader)] = ScriptLoader::LoadThermalHeatFader;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::Burrower)] = ScriptLoader::LoadBurrower;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ScriptBeam)] = ScriptLoader::LoadBeam;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::WorldLightFader)] = ScriptLoader::LoadWorldLightFader;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::MetroidPrimeStage2)] = ScriptLoader::LoadMetroidPrimeStage2;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::MetroidPrimeStage1)] = ScriptLoader::LoadMetroidPrimeStage1;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::MazeNode)] = ScriptLoader::LoadMazeNode;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::OmegaPirate)] = ScriptLoader::LoadOmegaPirate;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PhazonPool)] = ScriptLoader::LoadPhazonPool;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::PhazonHealingNodule)] = ScriptLoader::LoadPhazonHealingNodule;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::NewCameraShaker)] = ScriptLoader::LoadNewCameraShaker;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::ShadowProjector)] = ScriptLoader::LoadShadowProjector;
|
||||
x90c_loaderFuncs[size_t(EScriptObjectType::EnergyBall)] = ScriptLoader::LoadEnergyBall;
|
||||
|
||||
CGameCollision::InitCollision();
|
||||
ControlMapper::ResetCommandFilters();
|
||||
|
@ -285,24 +285,26 @@ void CStateManager::UpdateThermalVisor() {
|
|||
}
|
||||
}
|
||||
|
||||
void CStateManager::RendererDrawCallback(const void* drawable, const void* ctx, int type) {
|
||||
const CStateManager& mgr = *static_cast<const CStateManager*>(ctx);
|
||||
void CStateManager::RendererDrawCallback(void* drawable, void* ctx, int type) {
|
||||
CStateManager& mgr = *static_cast<CStateManager*>(ctx);
|
||||
switch (type) {
|
||||
case 0: {
|
||||
const CActor& actor = *static_cast<const CActor*>(drawable);
|
||||
if (actor.xc8_drawnToken == mgr.x8dc_objectDrawToken)
|
||||
CActor& actor = *static_cast<CActor*>(drawable);
|
||||
if (actor.xc8_drawnToken == mgr.x8dc_objectDrawToken) {
|
||||
break;
|
||||
if (actor.xc6_nextDrawNode != kInvalidUniqueId)
|
||||
}
|
||||
if (actor.xc6_nextDrawNode != kInvalidUniqueId) {
|
||||
mgr.RecursiveDrawTree(actor.xc6_nextDrawNode);
|
||||
}
|
||||
actor.Render(mgr);
|
||||
const_cast<CActor&>(actor).xc8_drawnToken = mgr.x8dc_objectDrawToken;
|
||||
actor.xc8_drawnToken = mgr.x8dc_objectDrawToken;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
static_cast<const CSimpleShadow*>(drawable)->Render(mgr.x8f0_shadowTex);
|
||||
static_cast<CSimpleShadow*>(drawable)->Render(mgr.x8f0_shadowTex);
|
||||
break;
|
||||
case 2:
|
||||
static_cast<const CDecal*>(drawable)->Render();
|
||||
static_cast<CDecal*>(drawable)->Render();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -316,14 +318,13 @@ bool CStateManager::RenderLast(TUniqueId uid) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void CStateManager::AddDrawableActorPlane(const CActor& actor, const zeus::CPlane& plane,
|
||||
const zeus::CAABox& aabb) const {
|
||||
const_cast<CActor&>(actor).SetAddedToken(x8dc_objectDrawToken + 1);
|
||||
void CStateManager::AddDrawableActorPlane(CActor& actor, const zeus::CPlane& plane, const zeus::CAABox& aabb) const {
|
||||
actor.SetAddedToken(x8dc_objectDrawToken + 1);
|
||||
g_Renderer->AddPlaneObject(&actor, aabb, plane, 0);
|
||||
}
|
||||
|
||||
void CStateManager::AddDrawableActor(const CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const {
|
||||
const_cast<CActor&>(actor).SetAddedToken(x8dc_objectDrawToken + 1);
|
||||
void CStateManager::AddDrawableActor(CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const {
|
||||
actor.SetAddedToken(x8dc_objectDrawToken + 1);
|
||||
g_Renderer->AddDrawable(&actor, vec, aabb, 0, IRenderer::EDrawableSorting::SortedCallback);
|
||||
}
|
||||
|
||||
|
@ -518,10 +519,11 @@ void CStateManager::DrawDebugStuff() const {
|
|||
}
|
||||
}
|
||||
|
||||
void CStateManager::RenderCamerasAndAreaLights() const {
|
||||
void CStateManager::RenderCamerasAndAreaLights() {
|
||||
x870_cameraManager->RenderCameras(*this);
|
||||
for (const CCameraFilterPassPoly& filter : xb84_camFilterPasses)
|
||||
for (const CCameraFilterPassPoly& filter : xb84_camFilterPasses) {
|
||||
filter.Draw();
|
||||
}
|
||||
}
|
||||
|
||||
void CStateManager::DrawE3DeathEffect() {
|
||||
|
@ -632,46 +634,50 @@ void CStateManager::ResetViewAfterDraw(const SViewport& backupViewport,
|
|||
|
||||
void CStateManager::DrawWorld() {
|
||||
SCOPED_GRAPHICS_DEBUG_GROUP("CStateManager::DrawWorld", zeus::skBlue);
|
||||
CTimeProvider timeProvider(xf14_curTimeMod900);
|
||||
SViewport backupViewport = g_Viewport;
|
||||
const CTimeProvider timeProvider(xf14_curTimeMod900);
|
||||
const SViewport backupViewport = g_Viewport;
|
||||
|
||||
/* Area camera is in (not necessarily player) */
|
||||
TAreaId visAreaId = GetVisAreaId();
|
||||
const TAreaId visAreaId = GetVisAreaId();
|
||||
|
||||
x850_world->TouchSky();
|
||||
|
||||
DrawWorldCubeFaces();
|
||||
|
||||
zeus::CFrustum frustum = SetupViewForDraw(g_Viewport);
|
||||
zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix;
|
||||
const zeus::CFrustum frustum = SetupViewForDraw(g_Viewport);
|
||||
const zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix;
|
||||
|
||||
int areaCount = 0;
|
||||
const CGameArea* areaArr[10];
|
||||
std::array<const CGameArea*, 10> areaArr;
|
||||
for (const CGameArea& area : *x850_world) {
|
||||
if (areaCount == 10)
|
||||
if (areaCount == 10) {
|
||||
break;
|
||||
}
|
||||
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded;
|
||||
if (area.IsPostConstructed())
|
||||
if (area.IsPostConstructed()) {
|
||||
occState = area.GetOcclusionState();
|
||||
if (occState == CGameArea::EOcclusionState::Visible)
|
||||
}
|
||||
if (occState == CGameArea::EOcclusionState::Visible) {
|
||||
areaArr[areaCount++] = &area;
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(std::begin(areaArr), std::begin(areaArr) + areaCount,
|
||||
[visAreaId](const CGameArea* a, const CGameArea* b) -> bool {
|
||||
if (a->x4_selfIdx == b->x4_selfIdx)
|
||||
return false;
|
||||
if (visAreaId == a->x4_selfIdx)
|
||||
return false;
|
||||
if (visAreaId == b->x4_selfIdx)
|
||||
return true;
|
||||
return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) >
|
||||
CGraphics::g_ViewPoint.dot(b->GetAABB().center());
|
||||
});
|
||||
std::sort(areaArr.begin(), areaArr.begin() + areaCount, [visAreaId](const CGameArea* a, const CGameArea* b) {
|
||||
if (a->x4_selfIdx == b->x4_selfIdx) {
|
||||
return false;
|
||||
}
|
||||
if (visAreaId == a->x4_selfIdx) {
|
||||
return false;
|
||||
}
|
||||
if (visAreaId == b->x4_selfIdx) {
|
||||
return true;
|
||||
}
|
||||
return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) > CGraphics::g_ViewPoint.dot(b->GetAABB().center());
|
||||
});
|
||||
|
||||
int pvsCount = 0;
|
||||
CPVSVisSet pvsArr[10];
|
||||
for (const CGameArea** area = areaArr; area != areaArr + areaCount; ++area) {
|
||||
std::array<CPVSVisSet, 10> pvsArr;
|
||||
for (auto area = areaArr.cbegin(); area != areaArr.cbegin() + areaCount; ++area) {
|
||||
const CGameArea* areaPtr = *area;
|
||||
CPVSVisSet& pvsSet = pvsArr[pvsCount++];
|
||||
pvsSet.Reset(EPVSVisSetState::OutOfBounds);
|
||||
|
@ -712,14 +718,17 @@ void CStateManager::DrawWorld() {
|
|||
if (areaCount)
|
||||
SetupFogForArea(*areaArr[areaCount - 1]);
|
||||
|
||||
for (TUniqueId id : x86c_stateManagerContainer->xf370_)
|
||||
if (const CActor* ent = static_cast<const CActor*>(GetObjectById(id)))
|
||||
if (!thermal || ent->xe6_27_thermalVisorFlags & 0x1)
|
||||
for (const TUniqueId id : x86c_stateManagerContainer->xf370_) {
|
||||
if (auto* ent = static_cast<CActor*>(ObjectById(id))) {
|
||||
if (!thermal || ent->xe6_27_thermalVisorFlags & 0x1) {
|
||||
ent->Render(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool morphingPlayerVisible = false;
|
||||
int thermalActorCount = 0;
|
||||
CActor* thermalActorArr[1024];
|
||||
std::array<CActor*, 1024> thermalActorArr;
|
||||
for (int i = 0; i < areaCount; ++i) {
|
||||
const CGameArea& area = *areaArr[i];
|
||||
CPVSVisSet& pvs = pvsArr[i];
|
||||
|
@ -780,19 +789,25 @@ void CStateManager::DrawWorld() {
|
|||
if (thermal) {
|
||||
if (x86c_stateManagerContainer->xf39c_renderLast.size()) {
|
||||
CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN);
|
||||
for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast)
|
||||
if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id)))
|
||||
if (actor->xe6_27_thermalVisorFlags & 0x1)
|
||||
for (const TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) {
|
||||
if (auto* actor = static_cast<CActor*>(ObjectById(id))) {
|
||||
if (actor->xe6_27_thermalVisorFlags & 0x1) {
|
||||
actor->Render(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR);
|
||||
}
|
||||
g_Renderer->DoThermalBlendCold();
|
||||
xf34_thermalFlag = EThermalDrawFlag::Hot;
|
||||
|
||||
for (TUniqueId id : x86c_stateManagerContainer->xf370_)
|
||||
if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id)))
|
||||
if (actor->xe6_27_thermalVisorFlags & 0x2)
|
||||
for (const TUniqueId id : x86c_stateManagerContainer->xf370_) {
|
||||
if (auto* actor = static_cast<CActor*>(ObjectById(id))) {
|
||||
if (actor->xe6_27_thermalVisorFlags & 0x2) {
|
||||
actor->Render(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = areaCount - 1; i >= 0; --i) {
|
||||
const CGameArea& area = *areaArr[i];
|
||||
|
@ -847,10 +862,13 @@ void CStateManager::DrawWorld() {
|
|||
|
||||
if (x86c_stateManagerContainer->xf39c_renderLast.size()) {
|
||||
CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN);
|
||||
for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast)
|
||||
if (const CActor* actor = static_cast<const CActor*>(GetObjectById(id)))
|
||||
if (!thermal || actor->xe6_27_thermalVisorFlags & 0x2)
|
||||
for (const TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) {
|
||||
if (auto* actor = static_cast<CActor*>(ObjectById(id))) {
|
||||
if (!thermal || actor->xe6_27_thermalVisorFlags & 0x2) {
|
||||
actor->Render(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR);
|
||||
}
|
||||
|
||||
|
@ -876,15 +894,18 @@ void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const {
|
|||
SViewport backupVp = g_Viewport;
|
||||
|
||||
int areaCount = 0;
|
||||
const CGameArea* areaArr[10];
|
||||
std::array<const CGameArea*, 10> areaArr;
|
||||
for (const CGameArea& area : *x850_world) {
|
||||
if (areaCount == 10)
|
||||
if (areaCount == 10) {
|
||||
break;
|
||||
}
|
||||
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded;
|
||||
if (area.IsPostConstructed())
|
||||
if (area.IsPostConstructed()) {
|
||||
occState = area.GetOcclusionState();
|
||||
if (occState == CGameArea::EOcclusionState::Visible)
|
||||
}
|
||||
if (occState == CGameArea::EOcclusionState::Visible) {
|
||||
areaArr[areaCount++] = &area;
|
||||
}
|
||||
}
|
||||
|
||||
for (int f = 0; f < 6; ++f) {
|
||||
|
@ -896,20 +917,22 @@ void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const {
|
|||
SetupViewForCubeFaceDraw(actor.GetRenderBounds().center(), f);
|
||||
CGraphics::g_BooMainCommandQueue->clearTarget();
|
||||
|
||||
std::sort(
|
||||
std::begin(areaArr), std::begin(areaArr) + areaCount, [visAreaId](const CGameArea* a, const CGameArea* b) {
|
||||
if (a->x4_selfIdx == b->x4_selfIdx)
|
||||
return false;
|
||||
if (visAreaId == a->x4_selfIdx)
|
||||
return false;
|
||||
if (visAreaId == b->x4_selfIdx)
|
||||
return true;
|
||||
return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) > CGraphics::g_ViewPoint.dot(b->GetAABB().center());
|
||||
});
|
||||
std::sort(areaArr.begin(), areaArr.begin() + areaCount, [visAreaId](const CGameArea* a, const CGameArea* b) {
|
||||
if (a->x4_selfIdx == b->x4_selfIdx) {
|
||||
return false;
|
||||
}
|
||||
if (visAreaId == a->x4_selfIdx) {
|
||||
return false;
|
||||
}
|
||||
if (visAreaId == b->x4_selfIdx) {
|
||||
return true;
|
||||
}
|
||||
return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) > CGraphics::g_ViewPoint.dot(b->GetAABB().center());
|
||||
});
|
||||
|
||||
int pvsCount = 0;
|
||||
CPVSVisSet pvsArr[10];
|
||||
for (const CGameArea** area = areaArr; area != areaArr + areaCount; ++area) {
|
||||
std::array<CPVSVisSet, 10> pvsArr;
|
||||
for (auto area = areaArr.cbegin(); area != areaArr.cbegin() + areaCount; ++area) {
|
||||
const CGameArea* areaPtr = *area;
|
||||
CPVSVisSet& pvsSet = pvsArr[pvsCount++];
|
||||
pvsSet.Reset(EPVSVisSetState::OutOfBounds);
|
||||
|
@ -949,19 +972,22 @@ void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const {
|
|||
}
|
||||
|
||||
void CStateManager::DrawWorldCubeFaces() const {
|
||||
int areaCount = 0;
|
||||
const CGameArea* areaArr[10];
|
||||
size_t areaCount = 0;
|
||||
std::array<const CGameArea*, 10> areaArr;
|
||||
for (const CGameArea& area : *x850_world) {
|
||||
if (areaCount == 10)
|
||||
if (areaCount == areaArr.size()) {
|
||||
break;
|
||||
}
|
||||
CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded;
|
||||
if (area.IsPostConstructed())
|
||||
if (area.IsPostConstructed()) {
|
||||
occState = area.GetOcclusionState();
|
||||
if (occState == CGameArea::EOcclusionState::Visible)
|
||||
}
|
||||
if (occState == CGameArea::EOcclusionState::Visible) {
|
||||
areaArr[areaCount++] = &area;
|
||||
}
|
||||
}
|
||||
|
||||
for (int ai = 0; ai < areaCount; ++ai) {
|
||||
for (size_t ai = 0; ai < areaCount; ++ai) {
|
||||
const CGameArea& area = *areaArr[ai];
|
||||
int cubeInst = 0;
|
||||
for (CEntity* ent : *area.GetAreaObjects()) {
|
||||
|
@ -1161,14 +1187,16 @@ bool CStateManager::GetVisSetForArea(TAreaId a, TAreaId b, CPVSVisSet& setOut) c
|
|||
return false;
|
||||
}
|
||||
|
||||
void CStateManager::RecursiveDrawTree(TUniqueId node) const {
|
||||
if (TCastToConstPtr<CActor> actor = GetObjectById(node)) {
|
||||
void CStateManager::RecursiveDrawTree(TUniqueId node) {
|
||||
if (const TCastToPtr<CActor> actor = ObjectById(node)) {
|
||||
if (x8dc_objectDrawToken != actor->xc8_drawnToken) {
|
||||
if (actor->xc6_nextDrawNode != kInvalidUniqueId)
|
||||
if (actor->xc6_nextDrawNode != kInvalidUniqueId) {
|
||||
RecursiveDrawTree(actor->xc6_nextDrawNode);
|
||||
if (x8dc_objectDrawToken == actor->xcc_addedToken)
|
||||
}
|
||||
if (x8dc_objectDrawToken == actor->xcc_addedToken) {
|
||||
actor->Render(*this);
|
||||
const_cast<CActor*>(actor.GetPtr())->xc8_drawnToken = x8dc_objectDrawToken;
|
||||
}
|
||||
actor->xc8_drawnToken = x8dc_objectDrawToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1320,8 +1348,9 @@ std::pair<TEditorId, TUniqueId> CStateManager::LoadScriptObject(TAreaId aid, ESc
|
|||
|
||||
bool error = false;
|
||||
FScriptLoader loader = {};
|
||||
if (type < EScriptObjectType::ScriptObjectTypeMAX && type >= EScriptObjectType::Actor)
|
||||
loader = x90c_loaderFuncs[int(type)];
|
||||
if (type < EScriptObjectType::ScriptObjectTypeMAX && type >= EScriptObjectType::Actor) {
|
||||
loader = x90c_loaderFuncs[size_t(type)];
|
||||
}
|
||||
|
||||
CEntity* ent = nullptr;
|
||||
if (loader) {
|
||||
|
@ -1559,10 +1588,10 @@ bool CStateManager::TestRayDamage(const zeus::CVector3f& pos, const CActor& dama
|
|||
if (!hInfo)
|
||||
return false;
|
||||
|
||||
static const CMaterialList incList(EMaterialTypes::Solid);
|
||||
static const CMaterialList exList(EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player,
|
||||
EMaterialTypes::Occluder, EMaterialTypes::Character);
|
||||
static const CMaterialFilter filter(incList, exList, CMaterialFilter::EFilterType::IncludeExclude);
|
||||
static constexpr CMaterialList incList(EMaterialTypes::Solid);
|
||||
static constexpr CMaterialList exList(EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player,
|
||||
EMaterialTypes::Occluder, EMaterialTypes::Character);
|
||||
static constexpr CMaterialFilter filter(incList, exList, CMaterialFilter::EFilterType::IncludeExclude);
|
||||
|
||||
std::optional<zeus::CAABox> bounds = damagee.GetTouchBounds();
|
||||
if (!bounds)
|
||||
|
@ -1881,7 +1910,7 @@ void CStateManager::Update(float dt) {
|
|||
UpdateHintState(dt);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
for (size_t i = 0; i < numCameraPasses; ++i) {
|
||||
xb84_camFilterPasses[i].Update(dt);
|
||||
xd14_camBlurPasses[i].Update(dt);
|
||||
}
|
||||
|
@ -2060,35 +2089,45 @@ void CStateManager::MoveActors(float dt) {
|
|||
}
|
||||
|
||||
void CStateManager::CrossTouchActors() {
|
||||
bool visits[1024] = {};
|
||||
std::array<bool, 1024> visits{};
|
||||
|
||||
for (CEntity* ent : GetActorObjectList()) {
|
||||
if (!ent)
|
||||
if (!ent) {
|
||||
continue;
|
||||
CActor& actor = static_cast<CActor&>(*ent);
|
||||
if (!actor.GetActive() || !actor.GetCallTouch())
|
||||
}
|
||||
|
||||
auto& actor = static_cast<CActor&>(*ent);
|
||||
if (!actor.GetActive() || !actor.GetCallTouch()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::optional<zeus::CAABox> touchAABB = actor.GetTouchBounds();
|
||||
if (!touchAABB)
|
||||
if (!touchAABB) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CMaterialFilter filter = CMaterialFilter::skPassEverything;
|
||||
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Trigger))
|
||||
if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Trigger)) {
|
||||
filter = CMaterialFilter::MakeExclude(EMaterialTypes::Trigger);
|
||||
}
|
||||
|
||||
rstl::reserved_vector<TUniqueId, 1024> nearList;
|
||||
BuildNearList(nearList, *touchAABB, filter, &actor);
|
||||
|
||||
for (TUniqueId id : nearList) {
|
||||
CActor* ent2 = static_cast<CActor*>(ObjectById(id));
|
||||
if (!ent2)
|
||||
auto* ent2 = static_cast<CActor*>(ObjectById(id));
|
||||
if (!ent2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::optional<zeus::CAABox> touchAABB2 = ent2->GetTouchBounds();
|
||||
if (!ent2->GetActive() || !touchAABB2)
|
||||
if (!ent2->GetActive() || !touchAABB2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (visits[ent2->GetUniqueId().Value()])
|
||||
if (visits[ent2->GetUniqueId().Value()]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (touchAABB->intersects(*touchAABB2)) {
|
||||
actor.Touch(*ent2, *this);
|
||||
|
@ -2282,23 +2321,25 @@ void CStateManager::RemoveObject(TUniqueId uid) {
|
|||
|
||||
void CStateManager::UpdateRoomAcoustics(TAreaId aid) {
|
||||
u32 updateCount = 0;
|
||||
CScriptRoomAcoustics* updates[10];
|
||||
std::array<CScriptRoomAcoustics*, 10> updates;
|
||||
for (CEntity* ent : GetAllObjectList()) {
|
||||
if (TCastToPtr<CScriptRoomAcoustics> acoustics = ent) {
|
||||
if (acoustics->GetAreaIdAlways() != aid || !acoustics->GetActive())
|
||||
if (acoustics->GetAreaIdAlways() != aid || !acoustics->GetActive()) {
|
||||
continue;
|
||||
}
|
||||
updates[updateCount++] = acoustics.GetPtr();
|
||||
}
|
||||
if (updateCount >= 10)
|
||||
if (updateCount >= updates.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!updateCount) {
|
||||
if (updateCount == 0) {
|
||||
CScriptRoomAcoustics::DisableAuxCallbacks();
|
||||
return;
|
||||
}
|
||||
|
||||
auto idx = int(updateCount * x900_activeRandom->Float() * 0.99f);
|
||||
const auto idx = int(updateCount * x900_activeRandom->Float() * 0.99f);
|
||||
updates[idx]->EnableAuxCallbacks();
|
||||
}
|
||||
|
||||
|
@ -2314,7 +2355,7 @@ void CStateManager::SetCurrentAreaId(TAreaId aid) {
|
|||
if (x8c0_mapWorldInfo->IsAreaVisited(aid))
|
||||
return;
|
||||
x8c0_mapWorldInfo->SetAreaVisited(aid, true);
|
||||
x850_world->GetMapWorld()->RecalculateWorldSphere(*x8c0_mapWorldInfo, *x850_world);
|
||||
x850_world->IGetMapWorld()->RecalculateWorldSphere(*x8c0_mapWorldInfo, *x850_world);
|
||||
}
|
||||
|
||||
void CStateManager::AreaUnloaded(TAreaId) {
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
|
||||
private:
|
||||
s16 x0_nextFreeIndex = 0;
|
||||
u16 x8_idArr[1024] = {};
|
||||
std::array<u16, 1024> x8_idArr{};
|
||||
|
||||
/*
|
||||
std::unique_ptr<CObjectList> x80c_allObjs;
|
||||
|
@ -97,14 +97,16 @@ private:
|
|||
std::unique_ptr<CAiWaypointList> x83c_aiWaypointObjs;
|
||||
std::unique_ptr<CPlatformAndDoorList> x844_platformAndDoorObjs;
|
||||
*/
|
||||
std::array<std::unique_ptr<CObjectList>, 8> x808_objLists = {std::make_unique<CObjectList>(EGameObjectList::All),
|
||||
std::make_unique<CActorList>(),
|
||||
std::make_unique<CPhysicsActorList>(),
|
||||
std::make_unique<CGameCameraList>(),
|
||||
std::make_unique<CGameLightList>(),
|
||||
std::make_unique<CListeningAiList>(),
|
||||
std::make_unique<CAiWaypointList>(),
|
||||
std::make_unique<CPlatformAndDoorList>()};
|
||||
std::array<std::unique_ptr<CObjectList>, 8> x808_objLists{
|
||||
std::make_unique<CObjectList>(EGameObjectList::All),
|
||||
std::make_unique<CActorList>(),
|
||||
std::make_unique<CPhysicsActorList>(),
|
||||
std::make_unique<CGameCameraList>(),
|
||||
std::make_unique<CGameLightList>(),
|
||||
std::make_unique<CListeningAiList>(),
|
||||
std::make_unique<CAiWaypointList>(),
|
||||
std::make_unique<CPlatformAndDoorList>(),
|
||||
};
|
||||
|
||||
std::unique_ptr<CPlayer> x84c_player;
|
||||
std::unique_ptr<CWorld> x850_world;
|
||||
|
@ -156,7 +158,7 @@ private:
|
|||
CRandom16* x900_activeRandom = nullptr;
|
||||
EGameState x904_gameState = EGameState::Running;
|
||||
u32 x908_loaderCount = 0;
|
||||
FScriptLoader x90c_loaderFuncs[int(EScriptObjectType::ScriptObjectTypeMAX)] = {};
|
||||
std::array<FScriptLoader, size_t(EScriptObjectType::ScriptObjectTypeMAX)> x90c_loaderFuncs{};
|
||||
|
||||
bool xab0_worldLoaded = false;
|
||||
|
||||
|
@ -165,8 +167,10 @@ private:
|
|||
std::set<std::string> xb40_uniqueInstanceNames;
|
||||
|
||||
CFinalInput xb54_finalInput;
|
||||
CCameraFilterPassPoly xb84_camFilterPasses[9]; // size: 0x2c
|
||||
CCameraBlurPass xd14_camBlurPasses[9]; // size: 0x34
|
||||
|
||||
static constexpr size_t numCameraPasses = 9;
|
||||
std::array<CCameraFilterPassPoly, numCameraPasses> xb84_camFilterPasses; // size: 0x2c
|
||||
std::array<CCameraBlurPass, numCameraPasses> xd14_camBlurPasses; // size: 0x34
|
||||
|
||||
s32 xeec_hintIdx = -1;
|
||||
u32 xef0_hintPeriods = 0;
|
||||
|
@ -212,12 +216,12 @@ private:
|
|||
u32 xf94_ = 0;
|
||||
};
|
||||
|
||||
CColoredQuadFilter m_deathWhiteout = {EFilterType::Add};
|
||||
CColoredQuadFilter m_escapeWhiteout = {EFilterType::Add};
|
||||
CColoredQuadFilter m_deathWhiteout{EFilterType::Add};
|
||||
CColoredQuadFilter m_escapeWhiteout{EFilterType::Add};
|
||||
bool m_warping = false;
|
||||
|
||||
void UpdateThermalVisor();
|
||||
static void RendererDrawCallback(const void*, const void*, int);
|
||||
static void RendererDrawCallback(void*, void*, int);
|
||||
|
||||
public:
|
||||
CStateManager(const std::weak_ptr<CRelayTracker>&, const std::weak_ptr<CMapWorldInfo>&,
|
||||
|
@ -227,8 +231,8 @@ public:
|
|||
|
||||
u32 GetInputFrameIdx() const { return x8d4_inputFrameIdx; }
|
||||
bool RenderLast(TUniqueId);
|
||||
void AddDrawableActorPlane(const CActor& actor, const zeus::CPlane&, const zeus::CAABox& aabb) const;
|
||||
void AddDrawableActor(const CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const;
|
||||
void AddDrawableActorPlane(CActor& actor, const zeus::CPlane&, const zeus::CAABox& aabb) const;
|
||||
void AddDrawableActor(CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const;
|
||||
bool SpecialSkipCinematic();
|
||||
TAreaId GetVisAreaId() const;
|
||||
s32 GetWeaponIdCount(TUniqueId, EWeaponType) const;
|
||||
|
@ -251,7 +255,7 @@ public:
|
|||
const std::vector<CLight>& GetDynamicLightList() const { return x8e0_dynamicLights; }
|
||||
void BuildDynamicLightListForWorld();
|
||||
void DrawDebugStuff() const;
|
||||
void RenderCamerasAndAreaLights() const;
|
||||
void RenderCamerasAndAreaLights();
|
||||
void DrawE3DeathEffect();
|
||||
void DrawAdditionalFilters();
|
||||
zeus::CFrustum SetupDrawFrustum(const SViewport& vp) const;
|
||||
|
@ -271,7 +275,7 @@ public:
|
|||
void PreRender();
|
||||
void GetCharacterRenderMaskAndTarget(bool thawed, int& mask, int& target) const;
|
||||
bool GetVisSetForArea(TAreaId, TAreaId, CPVSVisSet& setOut) const;
|
||||
void RecursiveDrawTree(TUniqueId) const;
|
||||
void RecursiveDrawTree(TUniqueId);
|
||||
void SendScriptMsg(CEntity* dest, TUniqueId src, EScriptObjectMessage msg);
|
||||
void SendScriptMsg(TUniqueId dest, TUniqueId src, EScriptObjectMessage msg);
|
||||
void SendScriptMsg(TUniqueId src, TEditorId dest, EScriptObjectMessage msg, EScriptObjectState state);
|
||||
|
|
|
@ -16,7 +16,7 @@ class CStaticInterference {
|
|||
std::vector<CStaticInterferenceSource> m_sources;
|
||||
|
||||
public:
|
||||
CStaticInterference(int sourceCount);
|
||||
explicit CStaticInterference(int sourceCount);
|
||||
void RemoveSource(TUniqueId id);
|
||||
void Update(CStateManager&, float dt);
|
||||
float GetTotalInterference() const;
|
||||
|
|
|
@ -8,7 +8,7 @@ class CPaletteInfo {
|
|||
u64 m_dolphinHash;
|
||||
|
||||
public:
|
||||
CPaletteInfo(CInputStream& in)
|
||||
explicit CPaletteInfo(CInputStream& in)
|
||||
: m_format(in.readUint32Big()), m_elementCount(in.readUint32Big()), m_dolphinHash(in.readUint64Big()) {}
|
||||
};
|
||||
class CTextureInfo {
|
||||
|
@ -20,7 +20,7 @@ class CTextureInfo {
|
|||
std::optional<CPaletteInfo> m_paletteInfo;
|
||||
|
||||
public:
|
||||
CTextureInfo(CInputStream& in)
|
||||
explicit CTextureInfo(CInputStream& in)
|
||||
: m_format(ETexelFormat(in.readUint32Big()))
|
||||
, m_mipCount(in.readUint32Big())
|
||||
, m_width(in.readUint16Big())
|
||||
|
@ -36,7 +36,7 @@ public:
|
|||
std::map<CAssetId, CTextureInfo> m_textureInfo;
|
||||
|
||||
public:
|
||||
CTextureCache(CInputStream& in);
|
||||
explicit CTextureCache(CInputStream& in);
|
||||
|
||||
|
||||
const CTextureInfo* GetTextureInfo(CAssetId id) const;
|
||||
|
|
|
@ -112,7 +112,7 @@ CToken& CToken::operator=(const CToken& other) {
|
|||
}
|
||||
return *this;
|
||||
}
|
||||
CToken& CToken::operator=(CToken&& other) {
|
||||
CToken& CToken::operator=(CToken&& other) noexcept {
|
||||
Unlock();
|
||||
RemoveRef();
|
||||
x0_objRef = other.x0_objRef;
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
IObj* GetObj();
|
||||
const IObj* GetObj() const { return const_cast<CToken*>(this)->GetObj(); }
|
||||
CToken& operator=(const CToken& other);
|
||||
CToken& operator=(CToken&& other);
|
||||
CToken& operator=(CToken&& other) noexcept;
|
||||
CToken() = default;
|
||||
CToken(const CToken& other);
|
||||
CToken(CToken&& other) noexcept;
|
||||
|
@ -101,6 +101,7 @@ public:
|
|||
return TObjOwnerDerivedFromIObj<T>::GetNewDerivedObject(std::move(obj));
|
||||
}
|
||||
TToken() = default;
|
||||
virtual ~TToken() = default;
|
||||
TToken(const CToken& other) : CToken(other) {}
|
||||
TToken(CToken&& other) : CToken(std::move(other)) {}
|
||||
TToken(std::unique_ptr<T>&& obj) : CToken(GetIObjObjectFor(std::move(obj))) {}
|
||||
|
@ -108,13 +109,19 @@ public:
|
|||
*this = CToken(GetIObjObjectFor(std::move(obj)));
|
||||
return this;
|
||||
}
|
||||
T* GetObj() {
|
||||
virtual void Unlock() { CToken::Unlock(); }
|
||||
virtual void Lock() { CToken::Lock(); }
|
||||
virtual T* GetObj() {
|
||||
TObjOwnerDerivedFromIObj<T>* owner = static_cast<TObjOwnerDerivedFromIObj<T>*>(CToken::GetObj());
|
||||
if (owner)
|
||||
return owner->GetObj();
|
||||
return nullptr;
|
||||
}
|
||||
const T* GetObj() const { return const_cast<TToken<T>*>(this)->GetObj(); }
|
||||
virtual const T* GetObj() const { return const_cast<TToken<T>*>(this)->GetObj(); }
|
||||
virtual TToken& operator=(const CToken& other) {
|
||||
CToken::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
T* operator->() { return GetObj(); }
|
||||
const T* operator->() const { return GetObj(); }
|
||||
T& operator*() { return *GetObj(); }
|
||||
|
@ -130,26 +137,24 @@ public:
|
|||
TCachedToken() = default;
|
||||
TCachedToken(const CToken& other) : TToken<T>(other) {}
|
||||
TCachedToken(CToken&& other) : TToken<T>(std::move(other)) {}
|
||||
T* GetObj() {
|
||||
T* GetObj() override {
|
||||
if (!m_obj)
|
||||
m_obj = TToken<T>::GetObj();
|
||||
return m_obj;
|
||||
}
|
||||
const T* GetObj() const { return const_cast<TCachedToken<T>*>(this)->GetObj(); }
|
||||
T* operator->() { return GetObj(); }
|
||||
const T* operator->() const { return GetObj(); }
|
||||
void Unlock() {
|
||||
const T* GetObj() const override { return const_cast<TCachedToken<T>*>(this)->GetObj(); }
|
||||
void Unlock() override {
|
||||
TToken<T>::Unlock();
|
||||
m_obj = nullptr;
|
||||
}
|
||||
|
||||
TCachedToken& operator=(const TCachedToken& other) {
|
||||
CToken::operator=(other);
|
||||
TToken<T>::operator=(other);
|
||||
m_obj = nullptr;
|
||||
return *this;
|
||||
}
|
||||
TCachedToken& operator=(const CToken& other) {
|
||||
CToken::operator=(other);
|
||||
TCachedToken& operator=(const CToken& other) override {
|
||||
TToken<T>::operator=(other);
|
||||
m_obj = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
@ -167,7 +172,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
TLockedToken(const CToken& other) : TCachedToken<T>(other) { CToken::Lock(); }
|
||||
TLockedToken& operator=(const CToken& other) {
|
||||
TLockedToken& operator=(const CToken& other) override {
|
||||
CToken oldTok = std::move(*this);
|
||||
TCachedToken<T>::operator=(other);
|
||||
CToken::Lock();
|
||||
|
|
|
@ -242,7 +242,7 @@ void CBallCamera::Reset(const zeus::CTransform& xf, CStateManager& mgr) {
|
|||
}
|
||||
}
|
||||
|
||||
void CBallCamera::Render(const CStateManager& mgr) const {
|
||||
void CBallCamera::Render(CStateManager& mgr) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
@ -586,13 +586,13 @@ void CBallCamera::CheckFailsafe(float dt, CStateManager& mgr) {
|
|||
void CBallCamera::UpdateObjectTooCloseId(CStateManager& mgr) {
|
||||
x3e0_tooCloseActorDist = 1000000.f;
|
||||
x3dc_tooCloseActorId = kInvalidUniqueId;
|
||||
zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition();
|
||||
for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) {
|
||||
if (TCastToPtr<CScriptDoor> door = ent) {
|
||||
const zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition();
|
||||
for (const CEntity* ent : mgr.GetPlatformAndDoorObjectList()) {
|
||||
if (const TCastToConstPtr<CScriptDoor> door = ent) {
|
||||
if (mgr.GetPlayer().GetAreaIdAlways() == door->GetAreaIdAlways()) {
|
||||
door->GetBoundingBox();
|
||||
float minMag = std::min((door->GetTranslation() - GetTranslation()).magnitude(),
|
||||
(door->GetTranslation() - ballPos).magnitude());
|
||||
const float minMag = std::min((door->GetTranslation() - GetTranslation()).magnitude(),
|
||||
(door->GetTranslation() - ballPos).magnitude());
|
||||
if (minMag < 30.f && minMag < x3e0_tooCloseActorDist) {
|
||||
x3dc_tooCloseActorId = door->GetUniqueId();
|
||||
x3e0_tooCloseActorDist = minMag;
|
||||
|
@ -611,7 +611,7 @@ void CBallCamera::UpdateAnglePerSecond(float dt) {
|
|||
}
|
||||
|
||||
void CBallCamera::UpdateUsingPathCameras(float dt, CStateManager& mgr) {
|
||||
if (TCastToPtr<CPathCamera> cam = mgr.ObjectById(mgr.GetCameraManager()->GetPathCameraId())) {
|
||||
if (const TCastToConstPtr<CPathCamera> cam = mgr.ObjectById(mgr.GetCameraManager()->GetPathCameraId())) {
|
||||
TeleportCamera(cam->GetTransform(), mgr);
|
||||
x18d_26_lookAtBall = true;
|
||||
}
|
||||
|
@ -707,15 +707,15 @@ zeus::CVector3f CBallCamera::TweenVelocity(const zeus::CVector3f& curVel, const
|
|||
}
|
||||
|
||||
zeus::CVector3f CBallCamera::MoveCollisionActor(const zeus::CVector3f& pos, float dt, CStateManager& mgr) {
|
||||
if (TCastToPtr<CPhysicsActor> act = mgr.ObjectById(x46c_collisionActorId)) {
|
||||
zeus::CVector3f posDelta = pos - act->GetTranslation();
|
||||
if (const TCastToPtr<CPhysicsActor> act = mgr.ObjectById(x46c_collisionActorId)) {
|
||||
const zeus::CVector3f posDelta = pos - act->GetTranslation();
|
||||
if (!posDelta.canBeNormalized() || posDelta.magnitude() < 0.01f) {
|
||||
act->Stop();
|
||||
return act->GetTranslation();
|
||||
}
|
||||
zeus::CVector3f oldTranslation = act->GetTranslation();
|
||||
zeus::CVector3f oldVel = act->GetVelocity();
|
||||
zeus::CVector3f newVel = ComputeVelocity(oldVel, posDelta * (1.f / dt));
|
||||
const zeus::CVector3f oldTranslation = act->GetTranslation();
|
||||
const zeus::CVector3f oldVel = act->GetVelocity();
|
||||
const zeus::CVector3f newVel = ComputeVelocity(oldVel, posDelta * (1.f / dt));
|
||||
act->SetVelocityWR(newVel);
|
||||
act->SetMovable(true);
|
||||
act->AddMaterial(EMaterialTypes::Solid, mgr);
|
||||
|
@ -808,8 +808,8 @@ void CBallCamera::UpdateUsingFreeLook(float dt, CStateManager& mgr) {
|
|||
}
|
||||
|
||||
x37c_camSpline.UpdateSplineLength();
|
||||
zeus::CVector3f pos = x37c_camSpline.GetInterpolatedSplinePointByLength(splineT * x37c_camSpline.x44_length).origin;
|
||||
if (TCastToPtr<CPhysicsActor> act = mgr.ObjectById(x46c_collisionActorId)) {
|
||||
const zeus::CVector3f pos = x37c_camSpline.GetInterpolatedSplinePointByLength(splineT * x37c_camSpline.x44_length).origin;
|
||||
if (const TCastToPtr<CPhysicsActor> act = mgr.ObjectById(x46c_collisionActorId)) {
|
||||
CMaterialFilter filter = act->GetMaterialFilter();
|
||||
CMaterialFilter tmpFilter = filter;
|
||||
tmpFilter.IncludeList().Add(EMaterialTypes::Wall);
|
||||
|
@ -820,8 +820,9 @@ void CBallCamera::UpdateUsingFreeLook(float dt, CStateManager& mgr) {
|
|||
}
|
||||
|
||||
zeus::CVector3f lookDir = x1d8_lookPos - desiredPos;
|
||||
if (x18d_26_lookAtBall)
|
||||
if (x18d_26_lookAtBall) {
|
||||
lookDir = ballPos - desiredPos;
|
||||
}
|
||||
|
||||
if (lookDir.canBeNormalized()) {
|
||||
lookDir.normalize();
|
||||
|
@ -830,8 +831,9 @@ void CBallCamera::UpdateUsingFreeLook(float dt, CStateManager& mgr) {
|
|||
|
||||
TeleportCamera(desiredPos, mgr);
|
||||
|
||||
if (x3d0_24_camBehindFloorOrWall && x374_splineCtrl / x378_splineCtrlRange < 0.5f)
|
||||
if (x3d0_24_camBehindFloorOrWall && x374_splineCtrl / x378_splineCtrlRange < 0.5f) {
|
||||
x36c_splineState = ESplineState::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
zeus::CVector3f CBallCamera::InterpolateCameraElevation(const zeus::CVector3f& camPos, float dt) {
|
||||
|
@ -1307,7 +1309,7 @@ void CBallCamera::UpdateUsingColliders(float dt, CStateManager& mgr) {
|
|||
}
|
||||
|
||||
void CBallCamera::UpdateUsingSpindleCameras(float dt, CStateManager& mgr) {
|
||||
if (TCastToPtr<CScriptSpindleCamera> cam = mgr.ObjectById(mgr.GetCameraManager()->GetSpindleCameraId())) {
|
||||
if (const TCastToConstPtr<CScriptSpindleCamera> cam = mgr.ObjectById(mgr.GetCameraManager()->GetSpindleCameraId())) {
|
||||
TeleportCamera(cam->GetTransform(), mgr);
|
||||
x18d_26_lookAtBall = true;
|
||||
}
|
||||
|
@ -1315,12 +1317,13 @@ void CBallCamera::UpdateUsingSpindleCameras(float dt, CStateManager& mgr) {
|
|||
|
||||
zeus::CVector3f CBallCamera::ClampElevationToWater(zeus::CVector3f& pos, CStateManager& mgr) const {
|
||||
zeus::CVector3f ret = pos;
|
||||
if (TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(mgr.GetPlayer().GetFluidId())) {
|
||||
float waterZ = water->GetTriggerBoundsWR().max.z();
|
||||
if (pos.z() >= waterZ && pos.z() - waterZ <= 0.25f)
|
||||
if (const TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(mgr.GetPlayer().GetFluidId())) {
|
||||
const float waterZ = water->GetTriggerBoundsWR().max.z();
|
||||
if (pos.z() >= waterZ && pos.z() - waterZ <= 0.25f) {
|
||||
ret.z() = 0.25f + waterZ;
|
||||
else if (pos.z() < waterZ && pos.z() - waterZ >= -0.12f)
|
||||
} else if (pos.z() < waterZ && pos.z() - waterZ >= -0.12f) {
|
||||
ret.z() = waterZ - 0.12f;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1366,24 +1369,25 @@ void CBallCamera::UpdateUsingTransitions(float dt, CStateManager& mgr) {
|
|||
float distance = x194_targetMinDistance;
|
||||
ConstrainElevationAndDistance(elevation, distance, dt, mgr);
|
||||
distance = x194_targetMinDistance;
|
||||
bool r28 = IsBallNearDoor(GetTranslation(), mgr) || x478_shortMoveCount > 2;
|
||||
zeus::CVector3f toDesired =
|
||||
const bool r28 = IsBallNearDoor(GetTranslation(), mgr) || x478_shortMoveCount > 2;
|
||||
const zeus::CVector3f toDesired =
|
||||
FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, r28) - eyePos;
|
||||
zeus::CVector3f finalPos = toDesired * mgr.GetPlayer().GetMorphFactor() + eyePos;
|
||||
if (TCastToPtr<CPhysicsActor> act = mgr.ObjectById(x46c_collisionActorId)) {
|
||||
if (const TCastToPtr<CPhysicsActor> act = mgr.ObjectById(x46c_collisionActorId)) {
|
||||
act->SetTranslation(GetTranslation());
|
||||
finalPos = ClampElevationToWater(finalPos, mgr);
|
||||
finalPos = MoveCollisionActor(finalPos, dt, mgr);
|
||||
zeus::CVector3f camToLookDir = x1d8_lookPos - finalPos;
|
||||
if (camToLookDir.canBeNormalized()) {
|
||||
camToLookDir.normalize();
|
||||
float devDot = std::fabs(zeus::clamp(-1.f, lookDir.dot(camToLookDir), 1.f));
|
||||
float devAngle = zeus::clamp(-1.f, mgr.GetPlayer().GetMorphFactor() * 0.5f, 1.f) * std::acos(devDot);
|
||||
if (devDot < 1.f)
|
||||
const float devDot = std::fabs(zeus::clamp(-1.f, lookDir.dot(camToLookDir), 1.f));
|
||||
const float devAngle = zeus::clamp(-1.f, mgr.GetPlayer().GetMorphFactor() * 0.5f, 1.f) * std::acos(devDot);
|
||||
if (devDot < 1.f) {
|
||||
SetTransform(zeus::CQuaternion::lookAt(xe8.basis[1], camToLookDir, devAngle).toTransform() *
|
||||
xe8.getRotation());
|
||||
else
|
||||
} else {
|
||||
SetTransform(zeus::lookAt(zeus::skZero3f, camToLookDir));
|
||||
}
|
||||
}
|
||||
}
|
||||
SetTransform(ValidateCameraTransform(x34_transform, xe8));
|
||||
|
@ -1509,7 +1513,7 @@ bool CBallCamera::SplineIntersectTest(CMaterialList& intersectMat, CStateManager
|
|||
TUniqueId xe38 = kInvalidUniqueId;
|
||||
rstl::reserved_vector<CRayCastResult, 12> xacc;
|
||||
rstl::reserved_vector<CRayCastResult, 12> xd10;
|
||||
CMaterialFilter filter =
|
||||
constexpr auto filter =
|
||||
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Floor, EMaterialTypes::Wall},
|
||||
{EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player,
|
||||
EMaterialTypes::Character, EMaterialTypes::CameraPassthrough});
|
||||
|
@ -1544,18 +1548,23 @@ bool CBallCamera::SplineIntersectTest(CMaterialList& intersectMat, CStateManager
|
|||
}
|
||||
|
||||
bool CBallCamera::IsBallNearDoor(const zeus::CVector3f& pos, CStateManager& mgr) {
|
||||
TCastToConstPtr<CScriptDoor> door = mgr.GetObjectById(mgr.GetCameraManager()->GetBallCamera()->x3dc_tooCloseActorId);
|
||||
if (!door || door->x2a8_26_isOpen)
|
||||
const TCastToConstPtr<CScriptDoor> door =
|
||||
mgr.GetObjectById(mgr.GetCameraManager()->GetBallCamera()->x3dc_tooCloseActorId);
|
||||
if (!door || door->x2a8_26_isOpen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto tb = door->GetTouchBounds();
|
||||
zeus::CAABox testAABB(pos - 0.3f, pos + 0.3f);
|
||||
if (!tb || !tb->intersects(testAABB))
|
||||
const auto tb = door->GetTouchBounds();
|
||||
const zeus::CAABox testAABB(pos - 0.3f, pos + 0.3f);
|
||||
if (!tb || !tb->intersects(testAABB)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TCastToConstPtr<CScriptDock> dock = mgr.GetObjectById(door->x282_dockId))
|
||||
if (std::fabs(dock->GetPlane(mgr).pointToPlaneDist(pos)) < 1.15f)
|
||||
if (const TCastToConstPtr<CScriptDock> dock = mgr.GetObjectById(door->x282_dockId)) {
|
||||
if (std::fabs(dock->GetPlane(mgr).pointToPlaneDist(pos)) < 1.15f) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1586,17 +1595,20 @@ bool CBallCamera::ConstrainElevationAndDistance(float& elevation, float& distanc
|
|||
float newDistance = distance;
|
||||
float baseElevation = elevation;
|
||||
float springSpeed = 1.f;
|
||||
if (TCastToConstPtr<CScriptDoor> door = mgr.GetObjectById(x3dc_tooCloseActorId)) {
|
||||
if (const TCastToConstPtr<CScriptDoor> door = mgr.GetObjectById(x3dc_tooCloseActorId)) {
|
||||
if (!door->x2a8_29_ballDoor) {
|
||||
stretchFac = zeus::clamp(-1.f, std::fabs(x3e0_tooCloseActorDist / (3.f * distance)), 1.f);
|
||||
if (x3e0_tooCloseActorDist < 3.f * distance)
|
||||
if (x3e0_tooCloseActorDist < 3.f * distance) {
|
||||
doorClose = true;
|
||||
if (door->x2a8_26_isOpen)
|
||||
}
|
||||
if (door->x2a8_26_isOpen) {
|
||||
newDistance = stretchFac * (distance - x468_conservativeDoorCamDistance) + x468_conservativeDoorCamDistance;
|
||||
else
|
||||
} else {
|
||||
newDistance = stretchFac * (distance - 5.f) + 5.f;
|
||||
if (x18d_28_obtuseDirection)
|
||||
}
|
||||
if (x18d_28_obtuseDirection) {
|
||||
newDistance *= 1.f + x308_speedFactor;
|
||||
}
|
||||
baseElevation = door->x2a8_26_isOpen ? 0.75f : 1.5f;
|
||||
springSpeed = 4.f;
|
||||
}
|
||||
|
@ -1799,9 +1811,10 @@ bool CBallCamera::DetectCollision(const zeus::CVector3f& from, const zeus::CVect
|
|||
void CBallCamera::Think(float dt, CStateManager& mgr) {
|
||||
mgr.SetActorAreaId(*this, mgr.GetNextAreaId());
|
||||
UpdatePlayerMovement(dt, mgr);
|
||||
TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(x46c_collisionActorId);
|
||||
if (colAct)
|
||||
const TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(x46c_collisionActorId);
|
||||
if (colAct) {
|
||||
mgr.SetActorAreaId(*colAct, mgr.GetNextAreaId());
|
||||
}
|
||||
|
||||
switch (mgr.GetPlayer().GetCameraState()) {
|
||||
default:
|
||||
|
@ -1936,8 +1949,9 @@ void CBallCamera::TeleportCamera(const zeus::CVector3f& pos, CStateManager& mgr)
|
|||
TeleportColliders(x264_smallColliders, pos);
|
||||
TeleportColliders(x274_mediumColliders, pos);
|
||||
TeleportColliders(x284_largeColliders, pos);
|
||||
if (TCastToPtr<CCollisionActor> act = mgr.ObjectById(x46c_collisionActorId))
|
||||
if (const TCastToPtr<CCollisionActor> act = mgr.ObjectById(x46c_collisionActorId)) {
|
||||
act->SetTranslation(pos);
|
||||
}
|
||||
}
|
||||
|
||||
void CBallCamera::TeleportCamera(const zeus::CTransform& xf, CStateManager& mgr) {
|
||||
|
|
|
@ -247,7 +247,7 @@ public:
|
|||
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) override;
|
||||
void ProcessInput(const CFinalInput& input, CStateManager& mgr) override;
|
||||
void Reset(const zeus::CTransform&, CStateManager& mgr) override;
|
||||
void Render(const CStateManager& mgr) const override;
|
||||
void Render(CStateManager& mgr) override;
|
||||
EBallCameraBehaviour GetBehaviour() const { return x188_behaviour; }
|
||||
EBallCameraState GetState() const { return x400_state; }
|
||||
void SetState(EBallCameraState state, CStateManager& mgr);
|
||||
|
|
|
@ -104,9 +104,11 @@ void CCameraFilterPass<S>::DisableFilter(float time) {
|
|||
}
|
||||
|
||||
template <class S>
|
||||
void CCameraFilterPass<S>::Draw() const {
|
||||
if (m_shader)
|
||||
const_cast<S&>(*m_shader).DrawFilter(x8_shape, x18_curColor, GetT(x4_nextType == EFilterType::Passthru));
|
||||
void CCameraFilterPass<S>::Draw() {
|
||||
if (!m_shader) {
|
||||
return;
|
||||
}
|
||||
m_shader->DrawFilter(x8_shape, x18_curColor, GetT(x4_nextType == EFilterType::Passthru));
|
||||
}
|
||||
|
||||
float CCameraFilterPassBase::GetT(bool invert) const {
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
virtual void SetFilter(EFilterType type, EFilterShape shape, float time, const zeus::CColor& color,
|
||||
CAssetId txtr) = 0;
|
||||
virtual void DisableFilter(float time) = 0;
|
||||
virtual void Draw() const = 0;
|
||||
virtual void Draw() = 0;
|
||||
};
|
||||
|
||||
template <class S>
|
||||
|
@ -69,11 +69,11 @@ public:
|
|||
void Update(float dt) override;
|
||||
void SetFilter(EFilterType type, EFilterShape shape, float time, const zeus::CColor& color, CAssetId txtr) override;
|
||||
void DisableFilter(float time) override;
|
||||
void Draw() const override;
|
||||
void Draw() override;
|
||||
};
|
||||
|
||||
class CCameraFilterPassPoly {
|
||||
EFilterShape m_shape;
|
||||
EFilterShape m_shape{};
|
||||
std::unique_ptr<CCameraFilterPassBase> m_filter;
|
||||
|
||||
public:
|
||||
|
@ -107,8 +107,8 @@ class CCameraBlurPass {
|
|||
// bool x2d_noPersistentCopy = false;
|
||||
// u32 x30_persistentBuf = 0;
|
||||
|
||||
mutable std::optional<CCameraBlurFilter> m_shader;
|
||||
mutable std::optional<CXRayBlurFilter> m_xrayShader;
|
||||
std::optional<CCameraBlurFilter> m_shader;
|
||||
std::optional<CXRayBlurFilter> m_xrayShader;
|
||||
|
||||
public:
|
||||
void Draw(bool clearDepth = false);
|
||||
|
|
|
@ -71,10 +71,10 @@ void CCameraManager::EnterCinematic(CStateManager& mgr) {
|
|||
mgr.GetPlayer().GetPlayerGun()->CancelFiring(mgr);
|
||||
mgr.GetPlayer().UnFreeze(mgr);
|
||||
|
||||
for (CEntity* ent : mgr.GetAllObjectList()) {
|
||||
if (TCastToPtr<CExplosion> explo = ent) {
|
||||
for (const CEntity* ent : mgr.GetAllObjectList()) {
|
||||
if (const TCastToConstPtr<CExplosion> explo = ent) {
|
||||
mgr.FreeScriptObject(explo->GetUniqueId());
|
||||
} else if (TCastToPtr<CWeapon> weap = ent) {
|
||||
} else if (const TCastToConstPtr<CWeapon> weap = ent) {
|
||||
if (weap->GetActive()) {
|
||||
if (False(weap->GetAttribField() & EProjectileAttrib::KeepInCinematic)) {
|
||||
if (TCastToConstPtr<CAi>(mgr.GetObjectById(weap->GetOwnerId())) ||
|
||||
|
@ -87,13 +87,16 @@ void CCameraManager::EnterCinematic(CStateManager& mgr) {
|
|||
}
|
||||
|
||||
void CCameraManager::AddCinemaCamera(TUniqueId id, CStateManager& stateMgr) {
|
||||
if (x4_cineCameras.empty())
|
||||
if (x4_cineCameras.empty()) {
|
||||
EnterCinematic(stateMgr);
|
||||
}
|
||||
|
||||
RemoveCinemaCamera(id, stateMgr);
|
||||
x4_cineCameras.push_back(id);
|
||||
if (TCastToPtr<CCinematicCamera> cam = stateMgr.ObjectById(id)) {
|
||||
if (cam->GetFlags() & 0x4) // into player eye
|
||||
{
|
||||
|
||||
if (const TCastToPtr<CCinematicCamera> cam = stateMgr.ObjectById(id)) {
|
||||
// Into player eye
|
||||
if ((cam->GetFlags() & 0x4) != 0) {
|
||||
float time = 4.f;
|
||||
float delayTime = cam->GetDuration() - 4.f;
|
||||
if (delayTime < 0.f) {
|
||||
|
@ -105,12 +108,13 @@ void CCameraManager::AddCinemaCamera(TUniqueId id, CStateManager& stateMgr) {
|
|||
}
|
||||
}
|
||||
|
||||
void CCameraManager::SetInsideFluid(bool val, TUniqueId fluidId) {
|
||||
if (val) {
|
||||
void CCameraManager::SetInsideFluid(bool isInside, TUniqueId fluidId) {
|
||||
if (isInside) {
|
||||
++x74_fluidCounter;
|
||||
x78_fluidId = fluidId;
|
||||
} else
|
||||
} else {
|
||||
--x74_fluidCounter;
|
||||
}
|
||||
}
|
||||
|
||||
void CCameraManager::Update(float dt, CStateManager& stateMgr) {
|
||||
|
@ -149,8 +153,8 @@ void CCameraManager::CreateStandardCameras(CStateManager& stateMgr) {
|
|||
}
|
||||
|
||||
void CCameraManager::SkipCinematic(CStateManager& stateMgr) {
|
||||
TUniqueId camId = GetCurrentCameraId();
|
||||
CCinematicCamera* ent = static_cast<CCinematicCamera*>(stateMgr.ObjectById(camId));
|
||||
const TUniqueId camId = GetCurrentCameraId();
|
||||
auto* ent = static_cast<CCinematicCamera*>(stateMgr.ObjectById(camId));
|
||||
while (ent) {
|
||||
ent->SetActive(false);
|
||||
ent->WasDeactivated(stateMgr);
|
||||
|
@ -162,7 +166,7 @@ void CCameraManager::SkipCinematic(CStateManager& stateMgr) {
|
|||
|
||||
void CCameraManager::SetPathCamera(TUniqueId id, CStateManager& mgr) {
|
||||
xa4_pathCamId = id;
|
||||
if (TCastToPtr<CPathCamera> cam = mgr.ObjectById(id)) {
|
||||
if (const TCastToPtr<CPathCamera> cam = mgr.ObjectById(id)) {
|
||||
cam->Reset(GetCurrentCameraTransform(mgr), mgr);
|
||||
x80_ballCamera->TeleportCamera(cam->GetTransform(), mgr);
|
||||
}
|
||||
|
@ -170,7 +174,7 @@ void CCameraManager::SetPathCamera(TUniqueId id, CStateManager& mgr) {
|
|||
|
||||
void CCameraManager::SetSpindleCamera(TUniqueId id, CStateManager& mgr) {
|
||||
xa2_spindleCamId = id;
|
||||
if (TCastToPtr<CScriptSpindleCamera> cam = mgr.ObjectById(id)) {
|
||||
if (const TCastToPtr<CScriptSpindleCamera> cam = mgr.ObjectById(id)) {
|
||||
cam->Reset(GetCurrentCameraTransform(mgr), mgr);
|
||||
x80_ballCamera->TeleportCamera(cam->GetTransform(), mgr);
|
||||
}
|
||||
|
@ -187,32 +191,37 @@ void CCameraManager::InterpolateToBallCamera(const zeus::CTransform& xf, TUnique
|
|||
}
|
||||
|
||||
void CCameraManager::RestoreHintlessCamera(CStateManager& mgr) {
|
||||
TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(xa6_camHintId);
|
||||
zeus::CTransform ballCamXf = x80_ballCamera->GetTransform();
|
||||
const TCastToConstPtr<CScriptCameraHint> hint = mgr.ObjectById(xa6_camHintId);
|
||||
const zeus::CTransform ballCamXf = x80_ballCamera->GetTransform();
|
||||
|
||||
xa6_camHintId = kInvalidUniqueId;
|
||||
xa8_hintPriority = 1000;
|
||||
if (hint) {
|
||||
zeus::CVector3f camToPlayerFlat = mgr.GetPlayer().GetTranslation() - ballCamXf.origin;
|
||||
camToPlayerFlat.z() = 0.f;
|
||||
if (camToPlayerFlat.canBeNormalized())
|
||||
camToPlayerFlat.normalize();
|
||||
else
|
||||
camToPlayerFlat = mgr.GetPlayer().GetMoveDir();
|
||||
|
||||
x80_ballCamera->ResetToTweaks(mgr);
|
||||
x80_ballCamera->UpdateLookAtPosition(0.f, mgr);
|
||||
if (!mgr.GetPlayer().IsMorphBallTransitioning() &&
|
||||
hint->GetHint().GetBehaviourType() != CBallCamera::EBallCameraBehaviour::Default) {
|
||||
if ((hint->GetHint().GetOverrideFlags() & 0x1000) != 0) {
|
||||
x80_ballCamera->SetClampVelRange(hint->GetHint().GetClampVelRange());
|
||||
x80_ballCamera->SetClampVelTimer(hint->GetHint().GetClampVelTime());
|
||||
} else {
|
||||
x80_ballCamera->TeleportCamera(x80_ballCamera->UpdateLookDirection(camToPlayerFlat, mgr), mgr);
|
||||
InterpolateToBallCamera(ballCamXf, x80_ballCamera->GetUniqueId(), x80_ballCamera->GetLookPos(),
|
||||
hint->GetHint().GetClampVelTime(), hint->GetHint().GetClampVelRange(),
|
||||
hint->GetHint().GetClampRotRange(), (hint->GetHint().GetOverrideFlags() & 0x800) != 0,
|
||||
mgr);
|
||||
}
|
||||
if (!hint) {
|
||||
return;
|
||||
}
|
||||
|
||||
zeus::CVector3f camToPlayerFlat = mgr.GetPlayer().GetTranslation() - ballCamXf.origin;
|
||||
camToPlayerFlat.z() = 0.f;
|
||||
if (camToPlayerFlat.canBeNormalized()) {
|
||||
camToPlayerFlat.normalize();
|
||||
} else {
|
||||
camToPlayerFlat = mgr.GetPlayer().GetMoveDir();
|
||||
}
|
||||
|
||||
x80_ballCamera->ResetToTweaks(mgr);
|
||||
x80_ballCamera->UpdateLookAtPosition(0.f, mgr);
|
||||
if (!mgr.GetPlayer().IsMorphBallTransitioning() &&
|
||||
hint->GetHint().GetBehaviourType() != CBallCamera::EBallCameraBehaviour::Default) {
|
||||
if ((hint->GetHint().GetOverrideFlags() & 0x1000) != 0) {
|
||||
x80_ballCamera->SetClampVelRange(hint->GetHint().GetClampVelRange());
|
||||
x80_ballCamera->SetClampVelTimer(hint->GetHint().GetClampVelTime());
|
||||
} else {
|
||||
x80_ballCamera->TeleportCamera(x80_ballCamera->UpdateLookDirection(camToPlayerFlat, mgr), mgr);
|
||||
InterpolateToBallCamera(ballCamXf, x80_ballCamera->GetUniqueId(), x80_ballCamera->GetLookPos(),
|
||||
hint->GetHint().GetClampVelTime(), hint->GetHint().GetClampVelRange(),
|
||||
hint->GetHint().GetClampRotRange(), (hint->GetHint().GetOverrideFlags() & 0x800) != 0,
|
||||
mgr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,15 +241,16 @@ void CCameraManager::ApplyCameraHint(const CScriptCameraHint& hint, CStateManage
|
|||
mgr.GetPlayer().SetCameraState(CPlayer::EPlayerCameraState::Ball, mgr);
|
||||
}
|
||||
|
||||
TCastToPtr<CScriptCameraHint> oldHint = mgr.ObjectById(xa6_camHintId);
|
||||
const TCastToConstPtr<CScriptCameraHint> oldHint = mgr.ObjectById(xa6_camHintId);
|
||||
xa6_camHintId = hint.GetUniqueId();
|
||||
xa8_hintPriority = hint.GetPriority();
|
||||
|
||||
zeus::CTransform camXf = GetCurrentCameraTransform(mgr);
|
||||
const zeus::CTransform camXf = GetCurrentCameraTransform(mgr);
|
||||
x80_ballCamera->ApplyCameraHint(mgr);
|
||||
|
||||
if ((hint.GetHint().GetOverrideFlags() & 0x20) != 0)
|
||||
if ((hint.GetHint().GetOverrideFlags() & 0x20) != 0) {
|
||||
x80_ballCamera->ResetPosition(mgr);
|
||||
}
|
||||
|
||||
switch (hint.GetHint().GetBehaviourType()) {
|
||||
case CBallCamera::EBallCameraBehaviour::PathCameraDesiredPos:
|
||||
|
@ -256,8 +266,9 @@ void CCameraManager::ApplyCameraHint(const CScriptCameraHint& hint, CStateManage
|
|||
break;
|
||||
}
|
||||
|
||||
if ((hint.GetHint().GetOverrideFlags() & 0x2000) != 0)
|
||||
if ((hint.GetHint().GetOverrideFlags() & 0x2000) != 0) {
|
||||
SkipBallCameraCinematic(mgr);
|
||||
}
|
||||
|
||||
x80_ballCamera->UpdateLookAtPosition(0.f, mgr);
|
||||
|
||||
|
@ -273,7 +284,7 @@ void CCameraManager::ApplyCameraHint(const CScriptCameraHint& hint, CStateManage
|
|||
void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) {
|
||||
bool invalidHintRemoved = false;
|
||||
for (auto it = xac_cameraHints.begin(); it != xac_cameraHints.end();) {
|
||||
if (!TCastToPtr<CScriptCameraHint>(mgr.ObjectById(it->second))) {
|
||||
if (!TCastToConstPtr<CScriptCameraHint>(mgr.ObjectById(it->second))) {
|
||||
invalidHintRemoved = true;
|
||||
it = xac_cameraHints.erase(it);
|
||||
continue;
|
||||
|
@ -282,8 +293,8 @@ void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) {
|
|||
}
|
||||
|
||||
bool inactiveHintRemoved = false;
|
||||
for (TUniqueId id : x2b0_inactiveCameraHints) {
|
||||
if (TCastToConstPtr<CScriptCameraHint> hint = mgr.GetObjectById(id)) {
|
||||
for (const TUniqueId id : x2b0_inactiveCameraHints) {
|
||||
if (const TCastToConstPtr<CScriptCameraHint> hint = mgr.GetObjectById(id)) {
|
||||
if (hint->GetHelperCount() == 0 || hint->GetInactive()) {
|
||||
for (auto it = xac_cameraHints.begin(); it != xac_cameraHints.end(); ++it) {
|
||||
if (it->second == id) {
|
||||
|
@ -302,8 +313,8 @@ void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) {
|
|||
x2b0_inactiveCameraHints.clear();
|
||||
|
||||
bool activeHintAdded = false;
|
||||
for (TUniqueId id : x334_activeCameraHints) {
|
||||
if (TCastToConstPtr<CScriptCameraHint> hint = mgr.GetObjectById(id)) {
|
||||
for (const TUniqueId id : x334_activeCameraHints) {
|
||||
if (const TCastToConstPtr<CScriptCameraHint> hint = mgr.GetObjectById(id)) {
|
||||
bool activeHintPresent = false;
|
||||
for (auto it = xac_cameraHints.begin(); it != xac_cameraHints.end(); ++it) {
|
||||
if (it->second == id) {
|
||||
|
@ -329,16 +340,17 @@ void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) {
|
|||
return;
|
||||
}
|
||||
bool foundHint = false;
|
||||
CScriptCameraHint* bestHint = nullptr;
|
||||
const CScriptCameraHint* bestHint = nullptr;
|
||||
for (auto& h : xac_cameraHints) {
|
||||
if (TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(h.second)) {
|
||||
if (const TCastToConstPtr<CScriptCameraHint> hint = mgr.ObjectById(h.second)) {
|
||||
bestHint = hint.GetPtr();
|
||||
foundHint = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundHint)
|
||||
if (!foundHint) {
|
||||
RestoreHintlessCamera(mgr);
|
||||
}
|
||||
|
||||
bool changeHint = false;
|
||||
if (bestHint && foundHint) {
|
||||
|
@ -346,33 +358,37 @@ void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) {
|
|||
zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition();
|
||||
if ((bestHint->GetHint().GetOverrideFlags() & 0x100) != 0) {
|
||||
zeus::CVector3f camToBall = ballPos - ballCamXf.origin;
|
||||
if (camToBall.canBeNormalized())
|
||||
if (camToBall.canBeNormalized()) {
|
||||
camToBall.normalize();
|
||||
else
|
||||
} else {
|
||||
camToBall = ballCamXf.basis[1];
|
||||
}
|
||||
|
||||
for (auto it = xac_cameraHints.begin() + 1; it != xac_cameraHints.end(); ++it) {
|
||||
if (TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(it->second)) {
|
||||
if (const TCastToConstPtr<CScriptCameraHint> hint = mgr.ObjectById(it->second)) {
|
||||
if ((hint->GetHint().GetOverrideFlags() & 0x80) != 0 && hint->GetPriority() == bestHint->GetPriority() &&
|
||||
hint->GetAreaIdAlways() == bestHint->GetAreaIdAlways()) {
|
||||
zeus::CVector3f hintToBall = ballPos - bestHint->GetTranslation();
|
||||
if (hintToBall.canBeNormalized())
|
||||
if (hintToBall.canBeNormalized()) {
|
||||
hintToBall.normalize();
|
||||
else
|
||||
} else {
|
||||
hintToBall = bestHint->GetTransform().basis[1];
|
||||
}
|
||||
|
||||
float camHintDot = zeus::clamp(-1.f, camToBall.dot(hintToBall), 1.f);
|
||||
const float camHintDot = zeus::clamp(-1.f, camToBall.dot(hintToBall), 1.f);
|
||||
|
||||
zeus::CVector3f thisHintToBall = ballPos - hint->GetTranslation();
|
||||
if (thisHintToBall.canBeNormalized())
|
||||
if (thisHintToBall.canBeNormalized()) {
|
||||
thisHintToBall.normalize();
|
||||
else
|
||||
} else {
|
||||
thisHintToBall = hint->GetTransform().basis[1];
|
||||
}
|
||||
|
||||
float camThisHintDot = zeus::clamp(-1.f, camToBall.dot(thisHintToBall), 1.f);
|
||||
const float camThisHintDot = zeus::clamp(-1.f, camToBall.dot(thisHintToBall), 1.f);
|
||||
|
||||
if (camThisHintDot > camHintDot)
|
||||
if (camThisHintDot > camHintDot) {
|
||||
bestHint = hint.GetPtr();
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -381,44 +397,49 @@ void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(bestHint->GetFirstHelper())) {
|
||||
if (const TCastToConstPtr<CActor> act = mgr.GetObjectById(bestHint->GetFirstHelper())) {
|
||||
zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition();
|
||||
zeus::CVector3f f26 = act->GetTranslation() - ballPos;
|
||||
zeus::CVector3f ballToHelper = f26;
|
||||
if (ballToHelper.canBeNormalized())
|
||||
if (ballToHelper.canBeNormalized()) {
|
||||
ballToHelper.normalize();
|
||||
else
|
||||
} else {
|
||||
ballToHelper = bestHint->GetTransform().basis[1];
|
||||
}
|
||||
|
||||
for (auto it = xac_cameraHints.begin() + 1; it != xac_cameraHints.end(); ++it) {
|
||||
if (TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(it->second)) {
|
||||
if (const TCastToConstPtr<CScriptCameraHint> hint = mgr.ObjectById(it->second)) {
|
||||
if ((hint->GetHint().GetOverrideFlags() & 0x80) != 0 &&
|
||||
hint->GetPriority() == bestHint->GetPriority() &&
|
||||
hint->GetAreaIdAlways() == bestHint->GetAreaIdAlways()) {
|
||||
zeus::CVector3f hintToHelper = act->GetTranslation() - bestHint->GetTranslation();
|
||||
if (hintToHelper.canBeNormalized())
|
||||
if (hintToHelper.canBeNormalized()) {
|
||||
hintToHelper.normalize();
|
||||
else
|
||||
} else {
|
||||
hintToHelper = bestHint->GetTransform().basis[1];
|
||||
}
|
||||
|
||||
float ballHintDot = zeus::clamp(-1.f, ballToHelper.dot(hintToHelper), 1.f);
|
||||
const float ballHintDot = zeus::clamp(-1.f, ballToHelper.dot(hintToHelper), 1.f);
|
||||
|
||||
zeus::CVector3f thisBallToHelper = f26;
|
||||
if (thisBallToHelper.canBeNormalized())
|
||||
if (thisBallToHelper.canBeNormalized()) {
|
||||
thisBallToHelper.normalize();
|
||||
else
|
||||
} else {
|
||||
thisBallToHelper = hint->GetTransform().basis[1];
|
||||
}
|
||||
|
||||
zeus::CVector3f thisHintToHelper = act->GetTranslation() - hint->GetTranslation();
|
||||
if (thisHintToHelper.canBeNormalized())
|
||||
if (thisHintToHelper.canBeNormalized()) {
|
||||
thisHintToHelper.normalize();
|
||||
else
|
||||
} else {
|
||||
thisHintToHelper = hint->GetTransform().basis[1];
|
||||
}
|
||||
|
||||
float thisBallHintDot = zeus::clamp(-1.f, thisBallToHelper.dot(thisHintToHelper), 1.f);
|
||||
const float thisBallHintDot = zeus::clamp(-1.f, thisBallToHelper.dot(thisHintToHelper), 1.f);
|
||||
|
||||
if (thisBallHintDot > ballHintDot)
|
||||
if (thisBallHintDot > ballHintDot) {
|
||||
bestHint = hint.GetPtr();
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -429,24 +450,27 @@ void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) {
|
|||
}
|
||||
}
|
||||
|
||||
if (bestHint->GetUniqueId() != xa6_camHintId)
|
||||
if (bestHint->GetUniqueId() != xa6_camHintId) {
|
||||
changeHint = true;
|
||||
}
|
||||
} else if (xa6_camHintId != bestHint->GetUniqueId()) {
|
||||
if (bestHint->GetHint().GetBehaviourType() == CBallCamera::EBallCameraBehaviour::HintInitializePosition) {
|
||||
if ((bestHint->GetHint().GetOverrideFlags() & 0x20) != 0) {
|
||||
x80_ballCamera->TeleportCamera(zeus::lookAt(bestHint->GetTranslation(), x80_ballCamera->GetLookPos()), mgr);
|
||||
}
|
||||
DeleteCameraHint(bestHint->GetUniqueId(), mgr);
|
||||
if ((bestHint->GetHint().GetOverrideFlags() & 0x2000) != 0)
|
||||
if ((bestHint->GetHint().GetOverrideFlags() & 0x2000) != 0) {
|
||||
SkipBallCameraCinematic(mgr);
|
||||
}
|
||||
changeHint = false;
|
||||
} else {
|
||||
changeHint = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changeHint)
|
||||
if (changeHint) {
|
||||
ApplyCameraHint(*bestHint, mgr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -455,18 +479,20 @@ void CCameraManager::ThinkCameras(float dt, CStateManager& mgr) {
|
|||
CGameCameraList gcList = mgr.GetCameraObjectList();
|
||||
|
||||
for (CEntity* ent : gcList) {
|
||||
if (TCastToPtr<CGameCamera> gc = ent) {
|
||||
if (const TCastToPtr<CGameCamera> gc = ent) {
|
||||
gc->Think(dt, mgr);
|
||||
gc->UpdatePerspective(dt);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsInCinematicCamera())
|
||||
if (IsInCinematicCamera()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TUniqueId camId = GetLastCameraId();
|
||||
if (const CGameCamera* cam = TCastToConstPtr<CGameCamera>(mgr.GetObjectById(camId)))
|
||||
const TUniqueId camId = GetLastCameraId();
|
||||
if (const CGameCamera* cam = TCastToConstPtr<CGameCamera>(mgr.GetObjectById(camId))) {
|
||||
x3bc_curFov = cam->GetFov();
|
||||
}
|
||||
}
|
||||
|
||||
void CCameraManager::UpdateFog(float dt, CStateManager& mgr) {
|
||||
|
@ -480,14 +506,16 @@ void CCameraManager::UpdateFog(float dt, CStateManager& mgr) {
|
|||
}
|
||||
|
||||
if (x74_fluidCounter) {
|
||||
if (TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(x78_fluidId)) {
|
||||
zeus::CVector2f zRange(GetCurrentCamera(mgr)->GetNearClipDistance(), CalculateFogDensity(mgr, water.GetPtr()));
|
||||
if (const TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(x78_fluidId)) {
|
||||
const zeus::CVector2f zRange(GetCurrentCamera(mgr)->GetNearClipDistance(),
|
||||
CalculateFogDensity(mgr, water.GetPtr()));
|
||||
x3c_fog.SetFogExplicit(ERglFogMode::PerspExp, water->GetInsideFogColor(), zRange);
|
||||
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal)
|
||||
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) {
|
||||
mgr.GetCameraFilterPass(4).DisableFilter(0.f);
|
||||
else
|
||||
} else {
|
||||
mgr.GetCameraFilterPass(4).SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f,
|
||||
water->GetInsideFogColor(), {});
|
||||
}
|
||||
}
|
||||
xa0_26_inWater = true;
|
||||
} else if (xa0_26_inWater) {
|
||||
|
@ -524,8 +552,9 @@ void CCameraManager::UpdateRumble(float dt, CStateManager& mgr) {
|
|||
xa0_25_rumbling = false;
|
||||
}
|
||||
|
||||
if (mgr.GetPlayer().GetCameraState() != CPlayer::EPlayerCameraState::FirstPerson && !IsInCinematicCamera())
|
||||
if (mgr.GetPlayer().GetCameraState() != CPlayer::EPlayerCameraState::FirstPerson && !IsInCinematicCamera()) {
|
||||
x30_shakeOffset = zeus::skZero3f;
|
||||
}
|
||||
}
|
||||
|
||||
void CCameraManager::UpdateListener(CStateManager& mgr) {
|
||||
|
@ -534,13 +563,14 @@ void CCameraManager::UpdateListener(CStateManager& mgr) {
|
|||
}
|
||||
|
||||
float CCameraManager::CalculateFogDensity(CStateManager& mgr, const CScriptWater* water) const {
|
||||
float distanceFactor = 1.f - water->GetFluidPlane().GetAlpha();
|
||||
const float distanceFactor = 1.f - water->GetFluidPlane().GetAlpha();
|
||||
float distance = 0;
|
||||
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit))
|
||||
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) {
|
||||
distance =
|
||||
g_tweakGame->GetGravityWaterFogDistanceRange() * distanceFactor + g_tweakGame->GetGravityWaterFogDistanceBase();
|
||||
else
|
||||
} else {
|
||||
distance = g_tweakGame->GetWaterFogDistanceRange() * distanceFactor + g_tweakGame->GetWaterFogDistanceBase();
|
||||
}
|
||||
|
||||
return distance * x94_fogDensityFactor;
|
||||
}
|
||||
|
@ -550,7 +580,7 @@ void CCameraManager::ResetCameras(CStateManager& mgr) {
|
|||
xf.origin = mgr.GetPlayer().GetEyePosition();
|
||||
|
||||
for (CEntity* ent : mgr.GetCameraObjectList()) {
|
||||
TCastToPtr<CGameCamera> camObj(ent);
|
||||
const TCastToPtr<CGameCamera> camObj(ent);
|
||||
camObj->Reset(xf, mgr);
|
||||
}
|
||||
}
|
||||
|
@ -562,25 +592,29 @@ void CCameraManager::SetSpecialCameras(CFirstPersonCamera& fp, CBallCamera& ball
|
|||
|
||||
void CCameraManager::ProcessInput(const CFinalInput& input, CStateManager& stateMgr) {
|
||||
for (CEntity* ent : stateMgr.GetCameraObjectList()) {
|
||||
if (ent == nullptr)
|
||||
if (ent == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto& cam = static_cast<CGameCamera&>(*ent);
|
||||
if (input.ControllerIdx() != cam.x16c_controllerIdx)
|
||||
if (input.ControllerIdx() != cam.x16c_controllerIdx) {
|
||||
continue;
|
||||
}
|
||||
cam.ProcessInput(input, stateMgr);
|
||||
}
|
||||
}
|
||||
|
||||
void CCameraManager::RenderCameras(const CStateManager& mgr) {
|
||||
for (CEntity* cam : mgr.GetCameraObjectList())
|
||||
void CCameraManager::RenderCameras(CStateManager& mgr) {
|
||||
for (CEntity* cam : mgr.GetCameraObjectList()) {
|
||||
static_cast<CGameCamera*>(cam)->Render(mgr);
|
||||
}
|
||||
}
|
||||
|
||||
void CCameraManager::SetupBallCamera(CStateManager& mgr) {
|
||||
if (TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(xa6_camHintId)) {
|
||||
if (const TCastToConstPtr<CScriptCameraHint> hint = mgr.ObjectById(xa6_camHintId)) {
|
||||
if (hint->GetHint().GetBehaviourType() == CBallCamera::EBallCameraBehaviour::HintInitializePosition) {
|
||||
if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0)
|
||||
if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0) {
|
||||
x80_ballCamera->TeleportCamera(hint->GetTransform(), mgr);
|
||||
}
|
||||
AddInactiveCameraHint(xa6_camHintId, mgr);
|
||||
} else {
|
||||
ApplyCameraHint(*hint, mgr);
|
||||
|
@ -622,45 +656,60 @@ bool CCameraManager::HasBallCameraInitialPositionHint(CStateManager& mgr) const
|
|||
}
|
||||
|
||||
void CCameraManager::RemoveCinemaCamera(TUniqueId uid, CStateManager& mgr) {
|
||||
auto search = std::find(x4_cineCameras.begin(), x4_cineCameras.end(), uid);
|
||||
if (search != x4_cineCameras.end())
|
||||
x4_cineCameras.erase(search);
|
||||
const auto search = std::find(x4_cineCameras.cbegin(), x4_cineCameras.cend(), uid);
|
||||
|
||||
if (search == x4_cineCameras.cend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
x4_cineCameras.erase(search);
|
||||
}
|
||||
|
||||
void CCameraManager::DeleteCameraHint(TUniqueId id, CStateManager& mgr) {
|
||||
if (TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(id)) {
|
||||
auto search = std::find_if(x2b0_inactiveCameraHints.begin(), x2b0_inactiveCameraHints.end(),
|
||||
[id](TUniqueId tid) { return tid == id; });
|
||||
if (search == x2b0_inactiveCameraHints.end()) {
|
||||
hint->ClearIdList();
|
||||
hint->SetInactive(true);
|
||||
if (x2b0_inactiveCameraHints.size() != 64)
|
||||
x2b0_inactiveCameraHints.push_back(id);
|
||||
}
|
||||
const TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(id);
|
||||
|
||||
if (!hint) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto search = std::find_if(x2b0_inactiveCameraHints.cbegin(), x2b0_inactiveCameraHints.cend(),
|
||||
[id](TUniqueId tid) { return tid == id; });
|
||||
|
||||
if (search != x2b0_inactiveCameraHints.cend()) {
|
||||
return;
|
||||
}
|
||||
|
||||
hint->ClearIdList();
|
||||
hint->SetInactive(true);
|
||||
if (x2b0_inactiveCameraHints.size() != 64) {
|
||||
x2b0_inactiveCameraHints.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
void CCameraManager::AddInactiveCameraHint(TUniqueId id, CStateManager& mgr) {
|
||||
if (TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(id)) {
|
||||
auto search = std::find_if(x2b0_inactiveCameraHints.begin(), x2b0_inactiveCameraHints.end(),
|
||||
[id](TUniqueId tid) { return tid == id; });
|
||||
if (search == x2b0_inactiveCameraHints.end() && x2b0_inactiveCameraHints.size() != 64)
|
||||
if (const TCastToConstPtr<CScriptCameraHint> hint = mgr.ObjectById(id)) {
|
||||
const auto search = std::find_if(x2b0_inactiveCameraHints.cbegin(), x2b0_inactiveCameraHints.cend(),
|
||||
[id](TUniqueId tid) { return tid == id; });
|
||||
if (search == x2b0_inactiveCameraHints.cend() && x2b0_inactiveCameraHints.size() != 64) {
|
||||
x2b0_inactiveCameraHints.push_back(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CCameraManager::AddActiveCameraHint(TUniqueId id, CStateManager& mgr) {
|
||||
if (TCastToPtr<CScriptCameraHint> hint = mgr.ObjectById(id)) {
|
||||
auto search = std::find_if(x334_activeCameraHints.begin(), x334_activeCameraHints.end(),
|
||||
[id](TUniqueId tid) { return tid == id; });
|
||||
if (search == x334_activeCameraHints.end() && xac_cameraHints.size() != 64 && x334_activeCameraHints.size() != 64)
|
||||
if (const TCastToConstPtr<CScriptCameraHint> hint = mgr.ObjectById(id)) {
|
||||
const auto search = std::find_if(x334_activeCameraHints.cbegin(), x334_activeCameraHints.cend(),
|
||||
[id](TUniqueId tid) { return tid == id; });
|
||||
if (search == x334_activeCameraHints.cend() && xac_cameraHints.size() != 64 && x334_activeCameraHints.size() != 64) {
|
||||
x334_activeCameraHints.push_back(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TUniqueId CCameraManager::GetLastCineCameraId() const {
|
||||
if (x4_cineCameras.empty())
|
||||
if (x4_cineCameras.empty()) {
|
||||
return kInvalidUniqueId;
|
||||
}
|
||||
return x4_cineCameras.back();
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ class CCameraManager {
|
|||
void EnterCinematic(CStateManager& mgr);
|
||||
|
||||
public:
|
||||
CCameraManager(TUniqueId curCameraId = kInvalidUniqueId);
|
||||
explicit CCameraManager(TUniqueId curCameraId = kInvalidUniqueId);
|
||||
|
||||
static float Aspect() { return 1.42f; }
|
||||
static float FarPlane() { return 750.0f; }
|
||||
|
@ -96,9 +96,9 @@ public:
|
|||
zeus::CTransform GetCurrentCameraTransform(const CStateManager& stateMgr) const;
|
||||
void RemoveCameraShaker(u32 id);
|
||||
int AddCameraShaker(const CCameraShakeData& data, bool sfx);
|
||||
void AddCinemaCamera(TUniqueId, CStateManager& stateMgr);
|
||||
void RemoveCinemaCamera(TUniqueId, CStateManager&);
|
||||
void SetInsideFluid(bool, TUniqueId);
|
||||
void AddCinemaCamera(TUniqueId id, CStateManager& stateMgr);
|
||||
void RemoveCinemaCamera(TUniqueId uid, CStateManager& mgr);
|
||||
void SetInsideFluid(bool isInside, TUniqueId fluidId);
|
||||
void Update(float dt, CStateManager& stateMgr);
|
||||
CGameCamera* GetCurrentCamera(CStateManager& stateMgr) const;
|
||||
const CGameCamera* GetCurrentCamera(const CStateManager& stateMgr) const;
|
||||
|
@ -134,12 +134,12 @@ public:
|
|||
void UpdateRumble(float dt, CStateManager& mgr);
|
||||
void UpdateListener(CStateManager& mgr);
|
||||
|
||||
float CalculateFogDensity(CStateManager&, const CScriptWater*) const;
|
||||
void SetFogDensity(float, float);
|
||||
float CalculateFogDensity(CStateManager& mgr, const CScriptWater* water) const;
|
||||
void SetFogDensity(float fogDensityTarget, float fogDensitySpeed);
|
||||
|
||||
void ProcessInput(const CFinalInput& input, CStateManager& stateMgr);
|
||||
|
||||
void RenderCameras(const CStateManager& mgr);
|
||||
void RenderCameras(CStateManager& mgr);
|
||||
void SetupBallCamera(CStateManager& mgr);
|
||||
void SetPlayerCamera(CStateManager& mgr, TUniqueId newCamId);
|
||||
int GetFluidCounter() const { return x74_fluidCounter; }
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue