diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 8dbf65d070..f3a03b097f 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -278,8 +278,13 @@ namespace Nif { "NiRotatingParticlesData", &construct }, // Geometry, Gamebryo + { "NiParticleSystem", &construct }, + { "NiMeshParticleSystem", &construct }, { "NiPSysData", &construct }, + // Geometry, Bethesda + { "BSStripParticleSystem", &construct }, + // Modifiers, 4.0.0.2 { "NiGravity", &construct }, { "NiParticleColorModifier", &construct }, diff --git a/components/nif/particle.cpp b/components/nif/particle.cpp index 389449ed77..8dee873c0b 100644 --- a/components/nif/particle.cpp +++ b/components/nif/particle.cpp @@ -150,6 +150,46 @@ namespace Nif nif->readVector(mRotations, mNumVertices); } + void NiParticleSystem::read(NIFStream* nif) + { + // Weird loading to account for inheritance differences starting from SSE + if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_SSE) + NiParticles::read(nif); + else + { + NiAVObject::read(nif); + + nif->read(mBoundingSphere); + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76) + nif->readArray(mBoundMinMax); + + mSkin.read(nif); + mShaderProperty.read(nif); + mAlphaProperty.read(nif); + mVertDesc.read(nif); + } + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_SKY) + { + nif->readArray(mNearFar); + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_SSE) + mData.read(nif); + } + + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) + { + nif->read(mWorldSpace); + readRecordList(nif, mModifiers); + } + } + + void NiParticleSystem::post(Reader& nif) + { + NiParticles::post(nif); + + postRecordList(nif, mModifiers); + } + void NiPSysData::read(NIFStream* nif) { NiParticlesData::read(nif); @@ -175,6 +215,19 @@ namespace Nif } } + void NiPSysModifier::read(NIFStream* nif) + { + nif->read(mName); + mOrder = static_cast(nif->get()); + mTarget.read(nif); + nif->read(mActive); + } + + void NiPSysModifier::post(Reader& nif) + { + mTarget.post(nif); + } + void NiPSysModifierCtlr::read(NIFStream* nif) { NiSingleInterpController::read(nif); diff --git a/components/nif/particle.hpp b/components/nif/particle.hpp index ffdb307bab..f800ddefb7 100644 --- a/components/nif/particle.hpp +++ b/components/nif/particle.hpp @@ -4,6 +4,7 @@ #include "base.hpp" #include "controller.hpp" #include "data.hpp" +#include "node.hpp" namespace Nif { @@ -114,6 +115,19 @@ namespace Nif void read(NIFStream* nif) override; }; + struct NiParticleSystem : NiParticles + { + osg::BoundingSpheref mBoundingSphere; + std::array mBoundMinMax; + BSVertexDesc mVertDesc; + std::array mNearFar; + bool mWorldSpace{ true }; + NiPSysModifierList mModifiers; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + struct NiPSysData : NiParticlesData { std::vector mParticles; @@ -124,6 +138,35 @@ namespace Nif void read(NIFStream* nif) override; }; + // Abstract + struct NiPSysModifier : Record + { + enum class NiPSysModifierOrder : uint32_t + { + KillOldParticles = 0, + BSLOD = 1, + Emitter = 1000, + Spawn = 2000, + BSStripUpdateFO3 = 2500, + General = 3000, + Force = 4000, + Collider = 5000, + PosUpdate = 6000, + PostPosUpdate = 6500, + WorldshiftPartspawn = 6600, + BoundUpdate = 7000, + BSStripUpdateSK = 8000, + }; + + std::string mName; + NiPSysModifierOrder mOrder; + NiParticleSystemPtr mTarget; + bool mActive; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + // Abstract struct NiPSysModifierCtlr : NiSingleInterpController { diff --git a/components/nif/record.hpp b/components/nif/record.hpp index fd780e52eb..a4598ebe3c 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -172,6 +172,7 @@ namespace Nif RC_NiParticleRotation, RC_NiParticles, RC_NiParticlesData, + RC_NiParticleSystem, RC_NiParticleSystemController, RC_NiPathController, RC_NiPathInterpolator, diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index 53b9c02a95..2355879ac6 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -129,7 +129,9 @@ namespace Nif struct NiSourceTexture; struct NiPalette; struct NiParticleModifier; + struct NiParticleSystem; struct NiPSysEmitterCtlrData; + struct NiPSysModifier; struct NiBoolData; struct NiSkinPartition; struct BSShaderTextureSet; @@ -171,6 +173,7 @@ namespace Nif using NiSourceTexturePtr = RecordPtrT; using NiPalettePtr = RecordPtrT; using NiParticleModifierPtr = RecordPtrT; + using NiParticleSystemPtr = RecordPtrT; using NiPSysEmitterCtlrDataPtr = RecordPtrT; using NiBoolDataPtr = RecordPtrT; using NiSkinPartitionPtr = RecordPtrT; @@ -204,6 +207,7 @@ namespace Nif using bhkSerializableList = RecordListT; using bhkEntityList = RecordListT; using NiControllerSequenceList = RecordListT; + using NiPSysModifierList = RecordListT; } // Namespace #endif