diff --git a/CHANGELOG.md b/CHANGELOG.md index 38cd1efca5..e4094f0ec2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -91,6 +91,7 @@ Bug #6451: Weapon summoned from Cast When Used item will have the name "None" Bug #6473: Strings from NIF should be parsed only to first null terminator Bug #6493: Unlocking owned but not locked or unlocked containers is considered a crime + Bug #6517: Rotations for KeyframeData in NIFs should be optional Feature #890: OpenMW-CS: Column filtering Feature #1465: "Reset" argument for AI functions Feature #2554: Modifying an object triggers the instances table to scroll to the corresponding record diff --git a/components/nif/data.cpp b/components/nif/data.cpp index cac924733d..1b6d302d68 100644 --- a/components/nif/data.cpp +++ b/components/nif/data.cpp @@ -428,7 +428,7 @@ void NiMorphData::read(NIFStream *nif) for(int i = 0;i < morphCount;i++) { mMorphs[i].mKeyFrames = std::make_shared(); - mMorphs[i].mKeyFrames->read(nif, true, /*morph*/true); + mMorphs[i].mKeyFrames->read(nif, /*morph*/true); nif->getVector3s(mMorphs[i].mVertices, vertCount); } } @@ -445,9 +445,9 @@ void NiKeyframeData::read(NIFStream *nif) mXRotations = std::make_shared(); mYRotations = std::make_shared(); mZRotations = std::make_shared(); - mXRotations->read(nif, true); - mYRotations->read(nif, true); - mZRotations->read(nif, true); + mXRotations->read(nif); + mYRotations->read(nif); + mZRotations->read(nif); } mTranslations = std::make_shared(); mTranslations->read(nif); diff --git a/components/nif/nifkey.hpp b/components/nif/nifkey.hpp index 91869ff849..f1b4f94d00 100644 --- a/components/nif/nifkey.hpp +++ b/components/nif/nifkey.hpp @@ -48,92 +48,71 @@ struct KeyMapT { using ValueType = T; using KeyType = KeyT; - unsigned int mInterpolationType = InterpolationType_Linear; + unsigned int mInterpolationType = InterpolationType_Unknown; MapType mKeys; //Read in a KeyGroup (see http://niftools.sourceforge.net/doc/nif/NiKeyframeData.html) - void read(NIFStream *nif, bool force = false, bool morph = false) + void read(NIFStream *nif, bool morph = false) { assert(nif); - mInterpolationType = InterpolationType_Unknown; - if (morph && nif->getVersion() >= NIFStream::generateVersion(10,1,0,106)) nif->getString(); // Frame name size_t count = nif->getUInt(); - if (count == 0 && !force && !morph) - return; + + if (count != 0 || morph) + mInterpolationType = nif->getUInt(); + + KeyType key = {}; + + if (mInterpolationType == InterpolationType_Linear || mInterpolationType == InterpolationType_Constant) + { + for (size_t i = 0;i < count;i++) + { + float time = nif->getFloat(); + readValue(*nif, key); + mKeys[time] = key; + } + } + else if (mInterpolationType == InterpolationType_Quadratic) + { + for (size_t i = 0;i < count;i++) + { + float time = nif->getFloat(); + readQuadratic(*nif, key); + mKeys[time] = key; + } + } + else if (mInterpolationType == InterpolationType_TBC) + { + for (size_t i = 0;i < count;i++) + { + float time = nif->getFloat(); + readTBC(*nif, key); + mKeys[time] = key; + } + } + else if (mInterpolationType == InterpolationType_XYZ) + { + //XYZ keys aren't actually read here. + //data.cpp sees that the last type read was InterpolationType_XYZ and: + // Eats a floating point number, then + // Re-runs the read function 3 more times. + // When it does that it's reading in a bunch of InterpolationType_Linear keys, not InterpolationType_XYZ. + } + else if (count != 0 || morph) + { + std::stringstream error; + error << "Unhandled interpolation type: " << mInterpolationType; + nif->file->fail(error.str()); + } if (morph && nif->getVersion() > NIFStream::generateVersion(10,1,0,0)) { if (nif->getVersion() >= NIFStream::generateVersion(10,1,0,104) && nif->getVersion() <= NIFStream::generateVersion(20,1,0,2) && nif->getBethVersion() < 10) nif->getFloat(); // Legacy weight - return; - } - - mKeys.clear(); - - mInterpolationType = nif->getUInt(); - - KeyType key = {}; - NIFStream &nifReference = *nif; - - if (mInterpolationType == InterpolationType_Linear - || mInterpolationType == InterpolationType_Constant) - { - for(size_t i = 0;i < count;i++) - { - float time = nif->getFloat(); - readValue(nifReference, key); - mKeys[time] = key; - } - } - else if (mInterpolationType == InterpolationType_Quadratic) - { - for(size_t i = 0;i < count;i++) - { - float time = nif->getFloat(); - readQuadratic(nifReference, key); - mKeys[time] = key; - } - } - else if (mInterpolationType == InterpolationType_TBC) - { - for(size_t i = 0;i < count;i++) - { - float time = nif->getFloat(); - readTBC(nifReference, key); - mKeys[time] = key; - } - } - //XYZ keys aren't actually read here. - //data.hpp sees that the last type read was InterpolationType_XYZ and: - // Eats a floating point number, then - // Re-runs the read function 3 more times. - // When it does that it's reading in a bunch of InterpolationType_Linear keys, not InterpolationType_XYZ. - else if(mInterpolationType == InterpolationType_XYZ) - { - //Don't try to read XYZ keys into the wrong part - if ( count != 1 ) - { - std::stringstream error; - error << "XYZ_ROTATION_KEY count should always be '1' . Retrieved Value: " - << count; - nif->file->fail(error.str()); - } - } - else if (mInterpolationType == InterpolationType_Unknown) - { - if (count != 0) - nif->file->fail("Interpolation type 0 doesn't work with keys"); - } - else - { - std::stringstream error; - error << "Unhandled interpolation type: " << mInterpolationType; - nif->file->fail(error.str()); } }