diff --git a/fluid/component.lua b/fluid/component.lua index a92a745..2c13cb9 100644 --- a/fluid/component.lua +++ b/fluid/component.lua @@ -18,7 +18,7 @@ function Component.new(populate, inherit) return component end --- Creates and initializes a new Bag. +--- Creates and initializes a new Bag. -- @param ... The values passed to the populate function -- @return A new initialized Bag function Component:__initialize(...) diff --git a/fluid/entity.lua b/fluid/entity.lua index f706433..5c8a224 100644 --- a/fluid/entity.lua +++ b/fluid/entity.lua @@ -56,14 +56,14 @@ function Entity:apply() return self end ---- Gets a Component from the Entity +--- Gets a Component from the Entity. -- @param component The Component to get -- @return The Bag from the Component function Entity:get(component) return self.components[component] end ---- Returns true if the Entity has the Component +--- Returns true if the Entity has the Component. -- @params component The Component to check against -- @return True if the entity has the Bag. False otherwise function Entity:has(component) diff --git a/fluid/eventManager.lua b/fluid/eventManager.lua deleted file mode 100644 index 2362572..0000000 --- a/fluid/eventManager.lua +++ /dev/null @@ -1,62 +0,0 @@ -local EventManager = {} -EventManager.__index = EventManager - -function EventManager.new() - local eventManager = setmetatable({ - listeners = {}, - }, EventManager) - - return eventManager -end - -function EventManager:emit(name, ...) - local listeners = self.listeners[name] - - if listeners then - for i = 1, #listeners do - local listener = listeners[i] - listener[1][listener[2]](listener[1], ...) - end - end - - return self -end - -function EventManager:register(name, listener, callback, enabled) - enabled = enabled == nil and true - - local listeners = self.listeners[name] - - if not listeners then - listeners = {count = 0} - self.listeners[name] = listeners - end - - listeners.count = listeners.count + 1 - listeners[listeners.count] = {listener, callback or name} - - return self -end - -function EventManager:deregister(name, listener, callback) - local listeners = self.listeners[name] - - if listeners then - for index, other in ipairs(listeners) do - if listener[1] == other and listener[2] == (callback or name) then - table.remove(listeners, index) - listeners.count = listeners.count - 1 - - if callback then - break - end - end - end - end - - return self -end - -return setmetatable(EventManager, { - __call = function(_, ...) return EventManager.new(...) end, -}) diff --git a/fluid/init.lua b/fluid/init.lua index 1d756ae..f8e8cff 100644 --- a/fluid/init.lua +++ b/fluid/init.lua @@ -7,7 +7,6 @@ function Fluid.init(settings) Fluid.component = require(PATH..".component") Fluid.system = require(PATH..".system") Fluid.instance = require(PATH..".instance") - Fluid.eventManager = require(PATH..".eventManager") if settings and settings.useEvents then Fluid.instances = {} diff --git a/fluid/instance.lua b/fluid/instance.lua index 00fbce7..93013c8 100644 --- a/fluid/instance.lua +++ b/fluid/instance.lua @@ -1,32 +1,47 @@ local PATH = (...):gsub('%.[^%.]+$', '') -local List = require(PATH..".list") -local EventManager = require(PATH..".eventManager") +local List = require(PATH..".list") local Instance = {} Instance.__index = Instance +--- Creates a new Instance. +-- @return The new instance function Instance.new() local instance = setmetatable({ entities = List(), - systems = {}, + systems = List(), + events = {}, }, Instance) return instance end +--- Adds an Entity to the Instance. +-- @param e The Entity to add +-- @return self function Instance:addEntity(e) e.instances:add(self) self.entities:add(e) self:checkEntity(e) + + return self end +--- Checks an Entity against all the systems in the Instance. +-- @param e The Entity to check +-- @return self function Instance:checkEntity(e) for i = 1, self.systems.size do self.systems:get(i):__check(e) end + + return self end +--- Removes an Entity from the Instance. +-- @param e The Entity to remove +-- @return self function Instance:removeEntity(e) e.instances:remove(self) self.entities:remove(e) @@ -34,32 +49,94 @@ function Instance:removeEntity(e) for i = 1, self.systems.size do self.systems:get(i):__remove(e) end -end - -function Instance:addSystem(system, eventName, callback, enabled) - self.systems[eventName] = self.systems[eventName] or {} - - local i = #self.systems[eventName] + 1 - self.systems[eventName][i] = { - system = system, - eventName = eventName, - callback = callback or eventName, - enabled = enabled == nil or true, - } return self end +--- Adds a System to the Instance. +-- @param system The System to add +-- @param eventName The Event to register to +-- @param callback The function name to call. Defaults to eventName +-- @param enabled If the system is enabled. Defaults to true +-- @return self +function Instance:addSystem(system, eventName, callback, enabled) + if not self.systems:has(system) then + self.systems:add(system) + end + + if eventName then + self.events[eventName] = self.events[eventName] or {} + + local i = #self.events[eventName] + 1 + self.events[eventName][i] = { + system = system, + callback = callback or eventName, + enabled = enabled == nil and true or enabled, + } + end + + return self +end + +--- Enables a System in the Instance. +-- @param system The System to enable +-- @param eventName The Event it was registered to +-- @param callback The callback it was registered with. Defaults to eventName +-- @return self function Instance:enableSystem(system, eventName, callback) - + return self:setSystem(system, eventName, callback, true) end +--- Disables a System in the Instance. +-- @param system The System to disable +-- @param eventName The Event it was registered to +-- @param callback The callback it was registered with. Defaults to eventName +-- @return self function Instance:disableSystem(system, eventName, callback) - + return self:setSystem(system, eventName, callback, false) end -function Instance:emit(...) - self.eventManager:emit(...) +--- Sets a System 'enable' in the Instance. +-- @param system The System to set +-- @param eventName The Event it was registered to +-- @param callback The callback it was registered with. Defaults to eventName +-- @param enable The state to set it to +-- @return self +function Instance:setSystem(system, eventName, callback, enable) + callback = callback or eventName + + local listeners = self.events[eventName] + + if listeners then + for i = 1, #listeners do + local listener = listeners[i] + + if listerner.callback == callback then + listerner.enabled = enable + break + end + end + end + + return self +end + +--- Emits an Event in the Instance. +-- @param eventName The Event that should be emitted +-- @param ... Parameters passed to listeners +-- @return self +function Instance:emit(eventName, ...) + local listeners = self.events[eventName] + + if listeners then + for i = 1, #listeners do + local listener = listeners[i] + + if listener.enabled then + listener.system[listener.callback](listener.system, ...) + end + end + end return self end diff --git a/fluid/list.lua b/fluid/list.lua index 72fa68e..b464a27 100644 --- a/fluid/list.lua +++ b/fluid/list.lua @@ -1,6 +1,8 @@ local List = {} local mt = {__index = List} +--- Creates a new List. +-- @return A new list function List.new() return setmetatable({ objects = {}, @@ -9,20 +11,32 @@ function List.new() }, mt) end +--- Clears the List completely. +-- @return self function List:clear() self.objects = {} self.pointers = {} self.size = 0 + + return self end +--- Adds an object to the List. +-- @param obj The object to add +-- @return self function List:add(obj) local size = self.size + 1 self.objects[size] = obj self.pointers[obj] = size self.size = size + + return self end +--- Removes an object from the List. +-- @param obj The object to remove +-- @return self function List:remove(obj) local index = self.pointers[obj] local size = self.size @@ -38,15 +52,20 @@ function List:remove(obj) self.objects[size] = nil end - self.pointers[obj] = nil self.size = size - 1 end +--- Gets an object by numerical index. +-- @param index The index to look at +-- @return The object at the index function List:get(index) return self.objects[index] end +--- Gets if the List has the object. +-- @param obj The object to search for +-- @param true if the list has the object, false otherwise function List:has(obj) return self.pointers[obj] and true end diff --git a/fluid/pool.lua b/fluid/pool.lua index ed60ca4..678261b 100644 --- a/fluid/pool.lua +++ b/fluid/pool.lua @@ -5,6 +5,10 @@ local List = require(PATH..".list") local Pool = {} Pool.__index = Pool +--- Creates a new Pool +-- @param name Identifier for the Pool. +-- @param filter Table containing the required Components +-- @return The new Pool function Pool.new(name, filter) local pool = setmetatable(List(), Pool) @@ -14,6 +18,9 @@ function Pool.new(name, filter) return pool end +--- Checks if an Entity is eligible for the Pool. +-- @param e The Entity to check +-- @return True if the entity is eligible, false otherwise function Pool:eligible(e) for _, component in ipairs(self.filter) do if not e.components[component] or e.removed[component] then diff --git a/fluid/system.lua b/fluid/system.lua index e9e5b58..d3afd2d 100644 --- a/fluid/system.lua +++ b/fluid/system.lua @@ -28,6 +28,9 @@ System.mt = { end, } +--- Creates a new System prototype. +-- @param ... Variable amounts of filters +-- @return A new System prototype function System.new(...) local systemProto = setmetatable({ __filter = {...}, @@ -37,20 +40,19 @@ function System.new(...) return systemProto end +--- Default initialization function. +-- @param ... Varags function System:init(...) end -function System:destroy() - if self.instance then - self.instance:removeSystem(self) - end -end - -function System:__buildPool(pool) +--- Builds a Pool for the System. +-- @param baseFilter The 'raw' Filter +-- @return A new Pool +function System:__buildPool(baseFilter) local name = "pool" local filter = {} - for i, v in ipairs(pool) do + for i, v in ipairs(baseFilter) do if type(v) == "table" then filter[#filter + 1] = v elseif type(v) == "string" then @@ -61,6 +63,9 @@ function System:__buildPool(pool) return Pool(name, filter) end +--- Checks and applies an Entity to the System's pools. +-- @param e The Entity to check +-- @return True if the Entity was added, false if it was removed. Nil if nothing happend function System:__check(e) local systemHas = self:__has(e) @@ -84,6 +89,8 @@ function System:__check(e) end end +--- Tries to add an Entity to the System. +-- @param e The Entity to add function System:__tryAdd(e) if not self:__has(e) then self.__all[e] = 0 @@ -93,6 +100,8 @@ function System:__tryAdd(e) self.__all[e] = self.__all[e] + 1 end +--- Tries to remove an Entity from the System. +-- @param e The Entity to remove function System:__tryRemove(e) if self:__has(e) then self.__all[e] = self.__all[e] - 1 @@ -104,33 +113,32 @@ function System:__tryRemove(e) end end -function System:__remove(e) - if self:__has(e) then - for _, pool in ipairs(self.__pools) do - if pool:has(e) then - pool:remove(e) - self:entityRemovedFrom(e, pool) - end - end - - self.__all[e] = nil - self:entityRemoved(e) - end -end - +--- Returns if the System has the Entity. +-- @param The Entity to check for +-- @return True if the System has the Entity. False otherwise function System:__has(e) return self.__all[e] and true end +--- Default callback for adding an Entity. +-- @param e The Entity that was added function System:entityAdded(e) end +--- Default callback for adding an Entity to a pool. +-- @param e The Entity that was added +-- @param pool The pool the Entity was added to function System:entityAddedTo(e, pool) end +--- Default callback for removing an Entity. +-- @param e The Entity that was removed function System:entityRemoved(e) end +--- Default callback for removing an Entity from a pool. +-- @param e The Entity that was removed +-- @param pool The pool the Entity was removed from function System:entityRemovedFrom(e, pool) end diff --git a/main.lua b/main.lua index 2ec9616..1150623 100644 --- a/main.lua +++ b/main.lua @@ -89,9 +89,9 @@ function RandomRemover:update(dt) love.window.setTitle(love.timer.getFPS()) end -Game:addSystem(RandomRemover(), "update", nil, true) -Game:addSystem(RectangleRenderer(), "draw", nil, true) -Game:addSystem(CircleRenderer(), "draw", nil, true) +Game:addSystem(RandomRemover(), "update") +Game:addSystem(RectangleRenderer(), "draw") +Game:addSystem(CircleRenderer(), "draw") for i = 1, 100 do local e = Entity()