Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fully expose InputBindings to Lua #5965

Merged
merged 10 commits into from
Nov 14, 2024
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