# ludic.base/ecs_table_remove.ludic - removing a row moves the last one into its place, so the # rows stay dense; every index is told, and the slot's generation moves on export function tb_remove(tb: Table, h: int) -> bool { if tb_row(tb, h) < 0 { return false } for k in 0 .. len(tb.on_remove) { tb.on_remove[k].run(h) } let r = tb_row(tb, h) if r < 0 { return false } for g in 0 .. len(tb.grids) { grid_unlink(tb.grids[g], r) } for k in 0 .. len(tb.idx) { ix_unfile(tb.idx[k], r) } let last = tb.n - 1 if r != last { tb_move(tb, last, r) } tb_pop(tb) let s = h & ECS_SLOT tb.slot_row[s] = -1 tb.slot_gen[s] = (tb.slot_gen[s] + 1) & ECS_GEN kept_push(tb.free, s) return true } function tb_move(tb: Table, from: int, to: int) -> void { tb.rec[to] = tb.rec[from] tb.ent[to] = tb.ent[from] tb.added[to] = tb.added[from] tb.changed[to] = tb.changed[from] for c in 0 .. len(tb.f) { tb.f[c][to] = tb.f[c][from] } for c in 0 .. len(tb.i) { tb.i[c][to] = tb.i[c][from] } tb.slot_row[tb.ent[to] & ECS_SLOT] = to let b = to >> 6 if tb.blk[b] < tb.changed[to] { tb.blk[b] = tb.changed[to] } for g in 0 .. len(tb.grids) { grid_moved(tb.grids[g], from, to) } for k in 0 .. len(tb.idx) { ix_moved(tb.idx[k], from, to) } } function tb_pop(tb: Table) -> void { List.pop(tb.rec) List.pop(tb.ent) List.pop(tb.added) List.pop(tb.changed) for c in 0 .. len(tb.f) { List.pop(tb.f[c]) } for c in 0 .. len(tb.i) { List.pop(tb.i[c]) } for g in 0 .. len(tb.grids) { grid_shrink(tb.grids[g]) } for k in 0 .. len(tb.idx) { ix_shrink(tb.idx[k]) } tb.n -= 1 } # every row gone; the slots keep their generations, so an old handle still misses export function tb_clear(tb: Table) -> void { while tb.n > 0 { tb_remove(tb, tb.ent[tb.n - 1]) } }