aboutsummaryrefslogtreecommitdiff
path: root/src/entity_list.odin
blob: 633a553cd07c040d7fe55a86ce6ff59f744f6acf (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
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
}