From 9f4c03a1363785155df284d1a0f53d33c77ba385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Reuh=20Fildadut?= Date: Thu, 24 Jun 2021 16:24:54 +0200 Subject: [PATCH] Add callback, children, timer example systems --- ecs/callback.can | 35 ++++++++++++++++++++++++++++++++++ ecs/children.can | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ ecs/timer.can | 35 ++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 ecs/callback.can create mode 100644 ecs/children.can create mode 100644 ecs/timer.can diff --git a/ecs/callback.can b/ecs/callback.can new file mode 100644 index 0000000..dcd62f0 --- /dev/null +++ b/ecs/callback.can @@ -0,0 +1,35 @@ +--- Callback system +-- Allow to call callbacks defined in other systems in entity methods. +-- Example: +-- entity.callback:onMove(...) -- call onAdd(system, entitySystemTable, ...) on every system the entity belong to (which has this callback) +-- Can be also used for onAdd, etc. + +--- Recursively get a list of systems with a certain method. +let recGetSystemsWithMethod = (method, systems, l={}) + for _, s in ipairs(systems) do + if s[method] then + table.insert(l, s) + end + recGetSystemsWithMethod(method, s.systems, l) + end + return l +end + +return { + name = "callback", + filter = true, + methods = { + __index = :(c, k) + let s = recGetSystemsWithMethod(k, {@world}) + @methods[k] = :(c, ...) + let e = c.entity + for _, sys in ipairs(s) do + if sys._previous[e] then + sys[k](sys, e[sys.name], ...) + end + end + end + return @_methods_mt[k] + end + } +} diff --git a/ecs/children.can b/ecs/children.can new file mode 100644 index 0000000..b7fa482 --- /dev/null +++ b/ecs/children.can @@ -0,0 +1,49 @@ +--- Children system +-- Allow to build a hierarchy between entities. +-- Children are stored directly in the .children entity table: they are added when their parent is added, and removed when it is removed from the world. + +return { + name = "children", + filter = true, + default = { + parent = nil, -- reference to parent entity, if any + -- ... list of children + }, + methods = { + --- Add a new entity to the world, using this entity as a parent. + add = :(c, o) + if not o.children then + o.children = {} + end + o.children.parent = c.entity + table.insert(c, o) + @world:add(o) + end, + --- Remove an entity from the world and from this entity's children. + remove = :(c, o) + @world:remove(o) + for i=#c, 1, -1 do + if c[i] == o then + table.remove(c, i) + break + end + end + o.children.parent = nil + end + }, + onAdd = :(c) + for _, o in ipairs(c) do + o.children.parent = c.entity + @world:add(o) + end + end, + onRemove = :(c) + for _, o in ipairs(c) do + @world:remove(o) + o.children.parent = nil + end + if c.parent then + c.parent.children:remove(c.entity) + end + end +} diff --git a/ecs/timer.can b/ecs/timer.can new file mode 100644 index 0000000..52405e8 --- /dev/null +++ b/ecs/timer.can @@ -0,0 +1,35 @@ +--- Timer system +-- Handles ubiquitousse timers. + +let timer = require((...):match("^(.-)ecs%.timer").."scene") + +return { + name = "timer", + filter = "timer", + default = { + -- timer object + }, + process = :(t, dt) + t:update(dt) + if t:dead() then + @world:remove(t.entity) + end + end, + --- System methods --- + --- Add a new timer + run = :(func) + local t = timer.run(func) + @world:add { + timer = t + } + return t + end, + --- Add a new tween + tween = :(duration, tbl, to, method) + local t = timer.tween(duration, tbl, to, method) + @world:add { + timer = t + } + return t + end +}