Merge branch 'fix_niftest' into 'master'

Fix and support more features for niftest

See merge request OpenMW/openmw!2701
7220-lua-add-a-general-purpose-lexical-parser
psi29a 2 years ago
commit b44213a271

@ -33,18 +33,48 @@ bool hasExtension(const std::filesystem::path& filename, const std::string& exte
/// See if the file has the "nif" extension. /// See if the file has the "nif" extension.
bool isNIF(const std::filesystem::path& filename) bool isNIF(const std::filesystem::path& filename)
{ {
return hasExtension(filename, "nif"); return hasExtension(filename, ".nif");
} }
/// See if the file has the "bsa" extension. /// See if the file has the "bsa" extension.
bool isBSA(const std::filesystem::path& filename) bool isBSA(const std::filesystem::path& filename)
{ {
return hasExtension(filename, "bsa"); return hasExtension(filename, ".bsa");
}
std::unique_ptr<VFS::Archive> makeBsaArchive(const std::filesystem::path& path)
{
switch (Bsa::CompressedBSAFile::detectVersion(path))
{
case Bsa::BSAVER_UNKNOWN:
std::cerr << '"' << path << "\" is unknown BSA archive" << std::endl;
return nullptr;
case Bsa::BSAVER_UNCOMPRESSED:
return std::make_unique<VFS::BsaArchive>(path);
case Bsa::BSAVER_COMPRESSED:
return std::make_unique<VFS::CompressedBsaArchive>(path);
}
std::cerr << '"' << path << "\" is unsupported BSA archive" << std::endl;
return nullptr;
}
std::unique_ptr<VFS::Archive> makeArchive(const std::filesystem::path& path)
{
if (isBSA(path))
return makeBsaArchive(path);
if (std::filesystem::is_directory(path))
return std::make_unique<VFS::FileSystemArchive>(path);
return nullptr;
} }
/// Check all the nif files in a given VFS::Archive /// Check all the nif files in a given VFS::Archive
/// \note Can not read a bsa file inside of a bsa file. /// \note Can not read a bsa file inside of a bsa file.
void readVFS(std::unique_ptr<VFS::Archive>&& anArchive, const std::filesystem::path& archivePath = {}) void readVFS(std::unique_ptr<VFS::Archive>&& anArchive, const std::filesystem::path& archivePath = {})
{ {
if (anArchive == nullptr)
return;
VFS::Manager myManager(true); VFS::Manager myManager(true);
myManager.addArchive(std::move(anArchive)); myManager.addArchive(std::move(anArchive));
myManager.buildIndex(); myManager.buildIndex();
@ -65,7 +95,7 @@ void readVFS(std::unique_ptr<VFS::Archive>&& anArchive, const std::filesystem::p
if (!archivePath.empty() && !isBSA(archivePath)) if (!archivePath.empty() && !isBSA(archivePath))
{ {
// std::cout << "Reading BSA File: " << name << std::endl; // std::cout << "Reading BSA File: " << name << std::endl;
readVFS(std::make_unique<VFS::BsaArchive>(archivePath / name), archivePath / name); readVFS(makeBsaArchive(archivePath / name), archivePath / name);
// std::cout << "Done with BSA File: " << name << std::endl; // std::cout << "Done with BSA File: " << name << std::endl;
} }
} }
@ -77,7 +107,8 @@ void readVFS(std::unique_ptr<VFS::Archive>&& anArchive, const std::filesystem::p
} }
} }
bool parseOptions(int argc, char** argv, std::vector<Files::MaybeQuotedPath>& files) bool parseOptions(int argc, char** argv, std::vector<Files::MaybeQuotedPath>& files, bool& writeDebugLog,
std::vector<Files::MaybeQuotedPath>& archives)
{ {
bpo::options_description desc(R"(Ensure that OpenMW can use the provided NIF and BSA files bpo::options_description desc(R"(Ensure that OpenMW can use the provided NIF and BSA files
@ -88,6 +119,8 @@ Usages:
Allowed options)"); Allowed options)");
auto addOption = desc.add_options(); auto addOption = desc.add_options();
addOption("help,h", "print help message."); addOption("help,h", "print help message.");
addOption("write-debug-log,v", "write debug log for unsupported nif files");
addOption("archives", bpo::value<Files::MaybeQuotedPathContainer>(), "path to archive files to provide files");
addOption("input-file", bpo::value<Files::MaybeQuotedPathContainer>(), "input file"); addOption("input-file", bpo::value<Files::MaybeQuotedPathContainer>(), "input file");
// Default option if none provided // Default option if none provided
@ -105,9 +138,12 @@ Allowed options)");
std::cout << desc << std::endl; std::cout << desc << std::endl;
return false; return false;
} }
writeDebugLog = variables.count("write-debug-log") > 0;
if (variables.count("input-file")) if (variables.count("input-file"))
{ {
files = variables["input-file"].as<Files::MaybeQuotedPathContainer>(); files = variables["input-file"].as<Files::MaybeQuotedPathContainer>();
if (const auto it = variables.find("archives"); it != variables.end())
archives = it->second.as<Files::MaybeQuotedPathContainer>();
return true; return true;
} }
} }
@ -125,10 +161,26 @@ Allowed options)");
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
std::vector<Files::MaybeQuotedPath> files; std::vector<Files::MaybeQuotedPath> files;
if (!parseOptions(argc, argv, files)) bool writeDebugLog = false;
std::vector<Files::MaybeQuotedPath> archives;
if (!parseOptions(argc, argv, files, writeDebugLog, archives))
return 1; return 1;
Nif::Reader::setLoadUnsupportedFiles(true); Nif::Reader::setLoadUnsupportedFiles(true);
Nif::Reader::setWriteNifDebugLog(writeDebugLog);
std::unique_ptr<VFS::Manager> vfs;
if (!archives.empty())
{
vfs = std::make_unique<VFS::Manager>(true);
for (const std::filesystem::path& path : archives)
if (auto archive = makeArchive(path))
vfs->addArchive(std::move(archive));
else
std::cerr << '"' << path << "\" is unsupported archive" << std::endl;
vfs->buildIndex();
}
// std::cout << "Reading Files" << std::endl; // std::cout << "Reading Files" << std::endl;
for (const auto& path : files) for (const auto& path : files)
{ {
@ -139,17 +191,14 @@ int main(int argc, char** argv)
// std::cout << "Decoding: " << name << std::endl; // std::cout << "Decoding: " << name << std::endl;
Nif::NIFFile file(path); Nif::NIFFile file(path);
Nif::Reader reader(file); Nif::Reader reader(file);
reader.parse(Files::openConstrainedFileStream(path)); if (vfs != nullptr)
} reader.parse(vfs->get(Files::pathToUnicodeString(path)));
else if (isBSA(path)) else
{ reader.parse(Files::openConstrainedFileStream(path));
// std::cout << "Reading BSA File: " << name << std::endl;
readVFS(std::make_unique<VFS::BsaArchive>(path));
} }
else if (std::filesystem::is_directory(path)) else if (auto archive = makeArchive(path))
{ {
// std::cout << "Reading All Files in: " << name << std::endl; readVFS(std::move(archive), path);
readVFS(std::make_unique<VFS::FileSystemArchive>(path), path);
} }
else else
{ {

@ -600,6 +600,7 @@ namespace MWRender
NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor); NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor);
NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect); NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect);
Nif::Reader::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models")); Nif::Reader::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models"));
Nif::Reader::setWriteNifDebugLog(Settings::Manager::getBool("write nif debug log", "Models"));
mStateUpdater->setFogEnd(mViewDistance); mStateUpdater->setFogEnd(mViewDistance);

