1 ///Main header for reading .nif files 2 3 #ifndef OPENMW_COMPONENTS_NIF_NIFFILE_HPP 4 #define OPENMW_COMPONENTS_NIF_NIFFILE_HPP 5 6 #include <stdexcept> 7 #include <vector> 8 9 #include <components/debug/debuglog.hpp> 10 #include <components/files/constrainedfilestream.hpp> 11 12 #include "record.hpp" 13 14 namespace Nif 15 { 16 17 struct File 18 { 19 virtual ~File() = default; 20 21 virtual Record *getRecord(size_t index) const = 0; 22 23 virtual size_t numRecords() const = 0; 24 25 virtual Record *getRoot(size_t index = 0) const = 0; 26 27 virtual size_t numRoots() const = 0; 28 29 virtual std::string getString(uint32_t index) const = 0; 30 31 virtual void setUseSkinning(bool skinning) = 0; 32 33 virtual bool getUseSkinning() const = 0; 34 35 virtual std::string getFilename() const = 0; 36 37 virtual unsigned int getVersion() const = 0; 38 39 virtual unsigned int getUserVersion() const = 0; 40 41 virtual unsigned int getBethVersion() const = 0; 42 }; 43 44 class NIFFile final : public File 45 { 46 /// File version, user version, Bethesda version 47 unsigned int ver = 0; 48 unsigned int userVer = 0; 49 unsigned int bethVer = 0; 50 51 /// File name, used for error messages and opening the file 52 std::string filename; 53 54 /// Record list 55 std::vector<Record*> records; 56 57 /// Root list. This is a select portion of the pointers from records 58 std::vector<Record*> roots; 59 60 /// String table 61 std::vector<std::string> strings; 62 63 bool mUseSkinning = false; 64 65 static bool sLoadUnsupportedFiles; 66 67 /// Parse the file 68 void parse(Files::IStreamPtr stream); 69 70 /// Get the file's version in a human readable form 71 ///\returns A string containing a human readable NIF version number 72 std::string printVersion(unsigned int version); 73 74 ///Private Copy Constructor 75 NIFFile (NIFFile const &); 76 ///\overload 77 void operator = (NIFFile const &); 78 79 public: 80 // For generic versions NIFStream::generateVersion() is used instead 81 enum NIFVersion 82 { 83 VER_MW = 0x04000002, // 4.0.0.2. Main Morrowind NIF version. 84 VER_OB_OLD = 0x0A000102, // 10.0.1.2. Main older Oblivion NIF version. 85 VER_OB = 0x14000005, // 20.0.0.5. Main Oblivion NIF version. 86 VER_BGS = 0x14020007 // 20.2.0.7. Main Fallout 3/4/76/New Vegas and Skyrim/SkyrimSE NIF version. 87 }; 88 enum BethVersion 89 { 90 BETHVER_FO3 = 34, // Fallout 3 91 BETHVER_FO4 = 130 // Fallout 4 92 }; 93 94 /// Used if file parsing fails fail(const std::string & msg) const95 void fail(const std::string &msg) const 96 { 97 std::string err = " NIFFile Error: " + msg; 98 err += "\nFile: " + filename; 99 throw std::runtime_error(err); 100 } 101 /// Used when something goes wrong, but not catastrophically so warn(const std::string & msg) const102 void warn(const std::string &msg) const 103 { 104 Log(Debug::Warning) << " NIFFile Warning: " << msg << "\nFile: " << filename; 105 } 106 107 /// Open a NIF stream. The name is used for error messages. 108 NIFFile(Files::IStreamPtr stream, const std::string &name); 109 ~NIFFile(); 110 111 /// Get a given record getRecord(size_t index) const112 Record *getRecord(size_t index) const override 113 { 114 Record *res = records.at(index); 115 return res; 116 } 117 /// Number of records numRecords() const118 size_t numRecords() const override { return records.size(); } 119 120 /// Get a given root getRoot(size_t index=0) const121 Record *getRoot(size_t index=0) const override 122 { 123 Record *res = roots.at(index); 124 return res; 125 } 126 /// Number of roots numRoots() const127 size_t numRoots() const override { return roots.size(); } 128 129 /// Get a given string from the file's string table getString(uint32_t index) const130 std::string getString(uint32_t index) const override 131 { 132 if (index == std::numeric_limits<uint32_t>::max()) 133 return std::string(); 134 return strings.at(index); 135 } 136 137 /// Set whether there is skinning contained in this NIF file. 138 /// @note This is just a hint for users of the NIF file and has no effect on the loading procedure. 139 void setUseSkinning(bool skinning) override; 140 141 bool getUseSkinning() const override; 142 143 /// Get the name of the file getFilename() const144 std::string getFilename() const override { return filename; } 145 146 /// Get the version of the NIF format used getVersion() const147 unsigned int getVersion() const override { return ver; } 148 149 /// Get the user version of the NIF format used getUserVersion() const150 unsigned int getUserVersion() const override { return userVer; } 151 152 /// Get the Bethesda version of the NIF format used getBethVersion() const153 unsigned int getBethVersion() const override { return bethVer; } 154 155 static void setLoadUnsupportedFiles(bool load); 156 }; 157 using NIFFilePtr = std::shared_ptr<const Nif::NIFFile>; 158 159 160 161 } // Namespace 162 #endif 163