mirror of
				https://github.com/Reuh/ubiquitousse.git
				synced 2025-10-27 17:19:31 +00:00 
			
		
		
		
	Since I only use the LÖVE backend anyway, this simplifies the code. Tidied some code.
		
			
				
	
	
		
			156 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
	
		
			4.8 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local input = require((...):gsub("button$", "input"))
 | |
| 
 | |
| --- ButtonInput methods
 | |
| local button_mt
 | |
| button_mt = {
 | |
| 	-- Buttons inputs --
 | |
| 	-- Button input is a container for buttons detector. A button will be pressed when one of its detectors returns true.
 | |
| 	-- Inputs also knows if the button was just pressed or released.
 | |
| 	-- @tparam ButtonDetectors ... all the buttons detectors or buttons identifiers
 | |
| 	-- @tretrun ButtonInput the object
 | |
| 	_new = function(...)
 | |
| 		local r = setmetatable({
 | |
| 			hijackStack = {}, -- hijackers stack, last element is the object currently hijacking this input
 | |
| 			hijacking = nil, -- object currently hijacking this input
 | |
| 			detectors = {}, -- detectors list
 | |
| 			state = "none" -- current state (none, pressed, down, released)
 | |
| 		}, button_mt)
 | |
| 		table.insert(r.hijackStack, r)
 | |
| 		r.hijacking = r
 | |
| 		r:bind(...)
 | |
| 		return r
 | |
| 	end,
 | |
| 
 | |
| 	--- Returns a new ButtonInput with the same properties.
 | |
| 	-- @treturn ButtonInput the cloned object
 | |
| 	clone = function(self)
 | |
| 		return input.button(unpack(self.detectors))
 | |
| 	end,
 | |
| 
 | |
| 	--- Bind new ButtonDetector(s) to this input.
 | |
| 	-- @tparam ButtonDetectors ... buttons detectors or buttons identifiers to add
 | |
| 	-- @treturn ButtonInput this ButtonInput object
 | |
| 	bind = function(self, ...)
 | |
| 		for _, d in ipairs({...}) do
 | |
| 			table.insert(self.detectors, input.buttonDetector(d))
 | |
| 		end
 | |
| 		return self
 | |
| 	end,
 | |
| 	--- Unbind ButtonDetector(s).
 | |
| 	-- @tparam ButtonDetectors ... buttons detectors or buttons identifiers to remove
 | |
| 	-- @treturn ButtonInput this ButtonInput object
 | |
| 	unbind = function(self, ...)
 | |
| 		for _, d in ipairs({...}) do
 | |
| 			for i=#self.detectors, 1, -1 do
 | |
| 				if self.detectors[i] == d then
 | |
| 					table.remove(self.detectors, i)
 | |
| 					break
 | |
| 				end
 | |
| 			end
 | |
| 		end
 | |
| 		return self
 | |
| 	end,
 | |
| 	--- Unbind all ButtonDetector(s).
 | |
| 	-- @treturn ButtonInput this ButtonInput object
 | |
| 	clear = function(self)
 | |
| 		self.detectors = {}
 | |
| 		return self
 | |
| 	end,
 | |
| 
 | |
| 	--- Hijacks the input.
 | |
| 	-- This function returns a new input object which mirrors the current object, except it will hijack every new input.
 | |
| 	-- This means any new button press/down/release will only be visible to the new object; the button will always appear unpressed for the initial object.
 | |
| 	-- This is useful for contextual input, for example if you want to display a menu without pausing the game: the menu
 | |
| 	-- can hijack relevant inputs while it is open, so they don't trigger any action in the rest of the game.
 | |
| 	-- An input can be hijacked several times; the one which hijacked it last will be the active one.
 | |
| 	-- @treturn ButtonInput the new input object which is hijacking the input
 | |
| 	hijack = function(self)
 | |
| 		local hijacked = setmetatable({}, { __index = self, __newindex = self })
 | |
| 		table.insert(self.hijackStack, hijacked)
 | |
| 		self.hijacking = hijacked
 | |
| 		return hijacked
 | |
| 	end,
 | |
| 	--- Release the input that was hijacked by this object.
 | |
| 	-- Input will be given back to the previous object.
 | |
| 	-- @treturn ButtonInput this ButtonInput object
 | |
| 	free = function(self)
 | |
| 		local hijackStack = self.hijackStack
 | |
| 		for i, v in ipairs(hijackStack) do
 | |
| 			if v == self then
 | |
| 				table.remove(hijackStack, i)
 | |
| 				self.hijacking = hijackStack[#hijackStack]
 | |
| 				return self
 | |
| 			end
 | |
| 		end
 | |
| 		error("This object is currently not hijacking this input")
 | |
| 	end,
 | |
| 
 | |
| 	--- Returns true if the input was just pressed.
 | |
| 	-- @treturn boolean true if the input was pressed, false otherwise
 | |
| 	pressed = function(self)
 | |
| 		if self.hijacking == self then
 | |
| 			self:update()
 | |
| 			return self.state == "pressed"
 | |
| 		else
 | |
| 			return false
 | |
| 		end
 | |
| 	end,
 | |
| 	--- Returns true if the input was just released.
 | |
| 	-- @treturn boolean true if the input was released, false otherwise
 | |
| 	released = function(self)
 | |
| 		if self.hijacking == self then
 | |
| 			self:update()
 | |
| 			return self.state == "released"
 | |
| 		else
 | |
| 			return false
 | |
| 		end
 | |
| 	end,
 | |
| 	--- Returns true if the input is down.
 | |
| 	-- @treturn boolean true if the input is currently down, false otherwise
 | |
| 	down = function(self)
 | |
| 		if self.hijacking == self then
 | |
| 			self:update()
 | |
| 			local state = self.state
 | |
| 			return state == "down" or state == "pressed"
 | |
| 		else
 | |
| 			return false
 | |
| 		end
 | |
| 	end,
 | |
| 	--- Returns true if the input is up.
 | |
| 	-- @treturn boolean true if the input is currently up, false otherwise
 | |
| 	up = function(self)
 | |
| 		return not self:down()
 | |
| 	end,
 | |
| 
 | |
| 	--- Update button state.
 | |
| 	-- Automatically called, don't call unless you know what you're doing.
 | |
| 	update = function(self)
 | |
| 		if not input.updated[self] then
 | |
| 			local down = false
 | |
| 			for _, d in ipairs(self.detectors) do
 | |
| 				if d() then
 | |
| 					down = true
 | |
| 					break
 | |
| 				end
 | |
| 			end
 | |
| 			local state = self.state
 | |
| 			if down then
 | |
| 				if state == "none" or state == "released" then
 | |
| 					self.state = "pressed"
 | |
| 				else
 | |
| 					self.state = "down"
 | |
| 				end
 | |
| 			else
 | |
| 				if state == "down" or state == "pressed" then
 | |
| 					self.state = "released"
 | |
| 				else
 | |
| 					self.state = "none"
 | |
| 				end
 | |
| 			end
 | |
| 			input.updated[self] = true
 | |
| 		end
 | |
| 	end
 | |
| }
 | |
| button_mt.__index = button_mt
 | |
| 
 | |
| return button_mt
 |