Separate NIFFileReader from NIFFile

NIFFile might not always be created from a file or stream containing NIF data.
Basically there are 2 different responsibilities for this class:
1. Read NIF file
2. Provide input for nifosg and bulletnifloader.

Remove no longer needed NIFFileMock since the state of NIFFfile can be
initialized independently from reading NIF file.
coverity_clang_test
elsid 2 years ago
parent b39ccbeeef
commit f2fb3d6de8
No known key found for this signature in database
GPG Key ID: 4DE04C198CBA7625

@ -50,7 +50,9 @@ void readVFS(std::unique_ptr<VFS::Archive>&& anArchive, const std::filesystem::p
if (isNIF(name)) if (isNIF(name))
{ {
// std::cout << "Decoding: " << name << std::endl; // std::cout << "Decoding: " << name << std::endl;
Nif::NIFFile temp_nif(myManager.get(name), archivePath / name); Nif::NIFFile file(archivePath / name);
Nif::Reader reader(file);
reader.parse(myManager.get(name));
} }
else if (isBSA(name)) else if (isBSA(name))
{ {
@ -120,7 +122,7 @@ int main(int argc, char** argv)
if (!parseOptions(argc, argv, files)) if (!parseOptions(argc, argv, files))
return 1; return 1;
Nif::NIFFile::setLoadUnsupportedFiles(true); Nif::Reader::setLoadUnsupportedFiles(true);
// std::cout << "Reading Files" << std::endl; // std::cout << "Reading Files" << std::endl;
for (const auto& path : files) for (const auto& path : files)
{ {
@ -129,7 +131,9 @@ int main(int argc, char** argv)
if (isNIF(path)) if (isNIF(path))
{ {
// std::cout << "Decoding: " << name << std::endl; // std::cout << "Decoding: " << name << std::endl;
Nif::NIFFile temp_nif(Files::openConstrainedFileStream(path), path); Nif::NIFFile file(path);
Nif::Reader reader(file);
reader.parse(Files::openConstrainedFileStream(path));
} }
else if (isBSA(path)) else if (isBSA(path))
{ {

@ -616,7 +616,7 @@ namespace MWRender
MWBase::Environment::get().getWindowManager()->setCullMask(mask); MWBase::Environment::get().getWindowManager()->setCullMask(mask);
NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor); NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor);
NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect); NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect);
Nif::NIFFile::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models")); Nif::Reader::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models"));
mStateUpdater->setFogEnd(mViewDistance); mStateUpdater->setFogEnd(mViewDistance);

@ -333,31 +333,9 @@ namespace
dst.rotation.mValues[column][row] = src.getBasis().getRow(row)[column]; dst.rotation.mValues[column][row] = src.getBasis().getRow(row)[column];
} }
struct NifFileMock : Nif::File
{
MOCK_METHOD(Nif::Record*, getRecord, (std::size_t), (const, override));
MOCK_METHOD(std::size_t, numRecords, (), (const, override));
MOCK_METHOD(Nif::Record*, getRoot, (std::size_t), (const, override));
MOCK_METHOD(std::size_t, numRoots, (), (const, override));
MOCK_METHOD(std::string, getString, (uint32_t), (const, override));
MOCK_METHOD(void, setUseSkinning, (bool), (override));
MOCK_METHOD(bool, getUseSkinning, (), (const, override));
MOCK_METHOD(std::filesystem::path, getFilename, (), (const, override));
MOCK_METHOD(std::string, getHash, (), (const, override));
MOCK_METHOD(unsigned int, getVersion, (), (const, override));
MOCK_METHOD(unsigned int, getUserVersion, (), (const, override));
MOCK_METHOD(unsigned int, getBethVersion, (), (const, override));
};
struct RecordMock : Nif::Record
{
MOCK_METHOD(void, read, (Nif::NIFStream * nif), (override));
};
struct TestBulletNifLoader : Test struct TestBulletNifLoader : Test
{ {
BulletNifLoader mLoader; BulletNifLoader mLoader;
const StrictMock<const NifFileMock> mNifFile;
Nif::Node mNode; Nif::Node mNode;
Nif::Node mNode2; Nif::Node mNode2;
Nif::NiNode mNiNode; Nif::NiNode mNiNode;
@ -412,16 +390,15 @@ namespace
= { osg::Vec3f(0, 0, 0), osg::Vec3f(1, 0, 0), osg::Vec3f(1, 1, 0), osg::Vec3f(0, 1, 0) }; = { osg::Vec3f(0, 0, 0), osg::Vec3f(1, 0, 0), osg::Vec3f(1, 1, 0), osg::Vec3f(0, 1, 0) };
mNiTriStripsData.strips = { { 0, 1, 2, 3 } }; mNiTriStripsData.strips = { { 0, 1, 2, 3 } };
mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriStripsData); mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriStripsData);
EXPECT_CALL(mNifFile, getHash()).WillOnce(Return(mHash));
} }
}; };
TEST_F(TestBulletNifLoader, for_zero_num_roots_should_return_default) TEST_F(TestBulletNifLoader, for_zero_num_roots_should_return_default)
{ {
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(0)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
@ -432,10 +409,11 @@ namespace
TEST_F(TestBulletNifLoader, should_ignore_nullptr_root) TEST_F(TestBulletNifLoader, should_ignore_nullptr_root)
{ {
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(nullptr)); file.mRoots.push_back(nullptr);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
@ -444,10 +422,11 @@ namespace
TEST_F(TestBulletNifLoader, for_default_root_nif_node_should_return_default) TEST_F(TestBulletNifLoader, for_default_root_nif_node_should_return_default)
{ {
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode)); file.mRoots.push_back(&mNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
@ -458,10 +437,11 @@ namespace
{ {
mNode.recType = Nif::RC_RootCollisionNode; mNode.recType = Nif::RC_RootCollisionNode;
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode)); file.mRoots.push_back(&mNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
@ -470,10 +450,11 @@ namespace
TEST_F(TestBulletNifLoader, for_default_root_nif_node_and_filename_starting_with_x_should_return_default) TEST_F(TestBulletNifLoader, for_default_root_nif_node_and_filename_starting_with_x_should_return_default)
{ {
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("xtest.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode)); file.mRoots.push_back(&mNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
@ -489,10 +470,11 @@ namespace
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode)); file.mRoots.push_back(&mNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3); expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
@ -515,10 +497,11 @@ namespace
mNode.parents.push_back(&mNiNode); mNode.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3); expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
@ -547,10 +530,11 @@ namespace
mNiNode.bounds.box.center = osg::Vec3f(-4, -5, -6); mNiNode.bounds.box.center = osg::Vec3f(-4, -5, -6);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3); expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
@ -585,10 +569,11 @@ namespace
mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9); mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3); expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
@ -623,10 +608,11 @@ namespace
mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9); mNiNode.bounds.box.center = osg::Vec3f(-7, -8, -9);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNode), Nif::NodePtr(&mNode2) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
expected.mCollisionBox.mExtents = osg::Vec3f(4, 5, 6); expected.mCollisionBox.mExtents = osg::Vec3f(4, 5, 6);
@ -647,10 +633,11 @@ namespace
mNode.bounds.box.extents = osg::Vec3f(1, 2, 3); mNode.bounds.box.extents = osg::Vec3f(1, 2, 3);
mNode.bounds.box.center = osg::Vec3f(-1, -2, -3); mNode.bounds.box.center = osg::Vec3f(-1, -2, -3);
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNode)); file.mRoots.push_back(&mNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3); expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
@ -661,10 +648,11 @@ namespace
TEST_F(TestBulletNifLoader, for_tri_shape_root_node_should_return_shape_with_triangle_mesh_shape) TEST_F(TestBulletNifLoader, for_tri_shape_root_node_should_return_shape_with_triangle_mesh_shape)
{ {
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape)); file.mRoots.push_back(&mNiTriShape);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -682,10 +670,11 @@ namespace
mNiTriShape.bounds.box.extents = osg::Vec3f(1, 2, 3); mNiTriShape.bounds.box.extents = osg::Vec3f(1, 2, 3);
mNiTriShape.bounds.box.center = osg::Vec3f(-1, -2, -3); mNiTriShape.bounds.box.center = osg::Vec3f(-1, -2, -3);
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape)); file.mRoots.push_back(&mNiTriShape);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3); expected.mCollisionBox.mExtents = osg::Vec3f(1, 2, 3);
@ -699,10 +688,11 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -719,10 +709,11 @@ namespace
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
mNiTriShape.parents.push_back(&mNiNode2); mNiTriShape.parents.push_back(&mNiNode2);
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -739,10 +730,11 @@ namespace
mNiNode.children mNiNode.children
= Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape), Nif::NodePtr(&mNiTriShape2) })); = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape), Nif::NodePtr(&mNiTriShape2) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 1), btVector3(1, 0, 1), btVector3(1, 1, 1)); triangles->addTriangle(btVector3(0, 0, 1), btVector3(1, 0, 1), btVector3(1, 1, 1));
@ -760,10 +752,11 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("xtest.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -779,10 +772,11 @@ namespace
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.trafo);
mNiTriShape.trafo.scale = 3; mNiTriShape.trafo.scale = 3;
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("xtest.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape)); file.mRoots.push_back(&mNiTriShape);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -806,10 +800,11 @@ namespace
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
mNiNode.trafo.scale = 4; mNiNode.trafo.scale = 4;
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("xtest.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -840,10 +835,11 @@ namespace
Nif::NodePtr(&mNiTriShape2), Nif::NodePtr(&mNiTriShape2),
})); }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("xtest.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -876,10 +872,11 @@ namespace
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
mNiNode.trafo.scale = 4; mNiNode.trafo.scale = 4;
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -912,10 +909,11 @@ namespace
})); }));
mNiNode.trafo.scale = 4; mNiNode.trafo.scale = 4;
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle( triangles->addTriangle(
@ -943,11 +941,12 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2)); Nif::NIFFile file("xtest.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getRoot(1)).WillOnce(Return(&mNiTriShape2)); file.mRoots.push_back(&mNiTriShape2);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -974,10 +973,11 @@ namespace
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
mNiNode.recType = Nif::RC_AvoidNode; mNiNode.recType = Nif::RC_AvoidNode;
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -993,10 +993,11 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
@ -1011,10 +1012,11 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
@ -1030,10 +1032,11 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -1054,10 +1057,11 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -1077,10 +1081,11 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -1101,10 +1106,11 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -1131,10 +1137,11 @@ namespace
mNiNode.children = Nif::NodeList( mNiNode.children = Nif::NodeList(
std::vector<Nif::NodePtr>({ Nif::NodePtr(&niTriShape), Nif::NodePtr(&emptyCollisionNode) })); std::vector<Nif::NodePtr>({ Nif::NodePtr(&niTriShape), Nif::NodePtr(&emptyCollisionNode) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -1154,10 +1161,11 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
Resource::BulletShape expected; Resource::BulletShape expected;
@ -1177,10 +1185,11 @@ namespace
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiNode2) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiNode2) }));
mNiNode.recType = Nif::RC_NiNode; mNiNode.recType = Nif::RC_NiNode;
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -1194,10 +1203,11 @@ namespace
{ {
mNiTriShape.data = Nif::NiGeometryDataPtr(&mNiTriStripsData); mNiTriShape.data = Nif::NiGeometryDataPtr(&mNiTriStripsData);
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape)); file.mRoots.push_back(&mNiTriShape);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
const Resource::BulletShape expected; const Resource::BulletShape expected;
@ -1206,10 +1216,11 @@ namespace
TEST_F(TestBulletNifLoader, for_tri_strips_root_node_should_return_shape_with_triangle_mesh_shape) TEST_F(TestBulletNifLoader, for_tri_strips_root_node_should_return_shape_with_triangle_mesh_shape)
{ {
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips)); file.mRoots.push_back(&mNiTriStrips);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -1224,10 +1235,11 @@ namespace
{ {
mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriShapeData); mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriShapeData);
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips)); file.mRoots.push_back(&mNiTriStrips);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
const Resource::BulletShape expected; const Resource::BulletShape expected;
@ -1238,10 +1250,11 @@ namespace
{ {
mNiTriStripsData.strips.clear(); mNiTriStripsData.strips.clear();
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips)); file.mRoots.push_back(&mNiTriStrips);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
const Resource::BulletShape expected; const Resource::BulletShape expected;
@ -1252,10 +1265,11 @@ namespace
{ {
mNiTriStripsData.strips.front() = { 0, 1 }; mNiTriStripsData.strips.front() = { 0, 1 };
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips)); file.mRoots.push_back(&mNiTriStrips);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
const Resource::BulletShape expected; const Resource::BulletShape expected;
@ -1269,10 +1283,11 @@ namespace
mNiNode.recType = Nif::RC_AvoidNode; mNiNode.recType = Nif::RC_AvoidNode;
mNiTriStripsData.strips.front() = { 0, 1 }; mNiTriStripsData.strips.front() = { 0, 1 };
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("test.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips)); file.mRoots.push_back(&mNiTriStrips);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
const Resource::BulletShape expected; const Resource::BulletShape expected;
@ -1285,10 +1300,11 @@ namespace
mNiTriStrips.parents.push_back(&mNiNode); mNiTriStrips.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriStrips) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriStrips) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1)); Nif::NIFFile file("xtest.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
const Resource::BulletShape expected; const Resource::BulletShape expected;
@ -1301,11 +1317,12 @@ namespace
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2)); Nif::NIFFile file("xtest.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getRoot(1)).WillOnce(Return(&mNiTriStrips)); file.mRoots.push_back(&mNiTriStrips);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
@ -1330,11 +1347,12 @@ namespace
mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode2.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
mNiNode2.trafo.scale = 3; mNiNode2.trafo.scale = 3;
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2)); Nif::NIFFile file("xtest.nif");
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode)); file.mRoots.push_back(&mNiNode);
EXPECT_CALL(mNifFile, getRoot(1)).WillOnce(Return(&mNiNode2)); file.mRoots.push_back(&mNiNode2);
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); file.mHash = mHash;
const auto result = mLoader.load(mNifFile);
const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles1(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles1(new btTriangleMesh(false));
triangles1->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); triangles1->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));

