2021-09-22 14:37:00 +10:00
|
|
|
package engine
|
|
|
|
|
2021-09-22 15:48:02 +10:00
|
|
|
var _ interface {
|
|
|
|
Registrar
|
|
|
|
Scanner
|
|
|
|
} = &Container{}
|
|
|
|
|
2021-09-22 15:55:38 +10:00
|
|
|
// Container contains many components, in order.
|
2021-09-22 14:37:00 +10:00
|
|
|
type Container []interface{}
|
|
|
|
|
2021-09-22 15:55:38 +10:00
|
|
|
// Scan visits every component in the container.
|
2021-09-22 15:48:02 +10:00
|
|
|
func (c Container) Scan(visit func(interface{}) error) error {
|
|
|
|
for _, x := range c {
|
|
|
|
if err := visit(x); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2021-09-22 14:37:00 +10:00
|
|
|
|
|
|
|
// Register records component in the slice, if parent is the container.
|
|
|
|
func (c *Container) Register(component, parent interface{}) error {
|
|
|
|
if parent == c {
|
|
|
|
*c = append(*c, component)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unregister searches the slice for the component, and removes it by setting
|
|
|
|
// to nil. If the number of nil items is greater than half the slice, the slice
|
|
|
|
// is compacted.
|
|
|
|
func (c *Container) Unregister(component interface{}) {
|
|
|
|
free := 0
|
|
|
|
for i, x := range *c {
|
|
|
|
switch x {
|
|
|
|
case component:
|
|
|
|
(*c)[i] = nil
|
|
|
|
free++
|
|
|
|
case nil:
|
|
|
|
free++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if free > len(*c)/2 {
|
|
|
|
c.compact()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Container) compact() {
|
|
|
|
i := 0
|
|
|
|
for _, x := range *c {
|
|
|
|
if x != nil {
|
|
|
|
(*c)[i] = x
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*c = (*c)[:i]
|
|
|
|
}
|