From b248c3e1737f76ae0851ef58342ba7563de5111a Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 31 Dec 2022 22:08:17 +0100 Subject: [PATCH 01/37] Allow passing `initData` to the :addSript call (#7091) --- apps/openmw/mwlua/luamanagerimp.cpp | 4 ++-- apps/openmw/mwlua/luamanagerimp.hpp | 2 +- apps/openmw/mwlua/objectbindings.cpp | 13 +++++++++---- components/lua/scriptscontainer.cpp | 7 +++---- components/lua/scriptscontainer.hpp | 2 +- files/lua_api/openmw/core.lua | 1 + 6 files changed, 17 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwlua/luamanagerimp.cpp b/apps/openmw/mwlua/luamanagerimp.cpp index c11a87eaac..8516e5e21f 100644 --- a/apps/openmw/mwlua/luamanagerimp.cpp +++ b/apps/openmw/mwlua/luamanagerimp.cpp @@ -401,7 +401,7 @@ namespace MWLua return localScripts->getActorControls(); } - void LuaManager::addCustomLocalScript(const MWWorld::Ptr& ptr, int scriptId) + void LuaManager::addCustomLocalScript(const MWWorld::Ptr& ptr, int scriptId, std::string_view initData) { LocalScripts* localScripts = ptr.getRefData().getLuaScripts(); if (!localScripts) @@ -411,7 +411,7 @@ namespace MWLua if (ptr.isInCell() && MWBase::Environment::get().getWorldScene()->isCellActive(*ptr.getCell())) mActiveLocalScripts.insert(localScripts); } - localScripts->addCustomScript(scriptId); + localScripts->addCustomScript(scriptId, initData); } LocalScripts* LuaManager::createLocalScripts( diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index 9d02d11a3d..6482b7ddeb 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -57,7 +57,7 @@ namespace MWLua void setupPlayer(const MWWorld::Ptr& ptr) override; // Should be called once after each "clear". // Used only in Lua bindings - void addCustomLocalScript(const MWWorld::Ptr&, int scriptId); + void addCustomLocalScript(const MWWorld::Ptr&, int scriptId, std::string_view initData); void addUIMessage(std::string_view message) { mUIMessages.emplace_back(message); } void addInGameConsoleMessage(const std::string& msg, const Misc::Color& color) { diff --git a/apps/openmw/mwlua/objectbindings.cpp b/apps/openmw/mwlua/objectbindings.cpp index ab0e686e86..4fe520e68c 100644 --- a/apps/openmw/mwlua/objectbindings.cpp +++ b/apps/openmw/mwlua/objectbindings.cpp @@ -200,9 +200,9 @@ namespace MWLua if constexpr (std::is_same_v) { // Only for global scripts - objectT["addScript"] = [lua = context.mLua, luaManager = context.mLuaManager]( - const GObject& object, std::string_view path) { - const LuaUtil::ScriptsConfiguration& cfg = lua->getConfiguration(); + objectT["addScript"] = [context](const GObject& object, std::string_view path, + sol::optional initData) { + const LuaUtil::ScriptsConfiguration& cfg = context.mLua->getConfiguration(); std::optional scriptId = cfg.findId(path); if (!scriptId) throw std::runtime_error("Unknown script: " + std::string(path)); @@ -211,7 +211,12 @@ namespace MWLua "Script without CUSTOM tag can not be added dynamically: " + std::string(path)); if (object.ptr().getType() == ESM::REC_STAT) throw std::runtime_error("Attaching scripts to Static is not allowed: " + std::string(path)); - luaManager->addCustomLocalScript(object.ptr(), *scriptId); + if (initData) + context.mLuaManager->addCustomLocalScript( + object.ptr(), *scriptId, LuaUtil::serialize(*initData, context.mSerializer)); + else + context.mLuaManager->addCustomLocalScript( + object.ptr(), *scriptId, cfg[*scriptId].mInitializationData); }; objectT["hasScript"] = [lua = context.mLua](const GObject& object, std::string_view path) { const LuaUtil::ScriptsConfiguration& cfg = lua->getConfiguration(); diff --git a/components/lua/scriptscontainer.cpp b/components/lua/scriptscontainer.cpp index 6b6151b293..6f18727019 100644 --- a/components/lua/scriptscontainer.cpp +++ b/components/lua/scriptscontainer.cpp @@ -35,14 +35,13 @@ namespace LuaUtil mAPI.emplace(std::move(packageName), makeReadOnly(std::move(package))); } - bool ScriptsContainer::addCustomScript(int scriptId) + bool ScriptsContainer::addCustomScript(int scriptId, std::string_view initData) { - const ScriptsConfiguration& conf = mLua.getConfiguration(); - assert(conf.isCustomScript(scriptId)); + assert(mLua.getConfiguration().isCustomScript(scriptId)); std::optional onInit, onLoad; bool ok = addScript(scriptId, onInit, onLoad); if (ok && onInit) - callOnInit(scriptId, *onInit, conf[scriptId].mInitializationData); + callOnInit(scriptId, *onInit, initData); return ok; } diff --git a/components/lua/scriptscontainer.hpp b/components/lua/scriptscontainer.hpp index ebc7fd6d55..0177281be1 100644 --- a/components/lua/scriptscontainer.hpp +++ b/components/lua/scriptscontainer.hpp @@ -91,7 +91,7 @@ namespace LuaUtil // new script, adds it to the container, and calls onInit for this script. Returns `true` if the script was // successfully added. The script should have CUSTOM flag. If the flag is not set, or file not found, or has // syntax errors, returns false. If such script already exists in the container, then also returns false. - bool addCustomScript(int scriptId); + bool addCustomScript(int scriptId, std::string_view initData = ""); bool hasScript(int scriptId) const { return mScripts.count(scriptId) != 0; } void removeScript(int scriptId); diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 38f73ec669..a39df78911 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -144,6 +144,7 @@ -- @function [parent=#GameObject] addScript -- @param self -- @param #string scriptPath Path to the script in OpenMW virtual filesystem. +-- @param #table initData (optional) Initialization data to be passed to onInit. If missed then Lua initialization data from content files will be used (if exists for this script). --- -- Whether a script with given path is attached to this object. From c721a6cafa2d1a4d31a2e84e888b24685ae13478 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 28 Dec 2022 20:48:25 +0100 Subject: [PATCH 02/37] Initial commit to load ESM4 Some data is actually loaded and store in ESM Store Any new ESM4 will go through the same code path and be automatically sent to the right store --- apps/openmw/mwworld/esmloader.cpp | 56 ++++++++++++++----- apps/openmw/mwworld/esmstore.cpp | 93 +++++++++++++++++++++++++++++++ apps/openmw/mwworld/esmstore.hpp | 13 ++++- apps/openmw/mwworld/store.cpp | 31 +++++++++-- components/esm/defs.hpp | 5 ++ components/esm/refid.cpp | 5 ++ components/esm/refid.hpp | 2 + components/esm4/loadcell.cpp | 10 ++-- components/esm4/loadcell.hpp | 6 +- components/esm4/loadrefr.cpp | 13 +++-- components/esm4/loadrefr.hpp | 12 ++-- components/esm4/loadstat.cpp | 7 ++- components/esm4/loadstat.hpp | 6 +- components/to_utf8/to_utf8.hpp | 2 + 14 files changed, 221 insertions(+), 40 deletions(-) diff --git a/apps/openmw/mwworld/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index 3c1b6acc47..3265059a13 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -1,9 +1,13 @@ #include "esmloader.hpp" #include "esmstore.hpp" +#include #include #include +#include #include +#include +#include namespace MWWorld { @@ -21,28 +25,50 @@ namespace MWWorld void EsmLoader::load(const std::filesystem::path& filepath, int& index, Loading::Listener* listener) { - const ESM::ReadersCache::BusyItem reader = mReaders.get(static_cast(index)); - reader->setEncoder(mEncoder); - reader->setIndex(index); - reader->open(filepath); - reader->resolveParentFileIndices(mReaders); + auto stream = Files::openBinaryInputFileStream(filepath); + if (!stream->is_open()) + { + throw std::runtime_error(std::string("File Failed to open file: ") + std::strerror(errno) + "\n"); + return; + } + const ESM::Format format = ESM::readFormat(*stream); + stream->seekg(0); - assert(reader->getGameFiles().size() == reader->getParentFileIndices().size()); - for (std::size_t i = 0, n = reader->getParentFileIndices().size(); i < n; ++i) - if (i == static_cast(reader->getIndex())) - throw std::runtime_error("File " + Files::pathToUnicodeString(reader->getName()) + " asks for parent file " + switch (format) + { + case ESM::Format::Tes3: + { + const ESM::ReadersCache::BusyItem reader = mReaders.get(static_cast(index)); + reader->setEncoder(mEncoder); + reader->setIndex(index); + reader->open(filepath); + reader->resolveParentFileIndices(mReaders); + + assert(reader->getGameFiles().size() == reader->getParentFileIndices().size()); + for (std::size_t i = 0, n = reader->getParentFileIndices().size(); i < n; ++i) + if (i == static_cast(reader->getIndex())) + throw std::runtime_error("File " + Files::pathToUnicodeString(reader->getName()) + " asks for parent file " + reader->getGameFiles()[i].name + ", but it is not available or has been loaded in the wrong order. " "Please run the launcher to fix this issue."); - mESMVersions[index] = reader->getVer(); - mStore.load(*reader, listener, mDialogue); + mESMVersions[index] = reader->getVer(); + mStore.load(*reader, listener, mDialogue); - if (!mMasterFileFormat.has_value() - && (Misc::StringUtils::ciEndsWith(reader->getName().u8string(), u8".esm") - || Misc::StringUtils::ciEndsWith(reader->getName().u8string(), u8".omwgame"))) - mMasterFileFormat = reader->getFormat(); + if (!mMasterFileFormat.has_value() + && (Misc::StringUtils::ciEndsWith(reader->getName().u8string(), u8".esm") + || Misc::StringUtils::ciEndsWith(reader->getName().u8string(), u8".omwgame"))) + mMasterFileFormat = reader->getFormat(); + break; + } + case ESM::Format::Tes4: + { + ESM4::Reader readerESM4(std::move(stream), filepath); + readerESM4.setEncoder(mEncoder->getStatelessEncoder()); + mStore.loadESM4(readerESM4, listener, mDialogue); + } + } } } /* namespace MWWorld */ diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 03de9fda5d..15bf52757e 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -13,6 +13,11 @@ #include #include +#include +#include +#include +#include + #include #include @@ -180,6 +185,84 @@ namespace MWWorld } } } + + template + static void typedReadRecordESM4(ESM4::Reader& reader, ESMStore& stores, Store& store, int& found) + { + auto recordType = static_cast(reader.hdr().record.typeId); + + ESM::RecNameInts esm4RecName = static_cast(ESM::esm4Recname(recordType)); + if constexpr (std::is_convertible_v*, DynamicStore*>) + { + if constexpr (ESM::isESM4Rec(T::sRecordId)) + { + if (T::sRecordId == esm4RecName) + { + reader.getRecordData(); + T value; + value.load(reader); + store.insertStatic(value); + found++; + } + } + } + } + + static void readRecord(ESM4::Reader& reader, ESMStore& store) + { + int found = 0; + std::apply([&reader, &store, &found]( + auto&... x) { (ESMStoreImp::typedReadRecordESM4(reader, store, x, found), ...); }, + store.mStoreImp->mStores); + assert(found <= 1); + if (found == 0) // unhandled record + reader.skipRecordData(); + } + + static bool readItem(ESM4::Reader& reader, ESMStore& store) + { + if (!reader.getRecordHeader() || !reader.hasMoreRecs()) + return false; + + const ESM4::RecordHeader& header = reader.hdr(); + + if (header.record.typeId == ESM4::REC_GRUP) + return readGroup(reader, store); + + readRecord(reader, store); + return true; + } + + static bool readGroup(ESM4::Reader& reader, ESMStore& store) + { + const ESM4::RecordHeader& header = reader.hdr(); + + switch (static_cast(header.group.type)) + { + case ESM4::Grp_RecordType: + case ESM4::Grp_InteriorCell: + case ESM4::Grp_InteriorSubCell: + case ESM4::Grp_ExteriorCell: + case ESM4::Grp_ExteriorSubCell: + reader.enterGroup(); + return readItem(reader, store); + case ESM4::Grp_WorldChild: + case ESM4::Grp_CellChild: + case ESM4::Grp_TopicChild: + case ESM4::Grp_CellPersistentChild: + case ESM4::Grp_CellTemporaryChild: + case ESM4::Grp_CellVisibleDistChild: + reader.adjustGRUPFormId(); + reader.enterGroup(); + if (!reader.hasMoreRecs()) + return false; + return readItem(reader, store); + } + + reader.skipGroup(); + + return true; + } }; int ESMStore::find(const ESM::RefId& id) const @@ -338,6 +421,16 @@ namespace MWWorld } } + void ESMStore::loadESM4(ESM4::Reader& reader, Loading::Listener* listener, ESM::Dialogue*& dialogue) + { + while (reader.hasMoreRecs()) + { + reader.exitGroupCheck(); + if (!ESMStoreImp::readItem(reader, *this)) + break; + } + } + void ESMStore::setIdType(const ESM::RefId& id, ESM::RecNameInts type) { mStoreImp->mIds[id] = type; diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 7f5773c957..1ed66a1c71 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -24,6 +24,14 @@ namespace MWMechanics class SpellList; } +namespace ESM4 +{ + class Reader; + struct Static; + struct Cell; + struct Reference; +} + namespace ESM { class ReadersCache; @@ -95,7 +103,9 @@ namespace MWWorld Store, Store, // Special entry which is hardcoded and not loaded from an ESM - Store>; + Store, + + Store, Store, Store>; template static constexpr std::size_t getTypeIndex() @@ -162,6 +172,7 @@ namespace MWWorld void validateDynamic(); void load(ESM::ESMReader& esm, Loading::Listener* listener, ESM::Dialogue*& dialogue); + void loadESM4(ESM4::Reader& esm, Loading::Listener* listener, ESM::Dialogue*& dialogue); template const Store& get() const diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 11e58c0edb..27d74ddf59 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -13,6 +13,10 @@ #include #include +#include +#include +#include + namespace { // TODO: Switch to C++23 to get a working version of std::unordered_map::erase @@ -161,7 +165,10 @@ namespace MWWorld if (ptr == nullptr) { std::stringstream msg; - msg << T::getRecordType() << " '" << id << "' not found"; + if constexpr (!ESM::isESM4Rec(T::sRecordId)) + { + msg << T::getRecordType() << " '" << id << "' not found"; + } throw std::runtime_error(msg.str()); } return ptr; @@ -171,8 +178,10 @@ namespace MWWorld { T record; bool isDeleted = false; - - record.load(esm, isDeleted); + if constexpr (!ESM::isESM4Rec(T::sRecordId)) + { + record.load(esm, isDeleted); + } std::pair inserted = mStatic.insert_or_assign(record.mId, record); if (inserted.second) @@ -293,7 +302,11 @@ namespace MWWorld for (typename Dynamic::const_iterator iter(mDynamic.begin()); iter != mDynamic.end(); ++iter) { writer.startRecord(T::sRecordId); - iter->second.save(writer); + if constexpr (!ESM::isESM4Rec(T::sRecordId)) + { + iter->second.save(writer); + } + writer.endRecord(T::sRecordId); } } @@ -302,8 +315,10 @@ namespace MWWorld { T record; bool isDeleted = false; - - record.load(reader, isDeleted); + if constexpr (!ESM::isESM4Rec(T::sRecordId)) + { + record.load(reader, isDeleted); + } insert(record, overrideOnly); return RecordId(record.mId, isDeleted); @@ -1196,3 +1211,7 @@ template class MWWorld::TypedDynamicStore; template class MWWorld::TypedDynamicStore; template class MWWorld::TypedDynamicStore; template class MWWorld::TypedDynamicStore; + +template class MWWorld::TypedDynamicStore; +template class MWWorld::TypedDynamicStore; +template class MWWorld::TypedDynamicStore; diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index f3e1ad640e..431b85b9ae 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -333,6 +333,11 @@ namespace ESM REC_MSET4 = esm4Recname(ESM4::REC_MSET) // Media Set }; + constexpr bool isESM4Rec(RecNameInts RecName) + { + return RecName & sEsm4RecnameFlag; + } + /// Common subrecords enum SubRecNameInts { diff --git a/components/esm/refid.cpp b/components/esm/refid.cpp index ec18c4c642..3470ebd3d3 100644 --- a/components/esm/refid.cpp +++ b/components/esm/refid.cpp @@ -34,6 +34,11 @@ namespace ESM return newRefId; } + RefId RefId::formIdRefId(const ESM4::FormId id) + { + return ESM::RefId::stringRefId(ESM4::formIdToString(id)); + } + bool RefId::operator==(std::string_view rhs) const { return Misc::StringUtils::ciEqual(mId, rhs); diff --git a/components/esm/refid.hpp b/components/esm/refid.hpp index 6bc49313d0..8900f7ce75 100644 --- a/components/esm/refid.hpp +++ b/components/esm/refid.hpp @@ -1,6 +1,7 @@ #ifndef OPENMW_COMPONENTS_ESM_REFID_HPP #define OPENMW_COMPONENTS_ESM_REFID_HPP #include +#include #include #include #include @@ -26,6 +27,7 @@ namespace ESM // RefIds that are as string in the code. For serialization, and display. Using explicit conversions make it // very clear where in the code we need to convert from string to RefId and Vice versa. static RefId stringRefId(std::string_view id); + static RefId formIdRefId(const ESM4::FormId id); const std::string& getRefIdString() const { return mId; } private: diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 919c81b8e9..1321e31578 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -37,7 +37,8 @@ #include // FIXME: debug only #include "reader.hpp" -//#include "writer.hpp" +#include +// #include "writer.hpp" // TODO: Try loading only EDID and XCLC (along with mFormId, mFlags and mParent) // @@ -48,8 +49,9 @@ // longer/shorter/same as loading the subrecords. void ESM4::Cell::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; - reader.adjustFormId(mFormId); + auto formId = reader.hdr().record.id; + reader.adjustFormId(formId); + mId = ESM::RefId::formIdRefId(formId); mFlags = reader.hdr().record.flags; mParent = reader.currWorld(); @@ -71,7 +73,7 @@ void ESM4::Cell::load(ESM4::Reader& reader) // WARN: we need to call setCurrCell (and maybe setCurrCellGrid?) again before loading // cell child groups if we are loading them after restoring the context // (may be easier to update the context before saving?) - reader.setCurrCell(mFormId); // save for LAND (and other children) to access later + reader.setCurrCell(formId); // save for LAND (and other children) to access later std::uint32_t esmVer = reader.esmVersion(); bool isFONV = esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134; diff --git a/components/esm4/loadcell.hpp b/components/esm4/loadcell.hpp index ee77bd2bfc..bcc95f652f 100644 --- a/components/esm4/loadcell.hpp +++ b/components/esm4/loadcell.hpp @@ -33,6 +33,8 @@ #include "formid.hpp" #include "lighting.hpp" +#include +#include namespace ESM4 { @@ -61,7 +63,7 @@ namespace ESM4 { FormId mParent; // world formId (for grouping cells), from the loading sequence - FormId mFormId; // from the header + ESM::RefId mId; // from the header std::uint32_t mFlags; // from the header, see enum type RecordFlag for details std::string mEditorId; @@ -95,6 +97,8 @@ namespace ESM4 // void save(ESM4::Writer& writer) const; void blank(); + + static constexpr ESM::RecNameInts sRecordId = ESM::REC_CELL4; }; } diff --git a/components/esm4/loadrefr.cpp b/components/esm4/loadrefr.cpp index d96f52a741..b95f24e73a 100644 --- a/components/esm4/loadrefr.cpp +++ b/components/esm4/loadrefr.cpp @@ -30,14 +30,15 @@ #include #include "reader.hpp" -//#include "writer.hpp" +// #include "writer.hpp" void ESM4::Reference::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; - reader.adjustFormId(mFormId); + auto formId = reader.hdr().record.id; + reader.adjustFormId(formId); + mId = ESM::RefId::formIdRefId(formId); mFlags = reader.hdr().record.flags; - mParent = reader.currCell(); // NOTE: only for persistent refs? + mParent = ESM::RefId::formIdRefId(reader.currCell()); // NOTE: only for persistent refs? // TODO: Let the engine apply this? Saved games? // mInitiallyDisabled = ((mFlags & ESM4::Rec_Disabled) != 0) ? true : false; @@ -60,7 +61,9 @@ void ESM4::Reference::load(ESM4::Reader& reader) break; case ESM4::SUB_NAME: { - reader.getFormId(mBaseObj); + FormId BaseId; + reader.getFormId(BaseId); + mBaseObj = ESM::RefId::formIdRefId(BaseId); #if 0 if (mFlags & ESM4::Rec_Disabled) std::cout << "REFR disable at start " << formIdToString(mFormId) << diff --git a/components/esm4/loadrefr.hpp b/components/esm4/loadrefr.hpp index 04d537932e..baf199c4c4 100644 --- a/components/esm4/loadrefr.hpp +++ b/components/esm4/loadrefr.hpp @@ -30,6 +30,8 @@ #include #include "reference.hpp" // FormId, Placement, EnableParent +#include +#include namespace ESM4 { @@ -71,15 +73,15 @@ namespace ESM4 struct Reference { - FormId mParent; // cell FormId (currently persistent refs only), from the loading sequence - // NOTE: for exterior cells it will be the dummy cell FormId + ESM::RefId mParent; // cell FormId (currently persistent refs only), from the loading sequence + // NOTE: for exterior cells it will be the dummy cell FormId - FormId mFormId; // from the header + ESM::RefId mId; // from the header std::uint32_t mFlags; // from the header, see enum type RecordFlag for details std::string mEditorId; std::string mFullName; - FormId mBaseObj; + ESM::RefId mBaseObj; Placement mPlacement; float mScale = 1.0f; @@ -110,6 +112,8 @@ namespace ESM4 // void save(ESM4::Writer& writer) const; void blank(); + + static constexpr ESM::RecNameInts sRecordId = ESM::REC_REFR4; }; } diff --git a/components/esm4/loadstat.cpp b/components/esm4/loadstat.cpp index e8e789cb1b..edfbf0e4e6 100644 --- a/components/esm4/loadstat.cpp +++ b/components/esm4/loadstat.cpp @@ -30,12 +30,13 @@ #include #include "reader.hpp" -//#include "writer.hpp" +// #include "writer.hpp" void ESM4::Static::load(ESM4::Reader& reader) { - mFormId = reader.hdr().record.id; - reader.adjustFormId(mFormId); + FormId formId = reader.hdr().record.id; + reader.adjustFormId(formId); + mId = ESM::RefId::formIdRefId(formId); mFlags = reader.hdr().record.flags; while (reader.getSubRecordHeader()) diff --git a/components/esm4/loadstat.hpp b/components/esm4/loadstat.hpp index f34ba6a1cf..5d79f84d6f 100644 --- a/components/esm4/loadstat.hpp +++ b/components/esm4/loadstat.hpp @@ -32,6 +32,8 @@ #include #include "formid.hpp" +#include +#include namespace ESM4 { @@ -40,7 +42,7 @@ namespace ESM4 struct Static { - FormId mFormId; // from the header + ESM::RefId mId; // from the header std::uint32_t mFlags; // from the header, see enum type RecordFlag for details std::string mEditorId; @@ -53,6 +55,8 @@ namespace ESM4 // void save(ESM4::Writer& writer) const; // void blank(); + + static constexpr ESM::RecNameInts sRecordId = ESM::REC_STAT4; }; } diff --git a/components/to_utf8/to_utf8.hpp b/components/to_utf8/to_utf8.hpp index df5462dbb9..e72e24a753 100644 --- a/components/to_utf8/to_utf8.hpp +++ b/components/to_utf8/to_utf8.hpp @@ -68,6 +68,8 @@ namespace ToUTF8 /// ASCII-only string. Otherwise returns a view to the input. std::string_view getLegacyEnc(std::string_view input); + const StatelessUtf8Encoder* getStatelessEncoder() const { return &mImpl; } + private: std::string mBuffer; StatelessUtf8Encoder mImpl; From 077cf97bc4684d0a002f50d33717db668dad9881 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Fri, 30 Dec 2022 11:28:19 +0100 Subject: [PATCH 03/37] The esm4 reader logic is mutualised to avoid copy pasting code, readerutils gives functions that take visitors as params to decide how a record must be handled Check encoder exists, and get value of stateless encoder. fixes code formatting conventions Fixed output of record with RefId also fixed readTypedRecord and readRecord to have the proper return types Check if the type has a sRecordId --- apps/esmtool/tes4.cpp | 321 +++++++++++++++++------------- apps/openmw/mwworld/esmloader.cpp | 14 +- apps/openmw/mwworld/esmstore.cpp | 74 ++----- apps/openmw/mwworld/store.cpp | 15 +- components/CMakeLists.txt | 260 ++++++++++++------------ components/esm/refid.hpp | 3 +- components/esm4/loadcell.cpp | 4 +- components/esm4/loadcell.hpp | 1 + components/esm4/loadrefr.hpp | 1 + components/esm4/loadstat.hpp | 1 + components/esm4/readerutils.hpp | 84 ++++++++ components/to_utf8/to_utf8.hpp | 2 +- 12 files changed, 440 insertions(+), 340 deletions(-) create mode 100644 components/esm4/readerutils.hpp diff --git a/apps/esmtool/tes4.cpp b/apps/esmtool/tes4.cpp index f72175ec93..50c7d24b7c 100644 --- a/apps/esmtool/tes4.cpp +++ b/apps/esmtool/tes4.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -69,6 +70,19 @@ namespace EsmTool template constexpr bool hasFormId = HasFormId::value; + template > + struct HasRefId : std::false_type + { + }; + + template + struct HasRefId> : std::true_type + { + }; + + template + constexpr bool hasRefId = HasRefId::value; + template > struct HasFlags : std::false_type { @@ -169,6 +183,8 @@ namespace EsmTool std::cout << "\n Record: " << ESM::NAME(reader.hdr().record.typeId).toStringView(); if constexpr (hasFormId) std::cout << "\n FormId: " << value.mFormId; + if constexpr (hasRefId) + std::cout << "\n RefId: " << value.mId; if constexpr (hasFlags) std::cout << "\n Record flags: " << recordFlags(value.mFlags); if constexpr (hasEditorId) @@ -180,62 +196,80 @@ namespace EsmTool if constexpr (hasKf) std::cout << "\n Kf:" << WriteArray("\n - ", value.mKf); std::cout << '\n'; + return; } - void readRecord(const Params& params, ESM4::Reader& reader) + bool readRecord(const Params& params, ESM4::Reader& reader) { switch (static_cast(reader.hdr().record.typeId)) { case ESM4::REC_AACT: break; case ESM4::REC_ACHR: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_ACRE: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_ACTI: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_ADDN: break; case ESM4::REC_ALCH: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_ALOC: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_AMMO: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_ANIO: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_APPA: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_ARMA: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_ARMO: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_ARTO: break; case ESM4::REC_ASPC: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_ASTP: break; case ESM4::REC_AVIF: break; case ESM4::REC_BOOK: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_BPTD: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_CAMS: break; case ESM4::REC_CCRD: break; case ESM4::REC_CELL: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_CLAS: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_CLFM: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_CLMT: break; case ESM4::REC_CLOT: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_CMNY: break; case ESM4::REC_COBJ: @@ -243,25 +277,30 @@ namespace EsmTool case ESM4::REC_COLL: break; case ESM4::REC_CONT: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_CPTH: break; case ESM4::REC_CREA: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_CSTY: break; case ESM4::REC_DEBR: break; case ESM4::REC_DIAL: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_DLBR: break; case ESM4::REC_DLVW: break; case ESM4::REC_DOBJ: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_DOOR: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_DUAL: break; case ESM4::REC_ECZN: @@ -275,81 +314,103 @@ namespace EsmTool case ESM4::REC_EXPL: break; case ESM4::REC_EYES: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_FACT: break; case ESM4::REC_FLOR: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_FLST: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_FSTP: break; case ESM4::REC_FSTS: break; case ESM4::REC_FURN: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_GLOB: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_GMST: break; case ESM4::REC_GRAS: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_GRUP: break; case ESM4::REC_HAIR: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_HAZD: break; case ESM4::REC_HDPT: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_IDLE: // FIXME: ESM4::IdleAnimation::load does not work with Oblivion.esm - // return readTypedRecord(params, reader); + // readTypedRecord(params, reader); + return true; break; case ESM4::REC_IDLM: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_IMAD: break; case ESM4::REC_IMGS: break; case ESM4::REC_IMOD: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_INFO: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_INGR: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_IPCT: break; case ESM4::REC_IPDS: break; case ESM4::REC_KEYM: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_KYWD: break; case ESM4::REC_LAND: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_LCRT: break; case ESM4::REC_LCTN: break; case ESM4::REC_LGTM: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_LIGH: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_LSCR: break; case ESM4::REC_LTEX: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_LVLC: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_LVLI: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_LVLN: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_LVSP: break; case ESM4::REC_MATO: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_MATT: break; case ESM4::REC_MESG: @@ -357,49 +418,66 @@ namespace EsmTool case ESM4::REC_MGEF: break; case ESM4::REC_MISC: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_MOVT: break; case ESM4::REC_MSET: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_MSTT: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_MUSC: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_MUST: break; case ESM4::REC_NAVI: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_NAVM: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_NOTE: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_NPC_: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_OTFT: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_PACK: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_PERK: break; case ESM4::REC_PGRD: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_PGRE: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_PHZD: break; case ESM4::REC_PROJ: break; case ESM4::REC_PWAT: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_QUST: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_RACE: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_REFR: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_REGN: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_RELA: break; case ESM4::REC_REVB: @@ -407,23 +485,30 @@ namespace EsmTool case ESM4::REC_RFCT: break; case ESM4::REC_ROAD: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_SBSP: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_SCEN: break; case ESM4::REC_SCOL: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_SCPT: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_SCRL: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_SGST: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_SHOU: break; case ESM4::REC_SLGM: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_SMBN: break; case ESM4::REC_SMEN: @@ -433,97 +518,56 @@ namespace EsmTool case ESM4::REC_SNCT: break; case ESM4::REC_SNDR: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_SOPM: break; case ESM4::REC_SOUN: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_SPEL: break; case ESM4::REC_SPGD: break; case ESM4::REC_STAT: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_TACT: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_TERM: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_TES4: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_TREE: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_TXST: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_VTYP: break; case ESM4::REC_WATR: break; case ESM4::REC_WEAP: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_WOOP: break; case ESM4::REC_WRLD: - return readTypedRecord(params, reader); + readTypedRecord(params, reader); + return true; case ESM4::REC_WTHR: break; } if (!params.mQuite) std::cout << "\n Unsupported record: " << ESM::NAME(reader.hdr().record.typeId).toStringView() << '\n'; - - reader.skipRecordData(); + return false; } - bool readItem(const Params& params, ESM4::Reader& reader); - - bool readGroup(const Params& params, ESM4::Reader& reader) - { - const ESM4::RecordHeader& header = reader.hdr(); - - if (!params.mQuite) - std::cout << "\nGroup: " << toString(static_cast(header.group.type)) << " " - << ESM::NAME(header.group.typeId).toStringView() << '\n'; - - switch (static_cast(header.group.type)) - { - case ESM4::Grp_RecordType: - case ESM4::Grp_InteriorCell: - case ESM4::Grp_InteriorSubCell: - case ESM4::Grp_ExteriorCell: - case ESM4::Grp_ExteriorSubCell: - reader.enterGroup(); - return readItem(params, reader); - case ESM4::Grp_WorldChild: - case ESM4::Grp_CellChild: - case ESM4::Grp_TopicChild: - case ESM4::Grp_CellPersistentChild: - case ESM4::Grp_CellTemporaryChild: - case ESM4::Grp_CellVisibleDistChild: - reader.adjustGRUPFormId(); - reader.enterGroup(); - if (!reader.hasMoreRecs()) - return false; - return readItem(params, reader); - } - - reader.skipGroup(); - - return true; - } - - bool readItem(const Params& params, ESM4::Reader& reader) - { - if (!reader.getRecordHeader() || !reader.hasMoreRecs()) - return false; - - const ESM4::RecordHeader& header = reader.hdr(); - - if (header.record.typeId == ESM4::REC_GRUP) - return readGroup(params, reader); - - readRecord(params, reader); - return true; - } } int loadTes4(const Arguments& info, std::unique_ptr&& stream) @@ -551,12 +595,15 @@ namespace EsmTool } } - while (reader.hasMoreRecs()) - { - reader.exitGroupCheck(); - if (!readItem(params, reader)) - break; - } + auto visitorRec = [¶ms](ESM4::Reader& reader) { return readRecord(params, reader); }; + auto visistorGroup = [¶ms](ESM4::Reader& reader) { + if (params.mQuite) + return; + auto groupType = static_cast(reader.hdr().group.type); + std::cout << "\nGroup: " << toString(groupType) << " " + << ESM::NAME(reader.hdr().group.typeId).toStringView() << '\n'; + }; + ESM4::ReaderUtils::readAll(reader, visitorRec, visistorGroup); } catch (const std::exception& e) { diff --git a/apps/openmw/mwworld/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index 3265059a13..c529a9834c 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -1,13 +1,14 @@ #include "esmloader.hpp" #include "esmstore.hpp" +#include + #include #include #include #include #include #include -#include namespace MWWorld { @@ -30,7 +31,6 @@ namespace MWWorld if (!stream->is_open()) { throw std::runtime_error(std::string("File Failed to open file: ") + std::strerror(errno) + "\n"); - return; } const ESM::Format format = ESM::readFormat(*stream); stream->seekg(0); @@ -64,9 +64,13 @@ namespace MWWorld } case ESM::Format::Tes4: { - ESM4::Reader readerESM4(std::move(stream), filepath); - readerESM4.setEncoder(mEncoder->getStatelessEncoder()); - mStore.loadESM4(readerESM4, listener, mDialogue); + if (mEncoder) + { + ESM4::Reader readerESM4(std::move(stream), filepath); + auto statelessEncoder = mEncoder->getStatelessEncoder(); + readerESM4.setEncoder(&statelessEncoder); + mStore.loadESM4(readerESM4, listener, mDialogue); + } } } } diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 15bf52757e..31c788283d 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -13,12 +13,12 @@ #include #include +#include #include #include #include #include - -#include +#include #include #include "../mwmechanics/spelllist.hpp" @@ -186,13 +186,23 @@ namespace MWWorld } } + template > + struct HasRecordId : std::false_type + { + }; + + template + struct HasRecordId> : std::true_type + { + }; + template static void typedReadRecordESM4(ESM4::Reader& reader, ESMStore& stores, Store& store, int& found) { auto recordType = static_cast(reader.hdr().record.typeId); ESM::RecNameInts esm4RecName = static_cast(ESM::esm4Recname(recordType)); - if constexpr (std::is_convertible_v*, DynamicStore*>) + if constexpr (std::is_convertible_v*, DynamicStore*> && HasRecordId::value) { if constexpr (ESM::isESM4Rec(T::sRecordId)) { @@ -208,60 +218,14 @@ namespace MWWorld } } - static void readRecord(ESM4::Reader& reader, ESMStore& store) + static bool readRecord(ESM4::Reader& reader, ESMStore& store) { int found = 0; std::apply([&reader, &store, &found]( auto&... x) { (ESMStoreImp::typedReadRecordESM4(reader, store, x, found), ...); }, store.mStoreImp->mStores); assert(found <= 1); - if (found == 0) // unhandled record - reader.skipRecordData(); - } - - static bool readItem(ESM4::Reader& reader, ESMStore& store) - { - if (!reader.getRecordHeader() || !reader.hasMoreRecs()) - return false; - - const ESM4::RecordHeader& header = reader.hdr(); - - if (header.record.typeId == ESM4::REC_GRUP) - return readGroup(reader, store); - - readRecord(reader, store); - return true; - } - - static bool readGroup(ESM4::Reader& reader, ESMStore& store) - { - const ESM4::RecordHeader& header = reader.hdr(); - - switch (static_cast(header.group.type)) - { - case ESM4::Grp_RecordType: - case ESM4::Grp_InteriorCell: - case ESM4::Grp_InteriorSubCell: - case ESM4::Grp_ExteriorCell: - case ESM4::Grp_ExteriorSubCell: - reader.enterGroup(); - return readItem(reader, store); - case ESM4::Grp_WorldChild: - case ESM4::Grp_CellChild: - case ESM4::Grp_TopicChild: - case ESM4::Grp_CellPersistentChild: - case ESM4::Grp_CellTemporaryChild: - case ESM4::Grp_CellVisibleDistChild: - reader.adjustGRUPFormId(); - reader.enterGroup(); - if (!reader.hasMoreRecs()) - return false; - return readItem(reader, store); - } - - reader.skipGroup(); - - return true; + return found; } }; @@ -423,12 +387,8 @@ namespace MWWorld void ESMStore::loadESM4(ESM4::Reader& reader, Loading::Listener* listener, ESM::Dialogue*& dialogue) { - while (reader.hasMoreRecs()) - { - reader.exitGroupCheck(); - if (!ESMStoreImp::readItem(reader, *this)) - break; - } + auto visitorRec = [this](ESM4::Reader& reader) { return ESMStoreImp::readRecord(reader, *this); }; + ESM4::ReaderUtils::readAll(reader, visitorRec, [](ESM4::Reader&) {}); } void ESMStore::setIdType(const ESM::RefId& id, ESM::RecNameInts type) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 27d74ddf59..71161fa6a4 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -1,21 +1,18 @@ #include "store.hpp" -#include - -#include -#include -#include - -#include -#include - #include #include #include +#include +#include +#include +#include #include #include #include +#include +#include namespace { diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 243ea5841c..9646aae695 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -1,84 +1,84 @@ -project (Components) +project(Components) # Version file -set (VERSION_IN_FILE "${OpenMW_SOURCE_DIR}/files/version.in") -set (VERSION_FILE_PATH_BASE "${OpenMW_BINARY_DIR}") -set (VERSION_FILE_PATH_RELATIVE resources/version) -if (GIT_CHECKOUT) +set(VERSION_IN_FILE "${OpenMW_SOURCE_DIR}/files/version.in") +set(VERSION_FILE_PATH_BASE "${OpenMW_BINARY_DIR}") +set(VERSION_FILE_PATH_RELATIVE resources/version) + +if(GIT_CHECKOUT) get_generator_is_multi_config(multi_config) - add_custom_target (git-version - COMMAND ${CMAKE_COMMAND} - -DGIT_EXECUTABLE=${GIT_EXECUTABLE} - -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR} - -DVERSION_IN_FILE=${VERSION_IN_FILE} - -DVERSION_FILE_PATH_BASE=${VERSION_FILE_PATH_BASE} - -DVERSION_FILE_PATH_RELATIVE=${VERSION_FILE_PATH_RELATIVE} - -DOPENMW_VERSION_MAJOR=${OPENMW_VERSION_MAJOR} - -DOPENMW_VERSION_MINOR=${OPENMW_VERSION_MINOR} - -DOPENMW_VERSION_RELEASE=${OPENMW_VERSION_RELEASE} - -DOPENMW_VERSION=${OPENMW_VERSION} - -DMACROSFILE=${CMAKE_SOURCE_DIR}/cmake/OpenMWMacros.cmake - "-DCMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}" - -Dgenerator_is_multi_config_var=${multi_config} - -P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/GitVersion.cmake - VERBATIM) -else (GIT_CHECKOUT) + add_custom_target(git-version + COMMAND ${CMAKE_COMMAND} + -DGIT_EXECUTABLE=${GIT_EXECUTABLE} + -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR} + -DVERSION_IN_FILE=${VERSION_IN_FILE} + -DVERSION_FILE_PATH_BASE=${VERSION_FILE_PATH_BASE} + -DVERSION_FILE_PATH_RELATIVE=${VERSION_FILE_PATH_RELATIVE} + -DOPENMW_VERSION_MAJOR=${OPENMW_VERSION_MAJOR} + -DOPENMW_VERSION_MINOR=${OPENMW_VERSION_MINOR} + -DOPENMW_VERSION_RELEASE=${OPENMW_VERSION_RELEASE} + -DOPENMW_VERSION=${OPENMW_VERSION} + -DMACROSFILE=${CMAKE_SOURCE_DIR}/cmake/OpenMWMacros.cmake + "-DCMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}" + -Dgenerator_is_multi_config_var=${multi_config} + -P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/GitVersion.cmake + VERBATIM) +else(GIT_CHECKOUT) configure_resource_file(${VERSION_IN_FILE} ${VERSION_FILE_PATH_BASE} ${VERSION_FILE_PATH_RELATIVE}) -endif (GIT_CHECKOUT) +endif(GIT_CHECKOUT) # source files - -add_component_dir (lua +add_component_dir(lua luastate scriptscontainer utilpackage serialization configuration l10n storage - ) +) -add_component_dir (l10n +add_component_dir(l10n messagebundles manager - ) +) -add_component_dir (settings +add_component_dir(settings settings parser - ) +) -add_component_dir (bsa +add_component_dir(bsa bsa_file compressedbsafile - ) +) -add_component_dir (vfs +add_component_dir(vfs manager archive bsaarchive filesystemarchive registerarchives - ) +) -add_component_dir (resource +add_component_dir(resource scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem resourcemanager stats animation foreachbulletobject errormarker - ) +) -add_component_dir (shader +add_component_dir(shader shadermanager shadervisitor removedalphafunc - ) +) -add_component_dir (sceneutil +add_component_dir(sceneutil clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller lightmanager lightutil positionattitudetransform workqueue pathgridutil waterutil writescene serialize optimizer actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin osgacontroller rtt screencapture depth color riggeometryosgaextension extradata unrefqueue - ) +) -add_component_dir (nif +add_component_dir(nif controlled effect niftypes record controller extra node record_ptr data niffile property nifkey base nifstream physics - ) +) -add_component_dir (nifosg +add_component_dir(nifosg nifloader controller particle matrixtransform - ) +) -add_component_dir (nifbullet +add_component_dir(nifbullet bulletnifloader - ) +) -add_component_dir (to_utf8 +add_component_dir(to_utf8 to_utf8 - ) +) add_component_dir(esm attr common defs esmcommon records util luascripts format refid) @@ -86,7 +86,7 @@ add_component_dir(fx pass technique lexer widgets stateupdater) add_component_dir(std140 ubo) -add_component_dir (esm3 +add_component_dir(esm3 esmreader esmwriter loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell loadclas loadclot loadcont loadcrea loaddial loaddoor loadench loadfact loadglob loadgmst loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc @@ -96,13 +96,13 @@ add_component_dir (esm3 inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache - ) +) -add_component_dir (esm3terrain +add_component_dir(esm3terrain storage - ) +) -add_component_dir (esm4 +add_component_dir(esm4 acti actor common @@ -191,96 +191,97 @@ add_component_dir (esm4 loadweap loadwrld reader + readerutils reference script ) -add_component_dir (misc +add_component_dir(misc constants utf8stream resourcehelpers rng messageformatparser weakcache thread compression osguservalues color tuplemeta tuplehelpers - ) +) -add_component_dir (stereo +add_component_dir(stereo frustum multiview stereomanager types - ) +) -add_component_dir (debug +add_component_dir(debug debugging debuglog gldebug debugdraw - ) +) IF(NOT WIN32 AND NOT APPLE) add_definitions(-DGLOBAL_DATA_PATH="${GLOBAL_DATA_PATH}") add_definitions(-DGLOBAL_CONFIG_PATH="${GLOBAL_CONFIG_PATH}") ENDIF() -add_component_dir (files + +add_component_dir(files linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager constrainedfilestream memorystream hash configfileparser openfile constrainedfilestreambuf conversion - ) +) -add_component_dir (compiler +add_component_dir(compiler context controlparser errorhandler exception exprparser extensions fileparser generator lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler stringparser tokenloc nullerrorhandler opcodes extensions0 declarationparser quickfileparser discardparser junkparser - ) +) -add_component_dir (interpreter +add_component_dir(interpreter context controlopcodes genericopcodes installopcodes interpreter localopcodes mathopcodes miscopcodes opcodes runtime types defines - ) +) -add_component_dir (translation +add_component_dir(translation translation - ) +) -add_component_dir (terrain +add_component_dir(terrain storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer quadtreeworld quadtreenode viewdata cellborder view heightcull - ) +) -add_component_dir (loadinglistener +add_component_dir(loadinglistener loadinglistener - ) +) -add_component_dir (myguiplatform +add_component_dir(myguiplatform myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener additivelayer scalinglayer - ) +) -add_component_dir (widgets +add_component_dir(widgets box fontwrapper imagebutton tags list numericeditbox sharedstatebutton windowcaption widgets - ) +) -add_component_dir (fontloader +add_component_dir(fontloader fontloader - ) +) -add_component_dir (sdlutil +add_component_dir(sdlutil gl4es_init sdlgraphicswindow imagetosurface sdlinputwrapper sdlvideowrapper events sdlcursormanager sdlmappings - ) +) -add_component_dir (version +add_component_dir(version version - ) +) -add_component_dir (fallback +add_component_dir(fallback fallback validate - ) +) -add_component_dir (lua_ui +add_component_dir(lua_ui registerscriptsettings scriptsettings properties widget element util layers content alignment resources adapter text textedit window image container flex - ) - +) if(WIN32) - add_component_dir (crashcatcher + add_component_dir(crashcatcher windows_crashcatcher windows_crashmonitor windows_crashshm ) elseif(NOT ANDROID) - add_component_dir (crashcatcher + add_component_dir(crashcatcher crashcatcher ) endif() @@ -316,11 +317,11 @@ add_component_dir(detournavigator stats commulativeaabb recastcontext - ) +) add_component_dir(loadinglistener reporter - ) +) add_component_dir(sqlite3 db @@ -335,63 +336,63 @@ add_component_dir(esmloader add_component_dir(navmeshtool protocol - ) +) add_component_dir(platform platform file - ) +) -if (WIN32) +if(WIN32) add_component_dir(platform file.win32 - ) -elseif (UNIX) + ) +elseif(UNIX) add_component_dir(platform file.posix - ) -else () + ) +else() add_component_dir(platform file.stdio - ) + ) endif() -set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui - ) +set(ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui +) -if (USE_QT) - add_component_qt_dir (contentselector +if(USE_QT) + add_component_qt_dir(contentselector model/modelitem model/esmfile model/naturalsort model/contentmodel model/loadordererror view/combobox view/contentselector - ) - add_component_qt_dir (config + ) + add_component_qt_dir(config gamesettings launchersettings settingsbase - ) + ) - add_component_qt_dir (process + add_component_qt_dir(process processinvoker - ) + ) - add_component_qt_dir (misc + add_component_qt_dir(misc helpviewer - ) + ) - add_component_qt_dir (files + add_component_qt_dir(files qtconversion - ) + ) QT5_WRAP_UI(ESM_UI_HDR ${ESM_UI}) endif() -if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" AND NOT APPLE) add_definitions(-fPIC) endif() -endif () +endif() include_directories(${BULLET_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) @@ -436,7 +437,7 @@ target_link_libraries(components smhasher ${ICU_LIBRARIES} yaml-cpp - ) +) if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.77.0) target_link_libraries(components ${Boost_ATOMIC_LIBRARY}) @@ -444,46 +445,46 @@ endif() target_link_libraries(components ${BULLET_LIBRARIES}) -if (WIN32) +if(WIN32) target_link_libraries(components - ${Boost_LOCALE_LIBRARY} - ${Boost_ZLIB_LIBRARY}) + ${Boost_LOCALE_LIBRARY} + ${Boost_ZLIB_LIBRARY}) endif() -if (USE_QT) +if(USE_QT) add_library(components_qt STATIC ${COMPONENT_QT_FILES} ${ESM_UI_HDR}) target_link_libraries(components_qt components Qt5::Widgets Qt5::Core) target_compile_definitions(components_qt PRIVATE OPENMW_DOC_BASEURL="${OPENMW_DOC_BASEURL}") endif() -if (GIT_CHECKOUT) - add_dependencies (components git-version) -endif (GIT_CHECKOUT) +if(GIT_CHECKOUT) + add_dependencies(components git-version) +endif(GIT_CHECKOUT) -if (OSG_STATIC AND CMAKE_SYSTEM_NAME MATCHES "Linux") +if(OSG_STATIC AND CMAKE_SYSTEM_NAME MATCHES "Linux") find_package(X11 REQUIRED COMPONENTS Xinerama Xrandr) target_link_libraries(components ${CMAKE_DL_LIBS} X11::X11 X11::Xinerama X11::Xrandr) find_package(Fontconfig MODULE) + if(Fontconfig_FOUND) target_link_libraries(components Fontconfig::Fontconfig) endif() endif() -if (WIN32) +if(WIN32) target_link_libraries(components shlwapi) endif() # Fix for not visible pthreads functions for linker with glibc 2.15 -if (UNIX AND NOT APPLE) -target_link_libraries(components ${CMAKE_THREAD_LIBS_INIT}) +if(UNIX AND NOT APPLE) + target_link_libraries(components ${CMAKE_THREAD_LIBS_INIT}) endif() -if (BUILD_WITH_CODE_COVERAGE) +if(BUILD_WITH_CODE_COVERAGE) add_definitions(--coverage) target_link_libraries(components gcov) endif() - # Make the variable accessible for other subdirectories set(COMPONENT_FILES ${COMPONENT_FILES} PARENT_SCOPE) @@ -492,8 +493,10 @@ target_compile_definitions(components PUBLIC BT_USE_DOUBLE_PRECISION) if(OSG_STATIC) unset(_osg_plugins_static_files) add_library(components_osg_plugins INTERFACE) + foreach(_plugin ${USED_OSG_PLUGINS}) string(TOUPPER ${_plugin} _plugin_uc) + if(OPENMW_USE_SYSTEM_OSG) list(APPEND _osg_plugins_static_files ${${_plugin_uc}_LIBRARY}) else() @@ -502,6 +505,7 @@ if(OSG_STATIC) add_dependencies(components_osg_plugins ${${_plugin_uc}_LIBRARY}) endif() endforeach() + # We use --whole-archive because OSG plugins use registration. get_whole_archive_options(_opts ${_osg_plugins_static_files}) target_link_options(components_osg_plugins INTERFACE ${_opts}) @@ -521,7 +525,7 @@ if(USE_QT) set_property(TARGET components_qt PROPERTY AUTOMOC ON) endif(USE_QT) -if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC) +if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC) target_precompile_headers(components PUBLIC diff --git a/components/esm/refid.hpp b/components/esm/refid.hpp index 8900f7ce75..0195d31ea4 100644 --- a/components/esm/refid.hpp +++ b/components/esm/refid.hpp @@ -1,12 +1,13 @@ #ifndef OPENMW_COMPONENTS_ESM_REFID_HPP #define OPENMW_COMPONENTS_ESM_REFID_HPP #include -#include #include #include #include #include +#include + namespace ESM { struct RefId diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index 1321e31578..adf8a13180 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -32,11 +32,11 @@ #include #include // FLT_MAX for gcc +#include // FIXME: debug only #include -#include // FIXME: debug only - #include "reader.hpp" + #include // #include "writer.hpp" diff --git a/components/esm4/loadcell.hpp b/components/esm4/loadcell.hpp index bcc95f652f..49e5d048b0 100644 --- a/components/esm4/loadcell.hpp +++ b/components/esm4/loadcell.hpp @@ -33,6 +33,7 @@ #include "formid.hpp" #include "lighting.hpp" + #include #include diff --git a/components/esm4/loadrefr.hpp b/components/esm4/loadrefr.hpp index baf199c4c4..fb54c35863 100644 --- a/components/esm4/loadrefr.hpp +++ b/components/esm4/loadrefr.hpp @@ -30,6 +30,7 @@ #include #include "reference.hpp" // FormId, Placement, EnableParent + #include #include diff --git a/components/esm4/loadstat.hpp b/components/esm4/loadstat.hpp index 5d79f84d6f..3b8a78d8fb 100644 --- a/components/esm4/loadstat.hpp +++ b/components/esm4/loadstat.hpp @@ -32,6 +32,7 @@ #include #include "formid.hpp" + #include #include diff --git a/components/esm4/readerutils.hpp b/components/esm4/readerutils.hpp new file mode 100644 index 0000000000..dd202a5f71 --- /dev/null +++ b/components/esm4/readerutils.hpp @@ -0,0 +1,84 @@ +#ifndef OPENMW_COMPONENTS_ESM4_READERUTILS +#define OPENMW_COMPONENTS_ESM4_READERUTILS + +#include +namespace ESM4 +{ + struct ReaderUtils + { + + /* RecordInvocable must be an invocable, takes an ESM4::Reader& as input, and outputs a boolean that indicates + if the record was read or ignored. Will be invoked for every record + + GroupInvocable's invocable must take a ESM4::Reader& as input, doesn't need to output anything. Will be invoked + for every group*/ + template + static void readAll(ESM4::Reader& reader, RecordInvocable&& recordInvocable, GroupInvocable&& groupInvocable) + { + while (reader.hasMoreRecs()) + { + reader.exitGroupCheck(); + if (!readItem(reader, recordInvocable, groupInvocable)) + break; + } + } + + template + static void readRecord(ESM4::Reader& reader, RecordInvocable&& recordInvocable) + { + if (!recordInvocable(reader)) + reader.skipRecordData(); + } + + template + static bool readGroup(ESM4::Reader& reader, RecordInvocable&& recordInvocable, GroupInvocable&& groupInvocable) + { + const ESM4::RecordHeader& header = reader.hdr(); + + groupInvocable(reader); + + switch (static_cast(header.group.type)) + { + case ESM4::Grp_RecordType: + case ESM4::Grp_InteriorCell: + case ESM4::Grp_InteriorSubCell: + case ESM4::Grp_ExteriorCell: + case ESM4::Grp_ExteriorSubCell: + reader.enterGroup(); + return readItem(reader, recordInvocable, groupInvocable); + case ESM4::Grp_WorldChild: + case ESM4::Grp_CellChild: + case ESM4::Grp_TopicChild: + case ESM4::Grp_CellPersistentChild: + case ESM4::Grp_CellTemporaryChild: + case ESM4::Grp_CellVisibleDistChild: + reader.adjustGRUPFormId(); + reader.enterGroup(); + if (!reader.hasMoreRecs()) + return false; + return readItem(reader, recordInvocable, groupInvocable); + } + + reader.skipGroup(); + + return true; + } + + template + static bool readItem(ESM4::Reader& reader, RecordInvocable&& recordInvocable, GroupInvocable&& groupInvocable) + { + if (!reader.getRecordHeader() || !reader.hasMoreRecs()) + return false; + + const ESM4::RecordHeader& header = reader.hdr(); + + if (header.record.typeId == ESM4::REC_GRUP) + return readGroup(reader, recordInvocable, groupInvocable); + + readRecord(reader, recordInvocable); + return true; + } + }; +} + +#endif // !OPENMW_COMPONENTS_ESM4_READERUTILS diff --git a/components/to_utf8/to_utf8.hpp b/components/to_utf8/to_utf8.hpp index e72e24a753..f7197fe553 100644 --- a/components/to_utf8/to_utf8.hpp +++ b/components/to_utf8/to_utf8.hpp @@ -68,7 +68,7 @@ namespace ToUTF8 /// ASCII-only string. Otherwise returns a view to the input. std::string_view getLegacyEnc(std::string_view input); - const StatelessUtf8Encoder* getStatelessEncoder() const { return &mImpl; } + const StatelessUtf8Encoder getStatelessEncoder() const { return mImpl; } private: std::string mBuffer; From ecadcc37bb3ca64bf0ca48bac0bdc1489e407a33 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Mon, 2 Jan 2023 14:50:46 +0300 Subject: [PATCH 04/37] OMWControls: Russian localization --- files/data/CMakeLists.txt | 1 + files/data/l10n/OMWControls/ru.yaml | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 files/data/l10n/OMWControls/ru.yaml diff --git a/files/data/CMakeLists.txt b/files/data/CMakeLists.txt index a4df9aa966..d3e052b3fc 100644 --- a/files/data/CMakeLists.txt +++ b/files/data/CMakeLists.txt @@ -51,6 +51,7 @@ set(BUILTIN_DATA_FILES l10n/OMWCamera/sv.yaml l10n/OMWCamera/fr.yaml l10n/OMWControls/en.yaml + l10n/OMWControls/ru.yaml l10n/OMWControls/sv.yaml l10n/PostProcessing/de.yaml l10n/PostProcessing/en.yaml diff --git a/files/data/l10n/OMWControls/ru.yaml b/files/data/l10n/OMWControls/ru.yaml new file mode 100644 index 0000000000..30bb15ee57 --- /dev/null +++ b/files/data/l10n/OMWControls/ru.yaml @@ -0,0 +1,16 @@ +ControlsPage: "Управление OpenMW" +ControlsPageDescription: "Дополнительные настройки, связанные с управлением игроком" + +MovementSettings: "Движение" + +alwaysRun: "Постоянный бег" +alwaysRunDescription: | + Когда эта настройка включена, по умолчанию персонаж бегает, в противном случае по умолчанию он ходит. + Клавиша бега (по умолчанию Shift) инвертирует режим временно, а клавиша постоянного бега (Caps Lock) переключает эту настройку. + +toggleSneak: "Переключение движения крадучись" +toggleSneakDescription: | + Эта настройка меняет поведение клавиши движения крадучись (по умолчанию Ctrl): + чтобы красться, её достаточно нажать единожды для переключения положения, а не зажимать. + Игрокам, которые много времени крадутся, может быть проще управлять персонажем, когда опция включена. + From cecc3cb73698380ea0e5bd18cb6e83540dde16d8 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Mon, 2 Jan 2023 14:51:25 +0300 Subject: [PATCH 05/37] Slightly more natural wording for Windowed Fullscreen hint --- files/data/l10n/SettingsMenu/en.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/data/l10n/SettingsMenu/en.yaml b/files/data/l10n/SettingsMenu/en.yaml index fea8ae78b7..9cd4cd83bf 100644 --- a/files/data/l10n/SettingsMenu/en.yaml +++ b/files/data/l10n/SettingsMenu/en.yaml @@ -62,6 +62,6 @@ WaterShaderTextureQuality: "Texture quality" WindowBorder: "Window Border" WindowMode: "Window Mode" WindowModeFullscreen: "Fullscreen" -WindowModeHint: "Hint: the Windowed Fullscreen mode\nalways uses a native screen resolution." +WindowModeHint: "Hint: Windowed Fullscreen mode\nalways uses the native display resolution." WindowModeWindowed: "Windowed" WindowModeWindowedFullscreen: "Windowed Fullscreen" From 8c7d34717974e0ee66b5c05c5ca884895c46ed92 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Thu, 22 Dec 2022 18:53:49 +0100 Subject: [PATCH 06/37] Reorganize l10n files --- apps/openmw/mwgui/debugwindow.cpp | 6 +- apps/openmw/mwgui/postprocessorhud.cpp | 28 ++--- apps/openmw/mwgui/savegamedialog.cpp | 4 +- apps/openmw/mwgui/settingswindow.cpp | 20 ++-- apps/openmw/mwinput/bindingsmanager.cpp | 10 +- .../detournavigator/asyncnavmeshupdater.cpp | 2 +- files/data/CMakeLists.txt | 49 +++----- files/data/l10n/BuiltInShaders/de.yaml | 7 -- files/data/l10n/DebugMenu/de.yaml | 4 - files/data/l10n/DebugMenu/en.yaml | 4 - files/data/l10n/DebugMenu/fr.yaml | 3 - files/data/l10n/DebugMenu/ru.yaml | 4 - files/data/l10n/DebugMenu/sv.yaml | 3 - files/data/l10n/Navigation/de.yaml | 1 - files/data/l10n/Navigation/en.yaml | 1 - files/data/l10n/Navigation/fr.yaml | 1 - files/data/l10n/Navigation/ru.yaml | 1 - files/data/l10n/Navigation/sv.yaml | 1 - .../l10n/{SettingsMenu => OMWEngine}/de.yaml | 21 ++++ .../l10n/{SettingsMenu => OMWEngine}/en.yaml | 21 ++++ .../l10n/{SettingsMenu => OMWEngine}/fr.yaml | 20 ++++ .../l10n/{SettingsMenu => OMWEngine}/ru.yaml | 21 ++++ .../l10n/{SettingsMenu => OMWEngine}/sv.yaml | 20 ++++ .../{PostProcessing => OMWShaders}/de.yaml | 13 ++ .../{BuiltInShaders => OMWShaders}/en.yaml | 27 +++++ .../{BuiltInShaders => OMWShaders}/fr.yaml | 27 +++++ .../{BuiltInShaders => OMWShaders}/ru.yaml | 27 +++++ .../{BuiltInShaders => OMWShaders}/sv.yaml | 29 ++++- files/data/l10n/PostProcessing/en.yaml | 21 ---- files/data/l10n/PostProcessing/fr.yaml | 21 ---- files/data/l10n/PostProcessing/ru.yaml | 21 ---- files/data/l10n/PostProcessing/sv.yaml | 22 ---- files/data/l10n/SavegameMenu/de.yaml | 2 - files/data/l10n/SavegameMenu/en.yaml | 2 - files/data/l10n/SavegameMenu/fr.yaml | 2 - files/data/l10n/SavegameMenu/ru.yaml | 2 - files/data/l10n/SavegameMenu/sv.yaml | 2 - files/data/mygui/openmw_debug_window.layout | 2 +- .../mygui/openmw_postprocessor_hud.layout | 8 +- .../mygui/openmw_postprocessor_hud.skin.xml | 2 +- .../data/mygui/openmw_savegame_dialog.layout | 2 +- .../data/mygui/openmw_settings_window.layout | 112 +++++++++--------- files/data/shaders/adjustments.omwfx | 10 +- files/data/shaders/bloomlinear.omwfx | 26 ++-- files/data/shaders/debug.omwfx | 14 +-- 45 files changed, 365 insertions(+), 281 deletions(-) delete mode 100644 files/data/l10n/BuiltInShaders/de.yaml delete mode 100644 files/data/l10n/DebugMenu/de.yaml delete mode 100644 files/data/l10n/DebugMenu/en.yaml delete mode 100644 files/data/l10n/DebugMenu/fr.yaml delete mode 100644 files/data/l10n/DebugMenu/ru.yaml delete mode 100644 files/data/l10n/DebugMenu/sv.yaml delete mode 100644 files/data/l10n/Navigation/de.yaml delete mode 100644 files/data/l10n/Navigation/en.yaml delete mode 100644 files/data/l10n/Navigation/fr.yaml delete mode 100644 files/data/l10n/Navigation/ru.yaml delete mode 100644 files/data/l10n/Navigation/sv.yaml rename files/data/l10n/{SettingsMenu => OMWEngine}/de.yaml (92%) rename files/data/l10n/{SettingsMenu => OMWEngine}/en.yaml (92%) rename files/data/l10n/{SettingsMenu => OMWEngine}/fr.yaml (93%) rename files/data/l10n/{SettingsMenu => OMWEngine}/ru.yaml (93%) rename files/data/l10n/{SettingsMenu => OMWEngine}/sv.yaml (93%) rename files/data/l10n/{PostProcessing => OMWShaders}/de.yaml (62%) rename files/data/l10n/{BuiltInShaders => OMWShaders}/en.yaml (63%) rename files/data/l10n/{BuiltInShaders => OMWShaders}/fr.yaml (64%) rename files/data/l10n/{BuiltInShaders => OMWShaders}/ru.yaml (62%) rename files/data/l10n/{BuiltInShaders => OMWShaders}/sv.yaml (59%) delete mode 100644 files/data/l10n/PostProcessing/en.yaml delete mode 100644 files/data/l10n/PostProcessing/fr.yaml delete mode 100644 files/data/l10n/PostProcessing/ru.yaml delete mode 100644 files/data/l10n/PostProcessing/sv.yaml delete mode 100644 files/data/l10n/SavegameMenu/de.yaml delete mode 100644 files/data/l10n/SavegameMenu/en.yaml delete mode 100644 files/data/l10n/SavegameMenu/fr.yaml delete mode 100644 files/data/l10n/SavegameMenu/ru.yaml delete mode 100644 files/data/l10n/SavegameMenu/sv.yaml diff --git a/apps/openmw/mwgui/debugwindow.cpp b/apps/openmw/mwgui/debugwindow.cpp index fe2fed02bb..2a9ae25664 100644 --- a/apps/openmw/mwgui/debugwindow.cpp +++ b/apps/openmw/mwgui/debugwindow.cpp @@ -104,20 +104,20 @@ namespace MWGui // - Shader editor MyGUI::TabItem* itemLV = mTabControl->addItem("Log Viewer"); - itemLV->setCaptionWithReplacing(" #{DebugMenu:LogViewer} "); + itemLV->setCaptionWithReplacing(" #{OMWEngine:LogViewer} "); mLogView = itemLV->createWidgetReal("LogEdit", MyGUI::FloatCoord(0, 0, 1, 1), MyGUI::Align::Stretch); mLogView->setEditReadOnly(true); MyGUI::TabItem* itemLuaProfiler = mTabControl->addItem("Lua Profiler"); - itemLuaProfiler->setCaptionWithReplacing(" #{DebugMenu:LuaProfiler} "); + itemLuaProfiler->setCaptionWithReplacing(" #{OMWEngine:LuaProfiler} "); mLuaProfiler = itemLuaProfiler->createWidgetReal( "LogEdit", MyGUI::FloatCoord(0, 0, 1, 1), MyGUI::Align::Stretch); mLuaProfiler->setEditReadOnly(true); #ifndef BT_NO_PROFILE MyGUI::TabItem* item = mTabControl->addItem("Physics Profiler"); - item->setCaptionWithReplacing(" #{DebugMenu:PhysicsProfiler} "); + item->setCaptionWithReplacing(" #{OMWEngine:PhysicsProfiler} "); mBulletProfilerEdit = item->createWidgetReal("LogEdit", MyGUI::FloatCoord(0, 0, 1, 1), MyGUI::Align::Stretch); #else diff --git a/apps/openmw/mwgui/postprocessorhud.cpp b/apps/openmw/mwgui/postprocessorhud.cpp index 5f58cb3032..9e05c180ca 100644 --- a/apps/openmw/mwgui/postprocessorhud.cpp +++ b/apps/openmw/mwgui/postprocessorhud.cpp @@ -329,26 +329,22 @@ namespace MWGui case fx::Technique::Status::Uncompiled: { if (technique->getDynamic()) - ss << "#{fontcolourhtml=header}#{PostProcessing:ShaderLocked}: #{fontcolourhtml=normal} " - "#{PostProcessing:ShaderLockedDescription}" + ss << "#{fontcolourhtml=header}#{OMWShaders:ShaderLocked}: #{fontcolourhtml=normal} " + "#{OMWShaders:ShaderLockedDescription}" << endl << endl; - ss << "#{fontcolourhtml=header}#{PostProcessing:Author}: #{fontcolourhtml=normal} " << author + ss << "#{fontcolourhtml=header}#{OMWShaders:Author}: #{fontcolourhtml=normal} " << author << endl + << endl + << "#{fontcolourhtml=header}#{OMWShaders:Version}: #{fontcolourhtml=normal} " << version << endl + << endl + << "#{fontcolourhtml=header}#{OMWShaders:Description}: #{fontcolourhtml=normal} " << description << endl << endl - << "#{fontcolourhtml=header}#{PostProcessing:Version}: #{fontcolourhtml=normal} " << version - << endl - << endl - << "#{fontcolourhtml=header}#{PostProcessing:Description}: #{fontcolourhtml=normal} " << description - << endl - << endl - << "#{fontcolourhtml=header}#{PostProcessing:InInteriors}: #{fontcolourhtml=normal} " - << flag_interior - << "#{fontcolourhtml=header} #{PostProcessing:InExteriors}: #{fontcolourhtml=normal} " - << flag_exterior - << "#{fontcolourhtml=header} #{PostProcessing:Underwater}: #{fontcolourhtml=normal} " + << "#{fontcolourhtml=header}#{OMWShaders:InInteriors}: #{fontcolourhtml=normal} " << flag_interior + << "#{fontcolourhtml=header} #{OMWShaders:InExteriors}: #{fontcolourhtml=normal} " << flag_exterior + << "#{fontcolourhtml=header} #{OMWShaders:Underwater}: #{fontcolourhtml=normal} " << flag_underwater - << "#{fontcolourhtml=header} #{PostProcessing:Abovewater}: #{fontcolourhtml=normal} " + << "#{fontcolourhtml=header} #{OMWShaders:Abovewater}: #{fontcolourhtml=normal} " << flag_abovewater; break; } @@ -370,7 +366,7 @@ namespace MWGui { MyGUI::Button* resetButton = mConfigArea->createWidget("MW_Button", { 0, 0, 0, 24 }, MyGUI::Align::Default); - resetButton->setCaptionWithReplacing("#{PostProcessing:ResetShader}"); + resetButton->setCaptionWithReplacing("#{OMWShaders:ResetShader}"); resetButton->setTextAlign(MyGUI::Align::Center); resetButton->eventMouseWheel += MyGUI::newDelegate(this, &PostProcessorHud::notifyMouseWheel); resetButton->eventMouseButtonClick diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 462fab75e0..ae5b8d53f2 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -216,7 +216,7 @@ namespace MWGui mCharacterSelection->setIndexSelected(selectedIndex); if (selectedIndex == MyGUI::ITEM_NONE) - mCharacterSelection->setCaptionWithReplacing("#{SavegameMenu:SelectCharacter}"); + mCharacterSelection->setCaptionWithReplacing("#{OMWEngine:SelectCharacter}"); fillSaveList(); } @@ -430,7 +430,7 @@ namespace MWGui if (Settings::Manager::getBool("timeplayed", "Saves")) { text << "\n" - << "#{SavegameMenu:TimePlayed}: " << formatTimeplayed(mCurrentSlot->mProfile.mTimePlayed); + << "#{OMWEngine:TimePlayed}: " << formatTimeplayed(mCurrentSlot->mProfile.mTimePlayed); } mInfoText->setCaptionWithReplacing(text.str()); diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index c06eb7ef7e..d7031fffef 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -45,14 +45,14 @@ namespace std::string textureMipmappingToStr(const std::string& val) { if (val == "linear") - return "#{SettingsMenu:TextureFilteringTrilinear}"; + return "#{OMWEngine:TextureFilteringTrilinear}"; if (val == "nearest") - return "#{SettingsMenu:TextureFilteringBilinear}"; + return "#{OMWEngine:TextureFilteringBilinear}"; if (val == "none") - return "#{SettingsMenu:TextureFilteringDisabled}"; + return "#{OMWEngine:TextureFilteringDisabled}"; Log(Debug::Warning) << "Warning: Invalid texture mipmap option: " << val; - return "#{SettingsMenu:TextureFilteringOther}"; + return "#{OMWEngine:TextureFilteringOther}"; } std::string lightingMethodToStr(SceneUtil::LightingMethod method) @@ -61,14 +61,14 @@ namespace switch (method) { case SceneUtil::LightingMethod::FFP: - result = "#{SettingsMenu:LightingMethodLegacy}"; + result = "#{OMWEngine:LightingMethodLegacy}"; break; case SceneUtil::LightingMethod::PerObjectUniform: - result = "#{SettingsMenu:LightingMethodShadersCompatibility}"; + result = "#{OMWEngine:LightingMethodShadersCompatibility}"; break; case SceneUtil::LightingMethod::SingleUBO: default: - result = "#{SettingsMenu:LightingMethodShaders}"; + result = "#{OMWEngine:LightingMethodShaders}"; break; } @@ -533,7 +533,7 @@ namespace MWGui _sender->setCaptionWithReplacing(_sender->getItemNameAt(_sender->getIndexSelected())); MWBase::Environment::get().getWindowManager()->interactiveMessageBox( - "#{SettingsMenu:ChangeRequiresRestart}", { "#{sOK}" }, true); + "#{OMWEngine:ChangeRequiresRestart}", { "#{sOK}" }, true); Settings::Manager::setString("lighting method", "Shaders", *_sender->getItemDataAt(pos)); apply(); @@ -547,7 +547,7 @@ namespace MWGui _sender->setCaptionWithReplacing(_sender->getItemNameAt(_sender->getIndexSelected())); MWBase::Environment::get().getWindowManager()->interactiveMessageBox( - "#{SettingsMenu:ChangeRequiresRestart}", { "#{sOK}" }, true); + "#{OMWEngine:ChangeRequiresRestart}", { "#{sOK}" }, true); std::vector currentLocales = Settings::Manager::getStringArray("preferred locales", "General"); if (currentLocales.size() <= langPriority) @@ -601,7 +601,7 @@ namespace MWGui { std::vector buttons = { "#{sYes}", "#{sNo}" }; MWBase::Environment::get().getWindowManager()->interactiveMessageBox( - "#{SettingsMenu:LightingResetToDefaults}", buttons, true); + "#{OMWEngine:LightingResetToDefaults}", buttons, true); int selectedButton = MWBase::Environment::get().getWindowManager()->readPressedButton(); if (selectedButton == 1 || selectedButton == -1) return; diff --git a/apps/openmw/mwinput/bindingsmanager.cpp b/apps/openmw/mwinput/bindingsmanager.cpp index a010b4e745..9eac57e830 100644 --- a/apps/openmw/mwinput/bindingsmanager.cpp +++ b/apps/openmw/mwinput/bindingsmanager.cpp @@ -441,13 +441,13 @@ namespace MWInput switch (action) { case A_Screenshot: - return "#{SettingsMenu:Screenshot}"; + return "#{OMWEngine:Screenshot}"; case A_ZoomIn: - return "#{SettingsMenu:CameraZoomIn}"; + return "#{OMWEngine:CameraZoomIn}"; case A_ZoomOut: - return "#{SettingsMenu:CameraZoomOut}"; + return "#{OMWEngine:CameraZoomOut}"; case A_ToggleHUD: - return "#{SettingsMenu:ToggleHUD}"; + return "#{OMWEngine:ToggleHUD}"; case A_Use: return "#{sUse}"; case A_Activate: @@ -519,7 +519,7 @@ namespace MWInput case A_QuickLoad: return "#{sQuickLoadCmd}"; case A_TogglePostProcessorHUD: - return "#{SettingsMenu:TogglePostProcessorHUD}"; + return "#{OMWEngine:TogglePostProcessorHUD}"; default: return {}; // not configurable } diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index 7df9d5d59b..ce6df7f1a4 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -276,7 +276,7 @@ namespace DetourNavigator const Loading::ScopedLoad load(listener); if (listener != nullptr) { - listener->setLabel("#{Navigation:BuildingNavigationMesh}"); + listener->setLabel("#{OMWEngine:BuildingNavigationMesh}"); listener->setProgressRange(maxProgress); } while (!mDone.wait_for(lock, std::chrono::milliseconds(20), isDone)) diff --git a/files/data/CMakeLists.txt b/files/data/CMakeLists.txt index a4df9aa966..f7a703e33a 100644 --- a/files/data/CMakeLists.txt +++ b/files/data/CMakeLists.txt @@ -20,31 +20,21 @@ set(BUILTIN_DATA_FILES fonts/MysticCards.omwfont fonts/MysticCardsFontLicense.txt - l10n/BuiltInShaders/de.yaml - l10n/BuiltInShaders/en.yaml - l10n/BuiltInShaders/ru.yaml - l10n/BuiltInShaders/sv.yaml - l10n/BuiltInShaders/fr.yaml + # Month names and date formatting l10n/Calendar/de.yaml l10n/Calendar/en.yaml l10n/Calendar/ru.yaml l10n/Calendar/sv.yaml l10n/Calendar/fr.yaml - l10n/DebugMenu/de.yaml - l10n/DebugMenu/en.yaml - l10n/DebugMenu/ru.yaml - l10n/DebugMenu/sv.yaml - l10n/DebugMenu/fr.yaml + + # Generic UI messages that can be reused by mods l10n/Interface/de.yaml l10n/Interface/en.yaml l10n/Interface/ru.yaml l10n/Interface/sv.yaml l10n/Interface/fr.yaml - l10n/Navigation/de.yaml - l10n/Navigation/en.yaml - l10n/Navigation/ru.yaml - l10n/Navigation/sv.yaml - l10n/Navigation/fr.yaml + + # L10n for scripts/omw l10n/OMWCamera/de.yaml l10n/OMWCamera/en.yaml l10n/OMWCamera/ru.yaml @@ -52,21 +42,20 @@ set(BUILTIN_DATA_FILES l10n/OMWCamera/fr.yaml l10n/OMWControls/en.yaml l10n/OMWControls/sv.yaml - l10n/PostProcessing/de.yaml - l10n/PostProcessing/en.yaml - l10n/PostProcessing/ru.yaml - l10n/PostProcessing/sv.yaml - l10n/PostProcessing/fr.yaml - l10n/SavegameMenu/de.yaml - l10n/SavegameMenu/en.yaml - l10n/SavegameMenu/ru.yaml - l10n/SavegameMenu/sv.yaml - l10n/SavegameMenu/fr.yaml - l10n/SettingsMenu/de.yaml - l10n/SettingsMenu/en.yaml - l10n/SettingsMenu/ru.yaml - l10n/SettingsMenu/sv.yaml - l10n/SettingsMenu/fr.yaml + + # L10n for OpenMW menus and non-game-specific messages + l10n/OMWEngine/de.yaml + l10n/OMWEngine/en.yaml + l10n/OMWEngine/ru.yaml + l10n/OMWEngine/sv.yaml + l10n/OMWEngine/fr.yaml + + # L10n for post-processing HUD and built-in shaders + l10n/OMWShaders/de.yaml + l10n/OMWShaders/en.yaml + l10n/OMWShaders/ru.yaml + l10n/OMWShaders/sv.yaml + l10n/OMWShaders/fr.yaml openmw_aux/util.lua openmw_aux/time.lua diff --git a/files/data/l10n/BuiltInShaders/de.yaml b/files/data/l10n/BuiltInShaders/de.yaml deleted file mode 100644 index 5886356782..0000000000 --- a/files/data/l10n/BuiltInShaders/de.yaml +++ /dev/null @@ -1,7 +0,0 @@ -DisplayDepthName: "Visualisiert den Tiefenpuffer." -DisplayDepthFactorDescription: "Bestimmt die Korrelation zwischen dem Pixeltiefenwert und seiner Ausgabefarbe. Hohe Werte führen zu einem helleren Bild." -DisplayDepthFactorName: "Farbfaktor" -ContrastLevelDescription: "Kontraststufe" -ContrastLevelName: "Kontrast" -GammaLevelDescription: "Gamma-Level" -GammaLevelName: "Gamma" \ No newline at end of file diff --git a/files/data/l10n/DebugMenu/de.yaml b/files/data/l10n/DebugMenu/de.yaml deleted file mode 100644 index 2ff4abd89f..0000000000 --- a/files/data/l10n/DebugMenu/de.yaml +++ /dev/null @@ -1,4 +0,0 @@ -DebugWindow: "Debug" -LogViewer: "Protokollansicht" -LuaProfiler: "Lua-Profiler" -PhysicsProfiler: "Physik-Profiler" diff --git a/files/data/l10n/DebugMenu/en.yaml b/files/data/l10n/DebugMenu/en.yaml deleted file mode 100644 index 6f76d147c6..0000000000 --- a/files/data/l10n/DebugMenu/en.yaml +++ /dev/null @@ -1,4 +0,0 @@ -DebugWindow: "Debug" -LogViewer: "Log Viewer" -LuaProfiler: "Lua Profiler" -PhysicsProfiler: "Physics Profiler" diff --git a/files/data/l10n/DebugMenu/fr.yaml b/files/data/l10n/DebugMenu/fr.yaml deleted file mode 100644 index 8b6716e5c6..0000000000 --- a/files/data/l10n/DebugMenu/fr.yaml +++ /dev/null @@ -1,3 +0,0 @@ -DebugWindow: "Fenêtre de débogage" -LogViewer: "Journal" -PhysicsProfiler: "Profileur des performances de la physique" diff --git a/files/data/l10n/DebugMenu/ru.yaml b/files/data/l10n/DebugMenu/ru.yaml deleted file mode 100644 index 0cd7131705..0000000000 --- a/files/data/l10n/DebugMenu/ru.yaml +++ /dev/null @@ -1,4 +0,0 @@ -DebugWindow: "Меню отладки" -LogViewer: "Журнал логов" -LuaProfiler: "Профилировщик Луа" -PhysicsProfiler: "Профилировщик физики" diff --git a/files/data/l10n/DebugMenu/sv.yaml b/files/data/l10n/DebugMenu/sv.yaml deleted file mode 100644 index 07807782de..0000000000 --- a/files/data/l10n/DebugMenu/sv.yaml +++ /dev/null @@ -1,3 +0,0 @@ -DebugWindow: "Felsökning" -LogViewer: "Loggvisare" -PhysicsProfiler: "Fysikprofilerare" diff --git a/files/data/l10n/Navigation/de.yaml b/files/data/l10n/Navigation/de.yaml deleted file mode 100644 index c63a9aeb25..0000000000 --- a/files/data/l10n/Navigation/de.yaml +++ /dev/null @@ -1 +0,0 @@ -BuildingNavigationMesh: "Baue Navigationsgitter" diff --git a/files/data/l10n/Navigation/en.yaml b/files/data/l10n/Navigation/en.yaml deleted file mode 100644 index 06fb8c26ba..0000000000 --- a/files/data/l10n/Navigation/en.yaml +++ /dev/null @@ -1 +0,0 @@ -BuildingNavigationMesh: "Building navigation mesh" diff --git a/files/data/l10n/Navigation/fr.yaml b/files/data/l10n/Navigation/fr.yaml deleted file mode 100644 index e7a6f9aecc..0000000000 --- a/files/data/l10n/Navigation/fr.yaml +++ /dev/null @@ -1 +0,0 @@ -BuildingNavigationMesh: "Construction du mesh de navigation" diff --git a/files/data/l10n/Navigation/ru.yaml b/files/data/l10n/Navigation/ru.yaml deleted file mode 100644 index 509c178dea..0000000000 --- a/files/data/l10n/Navigation/ru.yaml +++ /dev/null @@ -1 +0,0 @@ -BuildingNavigationMesh: "Построение навигационной сетки" diff --git a/files/data/l10n/Navigation/sv.yaml b/files/data/l10n/Navigation/sv.yaml deleted file mode 100644 index d7c4780f94..0000000000 --- a/files/data/l10n/Navigation/sv.yaml +++ /dev/null @@ -1 +0,0 @@ -BuildingNavigationMesh: "Bygger navigeringsmesh" diff --git a/files/data/l10n/SettingsMenu/de.yaml b/files/data/l10n/OMWEngine/de.yaml similarity index 92% rename from files/data/l10n/SettingsMenu/de.yaml rename to files/data/l10n/OMWEngine/de.yaml index 80c02597e2..6b9018b5a6 100644 --- a/files/data/l10n/SettingsMenu/de.yaml +++ b/files/data/l10n/OMWEngine/de.yaml @@ -1,3 +1,24 @@ +# Debug window + +DebugWindow: "Debug" +LogViewer: "Protokollansicht" +LuaProfiler: "Lua-Profiler" +PhysicsProfiler: "Physik-Profiler" + + +# Messages + +BuildingNavigationMesh: "Baue Navigationsgitter" + + +# Save game menu + +SelectCharacter: "Charakterauswahl..." +TimePlayed: "Spielzeit" + + +# Settings menu + ActorsProcessingRange: "Akteur-Verarbeitungsreichweite" Anisotropy: "Anisotropie" CameraSensitivity: "Kameraempfindlichkeit" diff --git a/files/data/l10n/SettingsMenu/en.yaml b/files/data/l10n/OMWEngine/en.yaml similarity index 92% rename from files/data/l10n/SettingsMenu/en.yaml rename to files/data/l10n/OMWEngine/en.yaml index fea8ae78b7..e659e69332 100644 --- a/files/data/l10n/SettingsMenu/en.yaml +++ b/files/data/l10n/OMWEngine/en.yaml @@ -1,3 +1,24 @@ +# Debug window + +DebugWindow: "Debug" +LogViewer: "Log Viewer" +LuaProfiler: "Lua Profiler" +PhysicsProfiler: "Physics Profiler" + + +# Messages + +BuildingNavigationMesh: "Building navigation mesh" + + +# Save game menu + +SelectCharacter: "Select Character..." +TimePlayed: "Time played" + + +# Settings menu + ActorsProcessingRange: "Actors Processing Range" Anisotropy: "Anisotropy" CameraSensitivity: "Camera Sensitivity" diff --git a/files/data/l10n/SettingsMenu/fr.yaml b/files/data/l10n/OMWEngine/fr.yaml similarity index 93% rename from files/data/l10n/SettingsMenu/fr.yaml rename to files/data/l10n/OMWEngine/fr.yaml index 29b1a4ec71..b2f4197a64 100644 --- a/files/data/l10n/SettingsMenu/fr.yaml +++ b/files/data/l10n/OMWEngine/fr.yaml @@ -1,3 +1,23 @@ +# Debug window + +DebugWindow: "Fenêtre de débogage" +LogViewer: "Journal" +PhysicsProfiler: "Profileur des performances de la physique" + + +# Messages + +BuildingNavigationMesh: "Construction du mesh de navigation" + + +# Save game menu + +SelectCharacter: "Sélection du personnage..." +TimePlayed: "Temps de jeu" + + +# Settings menu + ActorsProcessingRange: "Distance de traitement pour les personnages" Anisotropy: "Anisotropie" CameraSensitivity: "Sensibilité de la caméra" diff --git a/files/data/l10n/SettingsMenu/ru.yaml b/files/data/l10n/OMWEngine/ru.yaml similarity index 93% rename from files/data/l10n/SettingsMenu/ru.yaml rename to files/data/l10n/OMWEngine/ru.yaml index fc9760c3d6..35beec7f32 100644 --- a/files/data/l10n/SettingsMenu/ru.yaml +++ b/files/data/l10n/OMWEngine/ru.yaml @@ -1,3 +1,24 @@ +# Debug window + +DebugWindow: "Меню отладки" +LogViewer: "Журнал логов" +LuaProfiler: "Профилировщик Луа" +PhysicsProfiler: "Профилировщик физики" + + +# Messages + +BuildingNavigationMesh: "Построение навигационной сетки" + + +# Save game menu + +SelectCharacter: "Выберите персонажа..." +TimePlayed: "Время в игре" + + +# Settings menu + ActorsProcessingRange: "Дальность обработки персонажей" Anisotropy: "Анизотропная фильтрация" CameraSensitivity: "Чувствительность камеры" diff --git a/files/data/l10n/SettingsMenu/sv.yaml b/files/data/l10n/OMWEngine/sv.yaml similarity index 93% rename from files/data/l10n/SettingsMenu/sv.yaml rename to files/data/l10n/OMWEngine/sv.yaml index 865582b76f..704d1f719b 100644 --- a/files/data/l10n/SettingsMenu/sv.yaml +++ b/files/data/l10n/OMWEngine/sv.yaml @@ -1,3 +1,23 @@ +# Debug window + +DebugWindow: "Felsökning" +LogViewer: "Loggvisare" +PhysicsProfiler: "Fysikprofilerare" + + +# Messages + +BuildingNavigationMesh: "Bygger navigeringsmesh" + + +# Save game menu + +SelectCharacter: "Välj spelfigur..." +TimePlayed: "Speltid" + + +# Settings menu + ActorsProcessingRange: "Processavstånd för figurer" Anisotropy: "Anisotropi" CameraSensitivity: "Kamerakänslighet" diff --git a/files/data/l10n/PostProcessing/de.yaml b/files/data/l10n/OMWShaders/de.yaml similarity index 62% rename from files/data/l10n/PostProcessing/de.yaml rename to files/data/l10n/OMWShaders/de.yaml index fb0846555b..7d17199dd9 100644 --- a/files/data/l10n/PostProcessing/de.yaml +++ b/files/data/l10n/OMWShaders/de.yaml @@ -1,3 +1,5 @@ +# Post-processing HUD + Abovewater: "Überwasser" ActiveShaders: "Aktive Shader" Author: "Autor" @@ -19,3 +21,14 @@ ShaderLockedDescription: "Kann nicht umgeschaltet oder verschoben werden, gesteu ShaderResetUniform: "r" Underwater: "Unterwasser" Version: "Version" + + +# Built-in post-processing shaders + +DisplayDepthName: "Visualisiert den Tiefenpuffer." +DisplayDepthFactorDescription: "Bestimmt die Korrelation zwischen dem Pixeltiefenwert und seiner Ausgabefarbe. Hohe Werte führen zu einem helleren Bild." +DisplayDepthFactorName: "Farbfaktor" +ContrastLevelDescription: "Kontraststufe" +ContrastLevelName: "Kontrast" +GammaLevelDescription: "Gamma-Level" +GammaLevelName: "Gamma" diff --git a/files/data/l10n/BuiltInShaders/en.yaml b/files/data/l10n/OMWShaders/en.yaml similarity index 63% rename from files/data/l10n/BuiltInShaders/en.yaml rename to files/data/l10n/OMWShaders/en.yaml index 00354a45ff..8221be933f 100644 --- a/files/data/l10n/BuiltInShaders/en.yaml +++ b/files/data/l10n/OMWShaders/en.yaml @@ -1,3 +1,30 @@ +# Post-processing HUD + +Abovewater: "Abovewater" +ActiveShaders: "Active Shaders" +Author: "Author" +Description: "Description" +InactiveShaders: "Inactive Shaders" +InExteriors: "Exteriors" +InInteriors: "Interiors" +KeyboardControls: | + Keyboard controls: + + Shift+Right-Arrow > Activate shader + Shift+Left-Arrow > Deactive shader + Shift+Up-Arrow > Move shader up + Shift+Down-Arrow > Move shader down +PostProcessHUD: "Postprocess HUD" +ResetShader: "Reset shader to default state" +ShaderLocked: "Locked" +ShaderLockedDescription: "Cannot be toggled or moved, controlled by external Lua script" +ShaderResetUniform: "r" +Underwater: "Underwater" +Version: "Version" + + +# Built-in post-processing shaders + AdjustmentsDescription: "Colour adjustments." BloomDescription: "Bloom shader performing its calculations in (approximately) linear light." DebugDescription: "Debug shader." diff --git a/files/data/l10n/BuiltInShaders/fr.yaml b/files/data/l10n/OMWShaders/fr.yaml similarity index 64% rename from files/data/l10n/BuiltInShaders/fr.yaml rename to files/data/l10n/OMWShaders/fr.yaml index 8e43bd848a..3b4e47370e 100644 --- a/files/data/l10n/BuiltInShaders/fr.yaml +++ b/files/data/l10n/OMWShaders/fr.yaml @@ -1,3 +1,30 @@ +# Post-processing HUD + +Abovewater: "Hors de l'eau" +ActiveShaders: "Shaders actifs" +Author: "Auteur(e)" +Description: "Description" +InactiveShaders: "Shaders inactifs" +InExteriors: "À l'extérieur" +InInteriors: "En intérieur" +KeyboardControls: | + Raccourcis clavier: + + Majuscule+Flèche droite > Active le shader + Majuscule+Flèche gauche > Désactive le shader + Majuscule+Flèche haut > Monte le shader dans la liste + Majuscule+Flèche bas > Descend le shader dans la liste +MainPassDescription: "Transmet les données de la scène aux shaders de post-traitement. Ne peut être déplacé ou supprimé." +PostProcessHUD: "HUD de post-traitement" +ResetShader: "Restaure le shader dans sa configuration par défaut" +ShaderLocked: "Verrouillé" +ShaderResetUniform: "r" +Underwater: "Sous l'eau" +Version: "Version" + + +# Built-in post-processing shaders + AdjustmentsDescription: "Ajustements de l'image (couleurs, luminosité, contrastes...)." BloomDescription: "Flou lumineux, calculé (approximativement) de façon linéaire suivant l'intensité de la lumière." DebugDescription: "Shader de débogage." diff --git a/files/data/l10n/BuiltInShaders/ru.yaml b/files/data/l10n/OMWShaders/ru.yaml similarity index 62% rename from files/data/l10n/BuiltInShaders/ru.yaml rename to files/data/l10n/OMWShaders/ru.yaml index b61c61c29b..b886f72b54 100644 --- a/files/data/l10n/BuiltInShaders/ru.yaml +++ b/files/data/l10n/OMWShaders/ru.yaml @@ -1,3 +1,30 @@ +# Post-processing HUD + +Abovewater: "Над водой" +ActiveShaders: "Включенные шейдеры" +Author: "Автор" +Description: "Описание" +InactiveShaders: "Выключенные шейдеры" +InExteriors: "Вне помещений" +InInteriors: "В помещениях" +KeyboardControls: | + Управление с помощью клавиатуры: + + Shift+Right-Arrow > Включить шейдер + Shift+Left-Arrow > Выключить шейдер + Shift+Up-Arrow > Передвинуть шейдер выше + Shift+Down-Arrow > Передвинуть шейдер ниже +PostProcessHUD: "Настройки постобработки" +ResetShader: "Обнулить настройки этого шейдера" +ShaderLocked: "Заблокирован" +ShaderLockedDescription: "Не может быть выключен или передвинут, управляется внешним Lua-скриптом" +ShaderResetUniform: "x" +Underwater: "Под водой" +Version: "Версия" + + +# Built-in post-processing shaders + AdjustmentsDescription: "Коррекция цвета." DebugDescription: "Отладочный шейдер." DebugHeaderDepth: "Буфер глубины" diff --git a/files/data/l10n/BuiltInShaders/sv.yaml b/files/data/l10n/OMWShaders/sv.yaml similarity index 59% rename from files/data/l10n/BuiltInShaders/sv.yaml rename to files/data/l10n/OMWShaders/sv.yaml index fe9bfc8350..c1f1a5a333 100644 --- a/files/data/l10n/BuiltInShaders/sv.yaml +++ b/files/data/l10n/OMWShaders/sv.yaml @@ -1,3 +1,30 @@ +# Post-processing HUD + +Abovewater: "Ovan vatten" +ActiveShaders: "Aktiva shaders" +Author: "Skapare" # Author = Författare, but författare sounds very book-author-ish. Skapare, meaning "creator", sounds better in Swedish in this case. Ok? +Description: "Beskrivning" +ActiveShaders: "Inaktiva shaders" +InExteriors: "Exteriörer" +InInteriors: "Interiörer" +KeyboardControls: | + Tangentbordskontroller: + + Shift+Högerpil > Aktivera shader + Shift+Vänsterpil > Avaktivera shader + Shift+Pil upp > Flytta shader upp + Shift+Pil ner > Flytta shader ner +PostProcessHUD: "Postprocess HUD" +ResetShader: "Återställ shader to ursprungligt läge" +ShaderLocked: "Låst" +ShaderLockedDescription: "Kan ej aktiveras/inaktiveras eller flyttas. Kontrolleras av externt Lua-skript" +ShaderResetUniform: "r" +Underwater: "Under vatten" +Version: "Version" + + +# Built-in post-processing shaders + AdjustmentsDescription: "Färgjusteringar." BloomDescription: "Bloomshader som utför sina beräkningar i (ungefärligt) linjärt ljus." DebugDescription: "Felsökningsshader." @@ -10,7 +37,7 @@ DisplayNormalsName: "Visualisera normalvektorer" # på engelska står det "pass ContrastLevelDescription: "Kontrastnivå" ContrastLevelName: "Kontrast" GammaLevelDescription: "Gammanivå" -# GammaLevelName: "Gamma" samma som engelska +GammaLevelName: "Gamma" # samma som engelska StrengthLevelName: "Styrka" StrengthLevelDescription: "Effektens styrka." RadiusLevelName: "Radie" diff --git a/files/data/l10n/PostProcessing/en.yaml b/files/data/l10n/PostProcessing/en.yaml deleted file mode 100644 index 5416cd723f..0000000000 --- a/files/data/l10n/PostProcessing/en.yaml +++ /dev/null @@ -1,21 +0,0 @@ -Abovewater: "Abovewater" -ActiveShaders: "Active Shaders" -Author: "Author" -Description: "Description" -InactiveShaders: "Inactive Shaders" -InExteriors: "Exteriors" -InInteriors: "Interiors" -KeyboardControls: | - Keyboard controls: - - Shift+Right-Arrow > Activate shader - Shift+Left-Arrow > Deactive shader - Shift+Up-Arrow > Move shader up - Shift+Down-Arrow > Move shader down -PostProcessHUD: "Postprocess HUD" -ResetShader: "Reset shader to default state" -ShaderLocked: "Locked" -ShaderLockedDescription: "Cannot be toggled or moved, controlled by external Lua script" -ShaderResetUniform: "r" -Underwater: "Underwater" -Version: "Version" diff --git a/files/data/l10n/PostProcessing/fr.yaml b/files/data/l10n/PostProcessing/fr.yaml deleted file mode 100644 index c5500ac09d..0000000000 --- a/files/data/l10n/PostProcessing/fr.yaml +++ /dev/null @@ -1,21 +0,0 @@ -Abovewater: "Hors de l'eau" -ActiveShaders: "Shaders actifs" -Author: "Auteur(e)" -Description: "Description" -InactiveShaders: "Shaders inactifs" -InExteriors: "À l'extérieur" -InInteriors: "En intérieur" -KeyboardControls: | - Raccourcis clavier: - - Majuscule+Flèche droite > Active le shader - Majuscule+Flèche gauche > Désactive le shader - Majuscule+Flèche haut > Monte le shader dans la liste - Majuscule+Flèche bas > Descend le shader dans la liste -MainPassDescription: "Transmet les données de la scène aux shaders de post-traitement. Ne peut être déplacé ou supprimé." -PostProcessHUD: "HUD de post-traitement" -ResetShader: "Restaure le shader dans sa configuration par défaut" -ShaderLocked: "Verrouillé" -ShaderResetUniform: "r" -Underwater: "Sous l'eau" -Version: "Version" diff --git a/files/data/l10n/PostProcessing/ru.yaml b/files/data/l10n/PostProcessing/ru.yaml deleted file mode 100644 index d0a137bb9a..0000000000 --- a/files/data/l10n/PostProcessing/ru.yaml +++ /dev/null @@ -1,21 +0,0 @@ -Abovewater: "Над водой" -ActiveShaders: "Включенные шейдеры" -Author: "Автор" -Description: "Описание" -InactiveShaders: "Выключенные шейдеры" -InExteriors: "Вне помещений" -InInteriors: "В помещениях" -KeyboardControls: | - Управление с помощью клавиатуры: - - Shift+Right-Arrow > Включить шейдер - Shift+Left-Arrow > Выключить шейдер - Shift+Up-Arrow > Передвинуть шейдер выше - Shift+Down-Arrow > Передвинуть шейдер ниже -PostProcessHUD: "Настройки постобработки" -ResetShader: "Обнулить настройки этого шейдера" -ShaderLocked: "Заблокирован" -ShaderLockedDescription: "Не может быть выключен или передвинут, управляется внешним Lua-скриптом" -ShaderResetUniform: "x" -Underwater: "Под водой" -Version: "Версия" diff --git a/files/data/l10n/PostProcessing/sv.yaml b/files/data/l10n/PostProcessing/sv.yaml deleted file mode 100644 index 5c2e11a011..0000000000 --- a/files/data/l10n/PostProcessing/sv.yaml +++ /dev/null @@ -1,22 +0,0 @@ -Abovewater: "Ovan vatten" -ActiveShaders: "Aktiva shaders" -Author: "Skapare" # Author = Författare, but författare sounds very book-author-ish. Skapare, meaning "creator", sounds better in Swedish in this case. Ok? -Description: "Beskrivning" -ActiveShaders: "Inaktiva shaders" -InExteriors: "Exteriörer" -InInteriors: "Interiörer" -KeyboardControls: | - Tangentbordskontroller: - - Shift+Högerpil > Aktivera shader - Shift+Vänsterpil > Avaktivera shader - Shift+Pil upp > Flytta shader upp - Shift+Pil ner > Flytta shader ner -PostProcessHUD: "Postprocess HUD" -ResetShader: "Återställ shader to ursprungligt läge" -ShaderLocked: "Låst" -ShaderLockedDescription: "Kan ej aktiveras/inaktiveras eller flyttas. Kontrolleras av externt Lua-skript" -ShaderResetUniform: "r" -Underwater: "Under vatten" -Version: "Version" - diff --git a/files/data/l10n/SavegameMenu/de.yaml b/files/data/l10n/SavegameMenu/de.yaml deleted file mode 100644 index 225b6c3a07..0000000000 --- a/files/data/l10n/SavegameMenu/de.yaml +++ /dev/null @@ -1,2 +0,0 @@ -SelectCharacter: "Charakterauswahl..." -TimePlayed: "Spielzeit" diff --git a/files/data/l10n/SavegameMenu/en.yaml b/files/data/l10n/SavegameMenu/en.yaml deleted file mode 100644 index b7e3c60a5f..0000000000 --- a/files/data/l10n/SavegameMenu/en.yaml +++ /dev/null @@ -1,2 +0,0 @@ -SelectCharacter: "Select Character..." -TimePlayed: "Time played" diff --git a/files/data/l10n/SavegameMenu/fr.yaml b/files/data/l10n/SavegameMenu/fr.yaml deleted file mode 100644 index 15bc37b4a7..0000000000 --- a/files/data/l10n/SavegameMenu/fr.yaml +++ /dev/null @@ -1,2 +0,0 @@ -SelectCharacter: "Sélection du personnage..." -TimePlayed: "Temps de jeu" diff --git a/files/data/l10n/SavegameMenu/ru.yaml b/files/data/l10n/SavegameMenu/ru.yaml deleted file mode 100644 index 8b87500bd3..0000000000 --- a/files/data/l10n/SavegameMenu/ru.yaml +++ /dev/null @@ -1,2 +0,0 @@ -SelectCharacter: "Выберите персонажа..." -TimePlayed: "Время в игре" diff --git a/files/data/l10n/SavegameMenu/sv.yaml b/files/data/l10n/SavegameMenu/sv.yaml deleted file mode 100644 index ef23465f6c..0000000000 --- a/files/data/l10n/SavegameMenu/sv.yaml +++ /dev/null @@ -1,2 +0,0 @@ -SelectCharacter: "Välj spelfigur..." -TimePlayed: "Speltid" diff --git a/files/data/mygui/openmw_debug_window.layout b/files/data/mygui/openmw_debug_window.layout index a2635c3c46..7019c5292d 100644 --- a/files/data/mygui/openmw_debug_window.layout +++ b/files/data/mygui/openmw_debug_window.layout @@ -1,7 +1,7 @@ - + diff --git a/files/data/mygui/openmw_postprocessor_hud.layout b/files/data/mygui/openmw_postprocessor_hud.layout index 0c2868435a..4ed8ecdb36 100644 --- a/files/data/mygui/openmw_postprocessor_hud.layout +++ b/files/data/mygui/openmw_postprocessor_hud.layout @@ -2,7 +2,7 @@ - + @@ -12,7 +12,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -80,7 +80,7 @@ - + diff --git a/files/data/mygui/openmw_postprocessor_hud.skin.xml b/files/data/mygui/openmw_postprocessor_hud.skin.xml index b25b7f1372..35ab652f2c 100644 --- a/files/data/mygui/openmw_postprocessor_hud.skin.xml +++ b/files/data/mygui/openmw_postprocessor_hud.skin.xml @@ -59,7 +59,7 @@ - + diff --git a/files/data/mygui/openmw_savegame_dialog.layout b/files/data/mygui/openmw_savegame_dialog.layout index d2d8df295f..a1cdba89ab 100644 --- a/files/data/mygui/openmw_savegame_dialog.layout +++ b/files/data/mygui/openmw_savegame_dialog.layout @@ -6,7 +6,7 @@ - + diff --git a/files/data/mygui/openmw_settings_window.layout b/files/data/mygui/openmw_settings_window.layout index 0569751191..59e9d44ecc 100644 --- a/files/data/mygui/openmw_settings_window.layout +++ b/files/data/mygui/openmw_settings_window.layout @@ -75,7 +75,7 @@ - + @@ -87,7 +87,7 @@ - + @@ -204,10 +204,10 @@ - + - + @@ -226,7 +226,7 @@ - + @@ -238,7 +238,7 @@ - + @@ -277,13 +277,13 @@ - + - - - + + + @@ -293,7 +293,7 @@ - + @@ -303,7 +303,7 @@ - + @@ -313,15 +313,15 @@ - + - + - + @@ -339,7 +339,7 @@ - + @@ -375,17 +375,17 @@ - + - - + + - + @@ -394,7 +394,7 @@ - + @@ -435,7 +435,7 @@ - + @@ -449,7 +449,7 @@ - + @@ -463,14 +463,14 @@ - + - + @@ -489,7 +489,7 @@ - + @@ -498,12 +498,12 @@ - - - - - - + + + + + + @@ -511,7 +511,7 @@ - + @@ -521,9 +521,9 @@ - - - + + + @@ -532,10 +532,10 @@ - + - + @@ -546,7 +546,7 @@ - + @@ -554,7 +554,7 @@ - + @@ -567,7 +567,7 @@ - + @@ -579,13 +579,13 @@ - + - + @@ -597,13 +597,13 @@ - + - + @@ -615,13 +615,13 @@ - + - + @@ -631,7 +631,7 @@ - + @@ -640,10 +640,10 @@ - + - + @@ -681,24 +681,24 @@ - + - + - + - + - + - + diff --git a/files/data/shaders/adjustments.omwfx b/files/data/shaders/adjustments.omwfx index dff182d422..4a9d8ab73b 100644 --- a/files/data/shaders/adjustments.omwfx +++ b/files/data/shaders/adjustments.omwfx @@ -3,8 +3,8 @@ uniform_float uGamma { step = 0.01; min = 0.0; max = 5.0; - display_name = "#{BuiltInShaders:GammaLevelName}"; - description = "#{BuiltInShaders:GammaLevelDescription}"; + display_name = "#{OMWShaders:GammaLevelName}"; + description = "#{OMWShaders:GammaLevelDescription}"; } uniform_float uContrast { @@ -12,8 +12,8 @@ uniform_float uContrast { step = 0.01; min = 0.0; max = 5.0; - display_name = "#{BuiltInShaders:ContrastLevelName}"; - description = "#{BuiltInShaders:ContrastLevelDescription}"; + display_name = "#{OMWShaders:ContrastLevelName}"; + description = "#{OMWShaders:ContrastLevelDescription}"; } fragment main { @@ -31,7 +31,7 @@ fragment main { } technique { - description = "#{BuiltInShaders:AdjustmentsDescription}"; + description = "#{OMWShaders:AdjustmentsDescription}"; version = "1.0"; author = "OpenMW"; passes = main; diff --git a/files/data/shaders/bloomlinear.omwfx b/files/data/shaders/bloomlinear.omwfx index a0b78e4026..3de7139f39 100644 --- a/files/data/shaders/bloomlinear.omwfx +++ b/files/data/shaders/bloomlinear.omwfx @@ -3,48 +3,48 @@ uniform_float uGamma { min = 0.1; max = 4.0; step = 0.01; - display_name = "#{BuiltInShaders:GammaLevelName}"; - description = "#{BuiltInShaders:GammaLevelDescription}"; + display_name = "#{OMWShaders:GammaLevelName}"; + description = "#{OMWShaders:GammaLevelDescription}"; } uniform_float uThreshold { default = 0.35; min = 0.0; max = 1.0; step = 0.01; - display_name = "#{BuiltInShaders:BloomThresholdLevelName}"; - description = "#{BuiltInShaders:BloomThresholdLevelDescription}"; + display_name = "#{OMWShaders:BloomThresholdLevelName}"; + description = "#{OMWShaders:BloomThresholdLevelDescription}"; } uniform_float uClamp { default = 1.0; min = 0.0; max = 1.0; step = 0.01; - display_name = "#{BuiltInShaders:BloomClampLevelName}"; - description = "#{BuiltInShaders:BloomClampLevelDescription}"; + display_name = "#{OMWShaders:BloomClampLevelName}"; + description = "#{OMWShaders:BloomClampLevelDescription}"; } uniform_float uSkyFactor { default = 0.5; min = 0.0; max = 2.0; step = 0.01; - display_name = "#{BuiltInShaders:SkyFactorLevelName}"; - description = "#{BuiltInShaders:SkyFactorLevelDescription}"; + display_name = "#{OMWShaders:SkyFactorLevelName}"; + description = "#{OMWShaders:SkyFactorLevelDescription}"; } uniform_float uRadius { default = 0.5; min = 0.0; max = 1.0; step = 0.01; - display_name = "#{BuiltInShaders:RadiusLevelName}"; - description = "#{BuiltInShaders:RadiusLevelDescription}"; + display_name = "#{OMWShaders:RadiusLevelName}"; + description = "#{OMWShaders:RadiusLevelDescription}"; } uniform_float uStrength { default = 0.25; min = 0.0; max = 1.0; step = 0.01; - display_name = "#{BuiltInShaders:StrengthLevelName}"; - description = "#{BuiltInShaders:StrengthLevelDescription}"; + display_name = "#{OMWShaders:StrengthLevelName}"; + description = "#{OMWShaders:StrengthLevelDescription}"; } shared { @@ -215,7 +215,7 @@ fragment final(rt1=RT_Vertical) { technique { passes = nomipmap, horizontal, vertical, final; - description = "#{BuiltInShaders:BloomDescription}"; + description = "#{OMWShaders:BloomDescription}"; author = "OpenMW"; version = "1.0"; } diff --git a/files/data/shaders/debug.omwfx b/files/data/shaders/debug.omwfx index addcbf6c38..4bfeea2499 100644 --- a/files/data/shaders/debug.omwfx +++ b/files/data/shaders/debug.omwfx @@ -1,7 +1,7 @@ uniform_bool uDisplayDepth { - header = "#{BuiltInShaders:DebugHeaderDepth}"; + header = "#{OMWShaders:DebugHeaderDepth}"; default = true; - display_name = "#{BuiltInShaders:DisplayDepthName}"; + display_name = "#{OMWShaders:DisplayDepthName}"; } uniform_float uDepthFactor { @@ -9,14 +9,14 @@ uniform_float uDepthFactor { min = 0.01; max = 20.0; default = 1.0; - display_name = "#{BuiltInShaders:DisplayDepthFactorName}"; - description = "#{BuiltInShaders:DisplayDepthFactorDescription}"; + display_name = "#{OMWShaders:DisplayDepthFactorName}"; + description = "#{OMWShaders:DisplayDepthFactorDescription}"; } uniform_bool uDisplayNormals { - header = "#{BuiltInShaders:DebugHeaderNormals}"; + header = "#{OMWShaders:DebugHeaderNormals}"; default = true; - display_name = "#{BuiltInShaders:DisplayNormalsName}"; + display_name = "#{OMWShaders:DisplayNormalsName}"; } fragment main { @@ -38,7 +38,7 @@ fragment main { technique { passes = main; - description = "#{BuiltInShaders:DebugDescription}"; + description = "#{OMWShaders:DebugDescription}"; author = "OpenMW"; version = "1.0"; pass_normals = true; From 8dd2aa09ca3e28be93641cbbed420aa9b66491e5 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Mon, 2 Jan 2023 14:21:34 +0100 Subject: [PATCH 07/37] Add naming policy for scripts and l10n files to documentation --- docs/source/reference/lua-scripting/api.rst | 3 ++- .../reference/lua-scripting/overview.rst | 27 ++++++++++++++----- .../source/reference/modding/localisation.rst | 17 +++++++++++- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/docs/source/reference/lua-scripting/api.rst b/docs/source/reference/lua-scripting/api.rst index e59b926d0f..061f2ce5c7 100644 --- a/docs/source/reference/lua-scripting/api.rst +++ b/docs/source/reference/lua-scripting/api.rst @@ -59,7 +59,8 @@ Sources can be found in ``resources/vfs/openmw_aux``. In theory mods can overrid .. include:: tables/aux_packages.rst -**Interfaces of built-in scripts** +Interfaces of built-in scripts +------------------------------ .. list-table:: :widths: 20 20 60 diff --git a/docs/source/reference/lua-scripting/overview.rst b/docs/source/reference/lua-scripting/overview.rst index 47008428ab..f09b56a47c 100644 --- a/docs/source/reference/lua-scripting/overview.rst +++ b/docs/source/reference/lua-scripting/overview.rst @@ -85,7 +85,7 @@ Let's write a simple example of a `Player script`: .. code-block:: Lua - -- Save to my_lua_mod/example/player.lua + -- Save to my_lua_mod/scripts/example/player.lua local ui = require('openmw.ui') @@ -107,7 +107,7 @@ The options are: 1. Create text file "my_lua_mod.omwscripts" with the following line: :: - PLAYER: example/player.lua + PLAYER: scripts/example/player.lua 2. (not implemented yet) Add the script in OpenMW CS on "Lua scripts" view and save as "my_lua_mod.omwaddon". @@ -122,6 +122,19 @@ Enable it in ``openmw.cfg`` the same way as any other mod: Now every time the player presses "X" on a keyboard, a message is shown. +Lua scripts naming policy +========================= + +Technically scripts can be placed anywhere in the virtual file system, but we recommend to follow the naming policy and choose one of: + +- ``scripts//.lua``: general case. +- ``scripts///.lua``: if "ModName" is short and can potentially collide with other mods. +- ``scripts/.lua``: if it is a simple mod that consists from a single script, the script can placed to ``scripts/`` without subdirs. + +``scripts/omw/`` is reserved for built-in scripts, don't use it in mods. Overriding built-in scripts is not recommended, prefer to adjust their behaviour via :ref:`Interfaces of built-in scripts` instead. + +See also naming policy of :ref:`Localisation Files`. + Format of ``.omwscripts`` ========================= @@ -129,20 +142,20 @@ Format of ``.omwscripts`` # Lines starting with '#' are comments - GLOBAL: my_mod/some_global_script.lua + GLOBAL: scripts/my_mod/some_global_script.lua # Script that will be automatically attached to the player - PLAYER: my_mod/player.lua + PLAYER: scripts/my_mod/player.lua # Local script that will be automatically attached to every NPC and every creature in the game - NPC, CREATURE: my_mod/some_other_script.lua + NPC, CREATURE: scripts/my_mod/some_other_script.lua # Local script that can be attached to any object by a global script - CUSTOM: my_mod/something.lua + CUSTOM: scripts/my_mod/something.lua # Local script that will be automatically attached to any Container AND can be # attached to any other object by a global script. - CONTAINER, CUSTOM: my_mod/container.lua + CONTAINER, CUSTOM: scripts/my_mod/container.lua Each script is described by one line: ``: ``. diff --git a/docs/source/reference/modding/localisation.rst b/docs/source/reference/modding/localisation.rst index bc66053d58..457d2a6c27 100644 --- a/docs/source/reference/modding/localisation.rst +++ b/docs/source/reference/modding/localisation.rst @@ -31,11 +31,26 @@ E.g. if you include ``en_US.yaml`` and ``en_GB.yaml`` localisation files, you sh Note that because of the fallbacks only messages which differ between variants need to be included in the country-specific localisation files. Localisation Files --------------------------- +------------------ Localisation files (containing the message names and translations) should be stored in the VFS as files of the form ``l10n//.yaml``. +**Naming policy** + +"ContextName" should be in line with :ref:`Lua scripts naming policy`: + +- L10n files for ``scripts//.lua`` should be placed to ``l10n//.yaml``. +- L10n files for ``scripts///.lua`` should be placed to ``l10n//.yaml``. + +In most cases one mod should have only one l10n context. Don't create a new context for each single message. Really big mods with hundreds and thousands of messages can have several l10n contexts. In this case all context names should start with the name of the mod. I.e. `` = `` (or ````). + +L10n contexts with prefix "OMW" are reserved for the OpenMW itself (in particular for built-in scripts ``scripts/omw/``) and shouldn't be used in mods. + +Built-in l10n contexts "Interface" and "Calendar" don't have the "OMW" prefix because these messages are more generic and can be reused in mods. + +**Format** + Messages contents have the form of ICU MessageFormat strings. See `the Formatting Messages chapter of the ICU Guide `_ for a guide to MessageFormat, and see From f0a06258fb618f92505868b7a12ea495020c1d6c Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 31 Dec 2022 19:34:01 +0100 Subject: [PATCH 08/37] [Lua] New function `cell:hasTag` --- apps/openmw/mwlua/cellbindings.cpp | 13 +++++++++++++ files/lua_api/openmw/core.lua | 12 ++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwlua/cellbindings.cpp b/apps/openmw/mwlua/cellbindings.cpp index 0f0062714c..dff4af1afd 100644 --- a/apps/openmw/mwlua/cellbindings.cpp +++ b/apps/openmw/mwlua/cellbindings.cpp @@ -45,10 +45,23 @@ namespace MWLua cellT["gridX"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->getGridX(); }); cellT["gridY"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->getGridY(); }); cellT["hasWater"] = sol::readonly_property([](const CellT& c) { return c.mStore->getCell()->hasWater(); }); + cellT["hasSky"] = sol::readonly_property([](const CellT& c) { + return c.mStore->getCell()->isExterior() || (c.mStore->getCell()->mData.mFlags & ESM::Cell::QuasiEx) != 0; + }); cellT["isExterior"] = sol::readonly_property([](const CellT& c) { return c.mStore->isExterior(); }); + + // deprecated, use cell:hasTag("QuasiExterior") instead cellT["isQuasiExterior"] = sol::readonly_property( [](const CellT& c) { return (c.mStore->getCell()->mData.mFlags & ESM::Cell::QuasiEx) != 0; }); + cellT["hasTag"] = [](const CellT& c, std::string_view tag) -> bool { + if (tag == "NoSleep") + return (c.mStore->getCell()->mData.mFlags & ESM::Cell::NoSleep) != 0; + else if (tag == "QuasiExterior") + return (c.mStore->getCell()->mData.mFlags & ESM::Cell::QuasiEx) != 0; + return false; + }; + cellT["isInSameSpace"] = [](const CellT& c, const ObjectT& obj) { const MWWorld::Ptr& ptr = obj.ptr(); if (!ptr.isInCell()) diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 38f73ec669..ebe62477bf 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -182,11 +182,19 @@ -- @type Cell -- @field #string name Name of the cell (can be empty string). -- @field #string region Region of the cell. --- @field #boolean isExterior Whether the cell is an exterior. --- @field #boolean isQuasiExterior Whether the cell is a quasi exterior (like interior but with the sky and the wheather). +-- @field #boolean isExterior Whether the cell is an exterior cell. "Exterior" means grid of cells where the player can seamless walk from one cell to another without teleports. QuasiExterior (interior with sky) is not an exterior. +-- @field #boolean isQuasiExterior (DEPRECATED, use `hasTag("QuasiExterior")`) Whether the cell is a quasi exterior (like interior but with the sky and the wheather). -- @field #number gridX Index of the cell by X (only for exteriors). -- @field #number gridY Index of the cell by Y (only for exteriors). -- @field #boolean hasWater True if the cell contains water. +-- @field #boolean hasSky True if in this cell sky should be rendered. + +--- +-- Returns true if the cell has given tag. +-- @function [parent=#Cell] hasTag +-- @param self +-- @param #string tag One of "QuasiExterior", "NoSleep". +-- @return #boolean --- -- Returns true either if the cell contains the object or if the cell is an exterior and the object is also in an exterior. From e9190bedc86f6b84b96980dadf9058195bde4777 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Mon, 2 Jan 2023 18:35:05 +0100 Subject: [PATCH 09/37] Reverts useless CmakeList formatting --- components/CMakeLists.txt | 261 +++++++++++++++++++------------------- 1 file changed, 129 insertions(+), 132 deletions(-) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 9646aae695..c1dbe36798 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -1,84 +1,84 @@ -project(Components) +project (Components) # Version file -set(VERSION_IN_FILE "${OpenMW_SOURCE_DIR}/files/version.in") -set(VERSION_FILE_PATH_BASE "${OpenMW_BINARY_DIR}") -set(VERSION_FILE_PATH_RELATIVE resources/version) - -if(GIT_CHECKOUT) +set (VERSION_IN_FILE "${OpenMW_SOURCE_DIR}/files/version.in") +set (VERSION_FILE_PATH_BASE "${OpenMW_BINARY_DIR}") +set (VERSION_FILE_PATH_RELATIVE resources/version) +if (GIT_CHECKOUT) get_generator_is_multi_config(multi_config) - add_custom_target(git-version - COMMAND ${CMAKE_COMMAND} - -DGIT_EXECUTABLE=${GIT_EXECUTABLE} - -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR} - -DVERSION_IN_FILE=${VERSION_IN_FILE} - -DVERSION_FILE_PATH_BASE=${VERSION_FILE_PATH_BASE} - -DVERSION_FILE_PATH_RELATIVE=${VERSION_FILE_PATH_RELATIVE} - -DOPENMW_VERSION_MAJOR=${OPENMW_VERSION_MAJOR} - -DOPENMW_VERSION_MINOR=${OPENMW_VERSION_MINOR} - -DOPENMW_VERSION_RELEASE=${OPENMW_VERSION_RELEASE} - -DOPENMW_VERSION=${OPENMW_VERSION} - -DMACROSFILE=${CMAKE_SOURCE_DIR}/cmake/OpenMWMacros.cmake - "-DCMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}" - -Dgenerator_is_multi_config_var=${multi_config} - -P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/GitVersion.cmake - VERBATIM) -else(GIT_CHECKOUT) + add_custom_target (git-version + COMMAND ${CMAKE_COMMAND} + -DGIT_EXECUTABLE=${GIT_EXECUTABLE} + -DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR} + -DVERSION_IN_FILE=${VERSION_IN_FILE} + -DVERSION_FILE_PATH_BASE=${VERSION_FILE_PATH_BASE} + -DVERSION_FILE_PATH_RELATIVE=${VERSION_FILE_PATH_RELATIVE} + -DOPENMW_VERSION_MAJOR=${OPENMW_VERSION_MAJOR} + -DOPENMW_VERSION_MINOR=${OPENMW_VERSION_MINOR} + -DOPENMW_VERSION_RELEASE=${OPENMW_VERSION_RELEASE} + -DOPENMW_VERSION=${OPENMW_VERSION} + -DMACROSFILE=${CMAKE_SOURCE_DIR}/cmake/OpenMWMacros.cmake + "-DCMAKE_CONFIGURATION_TYPES=${CMAKE_CONFIGURATION_TYPES}" + -Dgenerator_is_multi_config_var=${multi_config} + -P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/GitVersion.cmake + VERBATIM) +else (GIT_CHECKOUT) configure_resource_file(${VERSION_IN_FILE} ${VERSION_FILE_PATH_BASE} ${VERSION_FILE_PATH_RELATIVE}) -endif(GIT_CHECKOUT) +endif (GIT_CHECKOUT) # source files -add_component_dir(lua + +add_component_dir (lua luastate scriptscontainer utilpackage serialization configuration l10n storage -) + ) -add_component_dir(l10n +add_component_dir (l10n messagebundles manager -) + ) -add_component_dir(settings +add_component_dir (settings settings parser -) + ) -add_component_dir(bsa +add_component_dir (bsa bsa_file compressedbsafile -) + ) -add_component_dir(vfs +add_component_dir (vfs manager archive bsaarchive filesystemarchive registerarchives -) + ) -add_component_dir(resource +add_component_dir (resource scenemanager keyframemanager imagemanager bulletshapemanager bulletshape niffilemanager objectcache multiobjectcache resourcesystem resourcemanager stats animation foreachbulletobject errormarker -) + ) -add_component_dir(shader +add_component_dir (shader shadermanager shadervisitor removedalphafunc -) + ) -add_component_dir(sceneutil +add_component_dir (sceneutil clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller lightmanager lightutil positionattitudetransform workqueue pathgridutil waterutil writescene serialize optimizer actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin osgacontroller rtt screencapture depth color riggeometryosgaextension extradata unrefqueue -) + ) -add_component_dir(nif +add_component_dir (nif controlled effect niftypes record controller extra node record_ptr data niffile property nifkey base nifstream physics -) + ) -add_component_dir(nifosg +add_component_dir (nifosg nifloader controller particle matrixtransform -) + ) -add_component_dir(nifbullet +add_component_dir (nifbullet bulletnifloader -) + ) -add_component_dir(to_utf8 +add_component_dir (to_utf8 to_utf8 -) + ) add_component_dir(esm attr common defs esmcommon records util luascripts format refid) @@ -86,7 +86,7 @@ add_component_dir(fx pass technique lexer widgets stateupdater) add_component_dir(std140 ubo) -add_component_dir(esm3 +add_component_dir (esm3 esmreader esmwriter loadacti loadalch loadappa loadarmo loadbody loadbook loadbsgn loadcell loadclas loadclot loadcont loadcrea loaddial loaddoor loadench loadfact loadglob loadgmst loadinfo loadingr loadland loadlevlist loadligh loadlock loadprob loadrepa loadltex loadmgef loadmisc @@ -96,13 +96,13 @@ add_component_dir(esm3 inventorystate containerstate npcstate creaturestate dialoguestate statstate npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache -) + ) -add_component_dir(esm3terrain +add_component_dir (esm3terrain storage -) + ) -add_component_dir(esm4 +add_component_dir (esm4 acti actor common @@ -191,97 +191,97 @@ add_component_dir(esm4 loadweap loadwrld reader - readerutils reference script + readerutils ) -add_component_dir(misc +add_component_dir (misc constants utf8stream resourcehelpers rng messageformatparser weakcache thread compression osguservalues color tuplemeta tuplehelpers -) + ) -add_component_dir(stereo +add_component_dir (stereo frustum multiview stereomanager types -) + ) -add_component_dir(debug +add_component_dir (debug debugging debuglog gldebug debugdraw -) + ) IF(NOT WIN32 AND NOT APPLE) add_definitions(-DGLOBAL_DATA_PATH="${GLOBAL_DATA_PATH}") add_definitions(-DGLOBAL_CONFIG_PATH="${GLOBAL_CONFIG_PATH}") ENDIF() - -add_component_dir(files +add_component_dir (files linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager constrainedfilestream memorystream hash configfileparser openfile constrainedfilestreambuf conversion -) + ) -add_component_dir(compiler +add_component_dir (compiler context controlparser errorhandler exception exprparser extensions fileparser generator lineparser literals locals output parser scanner scriptparser skipparser streamerrorhandler stringparser tokenloc nullerrorhandler opcodes extensions0 declarationparser quickfileparser discardparser junkparser -) + ) -add_component_dir(interpreter +add_component_dir (interpreter context controlopcodes genericopcodes installopcodes interpreter localopcodes mathopcodes miscopcodes opcodes runtime types defines -) + ) -add_component_dir(translation +add_component_dir (translation translation -) + ) -add_component_dir(terrain +add_component_dir (terrain storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager compositemaprenderer quadtreeworld quadtreenode viewdata cellborder view heightcull -) + ) -add_component_dir(loadinglistener +add_component_dir (loadinglistener loadinglistener -) + ) -add_component_dir(myguiplatform +add_component_dir (myguiplatform myguirendermanager myguidatamanager myguiplatform myguitexture myguiloglistener additivelayer scalinglayer -) + ) -add_component_dir(widgets +add_component_dir (widgets box fontwrapper imagebutton tags list numericeditbox sharedstatebutton windowcaption widgets -) + ) -add_component_dir(fontloader +add_component_dir (fontloader fontloader -) + ) -add_component_dir(sdlutil +add_component_dir (sdlutil gl4es_init sdlgraphicswindow imagetosurface sdlinputwrapper sdlvideowrapper events sdlcursormanager sdlmappings -) + ) -add_component_dir(version +add_component_dir (version version -) + ) -add_component_dir(fallback +add_component_dir (fallback fallback validate -) + ) -add_component_dir(lua_ui +add_component_dir (lua_ui registerscriptsettings scriptsettings properties widget element util layers content alignment resources adapter text textedit window image container flex -) + ) + if(WIN32) - add_component_dir(crashcatcher + add_component_dir (crashcatcher windows_crashcatcher windows_crashmonitor windows_crashshm ) elseif(NOT ANDROID) - add_component_dir(crashcatcher + add_component_dir (crashcatcher crashcatcher ) endif() @@ -317,11 +317,11 @@ add_component_dir(detournavigator stats commulativeaabb recastcontext -) + ) add_component_dir(loadinglistener reporter -) + ) add_component_dir(sqlite3 db @@ -336,63 +336,63 @@ add_component_dir(esmloader add_component_dir(navmeshtool protocol -) + ) add_component_dir(platform platform file -) + ) -if(WIN32) +if (WIN32) add_component_dir(platform file.win32 - ) -elseif(UNIX) + ) +elseif (UNIX) add_component_dir(platform file.posix - ) -else() + ) +else () add_component_dir(platform file.stdio - ) + ) endif() -set(ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui -) +set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui + ) -if(USE_QT) - add_component_qt_dir(contentselector +if (USE_QT) + add_component_qt_dir (contentselector model/modelitem model/esmfile model/naturalsort model/contentmodel model/loadordererror view/combobox view/contentselector - ) - add_component_qt_dir(config + ) + add_component_qt_dir (config gamesettings launchersettings settingsbase - ) + ) - add_component_qt_dir(process + add_component_qt_dir (process processinvoker - ) + ) - add_component_qt_dir(misc + add_component_qt_dir (misc helpviewer - ) + ) - add_component_qt_dir(files + add_component_qt_dir (files qtconversion - ) + ) QT5_WRAP_UI(ESM_UI_HDR ${ESM_UI}) endif() -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") +if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" AND NOT APPLE) add_definitions(-fPIC) endif() -endif() +endif () include_directories(${BULLET_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) @@ -437,7 +437,7 @@ target_link_libraries(components smhasher ${ICU_LIBRARIES} yaml-cpp -) + ) if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.77.0) target_link_libraries(components ${Boost_ATOMIC_LIBRARY}) @@ -445,46 +445,46 @@ endif() target_link_libraries(components ${BULLET_LIBRARIES}) -if(WIN32) +if (WIN32) target_link_libraries(components - ${Boost_LOCALE_LIBRARY} - ${Boost_ZLIB_LIBRARY}) + ${Boost_LOCALE_LIBRARY} + ${Boost_ZLIB_LIBRARY}) endif() -if(USE_QT) +if (USE_QT) add_library(components_qt STATIC ${COMPONENT_QT_FILES} ${ESM_UI_HDR}) target_link_libraries(components_qt components Qt5::Widgets Qt5::Core) target_compile_definitions(components_qt PRIVATE OPENMW_DOC_BASEURL="${OPENMW_DOC_BASEURL}") endif() -if(GIT_CHECKOUT) - add_dependencies(components git-version) -endif(GIT_CHECKOUT) +if (GIT_CHECKOUT) + add_dependencies (components git-version) +endif (GIT_CHECKOUT) -if(OSG_STATIC AND CMAKE_SYSTEM_NAME MATCHES "Linux") +if (OSG_STATIC AND CMAKE_SYSTEM_NAME MATCHES "Linux") find_package(X11 REQUIRED COMPONENTS Xinerama Xrandr) target_link_libraries(components ${CMAKE_DL_LIBS} X11::X11 X11::Xinerama X11::Xrandr) find_package(Fontconfig MODULE) - if(Fontconfig_FOUND) target_link_libraries(components Fontconfig::Fontconfig) endif() endif() -if(WIN32) +if (WIN32) target_link_libraries(components shlwapi) endif() # Fix for not visible pthreads functions for linker with glibc 2.15 -if(UNIX AND NOT APPLE) - target_link_libraries(components ${CMAKE_THREAD_LIBS_INIT}) +if (UNIX AND NOT APPLE) +target_link_libraries(components ${CMAKE_THREAD_LIBS_INIT}) endif() -if(BUILD_WITH_CODE_COVERAGE) +if (BUILD_WITH_CODE_COVERAGE) add_definitions(--coverage) target_link_libraries(components gcov) endif() + # Make the variable accessible for other subdirectories set(COMPONENT_FILES ${COMPONENT_FILES} PARENT_SCOPE) @@ -493,10 +493,8 @@ target_compile_definitions(components PUBLIC BT_USE_DOUBLE_PRECISION) if(OSG_STATIC) unset(_osg_plugins_static_files) add_library(components_osg_plugins INTERFACE) - foreach(_plugin ${USED_OSG_PLUGINS}) string(TOUPPER ${_plugin} _plugin_uc) - if(OPENMW_USE_SYSTEM_OSG) list(APPEND _osg_plugins_static_files ${${_plugin_uc}_LIBRARY}) else() @@ -505,7 +503,6 @@ if(OSG_STATIC) add_dependencies(components_osg_plugins ${${_plugin_uc}_LIBRARY}) endif() endforeach() - # We use --whole-archive because OSG plugins use registration. get_whole_archive_options(_opts ${_osg_plugins_static_files}) target_link_options(components_osg_plugins INTERFACE ${_opts}) @@ -525,7 +522,7 @@ if(USE_QT) set_property(TARGET components_qt PROPERTY AUTOMOC ON) endif(USE_QT) -if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC) +if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.16 AND MSVC) target_precompile_headers(components PUBLIC From 3b2d9161c4189bb3dac9ad07f5a396269f4caadd Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Mon, 2 Jan 2023 19:20:03 +0100 Subject: [PATCH 10/37] Applied review advice better deals with templated functions meant for esm3 used by esm4s. simplified loading of esm4 and dealing with unhandled record types. --- apps/esmtool/tes4.cpp | 3 +-- apps/openmw/mwworld/esmloader.cpp | 7 ++----- apps/openmw/mwworld/esmstore.cpp | 11 ++++------- apps/openmw/mwworld/store.cpp | 8 ++++---- components/esm4/loadcell.cpp | 2 +- 5 files changed, 12 insertions(+), 19 deletions(-) diff --git a/apps/esmtool/tes4.cpp b/apps/esmtool/tes4.cpp index 50c7d24b7c..78e5931c0e 100644 --- a/apps/esmtool/tes4.cpp +++ b/apps/esmtool/tes4.cpp @@ -184,7 +184,7 @@ namespace EsmTool if constexpr (hasFormId) std::cout << "\n FormId: " << value.mFormId; if constexpr (hasRefId) - std::cout << "\n RefId: " << value.mId; + std::cout << "\n FormId: " << value.mId; if constexpr (hasFlags) std::cout << "\n Record flags: " << recordFlags(value.mFlags); if constexpr (hasEditorId) @@ -196,7 +196,6 @@ namespace EsmTool if constexpr (hasKf) std::cout << "\n Kf:" << WriteArray("\n - ", value.mKf); std::cout << '\n'; - return; } bool readRecord(const Params& params, ESM4::Reader& reader) diff --git a/apps/openmw/mwworld/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index c529a9834c..be2b3abda9 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -28,10 +28,6 @@ namespace MWWorld { auto stream = Files::openBinaryInputFileStream(filepath); - if (!stream->is_open()) - { - throw std::runtime_error(std::string("File Failed to open file: ") + std::strerror(errno) + "\n"); - } const ESM::Format format = ESM::readFormat(*stream); stream->seekg(0); @@ -64,13 +60,14 @@ namespace MWWorld } case ESM::Format::Tes4: { - if (mEncoder) + if (mEncoder != nullptr) { ESM4::Reader readerESM4(std::move(stream), filepath); auto statelessEncoder = mEncoder->getStatelessEncoder(); readerESM4.setEncoder(&statelessEncoder); mStore.loadESM4(readerESM4, listener, mDialogue); } + break; } } } diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 31c788283d..6f39a3e602 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -197,7 +197,7 @@ namespace MWWorld }; template - static void typedReadRecordESM4(ESM4::Reader& reader, ESMStore& stores, Store& store, int& found) + static bool typedReadRecordESM4(ESM4::Reader& reader, Store& store) { auto recordType = static_cast(reader.hdr().record.typeId); @@ -212,20 +212,17 @@ namespace MWWorld T value; value.load(reader); store.insertStatic(value); - found++; + return true; } } } + return false; } static bool readRecord(ESM4::Reader& reader, ESMStore& store) { - int found = 0; - std::apply([&reader, &store, &found]( - auto&... x) { (ESMStoreImp::typedReadRecordESM4(reader, store, x, found), ...); }, + return std::apply([&reader](auto&... x) { return (ESMStoreImp::typedReadRecordESM4(reader, x) || ...); }, store.mStoreImp->mStores); - assert(found <= 1); - return found; } }; diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 71161fa6a4..60179f01b5 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -164,8 +164,9 @@ namespace MWWorld std::stringstream msg; if constexpr (!ESM::isESM4Rec(T::sRecordId)) { - msg << T::getRecordType() << " '" << id << "' not found"; + msg << T::getRecordType(); } + msg << " '" << id << "' not found"; throw std::runtime_error(msg.str()); } return ptr; @@ -298,13 +299,12 @@ namespace MWWorld { for (typename Dynamic::const_iterator iter(mDynamic.begin()); iter != mDynamic.end(); ++iter) { - writer.startRecord(T::sRecordId); if constexpr (!ESM::isESM4Rec(T::sRecordId)) { + writer.startRecord(T::sRecordId); iter->second.save(writer); + writer.endRecord(T::sRecordId); } - - writer.endRecord(T::sRecordId); } } template diff --git a/components/esm4/loadcell.cpp b/components/esm4/loadcell.cpp index adf8a13180..0b829d657f 100644 --- a/components/esm4/loadcell.cpp +++ b/components/esm4/loadcell.cpp @@ -36,9 +36,9 @@ #include #include "reader.hpp" +// #include "writer.hpp" #include -// #include "writer.hpp" // TODO: Try loading only EDID and XCLC (along with mFormId, mFlags and mParent) // From 6b6c732a59787ca2707cf02650677dc5fe39c245 Mon Sep 17 00:00:00 2001 From: "glassmancody.info" Date: Tue, 3 Jan 2023 10:16:30 -0800 Subject: [PATCH 11/37] properly update postprocess uniform for sun position in interiors --- apps/openmw/mwrender/renderingmanager.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index cb5ad8d9a6..ca71532828 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -771,9 +771,11 @@ namespace MWRender setAmbientColour(ambient); osg::Vec4f diffuse = SceneUtil::colourFromRGB(cell->mAmbi.mSunlight); - mSunLight->setDiffuse(diffuse); - mSunLight->setSpecular(diffuse); - mSunLight->setPosition(osg::Vec4f(-0.15f, 0.15f, 1.f, 0.f)); + setSunColour(diffuse, diffuse, 1.f); + + const osg::Vec4f interiorSunPos = osg::Vec4f(-0.15f, 0.15f, 1.f, 0.f); + mPostProcessor->getStateUpdater()->setSunPos(interiorSunPos, false); + mSunLight->setPosition(interiorSunPos); } void RenderingManager::setSunColour(const osg::Vec4f& diffuse, const osg::Vec4f& specular, float sunVis) From ba9c2c99282e5276f9104230df4dafe6f25c801c Mon Sep 17 00:00:00 2001 From: unelsson Date: Sat, 31 Dec 2022 01:03:25 +0200 Subject: [PATCH 12/37] Add TemplateRef to animated Collada model --- components/resource/scenemanager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 06fbd8470f..516f3e4af4 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -636,6 +636,9 @@ namespace Resource backToOriginTrans->addChild(newRiggeometryHolder); group->addChild(backToOriginTrans); + + node->getOrCreateUserDataContainer()->addUserObject( + new TemplateRef(newRiggeometryHolder->getGeometry(0))); } } } From 9b1c4054673700efd3453592dfe7d4bdd1be6213 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Tue, 3 Jan 2023 22:16:42 +0100 Subject: [PATCH 13/37] On store creation checks that each record has a different RecordId. --- apps/openmw/mwworld/esmstore.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 6f39a3e602..d69d4e8804 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -219,6 +219,35 @@ namespace MWWorld return false; } + template + static unsigned int hasSameRecordId(const Store& store, ESM::RecNameInts RecName) + { + if constexpr (HasRecordId::value) + { + return T::sRecordId == RecName ? 1 : 0; + } + else + { + return 0; + } + } + + template + static void testRecNameIntCount(const Store& store, const ESMStore::StoreTuple& stores) + { + if constexpr (HasRecordId::value) + { + const unsigned int recordIdCount + = std::apply([](auto&&... x) { return (hasSameRecordId(x, T::sRecordId) + ...); }, stores); + assert(recordIdCount == 1); + } + } + + static void testAllRecNameIntUnique(const ESMStore::StoreTuple& stores) + { + std::apply([&stores](auto&&... x) { (testRecNameIntCount(x, stores), ...); }, stores); + } + static bool readRecord(ESM4::Reader& reader, ESMStore& store) { return std::apply([&reader](auto&... x) { return (ESMStoreImp::typedReadRecordESM4(reader, x) || ...); }, @@ -250,6 +279,7 @@ namespace MWWorld { mStoreImp = std::make_unique(); std::apply([this](auto&... x) { (ESMStoreImp::assignStoreToIndex(*this, x), ...); }, mStoreImp->mStores); + ESMStoreImp::testAllRecNameIntUnique(mStoreImp->mStores); mDynamicCount = 0; getWritable().setCells(getWritable()); } From 64a9f742da453b04824ce0b9af96919e11b7b9d6 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Tue, 3 Jan 2023 23:28:31 +0100 Subject: [PATCH 14/37] Improves check: throws an error that says which RecName is used twice. --- apps/openmw/mwworld/esmstore.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index d69d4e8804..29d014afd1 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -196,6 +196,28 @@ namespace MWWorld { }; + struct RecNameIntChar + { + char name[6]; + RecNameIntChar(ESM::RecNameInts recName) + { + unsigned int FourCC = recName & ~ESM::sEsm4RecnameFlag; // Removes the flag + name[0] = FourCC & 0xFF; + name[1] = (FourCC >> 8) & 0xFF; + name[2] = (FourCC >> 16) & 0xFF; + name[3] = (FourCC >> 24) & 0xFF; + if (ESM::isESM4Rec(recName)) + { + name[4] = '4'; + name[5] = '\0'; + } + else + { + name[4] = '\0'; + } + } + }; + template static bool typedReadRecordESM4(ESM4::Reader& reader, Store& store) { @@ -239,7 +261,11 @@ namespace MWWorld { const unsigned int recordIdCount = std::apply([](auto&&... x) { return (hasSameRecordId(x, T::sRecordId) + ...); }, stores); - assert(recordIdCount == 1); + if (recordIdCount != 1) + { + throw std::runtime_error( + "The same RecNameInt is used twice ESM::REC_" + std::string(RecNameIntChar(T::sRecordId).name)); + } } } From e80dbd7c9566d369e9250bac425c49e81e58ae71 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 4 Jan 2023 00:17:45 +0100 Subject: [PATCH 15/37] Moved the test to test_store.cpp where it belongs --- apps/openmw/mwworld/esmstore.cpp | 56 -------------- apps/openmw/mwworld/esmstore.hpp | 3 +- apps/openmw_test_suite/mwworld/test_store.cpp | 77 +++++++++++++++++++ 3 files changed, 79 insertions(+), 57 deletions(-) diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 29d014afd1..6f39a3e602 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -196,28 +196,6 @@ namespace MWWorld { }; - struct RecNameIntChar - { - char name[6]; - RecNameIntChar(ESM::RecNameInts recName) - { - unsigned int FourCC = recName & ~ESM::sEsm4RecnameFlag; // Removes the flag - name[0] = FourCC & 0xFF; - name[1] = (FourCC >> 8) & 0xFF; - name[2] = (FourCC >> 16) & 0xFF; - name[3] = (FourCC >> 24) & 0xFF; - if (ESM::isESM4Rec(recName)) - { - name[4] = '4'; - name[5] = '\0'; - } - else - { - name[4] = '\0'; - } - } - }; - template static bool typedReadRecordESM4(ESM4::Reader& reader, Store& store) { @@ -241,39 +219,6 @@ namespace MWWorld return false; } - template - static unsigned int hasSameRecordId(const Store& store, ESM::RecNameInts RecName) - { - if constexpr (HasRecordId::value) - { - return T::sRecordId == RecName ? 1 : 0; - } - else - { - return 0; - } - } - - template - static void testRecNameIntCount(const Store& store, const ESMStore::StoreTuple& stores) - { - if constexpr (HasRecordId::value) - { - const unsigned int recordIdCount - = std::apply([](auto&&... x) { return (hasSameRecordId(x, T::sRecordId) + ...); }, stores); - if (recordIdCount != 1) - { - throw std::runtime_error( - "The same RecNameInt is used twice ESM::REC_" + std::string(RecNameIntChar(T::sRecordId).name)); - } - } - } - - static void testAllRecNameIntUnique(const ESMStore::StoreTuple& stores) - { - std::apply([&stores](auto&&... x) { (testRecNameIntCount(x, stores), ...); }, stores); - } - static bool readRecord(ESM4::Reader& reader, ESMStore& store) { return std::apply([&reader](auto&... x) { return (ESMStoreImp::typedReadRecordESM4(reader, x) || ...); }, @@ -305,7 +250,6 @@ namespace MWWorld { mStoreImp = std::make_unique(); std::apply([this](auto&... x) { (ESMStoreImp::assignStoreToIndex(*this, x), ...); }, mStoreImp->mStores); - ESMStoreImp::testAllRecNameIntUnique(mStoreImp->mStores); mDynamicCount = 0; getWritable().setCells(getWritable()); } diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 1ed66a1c71..61083b3ec0 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -86,7 +86,7 @@ namespace MWWorld class ESMStore { friend struct ESMStoreImp; // This allows StoreImp to extend esmstore without beeing included everywhere - + public: using StoreTuple = std::tuple, Store, Store, Store, Store, Store, Store, Store, Store, Store, Store, Store, Store, @@ -107,6 +107,7 @@ namespace MWWorld Store, Store, Store>; + private: template static constexpr std::size_t getTypeIndex() { diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index f869f0e448..b69678c4d6 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -8,6 +8,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include #include @@ -289,6 +295,77 @@ TEST_F(StoreTest, delete_test) ASSERT_TRUE(mEsmStore.get().getSize() == 1); } +template > +struct HasRecordId : std::false_type +{ +}; + +template +struct HasRecordId> : std::true_type +{ +}; + +struct RecNameIntChar +{ + char name[6]; + RecNameIntChar(ESM::RecNameInts recName) + { + unsigned int FourCC = recName & ~ESM::sEsm4RecnameFlag; // Removes the flag + name[0] = FourCC & 0xFF; + name[1] = (FourCC >> 8) & 0xFF; + name[2] = (FourCC >> 16) & 0xFF; + name[3] = (FourCC >> 24) & 0xFF; + if (ESM::isESM4Rec(recName)) + { + name[4] = '4'; + name[5] = '\0'; + } + else + { + name[4] = '\0'; + } + } +}; + +template +static unsigned int hasSameRecordId(const MWWorld::Store& store, ESM::RecNameInts RecName) +{ + if constexpr (HasRecordId::value) + { + return T::sRecordId == RecName ? 1 : 0; + } + else + { + return 0; + } +} + +template +static void testRecNameIntCount(const MWWorld::Store& store, const MWWorld::ESMStore::StoreTuple& stores) +{ + if constexpr (HasRecordId::value) + { + const unsigned int recordIdCount + = std::apply([](auto&&... x) { return (hasSameRecordId(x, T::sRecordId) + ...); }, stores); + if (recordIdCount != 1) + { + std::cout << "The same RecNameInt is used twice ESM::REC_" + std::string(RecNameIntChar(T::sRecordId).name) + << std::endl; + } + ASSERT_TRUE(recordIdCount == 1); + } +} + +static void testAllRecNameIntUnique(const MWWorld::ESMStore::StoreTuple& stores) +{ + std::apply([&stores](auto&&... x) { (testRecNameIntCount(x, stores), ...); }, stores); +} + +TEST_F(StoreTest, recordId_Unique) // Test that each type has a unique recordId +{ + testAllRecNameIntUnique(MWWorld::ESMStore::StoreTuple()); +} + /// Tests overwriting of records. TEST_F(StoreTest, overwrite_test) { From dc37fd2866caab2ee2a0e38ba9a18c3d91a7ba62 Mon Sep 17 00:00:00 2001 From: Rasinin Date: Wed, 4 Jan 2023 17:26:04 +0800 Subject: [PATCH 16/37] updateluadocumentor --- docs/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/README.md b/docs/README.md index f98cf56054..cc81a7b8cb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -49,8 +49,8 @@ pip3 install -r docs/requirements.txt sudo apt install luarocks git clone https://gitlab.com/ptmikheev/openmw-luadocumentor.git cd openmw-luadocumentor/luarocks -luarocks --local pack openmwluadocumentor-0.1.1-1.rockspec -luarocks --local install openmwluadocumentor-0.1.1-1.src.rock +luarocks --local pack openmwluadocumentor-0.2.0-1.rockspec +luarocks --local install openmwluadocumentor-0.2.0-1.src.rock ``` **Windows** @@ -61,8 +61,8 @@ luarocks --local install openmwluadocumentor-0.1.1-1.src.rock - `cd openmw-luadocumentor/luarocks` - open "Developer Command Prompt for VS <2017/2019>" in this directory and run: ```bash -luarocks --local pack openmwluadocumentor-0.1.1-1.rockspec -luarocks --local install openmwluadocumentor-0.1.1-1.src.rock +luarocks --local pack openmwluadocumentor-0.2.0-1.rockspec +luarocks --local install openmwluadocumentor-0.2.0-1.src.rock ``` ### Generating HTML From 02f0af42d98f65eb1be8cd245c519c3411a5e156 Mon Sep 17 00:00:00 2001 From: Rasinin Date: Wed, 4 Jan 2023 17:59:19 +0800 Subject: [PATCH 17/37] updateluacoredoc: recordid desc --- files/lua_api/openmw/core.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/lua_api/openmw/core.lua b/files/lua_api/openmw/core.lua index 38f73ec669..9b5f13f414 100644 --- a/files/lua_api/openmw/core.lua +++ b/files/lua_api/openmw/core.lua @@ -112,7 +112,7 @@ -- @field #Cell cell The cell where the object currently is. During loading a game and for objects in an inventory or a container `cell` is nil. -- @field #table type Type of the object (one of the tables from the package @{openmw.types#types}). -- @field #number count Count (makes sense if stored in a container). --- @field #string recordId Record ID. +-- @field #string recordId Returns record ID of the object in lowercase. --- -- Does the object still exist and is available. From 631fa26872a1e646e3ff6b6a923b32b839d79960 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 4 Jan 2023 12:20:02 +0100 Subject: [PATCH 18/37] Applies review advice. --- apps/esmtool/tes4.cpp | 4 +- apps/openmw/mwworld/esmloader.cpp | 11 ++--- apps/openmw/mwworld/esmstore.cpp | 12 +---- apps/openmw/mwworld/esmstore.hpp | 12 ++++- apps/openmw_test_suite/mwworld/test_store.cpp | 49 +++---------------- components/to_utf8/to_utf8.hpp | 2 +- 6 files changed, 27 insertions(+), 63 deletions(-) diff --git a/apps/esmtool/tes4.cpp b/apps/esmtool/tes4.cpp index 78e5931c0e..1b85c37c11 100644 --- a/apps/esmtool/tes4.cpp +++ b/apps/esmtool/tes4.cpp @@ -595,14 +595,14 @@ namespace EsmTool } auto visitorRec = [¶ms](ESM4::Reader& reader) { return readRecord(params, reader); }; - auto visistorGroup = [¶ms](ESM4::Reader& reader) { + auto visitorGroup = [¶ms](ESM4::Reader& reader) { if (params.mQuite) return; auto groupType = static_cast(reader.hdr().group.type); std::cout << "\nGroup: " << toString(groupType) << " " << ESM::NAME(reader.hdr().group.typeId).toStringView() << '\n'; }; - ESM4::ReaderUtils::readAll(reader, visitorRec, visistorGroup); + ESM4::ReaderUtils::readAll(reader, visitorRec, visitorGroup); } catch (const std::exception& e) { diff --git a/apps/openmw/mwworld/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index be2b3abda9..e0280c91b5 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -60,13 +60,10 @@ namespace MWWorld } case ESM::Format::Tes4: { - if (mEncoder != nullptr) - { - ESM4::Reader readerESM4(std::move(stream), filepath); - auto statelessEncoder = mEncoder->getStatelessEncoder(); - readerESM4.setEncoder(&statelessEncoder); - mStore.loadESM4(readerESM4, listener, mDialogue); - } + ESM4::Reader readerESM4(std::move(stream), filepath); + auto statelessEncoder = mEncoder->getStatelessEncoder(); + readerESM4.setEncoder(&statelessEncoder); + mStore.loadESM4(readerESM4); break; } } diff --git a/apps/openmw/mwworld/esmstore.cpp b/apps/openmw/mwworld/esmstore.cpp index 6f39a3e602..71f4e1e40d 100644 --- a/apps/openmw/mwworld/esmstore.cpp +++ b/apps/openmw/mwworld/esmstore.cpp @@ -186,16 +186,6 @@ namespace MWWorld } } - template > - struct HasRecordId : std::false_type - { - }; - - template - struct HasRecordId> : std::true_type - { - }; - template static bool typedReadRecordESM4(ESM4::Reader& reader, Store& store) { @@ -382,7 +372,7 @@ namespace MWWorld } } - void ESMStore::loadESM4(ESM4::Reader& reader, Loading::Listener* listener, ESM::Dialogue*& dialogue) + void ESMStore::loadESM4(ESM4::Reader& reader) { auto visitorRec = [this](ESM4::Reader& reader) { return ESMStoreImp::readRecord(reader, *this); }; ESM4::ReaderUtils::readAll(reader, visitorRec, [](ESM4::Reader&) {}); diff --git a/apps/openmw/mwworld/esmstore.hpp b/apps/openmw/mwworld/esmstore.hpp index 61083b3ec0..9d737c3f53 100644 --- a/apps/openmw/mwworld/esmstore.hpp +++ b/apps/openmw/mwworld/esmstore.hpp @@ -173,7 +173,7 @@ namespace MWWorld void validateDynamic(); void load(ESM::ESMReader& esm, Loading::Listener* listener, ESM::Dialogue*& dialogue); - void loadESM4(ESM4::Reader& esm, Loading::Listener* listener, ESM::Dialogue*& dialogue); + void loadESM4(ESM4::Reader& esm); template const Store& get() const @@ -264,6 +264,16 @@ namespace MWWorld template <> const ESM::NPC* ESMStore::insert(const ESM::NPC& npc); + + template > + struct HasRecordId : std::false_type + { + }; + + template + struct HasRecordId> : std::true_type + { + }; } #endif diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index b69678c4d6..19363064f0 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -295,42 +295,10 @@ TEST_F(StoreTest, delete_test) ASSERT_TRUE(mEsmStore.get().getSize() == 1); } -template > -struct HasRecordId : std::false_type -{ -}; - -template -struct HasRecordId> : std::true_type -{ -}; - -struct RecNameIntChar -{ - char name[6]; - RecNameIntChar(ESM::RecNameInts recName) - { - unsigned int FourCC = recName & ~ESM::sEsm4RecnameFlag; // Removes the flag - name[0] = FourCC & 0xFF; - name[1] = (FourCC >> 8) & 0xFF; - name[2] = (FourCC >> 16) & 0xFF; - name[3] = (FourCC >> 24) & 0xFF; - if (ESM::isESM4Rec(recName)) - { - name[4] = '4'; - name[5] = '\0'; - } - else - { - name[4] = '\0'; - } - } -}; - template static unsigned int hasSameRecordId(const MWWorld::Store& store, ESM::RecNameInts RecName) { - if constexpr (HasRecordId::value) + if constexpr (MWWorld::HasRecordId::value) { return T::sRecordId == RecName ? 1 : 0; } @@ -343,16 +311,15 @@ static unsigned int hasSameRecordId(const MWWorld::Store& store, ESM::RecName template static void testRecNameIntCount(const MWWorld::Store& store, const MWWorld::ESMStore::StoreTuple& stores) { - if constexpr (HasRecordId::value) + if constexpr (MWWorld::HasRecordId::value) { const unsigned int recordIdCount = std::apply([](auto&&... x) { return (hasSameRecordId(x, T::sRecordId) + ...); }, stores); - if (recordIdCount != 1) - { - std::cout << "The same RecNameInt is used twice ESM::REC_" + std::string(RecNameIntChar(T::sRecordId).name) - << std::endl; - } - ASSERT_TRUE(recordIdCount == 1); + std::string RecordIdName(ESM::NAME(T::sRecordId & ~ESM::sEsm4RecnameFlag).toStringView()); + if (ESM::isESM4Rec(T::sRecordId)) + RecordIdName += '4'; + + ASSERT_EQ(recordIdCount, 1) << "The same RecNameInt is used twice ESM::REC_" << RecordIdName; } } @@ -361,7 +328,7 @@ static void testAllRecNameIntUnique(const MWWorld::ESMStore::StoreTuple& stores) std::apply([&stores](auto&&... x) { (testRecNameIntCount(x, stores), ...); }, stores); } -TEST_F(StoreTest, recordId_Unique) // Test that each type has a unique recordId +TEST_F(StoreTest, eachRecordTypeShouldHaveUniqueRecordId) { testAllRecNameIntUnique(MWWorld::ESMStore::StoreTuple()); } diff --git a/components/to_utf8/to_utf8.hpp b/components/to_utf8/to_utf8.hpp index f7197fe553..11a466e44c 100644 --- a/components/to_utf8/to_utf8.hpp +++ b/components/to_utf8/to_utf8.hpp @@ -68,7 +68,7 @@ namespace ToUTF8 /// ASCII-only string. Otherwise returns a view to the input. std::string_view getLegacyEnc(std::string_view input); - const StatelessUtf8Encoder getStatelessEncoder() const { return mImpl; } + StatelessUtf8Encoder getStatelessEncoder() const { return mImpl; } private: std::string mBuffer; From b88eee08c228f63febc2feab9c9dfdd493020b02 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 4 Jan 2023 14:07:47 +0100 Subject: [PATCH 19/37] Store display's the ESM4's RecnameInt when not found --- apps/openmw/mwworld/store.cpp | 18 ++++++++++++++++++ apps/openmw/mwworld/store.hpp | 2 ++ apps/openmw_test_suite/mwworld/test_store.cpp | 7 ++----- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 60179f01b5..bf8d656ecd 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -166,6 +166,10 @@ namespace MWWorld { msg << T::getRecordType(); } + else + { + msg << "ESM::REC_" << getRecNameString(T::sRecordId).toStringView(); + } msg << " '" << id << "' not found"; throw std::runtime_error(msg.str()); } @@ -1164,6 +1168,20 @@ namespace MWWorld return mKeywordSearch; } + + ESM::FixedString<6> getRecNameString(ESM::RecNameInts recName) + { + ESM::FixedString<6> name; + name.assign(""); + ESM::NAME fourCCName(recName & ~ESM::sEsm4RecnameFlag); + for (int i = 0; i < 4; i++) + name.mData[i] = fourCCName.mData[i]; + if (ESM::isESM4Rec(recName)) + { + name.mData[4] = '4'; + } + return name; + } } template class MWWorld::TypedDynamicStore; diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index a6f869e362..6acfb6d41e 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -517,6 +517,8 @@ namespace MWWorld const MWDialogue::KeywordSearch& getDialogIdKeywordSearch() const; }; + ESM::FixedString<6> getRecNameString(ESM::RecNameInts recName); + } // end namespace #endif diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index 19363064f0..e8c4dbc8a7 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -315,11 +315,8 @@ static void testRecNameIntCount(const MWWorld::Store& store, const MWWorld::E { const unsigned int recordIdCount = std::apply([](auto&&... x) { return (hasSameRecordId(x, T::sRecordId) + ...); }, stores); - std::string RecordIdName(ESM::NAME(T::sRecordId & ~ESM::sEsm4RecnameFlag).toStringView()); - if (ESM::isESM4Rec(T::sRecordId)) - RecordIdName += '4'; - - ASSERT_EQ(recordIdCount, 1) << "The same RecNameInt is used twice ESM::REC_" << RecordIdName; + ASSERT_EQ(recordIdCount, 1) << "The same RecNameInt is used twice ESM::REC_" + << MWWorld::getRecNameString(T::sRecordId).toStringView(); } } From 400d51c09977f22775f0f95eb18b369ea3477889 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Wed, 4 Jan 2023 14:19:12 +0100 Subject: [PATCH 20/37] Fix compile MSVC --- apps/openmw_test_suite/mwworld/test_store.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index e8c4dbc8a7..d2163520f7 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -315,8 +315,8 @@ static void testRecNameIntCount(const MWWorld::Store& store, const MWWorld::E { const unsigned int recordIdCount = std::apply([](auto&&... x) { return (hasSameRecordId(x, T::sRecordId) + ...); }, stores); - ASSERT_EQ(recordIdCount, 1) << "The same RecNameInt is used twice ESM::REC_" - << MWWorld::getRecNameString(T::sRecordId).toStringView(); + ASSERT_EQ(recordIdCount, static_cast(1)) + << "The same RecNameInt is used twice ESM::REC_" << MWWorld::getRecNameString(T::sRecordId).toStringView(); } } From d065dbbefa9c067bf0eef3c2d32fe107498224b9 Mon Sep 17 00:00:00 2001 From: unelsson Date: Wed, 4 Jan 2023 16:07:47 +0200 Subject: [PATCH 21/37] Add named-based Collada recognition --- apps/openmw/mwrender/objectpaging.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index 2140bd5412..b3f03de33c 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -643,7 +644,8 @@ namespace MWRender { if (cnode->getNumChildrenRequiringUpdateTraversal() > 0 || SceneUtil::hasUserDescription(cnode, Constants::NightDayLabel) - || SceneUtil::hasUserDescription(cnode, Constants::HerbalismLabel)) + || SceneUtil::hasUserDescription(cnode, Constants::HerbalismLabel) + || cnode->getName() == "Collada visual scene group") continue; else refnumSet->mRefnums.push_back(pair.first); From 4b8b3a9187e62f85321d9bc5b2a5ce0b106ff4cf Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Wed, 4 Jan 2023 21:38:48 +0100 Subject: [PATCH 22/37] Raise an error if initData in obj:addScript has incorrect type. --- apps/openmw/mwlua/objectbindings.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwlua/objectbindings.cpp b/apps/openmw/mwlua/objectbindings.cpp index 4fe520e68c..977aa9569c 100644 --- a/apps/openmw/mwlua/objectbindings.cpp +++ b/apps/openmw/mwlua/objectbindings.cpp @@ -200,8 +200,7 @@ namespace MWLua if constexpr (std::is_same_v) { // Only for global scripts - objectT["addScript"] = [context](const GObject& object, std::string_view path, - sol::optional initData) { + objectT["addScript"] = [context](const GObject& object, std::string_view path, sol::object initData) { const LuaUtil::ScriptsConfiguration& cfg = context.mLua->getConfiguration(); std::optional scriptId = cfg.findId(path); if (!scriptId) @@ -211,9 +210,9 @@ namespace MWLua "Script without CUSTOM tag can not be added dynamically: " + std::string(path)); if (object.ptr().getType() == ESM::REC_STAT) throw std::runtime_error("Attaching scripts to Static is not allowed: " + std::string(path)); - if (initData) - context.mLuaManager->addCustomLocalScript( - object.ptr(), *scriptId, LuaUtil::serialize(*initData, context.mSerializer)); + if (initData != sol::nil) + context.mLuaManager->addCustomLocalScript(object.ptr(), *scriptId, + LuaUtil::serialize(initData.as(), context.mSerializer)); else context.mLuaManager->addCustomLocalScript( object.ptr(), *scriptId, cfg[*scriptId].mInitializationData); From a08f37cfe84367624f625b68ff339d24c2476111 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 4 Jan 2023 22:18:56 +0100 Subject: [PATCH 23/37] Don't use a levelled creature's base pointer when spawning a new instance --- apps/openmw/mwclass/creaturelevlist.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index a9b7abdc7d..464a1acfa0 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -127,10 +127,10 @@ namespace MWClass if (!customData.mSpawn) return; - MWWorld::LiveCellRef* ref = ptr.get(); - + const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); auto& prng = MWBase::Environment::get().getWorld()->getPrng(); - const ESM::RefId& id = MWMechanics::getLevelledItem(ref->mBase, true, prng); + const ESM::RefId& id = MWMechanics::getLevelledItem( + store.get().find(ptr.getCellRef().getRefId()), true, prng); if (!id.empty()) { @@ -144,7 +144,6 @@ namespace MWClass customData.mSpawnActorId = -1; } - const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); MWWorld::ManualRef manualRef(store, id); manualRef.getPtr().getCellRef().setPosition(ptr.getCellRef().getPosition()); manualRef.getPtr().getCellRef().setScale(ptr.getCellRef().getScale()); From bfa0e751dd39ce2bed090cb1a3a5239bfac3661d Mon Sep 17 00:00:00 2001 From: unelsson Date: Thu, 5 Jan 2023 01:34:26 +0200 Subject: [PATCH 24/37] Skip merging for only animated models (Collada) --- apps/openmw/mwrender/objectpaging.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index b3f03de33c..4d847a3619 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -16,7 +17,6 @@ #include #include -#include #include #include #include @@ -645,7 +645,8 @@ namespace MWRender if (cnode->getNumChildrenRequiringUpdateTraversal() > 0 || SceneUtil::hasUserDescription(cnode, Constants::NightDayLabel) || SceneUtil::hasUserDescription(cnode, Constants::HerbalismLabel) - || cnode->getName() == "Collada visual scene group") + || (cnode->getName() == "Collada visual scene group" + && dynamic_cast(cnode->getUpdateCallback()))) continue; else refnumSet->mRefnums.push_back(pair.first); From 5b0713517a815b23e7acc094e378ff747eefe463 Mon Sep 17 00:00:00 2001 From: unelsson Date: Thu, 5 Jan 2023 01:40:36 +0200 Subject: [PATCH 25/37] Clang-format --- components/resource/scenemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index 516f3e4af4..b6a22c08a4 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -636,7 +636,7 @@ namespace Resource backToOriginTrans->addChild(newRiggeometryHolder); group->addChild(backToOriginTrans); - + node->getOrCreateUserDataContainer()->addUserObject( new TemplateRef(newRiggeometryHolder->getGeometry(0))); } From b217d1fc3661cd83daf43b965ef19977066702d4 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 6 Jan 2023 16:01:30 +0400 Subject: [PATCH 26/37] Use OpenMW logging levels for MyGUI log (feature 7130) --- CHANGELOG.md | 1 + components/myguiplatform/myguiloglistener.cpp | 13 +++++++++++++ components/myguiplatform/myguiloglistener.hpp | 4 +++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f81c6f235..2d12db3850 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ Feature #6995: Localize the "show effect duration" option Feature #7058: Implement TestModels (T3D) console command Feature #7087: Block resolution change in the Windowed Fullscreen mode + Feature #7130: Ability to set MyGUI logging verbosity 0.48.0 ------ diff --git a/components/myguiplatform/myguiloglistener.cpp b/components/myguiplatform/myguiloglistener.cpp index 9002d390f5..42dc9c0415 100644 --- a/components/myguiplatform/myguiloglistener.cpp +++ b/components/myguiplatform/myguiloglistener.cpp @@ -37,4 +37,17 @@ namespace osgMyGUI << separator << _line << std::endl; } } + + MyGUI::LogLevel LogFacility::getCurrentLogLevel() const + { + switch (Debug::CurrentDebugLevel) + { + case Debug::Error: + return MyGUI::LogLevel::Error; + case Debug::Warning: + return MyGUI::LogLevel::Warning; + default: + return MyGUI::LogLevel::Info; + } + } } diff --git a/components/myguiplatform/myguiloglistener.hpp b/components/myguiplatform/myguiloglistener.hpp index ec8bd16578..1af63a397f 100644 --- a/components/myguiplatform/myguiloglistener.hpp +++ b/components/myguiplatform/myguiloglistener.hpp @@ -47,12 +47,14 @@ namespace osgMyGUI MyGUI::LevelLogFilter mFilter; MyGUI::LogSource mSource; + MyGUI::LogLevel getCurrentLogLevel() const; + public: LogFacility(const std::filesystem::path& output, bool console) : mFile(output) { mConsole.setEnabled(console); - mFilter.setLoggingLevel(MyGUI::LogLevel::Info); + mFilter.setLoggingLevel(getCurrentLogLevel()); mSource.addLogListener(&mFile); mSource.addLogListener(&mConsole); From 760135591bc45f9922f54d757ec759f01ca16f38 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 6 Jan 2023 17:34:27 +0400 Subject: [PATCH 27/37] Clear character name in the loading menu when there are no saves left (bug 7088) --- CHANGELOG.md | 1 + apps/openmw/mwgui/savegamedialog.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f81c6f235..c5f6ee8a62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Bug #7042: Weapon follow animations that immediately follow the hit animations cause multiple hits Bug #7044: Changing a class' services does not affect autocalculated NPCs Bug #7084: Resurrecting an actor doesn't take into account base record changes + Bug #7088: Deleting last save game of last character doesn't clear character name/details Feature #6447: Add LOD support to Object Paging Feature #6933: Support high-resolution cursor textures Feature #6945: Support S3TC-compressed and BGR/BGRA NiPixelData diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index ae5b8d53f2..595591a78b 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -111,7 +111,7 @@ namespace MWGui onCharacterSelected(mCharacterSelection, nextCharacter); } else - fillSaveList(); + mCharacterSelection->setIndexSelected(MyGUI::ITEM_NONE); } } From 7c609052668df7f376b4de30fb7bf1ad4561377b Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 2 Jan 2023 17:54:14 +0100 Subject: [PATCH 28/37] Put ESM::FixedString tests into unnamed namespace --- .../esm/test_fixed_string.cpp | 261 +++++++++--------- 1 file changed, 132 insertions(+), 129 deletions(-) diff --git a/apps/openmw_test_suite/esm/test_fixed_string.cpp b/apps/openmw_test_suite/esm/test_fixed_string.cpp index 078cb8609e..bcf776ca51 100644 --- a/apps/openmw_test_suite/esm/test_fixed_string.cpp +++ b/apps/openmw_test_suite/esm/test_fixed_string.cpp @@ -2,142 +2,145 @@ #include "components/esm/esmcommon.hpp" #include -TEST(EsmFixedString, operator__eq_ne) +namespace { + TEST(EsmFixedString, operator__eq_ne) { - SCOPED_TRACE("asdc == asdc"); - constexpr ESM::NAME name("asdc"); - char s[4] = { 'a', 's', 'd', 'c' }; - std::string ss(s, 4); + { + SCOPED_TRACE("asdc == asdc"); + constexpr ESM::NAME name("asdc"); + char s[4] = { 'a', 's', 'd', 'c' }; + std::string ss(s, 4); - EXPECT_TRUE(name == s); - EXPECT_TRUE(name == ss.c_str()); - EXPECT_TRUE(name == ss); + EXPECT_TRUE(name == s); + EXPECT_TRUE(name == ss.c_str()); + EXPECT_TRUE(name == ss); + } + { + SCOPED_TRACE("asdc == asdcx"); + constexpr ESM::NAME name("asdc"); + char s[5] = { 'a', 's', 'd', 'c', 'x' }; + std::string ss(s, 5); + + EXPECT_TRUE(name != s); + EXPECT_TRUE(name != ss.c_str()); + EXPECT_TRUE(name != ss); + } + { + SCOPED_TRACE("asdc == asdc[NULL]"); + const ESM::NAME name("asdc"); + char s[5] = { 'a', 's', 'd', 'c', '\0' }; + std::string ss(s, 5); + + EXPECT_TRUE(name == s); + EXPECT_TRUE(name == ss.c_str()); + EXPECT_TRUE(name == ss); + } } + TEST(EsmFixedString, operator__eq_ne_const) { - SCOPED_TRACE("asdc == asdcx"); - constexpr ESM::NAME name("asdc"); - char s[5] = { 'a', 's', 'd', 'c', 'x' }; - std::string ss(s, 5); + { + SCOPED_TRACE("asdc == asdc (const)"); + constexpr ESM::NAME name("asdc"); + const char s[4] = { 'a', 's', 'd', 'c' }; + std::string ss(s, 4); - EXPECT_TRUE(name != s); - EXPECT_TRUE(name != ss.c_str()); - EXPECT_TRUE(name != ss); + EXPECT_TRUE(name == s); + EXPECT_TRUE(name == ss.c_str()); + EXPECT_TRUE(name == ss); + } + { + SCOPED_TRACE("asdc == asdcx (const)"); + constexpr ESM::NAME name("asdc"); + const char s[5] = { 'a', 's', 'd', 'c', 'x' }; + std::string ss(s, 5); + + EXPECT_TRUE(name != s); + EXPECT_TRUE(name != ss.c_str()); + EXPECT_TRUE(name != ss); + } + { + SCOPED_TRACE("asdc == asdc[NULL] (const)"); + constexpr ESM::NAME name("asdc"); + const char s[5] = { 'a', 's', 'd', 'c', '\0' }; + std::string ss(s, 5); + + EXPECT_TRUE(name == s); + EXPECT_TRUE(name == ss.c_str()); + EXPECT_TRUE(name == ss); + } } - { - SCOPED_TRACE("asdc == asdc[NULL]"); - const ESM::NAME name("asdc"); - char s[5] = { 'a', 's', 'd', 'c', '\0' }; - std::string ss(s, 5); - EXPECT_TRUE(name == s); - EXPECT_TRUE(name == ss.c_str()); - EXPECT_TRUE(name == ss); + TEST(EsmFixedString, empty_strings) + { + { + SCOPED_TRACE("4 bytes"); + ESM::NAME empty = ESM::NAME(); + EXPECT_TRUE(empty == ""); + EXPECT_TRUE(empty == static_cast(0)); + EXPECT_TRUE(empty != "some string"); + EXPECT_TRUE(empty != static_cast(42)); + } + { + SCOPED_TRACE("32 bytes"); + ESM::NAME32 empty = ESM::NAME32(); + EXPECT_TRUE(empty == ""); + EXPECT_TRUE(empty != "some string"); + } + } + + TEST(EsmFixedString, assign_should_zero_untouched_bytes_for_4) + { + ESM::NAME value; + value = static_cast(0xFFFFFFFFu); + value.assign(std::string(1, 'a')); + EXPECT_EQ(value, static_cast('a')) << value.toInt(); + } + + TEST(EsmFixedString, assign_should_only_truncate_for_4) + { + ESM::NAME value; + value.assign(std::string(5, 'a')); + EXPECT_EQ(value, std::string(4, 'a')); + } + + TEST(EsmFixedString, assign_should_truncate_and_set_last_element_to_zero) + { + ESM::FixedString<17> value; + value.assign(std::string(20, 'a')); + EXPECT_EQ(value, std::string(16, 'a')); + } + + TEST(EsmFixedString, assign_should_truncate_and_set_last_element_to_zero_for_32) + { + ESM::NAME32 value; + value.assign(std::string(33, 'a')); + EXPECT_EQ(value, std::string(31, 'a')); + } + + TEST(EsmFixedString, assign_should_truncate_and_set_last_element_to_zero_for_64) + { + ESM::NAME64 value; + value.assign(std::string(65, 'a')); + EXPECT_EQ(value, std::string(63, 'a')); + } + + TEST(EsmFixedString, assignment_operator_is_supported_for_uint32) + { + ESM::NAME value; + value = static_cast(0xFEDCBA98u); + EXPECT_EQ(value, static_cast(0xFEDCBA98u)) << value.toInt(); + } + + TEST(EsmFixedString, construction_from_uint32_is_supported) + { + constexpr ESM::NAME value(0xFEDCBA98u); + EXPECT_EQ(value, static_cast(0xFEDCBA98u)) << value.toInt(); + } + + TEST(EsmFixedString, construction_from_RecNameInts_is_supported) + { + constexpr ESM::NAME value(ESM::RecNameInts::REC_ACTI); + EXPECT_EQ(value, static_cast(ESM::RecNameInts::REC_ACTI)) << value.toInt(); } } -TEST(EsmFixedString, operator__eq_ne_const) -{ - { - SCOPED_TRACE("asdc == asdc (const)"); - constexpr ESM::NAME name("asdc"); - const char s[4] = { 'a', 's', 'd', 'c' }; - std::string ss(s, 4); - - EXPECT_TRUE(name == s); - EXPECT_TRUE(name == ss.c_str()); - EXPECT_TRUE(name == ss); - } - { - SCOPED_TRACE("asdc == asdcx (const)"); - constexpr ESM::NAME name("asdc"); - const char s[5] = { 'a', 's', 'd', 'c', 'x' }; - std::string ss(s, 5); - - EXPECT_TRUE(name != s); - EXPECT_TRUE(name != ss.c_str()); - EXPECT_TRUE(name != ss); - } - { - SCOPED_TRACE("asdc == asdc[NULL] (const)"); - constexpr ESM::NAME name("asdc"); - const char s[5] = { 'a', 's', 'd', 'c', '\0' }; - std::string ss(s, 5); - - EXPECT_TRUE(name == s); - EXPECT_TRUE(name == ss.c_str()); - EXPECT_TRUE(name == ss); - } -} - -TEST(EsmFixedString, empty_strings) -{ - { - SCOPED_TRACE("4 bytes"); - ESM::NAME empty = ESM::NAME(); - EXPECT_TRUE(empty == ""); - EXPECT_TRUE(empty == static_cast(0)); - EXPECT_TRUE(empty != "some string"); - EXPECT_TRUE(empty != static_cast(42)); - } - { - SCOPED_TRACE("32 bytes"); - ESM::NAME32 empty = ESM::NAME32(); - EXPECT_TRUE(empty == ""); - EXPECT_TRUE(empty != "some string"); - } -} - -TEST(EsmFixedString, assign_should_zero_untouched_bytes_for_4) -{ - ESM::NAME value; - value = static_cast(0xFFFFFFFFu); - value.assign(std::string(1, 'a')); - EXPECT_EQ(value, static_cast('a')) << value.toInt(); -} - -TEST(EsmFixedString, assign_should_only_truncate_for_4) -{ - ESM::NAME value; - value.assign(std::string(5, 'a')); - EXPECT_EQ(value, std::string(4, 'a')); -} - -TEST(EsmFixedString, assign_should_truncate_and_set_last_element_to_zero) -{ - ESM::FixedString<17> value; - value.assign(std::string(20, 'a')); - EXPECT_EQ(value, std::string(16, 'a')); -} - -TEST(EsmFixedString, assign_should_truncate_and_set_last_element_to_zero_for_32) -{ - ESM::NAME32 value; - value.assign(std::string(33, 'a')); - EXPECT_EQ(value, std::string(31, 'a')); -} - -TEST(EsmFixedString, assign_should_truncate_and_set_last_element_to_zero_for_64) -{ - ESM::NAME64 value; - value.assign(std::string(65, 'a')); - EXPECT_EQ(value, std::string(63, 'a')); -} - -TEST(EsmFixedString, assignment_operator_is_supported_for_uint32) -{ - ESM::NAME value; - value = static_cast(0xFEDCBA98u); - EXPECT_EQ(value, static_cast(0xFEDCBA98u)) << value.toInt(); -} - -TEST(EsmFixedString, construction_from_uint32_is_supported) -{ - constexpr ESM::NAME value(0xFEDCBA98u); - EXPECT_EQ(value, static_cast(0xFEDCBA98u)) << value.toInt(); -} - -TEST(EsmFixedString, construction_from_RecNameInts_is_supported) -{ - constexpr ESM::NAME value(ESM::RecNameInts::REC_ACTI); - EXPECT_EQ(value, static_cast(ESM::RecNameInts::REC_ACTI)) << value.toInt(); -} From c80ba92ab72391f98eb42491db102707ace3f874 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 2 Jan 2023 17:21:36 +0100 Subject: [PATCH 29/37] Add more tests for ESM::FixedString --- .../esm/test_fixed_string.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/apps/openmw_test_suite/esm/test_fixed_string.cpp b/apps/openmw_test_suite/esm/test_fixed_string.cpp index bcf776ca51..f3d4071c28 100644 --- a/apps/openmw_test_suite/esm/test_fixed_string.cpp +++ b/apps/openmw_test_suite/esm/test_fixed_string.cpp @@ -37,6 +37,7 @@ namespace EXPECT_TRUE(name == ss); } } + TEST(EsmFixedString, operator__eq_ne_const) { { @@ -143,4 +144,30 @@ namespace constexpr ESM::NAME value(ESM::RecNameInts::REC_ACTI); EXPECT_EQ(value, static_cast(ESM::RecNameInts::REC_ACTI)) << value.toInt(); } + + TEST(EsmFixedString, equality_operator_for_not_convertible_to_uint32_with_string_literal) + { + const ESM::FixedString<5> value("abcd"); + EXPECT_EQ(value, "abcd"); + } + + TEST(EsmFixedString, equality_operator_for_not_convertible_to_uint32_with_fixed_size_char_array) + { + const ESM::FixedString<5> value("abcd"); + const char other[5] = { 'a', 'b', 'c', 'd', '\0' }; + EXPECT_EQ(value, other); + } + + TEST(EsmFixedString, equality_operator_for_not_convertible_to_uint32_with_const_char_pointer) + { + const ESM::FixedString<5> value("abcd"); + const char other[5] = { 'a', 'b', 'c', 'd', '\0' }; + EXPECT_EQ(value, static_cast(other)); + } + + TEST(EsmFixedString, equality_operator_for_not_convertible_to_uint32_with_string) + { + const ESM::FixedString<5> value("abcd"); + EXPECT_EQ(value, std::string("abcd")); + } } From 2bbed8cc0698e946a084425d8762fb89685b80f7 Mon Sep 17 00:00:00 2001 From: elsid Date: Mon, 2 Jan 2023 17:03:03 +0100 Subject: [PATCH 30/37] =?UTF-8?q?Fix=20gcc=20warning:=20array=20subscript?= =?UTF-8?q?=205=20is=20outside=20array=20bounds=20of=20=E2=80=98const=20ch?= =?UTF-8?q?ar=20[5]=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In function ‘bool ESM::operator==(const FixedString&, const T* const&) [with long unsigned int capacity = 5; T = char; = void]’, inlined from ‘testing::AssertionResult testing::internal::CmpHelperEQ(const char*, const char*, const T1&, const T2&) [with T1 = ESM::FixedString<5>; T2 = const char*]’ at /home/elsid/dev/googletest/build/gcc/release/install/include/gtest/gtest.h:1358:11, inlined from ‘static testing::AssertionResult testing::internal::EqHelper::Compare(const char*, const char*, const T1&, const T2&) [with T1 = ESM::FixedString<5>; T2 = const char*; typename std::enable_if<((! std::is_integral<_Tp>::value) || (! std::is_pointer<_Dp>::value))>::type* = 0]’ at /home/elsid/dev/googletest/build/gcc/release/install/include/gtest/gtest.h:1377:64, inlined from ‘virtual void {anonymous}::EsmFixedString_equality_operator_for_not_convertible_to_uint32_with_const_char_pointer_Test::TestBody()’ at apps/openmw_test_suite/esm/test_fixed_string.cpp:165:9: components/esm/esmcommon.hpp:134:19: warning: array subscript 5 is outside array bounds of ‘const char [5]’ [-Warray-bounds] 134 | return rhs[capacity] == '\0'; | ~~~^ apps/openmw_test_suite/esm/test_fixed_string.cpp: In member function ‘virtual void {anonymous}::EsmFixedString_equality_operator_for_not_convertible_to_uint32_with_const_char_pointer_Test::TestBody()’: apps/openmw_test_suite/esm/test_fixed_string.cpp:164:20: note: at offset 5 into object ‘other’ of size 5 164 | const char other[5] = { 'a', 'b', 'c', 'd', '\0' }; | ^~~~~ --- .../esm/test_fixed_string.cpp | 15 ++++++++++++++ components/esm/esmcommon.hpp | 20 ++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/apps/openmw_test_suite/esm/test_fixed_string.cpp b/apps/openmw_test_suite/esm/test_fixed_string.cpp index f3d4071c28..76ed346daa 100644 --- a/apps/openmw_test_suite/esm/test_fixed_string.cpp +++ b/apps/openmw_test_suite/esm/test_fixed_string.cpp @@ -170,4 +170,19 @@ namespace const ESM::FixedString<5> value("abcd"); EXPECT_EQ(value, std::string("abcd")); } + + TEST(EsmFixedString, equality_operator_for_not_convertible_to_uint32_with_string_view) + { + const ESM::FixedString<5> value("abcd"); + const std::string other("abcd"); + EXPECT_EQ(value, std::string_view(other)); + } + + TEST(EsmFixedString, equality_operator_should_not_get_out_of_bounds) + { + ESM::FixedString<5> value; + const char other[5] = { 'a', 'b', 'c', 'd', 'e' }; + std::memcpy(value.mData, other, sizeof(other)); + EXPECT_EQ(value, static_cast(other)); + } } diff --git a/components/esm/esmcommon.hpp b/components/esm/esmcommon.hpp index f272fa553e..e12a4703ce 100644 --- a/components/esm/esmcommon.hpp +++ b/components/esm/esmcommon.hpp @@ -121,23 +121,23 @@ namespace ESM } }; - template >> - inline bool operator==(const FixedString& lhs, const T* const& rhs) noexcept + template + inline bool operator==(const FixedString& lhs, std::string_view rhs) noexcept { - for (std::size_t i = 0; i < capacity; ++i) + for (std::size_t i = 0, n = std::min(rhs.size(), capacity); i < n; ++i) { if (lhs.mData[i] != rhs[i]) return false; if (lhs.mData[i] == '\0') return true; } - return rhs[capacity] == '\0'; + return rhs.size() <= capacity || rhs[capacity] == '\0'; } - template - inline bool operator==(const FixedString& lhs, const std::string& rhs) noexcept + template >> + inline bool operator==(const FixedString& lhs, const T* const& rhs) noexcept { - return lhs == rhs.c_str(); + return lhs == std::string_view(rhs, capacity); } template @@ -156,6 +156,12 @@ namespace ESM return lhs.toInt() == rhs.toInt(); } + template >> + inline bool operator==(const FixedString<4>& lhs, const T* const& rhs) noexcept + { + return lhs == std::string_view(rhs, 5); + } + template inline bool operator!=(const FixedString& lhs, const Rhs& rhs) noexcept { From 9a4977d334241c48d0bf6ace61b4d7d78ce0983b Mon Sep 17 00:00:00 2001 From: "glassmancody.info" Date: Fri, 6 Jan 2023 22:23:03 -0800 Subject: [PATCH 31/37] rain occlusion --- CHANGELOG.md | 1 + apps/launcher/advancedpage.cpp | 2 + apps/openmw/CMakeLists.txt | 2 +- .../mwrender/precipitationocclusion.cpp | 170 ++++++++++++++++++ .../mwrender/precipitationocclusion.hpp | 33 ++++ apps/openmw/mwrender/renderingmanager.cpp | 4 +- apps/openmw/mwrender/sky.cpp | 32 +++- apps/openmw/mwrender/sky.hpp | 8 +- components/shader/shadervisitor.cpp | 6 + .../reference/modding/settings/shaders.rst | 15 ++ files/settings-default.cfg | 3 + files/shaders/CMakeLists.txt | 6 +- files/shaders/objects_fragment.glsl | 22 +++ files/shaders/objects_vertex.glsl | 12 ++ files/shaders/precipitation_fragment.glsl | 15 ++ files/shaders/precipitation_vertex.glsl | 13 ++ files/ui/advancedpage.ui | 10 ++ 17 files changed, 338 insertions(+), 16 deletions(-) create mode 100644 apps/openmw/mwrender/precipitationocclusion.cpp create mode 100644 apps/openmw/mwrender/precipitationocclusion.hpp create mode 100644 files/shaders/precipitation_fragment.glsl create mode 100644 files/shaders/precipitation_vertex.glsl diff --git a/CHANGELOG.md b/CHANGELOG.md index 551a7d9aa6..8ae19018e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -219,6 +219,7 @@ Feature #5198: Implement "Magic effect expired" event Feature #5454: Clear active spells from actor when he disappears from scene Feature #5489: MCP: Telekinesis fix for activators + Feature #5492: Let rain and snow collide with statics Feature #5701: Convert osgAnimation::RigGeometry to double-buffered custom version Feature #5737: OpenMW-CS: Handle instance move from one cell to another Feature #5928: Allow Glow in the Dahrk to be disabled diff --git a/apps/launcher/advancedpage.cpp b/apps/launcher/advancedpage.cpp index bfd12d27c1..9fe478f94a 100644 --- a/apps/launcher/advancedpage.cpp +++ b/apps/launcher/advancedpage.cpp @@ -126,6 +126,7 @@ bool Launcher::AdvancedPage::loadSettings() antialiasAlphaTestCheckBox->setCheckState(Qt::Unchecked); } loadSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders"); + loadSettingBool(weatherParticleOcclusionCheckBox, "weather particle occlusion", "Shaders"); loadSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game"); connect(animSourcesCheckBox, &QCheckBox::toggled, this, &AdvancedPage::slotAnimSourcesToggled); loadSettingBool(animSourcesCheckBox, "use additional anim sources", "Game"); @@ -285,6 +286,7 @@ void Launcher::AdvancedPage::saveSettings() saveSettingBool(softParticlesCheckBox, "soft particles", "Shaders"); saveSettingBool(antialiasAlphaTestCheckBox, "antialias alpha test", "Shaders"); saveSettingBool(adjustCoverageForAlphaTestCheckBox, "adjust coverage for alpha test", "Shaders"); + saveSettingBool(weatherParticleOcclusionCheckBox, "weather particle occlusion", "Shaders"); saveSettingBool(magicItemAnimationsCheckBox, "use magic item animations", "Game"); saveSettingBool(animSourcesCheckBox, "use additional anim sources", "Game"); saveSettingBool(weaponSheathingCheckBox, "weapon sheathing", "Game"); diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index ced1060ce9..e9683cc40a 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -23,7 +23,7 @@ add_openmw_dir (mwrender creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation screenshotmanager bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation renderbin actoranimation landmanager navmesh actorspaths recastmesh fogmanager objectpaging groundcover - postprocessor pingpongcull luminancecalculator pingpongcanvas transparentpass navmeshmode + postprocessor pingpongcull luminancecalculator pingpongcanvas transparentpass navmeshmode precipitationocclusion ) add_openmw_dir (mwinput diff --git a/apps/openmw/mwrender/precipitationocclusion.cpp b/apps/openmw/mwrender/precipitationocclusion.cpp new file mode 100644 index 0000000000..40eddea270 --- /dev/null +++ b/apps/openmw/mwrender/precipitationocclusion.cpp @@ -0,0 +1,170 @@ +#include "precipitationocclusion.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../mwbase/environment.hpp" + +#include "vismask.hpp" + +namespace +{ + class PrecipitationOcclusionUpdater : public SceneUtil::StateSetUpdater + { + public: + PrecipitationOcclusionUpdater(osg::ref_ptr depthTexture) + : mDepthTexture(depthTexture) + { + } + + private: + void setDefaults(osg::StateSet* stateset) override + { + stateset->setTextureAttributeAndModes(3, mDepthTexture); + stateset->addUniform(new osg::Uniform("orthoDepthMap", 3)); + stateset->addUniform(new osg::Uniform("depthSpaceMatrix", mDepthSpaceMatrix)); + } + void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override + { + osg::Camera* camera = nv->asCullVisitor()->getCurrentCamera(); + stateset->getUniform("depthSpaceMatrix")->set(camera->getViewMatrix() * camera->getProjectionMatrix()); + } + + osg::Matrixf mDepthSpaceMatrix; + osg::ref_ptr mDepthTexture; + }; + + class DepthCameraUpdater : public SceneUtil::StateSetUpdater + { + public: + DepthCameraUpdater() + : mDummyTexture(new osg::Texture2D) + { + mDummyTexture->setInternalFormat(GL_RGB); + mDummyTexture->setTextureSize(1, 1); + + Shader::ShaderManager& shaderMgr + = MWBase::Environment::get().getResourceSystem()->getSceneManager()->getShaderManager(); + osg::ref_ptr vertex + = shaderMgr.getShader("precipitationdepth_vertex.glsl", {}, osg::Shader::VERTEX); + osg::ref_ptr fragment + = shaderMgr.getShader("precipitationdepth_fragment.glsl", {}, osg::Shader::FRAGMENT); + mProgram = shaderMgr.getProgram(vertex, fragment); + } + + private: + void setDefaults(osg::StateSet* stateset) override + { + stateset->addUniform(new osg::Uniform("projectionMatrix", osg::Matrixf())); + stateset->setAttributeAndModes(mProgram, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); + stateset->setTextureAttributeAndModes(0, mDummyTexture); + stateset->setRenderBinDetails( + osg::StateSet::OPAQUE_BIN, "RenderBin", osg::StateSet::OVERRIDE_PROTECTED_RENDERBIN_DETAILS); + } + void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override + { + osg::Camera* camera = nv->asCullVisitor()->getCurrentCamera(); + stateset->getUniform("projectionMatrix")->set(camera->getProjectionMatrix()); + } + + osg::Matrixf mProjectionMatrix; + osg::ref_ptr mDummyTexture; + osg::ref_ptr mProgram; + }; +} + +namespace MWRender +{ + PrecipitationOccluder::PrecipitationOccluder( + osg::Group* skyNode, osg::Group* sceneNode, osg::Group* rootNode, osg::Camera* camera) + : mSkyNode(skyNode) + , mSceneNode(sceneNode) + , mRootNode(rootNode) + , mSceneCamera(camera) + { + constexpr int rttSize = 256; + + mDepthTexture = new osg::Texture2D; + mDepthTexture->setTextureSize(rttSize, rttSize); + mDepthTexture->setSourceFormat(GL_DEPTH_COMPONENT); + mDepthTexture->setInternalFormat(GL_DEPTH_COMPONENT24); + mDepthTexture->setSourceType(GL_UNSIGNED_INT); + mDepthTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_BORDER); + mDepthTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_BORDER); + mDepthTexture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); + mDepthTexture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); + mDepthTexture->setBorderColor( + SceneUtil::AutoDepth::isReversed() ? osg::Vec4(0, 0, 0, 0) : osg::Vec4(1, 1, 1, 1)); + + mCamera = new osg::Camera; + mCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); + mCamera->setRenderOrder(osg::Camera::PRE_RENDER); + mCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); + mCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT); + mCamera->setNodeMask(Mask_RenderToTexture); + mCamera->setCullMask(Mask_Scene | Mask_Object | Mask_Static); + mCamera->setViewport(0, 0, rttSize, rttSize); + mCamera->attach(osg::Camera::DEPTH_BUFFER, mDepthTexture); + mCamera->addChild(mSceneNode); + + SceneUtil::setCameraClearDepth(mCamera); + } + + void PrecipitationOccluder::update() + { + const osg::Vec3 pos = mSceneCamera->getInverseViewMatrix().getTrans(); + + const float zmin = pos.z() - mRange.z() - Constants::CellSizeInUnits; + const float zmax = pos.z() + mRange.z() + Constants::CellSizeInUnits; + const float near = 0; + const float far = zmax - zmin; + + const float left = -mRange.x() / 2; + const float right = -left; + const float top = mRange.y() / 2; + const float bottom = -top; + + if (SceneUtil::AutoDepth::isReversed()) + { + mCamera->setProjectionMatrix( + SceneUtil::getReversedZProjectionMatrixAsOrtho(left, right, bottom, top, near, far)); + } + else + { + mCamera->setProjectionMatrix(osg::Matrixf::ortho(left, right, bottom, top, near, far)); + } + + mCamera->setViewMatrixAsLookAt( + osg::Vec3(pos.x(), pos.y(), zmax), osg::Vec3(pos.x(), pos.y(), zmin), osg::Vec3(0, 1, 0)); + } + + void PrecipitationOccluder::enable() + { + mSkyNode->setCullCallback(new PrecipitationOcclusionUpdater(mDepthTexture)); + mCamera->setCullCallback(new DepthCameraUpdater); + + mRootNode->removeChild(mCamera); + mRootNode->addChild(mCamera); + } + + void PrecipitationOccluder::disable() + { + mSkyNode->setCullCallback(nullptr); + mCamera->setCullCallback(nullptr); + + mRootNode->removeChild(mCamera); + } + + void PrecipitationOccluder::updateRange(const osg::Vec3f range) + { + const osg::Vec3f margin = { -50, -50, 0 }; + mRange = range - margin; + } +} diff --git a/apps/openmw/mwrender/precipitationocclusion.hpp b/apps/openmw/mwrender/precipitationocclusion.hpp new file mode 100644 index 0000000000..9910777449 --- /dev/null +++ b/apps/openmw/mwrender/precipitationocclusion.hpp @@ -0,0 +1,33 @@ +#ifndef OPENMW_MWRENDER_PRECIPITATIONOCCLUSION_H +#define OPENMW_MWRENDER_PRECIPITATIONOCCLUSION_H + +#include +#include + +namespace MWRender +{ + class PrecipitationOccluder + { + public: + PrecipitationOccluder(osg::Group* skyNode, osg::Group* sceneNode, osg::Group* rootNode, osg::Camera* camera); + + void update(); + + void enable(); + + void disable(); + + void updateRange(const osg::Vec3f range); + + private: + osg::Group* mSkyNode; + osg::Group* mSceneNode; + osg::Group* mRootNode; + osg::ref_ptr mCamera; + osg::ref_ptr mSceneCamera; + osg::ref_ptr mDepthTexture; + osg::Vec3f mRange; + }; +} + +#endif diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ca71532828..30cf10dada 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -586,8 +586,8 @@ namespace MWRender mFog = std::make_unique(); - mSky = std::make_unique(sceneRoot, resourceSystem->getSceneManager(), mSkyBlending); - mSky->setCamera(mViewer->getCamera()); + mSky = std::make_unique( + sceneRoot, mRootNode, mViewer->getCamera(), resourceSystem->getSceneManager(), mSkyBlending); if (mSkyBlending) { int skyTextureUnit = mResourceSystem->getSceneManager()->getShaderManager().reserveGlobalTextureUnits( diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index af0b161ee1..dd45a8d560 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -228,9 +228,10 @@ namespace namespace MWRender { - SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager, bool enableSkyRTT) + SkyManager::SkyManager(osg::Group* parentNode, osg::Group* rootNode, osg::Camera* camera, + Resource::SceneManager* sceneManager, bool enableSkyRTT) : mSceneManager(sceneManager) - , mCamera(nullptr) + , mCamera(camera) , mAtmosphereNightRoll(0.f) , mCreated(false) , mIsStorm(false) @@ -289,6 +290,8 @@ namespace MWRender mRootNode->setNodeMask(Mask_Sky); mRootNode->addChild(mEarlyRenderBinRoot); mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot); + + mPrecipitationOccluder = std::make_unique(skyroot, parentNode, rootNode, camera); } void SkyManager::create() @@ -382,11 +385,6 @@ namespace MWRender mCreated = true; } - void SkyManager::setCamera(osg::Camera* camera) - { - mCamera = camera; - } - void SkyManager::createRain() { if (mRainNode) @@ -466,9 +464,11 @@ namespace MWRender mRainNode->setNodeMask(Mask_WeatherParticles); mRainParticleSystem->setUserValue("simpleLighting", true); + mRainParticleSystem->setUserValue("particleOcclusion", true); mSceneManager->recreateShaders(mRainNode); mRootNode->addChild(mRainNode); + mPrecipitationOccluder->enable(); } void SkyManager::destroyRain() @@ -482,6 +482,7 @@ namespace MWRender mCounter = nullptr; mRainParticleSystem = nullptr; mRainShooter = nullptr; + mPrecipitationOccluder->disable(); } SkyManager::~SkyManager() @@ -563,6 +564,7 @@ namespace MWRender * osg::DegreesToRadians(360.f) / (3600 * 96.f); if (mAtmosphereNightNode->getNodeMask() != 0) mAtmosphereNightNode->setAttitude(osg::Quat(mAtmosphereNightRoll, osg::Vec3f(0, 0, 1))); + mPrecipitationOccluder->update(); } void SkyManager::setEnabled(bool enabled) @@ -606,6 +608,7 @@ namespace MWRender mPlacer->setZRange(-rainRange.z() / 2, rainRange.z() / 2); mCounter->setNumberOfParticlesPerSecondToCreate(mRainMaxRaindrops / mRainEntranceSpeed * 20); + mPrecipitationOccluder->updateRange(rainRange); } } @@ -671,6 +674,10 @@ namespace MWRender mRootNode->removeChild(mParticleNode); mParticleNode = nullptr; } + if (mRainEffect.empty()) + { + mPrecipitationOccluder->disable(); + } } else { @@ -693,6 +700,8 @@ namespace MWRender SceneUtil::FindByClassVisitor findPSVisitor("ParticleSystem"); mParticleEffect->accept(findPSVisitor); + const osg::Vec3 defaultWrapRange = osg::Vec3(1024, 1024, 800); + for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i) { osgParticle::ParticleSystem* ps @@ -700,7 +709,7 @@ namespace MWRender osg::ref_ptr program = new osgParticle::ModularProgram; if (!mIsStorm) - program->addOperator(new WrapAroundOperator(mCamera, osg::Vec3(1024, 1024, 800))); + program->addOperator(new WrapAroundOperator(mCamera, defaultWrapRange)); program->addOperator(new WeatherAlphaOperator(mPrecipitationAlpha, false)); program->setParticleSystem(ps); mParticleNode->addChild(program); @@ -713,9 +722,16 @@ namespace MWRender } ps->setUserValue("simpleLighting", true); + ps->setUserValue("particleOcclusion", true); } mSceneManager->recreateShaders(mParticleNode); + + if (mCurrentParticleEffect == "meshes\\snow.nif") + { + mPrecipitationOccluder->enable(); + mPrecipitationOccluder->updateRange(defaultWrapRange); + } } } diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index a365d32342..16cc0df7bd 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -8,6 +8,7 @@ #include #include +#include "precipitationocclusion.hpp" #include "skyutil.hpp" namespace osg @@ -43,7 +44,8 @@ namespace MWRender class SkyManager { public: - SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager, bool enableSkyRTT); + SkyManager(osg::Group* parentNode, osg::Group* rootNode, osg::Camera* camera, + Resource::SceneManager* sceneManager, bool enableSkyRTT); ~SkyManager(); void update(float duration); @@ -98,8 +100,6 @@ namespace MWRender void listAssetsToPreload(std::vector& models, std::vector& textures); - void setCamera(osg::Camera* camera); - float getBaseWindSpeed() const; void setSunglare(bool enabled); @@ -151,6 +151,8 @@ namespace MWRender osg::ref_ptr mCounter; osg::ref_ptr mRainShooter; + std::unique_ptr mPrecipitationOccluder; + bool mCreated; bool mIsStorm; diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index 4e5f68edf5..2a2429ff79 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -675,6 +676,11 @@ namespace Shader if (simpleLighting || dynamic_cast(&node)) defineMap["forcePPL"] = "0"; + bool particleOcclusion = false; + node.getUserValue("particleOcclusion", particleOcclusion); + defineMap["particleOcclusion"] + = particleOcclusion && Settings::Manager::getBool("weather particle occlusion", "Shaders") ? "1" : "0"; + if (reqs.mAlphaBlend && mSupportsNormalsRT) { if (reqs.mSoftParticles) diff --git a/docs/source/reference/modding/settings/shaders.rst b/docs/source/reference/modding/settings/shaders.rst index bd74d01fdd..e46e9ebb99 100644 --- a/docs/source/reference/modding/settings/shaders.rst +++ b/docs/source/reference/modding/settings/shaders.rst @@ -287,3 +287,18 @@ the look of some particle systems. Note that the rendering will act as if you have 'force shaders' option enabled. This means that shaders will be used to render all objects and the terrain. + +weather particle occlusion +-------------------------- + +:Type: boolean +:Range: True/False +:Default: False + +Enables particle occlusion for rain and snow particle effects. +When enabled, rain and snow will not clip through ceilings and overhangs. +Currently this relies on an additional render pass, which may lead to a performance hit. + +.. warning:: + This is an experimental feature that may cause visual oddities, especially when using default rain settings. + It is recommended to at least double the rain diameter through `openmw.cfg`.` diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 7c6c2e62fb..0981ecacc0 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -499,6 +499,9 @@ adjust coverage for alpha test = true # Soften intersection of blended particle systems with opaque geometry soft particles = false +# Rain and snow particle occlusion +weather particle occlusion = false + [Input] # Capture control of the cursor prevent movement outside the window. diff --git a/files/shaders/CMakeLists.txt b/files/shaders/CMakeLists.txt index d688f9e7d9..9215f78da0 100644 --- a/files/shaders/CMakeLists.txt +++ b/files/shaders/CMakeLists.txt @@ -34,8 +34,8 @@ set(SHADER_FILES shadowcasting_vertex.glsl shadowcasting_fragment.glsl vertexcolors.glsl - multiview_resolve_vertex.glsl - multiview_resolve_fragment.glsl + multiview_resolve_vertex.glsl + multiview_resolve_fragment.glsl nv_default_vertex.glsl nv_default_fragment.glsl nv_nolighting_vertex.glsl @@ -55,6 +55,8 @@ set(SHADER_FILES fullscreen_tri_vertex.glsl fullscreen_tri_fragment.glsl fog.glsl + precipitation_vertex.glsl + precipitation_fragment.glsl ) copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_RESOURCES_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}") diff --git a/files/shaders/objects_fragment.glsl b/files/shaders/objects_fragment.glsl index caf8b672ca..f05ff8eba8 100644 --- a/files/shaders/objects_fragment.glsl +++ b/files/shaders/objects_fragment.glsl @@ -92,8 +92,30 @@ varying vec3 passNormal; #include "softparticles.glsl" #endif +#if @particleOcclusion +uniform sampler2D orthoDepthMap; + +varying vec3 orthoDepthMapCoord; + +void precipitationOcclusion() +{ + float sceneDepth = texture2D(orthoDepthMap, orthoDepthMapCoord.xy * 0.5 + 0.5).r; +#if @reverseZ + if (orthoDepthMapCoord.z < sceneDepth) + discard; +#else + if (orthoDepthMapCoord.z * 0.5 + 0.5 > sceneDepth) + discard; +#endif +} +#endif + void main() { +#if @particleOcclusion + precipitationOcclusion(); +#endif + #if @diffuseMap vec2 adjustedDiffuseUV = diffuseMapUV; #endif diff --git a/files/shaders/objects_vertex.glsl b/files/shaders/objects_vertex.glsl index 971b95d8e0..12af0fa003 100644 --- a/files/shaders/objects_vertex.glsl +++ b/files/shaders/objects_vertex.glsl @@ -66,8 +66,20 @@ varying vec3 passNormal; #include "lighting.glsl" #include "depth.glsl" +#if @particleOcclusion +varying vec3 orthoDepthMapCoord; + +uniform mat4 depthSpaceMatrix; +uniform mat4 osg_ViewMatrixInverse; +#endif + void main(void) { +#if @particleOcclusion + mat4 model = osg_ViewMatrixInverse * gl_ModelViewMatrix; + orthoDepthMapCoord = ((depthSpaceMatrix * model) * vec4(gl_Vertex.xyz, 1.0)).xyz; +#endif + gl_Position = mw_modelToClip(gl_Vertex); vec4 viewPos = mw_modelToView(gl_Vertex); diff --git a/files/shaders/precipitation_fragment.glsl b/files/shaders/precipitation_fragment.glsl new file mode 100644 index 0000000000..b16eb0fd99 --- /dev/null +++ b/files/shaders/precipitation_fragment.glsl @@ -0,0 +1,15 @@ +#version 120 + +uniform sampler2D diffuseMap; +varying vec2 diffuseMapUV; + +#include "vertexcolors.glsl" + +void main() +{ + gl_FragData[0].rgb = vec3(1.0); + gl_FragData[0].a = texture2D(diffuseMap, diffuseMapUV).a * getDiffuseColor().a; + + if (gl_FragData[0].a <= 0.5) + discard; +} \ No newline at end of file diff --git a/files/shaders/precipitation_vertex.glsl b/files/shaders/precipitation_vertex.glsl new file mode 100644 index 0000000000..a202d9cd96 --- /dev/null +++ b/files/shaders/precipitation_vertex.glsl @@ -0,0 +1,13 @@ +#version 120 + +uniform mat4 projectionMatrix; +varying vec2 diffuseMapUV; + +#include "vertexcolors.glsl" + +void main() +{ + gl_Position = projectionMatrix * (gl_ModelViewMatrix * gl_Vertex); + diffuseMapUV = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy; + passColor = gl_Color; +} \ No newline at end of file diff --git a/files/ui/advancedpage.ui b/files/ui/advancedpage.ui index d1da187fbe..f373f5532a 100644 --- a/files/ui/advancedpage.ui +++ b/files/ui/advancedpage.ui @@ -485,6 +485,16 @@ + + + + <html><head/><body><p>EXPERIMENTAL: Stop rain and snow from falling through overhangs and roofs.</p></body></html> + + + Weather Particle Occlusion + + + From 9630246cae48dfea06730c6648d080993425fa3d Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Fri, 6 Jan 2023 22:13:03 +0400 Subject: [PATCH 32/37] Sort quests in journal by name (bug 7054) --- CHANGELOG.md | 1 + apps/openmw/mwgui/journalwindow.cpp | 1 + components/widgets/list.cpp | 8 ++++++++ components/widgets/list.hpp | 1 + 4 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 551a7d9aa6..c6abd88bb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Bug #7034: Misc items defined in one content file are not treated as keys if another content file uses them as such Bug #7042: Weapon follow animations that immediately follow the hit animations cause multiple hits Bug #7044: Changing a class' services does not affect autocalculated NPCs + Bug #7054: Quests aren't sorted by name Bug #7084: Resurrecting an actor doesn't take into account base record changes Bug #7088: Deleting last save game of last character doesn't clear character name/details Feature #6447: Add LOD support to Object Paging diff --git a/apps/openmw/mwgui/journalwindow.cpp b/apps/openmw/mwgui/journalwindow.cpp index 21cf30b556..1319379e60 100644 --- a/apps/openmw/mwgui/journalwindow.cpp +++ b/apps/openmw/mwgui/journalwindow.cpp @@ -558,6 +558,7 @@ namespace mModel->visitQuestNames(!mAllQuests, add); + list->sort(); list->adjustSize(); if (mAllQuests) diff --git a/components/widgets/list.cpp b/components/widgets/list.cpp index 92cf237875..de1c160288 100644 --- a/components/widgets/list.cpp +++ b/components/widgets/list.cpp @@ -4,6 +4,8 @@ #include #include +#include + namespace Gui { @@ -124,6 +126,12 @@ namespace Gui return mItems[at]; } + void MWList::sort() + { + // A special case for separators is not needed for now + std::sort(mItems.begin(), mItems.end(), Misc::StringUtils::ciLess); + } + void MWList::removeItem(const std::string& name) { assert(std::find(mItems.begin(), mItems.end(), name) != mItems.end()); diff --git a/components/widgets/list.hpp b/components/widgets/list.hpp index a0df792696..b9e397f1a8 100644 --- a/components/widgets/list.hpp +++ b/components/widgets/list.hpp @@ -35,6 +35,7 @@ namespace Gui */ void adjustSize(); + void sort(); void addItem(std::string_view name); void addSeparator(); ///< add a seperator between the current and the next item. void removeItem(const std::string& name); From 152bdb2f65c29fe30ddb348f2e925227df52d772 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 7 Jan 2023 22:16:35 +0300 Subject: [PATCH 33/37] Prevent missing KO animations from cancelling KO --- apps/openmw/mwmechanics/character.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 21e30ec8ac..966ed5a158 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -400,6 +400,9 @@ namespace MWMechanics { if (!mAnimation->isPlaying(mCurrentHit)) { + if (isKnockedOut() && mCurrentHit.empty() && knockout) + return; + mHitState = CharState_None; mCurrentHit.clear(); stats.setKnockedDown(false); @@ -450,18 +453,6 @@ namespace MWMechanics mCurrentHit = chooseRandomGroup(hitStateToAnimGroup(CharState_Hit)); } - if (!mAnimation->hasAnimation(mCurrentHit)) - { - // The hit animation is missing. Reset the current hit state and immediately cancel all states as if the - // animation were instantaneous. - mHitState = CharState_None; - mCurrentHit.clear(); - stats.setKnockedDown(false); - stats.setHitRecovery(false); - resetCurrentIdleState(); - return; - } - // Cancel upper body animations if (isKnockedOut() || isKnockedDown()) { @@ -479,6 +470,12 @@ namespace MWMechanics } } + if (!mAnimation->hasAnimation(mCurrentHit)) + { + mCurrentHit.clear(); + return; + } + mAnimation->play( mCurrentHit, priority, MWRender::Animation::BlendMask_All, true, 1, startKey, stopKey, 0.0f, ~0ul); } From fa7991fcb3bfbf73f3adcb5465cf23adb6cd0020 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 7 Jan 2023 22:35:29 +0300 Subject: [PATCH 34/37] For hit state, cancel non-biped idle if there is an active animation --- apps/openmw/mwmechanics/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 966ed5a158..9999cfc3c6 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -752,7 +752,7 @@ namespace MWMechanics // FIXME: if one of the below states is close to their last animation frame (i.e. will be disabled in the coming // update), the idle animation should be displayed if (((mUpperBodyState != UpperBodyState::None && mUpperBodyState != UpperBodyState::WeaponEquipped) - || mMovementState != CharState_None || mHitState != CharState_None) + || mMovementState != CharState_None || !mCurrentHit.empty()) && !mPtr.getClass().isBipedal(mPtr)) { resetCurrentIdleState(); From 7a0b998d4f7f7c30f25ad319512147fb031bb7c3 Mon Sep 17 00:00:00 2001 From: Petr Mikheev Date: Sat, 7 Jan 2023 23:42:53 +0100 Subject: [PATCH 35/37] Cleanup unused actions --- apps/openmw/mwinput/actions.hpp | 103 +++++++++++++--------------- apps/openmw/mwlua/inputbindings.cpp | 3 - files/lua_api/openmw/input.lua | 3 - 3 files changed, 48 insertions(+), 61 deletions(-) diff --git a/apps/openmw/mwinput/actions.hpp b/apps/openmw/mwinput/actions.hpp index e586a613f7..538d12f2c2 100644 --- a/apps/openmw/mwinput/actions.hpp +++ b/apps/openmw/mwinput/actions.hpp @@ -5,75 +5,68 @@ namespace MWInput { enum Actions { - // please add new actions at the bottom, in order to preserve the channel IDs in the key configuration files + // Action IDs are used in the configuration file input_v3.xml - A_GameMenu, + A_GameMenu = 0, - A_Unused, + A_Screenshot = 2, // Take a screenshot - A_Screenshot, // Take a screenshot + A_Inventory = 3, // Toggle inventory screen + A_Console = 4, // Toggle console screen - A_Inventory, // Toggle inventory screen + A_MoveLeft = 5, // Move player left / right + A_MoveRight = 6, + A_MoveForward = 7, // Forward / Backward + A_MoveBackward = 8, - A_Console, // Toggle console screen + A_Activate = 9, - A_MoveLeft, // Move player left / right - A_MoveRight, - A_MoveForward, // Forward / Backward - A_MoveBackward, + A_Use = 10, // Use weapon, spell, etc. + A_Jump = 11, + A_AutoMove = 12, // Toggle Auto-move forward + A_Rest = 13, // Rest + A_Journal = 14, // Journal + A_Run = 17, // Run when held + A_CycleSpellLeft = 18, // cycling through spells + A_CycleSpellRight = 19, + A_CycleWeaponLeft = 20, // Cycling through weapons + A_CycleWeaponRight = 21, + A_AlwaysRun = 23, // Toggle Walking/Running + A_Sneak = 24, - A_Activate, + A_QuickSave = 25, + A_QuickLoad = 26, + A_QuickMenu = 27, + A_ToggleWeapon = 28, + A_ToggleSpell = 29, - A_Use, // Use weapon, spell, etc. - A_Jump, - A_AutoMove, // Toggle Auto-move forward - A_Rest, // Rest - A_Journal, // Journal - A_Weapon, // Draw/Sheath weapon - A_Spell, // Ready/Unready Casting - A_Run, // Run when held - A_CycleSpellLeft, // cycling through spells - A_CycleSpellRight, - A_CycleWeaponLeft, // Cycling through weapons - A_CycleWeaponRight, - A_ToggleSneak, // Toggles Sneak - A_AlwaysRun, // Toggle Walking/Running - A_Sneak, + A_TogglePOV = 30, - A_QuickSave, - A_QuickLoad, - A_QuickMenu, - A_ToggleWeapon, - A_ToggleSpell, + A_QuickKey1 = 31, + A_QuickKey2 = 32, + A_QuickKey3 = 33, + A_QuickKey4 = 34, + A_QuickKey5 = 35, + A_QuickKey6 = 36, + A_QuickKey7 = 37, + A_QuickKey8 = 38, + A_QuickKey9 = 39, + A_QuickKey10 = 40, - A_TogglePOV, + A_QuickKeysMenu = 41, - A_QuickKey1, - A_QuickKey2, - A_QuickKey3, - A_QuickKey4, - A_QuickKey5, - A_QuickKey6, - A_QuickKey7, - A_QuickKey8, - A_QuickKey9, - A_QuickKey10, + A_ToggleHUD = 42, + A_ToggleDebug = 43, - A_QuickKeysMenu, + A_LookUpDown = 44, // Joystick look + A_LookLeftRight = 45, + A_MoveForwardBackward = 46, + A_MoveLeftRight = 47, - A_ToggleHUD, + A_ZoomIn = 48, + A_ZoomOut = 49, - A_ToggleDebug, - - A_LookUpDown, // Joystick look - A_LookLeftRight, - A_MoveForwardBackward, - A_MoveLeftRight, - - A_ZoomIn, - A_ZoomOut, - - A_TogglePostProcessorHUD, + A_TogglePostProcessorHUD = 50, A_Last // Marker for the last item }; diff --git a/apps/openmw/mwlua/inputbindings.cpp b/apps/openmw/mwlua/inputbindings.cpp index 105a107301..ae3ce82fcb 100644 --- a/apps/openmw/mwlua/inputbindings.cpp +++ b/apps/openmw/mwlua/inputbindings.cpp @@ -98,14 +98,11 @@ namespace MWLua { "AutoMove", MWInput::A_AutoMove }, { "Rest", MWInput::A_Rest }, { "Journal", MWInput::A_Journal }, - { "Weapon", MWInput::A_Weapon }, - { "Spell", MWInput::A_Spell }, { "Run", MWInput::A_Run }, { "CycleSpellLeft", MWInput::A_CycleSpellLeft }, { "CycleSpellRight", MWInput::A_CycleSpellRight }, { "CycleWeaponLeft", MWInput::A_CycleWeaponLeft }, { "CycleWeaponRight", MWInput::A_CycleWeaponRight }, - { "ToggleSneak", MWInput::A_ToggleSneak }, { "AlwaysRun", MWInput::A_AlwaysRun }, { "Sneak", MWInput::A_Sneak }, diff --git a/files/lua_api/openmw/input.lua b/files/lua_api/openmw/input.lua index 205ab584d9..e0aa917420 100644 --- a/files/lua_api/openmw/input.lua +++ b/files/lua_api/openmw/input.lua @@ -118,14 +118,11 @@ -- @field [parent=#ACTION] #number Jump -- @field [parent=#ACTION] #number AutoMove -- @field [parent=#ACTION] #number Journal --- @field [parent=#ACTION] #number Weapon --- @field [parent=#ACTION] #number Spell -- @field [parent=#ACTION] #number Run -- @field [parent=#ACTION] #number CycleSpellLeft -- @field [parent=#ACTION] #number CycleSpellRight -- @field [parent=#ACTION] #number CycleWeaponLeft -- @field [parent=#ACTION] #number CycleWeaponRight --- @field [parent=#ACTION] #number ToggleSneak -- @field [parent=#ACTION] #number AlwaysRun -- @field [parent=#ACTION] #number Sneak -- @field [parent=#ACTION] #number QuickSave From 5a6a25361ab90ea5c42b9c67bff196632f4460ab Mon Sep 17 00:00:00 2001 From: psi29a Date: Sat, 7 Jan 2023 22:48:38 +0000 Subject: [PATCH 36/37] Revert "Merge branch 'confpyupdate' into 'master'" This reverts merge request !2581 --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 87c50d1404..7f2affbb75 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -151,7 +151,7 @@ def setup(app): app.add_stylesheet('figures.css') app.add_stylesheet('luadoc.css') try: - subprocess.call(['sh', project_root + '/docs/source/generate_luadoc.sh']) + subprocess.call(project_root + '/docs/source/generate_luadoc.sh') except Exception as e: print('Can\'t generate Lua API documentation:', e) From 0de6b79966fd9452a8ecc392de89997529ca41f1 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Sun, 8 Jan 2023 12:59:47 +0100 Subject: [PATCH 37/37] Fixes issue with topic info edition. Also future proofs reference on RefId's string. --- apps/opencs/model/world/collection.hpp | 8 +------- apps/opencs/model/world/data.cpp | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index c4288b117c..b00393b8af 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -490,13 +490,7 @@ namespace CSMWorld int Collection::searchId(const ESM::RefId& id) const { - std::map::const_iterator iter - = mIndex.find(Misc::StringUtils::lowerCase(id.getRefIdString())); - - if (iter == mIndex.end()) - return -1; - - return iter->second; + return searchId(id.getRefIdString()); } template diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index da77405d29..51ffe52436 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -1242,10 +1242,10 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages) case ESM::REC_DIAL: { ESM::Dialogue record; - const std::string& recordIdString = record.mId.getRefIdString(); bool isDeleted = false; record.load(*mReader, isDeleted); + const std::string& recordIdString = record.mId.getRefIdString(); if (isDeleted) {