42
42
index: number,
43
43
count: number,
44
44
column: number
45
- }
45
+ }
46
46
47
47
]]
48
48
@@ -131,7 +131,7 @@ local function ECS_ENTITY_T_LO(e: i53): i24
131
131
return if e > ECS_ENTITY_MASK then (e // ECS_ID_FLAGS_MASK ) // ECS_ENTITY_MASK else e
132
132
end
133
133
134
- local function STRIP_GENERATION (e : i53 ): i24
134
+ local function STRIP_GENERATION (e : i53 ): i24
135
135
return ECS_ENTITY_T_LO (e )
136
136
end
137
137
@@ -149,7 +149,7 @@ local function getAlive(index: EntityIndex, e: i24): i53
149
149
if id then
150
150
local currentGeneration = ECS_GENERATION (id )
151
151
local gen = ECS_GENERATION (e )
152
- if gen == currentGeneration then
152
+ if gen == currentGeneration then
153
153
return id
154
154
end
155
155
@@ -159,7 +159,7 @@ local function getAlive(index: EntityIndex, e: i24): i53
159
159
error (ERROR_ENTITY_NOT_ALIVE )
160
160
end
161
161
162
- local function sparseGet (entityIndex , id )
162
+ local function sparseGet (entityIndex , id )
163
163
return entityIndex .sparse [getAlive (entityIndex , id )]
164
164
end
165
165
353
353
-- TODO:
354
354
-- should have an additional `nth` parameter which selects the nth target
355
355
-- this is important when an entity can have multiple relationships with the same target
356
- local function target (world : World , entity : i53 , relation : i24 --[[, nth: number]] ): i24 ?
356
+ local function target (world : World , entity : i53 , relation : i24 --[[, nth: number]] ): i24 ?
357
357
local entityIndex = world .entityIndex
358
358
local record = entityIndex .sparse [entity ]
359
359
local archetype = record .archetype
@@ -374,7 +374,7 @@ local function target(world: World, entity: i53, relation: i24--[[, nth: number]
374
374
return ECS_PAIR_OBJECT (entityIndex , archetype .types [archetypeRecord ])
375
375
end
376
376
377
- local function parent (world : World , entity : i53 )
377
+ local function parent (world : World , entity : i53 )
378
378
return target (world , entity , EcsChildOf )
379
379
end
380
380
@@ -462,7 +462,7 @@ local function add(world: World, entityId: i53, componentId: i53)
462
462
end
463
463
464
464
-- Symmetric like `World.add` but idempotent
465
- local function set (world : World , entityId : i53 , componentId : i53 , data : unknown )
465
+ local function set (world : World , entityId : i53 , componentId : i53 , data : unknown )
466
466
local record = world .entityIndex .sparse [entityId ]
467
467
local from = record .archetype
468
468
local to = archetypeTraverseAdd (world , componentId , from )
@@ -600,17 +600,17 @@ local function delete(world: World, entityId: i53)
600
600
601
601
end
602
602
603
- local function clear (world : World , entityId : i53 )
603
+ local function clear (world : World , entityId : i53 )
604
604
--TODO: use sparse_get (stashed)
605
605
local record = world .entityIndex .sparse [entityId ]
606
- if not record then
606
+ if not record then
607
607
return
608
608
end
609
609
610
610
local ROOT_ARCHETYPE = world .ROOT_ARCHETYPE
611
611
local archetype = record .archetype
612
612
613
- if archetype == nil or archetype == ROOT_ARCHETYPE then
613
+ if archetype == nil or archetype == ROOT_ARCHETYPE then
614
614
return
615
615
end
616
616
@@ -662,21 +662,29 @@ local function noop(_self: Query, ...): () -> ()
662
662
end
663
663
664
664
local EmptyQuery = {
665
- __iter = noop ,
666
- without = noop ,
665
+ __iter = iterNoop ,
666
+ next = noop ,
667
+ replace = noop ,
668
+ without = function (self )
669
+ return self
670
+ end
667
671
}
668
- EmptyQuery .__index = EmptyQuery
669
- setmetatable (EmptyQuery , EmptyQuery )
670
672
671
673
export type Query = typeof (EmptyQuery )
672
674
673
675
type CompatibleArchetype = { archetype : Archetype , indices : { number } }
674
676
675
- local function preparedQuery (compatibleArchetypes : { Archetype },
676
- components : { i53 ? }, indices : { { number } })
677
+ local function replaceMult (row , columns , ... )
678
+ for i , column in columns do
679
+ column [row ] = select (i , ... )
680
+ end
681
+ end
682
+
683
+ local function preparedQuery (compatibleArchetypes : { Archetype },
684
+ components : { i53 ? }, indices : { { number } })
677
685
678
686
local queryLength = # components
679
-
687
+
680
688
local lastArchetype = 1
681
689
local archetype : Archetype = compatibleArchetypes [lastArchetype ]
682
690
@@ -686,16 +694,16 @@ local function preparedQuery(compatibleArchetypes: { Archetype },
686
694
687
695
local queryOutput = {}
688
696
689
- local entities = archetype .entities
697
+ local entities = archetype .entities
690
698
local i = # entities
691
699
692
700
local function queryNext (): ...any
693
701
local entityId = entities [i ]
694
- while entityId == nil do
702
+ while entityId == nil do
695
703
lastArchetype += 1
696
704
archetype = compatibleArchetypes [lastArchetype ]
697
-
698
- if not archetype then
705
+
706
+ if not archetype then
699
707
return
700
708
end
701
709
@@ -782,34 +790,77 @@ local function preparedQuery(compatibleArchetypes: { Archetype },
782
790
783
791
return self
784
792
end
785
-
786
- local it = {
787
- __iter = function ()
788
- lastArchetype = 1
789
- archetype = compatibleArchetypes [1 ]
790
- entities = archetype .entities
791
- i = # entities
792
793
793
- return queryNext
794
- end ,
794
+ local function iter ()
795
+ lastArchetype = 1
796
+ archetype = compatibleArchetypes [1 ]
797
+ entities = archetype .entities
798
+ i = # entities
799
+
800
+ return queryNext
801
+ end
802
+
803
+ local function replace (_ , fn )
804
+ for i , archetype in compatibleArchetypes do
805
+ local tr = indices [i ]
806
+ local columns = archetype .columns
807
+
808
+ for row in archetype .entities do
809
+ if queryLength == 1 then
810
+ local a = columns [tr [1 ]]
811
+ local pa = fn (a [row ])
812
+
813
+ a [row ] = pa
814
+ elseif queryLength == 2 then
815
+ local a = columns [tr [1 ]]
816
+ local b = columns [tr [2 ]]
817
+
818
+ a [row ], b [row ] = fn (a [row ], b [row ])
819
+ elseif queryLength == 3 then
820
+ local a = columns [tr [1 ]]
821
+ local b = columns [tr [2 ]]
822
+ local c = columns [tr [3 ]]
823
+
824
+ a [row ], b [row ], c [row ] = fn (a [row ], b [row ], c [row ])
825
+ elseif queryLength == 4 then
826
+ local a = columns [tr [1 ]]
827
+ local b = columns [tr [2 ]]
828
+ local c = columns [tr [3 ]]
829
+ local d = columns [tr [4 ]]
830
+
831
+ a [row ], b [row ], c [row ], d [row ] = fn (
832
+ a [row ], b [row ], c [row ], d [row ])
833
+ else
834
+ for i = 1 , queryLength do
835
+ queryOutput [i ] = columns [tr [i ]][row ]
836
+ end
837
+ replaceMult (row , columns , fn (unpack (queryOutput )))
838
+ end
839
+ end
840
+ end
841
+ end
842
+
843
+ local it = {
844
+ __iter = iter ,
795
845
next = queryNext ,
796
- without = without
846
+ without = without ,
847
+ replace = replace
797
848
}
798
849
799
850
return setmetatable (it , it ) :: any
800
851
end
801
852
802
- local function query (world : World , ... : number ): Query
853
+ local function query (world : World , ... : number ): Query
803
854
-- breaking?
804
855
if (... ) == nil then
805
856
error ("Missing components" )
806
857
end
807
858
808
859
local indices : { { number } } = {}
809
- local compatibleArchetypes : { Archetype } = {}
860
+ local compatibleArchetypes : { Archetype } = {}
810
861
local length = 0
811
862
812
- local components : { number } = { ... }
863
+ local components : { number } = { ... }
813
864
local archetypes : { Archetype } = world .archetypes :: any
814
865
815
866
local firstArchetypeMap : ArchetypeMap
@@ -989,7 +1040,7 @@ export type WorldShim = typeof(setmetatable(
989
1040
local World = {}
990
1041
World .__index = World
991
1042
992
- function World .new ()
1043
+ function World .new ()
993
1044
local self = setmetatable ({
994
1045
archetypeIndex = {} :: { [string ]: Archetype },
995
1046
archetypes = {} :: Archetypes ,
0 commit comments