@ -23,7 +23,7 @@ namespace Nif
controller.read(nif); controller.read(nif);
} }
void Named::post(NIFFile* nif) void Named::post(Reader& nif)
{ {
extra.post(nif); extra.post(nif);
extralist.post(nif); extralist.post(nif);

@ -18,7 +18,7 @@ namespace Nif
unsigned int recordSize{ 0u }; unsigned int recordSize{ 0u };
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override { next.post(nif); } void post(Reader& nif) override { next.post(nif); }
}; };
struct Controller : public Record struct Controller : public Record
@ -43,7 +43,7 @@ namespace Nif
NamedPtr target; NamedPtr target;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
bool isActive() const { return flags & Flag_Active; } bool isActive() const { return flags & Flag_Active; }
ExtrapolationMode extrapolationMode() const { return static_cast<ExtrapolationMode>(flags & Mask); } ExtrapolationMode extrapolationMode() const { return static_cast<ExtrapolationMode>(flags & Mask); }
@ -58,7 +58,7 @@ namespace Nif
ControllerPtr controller; ControllerPtr controller;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
using NiSequenceStreamHelper = Named; using NiSequenceStreamHelper = Named;

@ -42,7 +42,7 @@ namespace Nif
/* bool mPersistRenderData = */ nif->getBoolean(); /* bool mPersistRenderData = */ nif->getBoolean();
} }
void NiSourceTexture::post(NIFFile* nif) void NiSourceTexture::post(Reader& nif)
{ {
Named::post(nif); Named::post(nif);
data.post(nif); data.post(nif);
@ -59,7 +59,7 @@ namespace Nif
controller.read(nif); controller.read(nif);
} }
void NiParticleModifier::post(NIFFile* nif) void NiParticleModifier::post(Reader& nif)
{ {
next.post(nif); next.post(nif);
controller.post(nif); controller.post(nif);
@ -78,7 +78,7 @@ namespace Nif
data.read(nif); data.read(nif);
} }
void NiParticleColorModifier::post(NIFFile* nif) void NiParticleColorModifier::post(Reader& nif)
{ {
NiParticleModifier::post(nif); NiParticleModifier::post(nif);
data.post(nif); data.post(nif);

@ -62,7 +62,7 @@ namespace Nif
unsigned int alpha; unsigned int alpha;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct BSShaderTextureSet : public Record struct BSShaderTextureSet : public Record
@ -89,7 +89,7 @@ namespace Nif
ControllerPtr controller; ControllerPtr controller;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiParticleGrowFade : public NiParticleModifier struct NiParticleGrowFade : public NiParticleModifier
@ -105,7 +105,7 @@ namespace Nif
NiColorDataPtr data; NiColorDataPtr data;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiGravity : public NiParticleModifier struct NiGravity : public NiParticleModifier

@ -22,7 +22,7 @@ namespace Nif
target.read(nif); target.read(nif);
} }
void Controller::post(NIFFile* nif) void Controller::post(Reader& nif)
{ {
Record::post(nif); Record::post(nif);
next.post(nif); next.post(nif);
@ -44,7 +44,7 @@ namespace Nif
mInterpolator.read(nif); mInterpolator.read(nif);
} }
void NiSingleInterpController::post(NIFFile* nif) void NiSingleInterpController::post(Reader& nif)
{ {
NiInterpController::post(nif); NiInterpController::post(nif);
mInterpolator.post(nif); mInterpolator.post(nif);
@ -104,7 +104,7 @@ namespace Nif
nif->getChar(); nif->getChar();
} }
void NiParticleSystemController::post(NIFFile* nif) void NiParticleSystemController::post(Reader& nif)
{ {
Controller::post(nif); Controller::post(nif);
emitter.post(nif); emitter.post(nif);
@ -128,7 +128,7 @@ namespace Nif
mData.read(nif); mData.read(nif);
} }
void NiMaterialColorController::post(NIFFile* nif) void NiMaterialColorController::post(Reader& nif)
{ {
NiPoint3InterpController::post(nif); NiPoint3InterpController::post(nif);
mData.post(nif); mData.post(nif);
@ -142,7 +142,7 @@ namespace Nif
target.read(nif); target.read(nif);
} }
void NiLookAtController::post(NIFFile* nif) void NiLookAtController::post(Reader& nif)
{ {
Controller::post(nif); Controller::post(nif);
target.post(nif); target.post(nif);
@ -160,7 +160,7 @@ namespace Nif
floatData.read(nif); floatData.read(nif);
} }
void NiPathController::post(NIFFile* nif) void NiPathController::post(Reader& nif)
{ {
Controller::post(nif); Controller::post(nif);
@ -176,7 +176,7 @@ namespace Nif
data.read(nif); data.read(nif);
} }
void NiUVController::post(NIFFile* nif) void NiUVController::post(Reader& nif)
{ {
Controller::post(nif); Controller::post(nif);
data.post(nif); data.post(nif);
@ -189,7 +189,7 @@ namespace Nif
mData.read(nif); mData.read(nif);
} }
void NiKeyframeController::post(NIFFile* nif) void NiKeyframeController::post(Reader& nif)
{ {
NiSingleInterpController::post(nif); NiSingleInterpController::post(nif);
mData.post(nif); mData.post(nif);
@ -206,7 +206,7 @@ namespace Nif
mExtraTargets = targets; mExtraTargets = targets;
} }
void NiMultiTargetTransformController::post(NIFFile* nif) void NiMultiTargetTransformController::post(Reader& nif)
{ {
NiInterpController::post(nif); NiInterpController::post(nif);
mExtraTargets.post(nif); mExtraTargets.post(nif);
@ -219,7 +219,7 @@ namespace Nif
mData.read(nif); mData.read(nif);
} }
void NiAlphaController::post(NIFFile* nif) void NiAlphaController::post(Reader& nif)
{ {
NiFloatInterpController::post(nif); NiFloatInterpController::post(nif);
mData.post(nif); mData.post(nif);
@ -232,7 +232,7 @@ namespace Nif
mData.read(nif); mData.read(nif);
} }
void NiRollController::post(NIFFile* nif) void NiRollController::post(Reader& nif)
{ {
NiSingleInterpController::post(nif); NiSingleInterpController::post(nif);
mData.post(nif); mData.post(nif);
@ -275,7 +275,7 @@ namespace Nif
} }
} }
void NiGeomMorpherController::post(NIFFile* nif) void NiGeomMorpherController::post(Reader& nif)
{ {
NiInterpController::post(nif); NiInterpController::post(nif);
mData.post(nif); mData.post(nif);
@ -289,7 +289,7 @@ namespace Nif
mData.read(nif); mData.read(nif);
} }
void NiVisController::post(NIFFile* nif) void NiVisController::post(Reader& nif)
{ {
NiBoolInterpController::post(nif); NiBoolInterpController::post(nif);
mData.post(nif); mData.post(nif);
@ -307,7 +307,7 @@ namespace Nif
mSources.read(nif); mSources.read(nif);
} }
void NiFlipController::post(NIFFile* nif) void NiFlipController::post(Reader& nif)
{ {
NiFloatInterpController::post(nif); NiFloatInterpController::post(nif);
mSources.post(nif); mSources.post(nif);
@ -334,7 +334,7 @@ namespace Nif
data.read(nif); data.read(nif);
} }
void NiPoint3Interpolator::post(NIFFile* nif) void NiPoint3Interpolator::post(Reader& nif)
{ {
data.post(nif); data.post(nif);
} }
@ -345,7 +345,7 @@ namespace Nif
data.read(nif); data.read(nif);
} }
void NiBoolInterpolator::post(NIFFile* nif) void NiBoolInterpolator::post(Reader& nif)
{ {
data.post(nif); data.post(nif);
} }
@ -356,7 +356,7 @@ namespace Nif
data.read(nif); data.read(nif);
} }
void NiFloatInterpolator::post(NIFFile* nif) void NiFloatInterpolator::post(Reader& nif)
{ {
data.post(nif); data.post(nif);
} }
@ -378,7 +378,7 @@ namespace Nif
data.read(nif); data.read(nif);
} }
void NiTransformInterpolator::post(NIFFile* nif) void NiTransformInterpolator::post(Reader& nif)
{ {
data.post(nif); data.post(nif);
} }
@ -389,7 +389,7 @@ namespace Nif
data.read(nif); data.read(nif);
} }
void NiColorInterpolator::post(NIFFile* nif) void NiColorInterpolator::post(Reader& nif)
{ {
data.post(nif); data.post(nif);
} }

