Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
8.8 kB · 206 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207#include <components/debug/debugging.hpp>#include <components/debug/debuglog.hpp>#include <components/esm/defs.hpp>#include <components/esm3/loadcell.hpp>#include <components/esm3/readerscache.hpp>#include <components/esmloader/esmdata.hpp>#include <components/esmloader/load.hpp>#include <components/fallback/fallback.hpp>#include <components/fallback/validate.hpp>#include <components/files/collections.hpp>#include <components/files/configurationmanager.hpp>#include <components/files/multidircollection.hpp>#include <components/misc/strings/conversion.hpp>#include <components/platform/platform.hpp>#include <components/resource/bgsmfilemanager.hpp>#include <components/resource/bulletshape.hpp>#include <components/resource/bulletshapemanager.hpp>#include <components/resource/foreachbulletobject.hpp>#include <components/resource/imagemanager.hpp>#include <components/resource/niffilemanager.hpp>#include <components/resource/scenemanager.hpp>#include <components/settings/settings.hpp>#include <components/toutf8/toutf8.hpp>#include <components/version/version.hpp>#include <components/vfs/manager.hpp>#include <components/vfs/registerarchives.hpp>
#include <boost/program_options.hpp>
#include <charconv>#include <cstddef>#include <cstdint>#include <filesystem>#include <iomanip>#include <limits>#include <map>#include <memory>#include <ostream>#include <string>#include <string_view>#include <system_error>#include <type_traits>#include <utility>#include <vector>
namespace{ namespace bpo = boost::program_options;
using StringsVector = std::vector<std::string>;
constexpr std::string_view applicationName = "BulletObjectTool";
bpo::options_description makeOptionsDescription() { bpo::options_description result; auto addOption = result.add_options(); addOption("help", "print help message");
addOption("version", "print version information and quit");
addOption("data", bpo::value<Files::MaybeQuotedPathContainer>() ->default_value(Files::MaybeQuotedPathContainer(), "data") ->multitoken() ->composing(), "set data directories (later directories have higher priority)");
addOption("data-local", bpo::value<Files::MaybeQuotedPathContainer::value_type>()->default_value( Files::MaybeQuotedPathContainer::value_type(), ""), "set local data directory (highest priority)");
addOption("fallback-archive", bpo::value<StringsVector>()->default_value(StringsVector(), "fallback-archive")->multitoken()->composing(), "set fallback BSA archives (later archives have higher priority)");
addOption("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")->multitoken()->composing(), "content file(s): esm/esp, or omwgame/omwaddon/omwscripts");
addOption("encoding", bpo::value<std::string>()->default_value("win1252"), "Character encoding used in OpenMW game messages:\n" "\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, " "Croatian, Serbian (Latin script), Romanian and Albanian languages\n" "\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n" "\n\twin1252 - Western European (Latin) alphabet, used by default");
addOption("fallback", bpo::value<Fallback::FallbackMap>()->default_value(Fallback::FallbackMap(), "")->multitoken()->composing(), "fallback values");
Files::ConfigurationManager::addCommonOptions(result);
return result; }
struct WriteArray { const float (&mValue)[3];
friend std::ostream& operator<<(std::ostream& stream, const WriteArray& value) { for (std::size_t i = 0; i < 2; ++i) stream << std::setprecision(std::numeric_limits<float>::max_exponent10) << value.mValue[i] << ", "; return stream << std::setprecision(std::numeric_limits<float>::max_exponent10) << value.mValue[2]; } };
int runBulletObjectTool(int argc, char* argv[]) { Platform::init();
bpo::options_description desc = makeOptionsDescription();
bpo::parsed_options options = bpo::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); bpo::variables_map variables;
bpo::store(options, variables); bpo::notify(variables);
if (variables.find("help") != variables.end()) { Debug::getRawStdout() << desc << std::endl; return 0; }
Files::ConfigurationManager config; config.processPaths(variables, std::filesystem::current_path()); config.readConfiguration(variables, desc);
Debug::setupLogging(config.getLogPath(), applicationName);
const std::string encoding(variables["encoding"].as<std::string>()); Log(Debug::Info) << ToUTF8::encodingUsingMessage(encoding); ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(encoding));
Files::PathContainer dataDirs(asPathContainer(variables["data"].as<Files::MaybeQuotedPathContainer>()));
auto local = variables["data-local"].as<Files::MaybeQuotedPathContainer::value_type>(); if (!local.empty()) dataDirs.push_back(std::move(local));
config.filterOutNonExistingPaths(dataDirs);
const auto& resDir = variables["resources"].as<Files::MaybeQuotedPath>(); Log(Debug::Info) << Version::getOpenmwVersionDescription(); dataDirs.insert(dataDirs.begin(), resDir / "vfs"); const Files::Collections fileCollections(dataDirs); const auto& archives = variables["fallback-archive"].as<StringsVector>(); StringsVector contentFiles{ "builtin.omwscripts" }; const auto& configContentFiles = variables["content"].as<StringsVector>(); contentFiles.insert(contentFiles.end(), configContentFiles.begin(), configContentFiles.end());
Fallback::Map::init(variables["fallback"].as<Fallback::FallbackMap>().mMap);
VFS::Manager vfs;
VFS::registerArchives(&vfs, fileCollections, archives, true, &encoder.getStatelessEncoder());
Settings::Manager::load(config);
ESM::ReadersCache readers; EsmLoader::Query query; query.mLoadActivators = true; query.mLoadCells = true; query.mLoadContainers = true; query.mLoadDoors = true; query.mLoadGameSettings = true; query.mLoadLands = true; query.mLoadStatics = true; const EsmLoader::EsmData esmData = EsmLoader::loadEsmData(query, contentFiles, fileCollections, readers, &encoder);
constexpr double expiryDelay = 0; Resource::ImageManager imageManager(&vfs, expiryDelay); Resource::NifFileManager nifFileManager(&vfs, &encoder.getStatelessEncoder()); Resource::BgsmFileManager bgsmFileManager(&vfs, expiryDelay); Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager, &bgsmFileManager, expiryDelay); Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager, expiryDelay);
Resource::forEachBulletObject( readers, vfs, bulletShapeManager, esmData, [](const ESM::Cell& cell, const Resource::BulletObject& object) { Log(Debug::Verbose) << "Found bullet object in " << (cell.isExterior() ? "exterior" : "interior") << " cell \"" << cell.getDescription() << "\":" << " fileName=\"" << object.mShape->mFileName << '"' << " fileHash=" << Misc::StringUtils::toHex(object.mShape->mFileHash) << " collisionShape=" << std::boolalpha << (object.mShape->mCollisionShape == nullptr) << " avoidCollisionShape=" << std::boolalpha << (object.mShape->mAvoidCollisionShape == nullptr) << " position=(" << WriteArray{ object.mPosition.pos } << ')' << " rotation=(" << WriteArray{ object.mPosition.rot } << ')' << " scale=" << std::setprecision(std::numeric_limits<float>::max_exponent10) << object.mScale; });
Log(Debug::Info) << "Done";
return 0; }}
int main(int argc, char* argv[]){ return Debug::wrapApplication(runBulletObjectTool, argc, argv, applicationName);}