aboutsummaryrefslogtreecommitdiff
path: root/src/entity_list.odin
blob: d5cdb5015f6087e002b6913aba1ae2d98e1605a9 (plain)
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
package demonchime

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 {
    resize(&list.items, 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), h: Entity_Handle) {
  if int(h.idx) >= len(list.items) ||
     list.items[h.idx].handle != h {
    return
  }

  append(&list.holes, h)
  list.items[h.idx] = {}
}

get_entity :: proc(list: Entity_List($T), h: Entity_Handle) -> ^T {
  if h.idx >= u32(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 {
  return len(list.items) - len(list.holes)
}

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.uses > 0 {
      entity := &it.list.items[it.idx]
      it.idx += 1
      return entity, true
    }
    it.idx += 1
  }
  return nil, false
}