mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-30 03:32:36 +00:00
256 lines
7.9 KiB
Lua
256 lines
7.9 KiB
Lua
local core = require('openmw.core')
|
|
local input = require('openmw.input')
|
|
local util = require('openmw.util')
|
|
local async = require('openmw.async')
|
|
local storage = require('openmw.storage')
|
|
local ui = require('openmw.ui')
|
|
|
|
local I = require('openmw.interfaces')
|
|
|
|
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 keyboardPresses = {}
|
|
local keybordHolds = {}
|
|
local boundActions = {}
|
|
|
|
local function bindAction(action)
|
|
if boundActions[action] then return end
|
|
boundActions[action] = true
|
|
input.bindAction(action, async:callback(function()
|
|
if keybordHolds[action] then
|
|
for _, binding in pairs(keybordHolds[action]) do
|
|
if input.isKeyPressed(binding.code) then return true end
|
|
end
|
|
end
|
|
return false
|
|
end), {})
|
|
end
|
|
|
|
local function registerBinding(binding, id)
|
|
if not input.actions[binding.key] and not input.triggers[binding.key] then
|
|
print(string.format('Skipping binding for unknown action or trigger: "%s"', binding.key))
|
|
return
|
|
end
|
|
if binding.type == 'keyboardPress' then
|
|
local bindings = keyboardPresses[binding.code] or {}
|
|
bindings[id] = binding
|
|
keyboardPresses[binding.code] = bindings
|
|
elseif binding.type == 'keyboardHold' then
|
|
local bindings = keybordHolds[binding.key] or {}
|
|
bindings[id] = binding
|
|
keybordHolds[binding.key] = bindings
|
|
bindAction(binding.key)
|
|
else
|
|
error('Unknown binding type "' .. binding.type .. '"')
|
|
end
|
|
end
|
|
|
|
function clearBinding(id)
|
|
for _, boundTriggers in pairs(keyboardPresses) do
|
|
boundTriggers[id] = nil
|
|
end
|
|
for _, boundKeys in pairs(keybordHolds) do
|
|
boundKeys[id] = nil
|
|
end
|
|
end
|
|
|
|
local function updateBinding(id, binding)
|
|
bindingSection:set(id, binding)
|
|
clearBinding(id)
|
|
if binding ~= nil then
|
|
registerBinding(binding, id)
|
|
end
|
|
return id
|
|
end
|
|
|
|
local interfaceL10n = core.l10n('interface')
|
|
|
|
I.Settings.registerRenderer('inputBinding', function(id, set, arg)
|
|
if type(id) ~= 'string' then error('inputBinding: must have a string default value') end
|
|
if not arg.type then error('inputBinding: type argument is required') end
|
|
if not arg.key then error('inputBinding: key argument is required') end
|
|
local info = input.actions[arg.key] or input.triggers[arg.key]
|
|
if not info then return {} end
|
|
|
|
local l10n = core.l10n(info.key)
|
|
|
|
local name = {
|
|
template = I.MWUI.templates.textNormal,
|
|
props = {
|
|
text = l10n(info.name),
|
|
},
|
|
}
|
|
|
|
local description = {
|
|
template = I.MWUI.templates.textNormal,
|
|
props = {
|
|
text = l10n(info.description),
|
|
},
|
|
}
|
|
|
|
local binding = bindingSection:get(id)
|
|
local label = binding and input.getKeyName(binding.code) or interfaceL10n('None')
|
|
|
|
local recorder = {
|
|
template = I.MWUI.templates.textEditLine,
|
|
props = {
|
|
readOnly = true,
|
|
text = label,
|
|
},
|
|
events = {
|
|
focusGain = async:callback(function()
|
|
if binding == nil then return end
|
|
updateBinding(id, nil)
|
|
set(id)
|
|
end),
|
|
keyPress = async:callback(function(key)
|
|
if binding ~= nil or key.code == input.KEY.Escape then return end
|
|
|
|
local newBinding = {
|
|
code = key.code,
|
|
type = arg.type,
|
|
key = arg.key,
|
|
}
|
|
updateBinding(id, newBinding)
|
|
set(id)
|
|
end),
|
|
},
|
|
}
|
|
|
|
local row = {
|
|
type = ui.TYPE.Flex,
|
|
props = {
|
|
horizontal = true,
|
|
},
|
|
content = ui.content {
|
|
name,
|
|
{ props = { size = util.vector2(10, 0) } },
|
|
recorder,
|
|
},
|
|
}
|
|
local column = {
|
|
type = ui.TYPE.Flex,
|
|
content = ui.content {
|
|
row,
|
|
description,
|
|
},
|
|
}
|
|
|
|
return column
|
|
end)
|
|
|
|
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 bindings = keyboardPresses[e.code]
|
|
if bindings then
|
|
for _, binding in pairs(bindings) do
|
|
input.activateTrigger(binding.key)
|
|
end
|
|
end
|
|
end,
|
|
}
|
|
}
|