1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
package demonchime
import "core:math"
Entity_Handle :: struct {
idx: u32,
uses: u32,
}
Entity_List :: struct($T: typeid) {
items: [dynamic]T,
holes: [dynamic]Entity_Handle,
}
delete_entity_list :: proc(list: Entity_List($T)) {
delete(list.items)
delete(list.holes)
}
make_entity :: proc(list: ^Entity_List($T), ent: T) -> (Entity_Handle, ^T) {
handle: Entity_Handle
if len(list.holes) > 0 {
handle = pop(&list.holes)
handle.uses += 1
} else {
// because index 0 in a handle is considered a null handle
resize(&list.items, math.max(2, len(list.items) + 1))
handle.idx = u32(len(list.items) - 1)
handle.uses = 1
}
list.items[handle.idx] = ent
list.items[handle.idx].handle = handle
return handle, &list.items[handle.idx]
}
delete_entity :: proc(list: ^Entity_List($T), handle: Entity_Handle) {
if handle.idx <= 0 || int(handle.idx) >= len(list.items) {
return
}
if list.items[handle.idx].handle != handle {
return
}
append(&list.holes, handle)
list.items[handle.idx] = {}
}
get_entity :: proc(list: Entity_List($T), h: Entity_Handle) -> ^T {
if h.idx < 1 || h.idx >= len(list.items) || list.items[h.idx].handle == h {
return nil
}
return &list.items[h.idx]
}
active_entity_count :: proc(list: Entity_List($T)) -> int {
// - 1 because there's an empty slot at the beginning
return len(list.items) - len(list.holes) - 1
}
Entity_List_Iter :: struct($T: typeid) {
list: Entity_List(T),
idx: int,
}
iter_entity_list :: proc(list: Entity_List($T)) -> Entity_List_Iter(T) {
return Entity_List_Iter(T) { list = list }
}
entity_list_iter :: proc(it: ^Entity_List_Iter($T)) -> (^T, bool) {
for it.idx < len(it.list.items) {
if it.list.items[it.idx].handle.idx > 0 {
entity := &it.list.items[it.idx]
it.idx += 1
return entity, true
}
it.idx += 1
}
return nil, false
}
|