#include "controller.hpp" #include "data.hpp" #include "node.hpp" #include "particle.hpp" #include "texture.hpp" namespace Nif { void Controller::read(NIFStream* nif) { next.read(nif); flags = nif->getUShort(); frequency = nif->getFloat(); phase = nif->getFloat(); timeStart = nif->getFloat(); timeStop = nif->getFloat(); target.read(nif); } void Controller::post(Reader& nif) { Record::post(nif); next.post(nif); target.post(nif); } void ControlledBlock::read(NIFStream* nif) { if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mTargetName = nif->getSizedString(); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106)) mInterpolator.read(nif); if (nif->getVersion() <= NIFStream::generateVersion(20, 5, 0, 0)) mController.read(nif); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) return; if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 110)) { mBlendInterpolator.read(nif); mBlendIndex = nif->getUShort(); } if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106) && nif->getBethVersion() > 0) mPriority = nif->getChar(); if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 0)) { mStringPalette.read(nif); mNodeNameOffset = nif->getUInt(); mPropertyTypeOffset = nif->getUInt(); mControllerTypeOffset = nif->getUInt(); mControllerIdOffset = nif->getUInt(); mInterpolatorIdOffset = nif->getUInt(); } else { mNodeName = nif->getString(); mPropertyType = nif->getString(); mControllerType = nif->getString(); mControllerId = nif->getString(); mInterpolatorId = nif->getString(); } } void ControlledBlock::post(Reader& nif) { mInterpolator.post(nif); mController.post(nif); mBlendInterpolator.post(nif); mStringPalette.post(nif); // TODO: probably should fill the strings with string palette contents here } void NiSequence::read(NIFStream* nif) { mName = nif->getString(); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) { mAccumRootName = nif->getString(); mTextKeys.read(nif); } size_t numControlledBlocks = nif->getUInt(); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106)) mArrayGrowBy = nif->getUInt(); mControlledBlocks.resize(numControlledBlocks); for (ControlledBlock& block : mControlledBlocks) block.read(nif); } void NiSequence::post(Reader& nif) { mTextKeys.post(nif); for (ControlledBlock& block : mControlledBlocks) block.post(nif); } void NiControllerSequence::read(NIFStream* nif) { NiSequence::read(nif); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) return; mWeight = nif->getFloat(); mTextKeys.read(nif); mExtrapolationMode = static_cast(nif->getUInt()); mFrequency = nif->getFloat(); if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1)) mPhase = nif->getFloat(); mStartTime = nif->getFloat(); mStopTime = nif->getFloat(); mPlayBackwards = nif->getVersion() == NIFStream::generateVersion(10, 1, 0, 106) && nif->getBoolean(); mManager.read(nif); mAccumRootName = nif->getString(); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 113) && nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 0)) mStringPalette.read(nif); else if (nif->getVersion() >= NIFFile::NIFVersion::VER_BGS && nif->getBethVersion() >= 24) { size_t numAnimNotes = 1; if (nif->getBethVersion() >= 29) numAnimNotes = nif->getUShort(); nif->skip(4 * numAnimNotes); // BSAnimNotes links } } void NiControllerSequence::post(Reader& nif) { NiSequence::post(nif); mManager.post(nif); mStringPalette.post(nif); } void NiInterpController::read(NIFStream* nif) { Controller::read(nif); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104) && nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 108)) mManagerControlled = nif->getBoolean(); } void NiSingleInterpController::read(NIFStream* nif) { NiInterpController::read(nif); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104)) mInterpolator.read(nif); } void NiSingleInterpController::post(Reader& nif) { NiInterpController::post(nif); mInterpolator.post(nif); } void NiParticleSystemController::read(NIFStream* nif) { Controller::read(nif); velocity = nif->getFloat(); velocityRandom = nif->getFloat(); verticalDir = nif->getFloat(); verticalAngle = nif->getFloat(); horizontalDir = nif->getFloat(); horizontalAngle = nif->getFloat(); /*normal?*/ nif->getVector3(); color = nif->getVector4(); size = nif->getFloat(); startTime = nif->getFloat(); stopTime = nif->getFloat(); nif->getChar(); emitRate = nif->getFloat(); lifetime = nif->getFloat(); lifetimeRandom = nif->getFloat(); emitFlags = nif->getUShort(); offsetRandom = nif->getVector3(); emitter.read(nif); /* Unknown Short, 0? * Unknown Float, 1.0? * Unknown Int, 1? * Unknown Int, 0? * Unknown Short, 0? */ nif->skip(16); numParticles = nif->getUShort(); activeCount = nif->getUShort(); particles.resize(numParticles); for (size_t i = 0; i < particles.size(); i++) { particles[i].velocity = nif->getVector3(); nif->getVector3(); /* unknown */ particles[i].lifetime = nif->getFloat(); particles[i].lifespan = nif->getFloat(); particles[i].timestamp = nif->getFloat(); nif->getUShort(); /* unknown */ particles[i].vertex = nif->getUShort(); } nif->getUInt(); /* -1? */ affectors.read(nif); colliders.read(nif); nif->getChar(); } void NiParticleSystemController::post(Reader& nif) { Controller::post(nif); emitter.post(nif); affectors.post(nif); colliders.post(nif); } void NiMaterialColorController::read(NIFStream* nif) { NiPoint3InterpController::read(nif); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) mTargetColor = static_cast(nif->get() & 3); else mTargetColor = static_cast((flags >> 4) & 3); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } void NiMaterialColorController::post(Reader& nif) { NiPoint3InterpController::post(nif); mData.post(nif); } void NiLookAtController::read(NIFStream* nif) { Controller::read(nif); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) lookAtFlags = nif->getUShort(); target.read(nif); } void NiLookAtController::post(Reader& nif) { Controller::post(nif); target.post(nif); } void NiPathController::read(NIFStream* nif) { Controller::read(nif); bankDir = nif->getInt(); maxBankAngle = nif->getFloat(); smoothing = nif->getFloat(); nif->read(followAxis); posData.read(nif); floatData.read(nif); } void NiPathController::post(Reader& nif) { Controller::post(nif); posData.post(nif); floatData.post(nif); } void NiUVController::read(NIFStream* nif) { Controller::read(nif); uvSet = nif->getUShort(); data.read(nif); } void NiUVController::post(Reader& nif) { Controller::post(nif); data.post(nif); } void NiKeyframeController::read(NIFStream* nif) { NiSingleInterpController::read(nif); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } void NiKeyframeController::post(Reader& nif) { NiSingleInterpController::post(nif); mData.post(nif); } void NiMultiTargetTransformController::read(NIFStream* nif) { NiInterpController::read(nif); mExtraTargets.resize(nif->get()); for (NiAVObjectPtr& extraTarget : mExtraTargets) extraTarget.read(nif); } void NiMultiTargetTransformController::post(Reader& nif) { NiInterpController::post(nif); postRecordList(nif, mExtraTargets); } void NiAlphaController::read(NIFStream* nif) { NiFloatInterpController::read(nif); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } void NiAlphaController::post(Reader& nif) { NiFloatInterpController::post(nif); mData.post(nif); } void NiRollController::read(NIFStream* nif) { NiSingleInterpController::read(nif); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } void NiRollController::post(Reader& nif) { NiSingleInterpController::post(nif); mData.post(nif); } void NiGeomMorpherController::read(NIFStream* nif) { NiInterpController::read(nif); if (nif->getVersion() >= NIFFile::NIFVersion::VER_OB_OLD) mUpdateNormals = nif->getUShort() & 1; mData.read(nif); if (nif->getVersion() >= NIFFile::NIFVersion::VER_MW) { mAlwaysActive = nif->getChar(); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106)) { if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) { readRecordList(nif, mInterpolators); if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getBethVersion() > 9) { unsigned int numUnknown = nif->getUInt(); nif->skip(4 * numUnknown); } } else { std::vector interpolators; size_t numInterps = nif->getUInt(); interpolators.resize(numInterps); mWeights.resize(numInterps); for (size_t i = 0; i < numInterps; i++) { interpolators[i].read(nif); mWeights[i] = nif->getFloat(); } mInterpolators = interpolators; } } } } void NiGeomMorpherController::post(Reader& nif) { NiInterpController::post(nif); mData.post(nif); postRecordList(nif, mInterpolators); } void NiVisController::read(NIFStream* nif) { NiBoolInterpController::read(nif); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } void NiVisController::post(Reader& nif) { NiBoolInterpController::post(nif); mData.post(nif); } void NiFlipController::read(NIFStream* nif) { NiFloatInterpController::read(nif); mTexSlot = nif->getUInt(); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) { timeStart = nif->getFloat(); mDelta = nif->getFloat(); } readRecordList(nif, mSources); } void NiFlipController::post(Reader& nif) { NiFloatInterpController::post(nif); postRecordList(nif, mSources); } void NiTextureTransformController::read(NIFStream* nif) { NiFloatInterpController::read(nif); mShaderMap = nif->getBoolean(); nif->read(mTexSlot); nif->read(mTransformMember); if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103)) mData.read(nif); } void NiTextureTransformController::post(Reader& nif) { NiFloatInterpController::post(nif); mData.post(nif); } void bhkBlendController::read(NIFStream* nif) { Controller::read(nif); nif->getUInt(); // Zero } void BSEffectShaderPropertyFloatController::read(NIFStream* nif) { NiFloatInterpController::read(nif); nif->read(mControlledVariable); } void BSEffectShaderPropertyColorController::read(NIFStream* nif) { NiPoint3InterpController::read(nif); nif->read(mControlledColor); } void NiControllerManager::read(NIFStream* nif) { Controller::read(nif); mCumulative = nif->getBoolean(); 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) { defaultVal = nif->getVector3(); data.read(nif); } void NiPoint3Interpolator::post(Reader& nif) { data.post(nif); } void NiBoolInterpolator::read(NIFStream* nif) { defaultVal = nif->getBoolean(); data.read(nif); } void NiBoolInterpolator::post(Reader& nif) { data.post(nif); } void NiFloatInterpolator::read(NIFStream* nif) { defaultVal = nif->getFloat(); data.read(nif); } void NiFloatInterpolator::post(Reader& nif) { data.post(nif); } void NiTransformInterpolator::read(NIFStream* nif) { nif->read(mDefaultTransform); mData.read(nif); } void NiTransformInterpolator::post(Reader& nif) { mData.post(nif); } void NiColorInterpolator::read(NIFStream* nif) { defaultVal = nif->getVector4(); data.read(nif); } void NiColorInterpolator::post(Reader& nif) { data.post(nif); } void NiBlendInterpolator::read(NIFStream* nif) { if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112)) { nif->read(mFlags); mItems.resize(nif->get()); nif->read(mWeightThreshold); if (!(mFlags & Flag_ManagerControlled)) { mInterpCount = nif->get(); mSingleIndex = nif->get(); mHighPriority = nif->get(); mNextHighPriority = nif->get(); nif->read(mSingleTime); nif->read(mHighWeightsSum); nif->read(mNextHighWeightsSum); nif->read(mHighEaseSpinner); for (Item& item : mItems) item.read(nif); } return; } if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 110)) { mItems.resize(nif->get()); for (Item& item : mItems) item.read(nif); if (nif->get()) mFlags |= Flag_ManagerControlled; nif->read(mWeightThreshold); if (nif->get()) mFlags |= Flag_OnlyUseHighestWeight; mInterpCount = nif->get(); mSingleIndex = nif->get(); mSingleInterpolator.read(nif); nif->read(mSingleTime); mHighPriority = nif->get(); mNextHighPriority = nif->get(); return; } mItems.resize(nif->get()); nif->read(mArrayGrowBy); for (Item& item : mItems) item.read(nif); if (nif->get()) mFlags |= Flag_ManagerControlled; nif->read(mWeightThreshold); if (nif->get()) mFlags |= Flag_OnlyUseHighestWeight; nif->read(mInterpCount); nif->read(mSingleIndex); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 108)) { mSingleInterpolator.read(nif); nif->read(mSingleTime); } nif->read(mHighPriority); nif->read(mNextHighPriority); } void NiBlendInterpolator::post(Reader& nif) { for (Item& item : mItems) item.post(nif); mSingleInterpolator.post(nif); } void NiBlendInterpolator::Item::read(NIFStream* nif) { mInterpolator.read(nif); nif->read(mWeight); nif->read(mNormalizedWeight); if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 110)) mPriority = nif->get(); else nif->read(mPriority); nif->read(mEaseSpinner); } void NiBlendInterpolator::Item::post(Reader& nif) { mInterpolator.post(nif); } }