diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index d0508e9d4..c107b58e2 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -19,7 +19,7 @@ add_component_dir (bsa ) add_component_dir (nif - controlled effect niftypes record controller extra node record_ptr data niffile property nifkey data node + controlled effect niftypes record controller extra node record_ptr data niffile property nifkey data node base ) add_component_dir (nifcache diff --git a/components/nif/base.hpp b/components/nif/base.hpp new file mode 100644 index 000000000..30c652b64 --- /dev/null +++ b/components/nif/base.hpp @@ -0,0 +1,91 @@ +///This file holds the main classes of NIF Records used by everything else. +#ifndef OPENMW_COMPONENTS_NIF_BASE_HPP +#define OPENMW_COMPONENTS_NIF_BASE_HPP + +#include "record.hpp" +#include "niffile.hpp" +#include "recordptr.hpp" +#include "nifstream.hpp" +#include "nifkey.hpp" + +namespace Nif +{ +/** A record that can have extra data. The extra data objects + themselves descend from the Extra class, and all the extra data + connected to an object form a linked list +*/ +class Extra : public Record +{ +public: + ExtraPtr extra; + + void read(NIFStream *nif) { extra.read(nif); } + void post(NIFFile *nif) { extra.post(nif); } +}; + +class Controller : public Record +{ +public: + ControllerPtr next; + int flags; + float frequency, phase; + float timeStart, timeStop; + ControlledPtr target; + + void read(NIFStream *nif) + { + next.read(nif); + + flags = nif->getUShort(); + + frequency = nif->getFloat(); + phase = nif->getFloat(); + timeStart = nif->getFloat(); + timeStop = nif->getFloat(); + + target.read(nif); + } + + void post(NIFFile *nif) + { + Record::post(nif); + next.post(nif); + target.post(nif); + } +}; + +/// Anything that has a controller +class Controlled : public Extra +{ +public: + ControllerPtr controller; + + void read(NIFStream *nif) + { + Extra::read(nif); + controller.read(nif); + } + + void post(NIFFile *nif) + { + Extra::post(nif); + controller.post(nif); + } +}; + +/// Has name, extra-data and controller +class Named : public Controlled +{ +public: + std::string name; + + void read(NIFStream *nif) + { + name = nif->getString(); + Controlled::read(nif); + } +}; +typedef Named NiSequenceStreamHelper; + +} // Namespace +#endif diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index 6acb8ff20..815aa7d3f 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -24,44 +24,70 @@ #ifndef OPENMW_COMPONENTS_NIF_CONTROLLED_HPP #define OPENMW_COMPONENTS_NIF_CONTROLLED_HPP -#include "extra.hpp" -#include "controller.hpp" +#include "base.hpp" namespace Nif { -/// Anything that has a controller -class Controlled : public Extra +class NiSourceTexture : public Named { public: - ControllerPtr controller; + // Is this an external (references a separate texture file) or + // internal (data is inside the nif itself) texture? + bool external; + + std::string filename; // In case of external textures + NiPixelDataPtr data; // In case of internal textures + + /* Pixel layout + 0 - Palettised + 1 - High color 16 + 2 - True color 32 + 3 - Compressed + 4 - Bumpmap + 5 - Default */ + int pixel; + + /* Mipmap format + 0 - no + 1 - yes + 2 - default */ + int mipmap; + + /* Alpha + 0 - none + 1 - binary + 2 - smooth + 3 - default (use material alpha, or multiply material with texture if present) + */ + int alpha; void read(NIFStream *nif) { - Extra::read(nif); - controller.read(nif); + Named::read(nif); + + external = !!nif->getChar(); + if(external) + filename = nif->getString(); + else + { + nif->getChar(); // always 1 + data.read(nif); + } + + pixel = nif->getInt(); + mipmap = nif->getInt(); + alpha = nif->getInt(); + + nif->getChar(); // always 1 } void post(NIFFile *nif) { - Extra::post(nif); - controller.post(nif); - } -}; - -/// Has name, extra-data and controller -class Named : public Controlled -{ -public: - std::string name; - - void read(NIFStream *nif) - { - name = nif->getString(); - Controlled::read(nif); + Named::post(nif); + data.post(nif); } }; -typedef Named NiSequenceStreamHelper; class NiParticleGrowFade : public Controlled { @@ -147,5 +173,7 @@ public: } }; + + } // Namespace #endif diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 920e634e6..9ae527e5a 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -24,44 +24,11 @@ #ifndef OPENMW_COMPONENTS_NIF_CONTROLLER_HPP #define OPENMW_COMPONENTS_NIF_CONTROLLER_HPP -#include "record.hpp" -#include "niffile.hpp" -#include "recordptr.hpp" +#include "base.hpp" namespace Nif { -class Controller : public Record -{ -public: - ControllerPtr next; - int flags; - float frequency, phase; - float timeStart, timeStop; - ControlledPtr target; - - void read(NIFStream *nif) - { - next.read(nif); - - flags = nif->getUShort(); - - frequency = nif->getFloat(); - phase = nif->getFloat(); - timeStart = nif->getFloat(); - timeStop = nif->getFloat(); - - target.read(nif); - } - - void post(NIFFile *nif) - { - Record::post(nif); - next.post(nif); - target.post(nif); - } -}; - class NiParticleSystemController : public Controller { public: diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 34ef3a34e..5efd0d6c9 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -24,73 +24,11 @@ #ifndef OPENMW_COMPONENTS_NIF_DATA_HPP #define OPENMW_COMPONENTS_NIF_DATA_HPP -#include "controlled.hpp" -#include "nifstream.hpp" -#include "nifkey.hpp" +#include "base.hpp" namespace Nif { -class NiSourceTexture : public Named -{ -public: - // Is this an external (references a separate texture file) or - // internal (data is inside the nif itself) texture? - bool external; - - std::string filename; // In case of external textures - NiPixelDataPtr data; // In case of internal textures - - /* Pixel layout - 0 - Palettised - 1 - High color 16 - 2 - True color 32 - 3 - Compressed - 4 - Bumpmap - 5 - Default */ - int pixel; - - /* Mipmap format - 0 - no - 1 - yes - 2 - default */ - int mipmap; - - /* Alpha - 0 - none - 1 - binary - 2 - smooth - 3 - default (use material alpha, or multiply material with texture if present) - */ - int alpha; - - void read(NIFStream *nif) - { - Named::read(nif); - - external = !!nif->getChar(); - if(external) - filename = nif->getString(); - else - { - nif->getChar(); // always 1 - data.read(nif); - } - - pixel = nif->getInt(); - mipmap = nif->getInt(); - alpha = nif->getInt(); - - nif->getChar(); // always 1 - } - - void post(NIFFile *nif) - { - Named::post(nif); - data.post(nif); - } -}; - // Common ancestor for several data classes class ShapeData : public Record { diff --git a/components/nif/extra.hpp b/components/nif/extra.hpp index 45c4fefc6..2913c62b0 100644 --- a/components/nif/extra.hpp +++ b/components/nif/extra.hpp @@ -24,26 +24,11 @@ #ifndef OPENMW_COMPONENTS_NIF_EXTRA_HPP #define OPENMW_COMPONENTS_NIF_EXTRA_HPP -#include "record.hpp" -#include "niffile.hpp" -#include "recordptr.hpp" +#include "base.hpp" namespace Nif { -/** A record that can have extra data. The extra data objects - themselves decend from the Extra class, and all the extra data - connected to an object form a linked list -*/ -class Extra : public Record -{ -public: - ExtraPtr extra; - - void read(NIFStream *nif) { extra.read(nif); } - void post(NIFFile *nif) { extra.post(nif); } -}; - class NiVertWeightsExtraData : public Extra { public: diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 2240d65b0..c689e27b3 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -109,6 +109,23 @@ static std::map makeFactory() ///Make the factory map used for parsing the file static const std::map factories = makeFactory(); +/// Get the file's version in a human readable form +std::string NIFFile::printVersion(unsigned int version) +{ + union ver_quad + { + uint32_t full; + uint8_t quad[4]; + } version_out; + + version_out.full = version; + + return Ogre::StringConverter::toString(version_out.quad[3]) + +"." + Ogre::StringConverter::toString(version_out.quad[2]) + +"." + Ogre::StringConverter::toString(version_out.quad[1]) + +"." + Ogre::StringConverter::toString(version_out.quad[0]); +} + void NIFFile::parse() { NIFStream nif (this, Ogre::ResourceGroupManager::getSingleton().openResource(filename)); @@ -119,10 +136,9 @@ void NIFFile::parse() fail("Invalid NIF header"); // Get BCD version - ver = nif.getInt(); + ver = nif.getUInt(); if(ver != VER_MW) - fail("Unsupported NIF version"); - + fail("Unsupported NIF version: " + printVersion(ver)); // Number of records size_t recNum = nif.getInt(); records.resize(recNum); diff --git a/components/nif/niffile.hpp b/components/nif/niffile.hpp index 108e455d7..2ef2a6fda 100644 --- a/components/nif/niffile.hpp +++ b/components/nif/niffile.hpp @@ -19,7 +19,7 @@ class NIFFile }; /// Nif file version - int ver; + unsigned int ver; /// File name, used for error messages and opening the file std::string filename; @@ -33,6 +33,10 @@ class NIFFile /// Parse the file void parse(); + /// Get the file's version in a human readable form + ///\returns A string containing a human readable NIF version number + std::string printVersion(unsigned int version); + ///Private Copy Constructor NIFFile (NIFFile const &); ///\overload @@ -74,6 +78,9 @@ public: } /// Number of roots size_t numRoots() const { return roots.size(); } + + /// Get the name of the file + std::string getFilename(){ return filename; } }; diff --git a/components/nif/nifstream.hpp b/components/nif/nifstream.hpp index 22d39b8d7..e62193a24 100644 --- a/components/nif/nifstream.hpp +++ b/components/nif/nifstream.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "niftypes.hpp" @@ -142,7 +143,8 @@ public: std::vector str (length+1, 0); if(inp->read(&str[0], length) != length) - throw std::runtime_error ("string length in NIF file does not match"); + throw std::runtime_error (": String length in NIF file "+ file->getFilename() +" does not match! Expected length: " + + Ogre::StringConverter::toString(length)); return &str[0]; } diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 01e0e9a2d..c8c0b6db9 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -4,9 +4,12 @@ #include #include "controlled.hpp" +#include "extra.hpp" #include "data.hpp" #include "property.hpp" #include "niftypes.hpp" +#include "controller.hpp" +#include "base.hpp" namespace Nif { diff --git a/components/nif/property.hpp b/components/nif/property.hpp index 06c8260ce..2c7747a3e 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -24,7 +24,7 @@ #ifndef OPENMW_COMPONENTS_NIF_PROPERTY_HPP #define OPENMW_COMPONENTS_NIF_PROPERTY_HPP -#include "controlled.hpp" +#include "base.hpp" namespace Nif {