mirror of https://github.com/AxioDL/metaforce.git
1034 lines
32 KiB
C++
1034 lines
32 KiB
C++
#include "Runtime/Particle/CParticleDataFactory.hpp"
|
|
|
|
#include "Runtime/CRandom16.hpp"
|
|
#include "Runtime/CSimplePool.hpp"
|
|
#include "Runtime/CToken.hpp"
|
|
#include "Runtime/Graphics/CModel.hpp"
|
|
#include "Runtime/Particle/CElectricDescription.hpp"
|
|
#include "Runtime/Particle/CGenDescription.hpp"
|
|
#include "Runtime/Particle/CSwooshDescription.hpp"
|
|
|
|
namespace metaforce {
|
|
static logvisor::Module Log("metaforce::CParticleDataFactory");
|
|
|
|
float CParticleDataFactory::GetReal(CInputStream& in) { return in.readFloatBig(); }
|
|
|
|
s32 CParticleDataFactory::GetInt(CInputStream& in) { return in.readInt32Big(); }
|
|
|
|
bool CParticleDataFactory::GetBool(CInputStream& in) {
|
|
FourCC cid = GetClassID(in);
|
|
if (cid != FOURCC('CNST'))
|
|
Log.report(logvisor::Fatal, FMT_STRING("bool element does not begin with CNST"));
|
|
return in.readBool();
|
|
}
|
|
|
|
FourCC CParticleDataFactory::GetClassID(CInputStream& in) {
|
|
u32 val = 0;
|
|
in.readBytesToBuf(&val, 4);
|
|
return val;
|
|
}
|
|
|
|
SParticleModel CParticleDataFactory::GetModel(CInputStream& in, CSimplePool* resPool) {
|
|
FourCC clsId = GetClassID(in);
|
|
if (clsId == SBIG('NONE'))
|
|
return {};
|
|
CAssetId id = in.readUint32Big();
|
|
if (!id.IsValid())
|
|
return {};
|
|
return {resPool->GetObj({FOURCC('CMDL'), id}), true};
|
|
}
|
|
|
|
SChildGeneratorDesc CParticleDataFactory::GetChildGeneratorDesc(CAssetId res, CSimplePool* resPool,
|
|
const std::vector<CAssetId>& tracker) {
|
|
if (std::count(tracker.cbegin(), tracker.cend(), res) == 0)
|
|
return {resPool->GetObj({FOURCC('PART'), res}), true};
|
|
return {};
|
|
}
|
|
|
|
SChildGeneratorDesc CParticleDataFactory::GetChildGeneratorDesc(CInputStream& in, CSimplePool* resPool,
|
|
const std::vector<CAssetId>& tracker) {
|
|
FourCC clsId = GetClassID(in);
|
|
if (clsId == SBIG('NONE'))
|
|
return {};
|
|
CAssetId id = in.readUint32Big();
|
|
if (!id.IsValid())
|
|
return {};
|
|
return GetChildGeneratorDesc(id, resPool, tracker);
|
|
}
|
|
|
|
SSwooshGeneratorDesc CParticleDataFactory::GetSwooshGeneratorDesc(CInputStream& in, CSimplePool* resPool) {
|
|
FourCC clsId = GetClassID(in);
|
|
if (clsId == SBIG('NONE'))
|
|
return {};
|
|
CAssetId id = in.readUint32Big();
|
|
if (!id.IsValid())
|
|
return {};
|
|
return {resPool->GetObj({FOURCC('SWHC'), id}), true};
|
|
}
|
|
|
|
SElectricGeneratorDesc CParticleDataFactory::GetElectricGeneratorDesc(CInputStream& in, CSimplePool* resPool) {
|
|
FourCC clsId = GetClassID(in);
|
|
if (clsId == SBIG('NONE'))
|
|
return {};
|
|
CAssetId id = in.readUint32Big();
|
|
if (!id.IsValid())
|
|
return {};
|
|
return {resPool->GetObj({FOURCC('ELSC'), id}), true};
|
|
}
|
|
|
|
std::unique_ptr<CUVElement> CParticleDataFactory::GetTextureElement(CInputStream& in, CSimplePool* resPool) {
|
|
FourCC clsId = GetClassID(in);
|
|
switch (clsId.toUint32()) {
|
|
case SBIG('CNST'): {
|
|
FourCC subId = GetClassID(in);
|
|
if (subId == SBIG('NONE'))
|
|
return nullptr;
|
|
CAssetId id = in.readUint32Big();
|
|
TToken<CTexture> txtr = resPool->GetObj({FOURCC('TXTR'), id});
|
|
return std::make_unique<CUVEConstant>(std::move(txtr));
|
|
}
|
|
case SBIG('ATEX'): {
|
|
const FourCC subId = GetClassID(in);
|
|
if (subId == SBIG('NONE')) {
|
|
return nullptr;
|
|
}
|
|
const CAssetId id = in.readUint32Big();
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
auto c = GetIntElement(in);
|
|
auto d = GetIntElement(in);
|
|
auto e = GetIntElement(in);
|
|
const bool f = GetBool(in);
|
|
TToken<CTexture> txtr = resPool->GetObj({FOURCC('TXTR'), id});
|
|
return std::make_unique<CUVEAnimTexture>(std::move(txtr), std::move(std::move(a)), std::move(b), std::move(c),
|
|
std::move(d), std::move(e), f);
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<CColorElement> CParticleDataFactory::GetColorElement(CInputStream& in) {
|
|
FourCC clsId = GetClassID(in);
|
|
switch (clsId.toUint32()) {
|
|
case SBIG('KEYE'):
|
|
case SBIG('KEYP'): {
|
|
return std::make_unique<CCEKeyframeEmitter>(in);
|
|
}
|
|
case SBIG('CNST'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
if (a->IsConstant() && b->IsConstant() && c->IsConstant() && d->IsConstant()) {
|
|
float af, bf, cf, df;
|
|
a->GetValue(0, af);
|
|
b->GetValue(0, bf);
|
|
c->GetValue(0, cf);
|
|
d->GetValue(0, df);
|
|
return std::make_unique<CCEFastConstant>(af, bf, cf, df);
|
|
} else {
|
|
return std::make_unique<CCEConstant>(std::move(std::move(a)), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
}
|
|
case SBIG('CHAN'): {
|
|
auto a = GetColorElement(in);
|
|
auto b = GetColorElement(in);
|
|
auto c = GetIntElement(in);
|
|
return std::make_unique<CCETimeChain>(std::move(std::move(a)), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('CFDE'): {
|
|
auto a = GetColorElement(in);
|
|
auto b = GetColorElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
return std::make_unique<CCEFadeEnd>(std::move(std::move(a)), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
case SBIG('FADE'): {
|
|
auto a = GetColorElement(in);
|
|
auto b = GetColorElement(in);
|
|
auto c = GetRealElement(in);
|
|
return std::make_unique<CCEFade>(std::move(std::move(a)), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('PULS'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
auto c = GetColorElement(in);
|
|
auto d = GetColorElement(in);
|
|
return std::make_unique<CCEPulse>(std::move(std::move(a)), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
case SBIG('PCOL'): {
|
|
return std::make_unique<CCEParticleColor>();
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<CModVectorElement> CParticleDataFactory::GetModVectorElement(CInputStream& in) {
|
|
FourCC clsId = GetClassID(in);
|
|
switch (clsId.toUint32()) {
|
|
case SBIG('IMPL'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
const bool e = GetBool(in);
|
|
return std::make_unique<CMVEImplosion>(std::move(a), std::move(b), std::move(c), std::move(d), e);
|
|
}
|
|
case SBIG('EMPL'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
const bool e = GetBool(in);
|
|
return std::make_unique<CMVEExponentialImplosion>(std::move(a), std::move(b), std::move(c), std::move(d), e);
|
|
}
|
|
case SBIG('CHAN'): {
|
|
auto a = GetModVectorElement(in);
|
|
auto b = GetModVectorElement(in);
|
|
auto c = GetIntElement(in);
|
|
return std::make_unique<CMVETimeChain>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('BNCE'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
const bool e = GetBool(in);
|
|
return std::make_unique<CMVEBounce>(std::move(a), std::move(b), std::move(c), std::move(d), e);
|
|
}
|
|
case SBIG('CNST'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
if (a->IsConstant() && b->IsConstant() && c->IsConstant()) {
|
|
float af, bf, cf;
|
|
a->GetValue(0, af);
|
|
b->GetValue(0, bf);
|
|
c->GetValue(0, cf);
|
|
// NOTE: 0-00 bug uses the value of a for each element
|
|
// Other versions unknown
|
|
return std::make_unique<CMVEFastConstant>(af, bf, cf);
|
|
} else {
|
|
return std::make_unique<CMVEConstant>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
}
|
|
case SBIG('GRAV'): {
|
|
auto a = GetVectorElement(in);
|
|
return std::make_unique<CMVEGravity>(std::move(a));
|
|
}
|
|
case SBIG('EXPL'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CMVEExplode>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('SPOS'): {
|
|
auto a = GetVectorElement(in);
|
|
return std::make_unique<CMVESetPosition>(std::move(a));
|
|
}
|
|
case SBIG('LMPL'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
const bool e = GetBool(in);
|
|
return std::make_unique<CMVELinearImplosion>(std::move(a), std::move(b), std::move(c), std::move(d), e);
|
|
}
|
|
case SBIG('PULS'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
auto c = GetModVectorElement(in);
|
|
auto d = GetModVectorElement(in);
|
|
return std::make_unique<CMVEPulse>(std::move(a), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
case SBIG('WIND'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CMVEWind>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('SWRL'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
return std::make_unique<CMVESwirl>(std::move(a), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<CEmitterElement> CParticleDataFactory::GetEmitterElement(CInputStream& in) {
|
|
FourCC clsId = GetClassID(in);
|
|
switch (clsId.toUint32()) {
|
|
case SBIG('SETR'): {
|
|
FourCC prop = GetClassID(in);
|
|
if (prop == SBIG('ILOC')) {
|
|
auto a = GetVectorElement(in);
|
|
prop = GetClassID(in);
|
|
if (prop == SBIG('IVEC')) {
|
|
auto b = GetVectorElement(in);
|
|
return std::make_unique<CEESimpleEmitter>(std::move(a), std::move(b));
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
case SBIG('SEMR'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
return std::make_unique<CEESimpleEmitter>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('SPHE'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
return std::make_unique<CVESphere>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('ASPH'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
auto e = GetRealElement(in);
|
|
auto f = GetRealElement(in);
|
|
auto g = GetRealElement(in);
|
|
return std::make_unique<CVEAngleSphere>(std::move(a), std::move(f), std::move(g), std::move(b), std::move(c),
|
|
std::move(d), std::move(e));
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<CVectorElement> CParticleDataFactory::GetVectorElement(CInputStream& in) {
|
|
FourCC clsId = GetClassID(in);
|
|
switch (clsId.toUint32()) {
|
|
case SBIG('CONE'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CVECone>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('CHAN'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
auto c = GetIntElement(in);
|
|
return std::make_unique<CVETimeChain>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('ANGC'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
auto e = GetRealElement(in);
|
|
return std::make_unique<CVEAngleCone>(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e));
|
|
}
|
|
case SBIG('ADD_'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
return std::make_unique<CVEAdd>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('CCLU'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
auto c = GetIntElement(in);
|
|
auto d = GetRealElement(in);
|
|
return std::make_unique<CVECircleCluster>(std::move(a), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
case SBIG('CNST'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
if (a->IsConstant() && b->IsConstant() && c->IsConstant()) {
|
|
float af, bf, cf;
|
|
a->GetValue(0, af);
|
|
b->GetValue(0, bf);
|
|
c->GetValue(0, cf);
|
|
return std::make_unique<CVEFastConstant>(af, bf, cf);
|
|
} else {
|
|
return std::make_unique<CVEConstant>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
}
|
|
case SBIG('CIRC'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
auto e = GetRealElement(in);
|
|
return std::make_unique<CVECircle>(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e));
|
|
}
|
|
case SBIG('KEYE'):
|
|
case SBIG('KEYP'): {
|
|
return std::make_unique<CVEKeyframeEmitter>(in);
|
|
}
|
|
case SBIG('MULT'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
return std::make_unique<CVEMultiply>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('RTOV'): {
|
|
auto a = GetRealElement(in);
|
|
return std::make_unique<CVERealToVector>(std::move(a));
|
|
}
|
|
case SBIG('PULS'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
auto c = GetVectorElement(in);
|
|
auto d = GetVectorElement(in);
|
|
return std::make_unique<CVEPulse>(std::move(a), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
case SBIG('PVEL'): {
|
|
return std::make_unique<CVEParticleVelocity>();
|
|
}
|
|
case SBIG('PLCO'): {
|
|
return std::make_unique<CVEParticleColor>();
|
|
}
|
|
case SBIG('PLOC'): {
|
|
return std::make_unique<CVEParticleLocation>();
|
|
}
|
|
case SBIG('PSOF'): {
|
|
return std::make_unique<CVEParticleSystemOrientationFront>();
|
|
}
|
|
case SBIG('PSOU'): {
|
|
return std::make_unique<CVEParticleSystemOrientationUp>();
|
|
}
|
|
case SBIG('PSOR'): {
|
|
return std::make_unique<CVEParticleSystemOrientationRight>();
|
|
}
|
|
case SBIG('PSTR'): {
|
|
return std::make_unique<CVEParticleSystemTranslation>();
|
|
}
|
|
case SBIG('SUB_'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
return std::make_unique<CVESubtract>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('CTVC'): {
|
|
auto a = GetColorElement(in);
|
|
return std::make_unique<CVEColorToVector>(std::move(a));
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<CRealElement> CParticleDataFactory::GetRealElement(CInputStream& in) {
|
|
FourCC clsId = GetClassID(in);
|
|
switch (clsId.toUint32()) {
|
|
case SBIG('LFTW'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CRELifetimeTween>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('CNST'): {
|
|
const float a = GetReal(in);
|
|
return std::make_unique<CREConstant>(a);
|
|
}
|
|
case SBIG('CHAN'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetIntElement(in);
|
|
return std::make_unique<CRETimeChain>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('ADD_'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CREAdd>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('CLMP'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
return std::make_unique<CREClamp>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('KEYE'):
|
|
case SBIG('KEYP'): {
|
|
return std::make_unique<CREKeyframeEmitter>(in);
|
|
}
|
|
case SBIG('IRND'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CREInitialRandom>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('RAND'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CRERandom>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('DOTP'): {
|
|
auto a = GetVectorElement(in);
|
|
auto b = GetVectorElement(in);
|
|
return std::make_unique<CREDotProduct>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('MULT'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CREMultiply>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('PULS'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
return std::make_unique<CREPulse>(std::move(a), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
case SBIG('SCAL'): {
|
|
auto a = GetRealElement(in);
|
|
return std::make_unique<CRETimeScale>(std::move(a));
|
|
}
|
|
case SBIG('RLPT'): {
|
|
auto a = GetRealElement(in);
|
|
return std::make_unique<CRELifetimePercent>(std::move(a));
|
|
}
|
|
case SBIG('SINE'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
return std::make_unique<CRESineWave>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('ISWT'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CREInitialSwitch>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('CLTN'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
return std::make_unique<CRECompareLessThan>(std::move(a), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
case SBIG('CEQL'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
return std::make_unique<CRECompareEquals>(std::move(a), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
case SBIG('PAP1'): {
|
|
return std::make_unique<CREParticleAccessParam1>();
|
|
}
|
|
case SBIG('PAP2'): {
|
|
return std::make_unique<CREParticleAccessParam2>();
|
|
}
|
|
case SBIG('PAP3'): {
|
|
return std::make_unique<CREParticleAccessParam3>();
|
|
}
|
|
case SBIG('PAP4'): {
|
|
return std::make_unique<CREParticleAccessParam4>();
|
|
}
|
|
case SBIG('PAP5'): {
|
|
return std::make_unique<CREParticleAccessParam5>();
|
|
}
|
|
case SBIG('PAP6'): {
|
|
return std::make_unique<CREParticleAccessParam6>();
|
|
}
|
|
case SBIG('PAP7'): {
|
|
return std::make_unique<CREParticleAccessParam7>();
|
|
}
|
|
case SBIG('PAP8'): {
|
|
return std::make_unique<CREParticleAccessParam8>();
|
|
}
|
|
case SBIG('PSLL'): {
|
|
return std::make_unique<CREParticleSizeOrLineLength>();
|
|
}
|
|
case SBIG('PRLW'): {
|
|
return std::make_unique<CREParticleRotationOrLineWidth>();
|
|
}
|
|
case SBIG('SUB_'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CRESubtract>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('VMAG'): {
|
|
auto a = GetVectorElement(in);
|
|
return std::make_unique<CREVectorMagnitude>(std::move(a));
|
|
}
|
|
case SBIG('VXTR'): {
|
|
auto a = GetVectorElement(in);
|
|
return std::make_unique<CREVectorXToReal>(std::move(a));
|
|
}
|
|
case SBIG('VYTR'): {
|
|
auto a = GetVectorElement(in);
|
|
return std::make_unique<CREVectorYToReal>(std::move(a));
|
|
}
|
|
case SBIG('VZTR'): {
|
|
auto a = GetVectorElement(in);
|
|
return std::make_unique<CREVectorZToReal>(std::move(a));
|
|
}
|
|
case SBIG('CEXT'): {
|
|
auto a = GetIntElement(in);
|
|
return std::make_unique<CREExternalVar>(std::move(a));
|
|
}
|
|
case SBIG('ITRL'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CREIntTimesReal>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('CRNG'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
auto c = GetRealElement(in);
|
|
auto d = GetRealElement(in);
|
|
auto e = GetRealElement(in);
|
|
return std::make_unique<CREConstantRange>(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e));
|
|
}
|
|
case SBIG('GTCR'): {
|
|
auto a = GetColorElement(in);
|
|
return std::make_unique<CREGetComponentRed>(std::move(a));
|
|
}
|
|
case SBIG('GTCG'): {
|
|
auto a = GetColorElement(in);
|
|
return std::make_unique<CREGetComponentGreen>(std::move(a));
|
|
}
|
|
case SBIG('GTCB'): {
|
|
auto a = GetColorElement(in);
|
|
return std::make_unique<CREGetComponentBlue>(std::move(a));
|
|
}
|
|
case SBIG('GTCA'): {
|
|
auto a = GetColorElement(in);
|
|
return std::make_unique<CREGetComponentAlpha>(std::move(a));
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<CIntElement> CParticleDataFactory::GetIntElement(CInputStream& in) {
|
|
FourCC clsId = GetClassID(in);
|
|
switch (clsId.toUint32()) {
|
|
case SBIG('KEYE'):
|
|
case SBIG('KEYP'): {
|
|
return std::make_unique<CIEKeyframeEmitter>(in);
|
|
}
|
|
case SBIG('DETH'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
return std::make_unique<CIEDeath>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('CLMP'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
auto c = GetIntElement(in);
|
|
return std::make_unique<CIEClamp>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('CHAN'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
auto c = GetIntElement(in);
|
|
return std::make_unique<CIETimeChain>(std::move(a), std::move(b), std::move(c));
|
|
}
|
|
case SBIG('ADD_'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
return std::make_unique<CIEAdd>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('CNST'): {
|
|
const int a = GetInt(in);
|
|
return std::make_unique<CIEConstant>(a);
|
|
}
|
|
case SBIG('IMPL'): {
|
|
auto a = GetIntElement(in);
|
|
return std::make_unique<CIEImpulse>(std::move(a));
|
|
}
|
|
case SBIG('ILPT'): {
|
|
auto a = GetIntElement(in);
|
|
return std::make_unique<CIELifetimePercent>(std::move(a));
|
|
}
|
|
case SBIG('IRND'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
return std::make_unique<CIEInitialRandom>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('PULS'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
auto c = GetIntElement(in);
|
|
auto d = GetIntElement(in);
|
|
return std::make_unique<CIEPulse>(std::move(a), std::move(b), std::move(c), std::move(d));
|
|
}
|
|
case SBIG('MULT'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
return std::make_unique<CIEMultiply>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('SPAH'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
auto c = GetIntElement(in);
|
|
return std::make_unique<CIESampleAndHold>(std::move(c), std::move(a), std::move(b));
|
|
}
|
|
case SBIG('RAND'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
return std::make_unique<CIERandom>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('RTOI'): {
|
|
auto a = GetRealElement(in);
|
|
auto b = GetRealElement(in);
|
|
return std::make_unique<CIERealToInt>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('TSCL'): {
|
|
auto a = GetRealElement(in);
|
|
return std::make_unique<CIETimeScale>(std::move(a));
|
|
}
|
|
case SBIG('GAPC'): {
|
|
return std::make_unique<CIEGetActiveParticleCount>();
|
|
}
|
|
case SBIG('GTCP'): {
|
|
return std::make_unique<CIEGetCumulativeParticleCount>();
|
|
}
|
|
case SBIG('GEMT'): {
|
|
return std::make_unique<CIEGetEmitterTime>();
|
|
}
|
|
case SBIG('MODU'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
return std::make_unique<CIEModulo>(std::move(a), std::move(b));
|
|
}
|
|
case SBIG('SUB_'): {
|
|
auto a = GetIntElement(in);
|
|
auto b = GetIntElement(in);
|
|
return std::make_unique<CIESubtract>(std::move(a), std::move(b));
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
std::unique_ptr<CGenDescription> CParticleDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) {
|
|
std::vector<CAssetId> tracker;
|
|
tracker.reserve(8);
|
|
return CreateGeneratorDescription(in, tracker, 0, resPool);
|
|
}
|
|
|
|
std::unique_ptr<CGenDescription> CParticleDataFactory::CreateGeneratorDescription(CInputStream& in,
|
|
std::vector<CAssetId>& tracker,
|
|
CAssetId resId,
|
|
CSimplePool* resPool) {
|
|
if (std::count(tracker.cbegin(), tracker.cend(), resId) == 0) {
|
|
tracker.push_back(resId);
|
|
FourCC cid = GetClassID(in);
|
|
if (cid == FOURCC('GPSM')) {
|
|
auto ret = std::make_unique<CGenDescription>();
|
|
CreateGPSM(ret.get(), in, tracker, resPool);
|
|
LoadGPSMTokens(ret.get());
|
|
return ret;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
bool CParticleDataFactory::CreateGPSM(CGenDescription* fillDesc, CInputStream& in, std::vector<CAssetId>& tracker,
|
|
CSimplePool* resPool) {
|
|
CRandom16 rand;
|
|
CGlobalRandom gr(rand);
|
|
FourCC clsId = GetClassID(in);
|
|
while (clsId != SBIG('_END')) {
|
|
switch (clsId.toUint32()) {
|
|
case SBIG('PMCL'):
|
|
fillDesc->x78_x64_PMCL = GetColorElement(in);
|
|
break;
|
|
case SBIG('LFOR'):
|
|
fillDesc->x118_x104_LFOR = GetRealElement(in);
|
|
break;
|
|
case SBIG('IDTS'):
|
|
fillDesc->xa4_x90_IDTS = GetChildGeneratorDesc(in, resPool, tracker);
|
|
break;
|
|
case SBIG('EMTR'):
|
|
fillDesc->x40_x2c_EMTR = GetEmitterElement(in);
|
|
break;
|
|
case SBIG('COLR'):
|
|
fillDesc->x30_x24_COLR = GetColorElement(in);
|
|
break;
|
|
case SBIG('CIND'):
|
|
fillDesc->x45_30_x32_24_CIND = GetBool(in);
|
|
break;
|
|
case SBIG('AAPH'):
|
|
fillDesc->x44_26_x30_26_AAPH = GetBool(in);
|
|
break;
|
|
case SBIG('CSSD'):
|
|
fillDesc->xa0_x8c_CSSD = GetIntElement(in);
|
|
break;
|
|
case SBIG('GRTE'):
|
|
fillDesc->x2c_x20_GRTE = GetRealElement(in);
|
|
break;
|
|
case SBIG('FXLL'):
|
|
fillDesc->x44_25_x30_25_FXLL = GetBool(in);
|
|
break;
|
|
case SBIG('ICTS'):
|
|
fillDesc->x8c_x78_ICTS = GetChildGeneratorDesc(in, resPool, tracker);
|
|
break;
|
|
case SBIG('KSSM'): {
|
|
fillDesc->xd0_xbc_KSSM.reset();
|
|
FourCC cid = GetClassID(in);
|
|
if (cid != SBIG('CNST'))
|
|
break;
|
|
fillDesc->xd0_xbc_KSSM = std::make_unique<CSpawnSystemKeyframeData>(in);
|
|
fillDesc->xd0_xbc_KSSM->LoadAllSpawnedSystemTokens(resPool);
|
|
break;
|
|
}
|
|
case SBIG('ILOC'):
|
|
GetVectorElement(in);
|
|
break;
|
|
case SBIG('IITS'):
|
|
fillDesc->xb8_xa4_IITS = GetChildGeneratorDesc(in, resPool, tracker);
|
|
break;
|
|
case SBIG('IVEC'):
|
|
GetVectorElement(in);
|
|
break;
|
|
case SBIG('LDIR'):
|
|
fillDesc->x110_xfc_LDIR = GetVectorElement(in);
|
|
break;
|
|
case SBIG('LCLR'):
|
|
fillDesc->x104_xf0_LCLR = GetColorElement(in);
|
|
break;
|
|
case SBIG('LENG'):
|
|
fillDesc->x20_x14_LENG = GetRealElement(in);
|
|
break;
|
|
case SBIG('MAXP'):
|
|
fillDesc->x28_x1c_MAXP = GetIntElement(in);
|
|
break;
|
|
case SBIG('LOFF'):
|
|
fillDesc->x10c_xf8_LOFF = GetVectorElement(in);
|
|
break;
|
|
case SBIG('LINT'):
|
|
fillDesc->x108_xf4_LINT = GetRealElement(in);
|
|
break;
|
|
case SBIG('LINE'):
|
|
fillDesc->x44_24_x30_24_LINE = GetBool(in);
|
|
break;
|
|
case SBIG('LFOT'):
|
|
fillDesc->x114_x100_LFOT = GetIntElement(in);
|
|
break;
|
|
case SBIG('LIT_'):
|
|
fillDesc->x44_29_x30_29_LIT_ = GetBool(in);
|
|
break;
|
|
case SBIG('LTME'):
|
|
fillDesc->x34_x28_LTME = GetIntElement(in);
|
|
break;
|
|
case SBIG('LSLA'):
|
|
fillDesc->x11c_x108_LSLA = GetRealElement(in);
|
|
break;
|
|
case SBIG('LTYP'):
|
|
fillDesc->x100_xec_LTYP = GetIntElement(in);
|
|
break;
|
|
case SBIG('NDSY'):
|
|
fillDesc->xb4_xa0_NDSY = GetIntElement(in);
|
|
break;
|
|
case SBIG('MBSP'):
|
|
fillDesc->x48_x34_MBSP = GetIntElement(in);
|
|
break;
|
|
case SBIG('MBLR'):
|
|
fillDesc->x44_30_x31_24_MBLR = GetBool(in);
|
|
break;
|
|
case SBIG('NCSY'):
|
|
fillDesc->x9c_x88_NCSY = GetIntElement(in);
|
|
break;
|
|
case SBIG('PISY'):
|
|
fillDesc->xc8_xb4_PISY = GetIntElement(in);
|
|
break;
|
|
case SBIG('OPTS'):
|
|
fillDesc->x45_31_x32_25_OPTS = GetBool(in);
|
|
break;
|
|
case SBIG('PMAB'):
|
|
fillDesc->x44_31_x31_25_PMAB = GetBool(in);
|
|
break;
|
|
case SBIG('SESD'):
|
|
fillDesc->xf8_xe4_SESD = GetIntElement(in);
|
|
break;
|
|
case SBIG('SEPO'):
|
|
fillDesc->xfc_xe8_SEPO = GetVectorElement(in);
|
|
break;
|
|
case SBIG('PSLT'):
|
|
fillDesc->xc_x0_PSLT = GetIntElement(in);
|
|
break;
|
|
case SBIG('PMSC'):
|
|
fillDesc->x74_x60_PMSC = GetVectorElement(in);
|
|
break;
|
|
case SBIG('PMOP'):
|
|
fillDesc->x6c_x58_PMOP = GetVectorElement(in);
|
|
break;
|
|
case SBIG('PMDL'):
|
|
fillDesc->x5c_x48_PMDL = GetModel(in, resPool);
|
|
break;
|
|
case SBIG('PMRT'):
|
|
fillDesc->x70_x5c_PMRT = GetVectorElement(in);
|
|
break;
|
|
case SBIG('POFS'):
|
|
fillDesc->x18_xc_POFS = GetVectorElement(in);
|
|
break;
|
|
case SBIG('PMUS'):
|
|
fillDesc->x45_24_x31_26_PMUS = GetBool(in);
|
|
break;
|
|
case SBIG('PSIV'):
|
|
GetVectorElement(in);
|
|
break;
|
|
case SBIG('ROTA'):
|
|
fillDesc->x50_x3c_ROTA = GetRealElement(in);
|
|
break;
|
|
case SBIG('PSVM'):
|
|
GetModVectorElement(in);
|
|
break;
|
|
case SBIG('PSTS'):
|
|
fillDesc->x14_x8_PSTS = GetRealElement(in);
|
|
break;
|
|
case SBIG('PSOV'):
|
|
GetVectorElement(in);
|
|
break;
|
|
case SBIG('PSWT'):
|
|
fillDesc->x10_x4_PSWT = GetIntElement(in);
|
|
break;
|
|
case SBIG('SEED'):
|
|
fillDesc->x1c_x10_SEED = GetIntElement(in);
|
|
break;
|
|
case SBIG('PMOO'):
|
|
fillDesc->x45_25_x31_27_PMOO = GetBool(in);
|
|
break;
|
|
case SBIG('SSSD'):
|
|
fillDesc->xe4_xd0_SSSD = GetIntElement(in);
|
|
break;
|
|
case SBIG('SORT'):
|
|
fillDesc->x44_28_x30_28_SORT = GetBool(in);
|
|
break;
|
|
case SBIG('SIZE'):
|
|
fillDesc->x4c_x38_SIZE = GetRealElement(in);
|
|
break;
|
|
case SBIG('SISY'):
|
|
fillDesc->xcc_xb8_SISY = GetIntElement(in);
|
|
break;
|
|
case SBIG('SSPO'):
|
|
fillDesc->xe8_xd4_SSPO = GetVectorElement(in);
|
|
break;
|
|
case SBIG('TEXR'):
|
|
fillDesc->x54_x40_TEXR = GetTextureElement(in, resPool);
|
|
break;
|
|
case SBIG('SSWH'):
|
|
fillDesc->xd4_xc0_SSWH = GetSwooshGeneratorDesc(in, resPool);
|
|
break;
|
|
case SBIG('TIND'):
|
|
fillDesc->x58_x44_TIND = GetTextureElement(in, resPool);
|
|
break;
|
|
case SBIG('VMD4'):
|
|
fillDesc->x45_29_x31_31_VMD4 = GetBool(in);
|
|
break;
|
|
case SBIG('VMD3'):
|
|
fillDesc->x45_28_x31_30_VMD3 = GetBool(in);
|
|
break;
|
|
case SBIG('VMD2'):
|
|
fillDesc->x45_27_x31_29_VMD2 = GetBool(in);
|
|
break;
|
|
case SBIG('VMD1'):
|
|
fillDesc->x45_26_x31_28_VMD1 = GetBool(in);
|
|
break;
|
|
case SBIG('VEL4'):
|
|
fillDesc->x88_x74_VEL4 = GetModVectorElement(in);
|
|
break;
|
|
case SBIG('VEL3'):
|
|
fillDesc->x84_x70_VEL3 = GetModVectorElement(in);
|
|
break;
|
|
case SBIG('VEL2'):
|
|
fillDesc->x80_x6c_VEL2 = GetModVectorElement(in);
|
|
break;
|
|
case SBIG('VEL1'):
|
|
fillDesc->x7c_x68_VEL1 = GetModVectorElement(in);
|
|
break;
|
|
case SBIG('ZBUF'):
|
|
fillDesc->x44_27_x30_27_ZBUF = GetBool(in);
|
|
break;
|
|
case SBIG('WIDT'):
|
|
fillDesc->x24_x18_WIDT = GetRealElement(in);
|
|
break;
|
|
case SBIG('ORNT'):
|
|
fillDesc->x30_30_ORNT = GetBool(in);
|
|
break;
|
|
case SBIG('RSOP'):
|
|
fillDesc->x30_31_RSOP = GetBool(in);
|
|
break;
|
|
case SBIG('ADV1'):
|
|
fillDesc->x10c_ADV1 = GetRealElement(in);
|
|
break;
|
|
case SBIG('ADV2'):
|
|
fillDesc->x110_ADV2 = GetRealElement(in);
|
|
break;
|
|
case SBIG('ADV3'):
|
|
fillDesc->x114_ADV3 = GetRealElement(in);
|
|
break;
|
|
case SBIG('ADV4'):
|
|
fillDesc->x118_ADV4 = GetRealElement(in);
|
|
break;
|
|
case SBIG('ADV5'):
|
|
fillDesc->x11c_ADV5 = GetRealElement(in);
|
|
break;
|
|
case SBIG('ADV6'):
|
|
fillDesc->x120_ADV6 = GetRealElement(in);
|
|
break;
|
|
case SBIG('ADV7'):
|
|
fillDesc->x124_ADV7 = GetRealElement(in);
|
|
break;
|
|
case SBIG('ADV8'):
|
|
fillDesc->x128_ADV8 = GetRealElement(in);
|
|
break;
|
|
case SBIG('SELC'):
|
|
fillDesc->xec_xd8_SELC = GetElectricGeneratorDesc(in, resPool);
|
|
break;
|
|
default: {
|
|
Log.report(logvisor::Fatal, FMT_STRING("Unknown GPSM class {} @{}"), clsId, in.position());
|
|
return false;
|
|
}
|
|
}
|
|
clsId = GetClassID(in);
|
|
}
|
|
|
|
/* Now for our custom additions, if available */
|
|
if (!in.atEnd() && (in.position() + 4) < in.length()) {
|
|
clsId = GetClassID(in);
|
|
if (clsId == 0xFFFFFFFF)
|
|
return true;
|
|
|
|
while (clsId != SBIG('_END') && !in.atEnd()) {
|
|
switch (clsId.toUint32()) {
|
|
case SBIG('BGCL'):
|
|
fillDesc->m_bevelGradient = GetColorElement(in);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
clsId = GetClassID(in);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CParticleDataFactory::LoadGPSMTokens(CGenDescription* desc) {
|
|
if (desc->x5c_x48_PMDL.m_found)
|
|
desc->x5c_x48_PMDL.m_model = desc->x5c_x48_PMDL.m_token.GetObj();
|
|
|
|
if (desc->x8c_x78_ICTS.m_found)
|
|
desc->x8c_x78_ICTS.m_gen = desc->x8c_x78_ICTS.m_token.GetObj();
|
|
|
|
if (desc->xa4_x90_IDTS.m_found)
|
|
desc->xa4_x90_IDTS.m_gen = desc->xa4_x90_IDTS.m_token.GetObj();
|
|
|
|
if (desc->xb8_xa4_IITS.m_found)
|
|
desc->xb8_xa4_IITS.m_gen = desc->xb8_xa4_IITS.m_token.GetObj();
|
|
|
|
if (desc->xd4_xc0_SSWH.m_found)
|
|
desc->xd4_xc0_SSWH.m_swoosh = desc->xd4_xc0_SSWH.m_token.GetObj();
|
|
}
|
|
|
|
CFactoryFnReturn FParticleFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms,
|
|
CObjectReference* selfRef) {
|
|
auto* const sp = vparms.GetOwnedObj<CSimplePool*>();
|
|
return TToken<CGenDescription>::GetIObjObjectFor(CParticleDataFactory::GetGeneratorDesc(in, sp));
|
|
}
|
|
|
|
} // namespace metaforce
|