1
1
--[[
2
- ECS Lua v2.1.1
2
+ ECS Lua v2.1.2
3
3
4
4
ECS Lua is a fast and easy to use ECS (Entity Component System) engine for game development.
5
5
818
818
__F__ [" ECS" ] = function ()
819
819
-- src/ECS.lua
820
820
--[[
821
- ECS Lua v2.1.0 [2021-10-15 11:00]
821
+ ECS Lua v2.1.2
822
822
823
823
ECS Lua is a fast and easy to use ECS (Entity Component System) engine for game development.
824
824
@@ -1233,12 +1233,12 @@ __F__["EntityRepository"] = function()
1233
1233
local archetype = entity .archetype
1234
1234
local storage = self ._archetypes [archetype ]
1235
1235
if (storage == nil ) then
1236
- storage = { Count = 0 , Entities = {} }
1236
+ storage = { count = 0 , entities = {} }
1237
1237
self ._archetypes [archetype ] = storage
1238
1238
end
1239
1239
1240
- storage .Entities [entity ] = true
1241
- storage .Count = storage .Count + 1
1240
+ storage .entities [entity ] = true
1241
+ storage .count = storage .count + 1
1242
1242
1243
1243
self ._entitiesArchetype [entity ] = archetype
1244
1244
else
@@ -1259,10 +1259,10 @@ __F__["EntityRepository"] = function()
1259
1259
self ._entitiesArchetype [entity ] = nil
1260
1260
1261
1261
local storage = self ._archetypes [archetypeOld ]
1262
- if (storage ~= nil and storage .Entities [entity ] == true ) then
1263
- storage .Entities [entity ] = nil
1264
- storage .Count = storage .Count - 1
1265
- if (storage .Count == 0 ) then
1262
+ if (storage ~= nil and storage .entities [entity ] == true ) then
1263
+ storage .entities [entity ] = nil
1264
+ storage .count = storage .count - 1
1265
+ if (storage .count == 0 ) then
1266
1266
self ._archetypes [archetypeOld ] = nil
1267
1267
end
1268
1268
end
@@ -1293,7 +1293,7 @@ __F__["EntityRepository"] = function()
1293
1293
local chunks = {}
1294
1294
for archetype , storage in pairs (self ._archetypes ) do
1295
1295
if query :Match (archetype ) then
1296
- table.insert (chunks , storage .Entities )
1296
+ table.insert (chunks , storage .entities )
1297
1297
end
1298
1298
end
1299
1299
return query :Result (chunks ), # chunks > 0
@@ -1328,14 +1328,14 @@ __F__["Event"] = function()
1328
1328
Connection .__index = Connection
1329
1329
1330
1330
function Connection .New (event , handler )
1331
- return setmetatable ({ _Event = event , _Handler = handler }, Connection )
1331
+ return setmetatable ({ _event = event , _handler = handler }, Connection )
1332
1332
end
1333
1333
1334
1334
-- Unsubscribe
1335
1335
function Connection :Disconnect ()
1336
- local event = self ._Event
1336
+ local event = self ._event
1337
1337
if (event and not event .destroyed ) then
1338
- local idx = table .find (event ._handlers , self ._Handler )
1338
+ local idx = table .find (event ._handlers , self ._handler )
1339
1339
if idx ~= nil then
1340
1340
table.remove (event ._handlers , idx )
1341
1341
end
@@ -1492,7 +1492,6 @@ __F__["Query"] = function()
1492
1492
@return QueryResult
1493
1493
]]
1494
1494
function Query :Result (chunks )
1495
- self ._lastResultChunks = chunks
1496
1495
return QueryResult .New (chunks , self ._clauses )
1497
1496
end
1498
1497
@@ -1894,7 +1893,7 @@ __F__["QueryResult"] = function()
1894
1893
]]
1895
1894
function QueryResult :AnyMatch (predicate )
1896
1895
local anyMatch = false
1897
- self :Run (function (value )
1896
+ self :ForEach (function (value )
1898
1897
if predicate (value ) then
1899
1898
anyMatch = true
1900
1899
end
@@ -1912,7 +1911,7 @@ __F__["QueryResult"] = function()
1912
1911
]]
1913
1912
function QueryResult :AllMatch (predicate )
1914
1913
local allMatch = true
1915
- self :Run (function (value )
1914
+ self :ForEach (function (value )
1916
1915
if (not predicate (value )) then
1917
1916
allMatch = false
1918
1917
end
@@ -1935,38 +1934,22 @@ __F__["QueryResult"] = function()
1935
1934
]]
1936
1935
function QueryResult :FindAny ()
1937
1936
local out
1938
- self :Run (function (value )
1937
+ self :ForEach (function (value )
1939
1938
out = value
1940
1939
-- break
1941
1940
return true
1942
1941
end )
1943
1942
return out
1944
1943
end
1945
1944
1946
- --[[
1947
- Performs an action for each element of this QueryResult.
1948
-
1949
- This is a terminal operation.
1950
-
1951
- The behavior of this operation is explicitly nondeterministic. This operation does not guarantee to respect the
1952
- encounter order of the QueryResult.
1953
-
1954
- @param action {function(value, count) -> bool} A action to perform on the elements, breaks execution case returns true
1955
- ]]
1956
- function QueryResult :ForEach (action )
1957
- self :Run (function (value , count )
1958
- return action (value , count ) == true
1959
- end )
1960
- end
1961
-
1962
1945
--[[
1963
1946
Returns an array containing the elements of this QueryResult.
1964
1947
1965
1948
This is a terminal operation.
1966
1949
]]
1967
1950
function QueryResult :ToArray ()
1968
1951
local array = {}
1969
- self :Run (function (value )
1952
+ self :ForEach (function (value )
1970
1953
table.insert (array , value )
1971
1954
end )
1972
1955
return array
@@ -1981,7 +1964,7 @@ __F__["QueryResult"] = function()
1981
1964
]]
1982
1965
function QueryResult :Iterator ()
1983
1966
local thread = coroutine.create (function ()
1984
- self :Run (function (value , count )
1967
+ self :ForEach (function (value , count )
1985
1968
-- These will be passed back again next iteration
1986
1969
coroutine.yield (value , count )
1987
1970
end )
@@ -1993,13 +1976,17 @@ __F__["QueryResult"] = function()
1993
1976
end
1994
1977
end
1995
1978
1996
-
1997
1979
--[[
1998
- Pipeline this QueryResult, applying callback to each value
1980
+ Performs an action for each element of this QueryResult.
1981
+
1982
+ This is a terminal operation.
1983
+
1984
+ The behavior of this operation is explicitly nondeterministic. This operation does not guarantee to respect the
1985
+ encounter order of the QueryResult.
1999
1986
2000
- @param callback {function(value, count) -> bool} Break execution case returns true
1987
+ @param action {function(value, count) -> bool} A action to perform on the elements, breaks execution case returns true
2001
1988
]]
2002
- function QueryResult :Run ( callback )
1989
+ function QueryResult :ForEach ( action )
2003
1990
local count = 1
2004
1991
local pipeline = self ._pipeline
2005
1992
@@ -2008,13 +1995,14 @@ __F__["QueryResult"] = function()
2008
1995
-- faster
2009
1996
for _ , entities in ipairs (self .chunks ) do
2010
1997
for entity , _ in pairs (entities ) do
2011
- if (callback (entity , count ) == true ) then
1998
+ if (action (entity , count ) == true ) then
2012
1999
return
2013
2000
end
2014
2001
count = count + 1
2015
2002
end
2016
2003
end
2017
2004
else
2005
+ -- Pipeline this QueryResult, applying callback to each value
2018
2006
for i , entities in ipairs (self .chunks ) do
2019
2007
for entity ,_ in pairs (entities ) do
2020
2008
local mustStop = false
@@ -2038,7 +2026,7 @@ __F__["QueryResult"] = function()
2038
2026
end
2039
2027
2040
2028
if itemAccepted then
2041
- if (callback (value , count ) == true ) then
2029
+ if (action (value , count ) == true ) then
2042
2030
return
2043
2031
end
2044
2032
count = count + 1
@@ -2296,7 +2284,29 @@ __F__["SystemExecutor"] = function()
2296
2284
local SystemExecutor = {}
2297
2285
SystemExecutor .__index = SystemExecutor
2298
2286
2299
- function SystemExecutor .New (world , systems )
2287
+ function SystemExecutor .New (world )
2288
+ local executor = setmetatable ({
2289
+ _world = world ,
2290
+ _onExit = {},
2291
+ _onEnter = {},
2292
+ _onRemove = {},
2293
+ _task = {},
2294
+ _render = {},
2295
+ _process = {},
2296
+ _transform = {},
2297
+ _schedulers = {},
2298
+ _lastFrameMatchQueries = {},
2299
+ _currentFrameMatchQueries = {},
2300
+ }, SystemExecutor )
2301
+
2302
+ world :OnQueryMatch (function (query )
2303
+ executor ._currentFrameMatchQueries [query ] = true
2304
+ end )
2305
+
2306
+ return executor
2307
+ end
2308
+
2309
+ function SystemExecutor :SetSystems (systems )
2300
2310
local onExit = {}
2301
2311
local onEnter = {}
2302
2312
local onRemove = {}
@@ -2348,26 +2358,13 @@ __F__["SystemExecutor"] = function()
2348
2358
table.sort (updateProcess , orderSystems )
2349
2359
table.sort (updateTransform , orderSystems )
2350
2360
2351
- -- tasks = resolveDependecy(systems)
2352
- local executor = setmetatable ({
2353
- _world = world ,
2354
- _onExit = onExit ,
2355
- _onEnter = onEnter ,
2356
- _onRemove = onRemove ,
2357
- _task = updateTask ,
2358
- _render = updateRender ,
2359
- _process = updateProcess ,
2360
- _transform = updateTransform ,
2361
- _schedulers = {},
2362
- _lastFrameMatchQueries = {},
2363
- _currentFrameMatchQueries = {},
2364
- }, SystemExecutor )
2365
-
2366
- world :OnQueryMatch (function (query )
2367
- executor ._currentFrameMatchQueries [query ] = true
2368
- end )
2369
-
2370
- return executor
2361
+ self ._onExit = onExit
2362
+ self ._onEnter = onEnter
2363
+ self ._onRemove = onRemove
2364
+ self ._task = updateTask
2365
+ self ._render = updateRender
2366
+ self ._process = updateProcess
2367
+ self ._transform = updateTransform
2371
2368
end
2372
2369
2373
2370
--[[
@@ -2989,22 +2986,17 @@ __F__["World"] = function()
2989
2986
]]
2990
2987
version = 0 ,
2991
2988
--[[
2992
- Allows you to define the maximum time that the JobSystem can operate in each step. This value is a percentage
2993
- of the expected time for each frame (see World:SetFrequency(frequency)).
2989
+ Allows you to define the maximum time that the JobSystem can operate in each frame.
2994
2990
2995
- The default value is 0.7
2991
+ The default value is 0.011666666666666665 = ((1000/60/1000)*0.7)
2996
2992
2997
- Ex1. If the world has a frequency set to 30Hz (30 fps), then the JobSystem will try to run a maximum of 0.0077
2998
- seconds in each step, totaling 0.023 seconds of processing per frame. A game that runs at 30fps has 0.0333
2999
- seconds to do all the processing for each frame, including rendering (1000/30/1000)
2993
+ A game that runs at 30fps has 0.0333 seconds to do all the processing for each frame, including rendering
3000
2994
- 30FPS = ((1000/30/1000)*0.7)/3 = 0.007777777777777777
3001
2995
3002
- Ex2. If the world has the frequency set to 60Hz (60 fps), then the JobSystem will try to run a maximum of 0.0038
3003
- seconds in each step, totaling 0.011 seconds of processing per frame. A game that runs at 60fps has 0.0166
3004
- seconds to do all the processing for each frame, including rendering (1000/60/1000)
2996
+ A game that runs at 60fps has 0.0166 seconds to do all the processing for each frame, including rendering
3005
2997
- 60FPS = ((1000/60/1000)*0.7)/3 = 0.0038888888888888883
3006
2998
]]
3007
- maxScheduleExecTimePercent = 0.7 ,
2999
+ maxTasksExecTime = 0.013333333333333334 ,
3008
3000
_dirty = false , -- True when create/remove entity, add/remove entity component (change archetype)
3009
3001
_timer = Timer .New (frequency ),
3010
3002
_systems = {}, -- systems in this world
@@ -3017,7 +3009,7 @@ __F__["World"] = function()
3017
3009
}, World )
3018
3010
3019
3011
-- System execution plan
3020
- world ._executor = SystemExecutor .New (world , {} )
3012
+ world ._executor = SystemExecutor .New (world )
3021
3013
3022
3014
world ._onChangeArchetypeEvent :Connect (function (entity , archetypeOld , archetypeNew )
3023
3015
world :_OnChangeArchetype (entity , archetypeOld , archetypeNew )
@@ -3072,7 +3064,8 @@ __F__["World"] = function()
3072
3064
3073
3065
if self ._systems [systemClass ] == nil then
3074
3066
self ._systems [systemClass ] = systemClass .New (self , config )
3075
- self ._executor = SystemExecutor .New (self , self ._systems )
3067
+
3068
+ self ._executor :SetSystems (self ._systems )
3076
3069
end
3077
3070
end
3078
3071
end
@@ -3186,32 +3179,39 @@ __F__["World"] = function()
3186
3179
]]
3187
3180
function World :Update (step , now )
3188
3181
3189
- --[[
3190
- .-------------------------------------.
3191
- |----- process|transform|render ------|
3192
- | | |
3193
- | s:ShouldUpdate() | < |
3194
- | s:Update() | s:OnRemove() |
3195
- | | s:OnExit() |
3196
- | | s:OnEnter() |
3197
- | | >{0...n} |
3198
- | | |
3199
- '-------------------------------------'
3200
- ]]
3201
-
3182
+
3202
3183
self ._timer :Update (
3203
3184
now , step ,
3204
3185
function (Time )
3186
+ --[[
3187
+ JobSystem
3188
+ .------------------.
3189
+ | pipeline |
3190
+ |------------------|
3191
+ | s:ShouldUpdate() |
3192
+ | s:Update() |
3193
+ '------------------'
3194
+ ]]
3205
3195
if step == " process" then
3206
3196
self ._executor :ScheduleTasks (Time )
3207
3197
end
3208
3198
-- run suspended Tasks
3209
- -- 60FPS = ((1000/60/1000)*0.7)/3 = 0.0038888888888888883
3210
- -- 30FPS = ((1000/30/1000)*0.7)/3 = 0.007777777777777777
3211
- local maxScheduleExecTime = (self ._timer .Time .DeltaFixed * (self .maxScheduleExecTimePercent or 0.7 ))/ 3
3212
- self ._executor :ExecTasks (maxScheduleExecTime )
3199
+ self ._executor :ExecTasks (self .maxTasksExecTime )
3213
3200
end ,
3214
3201
function (Time )
3202
+ --[[
3203
+ .------------------.
3204
+ | pipeline |
3205
+ |------------------|
3206
+ | s:ShouldUpdate() |
3207
+ | s:Update() |
3208
+ | |
3209
+ |-- CLEAR ---------|
3210
+ | s:OnRemove() |
3211
+ | s:OnExit() |
3212
+ | s:OnEnter() |
3213
+ '------------------'
3214
+ ]]
3215
3215
if step == " process" then
3216
3216
self ._executor :ExecProcess (Time )
3217
3217
elseif step == " transform" then
0 commit comments