1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-31 23:45:35 +00:00
openmw/files/data/scripts/omw/input/actionbindings.lua

230 lines
7.8 KiB
Lua
Raw Normal View History

2023-12-29 18:56:59 +00:00
local input = require('openmw.input')
local util = require('openmw.util')
local async = require('openmw.async')
local storage = require('openmw.storage')
local actionPressHandlers = {}
local function onActionPress(id, handler)
actionPressHandlers[id] = actionPressHandlers[id] or {}
table.insert(actionPressHandlers[id], handler)
end
local function bindHold(key, actionId)
input.bindAction(key, async:callback(function()
return input.isActionPressed(actionId)
end), {})
end
local function bindMovement(key, actionId, axisId, direction)
input.bindAction(key, async:callback(function()
local actionActive = input.isActionPressed(actionId)
local axisActive = input.getAxisValue(axisId) * direction > 0
return (actionActive or axisActive) and 1 or 0
end), {})
end
local function bindTrigger(key, actionid)
onActionPress(actionid, function()
input.activateTrigger(key)
end)
end
bindTrigger('AlwaysRun', input.ACTION.AlwaysRun)
bindTrigger('ToggleSneak', input.ACTION.Sneak)
bindTrigger('ToggleWeapon', input.ACTION.ToggleWeapon)
bindTrigger('ToggleSpell', input.ACTION.ToggleSpell)
bindTrigger('Jump', input.ACTION.Jump)
bindTrigger('AutoMove', input.ACTION.AutoMove)
bindTrigger('Inventory', input.ACTION.Inventory)
bindTrigger('Journal', input.ACTION.Journal)
bindTrigger('QuickKeysMenu', input.ACTION.QuickKeysMenu)
bindHold('TogglePOV', input.ACTION.TogglePOV)
bindHold('Sneak', input.ACTION.Sneak)
bindHold('Run', input.ACTION.Run)
input.bindAction('Run', async:callback(function(_, value)
local controllerInput = util.vector2(
input.getAxisValue(input.CONTROLLER_AXIS.MoveForwardBackward),
input.getAxisValue(input.CONTROLLER_AXIS.MoveLeftRight)
):length2()
return value or controllerInput > 0.25
end), {})
input.bindAction('Use', async:callback(function()
-- The value "0.6" shouldn't exceed the triggering threshold in BindingsManager::actionValueChanged.
-- TODO: Move more logic from BindingsManager to Lua and consider to make this threshold configurable.
return input.isActionPressed(input.ACTION.Use) or input.getAxisValue(input.CONTROLLER_AXIS.TriggerRight) >= 0.6
end), {})
bindMovement('MoveBackward', input.ACTION.MoveBackward, input.CONTROLLER_AXIS.MoveForwardBackward, 1)
bindMovement('MoveForward', input.ACTION.MoveForward, input.CONTROLLER_AXIS.MoveForwardBackward, -1)
bindMovement('MoveRight', input.ACTION.MoveRight, input.CONTROLLER_AXIS.MoveLeftRight, 1)
bindMovement('MoveLeft', input.ACTION.MoveLeft, input.CONTROLLER_AXIS.MoveLeftRight, -1)
do
local zoomInOut = 0
onActionPress(input.ACTION.ZoomIn, function()
zoomInOut = zoomInOut + 1
end)
onActionPress(input.ACTION.ZoomOut, function()
zoomInOut = zoomInOut - 1
end)
input.bindAction('Zoom3rdPerson', async:callback(function(dt, _, togglePOV)
local Zoom3rdPerson = zoomInOut * 10
if togglePOV then
local triggerLeft = input.getAxisValue(input.CONTROLLER_AXIS.TriggerLeft)
local triggerRight = input.getAxisValue(input.CONTROLLER_AXIS.TriggerRight)
local controllerZoom = (triggerRight - triggerLeft) * 100 * dt
Zoom3rdPerson = Zoom3rdPerson + controllerZoom
end
zoomInOut = 0
return Zoom3rdPerson
end), { 'TogglePOV' })
end
local bindingSection = storage.playerSection('OMWInputBindings')
local devices = {
keyboard = true,
mouse = true,
controller = true
}
local function invalidBinding(binding)
if not binding.key then
return 'has no key'
elseif binding.type ~= 'action' and binding.type ~= 'trigger' then
return string.format('has invalid type', binding.type)
elseif binding.type == 'action' and not input.actions[binding.key] then
return string.format("action %s doesn't exist", binding.key)
elseif binding.type == 'trigger' and not input.triggers[binding.key] then
return string.format("trigger %s doesn't exist", binding.key)
elseif not binding.device or not devices[binding.device] then
return string.format("invalid device %s", binding.device)
elseif not binding.button then
return 'has no button'
end
end
2023-12-29 18:56:59 +00:00
local boundActions = {}
local actionBindings = {}
local function bindAction(binding, id)
local action = binding.key
actionBindings[action] = actionBindings[action] or {}
actionBindings[action][id] = binding
if not boundActions[action] then
boundActions[binding.key] = true
input.bindAction(action, async:callback(function()
for _, binding in pairs(actionBindings[action] or {}) do
if binding.device == 'keyboard' then
if input.isKeyPressed(binding.button) then
return true
end
elseif binding.device == 'mouse' then
if input.isMouseButtonPressed(binding.button) then
return true
end
elseif binding.device == 'controller' then
if input.isControllerButtonPressed(binding.button) then
return true
end
end
2023-12-29 18:56:59 +00:00
end
return false
end), {})
end
end
local triggerBindings = {}
for device in pairs(devices) do triggerBindings[device] = {} end
local function bindTrigger(binding, id)
local deviceBindings = triggerBindings[binding.device]
deviceBindings[binding.button] = deviceBindings[binding.button] or {}
deviceBindings[binding.button][id] = binding
2023-12-29 18:56:59 +00:00
end
local function registerBinding(binding, id)
local invalid = invalidBinding(binding)
if invalid then
print(string.format('Skipping invalid binding %s: %s', id, invalid))
elseif binding.type == 'action' then
bindAction(binding, id)
elseif binding.type == 'trigger' then
bindTrigger(binding, id)
2023-12-29 18:56:59 +00:00
end
end
function clearBinding(id)
for _, deviceBindings in pairs(triggerBindings) do
for _, buttonBindings in pairs(deviceBindings) do
buttonBindings[id] = nil
end
2023-12-29 18:56:59 +00:00
end
for _, bindings in pairs(actionBindings) do
bindings[id] = nil
2023-12-29 18:56:59 +00:00
end
end
bindingSection:subscribe(async:callback(function(_, id)
if not id then return end
local binding = bindingSection:get(id)
2023-12-29 18:56:59 +00:00
clearBinding(id)
if binding ~= nil then
registerBinding(binding, id)
end
return id
end))
2023-12-29 18:56:59 +00:00
local initiated = false
local function init()
for id, binding in pairs(bindingSection:asTable()) do
registerBinding(binding, id)
end
end
return {
engineHandlers = {
onFrame = function()
if not initiated then
initiated = true
init()
end
end,
onInputAction = function(id)
if not actionPressHandlers[id] then
return
end
for _, handler in ipairs(actionPressHandlers[id]) do
handler()
end
end,
onKeyPress = function(e)
local buttonTriggers = triggerBindings.keyboard[e.code]
if not buttonTriggers then return end
for _, binding in pairs(buttonTriggers) do
input.activateTrigger(binding.key)
end
end,
onMouseButtonPress = function(button)
local buttonTriggers = triggerBindings.mouse[button]
if not buttonTriggers then return end
for _, binding in pairs(buttonTriggers) do
input.activateTrigger(binding.key)
end
end,
onControllerButtonPress = function(id)
local buttonTriggers = triggerBindings.controller[id]
if not buttonTriggers then return end
for _, binding in pairs(buttonTriggers) do
input.activateTrigger(binding.key)
2023-12-29 18:56:59 +00:00
end
end,
}
}