WaterDroplet Factory

This commit is contained in:
inspectredc
2024-04-25 16:25:13 -06:00
committed by Lywx
parent 32c49216fd
commit 4b72a6c401
4 changed files with 233 additions and 0 deletions
+2
View File
@@ -42,6 +42,7 @@
#include "factories/sm64/MovtexQuadFactory.h"
#include "factories/sm64/PaintingMapFactory.h"
#include "factories/sm64/TrajectoryFactory.h"
#include "factories/sm64/WaterDropletFactory.h"
#include "factories/mk64/CourseVtx.h"
#include "factories/mk64/Waypoints.h"
@@ -107,6 +108,7 @@ void Companion::Init(const ExportType type) {
this->RegisterFactory("SM64:MOVTEX", std::make_shared<SM64::MovtexFactory>());
this->RegisterFactory("SM64:PAINTING_MAP", std::make_shared<SM64::PaintingMapFactory>());
this->RegisterFactory("SM64:TRAJECTORY", std::make_shared<SM64::TrajectoryFactory>());
this->RegisterFactory("SM64:WATER_DROPLET", std::make_shared<SM64::WaterDropletFactory>());
// MK64 specific
this->RegisterFactory("MK64:COURSE_VTX", std::make_shared<MK64::CourseVtxFactory>());
+1
View File
@@ -37,6 +37,7 @@ enum class ResourceType {
MovtexQuad = 0x4D4F5651, // MOVQ
PaintingData = 0x5041494E, // PAIN
Trajectory = 0x5452414A, // TRAJ
WaterDroplet = 0x57545244, // WTRD
// MK64
CourseVertex = 0x43565458, // CVTX
+171
View File
@@ -0,0 +1,171 @@
#include "WaterDropletFactory.h"
#include "spdlog/spdlog.h"
#include "Companion.h"
#include "utils/Decompressor.h"
#include "utils/TorchUtils.h"
#include <regex>
#define FORMAT_FLOAT(x) std::fixed << std::setprecision(1) << x << "f"
ExportResult SM64::WaterDropletHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, 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 struct WaterDropletParams " << symbol << "[];\n";
return std::nullopt;
}
ExportResult SM64::WaterDropletCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
const auto symbol = GetSafeNode(node, "symbol", entryName);
const auto offset = GetSafeNode<uint32_t>(node, "offset");
auto waterDropletData = std::static_pointer_cast<SM64::WaterDropletData>(raw);
write << "struct WaterDropletParams " << symbol << " = {\n";
std::stringstream flagData;
auto flags = waterDropletData->flags;
bool prevFlag = false;
if (waterDropletData->flags & WATER_DROPLET_FLAG_RAND_ANGLE) {
flags -= WATER_DROPLET_FLAG_RAND_ANGLE;
flagData << "WATER_DROPLET_FLAG_RAND_ANGLE";
prevFlag = true;
}
if (waterDropletData->flags & WATER_DROPLET_FLAG_RAND_OFFSET_XZ) {
flags -= WATER_DROPLET_FLAG_RAND_OFFSET_XZ;
if (prevFlag) {
flagData << " | ";
}
flagData << "WATER_DROPLET_FLAG_RAND_OFFSET_XZ";
prevFlag = true;
}
if (waterDropletData->flags & WATER_DROPLET_FLAG_RAND_OFFSET_XYZ) {
flags -= WATER_DROPLET_FLAG_RAND_OFFSET_XYZ;
if (prevFlag) {
flagData << " | ";
}
flagData << "WATER_DROPLET_FLAG_RAND_OFFSET_XYZ";
prevFlag = true;
}
if (waterDropletData->flags & WATER_DROPLET_FLAG_SET_Y_TO_WATER_LEVEL) {
flags -= WATER_DROPLET_FLAG_SET_Y_TO_WATER_LEVEL;
if (prevFlag) {
flagData << " | ";
}
flagData << "WATER_DROPLET_FLAG_SET_Y_TO_WATER_LEVEL";
prevFlag = true;
}
if (waterDropletData->flags & WATER_DROPLET_FLAG_RAND_ANGLE_INCR_PLUS_8000) {
flags -= WATER_DROPLET_FLAG_RAND_ANGLE_INCR_PLUS_8000;
if (prevFlag) {
flagData << " | ";
}
flagData << "WATER_DROPLET_FLAG_RAND_ANGLE_INCR_PLUS_8000";
prevFlag = true;
}
if (waterDropletData->flags & WATER_DROPLET_FLAG_RAND_ANGLE_INCR) {
flags -= WATER_DROPLET_FLAG_RAND_ANGLE_INCR;
if (prevFlag) {
flagData << " | ";
}
flagData << "WATER_DROPLET_FLAG_RAND_ANGLE_INCR";
}
if (flags != 0) {
throw std::runtime_error("WaterDropletCodeExporter: Invalid flags field");
}
std::stringstream model;
if (waterDropletData->model == MODEL_FISH) {
model << "MODEL_FISH";
} else if (waterDropletData->model == MODEL_WHITE_PARTICLE_SMALL) {
model << "MODEL_WHITE_PARTICLE_SMALL";
} else {
model << waterDropletData->model;
}
std::stringstream bhvSymbol;
auto dec = Companion::Instance->GetNodeByAddr(waterDropletData->behavior);
if (dec.has_value()) {
auto bhvNode = std::get<1>(dec.value());
bhvSymbol << GetSafeNode<std::string>(bhvNode, "symbol");
} else {
SPDLOG_WARN("Cannot find node for ptr 0x{:X}", waterDropletData->behavior);
bhvSymbol << std::hex << "0x" << waterDropletData->behavior << std::dec;
}
write << fourSpaceTab << "/* Flags */ " << flagData.str() << ",\n";
write << fourSpaceTab << "/* Model */ " << model.str() << ",\n";
write << fourSpaceTab << "/* Behavior */ " << bhvSymbol.str() << ",\n";
write << fourSpaceTab << "/* Move angle range */ " << std::hex << "0x" << waterDropletData->moveAngleRange << std::dec << ",\n";
write << fourSpaceTab << "/* Unused (flag-specific) */ " << waterDropletData->moveRange << ",\n";
write << fourSpaceTab << "/* Random fvel offset, scale */ " << FORMAT_FLOAT(waterDropletData->randForwardVelOffset) << ", " << FORMAT_FLOAT(waterDropletData->randForwardVelScale) << ",\n";
write << fourSpaceTab << "/* Random yvel offset, scale */ " << FORMAT_FLOAT(waterDropletData->randYVelOffset) << ", " << FORMAT_FLOAT(waterDropletData->randYVelScale) << ",\n";
write << fourSpaceTab << "/* Random size offset, scale */ " << FORMAT_FLOAT(waterDropletData->randSizeOffset) << ", " << FORMAT_FLOAT(waterDropletData->randSizeScale) << ",\n";
write << "};\n";
size_t size = 0;
return offset + size;
}
ExportResult SM64::WaterDropletBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
auto writer = LUS::BinaryWriter();
auto waterDropletData = std::static_pointer_cast<SM64::WaterDropletData>(raw);
WriteHeader(writer, LUS::ResourceType::WaterDroplet, 0);
writer.Write(waterDropletData->flags);
writer.Write(waterDropletData->model);
auto ptr = waterDropletData->behavior;
auto dec = Companion::Instance->GetNodeByAddr(ptr);
if (dec.has_value()) {
uint64_t hash = CRC64(std::get<0>(dec.value()).c_str());
SPDLOG_INFO("Found Behavior Script: 0x{:X} Hash: 0x{:X} Path: {}", ptr, hash, std::get<0>(dec.value()));
writer.Write(hash);
} else {
SPDLOG_WARN("Could not find Behavior Script at 0x{:X}", ptr);
}
writer.Write(waterDropletData->moveAngleRange);
writer.Write(waterDropletData->moveRange);
writer.Write(waterDropletData->randForwardVelOffset);
writer.Write(waterDropletData->randForwardVelScale);
writer.Write(waterDropletData->randYVelOffset);
writer.Write(waterDropletData->randYVelScale);
writer.Write(waterDropletData->randSizeOffset);
writer.Write(waterDropletData->randSizeScale);
writer.Finish(write);
return std::nullopt;
}
std::optional<std::shared_ptr<IParsedData>> SM64::WaterDropletFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
auto [_, segment] = Decompressor::AutoDecode(node, buffer);
LUS::BinaryReader reader(segment.data, segment.size);
reader.SetEndianness(LUS::Endianness::Big);
auto flags = reader.ReadInt16();
auto model = reader.ReadInt16();
auto behavior = reader.ReadUInt32();
auto moveAngleRange = reader.ReadInt16();
auto moveRange = reader.ReadInt16();
auto randForwardVelOffset = reader.ReadFloat();
auto randForwardVelScale = reader.ReadFloat();
auto randYVelOffset = reader.ReadFloat();
auto randYVelScale = reader.ReadFloat();
auto randSizeOffset = reader.ReadFloat();
auto randSizeScale = reader.ReadFloat();
// For autogen if desired
// YAML::Node bhvNode;
// bhvNode["type"] = "SM64:BEHAVIOR_SCRIPT";
// bhvNode["offset"] = behavior;
// Companion::Instance->AddAsset(bhvNode);
return std::make_shared<SM64::WaterDropletData>(flags, model, behavior, moveAngleRange, moveRange, randForwardVelOffset, randForwardVelScale, randYVelOffset, randYVelScale, randSizeOffset, randSizeScale);
}
+59
View File
@@ -0,0 +1,59 @@
#pragma once
#include "factories/BaseFactory.h"
#define WATER_DROPLET_FLAG_RAND_ANGLE 0x02
#define WATER_DROPLET_FLAG_RAND_OFFSET_XZ 0x04 // Unused
#define WATER_DROPLET_FLAG_RAND_OFFSET_XYZ 0x08 // Unused
#define WATER_DROPLET_FLAG_SET_Y_TO_WATER_LEVEL 0x20
#define WATER_DROPLET_FLAG_RAND_ANGLE_INCR_PLUS_8000 0x40
#define WATER_DROPLET_FLAG_RAND_ANGLE_INCR 0x80 // Unused
#define MODEL_WHITE_PARTICLE_SMALL 0xA4
#define MODEL_FISH 0xB9
namespace SM64 {
class WaterDropletData : public IParsedData {
public:
int16_t flags;
int16_t model;
uint32_t behavior;
int16_t moveAngleRange;
int16_t moveRange;
float randForwardVelOffset;
float randForwardVelScale;
float randYVelOffset;
float randYVelScale;
float randSizeOffset;
float randSizeScale;
WaterDropletData(
int16_t flags, int16_t model, uint32_t behavior, int16_t moveAngleRange, int16_t moveRange, float randForwardVelOffset, float randForwardVelScale, float randYVelOffset, float randYVelScale, float randSizeOffset, float randSizeScale
) : flags(flags), model(model), behavior(behavior), moveAngleRange(moveAngleRange), moveRange(moveRange), randForwardVelOffset(randForwardVelOffset), randForwardVelScale(randForwardVelScale), randYVelOffset(randYVelOffset), randYVelScale(randYVelScale), randSizeOffset(randSizeOffset), randSizeScale(randSizeScale) {}
};
class WaterDropletHeaderExporter : public BaseExporter {
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
};
class WaterDropletBinaryExporter : public BaseExporter {
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
};
class WaterDropletCodeExporter : public BaseExporter {
ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override;
};
class WaterDropletFactory : public BaseFactory {
public:
std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override;
inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override {
return {
REGISTER(Code, WaterDropletCodeExporter)
REGISTER(Header, WaterDropletHeaderExporter)
REGISTER(Binary, WaterDropletBinaryExporter)
};
}
};
}