mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-24 17:10:03 +00:00
parent
1e633d4563
commit
c80bb0e2fd
2 changed files with 123 additions and 79 deletions
170
src/init.luau
170
src/init.luau
|
@ -26,7 +26,7 @@ type GraphEdges = Map<i53, GraphEdge>
|
||||||
type GraphNode = {
|
type GraphNode = {
|
||||||
add: GraphEdges,
|
add: GraphEdges,
|
||||||
remove: GraphEdges,
|
remove: GraphEdges,
|
||||||
refs: GraphEdge
|
refs: GraphEdge,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Archetype = {
|
export type Archetype = {
|
||||||
|
@ -69,34 +69,34 @@ type ArchetypeDiff = {
|
||||||
removed: Ty,
|
removed: Ty,
|
||||||
}
|
}
|
||||||
|
|
||||||
local HI_COMPONENT_ID = _G.__JECS_HI_COMPONENT_ID or 256
|
local HI_COMPONENT_ID = _G.__JECS_HI_COMPONENT_ID or 256
|
||||||
|
|
||||||
local EcsOnAdd = HI_COMPONENT_ID + 1
|
local EcsOnAdd = HI_COMPONENT_ID + 1
|
||||||
local EcsOnRemove = HI_COMPONENT_ID + 2
|
local EcsOnRemove = HI_COMPONENT_ID + 2
|
||||||
local EcsOnSet = HI_COMPONENT_ID + 3
|
local EcsOnSet = HI_COMPONENT_ID + 3
|
||||||
local EcsWildcard = HI_COMPONENT_ID + 4
|
local EcsWildcard = HI_COMPONENT_ID + 4
|
||||||
local EcsChildOf = HI_COMPONENT_ID + 5
|
local EcsChildOf = HI_COMPONENT_ID + 5
|
||||||
local EcsComponent = HI_COMPONENT_ID + 6
|
local EcsComponent = HI_COMPONENT_ID + 6
|
||||||
local EcsOnDelete = HI_COMPONENT_ID + 7
|
local EcsOnDelete = HI_COMPONENT_ID + 7
|
||||||
local EcsOnDeleteTarget = HI_COMPONENT_ID + 8
|
local EcsOnDeleteTarget = HI_COMPONENT_ID + 8
|
||||||
local EcsDelete = HI_COMPONENT_ID + 9
|
local EcsDelete = HI_COMPONENT_ID + 9
|
||||||
local EcsRemove = HI_COMPONENT_ID + 10
|
local EcsRemove = HI_COMPONENT_ID + 10
|
||||||
local EcsName = HI_COMPONENT_ID + 11
|
local EcsName = HI_COMPONENT_ID + 11
|
||||||
local EcsRest = HI_COMPONENT_ID + 12
|
local EcsRest = HI_COMPONENT_ID + 12
|
||||||
|
|
||||||
local ECS_PAIR_FLAG = 0x8
|
local ECS_PAIR_FLAG = 0x8
|
||||||
local ECS_ID_FLAGS_MASK = 0x10
|
local ECS_ID_FLAGS_MASK = 0x10
|
||||||
local ECS_ENTITY_MASK = bit32.lshift(1, 24)
|
local ECS_ENTITY_MASK = bit32.lshift(1, 24)
|
||||||
local ECS_GENERATION_MASK = bit32.lshift(1, 16)
|
local ECS_GENERATION_MASK = bit32.lshift(1, 16)
|
||||||
|
|
||||||
local ECS_ID_DELETE = 0b0000_0001
|
local ECS_ID_DELETE = 0b0000_0001
|
||||||
local ECS_ID_IS_TAG = 0b0000_0010
|
local ECS_ID_IS_TAG = 0b0000_0010
|
||||||
local ECS_ID_HAS_ON_ADD = 0b0000_0100
|
local ECS_ID_HAS_ON_ADD = 0b0000_0100
|
||||||
local ECS_ID_HAS_ON_SET = 0b0000_1000
|
local ECS_ID_HAS_ON_SET = 0b0000_1000
|
||||||
local ECS_ID_HAS_ON_REMOVE = 0b0001_0000
|
local ECS_ID_HAS_ON_REMOVE = 0b0001_0000
|
||||||
local ECS_ID_MASK = 0b0000_0000
|
local ECS_ID_MASK = 0b0000_0000
|
||||||
|
|
||||||
local NULL_ARRAY = table.freeze({})
|
local NULL_ARRAY = table.freeze({})
|
||||||
|
|
||||||
local function FLAGS_ADD(is_pair: boolean): number
|
local function FLAGS_ADD(is_pair: boolean): number
|
||||||
local flags = 0x0
|
local flags = 0x0
|
||||||
|
@ -389,9 +389,9 @@ local function world_has(world: World, entity: number, ...: i53): boolean
|
||||||
end
|
end
|
||||||
|
|
||||||
local function world_target(world: World, entity: i53, relation: i24, index): i24?
|
local function world_target(world: World, entity: i53, relation: i24, index): i24?
|
||||||
if index == nil then
|
if index == nil then
|
||||||
index = 0
|
index = 0
|
||||||
end
|
end
|
||||||
local record = world.entityIndex.sparse[entity]
|
local record = world.entityIndex.sparse[entity]
|
||||||
local archetype = record.archetype
|
local archetype = record.archetype
|
||||||
if not archetype then
|
if not archetype then
|
||||||
|
@ -621,16 +621,16 @@ local function init_edge_for_add(world, archetype, edge: GraphEdge, id, to)
|
||||||
archetype_init_edge(archetype, edge, id, to)
|
archetype_init_edge(archetype, edge, id, to)
|
||||||
archetype_ensure_edge(world, archetype.node.add, id)
|
archetype_ensure_edge(world, archetype.node.add, id)
|
||||||
if archetype ~= to then
|
if archetype ~= to then
|
||||||
local to_refs = to.node.refs
|
local to_refs = to.node.refs
|
||||||
local next_edge = to_refs.next
|
local next_edge = to_refs.next
|
||||||
|
|
||||||
to_refs.next = edge
|
to_refs.next = edge
|
||||||
edge.prev = to_refs
|
edge.prev = to_refs
|
||||||
edge.next = next_edge
|
edge.next = next_edge
|
||||||
|
|
||||||
if next_edge then
|
if next_edge then
|
||||||
next_edge.prev = edge
|
next_edge.prev = edge
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -638,16 +638,16 @@ local function init_edge_for_remove(world, archetype, edge, id, to)
|
||||||
archetype_init_edge(archetype, edge, id, to)
|
archetype_init_edge(archetype, edge, id, to)
|
||||||
archetype_ensure_edge(world, archetype.node.remove, id)
|
archetype_ensure_edge(world, archetype.node.remove, id)
|
||||||
if archetype ~= to then
|
if archetype ~= to then
|
||||||
local to_refs = to.node.refs
|
local to_refs = to.node.refs
|
||||||
local prev_edge = to_refs.prev
|
local prev_edge = to_refs.prev
|
||||||
|
|
||||||
to_refs.prev = edge
|
to_refs.prev = edge
|
||||||
edge.next = to_refs
|
edge.next = to_refs
|
||||||
edge.prev = prev_edge
|
edge.prev = prev_edge
|
||||||
|
|
||||||
if prev_edge then
|
if prev_edge then
|
||||||
prev_edge.next = edge
|
prev_edge.next = edge
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -873,35 +873,34 @@ local function archetype_clear_edges(archetype: Archetype)
|
||||||
end
|
end
|
||||||
|
|
||||||
local cur = node_refs.next
|
local cur = node_refs.next
|
||||||
while cur do
|
while cur do
|
||||||
local edge = cur
|
local edge = cur
|
||||||
local next_edge = edge.next
|
local next_edge = edge.next
|
||||||
archetype_remove_edge(edge.from.node.add, edge.id, edge)
|
archetype_remove_edge(edge.from.node.add, edge.id, edge)
|
||||||
cur = next_edge
|
cur = next_edge
|
||||||
end
|
end
|
||||||
|
|
||||||
cur = node_refs.prev
|
cur = node_refs.prev
|
||||||
while cur do
|
while cur do
|
||||||
local edge = cur
|
local edge = cur
|
||||||
local next_edge = edge.prev
|
local next_edge = edge.prev
|
||||||
archetype_remove_edge(edge.from.node.remove, edge.id, edge)
|
archetype_remove_edge(edge.from.node.remove, edge.id, edge)
|
||||||
cur = next_edge
|
cur = next_edge
|
||||||
end
|
end
|
||||||
|
|
||||||
node_refs.next = nil
|
node_refs.next = nil
|
||||||
node_refs.prev = nil
|
node_refs.prev = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local function archetype_destroy(world: World, archetype: Archetype)
|
local function archetype_destroy(world: World, archetype: Archetype)
|
||||||
|
if archetype == world.ROOT_ARCHETYPE then
|
||||||
if archetype == world.ROOT_ARCHETYPE then
|
return
|
||||||
return
|
end
|
||||||
end
|
|
||||||
|
|
||||||
local component_index = world.componentIndex
|
local component_index = world.componentIndex
|
||||||
archetype_clear_edges(archetype)
|
archetype_clear_edges(archetype)
|
||||||
local archetype_id = archetype.id
|
local archetype_id = archetype.id
|
||||||
world.archetypes[archetype_id] = nil
|
world.archetypes[archetype_id] = nil
|
||||||
world.archetypeIndex[archetype.type] = nil
|
world.archetypeIndex[archetype.type] = nil
|
||||||
local records = archetype.records
|
local records = archetype.records
|
||||||
|
|
||||||
|
@ -917,7 +916,7 @@ local function archetype_destroy(world: World, archetype: Archetype)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function world_cleanup(world)
|
local function world_cleanup(world)
|
||||||
local archetypes = world.archetypes
|
local archetypes = world.archetypes
|
||||||
|
|
||||||
for _, archetype in archetypes do
|
for _, archetype in archetypes do
|
||||||
if #archetype.entities == 0 then
|
if #archetype.entities == 0 then
|
||||||
|
@ -929,7 +928,7 @@ local function world_cleanup(world)
|
||||||
local new_archetype_map = {}
|
local new_archetype_map = {}
|
||||||
|
|
||||||
for index, archetype in archetypes do
|
for index, archetype in archetypes do
|
||||||
new_archetypes[index] = archetype
|
new_archetypes[index] = archetype
|
||||||
new_archetype_map[archetype.type] = archetype
|
new_archetype_map[archetype.type] = archetype
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1036,24 +1035,23 @@ do
|
||||||
end
|
end
|
||||||
local object = ECS_ENTITY_T_LO(id)
|
local object = ECS_ENTITY_T_LO(id)
|
||||||
if object == delete then
|
if object == delete then
|
||||||
local id_record = component_index[id]
|
local id_record = component_index[id]
|
||||||
local flags = id_record.flags
|
local flags = id_record.flags
|
||||||
if bit32.band(flags, ECS_ID_DELETE) ~= 0 then
|
if bit32.band(flags, ECS_ID_DELETE) ~= 0 then
|
||||||
for _, child in children do
|
for _, child in children do
|
||||||
-- Cascade deletions of it has Delete as component trait
|
-- Cascade deletions of it has Delete as component trait
|
||||||
world_delete(world, child, destruct)
|
world_delete(world, child, destruct)
|
||||||
end
|
end
|
||||||
|
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
for _, child in children do
|
for _, child in children do
|
||||||
world_remove(world, child, id)
|
world_remove(world, child, id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
archetype_destroy(world, idr_t_archetype)
|
archetype_destroy(world, idr_t_archetype)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1329,11 +1327,11 @@ local function query_iter_init(query)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function query_iter(query)
|
local function query_iter(query)
|
||||||
local query_next = query.next
|
local query_next = query.next
|
||||||
if not query_next then
|
if not query_next then
|
||||||
query_next = query_iter_init(query)
|
query_next = query_iter_init(query)
|
||||||
end
|
end
|
||||||
return query_next
|
return query_next
|
||||||
end
|
end
|
||||||
|
|
||||||
local function query_without(query, ...)
|
local function query_without(query, ...)
|
||||||
|
@ -1800,4 +1798,20 @@ return {
|
||||||
pair_first = ecs_pair_first,
|
pair_first = ecs_pair_first,
|
||||||
pair_second = ecs_pair_second,
|
pair_second = ecs_pair_second,
|
||||||
entity_index_get_alive = entity_index_get_alive,
|
entity_index_get_alive = entity_index_get_alive,
|
||||||
|
|
||||||
|
archetype_append_to_records = archetype_append_to_records,
|
||||||
|
id_record_ensure = id_record_ensure,
|
||||||
|
archetype_create = archetype_create,
|
||||||
|
archetype_ensure = archetype_ensure,
|
||||||
|
find_insert = find_insert,
|
||||||
|
find_archetype_with = find_archetype_with,
|
||||||
|
find_archetype_without = find_archetype_without,
|
||||||
|
archetype_init_edge = archetype_init_edge,
|
||||||
|
archetype_ensure_edge = archetype_ensure_edge,
|
||||||
|
init_edge_for_add = init_edge_for_add,
|
||||||
|
init_edge_for_remove = init_edge_for_remove,
|
||||||
|
create_edge_for_add = create_edge_for_add,
|
||||||
|
create_edge_for_remove = create_edge_for_remove,
|
||||||
|
archetype_traverse_add = archetype_traverse_add,
|
||||||
|
archetype_traverse_remove = archetype_traverse_remove,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
local jecs = require("@jecs")
|
local jecs: typeof(require("../jecs/src")) = require("@jecs");
|
||||||
|
|
||||||
local testkit = require("@testkit")
|
local testkit = require("@testkit")
|
||||||
local BENCH, START = testkit.benchmark()
|
local BENCH, START = testkit.benchmark()
|
||||||
local __ = jecs.Wildcard
|
local __ = jecs.Wildcard
|
||||||
|
@ -71,6 +72,35 @@ local function name(world, e)
|
||||||
return world:get(e, jecs.Name)
|
return world:get(e, jecs.Name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
TEST("archetype", function()
|
||||||
|
local archetype_append_to_records = jecs.archetype_append_to_records
|
||||||
|
local id_record_ensure = jecs.id_record_ensure
|
||||||
|
local archetype_create = jecs.archetype_create
|
||||||
|
local archetype_ensure = jecs.archetype_ensure
|
||||||
|
local find_insert = jecs.find_insert
|
||||||
|
local find_archetype_with = jecs.find_archetype_with
|
||||||
|
local find_archetype_without = jecs.find_archetype_without
|
||||||
|
local archetype_init_edge = jecs.archetype_init_edge
|
||||||
|
local archetype_ensure_edge = jecs.archetype_ensure_edge
|
||||||
|
local init_edge_for_add = jecs.init_edge_for_add
|
||||||
|
local init_edge_for_remove = jecs.init_edge_for_remove
|
||||||
|
local create_edge_for_add = jecs.create_edge_for_add
|
||||||
|
local create_edge_for_remove = jecs.create_edge_for_remove
|
||||||
|
local archetype_traverse_add = jecs.archetype_traverse_add
|
||||||
|
local archetype_traverse_remove = jecs.archetype_traverse_remove
|
||||||
|
|
||||||
|
local world = world_new()
|
||||||
|
local root = world.ROOT_ARCHETYPE
|
||||||
|
local c1 = world:component()
|
||||||
|
local c2 = world:component()
|
||||||
|
local c3 = world:component()
|
||||||
|
|
||||||
|
local a1 = archetype_traverse_add(world, c1, nil)
|
||||||
|
local a2 = archetype_traverse_remove(world, c1, a1)
|
||||||
|
CHECK(root.node.add[c1].to == a1)
|
||||||
|
CHECK(root == a2)
|
||||||
|
end)
|
||||||
|
|
||||||
TEST("world:cleanup()", function()
|
TEST("world:cleanup()", function()
|
||||||
local world = world_new()
|
local world = world_new()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
|
|
Loading…
Reference in a new issue