sm64 collision factory

This commit is contained in:
inspectredc
2024-04-02 08:12:06 -06:00
committed by Lywx
parent c567193d17
commit 513251ec9b
5 changed files with 1611 additions and 0 deletions
+2
View File
@@ -29,6 +29,7 @@
#include "factories/Vec3sFactory.h"
#include "factories/sm64/AnimationFactory.h"
#include "factories/sm64/CollisionFactory.h"
#include "factories/sm64/DialogFactory.h"
#include "factories/sm64/DictionaryFactory.h"
#include "factories/sm64/TextFactory.h"
@@ -86,6 +87,7 @@ void Companion::Init(const ExportType type) {
this->RegisterFactory("SM64:TEXT", std::make_shared<SM64::TextFactory>());
this->RegisterFactory("SM64:DICTIONARY", std::make_shared<SM64::DictionaryFactory>());
this->RegisterFactory("SM64:ANIM", std::make_shared<SM64::AnimationFactory>());
this->RegisterFactory("SM64:COLLISION", std::make_shared<SM64::CollisionFactory>());
this->RegisterFactory("SM64:GEO_LAYOUT", std::make_shared<SM64::GeoLayoutFactory>());
// MK64 specific
+470
View File
@@ -0,0 +1,470 @@
#include "CollisionFactory.h"
#include "Companion.h"
#include "spdlog/spdlog.h"
#define FORMAT_HEX(x) std::hex << x << std::dec
std::unordered_map<int16_t, SpecialPresetTypes> specialPresetMap = {
{ 0x00, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x01, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x02, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x03, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x04, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x05, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x06, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x07, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x08, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x09, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x0A, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x0B, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x0C, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x0D, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x0E, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x0F, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x10, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x11, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x12, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x13, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x14, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x15, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x16, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x17, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x18, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x19, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x1A, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x1B, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x1C, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x1D, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x1E, SpecialPresetTypes::SPTYPE_UNKNOWN },
{ 0x1F, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x20, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x21, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x22, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x23, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x24, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x25, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x26, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x27, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x28, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x65, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x66, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x67, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x68, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x69, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x6A, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x6B, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x6C, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x6D, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x6E, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x6F, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x70, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x71, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x72, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x73, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x74, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x75, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x76, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x77, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x78, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x79, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x7A, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x7B, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x7C, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x7D, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
{ 0x89, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x7E, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x7F, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x80, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x81, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x82, SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS },
{ 0x8A, SpecialPresetTypes::SPTYPE_DEF_PARAM_AND_YROT },
{ 0x8B, SpecialPresetTypes::SPTYPE_DEF_PARAM_AND_YROT },
{ 0x8C, SpecialPresetTypes::SPTYPE_DEF_PARAM_AND_YROT },
{ 0x8D, SpecialPresetTypes::SPTYPE_DEF_PARAM_AND_YROT },
{ 0x88, SpecialPresetTypes::SPTYPE_PARAMS_AND_YROT },
{ 0x83, SpecialPresetTypes::SPTYPE_PARAMS_AND_YROT },
{ 0x84, SpecialPresetTypes::SPTYPE_PARAMS_AND_YROT },
{ 0x85, SpecialPresetTypes::SPTYPE_PARAMS_AND_YROT },
{ 0x86, SpecialPresetTypes::SPTYPE_PARAMS_AND_YROT },
{ 0x87, SpecialPresetTypes::SPTYPE_PARAMS_AND_YROT },
{ 0xFF, SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS },
};
ExportResult SM64::CollisionCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto symbol = GetSafeNode(node, "symbol", entryName);
auto offset = GetSafeNode<uint32_t>(node, "offset");
const auto collision = std::static_pointer_cast<Collision>(data).get();
uint32_t count = 0;
write << "Collision " << symbol << "[] = {\n";
write << fourSpaceTab;
write << "COL_INIT(),\n";
++count;
// Vertices
if (collision->mVertices.size() > 0) {
write << fourSpaceTab;
write << "COL_VERTEX_INIT(" << FORMAT_HEX(collision->mVertices.size()) << "),\n";
++count;
}
for (auto &vertex : collision->mVertices) {
write << fourSpaceTab;
write << "COL_VERTEX(";
write << vertex.x << ", ";
write << vertex.y << ", ";
write << vertex.z << "),\n";
count += 3;
}
// Surfaces
for (auto &surface : collision->mSurfaces) {
// size check is probably not necessary here
if (surface.tris.size() > 0) {
write << fourSpaceTab;
write << "COL_TRI_INIT(";
write << surface.surfaceType << ", ";
write << surface.tris.size() << "),\n";
count += 2;
}
bool hasForce = false;
switch (surface.surfaceType) {
case SurfaceType::SURFACE_0004:
case SurfaceType::SURFACE_FLOWING_WATER:
case SurfaceType::SURFACE_DEEP_MOVING_QUICKSAND:
case SurfaceType::SURFACE_SHALLOW_MOVING_QUICKSAND:
case SurfaceType::SURFACE_MOVING_QUICKSAND:
case SurfaceType::SURFACE_HORIZONTAL_WIND:
case SurfaceType::SURFACE_INSTANT_MOVING_QUICKSAND:
hasForce = true;
break;
default:
break;
}
for (auto &tri : surface.tris) {
write << fourSpaceTab;
if (hasForce) {
write << "COL_TRI_SPECIAL(";
} else {
write << "COL_TRI(";
}
write << tri.x << ", ";
write << tri.y << ", ";
if (hasForce) {
write << tri.z << ", ";
write << tri.force << "),\n";
count += 4;
} else {
write << tri.z << "),\n";
count += 3;
}
}
}
if (collision->mSurfaces.size()) {
write << fourSpaceTab;
write << "COL_TRI_STOP()";
++count;
}
// Special Objects
if (collision->mSpecialObjects.size() > 0) {
write << fourSpaceTab;
write << "COL_SPECIAL_INIT(" << collision->mSpecialObjects.size() << "),\n";
count += 2;
}
for (auto &specialObject : collision->mSpecialObjects) {
write << fourSpaceTab;
if (specialPresetMap.find((int16_t)specialObject.presetId) == specialPresetMap.end()) {
throw std::runtime_error("Special Preset Id has no associated Type");
}
SpecialPresetTypes type = specialPresetMap.at((int16_t)specialObject.presetId);
switch (type) {
case SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS:
case SpecialPresetTypes::SPTYPE_DEF_PARAM_AND_YROT:
write << "SPECIAL_OBJECT_WITH_YAW(";
break;
case SpecialPresetTypes::SPTYPE_PARAMS_AND_YROT:
write << "SPECIAL_OBJECT_WITH_YAW_AND_PARAM(";
break;
case SpecialPresetTypes::SPTYPE_UNKNOWN:
break;
default:
write << "SPECIAL_OBJECT(";
break;
}
write << specialObject.presetId << ", ";
write << specialObject.x << ", ";
write << specialObject.y << ", ";
write << specialObject.z;
count += 4;
for (int16_t extraParam : specialObject.extraParams) {
write << ", ";
write << extraParam;
++count;
}
if (type != SpecialPresetTypes::SPTYPE_UNKNOWN) {
write << ")";
}
write << ",\n";
}
// Environment Region Boxes
if (collision->mEnvRegionBoxes.size() > 0) {
write << fourSpaceTab;
write << "COL_WATER_BOX_INIT(" << collision->mEnvRegionBoxes.size() << "),\n";
count += 2;
}
for (auto &envRegionBox : collision->mEnvRegionBoxes) {
write << fourSpaceTab;
write << envRegionBox.id << ", ";
write << envRegionBox.x1 << ", ";
write << envRegionBox.z1 << ", ";
write << envRegionBox.x2 << ", ";
write << envRegionBox.z2 << ", ";
write << envRegionBox.height << "),\n";
count += 6;
}
if (Companion::Instance->IsDebug()) {
write << "// size: 0x" << std::hex << std::uppercase << "" << "\n";
}
return offset + count * sizeof(int16_t);
}
ExportResult SM64::CollisionHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node &node, std::string* replacement ) {
const auto symbol = GetSafeNode(node, "symbol", entryName);
if(Companion::Instance->IsOTRMode()){
write << "static const char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
return std::nullopt;
}
write << "extern " << "Collision " << symbol << "[];\n";
return std::nullopt;
}
ExportResult SM64::CollisionBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node &node, std::string* replacement ) {
const auto collision = std::static_pointer_cast<Collision>(data).get();
auto writer = LUS::BinaryWriter();
writer.SetEndianness(LUS::Endianness::Big);
writer.Write((int16_t)COL_INIT());
// Vertices
if (collision->mVertices.size() > 0) {
writer.Write((int16_t)COL_VERTEX_INIT(collision->mVertices.size()));
}
for (auto &vertex : collision->mVertices) {
writer.Write(vertex.x);
writer.Write(vertex.y);
writer.Write(vertex.z);
}
// Surfaces
for (auto &surface : collision->mSurfaces) {
// size check is probably not necessary here
if (surface.tris.size() > 0) {
writer.Write((int16_t)surface.surfaceType);
writer.Write((int16_t)surface.tris.size());
}
bool hasForce = false;
switch (surface.surfaceType) {
case SurfaceType::SURFACE_0004:
case SurfaceType::SURFACE_FLOWING_WATER:
case SurfaceType::SURFACE_DEEP_MOVING_QUICKSAND:
case SurfaceType::SURFACE_SHALLOW_MOVING_QUICKSAND:
case SurfaceType::SURFACE_MOVING_QUICKSAND:
case SurfaceType::SURFACE_HORIZONTAL_WIND:
case SurfaceType::SURFACE_INSTANT_MOVING_QUICKSAND:
hasForce = true;
break;
default:
break;
}
for (auto &tri : surface.tris) {
writer.Write(tri.x);
writer.Write(tri.y);
writer.Write(tri.z);
if (hasForce) {
writer.Write(tri.force);
}
}
}
if (collision->mSurfaces.size()) {
writer.Write((int16_t)COL_TRI_STOP());
}
// Special Objects
if (collision->mSpecialObjects.size() > 0) {
writer.Write((int16_t)TERRAIN_LOAD_OBJECTS);
writer.Write((int16_t)collision->mSpecialObjects.size());
}
for (auto &specialObject : collision->mSpecialObjects) {
writer.Write((int16_t)specialObject.presetId);
writer.Write(specialObject.x);
writer.Write(specialObject.y);
writer.Write(specialObject.z);
for (int16_t extraParam : specialObject.extraParams) {
writer.Write(extraParam);
}
}
// Environment Region Boxes
if (collision->mEnvRegionBoxes.size() > 0) {
writer.Write((int16_t)TERRAIN_LOAD_ENVIRONMENT);
writer.Write((int16_t)collision->mEnvRegionBoxes.size());
}
for (auto &envRegionBox : collision->mEnvRegionBoxes) {
writer.Write(envRegionBox.id);
writer.Write(envRegionBox.x1);
writer.Write(envRegionBox.z1);
writer.Write(envRegionBox.x2);
writer.Write(envRegionBox.z2);
writer.Write(envRegionBox.height);
}
std::vector<char> buffer = writer.ToVector();
writer.Close();
LUS::BinaryWriter output = LUS::BinaryWriter();
WriteHeader(output, LUS::ResourceType::Blob, 0);
output.Write(static_cast<uint32_t>(buffer.size()));
output.Write(buffer.data(), buffer.size());
output.Finish(write);
output.Close();
return std::nullopt;
}
std::optional<std::shared_ptr<IParsedData>> SM64::CollisionFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
std::vector<CollisionVertex> vertices;
std::vector<CollisionSurface> surfaces;
std::vector<SpecialObject> specialObjects;
std::vector<EnvRegionBox> envRegionBoxes;
bool processing = true;
auto [_, segment] = Decompressor::AutoDecode(node, buffer);
auto cmd = segment.data;
LUS::BinaryReader reader(segment.data, segment.size);
reader.SetEndianness(LUS::Endianness::Big);
while (processing) {
int16_t terrainLoadType = reader.ReadInt16();
if (TERRAIN_LOAD_IS_SURFACE_TYPE_LOW(terrainLoadType)) {
SurfaceType surfaceType = static_cast<SurfaceType>(terrainLoadType);
bool hasForce = false;
switch (surfaceType) {
case SurfaceType::SURFACE_0004:
case SurfaceType::SURFACE_FLOWING_WATER:
case SurfaceType::SURFACE_DEEP_MOVING_QUICKSAND:
case SurfaceType::SURFACE_SHALLOW_MOVING_QUICKSAND:
case SurfaceType::SURFACE_MOVING_QUICKSAND:
case SurfaceType::SURFACE_HORIZONTAL_WIND:
case SurfaceType::SURFACE_INSTANT_MOVING_QUICKSAND:
hasForce = true;
break;
default:
break;
}
int16_t numSurfaces = reader.ReadInt16();
std::vector<CollisionTri> tris;
for (int16_t i = 0; i < numSurfaces; ++i) {
int16_t x = reader.ReadInt16();
int16_t y = reader.ReadInt16();
int16_t z = reader.ReadInt16();
int16_t force = hasForce ? reader.ReadInt16() : -1;
tris.emplace_back(x, y, z, force);
}
surfaces.emplace_back(surfaceType, tris);
} else if (terrainLoadType == TERRAIN_LOAD_VERTICES) {
int16_t numVertices = reader.ReadInt16();
for (int16_t i = 0; i < numVertices; ++i) {
int16_t x = reader.ReadInt16();
int16_t y = reader.ReadInt16();
int16_t z = reader.ReadInt16();
vertices.emplace_back(x, y, z);
}
} else if (terrainLoadType == TERRAIN_LOAD_OBJECTS) {
int16_t numSpecialObjects = reader.ReadInt16();
for (int16_t i = 0; i < numSpecialObjects; ++i) {
int16_t presetId = reader.ReadInt16();
int16_t x = reader.ReadInt16();
int16_t y = reader.ReadInt16();
int16_t z = reader.ReadInt16();
if (specialPresetMap.find(presetId) == specialPresetMap.end()) {
throw std::runtime_error("Special Preset Id has no associated Type");
}
SpecialPresets specialPresetId = static_cast<SpecialPresets>(presetId);
SpecialPresetTypes type = specialPresetMap.at(presetId);
std::vector<int16_t> extraParams;
switch (type) {
case SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS:
extraParams.emplace_back(reader.ReadInt16());
case SpecialPresetTypes::SPTYPE_PARAMS_AND_YROT:
extraParams.emplace_back(reader.ReadInt16());
extraParams.emplace_back(reader.ReadInt16());
case SpecialPresetTypes::SPTYPE_UNKNOWN:
extraParams.emplace_back(reader.ReadInt16());
extraParams.emplace_back(reader.ReadInt16());
extraParams.emplace_back(reader.ReadInt16());
break;
case SpecialPresetTypes::SPTYPE_DEF_PARAM_AND_YROT:
extraParams.emplace_back(reader.ReadInt16());
break;
default:
break;
}
specialObjects.emplace_back(specialPresetId, x, y, z, extraParams);
}
} else if (terrainLoadType == TERRAIN_LOAD_ENVIRONMENT) {
int16_t numRegions = reader.ReadInt16();
for (int16_t i = 0; i < numRegions; ++i) {
int16_t id = reader.ReadInt16();
int16_t x1 = reader.ReadInt16();
int16_t z1 = reader.ReadInt16();
int16_t x2 = reader.ReadInt16();
int16_t z2 = reader.ReadInt16();
int16_t height = reader.ReadInt16();
envRegionBoxes.emplace_back(id, x1, z1, x2, z2, height);
}
} else if (terrainLoadType == TERRAIN_LOAD_CONTINUE) {
// need to figure out a way to handle when this should appear in exporters. seems to always be after vertices
} else if (terrainLoadType == TERRAIN_LOAD_END) {
processing = false;
} else if (TERRAIN_LOAD_IS_SURFACE_TYPE_HIGH(terrainLoadType)) {
SurfaceType surfaceType = static_cast<SurfaceType>(terrainLoadType);
bool hasForce = false;
switch (surfaceType) {
case SurfaceType::SURFACE_0004:
case SurfaceType::SURFACE_FLOWING_WATER:
case SurfaceType::SURFACE_DEEP_MOVING_QUICKSAND:
case SurfaceType::SURFACE_SHALLOW_MOVING_QUICKSAND:
case SurfaceType::SURFACE_MOVING_QUICKSAND:
case SurfaceType::SURFACE_HORIZONTAL_WIND:
case SurfaceType::SURFACE_INSTANT_MOVING_QUICKSAND:
hasForce = true;
break;
default:
break;
}
int16_t numSurfaces = reader.ReadInt16();
std::vector<CollisionTri> tris;
for (int16_t i = 0; i < numSurfaces; ++i) {
int16_t x = reader.ReadInt16();
int16_t y = reader.ReadInt16();
int16_t z = reader.ReadInt16();
int16_t force = hasForce ? reader.ReadInt16() : -1;
tris.emplace_back(x, y, z, force);
}
surfaces.emplace_back(surfaceType, tris);
}
}
return std::make_shared<Collision>(vertices, surfaces, specialObjects, envRegionBoxes);
}
+82
View File
@@ -0,0 +1,82 @@
#pragma once
#include "../BaseFactory.h"
#include "collision/SpecialPresetNames.h"
#include "collision/SurfaceTerrains.h"
namespace SM64 {
struct CollisionVertex {
int16_t x;
int16_t y;
int16_t z;
CollisionVertex(int16_t x, int16_t y, int16_t z) : x(x), y(y), z(z) {};
};
struct CollisionTri {
int16_t x;
int16_t y;
int16_t z;
int16_t force;
CollisionTri(int16_t x, int16_t y, int16_t z, int16_t force) : x(x), y(y), z(z), force(force) {};
};
struct CollisionSurface {
SurfaceType surfaceType;
std::vector<CollisionTri> tris;
CollisionSurface(SurfaceType surfaceType, std::vector<CollisionTri> tris) : surfaceType(surfaceType), tris(std::move(tris)) {};
};
struct SpecialObject {
SpecialPresets presetId;
int16_t x;
int16_t y;
int16_t z;
std::vector<int16_t> extraParams; // e.g. y-rot
SpecialObject(SpecialPresets presetId, int16_t x, int16_t y, int16_t z, std::vector<int16_t> extraParams) : presetId(presetId), x(x), y(y), z(z), extraParams(std::move(extraParams)) {};
};
struct EnvRegionBox {
int16_t id;
int16_t x1;
int16_t z1;
int16_t x2;
int16_t z2;
int16_t height;
EnvRegionBox(int16_t id, int16_t x1, int16_t z1, int16_t x2, int16_t z2, int16_t height) : id(id), x1(x1), z1(z1), x2(x2), z2(z2), height(height) {};
}; // e.g. water-box
class Collision : public IParsedData {
public:
std::vector<CollisionVertex> mVertices;
std::vector<CollisionSurface> mSurfaces;
std::vector<SpecialObject> mSpecialObjects;
std::vector<EnvRegionBox> mEnvRegionBoxes;
explicit Collision(std::vector<CollisionVertex> vertices, std::vector<CollisionSurface> surfaces, std::vector<SpecialObject> specialObjects, std::vector<EnvRegionBox> envRegionBoxes) : mVertices(std::move(vertices)), mSurfaces(std::move(surfaces)), mSpecialObjects(std::move(specialObjects)), mEnvRegionBoxes(std::move(envRegionBoxes)) {}
};
class CollisionCodeExporter : public BaseExporter {
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
};
class CollisionHeaderExporter : public BaseExporter {
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
};
class CollisionBinaryExporter : public BaseExporter {
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
};
class CollisionFactory : public BaseFactory {
public:
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
return {
REGISTER(Header, CollisionHeaderExporter)
REGISTER(Binary, CollisionBinaryExporter)
REGISTER(Code, CollisionCodeExporter)
};
}
};
}
@@ -0,0 +1,385 @@
#pragma once
#include <string>
#include <spdlog/spdlog.h>
#include <spdlog/fmt/ostr.h>
enum class SpecialPresetTypes {
SPTYPE_NO_YROT_OR_PARAMS,
SPTYPE_YROT_NO_PARAMS,
SPTYPE_PARAMS_AND_YROT,
SPTYPE_UNKNOWN,
SPTYPE_DEF_PARAM_AND_YROT,
};
inline std::ostream& operator<<(std::ostream& out, const SpecialPresetTypes& type) {
std::string output;
switch (type) {
case SpecialPresetTypes::SPTYPE_NO_YROT_OR_PARAMS:
output = "SPTYPE_NO_YROT_OR_PARAMS";
break;
case SpecialPresetTypes::SPTYPE_YROT_NO_PARAMS:
output = "SPTYPE_YROT_NO_PARAMS";
break;
case SpecialPresetTypes::SPTYPE_PARAMS_AND_YROT:
output = "SPTYPE_PARAMS_AND_YROT";
break;
case SpecialPresetTypes::SPTYPE_UNKNOWN:
output = "SPTYPE_UNKNOWN";
break;
case SpecialPresetTypes::SPTYPE_DEF_PARAM_AND_YROT:
output = "SPTYPE_DEF_PARAM_AND_YROT";
break;
default:
throw std::runtime_error("Unknown Special Preset Type");
}
return out << output;
}
enum class SpecialPresets {
special_null_start,
special_yellow_coin,
special_yellow_coin_2,
special_unknown_3,
special_boo,
special_unknown_5,
special_lll_moving_octagonal_mesh_platform,
special_snow_ball,
special_lll_drawbridge_spawner,
special_empty_9,
special_lll_rotating_block_with_fire_bars,
special_lll_floating_wood_bridge,
special_tumbling_platform,
special_lll_rotating_hexagonal_ring,
special_lll_sinking_rectangular_platform,
special_lll_sinking_square_platforms,
special_lll_tilting_square_platform,
special_lll_bowser_puzzle,
special_mr_i,
special_small_bully,
special_big_bully,
special_empty_21,
special_empty_22,
special_empty_23,
special_empty_24,
special_empty_25,
special_moving_blue_coin,
special_jrb_chest,
special_water_ring,
special_mine,
special_empty_30,
special_empty_31,
special_butterfly,
special_bowser,
special_wf_rotating_wooden_platform,
special_small_bomp,
special_wf_sliding_platform,
special_tower_platform_group,
special_rotating_counter_clockwise,
special_wf_tumbling_bridge,
special_large_bomp,
special_level_geo_03 = 0x65,
special_level_geo_04,
special_level_geo_05,
special_level_geo_06,
special_level_geo_07,
special_level_geo_08,
special_level_geo_09,
special_level_geo_0A,
special_level_geo_0B,
special_level_geo_0C,
special_level_geo_0D,
special_level_geo_0E,
special_level_geo_0F,
special_level_geo_10,
special_level_geo_11,
special_level_geo_12,
special_level_geo_13,
special_level_geo_14,
special_level_geo_15,
special_level_geo_16,
special_bubble_tree,
special_spiky_tree,
special_snow_tree,
special_unknown_tree,
special_palm_tree,
special_wooden_door,
special_haunted_door = special_wooden_door,
special_unknown_door,
special_metal_door,
special_hmc_door,
special_unknown2_door,
special_wooden_door_warp,
special_unknown1_door_warp,
special_metal_door_warp,
special_unknown2_door_warp,
special_unknown3_door_warp,
special_castle_door_warp,
special_castle_door,
special_0stars_door,
special_1star_door,
special_3star_door,
special_key_door,
special_null_end = 0xFF
};
inline std::ostream& operator<<(std::ostream& out, const SpecialPresets& preset) {
std::string output;
switch (preset) {
case SpecialPresets::special_null_start:
output = "special_null_start";
break;
case SpecialPresets::special_yellow_coin:
output = "special_yellow_coin";
break;
case SpecialPresets::special_yellow_coin_2:
output = "special_yellow_coin_2";
break;
case SpecialPresets::special_unknown_3:
output = "special_unknown_3";
break;
case SpecialPresets::special_boo:
output = "special_boo";
break;
case SpecialPresets::special_unknown_5:
output = "special_unknown_5";
break;
case SpecialPresets::special_lll_moving_octagonal_mesh_platform:
output = "special_lll_moving_octagonal_mesh_platform";
break;
case SpecialPresets::special_snow_ball:
output = "special_snow_ball";
break;
case SpecialPresets::special_lll_drawbridge_spawner:
output = "special_lll_drawbridge_spawner";
break;
case SpecialPresets::special_empty_9:
output = "special_empty_9";
break;
case SpecialPresets::special_lll_rotating_block_with_fire_bars:
output = "special_lll_rotating_block_with_fire_bars";
break;
case SpecialPresets::special_lll_floating_wood_bridge:
output = "special_lll_floating_wood_bridge";
break;
case SpecialPresets::special_tumbling_platform:
output = "special_tumbling_platform";
break;
case SpecialPresets::special_lll_rotating_hexagonal_ring:
output = "special_lll_rotating_hexagonal_ring";
break;
case SpecialPresets::special_lll_sinking_rectangular_platform:
output = "special_lll_sinking_rectangular_platform";
break;
case SpecialPresets::special_lll_sinking_square_platforms:
output = "special_lll_sinking_square_platforms";
break;
case SpecialPresets::special_lll_tilting_square_platform:
output = "special_lll_tilting_square_platform";
break;
case SpecialPresets::special_lll_bowser_puzzle:
output = "special_lll_bowser_puzzle";
break;
case SpecialPresets::special_mr_i:
output = "special_mr_i";
break;
case SpecialPresets::special_small_bully:
output = "special_small_bully";
break;
case SpecialPresets::special_big_bully:
output = "special_big_bully";
break;
case SpecialPresets::special_empty_21:
output = "special_empty_21";
break;
case SpecialPresets::special_empty_22:
output = "special_empty_22";
break;
case SpecialPresets::special_empty_23:
output = "special_empty_23";
break;
case SpecialPresets::special_empty_24:
output = "special_empty_24";
break;
case SpecialPresets::special_empty_25:
output = "special_empty_25";
break;
case SpecialPresets::special_moving_blue_coin:
output = "special_moving_blue_coin";
break;
case SpecialPresets::special_jrb_chest:
output = "special_jrb_chest";
break;
case SpecialPresets::special_water_ring:
output = "special_water_ring";
break;
case SpecialPresets::special_mine:
output = "special_mine";
break;
case SpecialPresets::special_empty_30:
output = "special_empty_30";
break;
case SpecialPresets::special_empty_31:
output = "special_empty_31";
break;
case SpecialPresets::special_butterfly:
output = "special_butterfly";
break;
case SpecialPresets::special_bowser:
output = "special_bowser";
break;
case SpecialPresets::special_wf_rotating_wooden_platform:
output = "special_wf_rotating_wooden_platform";
break;
case SpecialPresets::special_small_bomp:
output = "special_small_bomp";
break;
case SpecialPresets::special_wf_sliding_platform:
output = "special_wf_sliding_platform";
break;
case SpecialPresets::special_tower_platform_group:
output = "special_tower_platform_group";
break;
case SpecialPresets::special_rotating_counter_clockwise:
output = "special_rotating_counter_clockwise";
break;
case SpecialPresets::special_wf_tumbling_bridge:
output = "special_wf_tumbling_bridge";
break;
case SpecialPresets::special_large_bomp:
output = "special_large_bomp";
break;
case SpecialPresets::special_level_geo_03:
output = "special_level_geo_03";
break;
case SpecialPresets::special_level_geo_04:
output = "special_level_geo_04";
break;
case SpecialPresets::special_level_geo_05:
output = "special_level_geo_05";
break;
case SpecialPresets::special_level_geo_06:
output = "special_level_geo_06";
break;
case SpecialPresets::special_level_geo_07:
output = "special_level_geo_07";
break;
case SpecialPresets::special_level_geo_08:
output = "special_level_geo_08";
break;
case SpecialPresets::special_level_geo_09:
output = "special_level_geo_09";
break;
case SpecialPresets::special_level_geo_0A:
output = "special_level_geo_0A";
break;
case SpecialPresets::special_level_geo_0B:
output = "special_level_geo_0B";
break;
case SpecialPresets::special_level_geo_0C:
output = "special_level_geo_0C";
break;
case SpecialPresets::special_level_geo_0D:
output = "special_level_geo_0D";
break;
case SpecialPresets::special_level_geo_0E:
output = "special_level_geo_0E";
break;
case SpecialPresets::special_level_geo_0F:
output = "special_level_geo_0F";
break;
case SpecialPresets::special_level_geo_10:
output = "special_level_geo_10";
break;
case SpecialPresets::special_level_geo_11:
output = "special_level_geo_11";
break;
case SpecialPresets::special_level_geo_12:
output = "special_level_geo_12";
break;
case SpecialPresets::special_level_geo_13:
output = "special_level_geo_13";
break;
case SpecialPresets::special_level_geo_14:
output = "special_level_geo_14";
break;
case SpecialPresets::special_level_geo_15:
output = "special_level_geo_15";
break;
case SpecialPresets::special_level_geo_16:
output = "special_level_geo_16";
break;
case SpecialPresets::special_bubble_tree:
output = "special_bubble_tree";
break;
case SpecialPresets::special_spiky_tree:
output = "special_spiky_tree";
break;
case SpecialPresets::special_snow_tree:
output = "special_snow_tree";
break;
case SpecialPresets::special_unknown_tree:
output = "special_unknown_tree";
break;
case SpecialPresets::special_palm_tree:
output = "special_palm_tree";
break;
case SpecialPresets::special_wooden_door:
output = "special_wooden_door";
break;
case SpecialPresets::special_unknown_door:
output = "special_unknown_door";
break;
case SpecialPresets::special_metal_door:
output = "special_metal_door";
break;
case SpecialPresets::special_hmc_door:
output = "special_hmc_door";
break;
case SpecialPresets::special_unknown2_door:
output = "special_unknown2_door";
break;
case SpecialPresets::special_wooden_door_warp:
output = "special_wooden_door_warp";
break;
case SpecialPresets::special_unknown1_door_warp:
output = "special_unknown1_door_warp";
break;
case SpecialPresets::special_metal_door_warp:
output = "special_metal_door_warp";
break;
case SpecialPresets::special_unknown2_door_warp:
output = "special_unknown2_door_warp";
break;
case SpecialPresets::special_unknown3_door_warp:
output = "special_unknown3_door_warp";
break;
case SpecialPresets::special_castle_door_warp:
output = "special_castle_door_warp";
break;
case SpecialPresets::special_castle_door:
output = "special_castle_door";
break;
case SpecialPresets::special_0stars_door:
output = "special_0stars_door";
break;
case SpecialPresets::special_1star_door:
output = "special_1star_door";
break;
case SpecialPresets::special_3star_door:
output = "special_3star_door";
break;
case SpecialPresets::special_key_door:
output = "special_key_door";
break;
case SpecialPresets::special_null_end:
output = "special_null_end";
break;
default:
throw std::runtime_error("Unknown Special Preset");
}
return out << output;
}
File diff suppressed because it is too large Load Diff