#ifndef _DNAMP3_CMDL_MATERIALS_HPP_ #define _DNAMP3_CMDL_MATERIALS_HPP_ #include "../DNACommon/DNACommon.hpp" #include "../DNACommon/GX.hpp" #include "../DNAMP1/CMDLMaterials.hpp" #include "DNAMP3.hpp" namespace DataSpec::DNAMP3 { struct MaterialSet : BigDNA { static constexpr bool OneSection() {return true;} DECL_DNA Value materialCount; /* Dummy methods from MP1/2 */ void addTexture(const UniqueID32&) {} void addMaterialEndOff(atUint32) {++materialCount;} struct Material : BigDNA { Delete expl; using VAFlags = DNAMP1::MaterialSet::Material::VAFlags; struct Header : BigDNA { DECL_DNA Value size; struct Flags : BigDNA { DECL_DNA Value flags; bool alphaBlending() const {return (flags & 0x8) != 0;} void setAlphaBlending(bool enabled) {flags &= ~0x8; flags |= atUint32(enabled) << 3;} bool punchthroughAlpha() const {return (flags & 0x10) != 0;} void setPunchthroughAlpha(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;} bool additiveBlending() const {return (flags & 0x20) != 0;} void setAdditiveBlending(bool enabled) {flags &= ~0x20; flags |= atUint32(enabled) << 5;} bool shadowOccluderMesh() const {return (flags & 0x100) != 0;} void setShadowOccluderMesh(bool enabled) {flags &= ~0x100; flags |= atUint32(enabled) << 8;} bool lightmapUVArray() const {return false;} /* For polymorphic compatibility with MP1/2 */ } flags; Value groupIdx; Value unk1; VAFlags vaFlags; Value unk2; Value unk3; Value unk4; } header; const Header::Flags& getFlags() const {return header.flags;} const VAFlags& getVAFlags() const {return header.vaFlags;} struct ISection : BigDNA { Delete expl; enum class Type : atUint32 { PASS = SBIG('PASS'), CLR = SBIG('CLR '), INT = SBIG('INT ') } m_type; ISection(Type type) : m_type(type) {} virtual void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const=0; }; struct SectionPASS : ISection { SectionPASS() : ISection(ISection::Type::PASS) {} DECL_DNA Value size; enum class Subtype : atUint32 { DIFF = SBIG('DIFF'), RIML = SBIG('RIML'), BLOL = SBIG('BLOL'), BLOD = SBIG('BLOD'), CLR = SBIG('CLR '), TRAN = SBIG('TRAN'), INCA = SBIG('INCA'), RFLV = SBIG('RFLV'), RFLD = SBIG('RFLD'), LRLD = SBIG('LRLD'), LURD = SBIG('LURD'), BLOI = SBIG('BLOI'), XRAY = SBIG('XRAY'), TOON = SBIG('TOON') }; DNAFourCC subtype; struct Flags : BigDNA { DECL_DNA Value flags; bool TRANInvert() const {return (flags & 0x10) != 0;} void setTRANInvert(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;} } flags; UniqueID64 txtrId; Value uvSrc; Value uvAnimSize; struct UVAnimation : BigDNA { DECL_DNA Value unk1; Value unk2; DNAMP1::MaterialSet::Material::UVAnimation anim; }; Vector uvAnim; void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const; }; struct SectionCLR : ISection { SectionCLR() : ISection(ISection::Type::CLR) {} DECL_DNA enum class Subtype : atUint32 { CLR = SBIG('CLR '), DIFB = SBIG('DIFB') }; DNAFourCC subtype; GX::Color color; void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const; }; struct SectionINT : ISection { SectionINT() : ISection(ISection::Type::INT) {} DECL_DNA enum class Subtype : atUint32 { OPAC = SBIG('OPAC'), BLOD = SBIG('BLOD'), BLOI = SBIG('BLOI'), BNIF = SBIG('BNIF'), XRBR = SBIG('XRBR') }; DNAFourCC subtype; Value value; void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const; }; struct SectionFactory : BigDNA { Delete expl; std::unique_ptr section; void read(athena::io::IStreamReader& reader) { DNAFourCC type; type.read(reader); switch (ISection::Type(type.toUint32())) { case ISection::Type::PASS: section.reset(new struct SectionPASS); section->read(reader); break; case ISection::Type::CLR: section.reset(new struct SectionCLR); section->read(reader); break; case ISection::Type::INT: section.reset(new struct SectionINT); section->read(reader); break; default: section.reset(nullptr); break; } } void write(athena::io::IStreamWriter& writer) const { if (!section) return; writer.writeUBytes((atUint8*)§ion->m_type, 4); section->write(writer); } size_t binarySize(size_t __isz) const { return section->binarySize(__isz + 4); } }; std::vector sections; void read(athena::io::IStreamReader& reader) { header.read(reader); sections.clear(); do { sections.emplace_back(); sections.back().read(reader); } while (sections.back().section); sections.pop_back(); } void write(athena::io::IStreamWriter& writer) const { header.write(writer); for (const SectionFactory& section : sections) section.write(writer); writer.writeUBytes((atUint8*)"END ", 4); } size_t binarySize(size_t __isz) const { __isz = header.binarySize(__isz); for (const SectionFactory& section : sections) __isz = section.binarySize(__isz); return __isz + 4; } }; Vector materials; static void RegisterMaterialProps(hecl::blender::PyOutStream& out); static void ConstructMaterial(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, const PAK::Entry& entry, const MaterialSet::Material& material, unsigned groupIdx, unsigned matIdx); void readToBlender(hecl::blender::PyOutStream& os, const PAKRouter& pakRouter, const PAKRouter::EntryType& entry, unsigned setIdx) { DNACMDL::ReadMaterialSetToBlender_3(os, *this, pakRouter, entry, setIdx); } }; } #endif // _DNAMP3_CMDL_MATERIALS_HPP_