diff --git a/.clang-tidy b/.clang-tidy index 92500ad04d..90c72765ca 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -13,3 +13,7 @@ HeaderFilterRegex: '(apps|components)/' CheckOptions: - key: readability-identifier-naming.ConceptCase value: CamelCase +- key: readability-identifier-naming.NamespaceCase + value: CamelCase +- key: readability-identifier-naming.NamespaceIgnoredRegexp + value: 'osg(DB|FX|Particle|Shadow|Viewer|Util)?' diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 42074a0667..48d9f5ff8a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,6 +46,9 @@ Ubuntu_GCC_preprocess: - pip3 install --user click termtables script: - CI/ubuntu_gcc_preprocess.sh + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_ID != "7107382" .Ubuntu: extends: .Ubuntu_Image @@ -268,6 +271,9 @@ Ubuntu_GCC_tests_asan: when: always reports: junit: build/*-tests.xml + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_ID != "7107382" Ubuntu_GCC_tests_ubsan: extends: Ubuntu_GCC @@ -285,6 +291,9 @@ Ubuntu_GCC_tests_ubsan: when: always reports: junit: build/*-tests.xml + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_ID != "7107382" .Ubuntu_GCC_tests_tsan: extends: Ubuntu_GCC @@ -322,6 +331,9 @@ Ubuntu_GCC_tests_coverage: coverage_format: cobertura path: coverage.xml junit: build/*-tests.xml + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_ID != "7107382" .Ubuntu_Static_Deps: extends: Ubuntu_Clang @@ -402,6 +414,9 @@ Ubuntu_Clang: - build/ expire_in: 12h timeout: 3h + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_PIPELINE_SOURCE == "push" && $CI_PROJECT_ID != "7107382" Ubuntu_Clang_Tidy_components: extends: .Ubuntu_Clang_Tidy_Base @@ -502,7 +517,14 @@ Ubuntu_GCC_integration_tests_asan: .MacOS: stage: build rules: - - if: $CI_PROJECT_ID == "7107382" + - if: $CI_PROJECT_ID != "7107382" + when: never + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + when: manual + - if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "schedule" + image: macos-15-xcode-16 + tags: + - saas-macos-medium-m1 cache: paths: - ccache/ @@ -535,13 +557,10 @@ Ubuntu_GCC_integration_tests_asan: paths: - build/OpenMW-*.dmg -macOS14_Xcode15_amd64: +macOS15_Xcode16_amd64: extends: .MacOS - image: macos-14-xcode-15 - tags: - - saas-macos-medium-m1 cache: - key: macOS14_Xcode15_amd64.v2 + key: macOS15_Xcode16_amd64.v1 variables: CCACHE_SIZE: 3G DMG_IDENTIFIER: amd64 @@ -550,13 +569,10 @@ macOS14_Xcode15_amd64: HOMEBREW_NO_EMOJI: true HOMEBREW_NO_INSTALL_CLEANUP: true -macOS14_Xcode15_arm64: +macOS15_Xcode16_arm64: extends: .MacOS - image: macos-14-xcode-15 - tags: - - saas-macos-medium-m1 cache: - key: macOS14_Xcode15_arm64.v1 + key: macOS15_Xcode16_arm64.v1 variables: DMG_IDENTIFIER: arm64 CCACHE_SIZE: 3G @@ -687,7 +703,7 @@ macOS14_Xcode15_arm64: - Get-Volume - Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log cache: - key: ninja-2022-v12 + key: ninja-2022-v13 paths: - ccache - deps @@ -845,7 +861,7 @@ macOS14_Xcode15_arm64: - Get-Volume - Copy-Item C:\ProgramData\chocolatey\logs\chocolatey.log cache: - key: msbuild-2022-v12 + key: msbuild-2022-v13 paths: - deps - MSVC2022_64/deps/Qt diff --git a/AUTHORS.md b/AUTHORS.md index 51910dedaa..c2e71aa85d 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -197,7 +197,7 @@ Programmers Qlonever Radu-Marius Popovici (rpopovici) Rafael Moura (dhustkoder) - Randy Davin (Kindi) + Randy Davin (Kuyondo) rdimesio rexelion riothamus diff --git a/CI/before_script.msvc.sh b/CI/before_script.msvc.sh index 940c72c806..9363211e9a 100644 --- a/CI/before_script.msvc.sh +++ b/CI/before_script.msvc.sh @@ -377,6 +377,8 @@ case $VS_VERSION in MSVC_DISPLAY_YEAR="2022" QT_MSVC_YEAR="2019" + + VCPKG_TRIPLET="x64-windows" ;; 16|16.0|2019 ) @@ -386,6 +388,8 @@ case $VS_VERSION in MSVC_DISPLAY_YEAR="2019" QT_MSVC_YEAR="2019" + + VCPKG_TRIPLET="x64-windows-2019" ;; 15|15.0|2017 ) @@ -546,7 +550,7 @@ fi QT_VER='6.6.3' AQT_VERSION='v3.1.15' -VCPKG_TAG="2024-11-10" +VCPKG_TAG="2025-07-23" VCPKG_PATH="vcpkg-x64-${VS_VERSION:?}-${VCPKG_TAG:?}" VCPKG_PDB_PATH="vcpkg-x64-${VS_VERSION:?}-pdb-${VCPKG_TAG:?}" VCPKG_MANIFEST="${VCPKG_PATH:?}.txt" @@ -633,16 +637,16 @@ printf "vcpkg packages ${VCPKG_TAG:?}... " fi add_cmake_opts -DCMAKE_TOOLCHAIN_FILE="$(real_pwd)/${VCPKG_PATH:?}/scripts/buildsystems/vcpkg.cmake" - add_cmake_opts -DLuaJit_INCLUDE_DIR="$(real_pwd)/${VCPKG_PATH:?}/installed/x64-windows/include/luajit" - add_cmake_opts -DLuaJit_LIBRARY="$(real_pwd)/${VCPKG_PATH:?}/installed/x64-windows/lib/lua51.lib" + add_cmake_opts -DLuaJit_INCLUDE_DIR="$(real_pwd)/${VCPKG_PATH:?}/installed/${VCPKG_TRIPLET}/include/luajit" + add_cmake_opts -DLuaJit_LIBRARY="$(real_pwd)/${VCPKG_PATH:?}/installed/${VCPKG_TRIPLET}/lib/lua51.lib" for CONFIGURATION in ${CONFIGURATIONS[@]}; do if [[ ${CONFIGURATION:?} == "Debug" ]]; then - VCPKG_DLL_BIN="$(pwd)/${VCPKG_PATH:?}/installed/x64-windows/debug/bin" + VCPKG_DLL_BIN="$(pwd)/${VCPKG_PATH:?}/installed/${VCPKG_TRIPLET}/debug/bin" add_runtime_dlls ${CONFIGURATION:?} "${VCPKG_DLL_BIN:?}/Debug/MyGUIEngine_d.dll" else - VCPKG_DLL_BIN="$(pwd)/${VCPKG_PATH:?}/installed/x64-windows/bin" + VCPKG_DLL_BIN="$(pwd)/${VCPKG_PATH:?}/installed/${VCPKG_TRIPLET}/bin" add_runtime_dlls ${CONFIGURATION:?} "${VCPKG_DLL_BIN:?}/Release/MyGUIEngine.dll" fi diff --git a/apps/components_tests/esm3/testsaveload.cpp b/apps/components_tests/esm3/testsaveload.cpp index 41a79313cc..7e5b73e4dd 100644 --- a/apps/components_tests/esm3/testsaveload.cpp +++ b/apps/components_tests/esm3/testsaveload.cpp @@ -723,7 +723,7 @@ namespace ESM TEST_P(Esm3SaveLoadRecordTest, landShouldNotChange) { LandRecordData data; - std::iota(data.mHeights.begin(), data.mHeights.end(), 1); + std::iota(data.mHeights.begin(), data.mHeights.end(), 1.0f); std::for_each(data.mHeights.begin(), data.mHeights.end(), [](float& v) { v *= Land::sHeightScale; }); data.mMinHeight = *std::min_element(data.mHeights.begin(), data.mHeights.end()); data.mMaxHeight = *std::max_element(data.mHeights.begin(), data.mHeights.end()); diff --git a/apps/components_tests/fx/lexer.cpp b/apps/components_tests/fx/lexer.cpp index 9c095a1f64..976f88d7a3 100644 --- a/apps/components_tests/fx/lexer.cpp +++ b/apps/components_tests/fx/lexer.cpp @@ -5,7 +5,7 @@ namespace { using namespace testing; - using namespace fx::Lexer; + using namespace Fx::Lexer; struct LexerTest : Test { diff --git a/apps/components_tests/fx/technique.cpp b/apps/components_tests/fx/technique.cpp index 2becf4da5b..b04ff5c52a 100644 --- a/apps/components_tests/fx/technique.cpp +++ b/apps/components_tests/fx/technique.cpp @@ -91,7 +91,7 @@ namespace )" }; using namespace testing; - using namespace fx; + using namespace Fx; struct TechniqueTest : Test { diff --git a/apps/components_tests/lua/testl10n.cpp b/apps/components_tests/lua/testl10n.cpp index 5528c0520a..7446822f7f 100644 --- a/apps/components_tests/lua/testl10n.cpp +++ b/apps/components_tests/lua/testl10n.cpp @@ -105,7 +105,7 @@ speed: "Speed" lua.protectedCall([&](LuaUtil::LuaView& view) { sol::state_view& l = view.sol(); internal::CaptureStdout(); - l10n::Manager l10nManager(mVFS.get()); + L10n::Manager l10nManager(mVFS.get()); l10nManager.setPreferredLocales({ "de", "en" }); EXPECT_THAT(internal::GetCapturedStdout(), "Preferred locales: gmst de en\n"); diff --git a/apps/essimporter/converter.hpp b/apps/essimporter/converter.hpp index 095e36c7ee..520dd27f2a 100644 --- a/apps/essimporter/converter.hpp +++ b/apps/essimporter/converter.hpp @@ -249,7 +249,7 @@ namespace ESSImport { ESM::InventoryState& invState = mContext->mPlayer.mObject.mInventory; - for (size_t i = 0; i < invState.mItems.size(); ++i) + for (uint32_t i = 0; i < static_cast(invState.mItems.size()); ++i) { // FIXME: in case of conflict (multiple items with this refID) use the already equipped one? if (invState.mItems[i].mRef.mRefID == refr.mActorData.mSelectedEnchantItem) diff --git a/apps/launcher/main.cpp b/apps/launcher/main.cpp index 2ea152305f..ff85154289 100644 --- a/apps/launcher/main.cpp +++ b/apps/launcher/main.cpp @@ -42,7 +42,7 @@ int runLauncher(int argc, char* argv[]) resourcesPath = Files::pathToQString(variables["resources"].as().u8string()); } - l10n::installQtTranslations(app, "launcher", resourcesPath); + L10n::installQtTranslations(app, "launcher", resourcesPath); Launcher::MainDialog mainWin(configurationManager); diff --git a/apps/navmeshtool/worldspacedata.cpp b/apps/navmeshtool/worldspacedata.cpp index ec44d33e6c..df5c48e7ab 100644 --- a/apps/navmeshtool/worldspacedata.cpp +++ b/apps/navmeshtool/worldspacedata.cpp @@ -201,8 +201,8 @@ namespace NavMeshTool { if (!land.has_value() || osg::Vec2i(land->mX, land->mY) != cellPosition || (land->mDataTypes & ESM::Land::DATA_VHGT) == 0) - return { HeightfieldPlane{ ESM::Land::DEFAULT_HEIGHT }, ESM::Land::DEFAULT_HEIGHT, - ESM::Land::DEFAULT_HEIGHT }; + return { HeightfieldPlane{ static_cast(ESM::Land::DEFAULT_HEIGHT) }, + static_cast(ESM::Land::DEFAULT_HEIGHT), static_cast(ESM::Land::DEFAULT_HEIGHT) }; ESM::Land::LandData& landData = *landDatas.emplace_back(std::make_unique()); land->loadData(ESM::Land::DATA_VHGT, landData); diff --git a/apps/opencs/model/world/infoselectwrapper.cpp b/apps/opencs/model/world/infoselectwrapper.cpp index 2e9ed6e150..1ce126e0ee 100644 --- a/apps/opencs/model/world/infoselectwrapper.cpp +++ b/apps/opencs/model/world/infoselectwrapper.cpp @@ -625,8 +625,6 @@ bool CSMWorld::ConstInfoSelectWrapper::conditionIsAlwaysTrue( default: throw std::logic_error("InfoCondition: operator can not be used to compare"); } - - return false; } template @@ -651,8 +649,6 @@ bool CSMWorld::ConstInfoSelectWrapper::conditionIsNeverTrue( default: throw std::logic_error("InfoCondition: operator can not be used to compare"); } - - return false; } QVariant CSMWorld::ConstInfoSelectWrapper::getValue() const diff --git a/apps/opencs/model/world/refidcollection.cpp b/apps/opencs/model/world/refidcollection.cpp index e0d5799726..6fff14674f 100644 --- a/apps/opencs/model/world/refidcollection.cpp +++ b/apps/opencs/model/world/refidcollection.cpp @@ -753,7 +753,6 @@ void CSMWorld::RefIdCollection::cloneRecord( bool CSMWorld::RefIdCollection::touchRecord(const ESM::RefId& id) { throw std::runtime_error("RefIdCollection::touchRecord is unimplemented"); - return false; } void CSMWorld::RefIdCollection::appendRecord(std::unique_ptr record, UniversalId::Type type) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 5807ef222b..244c458f46 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -755,7 +755,7 @@ void OMW::Engine::prepareEngine() mViewer->addEventHandler(mScreenCaptureHandler); - mL10nManager = std::make_unique(mVFS.get()); + mL10nManager = std::make_unique(mVFS.get()); mL10nManager->setPreferredLocales(Settings::general().mPreferredLocales, Settings::general().mGmstOverridesL10n); mEnvironment.setL10nManager(*mL10nManager); diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 38e95ea7c8..97b6a78ee9 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -113,7 +113,7 @@ namespace MWDialogue class Journal; } -namespace l10n +namespace L10n { class Manager; } @@ -141,7 +141,7 @@ namespace OMW std::unique_ptr mStateManager; std::unique_ptr mLuaManager; std::unique_ptr mLuaWorker; - std::unique_ptr mL10nManager; + std::unique_ptr mL10nManager; MWBase::Environment mEnvironment; ToUTF8::FromType mEncoding; std::unique_ptr mEncoder; diff --git a/apps/openmw/mwbase/environment.hpp b/apps/openmw/mwbase/environment.hpp index aa8a41b7c1..94f918a60b 100644 --- a/apps/openmw/mwbase/environment.hpp +++ b/apps/openmw/mwbase/environment.hpp @@ -10,7 +10,7 @@ namespace Resource class ResourceSystem; } -namespace l10n +namespace L10n { class Manager; } @@ -57,7 +57,7 @@ namespace MWBase StateManager* mStateManager = nullptr; LuaManager* mLuaManager = nullptr; Resource::ResourceSystem* mResourceSystem = nullptr; - l10n::Manager* mL10nManager = nullptr; + L10n::Manager* mL10nManager = nullptr; float mFrameRateLimit = 0; float mFrameDuration = 0; @@ -95,7 +95,7 @@ namespace MWBase void setResourceSystem(Resource::ResourceSystem& value) { mResourceSystem = &value; } - void setL10nManager(l10n::Manager& value) { mL10nManager = &value; } + void setL10nManager(L10n::Manager& value) { mL10nManager = &value; } Misc::NotNullPtr getWorld() const { return mWorld; } Misc::NotNullPtr getWorldModel() const { return mWorldModel; } @@ -122,7 +122,7 @@ namespace MWBase Misc::NotNullPtr getResourceSystem() const { return mResourceSystem; } - Misc::NotNullPtr getL10nManager() const { return mL10nManager; } + Misc::NotNullPtr getL10nManager() const { return mL10nManager; } float getFrameRateLimit() const { return mFrameRateLimit; } diff --git a/apps/openmw/mwbase/inputmanager.hpp b/apps/openmw/mwbase/inputmanager.hpp index 4358c7a1e0..373182fb5b 100644 --- a/apps/openmw/mwbase/inputmanager.hpp +++ b/apps/openmw/mwbase/inputmanager.hpp @@ -92,6 +92,8 @@ namespace MWBase virtual void executeAction(int action) = 0; virtual bool controlsDisabled() = 0; + + virtual void saveBindings() = 0; }; } diff --git a/apps/openmw/mwbase/luamanager.hpp b/apps/openmw/mwbase/luamanager.hpp index a5d6fe1114..bbdb843199 100644 --- a/apps/openmw/mwbase/luamanager.hpp +++ b/apps/openmw/mwbase/luamanager.hpp @@ -1,6 +1,7 @@ #ifndef GAME_MWBASE_LUAMANAGER_H #define GAME_MWBASE_LUAMANAGER_H +#include #include #include #include @@ -75,6 +76,7 @@ namespace MWBase virtual void questUpdated(const ESM::RefId& questId, int stage) = 0; // `arg` is either forwarded from MWGui::pushGuiMode or empty virtual void uiModeChanged(const MWWorld::Ptr& arg) = 0; + virtual void savePermanentStorage(const std::filesystem::path& userConfigPath) = 0; // TODO: notify LuaManager about other events // virtual void objectOnHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index b85bb9e996..a1c632dab9 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -530,10 +530,11 @@ namespace MWClass const MWBase::World* world = MWBase::Environment::get().getWorld(); const MWMechanics::MagicEffects& mageffects = stats.getMagicEffects(); + const float normalizedEncumbrance = getNormalizedEncumbrance(ptr); float moveSpeed; - if (getEncumbrance(ptr) > getCapacity(ptr)) + if (normalizedEncumbrance > 1.0f) moveSpeed = 0.0f; else if (canFly(ptr) || (mageffects.getOrDefault(ESM::MagicEffect::Levitate).getMagnitude() > 0 && world->isLevitationEnabled())) @@ -543,7 +544,6 @@ namespace MWClass + mageffects.getOrDefault(ESM::MagicEffect::Levitate).getMagnitude()); flySpeed = gmst.fMinFlySpeed->mValue.getFloat() + flySpeed * (gmst.fMaxFlySpeed->mValue.getFloat() - gmst.fMinFlySpeed->mValue.getFloat()); - const float normalizedEncumbrance = getNormalizedEncumbrance(ptr); flySpeed *= 1.0f - gmst.fEncumberedMoveEffect->mValue.getFloat() * normalizedEncumbrance; flySpeed = std::max(0.0f, flySpeed); moveSpeed = flySpeed; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index c03d132503..693caeb5ae 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -990,15 +990,10 @@ namespace MWClass const MWMechanics::MagicEffects& mageffects = stats.getMagicEffects(); const float normalizedEncumbrance = getNormalizedEncumbrance(ptr); - - bool swimming = world->isSwimming(ptr); - bool sneaking = MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr); - bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run); - bool inair = !world->isOnGround(ptr) && !swimming && !world->isFlying(ptr); - running = running && (inair || MWBase::Environment::get().getMechanicsManager()->isRunning(ptr)); + const bool running = MWBase::Environment::get().getMechanicsManager()->isRunning(ptr); float moveSpeed; - if (getEncumbrance(ptr) > getCapacity(ptr)) + if (normalizedEncumbrance > 1.0f) moveSpeed = 0.0f; else if (mageffects.getOrDefault(ESM::MagicEffect::Levitate).getMagnitude() > 0 && world->isLevitationEnabled()) { @@ -1011,9 +1006,9 @@ namespace MWClass flySpeed = std::max(0.0f, flySpeed); moveSpeed = flySpeed; } - else if (swimming) + else if (world->isSwimming(ptr)) moveSpeed = getSwimSpeed(ptr); - else if (running && !sneaking) + else if (running && !MWBase::Environment::get().getMechanicsManager()->isSneaking(ptr)) moveSpeed = getRunSpeed(ptr); else moveSpeed = getWalkSpeed(ptr); @@ -1509,14 +1504,8 @@ namespace MWClass float Npc::getSwimSpeed(const MWWorld::Ptr& ptr) const { - const MWBase::World* world = MWBase::Environment::get().getWorld(); - const MWMechanics::NpcStats& stats = getNpcStats(ptr); - const MWMechanics::MagicEffects& mageffects = stats.getMagicEffects(); - const bool swimming = world->isSwimming(ptr); - const bool inair = !world->isOnGround(ptr) && !swimming && !world->isFlying(ptr); - const bool running = stats.getStance(MWMechanics::CreatureStats::Stance_Run) - && (inair || MWBase::Environment::get().getMechanicsManager()->isRunning(ptr)); - - return getSwimSpeedImpl(ptr, getGmst(), mageffects, running ? getRunSpeed(ptr) : getWalkSpeed(ptr)); + const MWMechanics::MagicEffects& effects = getNpcStats(ptr).getMagicEffects(); + const bool running = MWBase::Environment::get().getMechanicsManager()->isRunning(ptr); + return getSwimSpeedImpl(ptr, getGmst(), effects, running ? getRunSpeed(ptr) : getWalkSpeed(ptr)); } } diff --git a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp index 9f3bb0b26f..ab92300804 100644 --- a/apps/openmw/mwdialogue/dialoguemanagerimp.cpp +++ b/apps/openmw/mwdialogue/dialoguemanagerimp.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -448,12 +449,14 @@ namespace MWDialogue { updateOriginalDisposition(); MWMechanics::NpcStats& npcStats = mActor.getClass().getNpcStats(mActor); - // Clamp permanent disposition change so that final disposition doesn't go below 0 (could happen with - // intimidate) - npcStats.setBaseDisposition(0); - int zero = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor, false); - int disposition = std::clamp(mOriginalDisposition + mPermanentDispositionChange, -zero, 100 - zero); + // Get the sum of disposition effects minus charm (shouldn't be made permanent) + npcStats.setBaseDisposition(0); + int zero = MWBase::Environment::get().getMechanicsManager()->getDerivedDisposition(mActor, false) + - npcStats.getMagicEffects().getOrDefault(ESM::MagicEffect::Charm).getMagnitude(); + + // Clamp new permanent disposition to avoid negative derived disposition (can be caused by intimidate) + int disposition = std::clamp(mOriginalDisposition + mPermanentDispositionChange, -zero, 100 - zero); npcStats.setBaseDisposition(disposition); } mPermanentDispositionChange = 0; diff --git a/apps/openmw/mwgui/containeritemmodel.cpp b/apps/openmw/mwgui/containeritemmodel.cpp index 09b66672ba..ff50431d86 100644 --- a/apps/openmw/mwgui/containeritemmodel.cpp +++ b/apps/openmw/mwgui/containeritemmodel.cpp @@ -224,7 +224,7 @@ namespace MWGui if (target.getType() != ESM::Container::sRecordId) return true; - // check container organic flag + // Check container organic flag MWWorld::LiveCellRef* ref = target.get(); if (ref->mBase->mFlags & ESM::Container::Organic) { @@ -232,9 +232,18 @@ namespace MWGui return false; } - // check that we don't exceed container capacity - float weight = item.getClass().getWeight(item) * count; - if (target.getClass().getCapacity(target) < target.getClass().getEncumbrance(target) + weight) + // Check for container without capacity + float capacity = target.getClass().getCapacity(target); + if (capacity <= 0.0f) + { + MWBase::Environment::get().getWindowManager()->messageBox("#{sContentsMessage3}"); + return false; + } + + // Check the container capacity plus one increment so the expected total weight can + // fit in the container with floating-point imprecision + float newEncumbrance = target.getClass().getEncumbrance(target) + (item.getClass().getWeight(item) * count); + if (std::nextafterf(capacity, std::numeric_limits::max()) < newEncumbrance) { MWBase::Environment::get().getWindowManager()->messageBox("#{sContentsMessage3}"); return false; diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index dcd9d1dc74..06490501c3 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -97,7 +97,7 @@ namespace MWGui , mPendingControllerAction(ControllerAction::None) { mPreviewTexture - = std::make_unique(mPreview->getTexture(), mPreview->getTextureStateSet()); + = std::make_unique(mPreview->getTexture(), mPreview->getTextureStateSet()); mPreview->rebuild(); mMainWidget->castType()->eventWindowChangeCoord @@ -646,24 +646,37 @@ namespace MWGui } std::unique_ptr action = ptr.getClass().use(ptr, force); + + MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr); + auto [eqSlots, canStack] = ptr.getClass().getEquipmentSlots(ptr); + bool isFromDragAndDrop = mDragAndDrop->mItem.mBase == ptr; + int useCount = isFromDragAndDrop ? mDragAndDrop->mDraggedCount : ptr.getCellRef().getCount(); + + if (!eqSlots.empty()) + { + MWWorld::ContainerStoreIterator it = invStore.getSlot(eqSlots.front()); + if (it != invStore.end() && it->getCellRef().getRefId() == ptr.getCellRef().getRefId()) + useCount += it->getCellRef().getCount(); + } + action->execute(player, !canEquip); - // Handles partial equipping (final part) - if (mEquippedStackableCount.has_value()) - { - // the count to unequip - int count = ptr.getCellRef().getCount() - mDragAndDrop->mDraggedCount - mEquippedStackableCount.value(); - if (count > 0) - { - MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr); - invStore.unequipItemQuantity(ptr, count); - updateItemView(); - } - mEquippedStackableCount.reset(); - } + // Partial equipping + int excess = ptr.getCellRef().getCount() - useCount; + if (excess > 0 && canStack) + invStore.unequipItemQuantity(ptr, excess); if (isVisible()) { + if (isFromDragAndDrop) + { + // Feature: Don't stop draganddrop if potion or ingredient was used + if (ptr.getType() != ESM::Potion::sRecordId && ptr.getType() != ESM::Ingredient::sRecordId) + mDragAndDrop->finish(); + else + mDragAndDrop->update(); + } + mItemView->update(); notifyContentChanged(); @@ -685,8 +698,6 @@ namespace MWGui return; } - mDragAndDrop->finish(); - if (mDragAndDrop->mSourceModel != mTradeModel) { // Move item to the player's inventory @@ -694,33 +705,7 @@ namespace MWGui mDragAndDrop->mItem, mDragAndDrop->mDraggedCount, mTradeModel); } - // Handles partial equipping - mEquippedStackableCount.reset(); - const auto slots = ptr.getClass().getEquipmentSlots(ptr); - if (!slots.first.empty() && slots.second) - { - MWWorld::InventoryStore& invStore = mPtr.getClass().getInventoryStore(mPtr); - MWWorld::ConstContainerStoreIterator slotIt = invStore.getSlot(slots.first.front()); - - // Save the currently equipped count before useItem() - if (slotIt != invStore.end() && slotIt->getCellRef().getRefId() == ptr.getCellRef().getRefId()) - mEquippedStackableCount = slotIt->getCellRef().getCount(); - else - mEquippedStackableCount = 0; - } - MWBase::Environment::get().getLuaManager()->useItem(ptr, MWMechanics::getPlayer(), false); - - // If item is ingredient or potion don't stop drag and drop to simplify action of taking more than one 1 - // item - if ((ptr.getType() == ESM::Potion::sRecordId || ptr.getType() == ESM::Ingredient::sRecordId) - && mDragAndDrop->mDraggedCount > 1) - { - // Item can be provided from other window for example container. - // But after DragAndDrop::startDrag item automaticly always gets to player inventory. - mSelectedItem = getModel()->getIndex(mDragAndDrop->mItem); - dragItem(nullptr, mDragAndDrop->mDraggedCount - 1); - } } else { diff --git a/apps/openmw/mwgui/inventorywindow.hpp b/apps/openmw/mwgui/inventorywindow.hpp index d2272ec775..bbef1e2380 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -89,7 +89,6 @@ namespace MWGui Misc::NotNullPtr mItemTransfer; int mSelectedItem; - std::optional mEquippedStackableCount; MWWorld::Ptr mPtr; diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 263e676e15..8322ae9073 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -294,7 +294,7 @@ namespace MWGui if (!mGuiTexture.get()) { - mGuiTexture = std::make_unique(mTexture); + mGuiTexture = std::make_unique(mTexture); } if (!mCopyFramebufferToTextureCallback) diff --git a/apps/openmw/mwgui/mapwindow.cpp b/apps/openmw/mwgui/mapwindow.cpp index 5b0e5dc7cc..7dc1fdaf15 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -600,27 +600,27 @@ namespace MWGui osg::ref_ptr texture = mLocalMapRender->getMapTexture(entry.mCellX, entry.mCellY); if (texture) { - entry.mMapTexture = std::make_unique(texture); + entry.mMapTexture = std::make_unique(texture); entry.mMapWidget->setRenderItemTexture(entry.mMapTexture.get()); entry.mMapWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); needRedraw = true; } else - entry.mMapTexture = std::make_unique(std::string(), nullptr); + entry.mMapTexture = std::make_unique(std::string(), nullptr); } if (!entry.mFogTexture && mFogOfWarToggled && mFogOfWarEnabled) { osg::ref_ptr tex = mLocalMapRender->getFogOfWarTexture(entry.mCellX, entry.mCellY); if (tex) { - entry.mFogTexture = std::make_unique(tex); + entry.mFogTexture = std::make_unique(tex); entry.mFogWidget->setRenderItemTexture(entry.mFogTexture.get()); entry.mFogWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); } else { entry.mFogWidget->setImageTexture("black"); - entry.mFogTexture = std::make_unique(std::string(), nullptr); + entry.mFogTexture = std::make_unique(std::string(), nullptr); } needRedraw = true; } @@ -1306,11 +1306,12 @@ namespace MWGui { if (!mGlobalMapTexture.get()) { - mGlobalMapTexture = std::make_unique(mGlobalMapRender->getBaseTexture()); + mGlobalMapTexture = std::make_unique(mGlobalMapRender->getBaseTexture()); mGlobalMapImage->setRenderItemTexture(mGlobalMapTexture.get()); mGlobalMapImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); - mGlobalMapOverlayTexture = std::make_unique(mGlobalMapRender->getOverlayTexture()); + mGlobalMapOverlayTexture + = std::make_unique(mGlobalMapRender->getOverlayTexture()); mGlobalMapOverlay->setRenderItemTexture(mGlobalMapOverlayTexture.get()); mGlobalMapOverlay->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); diff --git a/apps/openmw/mwgui/postprocessorhud.cpp b/apps/openmw/mwgui/postprocessorhud.cpp index cc95203a0f..4513bea9da 100644 --- a/apps/openmw/mwgui/postprocessorhud.cpp +++ b/apps/openmw/mwgui/postprocessorhud.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -35,9 +36,9 @@ namespace MWGui { namespace { - std::shared_ptr& getTechnique(const MyGUI::ListBox& list, size_t selected) + std::shared_ptr& getTechnique(const MyGUI::ListBox& list, size_t selected) { - return *list.getItemDataAt>(selected); + return *list.getItemDataAt>(selected); } } @@ -50,8 +51,9 @@ namespace MWGui MyGUI::ListBox::onKeyButtonPressed(key, ch); } - PostProcessorHud::PostProcessorHud() + PostProcessorHud::PostProcessorHud(Files::ConfigurationManager& cfgMgr) : WindowBase("openmw_postprocessor_hud.layout") + , mCfgMgr(cfgMgr) { getWidget(mActiveList, "ActiveList"); getWidget(mInactiveList, "InactiveList"); @@ -110,7 +112,7 @@ namespace MWGui { for (size_t i = 1; i < mConfigArea->getChildCount(); ++i) { - if (auto* child = dynamic_cast(mConfigArea->getChildAt(i))) + if (auto* child = dynamic_cast(mConfigArea->getChildAt(i))) child->toDefault(); } } @@ -243,6 +245,8 @@ namespace MWGui void PostProcessorHud::onClose() { + Settings::ShaderManager::get().save(); + Settings::Manager::saveUser(mCfgMgr.getUserConfigPath() / "settings.cfg"); toggleMode(Settings::ShaderManager::Mode::Normal); } @@ -309,7 +313,7 @@ namespace MWGui auto technique = processor->loadTechnique(path); - if (technique->getStatus() == fx::Technique::Status::File_Not_exists) + if (technique->getStatus() == Fx::Technique::Status::File_Not_exists) return; while (mConfigArea->getChildCount() > 0) @@ -330,15 +334,15 @@ namespace MWGui const auto flags = technique->getFlags(); - const auto flag_interior = serializeBool(!(flags & fx::Technique::Flag_Disable_Interiors)); - const auto flag_exterior = serializeBool(!(flags & fx::Technique::Flag_Disable_Exteriors)); - const auto flag_underwater = serializeBool(!(flags & fx::Technique::Flag_Disable_Underwater)); - const auto flag_abovewater = serializeBool(!(flags & fx::Technique::Flag_Disable_Abovewater)); + const auto flag_interior = serializeBool(!(flags & Fx::Technique::Flag_Disable_Interiors)); + const auto flag_exterior = serializeBool(!(flags & Fx::Technique::Flag_Disable_Exteriors)); + const auto flag_underwater = serializeBool(!(flags & Fx::Technique::Flag_Disable_Underwater)); + const auto flag_abovewater = serializeBool(!(flags & Fx::Technique::Flag_Disable_Abovewater)); switch (technique->getStatus()) { - case fx::Technique::Status::Success: - case fx::Technique::Status::Uncompiled: + case Fx::Technique::Status::Success: + case Fx::Technique::Status::Uncompiled: { if (technique->getDynamic()) ss << "#{fontcolourhtml=header}#{OMWShaders:ShaderLocked}: #{fontcolourhtml=normal} " @@ -360,13 +364,13 @@ namespace MWGui << flag_abovewater; break; } - case fx::Technique::Status::Parse_Error: + case Fx::Technique::Status::Parse_Error: ss << "#{fontcolourhtml=negative}Shader Compile Error: #{fontcolourhtml=normal} <" << std::string(technique->getName()) << "> failed to compile." << endl << endl << technique->getLastError(); break; - case fx::Technique::Status::File_Not_exists: + case Fx::Technique::Status::File_Not_exists: break; } @@ -398,7 +402,7 @@ namespace MWGui divider->setCaptionWithReplacing(uniform->mHeader); } - fx::Widgets::UniformBase* uwidget = mConfigArea->createWidget( + Fx::Widgets::UniformBase* uwidget = mConfigArea->createWidget( "MW_UniformEdit", { 0, 0, 0, 22 }, MyGUI::Align::Default); uwidget->init(uniform); uwidget->getLabel()->eventMouseWheel += MyGUI::newDelegate(this, &PostProcessorHud::notifyMouseWheel); @@ -489,14 +493,14 @@ namespace MWGui void PostProcessorHud::registerMyGUIComponents() { MyGUI::FactoryManager& factory = MyGUI::FactoryManager::getInstance(); - factory.registerFactory("Widget"); - factory.registerFactory("Widget"); - factory.registerFactory("Widget"); - factory.registerFactory("Widget"); - factory.registerFactory("Widget"); - factory.registerFactory("Widget"); - factory.registerFactory("Widget"); - factory.registerFactory("Widget"); + factory.registerFactory("Widget"); + factory.registerFactory("Widget"); + factory.registerFactory("Widget"); + factory.registerFactory("Widget"); + factory.registerFactory("Widget"); + factory.registerFactory("Widget"); + factory.registerFactory("Widget"); + factory.registerFactory("Widget"); factory.registerFactory("Widget"); } } diff --git a/apps/openmw/mwgui/postprocessorhud.hpp b/apps/openmw/mwgui/postprocessorhud.hpp index 0028999966..b5cf2495a6 100644 --- a/apps/openmw/mwgui/postprocessorhud.hpp +++ b/apps/openmw/mwgui/postprocessorhud.hpp @@ -5,6 +5,7 @@ #include +#include #include #include @@ -32,7 +33,7 @@ namespace MWGui }; public: - PostProcessorHud(); + PostProcessorHud(Files::ConfigurationManager& cfgMgr); void onOpen() override; @@ -99,6 +100,8 @@ namespace MWGui std::string mOverrideHint; int mOffset = 0; + + Files::ConfigurationManager& mCfgMgr; }; } diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index fdc8725fa0..f1843fb4d7 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -161,7 +161,7 @@ namespace MWGui mPreview->setAngle(mCurrentAngle); mPreviewTexture - = std::make_unique(mPreview->getTexture(), mPreview->getTextureStateSet()); + = std::make_unique(mPreview->getTexture(), mPreview->getTextureStateSet()); mPreviewImage->setRenderItemTexture(mPreviewTexture.get()); mPreviewImage->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f)); diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 35a6de2950..afe18455b5 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -522,7 +522,7 @@ namespace MWGui texture->setResizeNonPowerOfTwoHint(false); texture->setUnRefImageDataAfterApply(true); - mScreenshotTexture = std::make_unique(texture); + mScreenshotTexture = std::make_unique(texture); mScreenshot->setRenderItemTexture(mScreenshotTexture.get()); } diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 11a06c7b44..b1d69966ad 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include "../mwbase/soundmanager.hpp" #include "../mwbase/windowmanager.hpp" #include "../mwbase/world.hpp" +#include "../mwlua/luamanagerimp.hpp" #include "confirmationdialog.hpp" @@ -247,10 +249,11 @@ namespace MWGui } } - SettingsWindow::SettingsWindow() + SettingsWindow::SettingsWindow(Files::ConfigurationManager& cfgMgr) : WindowBase("openmw_settings_window.layout") , mKeyboardMode(true) , mCurrentPage(-1) + , mCfgMgr(cfgMgr) { const bool terrain = Settings::terrain().mDistantTerrain; const std::string_view widgetName = terrain ? "RenderingDistanceSlider" : "LargeRenderingDistanceSlider"; @@ -1096,6 +1099,14 @@ namespace MWGui MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mOkButton); } + void SettingsWindow::onClose() + { + // Save user settings + Settings::Manager::saveUser(mCfgMgr.getUserConfigPath() / "settings.cfg"); + MWBase::Environment::get().getLuaManager()->savePermanentStorage(mCfgMgr.getUserConfigPath()); + MWBase::Environment::get().getInputManager()->saveBindings(); + } + void SettingsWindow::onWindowResize(MyGUI::Window* _sender) { layoutControlsBox(); diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 555468d806..0cc1c13fb4 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -1,6 +1,7 @@ #ifndef MWGUI_SETTINGS_H #define MWGUI_SETTINGS_H +#include #include #include "windowbase.hpp" @@ -10,10 +11,12 @@ namespace MWGui class SettingsWindow : public WindowBase { public: - SettingsWindow(); + SettingsWindow(Files::ConfigurationManager& cfgMgr); void onOpen() override; + void onClose() override; + void onFrame(float duration) override; void updateControlsBox(); @@ -122,6 +125,7 @@ namespace MWGui private: void resetScrollbars(); + Files::ConfigurationManager& mCfgMgr; }; } diff --git a/apps/openmw/mwgui/videowidget.cpp b/apps/openmw/mwgui/videowidget.cpp index a82d8ce67f..0fc555ab27 100644 --- a/apps/openmw/mwgui/videowidget.cpp +++ b/apps/openmw/mwgui/videowidget.cpp @@ -50,7 +50,7 @@ namespace MWGui if (!texture) return; - mTexture = std::make_unique(texture); + mTexture = std::make_unique(texture); setRenderItemTexture(mTexture.get()); getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f)); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 8073db875a..c5804a7858 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -207,7 +207,7 @@ namespace MWGui SDL_GL_GetDrawableSize(window, &dw, &dh); mScalingFactor = Settings::gui().mScalingFactor * (dw / w); - mGuiPlatform = std::make_unique(viewer, guiRoot, resourceSystem->getImageManager(), + mGuiPlatform = std::make_unique(viewer, guiRoot, resourceSystem->getImageManager(), resourceSystem->getVFS(), mScalingFactor, "mygui", logpath / "MyGUI.log"); mGui = std::make_unique(); @@ -231,8 +231,8 @@ namespace MWGui MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); - MyGUI::FactoryManager::getInstance().registerFactory("Layer"); - MyGUI::FactoryManager::getInstance().registerFactory("Layer"); + MyGUI::FactoryManager::getInstance().registerFactory("Layer"); + MyGUI::FactoryManager::getInstance().registerFactory("Layer"); BookPage::registerMyGUIComponents(); PostProcessorHud::registerMyGUIComponents(); ItemView::registerComponents(); @@ -411,7 +411,7 @@ namespace MWGui mCountDialog = countDialog.get(); mWindows.push_back(std::move(countDialog)); - auto settingsWindow = std::make_unique(); + auto settingsWindow = std::make_unique(mCfgMgr); mSettingsWindow = settingsWindow.get(); mWindows.push_back(std::move(settingsWindow)); trackWindow(mSettingsWindow, makeSettingsWindowSettingValues()); @@ -505,7 +505,7 @@ namespace MWGui mWindows.push_back(std::move(debugWindow)); trackWindow(mDebugWindow, makeDebugWindowSettingValues()); - auto postProcessorHud = std::make_unique(); + auto postProcessorHud = std::make_unique(mCfgMgr); mPostProcessorHud = postProcessorHud.get(); mWindows.push_back(std::move(postProcessorHud)); trackWindow(mPostProcessorHud, makePostprocessorWindowSettingValues()); @@ -1252,7 +1252,7 @@ namespace MWGui std::vector split; Misc::StringUtils::split(tag, split, ":"); - l10n::Manager& l10nManager = *MWBase::Environment::get().getL10nManager(); + L10n::Manager& l10nManager = *MWBase::Environment::get().getL10nManager(); // If a key has a "Context:KeyName" format, use YAML to translate data if (split.size() == 2) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 1d2ee6a6d4..06360dd9f2 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -416,7 +416,7 @@ namespace MWGui Resource::ResourceSystem* mResourceSystem; osg::ref_ptr mWorkQueue; - std::unique_ptr mGuiPlatform; + std::unique_ptr mGuiPlatform; osgViewer::Viewer* mViewer; std::unique_ptr mFontLoader; diff --git a/apps/openmw/mwinput/bindingsmanager.cpp b/apps/openmw/mwinput/bindingsmanager.cpp index 339ebf4276..22322014d4 100644 --- a/apps/openmw/mwinput/bindingsmanager.cpp +++ b/apps/openmw/mwinput/bindingsmanager.cpp @@ -196,23 +196,7 @@ namespace MWInput BindingsManager::~BindingsManager() { - const std::string newFileName = Files::pathToUnicodeString(mUserFile) + ".new"; - try - { - if (mInputBinder->save(newFileName)) - { - std::filesystem::rename(Files::pathFromUnicodeString(newFileName), mUserFile); - Log(Debug::Info) << "Saved input bindings: " << mUserFile; - } - else - { - Log(Debug::Error) << "Failed to save input bindings to " << newFileName; - } - } - catch (const std::exception& e) - { - Log(Debug::Error) << "Failed to save input bindings to " << newFileName << ": " << e.what(); - } + saveBindings(); } void BindingsManager::update(float dt) @@ -715,4 +699,25 @@ namespace MWInput if (previousValue <= 0.6 && currentValue > 0.6) manager->executeAction(action); } + + void BindingsManager::saveBindings() + { + const std::string newFileName = Files::pathToUnicodeString(mUserFile) + ".new"; + try + { + if (mInputBinder->save(newFileName)) + { + std::filesystem::rename(Files::pathFromUnicodeString(newFileName), mUserFile); + Log(Debug::Info) << "Saved input bindings: " << mUserFile; + } + else + { + Log(Debug::Error) << "Failed to save input bindings to " << newFileName; + } + } + catch (const std::exception& e) + { + Log(Debug::Error) << "Failed to save input bindings to " << newFileName << ": " << e.what(); + } + } } diff --git a/apps/openmw/mwinput/bindingsmanager.hpp b/apps/openmw/mwinput/bindingsmanager.hpp index bee9e07cf7..40c2076d3c 100644 --- a/apps/openmw/mwinput/bindingsmanager.hpp +++ b/apps/openmw/mwinput/bindingsmanager.hpp @@ -65,6 +65,8 @@ namespace MWInput void actionValueChanged(int action, float currentValue, float previousValue); + void saveBindings(); + private: void setupSDLKeyMappings(); diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 7a82c96d09..250b25aeaa 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -263,4 +263,9 @@ namespace MWInput { mActionManager->executeAction(action); } + + void InputManager::saveBindings() + { + mBindingsManager->saveBindings(); + } } diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 27a938f1ea..3e964ae2a8 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -109,6 +109,8 @@ namespace MWInput private: bool mControlsDisabled; + void saveBindings() override; + std::unique_ptr mInputWrapper; std::unique_ptr mBindingsManager; std::unique_ptr mControlSwitch; diff --git a/apps/openmw/mwlua/luamanagerimp.hpp b/apps/openmw/mwlua/luamanagerimp.hpp index 3f2135e9c9..9877c98fb9 100644 --- a/apps/openmw/mwlua/luamanagerimp.hpp +++ b/apps/openmw/mwlua/luamanagerimp.hpp @@ -43,7 +43,7 @@ namespace MWLua void init(); void loadPermanentStorage(const std::filesystem::path& userConfigPath); - void savePermanentStorage(const std::filesystem::path& userConfigPath); + void savePermanentStorage(const std::filesystem::path& userConfigPath) override; // \brief Executes lua handlers. Defaults to running in parallel with OSG Cull. // diff --git a/apps/openmw/mwlua/postprocessingbindings.cpp b/apps/openmw/mwlua/postprocessingbindings.cpp index 6127cb4b27..f12bda8650 100644 --- a/apps/openmw/mwlua/postprocessingbindings.cpp +++ b/apps/openmw/mwlua/postprocessingbindings.cpp @@ -35,9 +35,9 @@ namespace MWLua { struct Shader { - std::shared_ptr mShader; + std::shared_ptr mShader; - Shader(std::shared_ptr shader) + Shader(std::shared_ptr shader) : mShader(std::move(shader)) { } diff --git a/apps/openmw/mwmechanics/actor.hpp b/apps/openmw/mwmechanics/actor.hpp index d7438712d9..69e370ec86 100644 --- a/apps/openmw/mwmechanics/actor.hpp +++ b/apps/openmw/mwmechanics/actor.hpp @@ -28,7 +28,7 @@ namespace MWMechanics class Actor { public: - Actor(const MWWorld::Ptr& ptr, MWRender::Animation* animation) + Actor(const MWWorld::Ptr& ptr, MWRender::Animation& animation) : mCharacterController(ptr, animation) , mPositionAdjusted(ptr.getClass().getCreatureStats(ptr).getFallHeight() > 0) { @@ -62,14 +62,22 @@ namespace MWMechanics void setPositionAdjusted(bool adjusted) { mPositionAdjusted = adjusted; } bool getPositionAdjusted() const { return mPositionAdjusted; } + void invalidate() + { + mInvalid = true; + mCharacterController.detachAnimation(); + } + bool isInvalid() const { return mInvalid; } + private: CharacterController mCharacterController; int mGreetingTimer{ 0 }; float mTargetAngleRadians{ 0.f }; GreetingState mGreetingState{ Greet_None }; - bool mIsTurningToPlayer{ false }; Misc::DeviatingPeriodicTimer mEngageCombat{ 1.0f, 0.25f, Misc::Rng::deviate(0, 0.25f, MWBase::Environment::get().getWorld()->getPrng()) }; + bool mIsTurningToPlayer{ false }; + bool mInvalid{ false }; bool mPositionAdjusted; }; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 65eb71232f..3ba6bfdc8d 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -122,6 +122,8 @@ namespace { for (const MWMechanics::Actor& actor : actors) { + if (actor.isInvalid()) + continue; const MWWorld::Ptr& iteratedActor = actor.getPtr(); if (iteratedActor == player || iteratedActor == actorPtr) continue; @@ -345,7 +347,7 @@ namespace MWMechanics // Find something nearby. for (const Actor& otherActor : actors) { - if (otherActor.getPtr() == ptr) + if (otherActor.isInvalid() || otherActor.getPtr() == ptr) continue; updateHeadTracking( @@ -681,7 +683,7 @@ namespace MWMechanics } } - if (creatureStats2.getMagicEffects().getOrDefault(ESM::MagicEffect::Invisibility).getMagnitude() > 0) + if (isTargetMagicallyHidden(actor2)) return; // Stop here if target is unreachable @@ -1195,7 +1197,7 @@ namespace MWMechanics MWRender::Animation* anim = MWBase::Environment::get().getWorld()->getAnimation(ptr); if (!anim) return; - const auto it = mActors.emplace(mActors.end(), ptr, anim); + const auto it = mActors.emplace(mActors.end(), ptr, *anim); mIndex.emplace(ptr.mRef, it); if (updateImmediately) @@ -1247,7 +1249,7 @@ namespace MWMechanics { if (!keepActive) removeTemporaryEffects(iter->second->getPtr()); - mActors.erase(iter->second); + iter->second->invalidate(); mIndex.erase(iter); } } @@ -1299,16 +1301,15 @@ namespace MWMechanics void Actors::dropActors(const MWWorld::CellStore* cellStore, const MWWorld::Ptr& ignore) { - for (auto iter = mActors.begin(); iter != mActors.end();) + for (Actor& actor : mActors) { - if ((iter->getPtr().isInCell() && iter->getPtr().getCell() == cellStore) && iter->getPtr() != ignore) + if (!actor.isInvalid() && actor.getPtr().isInCell() && actor.getPtr().getCell() == cellStore + && actor.getPtr() != ignore) { - removeTemporaryEffects(iter->getPtr()); - mIndex.erase(iter->getPtr().mRef); - iter = mActors.erase(iter); + removeTemporaryEffects(actor.getPtr()); + mIndex.erase(actor.getPtr().mRef); + actor.invalidate(); } - else - ++iter; } } @@ -1327,6 +1328,8 @@ namespace MWMechanics const MWBase::World* const world = MWBase::Environment::get().getWorld(); for (const Actor& actor : mActors) { + if (actor.isInvalid()) + continue; const MWWorld::Ptr& ptr = actor.getPtr(); if (ptr == player) continue; // Don't interfere with player controls. @@ -1391,6 +1394,8 @@ namespace MWMechanics // Iterate through all other actors and predict collisions. for (const Actor& otherActor : mActors) { + if (otherActor.isInvalid()) + continue; const MWWorld::Ptr& otherPtr = otherActor.getPtr(); if (otherPtr == ptr || otherPtr == currentTarget) continue; @@ -1509,6 +1514,8 @@ namespace MWMechanics // AI and magic effects update for (Actor& actor : mActors) { + if (actor.isInvalid()) + continue; const bool isPlayer = actor.getPtr() == player; CharacterController& ctrl = actor.getCharacterController(); MWBase::LuaManager::ActorControls* luaControls @@ -1570,6 +1577,8 @@ namespace MWMechanics for (const Actor& otherActor : mActors) { + if (otherActor.isInvalid()) + continue; if (otherActor.getPtr() == actor.getPtr() || isPlayer) // player is not AI-controlled continue; engageCombat( @@ -1627,6 +1636,8 @@ namespace MWMechanics CharacterController* playerCharacter = nullptr; for (Actor& actor : mActors) { + if (actor.isInvalid()) + continue; const float dist = (playerPos - actor.getPtr().getRefData().getPosition().asVec3()).length(); const bool isPlayer = actor.getPtr() == player; CreatureStats& stats = actor.getPtr().getClass().getCreatureStats(actor.getPtr()); @@ -1692,8 +1703,15 @@ namespace MWMechanics luaControls->mJump = false; } - for (const Actor& actor : mActors) + for (auto it = mActors.begin(); it != mActors.end();) { + if (it->isInvalid()) + { + it = mActors.erase(it); + continue; + } + const Actor& actor = *it; + it++; const MWWorld::Class& cls = actor.getPtr().getClass(); CreatureStats& stats = cls.getCreatureStats(actor.getPtr()); @@ -1743,6 +1761,8 @@ namespace MWMechanics { for (Actor& actor : mActors) { + if (actor.isInvalid()) + continue; const MWWorld::Class& cls = actor.getPtr().getClass(); CreatureStats& stats = cls.getCreatureStats(actor.getPtr()); @@ -1830,6 +1850,8 @@ namespace MWMechanics { for (const Actor& actor : mActors) { + if (actor.isInvalid()) + continue; MWMechanics::ActiveSpells& spells = actor.getPtr().getClass().getCreatureStats(actor.getPtr()).getActiveSpells(); spells.purge(actor.getPtr(), casterActorId); @@ -1849,6 +1871,8 @@ namespace MWMechanics for (const Actor& actor : mActors) { + if (actor.isInvalid()) + continue; if (actor.getPtr().getClass().getCreatureStats(actor.getPtr()).isDead()) { adjustMagicEffects(actor.getPtr(), duration); @@ -2046,7 +2070,10 @@ namespace MWMechanics void Actors::persistAnimationStates() const { for (const Actor& actor : mActors) - actor.getCharacterController().persistAnimationState(); + { + if (!actor.isInvalid()) + actor.getCharacterController().persistAnimationState(); + } } void Actors::clearAnimationQueue(const MWWorld::Ptr& ptr, bool clearScripted) @@ -2060,6 +2087,8 @@ namespace MWMechanics { for (const Actor& actor : mActors) { + if (actor.isInvalid()) + continue; if ((actor.getPtr().getRefData().getPosition().asVec3() - position).length2() <= radius * radius) out.push_back(actor.getPtr()); } @@ -2069,6 +2098,8 @@ namespace MWMechanics { for (const Actor& actor : mActors) { + if (actor.isInvalid()) + continue; if ((actor.getPtr().getRefData().getPosition().asVec3() - position).length2() <= radius * radius) return true; } @@ -2082,6 +2113,8 @@ namespace MWMechanics list.push_back(actorPtr); for (const Actor& actor : mActors) { + if (actor.isInvalid()) + continue; const MWWorld::Ptr& iteratedActor = actor.getPtr(); if (iteratedActor == getPlayer()) continue; @@ -2352,10 +2385,11 @@ namespace MWMechanics if (!MWBase::Environment::get().getMechanicsManager()->isAIActive()) return; - for (auto it = mActors.begin(); it != mActors.end();) + for (const Actor& actor : mActors) { - const MWWorld::Ptr ptr = it->getPtr(); - ++it; + if (actor.isInvalid()) + continue; + const MWWorld::Ptr ptr = actor.getPtr(); if (ptr == getPlayer() || !isConscious(ptr) || ptr.getClass().getCreatureStats(ptr).isParalyzed()) continue; MWMechanics::AiSequence& seq = ptr.getClass().getCreatureStats(ptr).getAiSequence(); diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 87cc469eb4..1aac063ce3 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -535,7 +535,7 @@ namespace MWMechanics bool CharacterController::onOpen() const { - if (mPtr.getType() == ESM::Container::sRecordId) + if (mPtr.getType() == ESM::Container::sRecordId && mAnimation) { if (!mAnimation->hasAnimation("containeropen")) return true; @@ -559,7 +559,7 @@ namespace MWMechanics { if (mPtr.getType() == ESM::Container::sRecordId) { - if (!mAnimation->hasAnimation("containerclose")) + if (!mAnimation || !mAnimation->hasAnimation("containerclose")) return; float complete, startPoint = 0.f; @@ -886,11 +886,12 @@ namespace MWMechanics if (mDeathState == CharState_None && MWBase::Environment::get().getWorld()->isSwimming(mPtr)) mDeathState = CharState_SwimDeath; - if (mDeathState == CharState_None || !mAnimation->hasAnimation(deathStateToAnimGroup(mDeathState))) + if (mDeathState == CharState_None + || (mAnimation && !mAnimation->hasAnimation(deathStateToAnimGroup(mDeathState)))) mDeathState = chooseRandomDeathState(); // Do not interrupt scripted animation by death - if (isScriptedAnimPlaying()) + if (!mAnimation || isScriptedAnimPlaying()) return; playDeath(startpoint, mDeathState); @@ -910,13 +911,10 @@ namespace MWMechanics return result; } - CharacterController::CharacterController(const MWWorld::Ptr& ptr, MWRender::Animation* anim) + CharacterController::CharacterController(const MWWorld::Ptr& ptr, MWRender::Animation& anim) : mPtr(ptr) - , mAnimation(anim) + , mAnimation(&anim) { - if (!mAnimation) - return; - mAnimation->setTextKeyListener(this); const MWWorld::Class& cls = mPtr.getClass(); @@ -992,17 +990,25 @@ namespace MWMechanics } CharacterController::~CharacterController() + { + detachAnimation(); + } + + void CharacterController::detachAnimation() { if (mAnimation) { persistAnimationState(); mAnimation->setTextKeyListener(nullptr); + mAnimation = nullptr; } } void CharacterController::handleTextKey( std::string_view groupname, SceneUtil::TextKeyMap::ConstIterator key, const SceneUtil::TextKeyMap& map) { + if (!mAnimation) + return; std::string_view evt = key->second; MWBase::Environment::get().getLuaManager()->animationTextKey(mPtr, key->second); @@ -1232,7 +1238,8 @@ namespace MWMechanics float CharacterController::calculateWindUp() const { - if (mCurrentWeapon.empty() || mWeaponType == ESM::Weapon::PickProbe || isRandomAttackAnimation(mCurrentWeapon)) + if (!mAnimation || mCurrentWeapon.empty() || mWeaponType == ESM::Weapon::PickProbe + || isRandomAttackAnimation(mCurrentWeapon)) return -1.f; float minAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon + ": " + mAttackType + " min attack"); @@ -1950,6 +1957,8 @@ namespace MWMechanics void CharacterController::update(float duration) { + if (!mAnimation) + return; MWBase::World* world = MWBase::Environment::get().getWorld(); MWBase::SoundManager* sndMgr = MWBase::Environment::get().getSoundManager(); const MWWorld::Class& cls = mPtr.getClass(); @@ -2528,7 +2537,7 @@ namespace MWMechanics ESM::AnimationState::ScriptedAnimation anim; anim.mGroup = iter->mGroup; - if (iter == mAnimQueue.begin()) + if (iter == mAnimQueue.begin() && mAnimation) { float complete; size_t loopcount; @@ -2741,23 +2750,18 @@ namespace MWMechanics void CharacterController::clearAnimQueue(bool clearScriptedAnims) { // Do not interrupt scripted animations, if we want to keep them - if ((!isScriptedAnimPlaying() || clearScriptedAnims) && !mAnimQueue.empty()) + if (mAnimation && (!isScriptedAnimPlaying() || clearScriptedAnims) && !mAnimQueue.empty()) mAnimation->disable(mAnimQueue.front().mGroup); if (clearScriptedAnims) { - mAnimation->setPlayScriptedOnly(false); + if (mAnimation) + mAnimation->setPlayScriptedOnly(false); mAnimQueue.clear(); return; } - for (AnimationQueue::iterator it = mAnimQueue.begin(); it != mAnimQueue.end();) - { - if (!it->mScripted) - it = mAnimQueue.erase(it); - else - ++it; - } + std::erase_if(mAnimQueue, [](const AnimationQueueEntry& entry) { return !entry.mScripted; }); } void CharacterController::forceStateUpdate() @@ -2866,6 +2870,8 @@ namespace MWMechanics void CharacterController::setVisibility(float visibility) const { + if (!mAnimation) + return; // We should take actor's invisibility in account if (mPtr.getClass().isActor()) { @@ -2926,7 +2932,7 @@ namespace MWMechanics bool CharacterController::isReadyToBlock() const { - return updateCarriedLeftVisible(mWeaponType); + return mAnimation && updateCarriedLeftVisible(mWeaponType); } bool CharacterController::isKnockedDown() const @@ -3030,7 +3036,8 @@ namespace MWMechanics void CharacterController::setActive(int active) const { - mAnimation->setActive(active); + if (mAnimation) + mAnimation->setActive(active); } void CharacterController::setHeadTrackTarget(const MWWorld::ConstPtr& target) @@ -3061,6 +3068,8 @@ namespace MWMechanics float CharacterController::getAnimationMovementDirection() const { + if (!mAnimation) + return 0.f; switch (mMovementState) { case CharState_RunLeft: @@ -3155,6 +3164,8 @@ namespace MWMechanics MWWorld::MovementDirectionFlags CharacterController::getSupportedMovementDirections() const { + if (!mAnimation) + return 0; using namespace std::string_view_literals; // There are fallbacks in the CharacterController::refreshMovementAnims for certain animations. Arrays below // represent them. diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index d5c642c883..2a1982c664 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -252,13 +252,21 @@ namespace MWMechanics void prepareHit(); + void unpersistAnimationState(); + + void playBlendedAnimation(const std::string& groupname, const MWRender::AnimPriority& priority, int blendMask, + bool autodisable, float speedmult, std::string_view start, std::string_view stop, float startpoint, + uint32_t loops, bool loopfallback = false) const; + public: - CharacterController(const MWWorld::Ptr& ptr, MWRender::Animation* anim); + CharacterController(const MWWorld::Ptr& ptr, MWRender::Animation& anim); virtual ~CharacterController(); CharacterController(const CharacterController&) = delete; CharacterController(CharacterController&&) = delete; + void detachAnimation(); + const MWWorld::Ptr& getPtr() const { return mPtr; } void handleTextKey(std::string_view groupname, SceneUtil::TextKeyMap::ConstIterator key, @@ -275,11 +283,6 @@ namespace MWMechanics void onClose() const; void persistAnimationState() const; - void unpersistAnimationState(); - - void playBlendedAnimation(const std::string& groupname, const MWRender::AnimPriority& priority, int blendMask, - bool autodisable, float speedmult, std::string_view start, std::string_view stop, float startpoint, - uint32_t loops, bool loopfallback = false) const; bool playGroup(std::string_view groupname, int mode, uint32_t count, bool scripted = false); bool playGroupLua(std::string_view groupname, float speed, std::string_view startKey, std::string_view stopKey, uint32_t loops, bool forceLoop); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 384c25953b..c20061d022 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -368,17 +368,28 @@ namespace MWMechanics bool MechanicsManager::isRunning(const MWWorld::Ptr& ptr) { - return mActors.isRunning(ptr); + CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); + if (!stats.getStance(MWMechanics::CreatureStats::Stance_Run)) + return false; + + if (mActors.isRunning(ptr)) + return true; + + MWBase::World* world = MWBase::Environment::get().getWorld(); + return !world->isOnGround(ptr) && !world->isSwimming(ptr) && !world->isFlying(ptr); } bool MechanicsManager::isSneaking(const MWWorld::Ptr& ptr) { CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); + if (!stats.getStance(MWMechanics::CreatureStats::Stance_Sneak)) + return false; + + if (mActors.isSneaking(ptr)) + return true; + MWBase::World* world = MWBase::Environment::get().getWorld(); - bool animActive = mActors.isSneaking(ptr); - bool stanceOn = stats.getStance(MWMechanics::CreatureStats::Stance_Sneak); - bool inair = !world->isOnGround(ptr) && !world->isSwimming(ptr) && !world->isFlying(ptr); - return stanceOn && (animActive || inair); + return !world->isOnGround(ptr) && !world->isSwimming(ptr) && !world->isFlying(ptr); } void MechanicsManager::rest(double hours, bool sleep) @@ -1725,6 +1736,8 @@ namespace MWMechanics .getActorId()); // Stops guard from ending combat if player is unreachable for (const Actor& actor : mActors) { + if (actor.isInvalid()) + continue; if (actor.getPtr().getClass().isClass(actor.getPtr(), "Guard")) { MWMechanics::AiSequence& aiSeq diff --git a/apps/openmw/mwmechanics/objects.cpp b/apps/openmw/mwmechanics/objects.cpp index 12d342666b..62f0df556d 100644 --- a/apps/openmw/mwmechanics/objects.cpp +++ b/apps/openmw/mwmechanics/objects.cpp @@ -20,7 +20,7 @@ namespace MWMechanics if (anim == nullptr) return; - const auto it = mObjects.emplace(mObjects.end(), ptr, anim); + const auto it = mObjects.emplace(mObjects.end(), ptr, *anim); mIndex.emplace(ptr.mRef, it); } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 1b5bc6b660..807f785b1b 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -154,7 +154,7 @@ namespace MWRender float mLoopStopTime = 0; float mStopTime = 0; - std::shared_ptr mTime = std::make_shared(0); + std::shared_ptr mTime = std::make_shared(0.0f); float mSpeedMult = 1; bool mPlaying = false; diff --git a/apps/openmw/mwrender/pathgrid.cpp b/apps/openmw/mwrender/pathgrid.cpp index a39ba86a60..137a781342 100644 --- a/apps/openmw/mwrender/pathgrid.cpp +++ b/apps/openmw/mwrender/pathgrid.cpp @@ -58,8 +58,6 @@ namespace MWRender default: return false; } - - return false; } void Pathgrid::addCell(const MWWorld::CellStore* store) diff --git a/apps/openmw/mwrender/pingpongcanvas.cpp b/apps/openmw/mwrender/pingpongcanvas.cpp index 5a37e09d84..a289272d1b 100644 --- a/apps/openmw/mwrender/pingpongcanvas.cpp +++ b/apps/openmw/mwrender/pingpongcanvas.cpp @@ -46,7 +46,7 @@ namespace MWRender mMultiviewResolveStateSet->addUniform(new osg::Uniform("lastShader", 0)); } - void PingPongCanvas::setPasses(fx::DispatchArray&& passes) + void PingPongCanvas::setPasses(Fx::DispatchArray&& passes) { mPasses = std::move(passes); } @@ -54,8 +54,8 @@ namespace MWRender void PingPongCanvas::setMask(bool underwater, bool exterior) { mMask = 0; - mMask |= underwater ? fx::Technique::Flag_Disable_Underwater : fx::Technique::Flag_Disable_Abovewater; - mMask |= exterior ? fx::Technique::Flag_Disable_Exteriors : fx::Technique::Flag_Disable_Interiors; + mMask |= underwater ? Fx::Technique::Flag_Disable_Underwater : Fx::Technique::Flag_Disable_Abovewater; + mMask |= exterior ? Fx::Technique::Flag_Disable_Exteriors : Fx::Technique::Flag_Disable_Interiors; } void PingPongCanvas::drawGeometry(osg::RenderInfo& renderInfo) const diff --git a/apps/openmw/mwrender/pingpongcanvas.hpp b/apps/openmw/mwrender/pingpongcanvas.hpp index 5a37b7fbc9..f5bfcb6ffe 100644 --- a/apps/openmw/mwrender/pingpongcanvas.hpp +++ b/apps/openmw/mwrender/pingpongcanvas.hpp @@ -31,14 +31,14 @@ namespace MWRender void dirty() { mDirty = true; } - void setDirtyAttachments(const std::vector& attachments) + void setDirtyAttachments(const std::vector& attachments) { mDirtyAttachments = attachments; } - const fx::DispatchArray& getPasses() { return mPasses; } + const Fx::DispatchArray& getPasses() { return mPasses; } - void setPasses(fx::DispatchArray&& passes); + void setPasses(Fx::DispatchArray&& passes); void setMask(bool underwater, bool exterior); @@ -60,8 +60,8 @@ namespace MWRender bool mAvgLum = false; bool mPostprocessing = false; - fx::DispatchArray mPasses; - fx::FlagsType mMask = 0; + Fx::DispatchArray mPasses; + Fx::FlagsType mMask = 0; osg::ref_ptr mFallbackProgram; osg::ref_ptr mMultiviewResolveProgram; @@ -74,7 +74,7 @@ namespace MWRender osg::ref_ptr mTextureDistortion; mutable bool mDirty = false; - mutable std::vector mDirtyAttachments; + mutable std::vector mDirtyAttachments; mutable osg::ref_ptr mRenderViewport; mutable osg::ref_ptr mMultiviewResolveFramebuffer; mutable osg::ref_ptr mDestinationFBO; diff --git a/apps/openmw/mwrender/postprocessor.cpp b/apps/openmw/mwrender/postprocessor.cpp index d941e5daff..365429a4a8 100644 --- a/apps/openmw/mwrender/postprocessor.cpp +++ b/apps/openmw/mwrender/postprocessor.cpp @@ -207,7 +207,7 @@ namespace MWRender mGLSLVersion = ext->glslLanguageVersion * 100; mUBO = ext->isUniformBufferObjectSupported && mGLSLVersion >= 330; - mStateUpdater = new fx::StateUpdater(mUBO); + mStateUpdater = new Fx::StateUpdater(mUBO); addChild(mHUDCamera); addChild(mRootNode); @@ -251,10 +251,10 @@ namespace MWRender void PostProcessor::populateTechniqueFiles() { - for (const auto& path : mVFS->getRecursiveDirectoryIterator(fx::Technique::sSubdir)) + for (const auto& path : mVFS->getRecursiveDirectoryIterator(Fx::Technique::sSubdir)) { std::string_view fileExt = Misc::getFileExtension(path); - if (path.parent().parent().empty() && fileExt == fx::Technique::sExt) + if (path.parent().parent().empty() && fileExt == Fx::Technique::sExt) { mTechniqueFiles.emplace(path); } @@ -347,7 +347,7 @@ namespace MWRender for (auto& technique : mTechniques) { - if (technique->getStatus() == fx::Technique::Status::File_Not_exists) + if (technique->getStatus() == Fx::Technique::Status::File_Not_exists) continue; const auto lastWriteTime = mVFS->getLastModified(technique->getFileName()); @@ -400,7 +400,7 @@ namespace MWRender createObjectsForFrame(frameId); mDirty = false; - mCanvases[frameId]->setPasses(fx::DispatchArray(mTemplateData)); + mCanvases[frameId]->setPasses(Fx::DispatchArray(mTemplateData)); } if ((mNormalsSupported && mNormals != mPrevNormals) || (mPassLights != mPrevPassLights)) @@ -565,7 +565,7 @@ namespace MWRender mNormals = false; mPassLights = false; - std::vector attachmentsToDirty; + std::vector attachmentsToDirty; for (const auto& technique : mTechniques) { @@ -579,7 +579,7 @@ namespace MWRender continue; } - fx::DispatchNode node; + Fx::DispatchNode node; node.mFlags = technique->getFlags(); @@ -592,7 +592,7 @@ namespace MWRender if (technique->getLights()) mPassLights = true; - if (node.mFlags & fx::Technique::Flag_Disable_SunGlare) + if (node.mFlags & Fx::Technique::Flag_Disable_SunGlare) sunglare = false; // required default samplers available to every shader pass @@ -638,7 +638,7 @@ namespace MWRender for (const auto& pass : technique->getPasses()) { int subTexUnit = texUnit; - fx::DispatchNode::SubPass subPass; + Fx::DispatchNode::SubPass subPass; pass->prepareStateSet(subPass.mStateSet, technique->getName()); @@ -673,7 +673,7 @@ namespace MWRender [renderTarget](const auto& rt) { return renderTarget.mTarget == rt.mTarget; }) == attachmentsToDirty.cend()) { - attachmentsToDirty.push_back(fx::Types::RenderTarget(renderTarget)); + attachmentsToDirty.push_back(Fx::Types::RenderTarget(renderTarget)); } } @@ -692,7 +692,7 @@ namespace MWRender [renderTarget](const auto& rt) { return renderTarget.mTarget == rt.mTarget; }) == attachmentsToDirty.cend()) { - attachmentsToDirty.push_back(fx::Types::RenderTarget(renderTarget)); + attachmentsToDirty.push_back(Fx::Types::RenderTarget(renderTarget)); } subTexUnit++; } @@ -705,7 +705,7 @@ namespace MWRender mTemplateData.emplace_back(std::move(node)); } - mCanvases[frameId]->setPasses(fx::DispatchArray(mTemplateData)); + mCanvases[frameId]->setPasses(Fx::DispatchArray(mTemplateData)); if (auto hud = MWBase::Environment::get().getWindowManager()->getPostProcessorHud()) hud->updateTechniques(); @@ -717,7 +717,7 @@ namespace MWRender } PostProcessor::Status PostProcessor::enableTechnique( - std::shared_ptr technique, std::optional location) + std::shared_ptr technique, std::optional location) { if (technique->getLocked() || (location.has_value() && location.value() < 0)) return Status_Error; @@ -732,7 +732,7 @@ namespace MWRender return Status_Toggled; } - PostProcessor::Status PostProcessor::disableTechnique(std::shared_ptr technique, bool dirty) + PostProcessor::Status PostProcessor::disableTechnique(std::shared_ptr technique, bool dirty) { if (technique->getLocked()) return Status_Error; @@ -748,7 +748,7 @@ namespace MWRender return Status_Toggled; } - bool PostProcessor::isTechniqueEnabled(const std::shared_ptr& technique) const + bool PostProcessor::isTechniqueEnabled(const std::shared_ptr& technique) const { if (auto it = std::find(mTechniques.begin(), mTechniques.end(), technique); it == mTechniques.end()) return false; @@ -756,13 +756,13 @@ namespace MWRender return technique->isValid(); } - std::shared_ptr PostProcessor::loadTechnique(std::string_view name, bool loadNextFrame) + std::shared_ptr PostProcessor::loadTechnique(std::string_view name, bool loadNextFrame) { - VFS::Path::Normalized path = fx::Technique::makeFileName(name); + VFS::Path::Normalized path = Fx::Technique::makeFileName(name); return loadTechnique(VFS::Path::NormalizedView(path), loadNextFrame); } - std::shared_ptr PostProcessor::loadTechnique(VFS::Path::NormalizedView path, bool loadNextFrame) + std::shared_ptr PostProcessor::loadTechnique(VFS::Path::NormalizedView path, bool loadNextFrame) { for (const auto& technique : mTemplates) if (technique->getFileName() == path) @@ -778,12 +778,12 @@ namespace MWRender else name = path.stem(); - auto technique = std::make_shared(*mVFS, *mRendering.getResourceSystem()->getImageManager(), + auto technique = std::make_shared(*mVFS, *mRendering.getResourceSystem()->getImageManager(), path, std::move(name), renderWidth(), renderHeight(), mUBO, mNormalsSupported); technique->compile(); - if (technique->getStatus() != fx::Technique::Status::File_Not_exists) + if (technique->getStatus() != Fx::Technique::Status::File_Not_exists) technique->setLastModificationTime(mVFS->getLastModified(path)); if (loadNextFrame) @@ -840,7 +840,7 @@ namespace MWRender { for (auto& technique : mTemplates) { - if (technique->getStatus() == fx::Technique::Status::File_Not_exists) + if (technique->getStatus() == Fx::Technique::Status::File_Not_exists) continue; technique->compile(); } diff --git a/apps/openmw/mwrender/postprocessor.hpp b/apps/openmw/mwrender/postprocessor.hpp index eb9bc6347c..f81a50e9d6 100644 --- a/apps/openmw/mwrender/postprocessor.hpp +++ b/apps/openmw/mwrender/postprocessor.hpp @@ -58,7 +58,7 @@ namespace MWRender public: using FBOArray = std::array, 6>; using TextureArray = std::array, 6>; - using TechniqueList = std::vector>; + using TechniqueList = std::vector>; enum TextureIndex { @@ -122,7 +122,7 @@ namespace MWRender osg::ref_ptr getHUDCamera() { return mHUDCamera; } - osg::ref_ptr getStateUpdater() { return mStateUpdater; } + osg::ref_ptr getStateUpdater() { return mStateUpdater; } const TechniqueList& getTechniques() { return mTechniques; } @@ -132,14 +132,14 @@ namespace MWRender void resize(); - Status enableTechnique(std::shared_ptr technique, std::optional location = std::nullopt); + Status enableTechnique(std::shared_ptr technique, std::optional location = std::nullopt); - Status disableTechnique(std::shared_ptr technique, bool dirty = true); + Status disableTechnique(std::shared_ptr technique, bool dirty = true); bool getSupportsNormalsRT() const { return mNormalsSupported; } template - void setUniform(std::shared_ptr technique, const std::string& name, const T& value) + void setUniform(std::shared_ptr technique, const std::string& name, const T& value) { if (!isEnabled()) return; @@ -158,7 +158,7 @@ namespace MWRender (*it)->setValue(value); } - std::optional getUniformSize(std::shared_ptr technique, const std::string& name) + std::optional getUniformSize(std::shared_ptr technique, const std::string& name) { auto it = technique->findUniform(name); @@ -168,7 +168,7 @@ namespace MWRender return (*it)->getNumElements(); } - bool isTechniqueEnabled(const std::shared_ptr& technique) const; + bool isTechniqueEnabled(const std::shared_ptr& technique) const; void setExteriorFlag(bool exterior) { mExteriorFlag = exterior; } @@ -176,8 +176,8 @@ namespace MWRender void toggleMode(); - std::shared_ptr loadTechnique(VFS::Path::NormalizedView path, bool loadNextFrame = false); - std::shared_ptr loadTechnique(std::string_view name, bool loadNextFrame = false); + std::shared_ptr loadTechnique(VFS::Path::NormalizedView path, bool loadNextFrame = false); + std::shared_ptr loadTechnique(std::string_view name, bool loadNextFrame = false); TechniqueList getChain(); @@ -263,13 +263,13 @@ namespace MWRender int mHeight; int mSamples; - osg::ref_ptr mStateUpdater; + osg::ref_ptr mStateUpdater; osg::ref_ptr mPingPongCull; std::array, 2> mCanvases; osg::ref_ptr mTransparentDepthPostPass; osg::ref_ptr mDistortionCallback; - fx::DispatchArray mTemplateData; + Fx::DispatchArray mTemplateData; }; } diff --git a/apps/openmw/mwscript/controlextensions.cpp b/apps/openmw/mwscript/controlextensions.cpp index b9e8f8965a..3a70ec5142 100644 --- a/apps/openmw/mwscript/controlextensions.cpp +++ b/apps/openmw/mwscript/controlextensions.cpp @@ -164,14 +164,7 @@ namespace MWScript void execute(Interpreter::Runtime& runtime) override { MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayerPtr(); - MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); - MWBase::World* world = MWBase::Environment::get().getWorld(); - - bool stanceOn = stats.getStance(MWMechanics::CreatureStats::Stance_Run); - bool running = MWBase::Environment::get().getMechanicsManager()->isRunning(ptr); - bool inair = !world->isOnGround(ptr) && !world->isSwimming(ptr) && !world->isFlying(ptr); - - runtime.push(stanceOn && (running || inair)); + runtime.push(MWBase::Environment::get().getMechanicsManager()->isRunning(ptr)); } }; diff --git a/apps/openmw/mwsound/openaloutput.cpp b/apps/openmw/mwsound/openaloutput.cpp index 0f27524912..60c9e5f3ea 100644 --- a/apps/openmw/mwsound/openaloutput.cpp +++ b/apps/openmw/mwsound/openaloutput.cpp @@ -34,7 +34,7 @@ namespace { - const int sLoudnessFPS = 20; // loudness values per second of audio + const float sLoudnessFPS = 20.0f; // loudness values per second of audio ALCenum checkALCError(ALCdevice* device, const char* func, int line) { diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index f31e261106..86af303341 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -55,7 +55,7 @@ void MWWorld::InventoryStore::storeEquipmentState( } if (mSelectedEnchantItem.getType() != -1 && mSelectedEnchantItem->getBase() == &ref) - inventory.mSelectedEnchantItem = index; + inventory.mSelectedEnchantItem = static_cast(index); } void MWWorld::InventoryStore::readEquipmentState( diff --git a/apps/wizard/main.cpp b/apps/wizard/main.cpp index 09a34994e4..bfade9bf68 100644 --- a/apps/wizard/main.cpp +++ b/apps/wizard/main.cpp @@ -45,7 +45,7 @@ int main(int argc, char* argv[]) resourcesPath = Files::pathToQString(variables["resources"].as().u8string()); } - l10n::installQtTranslations(app, "wizard", resourcesPath); + L10n::installQtTranslations(app, "wizard", resourcesPath); Wizard::MainWizard wizard(std::move(configurationManager)); diff --git a/components/fallback/validate.hpp b/components/fallback/validate.hpp index 9540c85654..f5dfff9e26 100644 --- a/components/fallback/validate.hpp +++ b/components/fallback/validate.hpp @@ -5,10 +5,12 @@ #include #include +// NOLINTBEGIN(readability-identifier-naming) namespace boost { class any; } +// NOLINTEND(readability-identifier-naming) namespace Fallback { diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index 306ea38fe1..2e10f21252 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -9,11 +9,13 @@ #include #include +// NOLINTBEGIN(readability-identifier-naming) namespace boost::program_options { class options_description; class variables_map; } +// NOLINTEND(readability-identifier-naming) /** * \namespace Files diff --git a/components/fontloader/fontloader.cpp b/components/fontloader/fontloader.cpp index c9003f3aa8..f43c78bfd3 100644 --- a/components/fontloader/fontloader.cpp +++ b/components/fontloader/fontloader.cpp @@ -276,8 +276,8 @@ namespace Gui { Log(Debug::Info) << "Loading font file " << fileName; - osgMyGUI::DataManager* dataManager - = dynamic_cast(&osgMyGUI::DataManager::getInstance()); + MyGUIPlatform::DataManager* dataManager + = dynamic_cast(&MyGUIPlatform::DataManager::getInstance()); if (!dataManager) { Log(Debug::Error) << "Can not load TrueType font " << fontId << ": osgMyGUI::DataManager is not available."; @@ -287,7 +287,7 @@ namespace Gui // TODO: it may be worth to take in account resolution change, but it is not safe to replace used assets std::unique_ptr layersStream(dataManager->getData("openmw_layers.xml")); MyGUI::IntSize bookSize = getBookSize(layersStream.get()); - float bookScale = osgMyGUI::ScalingLayer::getScaleFactor(bookSize); + float bookScale = MyGUIPlatform::ScalingLayer::getScaleFactor(bookSize); const auto oldDataPath = dataManager->getDataPath({}); dataManager->setResourcePath("fonts"); diff --git a/components/fx/lexer.cpp b/components/fx/lexer.cpp index 2fc25e44f1..cab59df314 100644 --- a/components/fx/lexer.cpp +++ b/components/fx/lexer.cpp @@ -8,7 +8,7 @@ #include -namespace fx +namespace Fx { namespace Lexer { diff --git a/components/fx/lexer.hpp b/components/fx/lexer.hpp index dda6b3a0f6..1b32298608 100644 --- a/components/fx/lexer.hpp +++ b/components/fx/lexer.hpp @@ -9,7 +9,7 @@ #include "lexertypes.hpp" -namespace fx +namespace Fx { namespace Lexer { diff --git a/components/fx/lexertypes.hpp b/components/fx/lexertypes.hpp index 2a56a84a1a..327d6832c8 100644 --- a/components/fx/lexertypes.hpp +++ b/components/fx/lexertypes.hpp @@ -4,7 +4,7 @@ #include #include -namespace fx +namespace Fx { namespace Lexer { diff --git a/components/fx/parseconstants.hpp b/components/fx/parseconstants.hpp index 3ad9abd959..eec315042b 100644 --- a/components/fx/parseconstants.hpp +++ b/components/fx/parseconstants.hpp @@ -13,11 +13,11 @@ #include "technique.hpp" -namespace fx +namespace Fx { - namespace constants + namespace Constants { - constexpr std::array, 6> TechniqueFlag = { { + constexpr std::array, 6> TechniqueFlag = { { { "disable_interiors", Technique::Flag_Disable_Interiors }, { "disable_exteriors", Technique::Flag_Disable_Exteriors }, { "disable_underwater", Technique::Flag_Disable_Underwater }, diff --git a/components/fx/pass.cpp b/components/fx/pass.cpp index c55bee76e3..85b420f4fd 100644 --- a/components/fx/pass.cpp +++ b/components/fx/pass.cpp @@ -49,7 +49,7 @@ void main() } -namespace fx +namespace Fx { Pass::Pass(Pass::Type type, Pass::Order order, bool ubo) : mCompiled(false) diff --git a/components/fx/pass.hpp b/components/fx/pass.hpp index 1c417ac8cf..2e68bddcc5 100644 --- a/components/fx/pass.hpp +++ b/components/fx/pass.hpp @@ -18,7 +18,7 @@ namespace osg class StateSet; } -namespace fx +namespace Fx { class Technique; diff --git a/components/fx/stateupdater.cpp b/components/fx/stateupdater.cpp index 9e86f25b9c..8dd6bce994 100644 --- a/components/fx/stateupdater.cpp +++ b/components/fx/stateupdater.cpp @@ -5,7 +5,7 @@ #include -namespace fx +namespace Fx { std::string StateUpdater::sDefinition = UniformData::getDefinition("_omw_data"); diff --git a/components/fx/stateupdater.hpp b/components/fx/stateupdater.hpp index 33a7a09fe6..f5921faadf 100644 --- a/components/fx/stateupdater.hpp +++ b/components/fx/stateupdater.hpp @@ -7,7 +7,7 @@ #include #include -namespace fx +namespace Fx { class StateUpdater : public SceneUtil::StateSetUpdater { diff --git a/components/fx/technique.cpp b/components/fx/technique.cpp index 58ea55b2f6..5865298fe5 100644 --- a/components/fx/technique.cpp +++ b/components/fx/technique.cpp @@ -35,7 +35,7 @@ namespace }; } -namespace fx +namespace Fx { VFS::Path::Normalized Technique::makeFileName(std::string_view name) { @@ -280,7 +280,7 @@ namespace fx if (mRenderTargets.count(mBlockName)) error(Misc::StringUtils::format("redeclaration of render target '%s'", std::string(mBlockName))); - fx::Types::RenderTarget rt; + Fx::Types::RenderTarget rt; rt.mTarget->setTextureSize(mWidth, mHeight); rt.mTarget->setSourceFormat(GL_RGB); rt.mTarget->setInternalFormat(GL_RGB); @@ -341,7 +341,7 @@ namespace fx auto& pass = mPassMap[mBlockName]; if (!pass) - pass = std::make_shared(); + pass = std::make_shared(); pass->mName = mBlockName; @@ -364,7 +364,7 @@ namespace fx auto& pass = mPassMap[mBlockName]; if (!pass) - pass = std::make_shared(); + pass = std::make_shared(); pass->mUBO = mUBO; pass->mName = mBlockName; @@ -388,7 +388,7 @@ namespace fx auto& pass = mPassMap[mBlockName]; if (!pass) - pass = std::make_shared(); + pass = std::make_shared(); pass->mName = mBlockName; @@ -810,7 +810,7 @@ namespace fx auto& pass = mPassMap[mBlockName]; if (!pass) - pass = std::make_shared(); + pass = std::make_shared(); while (!isNext()) { @@ -883,7 +883,7 @@ namespace fx FlagsType Technique::parseFlags() { auto parseBit = [this](std::string_view term) { - for (const auto& [identifer, bit] : constants::TechniqueFlag) + for (const auto& [identifer, bit] : Constants::TechniqueFlag) { if (Misc::StringUtils::ciEqual(term, identifer)) return bit; @@ -902,7 +902,7 @@ namespace fx { expect(); - for (const auto& [identifer, mode] : constants::FilterMode) + for (const auto& [identifer, mode] : Constants::FilterMode) { if (asLiteral() == identifer) return mode; @@ -915,7 +915,7 @@ namespace fx { expect(); - for (const auto& [identifer, mode] : constants::WrapMode) + for (const auto& [identifer, mode] : Constants::WrapMode) { if (asLiteral() == identifer) return mode; @@ -933,7 +933,7 @@ namespace fx { expect(); - for (const auto& [identifer, mode] : constants::Compression) + for (const auto& [identifer, mode] : Constants::Compression) { if (asLiteral() == identifer) return mode; @@ -946,7 +946,7 @@ namespace fx { expect(); - for (const auto& [identifer, mode] : constants::InternalFormat) + for (const auto& [identifer, mode] : Constants::InternalFormat) { if (asLiteral() == identifer) return mode; @@ -959,7 +959,7 @@ namespace fx { expect(); - for (const auto& [identifer, mode] : constants::SourceType) + for (const auto& [identifer, mode] : Constants::SourceType) { if (asLiteral() == identifer) return mode; @@ -972,7 +972,7 @@ namespace fx { expect(); - for (const auto& [identifer, mode] : constants::SourceFormat) + for (const auto& [identifer, mode] : Constants::SourceFormat) { if (asLiteral() == identifer) return mode; @@ -985,7 +985,7 @@ namespace fx { expect(); - for (const auto& [identifer, mode] : constants::BlendEquation) + for (const auto& [identifer, mode] : Constants::BlendEquation) { if (asLiteral() == identifer) return mode; @@ -998,7 +998,7 @@ namespace fx { expect(); - for (const auto& [identifer, mode] : constants::BlendFunc) + for (const auto& [identifer, mode] : Constants::BlendFunc) { if (asLiteral() == identifer) return mode; @@ -1025,11 +1025,11 @@ namespace fx */ expect(); - std::vector> choices; + std::vector> choices; while (!isNext()) { - fx::Types::Choice choice; + Fx::Types::Choice choice; choice.mLabel = parseString(); expect(); choice.mValue = getUniformValue(); diff --git a/components/fx/technique.hpp b/components/fx/technique.hpp index 00b87a86e2..ebf3fe30f5 100644 --- a/components/fx/technique.hpp +++ b/components/fx/technique.hpp @@ -29,7 +29,7 @@ namespace VFS class Manager; } -namespace fx +namespace Fx { using FlagsType = size_t; @@ -85,7 +85,7 @@ namespace fx } // not safe to read/write in draw thread - std::shared_ptr mHandle = nullptr; + std::shared_ptr mHandle = nullptr; FlagsType mFlags = 0; diff --git a/components/fx/types.hpp b/components/fx/types.hpp index 1536cda115..ddfa966010 100644 --- a/components/fx/types.hpp +++ b/components/fx/types.hpp @@ -12,7 +12,7 @@ #include #include -namespace fx +namespace Fx { namespace Types { diff --git a/components/fx/widgets.cpp b/components/fx/widgets.cpp index 8382ca2d56..087e071b96 100644 --- a/components/fx/widgets.cpp +++ b/components/fx/widgets.cpp @@ -6,7 +6,7 @@ namespace { template void createVectorWidget( - const std::shared_ptr& uniform, MyGUI::Widget* client, fx::Widgets::UniformBase* base) + const std::shared_ptr& uniform, MyGUI::Widget* client, Fx::Widgets::UniformBase* base) { int height = client->getHeight(); base->setSize(base->getSize().width, (base->getSize().height - height) + (height * T::num_components)); @@ -16,13 +16,13 @@ namespace { auto* widget = client->createWidget( "MW_ValueEditNumber", { 0, height * i, client->getWidth(), height }, MyGUI::Align::Default); - widget->setData(uniform, static_cast(i)); + widget->setData(uniform, static_cast(i)); base->addItem(widget); } } } -namespace fx +namespace Fx { namespace Widgets { @@ -127,7 +127,7 @@ namespace fx mChoices->eventComboChangePosition += MyGUI::newDelegate(this, &EditChoice::notifyComboBoxChanged); } - void UniformBase::init(const std::shared_ptr& uniform) + void UniformBase::init(const std::shared_ptr& uniform) { if (uniform->mDisplayName.empty()) mLabel->setCaption(uniform->mName); diff --git a/components/fx/widgets.hpp b/components/fx/widgets.hpp index 59787ed9aa..c91fa01c4e 100644 --- a/components/fx/widgets.hpp +++ b/components/fx/widgets.hpp @@ -28,7 +28,7 @@ namespace Gui class AutoSizedButton; } -namespace fx +namespace Fx { namespace Widgets { @@ -46,7 +46,7 @@ namespace fx public: virtual ~EditBase() = default; - void setData(const std::shared_ptr& uniform, Index index = None) + void setData(const std::shared_ptr& uniform, Index index = None) { mUniform = uniform; mIndex = index; @@ -57,7 +57,7 @@ namespace fx virtual void toDefault() = 0; protected: - std::shared_ptr mUniform; + std::shared_ptr mUniform; Index mIndex; }; @@ -268,7 +268,7 @@ namespace fx MYGUI_RTTI_DERIVED(UniformBase) public: - void init(const std::shared_ptr& uniform); + void init(const std::shared_ptr& uniform); void toDefault(); diff --git a/components/l10n/manager.cpp b/components/l10n/manager.cpp index f6f4bb4f05..27a4d603d4 100644 --- a/components/l10n/manager.cpp +++ b/components/l10n/manager.cpp @@ -6,7 +6,7 @@ #include #include -namespace l10n +namespace L10n { void Manager::setPreferredLocales(const std::vector& langs, bool gmstHasPriority) diff --git a/components/l10n/manager.hpp b/components/l10n/manager.hpp index 2ee54921b3..4b047fa9d7 100644 --- a/components/l10n/manager.hpp +++ b/components/l10n/manager.hpp @@ -10,7 +10,7 @@ namespace VFS class Manager; } -namespace l10n +namespace L10n { class Manager diff --git a/components/l10n/messagebundles.cpp b/components/l10n/messagebundles.cpp index 2948ff155e..e8a56a9bb3 100644 --- a/components/l10n/messagebundles.cpp +++ b/components/l10n/messagebundles.cpp @@ -7,7 +7,7 @@ #include -namespace l10n +namespace L10n { MessageBundles::MessageBundles(const std::vector& preferredLocales, icu::Locale& fallbackLocale) : mFallbackLocale(fallbackLocale) diff --git a/components/l10n/messagebundles.hpp b/components/l10n/messagebundles.hpp index 0ea92e93fe..f142d3f2ac 100644 --- a/components/l10n/messagebundles.hpp +++ b/components/l10n/messagebundles.hpp @@ -10,7 +10,7 @@ #include #include -namespace l10n +namespace L10n { /** * @brief A collection of Message Bundles diff --git a/components/l10n/qttranslations.cpp b/components/l10n/qttranslations.cpp index 9bc146699e..1051b3dd2d 100644 --- a/components/l10n/qttranslations.cpp +++ b/components/l10n/qttranslations.cpp @@ -3,7 +3,7 @@ #include #include -namespace l10n +namespace L10n { QTranslator AppTranslator{}; QTranslator ComponentsTranslator{}; diff --git a/components/l10n/qttranslations.hpp b/components/l10n/qttranslations.hpp index 3ce87f0837..6a2bf9d903 100644 --- a/components/l10n/qttranslations.hpp +++ b/components/l10n/qttranslations.hpp @@ -4,7 +4,7 @@ #include #include -namespace l10n +namespace L10n { extern QTranslator AppTranslator; extern QTranslator ComponentsTranslator; diff --git a/components/lua/configuration.cpp b/components/lua/configuration.cpp index b327270fc1..858137ab73 100644 --- a/components/lua/configuration.cpp +++ b/components/lua/configuration.cpp @@ -55,7 +55,7 @@ namespace LuaUtil // Find duplicates; only the last occurrence will be used (unless `sMerge` flag is used). // Search for duplicates is case insensitive. std::vector skip(cfg.mScripts.size(), false); - for (size_t i = 0; i < cfg.mScripts.size(); ++i) + for (int i = 0; i < static_cast(cfg.mScripts.size()); ++i) { const ESM::LuaScriptCfg& script = cfg.mScripts[i]; bool global = script.mFlags & ESM::LuaScriptCfg::sGlobal; diff --git a/components/lua/l10n.cpp b/components/lua/l10n.cpp index ec42992ebb..8153efd5b5 100644 --- a/components/lua/l10n.cpp +++ b/components/lua/l10n.cpp @@ -8,7 +8,7 @@ namespace { struct L10nContext { - std::shared_ptr mData; + std::shared_ptr mData; }; void getICUArgs(std::string_view messageId, const sol::table& table, std::vector& argNames, @@ -52,7 +52,7 @@ namespace sol namespace LuaUtil { - sol::function initL10nLoader(lua_State* L, l10n::Manager* manager) + sol::function initL10nLoader(lua_State* L, L10n::Manager* manager) { sol::state_view lua(L); sol::usertype ctxDef = lua.new_usertype("L10nContext"); diff --git a/components/lua/l10n.hpp b/components/lua/l10n.hpp index 1fc3e17747..2abe7f56f2 100644 --- a/components/lua/l10n.hpp +++ b/components/lua/l10n.hpp @@ -3,14 +3,14 @@ #include -namespace l10n +namespace L10n { class Manager; } namespace LuaUtil { - sol::function initL10nLoader(lua_State*, l10n::Manager* manager); + sol::function initL10nLoader(lua_State*, L10n::Manager* manager); } #endif // COMPONENTS_LUA_L10N_H diff --git a/components/lua/luastate.cpp b/components/lua/luastate.cpp index f959263153..b83415e58d 100644 --- a/components/lua/luastate.cpp +++ b/components/lua/luastate.cpp @@ -453,7 +453,7 @@ namespace LuaUtil return call(sol::state_view(obj.lua_state())["tostring"], obj); } - std::string internal::formatCastingError(const sol::object& obj, const std::type_info& t) + std::string Internal::formatCastingError(const sol::object& obj, const std::type_info& t) { const char* typeName = t.name(); if (t == typeid(int)) diff --git a/components/lua/luastate.hpp b/components/lua/luastate.hpp index d842478cb1..7ce9a0ec94 100644 --- a/components/lua/luastate.hpp +++ b/components/lua/luastate.hpp @@ -325,7 +325,7 @@ namespace LuaUtil // String representation of a Lua object. Should be used for debugging/logging purposes only. std::string toString(const sol::object&); - namespace internal + namespace Internal { std::string formatCastingError(const sol::object& obj, const std::type_info&); } @@ -334,7 +334,7 @@ namespace LuaUtil decltype(auto) cast(const sol::object& obj) { if (!obj.is()) - throw std::runtime_error(internal::formatCastingError(obj, typeid(T))); + throw std::runtime_error(Internal::formatCastingError(obj, typeid(T))); return obj.as(); } diff --git a/components/myguiplatform/additivelayer.cpp b/components/myguiplatform/additivelayer.cpp index d170c831a6..9ffdc9b84e 100644 --- a/components/myguiplatform/additivelayer.cpp +++ b/components/myguiplatform/additivelayer.cpp @@ -5,7 +5,7 @@ #include "myguirendermanager.hpp" -namespace osgMyGUI +namespace MyGUIPlatform { AdditiveLayer::AdditiveLayer() diff --git a/components/myguiplatform/additivelayer.hpp b/components/myguiplatform/additivelayer.hpp index cfd5c82058..4b5185f97f 100644 --- a/components/myguiplatform/additivelayer.hpp +++ b/components/myguiplatform/additivelayer.hpp @@ -10,7 +10,7 @@ namespace osg class StateSet; } -namespace osgMyGUI +namespace MyGUIPlatform { /// @brief A Layer rendering with additive blend mode. diff --git a/components/myguiplatform/myguidatamanager.cpp b/components/myguiplatform/myguidatamanager.cpp index 49dba3634b..41a2d84e80 100644 --- a/components/myguiplatform/myguidatamanager.cpp +++ b/components/myguiplatform/myguidatamanager.cpp @@ -24,7 +24,7 @@ namespace }; } -namespace osgMyGUI +namespace MyGUIPlatform { void DataManager::setResourcePath(const std::filesystem::path& path) diff --git a/components/myguiplatform/myguidatamanager.hpp b/components/myguiplatform/myguidatamanager.hpp index 5b392177b7..f7489f8b65 100644 --- a/components/myguiplatform/myguidatamanager.hpp +++ b/components/myguiplatform/myguidatamanager.hpp @@ -11,7 +11,7 @@ namespace VFS class Manager; } -namespace osgMyGUI +namespace MyGUIPlatform { class DataManager : public MyGUI::DataManager diff --git a/components/myguiplatform/myguiloglistener.cpp b/components/myguiplatform/myguiloglistener.cpp index 3e52e75ad2..66b35e0961 100644 --- a/components/myguiplatform/myguiloglistener.cpp +++ b/components/myguiplatform/myguiloglistener.cpp @@ -4,7 +4,7 @@ #include -namespace osgMyGUI +namespace MyGUIPlatform { void CustomLogListener::open() { diff --git a/components/myguiplatform/myguiloglistener.hpp b/components/myguiplatform/myguiloglistener.hpp index 15cea0effd..3557f56540 100644 --- a/components/myguiplatform/myguiloglistener.hpp +++ b/components/myguiplatform/myguiloglistener.hpp @@ -10,7 +10,7 @@ #include #include -namespace osgMyGUI +namespace MyGUIPlatform { /// \brief Custom MyGUI::ILogListener interface implementation diff --git a/components/myguiplatform/myguiplatform.cpp b/components/myguiplatform/myguiplatform.cpp index 20fdaa7e7c..9d24e13ca1 100644 --- a/components/myguiplatform/myguiplatform.cpp +++ b/components/myguiplatform/myguiplatform.cpp @@ -6,7 +6,7 @@ #include "components/files/conversion.hpp" -namespace osgMyGUI +namespace MyGUIPlatform { Platform::Platform(osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ImageManager* imageManager, diff --git a/components/myguiplatform/myguiplatform.hpp b/components/myguiplatform/myguiplatform.hpp index 66b02cd8ba..ff7e4a339f 100644 --- a/components/myguiplatform/myguiplatform.hpp +++ b/components/myguiplatform/myguiplatform.hpp @@ -26,7 +26,7 @@ namespace VFS class Manager; } -namespace osgMyGUI +namespace MyGUIPlatform { class RenderManager; diff --git a/components/myguiplatform/myguirendermanager.cpp b/components/myguiplatform/myguirendermanager.cpp index 5d32641b6d..a17e387ed6 100644 --- a/components/myguiplatform/myguirendermanager.cpp +++ b/components/myguiplatform/myguirendermanager.cpp @@ -40,12 +40,12 @@ } \ } while (0) -namespace osgMyGUI +namespace MyGUIPlatform { class Drawable : public osg::Drawable { - osgMyGUI::RenderManager* mParent; + MyGUIPlatform::RenderManager* mParent; osg::ref_ptr mStateSet; public: @@ -58,12 +58,12 @@ namespace osgMyGUI { } - void setRenderManager(osgMyGUI::RenderManager* renderManager) { mRenderManager = renderManager; } + void setRenderManager(MyGUIPlatform::RenderManager* renderManager) { mRenderManager = renderManager; } void operator()(osg::Node*, osg::NodeVisitor*) { mRenderManager->update(); } private: - osgMyGUI::RenderManager* mRenderManager; + MyGUIPlatform::RenderManager* mRenderManager; }; // Stage 1: collect draw calls. Run during the Cull traversal. @@ -75,12 +75,12 @@ namespace osgMyGUI { } - void setRenderManager(osgMyGUI::RenderManager* renderManager) { mRenderManager = renderManager; } + void setRenderManager(MyGUIPlatform::RenderManager* renderManager) { mRenderManager = renderManager; } void operator()(osg::Node*, osg::NodeVisitor*) { mRenderManager->collectDrawCalls(); } private: - osgMyGUI::RenderManager* mRenderManager; + MyGUIPlatform::RenderManager* mRenderManager; }; // Stage 2: execute the draw calls. Run during the Draw traversal. May run in parallel with the update traversal @@ -162,7 +162,7 @@ namespace osgMyGUI } public: - Drawable(osgMyGUI::RenderManager* parent = nullptr) + Drawable(MyGUIPlatform::RenderManager* parent = nullptr) : mParent(parent) , mWriteTo(0) , mReadFrom(0) diff --git a/components/myguiplatform/myguirendermanager.hpp b/components/myguiplatform/myguirendermanager.hpp index 7f1582203a..737a0eb21e 100644 --- a/components/myguiplatform/myguirendermanager.hpp +++ b/components/myguiplatform/myguirendermanager.hpp @@ -28,7 +28,7 @@ namespace osg class StateSet; } -namespace osgMyGUI +namespace MyGUIPlatform { class Drawable; diff --git a/components/myguiplatform/myguitexture.cpp b/components/myguiplatform/myguitexture.cpp index 9d865e1296..529488beb1 100644 --- a/components/myguiplatform/myguitexture.cpp +++ b/components/myguiplatform/myguitexture.cpp @@ -8,7 +8,7 @@ #include #include -namespace osgMyGUI +namespace MyGUIPlatform { OSGTexture::OSGTexture(const std::string& name, Resource::ImageManager* imageManager) diff --git a/components/myguiplatform/myguitexture.hpp b/components/myguiplatform/myguitexture.hpp index 7139a81dba..3e34820069 100644 --- a/components/myguiplatform/myguitexture.hpp +++ b/components/myguiplatform/myguitexture.hpp @@ -17,7 +17,7 @@ namespace Resource class ImageManager; } -namespace osgMyGUI +namespace MyGUIPlatform { class OSGTexture final : public MyGUI::ITexture diff --git a/components/myguiplatform/scalinglayer.cpp b/components/myguiplatform/scalinglayer.cpp index c04134bfad..1660e4f0ca 100644 --- a/components/myguiplatform/scalinglayer.cpp +++ b/components/myguiplatform/scalinglayer.cpp @@ -3,7 +3,7 @@ #include #include -namespace osgMyGUI +namespace MyGUIPlatform { /// @brief the ProxyRenderTarget allows to adjust the pixel scale and offset for a "source" render target. diff --git a/components/myguiplatform/scalinglayer.hpp b/components/myguiplatform/scalinglayer.hpp index 4f04ce917a..512bb0109e 100644 --- a/components/myguiplatform/scalinglayer.hpp +++ b/components/myguiplatform/scalinglayer.hpp @@ -3,7 +3,7 @@ #include -namespace osgMyGUI +namespace MyGUIPlatform { ///@brief A Layer that lays out and renders widgets in screen-relative coordinates. The "Size" property determines diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 07eb342221..de5aa01b15 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1568,6 +1568,9 @@ namespace NifOsg } rig->setBoneInfo(std::move(boneInfo)); rig->setInfluences(influences); + rig->setTransform(data->mTransform.toMatrix()); + if (const Nif::NiAVObject* rootBone = skin->mRoot.getPtr()) + rig->setRootBone(rootBone->mName); drawable = rig; } @@ -1683,7 +1686,7 @@ namespace NifOsg if (hasColors) colors.emplace_back(elem.mVertColor[0], elem.mVertColor[1], elem.mVertColor[2], elem.mVertColor[3]); if (hasUV) - uvlist.emplace_back(halfToFloat(elem.mUV[0]), 1.0 - halfToFloat(elem.mUV[1])); + uvlist.emplace_back(halfToFloat(elem.mUV[0]), 1.0f - halfToFloat(elem.mUV[1])); } if (!vertices.empty()) @@ -1729,6 +1732,8 @@ namespace NifOsg } rig->setBoneInfo(std::move(boneInfo)); rig->setInfluences(influences); + if (const Nif::NiAVObject* rootBone = skin->mRoot.getPtr()) + rig->setRootBone(rootBone->mName); drawable = rig; } diff --git a/components/sceneutil/riggeometry.cpp b/components/sceneutil/riggeometry.cpp index d93b88349d..475522660e 100644 --- a/components/sceneutil/riggeometry.cpp +++ b/components/sceneutil/riggeometry.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include "skeleton.hpp" @@ -181,6 +182,12 @@ namespace SceneUtil ++boneInfo; } + osg::Matrixf transform; + if (mSkinToSkelMatrix) + transform = (*mSkinToSkelMatrix) * mData->mTransform; + else + transform = mData->mTransform; + for (const auto& [influences, vertices] : mData->mInfluences) { osg::Matrixf resultMat(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); @@ -196,8 +203,7 @@ namespace SceneUtil *resultMatPtr += *boneMatPtr * weight; } - if (mGeomToSkelMatrix) - resultMat *= (*mGeomToSkelMatrix); + resultMat *= transform; for (unsigned short vertex : vertices) { @@ -242,9 +248,14 @@ namespace SceneUtil mSkeleton->updateBoneMatrices(nv->getTraversalNumber()); - updateGeomToSkelMatrix(nv->getNodePath()); + updateSkinToSkelMatrix(nv->getNodePath()); osg::BoundingBox box; + osg::Matrixf transform; + if (mSkinToSkelMatrix) + transform = (*mSkinToSkelMatrix) * mData->mTransform; + else + transform = mData->mTransform; size_t index = 0; for (const BoneInfo& info : mData->mBones) @@ -254,10 +265,7 @@ namespace SceneUtil continue; osg::BoundingSpheref bs = info.mBoundSphere; - if (mGeomToSkelMatrix) - transformBoundingSphere(bone->mMatrixInSkeletonSpace * (*mGeomToSkelMatrix), bs); - else - transformBoundingSphere(bone->mMatrixInSkeletonSpace, bs); + transformBoundingSphere(bone->mMatrixInSkeletonSpace * transform, bs); box.expandBy(bs); } @@ -280,31 +288,39 @@ namespace SceneUtil } } - void RigGeometry::updateGeomToSkelMatrix(const osg::NodePath& nodePath) + void RigGeometry::updateSkinToSkelMatrix(const osg::NodePath& nodePath) { - bool foundSkel = false; - osg::RefMatrix* geomToSkelMatrix = mGeomToSkelMatrix; - if (geomToSkelMatrix) - geomToSkelMatrix->makeIdentity(); - for (osg::NodePath::const_iterator it = nodePath.begin(); it != nodePath.end() - 1; ++it) + if (mSkinToSkelMatrix) + mSkinToSkelMatrix->makeIdentity(); + auto skeletonRoot = std::find(nodePath.begin(), nodePath.end(), mSkeleton); + if (skeletonRoot == nodePath.end()) + return; + skeletonRoot++; + auto skinRoot = nodePath.end(); + if (!mData->mRootBone.empty()) + skinRoot = std::find_if(skeletonRoot, nodePath.end(), + [&](const osg::Node* node) { return Misc::StringUtils::ciEqual(node->getName(), mData->mRootBone); }); + if (skinRoot == nodePath.end()) { - osg::Node* node = *it; - if (!foundSkel) + // Failed to find skin root, cancel out everything up till the trishape. + // Our parent node is the trishape's transform + skinRoot = nodePath.end() - 2; + if ((*skinRoot)->getName() != getName()) // but maybe it can get optimized out + skinRoot++; + } + else + skinRoot++; + for (auto it = skeletonRoot; it != skinRoot; ++it) + { + const osg::Node* node = *it; + if (const osg::Transform* trans = node->asTransform()) { - if (node == mSkeleton) - foundSkel = true; - } - else - { - if (osg::Transform* trans = node->asTransform()) - { - osg::MatrixTransform* matrixTrans = trans->asMatrixTransform(); - if (matrixTrans && matrixTrans->getMatrix().isIdentity()) - continue; - if (!geomToSkelMatrix) - geomToSkelMatrix = mGeomToSkelMatrix = new osg::RefMatrix; - trans->computeWorldToLocalMatrix(*geomToSkelMatrix, nullptr); - } + const osg::MatrixTransform* matrixTrans = trans->asMatrixTransform(); + if (matrixTrans && matrixTrans->getMatrix().isIdentity()) + continue; + if (!mSkinToSkelMatrix) + mSkinToSkelMatrix = new osg::RefMatrix; + trans->computeWorldToLocalMatrix(*mSkinToSkelMatrix, nullptr); } } } @@ -346,12 +362,26 @@ namespace SceneUtil std::map influencesToVertices; for (size_t i = 0; i < influences.size(); i++) - influencesToVertices[influences[i]].emplace_back(i); + influencesToVertices[influences[i]].emplace_back(static_cast(i)); mData->mInfluences.reserve(influencesToVertices.size()); mData->mInfluences.assign(influencesToVertices.begin(), influencesToVertices.end()); } + void RigGeometry::setTransform(osg::Matrixf&& transform) + { + if (!mData) + mData = new InfluenceData; + mData->mTransform = transform; + } + + void RigGeometry::setRootBone(std::string_view name) + { + if (!mData) + mData = new InfluenceData; + mData->mRootBone = name; + } + void RigGeometry::accept(osg::NodeVisitor& nv) { if (!nv.validNodeMask(*this)) diff --git a/components/sceneutil/riggeometry.hpp b/components/sceneutil/riggeometry.hpp index 64ea1e2519..670c040758 100644 --- a/components/sceneutil/riggeometry.hpp +++ b/components/sceneutil/riggeometry.hpp @@ -4,6 +4,8 @@ #include #include +#include + namespace SceneUtil { class Skeleton; @@ -58,6 +60,10 @@ namespace SceneUtil /// @note The source geometry will not be modified. void setSourceGeometry(osg::ref_ptr sourceGeom); + void setTransform(osg::Matrixf&& transform); + + void setRootBone(std::string_view name); + osg::ref_ptr getSourceGeometry() const; void accept(osg::NodeVisitor& nv) override; @@ -89,13 +95,15 @@ namespace SceneUtil osg::ref_ptr mSourceTangents; Skeleton* mSkeleton{ nullptr }; - osg::ref_ptr mGeomToSkelMatrix; + osg::ref_ptr mSkinToSkelMatrix; using VertexList = std::vector; struct InfluenceData : public osg::Referenced { std::vector mBones; std::vector> mInfluences; + osg::Matrixf mTransform; + std::string mRootBone; }; osg::ref_ptr mData; std::vector mNodes; @@ -105,7 +113,7 @@ namespace SceneUtil bool initFromParentSkeleton(osg::NodeVisitor* nv); - void updateGeomToSkelMatrix(const osg::NodePath& nodePath); + void updateSkinToSkelMatrix(const osg::NodePath& nodePath); }; } diff --git a/components/terrain/chunkmanager.cpp b/components/terrain/chunkmanager.cpp index 7ccd89ac21..3d7c2b1dfc 100644 --- a/components/terrain/chunkmanager.cpp +++ b/components/terrain/chunkmanager.cpp @@ -19,6 +19,23 @@ namespace Terrain { + struct UpdateTextureFilteringFunctor + { + UpdateTextureFilteringFunctor(Resource::SceneManager* sceneMgr) + : mSceneManager(sceneMgr) + { + } + Resource::SceneManager* mSceneManager; + + void operator()(ChunkKey, osg::Object* obj) + { + TerrainDrawable* drawable = static_cast(obj); + CompositeMap* composite = drawable->getCompositeMap(); + if (composite && composite->mTexture) + mSceneManager->applyFilterSettings(composite->mTexture); + } + }; + ChunkManager::ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer, ESM::RefId worldspace, double expiryDelay) : GenericResourceManager(nullptr, expiryDelay) @@ -61,6 +78,12 @@ namespace Terrain return node; } + void ChunkManager::updateTextureFiltering() + { + UpdateTextureFilteringFunctor f(mSceneManager); + mCache->call(f); + } + void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats* stats) const { Resource::reportStats("Terrain Chunk", frameNumber, mCache->getStats(), *stats); @@ -85,10 +108,9 @@ namespace Terrain texture->setTextureWidth(mCompositeMapSize); texture->setTextureHeight(mCompositeMapSize); texture->setInternalFormat(GL_RGB); - texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); - texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); + mSceneManager->applyFilterSettings(texture); return texture; } diff --git a/components/terrain/chunkmanager.hpp b/components/terrain/chunkmanager.hpp index 20d6ba9327..b4f327e699 100644 --- a/components/terrain/chunkmanager.hpp +++ b/components/terrain/chunkmanager.hpp @@ -85,6 +85,8 @@ namespace Terrain void setCompositeMapLevel(float level) { mCompositeMapLevel = level; } void setMaxCompositeGeometrySize(float maxCompGeometrySize) { mMaxCompGeometrySize = maxCompGeometrySize; } + void updateTextureFiltering(); + void setNodeMask(unsigned int mask) { mNodeMask = mask; } unsigned int getNodeMask() override { return mNodeMask; } diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index 09d2680acd..9c3a7f589d 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -43,7 +43,8 @@ namespace // blendmap, apparently. matrix.preMultTranslate(osg::Vec3f(1.0f / blendmapScale / 4.0f, 1.0f / blendmapScale / 4.0f, 0.f)); - texMat = mTexMatMap.insert(std::make_pair(blendmapScale, new osg::TexMat(matrix))).first; + texMat = mTexMatMap.insert(std::make_pair(static_cast(blendmapScale), new osg::TexMat(matrix))) + .first; } return texMat->second; } diff --git a/components/terrain/world.cpp b/components/terrain/world.cpp index 58cfc0b068..e18881e490 100644 --- a/components/terrain/world.cpp +++ b/components/terrain/world.cpp @@ -133,6 +133,8 @@ namespace Terrain { if (mTextureManager) mTextureManager->updateTextureFiltering(); + if (mChunkManager) + mChunkManager->updateTextureFiltering(); } void World::clearAssociatedCaches() diff --git a/files/shaders/compatibility/water.frag b/files/shaders/compatibility/water.frag index 749dcf27cd..dbf36560b3 100644 --- a/files/shaders/compatibility/water.frag +++ b/files/shaders/compatibility/water.frag @@ -40,6 +40,8 @@ const vec3 SUN_EXT = vec3(0.45, 0.55, 0.68); // sunlight extinction const float SUN_SPEC_FADING_THRESHOLD = 0.15; // visibility at which sun specularity starts to fade const float SPEC_HARDNESS = 256.0; // specular highlights hardness +const float SPEC_BUMPINESS = 5.0; // surface bumpiness boost for specular +const float SPEC_BRIGHTNESS = 1.5; // boosts the brightness of the specular highlights const float BUMP_SUPPRESS_DEPTH = 300.0; // at what water depth bumpmap will be suppressed for reflections and refractions (prevents artifacts at shores) const float REFR_FOG_DISTORT_DISTANCE = 3000.0; // at what distance refraction fog will be calculated using real water depth instead of distorted depth (prevents splotchy shores) @@ -161,7 +163,13 @@ void main(void) sunSpec.a = min(1.0, sunSpec.a / SUN_SPEC_FADING_THRESHOLD); // specular - float specular = pow(max(dot(reflect(viewDir, normal), sunWorldDir), 0.0), SPEC_HARDNESS) * shadow * sunSpec.a; + const float SPEC_MAGIC = 1.55; // from the original blender shader, changing it makes the spec vanish or become too bright + + vec3 specNormal = normalize(vec3(normal.x * SPEC_BUMPINESS, normal.y * SPEC_BUMPINESS, normal.z)); + vec3 viewReflectDir = reflect(viewDir, specNormal); + float phongTerm = max(dot(viewReflectDir, sunWorldDir), 0.0); + float specular = pow(atan(phongTerm * SPEC_MAGIC), SPEC_HARDNESS) * SPEC_BRIGHTNESS; + specular = clamp(specular, 0.0, 1.0) * shadow * sunSpec.a; // artificial specularity to make rain ripples more noticeable vec3 skyColorEstimate = vec3(max(0.0, mix(-0.3, 1.0, sunFade)));