From de4d97826a5f23e467a538ba6fd2880f23b41310 Mon Sep 17 00:00:00 2001 From: Sam Hellawell Date: Tue, 30 Jul 2024 23:21:10 +0100 Subject: [PATCH 1/5] Fix: castRenderingRay doesnt hit terrain --- apps/openmw/mwrender/renderingmanager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index eefdd64528..07288c278b 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -1061,9 +1061,15 @@ namespace MWRender auto test = [&](const osgUtil::LineSegmentIntersector::Intersection& intersection) { PtrHolder* ptrHolder = nullptr; std::vector refnumMarkers; + bool hitNonObjectWorld = false; for (osg::NodePath::const_iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it) { + // Terrain doesnt contain any user data ptrs or flags, so we have to check the name + // TODO: better solution for this that could also be used for water and other world pieces with flags + if (!hitNonObjectWorld) + hitNonObjectWorld = (*it)->getName() == std::string_view("Terrain Root"); + osg::UserDataContainer* userDataContainer = (*it)->getUserDataContainer(); if (!userDataContainer) continue; @@ -1109,7 +1115,7 @@ namespace MWRender vertexCounter += refnumMarkers[i]->mNumVertices; } - if (!result.mHitObject.isEmpty() || result.mHitRefnum.isSet()) + if (!result.mHitObject.isEmpty() || result.mHitRefnum.isSet() || hitNonObjectWorld) { result.mHit = true; result.mHitPointWorld = intersection.getWorldIntersectPoint(); From ae0660db0aabab89cfa4f0ef259497d534308d81 Mon Sep 17 00:00:00 2001 From: Sam Hellawell Date: Wed, 31 Jul 2024 00:30:06 +0100 Subject: [PATCH 2/5] Use nodeMask... lets ignore the previous attempt --- apps/openmw/mwrender/renderingmanager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 07288c278b..7048f7c933 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -1051,6 +1051,7 @@ namespace MWRender RenderingManager::RayResult getIntersectionResult(osgUtil::LineSegmentIntersector* intersector, const osg::ref_ptr& visitor, std::span ignoreList = {}) { + constexpr auto nonObjectWorldMask = Mask_Terrain | Mask_Water; RenderingManager::RayResult result; result.mHit = false; result.mRatio = 0; @@ -1065,10 +1066,9 @@ namespace MWRender for (osg::NodePath::const_iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end(); ++it) { - // Terrain doesnt contain any user data ptrs or flags, so we have to check the name - // TODO: better solution for this that could also be used for water and other world pieces with flags + const auto& nodeMask = (*it)->getNodeMask(); if (!hitNonObjectWorld) - hitNonObjectWorld = (*it)->getName() == std::string_view("Terrain Root"); + hitNonObjectWorld = nodeMask & nonObjectWorldMask; osg::UserDataContainer* userDataContainer = (*it)->getUserDataContainer(); if (!userDataContainer) From 2df8c135253bf306e472a24001f5bc8b2b59df8e Mon Sep 17 00:00:00 2001 From: uramer Date: Wed, 7 Aug 2024 19:05:47 +0200 Subject: [PATCH 3/5] Lua triggers to cover remaining deprecated actions --- files/data/l10n/OMWControls/en.yaml | 46 +++++++++++++++++++ .../data/scripts/omw/input/actionbindings.lua | 32 +++++++++++++ 2 files changed, 78 insertions(+) diff --git a/files/data/l10n/OMWControls/en.yaml b/files/data/l10n/OMWControls/en.yaml index d4df56436b..1be6da6baf 100644 --- a/files/data/l10n/OMWControls/en.yaml +++ b/files/data/l10n/OMWControls/en.yaml @@ -82,3 +82,49 @@ SmoothMoveLeft_description: "Left movement adjusted for smooth Walk-Run transiti SmoothMoveRight_name: "Smooth Move Right" SmoothMoveRight_description: "Right movement adjusted for smooth Walk-Run transitions." + +# Non-dehardcoded actions +Activate_name: "Activate" +Activate_description: "Fallback for input.ACTIONS.Activate, binding does not do anything yet" +Console_name: "Console" +Console_description: "Fallback for input.ACTIONS.Console, binding does not do anything yet" +CycleSpellLeft_name: "CycleSpellLeft" +CycleSpellLeft_description: "Fallback for input.ACTIONS.CycleSpellLeft, binding does not do anything yet" +CycleSpellRight_name: "CycleSpellRight" +CycleSpellRight_description: "Fallback for input.ACTIONS.CycleSpellRight, binding does not do anything yet" +CycleWeaponLeft_name: "CycleWeaponLeft" +CycleWeaponLeft_description: "Fallback for input.ACTIONS.CycleWeaponLeft, binding does not do anything yet" +CycleWeaponRight_name: "CycleWeaponRight" +CycleWeaponRight_description: "Fallback for input.ACTIONS.CycleWeaponRight, binding does not do anything yet" +GameMenu_name: "GameMenu" +GameMenu_description: "Fallback for input.ACTIONS.GameMenu, binding does not do anything yet" +QuickLoad_name: "QuickLoad" +QuickLoad_description: "Fallback for input.ACTIONS.QuickLoad, binding does not do anything yet" +QuickSave_name: "QuickSave" +QuickSave_description: "Fallback for input.ACTIONS.QuickSave, binding does not do anything yet" +Screenshot_name: "Screenshot" +Screenshot_description: "Fallback for input.ACTIONS.Screenshot, binding does not do anything yet" +ToggleDebug_name: "ToggleDebug" +ToggleDebug_description: "Fallback for input.ACTIONS.ToggleDebug, binding does not do anything yet" +ToggleHUD_name: "ToggleHUD" +ToggleHUD_description: "Fallback for input.ACTIONS.ToggleHUD, binding does not do anything yet" +TogglePostProcessorHUD_name: "TogglePostProcessorHUD" +TogglePostProcessorHUD_description: "Fallback for input.ACTIONS.TogglePostProcessorHUD, binding does not do anything yet" +QuickKey1_name: "QuickKey1" +QuickKey1_description: "Fallback for input.ACTIONS.QuickKey1, binding does not do anything yet" +QuickKey2_name: "QuickKey2" +QuickKey2_description: "Fallback for input.ACTIONS.QuickKey2, binding does not do anything yet" +QuickKey3_name: "QuickKey3" +QuickKey3_description: "Fallback for input.ACTIONS.QuickKey3, binding does not do anything yet" +QuickKey4_name: "QuickKey4" +QuickKey4_description: "Fallback for input.ACTIONS.QuickKey4, binding does not do anything yet" +QuickKey5_name: "QuickKey5" +QuickKey5_description: "Fallback for input.ACTIONS.QuickKey5, binding does not do anything yet" +QuickKey6_name: "QuickKey6" +QuickKey6_description: "Fallback for input.ACTIONS.QuickKey6, binding does not do anything yet" +QuickKey7_name: "QuickKey7" +QuickKey7_description: "Fallback for input.ACTIONS.QuickKey7, binding does not do anything yet" +QuickKey8_name: "QuickKey8" +QuickKey8_description: "Fallback for input.ACTIONS.QuickKey8, binding does not do anything yet" +QuickKey9_name: "QuickKey9" +QuickKey9_description: "Fallback for input.ACTIONS.QuickKey9, binding does not do anything yet" diff --git a/files/data/scripts/omw/input/actionbindings.lua b/files/data/scripts/omw/input/actionbindings.lua index bc871a3934..741376bc75 100644 --- a/files/data/scripts/omw/input/actionbindings.lua +++ b/files/data/scripts/omw/input/actionbindings.lua @@ -29,6 +29,38 @@ local function bindTrigger(key, actionid) end) end +do -- Actions and Triggers currently unused by builtin scripts + -- TODO: as more mechanics are dehardcoded, move these declarations to relevant files + local triggers = { + Activate = input.ACTION.Activate, + Console = input.ACTION.Console, + CycleSpellLeft = input.ACTION.CycleSpellLeft, + CycleSpellRight = input.ACTION.CycleSpellRight, + CycleWeaponLeft = input.ACTION.CycleWeaponLeft, + CycleWeaponRight = input.ACTION.CycleWeaponRight, + GameMenu = input.ACTION.GameMenu, + QuickLoad = input.ACTION.QuickLoad, + QuickSave = input.ACTION.QuickSave, + Screenshot = input.ACTION.Screenshot, + ToggleDebug = input.ACTION.ToggleDebug, + ToggleHUD = input.ACTION.ToggleHUD, + TogglePostProcessorHUD = input.ACTION.ToggleHUD, + } + for i = 1, 9 do + local key = string.format('QuickKey%s', i) + triggers[key] = input.ACTION[key] + end + for key, action in pairs(triggers) do + input.registerTrigger { + key = key, + l10n = 'OMWControls', + name = key .. '_name', + description = key .. '_description', + } + bindTrigger(key, action) + end +end + bindTrigger('AlwaysRun', input.ACTION.AlwaysRun) bindTrigger('ToggleSneak', input.ACTION.Sneak) bindTrigger('ToggleWeapon', input.ACTION.ToggleWeapon) From ab628ea12a1ed97c3096d7d29bad0c3f1e6a231d Mon Sep 17 00:00:00 2001 From: uramer Date: Wed, 7 Aug 2024 19:20:12 +0200 Subject: [PATCH 4/5] Fix memory safety of actions/triggers iteration --- apps/openmw/mwlua/inputbindings.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwlua/inputbindings.cpp b/apps/openmw/mwlua/inputbindings.cpp index dbe79ca377..d26de4336a 100644 --- a/apps/openmw/mwlua/inputbindings.cpp +++ b/apps/openmw/mwlua/inputbindings.cpp @@ -71,9 +71,10 @@ namespace MWLua = [](LuaUtil::InputAction::Registry& registry, std::string_view key) { return registry[key]; }; { auto pairs = [](LuaUtil::InputAction::Registry& registry) { - auto next = [](LuaUtil::InputAction::Registry& registry, std::string_view key) - -> sol::optional> { - std::optional nextKey(registry.nextKey(key)); + auto next + = [](LuaUtil::InputAction::Registry& registry, + std::string_view key) -> sol::optional> { + std::optional nextKey(registry.nextKey(key)); if (!nextKey.has_value()) return sol::nullopt; else @@ -102,9 +103,10 @@ namespace MWLua = [](LuaUtil::InputTrigger::Registry& registry, std::string_view key) { return registry[key]; }; { auto pairs = [](LuaUtil::InputTrigger::Registry& registry) { - auto next = [](LuaUtil::InputTrigger::Registry& registry, std::string_view key) - -> sol::optional> { - std::optional nextKey(registry.nextKey(key)); + auto next + = [](LuaUtil::InputTrigger::Registry& registry, + std::string_view key) -> sol::optional> { + std::optional nextKey(registry.nextKey(key)); if (!nextKey.has_value()) return sol::nullopt; else From 9a15d5095cc9e9a51eb4d6b9d920c6cddac218e3 Mon Sep 17 00:00:00 2001 From: uramer Date: Thu, 8 Aug 2024 00:05:33 +0200 Subject: [PATCH 5/5] Clarify action/trigger usage in input module docs --- files/lua_api/openmw/input.lua | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/files/lua_api/openmw/input.lua b/files/lua_api/openmw/input.lua index a34bc040da..b8e5e51261 100644 --- a/files/lua_api/openmw/input.lua +++ b/files/lua_api/openmw/input.lua @@ -1,7 +1,34 @@ --- -- `openmw.input` can be used only in menu scripts and scripts attached to a player. +-- Most mods should prefer to use the actions/triggers API over the direct input device methods. +-- Actions have one value on each frame (resolved just before the `onFrame` engine handler), +-- while Triggers don't have a value, but can occur multiple times on each frame. +-- Prefer to use built-in methods of binding actions, such as the [inputBinding setting renderer](setting_renderers.html#inputbinding) -- @module input -- @usage local input = require('openmw.input') +-- -- Example of Action usage +-- input.registerAction { +-- key = 'MyAction', +-- type = input.ACTION_TYPE.Boolean, +-- l10n = 'MyLocalizationContext', +-- name = 'MyAction_name', +-- description = 'MyAction_full_description', +-- defaultValue = false, +-- } +-- return { +-- onFrame = function() +-- local myAction = input.getBooleanActionValue('MyAction') +-- if (myAction) then print('My action is active!') end +-- end, +-- } +-- -- Example of Trigger usage +-- input.registerTrigger { +-- key = 'MyTrigger', +-- l10n = 'MyLocalizationContext', +-- name = 'MyTrigger_name', +-- description = 'MyTrigger_full_description', +-- } +-- input.registerTriggerHandler('MyTrigger', async:callback(function() print('MyTrigger') end))