@ -44,7 +44,7 @@ namespace Nif
NiInterpolatorPtr mInterpolator; NiInterpolatorPtr mInterpolator;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
// Base class for controllers that use a NiFloatInterpolator to animate their target. // Base class for controllers that use a NiFloatInterpolator to animate their target.
@ -116,7 +116,7 @@ namespace Nif
NiParticleModifierPtr colliders; NiParticleModifierPtr colliders;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
bool noAutoAdjust() const { return emitFlags & EmitFlag_NoAutoAdjust; } bool noAutoAdjust() const { return emitFlags & EmitFlag_NoAutoAdjust; }
bool emitAtVertex() const { return flags & BSPArrayController_AtVertex; } bool emitAtVertex() const { return flags & BSPArrayController_AtVertex; }
@ -129,7 +129,7 @@ namespace Nif
unsigned int mTargetColor; unsigned int mTargetColor;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiPathController : public Controller struct NiPathController : public Controller
@ -152,7 +152,7 @@ namespace Nif
short followAxis; short followAxis;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiLookAtController : public Controller struct NiLookAtController : public Controller
@ -161,7 +161,7 @@ namespace Nif
unsigned short lookAtFlags{ 0 }; unsigned short lookAtFlags{ 0 };
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiUVController : public Controller struct NiUVController : public Controller
@ -170,7 +170,7 @@ namespace Nif
unsigned int uvSet; unsigned int uvSet;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiKeyframeController : public NiSingleInterpController struct NiKeyframeController : public NiSingleInterpController
@ -178,7 +178,7 @@ namespace Nif
NiKeyframeDataPtr mData; NiKeyframeDataPtr mData;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiMultiTargetTransformController : public NiInterpController struct NiMultiTargetTransformController : public NiInterpController
@ -186,7 +186,7 @@ namespace Nif
NodeList mExtraTargets; NodeList mExtraTargets;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiAlphaController : public NiFloatInterpController struct NiAlphaController : public NiFloatInterpController
@ -194,7 +194,7 @@ namespace Nif
NiFloatDataPtr mData; NiFloatDataPtr mData;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiRollController : public NiSingleInterpController struct NiRollController : public NiSingleInterpController
@ -202,7 +202,7 @@ namespace Nif
NiFloatDataPtr mData; NiFloatDataPtr mData;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiGeomMorpherController : public NiInterpController struct NiGeomMorpherController : public NiInterpController
@ -214,7 +214,7 @@ namespace Nif
std::vector<float> mWeights; std::vector<float> mWeights;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiVisController : public NiBoolInterpController struct NiVisController : public NiBoolInterpController
@ -222,7 +222,7 @@ namespace Nif
NiVisDataPtr mData; NiVisDataPtr mData;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiFlipController : public NiFloatInterpController struct NiFlipController : public NiFloatInterpController
@ -232,7 +232,7 @@ namespace Nif
NiSourceTextureList mSources; NiSourceTextureList mSources;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct bhkBlendController : public Controller struct bhkBlendController : public Controller
@ -255,7 +255,7 @@ namespace Nif
osg::Vec3f defaultVal; osg::Vec3f defaultVal;
NiPosDataPtr data; NiPosDataPtr data;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiBoolInterpolator : public NiInterpolator struct NiBoolInterpolator : public NiInterpolator
@ -263,7 +263,7 @@ namespace Nif
char defaultVal; char defaultVal;
NiBoolDataPtr data; NiBoolDataPtr data;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiFloatInterpolator : public NiInterpolator struct NiFloatInterpolator : public NiInterpolator
@ -271,7 +271,7 @@ namespace Nif
float defaultVal; float defaultVal;
NiFloatDataPtr data; NiFloatDataPtr data;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiTransformInterpolator : public NiInterpolator struct NiTransformInterpolator : public NiInterpolator
@ -282,7 +282,7 @@ namespace Nif
NiKeyframeDataPtr data; NiKeyframeDataPtr data;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiColorInterpolator : public NiInterpolator struct NiColorInterpolator : public NiInterpolator
@ -290,7 +290,7 @@ namespace Nif
osg::Vec4f defaultVal; osg::Vec4f defaultVal;
NiColorDataPtr data; NiColorDataPtr data;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
} // Namespace } // Namespace

