Skip to content

Commit

Permalink
Merge pull request #5965 from Web-eWorks/lua-input-bindings
Browse files Browse the repository at this point in the history
Fully expose InputBindings to Lua
  • Loading branch information
Webster Sheets authored Nov 14, 2024
2 parents 065419a + 69af3a8 commit f9e759f
Show file tree
Hide file tree
Showing 15 changed files with 765 additions and 94 deletions.
201 changes: 201 additions & 0 deletions data/meta/Input.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
-- Copyright © 2008-2024 Pioneer Developers. See AUTHORS.txt for details
-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

-- This file implements type information about C++ classes for Lua static analysis
-- TODO: document function usage

---@meta

---@class Input
local Input = {}

--- List of input keys to be used with various input functions.
--- The list is a mostly-complete port of common SDL_KeyCode values, indexed by
--- lowercase key names.
---@type table<string, integer>
Input.keys = {}

--==================================

---@class Input.ActionBinding
---@field id string
---@field type string
---@field binding table
---@field binding2 table
local ActionBinding = {}

function ActionBinding:SetPressed() end
function ActionBinding:SetReleased() end

---@return boolean
function ActionBinding:IsActive() end
---@return boolean
function ActionBinding:IsJustActive() end

---@param cb fun()
function ActionBinding:OnPressed(cb) end
---@param cb fun()
function ActionBinding:OnReleased(cb) end

--==================================

---@class Input.AxisBinding
---@field id string
---@field type string
---@field axis table
---@field positive table
---@field negative table
local AxisBinding = {}

---@param val number
function AxisBinding:SetValue(val) end
---@return number
function AxisBinding:GetValue() end

---@param cb fun(val: number)
function AxisBinding:OnValueChanged(cb) end

--==================================

---@class Input.JoystickInfo
---@field name string
---@field numButtons integer
---@field numHats integer
---@field numAxes integer
local JoystickInfo = {}

---@param button integer
---@return boolean
function JoystickInfo:GetButtonState(button) end

---@param hat integer
---@return boolean
function JoystickInfo:GetHatState(hat) end

---@param axis integer
---@return number
function JoystickInfo:GetAxisValue(axis) end

---@param axis integer
---@return number
function JoystickInfo:GetAxisDeadzone(axis) end

---@param axis integer
---@param deadzone number
function JoystickInfo:SetAxisDeadzone(axis, deadzone) end

---@param axis integer
---@return number
function JoystickInfo:GetAxisCurve(axis) end

---@param axis integer
---@param curve number
function JoystickInfo:SetAxisCurve(axis, curve) end

---@param axis integer
---@return boolean
function JoystickInfo:GetAxisZeroToOne(axis) end
---@param axis integer
---@param zeroToOne boolean
function JoystickInfo:SetAxisZeroToOne(axis, zeroToOne) end

--==================================

---@class Input.InputFrame
---@field id string
local InputFrame = {}

-- Add the given action binding to this frame
---@param action Input.ActionBinding
function InputFrame:AddAction(action) end

-- Add the given axis binding to this frame
---@param axis Input.AxisBinding
function InputFrame:AddAxis(axis) end

-- Add the input frame to the stack of active inputs
---@return boolean
function InputFrame:AddToStack() end

-- Remove the input frame from the stack of active inputs
function InputFrame:RemoveFromStack() end

--==================================

---@param enable boolean
function Input.EnableBindings(enable) end

---@return (Input.AxisBinding|Input.ActionBinding)[][][]
function Input.GetBindingPages() end

---@param id string
---@return Input.ActionBinding?
function Input.GetActionBinding(id) end

---@param id string
---@return Input.AxisBinding?
function Input.GetAxisBinding(id) end

---@param key integer
function Input.GetKeyName(key) end

---@return number
function Input.GetJoystickCount() end

---@param joy integer
---@return string
function Input.GetJoystickName(joy) end

---@param joy integer
---@return boolean
function Input.IsJoystickConnected(joy) end

---@param joy integer
---@return Input.JoystickInfo?
function Input.GetJoystick(joy) end

---@param joy integer
function Input.SaveJoystickConfig(joy) end

---@param binding Input.AxisBinding | Input.ActionBinding
function Input.SaveBinding(binding) end

---@return boolean
function Input.GetMouseYInverted() end

---@param inverted boolean
function Input.SetMouseYInverted(inverted) end

---@return boolean
function Input.GetJoystickEnabled() end

---@param enabled boolean
function Input.SetJoystickEnabled(enabled) end

---@return boolean
function Input.GetMouseCaptured() end

-- Create an InputFrame to add action/axis bindings to the active input stack
---@param id string The debug identifier of this InputFrame
---@param modal boolean? Should this InputFrame be modal?
---@return Input.InputFrame
function Input.CreateInputFrame(id, modal) end

-- Register an ActionBinding from Lua with the given default key associations
---@param id string The identifier of the action binding. Must be globally unique.
---@param groupId string The page and group this action binding is organized into, in the form "page.group"
---@param b1 table? The primary keychord for this binding
---@param b2 table? The secondary keychord for this binding
---@return Input.ActionBinding
function Input.RegisterActionBinding(id, groupId, b1, b2) end

