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

Fix IsKeyDown and AreKeysDown Processed Event #90

Closed
wants to merge 9 commits into from
Closed
5 changes: 4 additions & 1 deletion modules/input/Keyboard.lua
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ function Keyboard.new()
self._trove = Trove.new()
self.KeyDown = self._trove:Construct(Signal)
self.KeyUp = self._trove:Construct(Signal)
self.State = {}
self:_setup()
return self
end
Expand All @@ -74,7 +75,7 @@ end
```
]=]
function Keyboard:IsKeyDown(keyCode: Enum.KeyCode): boolean
return UserInputService:IsKeyDown(keyCode)
return self.State[keyCode] == true
end


Expand Down Expand Up @@ -112,11 +113,13 @@ function Keyboard:_setup()
self._trove:Connect(UserInputService.InputBegan, function(input, processed)
if processed then return end
if input.UserInputType == Enum.UserInputType.Keyboard then
self.State[input.KeyCode] = true
self.KeyDown:Fire(input.KeyCode)
end
end)

self._trove:Connect(UserInputService.InputEnded, function(input, processed)
self.State[input.KeyCode] = nil
if processed then return end
if input.UserInputType == Enum.UserInputType.Keyboard then
self.KeyUp:Fire(input.KeyCode)
Expand Down
98 changes: 71 additions & 27 deletions modules/trove/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
-- Stephen Leitnick
-- October 16, 2021


local FN_MARKER = newproxy()
local THREAD_MARKER = newproxy()

local RunService = game:GetService("RunService")


local function GetObjectCleanupFunction(object, cleanupMethod)
local t = typeof(object)
if t == "function" then
Expand All @@ -33,14 +31,17 @@ local function GetObjectCleanupFunction(object, cleanupMethod)
error("Failed to get cleanup function for object " .. t .. ": " .. tostring(object), 3)
end


local function AssertPromiseLike(object)
if type(object) ~= "table" or type(object.getStatus) ~= "function" or type(object.finally) ~= "function" or type(object.cancel) ~= "function" then
if
type(object) ~= "table"
or type(object.getStatus) ~= "function"
or type(object.finally) ~= "function"
or type(object.cancel) ~= "function"
then
error("Did not receive a Promise as an argument", 3)
end
end


--[=[
@class Trove
A Trove is helpful for tracking any sort of object during
Expand All @@ -49,18 +50,17 @@ end
local Trove = {}
Trove.__index = Trove


--[=[
@return Trove
Constructs a Trove object.
]=]
function Trove.new()
local self = setmetatable({}, Trove)
self._objects = {}
self._cleaning = false
return self
end


--[=[
@return Trove
Creates and adds another trove to itself. This is just shorthand
Expand All @@ -81,19 +81,23 @@ end
```
]=]
function Trove:Extend()
if self._cleaning then
error("Cannot call trove:Extend() while cleaning", 2)
end
return self:Construct(Trove)
end


--[=[
Clones the given instance and adds it to the trove. Shorthand for
`trove:Add(instance:Clone())`.
]=]
function Trove:Clone(instance: Instance): Instance
if self._cleaning then
error("Cannot call trove:Clone() while cleaning", 2)
end
return self:Add(instance:Clone())
end


--[=[
@param class table | (...any) -> any
@param ... any
Expand Down Expand Up @@ -128,6 +132,9 @@ end
```
]=]
function Trove:Construct(class, ...)
if self._cleaning then
error("Cannot call trove:Construct() while cleaning", 2)
end
local object = nil
local t = type(class)
if t == "table" then
Expand All @@ -138,7 +145,6 @@ function Trove:Construct(class, ...)
return self:Add(object)
end


--[=[
@param signal RBXScriptSignal
@param fn (...: any) -> ()
Expand All @@ -155,9 +161,33 @@ end
```
]=]
function Trove:Connect(signal, fn)
if self._cleaning then
error("Cannot call trove:Connect() while cleaning", 2)
end
return self:Add(signal:Connect(fn))
end

