You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/components/nif/controller.cpp

797 lines
22 KiB
C++

#include "controller.hpp"
#include "data.hpp"
#include "exception.hpp"
#include "node.hpp"
#include "particle.hpp"
#include "texture.hpp"
namespace Nif
{
void NiTimeController::read(NIFStream* nif)
{
mNext.read(nif);
nif->read(mFlags);
nif->read(mFrequency);
nif->read(mPhase);
nif->read(mTimeStart);
nif->read(mTimeStop);
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
mTarget.read(nif);
}
void NiTimeController::post(Reader& nif)
{
mNext.post(nif);
mTarget.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);
nif->read(mBlendIndex);
}
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106) && nif->getBethVersion() > 0)
nif->read(mPriority);
if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0)
&& nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 0))
{
mStringPalette.read(nif);
nif->read(mNodeNameOffset);
nif->read(mPropertyTypeOffset);
nif->read(mControllerTypeOffset);
nif->read(mControllerIdOffset);
nif->read(mInterpolatorIdOffset);
}
else
{
nif->read(mNodeName);
nif->read(mPropertyType);
nif->read(mControllerType);
nif->read(mControllerId);
nif->read(mInterpolatorId);
}
}
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)
{
nif->read(mName);
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
{
nif->read(mAccumRootName);
mTextKeys.read(nif);
}
mControlledBlocks.resize(nif->get<uint32_t>());
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 106))
nif->read(mArrayGrowBy);
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;
nif->read(mWeight);
mTextKeys.read(nif);
mExtrapolationMode = static_cast<NiTimeController::ExtrapolationMode>(nif->get<uint32_t>());
nif->read(mFrequency);
if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1))
nif->read(mPhase);
nif->read(mStartTime);
nif->read(mStopTime);
if (nif->getVersion() == NIFStream::generateVersion(10, 1, 0, 106))
nif->read(mPlayBackwards);
mManager.read(nif);
nif->read(mAccumRootName);
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)
{
uint16_t numAnimNotes = 1;
if (nif->getBethVersion() >= 29)
nif->read(numAnimNotes);
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)
{
NiTimeController::read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104)
&& nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 108))
nif->read(mManagerControlled);
}
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 NiParticleInfo::read(NIFStream* nif)
{
nif->read(mVelocity);
if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1))
nif->read(mRotationAxis);
nif->read(mAge);
nif->read(mLifespan);
nif->read(mLastUpdate);
nif->read(mSpawnGeneration);
nif->read(mCode);
}
void NiParticleSystemController::read(NIFStream* nif)
{
NiTimeController::read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
nif->read(mSpeed);
nif->read(mSpeedVariation);
nif->read(mDeclination);
nif->read(mDeclinationVariation);
nif->read(mPlanarAngle);
nif->read(mPlanarAngleVariation);
nif->read(mInitialNormal);
nif->read(mInitialColor);
nif->read(mInitialSize);
nif->read(mEmitStartTime);
nif->read(mEmitStopTime);
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
{
mResetParticleSystem = nif->get<uint8_t>() != 0;
nif->read(mBirthRate);
}
nif->read(mLifetime);
nif->read(mLifetimeVariation);
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
nif->read(mEmitFlags);
nif->read(mEmitterDimensions);
mEmitter.read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
{
nif->read(mNumSpawnGenerations);
nif->read(mPercentageSpawned);
nif->read(mSpawnMultiplier);
nif->read(mSpawnSpeedChaos);
nif->read(mSpawnDirChaos);
mParticles.resize(nif->get<uint16_t>());
nif->read(mNumValid);
for (NiParticleInfo& particle : mParticles)
particle.read(nif);
nif->skip(4); // NiEmitterModifier link
}
mModifier.read(nif);
mCollider.read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 15))
nif->read(mStaticTargetBound);
}
void NiParticleSystemController::post(Reader& nif)
{
NiTimeController::post(nif);
mEmitter.post(nif);
mModifier.post(nif);
mCollider.post(nif);
}
void NiMaterialColorController::read(NIFStream* nif)
{
NiPoint3InterpController::read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
mTargetColor = static_cast<TargetColor>(nif->get<uint16_t>() & 3);
else
mTargetColor = static_cast<TargetColor>((mFlags >> 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)
{
NiTimeController::read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
nif->read(mLookAtFlags);
mLookAt.read(nif);
}
void NiLookAtController::post(Reader& nif)
{
NiTimeController::post(nif);
mLookAt.post(nif);
}
void NiPathController::read(NIFStream* nif)
{
NiTimeController::read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
nif->read(mPathFlags);
else
mPathFlags = (mFlags >> 4);
nif->read(mBankDirection);
nif->read(mMaxBankAngle);
nif->read(mSmoothing);
nif->read(mFollowAxis);
mPathData.read(nif);
mPercentData.read(nif);
}
void NiPathController::post(Reader& nif)
{
NiTimeController::post(nif);
mPathData.post(nif);
mPercentData.post(nif);
}
void NiUVController::read(NIFStream* nif)
{
NiTimeController::read(nif);
nif->read(mUvSet);
mData.read(nif);
}
void NiUVController::post(Reader& nif)
{
NiTimeController::post(nif);
mData.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<uint16_t>());
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->get<uint16_t>() & 1;
mData.read(nif);
if (nif->getVersion() < NIFFile::NIFVersion::VER_MW)
return;
mAlwaysActive = nif->get<uint8_t>() != 0;
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 105))
return;
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
{
readRecordList(nif, mInterpolators);
if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0) && nif->getBethVersion() >= 10)
nif->skip(4 * nif->get<uint32_t>()); // Unknown
return;
}
mInterpolators.resize(nif->get<uint32_t>());
mWeights.resize(mInterpolators.size());
for (size_t i = 0; i < mInterpolators.size(); i++)
{
mInterpolators[i].read(nif);
nif->read(mWeights[i]);
}
}
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 = static_cast<NiTexturingProperty::TextureType>(nif->get<uint32_t>());
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
{
nif->read(mTimeStart);
nif->read(mDelta);
}
readRecordList(nif, mSources);
}
void NiFlipController::post(Reader& nif)
{
NiFloatInterpController::post(nif);
postRecordList(nif, mSources);
}
void NiTextureTransformController::read(NIFStream* nif)
{
NiFloatInterpController::read(nif);
nif->read(mShaderMap);
mTexSlot = static_cast<NiTexturingProperty::TextureType>(nif->get<uint32_t>());
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 NiBoneLODController::read(NIFStream* nif)
{
NiTimeController::read(nif);
nif->read(mLOD);
mNodeGroups.resize(nif->get<uint32_t>());
nif->read(mNumNodeGroups);
for (NiAVObjectList& group : mNodeGroups)
readRecordList(nif, group);
if (nif->getBethVersion() != 0 || nif->getVersion() < NIFStream::generateVersion(4, 2, 2, 0))
return;
mSkinnedShapeGroups.resize(nif->get<uint32_t>());
for (std::vector<SkinInfo>& group : mSkinnedShapeGroups)
{
group.resize(nif->get<uint32_t>());
for (SkinInfo& info : group)
{
info.mShape.read(nif);
info.mSkin.read(nif);
}
}
readRecordList(nif, mShapeGroups);
}
void NiBoneLODController::post(Reader& nif)
{
NiTimeController::post(nif);
for (NiAVObjectList& group : mNodeGroups)
postRecordList(nif, group);
for (std::vector<SkinInfo>& group : mSkinnedShapeGroups)
{
for (SkinInfo& info : group)
{
info.mShape.post(nif);
info.mSkin.post(nif);
}
}
postRecordList(nif, mShapeGroups);
}
void bhkBlendController::read(NIFStream* nif)
{
NiTimeController::read(nif);
uint32_t numKeys;
nif->read(numKeys);
// Is this possible?
if (numKeys != 0)
throw Nif::Exception(
"Unsupported keys in bhkBlendController " + std::to_string(recIndex), nif->getFile().getFilename());
}
void BSEffectShaderPropertyFloatController::read(NIFStream* nif)
{
NiFloatInterpController::read(nif);
nif->read(mControlledVariable);
}
void BSEffectShaderPropertyColorController::read(NIFStream* nif)
{
NiPoint3InterpController::read(nif);
nif->read(mControlledColor);
}
void BSKeyframeController::read(NIFStream* nif)
{
NiKeyframeController::read(nif);
mData2.read(nif);
}
void BSKeyframeController::post(Reader& nif)
{
NiKeyframeController::post(nif);
mData2.post(nif);
}
void BSLagBoneController::read(NIFStream* nif)
{
NiTimeController::read(nif);
nif->read(mLinearVelocity);
nif->read(mLinearRotation);
nif->read(mMaximumDistance);
}
void BSProceduralLightningController::read(NIFStream* nif)
{
NiTimeController::read(nif);
mGenerationInterp.read(nif);
mMutationInterp.read(nif);
mSubdivisionInterp.read(nif);
mNumBranchesInterp.read(nif);
mNumBranchesVarInterp.read(nif);
mLengthInterp.read(nif);
mLengthVarInterp.read(nif);
mWidthInterp.read(nif);
mArcOffsetInterp.read(nif);
nif->read(mSubdivisions);
nif->read(mNumBranches);
nif->read(mNumBranchesVar);
nif->read(mLength);
nif->read(mLengthVar);
nif->read(mWidth);
nif->read(mChildWidthMult);
nif->read(mArcOffset);
nif->read(mFadeMainBolt);
nif->read(mFadeChildBolts);
nif->read(mAnimateArcOffset);
mShaderProperty.read(nif);
}
void BSProceduralLightningController::post(Reader& nif)
{
NiTimeController::post(nif);
mGenerationInterp.post(nif);
mMutationInterp.post(nif);
mSubdivisionInterp.post(nif);
mNumBranchesInterp.post(nif);
mNumBranchesVarInterp.post(nif);
mLengthInterp.post(nif);
mLengthVarInterp.post(nif);
mWidthInterp.post(nif);
mArcOffsetInterp.post(nif);
mShaderProperty.post(nif);
}
void NiControllerManager::read(NIFStream* nif)
{
NiTimeController::read(nif);
nif->read(mCumulative);
readRecordList(nif, mSequences);
mObjectPalette.read(nif);
}
void NiControllerManager::post(Reader& nif)
{
NiTimeController::post(nif);
postRecordList(nif, mSequences);
mObjectPalette.post(nif);
}
void NiExtraDataController::read(NIFStream* nif)
{
NiSingleInterpController::read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10, 2, 0, 0))
nif->read(mExtraDataName);
}
void NiFloatExtraDataController::read(NIFStream* nif)
{
NiExtraDataController::read(nif);
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 104))
return;
// Unknown
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 0))
{
uint8_t numExtraBytes;
nif->read(numExtraBytes);
nif->skip(7);
nif->skip(numExtraBytes);
}
mData.read(nif);
}
void NiFloatExtraDataController::post(Reader& nif)
{
NiExtraDataController::post(nif);
mData.post(nif);
}
void NiFloatsExtraDataController::read(NIFStream* nif)
{
NiExtraDataController::read(nif);
nif->read(mFloatsExtraDataIndex);
if (nif->getVersion() <= NIFStream::generateVersion(10, 1, 0, 103))
mData.read(nif);
}
void NiFloatsExtraDataController::post(Reader& nif)
{
NiExtraDataController::post(nif);
mData.post(nif);
}
void NiFloatsExtraDataPoint3Controller::read(NIFStream* nif)
{
NiExtraDataController::read(nif);
nif->read(mFloatsExtraDataIndex);
}
void NiPathInterpolator::read(NIFStream* nif)
{
nif->read(mFlags);
nif->read(mBankDirection);
nif->read(mMaxBankAngle);
nif->read(mSmoothing);
nif->read(mFollowAxis);
mPathData.read(nif);
mPercentData.read(nif);
}
void NiPathInterpolator::post(Reader& nif)
{
mPathData.post(nif);
mPercentData.post(nif);
}
void NiLookAtInterpolator::read(NIFStream* nif)
{
nif->read(mLookAtFlags);
mLookAt.read(nif);
nif->read(mLookAtName);
if (nif->getVersion() <= NIFStream::generateVersion(20, 4, 0, 12))
nif->read(mTransform);
mTranslation.read(nif);
mRoll.read(nif);
mScale.read(nif);
}
void NiLookAtInterpolator::post(Reader& nif)
{
mLookAt.post(nif);
mTranslation.post(nif);
mRoll.post(nif);
mScale.post(nif);
}
void NiBlendInterpolator::read(NIFStream* nif)
{
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 112))
{
nif->read(mFlags);
mItems.resize(nif->get<uint8_t>());
nif->read(mWeightThreshold);
if (!(mFlags & Flag_ManagerControlled))
{
mInterpCount = nif->get<uint8_t>();
mSingleIndex = nif->get<uint8_t>();
mHighPriority = nif->get<int8_t>();
mNextHighPriority = nif->get<int8_t>();
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<uint8_t>());
for (Item& item : mItems)
item.read(nif);
if (nif->get<bool>())
mFlags |= Flag_ManagerControlled;
nif->read(mWeightThreshold);
if (nif->get<bool>())
mFlags |= Flag_OnlyUseHighestWeight;
mInterpCount = nif->get<uint8_t>();
mSingleIndex = nif->get<uint8_t>();
mSingleInterpolator.read(nif);
nif->read(mSingleTime);
mHighPriority = nif->get<int8_t>();
mNextHighPriority = nif->get<int8_t>();
return;
}
mItems.resize(nif->get<uint16_t>());
nif->read(mArrayGrowBy);
for (Item& item : mItems)
item.read(nif);
if (nif->get<bool>())
mFlags |= Flag_ManagerControlled;
nif->read(mWeightThreshold);
if (nif->get<bool>())
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<int8_t>();
else
nif->read(mPriority);
nif->read(mEaseSpinner);
}
void NiBlendInterpolator::Item::post(Reader& nif)
{
mInterpolator.post(nif);
}
}