mirror of
https://github.com/Reuh/ubiquitousse.git
synced 2025-10-27 09:09:30 +00:00
input: grabbing is now done by cloning the input and disabling the parent input
Fixes issues with child sources in grabbing inputs.
This commit is contained in:
parent
3d6ea21113
commit
8ac3ce010e
1 changed files with 96 additions and 74 deletions
100
input/input.lua
100
input/input.lua
|
|
@ -377,8 +377,13 @@ input_mt = {
|
|||
-- Should be called every frame, typically _after_ you've done all your input handling
|
||||
-- (otherwise `pressed` and `released` may never return true and `delta` might be wrong).
|
||||
--
|
||||
-- (Note: this should not be called on subinputs)
|
||||
-- If the input is grabbed, will update the input that grabbed it instead.
|
||||
--
|
||||
-- (Note: this do not need to be called on inputs that are grabbing another input as the grabbed input will update it automatically)
|
||||
update = function(self)
|
||||
if self.grabbed then
|
||||
self.grabbed:update() -- pass onto grabber
|
||||
else
|
||||
self:_update()
|
||||
for i=1, self._dimension do
|
||||
self._prevValue[i] = self._value[i]
|
||||
|
|
@ -386,15 +391,36 @@ input_mt = {
|
|||
for _, i in ipairs(self.children) do
|
||||
i:update()
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
--- Create a new input object based on this input `config` data.
|
||||
clone = function(self)
|
||||
return make_input(self.config)
|
||||
-- Unless `copyState` is set, the clone will only keep the `config` data and the input `name`; other state will be set to the default values.
|
||||
-- @tparam[opt=false] boolean copyState if `true`, will copy the currrent state of the input into the clone. The input states includes the current input value, if it is enabled/disabled, and the current joystick; note that the grabbed state (i.e. the `grabbed` and `grabbing` fields) is not copied.
|
||||
clone = function(self, copyState)
|
||||
local r = make_input(self.config)
|
||||
r.name = self.name
|
||||
if copyState then
|
||||
self:_copyStateInto(r)
|
||||
end
|
||||
return r
|
||||
end,
|
||||
_copyStateInto = function(self, dest)
|
||||
dest._state = self._state
|
||||
for i=1, self._dimension do
|
||||
dest._value[i] = self._value[i]
|
||||
dest._prevValue[i] = self._prevValue[i]
|
||||
end
|
||||
if not dest.enabled and self.enabled then
|
||||
self:disable()
|
||||
end
|
||||
dest._joystick = self._joystick
|
||||
for _, c in ipairs(self.children) do
|
||||
c:_copyStateInto(self.children[c.name])
|
||||
end
|
||||
end,
|
||||
|
||||
--- Reload the input `config`, and do the same for its children.
|
||||
-- This will reenable the input if it was disabled using `disable`.
|
||||
reload = function(self)
|
||||
-- get main options
|
||||
self._dimension = self.config.dimension or 1
|
||||
|
|
@ -641,48 +667,48 @@ input_mt = {
|
|||
event:bind("_active", onevent)
|
||||
end,
|
||||
|
||||
--- Grab the input and its children input and returns the new subinput.
|
||||
--- Grab the input and its children input and returns the resulting grabbing input.
|
||||
--
|
||||
-- The input will be disabled (will no longer update) and instead pass all new updates to the grabbing input.
|
||||
-- The input will also be set to a neutral position.
|
||||
--
|
||||
-- A grabbed input will no longer update and instead pass all new update to the subinput.
|
||||
-- This is typically used for contextual action or pause menus: by grabbing the player input, all the direct use of
|
||||
-- this input in the game will stop (can't move caracter, ...) and instead you can use the subinput to handle input in the pause menu.
|
||||
-- To stop grabbing an input, you will need to `release` the subinput.
|
||||
-- this input in the game will stop (can't move caracter, ...) and instead you can use the grabbing input to handle input in the pause menu.
|
||||
-- To stop grabbing an input, you will need to call `release` on the grabbing input.
|
||||
--
|
||||
-- This will also reset the input to a neutral state. The subinput will share everything with this input, except
|
||||
-- `grabbed`, `grabbing`, `event` (a new event registry is created), and of course its current state.
|
||||
-- The grabbing input is created by cloning the current input and starts with the same state as the input when it was grabbed.
|
||||
grab = function(self)
|
||||
local g = {
|
||||
grabbed = false,
|
||||
grabbing = self,
|
||||
event = signal.new(),
|
||||
children = {},
|
||||
_value = {},
|
||||
_prevValue = {},
|
||||
}
|
||||
for i=1, self._dimension do
|
||||
g._value[i] = self._value[i]
|
||||
g._prevValue[i] = self._prevValue[i]
|
||||
end
|
||||
for _, c in ipairs(self.children) do
|
||||
local gc = c:grab()
|
||||
table.insert(g.children, gc)
|
||||
g.children[c.name] = gc
|
||||
g[c.name] = gc
|
||||
end
|
||||
local g = self:clone(true)
|
||||
self:disable()
|
||||
self:neutralize()
|
||||
self.grabbed = setmetatable(g, { __index = self })
|
||||
self:_grab(g)
|
||||
return g
|
||||
end,
|
||||
--- Release a subinput and its children.
|
||||
-- The parent grabbed input will be updated again. This subinput will be reset to a neutral position and won't be updated further.
|
||||
release = function(self)
|
||||
assert(self.grabbing, "not a grabbed input")
|
||||
-- Set grabbed and grabbing in the input and its children.
|
||||
_grab = function(self, grabbed)
|
||||
self.grabbed = grabbed
|
||||
grabbed.grabbing = self
|
||||
for _, c in ipairs(self.children) do
|
||||
c:release()
|
||||
c:_grab(grabbed.children[c.name])
|
||||
end
|
||||
end,
|
||||
--- Release an input that is currently grabbing another and its children.
|
||||
-- The parent grabbed input will be re-enabled (will update again). This grabbing input will be reset to a neutral position and disabled.
|
||||
release = function(self)
|
||||
assert(self.grabbing, "can't release an input that is not grabbing another input")
|
||||
self:disable()
|
||||
self:neutralize()
|
||||
self.grabbing.grabbed = false
|
||||
local g = self.grabbing
|
||||
self:_release(g)
|
||||
g:enable()
|
||||
end,
|
||||
-- Unset grabbed and grabbing in the input and its children.
|
||||
_release = function(self, grabbing)
|
||||
self.grabbing = false
|
||||
grabbing.grabbed = false
|
||||
for _, c in ipairs(self.children) do
|
||||
c:_release(grabbing.children[c.name])
|
||||
end
|
||||
end,
|
||||
|
||||
--- Set the state of this input to a neutral position (i.e. value = 0 for every dimension).
|
||||
|
|
@ -747,9 +773,6 @@ input_mt = {
|
|||
-- Update the state of the input: called at least on every input value change and on :update().
|
||||
-- new: new value of the input if it has changed (list of numbers of size config.dimension, can be anything, but typically in [0-1]) (optional)
|
||||
_update = function(self, new)
|
||||
if self.grabbed then
|
||||
self.grabbed:_update(new) -- pass onto grabber
|
||||
else
|
||||
local threshold = self._threshold
|
||||
-- update values
|
||||
new = new or self._value
|
||||
|
|
@ -785,7 +808,6 @@ input_mt = {
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
input_mt.__index = input_mt
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue