mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-28 21:07:59 +03:00
Apply clang-format to code base
This commit is contained in:
parent
f37d0be806
commit
ddb0522bbf
2199 changed files with 118692 additions and 114392 deletions
|
@ -56,11 +56,16 @@ namespace
|
||||||
{
|
{
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
case 0: return AreaType_null;
|
case 0:
|
||||||
case 1: return AreaType_water;
|
return AreaType_null;
|
||||||
case 2: return AreaType_door;
|
case 1:
|
||||||
case 3: return AreaType_pathgrid;
|
return AreaType_water;
|
||||||
case 4: return AreaType_ground;
|
case 2:
|
||||||
|
return AreaType_door;
|
||||||
|
case 3:
|
||||||
|
return AreaType_pathgrid;
|
||||||
|
case 4:
|
||||||
|
return AreaType_ground;
|
||||||
}
|
}
|
||||||
return AreaType_null;
|
return AreaType_null;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +102,8 @@ namespace
|
||||||
if (distribution(random) < 0.939)
|
if (distribution(random) < 0.939)
|
||||||
{
|
{
|
||||||
generateVertices(std::back_inserter(vertices), triangles * 2.467, random);
|
generateVertices(std::back_inserter(vertices), triangles * 2.467, random);
|
||||||
generateIndices(std::back_inserter(indices), static_cast<int>(vertices.size() / 3) - 1, vertices.size() * 1.279, random);
|
generateIndices(std::back_inserter(indices), static_cast<int>(vertices.size() / 3) - 1,
|
||||||
|
vertices.size() * 1.279, random);
|
||||||
generateAreaTypes(std::back_inserter(areaTypes), indices.size() / 3, random);
|
generateAreaTypes(std::back_inserter(areaTypes), indices.size() / 3, random);
|
||||||
}
|
}
|
||||||
return Mesh(std::move(indices), std::move(vertices), std::move(areaTypes));
|
return Mesh(std::move(indices), std::move(vertices), std::move(areaTypes));
|
||||||
|
@ -113,10 +119,8 @@ namespace
|
||||||
result.mMinHeight = distribution(random);
|
result.mMinHeight = distribution(random);
|
||||||
result.mMaxHeight = result.mMinHeight + 1.0;
|
result.mMaxHeight = result.mMinHeight + 1.0;
|
||||||
result.mLength = static_cast<std::uint8_t>(ESM::Land::LAND_SIZE);
|
result.mLength = static_cast<std::uint8_t>(ESM::Land::LAND_SIZE);
|
||||||
std::generate_n(std::back_inserter(result.mHeights), ESM::Land::LAND_NUM_VERTS, [&]
|
std::generate_n(
|
||||||
{
|
std::back_inserter(result.mHeights), ESM::Land::LAND_NUM_VERTS, [&] { return distribution(random); });
|
||||||
return distribution(random);
|
|
||||||
});
|
|
||||||
result.mOriginalSize = ESM::Land::LAND_SIZE;
|
result.mOriginalSize = ESM::Land::LAND_SIZE;
|
||||||
result.mMinX = 0;
|
result.mMinX = 0;
|
||||||
result.mMinY = 0;
|
result.mMinY = 0;
|
||||||
|
@ -147,8 +151,8 @@ namespace
|
||||||
Mesh mesh = generateMesh(triangles, random);
|
Mesh mesh = generateMesh(triangles, random);
|
||||||
std::vector<CellWater> water;
|
std::vector<CellWater> water;
|
||||||
generateWater(std::back_inserter(water), 1, random);
|
generateWater(std::back_inserter(water), 1, random);
|
||||||
RecastMesh recastMesh(version, std::move(mesh), std::move(water),
|
RecastMesh recastMesh(version, std::move(mesh), std::move(water), { generateHeightfield(random) },
|
||||||
{generateHeightfield(random)}, {generateFlatHeightfield(random)}, {});
|
{ generateFlatHeightfield(random) }, {});
|
||||||
return Key{ AgentBounds{ agentShapeType, agentHalfExtents }, tilePosition, std::move(recastMesh) };
|
return Key{ AgentBounds{ agentShapeType, agentHalfExtents }, tilePosition, std::move(recastMesh) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,8 +172,7 @@ namespace
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Key key = generateKey(trianglesPerTile, random);
|
Key key = generateKey(trianglesPerTile, random);
|
||||||
cache.set(key.mAgentBounds, key.mTilePosition, key.mRecastMesh,
|
cache.set(key.mAgentBounds, key.mTilePosition, key.mRecastMesh, std::make_unique<PreparedNavMeshData>());
|
||||||
std::make_unique<PreparedNavMeshData>());
|
|
||||||
*out++ = std::move(key);
|
*out++ = std::move(key);
|
||||||
const std::size_t newSize = cache.getStats().mNavMeshCacheSize;
|
const std::size_t newSize = cache.getStats().mNavMeshCacheSize;
|
||||||
if (size >= newSize)
|
if (size >= newSize)
|
||||||
|
@ -250,8 +253,8 @@ namespace
|
||||||
while (state.KeepRunning())
|
while (state.KeepRunning())
|
||||||
{
|
{
|
||||||
const auto& key = keys[n++ % keys.size()];
|
const auto& key = keys[n++ % keys.size()];
|
||||||
const auto result = cache.set(key.mAgentBounds, key.mTilePosition, key.mRecastMesh,
|
const auto result = cache.set(
|
||||||
std::make_unique<PreparedNavMeshData>());
|
key.mAgentBounds, key.mTilePosition, key.mRecastMesh, std::make_unique<PreparedNavMeshData>());
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
#include <components/bsa/compressedbsafile.hpp>
|
#include <components/bsa/compressedbsafile.hpp>
|
||||||
#include <components/misc/strings/algorithm.hpp>
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/files/conversion.hpp>
|
#include <components/files/conversion.hpp>
|
||||||
|
#include <components/misc/strings/algorithm.hpp>
|
||||||
#include <components/misc/strings/conversion.hpp>
|
#include <components/misc/strings/conversion.hpp>
|
||||||
|
|
||||||
#define BSATOOL_VERSION 1.1
|
#define BSATOOL_VERSION 1.1
|
||||||
|
@ -73,14 +73,12 @@ Allowed options)");
|
||||||
bpo::variables_map variables;
|
bpo::variables_map variables;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv)
|
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).options(all).positional(p).run();
|
||||||
.options(all).positional(p).run();
|
|
||||||
bpo::store(valid_opts, variables);
|
bpo::store(valid_opts, variables);
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n"
|
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n" << desc << std::endl;
|
||||||
<< desc << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,28 +96,27 @@ Allowed options)");
|
||||||
}
|
}
|
||||||
if (!variables.count("mode"))
|
if (!variables.count("mode"))
|
||||||
{
|
{
|
||||||
std::cout << "ERROR: no mode specified!\n\n"
|
std::cout << "ERROR: no mode specified!\n\n" << desc << std::endl;
|
||||||
<< desc << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.mode = variables["mode"].as<std::string>();
|
info.mode = variables["mode"].as<std::string>();
|
||||||
if (!(info.mode == "list" || info.mode == "extract" || info.mode == "extractall" || info.mode == "add" || info.mode == "create"))
|
if (!(info.mode == "list" || info.mode == "extract" || info.mode == "extractall" || info.mode == "add"
|
||||||
|
|| info.mode == "create"))
|
||||||
{
|
{
|
||||||
std::cout << std::endl << "ERROR: invalid mode \"" << info.mode << "\"\n\n"
|
std::cout << std::endl << "ERROR: invalid mode \"" << info.mode << "\"\n\n" << desc << std::endl;
|
||||||
<< desc << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!variables.count("input-file"))
|
if (!variables.count("input-file"))
|
||||||
{
|
{
|
||||||
std::cout << "\nERROR: missing BSA archive\n\n"
|
std::cout << "\nERROR: missing BSA archive\n\n" << desc << std::endl;
|
||||||
<< desc << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto inputFiles = variables["input-file"].as<Files::MaybeQuotedPathContainer>();
|
auto inputFiles = variables["input-file"].as<Files::MaybeQuotedPathContainer>();
|
||||||
|
|
||||||
info.filename = inputFiles[0].u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
info.filename = inputFiles[0].u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26
|
||||||
|
// due to implementation bugs.
|
||||||
|
|
||||||
// Default output to the working directory
|
// Default output to the working directory
|
||||||
info.outdir = std::filesystem::current_path();
|
info.outdir = std::filesystem::current_path();
|
||||||
|
@ -128,28 +125,30 @@ Allowed options)");
|
||||||
{
|
{
|
||||||
if (inputFiles.size() < 2)
|
if (inputFiles.size() < 2)
|
||||||
{
|
{
|
||||||
std::cout << "\nERROR: file to extract unspecified\n\n"
|
std::cout << "\nERROR: file to extract unspecified\n\n" << desc << std::endl;
|
||||||
<< desc << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (inputFiles.size() > 1)
|
if (inputFiles.size() > 1)
|
||||||
info.extractfile = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
info.extractfile = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on
|
||||||
|
// MSVC 14.26 due to implementation bugs.
|
||||||
if (inputFiles.size() > 2)
|
if (inputFiles.size() > 2)
|
||||||
info.outdir = inputFiles[2].u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
info.outdir = inputFiles[2].u8string(); // This call to u8string is redundant, but required to build on
|
||||||
|
// MSVC 14.26 due to implementation bugs.
|
||||||
}
|
}
|
||||||
else if (info.mode == "add")
|
else if (info.mode == "add")
|
||||||
{
|
{
|
||||||
if (inputFiles.empty())
|
if (inputFiles.empty())
|
||||||
{
|
{
|
||||||
std::cout << "\nERROR: file to add unspecified\n\n"
|
std::cout << "\nERROR: file to add unspecified\n\n" << desc << std::endl;
|
||||||
<< desc << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (inputFiles.size() > 1)
|
if (inputFiles.size() > 1)
|
||||||
info.addfile = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
info.addfile = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on
|
||||||
|
// MSVC 14.26 due to implementation bugs.
|
||||||
}
|
}
|
||||||
else if (inputFiles.size() > 1)
|
else if (inputFiles.size() > 1)
|
||||||
info.outdir = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
info.outdir = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on
|
||||||
|
// MSVC 14.26 due to implementation bugs.
|
||||||
|
|
||||||
info.longformat = variables.count("long") != 0;
|
info.longformat = variables.count("long") != 0;
|
||||||
info.fullpath = variables.count("full-path") != 0;
|
info.fullpath = variables.count("full-path") != 0;
|
||||||
|
@ -221,14 +220,16 @@ int extract(std::unique_ptr<File>& bsa, Arguments& info)
|
||||||
std::filesystem::file_status s = std::filesystem::status(target.parent_path());
|
std::filesystem::file_status s = std::filesystem::status(target.parent_path());
|
||||||
if (!std::filesystem::is_directory(s))
|
if (!std::filesystem::is_directory(s))
|
||||||
{
|
{
|
||||||
std::cout << "ERROR: " << Files::pathToUnicodeString(target.parent_path()) << " is not a directory." << std::endl;
|
std::cout << "ERROR: " << Files::pathToUnicodeString(target.parent_path()) << " is not a directory."
|
||||||
|
<< std::endl;
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream out(target, std::ios::binary);
|
std::ofstream out(target, std::ios::binary);
|
||||||
|
|
||||||
// Write the file to disk
|
// Write the file to disk
|
||||||
std::cout << "Extracting " << Files::pathToUnicodeString(info.extractfile) << " to " << Files::pathToUnicodeString(target) << std::endl;
|
std::cout << "Extracting " << Files::pathToUnicodeString(info.extractfile) << " to "
|
||||||
|
<< Files::pathToUnicodeString(target) << std::endl;
|
||||||
|
|
||||||
out << stream->rdbuf();
|
out << stream->rdbuf();
|
||||||
out.close();
|
out.close();
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
#include <components/debug/debugging.hpp>
|
#include <components/debug/debugging.hpp>
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
#include <components/esm3/loadcell.hpp>
|
#include <components/esm3/loadcell.hpp>
|
||||||
|
#include <components/esm3/readerscache.hpp>
|
||||||
#include <components/esmloader/esmdata.hpp>
|
#include <components/esmloader/esmdata.hpp>
|
||||||
#include <components/esmloader/load.hpp>
|
#include <components/esmloader/load.hpp>
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
#include <components/fallback/validate.hpp>
|
#include <components/fallback/validate.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
#include <components/platform/platform.hpp>
|
||||||
#include <components/resource/bulletshapemanager.hpp>
|
#include <components/resource/bulletshapemanager.hpp>
|
||||||
#include <components/resource/foreachbulletobject.hpp>
|
#include <components/resource/foreachbulletobject.hpp>
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
|
@ -15,8 +17,6 @@
|
||||||
#include <components/version/version.hpp>
|
#include <components/version/version.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
#include <components/vfs/registerarchives.hpp>
|
#include <components/vfs/registerarchives.hpp>
|
||||||
#include <components/esm3/readerscache.hpp>
|
|
||||||
#include <components/platform/platform.hpp>
|
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
namespace bpo = boost::program_options;
|
namespace bpo = boost::program_options;
|
||||||
|
@ -44,33 +43,41 @@ namespace
|
||||||
|
|
||||||
addOption("version", "print version information and quit");
|
addOption("version", "print version information and quit");
|
||||||
|
|
||||||
addOption("data", bpo::value<Files::MaybeQuotedPathContainer>()->default_value(Files::MaybeQuotedPathContainer(), "data")
|
addOption("data",
|
||||||
->multitoken()->composing(), "set data directories (later directories have higher priority)");
|
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(), ""),
|
addOption("data-local",
|
||||||
|
bpo::value<Files::MaybeQuotedPathContainer::value_type>()->default_value(
|
||||||
|
Files::MaybeQuotedPathContainer::value_type(), ""),
|
||||||
"set local data directory (highest priority)");
|
"set local data directory (highest priority)");
|
||||||
|
|
||||||
addOption("fallback-archive", bpo::value<StringsVector>()->default_value(StringsVector(), "fallback-archive")
|
addOption("fallback-archive",
|
||||||
->multitoken()->composing(), "set fallback BSA archives (later archives have higher priority)");
|
bpo::value<StringsVector>()->default_value(StringsVector(), "fallback-archive")->multitoken()->composing(),
|
||||||
|
"set fallback BSA archives (later archives have higher priority)");
|
||||||
|
|
||||||
addOption("resources", bpo::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), "resources"),
|
addOption("resources",
|
||||||
|
bpo::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), "resources"),
|
||||||
"set resources directory");
|
"set resources directory");
|
||||||
|
|
||||||
addOption("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
addOption("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")->multitoken()->composing(),
|
||||||
->multitoken()->composing(), "content file(s): esm/esp, or omwgame/omwaddon/omwscripts");
|
"content file(s): esm/esp, or omwgame/omwaddon/omwscripts");
|
||||||
|
|
||||||
addOption("fs-strict", bpo::value<bool>()->implicit_value(true)
|
addOption("fs-strict", bpo::value<bool>()->implicit_value(true)->default_value(false),
|
||||||
->default_value(false), "strict file system handling (no case folding)");
|
"strict file system handling (no case folding)");
|
||||||
|
|
||||||
addOption("encoding", bpo::value<std::string>()->
|
addOption("encoding", bpo::value<std::string>()->default_value("win1252"),
|
||||||
default_value("win1252"),
|
|
||||||
"Character encoding used in OpenMW game messages:\n"
|
"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\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\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n"
|
||||||
"\n\twin1252 - Western European (Latin) alphabet, used by default");
|
"\n\twin1252 - Western European (Latin) alphabet, used by default");
|
||||||
|
|
||||||
addOption("fallback", bpo::value<FallbackMap>()->default_value(FallbackMap(), "")
|
addOption("fallback", bpo::value<FallbackMap>()->default_value(FallbackMap(), "")->multitoken()->composing(),
|
||||||
->multitoken()->composing(), "fallback values");
|
"fallback values");
|
||||||
;
|
;
|
||||||
Files::ConfigurationManager::addCommonOptions(result);
|
Files::ConfigurationManager::addCommonOptions(result);
|
||||||
|
|
||||||
|
@ -110,8 +117,7 @@ namespace
|
||||||
|
|
||||||
bpo::options_description desc = makeOptionsDescription();
|
bpo::options_description desc = makeOptionsDescription();
|
||||||
|
|
||||||
bpo::parsed_options options = bpo::command_line_parser(argc, argv)
|
bpo::parsed_options options = bpo::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||||
.options(desc).allow_unregistered().run();
|
|
||||||
bpo::variables_map variables;
|
bpo::variables_map variables;
|
||||||
|
|
||||||
bpo::store(options, variables);
|
bpo::store(options, variables);
|
||||||
|
@ -168,25 +174,28 @@ namespace
|
||||||
query.mLoadGameSettings = true;
|
query.mLoadGameSettings = true;
|
||||||
query.mLoadLands = true;
|
query.mLoadLands = true;
|
||||||
query.mLoadStatics = true;
|
query.mLoadStatics = true;
|
||||||
const EsmLoader::EsmData esmData = EsmLoader::loadEsmData(query, contentFiles, fileCollections, readers, &encoder);
|
const EsmLoader::EsmData esmData
|
||||||
|
= EsmLoader::loadEsmData(query, contentFiles, fileCollections, readers, &encoder);
|
||||||
|
|
||||||
Resource::ImageManager imageManager(&vfs);
|
Resource::ImageManager imageManager(&vfs);
|
||||||
Resource::NifFileManager nifFileManager(&vfs);
|
Resource::NifFileManager nifFileManager(&vfs);
|
||||||
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager);
|
Resource::SceneManager sceneManager(&vfs, &imageManager, &nifFileManager);
|
||||||
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager);
|
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager);
|
||||||
|
|
||||||
Resource::forEachBulletObject(readers, vfs, bulletShapeManager, esmData,
|
Resource::forEachBulletObject(
|
||||||
[] (const ESM::Cell& cell, const Resource::BulletObject& object)
|
readers, vfs, bulletShapeManager, esmData, [](const ESM::Cell& cell, const Resource::BulletObject& object) {
|
||||||
{
|
|
||||||
Log(Debug::Verbose) << "Found bullet object in " << (cell.isExterior() ? "exterior" : "interior")
|
Log(Debug::Verbose) << "Found bullet object in " << (cell.isExterior() ? "exterior" : "interior")
|
||||||
<< " cell \"" << cell.getDescription() << "\":"
|
<< " cell \"" << cell.getDescription() << "\":"
|
||||||
<< " fileName=\"" << object.mShape->mFileName << '"'
|
<< " fileName=\"" << object.mShape->mFileName << '"'
|
||||||
<< " fileHash=" << toHex(object.mShape->mFileHash)
|
<< " fileHash=" << toHex(object.mShape->mFileHash)
|
||||||
<< " collisionShape=" << std::boolalpha << (object.mShape->mCollisionShape == nullptr)
|
<< " collisionShape=" << std::boolalpha
|
||||||
<< " avoidCollisionShape=" << std::boolalpha << (object.mShape->mAvoidCollisionShape == nullptr)
|
<< (object.mShape->mCollisionShape == nullptr)
|
||||||
<< " position=(" << WriteArray {object.mPosition.pos} << ')'
|
<< " avoidCollisionShape=" << std::boolalpha
|
||||||
<< " rotation=(" << WriteArray {object.mPosition.rot} << ')'
|
<< (object.mShape->mAvoidCollisionShape == nullptr) << " position=("
|
||||||
<< " scale=" << std::setprecision(std::numeric_limits<float>::max_exponent10) << object.mScale;
|
<< WriteArray{ object.mPosition.pos } << ')' << " rotation=("
|
||||||
|
<< WriteArray{ object.mPosition.rot } << ')'
|
||||||
|
<< " scale=" << std::setprecision(std::numeric_limits<float>::max_exponent10)
|
||||||
|
<< object.mScale;
|
||||||
});
|
});
|
||||||
|
|
||||||
Log(Debug::Info) << "Done";
|
Log(Debug::Info) << "Done";
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef OPENMW_ESMTOOL_ARGUMENTS_H
|
#ifndef OPENMW_ESMTOOL_ARGUMENTS_H
|
||||||
#define OPENMW_ESMTOOL_ARGUMENTS_H
|
#define OPENMW_ESMTOOL_ARGUMENTS_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <optional>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <components/esm/format.hpp>
|
#include <components/esm/format.hpp>
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
#include <deque>
|
|
||||||
#include <list>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <map>
|
|
||||||
#include <fstream>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <deque>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <iomanip>
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
#include <components/esm/format.hpp>
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
#include <components/esm3/esmwriter.hpp>
|
#include <components/esm3/esmwriter.hpp>
|
||||||
#include <components/esm/format.hpp>
|
|
||||||
#include <components/files/openfile.hpp>
|
|
||||||
#include <components/misc/strings/algorithm.hpp>
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include <components/files/conversion.hpp>
|
#include <components/files/conversion.hpp>
|
||||||
|
#include <components/files/openfile.hpp>
|
||||||
|
#include <components/misc/strings/algorithm.hpp>
|
||||||
|
|
||||||
#include "record.hpp"
|
|
||||||
#include "labels.hpp"
|
|
||||||
#include "arguments.hpp"
|
#include "arguments.hpp"
|
||||||
|
#include "labels.hpp"
|
||||||
|
#include "record.hpp"
|
||||||
#include "tes4.hpp"
|
#include "tes4.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -43,7 +43,6 @@ struct ESMData
|
||||||
// Value: (Reference, Deleted flag)
|
// Value: (Reference, Deleted flag)
|
||||||
std::map<ESM::Cell*, std::deque<std::pair<ESM::CellRef, bool>>> mCellRefs;
|
std::map<ESM::Cell*, std::deque<std::pair<ESM::CellRef, bool>>> mCellRefs;
|
||||||
std::map<int, int> mRecordStats;
|
std::map<int, int> mRecordStats;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool parseOptions(int argc, char** argv, Arguments& info)
|
bool parseOptions(int argc, char** argv, Arguments& info)
|
||||||
|
@ -68,23 +67,24 @@ Allowed options)");
|
||||||
addOption("type,t", bpo::value<std::vector<std::string>>(),
|
addOption("type,t", bpo::value<std::vector<std::string>>(),
|
||||||
"Show only records of this type (four character record code). May "
|
"Show only records of this type (four character record code). May "
|
||||||
"be specified multiple times. Only affects dump mode.");
|
"be specified multiple times. Only affects dump mode.");
|
||||||
addOption("name,n", bpo::value<std::string>(),
|
addOption("name,n", bpo::value<std::string>(), "Show only the record with this name. Only affects dump mode.");
|
||||||
"Show only the record with this name. Only affects dump mode.");
|
addOption("plain,p",
|
||||||
addOption("plain,p", "Print contents of dialogs, books and scripts. "
|
"Print contents of dialogs, books and scripts. "
|
||||||
"(skipped by default)"
|
"(skipped by default)"
|
||||||
"Only affects dump mode.");
|
"Only affects dump mode.");
|
||||||
addOption("quiet,q", "Suppress all record information. Useful for speed tests.");
|
addOption("quiet,q", "Suppress all record information. Useful for speed tests.");
|
||||||
addOption("loadcells,C", "Browse through contents of all cells.");
|
addOption("loadcells,C", "Browse through contents of all cells.");
|
||||||
|
|
||||||
addOption( "encoding,e", bpo::value<std::string>(&(info.encoding))->
|
addOption("encoding,e", bpo::value<std::string>(&(info.encoding))->default_value("win1252"),
|
||||||
default_value("win1252"),
|
|
||||||
"Character encoding used in ESMTool:\n"
|
"Character encoding used in ESMTool:\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\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\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n"
|
||||||
"\n\twin1252 - Western European (Latin) alphabet, used by default")
|
"\n\twin1252 - Western European (Latin) alphabet, used by default");
|
||||||
;
|
|
||||||
|
|
||||||
std::string finalText = "\nIf no option is given, the default action is to parse all records in the archive\nand display diagnostic information.";
|
std::string finalText
|
||||||
|
= "\nIf no option is given, the default action is to parse all records in the archive\nand display "
|
||||||
|
"diagnostic information.";
|
||||||
|
|
||||||
// input-file is hidden and used as a positional argument
|
// input-file is hidden and used as a positional argument
|
||||||
bpo::options_description hidden("Hidden Options");
|
bpo::options_description hidden("Hidden Options");
|
||||||
|
@ -102,8 +102,7 @@ Allowed options)");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv)
|
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).options(all).positional(p).run();
|
||||||
.options(all).positional(p).run();
|
|
||||||
|
|
||||||
bpo::store(valid_opts, variables);
|
bpo::store(valid_opts, variables);
|
||||||
}
|
}
|
||||||
|
@ -127,8 +126,7 @@ Allowed options)");
|
||||||
}
|
}
|
||||||
if (!variables.count("mode"))
|
if (!variables.count("mode"))
|
||||||
{
|
{
|
||||||
std::cout << "No mode specified!\n\n"
|
std::cout << "No mode specified!\n\n" << desc << finalText << std::endl;
|
||||||
<< desc << finalText << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,8 +138,7 @@ Allowed options)");
|
||||||
info.mode = variables["mode"].as<std::string>();
|
info.mode = variables["mode"].as<std::string>();
|
||||||
if (!(info.mode == "dump" || info.mode == "clone" || info.mode == "comp"))
|
if (!(info.mode == "dump" || info.mode == "clone" || info.mode == "comp"))
|
||||||
{
|
{
|
||||||
std::cout << "\nERROR: invalid mode \"" << info.mode << "\"\n\n"
|
std::cout << "\nERROR: invalid mode \"" << info.mode << "\"\n\n" << desc << finalText << std::endl;
|
||||||
<< desc << finalText << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,9 +158,11 @@ Allowed options)");
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
const auto inputFiles = variables["input-file"].as<Files::MaybeQuotedPathContainer>();
|
const auto inputFiles = variables["input-file"].as<Files::MaybeQuotedPathContainer>();
|
||||||
info.filename = inputFiles[0].u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
info.filename = inputFiles[0].u8string(); // This call to u8string is redundant, but required to build on
|
||||||
|
// MSVC 14.26 due to implementation bugs.
|
||||||
if (inputFiles.size() > 1)
|
if (inputFiles.size() > 1)
|
||||||
info.outname = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
info.outname = inputFiles[1].u8string(); // This call to u8string is redundant, but required to build on
|
||||||
|
// MSVC 14.26 due to implementation bugs.
|
||||||
|
|
||||||
if (const auto it = variables.find("raw"); it != variables.end())
|
if (const auto it = variables.find("raw"); it != variables.end())
|
||||||
info.mRawFormat = ESM::parseFormat(it->second.as<std::string>());
|
info.mRawFormat = ESM::parseFormat(it->second.as<std::string>());
|
||||||
|
@ -237,7 +236,8 @@ void loadCell(const Arguments& info, ESM::Cell &cell, ESM::ESMReader &esm, ESMDa
|
||||||
|
|
||||||
// Loop through all the references
|
// Loop through all the references
|
||||||
ESM::CellRef ref;
|
ESM::CellRef ref;
|
||||||
if(!quiet) std::cout << " References:\n";
|
if (!quiet)
|
||||||
|
std::cout << " References:\n";
|
||||||
|
|
||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
ESM::MovedCellRef movedCellRef;
|
ESM::MovedCellRef movedCellRef;
|
||||||
|
@ -247,11 +247,13 @@ void loadCell(const Arguments& info, ESM::Cell &cell, ESM::ESMReader &esm, ESMDa
|
||||||
if (data != nullptr && save)
|
if (data != nullptr && save)
|
||||||
data->mCellRefs[&cell].push_back(std::make_pair(ref, deleted));
|
data->mCellRefs[&cell].push_back(std::make_pair(ref, deleted));
|
||||||
|
|
||||||
if(quiet) continue;
|
if (quiet)
|
||||||
|
continue;
|
||||||
|
|
||||||
std::cout << " - Refnum: " << ref.mRefNum.mIndex << '\n';
|
std::cout << " - Refnum: " << ref.mRefNum.mIndex << '\n';
|
||||||
std::cout << " ID: " << ref.mRefID << '\n';
|
std::cout << " ID: " << ref.mRefID << '\n';
|
||||||
std::cout << " Position: (" << ref.mPos.pos[0] << ", " << ref.mPos.pos[1] << ", " << ref.mPos.pos[2] << ")\n";
|
std::cout << " Position: (" << ref.mPos.pos[0] << ", " << ref.mPos.pos[1] << ", " << ref.mPos.pos[2]
|
||||||
|
<< ")\n";
|
||||||
if (ref.mScale != 1.f)
|
if (ref.mScale != 1.f)
|
||||||
std::cout << " Scale: " << ref.mScale << '\n';
|
std::cout << " Scale: " << ref.mScale << '\n';
|
||||||
if (!ref.mOwner.empty())
|
if (!ref.mOwner.empty())
|
||||||
|
@ -276,8 +278,8 @@ void loadCell(const Arguments& info, ESM::Cell &cell, ESM::ESMReader &esm, ESMDa
|
||||||
std::cout << " Soul: " << ref.mSoul << '\n';
|
std::cout << " Soul: " << ref.mSoul << '\n';
|
||||||
if (ref.mTeleport)
|
if (ref.mTeleport)
|
||||||
{
|
{
|
||||||
std::cout << " Destination position: (" << ref.mDoorDest.pos[0] << ", "
|
std::cout << " Destination position: (" << ref.mDoorDest.pos[0] << ", " << ref.mDoorDest.pos[1]
|
||||||
<< ref.mDoorDest.pos[1] << ", " << ref.mDoorDest.pos[2] << ")\n";
|
<< ", " << ref.mDoorDest.pos[2] << ")\n";
|
||||||
if (!ref.mDestCell.empty())
|
if (!ref.mDestCell.empty())
|
||||||
std::cout << " Destination cell: " << ref.mDestCell << '\n';
|
std::cout << " Destination cell: " << ref.mDestCell << '\n';
|
||||||
}
|
}
|
||||||
|
@ -308,8 +310,8 @@ void printRawTes3(const std::filesystem::path &path)
|
||||||
esm.skipHSub();
|
esm.skipHSub();
|
||||||
n = esm.retSubName();
|
n = esm.retSubName();
|
||||||
std::ios::fmtflags f(std::cout.flags());
|
std::ios::fmtflags f(std::cout.flags());
|
||||||
std::cout << " " << n.toStringView() << " - " << esm.getSubSize()
|
std::cout << " " << n.toStringView() << " - " << esm.getSubSize() << " bytes @ 0x" << std::hex
|
||||||
<< " bytes @ 0x" << std::hex << offs << '\n';
|
<< offs << '\n';
|
||||||
std::cout.flags(f);
|
std::cout.flags(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,7 +369,8 @@ int loadTes3(const Arguments& info, std::unique_ptr<std::ifstream>&& stream, ESM
|
||||||
}
|
}
|
||||||
|
|
||||||
esm.skipRecord();
|
esm.skipRecord();
|
||||||
if (quiet) break;
|
if (quiet)
|
||||||
|
break;
|
||||||
std::cout << " Skipping\n";
|
std::cout << " Skipping\n";
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -379,7 +382,8 @@ int loadTes3(const Arguments& info, std::unique_ptr<std::ifstream>&& stream, ESM
|
||||||
|
|
||||||
// Is the user interested in this record type?
|
// Is the user interested in this record type?
|
||||||
bool interested = true;
|
bool interested = true;
|
||||||
if (!info.types.empty() && std::find(info.types.begin(), info.types.end(), n.toStringView()) == info.types.end())
|
if (!info.types.empty()
|
||||||
|
&& std::find(info.types.begin(), info.types.end(), n.toStringView()) == info.types.end())
|
||||||
interested = false;
|
interested = false;
|
||||||
|
|
||||||
if (!info.name.empty() && !Misc::StringUtils::ciEqual(info.name, record->getId()))
|
if (!info.name.empty() && !Misc::StringUtils::ciEqual(info.name, record->getId()))
|
||||||
|
@ -426,7 +430,8 @@ int load(const Arguments& info, ESMData* data)
|
||||||
printRawTes3(info.filename);
|
printRawTes3(info.filename);
|
||||||
break;
|
break;
|
||||||
case ESM::Format::Tes4:
|
case ESM::Format::Tes4:
|
||||||
std::cout << "Printing raw TES4 file is not supported: " << Files::pathToUnicodeString(info.filename) << "\n";
|
std::cout << "Printing raw TES4 file is not supported: "
|
||||||
|
<< Files::pathToUnicodeString(info.filename) << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -520,7 +525,8 @@ int clone(const Arguments& info)
|
||||||
esm.startRecord(typeName, record->getFlags());
|
esm.startRecord(typeName, record->getFlags());
|
||||||
|
|
||||||
record->save(esm);
|
record->save(esm);
|
||||||
if (typeName.toInt() == ESM::REC_CELL) {
|
if (typeName.toInt() == ESM::REC_CELL)
|
||||||
|
{
|
||||||
ESM::Cell* ptr = &record->cast<ESM::Cell>()->get();
|
ESM::Cell* ptr = &record->cast<ESM::Cell>()->get();
|
||||||
if (!data.mCellRefs[ptr].empty())
|
if (!data.mCellRefs[ptr].empty())
|
||||||
{
|
{
|
||||||
|
@ -570,14 +576,16 @@ int comp(const Arguments& info)
|
||||||
ESMData dataOne;
|
ESMData dataOne;
|
||||||
if (load(fileOne, &dataOne) != 0)
|
if (load(fileOne, &dataOne) != 0)
|
||||||
{
|
{
|
||||||
std::cout << "Failed to load " << Files::pathToUnicodeString(info.filename) << ", aborting comparison." << std::endl;
|
std::cout << "Failed to load " << Files::pathToUnicodeString(info.filename) << ", aborting comparison."
|
||||||
|
<< std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESMData dataTwo;
|
ESMData dataTwo;
|
||||||
if (load(fileTwo, &dataTwo) != 0)
|
if (load(fileTwo, &dataTwo) != 0)
|
||||||
{
|
{
|
||||||
std::cout << "Failed to load " << Files::pathToUnicodeString(info.outname) << ", aborting comparison." << std::endl;
|
std::cout << "Failed to load " << Files::pathToUnicodeString(info.outname) << ", aborting comparison."
|
||||||
|
<< std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,11 +243,16 @@ std::string_view aiTypeLabel(ESM::AiPackageType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ESM::AI_Wander: return "Wander";
|
case ESM::AI_Wander:
|
||||||
case ESM::AI_Travel: return "Travel";
|
return "Wander";
|
||||||
case ESM::AI_Follow: return "Follow";
|
case ESM::AI_Travel:
|
||||||
case ESM::AI_Escort: return "Escort";
|
return "Travel";
|
||||||
case ESM::AI_Activate: return "Activate";
|
case ESM::AI_Follow:
|
||||||
|
return "Follow";
|
||||||
|
case ESM::AI_Escort:
|
||||||
|
return "Escort";
|
||||||
|
case ESM::AI_Activate:
|
||||||
|
return "Activate";
|
||||||
}
|
}
|
||||||
return "Invalid";
|
return "Invalid";
|
||||||
}
|
}
|
||||||
|
@ -656,13 +661,15 @@ std::string_view ruleFunction(int idx)
|
||||||
std::string bodyPartFlags(int flags)
|
std::string bodyPartFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::BodyPart::BPF_Female) properties += "Female ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable ";
|
if (flags & ESM::BodyPart::BPF_Female)
|
||||||
int unused = (0xFFFFFFFF ^
|
properties += "Female ";
|
||||||
(ESM::BodyPart::BPF_Female|
|
if (flags & ESM::BodyPart::BPF_NotPlayable)
|
||||||
ESM::BodyPart::BPF_NotPlayable));
|
properties += "NotPlayable ";
|
||||||
if (flags & unused) properties += "Invalid ";
|
int unused = (0xFFFFFFFF ^ (ESM::BodyPart::BPF_Female | ESM::BodyPart::BPF_NotPlayable));
|
||||||
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -670,20 +677,23 @@ std::string bodyPartFlags(int flags)
|
||||||
std::string cellFlags(int flags)
|
std::string cellFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::Cell::HasWater) properties += "HasWater ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::Cell::Interior) properties += "Interior ";
|
if (flags & ESM::Cell::HasWater)
|
||||||
if (flags & ESM::Cell::NoSleep) properties += "NoSleep ";
|
properties += "HasWater ";
|
||||||
if (flags & ESM::Cell::QuasiEx) properties += "QuasiEx ";
|
if (flags & ESM::Cell::Interior)
|
||||||
|
properties += "Interior ";
|
||||||
|
if (flags & ESM::Cell::NoSleep)
|
||||||
|
properties += "NoSleep ";
|
||||||
|
if (flags & ESM::Cell::QuasiEx)
|
||||||
|
properties += "QuasiEx ";
|
||||||
// This used value is not in the ESM component.
|
// This used value is not in the ESM component.
|
||||||
if (flags & 0x00000040) properties += "Unknown ";
|
if (flags & 0x00000040)
|
||||||
int unused = (0xFFFFFFFF ^
|
properties += "Unknown ";
|
||||||
(ESM::Cell::HasWater|
|
int unused = (0xFFFFFFFF
|
||||||
ESM::Cell::Interior|
|
^ (ESM::Cell::HasWater | ESM::Cell::Interior | ESM::Cell::NoSleep | ESM::Cell::QuasiEx | 0x00000040));
|
||||||
ESM::Cell::NoSleep|
|
if (flags & unused)
|
||||||
ESM::Cell::QuasiEx|
|
properties += "Invalid ";
|
||||||
0x00000040));
|
|
||||||
if (flags & unused) properties += "Invalid ";
|
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -691,15 +701,17 @@ std::string cellFlags(int flags)
|
||||||
std::string containerFlags(int flags)
|
std::string containerFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::Container::Unknown) properties += "Unknown ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::Container::Organic) properties += "Organic ";
|
if (flags & ESM::Container::Unknown)
|
||||||
if (flags & ESM::Container::Respawn) properties += "Respawn ";
|
properties += "Unknown ";
|
||||||
int unused = (0xFFFFFFFF ^
|
if (flags & ESM::Container::Organic)
|
||||||
(ESM::Container::Unknown|
|
properties += "Organic ";
|
||||||
ESM::Container::Organic|
|
if (flags & ESM::Container::Respawn)
|
||||||
ESM::Container::Respawn));
|
properties += "Respawn ";
|
||||||
if (flags & unused) properties += "Invalid ";
|
int unused = (0xFFFFFFFF ^ (ESM::Container::Unknown | ESM::Container::Organic | ESM::Container::Respawn));
|
||||||
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -707,25 +719,29 @@ std::string containerFlags(int flags)
|
||||||
std::string creatureFlags(int flags)
|
std::string creatureFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::Creature::Base) properties += "Base ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::Creature::Walks) properties += "Walks ";
|
if (flags & ESM::Creature::Base)
|
||||||
if (flags & ESM::Creature::Swims) properties += "Swims ";
|
properties += "Base ";
|
||||||
if (flags & ESM::Creature::Flies) properties += "Flies ";
|
if (flags & ESM::Creature::Walks)
|
||||||
if (flags & ESM::Creature::Bipedal) properties += "Bipedal ";
|
properties += "Walks ";
|
||||||
if (flags & ESM::Creature::Respawn) properties += "Respawn ";
|
if (flags & ESM::Creature::Swims)
|
||||||
if (flags & ESM::Creature::Weapon) properties += "Weapon ";
|
properties += "Swims ";
|
||||||
if (flags & ESM::Creature::Essential) properties += "Essential ";
|
if (flags & ESM::Creature::Flies)
|
||||||
int unused = (0xFFFFFFFF ^
|
properties += "Flies ";
|
||||||
(ESM::Creature::Base|
|
if (flags & ESM::Creature::Bipedal)
|
||||||
ESM::Creature::Walks|
|
properties += "Bipedal ";
|
||||||
ESM::Creature::Swims|
|
if (flags & ESM::Creature::Respawn)
|
||||||
ESM::Creature::Flies|
|
properties += "Respawn ";
|
||||||
ESM::Creature::Bipedal|
|
if (flags & ESM::Creature::Weapon)
|
||||||
ESM::Creature::Respawn|
|
properties += "Weapon ";
|
||||||
ESM::Creature::Weapon|
|
if (flags & ESM::Creature::Essential)
|
||||||
ESM::Creature::Essential));
|
properties += "Essential ";
|
||||||
if (flags & unused) properties += "Invalid ";
|
int unused = (0xFFFFFFFF
|
||||||
|
^ (ESM::Creature::Base | ESM::Creature::Walks | ESM::Creature::Swims | ESM::Creature::Flies
|
||||||
|
| ESM::Creature::Bipedal | ESM::Creature::Respawn | ESM::Creature::Weapon | ESM::Creature::Essential));
|
||||||
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%02X)", flags);
|
properties += Misc::StringUtils::format("(0x%02X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -733,9 +749,12 @@ std::string creatureFlags(int flags)
|
||||||
std::string enchantmentFlags(int flags)
|
std::string enchantmentFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::Enchantment::Autocalc) properties += "Autocalc ";
|
properties += "[None] ";
|
||||||
if (flags & (0xFFFFFFFF ^ ESM::Enchantment::Autocalc)) properties += "Invalid ";
|
if (flags & ESM::Enchantment::Autocalc)
|
||||||
|
properties += "Autocalc ";
|
||||||
|
if (flags & (0xFFFFFFFF ^ ESM::Enchantment::Autocalc))
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -746,11 +765,16 @@ std::string landFlags(int flags)
|
||||||
// The ESM component says that this first four bits are used, but
|
// The ESM component says that this first four bits are used, but
|
||||||
// only the first three bits are used as far as I can tell.
|
// only the first three bits are used as far as I can tell.
|
||||||
// There's also no enumeration of the bit in the ESM component.
|
// There's also no enumeration of the bit in the ESM component.
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & 0x00000001) properties += "Unknown1 ";
|
properties += "[None] ";
|
||||||
if (flags & 0x00000004) properties += "Unknown3 ";
|
if (flags & 0x00000001)
|
||||||
if (flags & 0x00000002) properties += "Unknown2 ";
|
properties += "Unknown1 ";
|
||||||
if (flags & 0xFFFFFFF8) properties += "Invalid ";
|
if (flags & 0x00000004)
|
||||||
|
properties += "Unknown3 ";
|
||||||
|
if (flags & 0x00000002)
|
||||||
|
properties += "Unknown2 ";
|
||||||
|
if (flags & 0xFFFFFFF8)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -758,13 +782,15 @@ std::string landFlags(int flags)
|
||||||
std::string itemListFlags(int flags)
|
std::string itemListFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::ItemLevList::AllLevels) properties += "AllLevels ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::ItemLevList::Each) properties += "Each ";
|
if (flags & ESM::ItemLevList::AllLevels)
|
||||||
int unused = (0xFFFFFFFF ^
|
properties += "AllLevels ";
|
||||||
(ESM::ItemLevList::AllLevels|
|
if (flags & ESM::ItemLevList::Each)
|
||||||
ESM::ItemLevList::Each));
|
properties += "Each ";
|
||||||
if (flags & unused) properties += "Invalid ";
|
int unused = (0xFFFFFFFF ^ (ESM::ItemLevList::AllLevels | ESM::ItemLevList::Each));
|
||||||
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -772,10 +798,13 @@ std::string itemListFlags(int flags)
|
||||||
std::string creatureListFlags(int flags)
|
std::string creatureListFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::CreatureLevList::AllLevels) properties += "AllLevels ";
|
properties += "[None] ";
|
||||||
|
if (flags & ESM::CreatureLevList::AllLevels)
|
||||||
|
properties += "AllLevels ";
|
||||||
int unused = (0xFFFFFFFF ^ ESM::CreatureLevList::AllLevels);
|
int unused = (0xFFFFFFFF ^ ESM::CreatureLevList::AllLevels);
|
||||||
if (flags & unused) properties += "Invalid ";
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -783,27 +812,31 @@ std::string creatureListFlags(int flags)
|
||||||
std::string lightFlags(int flags)
|
std::string lightFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::Light::Dynamic) properties += "Dynamic ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::Light::Fire) properties += "Fire ";
|
if (flags & ESM::Light::Dynamic)
|
||||||
if (flags & ESM::Light::Carry) properties += "Carry ";
|
properties += "Dynamic ";
|
||||||
if (flags & ESM::Light::Flicker) properties += "Flicker ";
|
if (flags & ESM::Light::Fire)
|
||||||
if (flags & ESM::Light::FlickerSlow) properties += "FlickerSlow ";
|
properties += "Fire ";
|
||||||
if (flags & ESM::Light::Pulse) properties += "Pulse ";
|
if (flags & ESM::Light::Carry)
|
||||||
if (flags & ESM::Light::PulseSlow) properties += "PulseSlow ";
|
properties += "Carry ";
|
||||||
if (flags & ESM::Light::Negative) properties += "Negative ";
|
if (flags & ESM::Light::Flicker)
|
||||||
if (flags & ESM::Light::OffDefault) properties += "OffDefault ";
|
properties += "Flicker ";
|
||||||
int unused = (0xFFFFFFFF ^
|
if (flags & ESM::Light::FlickerSlow)
|
||||||
(ESM::Light::Dynamic|
|
properties += "FlickerSlow ";
|
||||||
ESM::Light::Fire|
|
if (flags & ESM::Light::Pulse)
|
||||||
ESM::Light::Carry|
|
properties += "Pulse ";
|
||||||
ESM::Light::Flicker|
|
if (flags & ESM::Light::PulseSlow)
|
||||||
ESM::Light::FlickerSlow|
|
properties += "PulseSlow ";
|
||||||
ESM::Light::Pulse|
|
if (flags & ESM::Light::Negative)
|
||||||
ESM::Light::PulseSlow|
|
properties += "Negative ";
|
||||||
ESM::Light::Negative|
|
if (flags & ESM::Light::OffDefault)
|
||||||
ESM::Light::OffDefault));
|
properties += "OffDefault ";
|
||||||
if (flags & unused) properties += "Invalid ";
|
int unused = (0xFFFFFFFF
|
||||||
|
^ (ESM::Light::Dynamic | ESM::Light::Fire | ESM::Light::Carry | ESM::Light::Flicker | ESM::Light::FlickerSlow
|
||||||
|
| ESM::Light::Pulse | ESM::Light::PulseSlow | ESM::Light::Negative | ESM::Light::OffDefault));
|
||||||
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -811,27 +844,47 @@ std::string lightFlags(int flags)
|
||||||
std::string magicEffectFlags(int flags)
|
std::string magicEffectFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::MagicEffect::TargetAttribute) properties += "TargetAttribute ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::MagicEffect::TargetSkill) properties += "TargetSkill ";
|
if (flags & ESM::MagicEffect::TargetAttribute)
|
||||||
if (flags & ESM::MagicEffect::NoDuration) properties += "NoDuration ";
|
properties += "TargetAttribute ";
|
||||||
if (flags & ESM::MagicEffect::NoMagnitude) properties += "NoMagnitude ";
|
if (flags & ESM::MagicEffect::TargetSkill)
|
||||||
if (flags & ESM::MagicEffect::Harmful) properties += "Harmful ";
|
properties += "TargetSkill ";
|
||||||
if (flags & ESM::MagicEffect::ContinuousVfx) properties += "ContinuousVFX ";
|
if (flags & ESM::MagicEffect::NoDuration)
|
||||||
if (flags & ESM::MagicEffect::CastSelf) properties += "CastSelf ";
|
properties += "NoDuration ";
|
||||||
if (flags & ESM::MagicEffect::CastTouch) properties += "CastTouch ";
|
if (flags & ESM::MagicEffect::NoMagnitude)
|
||||||
if (flags & ESM::MagicEffect::CastTarget) properties += "CastTarget ";
|
properties += "NoMagnitude ";
|
||||||
if (flags & ESM::MagicEffect::AppliedOnce) properties += "AppliedOnce ";
|
if (flags & ESM::MagicEffect::Harmful)
|
||||||
if (flags & ESM::MagicEffect::Stealth) properties += "Stealth ";
|
properties += "Harmful ";
|
||||||
if (flags & ESM::MagicEffect::NonRecastable) properties += "NonRecastable ";
|
if (flags & ESM::MagicEffect::ContinuousVfx)
|
||||||
if (flags & ESM::MagicEffect::IllegalDaedra) properties += "IllegalDaedra ";
|
properties += "ContinuousVFX ";
|
||||||
if (flags & ESM::MagicEffect::Unreflectable) properties += "Unreflectable ";
|
if (flags & ESM::MagicEffect::CastSelf)
|
||||||
if (flags & ESM::MagicEffect::CasterLinked) properties += "CasterLinked ";
|
properties += "CastSelf ";
|
||||||
if (flags & ESM::MagicEffect::AllowSpellmaking) properties += "AllowSpellmaking ";
|
if (flags & ESM::MagicEffect::CastTouch)
|
||||||
if (flags & ESM::MagicEffect::AllowEnchanting) properties += "AllowEnchanting ";
|
properties += "CastTouch ";
|
||||||
if (flags & ESM::MagicEffect::NegativeLight) properties += "NegativeLight ";
|
if (flags & ESM::MagicEffect::CastTarget)
|
||||||
|
properties += "CastTarget ";
|
||||||
|
if (flags & ESM::MagicEffect::AppliedOnce)
|
||||||
|
properties += "AppliedOnce ";
|
||||||
|
if (flags & ESM::MagicEffect::Stealth)
|
||||||
|
properties += "Stealth ";
|
||||||
|
if (flags & ESM::MagicEffect::NonRecastable)
|
||||||
|
properties += "NonRecastable ";
|
||||||
|
if (flags & ESM::MagicEffect::IllegalDaedra)
|
||||||
|
properties += "IllegalDaedra ";
|
||||||
|
if (flags & ESM::MagicEffect::Unreflectable)
|
||||||
|
properties += "Unreflectable ";
|
||||||
|
if (flags & ESM::MagicEffect::CasterLinked)
|
||||||
|
properties += "CasterLinked ";
|
||||||
|
if (flags & ESM::MagicEffect::AllowSpellmaking)
|
||||||
|
properties += "AllowSpellmaking ";
|
||||||
|
if (flags & ESM::MagicEffect::AllowEnchanting)
|
||||||
|
properties += "AllowEnchanting ";
|
||||||
|
if (flags & ESM::MagicEffect::NegativeLight)
|
||||||
|
properties += "NegativeLight ";
|
||||||
|
|
||||||
if (flags & 0xFFFC0000) properties += "Invalid ";
|
if (flags & 0xFFFC0000)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -839,21 +892,24 @@ std::string magicEffectFlags(int flags)
|
||||||
std::string npcFlags(int flags)
|
std::string npcFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::NPC::Base) properties += "Base ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::NPC::Autocalc) properties += "Autocalc ";
|
if (flags & ESM::NPC::Base)
|
||||||
if (flags & ESM::NPC::Female) properties += "Female ";
|
properties += "Base ";
|
||||||
if (flags & ESM::NPC::Respawn) properties += "Respawn ";
|
if (flags & ESM::NPC::Autocalc)
|
||||||
if (flags & ESM::NPC::Essential) properties += "Essential ";
|
properties += "Autocalc ";
|
||||||
|
if (flags & ESM::NPC::Female)
|
||||||
|
properties += "Female ";
|
||||||
|
if (flags & ESM::NPC::Respawn)
|
||||||
|
properties += "Respawn ";
|
||||||
|
if (flags & ESM::NPC::Essential)
|
||||||
|
properties += "Essential ";
|
||||||
// Whether corpses persist is a bit that is unaccounted for,
|
// Whether corpses persist is a bit that is unaccounted for,
|
||||||
// however relatively few NPCs have this bit set.
|
// however relatively few NPCs have this bit set.
|
||||||
int unused = (0xFF ^
|
int unused
|
||||||
(ESM::NPC::Base|
|
= (0xFF ^ (ESM::NPC::Base | ESM::NPC::Autocalc | ESM::NPC::Female | ESM::NPC::Respawn | ESM::NPC::Essential));
|
||||||
ESM::NPC::Autocalc|
|
if (flags & unused)
|
||||||
ESM::NPC::Female|
|
properties += "Invalid ";
|
||||||
ESM::NPC::Respawn|
|
|
||||||
ESM::NPC::Essential));
|
|
||||||
if (flags & unused) properties += "Invalid ";
|
|
||||||
properties += Misc::StringUtils::format("(0x%02X)", flags);
|
properties += Misc::StringUtils::format("(0x%02X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -861,14 +917,16 @@ std::string npcFlags(int flags)
|
||||||
std::string raceFlags(int flags)
|
std::string raceFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
|
properties += "[None] ";
|
||||||
// All races have the playable flag set in Bethesda files.
|
// All races have the playable flag set in Bethesda files.
|
||||||
if (flags & ESM::Race::Playable) properties += "Playable ";
|
if (flags & ESM::Race::Playable)
|
||||||
if (flags & ESM::Race::Beast) properties += "Beast ";
|
properties += "Playable ";
|
||||||
int unused = (0xFFFFFFFF ^
|
if (flags & ESM::Race::Beast)
|
||||||
(ESM::Race::Playable|
|
properties += "Beast ";
|
||||||
ESM::Race::Beast));
|
int unused = (0xFFFFFFFF ^ (ESM::Race::Playable | ESM::Race::Beast));
|
||||||
if (flags & unused) properties += "Invalid ";
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -876,15 +934,17 @@ std::string raceFlags(int flags)
|
||||||
std::string spellFlags(int flags)
|
std::string spellFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::Spell::F_Autocalc) properties += "Autocalc ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::Spell::F_PCStart) properties += "PCStart ";
|
if (flags & ESM::Spell::F_Autocalc)
|
||||||
if (flags & ESM::Spell::F_Always) properties += "Always ";
|
properties += "Autocalc ";
|
||||||
int unused = (0xFFFFFFFF ^
|
if (flags & ESM::Spell::F_PCStart)
|
||||||
(ESM::Spell::F_Autocalc|
|
properties += "PCStart ";
|
||||||
ESM::Spell::F_PCStart|
|
if (flags & ESM::Spell::F_Always)
|
||||||
ESM::Spell::F_Always));
|
properties += "Always ";
|
||||||
if (flags & unused) properties += "Invalid ";
|
int unused = (0xFFFFFFFF ^ (ESM::Spell::F_Autocalc | ESM::Spell::F_PCStart | ESM::Spell::F_Always));
|
||||||
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -892,16 +952,18 @@ std::string spellFlags(int flags)
|
||||||
std::string weaponFlags(int flags)
|
std::string weaponFlags(int flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
|
properties += "[None] ";
|
||||||
// The interpretation of the flags are still unclear to me.
|
// The interpretation of the flags are still unclear to me.
|
||||||
// Apparently you can't be Silver without being Magical? Many of
|
// Apparently you can't be Silver without being Magical? Many of
|
||||||
// the "Magical" weapons don't have enchantments of any sort.
|
// the "Magical" weapons don't have enchantments of any sort.
|
||||||
if (flags & ESM::Weapon::Magical) properties += "Magical ";
|
if (flags & ESM::Weapon::Magical)
|
||||||
if (flags & ESM::Weapon::Silver) properties += "Silver ";
|
properties += "Magical ";
|
||||||
int unused = (0xFFFFFFFF ^
|
if (flags & ESM::Weapon::Silver)
|
||||||
(ESM::Weapon::Magical|
|
properties += "Silver ";
|
||||||
ESM::Weapon::Silver));
|
int unused = (0xFFFFFFFF ^ (ESM::Weapon::Magical | ESM::Weapon::Silver));
|
||||||
if (flags & unused) properties += "Invalid ";
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -909,13 +971,19 @@ std::string weaponFlags(int flags)
|
||||||
std::string recordFlags(uint32_t flags)
|
std::string recordFlags(uint32_t flags)
|
||||||
{
|
{
|
||||||
std::string properties;
|
std::string properties;
|
||||||
if (flags == 0) properties += "[None] ";
|
if (flags == 0)
|
||||||
if (flags & ESM::FLAG_Deleted) properties += "Deleted ";
|
properties += "[None] ";
|
||||||
if (flags & ESM::FLAG_Persistent) properties += "Persistent ";
|
if (flags & ESM::FLAG_Deleted)
|
||||||
if (flags & ESM::FLAG_Ignored) properties += "Ignored ";
|
properties += "Deleted ";
|
||||||
if (flags & ESM::FLAG_Blocked) properties += "Blocked ";
|
if (flags & ESM::FLAG_Persistent)
|
||||||
|
properties += "Persistent ";
|
||||||
|
if (flags & ESM::FLAG_Ignored)
|
||||||
|
properties += "Ignored ";
|
||||||
|
if (flags & ESM::FLAG_Blocked)
|
||||||
|
properties += "Blocked ";
|
||||||
int unused = ~(ESM::FLAG_Deleted | ESM::FLAG_Persistent | ESM::FLAG_Ignored | ESM::FLAG_Blocked);
|
int unused = ~(ESM::FLAG_Deleted | ESM::FLAG_Persistent | ESM::FLAG_Ignored | ESM::FLAG_Blocked);
|
||||||
if (flags & unused) properties += "Invalid ";
|
if (flags & unused)
|
||||||
|
properties += "Invalid ";
|
||||||
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
properties += Misc::StringUtils::format("(0x%08X)", flags);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
|
@ -11,8 +11,8 @@ namespace
|
||||||
|
|
||||||
void printAIPackage(const ESM::AIPackage& p)
|
void printAIPackage(const ESM::AIPackage& p)
|
||||||
{
|
{
|
||||||
std::cout << " AI Type: " << aiTypeLabel(p.mType)
|
std::cout << " AI Type: " << aiTypeLabel(p.mType) << " (" << Misc::StringUtils::format("0x%08X", p.mType)
|
||||||
<< " (" << Misc::StringUtils::format("0x%08X", p.mType) << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
if (p.mType == ESM::AI_Wander)
|
if (p.mType == ESM::AI_Wander)
|
||||||
{
|
{
|
||||||
std::cout << " Distance: " << p.mWander.mDistance << std::endl;
|
std::cout << " Distance: " << p.mWander.mDistance << std::endl;
|
||||||
|
@ -28,14 +28,14 @@ void printAIPackage(const ESM::AIPackage& p)
|
||||||
}
|
}
|
||||||
else if (p.mType == ESM::AI_Travel)
|
else if (p.mType == ESM::AI_Travel)
|
||||||
{
|
{
|
||||||
std::cout << " Travel Coordinates: (" << p.mTravel.mX << ","
|
std::cout << " Travel Coordinates: (" << p.mTravel.mX << "," << p.mTravel.mY << "," << p.mTravel.mZ
|
||||||
<< p.mTravel.mY << "," << p.mTravel.mZ << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
std::cout << " Should repeat: " << static_cast<bool>(p.mTravel.mShouldRepeat != 0) << std::endl;
|
std::cout << " Should repeat: " << static_cast<bool>(p.mTravel.mShouldRepeat != 0) << std::endl;
|
||||||
}
|
}
|
||||||
else if (p.mType == ESM::AI_Follow || p.mType == ESM::AI_Escort)
|
else if (p.mType == ESM::AI_Follow || p.mType == ESM::AI_Escort)
|
||||||
{
|
{
|
||||||
std::cout << " Follow Coordinates: (" << p.mTarget.mX << ","
|
std::cout << " Follow Coordinates: (" << p.mTarget.mX << "," << p.mTarget.mY << "," << p.mTarget.mZ
|
||||||
<< p.mTarget.mY << "," << p.mTarget.mZ << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
std::cout << " Duration: " << p.mTarget.mDuration << std::endl;
|
std::cout << " Duration: " << p.mTarget.mDuration << std::endl;
|
||||||
std::cout << " Target ID: " << p.mTarget.mId.toString() << std::endl;
|
std::cout << " Target ID: " << p.mTarget.mId.toString() << std::endl;
|
||||||
std::cout << " Should repeat: " << static_cast<bool>(p.mTarget.mShouldRepeat != 0) << std::endl;
|
std::cout << " Should repeat: " << static_cast<bool>(p.mTarget.mShouldRepeat != 0) << std::endl;
|
||||||
|
@ -45,7 +45,8 @@ void printAIPackage(const ESM::AIPackage& p)
|
||||||
std::cout << " Name: " << p.mActivate.mName.toString() << std::endl;
|
std::cout << " Name: " << p.mActivate.mName.toString() << std::endl;
|
||||||
std::cout << " Should repeat: " << static_cast<bool>(p.mActivate.mShouldRepeat != 0) << std::endl;
|
std::cout << " Should repeat: " << static_cast<bool>(p.mActivate.mShouldRepeat != 0) << std::endl;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
std::cout << " BadPackage: " << Misc::StringUtils::format("0x%08X", p.mType) << std::endl;
|
std::cout << " BadPackage: " << Misc::StringUtils::format("0x%08X", p.mType) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,29 +77,64 @@ std::string ruleString(const ESM::DialInfo::SelectStruct& ss)
|
||||||
func_str = std::string(ruleFunction(func));
|
func_str = std::string(ruleFunction(func));
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
if (indicator == 's') type_str = "Global short";
|
if (indicator == 's')
|
||||||
else if (indicator == 'l') type_str = "Global long";
|
type_str = "Global short";
|
||||||
else if (indicator == 'f') type_str = "Global float";
|
else if (indicator == 'l')
|
||||||
|
type_str = "Global long";
|
||||||
|
else if (indicator == 'f')
|
||||||
|
type_str = "Global float";
|
||||||
break;
|
break;
|
||||||
case '3':
|
case '3':
|
||||||
if (indicator == 's') type_str = "Local short";
|
if (indicator == 's')
|
||||||
else if (indicator == 'l') type_str = "Local long";
|
type_str = "Local short";
|
||||||
else if (indicator == 'f') type_str = "Local float";
|
else if (indicator == 'l')
|
||||||
|
type_str = "Local long";
|
||||||
|
else if (indicator == 'f')
|
||||||
|
type_str = "Local float";
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
if (indicator == 'J')
|
||||||
|
type_str = "Journal";
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
if (indicator == 'I')
|
||||||
|
type_str = "Item type";
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
if (indicator == 'D')
|
||||||
|
type_str = "NPC Dead";
|
||||||
|
break;
|
||||||
|
case '7':
|
||||||
|
if (indicator == 'X')
|
||||||
|
type_str = "Not ID";
|
||||||
|
break;
|
||||||
|
case '8':
|
||||||
|
if (indicator == 'F')
|
||||||
|
type_str = "Not Faction";
|
||||||
|
break;
|
||||||
|
case '9':
|
||||||
|
if (indicator == 'C')
|
||||||
|
type_str = "Not Class";
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
if (indicator == 'R')
|
||||||
|
type_str = "Not Race";
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
if (indicator == 'L')
|
||||||
|
type_str = "Not Cell";
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
if (indicator == 's')
|
||||||
|
type_str = "Not Local";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
case '4': if (indicator == 'J') type_str = "Journal"; break;
|
|
||||||
case '5': if (indicator == 'I') type_str = "Item type"; break;
|
|
||||||
case '6': if (indicator == 'D') type_str = "NPC Dead"; break;
|
|
||||||
case '7': if (indicator == 'X') type_str = "Not ID"; break;
|
|
||||||
case '8': if (indicator == 'F') type_str = "Not Faction"; break;
|
|
||||||
case '9': if (indicator == 'C') type_str = "Not Class"; break;
|
|
||||||
case 'A': if (indicator == 'R') type_str = "Not Race"; break;
|
|
||||||
case 'B': if (indicator == 'L') type_str = "Not Cell"; break;
|
|
||||||
case 'C': if (indicator == 's') type_str = "Not Local"; break;
|
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the variable name to the function string if any.
|
// Append the variable name to the function string if any.
|
||||||
if (type != '1') func_str = rule.substr(5);
|
if (type != '1')
|
||||||
|
func_str = rule.substr(5);
|
||||||
|
|
||||||
// In the previous switch, we assumed that the second char was X
|
// In the previous switch, we assumed that the second char was X
|
||||||
// for all types not qual to one. If this wasn't true, go back to
|
// for all types not qual to one. If this wasn't true, go back to
|
||||||
|
@ -110,19 +146,33 @@ std::string ruleString(const ESM::DialInfo::SelectStruct& ss)
|
||||||
std::string oper_str = "??";
|
std::string oper_str = "??";
|
||||||
switch (oper)
|
switch (oper)
|
||||||
{
|
{
|
||||||
case '0': oper_str = "=="; break;
|
case '0':
|
||||||
case '1': oper_str = "!="; break;
|
oper_str = "==";
|
||||||
case '2': oper_str = "> "; break;
|
break;
|
||||||
case '3': oper_str = ">="; break;
|
case '1':
|
||||||
case '4': oper_str = "< "; break;
|
oper_str = "!=";
|
||||||
case '5': oper_str = "<="; break;
|
break;
|
||||||
default: break;
|
case '2':
|
||||||
|
oper_str = "> ";
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
oper_str = ">=";
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
oper_str = "< ";
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
oper_str = "<=";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
stream << ss.mValue;
|
stream << ss.mValue;
|
||||||
|
|
||||||
std::string result = Misc::StringUtils::format("%-12s %-32s %2s %s", type_str, func_str, oper_str, stream.str());
|
std::string result
|
||||||
|
= Misc::StringUtils::format("%-12s %-32s %2s %s", type_str, func_str, oper_str, stream.str());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,16 +181,15 @@ void printEffectList(const ESM::EffectList& effects)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const ESM::ENAMstruct& effect : effects.mList)
|
for (const ESM::ENAMstruct& effect : effects.mList)
|
||||||
{
|
{
|
||||||
std::cout << " Effect[" << i << "]: " << magicEffectLabel(effect.mEffectID)
|
std::cout << " Effect[" << i << "]: " << magicEffectLabel(effect.mEffectID) << " (" << effect.mEffectID
|
||||||
<< " (" << effect.mEffectID << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
if (effect.mSkill != -1)
|
if (effect.mSkill != -1)
|
||||||
std::cout << " Skill: " << skillLabel(effect.mSkill)
|
std::cout << " Skill: " << skillLabel(effect.mSkill) << " (" << (int)effect.mSkill << ")"
|
||||||
<< " (" << (int)effect.mSkill << ")" << std::endl;
|
<< std::endl;
|
||||||
if (effect.mAttribute != -1)
|
if (effect.mAttribute != -1)
|
||||||
std::cout << " Attribute: " << attributeLabel(effect.mAttribute)
|
std::cout << " Attribute: " << attributeLabel(effect.mAttribute) << " (" << (int)effect.mAttribute
|
||||||
<< " (" << (int)effect.mAttribute << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
std::cout << " Range: " << rangeTypeLabel(effect.mRange)
|
std::cout << " Range: " << rangeTypeLabel(effect.mRange) << " (" << effect.mRange << ")" << std::endl;
|
||||||
<< " (" << effect.mRange << ")" << std::endl;
|
|
||||||
// Area is always zero if range type is "Self"
|
// Area is always zero if range type is "Self"
|
||||||
if (effect.mRange != ESM::RT_Self)
|
if (effect.mRange != ESM::RT_Self)
|
||||||
std::cout << " Area: " << effect.mArea << std::endl;
|
std::cout << " Area: " << effect.mArea << std::endl;
|
||||||
|
@ -154,12 +203,10 @@ void printTransport(const std::vector<ESM::Transport::Dest>& transport)
|
||||||
{
|
{
|
||||||
for (const ESM::Transport::Dest& dest : transport)
|
for (const ESM::Transport::Dest& dest : transport)
|
||||||
{
|
{
|
||||||
std::cout << " Destination Position: "
|
std::cout << " Destination Position: " << Misc::StringUtils::format("%12.3f", dest.mPos.pos[0]) << ","
|
||||||
<< Misc::StringUtils::format("%12.3f", dest.mPos.pos[0]) << ","
|
|
||||||
<< Misc::StringUtils::format("%12.3f", dest.mPos.pos[1]) << ","
|
<< Misc::StringUtils::format("%12.3f", dest.mPos.pos[1]) << ","
|
||||||
<< Misc::StringUtils::format("%12.3f", dest.mPos.pos[2]) << ")" << std::endl;
|
<< Misc::StringUtils::format("%12.3f", dest.mPos.pos[2]) << ")" << std::endl;
|
||||||
std::cout << " Destination Rotation: "
|
std::cout << " Destination Rotation: " << Misc::StringUtils::format("%9.6f", dest.mPos.rot[0]) << ","
|
||||||
<< Misc::StringUtils::format("%9.6f", dest.mPos.rot[0]) << ","
|
|
||||||
<< Misc::StringUtils::format("%9.6f", dest.mPos.rot[1]) << ","
|
<< Misc::StringUtils::format("%9.6f", dest.mPos.rot[1]) << ","
|
||||||
<< Misc::StringUtils::format("%9.6f", dest.mPos.rot[2]) << ")" << std::endl;
|
<< Misc::StringUtils::format("%9.6f", dest.mPos.rot[2]) << ")" << std::endl;
|
||||||
if (!dest.mCellName.empty())
|
if (!dest.mCellName.empty())
|
||||||
|
@ -169,7 +216,8 @@ void printTransport(const std::vector<ESM::Transport::Dest>& transport)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace EsmTool {
|
namespace EsmTool
|
||||||
|
{
|
||||||
|
|
||||||
std::unique_ptr<RecordBase> RecordBase::create(const ESM::NAME type)
|
std::unique_ptr<RecordBase> RecordBase::create(const ESM::NAME type)
|
||||||
{
|
{
|
||||||
|
@ -431,8 +479,7 @@ void Record<ESM::Armor>::print()
|
||||||
std::cout << " Script: " << mData.mScript << std::endl;
|
std::cout << " Script: " << mData.mScript << std::endl;
|
||||||
if (!mData.mEnchant.empty())
|
if (!mData.mEnchant.empty())
|
||||||
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
|
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
|
||||||
std::cout << " Type: " << armorTypeLabel(mData.mData.mType)
|
std::cout << " Type: " << armorTypeLabel(mData.mData.mType) << " (" << mData.mData.mType << ")" << std::endl;
|
||||||
<< " (" << mData.mData.mType << ")" << std::endl;
|
|
||||||
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
||||||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||||
std::cout << " Health: " << mData.mData.mHealth << std::endl;
|
std::cout << " Health: " << mData.mData.mHealth << std::endl;
|
||||||
|
@ -440,8 +487,7 @@ void Record<ESM::Armor>::print()
|
||||||
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
|
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
|
||||||
for (const ESM::PartReference& part : mData.mParts.mParts)
|
for (const ESM::PartReference& part : mData.mParts.mParts)
|
||||||
{
|
{
|
||||||
std::cout << " Body Part: " << bodyPartLabel(part.mPart)
|
std::cout << " Body Part: " << bodyPartLabel(part.mPart) << " (" << (int)(part.mPart) << ")" << std::endl;
|
||||||
<< " (" << (int)(part.mPart) << ")" << std::endl;
|
|
||||||
std::cout << " Male Name: " << part.mMale << std::endl;
|
std::cout << " Male Name: " << part.mMale << std::endl;
|
||||||
if (!part.mFemale.empty())
|
if (!part.mFemale.empty())
|
||||||
std::cout << " Female Name: " << part.mFemale << std::endl;
|
std::cout << " Female Name: " << part.mFemale << std::endl;
|
||||||
|
@ -457,8 +503,8 @@ void Record<ESM::Apparatus>::print()
|
||||||
std::cout << " Model: " << mData.mModel << std::endl;
|
std::cout << " Model: " << mData.mModel << std::endl;
|
||||||
std::cout << " Icon: " << mData.mIcon << std::endl;
|
std::cout << " Icon: " << mData.mIcon << std::endl;
|
||||||
std::cout << " Script: " << mData.mScript << std::endl;
|
std::cout << " Script: " << mData.mScript << std::endl;
|
||||||
std::cout << " Type: " << apparatusTypeLabel(mData.mData.mType)
|
std::cout << " Type: " << apparatusTypeLabel(mData.mData.mType) << " (" << mData.mData.mType << ")"
|
||||||
<< " (" << mData.mData.mType << ")" << std::endl;
|
<< std::endl;
|
||||||
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
||||||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||||
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
|
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
|
||||||
|
@ -470,11 +516,11 @@ void Record<ESM::BodyPart>::print()
|
||||||
{
|
{
|
||||||
std::cout << " Race: " << mData.mRace << std::endl;
|
std::cout << " Race: " << mData.mRace << std::endl;
|
||||||
std::cout << " Model: " << mData.mModel << std::endl;
|
std::cout << " Model: " << mData.mModel << std::endl;
|
||||||
std::cout << " Type: " << meshTypeLabel(mData.mData.mType)
|
std::cout << " Type: " << meshTypeLabel(mData.mData.mType) << " (" << (int)mData.mData.mType << ")"
|
||||||
<< " (" << (int)mData.mData.mType << ")" << std::endl;
|
<< std::endl;
|
||||||
std::cout << " Flags: " << bodyPartFlags(mData.mData.mFlags) << std::endl;
|
std::cout << " Flags: " << bodyPartFlags(mData.mData.mFlags) << std::endl;
|
||||||
std::cout << " Part: " << meshPartLabel(mData.mData.mPart)
|
std::cout << " Part: " << meshPartLabel(mData.mData.mPart) << " (" << (int)mData.mData.mPart << ")"
|
||||||
<< " (" << (int)mData.mData.mPart << ")" << std::endl;
|
<< std::endl;
|
||||||
std::cout << " Vampire: " << (int)mData.mData.mVampire << std::endl;
|
std::cout << " Vampire: " << (int)mData.mData.mVampire << std::endl;
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -529,11 +575,10 @@ void Record<ESM::Cell>::print()
|
||||||
std::cout << " Region: " << mData.mRegion << std::endl;
|
std::cout << " Region: " << mData.mRegion << std::endl;
|
||||||
std::cout << " Flags: " << cellFlags(mData.mData.mFlags) << std::endl;
|
std::cout << " Flags: " << cellFlags(mData.mData.mFlags) << std::endl;
|
||||||
|
|
||||||
std::cout << " Coordinates: " << " (" << mData.getGridX() << ","
|
std::cout << " Coordinates: "
|
||||||
<< mData.getGridY() << ")" << std::endl;
|
<< " (" << mData.getGridX() << "," << mData.getGridY() << ")" << std::endl;
|
||||||
|
|
||||||
if (mData.mData.mFlags & ESM::Cell::Interior &&
|
if (mData.mData.mFlags & ESM::Cell::Interior && !(mData.mData.mFlags & ESM::Cell::QuasiEx))
|
||||||
!(mData.mData.mFlags & ESM::Cell::QuasiEx))
|
|
||||||
{
|
{
|
||||||
if (mData.hasAmbient())
|
if (mData.hasAmbient())
|
||||||
{
|
{
|
||||||
|
@ -554,7 +599,6 @@ void Record<ESM::Cell>::print()
|
||||||
std::cout << " Water Level Int: " << mData.mWaterInt << std::endl;
|
std::cout << " Water Level Int: " << mData.mWaterInt << std::endl;
|
||||||
std::cout << " RefId counter: " << mData.mRefNumCounter << std::endl;
|
std::cout << " RefId counter: " << mData.mRefNumCounter << std::endl;
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -564,18 +608,18 @@ void Record<ESM::Class>::print()
|
||||||
std::cout << " Description: " << mData.mDescription << std::endl;
|
std::cout << " Description: " << mData.mDescription << std::endl;
|
||||||
std::cout << " Playable: " << mData.mData.mIsPlayable << std::endl;
|
std::cout << " Playable: " << mData.mData.mIsPlayable << std::endl;
|
||||||
std::cout << " AutoCalc: " << mData.mData.mCalc << std::endl;
|
std::cout << " AutoCalc: " << mData.mData.mCalc << std::endl;
|
||||||
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0])
|
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0]) << " (" << mData.mData.mAttribute[0]
|
||||||
<< " (" << mData.mData.mAttribute[0] << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1])
|
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1]) << " (" << mData.mData.mAttribute[1]
|
||||||
<< " (" << mData.mData.mAttribute[1] << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
std::cout << " Specialization: " << specializationLabel(mData.mData.mSpecialization)
|
std::cout << " Specialization: " << specializationLabel(mData.mData.mSpecialization) << " ("
|
||||||
<< " (" << mData.mData.mSpecialization << ")" << std::endl;
|
<< mData.mData.mSpecialization << ")" << std::endl;
|
||||||
for (int i = 0; i != 5; i++)
|
for (int i = 0; i != 5; i++)
|
||||||
std::cout << " Minor Skill: " << skillLabel(mData.mData.mSkills[i][0])
|
std::cout << " Minor Skill: " << skillLabel(mData.mData.mSkills[i][0]) << " (" << mData.mData.mSkills[i][0]
|
||||||
<< " (" << mData.mData.mSkills[i][0] << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
for (int i = 0; i != 5; i++)
|
for (int i = 0; i != 5; i++)
|
||||||
std::cout << " Major Skill: " << skillLabel(mData.mData.mSkills[i][1])
|
std::cout << " Major Skill: " << skillLabel(mData.mData.mSkills[i][1]) << " (" << mData.mData.mSkills[i][1]
|
||||||
<< " (" << mData.mData.mSkills[i][1] << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,15 +633,14 @@ void Record<ESM::Clothing>::print()
|
||||||
std::cout << " Script: " << mData.mScript << std::endl;
|
std::cout << " Script: " << mData.mScript << std::endl;
|
||||||
if (!mData.mEnchant.empty())
|
if (!mData.mEnchant.empty())
|
||||||
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
|
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
|
||||||
std::cout << " Type: " << clothingTypeLabel(mData.mData.mType)
|
std::cout << " Type: " << clothingTypeLabel(mData.mData.mType) << " (" << mData.mData.mType << ")"
|
||||||
<< " (" << mData.mData.mType << ")" << std::endl;
|
<< std::endl;
|
||||||
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
||||||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||||
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
|
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
|
||||||
for (const ESM::PartReference& part : mData.mParts.mParts)
|
for (const ESM::PartReference& part : mData.mParts.mParts)
|
||||||
{
|
{
|
||||||
std::cout << " Body Part: " << bodyPartLabel(part.mPart)
|
std::cout << " Body Part: " << bodyPartLabel(part.mPart) << " (" << (int)(part.mPart) << ")" << std::endl;
|
||||||
<< " (" << (int)(part.mPart) << ")" << std::endl;
|
|
||||||
std::cout << " Male Name: " << part.mMale << std::endl;
|
std::cout << " Male Name: " << part.mMale << std::endl;
|
||||||
if (!part.mFemale.empty())
|
if (!part.mFemale.empty())
|
||||||
std::cout << " Female Name: " << part.mFemale << std::endl;
|
std::cout << " Female Name: " << part.mFemale << std::endl;
|
||||||
|
@ -631,8 +674,8 @@ void Record<ESM::Creature>::print()
|
||||||
std::cout << " Original: " << mData.mOriginal << std::endl;
|
std::cout << " Original: " << mData.mOriginal << std::endl;
|
||||||
std::cout << " Scale: " << mData.mScale << std::endl;
|
std::cout << " Scale: " << mData.mScale << std::endl;
|
||||||
|
|
||||||
std::cout << " Type: " << creatureTypeLabel(mData.mData.mType)
|
std::cout << " Type: " << creatureTypeLabel(mData.mData.mType) << " (" << mData.mData.mType << ")"
|
||||||
<< " (" << mData.mData.mType << ")" << std::endl;
|
<< std::endl;
|
||||||
std::cout << " Level: " << mData.mData.mLevel << std::endl;
|
std::cout << " Level: " << mData.mData.mLevel << std::endl;
|
||||||
|
|
||||||
std::cout << " Attributes:" << std::endl;
|
std::cout << " Attributes:" << std::endl;
|
||||||
|
@ -652,12 +695,9 @@ void Record<ESM::Creature>::print()
|
||||||
std::cout << " Combat: " << mData.mData.mCombat << std::endl;
|
std::cout << " Combat: " << mData.mData.mCombat << std::endl;
|
||||||
std::cout << " Magic: " << mData.mData.mMagic << std::endl;
|
std::cout << " Magic: " << mData.mData.mMagic << std::endl;
|
||||||
std::cout << " Stealth: " << mData.mData.mStealth << std::endl;
|
std::cout << " Stealth: " << mData.mData.mStealth << std::endl;
|
||||||
std::cout << " Attack1: " << mData.mData.mAttack[0]
|
std::cout << " Attack1: " << mData.mData.mAttack[0] << "-" << mData.mData.mAttack[1] << std::endl;
|
||||||
<< "-" << mData.mData.mAttack[1] << std::endl;
|
std::cout << " Attack2: " << mData.mData.mAttack[2] << "-" << mData.mData.mAttack[3] << std::endl;
|
||||||
std::cout << " Attack2: " << mData.mData.mAttack[2]
|
std::cout << " Attack3: " << mData.mData.mAttack[4] << "-" << mData.mData.mAttack[5] << std::endl;
|
||||||
<< "-" << mData.mData.mAttack[3] << std::endl;
|
|
||||||
std::cout << " Attack3: " << mData.mData.mAttack[4]
|
|
||||||
<< "-" << mData.mData.mAttack[5] << std::endl;
|
|
||||||
std::cout << " Gold: " << mData.mData.mGold << std::endl;
|
std::cout << " Gold: " << mData.mData.mGold << std::endl;
|
||||||
|
|
||||||
for (const ESM::ContItem& item : mData.mInventory.mList)
|
for (const ESM::ContItem& item : mData.mInventory.mList)
|
||||||
|
@ -687,8 +727,7 @@ void Record<ESM::Creature>::print()
|
||||||
template <>
|
template <>
|
||||||
void Record<ESM::Dialogue>::print()
|
void Record<ESM::Dialogue>::print()
|
||||||
{
|
{
|
||||||
std::cout << " Type: " << dialogTypeLabel(mData.mType)
|
std::cout << " Type: " << dialogTypeLabel(mData.mType) << " (" << (int)mData.mType << ")" << std::endl;
|
||||||
<< " (" << (int)mData.mType << ")" << std::endl;
|
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
// Sadly, there are no DialInfos, because the loader dumps as it
|
// Sadly, there are no DialInfos, because the loader dumps as it
|
||||||
// loads, rather than loading and then dumping. :-( Anyone mind if
|
// loads, rather than loading and then dumping. :-( Anyone mind if
|
||||||
|
@ -711,8 +750,7 @@ void Record<ESM::Door>::print()
|
||||||
template <>
|
template <>
|
||||||
void Record<ESM::Enchantment>::print()
|
void Record<ESM::Enchantment>::print()
|
||||||
{
|
{
|
||||||
std::cout << " Type: " << enchantTypeLabel(mData.mData.mType)
|
std::cout << " Type: " << enchantTypeLabel(mData.mData.mType) << " (" << mData.mData.mType << ")" << std::endl;
|
||||||
<< " (" << mData.mData.mType << ")" << std::endl;
|
|
||||||
std::cout << " Cost: " << mData.mData.mCost << std::endl;
|
std::cout << " Cost: " << mData.mData.mCost << std::endl;
|
||||||
std::cout << " Charge: " << mData.mData.mCharge << std::endl;
|
std::cout << " Charge: " << mData.mData.mCharge << std::endl;
|
||||||
std::cout << " Flags: " << enchantmentFlags(mData.mData.mFlags) << std::endl;
|
std::cout << " Flags: " << enchantmentFlags(mData.mData.mFlags) << std::endl;
|
||||||
|
@ -725,10 +763,10 @@ void Record<ESM::Faction>::print()
|
||||||
{
|
{
|
||||||
std::cout << " Name: " << mData.mName << std::endl;
|
std::cout << " Name: " << mData.mName << std::endl;
|
||||||
std::cout << " Hidden: " << mData.mData.mIsHidden << std::endl;
|
std::cout << " Hidden: " << mData.mData.mIsHidden << std::endl;
|
||||||
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0])
|
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0]) << " (" << mData.mData.mAttribute[0]
|
||||||
<< " (" << mData.mData.mAttribute[0] << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1])
|
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1]) << " (" << mData.mData.mAttribute[1]
|
||||||
<< " (" << mData.mData.mAttribute[1] << ")" << std::endl;
|
<< ")" << std::endl;
|
||||||
for (int skill : mData.mData.mSkills)
|
for (int skill : mData.mData.mSkills)
|
||||||
if (skill != -1)
|
if (skill != -1)
|
||||||
std::cout << " Skill: " << skillLabel(skill) << " (" << skill << ")" << std::endl;
|
std::cout << " Skill: " << skillLabel(skill) << " (" << skill << ")" << std::endl;
|
||||||
|
@ -736,16 +774,11 @@ void Record<ESM::Faction>::print()
|
||||||
if (!mData.mRanks[i].empty())
|
if (!mData.mRanks[i].empty())
|
||||||
{
|
{
|
||||||
std::cout << " Rank: " << mData.mRanks[i] << std::endl;
|
std::cout << " Rank: " << mData.mRanks[i] << std::endl;
|
||||||
std::cout << " Attribute1 Requirement: "
|
std::cout << " Attribute1 Requirement: " << mData.mData.mRankData[i].mAttribute1 << std::endl;
|
||||||
<< mData.mData.mRankData[i].mAttribute1 << std::endl;
|
std::cout << " Attribute2 Requirement: " << mData.mData.mRankData[i].mAttribute2 << std::endl;
|
||||||
std::cout << " Attribute2 Requirement: "
|
std::cout << " One Skill at Level: " << mData.mData.mRankData[i].mPrimarySkill << std::endl;
|
||||||
<< mData.mData.mRankData[i].mAttribute2 << std::endl;
|
std::cout << " Two Skills at Level: " << mData.mData.mRankData[i].mFavouredSkill << std::endl;
|
||||||
std::cout << " One Skill at Level: "
|
std::cout << " Faction Reaction: " << mData.mData.mRankData[i].mFactReaction << std::endl;
|
||||||
<< mData.mData.mRankData[i].mPrimarySkill << std::endl;
|
|
||||||
std::cout << " Two Skills at Level: "
|
|
||||||
<< mData.mData.mRankData[i].mFavouredSkill << std::endl;
|
|
||||||
std::cout << " Faction Reaction: "
|
|
||||||
<< mData.mData.mRankData[i].mFactReaction << std::endl;
|
|
||||||
}
|
}
|
||||||
for (const auto& reaction : mData.mReactions)
|
for (const auto& reaction : mData.mReactions)
|
||||||
std::cout << " Reaction: " << reaction.second << " = " << reaction.first << std::endl;
|
std::cout << " Reaction: " << reaction.second << " = " << reaction.first << std::endl;
|
||||||
|
@ -799,9 +832,8 @@ void Record<ESM::DialInfo>::print()
|
||||||
if (!mData.mSound.empty())
|
if (!mData.mSound.empty())
|
||||||
std::cout << " Sound File: " << mData.mSound << std::endl;
|
std::cout << " Sound File: " << mData.mSound << std::endl;
|
||||||
|
|
||||||
|
std::cout << " Quest Status: " << questStatusLabel(mData.mQuestStatus) << " (" << mData.mQuestStatus << ")"
|
||||||
std::cout << " Quest Status: " << questStatusLabel(mData.mQuestStatus)
|
<< std::endl;
|
||||||
<< " (" << mData.mQuestStatus << ")" << std::endl;
|
|
||||||
std::cout << " Unknown1: " << mData.mData.mUnknown1 << std::endl;
|
std::cout << " Unknown1: " << mData.mData.mUnknown1 << std::endl;
|
||||||
std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl;
|
std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl;
|
||||||
|
|
||||||
|
@ -838,13 +870,14 @@ void Record<ESM::Ingredient>::print()
|
||||||
for (int i = 0; i != 4; i++)
|
for (int i = 0; i != 4; i++)
|
||||||
{
|
{
|
||||||
// A value of -1 means no effect
|
// A value of -1 means no effect
|
||||||
if (mData.mData.mEffectID[i] == -1) continue;
|
if (mData.mData.mEffectID[i] == -1)
|
||||||
std::cout << " Effect: " << magicEffectLabel(mData.mData.mEffectID[i])
|
continue;
|
||||||
<< " (" << mData.mData.mEffectID[i] << ")" << std::endl;
|
std::cout << " Effect: " << magicEffectLabel(mData.mData.mEffectID[i]) << " (" << mData.mData.mEffectID[i]
|
||||||
std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i])
|
<< ")" << std::endl;
|
||||||
<< " (" << mData.mData.mSkills[i] << ")" << std::endl;
|
std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i]) << " (" << mData.mData.mSkills[i] << ")"
|
||||||
std::cout << " Attribute: " << attributeLabel(mData.mData.mAttributes[i])
|
<< std::endl;
|
||||||
<< " (" << mData.mData.mAttributes[i] << ")" << std::endl;
|
std::cout << " Attribute: " << attributeLabel(mData.mData.mAttributes[i]) << " ("
|
||||||
|
<< mData.mData.mAttributes[i] << ")" << std::endl;
|
||||||
}
|
}
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -874,8 +907,7 @@ void Record<ESM::CreatureLevList>::print()
|
||||||
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
|
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
|
||||||
std::cout << " Number of items: " << mData.mList.size() << std::endl;
|
std::cout << " Number of items: " << mData.mList.size() << std::endl;
|
||||||
for (const ESM::LevelledListBase::LevelItem& item : mData.mList)
|
for (const ESM::LevelledListBase::LevelItem& item : mData.mList)
|
||||||
std::cout << " Creature: Level: " << item.mLevel
|
std::cout << " Creature: Level: " << item.mLevel << " Creature: " << item.mId << std::endl;
|
||||||
<< " Creature: " << item.mId << std::endl;
|
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -886,8 +918,7 @@ void Record<ESM::ItemLevList>::print()
|
||||||
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
|
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
|
||||||
std::cout << " Number of items: " << mData.mList.size() << std::endl;
|
std::cout << " Number of items: " << mData.mList.size() << std::endl;
|
||||||
for (const ESM::LevelledListBase::LevelItem& item : mData.mList)
|
for (const ESM::LevelledListBase::LevelItem& item : mData.mList)
|
||||||
std::cout << " Inventory: Level: " << item.mLevel
|
std::cout << " Inventory: Level: " << item.mLevel << " Item: " << item.mId << std::endl;
|
||||||
<< " Item: " << item.mId << std::endl;
|
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -969,8 +1000,7 @@ void Record<ESM::LandTexture>::print()
|
||||||
template <>
|
template <>
|
||||||
void Record<ESM::MagicEffect>::print()
|
void Record<ESM::MagicEffect>::print()
|
||||||
{
|
{
|
||||||
std::cout << " Index: " << magicEffectLabel(mData.mIndex)
|
std::cout << " Index: " << magicEffectLabel(mData.mIndex) << " (" << mData.mIndex << ")" << std::endl;
|
||||||
<< " (" << mData.mIndex << ")" << std::endl;
|
|
||||||
std::cout << " Description: " << mData.mDescription << std::endl;
|
std::cout << " Description: " << mData.mDescription << std::endl;
|
||||||
std::cout << " Icon: " << mData.mIcon << std::endl;
|
std::cout << " Icon: " << mData.mIcon << std::endl;
|
||||||
std::cout << " Flags: " << magicEffectFlags(mData.mData.mFlags) << std::endl;
|
std::cout << " Flags: " << magicEffectFlags(mData.mData.mFlags) << std::endl;
|
||||||
|
@ -991,16 +1021,15 @@ void Record<ESM::MagicEffect>::print()
|
||||||
std::cout << " Area Static: " << mData.mArea << std::endl;
|
std::cout << " Area Static: " << mData.mArea << std::endl;
|
||||||
if (!mData.mAreaSound.empty())
|
if (!mData.mAreaSound.empty())
|
||||||
std::cout << " Area Sound: " << mData.mAreaSound << std::endl;
|
std::cout << " Area Sound: " << mData.mAreaSound << std::endl;
|
||||||
std::cout << " School: " << schoolLabel(mData.mData.mSchool)
|
std::cout << " School: " << schoolLabel(mData.mData.mSchool) << " (" << mData.mData.mSchool << ")"
|
||||||
<< " (" << mData.mData.mSchool << ")" << std::endl;
|
<< std::endl;
|
||||||
std::cout << " Base Cost: " << mData.mData.mBaseCost << std::endl;
|
std::cout << " Base Cost: " << mData.mData.mBaseCost << std::endl;
|
||||||
std::cout << " Unknown 1: " << mData.mData.mUnknown1 << std::endl;
|
std::cout << " Unknown 1: " << mData.mData.mUnknown1 << std::endl;
|
||||||
std::cout << " Speed: " << mData.mData.mSpeed << std::endl;
|
std::cout << " Speed: " << mData.mData.mSpeed << std::endl;
|
||||||
std::cout << " Unknown 2: " << mData.mData.mUnknown2 << std::endl;
|
std::cout << " Unknown 2: " << mData.mData.mUnknown2 << std::endl;
|
||||||
std::cout << " RGB Color: " << "("
|
std::cout << " RGB Color: "
|
||||||
<< mData.mData.mRed << ","
|
<< "(" << mData.mData.mRed << "," << mData.mData.mGreen << "," << mData.mData.mBlue << ")"
|
||||||
<< mData.mData.mGreen << ","
|
<< std::endl;
|
||||||
<< mData.mData.mBlue << ")" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
@ -1042,7 +1071,8 @@ void Record<ESM::NPC>::print()
|
||||||
std::cout << " Rank: " << (int)mData.mNpdt.mRank << std::endl;
|
std::cout << " Rank: " << (int)mData.mNpdt.mRank << std::endl;
|
||||||
std::cout << " Gold: " << mData.mNpdt.mGold << std::endl;
|
std::cout << " Gold: " << mData.mNpdt.mGold << std::endl;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
std::cout << " Level: " << mData.mNpdt.mLevel << std::endl;
|
std::cout << " Level: " << mData.mNpdt.mLevel << std::endl;
|
||||||
std::cout << " Reputation: " << (int)mData.mNpdt.mReputation << std::endl;
|
std::cout << " Reputation: " << (int)mData.mNpdt.mReputation << std::endl;
|
||||||
std::cout << " Disposition: " << (int)mData.mNpdt.mDisposition << std::endl;
|
std::cout << " Disposition: " << (int)mData.mNpdt.mDisposition << std::endl;
|
||||||
|
@ -1060,8 +1090,7 @@ void Record<ESM::NPC>::print()
|
||||||
|
|
||||||
std::cout << " Skills:" << std::endl;
|
std::cout << " Skills:" << std::endl;
|
||||||
for (int i = 0; i != ESM::Skill::Length; i++)
|
for (int i = 0; i != ESM::Skill::Length; i++)
|
||||||
std::cout << " " << skillLabel(i) << ": "
|
std::cout << " " << skillLabel(i) << ": " << (int)(mData.mNpdt.mSkills[i]) << std::endl;
|
||||||
<< (int)(mData.mNpdt.mSkills[i]) << std::endl;
|
|
||||||
|
|
||||||
std::cout << " Health: " << mData.mNpdt.mHealth << std::endl;
|
std::cout << " Health: " << mData.mNpdt.mHealth << std::endl;
|
||||||
std::cout << " Magicka: " << mData.mNpdt.mMana << std::endl;
|
std::cout << " Magicka: " << mData.mNpdt.mMana << std::endl;
|
||||||
|
@ -1109,8 +1138,7 @@ void Record<ESM::Pathgrid>::print()
|
||||||
for (const ESM::Pathgrid::Point& point : mData.mPoints)
|
for (const ESM::Pathgrid::Point& point : mData.mPoints)
|
||||||
{
|
{
|
||||||
std::cout << " Point[" << i << "]:" << std::endl;
|
std::cout << " Point[" << i << "]:" << std::endl;
|
||||||
std::cout << " Coordinates: (" << point.mX << ","
|
std::cout << " Coordinates: (" << point.mX << "," << point.mY << "," << point.mZ << ")" << std::endl;
|
||||||
<< point.mY << "," << point.mZ << ")" << std::endl;
|
|
||||||
std::cout << " Auto-Generated: " << (int)point.mAutogenerated << std::endl;
|
std::cout << " Auto-Generated: " << (int)point.mAutogenerated << std::endl;
|
||||||
std::cout << " Connections: " << (int)point.mConnectionNum << std::endl;
|
std::cout << " Connections: " << (int)point.mConnectionNum << std::endl;
|
||||||
std::cout << " Unknown: " << point.mUnknown << std::endl;
|
std::cout << " Unknown: " << point.mUnknown << std::endl;
|
||||||
|
@ -1132,11 +1160,8 @@ void Record<ESM::Pathgrid>::print()
|
||||||
template <>
|
template <>
|
||||||
void Record<ESM::Race>::print()
|
void Record<ESM::Race>::print()
|
||||||
{
|
{
|
||||||
static const char *sAttributeNames[8] =
|
static const char* sAttributeNames[8]
|
||||||
{
|
= { "Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality", "Luck" };
|
||||||
"Strength", "Intelligence", "Willpower", "Agility",
|
|
||||||
"Speed", "Endurance", "Personality", "Luck"
|
|
||||||
};
|
|
||||||
|
|
||||||
std::cout << " Name: " << mData.mName << std::endl;
|
std::cout << " Name: " << mData.mName << std::endl;
|
||||||
std::cout << " Description: " << mData.mDescription << std::endl;
|
std::cout << " Description: " << mData.mDescription << std::endl;
|
||||||
|
@ -1149,8 +1174,8 @@ void Record<ESM::Race>::print()
|
||||||
std::cout << (male ? " Male:" : " Female:") << std::endl;
|
std::cout << (male ? " Male:" : " Female:") << std::endl;
|
||||||
|
|
||||||
for (int j = 0; j < 8; ++j)
|
for (int j = 0; j < 8; ++j)
|
||||||
std::cout << " " << sAttributeNames[j] << ": "
|
std::cout << " " << sAttributeNames[j] << ": " << mData.mData.mAttributeValues[j].getValue(male)
|
||||||
<< mData.mData.mAttributeValues[j].getValue (male) << std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
std::cout << " Height: " << mData.mData.mHeight.getValue(male) << std::endl;
|
std::cout << " Height: " << mData.mData.mHeight.getValue(male) << std::endl;
|
||||||
std::cout << " Weight: " << mData.mData.mWeight.getValue(male) << std::endl;
|
std::cout << " Weight: " << mData.mData.mWeight.getValue(male) << std::endl;
|
||||||
|
@ -1159,10 +1184,8 @@ void Record<ESM::Race>::print()
|
||||||
for (int i = 0; i != 7; i++)
|
for (int i = 0; i != 7; i++)
|
||||||
// Not all races have 7 skills.
|
// Not all races have 7 skills.
|
||||||
if (mData.mData.mBonus[i].mSkill != -1)
|
if (mData.mData.mBonus[i].mSkill != -1)
|
||||||
std::cout << " Skill: "
|
std::cout << " Skill: " << skillLabel(mData.mData.mBonus[i].mSkill) << " ("
|
||||||
<< skillLabel(mData.mData.mBonus[i].mSkill)
|
<< mData.mData.mBonus[i].mSkill << ") = " << mData.mData.mBonus[i].mBonus << std::endl;
|
||||||
<< " (" << mData.mData.mBonus[i].mSkill << ") = "
|
|
||||||
<< mData.mData.mBonus[i].mBonus << std::endl;
|
|
||||||
|
|
||||||
for (const std::string& power : mData.mPowers.mList)
|
for (const std::string& power : mData.mPowers.mList)
|
||||||
std::cout << " Power: " << power << std::endl;
|
std::cout << " Power: " << power << std::endl;
|
||||||
|
@ -1230,13 +1253,12 @@ void Record<ESM::Script>::print()
|
||||||
template <>
|
template <>
|
||||||
void Record<ESM::Skill>::print()
|
void Record<ESM::Skill>::print()
|
||||||
{
|
{
|
||||||
std::cout << " ID: " << skillLabel(mData.mIndex)
|
std::cout << " ID: " << skillLabel(mData.mIndex) << " (" << mData.mIndex << ")" << std::endl;
|
||||||
<< " (" << mData.mIndex << ")" << std::endl;
|
|
||||||
std::cout << " Description: " << mData.mDescription << std::endl;
|
std::cout << " Description: " << mData.mDescription << std::endl;
|
||||||
std::cout << " Governing Attribute: " << attributeLabel(mData.mData.mAttribute)
|
std::cout << " Governing Attribute: " << attributeLabel(mData.mData.mAttribute) << " ("
|
||||||
<< " (" << mData.mData.mAttribute << ")" << std::endl;
|
<< mData.mData.mAttribute << ")" << std::endl;
|
||||||
std::cout << " Specialization: " << specializationLabel(mData.mData.mSpecialization)
|
std::cout << " Specialization: " << specializationLabel(mData.mData.mSpecialization) << " ("
|
||||||
<< " (" << mData.mData.mSpecialization << ")" << std::endl;
|
<< mData.mData.mSpecialization << ")" << std::endl;
|
||||||
for (int i = 0; i != 4; i++)
|
for (int i = 0; i != 4; i++)
|
||||||
std::cout << " UseValue[" << i << "]:" << mData.mData.mUseValue[i] << std::endl;
|
std::cout << " UseValue[" << i << "]:" << mData.mData.mUseValue[i] << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -1247,8 +1269,7 @@ void Record<ESM::SoundGenerator>::print()
|
||||||
if (!mData.mCreature.empty())
|
if (!mData.mCreature.empty())
|
||||||
std::cout << " Creature: " << mData.mCreature << std::endl;
|
std::cout << " Creature: " << mData.mCreature << std::endl;
|
||||||
std::cout << " Sound: " << mData.mSound << std::endl;
|
std::cout << " Sound: " << mData.mSound << std::endl;
|
||||||
std::cout << " Type: " << soundTypeLabel(mData.mType)
|
std::cout << " Type: " << soundTypeLabel(mData.mType) << " (" << mData.mType << ")" << std::endl;
|
||||||
<< " (" << mData.mType << ")" << std::endl;
|
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1258,8 +1279,7 @@ void Record<ESM::Sound>::print()
|
||||||
std::cout << " Sound: " << mData.mSound << std::endl;
|
std::cout << " Sound: " << mData.mSound << std::endl;
|
||||||
std::cout << " Volume: " << (int)mData.mData.mVolume << std::endl;
|
std::cout << " Volume: " << (int)mData.mData.mVolume << std::endl;
|
||||||
if (mData.mData.mMinRange != 0 && mData.mData.mMaxRange != 0)
|
if (mData.mData.mMinRange != 0 && mData.mData.mMaxRange != 0)
|
||||||
std::cout << " Range: " << (int)mData.mData.mMinRange << " - "
|
std::cout << " Range: " << (int)mData.mData.mMinRange << " - " << (int)mData.mData.mMaxRange << std::endl;
|
||||||
<< (int)mData.mData.mMaxRange << std::endl;
|
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1267,8 +1287,7 @@ template<>
|
||||||
void Record<ESM::Spell>::print()
|
void Record<ESM::Spell>::print()
|
||||||
{
|
{
|
||||||
std::cout << " Name: " << mData.mName << std::endl;
|
std::cout << " Name: " << mData.mName << std::endl;
|
||||||
std::cout << " Type: " << spellTypeLabel(mData.mData.mType)
|
std::cout << " Type: " << spellTypeLabel(mData.mData.mType) << " (" << mData.mData.mType << ")" << std::endl;
|
||||||
<< " (" << mData.mData.mType << ")" << std::endl;
|
|
||||||
std::cout << " Flags: " << spellFlags(mData.mData.mFlags) << std::endl;
|
std::cout << " Flags: " << spellFlags(mData.mData.mFlags) << std::endl;
|
||||||
std::cout << " Cost: " << mData.mData.mCost << std::endl;
|
std::cout << " Cost: " << mData.mData.mCost << std::endl;
|
||||||
printEffectList(mData.mEffects);
|
printEffectList(mData.mEffects);
|
||||||
|
@ -1303,8 +1322,7 @@ void Record<ESM::Weapon>::print()
|
||||||
std::cout << " Script: " << mData.mScript << std::endl;
|
std::cout << " Script: " << mData.mScript << std::endl;
|
||||||
if (!mData.mEnchant.empty())
|
if (!mData.mEnchant.empty())
|
||||||
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
|
std::cout << " Enchantment: " << mData.mEnchant << std::endl;
|
||||||
std::cout << " Type: " << weaponTypeLabel(mData.mData.mType)
|
std::cout << " Type: " << weaponTypeLabel(mData.mData.mType) << " (" << mData.mData.mType << ")" << std::endl;
|
||||||
<< " (" << mData.mData.mType << ")" << std::endl;
|
|
||||||
std::cout << " Flags: " << weaponFlags(mData.mData.mFlags) << std::endl;
|
std::cout << " Flags: " << weaponFlags(mData.mData.mFlags) << std::endl;
|
||||||
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
||||||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||||
|
@ -1313,14 +1331,11 @@ void Record<ESM::Weapon>::print()
|
||||||
std::cout << " Reach: " << mData.mData.mReach << std::endl;
|
std::cout << " Reach: " << mData.mData.mReach << std::endl;
|
||||||
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
|
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
|
||||||
if (mData.mData.mChop[0] != 0 && mData.mData.mChop[1] != 0)
|
if (mData.mData.mChop[0] != 0 && mData.mData.mChop[1] != 0)
|
||||||
std::cout << " Chop: " << (int)mData.mData.mChop[0] << "-"
|
std::cout << " Chop: " << (int)mData.mData.mChop[0] << "-" << (int)mData.mData.mChop[1] << std::endl;
|
||||||
<< (int)mData.mData.mChop[1] << std::endl;
|
|
||||||
if (mData.mData.mSlash[0] != 0 && mData.mData.mSlash[1] != 0)
|
if (mData.mData.mSlash[0] != 0 && mData.mData.mSlash[1] != 0)
|
||||||
std::cout << " Slash: " << (int)mData.mData.mSlash[0] << "-"
|
std::cout << " Slash: " << (int)mData.mData.mSlash[0] << "-" << (int)mData.mData.mSlash[1] << std::endl;
|
||||||
<< (int)mData.mData.mSlash[1] << std::endl;
|
|
||||||
if (mData.mData.mThrust[0] != 0 && mData.mData.mThrust[1] != 0)
|
if (mData.mData.mThrust[0] != 0 && mData.mData.mThrust[1] != 0)
|
||||||
std::cout << " Thrust: " << (int)mData.mData.mThrust[0] << "-"
|
std::cout << " Thrust: " << (int)mData.mData.mThrust[0] << "-" << (int)mData.mData.mThrust[1] << std::endl;
|
||||||
<< (int)mData.mData.mThrust[1] << std::endl;
|
|
||||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef OPENMW_ESMTOOL_RECORD_H
|
#ifndef OPENMW_ESMTOOL_RECORD_H
|
||||||
#define OPENMW_ESMTOOL_RECORD_H
|
#define OPENMW_ESMTOOL_RECORD_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <components/esm/records.hpp>
|
#include <components/esm/records.hpp>
|
||||||
|
|
||||||
|
@ -14,7 +14,8 @@ namespace ESM
|
||||||
|
|
||||||
namespace EsmTool
|
namespace EsmTool
|
||||||
{
|
{
|
||||||
template <class T> class Record;
|
template <class T>
|
||||||
|
class Record;
|
||||||
|
|
||||||
class RecordBase
|
class RecordBase
|
||||||
{
|
{
|
||||||
|
@ -35,21 +36,13 @@ namespace EsmTool
|
||||||
|
|
||||||
virtual std::string getId() const = 0;
|
virtual std::string getId() const = 0;
|
||||||
|
|
||||||
uint32_t getFlags() const {
|
uint32_t getFlags() const { return mFlags; }
|
||||||
return mFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFlags(uint32_t flags) {
|
void setFlags(uint32_t flags) { mFlags = flags; }
|
||||||
mFlags = flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESM::NAME getType() const {
|
ESM::NAME getType() const { return mType; }
|
||||||
return mType;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPrintPlain(bool plain) {
|
void setPrintPlain(bool plain) { mPrintPlain = plain; }
|
||||||
mPrintPlain = plain;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void load(ESM::ESMReader& esm) = 0;
|
virtual void load(ESM::ESMReader& esm) = 0;
|
||||||
virtual void save(ESM::ESMWriter& esm) = 0;
|
virtual void save(ESM::ESMWriter& esm) = 0;
|
||||||
|
@ -59,7 +52,8 @@ namespace EsmTool
|
||||||
|
|
||||||
// just make it a bit shorter
|
// just make it a bit shorter
|
||||||
template <class T>
|
template <class T>
|
||||||
Record<T> *cast() {
|
Record<T>* cast()
|
||||||
|
{
|
||||||
return static_cast<Record<T>*>(this);
|
return static_cast<Record<T>*>(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -73,75 +67,115 @@ namespace EsmTool
|
||||||
public:
|
public:
|
||||||
Record()
|
Record()
|
||||||
: mIsDeleted(false)
|
: mIsDeleted(false)
|
||||||
{}
|
{
|
||||||
|
|
||||||
std::string getId() const override {
|
|
||||||
return mData.mId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
T &get() {
|
std::string getId() const override { return mData.mId; }
|
||||||
return mData;
|
|
||||||
}
|
|
||||||
|
|
||||||
void save(ESM::ESMWriter &esm) override {
|
T& get() { return mData; }
|
||||||
mData.save(esm, mIsDeleted);
|
|
||||||
}
|
|
||||||
|
|
||||||
void load(ESM::ESMReader &esm) override {
|
void save(ESM::ESMWriter& esm) override { mData.save(esm, mIsDeleted); }
|
||||||
mData.load(esm, mIsDeleted);
|
|
||||||
}
|
void load(ESM::ESMReader& esm) override { mData.load(esm, mIsDeleted); }
|
||||||
|
|
||||||
void print() override;
|
void print() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> std::string Record<ESM::Cell>::getId() const;
|
template <>
|
||||||
template<> std::string Record<ESM::Land>::getId() const;
|
std::string Record<ESM::Cell>::getId() const;
|
||||||
template<> std::string Record<ESM::MagicEffect>::getId() const;
|
template <>
|
||||||
template<> std::string Record<ESM::Pathgrid>::getId() const;
|
std::string Record<ESM::Land>::getId() const;
|
||||||
template<> std::string Record<ESM::Skill>::getId() const;
|
template <>
|
||||||
|
std::string Record<ESM::MagicEffect>::getId() const;
|
||||||
|
template <>
|
||||||
|
std::string Record<ESM::Pathgrid>::getId() const;
|
||||||
|
template <>
|
||||||
|
std::string Record<ESM::Skill>::getId() const;
|
||||||
|
|
||||||
template<> void Record<ESM::Activator>::print();
|
template <>
|
||||||
template<> void Record<ESM::Potion>::print();
|
void Record<ESM::Activator>::print();
|
||||||
template<> void Record<ESM::Armor>::print();
|
template <>
|
||||||
template<> void Record<ESM::Apparatus>::print();
|
void Record<ESM::Potion>::print();
|
||||||
template<> void Record<ESM::BodyPart>::print();
|
template <>
|
||||||
template<> void Record<ESM::Book>::print();
|
void Record<ESM::Armor>::print();
|
||||||
template<> void Record<ESM::BirthSign>::print();
|
template <>
|
||||||
template<> void Record<ESM::Cell>::print();
|
void Record<ESM::Apparatus>::print();
|
||||||
template<> void Record<ESM::Class>::print();
|
template <>
|
||||||
template<> void Record<ESM::Clothing>::print();
|
void Record<ESM::BodyPart>::print();
|
||||||
template<> void Record<ESM::Container>::print();
|
template <>
|
||||||
template<> void Record<ESM::Creature>::print();
|
void Record<ESM::Book>::print();
|
||||||
template<> void Record<ESM::Dialogue>::print();
|
template <>
|
||||||
template<> void Record<ESM::Door>::print();
|
void Record<ESM::BirthSign>::print();
|
||||||
template<> void Record<ESM::Enchantment>::print();
|
template <>
|
||||||
template<> void Record<ESM::Faction>::print();
|
void Record<ESM::Cell>::print();
|
||||||
template<> void Record<ESM::Global>::print();
|
template <>
|
||||||
template<> void Record<ESM::GameSetting>::print();
|
void Record<ESM::Class>::print();
|
||||||
template<> void Record<ESM::DialInfo>::print();
|
template <>
|
||||||
template<> void Record<ESM::Ingredient>::print();
|
void Record<ESM::Clothing>::print();
|
||||||
template<> void Record<ESM::Land>::print();
|
template <>
|
||||||
template<> void Record<ESM::CreatureLevList>::print();
|
void Record<ESM::Container>::print();
|
||||||
template<> void Record<ESM::ItemLevList>::print();
|
template <>
|
||||||
template<> void Record<ESM::Light>::print();
|
void Record<ESM::Creature>::print();
|
||||||
template<> void Record<ESM::Lockpick>::print();
|
template <>
|
||||||
template<> void Record<ESM::Probe>::print();
|
void Record<ESM::Dialogue>::print();
|
||||||
template<> void Record<ESM::Repair>::print();
|
template <>
|
||||||
template<> void Record<ESM::LandTexture>::print();
|
void Record<ESM::Door>::print();
|
||||||
template<> void Record<ESM::MagicEffect>::print();
|
template <>
|
||||||
template<> void Record<ESM::Miscellaneous>::print();
|
void Record<ESM::Enchantment>::print();
|
||||||
template<> void Record<ESM::NPC>::print();
|
template <>
|
||||||
template<> void Record<ESM::Pathgrid>::print();
|
void Record<ESM::Faction>::print();
|
||||||
template<> void Record<ESM::Race>::print();
|
template <>
|
||||||
template<> void Record<ESM::Region>::print();
|
void Record<ESM::Global>::print();
|
||||||
template<> void Record<ESM::Script>::print();
|
template <>
|
||||||
template<> void Record<ESM::Skill>::print();
|
void Record<ESM::GameSetting>::print();
|
||||||
template<> void Record<ESM::SoundGenerator>::print();
|
template <>
|
||||||
template<> void Record<ESM::Sound>::print();
|
void Record<ESM::DialInfo>::print();
|
||||||
template<> void Record<ESM::Spell>::print();
|
template <>
|
||||||
template<> void Record<ESM::StartScript>::print();
|
void Record<ESM::Ingredient>::print();
|
||||||
template<> void Record<ESM::Static>::print();
|
template <>
|
||||||
template<> void Record<ESM::Weapon>::print();
|
void Record<ESM::Land>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::CreatureLevList>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::ItemLevList>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Light>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Lockpick>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Probe>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Repair>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::LandTexture>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::MagicEffect>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Miscellaneous>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::NPC>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Pathgrid>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Race>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Region>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Script>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Skill>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::SoundGenerator>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Sound>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Spell>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::StartScript>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Static>::print();
|
||||||
|
template <>
|
||||||
|
void Record<ESM::Weapon>::print();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,79 +21,115 @@ namespace EsmTool
|
||||||
|
|
||||||
explicit Params(const Arguments& info)
|
explicit Params(const Arguments& info)
|
||||||
: mQuite(info.quiet_given || info.mode == "clone")
|
: mQuite(info.quiet_given || info.mode == "clone")
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string toString(ESM4::GroupType type)
|
std::string toString(ESM4::GroupType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ESM4::Grp_RecordType: return "RecordType";
|
case ESM4::Grp_RecordType:
|
||||||
case ESM4::Grp_WorldChild: return "WorldChild";
|
return "RecordType";
|
||||||
case ESM4::Grp_InteriorCell: return "InteriorCell";
|
case ESM4::Grp_WorldChild:
|
||||||
case ESM4::Grp_InteriorSubCell: return "InteriorSubCell";
|
return "WorldChild";
|
||||||
case ESM4::Grp_ExteriorCell: return "ExteriorCell";
|
case ESM4::Grp_InteriorCell:
|
||||||
case ESM4::Grp_ExteriorSubCell: return "ExteriorSubCell";
|
return "InteriorCell";
|
||||||
case ESM4::Grp_CellChild: return "CellChild";
|
case ESM4::Grp_InteriorSubCell:
|
||||||
case ESM4::Grp_TopicChild: return "TopicChild";
|
return "InteriorSubCell";
|
||||||
case ESM4::Grp_CellPersistentChild: return "CellPersistentChild";
|
case ESM4::Grp_ExteriorCell:
|
||||||
case ESM4::Grp_CellTemporaryChild: return "CellTemporaryChild";
|
return "ExteriorCell";
|
||||||
case ESM4::Grp_CellVisibleDistChild: return "CellVisibleDistChild";
|
case ESM4::Grp_ExteriorSubCell:
|
||||||
|
return "ExteriorSubCell";
|
||||||
|
case ESM4::Grp_CellChild:
|
||||||
|
return "CellChild";
|
||||||
|
case ESM4::Grp_TopicChild:
|
||||||
|
return "TopicChild";
|
||||||
|
case ESM4::Grp_CellPersistentChild:
|
||||||
|
return "CellPersistentChild";
|
||||||
|
case ESM4::Grp_CellTemporaryChild:
|
||||||
|
return "CellTemporaryChild";
|
||||||
|
case ESM4::Grp_CellVisibleDistChild:
|
||||||
|
return "CellVisibleDistChild";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Unknown (" + std::to_string(type) + ")";
|
return "Unknown (" + std::to_string(type) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, class = std::void_t<>>
|
template <class T, class = std::void_t<>>
|
||||||
struct HasFormId : std::false_type {};
|
struct HasFormId : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct HasFormId<T, std::void_t<decltype(T::mFormId)>> : std::true_type {};
|
struct HasFormId<T, std::void_t<decltype(T::mFormId)>> : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool hasFormId = HasFormId<T>::value;
|
constexpr bool hasFormId = HasFormId<T>::value;
|
||||||
|
|
||||||
template <class T, class = std::void_t<>>
|
template <class T, class = std::void_t<>>
|
||||||
struct HasFlags : std::false_type {};
|
struct HasFlags : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct HasFlags<T, std::void_t<decltype(T::mFlags)>> : std::true_type {};
|
struct HasFlags<T, std::void_t<decltype(T::mFlags)>> : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool hasFlags = HasFlags<T>::value;
|
constexpr bool hasFlags = HasFlags<T>::value;
|
||||||
|
|
||||||
template <class T, class = std::void_t<>>
|
template <class T, class = std::void_t<>>
|
||||||
struct HasEditorId : std::false_type {};
|
struct HasEditorId : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct HasEditorId<T, std::void_t<decltype(T::mEditorId)>> : std::true_type {};
|
struct HasEditorId<T, std::void_t<decltype(T::mEditorId)>> : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool hasEditorId = HasEditorId<T>::value;
|
constexpr bool hasEditorId = HasEditorId<T>::value;
|
||||||
|
|
||||||
template <class T, class = std::void_t<>>
|
template <class T, class = std::void_t<>>
|
||||||
struct HasModel : std::false_type {};
|
struct HasModel : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct HasModel<T, std::void_t<decltype(T::mModel)>> : std::true_type {};
|
struct HasModel<T, std::void_t<decltype(T::mModel)>> : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool hasModel = HasModel<T>::value;
|
constexpr bool hasModel = HasModel<T>::value;
|
||||||
|
|
||||||
template <class T, class = std::void_t<>>
|
template <class T, class = std::void_t<>>
|
||||||
struct HasNif : std::false_type {};
|
struct HasNif : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct HasNif<T, std::void_t<decltype(T::mNif)>> : std::true_type {};
|
struct HasNif<T, std::void_t<decltype(T::mNif)>> : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool hasNif = HasNif<T>::value;
|
constexpr bool hasNif = HasNif<T>::value;
|
||||||
|
|
||||||
template <class T, class = std::void_t<>>
|
template <class T, class = std::void_t<>>
|
||||||
struct HasKf : std::false_type {};
|
struct HasKf : std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct HasKf<T, std::void_t<decltype(T::mKf)>> : std::true_type {};
|
struct HasKf<T, std::void_t<decltype(T::mKf)>> : std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
constexpr bool hasKf = HasKf<T>::value;
|
constexpr bool hasKf = HasKf<T>::value;
|
||||||
|
@ -150,148 +186,286 @@ namespace EsmTool
|
||||||
{
|
{
|
||||||
switch (static_cast<ESM4::RecordTypes>(reader.hdr().record.typeId))
|
switch (static_cast<ESM4::RecordTypes>(reader.hdr().record.typeId))
|
||||||
{
|
{
|
||||||
case ESM4::REC_AACT: break;
|
case ESM4::REC_AACT:
|
||||||
case ESM4::REC_ACHR: return readTypedRecord<ESM4::ActorCharacter>(params, reader);
|
break;
|
||||||
case ESM4::REC_ACRE: return readTypedRecord<ESM4::ActorCreature>(params, reader);
|
case ESM4::REC_ACHR:
|
||||||
case ESM4::REC_ACTI: return readTypedRecord<ESM4::Activator>(params, reader);
|
return readTypedRecord<ESM4::ActorCharacter>(params, reader);
|
||||||
case ESM4::REC_ADDN: break;
|
case ESM4::REC_ACRE:
|
||||||
case ESM4::REC_ALCH: return readTypedRecord<ESM4::Potion>(params, reader);
|
return readTypedRecord<ESM4::ActorCreature>(params, reader);
|
||||||
case ESM4::REC_ALOC: return readTypedRecord<ESM4::MediaLocationController>(params, reader);
|
case ESM4::REC_ACTI:
|
||||||
case ESM4::REC_AMMO: return readTypedRecord<ESM4::Ammunition>(params, reader);
|
return readTypedRecord<ESM4::Activator>(params, reader);
|
||||||
case ESM4::REC_ANIO: return readTypedRecord<ESM4::AnimObject>(params, reader);
|
case ESM4::REC_ADDN:
|
||||||
case ESM4::REC_APPA: return readTypedRecord<ESM4::Apparatus>(params, reader);
|
break;
|
||||||
case ESM4::REC_ARMA: return readTypedRecord<ESM4::ArmorAddon>(params, reader);
|
case ESM4::REC_ALCH:
|
||||||
case ESM4::REC_ARMO: return readTypedRecord<ESM4::Armor>(params, reader);
|
return readTypedRecord<ESM4::Potion>(params, reader);
|
||||||
case ESM4::REC_ARTO: break;
|
case ESM4::REC_ALOC:
|
||||||
case ESM4::REC_ASPC: return readTypedRecord<ESM4::AcousticSpace>(params, reader);
|
return readTypedRecord<ESM4::MediaLocationController>(params, reader);
|
||||||
case ESM4::REC_ASTP: break;
|
case ESM4::REC_AMMO:
|
||||||
case ESM4::REC_AVIF: break;
|
return readTypedRecord<ESM4::Ammunition>(params, reader);
|
||||||
case ESM4::REC_BOOK: return readTypedRecord<ESM4::Book>(params, reader);
|
case ESM4::REC_ANIO:
|
||||||
case ESM4::REC_BPTD: return readTypedRecord<ESM4::BodyPartData>(params, reader);
|
return readTypedRecord<ESM4::AnimObject>(params, reader);
|
||||||
case ESM4::REC_CAMS: break;
|
case ESM4::REC_APPA:
|
||||||
case ESM4::REC_CCRD: break;
|
return readTypedRecord<ESM4::Apparatus>(params, reader);
|
||||||
case ESM4::REC_CELL: return readTypedRecord<ESM4::Cell>(params, reader);
|
case ESM4::REC_ARMA:
|
||||||
case ESM4::REC_CLAS: return readTypedRecord<ESM4::Class>(params, reader);
|
return readTypedRecord<ESM4::ArmorAddon>(params, reader);
|
||||||
case ESM4::REC_CLFM: return readTypedRecord<ESM4::Colour>(params, reader);
|
case ESM4::REC_ARMO:
|
||||||
case ESM4::REC_CLMT: break;
|
return readTypedRecord<ESM4::Armor>(params, reader);
|
||||||
case ESM4::REC_CLOT: return readTypedRecord<ESM4::Clothing>(params, reader);
|
case ESM4::REC_ARTO:
|
||||||
case ESM4::REC_CMNY: break;
|
break;
|
||||||
case ESM4::REC_COBJ: break;
|
case ESM4::REC_ASPC:
|
||||||
case ESM4::REC_COLL: break;
|
return readTypedRecord<ESM4::AcousticSpace>(params, reader);
|
||||||
case ESM4::REC_CONT: return readTypedRecord<ESM4::Container>(params, reader);
|
case ESM4::REC_ASTP:
|
||||||
case ESM4::REC_CPTH: break;
|
break;
|
||||||
case ESM4::REC_CREA: return readTypedRecord<ESM4::Creature>(params, reader);
|
case ESM4::REC_AVIF:
|
||||||
case ESM4::REC_CSTY: break;
|
break;
|
||||||
case ESM4::REC_DEBR: break;
|
case ESM4::REC_BOOK:
|
||||||
case ESM4::REC_DIAL: return readTypedRecord<ESM4::Dialogue>(params, reader);
|
return readTypedRecord<ESM4::Book>(params, reader);
|
||||||
case ESM4::REC_DLBR: break;
|
case ESM4::REC_BPTD:
|
||||||
case ESM4::REC_DLVW: break;
|
return readTypedRecord<ESM4::BodyPartData>(params, reader);
|
||||||
case ESM4::REC_DOBJ: return readTypedRecord<ESM4::DefaultObj>(params, reader);
|
case ESM4::REC_CAMS:
|
||||||
case ESM4::REC_DOOR: return readTypedRecord<ESM4::Door>(params, reader);
|
break;
|
||||||
case ESM4::REC_DUAL: break;
|
case ESM4::REC_CCRD:
|
||||||
case ESM4::REC_ECZN: break;
|
break;
|
||||||
case ESM4::REC_EFSH: break;
|
case ESM4::REC_CELL:
|
||||||
case ESM4::REC_ENCH: break;
|
return readTypedRecord<ESM4::Cell>(params, reader);
|
||||||
case ESM4::REC_EQUP: break;
|
case ESM4::REC_CLAS:
|
||||||
case ESM4::REC_EXPL: break;
|
return readTypedRecord<ESM4::Class>(params, reader);
|
||||||
case ESM4::REC_EYES: return readTypedRecord<ESM4::Eyes>(params, reader);
|
case ESM4::REC_CLFM:
|
||||||
case ESM4::REC_FACT: break;
|
return readTypedRecord<ESM4::Colour>(params, reader);
|
||||||
case ESM4::REC_FLOR: return readTypedRecord<ESM4::Flora>(params, reader);
|
case ESM4::REC_CLMT:
|
||||||
case ESM4::REC_FLST: return readTypedRecord<ESM4::FormIdList>(params, reader);
|
break;
|
||||||
case ESM4::REC_FSTP: break;
|
case ESM4::REC_CLOT:
|
||||||
case ESM4::REC_FSTS: break;
|
return readTypedRecord<ESM4::Clothing>(params, reader);
|
||||||
case ESM4::REC_FURN: return readTypedRecord<ESM4::Furniture>(params, reader);
|
case ESM4::REC_CMNY:
|
||||||
case ESM4::REC_GLOB: return readTypedRecord<ESM4::GlobalVariable>(params, reader);
|
break;
|
||||||
case ESM4::REC_GMST: break;
|
case ESM4::REC_COBJ:
|
||||||
case ESM4::REC_GRAS: return readTypedRecord<ESM4::Grass>(params, reader);
|
break;
|
||||||
case ESM4::REC_GRUP: break;
|
case ESM4::REC_COLL:
|
||||||
case ESM4::REC_HAIR: return readTypedRecord<ESM4::Hair>(params, reader);
|
break;
|
||||||
case ESM4::REC_HAZD: break;
|
case ESM4::REC_CONT:
|
||||||
case ESM4::REC_HDPT: return readTypedRecord<ESM4::HeadPart>(params, reader);
|
return readTypedRecord<ESM4::Container>(params, reader);
|
||||||
|
case ESM4::REC_CPTH:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_CREA:
|
||||||
|
return readTypedRecord<ESM4::Creature>(params, reader);
|
||||||
|
case ESM4::REC_CSTY:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_DEBR:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_DIAL:
|
||||||
|
return readTypedRecord<ESM4::Dialogue>(params, reader);
|
||||||
|
case ESM4::REC_DLBR:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_DLVW:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_DOBJ:
|
||||||
|
return readTypedRecord<ESM4::DefaultObj>(params, reader);
|
||||||
|
case ESM4::REC_DOOR:
|
||||||
|
return readTypedRecord<ESM4::Door>(params, reader);
|
||||||
|
case ESM4::REC_DUAL:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_ECZN:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_EFSH:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_ENCH:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_EQUP:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_EXPL:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_EYES:
|
||||||
|
return readTypedRecord<ESM4::Eyes>(params, reader);
|
||||||
|
case ESM4::REC_FACT:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_FLOR:
|
||||||
|
return readTypedRecord<ESM4::Flora>(params, reader);
|
||||||
|
case ESM4::REC_FLST:
|
||||||
|
return readTypedRecord<ESM4::FormIdList>(params, reader);
|
||||||
|
case ESM4::REC_FSTP:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_FSTS:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_FURN:
|
||||||
|
return readTypedRecord<ESM4::Furniture>(params, reader);
|
||||||
|
case ESM4::REC_GLOB:
|
||||||
|
return readTypedRecord<ESM4::GlobalVariable>(params, reader);
|
||||||
|
case ESM4::REC_GMST:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_GRAS:
|
||||||
|
return readTypedRecord<ESM4::Grass>(params, reader);
|
||||||
|
case ESM4::REC_GRUP:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_HAIR:
|
||||||
|
return readTypedRecord<ESM4::Hair>(params, reader);
|
||||||
|
case ESM4::REC_HAZD:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_HDPT:
|
||||||
|
return readTypedRecord<ESM4::HeadPart>(params, reader);
|
||||||
case ESM4::REC_IDLE:
|
case ESM4::REC_IDLE:
|
||||||
// FIXME: ESM4::IdleAnimation::load does not work with Oblivion.esm
|
// FIXME: ESM4::IdleAnimation::load does not work with Oblivion.esm
|
||||||
// return readTypedRecord<ESM4::IdleAnimation>(params, reader);
|
// return readTypedRecord<ESM4::IdleAnimation>(params, reader);
|
||||||
break;
|
break;
|
||||||
case ESM4::REC_IDLM: return readTypedRecord<ESM4::IdleMarker>(params, reader);
|
case ESM4::REC_IDLM:
|
||||||
case ESM4::REC_IMAD: break;
|
return readTypedRecord<ESM4::IdleMarker>(params, reader);
|
||||||
case ESM4::REC_IMGS: break;
|
case ESM4::REC_IMAD:
|
||||||
case ESM4::REC_IMOD: return readTypedRecord<ESM4::ItemMod>(params, reader);
|
break;
|
||||||
case ESM4::REC_INFO: return readTypedRecord<ESM4::DialogInfo>(params, reader);
|
case ESM4::REC_IMGS:
|
||||||
case ESM4::REC_INGR: return readTypedRecord<ESM4::Ingredient>(params, reader);
|
break;
|
||||||
case ESM4::REC_IPCT: break;
|
case ESM4::REC_IMOD:
|
||||||
case ESM4::REC_IPDS: break;
|
return readTypedRecord<ESM4::ItemMod>(params, reader);
|
||||||
case ESM4::REC_KEYM: return readTypedRecord<ESM4::Key>(params, reader);
|
case ESM4::REC_INFO:
|
||||||
case ESM4::REC_KYWD: break;
|
return readTypedRecord<ESM4::DialogInfo>(params, reader);
|
||||||
case ESM4::REC_LAND: return readTypedRecord<ESM4::Land>(params, reader);
|
case ESM4::REC_INGR:
|
||||||
case ESM4::REC_LCRT: break;
|
return readTypedRecord<ESM4::Ingredient>(params, reader);
|
||||||
case ESM4::REC_LCTN: break;
|
case ESM4::REC_IPCT:
|
||||||
case ESM4::REC_LGTM: return readTypedRecord<ESM4::LightingTemplate>(params, reader);
|
break;
|
||||||
case ESM4::REC_LIGH: return readTypedRecord<ESM4::Light>(params, reader);
|
case ESM4::REC_IPDS:
|
||||||
case ESM4::REC_LSCR: break;
|
break;
|
||||||
case ESM4::REC_LTEX: return readTypedRecord<ESM4::LandTexture>(params, reader);
|
case ESM4::REC_KEYM:
|
||||||
case ESM4::REC_LVLC: return readTypedRecord<ESM4::LevelledCreature>(params, reader);
|
return readTypedRecord<ESM4::Key>(params, reader);
|
||||||
case ESM4::REC_LVLI: return readTypedRecord<ESM4::LevelledItem>(params, reader);
|
case ESM4::REC_KYWD:
|
||||||
case ESM4::REC_LVLN: return readTypedRecord<ESM4::LevelledNpc>(params, reader);
|
break;
|
||||||
case ESM4::REC_LVSP: break;
|
case ESM4::REC_LAND:
|
||||||
case ESM4::REC_MATO: return readTypedRecord<ESM4::Material>(params, reader);
|
return readTypedRecord<ESM4::Land>(params, reader);
|
||||||
case ESM4::REC_MATT: break;
|
case ESM4::REC_LCRT:
|
||||||
case ESM4::REC_MESG: break;
|
break;
|
||||||
case ESM4::REC_MGEF: break;
|
case ESM4::REC_LCTN:
|
||||||
case ESM4::REC_MISC: return readTypedRecord<ESM4::MiscItem>(params, reader);
|
break;
|
||||||
case ESM4::REC_MOVT: break;
|
case ESM4::REC_LGTM:
|
||||||
case ESM4::REC_MSET: return readTypedRecord<ESM4::MediaSet>(params, reader);
|
return readTypedRecord<ESM4::LightingTemplate>(params, reader);
|
||||||
case ESM4::REC_MSTT: return readTypedRecord<ESM4::MovableStatic>(params, reader);
|
case ESM4::REC_LIGH:
|
||||||
case ESM4::REC_MUSC: return readTypedRecord<ESM4::Music>(params, reader);
|
return readTypedRecord<ESM4::Light>(params, reader);
|
||||||
case ESM4::REC_MUST: break;
|
case ESM4::REC_LSCR:
|
||||||
case ESM4::REC_NAVI: return readTypedRecord<ESM4::Navigation>(params, reader);
|
break;
|
||||||
case ESM4::REC_NAVM: return readTypedRecord<ESM4::NavMesh>(params, reader);
|
case ESM4::REC_LTEX:
|
||||||
case ESM4::REC_NOTE: return readTypedRecord<ESM4::Note>(params, reader);
|
return readTypedRecord<ESM4::LandTexture>(params, reader);
|
||||||
case ESM4::REC_NPC_: return readTypedRecord<ESM4::Npc>(params, reader);
|
case ESM4::REC_LVLC:
|
||||||
case ESM4::REC_OTFT: return readTypedRecord<ESM4::Outfit>(params, reader);
|
return readTypedRecord<ESM4::LevelledCreature>(params, reader);
|
||||||
case ESM4::REC_PACK: return readTypedRecord<ESM4::AIPackage>(params, reader);
|
case ESM4::REC_LVLI:
|
||||||
case ESM4::REC_PERK: break;
|
return readTypedRecord<ESM4::LevelledItem>(params, reader);
|
||||||
case ESM4::REC_PGRD: return readTypedRecord<ESM4::Pathgrid>(params, reader);
|
case ESM4::REC_LVLN:
|
||||||
case ESM4::REC_PGRE: return readTypedRecord<ESM4::PlacedGrenade>(params, reader);
|
return readTypedRecord<ESM4::LevelledNpc>(params, reader);
|
||||||
case ESM4::REC_PHZD: break;
|
case ESM4::REC_LVSP:
|
||||||
case ESM4::REC_PROJ: break;
|
break;
|
||||||
case ESM4::REC_PWAT: return readTypedRecord<ESM4::PlaceableWater>(params, reader);
|
case ESM4::REC_MATO:
|
||||||
case ESM4::REC_QUST: return readTypedRecord<ESM4::Quest>(params, reader);
|
return readTypedRecord<ESM4::Material>(params, reader);
|
||||||
case ESM4::REC_RACE: return readTypedRecord<ESM4::Race>(params, reader);
|
case ESM4::REC_MATT:
|
||||||
case ESM4::REC_REFR: return readTypedRecord<ESM4::Reference>(params, reader);
|
break;
|
||||||
case ESM4::REC_REGN: return readTypedRecord<ESM4::Region>(params, reader);
|
case ESM4::REC_MESG:
|
||||||
case ESM4::REC_RELA: break;
|
break;
|
||||||
case ESM4::REC_REVB: break;
|
case ESM4::REC_MGEF:
|
||||||
case ESM4::REC_RFCT: break;
|
break;
|
||||||
case ESM4::REC_ROAD: return readTypedRecord<ESM4::Road>(params, reader);
|
case ESM4::REC_MISC:
|
||||||
case ESM4::REC_SBSP: return readTypedRecord<ESM4::SubSpace>(params, reader);
|
return readTypedRecord<ESM4::MiscItem>(params, reader);
|
||||||
case ESM4::REC_SCEN: break;
|
case ESM4::REC_MOVT:
|
||||||
case ESM4::REC_SCOL: return readTypedRecord<ESM4::StaticCollection>(params, reader);
|
break;
|
||||||
case ESM4::REC_SCPT: return readTypedRecord<ESM4::Script>(params, reader);
|
case ESM4::REC_MSET:
|
||||||
case ESM4::REC_SCRL: return readTypedRecord<ESM4::Scroll>(params, reader);
|
return readTypedRecord<ESM4::MediaSet>(params, reader);
|
||||||
case ESM4::REC_SGST: return readTypedRecord<ESM4::SigilStone>(params, reader);
|
case ESM4::REC_MSTT:
|
||||||
case ESM4::REC_SHOU: break;
|
return readTypedRecord<ESM4::MovableStatic>(params, reader);
|
||||||
case ESM4::REC_SLGM: return readTypedRecord<ESM4::SoulGem>(params, reader);
|
case ESM4::REC_MUSC:
|
||||||
case ESM4::REC_SMBN: break;
|
return readTypedRecord<ESM4::Music>(params, reader);
|
||||||
case ESM4::REC_SMEN: break;
|
case ESM4::REC_MUST:
|
||||||
case ESM4::REC_SMQN: break;
|
break;
|
||||||
case ESM4::REC_SNCT: break;
|
case ESM4::REC_NAVI:
|
||||||
case ESM4::REC_SNDR: return readTypedRecord<ESM4::SoundReference>(params, reader);
|
return readTypedRecord<ESM4::Navigation>(params, reader);
|
||||||
case ESM4::REC_SOPM: break;
|
case ESM4::REC_NAVM:
|
||||||
case ESM4::REC_SOUN: return readTypedRecord<ESM4::Sound>(params, reader);
|
return readTypedRecord<ESM4::NavMesh>(params, reader);
|
||||||
case ESM4::REC_SPEL: break;
|
case ESM4::REC_NOTE:
|
||||||
case ESM4::REC_SPGD: break;
|
return readTypedRecord<ESM4::Note>(params, reader);
|
||||||
case ESM4::REC_STAT: return readTypedRecord<ESM4::Static>(params, reader);
|
case ESM4::REC_NPC_:
|
||||||
case ESM4::REC_TACT: return readTypedRecord<ESM4::TalkingActivator>(params, reader);
|
return readTypedRecord<ESM4::Npc>(params, reader);
|
||||||
case ESM4::REC_TERM: return readTypedRecord<ESM4::Terminal>(params, reader);
|
case ESM4::REC_OTFT:
|
||||||
case ESM4::REC_TES4: return readTypedRecord<ESM4::Header>(params, reader);
|
return readTypedRecord<ESM4::Outfit>(params, reader);
|
||||||
case ESM4::REC_TREE: return readTypedRecord<ESM4::Tree>(params, reader);
|
case ESM4::REC_PACK:
|
||||||
case ESM4::REC_TXST: return readTypedRecord<ESM4::TextureSet>(params, reader);
|
return readTypedRecord<ESM4::AIPackage>(params, reader);
|
||||||
case ESM4::REC_VTYP: break;
|
case ESM4::REC_PERK:
|
||||||
case ESM4::REC_WATR: break;
|
break;
|
||||||
case ESM4::REC_WEAP: return readTypedRecord<ESM4::Weapon>(params, reader);
|
case ESM4::REC_PGRD:
|
||||||
case ESM4::REC_WOOP: break;
|
return readTypedRecord<ESM4::Pathgrid>(params, reader);
|
||||||
case ESM4::REC_WRLD: return readTypedRecord<ESM4::World>(params, reader);
|
case ESM4::REC_PGRE:
|
||||||
case ESM4::REC_WTHR: break;
|
return readTypedRecord<ESM4::PlacedGrenade>(params, reader);
|
||||||
|
case ESM4::REC_PHZD:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_PROJ:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_PWAT:
|
||||||
|
return readTypedRecord<ESM4::PlaceableWater>(params, reader);
|
||||||
|
case ESM4::REC_QUST:
|
||||||
|
return readTypedRecord<ESM4::Quest>(params, reader);
|
||||||
|
case ESM4::REC_RACE:
|
||||||
|
return readTypedRecord<ESM4::Race>(params, reader);
|
||||||
|
case ESM4::REC_REFR:
|
||||||
|
return readTypedRecord<ESM4::Reference>(params, reader);
|
||||||
|
case ESM4::REC_REGN:
|
||||||
|
return readTypedRecord<ESM4::Region>(params, reader);
|
||||||
|
case ESM4::REC_RELA:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_REVB:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_RFCT:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_ROAD:
|
||||||
|
return readTypedRecord<ESM4::Road>(params, reader);
|
||||||
|
case ESM4::REC_SBSP:
|
||||||
|
return readTypedRecord<ESM4::SubSpace>(params, reader);
|
||||||
|
case ESM4::REC_SCEN:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_SCOL:
|
||||||
|
return readTypedRecord<ESM4::StaticCollection>(params, reader);
|
||||||
|
case ESM4::REC_SCPT:
|
||||||
|
return readTypedRecord<ESM4::Script>(params, reader);
|
||||||
|
case ESM4::REC_SCRL:
|
||||||
|
return readTypedRecord<ESM4::Scroll>(params, reader);
|
||||||
|
case ESM4::REC_SGST:
|
||||||
|
return readTypedRecord<ESM4::SigilStone>(params, reader);
|
||||||
|
case ESM4::REC_SHOU:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_SLGM:
|
||||||
|
return readTypedRecord<ESM4::SoulGem>(params, reader);
|
||||||
|
case ESM4::REC_SMBN:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_SMEN:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_SMQN:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_SNCT:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_SNDR:
|
||||||
|
return readTypedRecord<ESM4::SoundReference>(params, reader);
|
||||||
|
case ESM4::REC_SOPM:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_SOUN:
|
||||||
|
return readTypedRecord<ESM4::Sound>(params, reader);
|
||||||
|
case ESM4::REC_SPEL:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_SPGD:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_STAT:
|
||||||
|
return readTypedRecord<ESM4::Static>(params, reader);
|
||||||
|
case ESM4::REC_TACT:
|
||||||
|
return readTypedRecord<ESM4::TalkingActivator>(params, reader);
|
||||||
|
case ESM4::REC_TERM:
|
||||||
|
return readTypedRecord<ESM4::Terminal>(params, reader);
|
||||||
|
case ESM4::REC_TES4:
|
||||||
|
return readTypedRecord<ESM4::Header>(params, reader);
|
||||||
|
case ESM4::REC_TREE:
|
||||||
|
return readTypedRecord<ESM4::Tree>(params, reader);
|
||||||
|
case ESM4::REC_TXST:
|
||||||
|
return readTypedRecord<ESM4::TextureSet>(params, reader);
|
||||||
|
case ESM4::REC_VTYP:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_WATR:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_WEAP:
|
||||||
|
return readTypedRecord<ESM4::Weapon>(params, reader);
|
||||||
|
case ESM4::REC_WOOP:
|
||||||
|
break;
|
||||||
|
case ESM4::REC_WRLD:
|
||||||
|
return readTypedRecord<ESM4::World>(params, reader);
|
||||||
|
case ESM4::REC_WTHR:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.mQuite)
|
if (!params.mQuite)
|
||||||
|
@ -307,8 +481,8 @@ namespace EsmTool
|
||||||
const ESM4::RecordHeader& header = reader.hdr();
|
const ESM4::RecordHeader& header = reader.hdr();
|
||||||
|
|
||||||
if (!params.mQuite)
|
if (!params.mQuite)
|
||||||
std::cout << "\nGroup: " << toString(static_cast<ESM4::GroupType>(header.group.type))
|
std::cout << "\nGroup: " << toString(static_cast<ESM4::GroupType>(header.group.type)) << " "
|
||||||
<< " " << ESM::NAME(header.group.typeId).toStringView() << '\n';
|
<< ESM::NAME(header.group.typeId).toStringView() << '\n';
|
||||||
|
|
||||||
switch (static_cast<ESM4::GroupType>(header.group.type))
|
switch (static_cast<ESM4::GroupType>(header.group.type))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <components/misc/strings/lower.hpp>
|
#include <components/misc/strings/lower.hpp>
|
||||||
|
|
||||||
|
@ -57,30 +57,27 @@ namespace ESSImport
|
||||||
|
|
||||||
void convertANIS(const ANIS& anis, ESM::AnimationState& state)
|
void convertANIS(const ANIS& anis, ESM::AnimationState& state)
|
||||||
{
|
{
|
||||||
static const char* animGroups[] =
|
static const char* animGroups[] = { "Idle", "Idle2", "Idle3", "Idle4", "Idle5", "Idle6", "Idle7", "Idle8",
|
||||||
{
|
"Idle9", "Idlehh", "Idle1h", "Idle2c", "Idle2w", "IdleSwim", "IdleSpell", "IdleCrossbow", "IdleSneak",
|
||||||
"Idle", "Idle2", "Idle3", "Idle4", "Idle5", "Idle6", "Idle7", "Idle8", "Idle9", "Idlehh", "Idle1h", "Idle2c",
|
"IdleStorm", "Torch", "Hit1", "Hit2", "Hit3", "Hit4", "Hit5", "SwimHit1", "SwimHit2", "SwimHit3", "Death1",
|
||||||
"Idle2w", "IdleSwim", "IdleSpell", "IdleCrossbow", "IdleSneak", "IdleStorm", "Torch", "Hit1", "Hit2", "Hit3",
|
"Death2", "Death3", "Death4", "Death5", "DeathKnockDown", "DeathKnockOut", "KnockDown", "KnockOut",
|
||||||
"Hit4", "Hit5", "SwimHit1", "SwimHit2", "SwimHit3", "Death1", "Death2", "Death3", "Death4", "Death5",
|
"SwimDeath", "SwimDeath2", "SwimDeath3", "SwimDeathKnockDown", "SwimDeathKnockOut", "SwimKnockOut",
|
||||||
"DeathKnockDown", "DeathKnockOut", "KnockDown", "KnockOut", "SwimDeath", "SwimDeath2", "SwimDeath3",
|
"SwimKnockDown", "SwimWalkForward", "SwimWalkBack", "SwimWalkLeft", "SwimWalkRight", "SwimRunForward",
|
||||||
"SwimDeathKnockDown", "SwimDeathKnockOut", "SwimKnockOut", "SwimKnockDown", "SwimWalkForward",
|
"SwimRunBack", "SwimRunLeft", "SwimRunRight", "SwimTurnLeft", "SwimTurnRight", "WalkForward", "WalkBack",
|
||||||
"SwimWalkBack", "SwimWalkLeft", "SwimWalkRight", "SwimRunForward", "SwimRunBack", "SwimRunLeft",
|
"WalkLeft", "WalkRight", "TurnLeft", "TurnRight", "RunForward", "RunBack", "RunLeft", "RunRight",
|
||||||
"SwimRunRight", "SwimTurnLeft", "SwimTurnRight", "WalkForward", "WalkBack", "WalkLeft", "WalkRight",
|
"SneakForward", "SneakBack", "SneakLeft", "SneakRight", "Jump", "WalkForwardhh", "WalkBackhh", "WalkLefthh",
|
||||||
"TurnLeft", "TurnRight", "RunForward", "RunBack", "RunLeft", "RunRight", "SneakForward", "SneakBack",
|
"WalkRighthh", "TurnLefthh", "TurnRighthh", "RunForwardhh", "RunBackhh", "RunLefthh", "RunRighthh",
|
||||||
"SneakLeft", "SneakRight", "Jump", "WalkForwardhh", "WalkBackhh", "WalkLefthh", "WalkRighthh",
|
"SneakForwardhh", "SneakBackhh", "SneakLefthh", "SneakRighthh", "Jumphh", "WalkForward1h", "WalkBack1h",
|
||||||
"TurnLefthh", "TurnRighthh", "RunForwardhh", "RunBackhh", "RunLefthh", "RunRighthh", "SneakForwardhh",
|
"WalkLeft1h", "WalkRight1h", "TurnLeft1h", "TurnRight1h", "RunForward1h", "RunBack1h", "RunLeft1h",
|
||||||
"SneakBackhh", "SneakLefthh", "SneakRighthh", "Jumphh", "WalkForward1h", "WalkBack1h", "WalkLeft1h",
|
"RunRight1h", "SneakForward1h", "SneakBack1h", "SneakLeft1h", "SneakRight1h", "Jump1h", "WalkForward2c",
|
||||||
"WalkRight1h", "TurnLeft1h", "TurnRight1h", "RunForward1h", "RunBack1h", "RunLeft1h", "RunRight1h",
|
"WalkBack2c", "WalkLeft2c", "WalkRight2c", "TurnLeft2c", "TurnRight2c", "RunForward2c", "RunBack2c",
|
||||||
"SneakForward1h", "SneakBack1h", "SneakLeft1h", "SneakRight1h", "Jump1h", "WalkForward2c", "WalkBack2c",
|
"RunLeft2c", "RunRight2c", "SneakForward2c", "SneakBack2c", "SneakLeft2c", "SneakRight2c", "Jump2c",
|
||||||
"WalkLeft2c", "WalkRight2c", "TurnLeft2c", "TurnRight2c", "RunForward2c", "RunBack2c", "RunLeft2c",
|
"WalkForward2w", "WalkBack2w", "WalkLeft2w", "WalkRight2w", "TurnLeft2w", "TurnRight2w", "RunForward2w",
|
||||||
"RunRight2c", "SneakForward2c", "SneakBack2c", "SneakLeft2c", "SneakRight2c", "Jump2c", "WalkForward2w",
|
"RunBack2w", "RunLeft2w", "RunRight2w", "SneakForward2w", "SneakBack2w", "SneakLeft2w", "SneakRight2w",
|
||||||
"WalkBack2w", "WalkLeft2w", "WalkRight2w", "TurnLeft2w", "TurnRight2w", "RunForward2w", "RunBack2w",
|
"Jump2w", "SpellCast", "SpellTurnLeft", "SpellTurnRight", "Attack1", "Attack2", "Attack3", "SwimAttack1",
|
||||||
"RunLeft2w", "RunRight2w", "SneakForward2w", "SneakBack2w", "SneakLeft2w", "SneakRight2w", "Jump2w",
|
|
||||||
"SpellCast", "SpellTurnLeft", "SpellTurnRight", "Attack1", "Attack2", "Attack3", "SwimAttack1",
|
|
||||||
"SwimAttack2", "SwimAttack3", "HandToHand", "Crossbow", "BowAndArrow", "ThrowWeapon", "WeaponOneHand",
|
"SwimAttack2", "SwimAttack3", "HandToHand", "Crossbow", "BowAndArrow", "ThrowWeapon", "WeaponOneHand",
|
||||||
"WeaponTwoHand", "WeaponTwoWide", "Shield", "PickProbe", "InventoryHandToHand", "InventoryWeaponOneHand",
|
"WeaponTwoHand", "WeaponTwoWide", "Shield", "PickProbe", "InventoryHandToHand", "InventoryWeaponOneHand",
|
||||||
"InventoryWeaponTwoHand", "InventoryWeaponTwoWide"
|
"InventoryWeaponTwoHand", "InventoryWeaponTwoWide" };
|
||||||
};
|
|
||||||
|
|
||||||
if (anis.mGroupIndex < (sizeof(animGroups) / sizeof(*animGroups)))
|
if (anis.mGroupIndex < (sizeof(animGroups) / sizeof(*animGroups)))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#ifndef OPENMW_ESSIMPORT_CONVERTACDT_H
|
#ifndef OPENMW_ESSIMPORT_CONVERTACDT_H
|
||||||
#define OPENMW_ESSIMPORT_CONVERTACDT_H
|
#define OPENMW_ESSIMPORT_CONVERTACDT_H
|
||||||
|
|
||||||
#include <components/esm3/creaturestats.hpp>
|
|
||||||
#include <components/esm3/npcstats.hpp>
|
|
||||||
#include <components/esm3/loadskil.hpp>
|
|
||||||
#include <components/esm3/animationstate.hpp>
|
#include <components/esm3/animationstate.hpp>
|
||||||
|
#include <components/esm3/creaturestats.hpp>
|
||||||
|
#include <components/esm3/loadskil.hpp>
|
||||||
|
#include <components/esm3/npcstats.hpp>
|
||||||
|
|
||||||
#include "importacdt.hpp"
|
#include "importacdt.hpp"
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ namespace ESSImport
|
||||||
// OpenMW uses Health,Magicka,Fatigue, MW uses Health,Fatigue,Magicka
|
// OpenMW uses Health,Magicka,Fatigue, MW uses Health,Fatigue,Magicka
|
||||||
int translateDynamicIndex(int mwIndex);
|
int translateDynamicIndex(int mwIndex);
|
||||||
|
|
||||||
|
|
||||||
void convertACDT(const ACDT& acdt, ESM::CreatureStats& cStats);
|
void convertACDT(const ACDT& acdt, ESM::CreatureStats& cStats);
|
||||||
void convertACSC(const ACSC& acsc, ESM::CreatureStats& cStats);
|
void convertACSC(const ACSC& acsc, ESM::CreatureStats& cStats);
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
#include "converter.hpp"
|
#include "converter.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <osgDB/WriteFile>
|
#include <osgDB/WriteFile>
|
||||||
|
|
||||||
#include <components/esm3/creaturestate.hpp>
|
|
||||||
#include <components/esm3/containerstate.hpp>
|
#include <components/esm3/containerstate.hpp>
|
||||||
|
#include <components/esm3/creaturestate.hpp>
|
||||||
|
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
|
|
||||||
#include "convertcrec.hpp"
|
|
||||||
#include "convertcntc.hpp"
|
#include "convertcntc.hpp"
|
||||||
|
#include "convertcrec.hpp"
|
||||||
#include "convertscri.hpp"
|
#include "convertscri.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
@ -27,7 +27,6 @@ namespace
|
||||||
osgDB::writeImageFile(*image, out);
|
osgDB::writeImageFile(*image, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void convertCellRef(const ESSImport::CellRef& cellref, ESM::ObjectState& objstate)
|
void convertCellRef(const ESSImport::CellRef& cellref, ESM::ObjectState& objstate)
|
||||||
{
|
{
|
||||||
objstate.mEnabled = cellref.mEnabled;
|
objstate.mEnabled = cellref.mEnabled;
|
||||||
|
@ -89,7 +88,6 @@ namespace
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
struct MAPH
|
struct MAPH
|
||||||
{
|
{
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
@ -177,7 +175,8 @@ namespace ESSImport
|
||||||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image2, ostream);
|
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image2, ostream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: can't write global map image: " << result.message() << " code " << result.status() << std::endl;
|
std::cerr << "Error: can't write global map image: " << result.message() << " code " << result.status()
|
||||||
|
<< std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,7 +251,8 @@ namespace ESSImport
|
||||||
std::ostringstream filename;
|
std::ostringstream filename;
|
||||||
filename << "fog_" << cell.mData.mX << "_" << cell.mData.mY << ".tga";
|
filename << "fog_" << cell.mData.mX << "_" << cell.mData.mY << ".tga";
|
||||||
|
|
||||||
convertImage((char*)&newcell.mFogOfWar[0], newcell.mFogOfWar.size()*4, 16, 16, GL_RGBA, filename.str());
|
convertImage(
|
||||||
|
(char*)&newcell.mFogOfWar[0], newcell.mFogOfWar.size() * 4, 16, 16, GL_RGBA, filename.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +307,6 @@ namespace ESSImport
|
||||||
|
|
||||||
newcell.mRefs = cellrefs;
|
newcell.mRefs = cellrefs;
|
||||||
|
|
||||||
|
|
||||||
if (cell.isExterior())
|
if (cell.isExterior())
|
||||||
mExtCells[std::make_pair(cell.mData.mX, cell.mData.mY)] = newcell;
|
mExtCells[std::make_pair(cell.mData.mX, cell.mData.mY)] = newcell;
|
||||||
else
|
else
|
||||||
|
@ -359,8 +358,7 @@ namespace ESSImport
|
||||||
|
|
||||||
std::string idLower = Misc::StringUtils::lowerCase(out.mRefID);
|
std::string idLower = Misc::StringUtils::lowerCase(out.mRefID);
|
||||||
|
|
||||||
auto npccIt = mContext->mNpcChanges.find(
|
auto npccIt = mContext->mNpcChanges.find(std::make_pair(refIndex, out.mRefID));
|
||||||
std::make_pair(refIndex, out.mRefID));
|
|
||||||
if (npccIt != mContext->mNpcChanges.end())
|
if (npccIt != mContext->mNpcChanges.end())
|
||||||
{
|
{
|
||||||
ESM::NpcState objstate;
|
ESM::NpcState objstate;
|
||||||
|
@ -380,15 +378,15 @@ namespace ESSImport
|
||||||
convertCellRef(cellref, objstate);
|
convertCellRef(cellref, objstate);
|
||||||
|
|
||||||
objstate.mCreatureStats.mActorId = mContext->generateActorId();
|
objstate.mCreatureStats.mActorId = mContext->generateActorId();
|
||||||
mContext->mActorIdMap.insert(std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
mContext->mActorIdMap.insert(
|
||||||
|
std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
||||||
|
|
||||||
esm.writeHNT("OBJE", ESM::REC_NPC_);
|
esm.writeHNT("OBJE", ESM::REC_NPC_);
|
||||||
objstate.save(esm);
|
objstate.save(esm);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cntcIt = mContext->mContainerChanges.find(
|
auto cntcIt = mContext->mContainerChanges.find(std::make_pair(refIndex, out.mRefID));
|
||||||
std::make_pair(refIndex, out.mRefID));
|
|
||||||
if (cntcIt != mContext->mContainerChanges.end())
|
if (cntcIt != mContext->mContainerChanges.end())
|
||||||
{
|
{
|
||||||
ESM::ContainerState objstate;
|
ESM::ContainerState objstate;
|
||||||
|
@ -402,8 +400,7 @@ namespace ESSImport
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto crecIt = mContext->mCreatureChanges.find(
|
auto crecIt = mContext->mCreatureChanges.find(std::make_pair(refIndex, out.mRefID));
|
||||||
std::make_pair(refIndex, out.mRefID));
|
|
||||||
if (crecIt != mContext->mCreatureChanges.end())
|
if (crecIt != mContext->mCreatureChanges.end())
|
||||||
{
|
{
|
||||||
ESM::CreatureState objstate;
|
ESM::CreatureState objstate;
|
||||||
|
@ -422,7 +419,8 @@ namespace ESSImport
|
||||||
convertCellRef(cellref, objstate);
|
convertCellRef(cellref, objstate);
|
||||||
|
|
||||||
objstate.mCreatureStats.mActorId = mContext->generateActorId();
|
objstate.mCreatureStats.mActorId = mContext->generateActorId();
|
||||||
mContext->mActorIdMap.insert(std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
mContext->mActorIdMap.insert(
|
||||||
|
std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
||||||
|
|
||||||
esm.writeHNT("OBJE", ESM::REC_CREA);
|
esm.writeHNT("OBJE", ESM::REC_CREA);
|
||||||
objstate.save(esm);
|
objstate.save(esm);
|
||||||
|
@ -486,7 +484,8 @@ namespace ESSImport
|
||||||
|
|
||||||
if (it == mContext->mActiveSpells.end())
|
if (it == mContext->mActiveSpells.end())
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: Skipped conversion for magic projectile \"" << pnam.mArrowId.toString() << "\" (invalid spell link)" << std::endl;
|
std::cerr << "Warning: Skipped conversion for magic projectile \"" << pnam.mArrowId.toString()
|
||||||
|
<< "\" (invalid spell link)" << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,42 +9,42 @@
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
#include <components/esm3/esmwriter.hpp>
|
#include <components/esm3/esmwriter.hpp>
|
||||||
|
|
||||||
#include <components/esm3/loadcell.hpp>
|
|
||||||
#include <components/esm3/loadbook.hpp>
|
|
||||||
#include <components/esm3/loadclas.hpp>
|
|
||||||
#include <components/esm3/loadglob.hpp>
|
|
||||||
#include <components/esm3/cellstate.hpp>
|
#include <components/esm3/cellstate.hpp>
|
||||||
#include <components/esm3/loadfact.hpp>
|
|
||||||
#include <components/esm3/dialoguestate.hpp>
|
|
||||||
#include <components/esm3/custommarkerstate.hpp>
|
#include <components/esm3/custommarkerstate.hpp>
|
||||||
#include <components/esm3/loadcrea.hpp>
|
#include <components/esm3/dialoguestate.hpp>
|
||||||
#include <components/esm3/weatherstate.hpp>
|
|
||||||
#include <components/esm3/globalscript.hpp>
|
#include <components/esm3/globalscript.hpp>
|
||||||
|
#include <components/esm3/loadbook.hpp>
|
||||||
|
#include <components/esm3/loadcell.hpp>
|
||||||
|
#include <components/esm3/loadclas.hpp>
|
||||||
|
#include <components/esm3/loadcrea.hpp>
|
||||||
|
#include <components/esm3/loadfact.hpp>
|
||||||
|
#include <components/esm3/loadglob.hpp>
|
||||||
|
#include <components/esm3/projectilestate.hpp>
|
||||||
#include <components/esm3/queststate.hpp>
|
#include <components/esm3/queststate.hpp>
|
||||||
#include <components/esm3/stolenitems.hpp>
|
#include <components/esm3/stolenitems.hpp>
|
||||||
#include <components/esm3/projectilestate.hpp>
|
#include <components/esm3/weatherstate.hpp>
|
||||||
|
|
||||||
#include <components/misc/strings/algorithm.hpp>
|
#include <components/misc/strings/algorithm.hpp>
|
||||||
|
|
||||||
#include "importcrec.hpp"
|
|
||||||
#include "importcntc.hpp"
|
#include "importcntc.hpp"
|
||||||
|
#include "importcrec.hpp"
|
||||||
|
|
||||||
#include "importercontext.hpp"
|
|
||||||
#include "importcellref.hpp"
|
#include "importcellref.hpp"
|
||||||
#include "importklst.hpp"
|
#include "importdial.hpp"
|
||||||
|
#include "importercontext.hpp"
|
||||||
#include "importgame.hpp"
|
#include "importgame.hpp"
|
||||||
#include "importinfo.hpp"
|
#include "importinfo.hpp"
|
||||||
#include "importdial.hpp"
|
|
||||||
#include "importques.hpp"
|
|
||||||
#include "importjour.hpp"
|
#include "importjour.hpp"
|
||||||
#include "importscpt.hpp"
|
#include "importklst.hpp"
|
||||||
#include "importproj.h"
|
#include "importproj.h"
|
||||||
|
#include "importques.hpp"
|
||||||
|
#include "importscpt.hpp"
|
||||||
#include "importsplm.h"
|
#include "importsplm.h"
|
||||||
|
|
||||||
#include "convertacdt.hpp"
|
#include "convertacdt.hpp"
|
||||||
#include "convertnpcc.hpp"
|
#include "convertnpcc.hpp"
|
||||||
#include "convertscpt.hpp"
|
|
||||||
#include "convertplayer.hpp"
|
#include "convertplayer.hpp"
|
||||||
|
#include "convertscpt.hpp"
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
@ -61,16 +61,11 @@ public:
|
||||||
|
|
||||||
/// @note The load method of ESM records accept the deleted flag as a parameter.
|
/// @note The load method of ESM records accept the deleted flag as a parameter.
|
||||||
/// I don't know can the DELE sub-record appear in saved games, so the deleted flag will be ignored.
|
/// I don't know can the DELE sub-record appear in saved games, so the deleted flag will be ignored.
|
||||||
virtual void read(ESM::ESMReader& esm)
|
virtual void read(ESM::ESMReader& esm) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called after the input file has been read in completely, which may be necessary
|
/// Called after the input file has been read in completely, which may be necessary
|
||||||
/// if the conversion process relies on information in other records
|
/// if the conversion process relies on information in other records
|
||||||
virtual void write(ESM::ESMWriter& esm)
|
virtual void write(ESM::ESMWriter& esm) {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Context* mContext;
|
Context* mContext;
|
||||||
|
@ -256,7 +251,8 @@ public:
|
||||||
for (unsigned int i = 0; i < invState.mItems.size(); ++i)
|
for (unsigned int i = 0; i < invState.mItems.size(); ++i)
|
||||||
{
|
{
|
||||||
// FIXME: in case of conflict (multiple items with this refID) use the already equipped one?
|
// FIXME: in case of conflict (multiple items with this refID) use the already equipped one?
|
||||||
if (Misc::StringUtils::ciEqual(invState.mItems[i].mRef.mRefID, refr.mActorData.mSelectedEnchantItem))
|
if (Misc::StringUtils::ciEqual(
|
||||||
|
invState.mItems[i].mRef.mRefID, refr.mActorData.mSelectedEnchantItem))
|
||||||
invState.mSelectedEnchantItem = i;
|
invState.mSelectedEnchantItem = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,6 +263,7 @@ public:
|
||||||
esm.writeHNString("ID__", mSelectedSpell);
|
esm.writeHNString("ID__", mSelectedSpell);
|
||||||
esm.endRecord(ESM::REC_ASPL);
|
esm.endRecord(ESM::REC_ASPL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string mSelectedSpell;
|
std::string mSelectedSpell;
|
||||||
};
|
};
|
||||||
|
@ -275,17 +272,19 @@ class ConvertPCDT : public Converter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConvertPCDT()
|
ConvertPCDT()
|
||||||
: mFirstPersonCam(true),
|
: mFirstPersonCam(true)
|
||||||
mTeleportingEnabled(true),
|
, mTeleportingEnabled(true)
|
||||||
mLevitationEnabled(true)
|
, mLevitationEnabled(true)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void read(ESM::ESMReader& esm) override
|
void read(ESM::ESMReader& esm) override
|
||||||
{
|
{
|
||||||
PCDT pcdt;
|
PCDT pcdt;
|
||||||
pcdt.load(esm);
|
pcdt.load(esm);
|
||||||
|
|
||||||
convertPCDT(pcdt, mContext->mPlayer, mContext->mDialogueState.mKnownTopics, mFirstPersonCam, mTeleportingEnabled, mLevitationEnabled, mContext->mControlsState);
|
convertPCDT(pcdt, mContext->mPlayer, mContext->mDialogueState.mKnownTopics, mFirstPersonCam,
|
||||||
|
mTeleportingEnabled, mLevitationEnabled, mContext->mControlsState);
|
||||||
}
|
}
|
||||||
void write(ESM::ESMWriter& esm) override
|
void write(ESM::ESMWriter& esm) override
|
||||||
{
|
{
|
||||||
|
@ -298,6 +297,7 @@ public:
|
||||||
esm.writeHNT("FIRS", mFirstPersonCam);
|
esm.writeHNT("FIRS", mFirstPersonCam);
|
||||||
esm.endRecord(ESM::REC_CAM_);
|
esm.endRecord(ESM::REC_CAM_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mFirstPersonCam;
|
bool mFirstPersonCam;
|
||||||
bool mTeleportingEnabled;
|
bool mTeleportingEnabled;
|
||||||
|
@ -441,7 +441,8 @@ public:
|
||||||
// it needs a count argument. But for legacy savegames, we don't know
|
// it needs a count argument. But for legacy savegames, we don't know
|
||||||
// this count, so must assume all items of that ID are stolen,
|
// this count, so must assume all items of that ID are stolen,
|
||||||
// like vanilla MW did.
|
// like vanilla MW did.
|
||||||
,std::numeric_limits<int>::max()));
|
,
|
||||||
|
std::numeric_limits<int>::max()));
|
||||||
}
|
}
|
||||||
|
|
||||||
items.mStolenItems.insert(std::make_pair(it->first, owners));
|
items.mStolenItems.insert(std::make_pair(it->first, owners));
|
||||||
|
@ -498,6 +499,7 @@ public:
|
||||||
esm.endRecord(ESM::REC_QUES);
|
esm.endRecord(ESM::REC_QUES);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, DIAL> mDials;
|
std::map<std::string, DIAL> mDials;
|
||||||
};
|
};
|
||||||
|
@ -593,6 +595,7 @@ public:
|
||||||
esm.endRecord(ESM::REC_GSCR);
|
esm.endRecord(ESM::REC_GSCR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ESM::GlobalScript> mScripts;
|
std::vector<ESM::GlobalScript> mScripts;
|
||||||
};
|
};
|
||||||
|
@ -604,6 +607,7 @@ public:
|
||||||
int getStage() override { return 2; }
|
int getStage() override { return 2; }
|
||||||
void read(ESM::ESMReader& esm) override;
|
void read(ESM::ESMReader& esm) override;
|
||||||
void write(ESM::ESMWriter& esm) override;
|
void write(ESM::ESMWriter& esm) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void convertBaseState(ESM::BaseProjectileState& base, const PROJ::PNAM& pnam);
|
void convertBaseState(ESM::BaseProjectileState& base, const PROJ::PNAM& pnam);
|
||||||
PROJ mProj;
|
PROJ mProj;
|
||||||
|
@ -614,6 +618,7 @@ class ConvertSPLM : public Converter
|
||||||
public:
|
public:
|
||||||
void read(ESM::ESMReader& esm) override;
|
void read(ESM::ESMReader& esm) override;
|
||||||
void write(ESM::ESMWriter& esm) override;
|
void write(ESM::ESMWriter& esm) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SPLM mSPLM;
|
SPLM mSPLM;
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls)
|
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics,
|
||||||
|
bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls)
|
||||||
{
|
{
|
||||||
out.mObject.mPosition.rot[0] = -atan2(pcdt.mPNAM.mVerticalRotation.mData[2][1], pcdt.mPNAM.mVerticalRotation.mData[2][2]);
|
out.mObject.mPosition.rot[0]
|
||||||
|
= -atan2(pcdt.mPNAM.mVerticalRotation.mData[2][1], pcdt.mPNAM.mVerticalRotation.mData[2][2]);
|
||||||
|
|
||||||
out.mBirthsign = pcdt.mBirthsign;
|
out.mBirthsign = pcdt.mBirthsign;
|
||||||
out.mObject.mNpcStats.mBounty = pcdt.mBounty;
|
out.mObject.mNpcStats.mBounty = pcdt.mBounty;
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
|
|
||||||
#include "importplayer.hpp"
|
#include "importplayer.hpp"
|
||||||
|
|
||||||
#include <components/esm3/player.hpp>
|
|
||||||
#include <components/esm3/controlsstate.hpp>
|
#include <components/esm3/controlsstate.hpp>
|
||||||
|
#include <components/esm3/player.hpp>
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls);
|
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics,
|
||||||
|
bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,8 @@ namespace ESSImport
|
||||||
float mDynamic[3][2];
|
float mDynamic[3][2];
|
||||||
unsigned char mUnknown3[16];
|
unsigned char mUnknown3[16];
|
||||||
float mAttributes[8][2];
|
float mAttributes[8][2];
|
||||||
float mMagicEffects[27]; // Effect attributes: https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes
|
float mMagicEffects[27]; // Effect attributes:
|
||||||
|
// https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes
|
||||||
unsigned char mUnknown4[4];
|
unsigned char mUnknown4[4];
|
||||||
unsigned int mGoldPool;
|
unsigned int mGoldPool;
|
||||||
unsigned char mCountDown; // seen the same value as in ACSC.mCorpseClearCountdown, maybe
|
unsigned char mCountDown; // seen the same value as in ACSC.mCorpseClearCountdown, maybe
|
||||||
|
|
|
@ -14,7 +14,6 @@ namespace ESSImport
|
||||||
float scale;
|
float scale;
|
||||||
esm.getHNOT(scale, "XSCL");
|
esm.getHNOT(scale, "XSCL");
|
||||||
|
|
||||||
|
|
||||||
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|
||||||
|| esm.isNextSub("AI_A"))
|
|| esm.isNextSub("AI_A"))
|
||||||
mAiPackages.add(esm);
|
mAiPackages.add(esm);
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
#include "importer.hpp"
|
#include "importer.hpp"
|
||||||
|
|
||||||
#include <iomanip>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include <osgDB/ReadFile>
|
|
||||||
#include <osg/ImageUtils>
|
#include <osg/ImageUtils>
|
||||||
|
#include <osgDB/ReadFile>
|
||||||
|
|
||||||
|
#include <components/esm/defs.hpp>
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
#include <components/esm3/esmwriter.hpp>
|
#include <components/esm3/esmwriter.hpp>
|
||||||
#include <components/esm/defs.hpp>
|
|
||||||
|
|
||||||
#include <components/esm3/savedgame.hpp>
|
|
||||||
#include <components/esm3/player.hpp>
|
#include <components/esm3/player.hpp>
|
||||||
|
#include <components/esm3/savedgame.hpp>
|
||||||
|
|
||||||
#include <components/esm3/loadalch.hpp>
|
#include <components/esm3/loadalch.hpp>
|
||||||
#include <components/esm3/loadspel.hpp>
|
|
||||||
#include <components/esm3/loadarmo.hpp>
|
#include <components/esm3/loadarmo.hpp>
|
||||||
#include <components/esm3/loadweap.hpp>
|
|
||||||
#include <components/esm3/loadclot.hpp>
|
#include <components/esm3/loadclot.hpp>
|
||||||
#include <components/esm3/loadench.hpp>
|
#include <components/esm3/loadench.hpp>
|
||||||
#include <components/esm3/loadlevlist.hpp>
|
#include <components/esm3/loadlevlist.hpp>
|
||||||
|
#include <components/esm3/loadspel.hpp>
|
||||||
|
#include <components/esm3/loadweap.hpp>
|
||||||
|
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
|
|
||||||
|
@ -72,7 +72,8 @@ namespace
|
||||||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image, ostream);
|
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image, ostream);
|
||||||
if (!result.success())
|
if (!result.success())
|
||||||
{
|
{
|
||||||
std::cerr << "Error: can't write screenshot: " << result.message() << " code " << result.status() << std::endl;
|
std::cerr << "Error: can't write screenshot: " << result.message() << " code " << result.status()
|
||||||
|
<< std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,12 +86,12 @@ namespace
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
Importer::Importer(const std::filesystem::path &essfile, const std::filesystem::path &outfile, const std::string &encoding)
|
Importer::Importer(
|
||||||
|
const std::filesystem::path& essfile, const std::filesystem::path& outfile, const std::string& encoding)
|
||||||
: mEssFile(essfile)
|
: mEssFile(essfile)
|
||||||
, mOutFile(outfile)
|
, mOutFile(outfile)
|
||||||
, mEncoding(encoding)
|
, mEncoding(encoding)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct File
|
struct File
|
||||||
|
@ -190,7 +191,8 @@ namespace ESSImport
|
||||||
if (j >= rec2.mSubrecords.size())
|
if (j >= rec2.mSubrecords.size())
|
||||||
{
|
{
|
||||||
std::ios::fmtflags f(std::cout.flags());
|
std::ios::fmtflags f(std::cout.flags());
|
||||||
std::cout << "Subrecord in file1 not present in file2: (1) 0x" << std::hex << sub.mFileOffset << std::endl;
|
std::cout << "Subrecord in file1 not present in file2: (1) 0x" << std::hex << sub.mFileOffset
|
||||||
|
<< std::endl;
|
||||||
std::cout.flags(f);
|
std::cout.flags(f);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -200,8 +202,9 @@ namespace ESSImport
|
||||||
if (sub.mName != sub2.mName)
|
if (sub.mName != sub2.mName)
|
||||||
{
|
{
|
||||||
std::ios::fmtflags f(std::cout.flags());
|
std::ios::fmtflags f(std::cout.flags());
|
||||||
std::cout << "Different subrecord name (" << rec.mName << "." << sub.mName << " vs. " << sub2.mName << ") at (1) 0x" << std::hex << sub.mFileOffset
|
std::cout << "Different subrecord name (" << rec.mName << "." << sub.mName << " vs. " << sub2.mName
|
||||||
<< " (2) 0x" << sub2.mFileOffset << std::endl;
|
<< ") at (1) 0x" << std::hex << sub.mFileOffset << " (2) 0x" << sub2.mFileOffset
|
||||||
|
<< std::endl;
|
||||||
std::cout.flags(f);
|
std::cout.flags(f);
|
||||||
break; // TODO: try to recover
|
break; // TODO: try to recover
|
||||||
}
|
}
|
||||||
|
@ -213,8 +216,8 @@ namespace ESSImport
|
||||||
|
|
||||||
std::ios::fmtflags f(std::cout.flags());
|
std::ios::fmtflags f(std::cout.flags());
|
||||||
|
|
||||||
std::cout << "Different subrecord data for " << rec.mName << "." << sub.mName << " at (1) 0x" << std::hex << sub.mFileOffset
|
std::cout << "Different subrecord data for " << rec.mName << "." << sub.mName << " at (1) 0x"
|
||||||
<< " (2) 0x" << sub2.mFileOffset << std::endl;
|
<< std::hex << sub.mFileOffset << " (2) 0x" << sub2.mFileOffset << std::endl;
|
||||||
|
|
||||||
std::cout << "Data 1:" << std::endl;
|
std::cout << "Data 1:" << std::endl;
|
||||||
for (unsigned int k = 0; k < sub.mData.size(); ++k)
|
for (unsigned int k = 0; k < sub.mData.size(); ++k)
|
||||||
|
@ -333,7 +336,8 @@ namespace ESSImport
|
||||||
if (unknownRecords.insert(n.toInt()).second)
|
if (unknownRecords.insert(n.toInt()).second)
|
||||||
{
|
{
|
||||||
std::ios::fmtflags f(std::cerr.flags());
|
std::ios::fmtflags f(std::cerr.flags());
|
||||||
std::cerr << "Error: unknown record " << n.toString() << " (0x" << std::hex << esm.getFileOffset() << ")" << std::endl;
|
std::cerr << "Error: unknown record " << n.toString() << " (0x" << std::hex << esm.getFileOffset()
|
||||||
|
<< ")" << std::endl;
|
||||||
std::cerr.flags(f);
|
std::cerr.flags(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,8 +389,7 @@ namespace ESSImport
|
||||||
|
|
||||||
// Writing order should be Dynamic Store -> Cells -> Player,
|
// Writing order should be Dynamic Store -> Cells -> Player,
|
||||||
// so that references to dynamic records can be recognized when loading
|
// so that references to dynamic records can be recognized when loading
|
||||||
for (auto it = converters.begin();
|
for (auto it = converters.begin(); it != converters.end(); ++it)
|
||||||
it != converters.end(); ++it)
|
|
||||||
{
|
{
|
||||||
if (it->second->getStage() != 0)
|
if (it->second->getStage() != 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -398,8 +401,7 @@ namespace ESSImport
|
||||||
context.mPlayerBase.save(writer);
|
context.mPlayerBase.save(writer);
|
||||||
writer.endRecord(ESM::REC_NPC_);
|
writer.endRecord(ESM::REC_NPC_);
|
||||||
|
|
||||||
for (auto it = converters.begin();
|
for (auto it = converters.begin(); it != converters.end(); ++it)
|
||||||
it != converters.end(); ++it)
|
|
||||||
{
|
{
|
||||||
if (it->second->getStage() != 1)
|
if (it->second->getStage() != 1)
|
||||||
continue;
|
continue;
|
||||||
|
@ -410,8 +412,10 @@ namespace ESSImport
|
||||||
if (context.mPlayer.mCellId.mPaged)
|
if (context.mPlayer.mCellId.mPaged)
|
||||||
{
|
{
|
||||||
// exterior cell -> determine cell coordinates based on position
|
// exterior cell -> determine cell coordinates based on position
|
||||||
int cellX = static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[0] / Constants::CellSizeInUnits));
|
int cellX
|
||||||
int cellY = static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[1] / Constants::CellSizeInUnits));
|
= static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[0] / Constants::CellSizeInUnits));
|
||||||
|
int cellY
|
||||||
|
= static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[1] / Constants::CellSizeInUnits));
|
||||||
context.mPlayer.mCellId.mIndex.mX = cellX;
|
context.mPlayer.mCellId.mIndex.mX = cellX;
|
||||||
context.mPlayer.mCellId.mIndex.mY = cellY;
|
context.mPlayer.mCellId.mIndex.mY = cellY;
|
||||||
}
|
}
|
||||||
|
@ -423,8 +427,7 @@ namespace ESSImport
|
||||||
writer.endRecord(ESM::REC_ACTC);
|
writer.endRecord(ESM::REC_ACTC);
|
||||||
|
|
||||||
// Stage 2 requires cell references to be written / actors IDs assigned
|
// Stage 2 requires cell references to be written / actors IDs assigned
|
||||||
for (auto it = converters.begin();
|
for (auto it = converters.begin(); it != converters.end(); ++it)
|
||||||
it != converters.end(); ++it)
|
|
||||||
{
|
{
|
||||||
if (it->second->getStage() != 2)
|
if (it->second->getStage() != 2)
|
||||||
continue;
|
continue;
|
||||||
|
@ -440,5 +443,4 @@ namespace ESSImport
|
||||||
writer.endRecord(ESM::REC_INPU);
|
writer.endRecord(ESM::REC_INPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@ namespace ESSImport
|
||||||
class Importer
|
class Importer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Importer(const std::filesystem::path &essfile, const std::filesystem::path &outfile, const std::string& encoding);
|
Importer(
|
||||||
|
const std::filesystem::path& essfile, const std::filesystem::path& outfile, const std::string& encoding);
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
|
|
@ -3,17 +3,16 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <components/esm3/loadnpc.hpp>
|
#include <components/esm3/controlsstate.hpp>
|
||||||
#include <components/esm3/player.hpp>
|
|
||||||
#include <components/esm3/dialoguestate.hpp>
|
#include <components/esm3/dialoguestate.hpp>
|
||||||
#include <components/esm3/globalmap.hpp>
|
#include <components/esm3/globalmap.hpp>
|
||||||
#include <components/esm3/loadcrea.hpp>
|
#include <components/esm3/loadcrea.hpp>
|
||||||
#include <components/esm3/loadnpc.hpp>
|
#include <components/esm3/loadnpc.hpp>
|
||||||
#include <components/esm3/controlsstate.hpp>
|
#include <components/esm3/player.hpp>
|
||||||
|
|
||||||
#include "importnpcc.hpp"
|
|
||||||
#include "importcrec.hpp"
|
|
||||||
#include "importcntc.hpp"
|
#include "importcntc.hpp"
|
||||||
|
#include "importcrec.hpp"
|
||||||
|
#include "importnpcc.hpp"
|
||||||
#include "importsplm.h"
|
#include "importsplm.h"
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
|
@ -64,10 +63,8 @@ namespace ESSImport
|
||||||
playerCellId.mPaged = true;
|
playerCellId.mPaged = true;
|
||||||
playerCellId.mIndex.mX = playerCellId.mIndex.mY = 0;
|
playerCellId.mIndex.mX = playerCellId.mIndex.mY = 0;
|
||||||
mPlayer.mCellId = playerCellId;
|
mPlayer.mCellId = playerCellId;
|
||||||
mPlayer.mLastKnownExteriorPosition[0]
|
mPlayer.mLastKnownExteriorPosition[0] = mPlayer.mLastKnownExteriorPosition[1]
|
||||||
= mPlayer.mLastKnownExteriorPosition[1]
|
= mPlayer.mLastKnownExteriorPosition[2] = 0.0f;
|
||||||
= mPlayer.mLastKnownExteriorPosition[2]
|
|
||||||
= 0.0f;
|
|
||||||
mPlayer.mHasMark = 0;
|
mPlayer.mHasMark = 0;
|
||||||
mPlayer.mCurrentCrimeId = -1; // TODO
|
mPlayer.mCurrentCrimeId = -1; // TODO
|
||||||
mPlayer.mPaidCrimeId = -1;
|
mPlayer.mPaidCrimeId = -1;
|
||||||
|
@ -84,10 +81,7 @@ namespace ESSImport
|
||||||
mPlayerBase.blank();
|
mPlayerBase.blank();
|
||||||
}
|
}
|
||||||
|
|
||||||
int generateActorId()
|
int generateActorId() { return mNextActorId++; }
|
||||||
{
|
|
||||||
return mNextActorId++;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#ifndef OPENMW_ESSIMPORT_IMPORTINVENTORY_H
|
#ifndef OPENMW_ESSIMPORT_IMPORTINVENTORY_H
|
||||||
#define OPENMW_ESSIMPORT_IMPORTINVENTORY_H
|
#define OPENMW_ESSIMPORT_IMPORTINVENTORY_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <components/esm3/cellref.hpp>
|
|
||||||
#include <components/esm/esmcommon.hpp>
|
#include <components/esm/esmcommon.hpp>
|
||||||
|
#include <components/esm3/cellref.hpp>
|
||||||
|
|
||||||
#include "importscri.hpp"
|
#include "importscri.hpp"
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef OPENMW_ESSIMPORT_KLST_H
|
#ifndef OPENMW_ESSIMPORT_KLST_H
|
||||||
#define OPENMW_ESSIMPORT_KLST_H
|
#define OPENMW_ESSIMPORT_KLST_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#ifndef OPENMW_ESSIMPORT_PLAYER_H
|
#ifndef OPENMW_ESSIMPORT_PLAYER_H
|
||||||
#define OPENMW_ESSIMPORT_PLAYER_H
|
#define OPENMW_ESSIMPORT_PLAYER_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <components/esm/defs.hpp>
|
#include <components/esm/defs.hpp>
|
||||||
#include <components/esm3/cellref.hpp>
|
|
||||||
#include <components/esm/esmcommon.hpp>
|
#include <components/esm/esmcommon.hpp>
|
||||||
|
#include <components/esm3/cellref.hpp>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef OPENMW_ESSIMPORT_IMPORTPROJ_H
|
#ifndef OPENMW_ESSIMPORT_IMPORTPROJ_H
|
||||||
#define OPENMW_ESSIMPORT_IMPORTPROJ_H
|
#define OPENMW_ESSIMPORT_IMPORTPROJ_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <components/esm/esmcommon.hpp>
|
#include <components/esm/esmcommon.hpp>
|
||||||
#include <components/esm/util.hpp>
|
#include <components/esm/util.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include "importscri.hpp"
|
#include "importscri.hpp"
|
||||||
|
|
||||||
#include <components/esm3/loadscpt.hpp>
|
|
||||||
#include <components/esm/esmcommon.hpp>
|
#include <components/esm/esmcommon.hpp>
|
||||||
|
#include <components/esm3/loadscpt.hpp>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef OPENMW_ESSIMPORT_IMPORTSPLM_H
|
#ifndef OPENMW_ESSIMPORT_IMPORTSPLM_H
|
||||||
#define OPENMW_ESSIMPORT_IMPORTSPLM_H
|
#define OPENMW_ESSIMPORT_IMPORTSPLM_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <components/esm/esmcommon.hpp>
|
#include <components/esm/esmcommon.hpp>
|
||||||
#include <components/esm/util.hpp>
|
#include <components/esm/util.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,6 @@ struct SPLM
|
||||||
int mUnknown;
|
int mUnknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct ActiveEffect
|
struct ActiveEffect
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <iostream>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
namespace bpo = boost::program_options;
|
namespace bpo = boost::program_options;
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -22,19 +21,18 @@ Allowed options)");
|
||||||
addOption("mwsave,m", bpo::value<Files::MaybeQuotedPath>(), "morrowind .ess save file");
|
addOption("mwsave,m", bpo::value<Files::MaybeQuotedPath>(), "morrowind .ess save file");
|
||||||
addOption("output,o", bpo::value<Files::MaybeQuotedPath>(), "output file (.omwsave)");
|
addOption("output,o", bpo::value<Files::MaybeQuotedPath>(), "output file (.omwsave)");
|
||||||
addOption("compare,c", "compare two .ess files");
|
addOption("compare,c", "compare two .ess files");
|
||||||
addOption("encoding", boost::program_options::value<std::string>()->default_value("win1252"), "encoding of the save file");
|
addOption("encoding", boost::program_options::value<std::string>()->default_value("win1252"),
|
||||||
|
"encoding of the save file");
|
||||||
p_desc.add("mwsave", 1).add("output", 1);
|
p_desc.add("mwsave", 1).add("output", 1);
|
||||||
Files::ConfigurationManager::addCommonOptions(desc);
|
Files::ConfigurationManager::addCommonOptions(desc);
|
||||||
|
|
||||||
bpo::variables_map variables;
|
bpo::variables_map variables;
|
||||||
|
|
||||||
bpo::parsed_options parsed = bpo::command_line_parser(argc, argv)
|
bpo::parsed_options parsed = bpo::command_line_parser(argc, argv).options(desc).positional(p_desc).run();
|
||||||
.options(desc)
|
|
||||||
.positional(p_desc)
|
|
||||||
.run();
|
|
||||||
bpo::store(parsed, variables);
|
bpo::store(parsed, variables);
|
||||||
|
|
||||||
if(variables.count("help") || !variables.count("mwsave") || !variables.count("output")) {
|
if (variables.count("help") || !variables.count("mwsave") || !variables.count("output"))
|
||||||
|
{
|
||||||
std::cout << desc;
|
std::cout << desc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +57,8 @@ Allowed options)");
|
||||||
if (std::filesystem::exists(outputFile)
|
if (std::filesystem::exists(outputFile)
|
||||||
&& (length < ext.size() || outputFile.u8string().substr(length - ext.size()) != ext))
|
&& (length < ext.size() || outputFile.u8string().substr(length - ext.size()) != ext))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Output file already exists and does not end in .omwsave. Did you mean to use --compare?");
|
throw std::runtime_error(
|
||||||
|
"Output file already exists and does not end in .omwsave. Did you mean to use --compare?");
|
||||||
}
|
}
|
||||||
importer.run();
|
importer.run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#include "advancedpage.hpp"
|
#include "advancedpage.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <string>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QCompleter>
|
#include <QCompleter>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include <components/config/gamesettings.hpp>
|
#include <components/config/gamesettings.hpp>
|
||||||
#include <components/contentselector/view/contentselector.hpp>
|
|
||||||
#include <components/contentselector/model/esmfile.hpp>
|
#include <components/contentselector/model/esmfile.hpp>
|
||||||
|
#include <components/contentselector/view/contentselector.hpp>
|
||||||
#include <components/detournavigator/collisionshapetype.hpp>
|
#include <components/detournavigator/collisionshapetype.hpp>
|
||||||
|
|
||||||
#include "utils/openalutil.hpp"
|
#include "utils/openalutil.hpp"
|
||||||
|
@ -37,14 +37,16 @@ Launcher::AdvancedPage::AdvancedPage(Config::GameSettings &gameSettings, QWidget
|
||||||
startDefaultCharacterAtField->setCompleter(&mCellNameCompleter);
|
startDefaultCharacterAtField->setCompleter(&mCellNameCompleter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::AdvancedPage::loadCellsForAutocomplete(QStringList cellNames) {
|
void Launcher::AdvancedPage::loadCellsForAutocomplete(QStringList cellNames)
|
||||||
|
{
|
||||||
// Update the list of suggestions for the "Start default character at" field
|
// Update the list of suggestions for the "Start default character at" field
|
||||||
mCellNameCompleterModel.setStringList(cellNames);
|
mCellNameCompleterModel.setStringList(cellNames);
|
||||||
mCellNameCompleter.setCompletionMode(QCompleter::PopupCompletion);
|
mCellNameCompleter.setCompletionMode(QCompleter::PopupCompletion);
|
||||||
mCellNameCompleter.setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
|
mCellNameCompleter.setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::AdvancedPage::on_skipMenuCheckBox_stateChanged(int state) {
|
void Launcher::AdvancedPage::on_skipMenuCheckBox_stateChanged(int state)
|
||||||
|
{
|
||||||
startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked);
|
startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked);
|
||||||
startDefaultCharacterAtField->setEnabled(state == Qt::Checked);
|
startDefaultCharacterAtField->setEnabled(state == Qt::Checked);
|
||||||
}
|
}
|
||||||
|
@ -52,10 +54,7 @@ void Launcher::AdvancedPage::on_skipMenuCheckBox_stateChanged(int state) {
|
||||||
void Launcher::AdvancedPage::on_runScriptAfterStartupBrowseButton_clicked()
|
void Launcher::AdvancedPage::on_runScriptAfterStartupBrowseButton_clicked()
|
||||||
{
|
{
|
||||||
QString scriptFile = QFileDialog::getOpenFileName(
|
QString scriptFile = QFileDialog::getOpenFileName(
|
||||||
this,
|
this, QObject::tr("Select script file"), QDir::currentPath(), QString(tr("Text file (*.txt)")));
|
||||||
QObject::tr("Select script file"),
|
|
||||||
QDir::currentPath(),
|
|
||||||
QString(tr("Text file (*.txt)")));
|
|
||||||
|
|
||||||
if (scriptFile.isEmpty())
|
if (scriptFile.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
@ -95,7 +94,8 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||||
loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||||
loadSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
loadSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
||||||
loadSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
loadSettingBool(
|
||||||
|
requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||||
loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
loadSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||||
loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
loadSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||||
loadSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
loadSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
||||||
|
@ -124,7 +124,8 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
loadSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
loadSettingBool(bumpMapLocalLightingCheckBox, "apply lighting to environment maps", "Shaders");
|
||||||
loadSettingBool(softParticlesCheckBox, "soft particles", "Shaders");
|
loadSettingBool(softParticlesCheckBox, "soft particles", "Shaders");
|
||||||
loadSettingBool(antialiasAlphaTestCheckBox, "antialias alpha test", "Shaders");
|
loadSettingBool(antialiasAlphaTestCheckBox, "antialias alpha test", "Shaders");
|
||||||
if (Settings::Manager::getInt("antialiasing", "Video") == 0) {
|
if (Settings::Manager::getInt("antialiasing", "Video") == 0)
|
||||||
|
{
|
||||||
antialiasAlphaTestCheckBox->setCheckState(Qt::Unchecked);
|
antialiasAlphaTestCheckBox->setCheckState(Qt::Unchecked);
|
||||||
}
|
}
|
||||||
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game");
|
||||||
|
@ -140,7 +141,8 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
|
|
||||||
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
||||||
const bool objectPaging = Settings::Manager::getBool("object paging", "Terrain");
|
const bool objectPaging = Settings::Manager::getBool("object paging", "Terrain");
|
||||||
if (distantTerrain && objectPaging) {
|
if (distantTerrain && objectPaging)
|
||||||
|
{
|
||||||
distantLandCheckBox->setCheckState(Qt::Checked);
|
distantLandCheckBox->setCheckState(Qt::Checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +212,8 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
// Bug fixes
|
// Bug fixes
|
||||||
{
|
{
|
||||||
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||||
loadSettingBool(trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game");
|
loadSettingBool(
|
||||||
|
trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
|
@ -220,7 +223,8 @@ bool Launcher::AdvancedPage::loadSettings()
|
||||||
loadSettingInt(maximumQuicksavesComboBox, "max quicksaves", "Saves");
|
loadSettingInt(maximumQuicksavesComboBox, "max quicksaves", "Saves");
|
||||||
|
|
||||||
// Other Settings
|
// Other Settings
|
||||||
QString screenshotFormatString = QString::fromStdString(Settings::Manager::getString("screenshot format", "General")).toUpper();
|
QString screenshotFormatString
|
||||||
|
= QString::fromStdString(Settings::Manager::getString("screenshot format", "General")).toUpper();
|
||||||
if (screenshotFormatComboBox->findText(screenshotFormatString) == -1)
|
if (screenshotFormatComboBox->findText(screenshotFormatString) == -1)
|
||||||
screenshotFormatComboBox->addItem(screenshotFormatString);
|
screenshotFormatComboBox->addItem(screenshotFormatString);
|
||||||
screenshotFormatComboBox->setCurrentIndex(screenshotFormatComboBox->findText(screenshotFormatString));
|
screenshotFormatComboBox->setCurrentIndex(screenshotFormatComboBox->findText(screenshotFormatString));
|
||||||
|
@ -257,7 +261,8 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||||
saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||||
saveSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
saveSettingBool(classicReflectedAbsorbSpellsCheckBox, "classic reflected absorb spells behavior", "Game");
|
||||||
saveSettingBool(requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
saveSettingBool(
|
||||||
|
requireAppropriateAmmunitionCheckBox, "only appropriate ammunition bypasses resistance", "Game");
|
||||||
saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
saveSettingBool(uncappedDamageFatigueCheckBox, "uncapped damage fatigue", "Game");
|
||||||
saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
saveSettingBool(normaliseRaceSpeedCheckBox, "normalise race speed", "Game");
|
||||||
saveSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
saveSettingBool(swimUpwardCorrectionCheckBox, "swim upward correction", "Game");
|
||||||
|
@ -291,7 +296,8 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
||||||
const bool objectPaging = Settings::Manager::getBool("object paging", "Terrain");
|
const bool objectPaging = Settings::Manager::getBool("object paging", "Terrain");
|
||||||
const bool wantDistantLand = distantLandCheckBox->checkState();
|
const bool wantDistantLand = distantLandCheckBox->checkState();
|
||||||
if (wantDistantLand != (distantTerrain && objectPaging)) {
|
if (wantDistantLand != (distantTerrain && objectPaging))
|
||||||
|
{
|
||||||
Settings::Manager::setBool("distant terrain", "Terrain", wantDistantLand);
|
Settings::Manager::setBool("distant terrain", "Terrain", wantDistantLand);
|
||||||
Settings::Manager::setBool("object paging", "Terrain", wantDistantLand);
|
Settings::Manager::setBool("object paging", "Terrain", wantDistantLand);
|
||||||
}
|
}
|
||||||
|
@ -377,7 +383,8 @@ void Launcher::AdvancedPage::saveSettings()
|
||||||
// Bug fixes
|
// Bug fixes
|
||||||
{
|
{
|
||||||
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||||
saveSettingBool(trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game");
|
saveSettingBool(
|
||||||
|
trainersTrainingSkillsBasedOnBaseSkillCheckBox, "trainers training skills based on base skill", "Game");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
|
|
|
@ -8,7 +8,10 @@
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
namespace Config { class GameSettings; }
|
namespace Config
|
||||||
|
{
|
||||||
|
class GameSettings;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Launcher
|
namespace Launcher
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
#include "maindialog.hpp"
|
#include "maindialog.hpp"
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QPushButton>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <apps/launcher/utils/cellnameloader.hpp>
|
#include <apps/launcher/utils/cellnameloader.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
@ -63,55 +63,38 @@ namespace Launcher
|
||||||
|
|
||||||
HandleNavMeshToolMessage operator()(NavMeshTool::ExpectedCells&& message) const
|
HandleNavMeshToolMessage operator()(NavMeshTool::ExpectedCells&& message) const
|
||||||
{
|
{
|
||||||
return HandleNavMeshToolMessage {
|
return HandleNavMeshToolMessage{ static_cast<int>(message.mCount), mExpectedMaxProgress,
|
||||||
static_cast<int>(message.mCount),
|
static_cast<int>(message.mCount) * 100, mProgress };
|
||||||
mExpectedMaxProgress,
|
|
||||||
static_cast<int>(message.mCount) * 100,
|
|
||||||
mProgress
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleNavMeshToolMessage operator()(NavMeshTool::ProcessedCells&& message) const
|
HandleNavMeshToolMessage operator()(NavMeshTool::ProcessedCells&& message) const
|
||||||
{
|
{
|
||||||
return HandleNavMeshToolMessage {
|
return HandleNavMeshToolMessage{ mCellsCount, mExpectedMaxProgress, mMaxProgress,
|
||||||
mCellsCount,
|
std::max(mProgress, static_cast<int>(message.mCount)) };
|
||||||
mExpectedMaxProgress,
|
|
||||||
mMaxProgress,
|
|
||||||
std::max(mProgress, static_cast<int>(message.mCount))
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleNavMeshToolMessage operator()(NavMeshTool::ExpectedTiles&& message) const
|
HandleNavMeshToolMessage operator()(NavMeshTool::ExpectedTiles&& message) const
|
||||||
{
|
{
|
||||||
const int expectedMaxProgress = mCellsCount + static_cast<int>(message.mCount);
|
const int expectedMaxProgress = mCellsCount + static_cast<int>(message.mCount);
|
||||||
return HandleNavMeshToolMessage {
|
return HandleNavMeshToolMessage{ mCellsCount, expectedMaxProgress,
|
||||||
mCellsCount,
|
std::max(mMaxProgress, expectedMaxProgress), mProgress };
|
||||||
expectedMaxProgress,
|
|
||||||
std::max(mMaxProgress, expectedMaxProgress),
|
|
||||||
mProgress
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleNavMeshToolMessage operator()(NavMeshTool::GeneratedTiles&& message) const
|
HandleNavMeshToolMessage operator()(NavMeshTool::GeneratedTiles&& message) const
|
||||||
{
|
{
|
||||||
int progress = mCellsCount + static_cast<int>(message.mCount);
|
int progress = mCellsCount + static_cast<int>(message.mCount);
|
||||||
if (mExpectedMaxProgress < mMaxProgress)
|
if (mExpectedMaxProgress < mMaxProgress)
|
||||||
progress += static_cast<int>(std::round(
|
progress += static_cast<int>(std::round((mMaxProgress - mExpectedMaxProgress)
|
||||||
(mMaxProgress - mExpectedMaxProgress)
|
* (static_cast<float>(progress) / static_cast<float>(mExpectedMaxProgress))));
|
||||||
* (static_cast<float>(progress) / static_cast<float>(mExpectedMaxProgress))
|
return HandleNavMeshToolMessage{ mCellsCount, mExpectedMaxProgress, mMaxProgress,
|
||||||
));
|
std::max(mProgress, progress) };
|
||||||
return HandleNavMeshToolMessage {
|
|
||||||
mCellsCount,
|
|
||||||
mExpectedMaxProgress,
|
|
||||||
mMaxProgress,
|
|
||||||
std::max(mProgress, progress)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int getMaxNavMeshDbFileSizeMiB()
|
int getMaxNavMeshDbFileSizeMiB()
|
||||||
{
|
{
|
||||||
return static_cast<int>(Settings::Manager::getInt64("max navmeshdb file size", "Navigator") / (1024 * 1024));
|
return static_cast<int>(
|
||||||
|
Settings::Manager::getInt64("max navmeshdb file size", "Navigator") / (1024 * 1024));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,10 +117,8 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config:
|
||||||
mNewProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this);
|
mNewProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this);
|
||||||
mCloneProfileDialog = new TextInputDialog(tr("Clone Content List"), tr("Content List name:"), this);
|
mCloneProfileDialog = new TextInputDialog(tr("Clone Content List"), tr("Content List name:"), this);
|
||||||
|
|
||||||
connect(mNewProfileDialog->lineEdit(), &LineEdit::textChanged,
|
connect(mNewProfileDialog->lineEdit(), &LineEdit::textChanged, this, &DataFilesPage::updateNewProfileOkButton);
|
||||||
this, &DataFilesPage::updateNewProfileOkButton);
|
connect(mCloneProfileDialog->lineEdit(), &LineEdit::textChanged, this, &DataFilesPage::updateCloneProfileOkButton);
|
||||||
connect(mCloneProfileDialog->lineEdit(), &LineEdit::textChanged,
|
|
||||||
this, &DataFilesPage::updateCloneProfileOkButton);
|
|
||||||
connect(ui.directoryAddSubdirsButton, &QPushButton::released, this, [this]() { this->addSubdirectories(true); });
|
connect(ui.directoryAddSubdirsButton, &QPushButton::released, this, [this]() { this->addSubdirectories(true); });
|
||||||
connect(ui.directoryInsertButton, &QPushButton::released, this, [this]() { this->addSubdirectories(false); });
|
connect(ui.directoryInsertButton, &QPushButton::released, this, [this]() { this->addSubdirectories(false); });
|
||||||
connect(ui.directoryUpButton, &QPushButton::released, this, [this]() { this->moveDirectory(-1); });
|
connect(ui.directoryUpButton, &QPushButton::released, this, [this]() { this->moveDirectory(-1); });
|
||||||
|
@ -145,15 +126,16 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config:
|
||||||
connect(ui.directoryRemoveButton, &QPushButton::released, this, [this]() { this->removeDirectory(); });
|
connect(ui.directoryRemoveButton, &QPushButton::released, this, [this]() { this->removeDirectory(); });
|
||||||
connect(ui.archiveUpButton, &QPushButton::released, this, [this]() { this->moveArchive(-1); });
|
connect(ui.archiveUpButton, &QPushButton::released, this, [this]() { this->moveArchive(-1); });
|
||||||
connect(ui.archiveDownButton, &QPushButton::released, this, [this]() { this->moveArchive(1); });
|
connect(ui.archiveDownButton, &QPushButton::released, this, [this]() { this->moveArchive(1); });
|
||||||
connect(ui.directoryListWidget->model(), &QAbstractItemModel::rowsMoved, this, [this]() { this->sortDirectories(); });
|
connect(
|
||||||
|
ui.directoryListWidget->model(), &QAbstractItemModel::rowsMoved, this, [this]() { this->sortDirectories(); });
|
||||||
|
|
||||||
buildView();
|
buildView();
|
||||||
loadSettings();
|
loadSettings();
|
||||||
|
|
||||||
// Connect signal and slot after the settings have been loaded. We only care about the user changing
|
// Connect signal and slot after the settings have been loaded. We only care about the user changing
|
||||||
// the addons and don't want to get signals of the system doing it during startup.
|
// the addons and don't want to get signals of the system doing it during startup.
|
||||||
connect(mSelector, &ContentSelectorView::ContentSelector::signalAddonDataChanged,
|
connect(mSelector, &ContentSelectorView::ContentSelector::signalAddonDataChanged, this,
|
||||||
this, &DataFilesPage::slotAddonDataChanged);
|
&DataFilesPage::slotAddonDataChanged);
|
||||||
// Call manually to indicate all changes to addon data during startup.
|
// Call manually to indicate all changes to addon data during startup.
|
||||||
slotAddonDataChanged();
|
slotAddonDataChanged();
|
||||||
}
|
}
|
||||||
|
@ -179,24 +161,25 @@ void Launcher::DataFilesPage::buildView()
|
||||||
refreshButton->setDefaultAction(ui.refreshDataFilesAction);
|
refreshButton->setDefaultAction(ui.refreshDataFilesAction);
|
||||||
|
|
||||||
// establish connections
|
// establish connections
|
||||||
connect (ui.profilesComboBox, qOverload<int>(&::ProfilesComboBox::currentIndexChanged),
|
connect(ui.profilesComboBox, qOverload<int>(&::ProfilesComboBox::currentIndexChanged), this,
|
||||||
this, &DataFilesPage::slotProfileChanged);
|
&DataFilesPage::slotProfileChanged);
|
||||||
|
|
||||||
connect (ui.profilesComboBox, &::ProfilesComboBox::profileRenamed,
|
connect(ui.profilesComboBox, &::ProfilesComboBox::profileRenamed, this, &DataFilesPage::slotProfileRenamed);
|
||||||
this, &DataFilesPage::slotProfileRenamed);
|
|
||||||
|
|
||||||
connect(ui.profilesComboBox, qOverload<const QString&, const QString&>(&::ProfilesComboBox::signalProfileChanged),
|
connect(ui.profilesComboBox, qOverload<const QString&, const QString&>(&::ProfilesComboBox::signalProfileChanged),
|
||||||
this, &DataFilesPage::slotProfileChangedByUser);
|
this, &DataFilesPage::slotProfileChangedByUser);
|
||||||
|
|
||||||
connect(ui.refreshDataFilesAction, &QAction::triggered,
|
connect(ui.refreshDataFilesAction, &QAction::triggered, this, &DataFilesPage::slotRefreshButtonClicked);
|
||||||
this, &DataFilesPage::slotRefreshButtonClicked);
|
|
||||||
|
|
||||||
connect(ui.updateNavMeshButton, &QPushButton::clicked, this, &DataFilesPage::startNavMeshTool);
|
connect(ui.updateNavMeshButton, &QPushButton::clicked, this, &DataFilesPage::startNavMeshTool);
|
||||||
connect(ui.cancelNavMeshButton, &QPushButton::clicked, this, &DataFilesPage::killNavMeshTool);
|
connect(ui.cancelNavMeshButton, &QPushButton::clicked, this, &DataFilesPage::killNavMeshTool);
|
||||||
|
|
||||||
connect(mNavMeshToolInvoker->getProcess(), &QProcess::readyReadStandardOutput, this, &DataFilesPage::readNavMeshToolStdout);
|
connect(mNavMeshToolInvoker->getProcess(), &QProcess::readyReadStandardOutput, this,
|
||||||
connect(mNavMeshToolInvoker->getProcess(), &QProcess::readyReadStandardError, this, &DataFilesPage::readNavMeshToolStderr);
|
&DataFilesPage::readNavMeshToolStdout);
|
||||||
connect(mNavMeshToolInvoker->getProcess(), qOverload<int,QProcess::ExitStatus>(&QProcess::finished), this, &DataFilesPage::navMeshToolFinished);
|
connect(mNavMeshToolInvoker->getProcess(), &QProcess::readyReadStandardError, this,
|
||||||
|
&DataFilesPage::readNavMeshToolStderr);
|
||||||
|
connect(mNavMeshToolInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||||
|
&DataFilesPage::navMeshToolFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Launcher::DataFilesPage::loadSettings()
|
bool Launcher::DataFilesPage::loadSettings()
|
||||||
|
@ -267,7 +250,8 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName)
|
||||||
|
|
||||||
// deactivate data-local and global data directory: they are always included
|
// deactivate data-local and global data directory: they are always included
|
||||||
const auto tmp = currentDir.toUtf8();
|
const auto tmp = currentDir.toUtf8();
|
||||||
if (currentDir == mDataLocal || std::filesystem::path(Misc::StringUtils::stringToU8String(tmp)) == globalDataDir)
|
if (currentDir == mDataLocal
|
||||||
|
|| std::filesystem::path(Misc::StringUtils::stringToU8String(tmp)) == globalDataDir)
|
||||||
{
|
{
|
||||||
auto flags = item->flags();
|
auto flags = item->flags();
|
||||||
item->setFlags(flags & ~(Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled));
|
item->setFlags(flags & ~(Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled));
|
||||||
|
@ -334,7 +318,8 @@ QStringList Launcher::DataFilesPage::filesInProfile(const QString& profileName,
|
||||||
void Launcher::DataFilesPage::saveSettings(const QString& profile)
|
void Launcher::DataFilesPage::saveSettings(const QString& profile)
|
||||||
{
|
{
|
||||||
if (const int value = ui.navMeshMaxSizeSpinBox->value(); value != getMaxNavMeshDbFileSizeMiB())
|
if (const int value = ui.navMeshMaxSizeSpinBox->value(); value != getMaxNavMeshDbFileSizeMiB())
|
||||||
Settings::Manager::setInt64("max navmeshdb file size", "Navigator", static_cast<std::int64_t>(value) * 1024 * 1024);
|
Settings::Manager::setInt64(
|
||||||
|
"max navmeshdb file size", "Navigator", static_cast<std::int64_t>(value) * 1024 * 1024);
|
||||||
|
|
||||||
QString profileName = profile;
|
QString profileName = profile;
|
||||||
|
|
||||||
|
@ -584,7 +569,6 @@ QString Launcher::DataFilesPage::selectDirectory()
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return QDir(fileDialog.selectedFiles()[0]).canonicalPath();
|
return QDir(fileDialog.selectedFiles()[0]).canonicalPath();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::DataFilesPage::addSubdirectories(bool append)
|
void Launcher::DataFilesPage::addSubdirectories(bool append)
|
||||||
|
@ -650,8 +634,8 @@ void Launcher::DataFilesPage::sortDirectories()
|
||||||
// Ensure disabled entries (aka default directories) are always at the top.
|
// Ensure disabled entries (aka default directories) are always at the top.
|
||||||
for (auto i = 1; i < ui.directoryListWidget->count(); ++i)
|
for (auto i = 1; i < ui.directoryListWidget->count(); ++i)
|
||||||
{
|
{
|
||||||
if (!(ui.directoryListWidget->item(i)->flags() & Qt::ItemIsEnabled) &&
|
if (!(ui.directoryListWidget->item(i)->flags() & Qt::ItemIsEnabled)
|
||||||
(ui.directoryListWidget->item(i - 1)->flags() & Qt::ItemIsEnabled))
|
&& (ui.directoryListWidget->item(i - 1)->flags() & Qt::ItemIsEnabled))
|
||||||
{
|
{
|
||||||
const auto item = ui.directoryListWidget->takeItem(i);
|
const auto item = ui.directoryListWidget->takeItem(i);
|
||||||
ui.directoryListWidget->insertItem(i - 1, item);
|
ui.directoryListWidget->insertItem(i - 1, item);
|
||||||
|
@ -743,8 +727,7 @@ bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text)
|
||||||
msgBox.setStandardButtons(QMessageBox::Cancel);
|
msgBox.setStandardButtons(QMessageBox::Cancel);
|
||||||
msgBox.setText(tr("Are you sure you want to delete <b>%1</b>?").arg(text));
|
msgBox.setText(tr("Are you sure you want to delete <b>%1</b>?").arg(text));
|
||||||
|
|
||||||
QAbstractButton *deleteButton =
|
QAbstractButton* deleteButton = msgBox.addButton(tr("Delete"), QMessageBox::ActionRole);
|
||||||
msgBox.addButton(tr("Delete"), QMessageBox::ActionRole);
|
|
||||||
|
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
|
|
||||||
|
@ -754,7 +737,8 @@ bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text)
|
||||||
void Launcher::DataFilesPage::slotAddonDataChanged()
|
void Launcher::DataFilesPage::slotAddonDataChanged()
|
||||||
{
|
{
|
||||||
QStringList selectedFiles = selectedFilePaths();
|
QStringList selectedFiles = selectedFilePaths();
|
||||||
if (previousSelectedFiles != selectedFiles) {
|
if (previousSelectedFiles != selectedFiles)
|
||||||
|
{
|
||||||
previousSelectedFiles = selectedFiles;
|
previousSelectedFiles = selectedFiles;
|
||||||
// Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a
|
// Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a
|
||||||
// barely perceptible UI lag. Splitting into its own thread to alleviate that.
|
// barely perceptible UI lag. Splitting into its own thread to alleviate that.
|
||||||
|
@ -863,7 +847,8 @@ void Launcher::DataFilesPage::readNavMeshToolStdout()
|
||||||
void Launcher::DataFilesPage::navMeshToolFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
void Launcher::DataFilesPage::navMeshToolFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||||
{
|
{
|
||||||
updateNavMeshProgress(0);
|
updateNavMeshProgress(0);
|
||||||
ui.navMeshLogPlainTextEdit->appendPlainText(QString::fromUtf8(mNavMeshToolInvoker->getProcess()->readAllStandardOutput()));
|
ui.navMeshLogPlainTextEdit->appendPlainText(
|
||||||
|
QString::fromUtf8(mNavMeshToolInvoker->getProcess()->readAllStandardOutput()));
|
||||||
if (exitCode == 0 && exitStatus == QProcess::ExitStatus::NormalExit)
|
if (exitCode == 0 && exitStatus == QProcess::ExitStatus::NormalExit)
|
||||||
ui.navMeshProgressBar->setValue(ui.navMeshProgressBar->maximum());
|
ui.navMeshProgressBar->setValue(ui.navMeshProgressBar->maximum());
|
||||||
ui.cancelNavMeshButton->setEnabled(false);
|
ui.cancelNavMeshButton->setEnabled(false);
|
||||||
|
|
|
@ -5,18 +5,27 @@
|
||||||
|
|
||||||
#include <components/process/processinvoker.hpp>
|
#include <components/process/processinvoker.hpp>
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
class QSortFilterProxyModel;
|
class QSortFilterProxyModel;
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
class QMenu;
|
class QMenu;
|
||||||
|
|
||||||
namespace Files { struct ConfigurationManager; }
|
namespace Files
|
||||||
namespace ContentSelectorView { class ContentSelector; }
|
{
|
||||||
namespace Config { class GameSettings;
|
struct ConfigurationManager;
|
||||||
class LauncherSettings; }
|
}
|
||||||
|
namespace ContentSelectorView
|
||||||
|
{
|
||||||
|
class ContentSelector;
|
||||||
|
}
|
||||||
|
namespace Config
|
||||||
|
{
|
||||||
|
class GameSettings;
|
||||||
|
class LauncherSettings;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Launcher
|
namespace Launcher
|
||||||
{
|
{
|
||||||
|
@ -157,7 +166,6 @@ namespace Launcher
|
||||||
QString findNextPath() { return path(); }
|
QString findNextPath() { return path(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QString path()
|
QString path()
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
@ -180,7 +188,6 @@ namespace Launcher
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QStringList filesInProfile(const QString& profileName, PathIterator& pathIterator);
|
QStringList filesInProfile(const QString& profileName, PathIterator& pathIterator);
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
|
|
||||||
#include <SDL_video.h>
|
#include <SDL_video.h>
|
||||||
|
|
||||||
#include <numeric>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
QString getAspect(int x, int y)
|
QString getAspect(int x, int y)
|
||||||
{
|
{
|
||||||
|
@ -42,7 +42,8 @@ Launcher::GraphicsPage::GraphicsPage(QWidget *parent)
|
||||||
customWidthSpinBox->setMaximum(res.width());
|
customWidthSpinBox->setMaximum(res.width());
|
||||||
customHeightSpinBox->setMaximum(res.height());
|
customHeightSpinBox->setMaximum(res.height());
|
||||||
|
|
||||||
connect(windowModeComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &GraphicsPage::slotFullScreenChanged);
|
connect(windowModeComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||||
|
&GraphicsPage::slotFullScreenChanged);
|
||||||
connect(standardRadioButton, &QRadioButton::toggled, this, &GraphicsPage::slotStandardToggled);
|
connect(standardRadioButton, &QRadioButton::toggled, this, &GraphicsPage::slotStandardToggled);
|
||||||
connect(screenComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &GraphicsPage::screenChanged);
|
connect(screenComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this, &GraphicsPage::screenChanged);
|
||||||
connect(framerateLimitCheckBox, &QCheckBox::toggled, this, &GraphicsPage::slotFramerateLimitToggled);
|
connect(framerateLimitCheckBox, &QCheckBox::toggled, this, &GraphicsPage::slotFramerateLimitToggled);
|
||||||
|
@ -65,7 +66,8 @@ bool Launcher::GraphicsPage::setupSDL()
|
||||||
msgBox.setWindowTitle(tr("Error receiving number of screens"));
|
msgBox.setWindowTitle(tr("Error receiving number of screens"));
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>SDL_GetNumVideoDisplays failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
msgBox.setText(
|
||||||
|
tr("<br><b>SDL_GetNumVideoDisplays failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -116,10 +118,13 @@ bool Launcher::GraphicsPage::loadSettings()
|
||||||
|
|
||||||
int resIndex = resolutionComboBox->findText(resolution, Qt::MatchStartsWith);
|
int resIndex = resolutionComboBox->findText(resolution, Qt::MatchStartsWith);
|
||||||
|
|
||||||
if (resIndex != -1) {
|
if (resIndex != -1)
|
||||||
|
{
|
||||||
standardRadioButton->toggle();
|
standardRadioButton->toggle();
|
||||||
resolutionComboBox->setCurrentIndex(resIndex);
|
resolutionComboBox->setCurrentIndex(resIndex);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
customRadioButton->toggle();
|
customRadioButton->toggle();
|
||||||
customWidthSpinBox->setValue(width);
|
customWidthSpinBox->setValue(width);
|
||||||
customHeightSpinBox->setValue(height);
|
customHeightSpinBox->setValue(height);
|
||||||
|
@ -152,8 +157,7 @@ bool Launcher::GraphicsPage::loadSettings()
|
||||||
if (Settings::Manager::getBool("enable indoor shadows", "Shadows"))
|
if (Settings::Manager::getBool("enable indoor shadows", "Shadows"))
|
||||||
indoorShadowsCheckBox->setCheckState(Qt::Checked);
|
indoorShadowsCheckBox->setCheckState(Qt::Checked);
|
||||||
|
|
||||||
shadowComputeSceneBoundsComboBox->setCurrentIndex(
|
shadowComputeSceneBoundsComboBox->setCurrentIndex(shadowComputeSceneBoundsComboBox->findText(
|
||||||
shadowComputeSceneBoundsComboBox->findText(
|
|
||||||
QString(tr(Settings::Manager::getString("compute scene bounds", "Shadows").c_str()))));
|
QString(tr(Settings::Manager::getString("compute scene bounds", "Shadows").c_str()))));
|
||||||
|
|
||||||
int shadowDistLimit = Settings::Manager::getInt("maximum shadow map distance", "Shadows");
|
int shadowDistLimit = Settings::Manager::getInt("maximum shadow map distance", "Shadows");
|
||||||
|
@ -199,13 +203,17 @@ void Launcher::GraphicsPage::saveSettings()
|
||||||
|
|
||||||
int cWidth = 0;
|
int cWidth = 0;
|
||||||
int cHeight = 0;
|
int cHeight = 0;
|
||||||
if (standardRadioButton->isChecked()) {
|
if (standardRadioButton->isChecked())
|
||||||
|
{
|
||||||
QRegExp resolutionRe(QString("(\\d+) x (\\d+).*"));
|
QRegExp resolutionRe(QString("(\\d+) x (\\d+).*"));
|
||||||
if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified())) {
|
if (resolutionRe.exactMatch(resolutionComboBox->currentText().simplified()))
|
||||||
|
{
|
||||||
cWidth = resolutionRe.cap(1).toInt();
|
cWidth = resolutionRe.cap(1).toInt();
|
||||||
cHeight = resolutionRe.cap(2).toInt();
|
cHeight = resolutionRe.cap(2).toInt();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
cWidth = customWidthSpinBox->value();
|
cWidth = customWidthSpinBox->value();
|
||||||
cHeight = customHeightSpinBox->value();
|
cHeight = customHeightSpinBox->value();
|
||||||
}
|
}
|
||||||
|
@ -301,7 +309,8 @@ QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
|
||||||
msgBox.setWindowTitle(tr("Error receiving resolutions"));
|
msgBox.setWindowTitle(tr("Error receiving resolutions"));
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>SDL_GetNumDisplayModes failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
msgBox.setText(
|
||||||
|
tr("<br><b>SDL_GetNumDisplayModes failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -314,7 +323,8 @@ QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
|
||||||
msgBox.setWindowTitle(tr("Error receiving resolutions"));
|
msgBox.setWindowTitle(tr("Error receiving resolutions"));
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>SDL_GetDisplayMode failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
msgBox.setText(
|
||||||
|
tr("<br><b>SDL_GetDisplayMode failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -322,10 +332,12 @@ QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
|
||||||
QString resolution = QString::number(mode.w) + QString(" x ") + QString::number(mode.h);
|
QString resolution = QString::number(mode.w) + QString(" x ") + QString::number(mode.h);
|
||||||
|
|
||||||
QString aspect = getAspect(mode.w, mode.h);
|
QString aspect = getAspect(mode.w, mode.h);
|
||||||
if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10")) {
|
if (aspect == QLatin1String("16:9") || aspect == QLatin1String("16:10"))
|
||||||
|
{
|
||||||
resolution.append(tr("\t(Wide ") + aspect + ")");
|
resolution.append(tr("\t(Wide ") + aspect + ")");
|
||||||
|
}
|
||||||
} else if (aspect == QLatin1String("4:3")) {
|
else if (aspect == QLatin1String("4:3"))
|
||||||
|
{
|
||||||
resolution.append(tr("\t(Standard 4:3)"));
|
resolution.append(tr("\t(Standard 4:3)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +365,8 @@ QRect Launcher::GraphicsPage::getMaximumResolution()
|
||||||
|
|
||||||
void Launcher::GraphicsPage::screenChanged(int screen)
|
void Launcher::GraphicsPage::screenChanged(int screen)
|
||||||
{
|
{
|
||||||
if (screen >= 0) {
|
if (screen >= 0)
|
||||||
|
{
|
||||||
resolutionComboBox->clear();
|
resolutionComboBox->clear();
|
||||||
resolutionComboBox->addItems(mResolutionsPerScreen[screen]);
|
resolutionComboBox->addItems(mResolutionsPerScreen[screen]);
|
||||||
}
|
}
|
||||||
|
@ -361,13 +374,17 @@ void Launcher::GraphicsPage::screenChanged(int screen)
|
||||||
|
|
||||||
void Launcher::GraphicsPage::slotFullScreenChanged(int mode)
|
void Launcher::GraphicsPage::slotFullScreenChanged(int mode)
|
||||||
{
|
{
|
||||||
if (mode == static_cast<int>(Settings::WindowMode::Fullscreen) || mode == static_cast<int>(Settings::WindowMode::WindowedFullscreen)) {
|
if (mode == static_cast<int>(Settings::WindowMode::Fullscreen)
|
||||||
|
|| mode == static_cast<int>(Settings::WindowMode::WindowedFullscreen))
|
||||||
|
{
|
||||||
standardRadioButton->toggle();
|
standardRadioButton->toggle();
|
||||||
customRadioButton->setEnabled(false);
|
customRadioButton->setEnabled(false);
|
||||||
customWidthSpinBox->setEnabled(false);
|
customWidthSpinBox->setEnabled(false);
|
||||||
customHeightSpinBox->setEnabled(false);
|
customHeightSpinBox->setEnabled(false);
|
||||||
windowBorderCheckBox->setEnabled(false);
|
windowBorderCheckBox->setEnabled(false);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
customRadioButton->setEnabled(true);
|
customRadioButton->setEnabled(true);
|
||||||
customWidthSpinBox->setEnabled(true);
|
customWidthSpinBox->setEnabled(true);
|
||||||
customHeightSpinBox->setEnabled(true);
|
customHeightSpinBox->setEnabled(true);
|
||||||
|
@ -377,11 +394,14 @@ void Launcher::GraphicsPage::slotFullScreenChanged(int mode)
|
||||||
|
|
||||||
void Launcher::GraphicsPage::slotStandardToggled(bool checked)
|
void Launcher::GraphicsPage::slotStandardToggled(bool checked)
|
||||||
{
|
{
|
||||||
if (checked) {
|
if (checked)
|
||||||
|
{
|
||||||
resolutionComboBox->setEnabled(true);
|
resolutionComboBox->setEnabled(true);
|
||||||
customWidthSpinBox->setEnabled(false);
|
customWidthSpinBox->setEnabled(false);
|
||||||
customHeightSpinBox->setEnabled(false);
|
customHeightSpinBox->setEnabled(false);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
resolutionComboBox->setEnabled(false);
|
resolutionComboBox->setEnabled(false);
|
||||||
customWidthSpinBox->setEnabled(true);
|
customWidthSpinBox->setEnabled(true);
|
||||||
customHeightSpinBox->setEnabled(true);
|
customHeightSpinBox->setEnabled(true);
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
namespace Files { struct ConfigurationManager; }
|
namespace Files
|
||||||
|
{
|
||||||
|
struct ConfigurationManager;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Launcher
|
namespace Launcher
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <QTranslator>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QTranslator>
|
||||||
|
|
||||||
#include <components/debug/debugging.hpp>
|
#include <components/debug/debugging.hpp>
|
||||||
#include <components/platform/platform.hpp>
|
#include <components/platform/platform.hpp>
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#include "maindialog.hpp"
|
#include "maindialog.hpp"
|
||||||
|
|
||||||
#include <components/version/version.hpp>
|
|
||||||
#include <components/misc/helpviewer.hpp>
|
#include <components/misc/helpviewer.hpp>
|
||||||
|
#include <components/version/version.hpp>
|
||||||
|
|
||||||
#include <QTime>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
#include <QTime>
|
||||||
|
|
||||||
#include <boost/program_options/options_description.hpp>
|
#include <boost/program_options/options_description.hpp>
|
||||||
#include <boost/program_options/variables_map.hpp>
|
#include <boost/program_options/variables_map.hpp>
|
||||||
|
@ -23,7 +23,8 @@
|
||||||
|
|
||||||
using namespace Process;
|
using namespace Process;
|
||||||
|
|
||||||
void cfgError(const QString& title, const QString& msg) {
|
void cfgError(const QString& title, const QString& msg)
|
||||||
|
{
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setWindowTitle(title);
|
msgBox.setWindowTitle(title);
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
|
@ -33,18 +34,18 @@ void cfgError(const QString& title, const QString& msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Launcher::MainDialog::MainDialog(QWidget* parent)
|
Launcher::MainDialog::MainDialog(QWidget* parent)
|
||||||
: QMainWindow(parent), mGameSettings (mCfgMgr)
|
: QMainWindow(parent)
|
||||||
|
, mGameSettings(mCfgMgr)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
mGameInvoker = new ProcessInvoker();
|
mGameInvoker = new ProcessInvoker();
|
||||||
mWizardInvoker = new ProcessInvoker();
|
mWizardInvoker = new ProcessInvoker();
|
||||||
|
|
||||||
connect(mWizardInvoker->getProcess(), &QProcess::started,
|
connect(mWizardInvoker->getProcess(), &QProcess::started, this, &MainDialog::wizardStarted);
|
||||||
this, &MainDialog::wizardStarted);
|
|
||||||
|
|
||||||
connect(mWizardInvoker->getProcess(), qOverload<int,QProcess::ExitStatus>(&QProcess::finished),
|
connect(mWizardInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||||
this, &MainDialog::wizardFinished);
|
&MainDialog::wizardFinished);
|
||||||
|
|
||||||
iconWidget->setViewMode(QListView::IconMode);
|
iconWidget->setViewMode(QListView::IconMode);
|
||||||
iconWidget->setWrapping(false);
|
iconWidget->setWrapping(false);
|
||||||
|
@ -114,7 +115,6 @@ void Launcher::MainDialog::createIcons()
|
||||||
advancedButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
advancedButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||||
|
|
||||||
connect(iconWidget, &QListWidget::currentItemChanged, this, &MainDialog::changePage);
|
connect(iconWidget, &QListWidget::currentItemChanged, this, &MainDialog::changePage);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::MainDialog::createPages()
|
void Launcher::MainDialog::createPages()
|
||||||
|
@ -148,7 +148,8 @@ void Launcher::MainDialog::createPages()
|
||||||
connect(mPlayPage, &PlayPage::signalProfileChanged, mDataFilesPage, &DataFilesPage::slotProfileChanged);
|
connect(mPlayPage, &PlayPage::signalProfileChanged, mDataFilesPage, &DataFilesPage::slotProfileChanged);
|
||||||
connect(mDataFilesPage, &DataFilesPage::signalProfileChanged, mPlayPage, &PlayPage::setProfilesIndex);
|
connect(mDataFilesPage, &DataFilesPage::signalProfileChanged, mPlayPage, &PlayPage::setProfilesIndex);
|
||||||
// Using Qt::QueuedConnection because signal is emitted in a subthread and slot is in the main thread
|
// Using Qt::QueuedConnection because signal is emitted in a subthread and slot is in the main thread
|
||||||
connect(mDataFilesPage, &DataFilesPage::signalLoadedCellsChanged, mAdvancedPage, &AdvancedPage::slotLoadedCellsChanged, Qt::QueuedConnection);
|
connect(mDataFilesPage, &DataFilesPage::signalLoadedCellsChanged, mAdvancedPage,
|
||||||
|
&AdvancedPage::slotLoadedCellsChanged, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
|
Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
|
||||||
|
@ -158,14 +159,15 @@ Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
|
||||||
|
|
||||||
// Dialog wizard and setup will fail if the config directory does not already exist
|
// Dialog wizard and setup will fail if the config directory does not already exist
|
||||||
const auto& userConfigDir = mCfgMgr.getUserConfigPath();
|
const auto& userConfigDir = mCfgMgr.getUserConfigPath();
|
||||||
if ( ! exists(userConfigDir) ) {
|
if (!exists(userConfigDir))
|
||||||
|
{
|
||||||
if (!create_directories(userConfigDir))
|
if (!create_directories(userConfigDir))
|
||||||
{
|
{
|
||||||
cfgError(tr("Error opening OpenMW configuration file"),
|
cfgError(tr("Error opening OpenMW configuration file"),
|
||||||
tr("<br><b>Could not create directory %0</b><br><br> \
|
tr("<br><b>Could not create directory %0</b><br><br> \
|
||||||
Please make sure you have the right permissions \
|
Please make sure you have the right permissions \
|
||||||
and try again.<br>").arg(Files::pathToQString(canonical(userConfigDir)))
|
and try again.<br>")
|
||||||
);
|
.arg(Files::pathToQString(canonical(userConfigDir))));
|
||||||
return FirstRunDialogResultFailure;
|
return FirstRunDialogResultFailure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,15 +178,15 @@ Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
|
||||||
msgBox.setWindowTitle(tr("First run"));
|
msgBox.setWindowTitle(tr("First run"));
|
||||||
msgBox.setIcon(QMessageBox::Question);
|
msgBox.setIcon(QMessageBox::Question);
|
||||||
msgBox.setStandardButtons(QMessageBox::NoButton);
|
msgBox.setStandardButtons(QMessageBox::NoButton);
|
||||||
msgBox.setText(tr("<html><head/><body><p><b>Welcome to OpenMW!</b></p> \
|
msgBox.setText(
|
||||||
|
tr("<html><head/><body><p><b>Welcome to OpenMW!</b></p> \
|
||||||
<p>It is recommended to run the Installation Wizard.</p> \
|
<p>It is recommended to run the Installation Wizard.</p> \
|
||||||
<p>The Wizard will let you select an existing Morrowind installation, \
|
<p>The Wizard will let you select an existing Morrowind installation, \
|
||||||
or install Morrowind for OpenMW to use.</p></body></html>"));
|
or install Morrowind for OpenMW to use.</p></body></html>"));
|
||||||
|
|
||||||
QAbstractButton *wizardButton =
|
QAbstractButton* wizardButton
|
||||||
msgBox.addButton(tr("Run &Installation Wizard"), QMessageBox::AcceptRole); // ActionRole doesn't work?!
|
= msgBox.addButton(tr("Run &Installation Wizard"), QMessageBox::AcceptRole); // ActionRole doesn't work?!
|
||||||
QAbstractButton *skipButton =
|
QAbstractButton* skipButton = msgBox.addButton(tr("Skip"), QMessageBox::RejectRole);
|
||||||
msgBox.addButton(tr("Skip"), QMessageBox::RejectRole);
|
|
||||||
|
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
|
|
||||||
|
@ -202,7 +204,8 @@ Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog()
|
||||||
return FirstRunDialogResultFailure;
|
return FirstRunDialogResultFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setup() || !setupGameData()) {
|
if (!setup() || !setupGameData())
|
||||||
|
{
|
||||||
return FirstRunDialogResultFailure;
|
return FirstRunDialogResultFailure;
|
||||||
}
|
}
|
||||||
return FirstRunDialogResultContinue;
|
return FirstRunDialogResultContinue;
|
||||||
|
@ -225,7 +228,8 @@ void Launcher::MainDialog::setVersionLabel()
|
||||||
// Add the compile date and time
|
// Add the compile date and time
|
||||||
auto compileDate = QLocale(QLocale::C).toDate(QString(__DATE__).simplified(), QLatin1String("MMM d yyyy"));
|
auto compileDate = QLocale(QLocale::C).toDate(QString(__DATE__).simplified(), QLatin1String("MMM d yyyy"));
|
||||||
auto compileTime = QLocale(QLocale::C).toTime(QString(__TIME__).simplified(), QLatin1String("hh:mm:ss"));
|
auto compileTime = QLocale(QLocale::C).toTime(QString(__TIME__).simplified(), QLatin1String("hh:mm:ss"));
|
||||||
versionLabel->setToolTip(tr("Compiled on %1 %2").arg(QLocale::system().toString(compileDate, QLocale::LongFormat),
|
versionLabel->setToolTip(tr("Compiled on %1 %2")
|
||||||
|
.arg(QLocale::system().toString(compileDate, QLocale::LongFormat),
|
||||||
QLocale::system().toString(compileTime, QLocale::ShortFormat)));
|
QLocale::system().toString(compileTime, QLocale::ShortFormat)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,12 +311,15 @@ bool Launcher::MainDialog::setupLauncherSettings()
|
||||||
{
|
{
|
||||||
qDebug() << "Loading config file:" << path.toUtf8().constData();
|
qDebug() << "Loading config file:" << path.toUtf8().constData();
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
if (file.exists()) {
|
if (file.exists())
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
{
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
cfgError(tr("Error opening OpenMW configuration file"),
|
cfgError(tr("Error opening OpenMW configuration file"),
|
||||||
tr("<br><b>Could not open %0 for reading</b><br><br> \
|
tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||||
Please make sure you have the right permissions \
|
Please make sure you have the right permissions \
|
||||||
and try again.<br>").arg(file.fileName()));
|
and try again.<br>")
|
||||||
|
.arg(file.fileName()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QTextStream stream(&file);
|
QTextStream stream(&file);
|
||||||
|
@ -336,16 +343,19 @@ bool Launcher::MainDialog::setupGameSettings()
|
||||||
|
|
||||||
QFile file;
|
QFile file;
|
||||||
|
|
||||||
auto loadFile = [&] (const QString& path, bool(Config::GameSettings::*reader)(QTextStream&, bool), bool ignoreContent = false) -> std::optional<bool>
|
auto loadFile = [&](const QString& path, bool (Config::GameSettings::*reader)(QTextStream&, bool),
|
||||||
{
|
bool ignoreContent = false) -> std::optional<bool> {
|
||||||
qDebug() << "Loading config file:" << path.toUtf8().constData();
|
qDebug() << "Loading config file:" << path.toUtf8().constData();
|
||||||
file.setFileName(path);
|
file.setFileName(path);
|
||||||
if (file.exists()) {
|
if (file.exists())
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
{
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
{
|
||||||
cfgError(tr("Error opening OpenMW configuration file"),
|
cfgError(tr("Error opening OpenMW configuration file"),
|
||||||
tr("<br><b>Could not open %0 for reading</b><br><br> \
|
tr("<br><b>Could not open %0 for reading</b><br><br> \
|
||||||
Please make sure you have the right permissions \
|
Please make sure you have the right permissions \
|
||||||
and try again.<br>").arg(file.fileName()));
|
and try again.<br>")
|
||||||
|
.arg(file.fileName()));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
QTextStream stream(&file);
|
QTextStream stream(&file);
|
||||||
|
@ -387,7 +397,10 @@ bool Launcher::MainDialog::setupGameData()
|
||||||
{
|
{
|
||||||
QDir dir(path3);
|
QDir dir(path3);
|
||||||
QStringList filters;
|
QStringList filters;
|
||||||
filters << "*.esp" << "*.esm" << "*.omwgame" << "*.omwaddon";
|
filters << "*.esp"
|
||||||
|
<< "*.esm"
|
||||||
|
<< "*.omwgame"
|
||||||
|
<< "*.omwaddon";
|
||||||
|
|
||||||
if (!dir.entryList(filters).isEmpty())
|
if (!dir.entryList(filters).isEmpty())
|
||||||
dataDirs.append(path3);
|
dataDirs.append(path3);
|
||||||
|
@ -399,13 +412,12 @@ bool Launcher::MainDialog::setupGameData()
|
||||||
msgBox.setWindowTitle(tr("Error detecting Morrowind installation"));
|
msgBox.setWindowTitle(tr("Error detecting Morrowind installation"));
|
||||||
msgBox.setIcon(QMessageBox::Warning);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setStandardButtons(QMessageBox::NoButton);
|
msgBox.setStandardButtons(QMessageBox::NoButton);
|
||||||
msgBox.setText(tr("<br><b>Could not find the Data Files location</b><br><br> \
|
msgBox.setText(
|
||||||
|
tr("<br><b>Could not find the Data Files location</b><br><br> \
|
||||||
The directory containing the data files was not found."));
|
The directory containing the data files was not found."));
|
||||||
|
|
||||||
QAbstractButton *wizardButton =
|
QAbstractButton* wizardButton = msgBox.addButton(tr("Run &Installation Wizard..."), QMessageBox::ActionRole);
|
||||||
msgBox.addButton(tr("Run &Installation Wizard..."), QMessageBox::ActionRole);
|
QAbstractButton* skipButton = msgBox.addButton(tr("Skip"), QMessageBox::RejectRole);
|
||||||
QAbstractButton *skipButton =
|
|
||||||
msgBox.addButton(tr("Skip"), QMessageBox::RejectRole);
|
|
||||||
|
|
||||||
Q_UNUSED(skipButton); // Suppress compiler unused warning
|
Q_UNUSED(skipButton); // Suppress compiler unused warning
|
||||||
|
|
||||||
|
@ -437,7 +449,8 @@ bool Launcher::MainDialog::setupGraphicsSettings()
|
||||||
{
|
{
|
||||||
cfgError(tr("Error reading OpenMW configuration files"),
|
cfgError(tr("Error reading OpenMW configuration files"),
|
||||||
tr("<br>The problem may be due to an incomplete installation of OpenMW.<br> \
|
tr("<br>The problem may be due to an incomplete installation of OpenMW.<br> \
|
||||||
Reinstalling OpenMW may resolve the problem.<br>") + e.what());
|
Reinstalling OpenMW may resolve the problem.<br>")
|
||||||
|
+ e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,7 +482,6 @@ void Launcher::MainDialog::saveSettings()
|
||||||
mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY);
|
mLauncherSettings.setValue(QString("General/MainWindow/posy"), posY);
|
||||||
|
|
||||||
mLauncherSettings.setValue(QString("General/firstrun"), QString("false"));
|
mLauncherSettings.setValue(QString("General/firstrun"), QString("false"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Launcher::MainDialog::writeSettings()
|
bool Launcher::MainDialog::writeSettings()
|
||||||
|
@ -483,12 +495,15 @@ bool Launcher::MainDialog::writeSettings()
|
||||||
|
|
||||||
const auto& userPath = mCfgMgr.getUserConfigPath();
|
const auto& userPath = mCfgMgr.getUserConfigPath();
|
||||||
|
|
||||||
if (!exists(userPath)) {
|
if (!exists(userPath))
|
||||||
if (!create_directories(userPath)) {
|
{
|
||||||
|
if (!create_directories(userPath))
|
||||||
|
{
|
||||||
cfgError(tr("Error creating OpenMW configuration directory"),
|
cfgError(tr("Error creating OpenMW configuration directory"),
|
||||||
tr("<br><b>Could not create %0</b><br><br> \
|
tr("<br><b>Could not create %0</b><br><br> \
|
||||||
Please make sure you have the right permissions \
|
Please make sure you have the right permissions \
|
||||||
and try again.<br>").arg(Files::pathToQString(userPath)));
|
and try again.<br>")
|
||||||
|
.arg(Files::pathToQString(userPath)));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,27 +515,30 @@ bool Launcher::MainDialog::writeSettings()
|
||||||
QFile file(Files::pathToQString(userPath / "openmw.cfg"));
|
QFile file(Files::pathToQString(userPath / "openmw.cfg"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
if (!file.open(QIODevice::ReadWrite | QIODevice::Text))
|
||||||
|
{
|
||||||
// File cannot be opened or created
|
// File cannot be opened or created
|
||||||
cfgError(tr("Error writing OpenMW configuration file"),
|
cfgError(tr("Error writing OpenMW configuration file"),
|
||||||
tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||||
Please make sure you have the right permissions \
|
Please make sure you have the right permissions \
|
||||||
and try again.<br>").arg(file.fileName()));
|
and try again.<br>")
|
||||||
|
.arg(file.fileName()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mGameSettings.writeFileWithComments(file);
|
mGameSettings.writeFileWithComments(file);
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// Graphics settings
|
// Graphics settings
|
||||||
const auto settingsPath = mCfgMgr.getUserConfigPath() / "settings.cfg";
|
const auto settingsPath = mCfgMgr.getUserConfigPath() / "settings.cfg";
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
Settings::Manager::saveUser(settingsPath);
|
Settings::Manager::saveUser(settingsPath);
|
||||||
}
|
}
|
||||||
catch (std::exception& e) {
|
catch (std::exception& e)
|
||||||
std::string msg = "<br><b>Error writing settings.cfg</b><br><br>" +
|
{
|
||||||
Files::pathToUnicodeString(settingsPath) + "<br><br>" + e.what();
|
std::string msg = "<br><b>Error writing settings.cfg</b><br><br>" + Files::pathToUnicodeString(settingsPath)
|
||||||
|
+ "<br><br>" + e.what();
|
||||||
cfgError(tr("Error writing user settings file"), tr(msg.c_str()));
|
cfgError(tr("Error writing user settings file"), tr(msg.c_str()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -528,12 +546,14 @@ bool Launcher::MainDialog::writeSettings()
|
||||||
// Launcher settings
|
// Launcher settings
|
||||||
file.setFileName(Files::pathToQString(userPath / Config::LauncherSettings::sLauncherConfigFileName));
|
file.setFileName(Files::pathToQString(userPath / Config::LauncherSettings::sLauncherConfigFileName));
|
||||||
|
|
||||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate))
|
||||||
|
{
|
||||||
// File cannot be opened or created
|
// File cannot be opened or created
|
||||||
cfgError(tr("Error writing Launcher configuration file"),
|
cfgError(tr("Error writing Launcher configuration file"),
|
||||||
tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
tr("<br><b>Could not open or create %0 for writing</b><br><br> \
|
||||||
Please make sure you have the right permissions \
|
Please make sure you have the right permissions \
|
||||||
and try again.<br>").arg(file.fileName()));
|
and try again.<br>")
|
||||||
|
.arg(file.fileName()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,12 +595,14 @@ void Launcher::MainDialog::play()
|
||||||
if (!writeSettings())
|
if (!writeSettings())
|
||||||
return qApp->quit();
|
return qApp->quit();
|
||||||
|
|
||||||
if (!mGameSettings.hasMaster()) {
|
if (!mGameSettings.hasMaster())
|
||||||
|
{
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setWindowTitle(tr("No game file selected"));
|
msgBox.setWindowTitle(tr("No game file selected"));
|
||||||
msgBox.setIcon(QMessageBox::Warning);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>You do not have a game file selected.</b><br><br> \
|
msgBox.setText(
|
||||||
|
tr("<br><b>You do not have a game file selected.</b><br><br> \
|
||||||
OpenMW will not start without a game file selected.<br>"));
|
OpenMW will not start without a game file selected.<br>"));
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#ifndef MAINDIALOG_H
|
#ifndef MAINDIALOG_H
|
||||||
#define MAINDIALOG_H
|
#define MAINDIALOG_H
|
||||||
|
|
||||||
|
|
||||||
#ifndef Q_MOC_RUN
|
#ifndef Q_MOC_RUN
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
|
||||||
|
@ -77,7 +76,10 @@ namespace Launcher
|
||||||
void loadSettings();
|
void loadSettings();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
|
|
||||||
inline bool startProgram(const QString &name, bool detached = false) { return startProgram(name, QStringList(), detached); }
|
inline bool startProgram(const QString& name, bool detached = false)
|
||||||
|
{
|
||||||
|
return startProgram(name, QStringList(), detached);
|
||||||
|
}
|
||||||
bool startProgram(const QString& name, const QStringList& arguments, bool detached = false);
|
bool startProgram(const QString& name, const QStringList& arguments, bool detached = false);
|
||||||
|
|
||||||
void closeEvent(QCloseEvent* event) override;
|
void closeEvent(QCloseEvent* event) override;
|
||||||
|
@ -95,7 +97,6 @@ namespace Launcher
|
||||||
|
|
||||||
Config::GameSettings mGameSettings;
|
Config::GameSettings mGameSettings;
|
||||||
Config::LauncherSettings mLauncherSettings;
|
Config::LauncherSettings mLauncherSettings;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
#include <QListView>
|
#include <QListView>
|
||||||
|
|
||||||
Launcher::PlayPage::PlayPage(QWidget *parent) : QWidget(parent)
|
Launcher::PlayPage::PlayPage(QWidget* parent)
|
||||||
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
setObjectName("PlayPage");
|
setObjectName("PlayPage");
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
@ -11,7 +12,6 @@ Launcher::PlayPage::PlayPage(QWidget *parent) : QWidget(parent)
|
||||||
|
|
||||||
connect(profilesComboBox, qOverload<int>(&QComboBox::activated), this, &PlayPage::signalProfileChanged);
|
connect(profilesComboBox, qOverload<int>(&QComboBox::activated), this, &PlayPage::signalProfileChanged);
|
||||||
connect(playButton, &QPushButton::clicked, this, &PlayPage::slotPlayClicked);
|
connect(playButton, &QPushButton::clicked, this, &PlayPage::slotPlayClicked);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::PlayPage::setProfilesModel(QAbstractItemModel* model)
|
void Launcher::PlayPage::setProfilesModel(QAbstractItemModel* model)
|
||||||
|
|
|
@ -26,9 +26,6 @@ namespace Launcher
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void slotPlayClicked();
|
void slotPlayClicked();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
#include "settingspage.hpp"
|
#include "settingspage.hpp"
|
||||||
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include <components/files/conversion.hpp>
|
#include <components/files/conversion.hpp>
|
||||||
#include <components/files/qtconversion.hpp>
|
#include <components/files/qtconversion.hpp>
|
||||||
|
|
||||||
#include "utils/textinputdialog.hpp"
|
|
||||||
#include "datafilespage.hpp"
|
#include "datafilespage.hpp"
|
||||||
|
#include "utils/textinputdialog.hpp"
|
||||||
|
|
||||||
using namespace Process;
|
using namespace Process;
|
||||||
|
|
||||||
Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager &cfg,
|
Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager& cfg, Config::GameSettings& gameSettings,
|
||||||
Config::GameSettings &gameSettings,
|
|
||||||
Config::LauncherSettings& launcherSettings, MainDialog* parent)
|
Config::LauncherSettings& launcherSettings, MainDialog* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, mCfgMgr(cfg)
|
, mCfgMgr(cfg)
|
||||||
|
@ -25,12 +24,7 @@ Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager &cfg,
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
QStringList languages;
|
QStringList languages;
|
||||||
languages << tr("English")
|
languages << tr("English") << tr("French") << tr("German") << tr("Italian") << tr("Polish") << tr("Russian")
|
||||||
<< tr("French")
|
|
||||||
<< tr("German")
|
|
||||||
<< tr("Italian")
|
|
||||||
<< tr("Polish")
|
|
||||||
<< tr("Russian")
|
|
||||||
<< tr("Spanish");
|
<< tr("Spanish");
|
||||||
|
|
||||||
languageComboBox->addItems(languages);
|
languageComboBox->addItems(languages);
|
||||||
|
@ -39,22 +33,19 @@ Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager &cfg,
|
||||||
mImporterInvoker = new ProcessInvoker();
|
mImporterInvoker = new ProcessInvoker();
|
||||||
resetProgressBar();
|
resetProgressBar();
|
||||||
|
|
||||||
connect(mWizardInvoker->getProcess(), &QProcess::started,
|
connect(mWizardInvoker->getProcess(), &QProcess::started, this, &SettingsPage::wizardStarted);
|
||||||
this, &SettingsPage::wizardStarted);
|
|
||||||
|
|
||||||
connect(mWizardInvoker->getProcess(), qOverload<int,QProcess::ExitStatus>(&QProcess::finished),
|
connect(mWizardInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||||
this, &SettingsPage::wizardFinished);
|
&SettingsPage::wizardFinished);
|
||||||
|
|
||||||
connect(mImporterInvoker->getProcess(), &QProcess::started,
|
connect(mImporterInvoker->getProcess(), &QProcess::started, this, &SettingsPage::importerStarted);
|
||||||
this, &SettingsPage::importerStarted);
|
|
||||||
|
|
||||||
connect(mImporterInvoker->getProcess(), qOverload<int,QProcess::ExitStatus>(&QProcess::finished),
|
connect(mImporterInvoker->getProcess(), qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this,
|
||||||
this, &SettingsPage::importerFinished);
|
&SettingsPage::importerFinished);
|
||||||
|
|
||||||
mProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this);
|
mProfileDialog = new TextInputDialog(tr("New Content List"), tr("Content List name:"), this);
|
||||||
|
|
||||||
connect(mProfileDialog->lineEdit(), &LineEdit::textChanged,
|
connect(mProfileDialog->lineEdit(), &LineEdit::textChanged, this, &SettingsPage::updateOkButton);
|
||||||
this, &SettingsPage::updateOkButton);
|
|
||||||
|
|
||||||
// Detect Morrowind configuration files
|
// Detect Morrowind configuration files
|
||||||
QStringList iniPaths;
|
QStringList iniPaths;
|
||||||
|
@ -76,10 +67,13 @@ Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager &cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!iniPaths.isEmpty()) {
|
if (!iniPaths.isEmpty())
|
||||||
|
{
|
||||||
settingsComboBox->addItems(iniPaths);
|
settingsComboBox->addItems(iniPaths);
|
||||||
importerButton->setEnabled(true);
|
importerButton->setEnabled(true);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
importerButton->setEnabled(false);
|
importerButton->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,16 +107,20 @@ void Launcher::SettingsPage::on_importerButton_clicked()
|
||||||
QFile file(Files::pathToQString(path));
|
QFile file(Files::pathToQString(path));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!file.exists()) {
|
if (!file.exists())
|
||||||
if (!file.open(QIODevice::ReadWrite)) {
|
{
|
||||||
|
if (!file.open(QIODevice::ReadWrite))
|
||||||
|
{
|
||||||
// File cannot be created
|
// File cannot be created
|
||||||
QMessageBox msgBox;
|
QMessageBox msgBox;
|
||||||
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
msgBox.setIcon(QMessageBox::Critical);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<html><head/><body><p><b>Could not open or create %1 for writing </b></p> \
|
msgBox.setText(
|
||||||
|
tr("<html><head/><body><p><b>Could not open or create %1 for writing </b></p> \
|
||||||
<p>Please make sure you have the right permissions \
|
<p>Please make sure you have the right permissions \
|
||||||
and try again.</p></body></html>").arg(file.fileName()));
|
and try again.</p></body></html>")
|
||||||
|
.arg(file.fileName()));
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -159,13 +157,9 @@ void Launcher::SettingsPage::on_importerButton_clicked()
|
||||||
|
|
||||||
void Launcher::SettingsPage::on_browseButton_clicked()
|
void Launcher::SettingsPage::on_browseButton_clicked()
|
||||||
{
|
{
|
||||||
QString iniFile = QFileDialog::getOpenFileName(
|
QString iniFile = QFileDialog::getOpenFileName(this, QObject::tr("Select configuration file"), QDir::currentPath(),
|
||||||
this,
|
|
||||||
QObject::tr("Select configuration file"),
|
|
||||||
QDir::currentPath(),
|
|
||||||
QString(tr("Morrowind configuration file (*.ini)")));
|
QString(tr("Morrowind configuration file (*.ini)")));
|
||||||
|
|
||||||
|
|
||||||
if (iniFile.isEmpty())
|
if (iniFile.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -176,7 +170,8 @@ void Launcher::SettingsPage::on_browseButton_clicked()
|
||||||
|
|
||||||
const QString path(QDir::toNativeSeparators(info.absoluteFilePath()));
|
const QString path(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||||
|
|
||||||
if (settingsComboBox->findText(path) == -1) {
|
if (settingsComboBox->findText(path) == -1)
|
||||||
|
{
|
||||||
settingsComboBox->addItem(path);
|
settingsComboBox->addItem(path);
|
||||||
settingsComboBox->setCurrentIndex(settingsComboBox->findText(path));
|
settingsComboBox->setCurrentIndex(settingsComboBox->findText(path));
|
||||||
importerButton->setEnabled(true);
|
importerButton->setEnabled(true);
|
||||||
|
@ -241,16 +236,15 @@ void Launcher::SettingsPage::resetProgressBar()
|
||||||
void Launcher::SettingsPage::updateOkButton(const QString& text)
|
void Launcher::SettingsPage::updateOkButton(const QString& text)
|
||||||
{
|
{
|
||||||
// We do this here because we need to access the profiles
|
// We do this here because we need to access the profiles
|
||||||
if (text.isEmpty()) {
|
if (text.isEmpty())
|
||||||
|
{
|
||||||
mProfileDialog->setOkButtonEnabled(false);
|
mProfileDialog->setOkButtonEnabled(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QStringList profiles(mLauncherSettings.getContentLists());
|
const QStringList profiles(mLauncherSettings.getContentLists());
|
||||||
|
|
||||||
(profiles.contains(text))
|
(profiles.contains(text)) ? mProfileDialog->setOkButtonEnabled(false) : mProfileDialog->setOkButtonEnabled(true);
|
||||||
? mProfileDialog->setOkButtonEnabled(false)
|
|
||||||
: mProfileDialog->setOkButtonEnabled(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::SettingsPage::saveSettings()
|
void Launcher::SettingsPage::saveSettings()
|
||||||
|
@ -259,11 +253,16 @@ void Launcher::SettingsPage::saveSettings()
|
||||||
|
|
||||||
mLauncherSettings.setValue(QLatin1String("Settings/language"), language);
|
mLauncherSettings.setValue(QLatin1String("Settings/language"), language);
|
||||||
|
|
||||||
if (language == QLatin1String("Polish")) {
|
if (language == QLatin1String("Polish"))
|
||||||
|
{
|
||||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1250"));
|
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1250"));
|
||||||
} else if (language == QLatin1String("Russian")) {
|
}
|
||||||
|
else if (language == QLatin1String("Russian"))
|
||||||
|
{
|
||||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1251"));
|
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1251"));
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252"));
|
mGameSettings.setValue(QLatin1String("encoding"), QLatin1String("win1252"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,15 @@
|
||||||
|
|
||||||
#include "maindialog.hpp"
|
#include "maindialog.hpp"
|
||||||
|
|
||||||
namespace Files { struct ConfigurationManager; }
|
namespace Files
|
||||||
namespace Config { class GameSettings;
|
{
|
||||||
class LauncherSettings; }
|
struct ConfigurationManager;
|
||||||
|
}
|
||||||
|
namespace Config
|
||||||
|
{
|
||||||
|
class GameSettings;
|
||||||
|
class LauncherSettings;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Launcher
|
namespace Launcher
|
||||||
{
|
{
|
||||||
|
@ -45,7 +51,6 @@ namespace Launcher
|
||||||
void updateOkButton(const QString& text);
|
void updateOkButton(const QString& text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Process::ProcessInvoker* mWizardInvoker;
|
Process::ProcessInvoker* mWizardInvoker;
|
||||||
Process::ProcessInvoker* mImporterInvoker;
|
Process::ProcessInvoker* mImporterInvoker;
|
||||||
|
|
||||||
|
@ -56,7 +61,6 @@ namespace Launcher
|
||||||
|
|
||||||
MainDialog* mMain;
|
MainDialog* mMain;
|
||||||
TextInputDialog* mProfileDialog;
|
TextInputDialog* mProfileDialog;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "cellnameloader.hpp"
|
#include "cellnameloader.hpp"
|
||||||
|
|
||||||
#include <components/esm3/loadcell.hpp>
|
|
||||||
#include <components/contentselector/view/contentselector.hpp>
|
#include <components/contentselector/view/contentselector.hpp>
|
||||||
|
#include <components/esm3/loadcell.hpp>
|
||||||
|
|
||||||
QSet<QString> CellNameLoader::getCellNames(QStringList& contentPaths)
|
QSet<QString> CellNameLoader::getCellNames(QStringList& contentPaths)
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,8 @@ QSet<QString> CellNameLoader::getCellNames(QStringList &contentPaths)
|
||||||
ESM::ESMReader esmReader;
|
ESM::ESMReader esmReader;
|
||||||
|
|
||||||
// Loop through all content files
|
// Loop through all content files
|
||||||
for (auto &contentPath : contentPaths) {
|
for (auto& contentPath : contentPaths)
|
||||||
|
{
|
||||||
if (contentPath.endsWith(".omwscripts", Qt::CaseInsensitive))
|
if (contentPath.endsWith(".omwscripts", Qt::CaseInsensitive))
|
||||||
continue;
|
continue;
|
||||||
esmReader.open(contentPath.toStdString());
|
esmReader.open(contentPath.toStdString());
|
||||||
|
@ -20,9 +21,11 @@ QSet<QString> CellNameLoader::getCellNames(QStringList &contentPaths)
|
||||||
ESM::NAME recordName = esmReader.getRecName();
|
ESM::NAME recordName = esmReader.getRecName();
|
||||||
esmReader.getRecHeader();
|
esmReader.getRecHeader();
|
||||||
|
|
||||||
if (isCellRecord(recordName)) {
|
if (isCellRecord(recordName))
|
||||||
|
{
|
||||||
QString cellName = getCellName(esmReader);
|
QString cellName = getCellName(esmReader);
|
||||||
if (!cellName.isEmpty()) {
|
if (!cellName.isEmpty())
|
||||||
|
{
|
||||||
cellNames.insert(cellName);
|
cellNames.insert(cellName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,4 +51,3 @@ QString CellNameLoader::getCellName(ESM::ESMReader &esmReader)
|
||||||
|
|
||||||
return QString::fromStdString(cell.mName);
|
return QString::fromStdString(cell.mName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,20 @@
|
||||||
|
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
|
|
||||||
namespace ESM {class ESMReader; struct Cell;}
|
namespace ESM
|
||||||
namespace ContentSelectorView {class ContentSelector;}
|
{
|
||||||
|
class ESMReader;
|
||||||
|
struct Cell;
|
||||||
|
}
|
||||||
|
namespace ContentSelectorView
|
||||||
|
{
|
||||||
|
class ContentSelector;
|
||||||
|
}
|
||||||
|
|
||||||
class CellNameLoader {
|
class CellNameLoader
|
||||||
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the names of all cells contained within the given content files
|
* Returns the names of all cells contained within the given content files
|
||||||
* @param contentPaths the file paths of each content file to be examined
|
* @param contentPaths the file paths of each content file to be examined
|
||||||
|
@ -36,5 +43,4 @@ private:
|
||||||
QString getCellName(ESM::ESMReader& esmReader);
|
QString getCellName(ESM::ESMReader& esmReader);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // OPENMW_CELLNAMELOADER_H
|
#endif // OPENMW_CELLNAMELOADER_H
|
||||||
|
|
|
@ -23,8 +23,7 @@ void LineEdit::resizeEvent(QResizeEvent *)
|
||||||
{
|
{
|
||||||
QSize sz = mClearButton->sizeHint();
|
QSize sz = mClearButton->sizeHint();
|
||||||
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||||
mClearButton->move(rect().right() - frameWidth - sz.width(),
|
mClearButton->move(rect().right() - frameWidth - sz.width(), (rect().bottom() + 1 - sz.height()) / 2);
|
||||||
(rect().bottom() + 1 - sz.height())/2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LineEdit::updateClearButton(const QString& text)
|
void LineEdit::updateClearButton(const QString& text)
|
||||||
|
|
|
@ -38,4 +38,3 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LIENEDIT_H
|
#endif // LIENEDIT_H
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Launcher
|
namespace Launcher
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
#include <QString>
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include "profilescombobox.hpp"
|
#include "profilescombobox.hpp"
|
||||||
|
|
||||||
ProfilesComboBox::ProfilesComboBox(QWidget *parent) :
|
ProfilesComboBox::ProfilesComboBox(QWidget* parent)
|
||||||
ContentSelectorView::ComboBox(parent)
|
: ContentSelectorView::ComboBox(parent)
|
||||||
{
|
{
|
||||||
connect(this, qOverload<int>(&ProfilesComboBox::activated),
|
connect(this, qOverload<int>(&ProfilesComboBox::activated), this, &ProfilesComboBox::slotIndexChangedByUser);
|
||||||
this, &ProfilesComboBox::slotIndexChangedByUser);
|
|
||||||
|
|
||||||
setInsertPolicy(QComboBox::NoInsert);
|
setInsertPolicy(QComboBox::NoInsert);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +16,8 @@ void ProfilesComboBox::setEditEnabled(bool editable)
|
||||||
if (isEditable() == editable)
|
if (isEditable() == editable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!editable) {
|
if (!editable)
|
||||||
|
{
|
||||||
disconnect(lineEdit(), &QLineEdit::editingFinished, this, &ProfilesComboBox::slotEditingFinished);
|
disconnect(lineEdit(), &QLineEdit::editingFinished, this, &ProfilesComboBox::slotEditingFinished);
|
||||||
disconnect(lineEdit(), &QLineEdit::textChanged, this, &ProfilesComboBox::slotTextChanged);
|
disconnect(lineEdit(), &QLineEdit::textChanged, this, &ProfilesComboBox::slotTextChanged);
|
||||||
return setEditable(false);
|
return setEditable(false);
|
||||||
|
@ -46,9 +46,12 @@ void ProfilesComboBox::slotTextChanged(const QString &text)
|
||||||
|
|
||||||
int index = findText(text);
|
int index = findText(text);
|
||||||
|
|
||||||
if (text.isEmpty() || (index != -1 && index != currentIndex())) {
|
if (text.isEmpty() || (index != -1 && index != currentIndex()))
|
||||||
|
{
|
||||||
lineEdit()->setPalette(palette);
|
lineEdit()->setPalette(palette);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
lineEdit()->setPalette(QApplication::palette());
|
lineEdit()->setPalette(QApplication::palette());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,5 +92,6 @@ ProfilesComboBox::ComboBoxLineEdit::ComboBoxLineEdit (QWidget *parent)
|
||||||
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||||
|
|
||||||
setObjectName(QString("ComboBoxLineEdit"));
|
setObjectName(QString("ComboBoxLineEdit"));
|
||||||
setStyleSheet(QString("ComboBoxLineEdit { background-color: transparent; padding-right: %1px; } ").arg(mClearButton->sizeHint().width() + frameWidth + 1));
|
setStyleSheet(QString("ComboBoxLineEdit { background-color: transparent; padding-right: %1px; } ")
|
||||||
|
.arg(mClearButton->sizeHint().width() + frameWidth + 1));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit ProfilesComboBox(QWidget* parent = nullptr);
|
explicit ProfilesComboBox(QWidget* parent = nullptr);
|
||||||
void setEditEnabled(bool editable);
|
void setEditEnabled(bool editable);
|
||||||
void setCurrentProfile(int index)
|
void setCurrentProfile(int index)
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#include "textinputdialog.hpp"
|
#include "textinputdialog.hpp"
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QLabel>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QValidator>
|
#include <QValidator>
|
||||||
#include <QLabel>
|
|
||||||
|
|
||||||
Launcher::TextInputDialog::TextInputDialog(const QString& title, const QString &text, QWidget *parent) :
|
Launcher::TextInputDialog::TextInputDialog(const QString& title, const QString& text, QWidget* parent)
|
||||||
QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
mButtonBox = new QDialogButtonBox(this);
|
mButtonBox = new QDialogButtonBox(this);
|
||||||
|
@ -43,9 +43,7 @@ Launcher::TextInputDialog::TextInputDialog(const QString& title, const QString &
|
||||||
connect(mButtonBox, &QDialogButtonBox::rejected, this, &TextInputDialog::reject);
|
connect(mButtonBox, &QDialogButtonBox::rejected, this, &TextInputDialog::reject);
|
||||||
}
|
}
|
||||||
|
|
||||||
Launcher::TextInputDialog::~TextInputDialog()
|
Launcher::TextInputDialog::~TextInputDialog() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int Launcher::TextInputDialog::exec()
|
int Launcher::TextInputDialog::exec()
|
||||||
{
|
{
|
||||||
|
@ -62,9 +60,12 @@ void Launcher::TextInputDialog::setOkButtonEnabled(bool enabled)
|
||||||
QPalette palette;
|
QPalette palette;
|
||||||
palette.setColor(QPalette::Text, Qt::red);
|
palette.setColor(QPalette::Text, Qt::red);
|
||||||
|
|
||||||
if (enabled) {
|
if (enabled)
|
||||||
|
{
|
||||||
mLineEdit->setPalette(QApplication::palette());
|
mLineEdit->setPalette(QApplication::palette());
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Existing profile name, make the text red
|
// Existing profile name, make the text red
|
||||||
mLineEdit->setPalette(palette);
|
mLineEdit->setPalette(palette);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ namespace Launcher
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit TextInputDialog(const QString& title, const QString& text, QWidget* parent = nullptr);
|
explicit TextInputDialog(const QString& title, const QString& text, QWidget* parent = nullptr);
|
||||||
~TextInputDialog() override;
|
~TextInputDialog() override;
|
||||||
|
|
||||||
|
@ -24,10 +23,8 @@ namespace Launcher
|
||||||
int exec() override;
|
int exec() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QDialogButtonBox* mButtonBox;
|
QDialogButtonBox* mButtonBox;
|
||||||
LineEdit* mLineEdit;
|
LineEdit* mLineEdit;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,16 +1,17 @@
|
||||||
#ifndef MWINIIMPORTER_IMPORTER
|
#ifndef MWINIIMPORTER_IMPORTER
|
||||||
#define MWINIIMPORTER_IMPORTER 1
|
#define MWINIIMPORTER_IMPORTER 1
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
#include <vector>
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iosfwd>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
class MwIniImporter {
|
class MwIniImporter
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::map<std::string, std::string> strmap;
|
typedef std::map<std::string, std::string> strmap;
|
||||||
typedef std::map<std::string, std::vector<std::string>> multistrmap;
|
typedef std::map<std::string, std::vector<std::string>> multistrmap;
|
||||||
|
@ -23,15 +24,15 @@ class MwIniImporter {
|
||||||
static multistrmap loadCfgFile(const std::filesystem::path& filename);
|
static multistrmap loadCfgFile(const std::filesystem::path& filename);
|
||||||
void merge(multistrmap& cfg, const multistrmap& ini) const;
|
void merge(multistrmap& cfg, const multistrmap& ini) const;
|
||||||
void mergeFallback(multistrmap& cfg, const multistrmap& ini) const;
|
void mergeFallback(multistrmap& cfg, const multistrmap& ini) const;
|
||||||
void importGameFiles(multistrmap &cfg, const multistrmap &ini,
|
void importGameFiles(multistrmap& cfg, const multistrmap& ini, const std::filesystem::path& iniFilename) const;
|
||||||
const std::filesystem::path& iniFilename) const;
|
|
||||||
void importArchives(multistrmap& cfg, const multistrmap& ini) const;
|
void importArchives(multistrmap& cfg, const multistrmap& ini) const;
|
||||||
static void writeToFile(std::ostream& out, const multistrmap& cfg);
|
static void writeToFile(std::ostream& out, const multistrmap& cfg);
|
||||||
|
|
||||||
static std::vector<std::string> dependencySort(MwIniImporter::dependencyList source);
|
static std::vector<std::string> dependencySort(MwIniImporter::dependencyList source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void dependencySortStep(std::string& element, MwIniImporter::dependencyList& source, std::vector<std::string>& result);
|
static void dependencySortStep(
|
||||||
|
std::string& element, MwIniImporter::dependencyList& source, std::vector<std::string>& result);
|
||||||
static std::vector<std::string>::iterator findString(std::vector<std::string>& source, const std::string& string);
|
static std::vector<std::string>::iterator findString(std::vector<std::string>& source, const std::string& string);
|
||||||
|
|
||||||
static void insertMultistrmap(multistrmap& cfg, const std::string& key, const std::string& value);
|
static void insertMultistrmap(multistrmap& cfg, const std::string& key, const std::string& value);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "importer.hpp"
|
#include "importer.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ namespace bpo = boost::program_options;
|
||||||
namespace sfs = std::filesystem;
|
namespace sfs = std::filesystem;
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Include on Windows only
|
// Include on Windows only
|
||||||
|
@ -22,13 +23,13 @@ int main(int argc, char *argv[]) {
|
||||||
class utf8argv
|
class utf8argv
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
utf8argv(int argc, wchar_t* wargv[])
|
utf8argv(int argc, wchar_t* wargv[])
|
||||||
{
|
{
|
||||||
args.reserve(argc);
|
args.reserve(argc);
|
||||||
argv = new const char*[argc];
|
argv = new const char*[argc];
|
||||||
|
|
||||||
for (int i = 0; i < argc; ++i) {
|
for (int i = 0; i < argc; ++i)
|
||||||
|
{
|
||||||
args.push_back(boost::locale::conv::utf_to_utf<char>(wargv[i]));
|
args.push_back(boost::locale::conv::utf_to_utf<char>(wargv[i]));
|
||||||
argv[i] = args.back().c_str();
|
argv[i] = args.back().c_str();
|
||||||
}
|
}
|
||||||
|
@ -52,7 +53,8 @@ private:
|
||||||
|
|
||||||
For boost::filesystem::path::imbue see components/files/windowspath.cpp
|
For boost::filesystem::path::imbue see components/files/windowspath.cpp
|
||||||
*/
|
*/
|
||||||
int wmain(int argc, wchar_t *wargv[]) {
|
int wmain(int argc, wchar_t* wargv[])
|
||||||
|
{
|
||||||
utf8argv converter(argc, wargv);
|
utf8argv converter(argc, wargv);
|
||||||
char** argv = converter.get();
|
char** argv = converter.get();
|
||||||
#endif
|
#endif
|
||||||
|
@ -72,7 +74,8 @@ int wmain(int argc, wchar_t *wargv[]) {
|
||||||
addOption("no-archives,A", "disable bsa archives import");
|
addOption("no-archives,A", "disable bsa archives import");
|
||||||
addOption("encoding,e", bpo::value<std::string>()->default_value("win1252"),
|
addOption("encoding,e", bpo::value<std::string>()->default_value("win1252"),
|
||||||
"Character encoding used in OpenMW game messages:\n"
|
"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\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\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n"
|
||||||
"\n\twin1252 - Western European (Latin) alphabet, used by default");
|
"\n\twin1252 - Western European (Latin) alphabet, used by default");
|
||||||
;
|
;
|
||||||
|
@ -80,29 +83,39 @@ int wmain(int argc, wchar_t *wargv[]) {
|
||||||
|
|
||||||
bpo::variables_map vm;
|
bpo::variables_map vm;
|
||||||
|
|
||||||
bpo::parsed_options parsed = bpo::command_line_parser(argc, argv)
|
bpo::parsed_options parsed = bpo::command_line_parser(argc, argv).options(desc).positional(p_desc).run();
|
||||||
.options(desc)
|
|
||||||
.positional(p_desc)
|
|
||||||
.run();
|
|
||||||
bpo::store(parsed, vm);
|
bpo::store(parsed, vm);
|
||||||
|
|
||||||
if(vm.count("help") || !vm.count("ini") || !vm.count("cfg")) {
|
if (vm.count("help") || !vm.count("ini") || !vm.count("cfg"))
|
||||||
|
{
|
||||||
std::cout << desc;
|
std::cout << desc;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bpo::notify(vm);
|
bpo::notify(vm);
|
||||||
|
|
||||||
std::filesystem::path iniFile(vm["ini"].as<Files::MaybeQuotedPath>().u8string()); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
std::filesystem::path iniFile(
|
||||||
std::filesystem::path cfgFile(vm["cfg"].as<Files::MaybeQuotedPath>().u8string()); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
vm["ini"].as<Files::MaybeQuotedPath>().u8string()); // This call to u8string is redundant, but required to
|
||||||
|
// build on MSVC 14.26 due to implementation bugs.
|
||||||
|
std::filesystem::path cfgFile(
|
||||||
|
vm["cfg"].as<Files::MaybeQuotedPath>().u8string()); // This call to u8string is redundant, but required to
|
||||||
|
// build on MSVC 14.26 due to implementation bugs.
|
||||||
|
|
||||||
// if no output is given, write back to cfg file
|
// if no output is given, write back to cfg file
|
||||||
std::filesystem::path outputFile = vm["output"].as<Files::MaybeQuotedPath>().u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
std::filesystem::path outputFile = vm["output"]
|
||||||
if(vm["output"].defaulted()) {
|
.as<Files::MaybeQuotedPath>()
|
||||||
outputFile = vm["cfg"].as<Files::MaybeQuotedPath>().u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
.u8string(); // This call to u8string is redundant, but required to build
|
||||||
|
// on MSVC 14.26 due to implementation bugs.
|
||||||
|
if (vm["output"].defaulted())
|
||||||
|
{
|
||||||
|
outputFile = vm["cfg"]
|
||||||
|
.as<Files::MaybeQuotedPath>()
|
||||||
|
.u8string(); // This call to u8string is redundant, but required to build on MSVC 14.26 due
|
||||||
|
// to implementation bugs.
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!std::filesystem::exists(iniFile)) {
|
if (!std::filesystem::exists(iniFile))
|
||||||
|
{
|
||||||
std::cerr << "ini file does not exist" << std::endl;
|
std::cerr << "ini file does not exist" << std::endl;
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
@ -129,11 +142,13 @@ int wmain(int argc, wchar_t *wargv[]) {
|
||||||
importer.merge(cfg, ini);
|
importer.merge(cfg, ini);
|
||||||
importer.mergeFallback(cfg, ini);
|
importer.mergeFallback(cfg, ini);
|
||||||
|
|
||||||
if(vm.count("game-files")) {
|
if (vm.count("game-files"))
|
||||||
|
{
|
||||||
importer.importGameFiles(cfg, ini, iniFile);
|
importer.importGameFiles(cfg, ini, iniFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!vm.count("no-archives")) {
|
if (!vm.count("no-archives"))
|
||||||
|
{
|
||||||
importer.importArchives(cfg, ini);
|
importer.importArchives(cfg, ini);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
#include "worldspacedata.hpp"
|
|
||||||
#include "navmesh.hpp"
|
#include "navmesh.hpp"
|
||||||
|
#include "worldspacedata.hpp"
|
||||||
|
|
||||||
#include <components/debug/debugging.hpp>
|
#include <components/debug/debugging.hpp>
|
||||||
|
#include <components/detournavigator/agentbounds.hpp>
|
||||||
#include <components/detournavigator/navmeshdb.hpp>
|
#include <components/detournavigator/navmeshdb.hpp>
|
||||||
#include <components/detournavigator/recastglobalallocator.hpp>
|
#include <components/detournavigator/recastglobalallocator.hpp>
|
||||||
#include <components/detournavigator/settings.hpp>
|
#include <components/detournavigator/settings.hpp>
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
|
#include <components/esm3/readerscache.hpp>
|
||||||
#include <components/esm3/variant.hpp>
|
#include <components/esm3/variant.hpp>
|
||||||
#include <components/esmloader/esmdata.hpp>
|
#include <components/esmloader/esmdata.hpp>
|
||||||
#include <components/esmloader/load.hpp>
|
#include <components/esmloader/load.hpp>
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
#include <components/fallback/validate.hpp>
|
#include <components/fallback/validate.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
#include <components/files/conversion.hpp>
|
||||||
|
#include <components/platform/platform.hpp>
|
||||||
#include <components/resource/bulletshapemanager.hpp>
|
#include <components/resource/bulletshapemanager.hpp>
|
||||||
#include <components/resource/imagemanager.hpp>
|
#include <components/resource/imagemanager.hpp>
|
||||||
#include <components/resource/niffilemanager.hpp>
|
#include <components/resource/niffilemanager.hpp>
|
||||||
|
@ -21,10 +25,6 @@
|
||||||
#include <components/version/version.hpp>
|
#include <components/version/version.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
#include <components/vfs/registerarchives.hpp>
|
#include <components/vfs/registerarchives.hpp>
|
||||||
#include <components/esm3/readerscache.hpp>
|
|
||||||
#include <components/platform/platform.hpp>
|
|
||||||
#include <components/detournavigator/agentbounds.hpp>
|
|
||||||
#include <components/files/conversion.hpp>
|
|
||||||
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace NavMeshTool
|
namespace NavMeshTool
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
|
@ -59,45 +58,63 @@ namespace NavMeshTool
|
||||||
|
|
||||||
addOption("version", "print version information and quit");
|
addOption("version", "print version information and quit");
|
||||||
|
|
||||||
addOption("data", bpo::value<Files::MaybeQuotedPathContainer>()->default_value(Files::MaybeQuotedPathContainer(), "data")
|
addOption("data",
|
||||||
->multitoken()->composing(), "set data directories (later directories have higher priority)");
|
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(), ""),
|
addOption("data-local",
|
||||||
|
bpo::value<Files::MaybeQuotedPathContainer::value_type>()->default_value(
|
||||||
|
Files::MaybeQuotedPathContainer::value_type(), ""),
|
||||||
"set local data directory (highest priority)");
|
"set local data directory (highest priority)");
|
||||||
|
|
||||||
addOption("fallback-archive", bpo::value<StringsVector>()->default_value(StringsVector(), "fallback-archive")
|
addOption("fallback-archive",
|
||||||
->multitoken()->composing(), "set fallback BSA archives (later archives have higher priority)");
|
bpo::value<StringsVector>()
|
||||||
|
->default_value(StringsVector(), "fallback-archive")
|
||||||
|
->multitoken()
|
||||||
|
->composing(),
|
||||||
|
"set fallback BSA archives (later archives have higher priority)");
|
||||||
|
|
||||||
addOption("resources", bpo::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), "resources"),
|
addOption("resources",
|
||||||
|
bpo::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), "resources"),
|
||||||
"set resources directory");
|
"set resources directory");
|
||||||
|
|
||||||
addOption("content", bpo::value<StringsVector>()->default_value(StringsVector(), "")
|
addOption("content",
|
||||||
->multitoken()->composing(), "content file(s): esm/esp, or omwgame/omwaddon/omwscripts");
|
bpo::value<StringsVector>()->default_value(StringsVector(), "")->multitoken()->composing(),
|
||||||
|
"content file(s): esm/esp, or omwgame/omwaddon/omwscripts");
|
||||||
|
|
||||||
addOption("fs-strict", bpo::value<bool>()->implicit_value(true)
|
addOption("fs-strict", bpo::value<bool>()->implicit_value(true)->default_value(false),
|
||||||
->default_value(false), "strict file system handling (no case folding)");
|
"strict file system handling (no case folding)");
|
||||||
|
|
||||||
addOption("encoding", bpo::value<std::string>()->
|
addOption("encoding", bpo::value<std::string>()->default_value("win1252"),
|
||||||
default_value("win1252"),
|
|
||||||
"Character encoding used in OpenMW game messages:\n"
|
"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\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\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n"
|
||||||
"\n\twin1252 - Western European (Latin) alphabet, used by default");
|
"\n\twin1252 - Western European (Latin) alphabet, used by default");
|
||||||
|
|
||||||
addOption("fallback", bpo::value<Fallback::FallbackMap>()->default_value(Fallback::FallbackMap(), "")
|
addOption("fallback",
|
||||||
->multitoken()->composing(), "fallback values");
|
bpo::value<Fallback::FallbackMap>()
|
||||||
|
->default_value(Fallback::FallbackMap(), "")
|
||||||
|
->multitoken()
|
||||||
|
->composing(),
|
||||||
|
"fallback values");
|
||||||
|
|
||||||
addOption("threads", bpo::value<std::size_t>()->default_value(std::max<std::size_t>(std::thread::hardware_concurrency() - 1, 1)),
|
addOption("threads",
|
||||||
|
bpo::value<std::size_t>()->default_value(
|
||||||
|
std::max<std::size_t>(std::thread::hardware_concurrency() - 1, 1)),
|
||||||
"number of threads for parallel processing");
|
"number of threads for parallel processing");
|
||||||
|
|
||||||
addOption("process-interior-cells", bpo::value<bool>()->implicit_value(true)
|
addOption("process-interior-cells", bpo::value<bool>()->implicit_value(true)->default_value(false),
|
||||||
->default_value(false), "build navmesh for interior cells");
|
"build navmesh for interior cells");
|
||||||
|
|
||||||
addOption("remove-unused-tiles", bpo::value<bool>()->implicit_value(true)
|
addOption("remove-unused-tiles", bpo::value<bool>()->implicit_value(true)->default_value(false),
|
||||||
->default_value(false), "remove tiles from cache that will not be used with current content profile");
|
"remove tiles from cache that will not be used with current content profile");
|
||||||
|
|
||||||
addOption("write-binary-log", bpo::value<bool>()->implicit_value(true)
|
addOption("write-binary-log", bpo::value<bool>()->implicit_value(true)->default_value(false),
|
||||||
->default_value(false), "write progress in binary messages to be consumed by the launcher");
|
"write progress in binary messages to be consumed by the launcher");
|
||||||
|
|
||||||
Files::ConfigurationManager::addCommonOptions(result);
|
Files::ConfigurationManager::addCommonOptions(result);
|
||||||
|
|
||||||
|
@ -110,8 +127,7 @@ namespace NavMeshTool
|
||||||
|
|
||||||
bpo::options_description desc = makeOptionsDescription();
|
bpo::options_description desc = makeOptionsDescription();
|
||||||
|
|
||||||
bpo::parsed_options options = bpo::command_line_parser(argc, argv)
|
bpo::parsed_options options = bpo::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
|
||||||
.options(desc).allow_unregistered().run();
|
|
||||||
bpo::variables_map variables;
|
bpo::variables_map variables;
|
||||||
|
|
||||||
bpo::store(options, variables);
|
bpo::store(options, variables);
|
||||||
|
@ -175,10 +191,13 @@ namespace NavMeshTool
|
||||||
Settings::Manager settings;
|
Settings::Manager settings;
|
||||||
settings.load(config);
|
settings.load(config);
|
||||||
|
|
||||||
const auto agentCollisionShape = DetourNavigator::toCollisionShapeType(Settings::Manager::getInt("actor collision shape type", "Game"));
|
const auto agentCollisionShape = DetourNavigator::toCollisionShapeType(
|
||||||
const osg::Vec3f agentHalfExtents = Settings::Manager::getVector3("default actor pathfind half extents", "Game");
|
Settings::Manager::getInt("actor collision shape type", "Game"));
|
||||||
|
const osg::Vec3f agentHalfExtents
|
||||||
|
= Settings::Manager::getVector3("default actor pathfind half extents", "Game");
|
||||||
const DetourNavigator::AgentBounds agentBounds{ agentCollisionShape, agentHalfExtents };
|
const DetourNavigator::AgentBounds agentBounds{ agentCollisionShape, agentHalfExtents };
|
||||||
const std::uint64_t maxDbFileSize = static_cast<std::uint64_t>(Settings::Manager::getInt64("max navmeshdb file size", "Navigator"));
|
const std::uint64_t maxDbFileSize
|
||||||
|
= static_cast<std::uint64_t>(Settings::Manager::getInt64("max navmeshdb file size", "Navigator"));
|
||||||
const auto dbPath = Files::pathToUnicodeString(config.getUserDataPath() / "navmesh.db");
|
const auto dbPath = Files::pathToUnicodeString(config.getUserDataPath() / "navmesh.db");
|
||||||
|
|
||||||
DetourNavigator::NavMeshDb db(dbPath, maxDbFileSize);
|
DetourNavigator::NavMeshDb db(dbPath, maxDbFileSize);
|
||||||
|
@ -192,7 +211,8 @@ namespace NavMeshTool
|
||||||
query.mLoadGameSettings = true;
|
query.mLoadGameSettings = true;
|
||||||
query.mLoadLands = true;
|
query.mLoadLands = true;
|
||||||
query.mLoadStatics = true;
|
query.mLoadStatics = true;
|
||||||
const EsmLoader::EsmData esmData = EsmLoader::loadEsmData(query, contentFiles, fileCollections, readers, &encoder);
|
const EsmLoader::EsmData esmData
|
||||||
|
= EsmLoader::loadEsmData(query, contentFiles, fileCollections, readers, &encoder);
|
||||||
|
|
||||||
Resource::ImageManager imageManager(&vfs);
|
Resource::ImageManager imageManager(&vfs);
|
||||||
Resource::NifFileManager nifFileManager(&vfs);
|
Resource::NifFileManager nifFileManager(&vfs);
|
||||||
|
@ -200,10 +220,11 @@ namespace NavMeshTool
|
||||||
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager);
|
Resource::BulletShapeManager bulletShapeManager(&vfs, &sceneManager, &nifFileManager);
|
||||||
DetourNavigator::RecastGlobalAllocator::init();
|
DetourNavigator::RecastGlobalAllocator::init();
|
||||||
DetourNavigator::Settings navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager();
|
DetourNavigator::Settings navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager();
|
||||||
navigatorSettings.mRecast.mSwimHeightScale = EsmLoader::getGameSetting(esmData.mGameSettings, "fSwimHeightScale").getFloat();
|
navigatorSettings.mRecast.mSwimHeightScale
|
||||||
|
= EsmLoader::getGameSetting(esmData.mGameSettings, "fSwimHeightScale").getFloat();
|
||||||
|
|
||||||
WorldspaceData cellsData = gatherWorldspaceData(navigatorSettings, readers, vfs, bulletShapeManager,
|
WorldspaceData cellsData = gatherWorldspaceData(
|
||||||
esmData, processInteriorCells, writeBinaryLog);
|
navigatorSettings, readers, vfs, bulletShapeManager, esmData, processInteriorCells, writeBinaryLog);
|
||||||
|
|
||||||
const Status status = generateAllNavMeshTiles(agentBounds, navigatorSettings, threadsNumber,
|
const Status status = generateAllNavMeshTiles(agentBounds, navigatorSettings, threadsNumber,
|
||||||
removeUnusedTiles, writeBinaryLog, cellsData, std::move(db));
|
removeUnusedTiles, writeBinaryLog, cellsData, std::move(db));
|
||||||
|
@ -217,10 +238,12 @@ namespace NavMeshTool
|
||||||
Log(Debug::Warning) << "Cancelled";
|
Log(Debug::Warning) << "Cancelled";
|
||||||
break;
|
break;
|
||||||
case Status::NotEnoughSpace:
|
case Status::NotEnoughSpace:
|
||||||
Log(Debug::Warning) << "Navmesh generation is cancelled due to running out of disk space or limits "
|
Log(Debug::Warning)
|
||||||
|
<< "Navmesh generation is cancelled due to running out of disk space or limits "
|
||||||
<< "for navmesh db. Check disk space at the db location \"" << dbPath
|
<< "for navmesh db. Check disk space at the db location \"" << dbPath
|
||||||
<< "\". If there is enough space, adjust \"max navmeshdb file size\" setting (see "
|
<< "\". If there is enough space, adjust \"max navmeshdb file size\" setting (see "
|
||||||
<< "https://openmw.readthedocs.io/en/latest/reference/modding/settings/navigator.html?highlight=navmesh#max-navmeshdb-file-size).";
|
<< "https://openmw.readthedocs.io/en/latest/reference/modding/settings/"
|
||||||
|
"navigator.html?highlight=navmesh#max-navmeshdb-file-size).";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "worldspacedata.hpp"
|
#include "worldspacedata.hpp"
|
||||||
|
|
||||||
|
#include <components/debug/debugging.hpp>
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/detournavigator/generatenavmeshtile.hpp>
|
#include <components/detournavigator/generatenavmeshtile.hpp>
|
||||||
#include <components/detournavigator/gettilespositions.hpp>
|
#include <components/detournavigator/gettilespositions.hpp>
|
||||||
|
@ -14,20 +15,19 @@
|
||||||
#include <components/detournavigator/settings.hpp>
|
#include <components/detournavigator/settings.hpp>
|
||||||
#include <components/detournavigator/tileposition.hpp>
|
#include <components/detournavigator/tileposition.hpp>
|
||||||
#include <components/misc/progressreporter.hpp>
|
#include <components/misc/progressreporter.hpp>
|
||||||
|
#include <components/navmeshtool/protocol.hpp>
|
||||||
#include <components/sceneutil/workqueue.hpp>
|
#include <components/sceneutil/workqueue.hpp>
|
||||||
#include <components/sqlite3/transaction.hpp>
|
#include <components/sqlite3/transaction.hpp>
|
||||||
#include <components/debug/debugging.hpp>
|
|
||||||
#include <components/navmeshtool/protocol.hpp>
|
|
||||||
|
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace NavMeshTool
|
namespace NavMeshTool
|
||||||
{
|
{
|
||||||
|
@ -35,17 +35,17 @@ namespace NavMeshTool
|
||||||
{
|
{
|
||||||
using DetourNavigator::AgentBounds;
|
using DetourNavigator::AgentBounds;
|
||||||
using DetourNavigator::GenerateNavMeshTile;
|
using DetourNavigator::GenerateNavMeshTile;
|
||||||
|
using DetourNavigator::MeshSource;
|
||||||
using DetourNavigator::NavMeshDb;
|
using DetourNavigator::NavMeshDb;
|
||||||
using DetourNavigator::NavMeshTileInfo;
|
using DetourNavigator::NavMeshTileInfo;
|
||||||
using DetourNavigator::PreparedNavMeshData;
|
using DetourNavigator::PreparedNavMeshData;
|
||||||
using DetourNavigator::RecastMeshProvider;
|
using DetourNavigator::RecastMeshProvider;
|
||||||
using DetourNavigator::MeshSource;
|
|
||||||
using DetourNavigator::Settings;
|
using DetourNavigator::Settings;
|
||||||
using DetourNavigator::ShapeId;
|
using DetourNavigator::ShapeId;
|
||||||
using DetourNavigator::TileId;
|
using DetourNavigator::TileId;
|
||||||
using DetourNavigator::TilePosition;
|
using DetourNavigator::TilePosition;
|
||||||
using DetourNavigator::TileVersion;
|
|
||||||
using DetourNavigator::TilesPositionsRange;
|
using DetourNavigator::TilesPositionsRange;
|
||||||
|
using DetourNavigator::TileVersion;
|
||||||
using Sqlite3::Transaction;
|
using Sqlite3::Transaction;
|
||||||
|
|
||||||
void logGeneratedTiles(std::size_t provided, std::size_t expected)
|
void logGeneratedTiles(std::size_t provided, std::size_t expected)
|
||||||
|
@ -59,7 +59,8 @@ namespace NavMeshTool
|
||||||
void serializeToStderr(const T& value)
|
void serializeToStderr(const T& value)
|
||||||
{
|
{
|
||||||
const std::vector<std::byte> data = serialize(value);
|
const std::vector<std::byte> data = serialize(value);
|
||||||
getLockedRawStderr()->write(reinterpret_cast<const char*>(data.data()), static_cast<std::streamsize>(data.size()));
|
getLockedRawStderr()->write(
|
||||||
|
reinterpret_cast<const char*>(data.data()), static_cast<std::streamsize>(data.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void logGeneratedTilesMessage(std::size_t number)
|
void logGeneratedTilesMessage(std::size_t number)
|
||||||
|
@ -69,10 +70,7 @@ namespace NavMeshTool
|
||||||
|
|
||||||
struct LogGeneratedTiles
|
struct LogGeneratedTiles
|
||||||
{
|
{
|
||||||
void operator()(std::size_t provided, std::size_t expected) const
|
void operator()(std::size_t provided, std::size_t expected) const { logGeneratedTiles(provided, expected); }
|
||||||
{
|
|
||||||
logGeneratedTiles(provided, expected);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NavMeshTileConsumer final : public DetourNavigator::NavMeshTileConsumer
|
class NavMeshTileConsumer final : public DetourNavigator::NavMeshTileConsumer
|
||||||
|
@ -87,7 +85,8 @@ namespace NavMeshTool
|
||||||
, mTransaction(mDb.startTransaction(Sqlite3::TransactionMode::Immediate))
|
, mTransaction(mDb.startTransaction(Sqlite3::TransactionMode::Immediate))
|
||||||
, mNextTileId(mDb.getMaxTileId() + 1)
|
, mNextTileId(mDb.getMaxTileId() + 1)
|
||||||
, mNextShapeId(mDb.getMaxShapeId() + 1)
|
, mNextShapeId(mDb.getMaxShapeId() + 1)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t getProvided() const { return mProvided.load(); }
|
std::size_t getProvided() const { return mProvided.load(); }
|
||||||
|
|
||||||
|
@ -137,34 +136,37 @@ namespace NavMeshTool
|
||||||
if (mRemoveUnusedTiles)
|
if (mRemoveUnusedTiles)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mMutex);
|
std::lock_guard lock(mMutex);
|
||||||
mDeleted += static_cast<std::size_t>(mDb.deleteTilesAtExcept(worldspace, tilePosition, TileId {tileId}));
|
mDeleted += static_cast<std::size_t>(
|
||||||
|
mDb.deleteTilesAtExcept(worldspace, tilePosition, TileId{ tileId }));
|
||||||
}
|
}
|
||||||
report();
|
report();
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(std::string_view worldspace, const TilePosition& tilePosition,
|
void insert(std::string_view worldspace, const TilePosition& tilePosition, std::int64_t version,
|
||||||
std::int64_t version, const std::vector<std::byte>& input, PreparedNavMeshData& data) override
|
const std::vector<std::byte>& input, PreparedNavMeshData& data) override
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mMutex);
|
std::lock_guard lock(mMutex);
|
||||||
if (mRemoveUnusedTiles)
|
if (mRemoveUnusedTiles)
|
||||||
mDeleted += static_cast<std::size_t>(mDb.deleteTilesAt(worldspace, tilePosition));
|
mDeleted += static_cast<std::size_t>(mDb.deleteTilesAt(worldspace, tilePosition));
|
||||||
data.mUserId = static_cast<unsigned>(mNextTileId);
|
data.mUserId = static_cast<unsigned>(mNextTileId);
|
||||||
mDb.insertTile(mNextTileId, worldspace, tilePosition, TileVersion {version}, input, serialize(data));
|
mDb.insertTile(
|
||||||
|
mNextTileId, worldspace, tilePosition, TileVersion{ version }, input, serialize(data));
|
||||||
++mNextTileId;
|
++mNextTileId;
|
||||||
}
|
}
|
||||||
++mInserted;
|
++mInserted;
|
||||||
report();
|
report();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(std::string_view worldspace, const TilePosition& tilePosition,
|
void update(std::string_view worldspace, const TilePosition& tilePosition, std::int64_t tileId,
|
||||||
std::int64_t tileId, std::int64_t version, PreparedNavMeshData& data) override
|
std::int64_t version, PreparedNavMeshData& data) override
|
||||||
{
|
{
|
||||||
data.mUserId = static_cast<unsigned>(tileId);
|
data.mUserId = static_cast<unsigned>(tileId);
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mMutex);
|
std::lock_guard lock(mMutex);
|
||||||
if (mRemoveUnusedTiles)
|
if (mRemoveUnusedTiles)
|
||||||
mDeleted += static_cast<std::size_t>(mDb.deleteTilesAtExcept(worldspace, tilePosition, TileId {tileId}));
|
mDeleted += static_cast<std::size_t>(
|
||||||
|
mDb.deleteTilesAtExcept(worldspace, tilePosition, TileId{ tileId }));
|
||||||
mDb.updateTile(TileId{ tileId }, TileVersion{ version }, serialize(data));
|
mDb.updateTile(TileId{ tileId }, TileVersion{ version }, serialize(data));
|
||||||
}
|
}
|
||||||
++mUpdated;
|
++mUpdated;
|
||||||
|
@ -252,32 +254,29 @@ namespace NavMeshTool
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Status generateAllNavMeshTiles(const AgentBounds& agentBounds, const Settings& settings,
|
Status generateAllNavMeshTiles(const AgentBounds& agentBounds, const Settings& settings, std::size_t threadsNumber,
|
||||||
std::size_t threadsNumber, bool removeUnusedTiles, bool writeBinaryLog, WorldspaceData& data,
|
bool removeUnusedTiles, bool writeBinaryLog, WorldspaceData& data, NavMeshDb&& db)
|
||||||
NavMeshDb&& db)
|
|
||||||
{
|
{
|
||||||
Log(Debug::Info) << "Generating navmesh tiles by " << threadsNumber << " parallel workers...";
|
Log(Debug::Info) << "Generating navmesh tiles by " << threadsNumber << " parallel workers...";
|
||||||
|
|
||||||
SceneUtil::WorkQueue workQueue(threadsNumber);
|
SceneUtil::WorkQueue workQueue(threadsNumber);
|
||||||
auto navMeshTileConsumer = std::make_shared<NavMeshTileConsumer>(std::move(db), removeUnusedTiles, writeBinaryLog);
|
auto navMeshTileConsumer
|
||||||
|
= std::make_shared<NavMeshTileConsumer>(std::move(db), removeUnusedTiles, writeBinaryLog);
|
||||||
std::size_t tiles = 0;
|
std::size_t tiles = 0;
|
||||||
std::mt19937_64 random;
|
std::mt19937_64 random;
|
||||||
|
|
||||||
for (const std::unique_ptr<WorldspaceNavMeshInput>& input : data.mNavMeshInputs)
|
for (const std::unique_ptr<WorldspaceNavMeshInput>& input : data.mNavMeshInputs)
|
||||||
{
|
{
|
||||||
const auto range = DetourNavigator::makeTilesPositionsRange(
|
const auto range = DetourNavigator::makeTilesPositionsRange(Misc::Convert::toOsgXY(input->mAabb.m_min),
|
||||||
Misc::Convert::toOsgXY(input->mAabb.m_min),
|
Misc::Convert::toOsgXY(input->mAabb.m_max), settings.mRecast);
|
||||||
Misc::Convert::toOsgXY(input->mAabb.m_max),
|
|
||||||
settings.mRecast
|
|
||||||
);
|
|
||||||
|
|
||||||
if (removeUnusedTiles)
|
if (removeUnusedTiles)
|
||||||
navMeshTileConsumer->removeTilesOutsideRange(input->mWorldspace, range);
|
navMeshTileConsumer->removeTilesOutsideRange(input->mWorldspace, range);
|
||||||
|
|
||||||
std::vector<TilePosition> worldspaceTiles;
|
std::vector<TilePosition> worldspaceTiles;
|
||||||
|
|
||||||
DetourNavigator::getTilesPositions(range,
|
DetourNavigator::getTilesPositions(
|
||||||
[&] (const TilePosition& tilePosition) { worldspaceTiles.push_back(tilePosition); });
|
range, [&](const TilePosition& tilePosition) { worldspaceTiles.push_back(tilePosition); });
|
||||||
|
|
||||||
tiles += worldspaceTiles.size();
|
tiles += worldspaceTiles.size();
|
||||||
|
|
||||||
|
@ -289,14 +288,9 @@ namespace NavMeshTool
|
||||||
std::shuffle(worldspaceTiles.begin(), worldspaceTiles.end(), random);
|
std::shuffle(worldspaceTiles.begin(), worldspaceTiles.end(), random);
|
||||||
|
|
||||||
for (const TilePosition& tilePosition : worldspaceTiles)
|
for (const TilePosition& tilePosition : worldspaceTiles)
|
||||||
workQueue.addWorkItem(new GenerateNavMeshTile(
|
workQueue.addWorkItem(new GenerateNavMeshTile(input->mWorldspace, tilePosition,
|
||||||
input->mWorldspace,
|
RecastMeshProvider(input->mTileCachedRecastMeshManager), agentBounds, settings,
|
||||||
tilePosition,
|
navMeshTileConsumer));
|
||||||
RecastMeshProvider(input->mTileCachedRecastMeshManager),
|
|
||||||
agentBounds,
|
|
||||||
settings,
|
|
||||||
navMeshTileConsumer
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Status status = navMeshTileConsumer->wait();
|
const Status status = navMeshTileConsumer->wait();
|
||||||
|
@ -307,10 +301,8 @@ namespace NavMeshTool
|
||||||
const auto updated = navMeshTileConsumer->getUpdated();
|
const auto updated = navMeshTileConsumer->getUpdated();
|
||||||
const auto deleted = navMeshTileConsumer->getDeleted();
|
const auto deleted = navMeshTileConsumer->getDeleted();
|
||||||
|
|
||||||
Log(Debug::Info) << "Generated navmesh for " << navMeshTileConsumer->getProvided() << " tiles, "
|
Log(Debug::Info) << "Generated navmesh for " << navMeshTileConsumer->getProvided() << " tiles, " << inserted
|
||||||
<< inserted << " are inserted, "
|
<< " are inserted, " << updated << " updated and " << deleted << " deleted";
|
||||||
<< updated << " updated and "
|
|
||||||
<< deleted << " deleted";
|
|
||||||
|
|
||||||
if (inserted + updated + deleted > 0)
|
if (inserted + updated + deleted > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,9 +23,9 @@ namespace NavMeshTool
|
||||||
NotEnoughSpace,
|
NotEnoughSpace,
|
||||||
};
|
};
|
||||||
|
|
||||||
Status generateAllNavMeshTiles(const DetourNavigator::AgentBounds& agentBounds, const DetourNavigator::Settings& settings,
|
Status generateAllNavMeshTiles(const DetourNavigator::AgentBounds& agentBounds,
|
||||||
std::size_t threadsNumber, bool removeUnusedTiles, bool writeBinaryLog, WorldspaceData& cellsData,
|
const DetourNavigator::Settings& settings, std::size_t threadsNumber, bool removeUnusedTiles,
|
||||||
DetourNavigator::NavMeshDb&& db);
|
bool writeBinaryLog, WorldspaceData& cellsData, DetourNavigator::NavMeshDb&& db);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
#include "worldspacedata.hpp"
|
#include "worldspacedata.hpp"
|
||||||
|
|
||||||
#include <components/bullethelpers/aabb.hpp>
|
#include <components/bullethelpers/aabb.hpp>
|
||||||
|
#include <components/debug/debugging.hpp>
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/detournavigator/gettilespositions.hpp>
|
#include <components/detournavigator/gettilespositions.hpp>
|
||||||
#include <components/detournavigator/objectid.hpp>
|
#include <components/detournavigator/objectid.hpp>
|
||||||
#include <components/detournavigator/recastmesh.hpp>
|
#include <components/detournavigator/recastmesh.hpp>
|
||||||
#include <components/detournavigator/tilecachedrecastmeshmanager.hpp>
|
|
||||||
#include <components/detournavigator/settings.hpp>
|
#include <components/detournavigator/settings.hpp>
|
||||||
|
#include <components/detournavigator/tilecachedrecastmeshmanager.hpp>
|
||||||
#include <components/esm3/cellref.hpp>
|
#include <components/esm3/cellref.hpp>
|
||||||
#include <components/esm3/esmreader.hpp>
|
#include <components/esm3/esmreader.hpp>
|
||||||
#include <components/esm3/loadcell.hpp>
|
#include <components/esm3/loadcell.hpp>
|
||||||
#include <components/esm3/loadland.hpp>
|
#include <components/esm3/loadland.hpp>
|
||||||
|
#include <components/esm3/readerscache.hpp>
|
||||||
#include <components/esmloader/esmdata.hpp>
|
#include <components/esmloader/esmdata.hpp>
|
||||||
#include <components/esmloader/lessbyid.hpp>
|
#include <components/esmloader/lessbyid.hpp>
|
||||||
#include <components/esmloader/record.hpp>
|
#include <components/esmloader/record.hpp>
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
#include <components/misc/strings/lower.hpp>
|
#include <components/misc/strings/lower.hpp>
|
||||||
|
#include <components/navmeshtool/protocol.hpp>
|
||||||
#include <components/resource/bulletshapemanager.hpp>
|
#include <components/resource/bulletshapemanager.hpp>
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
#include <components/vfs/manager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
#include <components/debug/debugging.hpp>
|
|
||||||
#include <components/navmeshtool/protocol.hpp>
|
|
||||||
#include <components/esm3/readerscache.hpp>
|
|
||||||
|
|
||||||
#include <LinearMath/btVector3.h>
|
#include <LinearMath/btVector3.h>
|
||||||
|
|
||||||
|
@ -56,21 +56,28 @@ namespace NavMeshTool
|
||||||
float mScale;
|
float mScale;
|
||||||
ESM::Position mPos;
|
ESM::Position mPos;
|
||||||
|
|
||||||
CellRef(ESM::RecNameInts type, ESM::RefNum refNum, std::string&& refId, float scale, const ESM::Position& pos)
|
CellRef(
|
||||||
: mType(type), mRefNum(refNum), mRefId(std::move(refId)), mScale(scale), mPos(pos) {}
|
ESM::RecNameInts type, ESM::RefNum refNum, std::string&& refId, float scale, const ESM::Position& pos)
|
||||||
|
: mType(type)
|
||||||
|
, mRefNum(refNum)
|
||||||
|
, mRefId(std::move(refId))
|
||||||
|
, mScale(scale)
|
||||||
|
, mPos(pos)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ESM::RecNameInts getType(const EsmLoader::EsmData& esmData, std::string_view refId)
|
ESM::RecNameInts getType(const EsmLoader::EsmData& esmData, std::string_view refId)
|
||||||
{
|
{
|
||||||
const auto it = std::lower_bound(esmData.mRefIdTypes.begin(), esmData.mRefIdTypes.end(),
|
const auto it = std::lower_bound(
|
||||||
refId, EsmLoader::LessById {});
|
esmData.mRefIdTypes.begin(), esmData.mRefIdTypes.end(), refId, EsmLoader::LessById{});
|
||||||
if (it == esmData.mRefIdTypes.end() || it->mId != refId)
|
if (it == esmData.mRefIdTypes.end() || it->mId != refId)
|
||||||
return {};
|
return {};
|
||||||
return it->mType;
|
return it->mType;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CellRef> loadCellRefs(const ESM::Cell& cell, const EsmLoader::EsmData& esmData,
|
std::vector<CellRef> loadCellRefs(
|
||||||
ESM::ReadersCache& readers)
|
const ESM::Cell& cell, const EsmLoader::EsmData& esmData, ESM::ReadersCache& readers)
|
||||||
{
|
{
|
||||||
std::vector<EsmLoader::Record<CellRef>> cellRefs;
|
std::vector<EsmLoader::Record<CellRef>> cellRefs;
|
||||||
|
|
||||||
|
@ -86,14 +93,15 @@ namespace NavMeshTool
|
||||||
const ESM::RecNameInts type = getType(esmData, cellRef.mRefID);
|
const ESM::RecNameInts type = getType(esmData, cellRef.mRefID);
|
||||||
if (type == ESM::RecNameInts{})
|
if (type == ESM::RecNameInts{})
|
||||||
continue;
|
continue;
|
||||||
cellRefs.emplace_back(deleted, type, cellRef.mRefNum, std::move(cellRef.mRefID),
|
cellRefs.emplace_back(
|
||||||
cellRef.mScale, cellRef.mPos);
|
deleted, type, cellRef.mRefNum, std::move(cellRef.mRefID), cellRef.mScale, cellRef.mPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Debug::Debug) << "Loaded " << cellRefs.size() << " cell refs";
|
Log(Debug::Debug) << "Loaded " << cellRefs.size() << " cell refs";
|
||||||
|
|
||||||
const auto getKey = [] (const EsmLoader::Record<CellRef>& v) -> const ESM::RefNum& { return v.mValue.mRefNum; };
|
const auto getKey
|
||||||
|
= [](const EsmLoader::Record<CellRef>& v) -> const ESM::RefNum& { return v.mValue.mRefNum; };
|
||||||
std::vector<CellRef> result = prepareRecords(cellRefs, getKey);
|
std::vector<CellRef> result = prepareRecords(cellRefs, getKey);
|
||||||
|
|
||||||
Log(Debug::Debug) << "Prepared " << result.size() << " unique cell refs";
|
Log(Debug::Debug) << "Prepared " << result.size() << " unique cell refs";
|
||||||
|
@ -103,8 +111,7 @@ namespace NavMeshTool
|
||||||
|
|
||||||
template <class F>
|
template <class F>
|
||||||
void forEachObject(const ESM::Cell& cell, const EsmLoader::EsmData& esmData, const VFS::Manager& vfs,
|
void forEachObject(const ESM::Cell& cell, const EsmLoader::EsmData& esmData, const VFS::Manager& vfs,
|
||||||
Resource::BulletShapeManager& bulletShapeManager, ESM::ReadersCache& readers,
|
Resource::BulletShapeManager& bulletShapeManager, ESM::ReadersCache& readers, F&& f)
|
||||||
F&& f)
|
|
||||||
{
|
{
|
||||||
std::vector<CellRef> cellRefs = loadCellRefs(cell, esmData, readers);
|
std::vector<CellRef> cellRefs = loadCellRefs(cell, esmData, readers);
|
||||||
|
|
||||||
|
@ -119,15 +126,15 @@ namespace NavMeshTool
|
||||||
if (cellRef.mType != ESM::REC_STAT)
|
if (cellRef.mType != ESM::REC_STAT)
|
||||||
model = Misc::ResourceHelpers::correctActorModelPath(model, &vfs);
|
model = Misc::ResourceHelpers::correctActorModelPath(model, &vfs);
|
||||||
|
|
||||||
osg::ref_ptr<const Resource::BulletShape> shape = [&]
|
osg::ref_ptr<const Resource::BulletShape> shape = [&] {
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return bulletShapeManager.getShape(Misc::ResourceHelpers::correctMeshPath(model, &vfs));
|
return bulletShapeManager.getShape(Misc::ResourceHelpers::correctMeshPath(model, &vfs));
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
Log(Debug::Warning) << "Failed to load cell ref \"" << cellRef.mRefId << "\" model \"" << model << "\": " << e.what();
|
Log(Debug::Warning) << "Failed to load cell ref \"" << cellRef.mRefId << "\" model \"" << model
|
||||||
|
<< "\": " << e.what();
|
||||||
return osg::ref_ptr<const Resource::BulletShape>();
|
return osg::ref_ptr<const Resource::BulletShape>();
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
@ -135,7 +142,8 @@ namespace NavMeshTool
|
||||||
if (shape == nullptr || shape->mCollisionShape == nullptr)
|
if (shape == nullptr || shape->mCollisionShape == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance(new Resource::BulletShapeInstance(std::move(shape)));
|
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance(
|
||||||
|
new Resource::BulletShapeInstance(std::move(shape)));
|
||||||
|
|
||||||
switch (cellRef.mType)
|
switch (cellRef.mType)
|
||||||
{
|
{
|
||||||
|
@ -158,35 +166,20 @@ namespace NavMeshTool
|
||||||
|
|
||||||
struct LessByXY
|
struct LessByXY
|
||||||
{
|
{
|
||||||
bool operator ()(const ESM::Land& lhs, const ESM::Land& rhs) const
|
bool operator()(const ESM::Land& lhs, const ESM::Land& rhs) const { return GetXY{}(lhs) < GetXY{}(rhs); }
|
||||||
{
|
|
||||||
return GetXY {}(lhs) < GetXY {}(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator ()(const ESM::Land& lhs, const osg::Vec2i& rhs) const
|
bool operator()(const ESM::Land& lhs, const osg::Vec2i& rhs) const { return GetXY{}(lhs) < rhs; }
|
||||||
{
|
|
||||||
return GetXY {}(lhs) < rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator ()(const osg::Vec2i& lhs, const ESM::Land& rhs) const
|
bool operator()(const osg::Vec2i& lhs, const ESM::Land& rhs) const { return lhs < GetXY{}(rhs); }
|
||||||
{
|
|
||||||
return lhs < GetXY {}(rhs);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
btAABB getAabb(const osg::Vec2i& cellPosition, btScalar minHeight, btScalar maxHeight)
|
btAABB getAabb(const osg::Vec2i& cellPosition, btScalar minHeight, btScalar maxHeight)
|
||||||
{
|
{
|
||||||
btAABB aabb;
|
btAABB aabb;
|
||||||
aabb.m_min = btVector3(
|
aabb.m_min = btVector3(static_cast<btScalar>(cellPosition.x() * ESM::Land::REAL_SIZE),
|
||||||
static_cast<btScalar>(cellPosition.x() * ESM::Land::REAL_SIZE),
|
static_cast<btScalar>(cellPosition.y() * ESM::Land::REAL_SIZE), minHeight);
|
||||||
static_cast<btScalar>(cellPosition.y() * ESM::Land::REAL_SIZE),
|
aabb.m_max = btVector3(static_cast<btScalar>((cellPosition.x() + 1) * ESM::Land::REAL_SIZE),
|
||||||
minHeight
|
static_cast<btScalar>((cellPosition.y() + 1) * ESM::Land::REAL_SIZE), maxHeight);
|
||||||
);
|
|
||||||
aabb.m_max = btVector3(
|
|
||||||
static_cast<btScalar>((cellPosition.x() + 1) * ESM::Land::REAL_SIZE),
|
|
||||||
static_cast<btScalar>((cellPosition.y() + 1) * ESM::Land::REAL_SIZE),
|
|
||||||
maxHeight
|
|
||||||
);
|
|
||||||
return aabb;
|
return aabb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +199,8 @@ namespace NavMeshTool
|
||||||
{
|
{
|
||||||
if (!land.has_value() || osg::Vec2i(land->mX, land->mY) != cellPosition
|
if (!land.has_value() || osg::Vec2i(land->mX, land->mY) != cellPosition
|
||||||
|| (land->mDataTypes & ESM::Land::DATA_VHGT) == 0)
|
|| (land->mDataTypes & ESM::Land::DATA_VHGT) == 0)
|
||||||
return {HeightfieldPlane {ESM::Land::DEFAULT_HEIGHT}, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT};
|
return { HeightfieldPlane{ ESM::Land::DEFAULT_HEIGHT }, ESM::Land::DEFAULT_HEIGHT,
|
||||||
|
ESM::Land::DEFAULT_HEIGHT };
|
||||||
|
|
||||||
ESM::Land::LandData& landData = *landDatas.emplace_back(std::make_unique<ESM::Land::LandData>());
|
ESM::Land::LandData& landData = *landDatas.emplace_back(std::make_unique<ESM::Land::LandData>());
|
||||||
land->loadData(ESM::Land::DATA_VHGT, &landData);
|
land->loadData(ESM::Land::DATA_VHGT, &landData);
|
||||||
|
@ -227,7 +221,8 @@ namespace NavMeshTool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldspaceNavMeshInput::WorldspaceNavMeshInput(std::string worldspace, const DetourNavigator::RecastSettings& settings)
|
WorldspaceNavMeshInput::WorldspaceNavMeshInput(
|
||||||
|
std::string worldspace, const DetourNavigator::RecastSettings& settings)
|
||||||
: mWorldspace(std::move(worldspace))
|
: mWorldspace(std::move(worldspace))
|
||||||
, mTileCachedRecastMeshManager(settings)
|
, mTileCachedRecastMeshManager(settings)
|
||||||
{
|
{
|
||||||
|
@ -259,23 +254,25 @@ namespace NavMeshTool
|
||||||
if (writeBinaryLog)
|
if (writeBinaryLog)
|
||||||
serializeToStderr(ProcessedCells{ static_cast<std::uint64_t>(i + 1) });
|
serializeToStderr(ProcessedCells{ static_cast<std::uint64_t>(i + 1) });
|
||||||
Log(Debug::Info) << "Skipped interior"
|
Log(Debug::Info) << "Skipped interior"
|
||||||
<< " cell (" << (i + 1) << "/" << esmData.mCells.size() << ") \"" << cell.getDescription() << "\"";
|
<< " cell (" << (i + 1) << "/" << esmData.mCells.size() << ") \""
|
||||||
|
<< cell.getDescription() << "\"";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(Debug::Debug) << "Processing " << (exterior ? "exterior" : "interior")
|
Log(Debug::Debug) << "Processing " << (exterior ? "exterior" : "interior") << " cell (" << (i + 1) << "/"
|
||||||
<< " cell (" << (i + 1) << "/" << esmData.mCells.size() << ") \"" << cell.getDescription() << "\"";
|
<< esmData.mCells.size() << ") \"" << cell.getDescription() << "\"";
|
||||||
|
|
||||||
const osg::Vec2i cellPosition(cell.mData.mX, cell.mData.mY);
|
const osg::Vec2i cellPosition(cell.mData.mX, cell.mData.mY);
|
||||||
const std::size_t cellObjectsBegin = data.mObjects.size();
|
const std::size_t cellObjectsBegin = data.mObjects.size();
|
||||||
|
|
||||||
WorldspaceNavMeshInput& navMeshInput = [&] () -> WorldspaceNavMeshInput&
|
WorldspaceNavMeshInput& navMeshInput = [&]() -> WorldspaceNavMeshInput& {
|
||||||
{
|
|
||||||
auto it = navMeshInputs.find(cell.mCellId.mWorldspace);
|
auto it = navMeshInputs.find(cell.mCellId.mWorldspace);
|
||||||
if (it == navMeshInputs.end())
|
if (it == navMeshInputs.end())
|
||||||
{
|
{
|
||||||
it = navMeshInputs.emplace(cell.mCellId.mWorldspace,
|
it = navMeshInputs
|
||||||
std::make_unique<WorldspaceNavMeshInput>(cell.mCellId.mWorldspace, settings.mRecast)).first;
|
.emplace(cell.mCellId.mWorldspace,
|
||||||
|
std::make_unique<WorldspaceNavMeshInput>(cell.mCellId.mWorldspace, settings.mRecast))
|
||||||
|
.first;
|
||||||
it->second->mTileCachedRecastMeshManager.setWorldspace(cell.mCellId.mWorldspace, nullptr);
|
it->second->mTileCachedRecastMeshManager.setWorldspace(cell.mCellId.mWorldspace, nullptr);
|
||||||
}
|
}
|
||||||
return *it->second;
|
return *it->second;
|
||||||
|
@ -285,28 +282,28 @@ namespace NavMeshTool
|
||||||
|
|
||||||
if (exterior)
|
if (exterior)
|
||||||
{
|
{
|
||||||
const auto it = std::lower_bound(esmData.mLands.begin(), esmData.mLands.end(), cellPosition, LessByXY {});
|
const auto it
|
||||||
const auto [heightfieldShape, minHeight, maxHeight] = makeHeightfieldShape(
|
= std::lower_bound(esmData.mLands.begin(), esmData.mLands.end(), cellPosition, LessByXY{});
|
||||||
it == esmData.mLands.end() ? std::optional<ESM::Land>() : *it,
|
const auto [heightfieldShape, minHeight, maxHeight]
|
||||||
cellPosition, data.mHeightfields, data.mLandData
|
= makeHeightfieldShape(it == esmData.mLands.end() ? std::optional<ESM::Land>() : *it, cellPosition,
|
||||||
);
|
data.mHeightfields, data.mLandData);
|
||||||
|
|
||||||
mergeOrAssign(getAabb(cellPosition, minHeight, maxHeight),
|
mergeOrAssign(
|
||||||
navMeshInput.mAabb, navMeshInput.mAabbInitialized);
|
getAabb(cellPosition, minHeight, maxHeight), navMeshInput.mAabb, navMeshInput.mAabbInitialized);
|
||||||
|
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addHeightfield(cellPosition, ESM::Land::REAL_SIZE, heightfieldShape, &guard);
|
navMeshInput.mTileCachedRecastMeshManager.addHeightfield(
|
||||||
|
cellPosition, ESM::Land::REAL_SIZE, heightfieldShape, &guard);
|
||||||
|
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addWater(cellPosition, ESM::Land::REAL_SIZE, -1, &guard);
|
navMeshInput.mTileCachedRecastMeshManager.addWater(cellPosition, ESM::Land::REAL_SIZE, -1, &guard);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((cell.mData.mFlags & ESM::Cell::HasWater) != 0)
|
if ((cell.mData.mFlags & ESM::Cell::HasWater) != 0)
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addWater(cellPosition, std::numeric_limits<int>::max(), cell.mWater, &guard);
|
navMeshInput.mTileCachedRecastMeshManager.addWater(
|
||||||
|
cellPosition, std::numeric_limits<int>::max(), cell.mWater, &guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
forEachObject(cell, esmData, vfs, bulletShapeManager, readers,
|
forEachObject(cell, esmData, vfs, bulletShapeManager, readers, [&](BulletObject object) {
|
||||||
[&] (BulletObject object)
|
|
||||||
{
|
|
||||||
if (object.getShapeInstance()->mVisualCollisionType != Resource::VisualCollisionType::None)
|
if (object.getShapeInstance()->mVisualCollisionType != Resource::VisualCollisionType::None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -317,16 +314,17 @@ namespace NavMeshTool
|
||||||
navMeshInput.mAabb.merge(BulletHelpers::getAabb(*avoid, transform));
|
navMeshInput.mAabb.merge(BulletHelpers::getAabb(*avoid, transform));
|
||||||
|
|
||||||
const ObjectId objectId(++objectsCounter);
|
const ObjectId objectId(++objectsCounter);
|
||||||
const CollisionShape shape(object.getShapeInstance(), *object.getCollisionObject().getCollisionShape(), object.getObjectTransform());
|
const CollisionShape shape(object.getShapeInstance(), *object.getCollisionObject().getCollisionShape(),
|
||||||
|
object.getObjectTransform());
|
||||||
|
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addObject(objectId, shape, transform,
|
navMeshInput.mTileCachedRecastMeshManager.addObject(
|
||||||
DetourNavigator::AreaType_ground, &guard);
|
objectId, shape, transform, DetourNavigator::AreaType_ground, &guard);
|
||||||
|
|
||||||
if (const btCollisionShape* avoid = object.getShapeInstance()->mAvoidCollisionShape.get())
|
if (const btCollisionShape* avoid = object.getShapeInstance()->mAvoidCollisionShape.get())
|
||||||
{
|
{
|
||||||
const CollisionShape avoidShape(object.getShapeInstance(), *avoid, object.getObjectTransform());
|
const CollisionShape avoidShape(object.getShapeInstance(), *avoid, object.getObjectTransform());
|
||||||
navMeshInput.mTileCachedRecastMeshManager.addObject(objectId, avoidShape, transform,
|
navMeshInput.mTileCachedRecastMeshManager.addObject(
|
||||||
DetourNavigator::AreaType_null, &guard);
|
objectId, avoidShape, transform, DetourNavigator::AreaType_null, &guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.mObjects.emplace_back(std::move(object));
|
data.mObjects.emplace_back(std::move(object));
|
||||||
|
@ -337,17 +335,17 @@ namespace NavMeshTool
|
||||||
if (writeBinaryLog)
|
if (writeBinaryLog)
|
||||||
serializeToStderr(ProcessedCells{ static_cast<std::uint64_t>(i + 1) });
|
serializeToStderr(ProcessedCells{ static_cast<std::uint64_t>(i + 1) });
|
||||||
|
|
||||||
Log(Debug::Info) << "Processed " << (exterior ? "exterior" : "interior")
|
Log(Debug::Info) << "Processed " << (exterior ? "exterior" : "interior") << " cell (" << (i + 1) << "/"
|
||||||
<< " cell (" << (i + 1) << "/" << esmData.mCells.size() << ") " << cellDescription
|
<< esmData.mCells.size() << ") " << cellDescription << " with "
|
||||||
<< " with " << (data.mObjects.size() - cellObjectsBegin) << " objects";
|
<< (data.mObjects.size() - cellObjectsBegin) << " objects";
|
||||||
}
|
}
|
||||||
|
|
||||||
data.mNavMeshInputs.reserve(navMeshInputs.size());
|
data.mNavMeshInputs.reserve(navMeshInputs.size());
|
||||||
std::transform(navMeshInputs.begin(), navMeshInputs.end(), std::back_inserter(data.mNavMeshInputs),
|
std::transform(navMeshInputs.begin(), navMeshInputs.end(), std::back_inserter(data.mNavMeshInputs),
|
||||||
[](auto& v) { return std::move(v.second); });
|
[](auto& v) { return std::move(v.second); });
|
||||||
|
|
||||||
Log(Debug::Info) << "Processed " << esmData.mCells.size() << " cells, added "
|
Log(Debug::Info) << "Processed " << esmData.mCells.size() << " cells, added " << data.mObjects.size()
|
||||||
<< data.mObjects.size() << " objects and " << data.mHeightfields.size() << " height fields";
|
<< " objects and " << data.mHeightfields.size() << " height fields";
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
namespace NavMeshTool
|
namespace NavMeshTool
|
||||||
{
|
{
|
||||||
using DetourNavigator::TileCachedRecastMeshManager;
|
|
||||||
using DetourNavigator::ObjectTransform;
|
using DetourNavigator::ObjectTransform;
|
||||||
|
using DetourNavigator::TileCachedRecastMeshManager;
|
||||||
|
|
||||||
struct WorldspaceNavMeshInput
|
struct WorldspaceNavMeshInput
|
||||||
{
|
{
|
||||||
|
@ -63,11 +63,9 @@ namespace NavMeshTool
|
||||||
float localScaling)
|
float localScaling)
|
||||||
: mShapeInstance(std::move(shapeInstance))
|
: mShapeInstance(std::move(shapeInstance))
|
||||||
, mObjectTransform{ position, localScaling }
|
, mObjectTransform{ position, localScaling }
|
||||||
, mCollisionObject(BulletHelpers::makeCollisionObject(
|
, mCollisionObject(BulletHelpers::makeCollisionObject(mShapeInstance->mCollisionShape.get(),
|
||||||
mShapeInstance->mCollisionShape.get(),
|
|
||||||
Misc::Convert::toBullet(position.asVec3()),
|
Misc::Convert::toBullet(position.asVec3()),
|
||||||
Misc::Convert::toBullet(Misc::Convert::makeOsgQuat(position))
|
Misc::Convert::toBullet(Misc::Convert::makeOsgQuat(position))))
|
||||||
))
|
|
||||||
{
|
{
|
||||||
mShapeInstance->setLocalScaling(btVector3(localScaling, localScaling, localScaling));
|
mShapeInstance->setLocalScaling(btVector3(localScaling, localScaling, localScaling));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
/// Program to test .nif files both on the FileSystem and in BSA archives.
|
/// Program to test .nif files both on the FileSystem and in BSA archives.
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
#include <components/files/constrainedfilestream.hpp>
|
||||||
|
#include <components/files/conversion.hpp>
|
||||||
#include <components/misc/strings/algorithm.hpp>
|
#include <components/misc/strings/algorithm.hpp>
|
||||||
#include <components/nif/niffile.hpp>
|
#include <components/nif/niffile.hpp>
|
||||||
#include <components/files/constrainedfilestream.hpp>
|
|
||||||
#include <components/vfs/manager.hpp>
|
|
||||||
#include <components/vfs/bsaarchive.hpp>
|
#include <components/vfs/bsaarchive.hpp>
|
||||||
#include <components/vfs/filesystemarchive.hpp>
|
#include <components/vfs/filesystemarchive.hpp>
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/vfs/manager.hpp>
|
||||||
#include <components/files/conversion.hpp>
|
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
@ -45,7 +45,8 @@ void readVFS(std::unique_ptr<VFS::Archive>&& anArchive, const std::filesystem::p
|
||||||
|
|
||||||
for (const auto& name : myManager.getRecursiveDirectoryIterator(""))
|
for (const auto& name : myManager.getRecursiveDirectoryIterator(""))
|
||||||
{
|
{
|
||||||
try{
|
try
|
||||||
|
{
|
||||||
if (isNIF(name))
|
if (isNIF(name))
|
||||||
{
|
{
|
||||||
// std::cout << "Decoding: " << name << std::endl;
|
// std::cout << "Decoding: " << name << std::endl;
|
||||||
|
@ -88,8 +89,7 @@ Allowed options)");
|
||||||
bpo::variables_map variables;
|
bpo::variables_map variables;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).
|
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).options(desc).positional(p).run();
|
||||||
options(desc).positional(p).run();
|
|
||||||
bpo::store(valid_opts, variables);
|
bpo::store(valid_opts, variables);
|
||||||
bpo::notify(variables);
|
bpo::notify(variables);
|
||||||
if (variables.count("help"))
|
if (variables.count("help"))
|
||||||
|
@ -105,8 +105,7 @@ Allowed options)");
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n"
|
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n" << desc << std::endl;
|
||||||
<< desc << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +143,8 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "ERROR: \"" << Files::pathToUnicodeString(path) << "\" is not a nif file, bsa file, or directory!" << std::endl;
|
std::cerr << "ERROR: \"" << Files::pathToUnicodeString(path)
|
||||||
|
<< "\" is not a nif file, bsa file, or directory!" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
|
|
@ -26,9 +26,15 @@
|
||||||
using namespace Fallback;
|
using namespace Fallback;
|
||||||
|
|
||||||
CS::Editor::Editor(int argc, char** argv)
|
CS::Editor::Editor(int argc, char** argv)
|
||||||
: mConfigVariables(readConfiguration()), mSettingsState (mCfgMgr), mDocumentManager (mCfgMgr),
|
: mConfigVariables(readConfiguration())
|
||||||
mPid(""), mLock(), mMerge (mDocumentManager),
|
, mSettingsState(mCfgMgr)
|
||||||
mIpcServerName ("org.openmw.OpenCS"), mServer(nullptr), mClientSocket(nullptr)
|
, mDocumentManager(mCfgMgr)
|
||||||
|
, mPid("")
|
||||||
|
, mLock()
|
||||||
|
, mMerge(mDocumentManager)
|
||||||
|
, mIpcServerName("org.openmw.OpenCS")
|
||||||
|
, mServer(nullptr)
|
||||||
|
, mClientSocket(nullptr)
|
||||||
{
|
{
|
||||||
std::pair<Files::PathContainer, std::vector<std::string>> config = readConfig();
|
std::pair<Files::PathContainer, std::vector<std::string>> config = readConfig();
|
||||||
|
|
||||||
|
@ -47,12 +53,10 @@ CS::Editor::Editor (int argc, char **argv)
|
||||||
mFileDialog.setLocalData(mLocal);
|
mFileDialog.setLocalData(mLocal);
|
||||||
mMerge.setLocalData(mLocal);
|
mMerge.setLocalData(mLocal);
|
||||||
|
|
||||||
connect (&mDocumentManager, &CSMDoc::DocumentManager::documentAdded,
|
connect(&mDocumentManager, &CSMDoc::DocumentManager::documentAdded, this, &Editor::documentAdded);
|
||||||
this, &Editor::documentAdded);
|
connect(
|
||||||
connect (&mDocumentManager, &CSMDoc::DocumentManager::documentAboutToBeRemoved,
|
&mDocumentManager, &CSMDoc::DocumentManager::documentAboutToBeRemoved, this, &Editor::documentAboutToBeRemoved);
|
||||||
this, &Editor::documentAboutToBeRemoved);
|
connect(&mDocumentManager, &CSMDoc::DocumentManager::lastDocumentDeleted, this, &Editor::lastDocumentDeleted);
|
||||||
connect (&mDocumentManager, &CSMDoc::DocumentManager::lastDocumentDeleted,
|
|
||||||
this, &Editor::lastDocumentDeleted);
|
|
||||||
|
|
||||||
connect(mViewManager, &CSVDoc::ViewManager::newGameRequest, this, &Editor::createGame);
|
connect(mViewManager, &CSVDoc::ViewManager::newGameRequest, this, &Editor::createGame);
|
||||||
connect(mViewManager, &CSVDoc::ViewManager::newAddonRequest, this, &Editor::createAddon);
|
connect(mViewManager, &CSVDoc::ViewManager::newAddonRequest, this, &Editor::createAddon);
|
||||||
|
@ -65,8 +69,8 @@ CS::Editor::Editor (int argc, char **argv)
|
||||||
connect(&mStartup, &CSVDoc::StartupDialogue::loadDocument, this, &Editor::loadDocument);
|
connect(&mStartup, &CSVDoc::StartupDialogue::loadDocument, this, &Editor::loadDocument);
|
||||||
connect(&mStartup, &CSVDoc::StartupDialogue::editConfig, this, &Editor::showSettings);
|
connect(&mStartup, &CSVDoc::StartupDialogue::editConfig, this, &Editor::showSettings);
|
||||||
|
|
||||||
connect (&mFileDialog, &CSVDoc::FileDialog::signalOpenFiles,
|
connect(&mFileDialog, &CSVDoc::FileDialog::signalOpenFiles, this,
|
||||||
this, [this](const std::filesystem::path &savePath){ this->openFiles(savePath); });
|
[this](const std::filesystem::path& savePath) { this->openFiles(savePath); });
|
||||||
connect(&mFileDialog, &CSVDoc::FileDialog::signalCreateNewFile, this, &Editor::createNewFile);
|
connect(&mFileDialog, &CSVDoc::FileDialog::signalCreateNewFile, this, &Editor::createNewFile);
|
||||||
connect(&mFileDialog, &CSVDoc::FileDialog::rejected, this, &Editor::cancelFileDialog);
|
connect(&mFileDialog, &CSVDoc::FileDialog::rejected, this, &Editor::cancelFileDialog);
|
||||||
|
|
||||||
|
@ -90,19 +94,32 @@ boost::program_options::variables_map CS::Editor::readConfiguration()
|
||||||
boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options");
|
boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options");
|
||||||
|
|
||||||
auto addOption = desc.add_options();
|
auto addOption = desc.add_options();
|
||||||
addOption("data", boost::program_options::value<Files::MaybeQuotedPathContainer>()->default_value(Files::MaybeQuotedPathContainer(), "data")->multitoken()->composing());
|
addOption("data",
|
||||||
addOption("data-local", boost::program_options::value<Files::MaybeQuotedPathContainer::value_type>()->default_value(Files::MaybeQuotedPathContainer::value_type(), ""));
|
boost::program_options::value<Files::MaybeQuotedPathContainer>()
|
||||||
|
->default_value(Files::MaybeQuotedPathContainer(), "data")
|
||||||
|
->multitoken()
|
||||||
|
->composing());
|
||||||
|
addOption("data-local",
|
||||||
|
boost::program_options::value<Files::MaybeQuotedPathContainer::value_type>()->default_value(
|
||||||
|
Files::MaybeQuotedPathContainer::value_type(), ""));
|
||||||
addOption("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false));
|
addOption("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false));
|
||||||
addOption("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
|
addOption("encoding", boost::program_options::value<std::string>()->default_value("win1252"));
|
||||||
addOption("resources", boost::program_options::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), "resources"));
|
addOption("resources",
|
||||||
addOption("fallback-archive", boost::program_options::value<std::vector<std::string>>()->
|
boost::program_options::value<Files::MaybeQuotedPath>()->default_value(Files::MaybeQuotedPath(), "resources"));
|
||||||
default_value(std::vector<std::string>(), "fallback-archive")->multitoken());
|
addOption("fallback-archive",
|
||||||
addOption("fallback", boost::program_options::value<FallbackMap>()->default_value(FallbackMap(), "")
|
boost::program_options::value<std::vector<std::string>>()
|
||||||
->multitoken()->composing(), "fallback values");
|
->default_value(std::vector<std::string>(), "fallback-archive")
|
||||||
addOption("script-blacklist", boost::program_options::value<std::vector<std::string>>()->default_value(std::vector<std::string>(), "")
|
->multitoken());
|
||||||
->multitoken(), "exclude specified script from the verifier (if the use of the blacklist is enabled)");
|
addOption("fallback",
|
||||||
addOption("script-blacklist-use", boost::program_options::value<bool>()->implicit_value(true)
|
boost::program_options::value<FallbackMap>()->default_value(FallbackMap(), "")->multitoken()->composing(),
|
||||||
->default_value(true), "enable script blacklisting");
|
"fallback values");
|
||||||
|
addOption("script-blacklist",
|
||||||
|
boost::program_options::value<std::vector<std::string>>()
|
||||||
|
->default_value(std::vector<std::string>(), "")
|
||||||
|
->multitoken(),
|
||||||
|
"exclude specified script from the verifier (if the use of the blacklist is enabled)");
|
||||||
|
addOption("script-blacklist-use", boost::program_options::value<bool>()->implicit_value(true)->default_value(true),
|
||||||
|
"enable script blacklisting");
|
||||||
Files::ConfigurationManager::addCommonOptions(desc);
|
Files::ConfigurationManager::addCommonOptions(desc);
|
||||||
|
|
||||||
boost::program_options::notify(variables);
|
boost::program_options::notify(variables);
|
||||||
|
@ -124,20 +141,26 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
||||||
mDocumentManager.setEncoding(ToUTF8::calculateEncoding(mEncodingName));
|
mDocumentManager.setEncoding(ToUTF8::calculateEncoding(mEncodingName));
|
||||||
mFileDialog.setEncoding(QString::fromUtf8(mEncodingName.c_str()));
|
mFileDialog.setEncoding(QString::fromUtf8(mEncodingName.c_str()));
|
||||||
|
|
||||||
mDocumentManager.setResourceDir (mResources = variables["resources"].as<Files::MaybeQuotedPath>().u8string()); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
mDocumentManager.setResourceDir(mResources = variables["resources"]
|
||||||
|
.as<Files::MaybeQuotedPath>()
|
||||||
|
.u8string()); // This call to u8string is redundant, but required
|
||||||
|
// to build on MSVC 14.26 due to implementation bugs.
|
||||||
|
|
||||||
if (variables["script-blacklist-use"].as<bool>())
|
if (variables["script-blacklist-use"].as<bool>())
|
||||||
mDocumentManager.setBlacklistedScripts (
|
mDocumentManager.setBlacklistedScripts(variables["script-blacklist"].as<std::vector<std::string>>());
|
||||||
variables["script-blacklist"].as<std::vector<std::string>>());
|
|
||||||
|
|
||||||
mFsStrict = variables["fs-strict"].as<bool>();
|
mFsStrict = variables["fs-strict"].as<bool>();
|
||||||
|
|
||||||
Files::PathContainer dataDirs, dataLocal;
|
Files::PathContainer dataDirs, dataLocal;
|
||||||
if (!variables["data"].empty()) {
|
if (!variables["data"].empty())
|
||||||
|
{
|
||||||
dataDirs = asPathContainer(variables["data"].as<Files::MaybeQuotedPathContainer>());
|
dataDirs = asPathContainer(variables["data"].as<Files::MaybeQuotedPathContainer>());
|
||||||
}
|
}
|
||||||
|
|
||||||
Files::PathContainer::value_type local(variables["data-local"].as<Files::MaybeQuotedPathContainer::value_type>().u8string()); // This call to u8string is redundant, but required to build on MSVC 14.26 due to implementation bugs.
|
Files::PathContainer::value_type local(variables["data-local"]
|
||||||
|
.as<Files::MaybeQuotedPathContainer::value_type>()
|
||||||
|
.u8string()); // This call to u8string is redundant, but required to
|
||||||
|
// build on MSVC 14.26 due to implementation bugs.
|
||||||
if (!local.empty())
|
if (!local.empty())
|
||||||
{
|
{
|
||||||
std::filesystem::create_directories(local);
|
std::filesystem::create_directories(local);
|
||||||
|
@ -154,7 +177,9 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
||||||
messageBox.setWindowTitle(tr("No local data path available"));
|
messageBox.setWindowTitle(tr("No local data path available"));
|
||||||
messageBox.setIcon(QMessageBox::Critical);
|
messageBox.setIcon(QMessageBox::Critical);
|
||||||
messageBox.setStandardButtons(QMessageBox::Ok);
|
messageBox.setStandardButtons(QMessageBox::Ok);
|
||||||
messageBox.setText(tr("<br><b>OpenCS is unable to access the local data directory. This may indicate a faulty configuration or a broken install.</b>"));
|
messageBox.setText(
|
||||||
|
tr("<br><b>OpenCS is unable to access the local data directory. This may indicate a faulty configuration "
|
||||||
|
"or a broken install.</b>"));
|
||||||
messageBox.exec();
|
messageBox.exec();
|
||||||
|
|
||||||
QApplication::exit(1);
|
QApplication::exit(1);
|
||||||
|
@ -227,13 +252,15 @@ void CS::Editor::loadDocument()
|
||||||
mFileDialog.showDialog(CSVDoc::ContentAction_Edit);
|
mFileDialog.showDialog(CSVDoc::ContentAction_Edit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CS::Editor::openFiles (const std::filesystem::path &savePath, const std::vector<std::filesystem::path> &discoveredFiles)
|
void CS::Editor::openFiles(
|
||||||
|
const std::filesystem::path& savePath, const std::vector<std::filesystem::path>& discoveredFiles)
|
||||||
{
|
{
|
||||||
std::vector<std::filesystem::path> files;
|
std::vector<std::filesystem::path> files;
|
||||||
|
|
||||||
if (discoveredFiles.empty())
|
if (discoveredFiles.empty())
|
||||||
{
|
{
|
||||||
for (const QString &path : mFileDialog.selectedFilePaths()) {
|
for (const QString& path : mFileDialog.selectedFilePaths())
|
||||||
|
{
|
||||||
files.emplace_back(Files::pathFromQString(path));
|
files.emplace_back(Files::pathFromQString(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +278,8 @@ void CS::Editor::createNewFile (const std::filesystem::path &savePath)
|
||||||
{
|
{
|
||||||
std::vector<std::filesystem::path> files;
|
std::vector<std::filesystem::path> files;
|
||||||
|
|
||||||
for (const QString &path : mFileDialog.selectedFilePaths()) {
|
for (const QString& path : mFileDialog.selectedFilePaths())
|
||||||
|
{
|
||||||
files.emplace_back(Files::pathFromQString(path));
|
files.emplace_back(Files::pathFromQString(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
#include <boost/interprocess/sync/file_lock.hpp>
|
#include <boost/interprocess/sync/file_lock.hpp>
|
||||||
#include <boost/program_options/variables_map.hpp>
|
#include <boost/program_options/variables_map.hpp>
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QString>
|
|
||||||
#include <QLocalServer>
|
#include <QLocalServer>
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#ifndef Q_MOC_RUN
|
#ifndef Q_MOC_RUN
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
|
@ -21,10 +21,10 @@
|
||||||
|
|
||||||
#include "model/prefs/state.hpp"
|
#include "model/prefs/state.hpp"
|
||||||
|
|
||||||
#include "view/doc/viewmanager.hpp"
|
|
||||||
#include "view/doc/startup.hpp"
|
|
||||||
#include "view/doc/filedialog.hpp"
|
#include "view/doc/filedialog.hpp"
|
||||||
#include "view/doc/newgame.hpp"
|
#include "view/doc/newgame.hpp"
|
||||||
|
#include "view/doc/startup.hpp"
|
||||||
|
#include "view/doc/viewmanager.hpp"
|
||||||
|
|
||||||
#include "view/prefs/dialogue.hpp"
|
#include "view/prefs/dialogue.hpp"
|
||||||
|
|
||||||
|
@ -62,7 +62,8 @@ namespace CS
|
||||||
std::string mEncodingName;
|
std::string mEncodingName;
|
||||||
|
|
||||||
boost::program_options::variables_map readConfiguration();
|
boost::program_options::variables_map readConfiguration();
|
||||||
///< Calls mCfgMgr.readConfiguration; should be used before initialization of mSettingsState as it depends on the configuration.
|
///< Calls mCfgMgr.readConfiguration; should be used before initialization of mSettingsState as it depends on
|
||||||
|
///< the configuration.
|
||||||
std::pair<Files::PathContainer, std::vector<std::string>> readConfig(bool quiet = false);
|
std::pair<Files::PathContainer, std::vector<std::string>> readConfig(bool quiet = false);
|
||||||
///< \return data paths
|
///< \return data paths
|
||||||
|
|
||||||
|
@ -71,7 +72,6 @@ namespace CS
|
||||||
Editor& operator=(const Editor&);
|
Editor& operator=(const Editor&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Editor(int argc, char** argv);
|
Editor(int argc, char** argv);
|
||||||
~Editor();
|
~Editor();
|
||||||
|
|
||||||
|
@ -89,7 +89,8 @@ namespace CS
|
||||||
void cancelFileDialog();
|
void cancelFileDialog();
|
||||||
|
|
||||||
void loadDocument();
|
void loadDocument();
|
||||||
void openFiles (const std::filesystem::path &path, const std::vector<std::filesystem::path> &discoveredFiles = {});
|
void openFiles(
|
||||||
|
const std::filesystem::path& path, const std::vector<std::filesystem::path>& discoveredFiles = {});
|
||||||
void createNewFile(const std::filesystem::path& path);
|
void createNewFile(const std::filesystem::path& path);
|
||||||
void createNewGame(const std::filesystem::path& file);
|
void createNewGame(const std::filesystem::path& file);
|
||||||
|
|
||||||
|
@ -106,7 +107,6 @@ namespace CS
|
||||||
void mergeDocument(CSMDoc::Document* document);
|
void mergeDocument(CSMDoc::Document* document);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QString mIpcServerName;
|
QString mIpcServerName;
|
||||||
QLocalServer* mServer;
|
QLocalServer* mServer;
|
||||||
QLocalSocket* mClientSocket;
|
QLocalSocket* mClientSocket;
|
||||||
|
|
|
@ -21,7 +21,6 @@ Q_DECLARE_METATYPE (std::string)
|
||||||
class Application : public QApplication
|
class Application : public QApplication
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool notify(QObject* receiver, QEvent* event) override
|
bool notify(QObject* receiver, QEvent* event) override
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -37,8 +36,10 @@ class Application : public QApplication
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Application(int& argc, char* argv[])
|
||||||
Application (int& argc, char *argv[]) : QApplication (argc, argv) {}
|
: QApplication(argc, argv)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int runApplication(int argc, char* argv[])
|
int runApplication(int argc, char* argv[])
|
||||||
|
@ -78,7 +79,6 @@ int runApplication(int argc, char *argv[])
|
||||||
return editor.run();
|
return editor.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
return wrapApplication(&runApplication, argc, argv, "OpenMW-CS", false);
|
return wrapApplication(&runApplication, argc, argv, "OpenMW-CS", false);
|
||||||
|
|
|
@ -6,18 +6,15 @@
|
||||||
|
|
||||||
bool CSMDoc::Blacklist::isBlacklisted(const CSMWorld::UniversalId& id) const
|
bool CSMDoc::Blacklist::isBlacklisted(const CSMWorld::UniversalId& id) const
|
||||||
{
|
{
|
||||||
std::map<CSMWorld::UniversalId::Type, std::vector<std::string> >::const_iterator iter =
|
std::map<CSMWorld::UniversalId::Type, std::vector<std::string>>::const_iterator iter = mIds.find(id.getType());
|
||||||
mIds.find (id.getType());
|
|
||||||
|
|
||||||
if (iter == mIds.end())
|
if (iter == mIds.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return std::binary_search (iter->second.begin(), iter->second.end(),
|
return std::binary_search(iter->second.begin(), iter->second.end(), Misc::StringUtils::lowerCase(id.getId()));
|
||||||
Misc::StringUtils::lowerCase (id.getId()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type,
|
void CSMDoc::Blacklist::add(CSMWorld::UniversalId::Type type, const std::vector<std::string>& ids)
|
||||||
const std::vector<std::string>& ids)
|
|
||||||
{
|
{
|
||||||
std::vector<std::string>& list = mIds[type];
|
std::vector<std::string>& list = mIds[type];
|
||||||
|
|
||||||
|
@ -25,6 +22,7 @@ void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type,
|
||||||
|
|
||||||
list.resize(size + ids.size());
|
list.resize(size + ids.size());
|
||||||
|
|
||||||
std::transform (ids.begin(), ids.end(), list.begin()+size, [](const std::string& s) { return Misc::StringUtils::lowerCase(s); } );
|
std::transform(ids.begin(), ids.end(), list.begin() + size,
|
||||||
|
[](const std::string& s) { return Misc::StringUtils::lowerCase(s); });
|
||||||
std::sort(list.begin(), list.end());
|
std::sort(list.begin(), list.end());
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
#define CSM_DOC_BLACKLIST_H
|
#define CSM_DOC_BLACKLIST_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ namespace CSMDoc
|
||||||
std::map<CSMWorld::UniversalId::Type, std::vector<std::string>> mIds;
|
std::map<CSMWorld::UniversalId::Type, std::vector<std::string>> mIds;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool isBlacklisted(const CSMWorld::UniversalId& id) const;
|
bool isBlacklisted(const CSMWorld::UniversalId& id) const;
|
||||||
|
|
||||||
void add(CSMWorld::UniversalId::Type type, const std::vector<std::string>& ids);
|
void add(CSMWorld::UniversalId::Type type, const std::vector<std::string>& ids);
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
#include "state.hpp"
|
#include "state.hpp"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <memory>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "../world/defaultgmsts.hpp"
|
#include "../world/defaultgmsts.hpp"
|
||||||
|
@ -82,8 +82,7 @@ void CSMDoc::Document::addOptionalGmsts()
|
||||||
|
|
||||||
void CSMDoc::Document::addOptionalGlobals()
|
void CSMDoc::Document::addOptionalGlobals()
|
||||||
{
|
{
|
||||||
static const char *sGlobals[] =
|
static const char* sGlobals[] = {
|
||||||
{
|
|
||||||
"DaysPassed",
|
"DaysPassed",
|
||||||
"PCWerewolf",
|
"PCWerewolf",
|
||||||
"PCYear",
|
"PCYear",
|
||||||
|
@ -152,8 +151,7 @@ void CSMDoc::Document::addOptionalMagicEffect (const ESM::MagicEffect& magicEffe
|
||||||
|
|
||||||
void CSMDoc::Document::createBase()
|
void CSMDoc::Document::createBase()
|
||||||
{
|
{
|
||||||
static const char *sGlobals[] =
|
static const char* sGlobals[] = {
|
||||||
{
|
|
||||||
"Day",
|
"Day",
|
||||||
"DaysPassed",
|
"DaysPassed",
|
||||||
"GameHour",
|
"GameHour",
|
||||||
|
@ -190,8 +188,7 @@ void CSMDoc::Document::createBase()
|
||||||
getData().getSkills().add(record);
|
getData().getSkills().add(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *sVoice[] =
|
static const char* sVoice[] = {
|
||||||
{
|
|
||||||
"Intruder",
|
"Intruder",
|
||||||
"Attack",
|
"Attack",
|
||||||
"Hello",
|
"Hello",
|
||||||
|
@ -213,8 +210,7 @@ void CSMDoc::Document::createBase()
|
||||||
getData().getTopics().add(record);
|
getData().getTopics().add(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *sGreetings[] =
|
static const char* sGreetings[] = {
|
||||||
{
|
|
||||||
"Greeting 0",
|
"Greeting 0",
|
||||||
"Greeting 1",
|
"Greeting 1",
|
||||||
"Greeting 2",
|
"Greeting 2",
|
||||||
|
@ -238,8 +234,7 @@ void CSMDoc::Document::createBase()
|
||||||
getData().getTopics().add(record);
|
getData().getTopics().add(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *sPersuasion[] =
|
static const char* sPersuasion[] = {
|
||||||
{
|
|
||||||
"Intimidate Success",
|
"Intimidate Success",
|
||||||
"Intimidate Fail",
|
"Intimidate Fail",
|
||||||
"Service Refusal",
|
"Service Refusal",
|
||||||
|
@ -276,19 +271,22 @@ void CSMDoc::Document::createBase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
CSMDoc::Document::Document(const Files::ConfigurationManager& configuration, std::vector<std::filesystem::path> files,
|
||||||
std::vector< std::filesystem::path > files,bool new_,
|
bool new_, const std::filesystem::path& savePath, const std::filesystem::path& resDir, ToUTF8::FromType encoding,
|
||||||
const std::filesystem::path& savePath, const std::filesystem::path& resDir,
|
const std::vector<std::string>& blacklistedScripts, bool fsStrict, const Files::PathContainer& dataPaths,
|
||||||
ToUTF8::FromType encoding, const std::vector<std::string>& blacklistedScripts,
|
const std::vector<std::string>& archives)
|
||||||
bool fsStrict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives)
|
: mSavePath(savePath)
|
||||||
: mSavePath (savePath), mContentFiles (std::move(files)), mNew (new_), mData (encoding, fsStrict, dataPaths, archives, resDir),
|
, mContentFiles(std::move(files))
|
||||||
mTools (*this, encoding),
|
, mNew(new_)
|
||||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
, mData(encoding, fsStrict, dataPaths, archives, resDir)
|
||||||
(savePath.filename().u8string() + u8".project")),
|
, mTools(*this, encoding)
|
||||||
mSavingOperation (*this, mProjectPath, encoding),
|
, mProjectPath((configuration.getUserDataPath() / "projects") / (savePath.filename().u8string() + u8".project"))
|
||||||
mSaving (&mSavingOperation),
|
, mSavingOperation(*this, mProjectPath, encoding)
|
||||||
mResDir(resDir), mRunner (mProjectPath),
|
, mSaving(&mSavingOperation)
|
||||||
mDirty (false), mIdCompletionManager(mData)
|
, mResDir(resDir)
|
||||||
|
, mRunner(mProjectPath)
|
||||||
|
, mDirty(false)
|
||||||
|
, mIdCompletionManager(mData)
|
||||||
{
|
{
|
||||||
if (mContentFiles.empty())
|
if (mContentFiles.empty())
|
||||||
throw std::runtime_error("Empty content file sequence");
|
throw std::runtime_error("Empty content file sequence");
|
||||||
|
@ -332,8 +330,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
connect(&mTools, &CSMTools::Tools::done, this, &Document::operationDone2);
|
connect(&mTools, &CSMTools::Tools::done, this, &Document::operationDone2);
|
||||||
connect(&mTools, &CSMTools::Tools::mergeDone, this, &Document::mergeDone);
|
connect(&mTools, &CSMTools::Tools::mergeDone, this, &Document::mergeDone);
|
||||||
|
|
||||||
connect (&mSaving, &OperationHolder::progress,
|
connect(&mSaving, &OperationHolder::progress, this, qOverload<int, int, int>(&Document::progress));
|
||||||
this, qOverload<int, int, int>(&Document::progress));
|
|
||||||
connect(&mSaving, &OperationHolder::done, this, &Document::operationDone2);
|
connect(&mSaving, &OperationHolder::done, this, &Document::operationDone2);
|
||||||
|
|
||||||
connect(&mSaving, &OperationHolder::reportMessage, this, &Document::reportMessage);
|
connect(&mSaving, &OperationHolder::reportMessage, this, &Document::reportMessage);
|
||||||
|
@ -341,9 +338,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
connect(&mRunner, &Runner::runStateChanged, this, &Document::runStateChanged);
|
connect(&mRunner, &Runner::runStateChanged, this, &Document::runStateChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::~Document()
|
CSMDoc::Document::~Document() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QUndoStack& CSMDoc::Document::getUndoStack()
|
QUndoStack& CSMDoc::Document::getUndoStack()
|
||||||
{
|
{
|
||||||
|
@ -397,8 +392,7 @@ bool CSMDoc::Document::isNew() const
|
||||||
void CSMDoc::Document::save()
|
void CSMDoc::Document::save()
|
||||||
{
|
{
|
||||||
if (mSaving.isRunning())
|
if (mSaving.isRunning())
|
||||||
throw std::logic_error (
|
throw std::logic_error("Failed to initiate save, because a save operation is already running.");
|
||||||
"Failed to initiate save, because a save operation is already running.");
|
|
||||||
|
|
||||||
mSaving.start();
|
mSaving.start();
|
||||||
|
|
||||||
|
@ -412,7 +406,6 @@ CSMWorld::UniversalId CSMDoc::Document::verify (const CSMWorld::UniversalId& rep
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CSMWorld::UniversalId CSMDoc::Document::newSearch()
|
CSMWorld::UniversalId CSMDoc::Document::newSearch()
|
||||||
{
|
{
|
||||||
return mTools.newSearch();
|
return mTools.newSearch();
|
||||||
|
@ -472,23 +465,21 @@ CSMTools::ReportModel *CSMDoc::Document::getReport (const CSMWorld::UniversalId&
|
||||||
return mTools.getReport(id);
|
return mTools.getReport(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMDoc::Document::isBlacklisted (const CSMWorld::UniversalId& id)
|
bool CSMDoc::Document::isBlacklisted(const CSMWorld::UniversalId& id) const
|
||||||
const
|
|
||||||
{
|
{
|
||||||
return mBlacklist.isBlacklisted(id);
|
return mBlacklist.isBlacklisted(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::startRunning (const std::string& profile,
|
void CSMDoc::Document::startRunning(const std::string& profile, const std::string& startupInstruction)
|
||||||
const std::string& startupInstruction)
|
|
||||||
{
|
{
|
||||||
std::vector<std::filesystem::path> contentFiles;
|
std::vector<std::filesystem::path> contentFiles;
|
||||||
|
|
||||||
for (const auto & mContentFile : mContentFiles) {
|
for (const auto& mContentFile : mContentFiles)
|
||||||
|
{
|
||||||
contentFiles.emplace_back(mContentFile.filename());
|
contentFiles.emplace_back(mContentFile.filename());
|
||||||
}
|
}
|
||||||
|
|
||||||
mRunner.configure (getData().getDebugProfiles().getRecord (profile).get(), contentFiles,
|
mRunner.configure(getData().getDebugProfiles().getRecord(profile).get(), contentFiles, startupInstruction);
|
||||||
startupInstruction);
|
|
||||||
|
|
||||||
int state = getState();
|
int state = getState();
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <QUndoStack>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QUndoStack>
|
||||||
|
|
||||||
#include <components/files/multidircollection.hpp>
|
#include <components/files/multidircollection.hpp>
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
@ -14,10 +14,10 @@
|
||||||
|
|
||||||
#include "../tools/tools.hpp"
|
#include "../tools/tools.hpp"
|
||||||
|
|
||||||
#include "saving.hpp"
|
|
||||||
#include "blacklist.hpp"
|
#include "blacklist.hpp"
|
||||||
#include "runner.hpp"
|
|
||||||
#include "operationholder.hpp"
|
#include "operationholder.hpp"
|
||||||
|
#include "runner.hpp"
|
||||||
|
#include "saving.hpp"
|
||||||
|
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ namespace CSMDoc
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::filesystem::path mSavePath;
|
std::filesystem::path mSavePath;
|
||||||
std::vector<std::filesystem::path> mContentFiles;
|
std::vector<std::filesystem::path> mContentFiles;
|
||||||
bool mNew;
|
bool mNew;
|
||||||
|
@ -71,8 +70,9 @@ namespace CSMDoc
|
||||||
|
|
||||||
CSMWorld::IdCompletionManager mIdCompletionManager;
|
CSMWorld::IdCompletionManager mIdCompletionManager;
|
||||||
|
|
||||||
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
|
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is
|
||||||
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
|
// connected to a slot, that is using other member variables. Unfortunately this connection is cut only in the
|
||||||
|
// QObject destructor, which is way too late.
|
||||||
QUndoStack mUndoStack;
|
QUndoStack mUndoStack;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
|
@ -96,12 +96,10 @@ namespace CSMDoc
|
||||||
void addOptionalMagicEffect(const ESM::MagicEffect& effect);
|
void addOptionalMagicEffect(const ESM::MagicEffect& effect);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Document(const Files::ConfigurationManager& configuration, std::vector<std::filesystem::path> files, bool new_,
|
||||||
Document (const Files::ConfigurationManager& configuration,
|
const std::filesystem::path& savePath, const std::filesystem::path& resDir, ToUTF8::FromType encoding,
|
||||||
std::vector< std::filesystem::path > files, bool new_,
|
const std::vector<std::string>& blacklistedScripts, bool fsStrict, const Files::PathContainer& dataPaths,
|
||||||
const std::filesystem::path& savePath, const std::filesystem::path& resDir,
|
const std::vector<std::string>& archives);
|
||||||
ToUTF8::FromType encoding, const std::vector<std::string>& blacklistedScripts,
|
|
||||||
bool fsStrict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives);
|
|
||||||
|
|
||||||
~Document();
|
~Document();
|
||||||
|
|
||||||
|
@ -143,8 +141,7 @@ namespace CSMDoc
|
||||||
|
|
||||||
bool isBlacklisted(const CSMWorld::UniversalId& id) const;
|
bool isBlacklisted(const CSMWorld::UniversalId& id) const;
|
||||||
|
|
||||||
void startRunning (const std::string& profile,
|
void startRunning(const std::string& profile, const std::string& startupInstruction = "");
|
||||||
const std::string& startupInstruction = "");
|
|
||||||
|
|
||||||
void stopRunning();
|
void stopRunning();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::DocumentManager::DocumentManager(const Files::ConfigurationManager& configuration)
|
CSMDoc::DocumentManager::DocumentManager(const Files::ConfigurationManager& configuration)
|
||||||
: mConfiguration (configuration), mEncoding (ToUTF8::WINDOWS_1252), mFsStrict(false)
|
: mConfiguration(configuration)
|
||||||
|
, mEncoding(ToUTF8::WINDOWS_1252)
|
||||||
|
, mFsStrict(false)
|
||||||
{
|
{
|
||||||
std::filesystem::path projectPath = configuration.getUserDataPath() / "projects";
|
std::filesystem::path projectPath = configuration.getUserDataPath() / "projects";
|
||||||
|
|
||||||
|
@ -19,20 +21,13 @@ CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& con
|
||||||
mLoader.moveToThread(&mLoaderThread);
|
mLoader.moveToThread(&mLoaderThread);
|
||||||
mLoaderThread.start();
|
mLoaderThread.start();
|
||||||
|
|
||||||
connect (&mLoader, &Loader::documentLoaded,
|
connect(&mLoader, &Loader::documentLoaded, this, &DocumentManager::documentLoaded);
|
||||||
this, &DocumentManager::documentLoaded);
|
connect(&mLoader, &Loader::documentNotLoaded, this, &DocumentManager::documentNotLoaded);
|
||||||
connect (&mLoader, &Loader::documentNotLoaded,
|
connect(this, &DocumentManager::loadRequest, &mLoader, &Loader::loadDocument);
|
||||||
this, &DocumentManager::documentNotLoaded);
|
connect(&mLoader, &Loader::nextStage, this, &DocumentManager::nextStage);
|
||||||
connect (this, &DocumentManager::loadRequest,
|
connect(&mLoader, &Loader::nextRecord, this, &DocumentManager::nextRecord);
|
||||||
&mLoader, &Loader::loadDocument);
|
connect(this, &DocumentManager::cancelLoading, &mLoader, &Loader::abortLoading);
|
||||||
connect (&mLoader, &Loader::nextStage,
|
connect(&mLoader, &Loader::loadMessage, this, &DocumentManager::loadMessage);
|
||||||
this, &DocumentManager::nextStage);
|
|
||||||
connect (&mLoader, &Loader::nextRecord,
|
|
||||||
this, &DocumentManager::nextRecord);
|
|
||||||
connect (this, &DocumentManager::cancelLoading,
|
|
||||||
&mLoader, &Loader::abortLoading);
|
|
||||||
connect (&mLoader, &Loader::loadMessage,
|
|
||||||
this, &DocumentManager::loadMessage);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::DocumentManager::~DocumentManager()
|
CSMDoc::DocumentManager::~DocumentManager()
|
||||||
|
@ -51,26 +46,25 @@ bool CSMDoc::DocumentManager::isEmpty()
|
||||||
return mDocuments.empty();
|
return mDocuments.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::DocumentManager::addDocument (const std::vector<std::filesystem::path>& files, const std::filesystem::path& savePath,
|
void CSMDoc::DocumentManager::addDocument(
|
||||||
bool new_)
|
const std::vector<std::filesystem::path>& files, const std::filesystem::path& savePath, bool new_)
|
||||||
{
|
{
|
||||||
Document* document = makeDocument(files, savePath, new_);
|
Document* document = makeDocument(files, savePath, new_);
|
||||||
insertDocument(document);
|
insertDocument(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document* CSMDoc::DocumentManager::makeDocument(
|
CSMDoc::Document* CSMDoc::DocumentManager::makeDocument(
|
||||||
const std::vector< std::filesystem::path >& files,
|
const std::vector<std::filesystem::path>& files, const std::filesystem::path& savePath, bool new_)
|
||||||
const std::filesystem::path& savePath, bool new_)
|
|
||||||
{
|
{
|
||||||
return new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mBlacklistedScripts, mFsStrict, mDataPaths, mArchives);
|
return new Document(mConfiguration, files, new_, savePath, mResDir, mEncoding, mBlacklistedScripts, mFsStrict,
|
||||||
|
mDataPaths, mArchives);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::DocumentManager::insertDocument(CSMDoc::Document* document)
|
void CSMDoc::DocumentManager::insertDocument(CSMDoc::Document* document)
|
||||||
{
|
{
|
||||||
mDocuments.push_back(document);
|
mDocuments.push_back(document);
|
||||||
|
|
||||||
connect (document, SIGNAL (mergeDone (CSMDoc::Document*)),
|
connect(document, SIGNAL(mergeDone(CSMDoc::Document*)), this, SLOT(insertDocument(CSMDoc::Document*)));
|
||||||
this, SLOT (insertDocument (CSMDoc::Document*)));
|
|
||||||
|
|
||||||
emit loadRequest(document);
|
emit loadRequest(document);
|
||||||
|
|
||||||
|
@ -122,7 +116,8 @@ void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::
|
||||||
removeDocument(document);
|
removeDocument(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::DocumentManager::setFileData(bool strict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives)
|
void CSMDoc::DocumentManager::setFileData(
|
||||||
|
bool strict, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives)
|
||||||
{
|
{
|
||||||
mFsStrict = strict;
|
mFsStrict = strict;
|
||||||
mDataPaths = dataPaths;
|
mDataPaths = dataPaths;
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
#ifndef CSM_DOC_DOCUMENTMGR_H
|
#ifndef CSM_DOC_DOCUMENTMGR_H
|
||||||
#define CSM_DOC_DOCUMENTMGR_H
|
#define CSM_DOC_DOCUMENTMGR_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
|
||||||
#include <components/fallback/fallback.hpp>
|
#include <components/fallback/fallback.hpp>
|
||||||
#include <components/files/multidircollection.hpp>
|
#include <components/files/multidircollection.hpp>
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
#include "loader.hpp"
|
#include "loader.hpp"
|
||||||
|
|
||||||
|
@ -48,13 +48,12 @@ namespace CSMDoc
|
||||||
DocumentManager& operator=(const DocumentManager&);
|
DocumentManager& operator=(const DocumentManager&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DocumentManager(const Files::ConfigurationManager& configuration);
|
DocumentManager(const Files::ConfigurationManager& configuration);
|
||||||
|
|
||||||
~DocumentManager();
|
~DocumentManager();
|
||||||
|
|
||||||
void addDocument (const std::vector< std::filesystem::path >& files,
|
void addDocument(
|
||||||
const std::filesystem::path& savePath, bool new_);
|
const std::vector<std::filesystem::path>& files, const std::filesystem::path& savePath, bool new_);
|
||||||
///< \param new_ Do not load the last content file in \a files and instead create in an
|
///< \param new_ Do not load the last content file in \a files and instead create in an
|
||||||
/// appropriate way.
|
/// appropriate way.
|
||||||
|
|
||||||
|
@ -64,8 +63,8 @@ namespace CSMDoc
|
||||||
///
|
///
|
||||||
/// \param new_ Do not load the last content file in \a files and instead create in an
|
/// \param new_ Do not load the last content file in \a files and instead create in an
|
||||||
/// appropriate way.
|
/// appropriate way.
|
||||||
Document *makeDocument (const std::vector< std::filesystem::path >& files,
|
Document* makeDocument(
|
||||||
const std::filesystem::path& savePath, bool new_);
|
const std::vector<std::filesystem::path>& files, const std::filesystem::path& savePath, bool new_);
|
||||||
|
|
||||||
void setResourceDir(const std::filesystem::path& parResDir);
|
void setResourceDir(const std::filesystem::path& parResDir);
|
||||||
|
|
||||||
|
@ -106,11 +105,9 @@ namespace CSMDoc
|
||||||
|
|
||||||
void lastDocumentDeleted();
|
void lastDocumentDeleted();
|
||||||
|
|
||||||
void loadingStopped (CSMDoc::Document *document, bool completed,
|
void loadingStopped(CSMDoc::Document* document, bool completed, const std::string& error);
|
||||||
const std::string& error);
|
|
||||||
|
|
||||||
void nextStage (CSMDoc::Document *document, const std::string& name,
|
void nextStage(CSMDoc::Document* document, const std::string& name, int totalRecords);
|
||||||
int totalRecords);
|
|
||||||
|
|
||||||
void nextRecord(CSMDoc::Document* document, int records);
|
void nextRecord(CSMDoc::Document* document, int records);
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,12 @@
|
||||||
|
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLoaded (0), mRecordsLeft (false) {}
|
CSMDoc::Loader::Stage::Stage()
|
||||||
|
: mFile(0)
|
||||||
|
, mRecordsLoaded(0)
|
||||||
|
, mRecordsLeft(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
CSMDoc::Loader::Loader()
|
CSMDoc::Loader::Loader()
|
||||||
: mShouldStop(false)
|
: mShouldStop(false)
|
||||||
|
@ -74,8 +78,8 @@ void CSMDoc::Loader::load()
|
||||||
CSMWorld::UniversalId log(CSMWorld::UniversalId::Type_LoadErrorLog, 0);
|
CSMWorld::UniversalId log(CSMWorld::UniversalId::Type_LoadErrorLog, 0);
|
||||||
|
|
||||||
{ // silence a g++ warning
|
{ // silence a g++ warning
|
||||||
for (CSMDoc::Messages::Iterator messageIter (messages.begin());
|
for (CSMDoc::Messages::Iterator messageIter(messages.begin()); messageIter != messages.end();
|
||||||
messageIter!=messages.end(); ++messageIter)
|
++messageIter)
|
||||||
{
|
{
|
||||||
document->getReport(log)->add(*messageIter);
|
document->getReport(log)->add(*messageIter);
|
||||||
emit loadMessage(document, messageIter->mMessage);
|
emit loadMessage(document, messageIter->mMessage);
|
||||||
|
@ -133,8 +137,7 @@ void CSMDoc::Loader::loadDocument (CSMDoc::Document *document)
|
||||||
|
|
||||||
void CSMDoc::Loader::abortLoading(CSMDoc::Document* document)
|
void CSMDoc::Loader::abortLoading(CSMDoc::Document* document)
|
||||||
{
|
{
|
||||||
for (std::vector<std::pair<Document *, Stage> >::iterator iter = mDocuments.begin();
|
for (std::vector<std::pair<Document*, Stage>>::iterator iter = mDocuments.begin(); iter != mDocuments.end(); ++iter)
|
||||||
iter!=mDocuments.end(); ++iter)
|
|
||||||
{
|
{
|
||||||
if (iter->first == document)
|
if (iter->first == document)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ namespace CSMDoc
|
||||||
bool mShouldStop;
|
bool mShouldStop;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Loader();
|
Loader();
|
||||||
|
|
||||||
QWaitCondition& hasThingsToDo();
|
QWaitCondition& hasThingsToDo();
|
||||||
|
@ -63,8 +62,7 @@ namespace CSMDoc
|
||||||
///< Document load has been interrupted either because of a call to abortLoading
|
///< Document load has been interrupted either because of a call to abortLoading
|
||||||
/// or a problem during loading). In the former case error will be an empty string.
|
/// or a problem during loading). In the former case error will be an empty string.
|
||||||
|
|
||||||
void nextStage (CSMDoc::Document *document, const std::string& name,
|
void nextStage(CSMDoc::Document* document, const std::string& name, int totalRecords);
|
||||||
int totalRecords);
|
|
||||||
|
|
||||||
void nextRecord(CSMDoc::Document* document, int records);
|
void nextRecord(CSMDoc::Document* document, int records);
|
||||||
///< \note This signal is only given once per group of records. The group size is
|
///< \note This signal is only given once per group of records. The group size is
|
||||||
|
|
|
@ -1,33 +1,45 @@
|
||||||
#include "messages.hpp"
|
#include "messages.hpp"
|
||||||
|
|
||||||
CSMDoc::Message::Message() : mSeverity(Severity_Default){}
|
CSMDoc::Message::Message()
|
||||||
|
: mSeverity(Severity_Default)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message,
|
CSMDoc::Message::Message(
|
||||||
const std::string& hint, Severity severity)
|
const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint, Severity severity)
|
||||||
: mId (id), mMessage (message), mHint (hint), mSeverity (severity)
|
: mId(id)
|
||||||
{}
|
, mMessage(message)
|
||||||
|
, mHint(hint)
|
||||||
|
, mSeverity(severity)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::string CSMDoc::Message::toString(Severity severity)
|
std::string CSMDoc::Message::toString(Severity severity)
|
||||||
{
|
{
|
||||||
switch (severity)
|
switch (severity)
|
||||||
{
|
{
|
||||||
case CSMDoc::Message::Severity_Info: return "Information";
|
case CSMDoc::Message::Severity_Info:
|
||||||
case CSMDoc::Message::Severity_Warning: return "Warning";
|
return "Information";
|
||||||
case CSMDoc::Message::Severity_Error: return "Error";
|
case CSMDoc::Message::Severity_Warning:
|
||||||
case CSMDoc::Message::Severity_SeriousError: return "Serious Error";
|
return "Warning";
|
||||||
case CSMDoc::Message::Severity_Default: break;
|
case CSMDoc::Message::Severity_Error:
|
||||||
|
return "Error";
|
||||||
|
case CSMDoc::Message::Severity_SeriousError:
|
||||||
|
return "Serious Error";
|
||||||
|
case CSMDoc::Message::Severity_Default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CSMDoc::Messages::Messages(Message::Severity default_)
|
CSMDoc::Messages::Messages(Message::Severity default_)
|
||||||
: mDefault(default_)
|
: mDefault(default_)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message,
|
void CSMDoc::Messages::add(
|
||||||
const std::string& hint, Message::Severity severity)
|
const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint, Message::Severity severity)
|
||||||
{
|
{
|
||||||
if (severity == Message::Severity_Default)
|
if (severity == Message::Severity_Default)
|
||||||
severity = mDefault;
|
severity = mDefault;
|
||||||
|
|
|
@ -27,8 +27,8 @@ namespace CSMDoc
|
||||||
|
|
||||||
Message();
|
Message();
|
||||||
|
|
||||||
Message (const CSMWorld::UniversalId& id, const std::string& message,
|
Message(
|
||||||
const std::string& hint, Severity severity);
|
const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint, Severity severity);
|
||||||
|
|
||||||
static std::string toString(Severity severity);
|
static std::string toString(Severity severity);
|
||||||
};
|
};
|
||||||
|
@ -36,22 +36,18 @@ namespace CSMDoc
|
||||||
class Messages
|
class Messages
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::vector<Message> Collection;
|
typedef std::vector<Message> Collection;
|
||||||
|
|
||||||
typedef Collection::const_iterator Iterator;
|
typedef Collection::const_iterator Iterator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Collection mMessages;
|
Collection mMessages;
|
||||||
Message::Severity mDefault;
|
Message::Severity mDefault;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Messages(Message::Severity default_);
|
Messages(Message::Severity default_);
|
||||||
|
|
||||||
void add (const CSMWorld::UniversalId& id, const std::string& message,
|
void add(const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint = "",
|
||||||
const std::string& hint = "",
|
|
||||||
Message::Severity severity = Message::Severity_Default);
|
Message::Severity severity = Message::Severity_Default);
|
||||||
|
|
||||||
Iterator begin() const;
|
Iterator begin() const;
|
||||||
|
|
|
@ -25,10 +25,18 @@ void CSMDoc::Operation::prepareStages()
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Operation::Operation(int type, bool ordered, bool finalAlways)
|
CSMDoc::Operation::Operation(int type, bool ordered, bool finalAlways)
|
||||||
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
|
: mType(type)
|
||||||
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
|
, mStages(std::vector<std::pair<Stage*, int>>())
|
||||||
mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false),
|
, mCurrentStage(mStages.begin())
|
||||||
mDefaultSeverity (Message::Severity_Error)
|
, mCurrentStep(0)
|
||||||
|
, mCurrentStepTotal(0)
|
||||||
|
, mTotalSteps(0)
|
||||||
|
, mOrdered(ordered)
|
||||||
|
, mFinalAlways(finalAlways)
|
||||||
|
, mError(false)
|
||||||
|
, mConnected(false)
|
||||||
|
, mPrepared(false)
|
||||||
|
, mDefaultSeverity(Message::Severity_Error)
|
||||||
{
|
{
|
||||||
mTimer = new QTimer(this);
|
mTimer = new QTimer(this);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +121,8 @@ void CSMDoc::Operation::executeStage()
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType);
|
emit reportMessage(
|
||||||
|
Message(CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef CSM_DOC_OPERATION_H
|
#ifndef CSM_DOC_OPERATION_H
|
||||||
#define CSM_DOC_OPERATION_H
|
#define CSM_DOC_OPERATION_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
@ -39,7 +39,6 @@ namespace CSMDoc
|
||||||
void prepareStages();
|
void prepareStages();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Operation(int type, bool ordered, bool finalAlways = false);
|
Operation(int type, bool ordered, bool finalAlways = false);
|
||||||
///< \param ordered Stages must be executed in the given order.
|
///< \param ordered Stages must be executed in the given order.
|
||||||
/// \param finalAlways Execute last stage even if an error occurred during earlier stages.
|
/// \param finalAlways Execute last stage even if an error occurred during earlier stages.
|
||||||
|
|
|
@ -15,14 +15,11 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation)
|
||||||
mOperation = operation;
|
mOperation = operation;
|
||||||
mOperation->moveToThread(&mThread);
|
mOperation->moveToThread(&mThread);
|
||||||
|
|
||||||
connect (mOperation, &Operation::progress,
|
connect(mOperation, &Operation::progress, this, &OperationHolder::progress);
|
||||||
this, &OperationHolder::progress);
|
|
||||||
|
|
||||||
connect (mOperation, &Operation::reportMessage,
|
connect(mOperation, &Operation::reportMessage, this, &OperationHolder::reportMessage);
|
||||||
this, &OperationHolder::reportMessage);
|
|
||||||
|
|
||||||
connect (mOperation, &Operation::done,
|
connect(mOperation, &Operation::done, this, &OperationHolder::doneSlot);
|
||||||
this, &OperationHolder::doneSlot);
|
|
||||||
|
|
||||||
connect(this, &OperationHolder::abortSignal, mOperation, &Operation::abort);
|
connect(this, &OperationHolder::abortSignal, mOperation, &Operation::abort);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ namespace CSMDoc
|
||||||
bool mRunning;
|
bool mRunning;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
OperationHolder(Operation* operation = nullptr);
|
OperationHolder(Operation* operation = nullptr);
|
||||||
|
|
||||||
void setOperation(Operation* operation);
|
void setOperation(Operation* operation);
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QCoreApplication>
|
|
||||||
|
|
||||||
#include <components/files/conversion.hpp>
|
#include <components/files/conversion.hpp>
|
||||||
#include <components/files/qtconversion.hpp>
|
#include <components/files/qtconversion.hpp>
|
||||||
|
@ -13,13 +13,13 @@
|
||||||
#include "operationholder.hpp"
|
#include "operationholder.hpp"
|
||||||
|
|
||||||
CSMDoc::Runner::Runner(std::filesystem::path projectPath)
|
CSMDoc::Runner::Runner(std::filesystem::path projectPath)
|
||||||
: mRunning (false), mStartup (nullptr), mProjectPath (std::move(projectPath))
|
: mRunning(false)
|
||||||
|
, mStartup(nullptr)
|
||||||
|
, mProjectPath(std::move(projectPath))
|
||||||
{
|
{
|
||||||
connect (&mProcess, qOverload<int, QProcess::ExitStatus>(&QProcess::finished),
|
connect(&mProcess, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), this, &Runner::finished);
|
||||||
this, &Runner::finished);
|
|
||||||
|
|
||||||
connect (&mProcess, &QProcess::readyReadStandardOutput,
|
connect(&mProcess, &QProcess::readyReadStandardOutput, this, &Runner::readyReadStandardOutput);
|
||||||
this, &Runner::readyReadStandardOutput);
|
|
||||||
|
|
||||||
mProcess.setProcessChannelMode(QProcess::MergedChannels);
|
mProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||||
|
|
||||||
|
@ -94,8 +94,7 @@ void CSMDoc::Runner::start (bool delayed)
|
||||||
arguments << "--content=" + Files::pathToQString(mContentFile);
|
arguments << "--content=" + Files::pathToQString(mContentFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
arguments
|
arguments << "--content=" + Files::pathToQString(mProjectPath.filename());
|
||||||
<< "--content=" + Files::pathToQString(mProjectPath.filename());
|
|
||||||
|
|
||||||
mProcess.start(path, arguments);
|
mProcess.start(path, arguments);
|
||||||
}
|
}
|
||||||
|
@ -123,8 +122,8 @@ bool CSMDoc::Runner::isRunning() const
|
||||||
return mRunning;
|
return mRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Runner::configure (const ESM::DebugProfile& profile,
|
void CSMDoc::Runner::configure(const ESM::DebugProfile& profile, const std::vector<std::filesystem::path>& contentFiles,
|
||||||
const std::vector<std::filesystem::path> &contentFiles, const std::string& startupInstruction)
|
const std::string& startupInstruction)
|
||||||
{
|
{
|
||||||
mProfile = profile;
|
mProfile = profile;
|
||||||
mContentFiles = contentFiles;
|
mContentFiles = contentFiles;
|
||||||
|
@ -144,13 +143,12 @@ QTextDocument *CSMDoc::Runner::getLog()
|
||||||
|
|
||||||
void CSMDoc::Runner::readyReadStandardOutput()
|
void CSMDoc::Runner::readyReadStandardOutput()
|
||||||
{
|
{
|
||||||
mLog.setPlainText (
|
mLog.setPlainText(mLog.toPlainText() + QString::fromUtf8(mProcess.readAllStandardOutput()));
|
||||||
mLog.toPlainText() + QString::fromUtf8 (mProcess.readAllStandardOutput()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CSMDoc::SaveWatcher::SaveWatcher(Runner* runner, OperationHolder* operation)
|
CSMDoc::SaveWatcher::SaveWatcher(Runner* runner, OperationHolder* operation)
|
||||||
: QObject (runner), mRunner (runner)
|
: QObject(runner)
|
||||||
|
, mRunner(runner)
|
||||||
{
|
{
|
||||||
connect(operation, &OperationHolder::done, this, &SaveWatcher::saveDone);
|
connect(operation, &OperationHolder::done, this, &SaveWatcher::saveDone);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef CSM_DOC_RUNNER_H
|
#ifndef CSM_DOC_RUNNER_H
|
||||||
#define CSM_DOC_RUNNER_H
|
#define CSM_DOC_RUNNER_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
@ -32,7 +32,6 @@ namespace CSMDoc
|
||||||
std::filesystem::path mProjectPath;
|
std::filesystem::path mProjectPath;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Runner(std::filesystem::path projectPath);
|
Runner(std::filesystem::path projectPath);
|
||||||
|
|
||||||
~Runner();
|
~Runner();
|
||||||
|
@ -47,8 +46,7 @@ namespace CSMDoc
|
||||||
/// is not necessarily identical to the moment the child process is started.
|
/// is not necessarily identical to the moment the child process is started.
|
||||||
bool isRunning() const;
|
bool isRunning() const;
|
||||||
|
|
||||||
void configure (const ESM::DebugProfile& profile,
|
void configure(const ESM::DebugProfile& profile, const std::vector<std::filesystem::path>& contentFiles,
|
||||||
const std::vector<std::filesystem::path> &contentFiles,
|
|
||||||
const std::string& startupInstruction);
|
const std::string& startupInstruction);
|
||||||
|
|
||||||
QTextDocument* getLog();
|
QTextDocument* getLog();
|
||||||
|
@ -74,7 +72,6 @@ namespace CSMDoc
|
||||||
Runner* mRunner;
|
Runner* mRunner;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// *this attaches itself to runner
|
/// *this attaches itself to runner
|
||||||
SaveWatcher(Runner* runner, OperationHolder* operation);
|
SaveWatcher(Runner* runner, OperationHolder* operation);
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "state.hpp"
|
|
||||||
#include "savingstages.hpp"
|
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
#include "savingstages.hpp"
|
||||||
|
#include "state.hpp"
|
||||||
|
|
||||||
CSMDoc::Saving::Saving (Document& document, const std::filesystem::path& projectPath,
|
CSMDoc::Saving::Saving(Document& document, const std::filesystem::path& projectPath, ToUTF8::FromType encoding)
|
||||||
ToUTF8::FromType encoding)
|
: Operation(State_Saving, true, true)
|
||||||
: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath, encoding)
|
, mDocument(document)
|
||||||
|
, mState(*this, projectPath, encoding)
|
||||||
{
|
{
|
||||||
// save project file
|
// save project file
|
||||||
appendStage(new OpenSaveStage(mDocument, mState, true));
|
appendStage(new OpenSaveStage(mDocument, mState, true));
|
||||||
|
@ -32,53 +33,48 @@ CSMDoc::Saving::Saving (Document& document, const std::filesystem::path& project
|
||||||
|
|
||||||
appendStage(new WriteHeaderStage(mDocument, mState, false));
|
appendStage(new WriteHeaderStage(mDocument, mState, false));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Global> >
|
appendStage(
|
||||||
(mDocument.getData().getGlobals(), mState));
|
new WriteCollectionStage<CSMWorld::IdCollection<ESM::Global>>(mDocument.getData().getGlobals(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::GameSetting> >
|
appendStage(
|
||||||
(mDocument.getData().getGmsts(), mState));
|
new WriteCollectionStage<CSMWorld::IdCollection<ESM::GameSetting>>(mDocument.getData().getGmsts(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Skill> >
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::Skill>>(mDocument.getData().getSkills(), mState));
|
||||||
(mDocument.getData().getSkills(), mState));
|
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Class> >
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::Class>>(mDocument.getData().getClasses(), mState));
|
||||||
(mDocument.getData().getClasses(), mState));
|
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Faction> >
|
appendStage(
|
||||||
(mDocument.getData().getFactions(), mState));
|
new WriteCollectionStage<CSMWorld::IdCollection<ESM::Faction>>(mDocument.getData().getFactions(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Race> >
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::Race>>(mDocument.getData().getRaces(), mState));
|
||||||
(mDocument.getData().getRaces(), mState));
|
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Sound> >
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::Sound>>(mDocument.getData().getSounds(), mState));
|
||||||
(mDocument.getData().getSounds(), mState));
|
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Script> >
|
appendStage(
|
||||||
(mDocument.getData().getScripts(), mState));
|
new WriteCollectionStage<CSMWorld::IdCollection<ESM::Script>>(mDocument.getData().getScripts(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Region> >
|
appendStage(
|
||||||
(mDocument.getData().getRegions(), mState));
|
new WriteCollectionStage<CSMWorld::IdCollection<ESM::Region>>(mDocument.getData().getRegions(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::BirthSign> >
|
appendStage(
|
||||||
(mDocument.getData().getBirthsigns(), mState));
|
new WriteCollectionStage<CSMWorld::IdCollection<ESM::BirthSign>>(mDocument.getData().getBirthsigns(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Spell> >
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::Spell>>(mDocument.getData().getSpells(), mState));
|
||||||
(mDocument.getData().getSpells(), mState));
|
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Enchantment> >
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::Enchantment>>(
|
||||||
(mDocument.getData().getEnchantments(), mState));
|
mDocument.getData().getEnchantments(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::BodyPart> >
|
appendStage(
|
||||||
(mDocument.getData().getBodyParts(), mState));
|
new WriteCollectionStage<CSMWorld::IdCollection<ESM::BodyPart>>(mDocument.getData().getBodyParts(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::SoundGenerator> >
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::SoundGenerator>>(
|
||||||
(mDocument.getData().getSoundGens(), mState));
|
mDocument.getData().getSoundGens(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::MagicEffect> >
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::MagicEffect>>(
|
||||||
(mDocument.getData().getMagicEffects(), mState));
|
mDocument.getData().getMagicEffects(), mState));
|
||||||
|
|
||||||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::StartScript> >
|
appendStage(new WriteCollectionStage<CSMWorld::IdCollection<ESM::StartScript>>(
|
||||||
(mDocument.getData().getStartScripts(), mState));
|
mDocument.getData().getStartScripts(), mState));
|
||||||
|
|
||||||
appendStage(new WriteRefIdCollectionStage(mDocument, mState));
|
appendStage(new WriteRefIdCollectionStage(mDocument, mState));
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,7 @@ namespace CSMDoc
|
||||||
SavingState mState;
|
SavingState mState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Saving(Document& document, const std::filesystem::path& projectPath, ToUTF8::FromType encoding);
|
||||||
Saving (Document& document, const std::filesystem::path& projectPath,
|
|
||||||
ToUTF8::FromType encoding);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
#include "savingstages.hpp"
|
#include "savingstages.hpp"
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <components/esm3/loaddial.hpp>
|
#include <components/esm3/loaddial.hpp>
|
||||||
#include <components/files/conversion.hpp>
|
#include <components/files/conversion.hpp>
|
||||||
|
|
||||||
#include "../world/infocollection.hpp"
|
|
||||||
#include "../world/cellcoordinates.hpp"
|
#include "../world/cellcoordinates.hpp"
|
||||||
|
#include "../world/infocollection.hpp"
|
||||||
|
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::OpenSaveStage::OpenSaveStage(Document& document, SavingState& state, bool projectFile)
|
CSMDoc::OpenSaveStage::OpenSaveStage(Document& document, SavingState& state, bool projectFile)
|
||||||
: mDocument (document), mState (state), mProjectFile (projectFile)
|
: mDocument(document)
|
||||||
{}
|
, mState(state)
|
||||||
|
, mProjectFile(projectFile)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int CSMDoc::OpenSaveStage::setup()
|
int CSMDoc::OpenSaveStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -24,18 +27,18 @@ void CSMDoc::OpenSaveStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
mState.start(mDocument, mProjectFile);
|
mState.start(mDocument, mProjectFile);
|
||||||
|
|
||||||
mState.getStream().open (
|
mState.getStream().open(mProjectFile ? mState.getPath() : mState.getTmpPath(), std::ios::binary);
|
||||||
mProjectFile ? mState.getPath() : mState.getTmpPath(),
|
|
||||||
std::ios::binary);
|
|
||||||
|
|
||||||
if (!mState.getStream().is_open())
|
if (!mState.getStream().is_open())
|
||||||
throw std::runtime_error("failed to open stream for saving");
|
throw std::runtime_error("failed to open stream for saving");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CSMDoc::WriteHeaderStage::WriteHeaderStage(Document& document, SavingState& state, bool simple)
|
CSMDoc::WriteHeaderStage::WriteHeaderStage(Document& document, SavingState& state, bool simple)
|
||||||
: mDocument (document), mState (state), mSimple (simple)
|
: mDocument(document)
|
||||||
{}
|
, mState(state)
|
||||||
|
, mSimple(simple)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int CSMDoc::WriteHeaderStage::setup()
|
int CSMDoc::WriteHeaderStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -61,17 +64,15 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mDocument.getData().getMetaData().save(mState.getWriter());
|
mDocument.getData().getMetaData().save(mState.getWriter());
|
||||||
mState.getWriter().setRecordCount (
|
mState.getWriter().setRecordCount(mDocument.getData().count(CSMWorld::RecordBase::State_Modified)
|
||||||
mDocument.getData().count (CSMWorld::RecordBase::State_Modified) +
|
+ mDocument.getData().count(CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) +
|
+ mDocument.getData().count(CSMWorld::RecordBase::State_Deleted));
|
||||||
mDocument.getData().count (CSMWorld::RecordBase::State_Deleted));
|
|
||||||
|
|
||||||
/// \todo refine dependency list (at least remove redundant dependencies)
|
/// \todo refine dependency list (at least remove redundant dependencies)
|
||||||
std::vector<std::filesystem::path> dependencies = mDocument.getContentFiles();
|
std::vector<std::filesystem::path> dependencies = mDocument.getContentFiles();
|
||||||
std::vector<std::filesystem::path>::const_iterator end(--dependencies.end());
|
std::vector<std::filesystem::path>::const_iterator end(--dependencies.end());
|
||||||
|
|
||||||
for (std::vector<std::filesystem::path>::const_iterator iter (dependencies.begin());
|
for (std::vector<std::filesystem::path>::const_iterator iter(dependencies.begin()); iter != end; ++iter)
|
||||||
iter!=end; ++iter)
|
|
||||||
{
|
{
|
||||||
auto name = Files::pathToUnicodeString(iter->filename());
|
auto name = Files::pathToUnicodeString(iter->filename());
|
||||||
auto size = std::filesystem::file_size(*iter);
|
auto size = std::filesystem::file_size(*iter);
|
||||||
|
@ -83,13 +84,12 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
|
||||||
mState.getWriter().save(mState.getStream());
|
mState.getWriter().save(mState.getStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage(Document& document, SavingState& state, bool journal)
|
||||||
CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage (Document& document,
|
: mState(state)
|
||||||
SavingState& state, bool journal)
|
, mTopics(journal ? document.getData().getJournals() : document.getData().getTopics())
|
||||||
: mState (state),
|
, mInfos(journal ? document.getData().getJournalInfos() : document.getData().getTopicInfos())
|
||||||
mTopics (journal ? document.getData().getJournals() : document.getData().getTopics()),
|
{
|
||||||
mInfos (journal ? document.getData().getJournalInfos() : document.getData().getTopicInfos())
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
int CSMDoc::WriteDialogueCollectionStage::setup()
|
int CSMDoc::WriteDialogueCollectionStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -174,10 +174,11 @@ void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CSMDoc::WriteRefIdCollectionStage::WriteRefIdCollectionStage(Document& document, SavingState& state)
|
CSMDoc::WriteRefIdCollectionStage::WriteRefIdCollectionStage(Document& document, SavingState& state)
|
||||||
: mDocument (document), mState (state)
|
: mDocument(document)
|
||||||
{}
|
, mState(state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int CSMDoc::WriteRefIdCollectionStage::setup()
|
int CSMDoc::WriteRefIdCollectionStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -189,11 +190,11 @@ void CSMDoc::WriteRefIdCollectionStage::perform (int stage, Messages& messages)
|
||||||
mDocument.getData().getReferenceables().save(stage, mState.getWriter());
|
mDocument.getData().getReferenceables().save(stage, mState.getWriter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMDoc::CollectionReferencesStage::CollectionReferencesStage(Document& document, SavingState& state)
|
||||||
CSMDoc::CollectionReferencesStage::CollectionReferencesStage (Document& document,
|
: mDocument(document)
|
||||||
SavingState& state)
|
, mState(state)
|
||||||
: mDocument (document), mState (state)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
int CSMDoc::CollectionReferencesStage::setup()
|
int CSMDoc::CollectionReferencesStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -202,7 +203,8 @@ int CSMDoc::CollectionReferencesStage::setup()
|
||||||
int size = mDocument.getData().getReferences().getSize();
|
int size = mDocument.getData().getReferences().getSize();
|
||||||
|
|
||||||
int steps = size / 100;
|
int steps = size / 100;
|
||||||
if (size%100) ++steps;
|
if (size % 100)
|
||||||
|
++steps;
|
||||||
|
|
||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
@ -213,16 +215,13 @@ void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages)
|
||||||
|
|
||||||
for (int i = stage * 100; i < stage * 100 + 100 && i < size; ++i)
|
for (int i = stage * 100; i < stage * 100 + 100 && i < size; ++i)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<CSMWorld::CellRef>& record =
|
const CSMWorld::Record<CSMWorld::CellRef>& record = mDocument.getData().getReferences().getRecord(i);
|
||||||
mDocument.getData().getReferences().getRecord (i);
|
|
||||||
|
|
||||||
if (record.isModified() || record.mState == CSMWorld::RecordBase::State_Deleted)
|
if (record.isModified() || record.mState == CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
std::string cellId = record.get().mOriginalCell.empty() ?
|
std::string cellId = record.get().mOriginalCell.empty() ? record.get().mCell : record.get().mOriginalCell;
|
||||||
record.get().mCell : record.get().mOriginalCell;
|
|
||||||
|
|
||||||
std::deque<int>& indices =
|
std::deque<int>& indices = mState.getSubRecords()[Misc::StringUtils::lowerCase(cellId)];
|
||||||
mState.getSubRecords()[Misc::StringUtils::lowerCase (cellId)];
|
|
||||||
|
|
||||||
// collect moved references at the end of the container
|
// collect moved references at the end of the container
|
||||||
bool interior = cellId.substr(0, 1) != "#";
|
bool interior = cellId.substr(0, 1) != "#";
|
||||||
|
@ -236,8 +235,8 @@ void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages)
|
||||||
|
|
||||||
// An empty mOriginalCell is meant to indicate that it is the same as
|
// An empty mOriginalCell is meant to indicate that it is the same as
|
||||||
// the current cell. It is possible that a moved ref is moved again.
|
// the current cell. It is possible that a moved ref is moved again.
|
||||||
if ((record.get().mOriginalCell.empty() ?
|
if ((record.get().mOriginalCell.empty() ? record.get().mCell : record.get().mOriginalCell) != stream.str()
|
||||||
record.get().mCell : record.get().mOriginalCell) != stream.str() && !interior && record.mState!=CSMWorld::RecordBase::State_ModifiedOnly && !record.get().mNew)
|
&& !interior && record.mState != CSMWorld::RecordBase::State_ModifiedOnly && !record.get().mNew)
|
||||||
indices.push_back(i);
|
indices.push_back(i);
|
||||||
else
|
else
|
||||||
indices.push_front(i);
|
indices.push_front(i);
|
||||||
|
@ -245,26 +244,25 @@ void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMDoc::WriteCellCollectionStage::WriteCellCollectionStage(Document& document, SavingState& state)
|
||||||
CSMDoc::WriteCellCollectionStage::WriteCellCollectionStage (Document& document,
|
: mDocument(document)
|
||||||
SavingState& state)
|
, mState(state)
|
||||||
: mDocument (document), mState (state)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
int CSMDoc::WriteCellCollectionStage::setup()
|
int CSMDoc::WriteCellCollectionStage::setup()
|
||||||
{
|
{
|
||||||
return mDocument.getData().getCells().getSize();
|
return mDocument.getData().getCells().getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque<int>& references, bool interior, unsigned int& newRefNum)
|
void CSMDoc::WriteCellCollectionStage::writeReferences(
|
||||||
|
const std::deque<int>& references, bool interior, unsigned int& newRefNum)
|
||||||
{
|
{
|
||||||
ESM::ESMWriter& writer = mState.getWriter();
|
ESM::ESMWriter& writer = mState.getWriter();
|
||||||
|
|
||||||
for (std::deque<int>::const_iterator iter (references.begin());
|
for (std::deque<int>::const_iterator iter(references.begin()); iter != references.end(); ++iter)
|
||||||
iter!=references.end(); ++iter)
|
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<CSMWorld::CellRef>& ref =
|
const CSMWorld::Record<CSMWorld::CellRef>& ref = mDocument.getData().getReferences().getRecord(*iter);
|
||||||
mDocument.getData().getReferences().getRecord (*iter);
|
|
||||||
|
|
||||||
if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted)
|
if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
|
@ -282,14 +280,14 @@ void CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque<int>& r
|
||||||
stream << "#" << index.first << " " << index.second;
|
stream << "#" << index.first << " " << index.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refRecord.mNew || refRecord.mRefNum.mIndex == 0 ||
|
if (refRecord.mNew || refRecord.mRefNum.mIndex == 0
|
||||||
(!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly &&
|
|| (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly
|
||||||
refRecord.mCell!=stream.str()))
|
&& refRecord.mCell != stream.str()))
|
||||||
{
|
{
|
||||||
refRecord.mRefNum.mIndex = newRefNum++;
|
refRecord.mRefNum.mIndex = newRefNum++;
|
||||||
}
|
}
|
||||||
else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell)
|
else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != stream.str()
|
||||||
!= stream.str() && !interior)
|
&& !interior)
|
||||||
{
|
{
|
||||||
// An empty mOriginalCell is meant to indicate that it is the same as
|
// An empty mOriginalCell is meant to indicate that it is the same as
|
||||||
// the current cell. It is possible that a moved ref is moved again.
|
// the current cell. It is possible that a moved ref is moved again.
|
||||||
|
@ -322,12 +320,11 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
||||||
std::deque<int> tempRefs;
|
std::deque<int> tempRefs;
|
||||||
std::deque<int> persistentRefs;
|
std::deque<int> persistentRefs;
|
||||||
|
|
||||||
std::map<std::string, std::deque<int> >::const_iterator references =
|
std::map<std::string, std::deque<int>>::const_iterator references
|
||||||
mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId));
|
= mState.getSubRecords().find(Misc::StringUtils::lowerCase(cell.get().mId));
|
||||||
|
|
||||||
if (cell.isModified() ||
|
if (cell.isModified() || cell.mState == CSMWorld::RecordBase::State_Deleted
|
||||||
cell.mState == CSMWorld::RecordBase::State_Deleted ||
|
|| references != mState.getSubRecords().end())
|
||||||
references!=mState.getSubRecords().end())
|
|
||||||
{
|
{
|
||||||
CSMWorld::Cell cellRecord = cell.get();
|
CSMWorld::Cell cellRecord = cell.get();
|
||||||
bool interior = cellRecord.mId.substr(0, 1) != "#";
|
bool interior = cellRecord.mId.substr(0, 1) != "#";
|
||||||
|
@ -337,18 +334,16 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
||||||
|
|
||||||
if (references != mState.getSubRecords().end())
|
if (references != mState.getSubRecords().end())
|
||||||
{
|
{
|
||||||
for (std::deque<int>::const_iterator iter (references->second.begin());
|
for (std::deque<int>::const_iterator iter(references->second.begin()); iter != references->second.end();
|
||||||
iter!=references->second.end(); ++iter)
|
++iter)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<CSMWorld::CellRef>& ref =
|
const CSMWorld::Record<CSMWorld::CellRef>& ref = mDocument.getData().getReferences().getRecord(*iter);
|
||||||
mDocument.getData().getReferences().getRecord (*iter);
|
|
||||||
|
|
||||||
CSMWorld::CellRef refRecord = ref.get();
|
CSMWorld::CellRef refRecord = ref.get();
|
||||||
|
|
||||||
CSMWorld::RefIdData::LocalIndex localIndex = refIdData.searchId(refRecord.mRefID);
|
CSMWorld::RefIdData::LocalIndex localIndex = refIdData.searchId(refRecord.mRefID);
|
||||||
unsigned int recordFlags = refIdData.getRecordFlags(refRecord.mRefID);
|
unsigned int recordFlags = refIdData.getRecordFlags(refRecord.mRefID);
|
||||||
bool isPersistent = ((recordFlags & ESM::FLAG_Persistent) != 0)
|
bool isPersistent = ((recordFlags & ESM::FLAG_Persistent) != 0) || refRecord.mTeleport
|
||||||
|| refRecord.mTeleport
|
|
||||||
|| localIndex.second == CSMWorld::UniversalId::Type_Creature
|
|| localIndex.second == CSMWorld::UniversalId::Type_Creature
|
||||||
|| localIndex.second == CSMWorld::UniversalId::Type_Npc;
|
|| localIndex.second == CSMWorld::UniversalId::Type_Npc;
|
||||||
|
|
||||||
|
@ -357,8 +352,8 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
||||||
else
|
else
|
||||||
tempRefs.push_back(*iter);
|
tempRefs.push_back(*iter);
|
||||||
|
|
||||||
if (refRecord.mNew ||
|
if (refRecord.mNew
|
||||||
(!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly &&
|
|| (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly &&
|
||||||
/// \todo consider worldspace
|
/// \todo consider worldspace
|
||||||
CSMWorld::CellCoordinates(refRecord.getCellIndex()).getId("") != refRecord.mCell))
|
CSMWorld::CellCoordinates(refRecord.getCellIndex()).getId("") != refRecord.mCell))
|
||||||
++cellRecord.mRefNumCounter;
|
++cellRecord.mRefNumCounter;
|
||||||
|
@ -396,11 +391,11 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMDoc::WritePathgridCollectionStage::WritePathgridCollectionStage(Document& document, SavingState& state)
|
||||||
CSMDoc::WritePathgridCollectionStage::WritePathgridCollectionStage (Document& document,
|
: mDocument(document)
|
||||||
SavingState& state)
|
, mState(state)
|
||||||
: mDocument (document), mState (state)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
int CSMDoc::WritePathgridCollectionStage::setup()
|
int CSMDoc::WritePathgridCollectionStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -410,8 +405,7 @@ int CSMDoc::WritePathgridCollectionStage::setup()
|
||||||
void CSMDoc::WritePathgridCollectionStage::perform(int stage, Messages& messages)
|
void CSMDoc::WritePathgridCollectionStage::perform(int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
ESM::ESMWriter& writer = mState.getWriter();
|
ESM::ESMWriter& writer = mState.getWriter();
|
||||||
const CSMWorld::Record<CSMWorld::Pathgrid>& pathgrid =
|
const CSMWorld::Record<CSMWorld::Pathgrid>& pathgrid = mDocument.getData().getPathgrids().getRecord(stage);
|
||||||
mDocument.getData().getPathgrids().getRecord (stage);
|
|
||||||
|
|
||||||
if (pathgrid.isModified() || pathgrid.mState == CSMWorld::RecordBase::State_Deleted)
|
if (pathgrid.isModified() || pathgrid.mState == CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
|
@ -432,11 +426,11 @@ void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMDoc::WriteLandCollectionStage::WriteLandCollectionStage(Document& document, SavingState& state)
|
||||||
CSMDoc::WriteLandCollectionStage::WriteLandCollectionStage (Document& document,
|
: mDocument(document)
|
||||||
SavingState& state)
|
, mState(state)
|
||||||
: mDocument (document), mState (state)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
int CSMDoc::WriteLandCollectionStage::setup()
|
int CSMDoc::WriteLandCollectionStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -446,8 +440,7 @@ int CSMDoc::WriteLandCollectionStage::setup()
|
||||||
void CSMDoc::WriteLandCollectionStage::perform(int stage, Messages& messages)
|
void CSMDoc::WriteLandCollectionStage::perform(int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
ESM::ESMWriter& writer = mState.getWriter();
|
ESM::ESMWriter& writer = mState.getWriter();
|
||||||
const CSMWorld::Record<CSMWorld::Land>& land =
|
const CSMWorld::Record<CSMWorld::Land>& land = mDocument.getData().getLand().getRecord(stage);
|
||||||
mDocument.getData().getLand().getRecord (stage);
|
|
||||||
|
|
||||||
if (land.isModified() || land.mState == CSMWorld::RecordBase::State_Deleted)
|
if (land.isModified() || land.mState == CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
|
@ -458,11 +451,11 @@ void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMDoc::WriteLandTextureCollectionStage::WriteLandTextureCollectionStage(Document& document, SavingState& state)
|
||||||
CSMDoc::WriteLandTextureCollectionStage::WriteLandTextureCollectionStage (Document& document,
|
: mDocument(document)
|
||||||
SavingState& state)
|
, mState(state)
|
||||||
: mDocument (document), mState (state)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
int CSMDoc::WriteLandTextureCollectionStage::setup()
|
int CSMDoc::WriteLandTextureCollectionStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -472,8 +465,7 @@ int CSMDoc::WriteLandTextureCollectionStage::setup()
|
||||||
void CSMDoc::WriteLandTextureCollectionStage::perform(int stage, Messages& messages)
|
void CSMDoc::WriteLandTextureCollectionStage::perform(int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
ESM::ESMWriter& writer = mState.getWriter();
|
ESM::ESMWriter& writer = mState.getWriter();
|
||||||
const CSMWorld::Record<CSMWorld::LandTexture>& landTexture =
|
const CSMWorld::Record<CSMWorld::LandTexture>& landTexture = mDocument.getData().getLandTextures().getRecord(stage);
|
||||||
mDocument.getData().getLandTextures().getRecord (stage);
|
|
||||||
|
|
||||||
if (landTexture.isModified() || landTexture.mState == CSMWorld::RecordBase::State_Deleted)
|
if (landTexture.isModified() || landTexture.mState == CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
|
@ -484,10 +476,10 @@ void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& mess
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CSMDoc::CloseSaveStage::CloseSaveStage(SavingState& state)
|
CSMDoc::CloseSaveStage::CloseSaveStage(SavingState& state)
|
||||||
: mState(state)
|
: mState(state)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int CSMDoc::CloseSaveStage::setup()
|
int CSMDoc::CloseSaveStage::setup()
|
||||||
{
|
{
|
||||||
|
@ -502,10 +494,11 @@ void CSMDoc::CloseSaveStage::perform (int stage, Messages& messages)
|
||||||
throw std::runtime_error("saving failed");
|
throw std::runtime_error("saving failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CSMDoc::FinalSavingStage::FinalSavingStage(Document& document, SavingState& state)
|
CSMDoc::FinalSavingStage::FinalSavingStage(Document& document, SavingState& state)
|
||||||
: mDocument (document), mState (state)
|
: mDocument(document)
|
||||||
{}
|
, mState(state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int CSMDoc::FinalSavingStage::setup()
|
int CSMDoc::FinalSavingStage::setup()
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
#include "stage.hpp"
|
#include "stage.hpp"
|
||||||
|
|
||||||
#include "../world/record.hpp"
|
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
#include "../world/record.hpp"
|
||||||
#include "../world/scope.hpp"
|
#include "../world/scope.hpp"
|
||||||
|
|
||||||
#include <components/esm/defs.hpp>
|
#include <components/esm/defs.hpp>
|
||||||
|
@ -33,7 +33,6 @@ namespace CSMDoc
|
||||||
bool mProjectFile;
|
bool mProjectFile;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
OpenSaveStage(Document& document, SavingState& state, bool projectFile);
|
OpenSaveStage(Document& document, SavingState& state, bool projectFile);
|
||||||
///< \param projectFile Saving the project file instead of the content file.
|
///< \param projectFile Saving the project file instead of the content file.
|
||||||
|
|
||||||
|
@ -51,7 +50,6 @@ namespace CSMDoc
|
||||||
bool mSimple;
|
bool mSimple;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WriteHeaderStage(Document& document, SavingState& state, bool simple);
|
WriteHeaderStage(Document& document, SavingState& state, bool simple);
|
||||||
///< \param simple Simplified header (used for project files).
|
///< \param simple Simplified header (used for project files).
|
||||||
|
|
||||||
|
@ -62,7 +60,6 @@ namespace CSMDoc
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class CollectionT>
|
template <class CollectionT>
|
||||||
class WriteCollectionStage : public Stage
|
class WriteCollectionStage : public Stage
|
||||||
{
|
{
|
||||||
|
@ -71,9 +68,8 @@ namespace CSMDoc
|
||||||
CSMWorld::Scope mScope;
|
CSMWorld::Scope mScope;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
WriteCollectionStage(
|
||||||
WriteCollectionStage (const CollectionT& collection, SavingState& state,
|
const CollectionT& collection, SavingState& state, CSMWorld::Scope scope = CSMWorld::Scope_Content);
|
||||||
CSMWorld::Scope scope = CSMWorld::Scope_Content);
|
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
@ -83,10 +79,13 @@ namespace CSMDoc
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class CollectionT>
|
template <class CollectionT>
|
||||||
WriteCollectionStage<CollectionT>::WriteCollectionStage (const CollectionT& collection,
|
WriteCollectionStage<CollectionT>::WriteCollectionStage(
|
||||||
SavingState& state, CSMWorld::Scope scope)
|
const CollectionT& collection, SavingState& state, CSMWorld::Scope scope)
|
||||||
: mCollection (collection), mState (state), mScope (scope)
|
: mCollection(collection)
|
||||||
{}
|
, mState(state)
|
||||||
|
, mScope(scope)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template <class CollectionT>
|
template <class CollectionT>
|
||||||
int WriteCollectionStage<CollectionT>::setup()
|
int WriteCollectionStage<CollectionT>::setup()
|
||||||
|
@ -104,9 +103,8 @@ namespace CSMDoc
|
||||||
CSMWorld::RecordBase::State state = mCollection.getRecord(stage).mState;
|
CSMWorld::RecordBase::State state = mCollection.getRecord(stage).mState;
|
||||||
typename CollectionT::ESXRecord record = mCollection.getRecord(stage).get();
|
typename CollectionT::ESXRecord record = mCollection.getRecord(stage).get();
|
||||||
|
|
||||||
if (state == CSMWorld::RecordBase::State_Modified ||
|
if (state == CSMWorld::RecordBase::State_Modified || state == CSMWorld::RecordBase::State_ModifiedOnly
|
||||||
state == CSMWorld::RecordBase::State_ModifiedOnly ||
|
|| state == CSMWorld::RecordBase::State_Deleted)
|
||||||
state == CSMWorld::RecordBase::State_Deleted)
|
|
||||||
{
|
{
|
||||||
writer.startRecord(record.sRecordId, record.mRecordFlags);
|
writer.startRecord(record.sRecordId, record.mRecordFlags);
|
||||||
record.save(writer, state == CSMWorld::RecordBase::State_Deleted);
|
record.save(writer, state == CSMWorld::RecordBase::State_Deleted);
|
||||||
|
@ -114,7 +112,6 @@ namespace CSMDoc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class WriteDialogueCollectionStage : public Stage
|
class WriteDialogueCollectionStage : public Stage
|
||||||
{
|
{
|
||||||
SavingState& mState;
|
SavingState& mState;
|
||||||
|
@ -122,7 +119,6 @@ namespace CSMDoc
|
||||||
CSMWorld::InfoCollection& mInfos;
|
CSMWorld::InfoCollection& mInfos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WriteDialogueCollectionStage(Document& document, SavingState& state, bool journal);
|
WriteDialogueCollectionStage(Document& document, SavingState& state, bool journal);
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
|
@ -132,14 +128,12 @@ namespace CSMDoc
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class WriteRefIdCollectionStage : public Stage
|
class WriteRefIdCollectionStage : public Stage
|
||||||
{
|
{
|
||||||
Document& mDocument;
|
Document& mDocument;
|
||||||
SavingState& mState;
|
SavingState& mState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WriteRefIdCollectionStage(Document& document, SavingState& state);
|
WriteRefIdCollectionStage(Document& document, SavingState& state);
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
|
@ -149,14 +143,12 @@ namespace CSMDoc
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CollectionReferencesStage : public Stage
|
class CollectionReferencesStage : public Stage
|
||||||
{
|
{
|
||||||
Document& mDocument;
|
Document& mDocument;
|
||||||
SavingState& mState;
|
SavingState& mState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CollectionReferencesStage(Document& document, SavingState& state);
|
CollectionReferencesStage(Document& document, SavingState& state);
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
|
@ -174,7 +166,6 @@ namespace CSMDoc
|
||||||
void writeReferences(const std::deque<int>& references, bool interior, unsigned int& newRefNum);
|
void writeReferences(const std::deque<int>& references, bool interior, unsigned int& newRefNum);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WriteCellCollectionStage(Document& document, SavingState& state);
|
WriteCellCollectionStage(Document& document, SavingState& state);
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
|
@ -184,14 +175,12 @@ namespace CSMDoc
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class WritePathgridCollectionStage : public Stage
|
class WritePathgridCollectionStage : public Stage
|
||||||
{
|
{
|
||||||
Document& mDocument;
|
Document& mDocument;
|
||||||
SavingState& mState;
|
SavingState& mState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WritePathgridCollectionStage(Document& document, SavingState& state);
|
WritePathgridCollectionStage(Document& document, SavingState& state);
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
|
@ -201,14 +190,12 @@ namespace CSMDoc
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class WriteLandCollectionStage : public Stage
|
class WriteLandCollectionStage : public Stage
|
||||||
{
|
{
|
||||||
Document& mDocument;
|
Document& mDocument;
|
||||||
SavingState& mState;
|
SavingState& mState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WriteLandCollectionStage(Document& document, SavingState& state);
|
WriteLandCollectionStage(Document& document, SavingState& state);
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
|
@ -218,14 +205,12 @@ namespace CSMDoc
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class WriteLandTextureCollectionStage : public Stage
|
class WriteLandTextureCollectionStage : public Stage
|
||||||
{
|
{
|
||||||
Document& mDocument;
|
Document& mDocument;
|
||||||
SavingState& mState;
|
SavingState& mState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WriteLandTextureCollectionStage(Document& document, SavingState& state);
|
WriteLandTextureCollectionStage(Document& document, SavingState& state);
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
|
@ -240,7 +225,6 @@ namespace CSMDoc
|
||||||
SavingState& mState;
|
SavingState& mState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CloseSaveStage(SavingState& state);
|
CloseSaveStage(SavingState& state);
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
|
@ -256,7 +240,6 @@ namespace CSMDoc
|
||||||
SavingState& mState;
|
SavingState& mState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FinalSavingStage(Document& document, SavingState& state);
|
FinalSavingStage(Document& document, SavingState& state);
|
||||||
|
|
||||||
int setup() override;
|
int setup() override;
|
||||||
|
|
|
@ -3,12 +3,14 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "operation.hpp"
|
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
#include "operation.hpp"
|
||||||
|
|
||||||
CSMDoc::SavingState::SavingState (Operation& operation, std::filesystem::path projectPath,
|
CSMDoc::SavingState::SavingState(Operation& operation, std::filesystem::path projectPath, ToUTF8::FromType encoding)
|
||||||
ToUTF8::FromType encoding)
|
: mOperation(operation)
|
||||||
: mOperation (operation), mEncoder (encoding), mProjectPath (std::move(projectPath)), mProjectFile (false)
|
, mEncoder(encoding)
|
||||||
|
, mProjectPath(std::move(projectPath))
|
||||||
|
, mProjectFile(false)
|
||||||
{
|
{
|
||||||
mWriter.setEncoder(&mEncoder);
|
mWriter.setEncoder(&mEncoder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#ifndef CSM_DOC_SAVINGSTATE_H
|
#ifndef CSM_DOC_SAVINGSTATE_H
|
||||||
#define CSM_DOC_SAVINGSTATE_H
|
#define CSM_DOC_SAVINGSTATE_H
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <map>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <components/esm3/esmwriter.hpp>
|
#include <components/esm3/esmwriter.hpp>
|
||||||
|
|
||||||
|
@ -28,9 +28,7 @@ namespace CSMDoc
|
||||||
std::map<std::string, std::deque<int>> mSubRecords; // record ID, list of subrecords
|
std::map<std::string, std::deque<int>> mSubRecords; // record ID, list of subrecords
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
SavingState(Operation& operation, std::filesystem::path projectPath, ToUTF8::FromType encoding);
|
||||||
SavingState (Operation& operation, std::filesystem::path projectPath,
|
|
||||||
ToUTF8::FromType encoding);
|
|
||||||
|
|
||||||
bool hasError() const;
|
bool hasError() const;
|
||||||
|
|
||||||
|
@ -51,7 +49,6 @@ namespace CSMDoc
|
||||||
std::map<std::string, std::deque<int>>& getSubRecords();
|
std::map<std::string, std::deque<int>>& getSubRecords();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef CSM_DOC_STAGE_H
|
#ifndef CSM_DOC_STAGE_H
|
||||||
#define CSM_DOC_STAGE_H
|
#define CSM_DOC_STAGE_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "messages.hpp"
|
#include "messages.hpp"
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ namespace CSMDoc
|
||||||
class Stage
|
class Stage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual ~Stage();
|
virtual ~Stage();
|
||||||
|
|
||||||
virtual int setup() = 0;
|
virtual int setup() = 0;
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
CSMFilter::AndNode::AndNode(const std::vector<std::shared_ptr<Node>>& nodes)
|
CSMFilter::AndNode::AndNode(const std::vector<std::shared_ptr<Node>>& nodes)
|
||||||
: NAryNode(nodes, "and")
|
: NAryNode(nodes, "and")
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool CSMFilter::AndNode::test (const CSMWorld::IdTableBase& table, int row,
|
bool CSMFilter::AndNode::test(const CSMWorld::IdTableBase& table, int row, const std::map<int, int>& columns) const
|
||||||
const std::map<int, int>& columns) const
|
|
||||||
{
|
{
|
||||||
int size = getSize();
|
int size = getSize();
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,9 @@ namespace CSMFilter
|
||||||
class AndNode : public NAryNode
|
class AndNode : public NAryNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AndNode(const std::vector<std::shared_ptr<Node>>& nodes);
|
AndNode(const std::vector<std::shared_ptr<Node>>& nodes);
|
||||||
|
|
||||||
bool test (const CSMWorld::IdTableBase& table, int row,
|
bool test(const CSMWorld::IdTableBase& table, int row, const std::map<int, int>& columns) const override;
|
||||||
const std::map<int, int>& columns) const override;
|
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#include "booleannode.hpp"
|
#include "booleannode.hpp"
|
||||||
|
|
||||||
CSMFilter::BooleanNode::BooleanNode (bool true_) : mTrue (true_) {}
|
CSMFilter::BooleanNode::BooleanNode(bool true_)
|
||||||
|
: mTrue(true_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool CSMFilter::BooleanNode::test (const CSMWorld::IdTableBase& table, int row,
|
bool CSMFilter::BooleanNode::test(const CSMWorld::IdTableBase& table, int row, const std::map<int, int>& columns) const
|
||||||
const std::map<int, int>& columns) const
|
|
||||||
{
|
{
|
||||||
return mTrue;
|
return mTrue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,9 @@ namespace CSMFilter
|
||||||
bool mTrue;
|
bool mTrue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
BooleanNode(bool true_);
|
BooleanNode(bool true_);
|
||||||
|
|
||||||
bool test (const CSMWorld::IdTableBase& table, int row,
|
bool test(const CSMWorld::IdTableBase& table, int row, const std::map<int, int>& columns) const override;
|
||||||
const std::map<int, int>& columns) const override;
|
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
|
|
||||||
|
@ -22,7 +20,6 @@ namespace CSMFilter
|
||||||
///< Return a string that represents this node.
|
///< Return a string that represents this node.
|
||||||
///
|
///
|
||||||
/// \param numericColumns Use numeric IDs instead of string to represent columns.
|
/// \param numericColumns Use numeric IDs instead of string to represent columns.
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,4 +4,3 @@ std::vector<int> CSMFilter::LeafNode::getReferencedColumns() const
|
||||||
{
|
{
|
||||||
return std::vector<int>();
|
return std::vector<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ namespace CSMFilter
|
||||||
class LeafNode : public Node
|
class LeafNode : public Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
std::vector<int> getReferencedColumns() const override;
|
std::vector<int> getReferencedColumns() const override;
|
||||||
///< Return a list of the IDs of the columns referenced by this node. The column mapping
|
///< Return a list of the IDs of the columns referenced by this node. The column mapping
|
||||||
/// passed into test as columns must contain all columns listed here.
|
/// passed into test as columns must contain all columns listed here.
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
CSMFilter::NAryNode::NAryNode (const std::vector<std::shared_ptr<Node> >& nodes,
|
CSMFilter::NAryNode::NAryNode(const std::vector<std::shared_ptr<Node>>& nodes, const std::string& name)
|
||||||
const std::string& name)
|
: mNodes(nodes)
|
||||||
: mNodes (nodes), mName (name)
|
, mName(name)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int CSMFilter::NAryNode::getSize() const
|
int CSMFilter::NAryNode::getSize() const
|
||||||
{
|
{
|
||||||
|
@ -21,8 +22,7 @@ std::vector<int> CSMFilter::NAryNode::getReferencedColumns() const
|
||||||
{
|
{
|
||||||
std::vector<int> columns;
|
std::vector<int> columns;
|
||||||
|
|
||||||
for (std::vector<std::shared_ptr<Node> >::const_iterator iter (mNodes.begin());
|
for (std::vector<std::shared_ptr<Node>>::const_iterator iter(mNodes.begin()); iter != mNodes.end(); ++iter)
|
||||||
iter!=mNodes.end(); ++iter)
|
|
||||||
{
|
{
|
||||||
std::vector<int> columns2 = (*iter)->getReferencedColumns();
|
std::vector<int> columns2 = (*iter)->getReferencedColumns();
|
||||||
|
|
||||||
|
@ -55,5 +55,3 @@ std::string CSMFilter::NAryNode::toString (bool numericColumns) const
|
||||||
|
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef CSM_FILTER_NARYNODE_H
|
#ifndef CSM_FILTER_NARYNODE_H
|
||||||
#define CSM_FILTER_NARYNODE_H
|
#define CSM_FILTER_NARYNODE_H
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "node.hpp"
|
#include "node.hpp"
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ namespace CSMFilter
|
||||||
std::string mName;
|
std::string mName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NAryNode(const std::vector<std::shared_ptr<Node>>& nodes, const std::string& name);
|
NAryNode(const std::vector<std::shared_ptr<Node>>& nodes, const std::string& name);
|
||||||
|
|
||||||
int getSize() const;
|
int getSize() const;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#ifndef CSM_FILTER_NODE_H
|
#ifndef CSM_FILTER_NODE_H
|
||||||
#define CSM_FILTER_NODE_H
|
#define CSM_FILTER_NODE_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
@ -26,13 +26,11 @@ namespace CSMFilter
|
||||||
Node& operator=(const Node&);
|
Node& operator=(const Node&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Node();
|
Node();
|
||||||
|
|
||||||
virtual ~Node();
|
virtual ~Node();
|
||||||
|
|
||||||
virtual bool test (const CSMWorld::IdTableBase& table, int row,
|
virtual bool test(const CSMWorld::IdTableBase& table, int row, const std::map<int, int>& columns) const = 0;
|
||||||
const std::map<int, int>& columns) const = 0;
|
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#include "notnode.hpp"
|
#include "notnode.hpp"
|
||||||
|
|
||||||
CSMFilter::NotNode::NotNode (std::shared_ptr<Node> child) : UnaryNode (child, "not") {}
|
CSMFilter::NotNode::NotNode(std::shared_ptr<Node> child)
|
||||||
|
: UnaryNode(child, "not")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool CSMFilter::NotNode::test (const CSMWorld::IdTableBase& table, int row,
|
bool CSMFilter::NotNode::test(const CSMWorld::IdTableBase& table, int row, const std::map<int, int>& columns) const
|
||||||
const std::map<int, int>& columns) const
|
|
||||||
{
|
{
|
||||||
return !getChild().test(table, row, columns);
|
return !getChild().test(table, row, columns);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,9 @@ namespace CSMFilter
|
||||||
class NotNode : public UnaryNode
|
class NotNode : public UnaryNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NotNode(std::shared_ptr<Node> child);
|
NotNode(std::shared_ptr<Node> child);
|
||||||
|
|
||||||
bool test (const CSMWorld::IdTableBase& table, int row,
|
bool test(const CSMWorld::IdTableBase& table, int row, const std::map<int, int>& columns) const override;
|
||||||
const std::map<int, int>& columns) const override;
|
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
CSMFilter::OrNode::OrNode(const std::vector<std::shared_ptr<Node>>& nodes)
|
CSMFilter::OrNode::OrNode(const std::vector<std::shared_ptr<Node>>& nodes)
|
||||||
: NAryNode(nodes, "or")
|
: NAryNode(nodes, "or")
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool CSMFilter::OrNode::test (const CSMWorld::IdTableBase& table, int row,
|
bool CSMFilter::OrNode::test(const CSMWorld::IdTableBase& table, int row, const std::map<int, int>& columns) const
|
||||||
const std::map<int, int>& columns) const
|
|
||||||
{
|
{
|
||||||
int size = getSize();
|
int size = getSize();
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,9 @@ namespace CSMFilter
|
||||||
class OrNode : public NAryNode
|
class OrNode : public NAryNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
OrNode(const std::vector<std::shared_ptr<Node>>& nodes);
|
OrNode(const std::vector<std::shared_ptr<Node>>& nodes);
|
||||||
|
|
||||||
bool test (const CSMWorld::IdTableBase& table, int row,
|
bool test(const CSMWorld::IdTableBase& table, int row, const std::map<int, int>& columns) const override;
|
||||||
const std::map<int, int>& columns) const override;
|
|
||||||
///< \return Can the specified table row pass through to filter?
|
///< \return Can the specified table row pass through to filter?
|
||||||
/// \param columns column ID to column index mapping
|
/// \param columns column ID to column index mapping
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <stdexcept>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <components/misc/strings/lower.hpp>
|
#include <components/misc/strings/lower.hpp>
|
||||||
|
|
||||||
|
@ -10,10 +10,10 @@
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
#include "../world/idcollection.hpp"
|
#include "../world/idcollection.hpp"
|
||||||
|
|
||||||
#include "booleannode.hpp"
|
|
||||||
#include "ornode.hpp"
|
|
||||||
#include "andnode.hpp"
|
#include "andnode.hpp"
|
||||||
|
#include "booleannode.hpp"
|
||||||
#include "notnode.hpp"
|
#include "notnode.hpp"
|
||||||
|
#include "ornode.hpp"
|
||||||
#include "textnode.hpp"
|
#include "textnode.hpp"
|
||||||
#include "valuenode.hpp"
|
#include "valuenode.hpp"
|
||||||
|
|
||||||
|
@ -73,13 +73,31 @@ namespace CSMFilter
|
||||||
bool isString() const;
|
bool isString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
Token::Token (Type type) : mType (type), mNumber(0.0) {}
|
Token::Token(Type type)
|
||||||
|
: mType(type)
|
||||||
|
, mNumber(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Token::Token (Type type, const std::string& string) : mType (type), mString (string), mNumber(0.0) {}
|
Token::Token(Type type, const std::string& string)
|
||||||
|
: mType(type)
|
||||||
|
, mString(string)
|
||||||
|
, mNumber(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Token::Token (const std::string& string) : mType (Type_String), mString (string), mNumber(0.0) {}
|
Token::Token(const std::string& string)
|
||||||
|
: mType(Type_String)
|
||||||
|
, mString(string)
|
||||||
|
, mNumber(0.0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Token::Token (double number) : mType (Type_Number), mNumber (number) {}
|
Token::Token(double number)
|
||||||
|
: mType(Type_Number)
|
||||||
|
, mNumber(number)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool Token::isString() const
|
bool Token::isString() const
|
||||||
{
|
{
|
||||||
|
@ -98,10 +116,13 @@ namespace CSMFilter
|
||||||
|
|
||||||
switch (left.mType)
|
switch (left.mType)
|
||||||
{
|
{
|
||||||
case Token::Type_String: return left.mString==right.mString;
|
case Token::Type_String:
|
||||||
case Token::Type_Number: return left.mNumber==right.mNumber;
|
return left.mString == right.mString;
|
||||||
|
case Token::Type_Number:
|
||||||
|
return left.mNumber == right.mNumber;
|
||||||
|
|
||||||
default: return true;
|
default:
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,8 +137,8 @@ CSMFilter::Token CSMFilter::Parser::getStringToken()
|
||||||
{
|
{
|
||||||
char c = mInput[mIndex];
|
char c = mInput[mIndex];
|
||||||
|
|
||||||
if (isAlpha(c) || c==':' || c=='_' || (!string.empty() && isDigit(c)) || c=='"' ||
|
if (isAlpha(c) || c == ':' || c == '_' || (!string.empty() && isDigit(c)) || c == '"'
|
||||||
(!string.empty() && string[0]=='"'))
|
|| (!string.empty() && string[0] == '"'))
|
||||||
string += c;
|
string += c;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -194,11 +215,14 @@ CSMFilter::Token CSMFilter::Parser::getNumberToken()
|
||||||
|
|
||||||
CSMFilter::Token CSMFilter::Parser::checkKeywords(const Token& token)
|
CSMFilter::Token CSMFilter::Parser::checkKeywords(const Token& token)
|
||||||
{
|
{
|
||||||
static const char *sKeywords[] =
|
static const char* sKeywords[] = {
|
||||||
{
|
"true",
|
||||||
"true", "false",
|
"false",
|
||||||
"and", "or", "not",
|
"and",
|
||||||
"string", "value",
|
"or",
|
||||||
|
"not",
|
||||||
|
"string",
|
||||||
|
"value",
|
||||||
nullptr,
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,12 +254,24 @@ CSMFilter::Token CSMFilter::Parser::getNextToken()
|
||||||
|
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case '(': ++mIndex; return Token (Token::Type_Open);
|
case '(':
|
||||||
case ')': ++mIndex; return Token (Token::Type_Close);
|
++mIndex;
|
||||||
case '[': ++mIndex; return Token (Token::Type_OpenSquare);
|
return Token(Token::Type_Open);
|
||||||
case ']': ++mIndex; return Token (Token::Type_CloseSquare);
|
case ')':
|
||||||
case ',': ++mIndex; return Token (Token::Type_Comma);
|
++mIndex;
|
||||||
case '!': ++mIndex; return Token (Token::Type_OneShot);
|
return Token(Token::Type_Close);
|
||||||
|
case '[':
|
||||||
|
++mIndex;
|
||||||
|
return Token(Token::Type_OpenSquare);
|
||||||
|
case ']':
|
||||||
|
++mIndex;
|
||||||
|
return Token(Token::Type_CloseSquare);
|
||||||
|
case ',':
|
||||||
|
++mIndex;
|
||||||
|
return Token(Token::Type_Comma);
|
||||||
|
case '!':
|
||||||
|
++mIndex;
|
||||||
|
return Token(Token::Type_OneShot);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == '"' || c == '_' || isAlpha(c) || c == ':')
|
if (c == '"' || c == '_' || isAlpha(c) || c == ':')
|
||||||
|
@ -340,9 +376,13 @@ std::shared_ptr<CSMFilter::Node> CSMFilter::Parser::parseNAry (const Token& keyw
|
||||||
|
|
||||||
switch (keyword.mType)
|
switch (keyword.mType)
|
||||||
{
|
{
|
||||||
case Token::Type_Keyword_And: return std::make_shared<AndNode>(nodes);
|
case Token::Type_Keyword_And:
|
||||||
case Token::Type_Keyword_Or: return std::make_shared<OrNode>(nodes);
|
return std::make_shared<AndNode>(nodes);
|
||||||
default: error(); return std::shared_ptr<Node>();
|
case Token::Type_Keyword_Or:
|
||||||
|
return std::make_shared<OrNode>(nodes);
|
||||||
|
default:
|
||||||
|
error();
|
||||||
|
return std::shared_ptr<Node>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,7 +581,11 @@ void CSMFilter::Parser::error()
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMFilter::Parser::Parser(const CSMWorld::Data& data)
|
CSMFilter::Parser::Parser(const CSMWorld::Data& data)
|
||||||
: mIndex (0), mError (false), mData (data) {}
|
: mIndex(0)
|
||||||
|
, mError(false)
|
||||||
|
, mData(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool CSMFilter::Parser::parse(const std::string& filter, bool allowPredefined)
|
bool CSMFilter::Parser::parse(const std::string& filter, bool allowPredefined)
|
||||||
{
|
{
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue