summaryrefslogtreecommitdiff
path: root/honey/ecs-systems.lua
blob: 5b9692b8577e99f5b28f0046c6b76d9f20d99198 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
local ecs = require 'honey.ecs'
local gl = honey.gl
local glfw = honey.glfw


local module = {}
setmetatable(module, {__index=_G})
setfenv(1, module)



--===== transform cascading =====--

transform = function(params)
	return {
		db = params.db,
		update = function(self, dt)
			local entities = self.db:queryComponent("transform")
	
			-- prepare transforms
			for id, transform in pairs(entities) do
				transform._visited = false
			end
	
			-- helper function
			local function recursiveTransform(transform)
				if transform._visited then
					return transform._matrix
				end
	
				if not transform.parent then
					transform._matrix = transform.matrix
				else
					local parentTransform = self.db:getComponent(transform.parent, "transform")
					local parentMatrix = recursiveTransform(parentTransform)
					transform._matrix = parentMatrix * transform.matrix
				end
				transform._visited = true
				return transform._matrix
			end
	
			-- compute transforms
			for id, transform in pairs(entities) do
				recursiveTransform(transform)
			end
		end,
		priority = 0,
	}
end



--===== rendering =====--

function renderCamera(params) 
	return {
		camera = params.camera,
		db = params.db,
		priority = params.priority or 99,
		update = function(self, dt)
			local cameraParams = self.db:getComponent(self.camera, "camera")
			local cameraTransform = self.db:getComponent(self.camera, "transform")
			local view
			if cameraTransform then
				view = cameraTransform._matrix
			else
				view = Mat4():identity()
			end
	
			local entities = self.db:queryComponent("renderMesh")
			for entity, tbl in pairs(entities) do
				-- get shader
				local shader = honey.shader.loadShader(tbl.shader.vertex, tbl.shader.fragment)
				shader:use()
	
				-- bind textures
				local texOffset = 0
				for name, texTbl in pairs(tbl.textures or {}) do
					local texture = honey.image.loadImage(texTbl.filename, texTbl.params)
					gl.BindTexture(gl.TEXTURE_2D + texOffset, texture.texture)
					shader:setInt(name, texOffset)
					texOffset = texOffset + 1
				end
	
				-- configure default uniforms
				local query = self.db:getComponent(entity, "transform")
				local model = (query and query._matrix) or Mat4():identity()
				shader:configure{
					float={
						time=glfw.GetTime(),
					},
					matrix={
						view=view,
						projection=cameraParams.projection,
						model=model,
					},
				}
	
				-- draw mesh
				local mesh = honey.mesh.loadMesh(tbl.mesh.filename, tbl.mesh.index)
				mesh:drawElements()
	
				-- unbind textures
				for i=0,texOffset-1 do
					gl.BindTexture(gl.TEXTURE_2D + i, 0)
				end
			end
		end,
	}
end



--===== update functions =====--


--===== script system =====--

script = function(params)
	return {
		db=params.db,
		update=function(self, dt)
			local entities = self.db:queryComponent("script")
			for id, script in pairs(entities) do
				local f = require(script.name)
				f(self.db, id, dt)
			end
		end
	}
end


return module