@ -16,7 +16,7 @@ namespace Nif
bones.read(nif); bones.read(nif);
} }
void NiSkinInstance::post(NIFFile* nif) void NiSkinInstance::post(Reader& nif)
{ {
data.post(nif); data.post(nif);
partitions.post(nif); partitions.post(nif);
@ -24,16 +24,16 @@ namespace Nif
bones.post(nif); bones.post(nif);
if (data.empty() || root.empty()) if (data.empty() || root.empty())
throw Nif::Exception("NiSkinInstance missing root or data", nif->getFilename()); throw Nif::Exception("NiSkinInstance missing root or data", nif.getFilename());
size_t bnum = bones.length(); size_t bnum = bones.length();
if (bnum != data->bones.size()) if (bnum != data->bones.size())
throw Nif::Exception("Mismatch in NiSkinData bone count", nif->getFilename()); throw Nif::Exception("Mismatch in NiSkinData bone count", nif.getFilename());
for (size_t i = 0; i < bnum; i++) for (size_t i = 0; i < bnum; i++)
{ {
if (bones[i].empty()) if (bones[i].empty())
throw Nif::Exception("Oops: Missing bone! Don't know how to handle this.", nif->getFilename()); throw Nif::Exception("Oops: Missing bone! Don't know how to handle this.", nif.getFilename());
bones[i]->setBone(); bones[i]->setBone();
} }
} }
@ -304,7 +304,7 @@ namespace Nif
nif->getUChars(data, numPixels * numFaces); nif->getUChars(data, numPixels * numFaces);
} }
void NiPixelData::post(NIFFile* nif) void NiPixelData::post(Reader& nif)
{ {
palette.post(nif); palette.post(nif);
} }
@ -360,7 +360,7 @@ namespace Nif
} }
} }
void NiSkinData::post(NIFFile* nif) void NiSkinData::post(Reader& nif)
{ {
partitions.post(nif); partitions.post(nif);
} }
@ -474,7 +474,7 @@ namespace Nif
palette = nif->getString(); palette = nif->getString();
if (nif->getUInt() != palette.size()) if (nif->getUInt() != palette.size())
Log(Debug::Warning) << "NIFFile Warning: Failed size check in NiStringPalette. File: " Log(Debug::Warning) << "NIFFile Warning: Failed size check in NiStringPalette. File: "
<< nif->file->getFilename(); << nif->getFile().getFilename();
} }
void NiBoolData::read(NIFStream* nif) void NiBoolData::read(NIFStream* nif)

