mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 00:26:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			229 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			229 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
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
 | 
						|
 | 
						|
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
 | 
						|
            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
 | 
						|
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)
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
function clearBinding(id)
 | 
						|
    for _, deviceBindings in pairs(triggerBindings) do
 | 
						|
        for _, buttonBindings in pairs(deviceBindings) do
 | 
						|
            buttonBindings[id] = nil
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    for _, bindings in pairs(actionBindings) do
 | 
						|
        bindings[id] = nil
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
bindingSection:subscribe(async:callback(function(_, id)
 | 
						|
    if not id then return end
 | 
						|
    local binding = bindingSection:get(id)
 | 
						|
    clearBinding(id)
 | 
						|
    if binding ~= nil then
 | 
						|
        registerBinding(binding, id)
 | 
						|
    end
 | 
						|
    return id
 | 
						|
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 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)
 | 
						|
            end
 | 
						|
        end,
 | 
						|
    }
 | 
						|
}
 |