-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathComponent.go
97 lines (78 loc) · 2.51 KB
/
Component.go
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package talosecs
import "reflect"
var entsComponents = map[Entity][]any{} // for filters
var componentsEnts = map[any]Entity{} // for GetEntity
var componentsPool = map[reflect.Type][]any{} // for GetComponent + filters
// AddComponent adds any Component to the specified Entity. Component is a simple data struct.
func AddComponent(entity Entity, comp any) {
if !isPointer(comp) {
panic("Only pointers to components allowed!")
}
componentsSlice, typeOf := getComponentsSpecificOutType(comp)
componentsSlice = append(componentsSlice, comp)
componentsPool[typeOf] = componentsSlice
componentsEnts[comp] = entity
entsComponents[entity] = append(entsComponents[entity], comp)
}
// DelComponent removes component of type T of specified entity. It will be not caught in next updateSystems and next GetComponent (even in the same frame).
func DelComponent[T any](entity Entity) {
comp, isExist := GetComponent[T](entity)
if isExist {
DelSpecificComponent(comp, entity)
}
}
func DelSpecificComponent(comp any, entity Entity) {
delete(componentsEnts, comp)
componentsSlice, typeOf := getComponentsSpecificOutType(comp)
for i, c := range componentsSlice {
if c == comp {
componentsPool[typeOf] = fastRemove(componentsSlice, i)
break
}
}
entityComponents := entsComponents[entity]
for i, iteratingC := range entityComponents {
if comp == iteratingC {
entsComponents[entity] = fastRemove(entityComponents, i)
break
}
}
if len(entsComponents[entity]) == 0 {
fullRemoveEntity(entity)
}
}
// GetComponent returns component of type T, attached to the entity. If there is component, returns false in 2nd result
func GetComponent[T any](entity Entity) (T, bool) {
for _, c := range entsComponents[entity] {
if c2, ok := c.(T); ok {
return c2, true
}
}
var defaultT T
return defaultT, false
}
func HasComponent[T any](entity Entity) bool {
_, has := GetComponent[T](entity)
return has
}
func getComponentsGeneric[T any]() ([]any, int) {
var defaultT T // workaround :/
return getComponentsSameTo(defaultT)
}
func getComponentsSameTo(comp any) ([]any, int) {
return getComponentsOfType(reflect.TypeOf(comp))
}
func getComponentsSpecificOutType(comp any) ([]any, reflect.Type) {
rType := reflect.TypeOf(comp)
slice, _ := getComponentsOfType(rType)
return slice, rType
}
func getComponentsOfType(rType reflect.Type) ([]any, int) {
var slice []any
if foundSlice, ok := componentsPool[rType]; ok {
slice = foundSlice
} else {
componentsPool[rType] = slice
}
return slice, len(slice)
}