diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index 16d553cec8..32291b8c12 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -43,7 +43,7 @@ namespace Nif if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 110)) { - nif->skip(4); // NiBlendInterpolator link + mBlendInterpolator.read(nif); mBlendIndex = nif->getUShort(); } if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106) && nif->getBethVersion() > 0) @@ -73,6 +73,7 @@ namespace Nif { mInterpolator.post(nif); mController.post(nif); + mBlendInterpolator.post(nif); mStringPalette.post(nif); // TODO: probably should fill the strings with string palette contents here } @@ -431,9 +432,15 @@ namespace Nif { Controller::read(nif); mCumulative = nif->getBoolean(); - unsigned int numSequences = nif->getUInt(); - nif->skip(4 * numSequences); // Controller sequences - nif->skip(4); // Object palette + readRecordList(nif, mSequences); + mObjectPalette.read(nif); + } + + void NiControllerManager::post(Reader& nif) + { + Controller::post(nif); + postRecordList(nif, mSequences); + mObjectPalette.post(nif); } void NiPoint3Interpolator::read(NIFStream* nif) @@ -502,4 +509,132 @@ namespace Nif data.post(nif); } + void NiBlendInterpolator::read(NIFStream* nif) + { + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112)) + mManagerControlled = nif->getChar() & 1; + size_t numInterps = 0; + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) + { + numInterps = nif->getUShort(); + mArrayGrowBy = nif->getUShort(); + } + else + { + numInterps = nif->getChar(); + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112)) + { + mWeightThreshold = nif->getFloat(); + if (!mManagerControlled) + { + mInterpCount = nif->getChar(); + mSingleIndex = nif->getChar(); + mHighPriority = nif->getChar(); + mNextHighPriority = nif->getChar(); + mSingleTime = nif->getFloat(); + mHighWeightsSum = nif->getFloat(); + mNextHighWeightsSum = nif->getFloat(); + mHighEaseSpinner = nif->getFloat(); + } + } + } + + if (!mManagerControlled) + { + mItems.resize(numInterps); + for (Item& item : mItems) + item.read(nif); + } + + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 111)) + { + mManagerControlled = nif->getBoolean(); + mWeightThreshold = nif->getFloat(); + mOnlyUseHighestWeight = nif->getBoolean(); + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) + { + mInterpCount = nif->getUShort(); + mSingleIndex = nif->getUShort(); + } + else + { + mInterpCount = nif->getChar(); + mSingleIndex = nif->getChar(); + } + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 108)) + { + mSingleInterpolator.read(nif); + mSingleTime = nif->getFloat(); + } + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) + { + mHighPriority = nif->getInt(); + mNextHighPriority = nif->getInt(); + } + else + { + mHighPriority = nif->getChar(); + mNextHighPriority = nif->getChar(); + } + } + } + + void NiBlendInterpolator::post(Reader& nif) + { + for (Item& item : mItems) + item.post(nif); + mSingleInterpolator.post(nif); + } + + void NiBlendInterpolator::Item::read(NIFStream* nif) + { + mInterpolator.read(nif); + mWeight = nif->getFloat(); + mNormalizedWeight = nif->getFloat(); + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) + mPriority = nif->getInt(); + else + mPriority = nif->getChar(); + mEaseSpinner = nif->getFloat(); + } + + void NiBlendInterpolator::Item::post(Reader& nif) + { + mInterpolator.post(nif); + } + + void NiBlendBoolInterpolator::read(NIFStream* nif) + { + NiBlendInterpolator::read(nif); + mValue = nif->getChar() != 0; + } + + void NiBlendFloatInterpolator::read(NIFStream* nif) + { + NiBlendInterpolator::read(nif); + mValue = nif->getFloat(); + } + + void NiBlendPoint3Interpolator::read(NIFStream* nif) + { + NiBlendInterpolator::read(nif); + mValue = nif->getVector3(); + } + + void NiBlendTransformInterpolator::read(NIFStream* nif) + { + NiBlendInterpolator::read(nif); + if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 109)) + { + mPosValue = nif->getVector3(); + mRotValue = nif->getQuaternion(); + mScaleValue = nif->getFloat(); + if (!nif->getBoolean()) + mPosValue = osg::Vec3f(); + if (!nif->getBoolean()) + mRotValue = osg::Quat(); + if (!nif->getBoolean()) + mScaleValue = 1.f; + } + } } diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index a5213a9be7..3f9c054906 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -34,6 +34,7 @@ namespace Nif std::string mTargetName; NiInterpolatorPtr mInterpolator; ControllerPtr mController; + NiBlendInterpolatorPtr mBlendInterpolator; unsigned short mBlendIndex; unsigned char mPriority; NiStringPalettePtr mStringPalette; @@ -295,7 +296,10 @@ namespace Nif struct NiControllerManager : public Controller { bool mCumulative; + NiControllerSequenceList mSequences; + NiDefaultAVObjectPalettePtr mObjectPalette; void read(NIFStream* nif) override; + void post(Reader& nif) override; }; struct NiInterpolator : public Record @@ -345,5 +349,62 @@ namespace Nif void post(Reader& nif) override; }; + // Abstract + struct NiBlendInterpolator : public NiInterpolator + { + struct Item + { + NiInterpolatorPtr mInterpolator; + float mWeight, mNormalizedWeight; + int mPriority; + float mEaseSpinner; + + void read(NIFStream* nif); + void post(Reader& nif); + }; + + bool mManagerControlled{ false }; + bool mOnlyUseHighestWeight{ false }; + unsigned short mArrayGrowBy{ 0 }; + float mWeightThreshold; + unsigned short mInterpCount; + unsigned short mSingleIndex; + int mHighPriority, mNextHighPriority; + float mSingleTime; + float mHighWeightsSum, mNextHighWeightsSum; + float mHighEaseSpinner; + std::vector mItems; + NiInterpolatorPtr mSingleInterpolator; + + void read(NIFStream* nif) override; + void post(Reader& nif) override; + }; + + struct NiBlendBoolInterpolator : public NiBlendInterpolator + { + char mValue; + void read(NIFStream* nif) override; + }; + + struct NiBlendFloatInterpolator : public NiBlendInterpolator + { + float mValue; + void read(NIFStream* nif) override; + }; + + struct NiBlendPoint3Interpolator : public NiBlendInterpolator + { + osg::Vec3f mValue; + void read(NIFStream* nif) override; + }; + + struct NiBlendTransformInterpolator : public NiBlendInterpolator + { + osg::Vec3f mPosValue; + osg::Quat mRotValue; + float mScaleValue; + void read(NIFStream* nif) override; + }; + } // Namespace #endif diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 2da28bb5d9..4debe760bc 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -175,6 +175,11 @@ namespace Nif { "NiSequence", &construct }, { "NiControllerSequence", &construct }, { "NiDefaultAVObjectPalette", &construct }, + { "NiBlendBoolInterpolator", &construct }, + { "NiBlendFloatInterpolator", &construct }, + { "NiBlendPoint3Interpolator", &construct }, + { "NiBlendTransformInterpolator", + &construct }, }; } diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 558066b8c6..bc2fa41409 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -152,6 +152,10 @@ namespace Nif RC_NiSequence, RC_NiControllerSequence, RC_NiDefaultAVObjectPalette, + RC_NiBlendBoolInterpolator, + RC_NiBlendFloatInterpolator, + RC_NiBlendPoint3Interpolator, + RC_NiBlendTransformInterpolator, }; /// Base class for all records diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index cb85763a22..5fa0d7d203 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -142,6 +142,9 @@ namespace Nif struct NiInterpolator; struct NiStringPalette; struct NiControllerManager; + struct NiBlendInterpolator; + struct NiDefaultAVObjectPalette; + struct NiControllerSequence; using NodePtr = RecordPtrT; using ExtraPtr = RecordPtrT; @@ -174,6 +177,8 @@ namespace Nif using NiInterpolatorPtr = RecordPtrT; using NiStringPalettePtr = RecordPtrT; using NiControllerManagerPtr = RecordPtrT; + using NiBlendInterpolatorPtr = RecordPtrT; + using NiDefaultAVObjectPalettePtr = RecordPtrT; using NodeList = RecordListT; using PropertyList = RecordListT; @@ -183,6 +188,7 @@ namespace Nif using NiTriStripsDataList = RecordListT; using bhkShapeList = RecordListT; using bhkSerializableList = RecordListT; + using NiControllerSequenceList = RecordListT; } // Namespace #endif