@ -139,7 +139,7 @@ namespace Nif
std::vector<unsigned char> data; std::vector<unsigned char> data;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiColorData : public Record struct NiColorData : public Record
@ -169,7 +169,7 @@ namespace Nif
NodeList bones; NodeList bones;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct BSDismemberSkinInstance : public NiSkinInstance struct BSDismemberSkinInstance : public NiSkinInstance
@ -198,7 +198,7 @@ namespace Nif
NiSkinPartitionPtr partitions; NiSkinPartitionPtr partitions;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiSkinPartition : public Record struct NiSkinPartition : public Record

@ -60,7 +60,7 @@ namespace Nif
nif->skip(2); // Unknown short nif->skip(2); // Unknown short
} }
void NiTextureEffect::post(NIFFile* nif) void NiTextureEffect::post(Reader& nif)
{ {
NiDynamicEffect::post(nif); NiDynamicEffect::post(nif);
texture.post(nif); texture.post(nif);

@ -86,7 +86,7 @@ namespace Nif
CoordGenType coordGenType; CoordGenType coordGenType;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
bool wrapT() const { return clamp & 1; } bool wrapT() const { return clamp & 1; }
bool wrapS() const { return (clamp >> 1) & 1; } bool wrapS() const { return (clamp >> 1) & 1; }

@ -23,11 +23,16 @@
namespace Nif namespace Nif
{ {
/// Open a NIF stream. The name is used for error messages. Reader::Reader(NIFFile& file)
NIFFile::NIFFile(Files::IStreamPtr&& stream, const std::filesystem::path& name) : ver(file.mVersion)
: filename(name) , userVer(file.mUserVersion)
, bethVer(file.mBethVersion)
, filename(file.mPath)
, hash(file.mHash)
, records(file.mRecords)
, roots(file.mRoots)
, mUseSkinning(file.mUseSkinning)
{ {
parse(std::move(stream));
} }
template <typename NodeType, RecordType recordType> template <typename NodeType, RecordType recordType>
@ -173,7 +178,7 @@ namespace Nif
/// Make the factory map used for parsing the file /// Make the factory map used for parsing the file
static const std::map<std::string, CreateRecord> factories = makeFactory(); static const std::map<std::string, CreateRecord> factories = makeFactory();
std::string NIFFile::printVersion(unsigned int version) std::string Reader::printVersion(unsigned int version)
{ {
int major = (version >> 24) & 0xFF; int major = (version >> 24) & 0xFF;
int minor = (version >> 16) & 0xFF; int minor = (version >> 16) & 0xFF;
@ -185,12 +190,12 @@ namespace Nif
return stream.str(); return stream.str();
} }
void NIFFile::parse(Files::IStreamPtr&& stream) void Reader::parse(Files::IStreamPtr&& stream)
{ {
const std::array<std::uint64_t, 2> fileHash = Files::getHash(filename, *stream); const std::array<std::uint64_t, 2> fileHash = Files::getHash(filename, *stream);
hash.append(reinterpret_cast<const char*>(fileHash.data()), fileHash.size() * sizeof(std::uint64_t)); hash.append(reinterpret_cast<const char*>(fileHash.data()), fileHash.size() * sizeof(std::uint64_t));
NIFStream nif(this, std::move(stream)); NIFStream nif(*this, std::move(stream));
// Check the header string // Check the header string
std::string head = nif.getVersionString(); std::string head = nif.getVersionString();
@ -209,7 +214,7 @@ namespace Nif
// It's not used by Morrowind assets but Morrowind supports it. // It's not used by Morrowind assets but Morrowind supports it.
static const std::array<uint32_t, 2> supportedVers = { static const std::array<uint32_t, 2> supportedVers = {
NIFStream::generateVersion(4, 0, 0, 0), NIFStream::generateVersion(4, 0, 0, 0),
VER_MW, NIFFile::VER_MW,
}; };
const bool supportedVersion = std::find(supportedVers.begin(), supportedVers.end(), ver) != supportedVers.end(); const bool supportedVersion = std::find(supportedVers.begin(), supportedVers.end(), ver) != supportedVers.end();
if (!supportedVersion) if (!supportedVersion)
@ -239,19 +244,19 @@ namespace Nif
// Bethesda stream header // Bethesda stream header
// It contains Bethesda format version and (useless) export information // It contains Bethesda format version and (useless) export information
if (ver == VER_OB_OLD if (ver == NIFFile::VER_OB_OLD
|| (userVer >= 3 || (userVer >= 3
&& ((ver == VER_OB || ver == VER_BGS) && ((ver == NIFFile::VER_OB || ver == NIFFile::VER_BGS)
|| (ver >= NIFStream::generateVersion(10, 1, 0, 0) && ver <= NIFStream::generateVersion(20, 0, 0, 4) || (ver >= NIFStream::generateVersion(10, 1, 0, 0) && ver <= NIFStream::generateVersion(20, 0, 0, 4)
&& userVer <= 11)))) && userVer <= 11))))
{ {
bethVer = nif.getUInt(); bethVer = nif.getUInt();
nif.getExportString(); // Author nif.getExportString(); // Author
if (bethVer > BETHVER_FO4) if (bethVer > NIFFile::BETHVER_FO4)
nif.getUInt(); // Unknown nif.getUInt(); // Unknown
nif.getExportString(); // Process script nif.getExportString(); // Process script
nif.getExportString(); // Export script nif.getExportString(); // Export script
if (bethVer == BETHVER_FO4) if (bethVer == NIFFile::BETHVER_FO4)
nif.getExportString(); // Max file path nif.getExportString(); // Max file path
} }
@ -347,29 +352,24 @@ namespace Nif
// Once parsing is done, do post-processing. // Once parsing is done, do post-processing.
for (const auto& record : records) for (const auto& record : records)
record->post(this); record->post(*this);
} }
void NIFFile::setUseSkinning(bool skinning) void Reader::setUseSkinning(bool skinning)
{ {
mUseSkinning = skinning; mUseSkinning = skinning;
} }
bool NIFFile::getUseSkinning() const std::atomic_bool Reader::sLoadUnsupportedFiles = false;
{
return mUseSkinning;
}
std::atomic_bool NIFFile::sLoadUnsupportedFiles = false;
void NIFFile::setLoadUnsupportedFiles(bool load) void Reader::setLoadUnsupportedFiles(bool load)
{ {
sLoadUnsupportedFiles = load; sLoadUnsupportedFiles = load;
} }
std::string NIFFile::getString(uint32_t index) const std::string Reader::getString(std::uint32_t index) const
{ {
if (index == std::numeric_limits<uint32_t>::max()) if (index == std::numeric_limits<std::uint32_t>::max())
return std::string(); return std::string();
return strings.at(index); return strings.at(index);
} }

@ -14,125 +14,123 @@
namespace Nif namespace Nif
{ {
struct File struct NIFFile
{ {
virtual ~File() = default; // For generic versions NIFStream::generateVersion() is used instead
enum NIFVersion
{
VER_MW = 0x04000002, // 4.0.0.2. Main Morrowind NIF version.
VER_OB_OLD = 0x0A000102, // 10.0.1.2. Main older Oblivion NIF version.
VER_OB = 0x14000005, // 20.0.0.5. Main Oblivion NIF version.
VER_BGS = 0x14020007 // 20.2.0.7. Main Fallout 3/4/76/New Vegas and Skyrim/SkyrimSE NIF version.
};
enum BethVersion
{
BETHVER_FO3 = 34, // Fallout 3
BETHVER_FO4 = 130 // Fallout 4
};
virtual Record* getRecord(size_t index) const = 0; /// File version, user version, Bethesda version
unsigned int mVersion = 0;
unsigned int mUserVersion = 0;
unsigned int mBethVersion = 0;
virtual size_t numRecords() const = 0; /// File name, used for error messages and opening the file
std::filesystem::path mPath;
std::string mHash;
virtual Record* getRoot(size_t index = 0) const = 0; /// Record list
std::vector<std::unique_ptr<Record>> mRecords;
/// Root list. This is a select portion of the pointers from records
std::vector<Record*> mRoots;
virtual size_t numRoots() const = 0; bool mUseSkinning = false;
explicit NIFFile(const std::filesystem::path& path)
: mPath(path)
{
}
virtual std::string getString(uint32_t index) const = 0; /// Get a given root
Record* getRoot(size_t index = 0) const { return mRoots.at(index); }
virtual void setUseSkinning(bool skinning) = 0; /// Number of roots
std::size_t numRoots() const { return mRoots.size(); }
virtual bool getUseSkinning() const = 0; /// Get the name of the file
const std::filesystem::path& getFilename() const { return mPath; }
virtual std::filesystem::path getFilename() const = 0; const std::string& getHash() const { return mHash; }
virtual std::string getHash() const = 0; /// Get the version of the NIF format used
unsigned int getVersion() const { return mVersion; }
virtual unsigned int getVersion() const = 0; /// Get the user version of the NIF format used
unsigned int getUserVersion() const { return mUserVersion; }
virtual unsigned int getUserVersion() const = 0; /// Get the Bethesda version of the NIF format used
unsigned int getBethVersion() const { return mBethVersion; }
virtual unsigned int getBethVersion() const = 0; bool getUseSkinning() const { return mUseSkinning; }
}; };
class NIFFile final : public File class Reader
{ {
/// File version, user version, Bethesda version /// File version, user version, Bethesda version
unsigned int ver = 0; unsigned int& ver;
unsigned int userVer = 0; unsigned int& userVer;
unsigned int bethVer = 0; unsigned int& bethVer;
/// File name, used for error messages and opening the file /// File name, used for error messages and opening the file
std::filesystem::path filename; std::filesystem::path& filename;
std::string hash; std::string& hash;
/// Record list /// Record list
std::vector<std::unique_ptr<Record>> records; std::vector<std::unique_ptr<Record>>& records;
/// Root list. This is a select portion of the pointers from records /// Root list. This is a select portion of the pointers from records
std::vector<Record*> roots; std::vector<Record*>& roots;
/// String table /// String table
std::vector<std::string> strings; std::vector<std::string> strings;
bool mUseSkinning = false; bool& mUseSkinning;
static std::atomic_bool sLoadUnsupportedFiles; static std::atomic_bool sLoadUnsupportedFiles;
/// Parse the file
void parse(Files::IStreamPtr&& stream);
/// Get the file's version in a human readable form /// Get the file's version in a human readable form
///\returns A string containing a human readable NIF version number ///\returns A string containing a human readable NIF version number
std::string printVersion(unsigned int version); std::string printVersion(unsigned int version);
/// Private Copy Constructor
NIFFile(NIFFile const&);
///\overload
void operator=(NIFFile const&);
public: public:
// For generic versions NIFStream::generateVersion() is used instead
enum NIFVersion
{
VER_MW = 0x04000002, // 4.0.0.2. Main Morrowind NIF version.
VER_OB_OLD = 0x0A000102, // 10.0.1.2. Main older Oblivion NIF version.
VER_OB = 0x14000005, // 20.0.0.5. Main Oblivion NIF version.
VER_BGS = 0x14020007 // 20.2.0.7. Main Fallout 3/4/76/New Vegas and Skyrim/SkyrimSE NIF version.
};
enum BethVersion
{
BETHVER_FO3 = 34, // Fallout 3
BETHVER_FO4 = 130 // Fallout 4
};
/// Open a NIF stream. The name is used for error messages. /// Open a NIF stream. The name is used for error messages.
NIFFile(Files::IStreamPtr&& stream, const std::filesystem::path& name); explicit Reader(NIFFile& file);
/// Get a given record /// Parse the file
Record* getRecord(size_t index) const override { return records.at(index).get(); } void parse(Files::IStreamPtr&& stream);
/// Number of records
size_t numRecords() const override { return records.size(); }
/// Get a given root /// Get a given record
Record* getRoot(size_t index = 0) const override Record* getRecord(size_t index) const { return records.at(index).get(); }
{
Record* res = roots.at(index);
return res;
}
/// Number of roots
size_t numRoots() const override { return roots.size(); }
/// Get a given string from the file's string table /// Get a given string from the file's string table
std::string getString(uint32_t index) const override; std::string getString(uint32_t index) const;
/// Set whether there is skinning contained in this NIF file. /// Set whether there is skinning contained in this NIF file.
/// @note This is just a hint for users of the NIF file and has no effect on the loading procedure. /// @note This is just a hint for users of the NIF file and has no effect on the loading procedure.
void setUseSkinning(bool skinning) override; void setUseSkinning(bool skinning);
bool getUseSkinning() const override;
/// Get the name of the file /// Get the name of the file
std::filesystem::path getFilename() const override { return filename; } std::filesystem::path getFilename() const { return filename; }
std::string getHash() const override { return hash; }
/// Get the version of the NIF format used /// Get the version of the NIF format used
unsigned int getVersion() const override { return ver; } unsigned int getVersion() const { return ver; }
/// Get the user version of the NIF format used /// Get the user version of the NIF format used
unsigned int getUserVersion() const override { return userVer; } unsigned int getUserVersion() const { return userVer; }
/// Get the Bethesda version of the NIF format used /// Get the Bethesda version of the NIF format used
unsigned int getBethVersion() const override { return bethVer; } unsigned int getBethVersion() const { return bethVer; }
static void setLoadUnsupportedFiles(bool load); static void setLoadUnsupportedFiles(bool load);
}; };

@ -113,8 +113,8 @@ namespace Nif
} }
else if (count != 0) else if (count != 0)
{ {
throw Nif::Exception( throw Nif::Exception("Unhandled interpolation type: " + std::to_string(mInterpolationType),
"Unhandled interpolation type: " + std::to_string(mInterpolationType), nif->file->getFilename()); nif->getFile().getFilename());
} }
} }

@ -34,20 +34,20 @@ namespace Nif
/// Read in a string, either from the string table using the index or from the stream using the specified length /// Read in a string, either from the string table using the index or from the stream using the specified length
std::string NIFStream::getString() std::string NIFStream::getString()
{ {
return getVersion() < generateVersion(20, 1, 0, 1) ? getSizedString() : file->getString(getUInt()); return getVersion() < generateVersion(20, 1, 0, 1) ? getSizedString() : file.getString(getUInt());
} }
// Convenience utility functions: get the versions of the currently read file // Convenience utility functions: get the versions of the currently read file
unsigned int NIFStream::getVersion() const unsigned int NIFStream::getVersion() const
{ {
return file->getVersion(); return file.getVersion();
} }
unsigned int NIFStream::getUserVersion() const unsigned int NIFStream::getUserVersion() const
{ {
return file->getBethVersion(); return file.getBethVersion();
} }
unsigned int NIFStream::getBethVersion() const unsigned int NIFStream::getBethVersion() const
{ {
return file->getBethVersion(); return file.getBethVersion();
} }
} }

