From d94d9fb122e42264eca20bb037fe8a82290bd3e2 Mon Sep 17 00:00:00 2001
From: sanine <sanine.not@pm.me>
Date: Thu, 16 Mar 2023 12:12:39 -0500
Subject: implement ecs node cascading

---
 honey/ecs.lua    | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 honey/mat4.lua   |  7 ++++
 honey/std.lua    | 17 ++++------
 honey/window.lua |  8 ++---
 4 files changed, 113 insertions(+), 16 deletions(-)

(limited to 'honey')

diff --git a/honey/ecs.lua b/honey/ecs.lua
index ef682b5..3bdf850 100644
--- a/honey/ecs.lua
+++ b/honey/ecs.lua
@@ -23,7 +23,8 @@ function Filter.new(_, operation, tbl)
 		end
 	end
 
-	return function(entity) 
+	return function(entity, _self) 
+		local entity = _self or entity -- able to call as . or :
 		return Filter.check(self, entity)
 	end
 end
@@ -97,4 +98,98 @@ function Filter.checkNOR(self, entity)
 end
 
 
+--===== worlds =====--
+
+World = {}
+World.__index = World
+
+function World.new(_)
+	local self = {}
+	self.systems = {}
+	self.entities = {}
+	setmetatable(self, World)
+	return self
+end
+setmetatable(World, {__call=World.new})
+
+
+local function systemLt(a, b)
+	return (a.priority or 50) < (b.priority or 50)
+end
+function World.addSystem(self, system)
+	assert(system.update, "systems must have an 'update' key")
+	assert(system.filter, "systems must have a 'filter' key")
+	system.entities = {}
+	table.insert(self.systems, system)
+	table.sort(self.systems, systemLt)
+end
+
+
+local function addEntityToSystem(system, entity)
+	-- check if entity is already present
+	if system.entities[entity] then return end
+
+	if system.onAddEntity then
+		system.onAddEntity(entity)
+	end
+	system.entities[entity] = true
+end
+
+
+local function removeEntityFromSystem(system, entity)
+	-- check if entity is already absent
+	if not system.entities[entity] then return end
+
+	if system.onRemoveEntity then
+		system.onRemoveEntity(entity)
+	end
+	system.entities[entity] = nil
+end
+
+
+function World.addEntity(self, entity)
+	self.entities[entity] = true
+	for _, system in ipairs(self.systems) do
+		if system.filter(entity) then
+			addEntityToSystem(system, entity)
+		end
+	end
+end
+
+
+function World.reconfigureEntity(self, entity)
+	for _, system in ipairs(self.systems) do
+		if system.filter(entity) then
+			addEntityToSystem(system, entity)
+		else
+			removeEntityFromSystem(system, entity)
+		end
+	end
+end
+
+
+function World.removeEntity(self, entity)
+	self.entities[entity] = nil
+	for _, system in ipairs(self.systems) do
+		removeEntityFromSystem(system, entity)
+	end
+end
+
+
+function World.reconfigureAllEntities(self)
+	for entity in pairs(self.entities) do
+		self:reconfigureEntity(entity)
+	end
+end
+
+
+function World.update(self, dt)
+	for _, system in ipairs(self.systems) do
+		for entity in pairs(system.entities) do
+			system.update(entity, dt)
+		end
+	end
+end
+
+
 return module
diff --git a/honey/mat4.lua b/honey/mat4.lua
index a97129c..8ea73d4 100644
--- a/honey/mat4.lua
+++ b/honey/mat4.lua
@@ -57,6 +57,13 @@ end
 setmetatable(Mat4, {__call=Mat4.new})
 
 
+function Mat4.Identity()
+	local m = Mat4()
+	m:identity()
+	return m
+end
+
+
 function Mat4.__index(self, key)
 	if type(key) == "number" then
 		return RowLookup(key, self.data)
diff --git a/honey/std.lua b/honey/std.lua
index ba86eb0..752df4d 100644
--- a/honey/std.lua
+++ b/honey/std.lua
@@ -1,16 +1,11 @@
 local init = require 'honey.init'
-local window = require 'honey.window'
-local mesh = require 'honey.mesh'
-local Vec3 = require 'honey.vec3'
-local Mat4 = require 'honey.mat4'
-local Shader = require 'honey.shader'
 
 honey.init = init.init
 honey.terminate = init.terminate
 
-honey.Window = window.Window
-honey.mesh = mesh
-honey.Vec3 = Vec3
-honey.Mat4 = Mat4
-
-honey.Shader = Shader
+honey.ecs        = require 'honey.ecs'
+honey.Mat4       = require 'honey.mat4'
+honey.mesh       = require 'honey.mesh'
+honey.Shader     = require 'honey.shader'
+honey.Vec3       = require 'honey.vec3'
+honey.Window     = require 'honey.window'
diff --git a/honey/window.lua b/honey/window.lua
index 471d51e..fa777d0 100644
--- a/honey/window.lua
+++ b/honey/window.lua
@@ -1,7 +1,7 @@
-local window = {}
+local module = {}
 local glfw = honey.glfw
-setmetatable(window, {__index=_G})
-setfenv(1, window)
+setmetatable(module, {__index=_G})
+setfenv(1, module)
 
 
 Window = {}
@@ -157,4 +157,4 @@ function Window.swapBuffers(self)
 end
 
 
-return window
+return module.Window
-- 
cgit v1.2.1