From 371e3a188e190a9c8b53dc6eef02d4eea72db826 Mon Sep 17 00:00:00 2001
From: sanine <sanine.not@pm.me>
Date: Thu, 13 Apr 2023 23:40:31 -0500
Subject: move message dispatching into ecs-systems.lua

---
 honey/ecs-systems.lua | 93 ++++++++++++++++++++++++++++++++++++++++++++++++---
 honey/ecs.lua         | 15 ++++++++-
 2 files changed, 103 insertions(+), 5 deletions(-)

(limited to 'honey')

diff --git a/honey/ecs-systems.lua b/honey/ecs-systems.lua
index 5b9692b..ed51e5d 100644
--- a/honey/ecs-systems.lua
+++ b/honey/ecs-systems.lua
@@ -8,6 +8,28 @@ setmetatable(module, {__index=_G})
 setfenv(1, module)
 
 
+-- helper function for retrieving script functions 
+local function getFunction(script)
+	local f = require(script.script)
+	if script.func then
+		return f[script.func]
+	else
+		return f
+	end
+end
+
+
+--===== dispatch messages to handlers =====--
+
+dispatch = function(entities, msg, data)
+	local query = entities:queryComponent(msg)
+	for id, handler in pairs(query) do
+		local f = getFunction(handler)
+		f(entities, id, data)
+	end
+end
+
+
 
 --===== transform cascading =====--
 
@@ -111,9 +133,6 @@ end
 
 
 
---===== update functions =====--
-
-
 --===== script system =====--
 
 script = function(params)
@@ -122,7 +141,7 @@ script = function(params)
 		update=function(self, dt)
 			local entities = self.db:queryComponent("script")
 			for id, script in pairs(entities) do
-				local f = require(script.name)
+				local f = getFunction(script)
 				f(self.db, id, dt)
 			end
 		end
@@ -130,4 +149,70 @@ script = function(params)
 end
 
 
+--===== physics =====--
+
+physics = function(params)
+	local interval = params.interval or 0.01
+	local groupSize = params.groupSize or 20
+	return {
+		db=params.db,
+		space=params.space,
+		world=params.world,
+		contactGroup=ode.JointGroupCreate(groupSize),
+		time=interval,
+		update=function(self, dt)
+			local query = self.db:queryComponent("physics")
+			-- TODO: create physics bodies 
+
+			self.time = self.time + dt
+			-- only run the update every [interval] seconds
+			if self.time > interval then
+				self.time = self.time - interval
+
+				-- check for near collisions between geoms
+				ode.SpaceCollide(self.space, function(a, b)
+					-- check for actual collisions
+					local collisions = ode.Collide(a, b, 1)
+					if #collisions > 0 then
+						-- set up the joint params
+						local contact = ode.CreateContact{ surface={
+							mode = ode.ContactBounce + ode.ContactSoftCFM,
+							mu = ode.Infinity,
+							bounce = 0.90,
+							bounce_vel = 0.1,
+							soft_cfm = 0.001,
+						}}
+						ode.ContactSetGeom(contact, collisions[1])
+						-- create the joint
+						local joint = ode.JointCreateContact(
+							self.world,
+							self.contactgroup,
+							contact
+						)
+						-- attach the two bodies
+						local bodyA = ode.GeomGetData(a)
+						local bodyB = ode.GeomGetData(b)
+						ode.JointAttach(joint, bodyA, bodyB)
+					end
+				end)
+				-- update the world
+				ode.WorldQuickStep(self.world, interval)
+				-- remove all contact joints
+				ode.JointGroupEmpty(self.contactGroup)
+
+				-- update entity transforms
+				for id, physics in pairs(query) do
+					local x,y,z = ode.BodyGetPosition(physics._body)
+					local d,a,b,c = ode.BodyGetQuaternion(physics._body)
+					entity.transform
+						:identity()
+						:translate(Vec3{x,y,z})
+						:mul(Quaternion{a,b,c,d}:toMat4())
+				end
+			end
+		end,
+	}
+end
+
+
 return module
diff --git a/honey/ecs.lua b/honey/ecs.lua
index 69feb12..39f1c77 100644
--- a/honey/ecs.lua
+++ b/honey/ecs.lua
@@ -69,9 +69,22 @@ function EntityDb.addComponent(self, id, name, value)
 end
 
 
+-- add multiple components at once, for convenience
+function EntityDb.addComponents(self, id, components)
+	for name, value in pairs(components) do
+		self:addComponent(id, name, value)
+	end
+end
+
+
 -- get all entities with a given component
 function EntityDb.queryComponent(self, name)
-	return self.components[name].data
+	local component = self.components[name]
+	if component then 
+		return component.data
+	else
+		return {}
+	end
 end
 
 
-- 
cgit v1.2.1