@ -22,7 +22,7 @@
namespace Nif namespace Nif
{ {
class NIFFile; class Reader;
template <std::size_t numInstances, typename T> template <std::size_t numInstances, typename T>
inline void readLittleEndianBufferOfType(Files::IStreamPtr& pIStream, T* dest) inline void readLittleEndianBufferOfType(Files::IStreamPtr& pIStream, T* dest)
@ -59,18 +59,20 @@ namespace Nif
class NIFStream class NIFStream
{ {
const Reader& file;
/// Input stream /// Input stream
Files::IStreamPtr inp; Files::IStreamPtr inp;
public: public:
NIFFile* const file; explicit NIFStream(const Reader& file, Files::IStreamPtr&& inp)
: file(file)
NIFStream(NIFFile* file, Files::IStreamPtr&& inp) , inp(std::move(inp))
: inp(std::move(inp))
, file(file)
{ {
} }
const Reader& getFile() const { return file; }
void skip(size_t size) { inp->ignore(size); } void skip(size_t size) { inp->ignore(size); }
char getChar() { return readLittleEndianType<char>(inp); } char getChar() { return readLittleEndianType<char>(inp); }

@ -70,7 +70,7 @@ namespace Nif
default: default:
{ {
throw Nif::Exception( throw Nif::Exception(
"Unhandled NiBoundingVolume type: " + std::to_string(type), nif->file->getFilename()); "Unhandled NiBoundingVolume type: " + std::to_string(type), nif->getFile().getFilename());
} }
} }
} }
@ -99,7 +99,7 @@ namespace Nif
isBone = false; isBone = false;
} }
void Node::post(NIFFile* nif) void Node::post(Reader& nif)
{ {
Named::post(nif); Named::post(nif);
props.post(nif); props.post(nif);
@ -128,7 +128,7 @@ namespace Nif
} }
} }
void NiNode::post(NIFFile* nif) void NiNode::post(Reader& nif)
{ {
Node::post(nif); Node::post(nif);
children.post(nif); children.post(nif);
@ -176,7 +176,7 @@ namespace Nif
} }
} }
void NiGeometry::post(NIFFile* nif) void NiGeometry::post(Reader& nif)
{ {
Node::post(nif); Node::post(nif);
data.post(nif); data.post(nif);
@ -184,7 +184,7 @@ namespace Nif
shaderprop.post(nif); shaderprop.post(nif);
alphaprop.post(nif); alphaprop.post(nif);
if (recType != RC_NiParticles && !skin.empty()) if (recType != RC_NiParticles && !skin.empty())
nif->setUseSkinning(true); nif.setUseSkinning(true);
} }
void BSLODTriShape::read(NIFStream* nif) void BSLODTriShape::read(NIFStream* nif)
@ -271,7 +271,7 @@ namespace Nif
mSubSorter.read(nif); mSubSorter.read(nif);
} }
void NiSortAdjustNode::post(NIFFile* nif) void NiSortAdjustNode::post(Reader& nif)
{ {
NiNode::post(nif); NiNode::post(nif);
mSubSorter.post(nif); mSubSorter.post(nif);

@ -94,7 +94,7 @@ namespace Nif
NiCollisionObjectPtr collision; NiCollisionObjectPtr collision;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
// Parent node, or nullptr for the root node. As far as I'm aware, only // Parent node, or nullptr for the root node. As far as I'm aware, only
// NiNodes (or types derived from NiNodes) can be parents. // NiNodes (or types derived from NiNodes) can be parents.
@ -126,7 +126,7 @@ namespace Nif
}; };
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiGeometry : Node struct NiGeometry : Node
@ -154,7 +154,7 @@ namespace Nif
NiAlphaPropertyPtr alphaprop; NiAlphaPropertyPtr alphaprop;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiTriShape : NiGeometry struct NiTriShape : NiGeometry
@ -263,7 +263,7 @@ namespace Nif
NiAccumulatorPtr mSubSorter; NiAccumulatorPtr mSubSorter;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiBillboardNode : NiNode struct NiBillboardNode : NiNode

