From fdc878d766c33b889d1cc74b413fb7830bf04df7 Mon Sep 17 00:00:00 2001 From: epochwon Date: Wed, 25 Jun 2025 17:04:21 -0400 Subject: [PATCH 01/29] elongate specular highlight --- files/shaders/compatibility/water.frag | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/files/shaders/compatibility/water.frag b/files/shaders/compatibility/water.frag index 749dcf27cd..6e447daad5 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,8 @@ 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; + vec3 R = reflect(viewDir, normalize(vec3(normal.x * SPEC_BUMPINESS, normal.y * SPEC_BUMPINESS, normal.z))); + float specular = clamp(pow(atan(max(dot(R, sunWorldDir), 0.0) * 1.55), SPEC_HARDNESS) * SPEC_BRIGHTNESS, 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))); From 13f1b76a25b0c56aa919a544e88566cc1e5c9287 Mon Sep 17 00:00:00 2001 From: epochwon Date: Wed, 25 Jun 2025 17:23:04 -0400 Subject: [PATCH 02/29] tabs to spaces --- files/shaders/compatibility/water.frag | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/shaders/compatibility/water.frag b/files/shaders/compatibility/water.frag index 6e447daad5..33b6fe1163 100644 --- a/files/shaders/compatibility/water.frag +++ b/files/shaders/compatibility/water.frag @@ -40,8 +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 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) From c89b2b0c600a4715a08f457daefb8bc350bb25e1 Mon Sep 17 00:00:00 2001 From: epochwon Date: Tue, 1 Jul 2025 10:42:42 -0400 Subject: [PATCH 03/29] fix indenting --- files/shaders/compatibility/water.frag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/shaders/compatibility/water.frag b/files/shaders/compatibility/water.frag index 33b6fe1163..81abdc094f 100644 --- a/files/shaders/compatibility/water.frag +++ b/files/shaders/compatibility/water.frag @@ -164,7 +164,7 @@ void main(void) // specular vec3 R = reflect(viewDir, normalize(vec3(normal.x * SPEC_BUMPINESS, normal.y * SPEC_BUMPINESS, normal.z))); - float specular = clamp(pow(atan(max(dot(R, sunWorldDir), 0.0) * 1.55), SPEC_HARDNESS) * SPEC_BRIGHTNESS, 0.0, 1.0) * shadow * sunSpec.a; + float specular = clamp(pow(atan(max(dot(R, sunWorldDir), 0.0) * 1.55), SPEC_HARDNESS) * SPEC_BRIGHTNESS, 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))); From 0027a5bcab250cc785fa77fdc1e69edbfc1d6d16 Mon Sep 17 00:00:00 2001 From: epochwon Date: Wed, 2 Jul 2025 10:49:27 -0400 Subject: [PATCH 04/29] make the specular terms easier to read, turn the magic number into a const --- files/shaders/compatibility/water.frag | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/files/shaders/compatibility/water.frag b/files/shaders/compatibility/water.frag index 81abdc094f..dbf36560b3 100644 --- a/files/shaders/compatibility/water.frag +++ b/files/shaders/compatibility/water.frag @@ -163,8 +163,13 @@ void main(void) sunSpec.a = min(1.0, sunSpec.a / SUN_SPEC_FADING_THRESHOLD); // specular - vec3 R = reflect(viewDir, normalize(vec3(normal.x * SPEC_BUMPINESS, normal.y * SPEC_BUMPINESS, normal.z))); - float specular = clamp(pow(atan(max(dot(R, sunWorldDir), 0.0) * 1.55), SPEC_HARDNESS) * SPEC_BRIGHTNESS, 0.0, 1.0) * 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))); From 400c5a6dbab6f5ccb4558f1b71876a77c85418ff Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Jul 2025 01:03:09 +0300 Subject: [PATCH 05/29] Bump mac CI image to macos-15-xcode-16 and tweak trigger rules --- .gitlab-ci.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1ca0d4251e..18872dfbc6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -502,7 +502,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/ @@ -537,11 +544,8 @@ Ubuntu_GCC_integration_tests_asan: macOS14_Xcode15_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 @@ -549,11 +553,8 @@ macOS14_Xcode15_amd64: macOS14_Xcode15_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 From 4f827b63366ec9e3de52e6623cd032c4d160913e Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Wed, 16 Jul 2025 11:30:21 +0300 Subject: [PATCH 06/29] Rename mac jobs, test caching --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 18872dfbc6..bde2d6a1b9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -542,7 +542,7 @@ Ubuntu_GCC_integration_tests_asan: paths: - build/OpenMW-*.dmg -macOS14_Xcode15_amd64: +macOS15_Xcode16_amd64: extends: .MacOS cache: key: macOS15_Xcode16_amd64.v1 @@ -551,7 +551,7 @@ macOS14_Xcode15_amd64: DMG_IDENTIFIER: amd64 MACOS_AMD64: true -macOS14_Xcode15_arm64: +macOS15_Xcode16_arm64: extends: .MacOS cache: key: macOS15_Xcode16_arm64.v1 From 614062d3876a310520069527a9c4bfb3bd6f6c71 Mon Sep 17 00:00:00 2001 From: Kuyondo Date: Tue, 15 Jul 2025 01:47:48 +0800 Subject: [PATCH 07/29] prevent item flickering on drag use and dont stop drag on denied lua itemusage --- AUTHORS.md | 2 +- apps/openmw/mwgui/inventorywindow.cpp | 67 +++++++++++---------------- apps/openmw/mwgui/inventorywindow.hpp | 1 - 3 files changed, 27 insertions(+), 43 deletions(-) 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/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index c558f1bad9..e5f6b7dc1e 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -573,24 +573,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(); @@ -612,8 +625,6 @@ namespace MWGui return; } - mDragAndDrop->finish(); - if (mDragAndDrop->mSourceModel != mTradeModel) { // Move item to the player's inventory @@ -621,33 +632,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 2dc25144d5..e245fe46ca 100644 --- a/apps/openmw/mwgui/inventorywindow.hpp +++ b/apps/openmw/mwgui/inventorywindow.hpp @@ -85,7 +85,6 @@ namespace MWGui Misc::NotNullPtr mItemTransfer; int mSelectedItem; - std::optional mEquippedStackableCount; MWWorld::Ptr mPtr; From c098f2ccde424ea399034e43fa621ca0b70e8ace Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 6 Nov 2024 19:46:45 +0100 Subject: [PATCH 08/29] Prevent iterator invalidation during actor traversal --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/actor.hpp | 6 +- apps/openmw/mwmechanics/actors.cpp | 58 ++++++++++++++----- .../mwmechanics/mechanicsmanagerimp.cpp | 2 + 4 files changed, 53 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5435835606..b4617936dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,7 @@ Bug #4754: Stack of ammunition cannot be equipped partially Bug #4816: GetWeaponDrawn returns 1 before weapon is attached Bug #4822: Non-weapon equipment and body parts can't inherit time from parent animation + Bug #4885: Disable in dialogue result script causes a crash Bug #4898: Odd/Incorrect lighting on meshes Bug #5057: Weapon swing sound plays at same pitch whether it hits or misses Bug #5062: Root bone rotations for NPC animation don't work the same as for creature animation diff --git a/apps/openmw/mwmechanics/actor.hpp b/apps/openmw/mwmechanics/actor.hpp index d7438712d9..1cafbe8253 100644 --- a/apps/openmw/mwmechanics/actor.hpp +++ b/apps/openmw/mwmechanics/actor.hpp @@ -62,14 +62,18 @@ namespace MWMechanics void setPositionAdjusted(bool adjusted) { mPositionAdjusted = adjusted; } bool getPositionAdjusted() const { return mPositionAdjusted; } + void invalidate() { mInvalid = true; } + 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..8491cdcb7b 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1247,7 +1247,7 @@ namespace MWMechanics { if (!keepActive) removeTemporaryEffects(iter->second->getPtr()); - mActors.erase(iter->second); + iter->second->invalidate(); mIndex.erase(iter); } } @@ -1299,16 +1299,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 +1326,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 +1392,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 +1512,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 +1575,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 +1634,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 +1701,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 +1759,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 +1848,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 +1869,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 +2068,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 +2085,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 +2096,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 +2111,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 +2383,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/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 384c25953b..f0ba99b0ca 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1725,6 +1725,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 From b2bb12cd1930029f8ba8ad97a9709229bcdcc83b Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 6 Nov 2024 21:33:58 +0100 Subject: [PATCH 09/29] Run ~CharacterController when invalidating an Actor --- apps/openmw/mwmechanics/actor.hpp | 21 +++++++++++++-------- apps/openmw/mwmechanics/actors.cpp | 4 +++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwmechanics/actor.hpp b/apps/openmw/mwmechanics/actor.hpp index 1cafbe8253..6deaba3a95 100644 --- a/apps/openmw/mwmechanics/actor.hpp +++ b/apps/openmw/mwmechanics/actor.hpp @@ -2,6 +2,7 @@ #define OPENMW_MECHANICS_ACTOR_H #include +#include #include "character.hpp" #include "creaturestats.hpp" @@ -29,18 +30,18 @@ namespace MWMechanics { public: Actor(const MWWorld::Ptr& ptr, MWRender::Animation* animation) - : mCharacterController(ptr, animation) - , mPositionAdjusted(ptr.getClass().getCreatureStats(ptr).getFallHeight() > 0) + : mPositionAdjusted(ptr.getClass().getCreatureStats(ptr).getFallHeight() > 0) { + mCharacterController.emplace(ptr, animation); } - const MWWorld::Ptr& getPtr() const { return mCharacterController.getPtr(); } + const MWWorld::Ptr& getPtr() const { return mCharacterController->getPtr(); } /// Notify this actor of its new base object Ptr, use when the object changed cells - void updatePtr(const MWWorld::Ptr& newPtr) { mCharacterController.updatePtr(newPtr); } + void updatePtr(const MWWorld::Ptr& newPtr) { mCharacterController->updatePtr(newPtr); } - CharacterController& getCharacterController() { return mCharacterController; } - const CharacterController& getCharacterController() const { return mCharacterController; } + CharacterController& getCharacterController() { return *mCharacterController; } + const CharacterController& getCharacterController() const { return *mCharacterController; } int getGreetingTimer() const { return mGreetingTimer; } void setGreetingTimer(int timer) { mGreetingTimer = timer; } @@ -62,11 +63,15 @@ namespace MWMechanics void setPositionAdjusted(bool adjusted) { mPositionAdjusted = adjusted; } bool getPositionAdjusted() const { return mPositionAdjusted; } - void invalidate() { mInvalid = true; } + void invalidate() + { + mInvalid = true; + mCharacterController.reset(); + } bool isInvalid() const { return mInvalid; } private: - CharacterController mCharacterController; + std::optional mCharacterController; int mGreetingTimer{ 0 }; float mTargetAngleRadians{ 0.f }; GreetingState mGreetingState{ Greet_None }; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 8491cdcb7b..6d1cdfcb3d 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( From d34aee6257499b2a015ce0d2be4792794f3baa49 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 7 Nov 2024 16:37:28 +0100 Subject: [PATCH 10/29] Allow unsetting a character controller's animation --- apps/openmw/mwmechanics/actor.hpp | 19 ++++--- apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwmechanics/character.cpp | 72 +++++++++++++++------------ apps/openmw/mwmechanics/character.hpp | 15 +++--- apps/openmw/mwmechanics/objects.cpp | 2 +- 5 files changed, 61 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwmechanics/actor.hpp b/apps/openmw/mwmechanics/actor.hpp index 6deaba3a95..69e370ec86 100644 --- a/apps/openmw/mwmechanics/actor.hpp +++ b/apps/openmw/mwmechanics/actor.hpp @@ -2,7 +2,6 @@ #define OPENMW_MECHANICS_ACTOR_H #include -#include #include "character.hpp" #include "creaturestats.hpp" @@ -29,19 +28,19 @@ namespace MWMechanics class Actor { public: - Actor(const MWWorld::Ptr& ptr, MWRender::Animation* animation) - : mPositionAdjusted(ptr.getClass().getCreatureStats(ptr).getFallHeight() > 0) + Actor(const MWWorld::Ptr& ptr, MWRender::Animation& animation) + : mCharacterController(ptr, animation) + , mPositionAdjusted(ptr.getClass().getCreatureStats(ptr).getFallHeight() > 0) { - mCharacterController.emplace(ptr, animation); } - const MWWorld::Ptr& getPtr() const { return mCharacterController->getPtr(); } + const MWWorld::Ptr& getPtr() const { return mCharacterController.getPtr(); } /// Notify this actor of its new base object Ptr, use when the object changed cells - void updatePtr(const MWWorld::Ptr& newPtr) { mCharacterController->updatePtr(newPtr); } + void updatePtr(const MWWorld::Ptr& newPtr) { mCharacterController.updatePtr(newPtr); } - CharacterController& getCharacterController() { return *mCharacterController; } - const CharacterController& getCharacterController() const { return *mCharacterController; } + CharacterController& getCharacterController() { return mCharacterController; } + const CharacterController& getCharacterController() const { return mCharacterController; } int getGreetingTimer() const { return mGreetingTimer; } void setGreetingTimer(int timer) { mGreetingTimer = timer; } @@ -66,12 +65,12 @@ namespace MWMechanics void invalidate() { mInvalid = true; - mCharacterController.reset(); + mCharacterController.detachAnimation(); } bool isInvalid() const { return mInvalid; } private: - std::optional mCharacterController; + CharacterController mCharacterController; int mGreetingTimer{ 0 }; float mTargetAngleRadians{ 0.f }; GreetingState mGreetingState{ Greet_None }; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 6d1cdfcb3d..0df37875f6 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1197,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) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 87cc469eb4..651bff3999 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; @@ -883,14 +883,16 @@ namespace MWMechanics } mDeathState = hitStateToDeathState(mHitState); - if (mDeathState == CharState_None && MWBase::Environment::get().getWorld()->isSwimming(mPtr)) - mDeathState = CharState_SwimDeath; - - if (mDeathState == CharState_None || !mAnimation->hasAnimation(deathStateToAnimGroup(mDeathState))) - mDeathState = chooseRandomDeathState(); + if (mDeathState == CharState_None) + { + if (MWBase::Environment::get().getWorld()->isSwimming(mPtr)) + mDeathState = CharState_SwimDeath; + else if (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 +912,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,11 +991,17 @@ namespace MWMechanics } CharacterController::~CharacterController() + { + detachAnimation(); + } + + void CharacterController::detachAnimation() { if (mAnimation) { persistAnimationState(); mAnimation->setTextKeyListener(nullptr); + mAnimation = nullptr; } } @@ -1066,7 +1071,7 @@ namespace MWMechanics std::string_view action = evt.substr(groupname.size() + 2); if (action == "equip attach") { - if (mUpperBodyState == UpperBodyState::Equipping) + if (mUpperBodyState == UpperBodyState::Equipping && mAnimation) { if (groupname == "shield") mAnimation->showCarriedLeft(true); @@ -1076,7 +1081,7 @@ namespace MWMechanics } else if (action == "unequip detach") { - if (mUpperBodyState == UpperBodyState::Unequipping) + if (mUpperBodyState == UpperBodyState::Unequipping && mAnimation) { if (groupname == "shield") mAnimation->showCarriedLeft(false); @@ -1148,18 +1153,18 @@ namespace MWMechanics mPtr, mAttackStrength, ESM::Weapon::AT_Thrust, mAttackVictim, mAttackHitPos, mAttackSuccess); } } - else if (action == "shoot attach") + else if (action == "shoot attach" && mAnimation) mAnimation->attachArrow(); else if (action == "shoot release") { // See notes for melee release above - if (mReadyToHit) + if (mReadyToHit && mAnimation) { mAnimation->releaseArrow(mAttackStrength); mReadyToHit = false; } } - else if (action == "shoot follow attach") + else if (action == "shoot follow attach" && mAnimation) mAnimation->attachArrow(); // Make sure this key is actually for the RangeType we are casting. The flame atronach has // the same animation for all range types, so there are 3 "release" keys on the same time, one for each range @@ -1232,7 +1237,8 @@ namespace MWMechanics float CharacterController::calculateWindUp() const { - if (mCurrentWeapon.empty() || mWeaponType == ESM::Weapon::PickProbe || isRandomAttackAnimation(mCurrentWeapon)) + if (mCurrentWeapon.empty() || mWeaponType == ESM::Weapon::PickProbe || isRandomAttackAnimation(mCurrentWeapon) + || !mAnimation) return -1.f; float minAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon + ": " + mAttackType + " min attack"); @@ -1950,6 +1956,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 +2536,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 +2749,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 +2869,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 +2931,7 @@ namespace MWMechanics bool CharacterController::isReadyToBlock() const { - return updateCarriedLeftVisible(mWeaponType); + return mAnimation && updateCarriedLeftVisible(mWeaponType); } bool CharacterController::isKnockedDown() const @@ -3030,7 +3035,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 +3067,8 @@ namespace MWMechanics float CharacterController::getAnimationMovementDirection() const { + if (!mAnimation) + return 0.f; switch (mMovementState) { case CharState_RunLeft: @@ -3155,6 +3163,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/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); } From 35eed6826940fa25256fbfcdba2427a3d25ddfb0 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Mon, 18 Nov 2024 17:26:43 +0100 Subject: [PATCH 11/29] Move null checks to address feedback --- apps/openmw/mwmechanics/character.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 651bff3999..cfe076184d 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1008,6 +1008,8 @@ namespace MWMechanics 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); @@ -1153,18 +1155,18 @@ namespace MWMechanics mPtr, mAttackStrength, ESM::Weapon::AT_Thrust, mAttackVictim, mAttackHitPos, mAttackSuccess); } } - else if (action == "shoot attach" && mAnimation) + else if (action == "shoot attach") mAnimation->attachArrow(); else if (action == "shoot release") { // See notes for melee release above - if (mReadyToHit && mAnimation) + if (mAttackStrength != -1.f && mAnimation) { mAnimation->releaseArrow(mAttackStrength); mReadyToHit = false; } } - else if (action == "shoot follow attach" && mAnimation) + else if (action == "shoot follow attach") mAnimation->attachArrow(); // Make sure this key is actually for the RangeType we are casting. The flame atronach has // the same animation for all range types, so there are 3 "release" keys on the same time, one for each range @@ -1237,8 +1239,8 @@ namespace MWMechanics float CharacterController::calculateWindUp() const { - if (mCurrentWeapon.empty() || mWeaponType == ESM::Weapon::PickProbe || isRandomAttackAnimation(mCurrentWeapon) - || !mAnimation) + if (!mAnimation || mCurrentWeapon.empty() || mWeaponType == ESM::Weapon::PickProbe + || isRandomAttackAnimation(mCurrentWeapon)) return -1.f; float minAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon + ": " + mAttackType + " min attack"); From 1dfa2629f020ea04b45f5144768f43f482a27982 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Mon, 18 Nov 2024 19:57:57 +0100 Subject: [PATCH 12/29] Remove more redundant checks --- apps/openmw/mwmechanics/character.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index cfe076184d..a22220bcda 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1073,7 +1073,7 @@ namespace MWMechanics std::string_view action = evt.substr(groupname.size() + 2); if (action == "equip attach") { - if (mUpperBodyState == UpperBodyState::Equipping && mAnimation) + if (mUpperBodyState == UpperBodyState::Equipping) { if (groupname == "shield") mAnimation->showCarriedLeft(true); @@ -1083,7 +1083,7 @@ namespace MWMechanics } else if (action == "unequip detach") { - if (mUpperBodyState == UpperBodyState::Unequipping && mAnimation) + if (mUpperBodyState == UpperBodyState::Unequipping) { if (groupname == "shield") mAnimation->showCarriedLeft(false); From 39cc8936396772d1424f07ddf095091e9559050d Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sat, 19 Jul 2025 09:38:44 +0200 Subject: [PATCH 13/29] Unbreak swimdeath fallback --- CHANGELOG.md | 1 - apps/openmw/mwmechanics/character.cpp | 15 +++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4617936dd..5435835606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,7 +80,6 @@ Bug #4754: Stack of ammunition cannot be equipped partially Bug #4816: GetWeaponDrawn returns 1 before weapon is attached Bug #4822: Non-weapon equipment and body parts can't inherit time from parent animation - Bug #4885: Disable in dialogue result script causes a crash Bug #4898: Odd/Incorrect lighting on meshes Bug #5057: Weapon swing sound plays at same pitch whether it hits or misses Bug #5062: Root bone rotations for NPC animation don't work the same as for creature animation diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index a22220bcda..77f1ef6d15 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -883,13 +883,12 @@ namespace MWMechanics } mDeathState = hitStateToDeathState(mHitState); - if (mDeathState == CharState_None) - { - if (MWBase::Environment::get().getWorld()->isSwimming(mPtr)) - mDeathState = CharState_SwimDeath; - else if (mAnimation && !mAnimation->hasAnimation(deathStateToAnimGroup(mDeathState))) - mDeathState = chooseRandomDeathState(); - } + if (mDeathState == CharState_None && MWBase::Environment::get().getWorld()->isSwimming(mPtr)) + mDeathState = CharState_SwimDeath; + + if (mDeathState == CharState_None + || (mAnimation && !mAnimation->hasAnimation(deathStateToAnimGroup(mDeathState)))) + mDeathState = chooseRandomDeathState(); // Do not interrupt scripted animation by death if (!mAnimation || isScriptedAnimPlaying()) @@ -1160,7 +1159,7 @@ namespace MWMechanics else if (action == "shoot release") { // See notes for melee release above - if (mAttackStrength != -1.f && mAnimation) + if (mAttackStrength != -1.f && mAnimation) { mAnimation->releaseArrow(mAttackStrength); mReadyToHit = false; From 10602a0412dab88bb5734e5f9d47c5418dde5662 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sat, 19 Jul 2025 12:03:06 +0300 Subject: [PATCH 14/29] Don't run some non-essential jobs on upstream branch pushes --- .gitlab-ci.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 42074a0667..119126de64 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 From 01fa3cc4e61b2fcc86cf4230502f56f9890d190b Mon Sep 17 00:00:00 2001 From: Aussiemon <1407091-Aussiemon@users.noreply.gitlab.com> Date: Sun, 20 Jul 2025 10:05:24 -0600 Subject: [PATCH 15/29] Subtract Charm from permanent disposition clamp range --- apps/openmw/mwdialogue/dialoguemanagerimp.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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; From 28851411a321c5eace03d5a52f8a210dd137110e Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 20 Jul 2025 11:00:19 +0200 Subject: [PATCH 16/29] Fix and enforce namespace naming --- .clang-tidy | 4 ++ apps/components_tests/fx/lexer.cpp | 2 +- apps/components_tests/fx/technique.cpp | 2 +- apps/components_tests/lua/testl10n.cpp | 2 +- apps/launcher/main.cpp | 2 +- apps/openmw/engine.cpp | 2 +- apps/openmw/engine.hpp | 4 +- apps/openmw/mwbase/environment.hpp | 8 ++-- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/loadingscreen.cpp | 2 +- apps/openmw/mwgui/mapwindow.cpp | 13 +++--- apps/openmw/mwgui/postprocessorhud.cpp | 42 +++++++++---------- apps/openmw/mwgui/race.cpp | 2 +- apps/openmw/mwgui/savegamedialog.cpp | 2 +- apps/openmw/mwgui/videowidget.cpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 8 ++-- apps/openmw/mwgui/windowmanagerimp.hpp | 2 +- apps/openmw/mwlua/postprocessingbindings.cpp | 4 +- apps/openmw/mwrender/pingpongcanvas.cpp | 6 +-- apps/openmw/mwrender/pingpongcanvas.hpp | 12 +++--- apps/openmw/mwrender/postprocessor.cpp | 42 +++++++++---------- apps/openmw/mwrender/postprocessor.hpp | 22 +++++----- apps/wizard/main.cpp | 2 +- components/fallback/validate.hpp | 2 + components/files/configurationmanager.hpp | 2 + components/fontloader/fontloader.cpp | 6 +-- components/fx/lexer.cpp | 2 +- components/fx/lexer.hpp | 2 +- components/fx/lexertypes.hpp | 2 +- components/fx/parseconstants.hpp | 6 +-- components/fx/pass.cpp | 2 +- components/fx/pass.hpp | 2 +- components/fx/stateupdater.cpp | 2 +- components/fx/stateupdater.hpp | 2 +- components/fx/technique.cpp | 34 +++++++-------- components/fx/technique.hpp | 4 +- components/fx/types.hpp | 2 +- components/fx/widgets.cpp | 8 ++-- components/fx/widgets.hpp | 8 ++-- components/l10n/manager.cpp | 2 +- components/l10n/manager.hpp | 2 +- components/l10n/messagebundles.cpp | 2 +- components/l10n/messagebundles.hpp | 2 +- components/l10n/qttranslations.cpp | 2 +- components/l10n/qttranslations.hpp | 2 +- components/lua/l10n.cpp | 4 +- components/lua/l10n.hpp | 4 +- components/lua/luastate.cpp | 2 +- components/lua/luastate.hpp | 4 +- components/myguiplatform/additivelayer.cpp | 2 +- components/myguiplatform/additivelayer.hpp | 2 +- components/myguiplatform/myguidatamanager.cpp | 2 +- components/myguiplatform/myguidatamanager.hpp | 2 +- components/myguiplatform/myguiloglistener.cpp | 2 +- components/myguiplatform/myguiloglistener.hpp | 2 +- components/myguiplatform/myguiplatform.cpp | 2 +- components/myguiplatform/myguiplatform.hpp | 2 +- .../myguiplatform/myguirendermanager.cpp | 14 +++---- .../myguiplatform/myguirendermanager.hpp | 2 +- components/myguiplatform/myguitexture.cpp | 2 +- components/myguiplatform/myguitexture.hpp | 2 +- components/myguiplatform/scalinglayer.cpp | 2 +- components/myguiplatform/scalinglayer.hpp | 2 +- 63 files changed, 175 insertions(+), 166 deletions(-) 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/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/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/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/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index c558f1bad9..e45388b2e0 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -91,7 +91,7 @@ namespace MWGui , mUpdateNextFrame(false) { mPreviewTexture - = std::make_unique(mPreview->getTexture(), mPreview->getTextureStateSet()); + = std::make_unique(mPreview->getTexture(), mPreview->getTextureStateSet()); mPreview->rebuild(); mMainWidget->castType()->eventWindowChangeCoord 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 bf4bd7644c..59d21886dc 100644 --- a/apps/openmw/mwgui/mapwindow.cpp +++ b/apps/openmw/mwgui/mapwindow.cpp @@ -599,27 +599,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; } @@ -1280,11 +1280,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..68be9a7d4a 100644 --- a/apps/openmw/mwgui/postprocessorhud.cpp +++ b/apps/openmw/mwgui/postprocessorhud.cpp @@ -35,9 +35,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); } } @@ -110,7 +110,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(); } } @@ -309,7 +309,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 +330,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 +360,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 +398,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 +489,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/race.cpp b/apps/openmw/mwgui/race.cpp index 7b445d419f..c7de8f4125 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -154,7 +154,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 4957789ffd..eec3b7bfe6 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -488,7 +488,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/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 c7c4b575a5..358816221d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -205,7 +205,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(); @@ -229,8 +229,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(); @@ -1127,7 +1127,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 b04c648986..c231718db6 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -402,7 +402,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/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/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/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/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 From 30cfb42ed1e21716ace66c44b47c0f9d09fc0365 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Mon, 21 Jul 2025 17:57:51 +0200 Subject: [PATCH 17/29] Fix rebase fallout --- apps/openmw/mwmechanics/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 77f1ef6d15..1aac063ce3 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1159,7 +1159,7 @@ namespace MWMechanics else if (action == "shoot release") { // See notes for melee release above - if (mAttackStrength != -1.f && mAnimation) + if (mReadyToHit) { mAnimation->releaseArrow(mAttackStrength); mReadyToHit = false; From 93cde36b09732f2dd06b8882fab7e9952e6f1ee2 Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Mon, 9 Jun 2025 12:05:01 +0300 Subject: [PATCH 18/29] Deduplicate GetPCRunning logic --- apps/openmw/mwclass/creature.cpp | 4 +-- apps/openmw/mwclass/npc.cpp | 25 ++++++------------- .../mwmechanics/mechanicsmanagerimp.cpp | 21 ++++++++++++---- apps/openmw/mwscript/controlextensions.cpp | 9 +------ 4 files changed, 26 insertions(+), 33 deletions(-) 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/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 384c25953b..d09b5b3f9b 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) 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)); } }; From 044c556f0eeeae8e297bfb1dc35b137dd6814a67 Mon Sep 17 00:00:00 2001 From: Aussiemon <1407091-Aussiemon@users.noreply.gitlab.com> Date: Wed, 23 Jul 2025 03:31:38 -0600 Subject: [PATCH 19/29] Fix precision issue with container capacity check --- apps/openmw/mwgui/containeritemmodel.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) 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; From 324bdf8f7ad7133672c3bc34b513473bd2c3161f Mon Sep 17 00:00:00 2001 From: Jared Davenport Date: Wed, 23 Jul 2025 09:32:04 +0000 Subject: [PATCH 20/29] Save user settings when closing windows --- apps/openmw/mwbase/inputmanager.hpp | 2 ++ apps/openmw/mwbase/luamanager.hpp | 2 ++ apps/openmw/mwgui/postprocessorhud.cpp | 6 +++- apps/openmw/mwgui/postprocessorhud.hpp | 5 +++- apps/openmw/mwgui/settingswindow.cpp | 13 ++++++++- apps/openmw/mwgui/settingswindow.hpp | 6 +++- apps/openmw/mwgui/windowmanagerimp.cpp | 4 +-- apps/openmw/mwinput/bindingsmanager.cpp | 39 ++++++++++++++----------- apps/openmw/mwinput/bindingsmanager.hpp | 2 ++ apps/openmw/mwinput/inputmanagerimp.cpp | 5 ++++ apps/openmw/mwinput/inputmanagerimp.hpp | 2 ++ apps/openmw/mwlua/luamanagerimp.hpp | 2 +- 12 files changed, 64 insertions(+), 24 deletions(-) diff --git a/apps/openmw/mwbase/inputmanager.hpp b/apps/openmw/mwbase/inputmanager.hpp index 5ee20476b3..de6cf91f4e 100644 --- a/apps/openmw/mwbase/inputmanager.hpp +++ b/apps/openmw/mwbase/inputmanager.hpp @@ -88,6 +88,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/mwgui/postprocessorhud.cpp b/apps/openmw/mwgui/postprocessorhud.cpp index cc95203a0f..3d13988937 100644 --- a/apps/openmw/mwgui/postprocessorhud.cpp +++ b/apps/openmw/mwgui/postprocessorhud.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -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"); @@ -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); } 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/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 02353c5d41..77032623d2 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"; @@ -1092,6 +1095,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 dc4e09f8ac..22a15eab97 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(); @@ -120,6 +123,7 @@ namespace MWGui private: void resetScrollbars(); + Files::ConfigurationManager& mCfgMgr; }; } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index c7c4b575a5..cc0d493a26 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -409,7 +409,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()); @@ -503,7 +503,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()); 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 328757a954..d81d720b21 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -246,4 +246,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 39a1133db5..46e4774b6b 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -106,6 +106,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. // From 52b785f7266d9b7532c3ffffd0f4ddf355e44726 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 23 Jul 2025 23:18:03 +0100 Subject: [PATCH 21/29] Use updated Windows dependencies The main changes are changing an OSG option that was disabling most of our warnings, and MSVC2019 switching to a custom vcpkg triplet. --- .gitlab-ci.yml | 4 ++-- CI/before_script.msvc.sh | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 119126de64..070b7c54d5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -702,7 +702,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 @@ -860,7 +860,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/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 From be54521cfa1a526d2d0e2fa2a9d5c14a82001a7b Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 24 Jul 2025 00:20:05 +0100 Subject: [PATCH 22/29] Fix loads of warnings These weren't detected due to https://gitlab.com/OpenMW/openmw/-/issues/7882, but now they are, so they can be fixed. --- apps/components_tests/esm3/testsaveload.cpp | 2 +- apps/essimporter/converter.hpp | 2 +- apps/navmeshtool/worldspacedata.cpp | 4 ++-- apps/opencs/model/world/infoselectwrapper.cpp | 4 ---- apps/opencs/model/world/refidcollection.cpp | 1 - apps/openmw/mwrender/animation.hpp | 2 +- apps/openmw/mwrender/pathgrid.cpp | 2 -- apps/openmw/mwsound/openaloutput.cpp | 2 +- apps/openmw/mwworld/inventorystore.cpp | 3 ++- components/lua/configuration.cpp | 2 +- components/nifosg/nifloader.cpp | 2 +- components/sceneutil/riggeometry.cpp | 2 +- components/terrain/material.cpp | 2 +- 13 files changed, 12 insertions(+), 18 deletions(-) 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/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/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/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/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..24e41e6016 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -54,8 +54,9 @@ void MWWorld::InventoryStore::storeEquipmentState( inventory.mEquipmentSlots[static_cast(index)] = i; } + // I'm not sure if the narrowing cast below is safe, but I think it'd break the save format if I widen the destination type if (mSelectedEnchantItem.getType() != -1 && mSelectedEnchantItem->getBase() == &ref) - inventory.mSelectedEnchantItem = index; + inventory.mSelectedEnchantItem = static_cast(index); } void MWWorld::InventoryStore::readEquipmentState( diff --git a/components/lua/configuration.cpp b/components/lua/configuration.cpp index b327270fc1..0bd04c1359 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(mScripts.size()); ++i) { const ESM::LuaScriptCfg& script = cfg.mScripts[i]; bool global = script.mFlags & ESM::LuaScriptCfg::sGlobal; diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 07eb342221..d9e20e810a 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1683,7 +1683,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()) diff --git a/components/sceneutil/riggeometry.cpp b/components/sceneutil/riggeometry.cpp index d93b88349d..f010f0dfaf 100644 --- a/components/sceneutil/riggeometry.cpp +++ b/components/sceneutil/riggeometry.cpp @@ -346,7 +346,7 @@ 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()); diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index 09d2680acd..9a0510f0ff 100644 --- a/components/terrain/material.cpp +++ b/components/terrain/material.cpp @@ -43,7 +43,7 @@ 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; } From f8a96fae24815ceb953785d20a979dca5aac8322 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 24 Jul 2025 00:26:47 +0100 Subject: [PATCH 23/29] Some formatting changes I missed --- apps/openmw/mwworld/inventorystore.cpp | 3 ++- components/terrain/material.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 24e41e6016..3ab48bafd8 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -54,7 +54,8 @@ void MWWorld::InventoryStore::storeEquipmentState( inventory.mEquipmentSlots[static_cast(index)] = i; } - // I'm not sure if the narrowing cast below is safe, but I think it'd break the save format if I widen the destination type + // I'm not sure if the narrowing cast below is safe, but I think it'd break the save format if I widen the + // destination type if (mSelectedEnchantItem.getType() != -1 && mSelectedEnchantItem->getBase() == &ref) inventory.mSelectedEnchantItem = static_cast(index); } diff --git a/components/terrain/material.cpp b/components/terrain/material.cpp index 9a0510f0ff..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(static_cast(blendmapScale), new osg::TexMat(matrix))).first; + texMat = mTexMatMap.insert(std::make_pair(static_cast(blendmapScale), new osg::TexMat(matrix))) + .first; } return texMat->second; } From 092d9a4c621cf0e5b9364045b8c86ab4f22ef105 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 24 Jul 2025 00:35:22 +0100 Subject: [PATCH 24/29] Remove dumb comment --- apps/openmw/mwworld/inventorystore.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 3ab48bafd8..86af303341 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -54,8 +54,6 @@ void MWWorld::InventoryStore::storeEquipmentState( inventory.mEquipmentSlots[static_cast(index)] = i; } - // I'm not sure if the narrowing cast below is safe, but I think it'd break the save format if I widen the - // destination type if (mSelectedEnchantItem.getType() != -1 && mSelectedEnchantItem->getBase() == &ref) inventory.mSelectedEnchantItem = static_cast(index); } From 437f22ed72ecb821362fed420778ec20a98433dd Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 24 Jul 2025 00:37:28 +0100 Subject: [PATCH 25/29] Typo fix --- components/lua/configuration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/lua/configuration.cpp b/components/lua/configuration.cpp index 0bd04c1359..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 (int i = 0; i < static_cast(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; From ad996393f1981dd3ee28f0a4f7af97746b69122c Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Mon, 10 Mar 2025 15:54:36 +0300 Subject: [PATCH 26/29] Apply filtering settings to composite maps --- components/terrain/chunkmanager.cpp | 26 ++++++++++++++++++++++++-- components/terrain/chunkmanager.hpp | 2 ++ components/terrain/world.cpp | 2 ++ 3 files changed, 28 insertions(+), 2 deletions(-) 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/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() From 8d7218c118867736981bdf0bad9ba67aa3e9a1b5 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sat, 30 Nov 2024 13:23:47 +0100 Subject: [PATCH 27/29] Take skin transform and skeleton root into account --- components/nifosg/nifloader.cpp | 3 + components/sceneutil/riggeometry.cpp | 88 +++++++++++++++++++--------- components/sceneutil/riggeometry.hpp | 12 +++- 3 files changed, 72 insertions(+), 31 deletions(-) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 07eb342221..0f2382457f 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; } diff --git a/components/sceneutil/riggeometry.cpp b/components/sceneutil/riggeometry.cpp index d93b88349d..8eb22895cf 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); } } } @@ -352,6 +368,20 @@ namespace SceneUtil 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); }; } From e3c9e6fe2baa46cf7e8ca8d817bf9f7518d1e980 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 24 Jul 2025 08:46:21 +0200 Subject: [PATCH 28/29] Set a root for BS skins as well --- components/nifosg/nifloader.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 0f2382457f..88c9feee21 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1732,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; } From f52d9ad9773583a528d2accba50634487f2d00d8 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Thu, 24 Jul 2025 17:02:42 +0200 Subject: [PATCH 29/29] Prevent hostile actors from engaging combat against actors with 75 chameleon --- apps/openmw/mwmechanics/actors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 0df37875f6..3ba6bfdc8d 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -683,7 +683,7 @@ namespace MWMechanics } } - if (creatureStats2.getMagicEffects().getOrDefault(ESM::MagicEffect::Invisibility).getMagnitude() > 0) + if (isTargetMagicallyHidden(actor2)) return; // Stop here if target is unreachable