-- Register an AxisBinding from Lua with the given default key associations
---@param id string The identifier of the axis binding. Must be globally unique.
---@param groupId string The page and group this axis binding is organized into, in the form "page.group"
---@param pos table? The positive-direction keychord for this axis binding
---@param neg table? The negative-direction keychord for this axis binding
---@param axis table? The joystick axis to associate with this axis binding
---@return Input.AxisBinding
function Input.RegisterAxisBinding(id, groupId, pos, neg, axis) end

return Input
23 changes: 23 additions & 0 deletions data/modules/Debug/TestInput.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- Copyright © 2008-2024 Pioneer Developers. See AUTHORS.txt for details
-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt

-- This file tests the Lua input API

--[[
local Input = require 'Input'
local action_disable = Input.RegisterActionBinding("TestInputDisable", "Debug.TestInput", { activator = { key = Input.keys["return"] } })
local frame = Input.CreateInputFrame("TestInputFrame", true)
frame:AddAction(action_disable)
action_disable:OnPressed(function()
frame:RemoveFromStack()
print("Test!")
end)
require 'Event'.Register("onGameStart", function()
frame:AddToStack()
end)
--]]
3 changes: 2 additions & 1 deletion data/pigui/libs/forwarded.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
-- Stuff from the C++ side that we want available directly in Lua
-- without any wrappers
local Engine = require 'Engine'
local Input = require 'Input'
local pigui = Engine.pigui

---@class ui
Expand Down Expand Up @@ -120,7 +121,7 @@ ui.setColumnOffset = pigui.SetColumnOffset
ui.getColumnWidth = pigui.GetColumnWidth
ui.setColumnWidth = pigui.SetColumnWidth
ui.getScrollY = pigui.GetScrollY
ui.keys = pigui.keys
ui.keys = Input.keys
ui.isKeyReleased = pigui.IsKeyReleased
ui.playSfx = pigui.PlaySfx
ui.isItemHovered = pigui.IsItemHovered
Expand Down
2 changes: 1 addition & 1 deletion data/pigui/modules/autopilot-window.lua
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ local speed_limiter = (function()
-- don't show tooltip during animation
local tooltip = variant and bindings.limiter.tooltip or anim_active and "" or lui.TURN_OFF
if ui.mainMenuButton(icons.speed_limiter, tooltip .. "##speed_limiter_toggle", variant) then
bindings.limiter.action:OnPress()
bindings.limiter.action:SetPressed()
end

if toggle_limiter then
Expand Down
12 changes: 10 additions & 2 deletions src/Input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,6 @@ bool Manager::AddInputFrame(InputFrame *frame)

m_inputFrames.push_back(frame);
frame->active = true;
frame->onFrameAdded.emit(frame);
m_frameListChanged = true;

return true;
Expand Down Expand Up @@ -363,7 +362,6 @@ void Manager::RemoveInputFrame(InputFrame *frame)

ClearInputFrameState(frame);
frame->active = false;
frame->onFrameRemoved.emit(frame);
m_frameListChanged = true;
}
}
Expand Down Expand Up @@ -414,6 +412,16 @@ InputBindings::Axis *Manager::GetAxisBinding(const std::string &id)
return axisBindings.count(id) ? &axisBindings[id] : &Input::nullAxis;
}

bool Manager::HasActionBinding(const std::string &id) const
{
return actionBindings.count(id) > 0;
}

bool Manager::HasAxisBinding(const std::string &id) const
{
return axisBindings.count(id) > 0;
}

/*
STATE MANAGEMENT
Expand Down
14 changes: 6 additions & 8 deletions src/Input.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ namespace Input {
using Axis = InputBindings::Axis;
using Action = InputBindings::Action;

InputFrame(Input::Manager *man, bool modal = false) :
InputFrame(Input::Manager *man, bool modal = false, std::string_view id = "") :
manager(man),
modal(modal)
modal(modal),
id(id)
{}

std::vector<Action *> actions;
Expand All @@ -61,16 +62,11 @@ namespace Input {
Manager *manager = nullptr;
bool active = false;
bool modal = false;
std::string id;

// Call this at startup to register all the bindings associated with the frame.
virtual void RegisterBindings(){};

// Called when the frame is added to the stack.
sigc::signal<void, InputFrame *> onFrameAdded;

// Called when the frame is removed from the stack.
sigc::signal<void, InputFrame *> onFrameRemoved;

Action *AddAction(const std::string &id);
Axis *AddAxis(const std::string &id);
};
Expand Down Expand Up @@ -160,11 +156,13 @@ class Input::Manager {
// The returned binding pointer points to the actual binding.
InputBindings::Action *AddActionBinding(const std::string &id, BindingGroup *group, InputBindings::Action &&binding);
InputBindings::Action *GetActionBinding(const std::string &id);
bool HasActionBinding(const std::string &id) const;

// Creates a new axis binding, copying the provided binding.
// The returned binding pointer points to the actual binding.
InputBindings::Axis *AddAxisBinding(const std::string &id, BindingGroup *group, InputBindings::Axis &&binding);
InputBindings::Axis *GetAxisBinding(const std::string &id);
bool HasAxisBinding(const std::string &id) const;

// Call EnableBindings() to temporarily disable handling input bindings while
// you're recording a new input binding or are in a modal window.
Expand Down
1 change: 1 addition & 0 deletions src/lua/Lua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ namespace Lua {
void UninitModules()
{
LuaEvent::Uninit();
LuaInput::Uninit();

delete Pi::luaNameGen;

Expand Down
Loading

0 comments on commit f9e759f

Please sign in to comment.