children?
This commit is contained in:
parent
3a5a150351
commit
a9401b505a
1 changed files with 31 additions and 15 deletions
|
@ -33,6 +33,9 @@ func init() {
|
||||||
gob.Register(&Game{})
|
gob.Register(&Game{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ComponentSet is a set of components.
|
||||||
|
type ComponentSet map[interface{}]struct{}
|
||||||
|
|
||||||
// Game implements the ebiten methods using a collection of components. One
|
// Game implements the ebiten methods using a collection of components. One
|
||||||
// component must be the designated root component.
|
// component must be the designated root component.
|
||||||
type Game struct {
|
type Game struct {
|
||||||
|
@ -43,10 +46,11 @@ type Game struct {
|
||||||
Projection geom.Projector
|
Projection geom.Projector
|
||||||
VoxelScale geom.Float3
|
VoxelScale geom.Float3
|
||||||
|
|
||||||
dbmu sync.RWMutex
|
dbmu sync.RWMutex
|
||||||
byID map[string]Identifier // Named components by ID
|
byID map[string]Identifier // Named components by ID
|
||||||
byAB map[abKey]map[interface{}]struct{} // Ancestor/behaviour index
|
byAB map[abKey]ComponentSet // Ancestor/behaviour index
|
||||||
par map[interface{}]interface{} // par[x] is parent of x
|
parent map[interface{}]interface{} // parent[x] is parent of x
|
||||||
|
children map[interface{}]ComponentSet // children[x] are chilren of x
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws everything.
|
// Draw draws everything.
|
||||||
|
@ -102,7 +106,13 @@ func (g *Game) Component(id string) Identifier {
|
||||||
func (g *Game) Parent(c interface{}) interface{} {
|
func (g *Game) Parent(c interface{}) interface{} {
|
||||||
g.dbmu.RLock()
|
g.dbmu.RLock()
|
||||||
defer g.dbmu.RUnlock()
|
defer g.dbmu.RUnlock()
|
||||||
return g.par[c]
|
return g.parent[c]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Game) Children(c interface{}) ComponentSet {
|
||||||
|
g.dbmu.RLock()
|
||||||
|
defer g.dbmu.RUnlock()
|
||||||
|
return g.children[c]
|
||||||
}
|
}
|
||||||
|
|
||||||
// PathRegister calls Register on every Registrar in the path between g and
|
// PathRegister calls Register on every Registrar in the path between g and
|
||||||
|
@ -154,7 +164,7 @@ func (g *Game) ReversePath(component interface{}) []interface{} {
|
||||||
// Query looks for components having both a given ancestor and implementing
|
// Query looks for components having both a given ancestor and implementing
|
||||||
// a given behaviour (see Behaviors in interface.go). This only returns sensible
|
// a given behaviour (see Behaviors in interface.go). This only returns sensible
|
||||||
// values after LoadAndPrepare. Note that every component is its own ancestor.
|
// values after LoadAndPrepare. Note that every component is its own ancestor.
|
||||||
func (g *Game) Query(ancestor interface{}, behaviour reflect.Type) map[interface{}]struct{} {
|
func (g *Game) Query(ancestor interface{}, behaviour reflect.Type) ComponentSet {
|
||||||
g.dbmu.RLock()
|
g.dbmu.RLock()
|
||||||
defer g.dbmu.RUnlock()
|
defer g.dbmu.RUnlock()
|
||||||
return g.byAB[abKey{ancestor, behaviour}]
|
return g.byAB[abKey{ancestor, behaviour}]
|
||||||
|
@ -232,8 +242,9 @@ func (g *Game) build() error {
|
||||||
g.dbmu.Lock()
|
g.dbmu.Lock()
|
||||||
defer g.dbmu.Unlock()
|
defer g.dbmu.Unlock()
|
||||||
g.byID = make(map[string]Identifier)
|
g.byID = make(map[string]Identifier)
|
||||||
g.byAB = make(map[abKey]map[interface{}]struct{})
|
g.byAB = make(map[abKey]ComponentSet)
|
||||||
g.par = make(map[interface{}]interface{})
|
g.parent = make(map[interface{}]interface{})
|
||||||
|
g.children = make(map[interface{}]ComponentSet)
|
||||||
return g.registerRecursive(g, nil)
|
return g.registerRecursive(g, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,8 +288,12 @@ func (g *Game) registerOne(component, parent interface{}) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// register in g.par
|
// register in g.parent and g.children
|
||||||
g.par[component] = parent
|
g.parent[component] = parent
|
||||||
|
if g.children[parent] == nil {
|
||||||
|
g.children[parent] = make(ComponentSet)
|
||||||
|
}
|
||||||
|
g.children[parent][component] = struct{}{}
|
||||||
|
|
||||||
// register in g.byAB
|
// register in g.byAB
|
||||||
ct := reflect.TypeOf(component)
|
ct := reflect.TypeOf(component)
|
||||||
|
@ -287,10 +302,10 @@ func (g *Game) registerOne(component, parent interface{}) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// TODO: better than O(len(path)^2) time and memory?
|
// TODO: better than O(len(path)^2) time and memory?
|
||||||
for p := component; p != nil; p = g.par[p] {
|
for p := component; p != nil; p = g.parent[p] {
|
||||||
k := abKey{p, b}
|
k := abKey{p, b}
|
||||||
if g.byAB[k] == nil {
|
if g.byAB[k] == nil {
|
||||||
g.byAB[k] = make(map[interface{}]struct{})
|
g.byAB[k] = make(ComponentSet)
|
||||||
}
|
}
|
||||||
g.byAB[k][component] = struct{}{}
|
g.byAB[k][component] = struct{}{}
|
||||||
}
|
}
|
||||||
|
@ -327,15 +342,16 @@ func (g *Game) unregisterOne(component interface{}) {
|
||||||
if !ct.Implements(b) {
|
if !ct.Implements(b) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for p := component; p != nil; p = g.par[p] {
|
for p := component; p != nil; p = g.parent[p] {
|
||||||
if k := (abKey{p, b}); g.byAB[k] != nil {
|
if k := (abKey{p, b}); g.byAB[k] != nil {
|
||||||
delete(g.byAB[k], component)
|
delete(g.byAB[k], component)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unregister from g.par
|
// unregister from g.parent and g.children
|
||||||
delete(g.par, component)
|
delete(g.children[g.parent[component]], component)
|
||||||
|
delete(g.parent, component)
|
||||||
|
|
||||||
// unregister from g.byID if needed
|
// unregister from g.byID if needed
|
||||||
if id, ok := component.(Identifier); ok && id.Ident() != "" {
|
if id, ok := component.(Identifier); ok && id.Ident() != "" {
|
||||||
|
|
Loading…
Reference in a new issue