@ -165,7 +165,7 @@ namespace Nif
mWorldObjectInfo.read(nif); mWorldObjectInfo.read(nif);
} }
void bhkWorldObject::post(NIFFile* nif) void bhkWorldObject::post(Reader& nif)
{ {
mShape.post(nif); mShape.post(nif);
} }
@ -181,7 +181,7 @@ namespace Nif
mShape.read(nif); mShape.read(nif);
} }
void bhkBvTreeShape::post(NIFFile* nif) void bhkBvTreeShape::post(Reader& nif)
{ {
mShape.post(nif); mShape.post(nif);
} }
@ -207,7 +207,7 @@ namespace Nif
nif->getUInts(mFilters, numFilters); nif->getUInts(mFilters, numFilters);
} }
void bhkNiTriStripsShape::post(NIFFile* nif) void bhkNiTriStripsShape::post(Reader& nif)
{ {
mData.post(nif); mData.post(nif);
} }
@ -229,7 +229,7 @@ namespace Nif
mData.read(nif); mData.read(nif);
} }
void bhkPackedNiTriStripsShape::post(NIFFile* nif) void bhkPackedNiTriStripsShape::post(Reader& nif)
{ {
mData.post(nif); mData.post(nif);
} }

@ -17,7 +17,7 @@ namespace Nif
{ {
class NIFStream; class NIFStream;
class NIFFile; struct NIFFile;
/// Non-record data types /// Non-record data types
@ -204,7 +204,7 @@ namespace Nif
NodePtr mTarget; NodePtr mTarget;
void read(NIFStream* nif) override { mTarget.read(nif); } void read(NIFStream* nif) override { mTarget.read(nif); }
void post(NIFFile* nif) override { mTarget.post(nif); } void post(Reader& nif) override { mTarget.post(nif); }
}; };
// Bethesda Havok-specific collision object // Bethesda Havok-specific collision object
@ -214,7 +214,7 @@ namespace Nif
bhkWorldObjectPtr mBody; bhkWorldObjectPtr mBody;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override void post(Reader& nif) override
{ {
NiCollisionObject::post(nif); NiCollisionObject::post(nif);
mBody.post(nif); mBody.post(nif);
@ -228,7 +228,7 @@ namespace Nif
HavokFilter mHavokFilter; HavokFilter mHavokFilter;
bhkWorldObjectCInfo mWorldObjectInfo; bhkWorldObjectCInfo mWorldObjectInfo;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
// Abstract // Abstract
@ -244,7 +244,7 @@ namespace Nif
{ {
bhkShapePtr mShape; bhkShapePtr mShape;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
// bhkBvTreeShape with Havok MOPP code // bhkBvTreeShape with Havok MOPP code
@ -265,7 +265,7 @@ namespace Nif
NiTriStripsDataList mData; NiTriStripsDataList mData;
std::vector<unsigned int> mFilters; std::vector<unsigned int> mFilters;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
// Bethesda packed triangle strip-based Havok shape collection // Bethesda packed triangle strip-based Havok shape collection
@ -278,7 +278,7 @@ namespace Nif
hkPackedNiTriStripsDataPtr mData; hkPackedNiTriStripsDataPtr mData;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
// bhkPackedNiTriStripsShape data block // bhkPackedNiTriStripsShape data block

@ -47,7 +47,7 @@ namespace Nif
} }
} }
void NiTexturingProperty::Texture::post(NIFFile* nif) void NiTexturingProperty::Texture::post(Reader& nif)
{ {
texture.post(nif); texture.post(nif);
} }
@ -92,7 +92,7 @@ namespace Nif
} }
} }
void NiTexturingProperty::post(NIFFile* nif) void NiTexturingProperty::post(Reader& nif)
{ {
Property::post(nif); Property::post(nif);
for (size_t i = 0; i < textures.size(); i++) for (size_t i = 0; i < textures.size(); i++)
@ -134,7 +134,7 @@ namespace Nif
parallax.scale = nif->getFloat(); parallax.scale = nif->getFloat();
} }
void BSShaderPPLightingProperty::post(NIFFile* nif) void BSShaderPPLightingProperty::post(Reader& nif)
{ {
BSShaderLightingProperty::post(nif); BSShaderLightingProperty::post(nif);
textureSet.post(nif); textureSet.post(nif);
@ -198,7 +198,7 @@ namespace Nif
} }
} }
void BSLightingShaderProperty::post(NIFFile* nif) void BSLightingShaderProperty::post(Reader& nif)
{ {
BSShaderProperty::post(nif); BSShaderProperty::post(nif);
mTextureSet.post(nif); mTextureSet.post(nif);

@ -53,7 +53,7 @@ namespace Nif
unsigned int clamp, uvSet; unsigned int clamp, uvSet;
void read(NIFStream* nif); void read(NIFStream* nif);
void post(NIFFile* nif); void post(Reader& nif);
bool wrapT() const { return clamp & 1; } bool wrapT() const { return clamp & 1; }
bool wrapS() const { return (clamp >> 1) & 1; } bool wrapS() const { return (clamp >> 1) & 1; }
@ -97,7 +97,7 @@ namespace Nif
osg::Vec4f bumpMapMatrix; osg::Vec4f bumpMapMatrix;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiFogProperty : public Property struct NiFogProperty : public Property
@ -166,7 +166,7 @@ namespace Nif
ParallaxSettings parallax; ParallaxSettings parallax;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct BSShaderNoLightingProperty : public BSShaderLightingProperty struct BSShaderNoLightingProperty : public BSShaderLightingProperty
@ -212,7 +212,7 @@ namespace Nif
float mEmissiveMult, mSpecStrength; float mEmissiveMult, mSpecStrength;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(NIFFile* nif) override; void post(Reader& nif) override;
}; };
struct NiDitherProperty : public Property struct NiDitherProperty : public Property

