mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-09 05:47:42 +00:00
Refactor particle serialization to use generative meta-information
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user