@ -220,13 +220,14 @@ namespace Nif
NIFFile::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();
const bool writeDebugLog = sWriteNifDebugLog;
if (!supportedVersion) if (!supportedVersion)
{ {
if (sLoadUnsupportedFiles) if (!sLoadUnsupportedFiles)
throw Nif::Exception("Unsupported NIF version: " + printVersion(ver), filename);
if (writeDebugLog)
Log(Debug::Warning) << " NIFFile Warning: Unsupported NIF version: " << printVersion(ver) Log(Debug::Warning) << " NIFFile Warning: Unsupported NIF version: " << printVersion(ver)
<< ". Proceed with caution! File: " << filename; << ". Proceed with caution! File: " << filename;
else
throw Nif::Exception("Unsupported NIF version: " + printVersion(ver), filename);
} }
// NIF data endianness // NIF data endianness
@ -322,7 +323,7 @@ namespace Nif
r = entry->second(); r = entry->second();
if (!supportedVersion) if (!supportedVersion && writeDebugLog)
Log(Debug::Verbose) << "NIF Debug: Reading record of type " << rec << ", index " << i << " (" Log(Debug::Verbose) << "NIF Debug: Reading record of type " << rec << ", index " << i << " ("
<< filename << ")"; << filename << ")";
@ -364,12 +365,18 @@ namespace Nif
} }
std::atomic_bool Reader::sLoadUnsupportedFiles = false; std::atomic_bool Reader::sLoadUnsupportedFiles = false;
std::atomic_bool Reader::sWriteNifDebugLog = false;
void Reader::setLoadUnsupportedFiles(bool load) void Reader::setLoadUnsupportedFiles(bool load)
{ {
sLoadUnsupportedFiles = load; sLoadUnsupportedFiles = load;
} }
void Reader::setWriteNifDebugLog(bool value)
{
sWriteNifDebugLog = value;
}
std::string Reader::getString(std::uint32_t index) const std::string Reader::getString(std::uint32_t index) const
{ {
if (index == std::numeric_limits<std::uint32_t>::max()) if (index == std::numeric_limits<std::uint32_t>::max())

@ -110,6 +110,7 @@ namespace Nif
bool& mUseSkinning; bool& mUseSkinning;
static std::atomic_bool sLoadUnsupportedFiles; static std::atomic_bool sLoadUnsupportedFiles;
static std::atomic_bool sWriteNifDebugLog;
/// 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
@ -145,6 +146,8 @@ namespace Nif
unsigned int getBethVersion() const { return bethVer; } unsigned int getBethVersion() const { return bethVer; }
static void setLoadUnsupportedFiles(bool load); static void setLoadUnsupportedFiles(bool load);
static void setWriteNifDebugLog(bool load);
}; };
using NIFFilePtr = std::shared_ptr<const Nif::NIFFile>; using NIFFilePtr = std::shared_ptr<const Nif::NIFFile>;

@ -263,3 +263,13 @@ weatherblizzard
Path to the file used for the blizzard clouds weather effect in Morrowind. Path to the file used for the blizzard clouds weather effect in Morrowind.
OpenMW doesn't use this file, instead it renders a similar looking particle OpenMW doesn't use this file, instead it renders a similar looking particle
effect. Changing this won't have any effect. effect. Changing this won't have any effect.
write nif debug log
-------------------
:Type: boolean
:Range: True/False
:Default: True
If enabled, log the loading process of unsupported NIF files.
:ref:`load unsupported nif files` setting must be enabled for this setting to have any effect.

@ -1116,6 +1116,9 @@ weathersnow = meshes/snow.nif
# Blizzard weather effect # Blizzard weather effect
weatherblizzard = meshes/blizzard.nif weatherblizzard = meshes/blizzard.nif
# Enable to write logs when loading unsupported nif file
write nif debug log = true
[Groundcover] [Groundcover]
# enable separate groundcover handling # enable separate groundcover handling

Loading…
Cancel
Save