--[=[
@param signal RBXScriptSignal
@param fn (...: any) -> ()
@return RBXScriptConnection
Connects the function to the signal, adds the connection
to the trove, and then returns the connection.

This is shorthand for `trove:Add(signal:Once(fn))`.

```lua
trove:ConnectOnce(workspace.ChildAdded, function(instance)
print(instance.Name .. " added to workspace")
end)
```
]=]
function Trove:ConnectOnce(signal, fn)
if self._cleaning then
error("Cannot call trove:Connect() while cleaning", 2)
end
return self:Add(signal:Once(fn))
end

--[=[
@param name string
Expand All @@ -173,13 +203,15 @@ end
```
]=]
function Trove:BindToRenderStep(name: string, priority: number, fn: (dt: number) -> ())
if self._cleaning then
error("Cannot call trove:BindToRenderStep() while cleaning", 2)
end
RunService:BindToRenderStep(name, priority, fn)
self:Add(function()
RunService:UnbindFromRenderStep(name)
end)
end


--[=[
@param promise Promise
@return Promise
Expand All @@ -204,17 +236,22 @@ end
:::
]=]
function Trove:AddPromise(promise)
if self._cleaning then
error("Cannot call trove:AddPromise() while cleaning", 2)
end
AssertPromiseLike(promise)
if promise:getStatus() == "Started" then
promise:finally(function()
return self:_findAndRemoveFromObjects(promise, false)
if self._cleaning then
return
end
self:_findAndRemoveFromObjects(promise, false)
end)
self:Add(promise, "cancel")
end
return promise
end


--[=[
@param object any -- Object to track
@param cleanupMethod string? -- Optional cleanup name override
Expand Down Expand Up @@ -264,12 +301,14 @@ end
```
]=]
function Trove:Add(object: any, cleanupMethod: string?): any
if self._cleaning then
error("Cannot call trove:Add() while cleaning", 2)
end
local cleanup = GetObjectCleanupFunction(object, cleanupMethod)
table.insert(self._objects, {object, cleanup})
table.insert(self._objects, { object, cleanup })
return object
end


--[=[
@param object any -- Object to remove
Removes the object from the Trove and cleans it up.
Expand All @@ -281,26 +320,33 @@ end
```
]=]
function Trove:Remove(object: any): boolean
if self._cleaning then
error("Cannot call trove:Remove() while cleaning", 2)
end
return self:_findAndRemoveFromObjects(object, true)
end


--[=[
Cleans up all objects in the trove. This is
similar to calling `Remove` on each object
within the trove.
within the trove. The ordering of the objects
removed is _not_ guaranteed.
]=]
function Trove:Clean()
for _,obj in ipairs(self._objects) do
if self._cleaning then
return
end
self._cleaning = true
for _, obj in self._objects do
self:_cleanupObject(obj[1], obj[2])
end
table.clear(self._objects)
self._cleaning = false
end


function Trove:_findAndRemoveFromObjects(object: any, cleanup: boolean): boolean
local objects = self._objects
for i,obj in ipairs(objects) do
for i, obj in ipairs(objects) do
if obj[1] == object then
local n = #objects
objects[i] = objects[n]
Expand All @@ -314,7 +360,6 @@ function Trove:_findAndRemoveFromObjects(object: any, cleanup: boolean): boolean
return false
end


function Trove:_cleanupObject(object, cleanupMethod)
if cleanupMethod == FN_MARKER then
object()
Expand All @@ -325,7 +370,6 @@ function Trove:_cleanupObject(object, cleanupMethod)
end
end


--[=[
@param instance Instance
@return RBXScriptConnection
Expand All @@ -340,19 +384,19 @@ end
:::
]=]
function Trove:AttachToInstance(instance: Instance)
assert(instance:IsDescendantOf(game), "Instance is not a descendant of the game hierarchy")
return self:Connect(instance.Destroying, function()
if self._cleaning then
error("Cannot call trove:AttachToInstance() while cleaning", 2)
end
return self:ConnectOnce(instance.Destroying, function()
self:Destroy()
end)
end


--[=[
Destroys the Trove object. Forces `Clean` to run.
Alias for `trove:Clean()`.
]=]
function Trove:Destroy()
self:Clean()
end


return Trove