mirror of
https://github.com/Ukendio/jecs.git
synced 2025-08-04 19:29:18 +00:00
Compare commits
7 commits
9637739131
...
b0065aa2ce
Author | SHA1 | Date | |
---|---|---|---|
|
b0065aa2ce | ||
|
ca10a8a8f3 | ||
|
9b57189c3a | ||
|
4ff492ceaf | ||
|
7c8358656a | ||
|
d6e720f200 | ||
|
3c7f3b4eb3 |
6 changed files with 184 additions and 81 deletions
|
@ -74,11 +74,12 @@ return function(world: types.World)
|
||||||
local removed = map.removed
|
local removed = map.removed
|
||||||
|
|
||||||
if removed then
|
if removed then
|
||||||
for i, e in removed do
|
for _, entity in removed do
|
||||||
if not world:contains(e) then
|
entity = ecs_map_get(world, entity)
|
||||||
|
if not world:contains(entity) then
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
world:remove(e, id)
|
world:remove(entity, id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
4
jecs.d.ts
vendored
4
jecs.d.ts
vendored
|
@ -105,7 +105,7 @@ export class World {
|
||||||
/**
|
/**
|
||||||
* Creates a new World.
|
* Creates a new World.
|
||||||
*/
|
*/
|
||||||
constructor();
|
private constructor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enforces a check for entities to be created within a desired range.
|
* Enforces a check for entities to be created within a desired range.
|
||||||
|
@ -249,6 +249,8 @@ export class World {
|
||||||
query<T extends Id[]>(...components: T): Query<InferComponents<T>>;
|
query<T extends Id[]>(...components: T): Query<InferComponents<T>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function world(): World;
|
||||||
|
|
||||||
export function component<T>(): Entity<T>;
|
export function component<T>(): Entity<T>;
|
||||||
|
|
||||||
export function tag(): Tag;
|
export function tag(): Tag;
|
||||||
|
|
133
jecs.luau
133
jecs.luau
|
@ -52,6 +52,8 @@ export type Query<T...> = typeof(setmetatable(
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
|
||||||
|
type QueryArm<T...> = () -> ()
|
||||||
|
|
||||||
export type Observer = {
|
export type Observer = {
|
||||||
callback: (archetype: Archetype) -> (),
|
callback: (archetype: Archetype) -> (),
|
||||||
query: QueryInner,
|
query: QueryInner,
|
||||||
|
@ -437,6 +439,7 @@ end
|
||||||
|
|
||||||
local function archetype_move(
|
local function archetype_move(
|
||||||
entity_index: EntityIndex,
|
entity_index: EntityIndex,
|
||||||
|
entity: Entity,
|
||||||
to: Archetype,
|
to: Archetype,
|
||||||
dst_row: i24,
|
dst_row: i24,
|
||||||
from: Archetype,
|
from: Archetype,
|
||||||
|
@ -450,6 +453,9 @@ local function archetype_move(
|
||||||
local id_types = from.types
|
local id_types = from.types
|
||||||
local columns_map = to.columns_map
|
local columns_map = to.columns_map
|
||||||
|
|
||||||
|
if src_row ~= last then
|
||||||
|
-- If the entity is the last row in the archetype then swapping it would be meaningless.
|
||||||
|
|
||||||
for i, column in src_columns do
|
for i, column in src_columns do
|
||||||
if column == NULL_ARRAY then
|
if column == NULL_ARRAY then
|
||||||
continue
|
continue
|
||||||
|
@ -463,35 +469,42 @@ local function archetype_move(
|
||||||
dst_column[dst_row] = column[src_row]
|
dst_column[dst_row] = column[src_row]
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If the entity is the last row in the archetype then swapping it would be meaningless.
|
|
||||||
if src_row ~= last then
|
|
||||||
-- Swap rempves columns to ensure there are no holes in the archetype.
|
-- Swap rempves columns to ensure there are no holes in the archetype.
|
||||||
column[src_row] = column[last]
|
column[src_row] = column[last]
|
||||||
end
|
|
||||||
column[last] = nil
|
column[last] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local moved = #src_entities
|
|
||||||
|
|
||||||
-- Move the entity from the source to the destination archetype.
|
-- Move the entity from the source to the destination archetype.
|
||||||
-- Because we have swapped columns we now have to update the records
|
-- Because we have swapped columns we now have to update the records
|
||||||
-- corresponding to the entities' rows that were swapped.
|
-- corresponding to the entities' rows that were swapped.
|
||||||
local e1 = src_entities[src_row]
|
|
||||||
local e2 = src_entities[moved]
|
|
||||||
|
|
||||||
if src_row ~= moved then
|
local e2 = src_entities[last]
|
||||||
src_entities[src_row] = e2
|
src_entities[src_row] = e2
|
||||||
end
|
|
||||||
|
|
||||||
src_entities[moved] = nil :: any
|
|
||||||
dst_entities[dst_row] = e1
|
|
||||||
|
|
||||||
local sparse_array = entity_index.sparse_array
|
local sparse_array = entity_index.sparse_array
|
||||||
|
|
||||||
local record1 = sparse_array[ECS_ENTITY_T_LO(e1 :: number)]
|
|
||||||
local record2 = sparse_array[ECS_ENTITY_T_LO(e2 :: number)]
|
local record2 = sparse_array[ECS_ENTITY_T_LO(e2 :: number)]
|
||||||
record1.row = dst_row
|
|
||||||
record2.row = src_row
|
record2.row = src_row
|
||||||
|
else
|
||||||
|
for i, column in src_columns do
|
||||||
|
if column == NULL_ARRAY then
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
-- Retrieves the new column index from the source archetype's record from each component
|
||||||
|
-- We have to do this because the columns are tightly packed and indexes may not correspond to each other.
|
||||||
|
local dst_column = columns_map[id_types[i]]
|
||||||
|
|
||||||
|
-- Sometimes target column may not exist, e.g. when you remove a component.
|
||||||
|
if dst_column then
|
||||||
|
dst_column[dst_row] = column[src_row]
|
||||||
|
end
|
||||||
|
|
||||||
|
column[last] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
src_entities[last] = nil :: any
|
||||||
|
dst_entities[dst_row] = entity
|
||||||
end
|
end
|
||||||
|
|
||||||
local function archetype_append(
|
local function archetype_append(
|
||||||
|
@ -524,7 +537,7 @@ local function entity_move(
|
||||||
local sourceRow = record.row
|
local sourceRow = record.row
|
||||||
local from = record.archetype
|
local from = record.archetype
|
||||||
local dst_row = archetype_append(entity, to)
|
local dst_row = archetype_append(entity, to)
|
||||||
archetype_move(entity_index, to, dst_row, from, sourceRow)
|
archetype_move(entity_index, entity, to, dst_row, from, sourceRow)
|
||||||
record.archetype = to
|
record.archetype = to
|
||||||
record.row = dst_row
|
record.row = dst_row
|
||||||
end
|
end
|
||||||
|
@ -658,6 +671,9 @@ local function id_record_ensure(world: World, id: Entity): ComponentRecord
|
||||||
local relation = id
|
local relation = id
|
||||||
local target = 0
|
local target = 0
|
||||||
local is_pair = ECS_IS_PAIR(id :: number)
|
local is_pair = ECS_IS_PAIR(id :: number)
|
||||||
|
|
||||||
|
local has_delete = false
|
||||||
|
|
||||||
if is_pair then
|
if is_pair then
|
||||||
relation = entity_index_get_alive(entity_index, ECS_PAIR_FIRST(id :: number)) :: i53
|
relation = entity_index_get_alive(entity_index, ECS_PAIR_FIRST(id :: number)) :: i53
|
||||||
ecs_assert(relation and entity_index_is_alive(
|
ecs_assert(relation and entity_index_is_alive(
|
||||||
|
@ -665,16 +681,19 @@ local function id_record_ensure(world: World, id: Entity): ComponentRecord
|
||||||
target = entity_index_get_alive(entity_index, ECS_PAIR_SECOND(id :: number)) :: i53
|
target = entity_index_get_alive(entity_index, ECS_PAIR_SECOND(id :: number)) :: i53
|
||||||
ecs_assert(target and entity_index_is_alive(
|
ecs_assert(target and entity_index_is_alive(
|
||||||
entity_index, target), ECS_INTERNAL_ERROR)
|
entity_index, target), ECS_INTERNAL_ERROR)
|
||||||
end
|
|
||||||
|
|
||||||
local cleanup_policy = world_target(world, relation, EcsOnDelete, 0)
|
|
||||||
local cleanup_policy_target = world_target(world, relation, EcsOnDeleteTarget, 0)
|
local cleanup_policy_target = world_target(world, relation, EcsOnDeleteTarget, 0)
|
||||||
|
|
||||||
local has_delete = false
|
if cleanup_policy_target == EcsDelete then
|
||||||
|
|
||||||
if cleanup_policy == EcsDelete or cleanup_policy_target == EcsDelete then
|
|
||||||
has_delete = true
|
has_delete = true
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
local cleanup_policy = world_target(world, relation, EcsOnDelete, 0)
|
||||||
|
|
||||||
|
if cleanup_policy == EcsDelete then
|
||||||
|
has_delete = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local on_add, on_change, on_remove = world_get(world,
|
local on_add, on_change, on_remove = world_get(world,
|
||||||
relation, EcsOnAdd, EcsOnChange, EcsOnRemove)
|
relation, EcsOnAdd, EcsOnChange, EcsOnRemove)
|
||||||
|
@ -2026,18 +2045,16 @@ local function ecs_bulk_insert(world: World, entity: Entity, ids: { Entity }, va
|
||||||
local value = values[i] :: any
|
local value = values[i] :: any
|
||||||
|
|
||||||
local on_add = idr.hooks.on_add
|
local on_add = idr.hooks.on_add
|
||||||
local on_change = idr.hooks.on_change
|
|
||||||
|
|
||||||
if value then
|
if value ~= nil then
|
||||||
columns_map[id][row] = value
|
columns_map[id][row] = value
|
||||||
|
local on_change = idr.hooks.on_change
|
||||||
local hook = if set then on_change else on_add
|
local hook = if set then on_change else on_add
|
||||||
if hook then
|
if hook then
|
||||||
hook(entity, id, value :: any)
|
hook(entity, id, value :: any)
|
||||||
end
|
end
|
||||||
else
|
elseif on_add then
|
||||||
if on_add then
|
on_add(entity, id)
|
||||||
on_add(entity, id, value)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2140,38 +2157,41 @@ local function world_new()
|
||||||
return r
|
return r
|
||||||
end
|
end
|
||||||
|
|
||||||
-- local function entity_index_try_get_safe(entity: number): Record?
|
-- local function inner_entity_index_try_get(entity: number): Record?
|
||||||
-- local r = entity_index_try_get_any_fast(entity_index, entity)
|
-- local r = inner_entity_index_try_get_any(entity)
|
||||||
-- if r then
|
-- if r then
|
||||||
-- local r_dense = r.dense
|
-- local r_dense = r.dense
|
||||||
-- if r_dense > entity_index.alive_count then
|
-- if r_dense > entity_index.alive_count then
|
||||||
-- return nil
|
-- return nil
|
||||||
-- end
|
-- end
|
||||||
-- if entity_index.dense_array[r_dense] ~= entity then
|
-- if eindex_dense_array[r_dense] ~= entity then
|
||||||
-- return nil
|
-- return nil
|
||||||
-- end
|
-- end
|
||||||
-- end
|
-- end
|
||||||
-- return r
|
-- return r
|
||||||
-- end
|
-- end
|
||||||
|
|
||||||
local function inner_entity_index_try_get(entity: number): Record?
|
local function inner_entity_index_try_get_unsafe(entity: number): Record?
|
||||||
local r = eindex_sparse_array[ECS_ENTITY_T_LO(entity)]
|
local r = inner_entity_index_try_get_any(entity)
|
||||||
if r then
|
if r then
|
||||||
if eindex_dense_array[r.dense] ~= entity then
|
local r_dense = r.dense
|
||||||
|
-- if r_dense > entity_index.alive_count then
|
||||||
|
-- return nil
|
||||||
|
-- end
|
||||||
|
if eindex_dense_array[r_dense] ~= entity then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return r
|
return r
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function inner_world_add<T, a>(
|
local function inner_world_add<T, a>(
|
||||||
world: World,
|
world: World,
|
||||||
entity: Entity<T>,
|
entity: Entity<T>,
|
||||||
id: Id<a>
|
id: Id<a>
|
||||||
): ()
|
): ()
|
||||||
local entity_index = world.entity_index
|
local entity_index = world.entity_index
|
||||||
local record = inner_entity_index_try_get(entity :: number)
|
local record = inner_entity_index_try_get_unsafe(entity :: number)
|
||||||
if not record then
|
if not record then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -2199,7 +2219,7 @@ local function world_new()
|
||||||
|
|
||||||
local function inner_world_get(world: World, entity: Entity,
|
local function inner_world_get(world: World, entity: Entity,
|
||||||
a: Id, b: Id?, c: Id?, d: Id?, e: Id?): ...any
|
a: Id, b: Id?, c: Id?, d: Id?, e: Id?): ...any
|
||||||
local record = inner_entity_index_try_get(entity::number)
|
local record = inner_entity_index_try_get_unsafe(entity::number)
|
||||||
if not record then
|
if not record then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
@ -2230,7 +2250,7 @@ local function world_new()
|
||||||
local function inner_world_has(world: World, entity: i53,
|
local function inner_world_has(world: World, entity: i53,
|
||||||
a: i53, b: i53?, c: i53?, d: i53?, e: i53?): boolean
|
a: i53, b: i53?, c: i53?, d: i53?, e: i53?): boolean
|
||||||
|
|
||||||
local record = inner_entity_index_try_get(entity)
|
local record = inner_entity_index_try_get_unsafe(entity)
|
||||||
if not record then
|
if not record then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
@ -2250,7 +2270,7 @@ local function world_new()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function inner_world_target<T, a>(world: World, entity: Entity<T>, relation: Id<a>, index: number?): Entity?
|
local function inner_world_target<T, a>(world: World, entity: Entity<T>, relation: Id<a>, index: number?): Entity?
|
||||||
local record = inner_entity_index_try_get(entity :: number)
|
local record = inner_entity_index_try_get_unsafe(entity :: number)
|
||||||
if not record then
|
if not record then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
@ -2312,7 +2332,7 @@ local function world_new()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function inner_world_set<T, a>(world: World, entity: Entity<T>, id: Id<a>, data: a): ()
|
local function inner_world_set<T, a>(world: World, entity: Entity<T>, id: Id<a>, data: a): ()
|
||||||
local record = inner_entity_index_try_get(entity :: number)
|
local record = inner_entity_index_try_get_unsafe(entity :: number)
|
||||||
if not record then
|
if not record then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -2413,7 +2433,7 @@ local function world_new()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function inner_world_remove<T, a>(world: World, entity: Entity<T>, id: Id<a>)
|
local function inner_world_remove<T, a>(world: World, entity: Entity<T>, id: Id<a>)
|
||||||
local record = inner_entity_index_try_get(entity :: number)
|
local record = inner_entity_index_try_get_unsafe(entity :: number)
|
||||||
if not record then
|
if not record then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -2450,8 +2470,8 @@ local function world_new()
|
||||||
local idr_archetype = archetypes[archetype_id]
|
local idr_archetype = archetypes[archetype_id]
|
||||||
local entities = idr_archetype.entities
|
local entities = idr_archetype.entities
|
||||||
local n = #entities
|
local n = #entities
|
||||||
|
table.move(entities, 1, n, count + 1, queue)
|
||||||
count += n
|
count += n
|
||||||
table.move(entities, 1, n, #queue + 1, queue)
|
|
||||||
end
|
end
|
||||||
for _, e in queue do
|
for _, e in queue do
|
||||||
inner_world_remove(world, e, entity)
|
inner_world_remove(world, e, entity)
|
||||||
|
@ -2533,11 +2553,12 @@ local function world_new()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function inner_world_delete<T>(world: World, entity: Entity<T>)
|
local function inner_world_delete<T>(world: World, entity: Entity<T>)
|
||||||
local entity_index = world.entity_index
|
local entity_index = world.entity_index
|
||||||
local record = inner_entity_index_try_get(entity::number)
|
local record = inner_entity_index_try_get_unsafe(entity::number)
|
||||||
if not record then
|
if not record then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -2575,16 +2596,42 @@ local function world_new()
|
||||||
archetype_destroy(world, idr_archetype)
|
archetype_destroy(world, idr_archetype)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
local on_remove = idr.hooks.on_remove
|
||||||
|
if on_remove then
|
||||||
for archetype_id in idr.records do
|
for archetype_id in idr.records do
|
||||||
local idr_archetype = archetypes[archetype_id]
|
local idr_archetype = archetypes[archetype_id]
|
||||||
|
local to = archetype_traverse_remove(world, entity, idr_archetype)
|
||||||
local entities = idr_archetype.entities
|
local entities = idr_archetype.entities
|
||||||
local n = #entities
|
local n = #entities
|
||||||
for i = n, 1, -1 do
|
for i = n, 1, -1 do
|
||||||
inner_world_remove(world, entities[i], entity)
|
local e = entities[i]
|
||||||
|
on_remove(e, entity)
|
||||||
|
local r = eindex_sparse_array[ECS_ID(e :: number)]
|
||||||
|
local from = r.archetype
|
||||||
|
if from ~= idr_archetype then
|
||||||
|
-- unfortunately the on_remove hook allows a window where `e` can have changed archetype
|
||||||
|
-- this is hypothetically not that expensive of an operation anyways
|
||||||
|
to = archetype_traverse_remove(world, entity, from)
|
||||||
|
end
|
||||||
|
entity_move(entity_index, e, r, to)
|
||||||
end
|
end
|
||||||
|
|
||||||
archetype_destroy(world, idr_archetype)
|
archetype_destroy(world, idr_archetype)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
for archetype_id in idr.records do
|
||||||
|
local idr_archetype = archetypes[archetype_id]
|
||||||
|
local to = archetype_traverse_remove(world, entity, idr_archetype)
|
||||||
|
local entities = idr_archetype.entities
|
||||||
|
local n = #entities
|
||||||
|
for i = n, 1, -1 do
|
||||||
|
local e = entities[i]
|
||||||
|
entity_move(entity_index, e, eindex_sparse_array[ECS_ID(e :: number)], to)
|
||||||
|
end
|
||||||
|
|
||||||
|
archetype_destroy(world, idr_archetype)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2803,7 +2850,7 @@ local function world_new()
|
||||||
if value == NULL then
|
if value == NULL then
|
||||||
inner_world_add(world, i, ty)
|
inner_world_add(world, i, ty)
|
||||||
else
|
else
|
||||||
inner_world_add(world, i, ty, value)
|
inner_world_set(world, i, ty, value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@rbxts/jecs",
|
"name": "@rbxts/jecs",
|
||||||
"version": "0.7.2",
|
"version": "0.7.3",
|
||||||
"description": "Stupidly fast Entity Component System",
|
"description": "Stupidly fast Entity Component System",
|
||||||
"main": "jecs.luau",
|
"main": "jecs.luau",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -22,9 +22,13 @@ type Entity<T=nil> = jecs.Entity<T>
|
||||||
type Id<T=unknown> = jecs.Id<T>
|
type Id<T=unknown> = jecs.Id<T>
|
||||||
|
|
||||||
local entity_visualiser = require("@tools/entity_visualiser")
|
local entity_visualiser = require("@tools/entity_visualiser")
|
||||||
local lifetime_tracker_add = require("@tools/lifetime_tracker")
|
|
||||||
local dwi = entity_visualiser.stringify
|
local dwi = entity_visualiser.stringify
|
||||||
|
|
||||||
|
TEST("repro", function()
|
||||||
|
|
||||||
|
|
||||||
|
end)
|
||||||
|
|
||||||
TEST("bulk", function()
|
TEST("bulk", function()
|
||||||
local world = jecs.world()
|
local world = jecs.world()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
|
@ -42,7 +46,10 @@ TEST("bulk", function()
|
||||||
CHECK(world:get(e, B) == 2)
|
CHECK(world:get(e, B) == 2)
|
||||||
CHECK(world:get(e, C) == 3)
|
CHECK(world:get(e, C) == 3)
|
||||||
|
|
||||||
jecs.bulk_insert(world, e, { D, E, F }, { 4, nil, 5 })
|
jecs.bulk_insert(world, e,
|
||||||
|
{ D, E, F },
|
||||||
|
{ 4, nil, 5 }
|
||||||
|
)
|
||||||
CHECK(world:get(e, A) == 1)
|
CHECK(world:get(e, A) == 1)
|
||||||
CHECK(world:get(e, B) == 2)
|
CHECK(world:get(e, B) == 2)
|
||||||
CHECK(world:get(e, C) == 3)
|
CHECK(world:get(e, C) == 3)
|
||||||
|
@ -51,7 +58,10 @@ TEST("bulk", function()
|
||||||
CHECK(world:get(e, E) == nil and world:has(e, E))
|
CHECK(world:get(e, E) == nil and world:has(e, E))
|
||||||
CHECK(world:get(e, F) == 5)
|
CHECK(world:get(e, F) == 5)
|
||||||
|
|
||||||
jecs.bulk_insert(world, e, { A, D, E, F, C }, { 10, 40, nil, 50, 30 })
|
jecs.bulk_insert(world, e,
|
||||||
|
{ A, D, E, F, C },
|
||||||
|
{ 10, 40, nil, 50, 30 }
|
||||||
|
)
|
||||||
|
|
||||||
CHECK(world:get(e, A) == 10)
|
CHECK(world:get(e, A) == 10)
|
||||||
CHECK(world:get(e, B) == 2)
|
CHECK(world:get(e, B) == 2)
|
||||||
|
@ -376,8 +386,51 @@ TEST("world:contains()", function()
|
||||||
end)
|
end)
|
||||||
|
|
||||||
TEST("world:delete()", function()
|
TEST("world:delete()", function()
|
||||||
|
do CASE "pair(OnDelete, Delete)"
|
||||||
|
local world = jecs.world()
|
||||||
|
local ct = world:component()
|
||||||
|
world:add(ct, jecs.pair(jecs.OnDelete, jecs.Delete))
|
||||||
|
|
||||||
|
local e1 = world:entity()
|
||||||
|
local e2 = world:entity()
|
||||||
|
|
||||||
|
local dummy = world:entity()
|
||||||
|
|
||||||
|
world:add(e1, ct)
|
||||||
|
world:add(e2, jecs.pair(ct, dummy))
|
||||||
|
|
||||||
|
world:delete(dummy)
|
||||||
|
|
||||||
|
CHECK(world:contains(e2))
|
||||||
|
|
||||||
|
world:delete(ct)
|
||||||
|
|
||||||
|
CHECK(not world:contains(e1))
|
||||||
|
end
|
||||||
|
|
||||||
|
do CASE "pair(OnDeleteTarget, Delete)"
|
||||||
|
local world = jecs.world()
|
||||||
|
local ct = world:component()
|
||||||
|
world:add(ct, jecs.pair(jecs.OnDeleteTarget, jecs.Delete))
|
||||||
|
|
||||||
|
local e1 = world:entity()
|
||||||
|
local e2 = world:entity()
|
||||||
|
|
||||||
|
local dummy = world:entity()
|
||||||
|
|
||||||
|
world:add(e1, ct)
|
||||||
|
|
||||||
|
world:add(e2, jecs.pair(ct, dummy))
|
||||||
|
|
||||||
|
world:delete(dummy)
|
||||||
|
|
||||||
|
CHECK(not world:contains(e2))
|
||||||
|
|
||||||
|
world:delete(ct)
|
||||||
|
|
||||||
|
CHECK(world:contains(e1))
|
||||||
|
end
|
||||||
do CASE "remove (*, R) pairs when relationship is invalidated"
|
do CASE "remove (*, R) pairs when relationship is invalidated"
|
||||||
print("-------")
|
|
||||||
local world = jecs.world()
|
local world = jecs.world()
|
||||||
local e1 = world:entity()
|
local e1 = world:entity()
|
||||||
local e2 = world:entity()
|
local e2 = world:entity()
|
||||||
|
@ -441,7 +494,7 @@ TEST("world:delete()", function()
|
||||||
local A = world:entity()
|
local A = world:entity()
|
||||||
local B = world:entity()
|
local B = world:entity()
|
||||||
|
|
||||||
world:add(Relation, pair(jecs.OnDelete, jecs.Delete))
|
world:add(Relation, pair(jecs.OnDeleteTarget, jecs.Delete))
|
||||||
|
|
||||||
local entity = world:entity()
|
local entity = world:entity()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ukendio/jecs"
|
name = "ukendio/jecs"
|
||||||
version = "0.7.2"
|
version = "0.7.3"
|
||||||
registry = "https://github.com/UpliftGames/wally-index"
|
registry = "https://github.com/UpliftGames/wally-index"
|
||||||
realm = "shared"
|
realm = "shared"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
Loading…
Reference in a new issue