@ -29,7 +29,7 @@
namespace Nif namespace Nif
{ {
class NIFFile; class Reader;
class NIFStream; class NIFStream;
enum RecordType enum RecordType
@ -164,7 +164,7 @@ namespace Nif
virtual void read(NIFStream* nif) = 0; virtual void read(NIFStream* nif) = 0;
/// Does post-processing, after the entire tree is loaded /// Does post-processing, after the entire tree is loaded
virtual void post(NIFFile* nif) {} virtual void post(Reader& nif) {}
virtual ~Record() {} virtual ~Record() {}
}; };

@ -44,13 +44,13 @@ namespace Nif
} }
/// Resolve index to pointer /// Resolve index to pointer
void post(NIFFile* nif) void post(Reader& nif)
{ {
if (index < 0) if (index < 0)
ptr = nullptr; ptr = nullptr;
else else
{ {
Record* r = nif->getRecord(index); Record* r = nif.getRecord(index);
// And cast it // And cast it
ptr = dynamic_cast<X*>(r); ptr = dynamic_cast<X*>(r);
assert(ptr != nullptr); assert(ptr != nullptr);
@ -107,7 +107,7 @@ namespace Nif
list[i].read(nif); list[i].read(nif);
} }
void post(NIFFile* nif) void post(Reader& nif)
{ {
for (size_t i = 0; i < list.size(); i++) for (size_t i = 0; i < list.size(); i++)
list[i].post(nif); list[i].post(nif);

@ -160,7 +160,7 @@ namespace
namespace NifBullet namespace NifBullet
{ {
osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif) osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::NIFFile& nif)
{ {
mShape = new Resource::BulletShape; mShape = new Resource::BulletShape;

@ -48,7 +48,7 @@ namespace NifBullet
abort(); abort();
} }
osg::ref_ptr<Resource::BulletShape> load(const Nif::File& file); osg::ref_ptr<Resource::BulletShape> load(const Nif::NIFFile& file);
private: private:
bool findBoundingBox(const Nif::Node& node, const std::string& filename); bool findBoundingBox(const Nif::Node& node, const std::string& filename);

@ -963,7 +963,7 @@ namespace NifOsg
if (matctrl->mData.empty() && matctrl->mInterpolator.empty()) if (matctrl->mData.empty() && matctrl->mInterpolator.empty())
continue; continue;
auto targetColor = static_cast<MaterialColorController::TargetColor>(matctrl->mTargetColor); auto targetColor = static_cast<MaterialColorController::TargetColor>(matctrl->mTargetColor);
if (mVersion <= Nif::NIFFile::NIFVersion::VER_MW if (mVersion <= Nif::NIFFile::VER_MW
&& targetColor == MaterialColorController::TargetColor::Specular) && targetColor == MaterialColorController::TargetColor::Specular)
continue; continue;
if (!matctrl->mInterpolator.empty() if (!matctrl->mInterpolator.empty()
@ -2398,7 +2398,7 @@ namespace NifOsg
} }
// While NetImmerse and Gamebryo support specular lighting, Morrowind has its support disabled. // While NetImmerse and Gamebryo support specular lighting, Morrowind has its support disabled.
if (mVersion <= Nif::NIFFile::NIFVersion::VER_MW || !specEnabled) if (mVersion <= Nif::NIFFile::VER_MW || !specEnabled)
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f)); mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
if (lightmode == 0) if (lightmode == 0)

@ -156,8 +156,10 @@ namespace Resource
osg::ref_ptr<SceneUtil::KeyframeHolder> loaded(new SceneUtil::KeyframeHolder); osg::ref_ptr<SceneUtil::KeyframeHolder> loaded(new SceneUtil::KeyframeHolder);
if (Misc::getFileExtension(normalized) == "kf") if (Misc::getFileExtension(normalized) == "kf")
{ {
NifOsg::Loader::loadKf( auto file = std::make_shared<Nif::NIFFile>(normalized);
Nif::NIFFilePtr(new Nif::NIFFile(mVFS->getNormalized(normalized), normalized)), *loaded.get()); Nif::Reader reader(*file);
reader.parse(mVFS->getNormalized(normalized));
NifOsg::Loader::loadKf(std::move(file), *loaded.get());
} }
else else
{ {

@ -45,7 +45,9 @@ namespace Resource
return static_cast<NifFileHolder*>(obj.get())->mNifFile; return static_cast<NifFileHolder*>(obj.get())->mNifFile;
else else
{ {
Nif::NIFFilePtr file(new Nif::NIFFile(mVFS->get(name), name)); auto file = std::make_shared<Nif::NIFFile>(name);
Nif::Reader reader(*file);
reader.parse(mVFS->get(name));
obj = new NifFileHolder(file); obj = new NifFileHolder(file);
mCache->addEntryToObjectCache(name, obj); mCache->addEntryToObjectCache(name, obj);
return file; return file;

Loading…
Cancel
Save