WIP: Scan now uses visitor pattern
This commit is contained in:
parent
83c3182be1
commit
fe2558b2c1
16 changed files with 143 additions and 28 deletions
|
@ -52,7 +52,10 @@ func (b *Billboard) Prepare(g *Game) error {
|
|||
}
|
||||
|
||||
// Scan returns a slice containing Src.
|
||||
func (b *Billboard) Scan() []interface{} { return []interface{}{&b.Src} }
|
||||
//func (b *Billboard) Scan() []interface{} { return []interface{}{&b.Src} }
|
||||
func (b *Billboard) Scan(visit func(interface{}) error) error {
|
||||
return visit(&b.Src)
|
||||
}
|
||||
|
||||
func (b *Billboard) String() string {
|
||||
return fmt.Sprintf("Billboard@%v", b.Pos)
|
||||
|
|
|
@ -86,7 +86,10 @@ func (c *Camera) Prepare(game *Game) error {
|
|||
}
|
||||
|
||||
// Scan returns s.Child.
|
||||
func (c *Camera) Scan() []interface{} { return []interface{}{c.Child} }
|
||||
//func (c *Camera) Scan() []interface{} { return []interface{}{c.Child} }
|
||||
func (c *Camera) Scan(visit func(interface{}) error) error {
|
||||
return visit(c.Child)
|
||||
}
|
||||
|
||||
// Transform returns the camera transform.
|
||||
func (c *Camera) Transform() (opts ebiten.DrawImageOptions) {
|
||||
|
|
|
@ -1,10 +1,23 @@
|
|||
package engine
|
||||
|
||||
var _ interface {
|
||||
Registrar
|
||||
Scanner
|
||||
} = &Container{}
|
||||
|
||||
// Container contains many components.
|
||||
type Container []interface{}
|
||||
|
||||
// Scan returns c.
|
||||
func (c Container) Scan() []interface{} { return c }
|
||||
//func (c Container) Scan() []interface{} { return c }
|
||||
func (c Container) Scan(visit func(interface{}) error) error {
|
||||
for _, x := range c {
|
||||
if err := visit(x); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Register records component in the slice, if parent is the container.
|
||||
func (c *Container) Register(component, parent interface{}) error {
|
||||
|
|
|
@ -114,7 +114,10 @@ func (d *DrawDAG) Prepare(game *Game) error {
|
|||
return d.Register(d, nil)
|
||||
}
|
||||
|
||||
func (d *DrawDAG) Scan() []interface{} { return []interface{}{d.Child} }
|
||||
//func (d *DrawDAG) Scan() []interface{} { return []interface{}{d.Child} }
|
||||
func (d *DrawDAG) Scan(visit func(interface{}) error) error {
|
||||
return visit(d.Child)
|
||||
}
|
||||
|
||||
// Update checks for any changes to descendants, and updates its internal
|
||||
// data structures accordingly.
|
||||
|
@ -160,11 +163,15 @@ func (d *DrawDAG) Register(component, _ interface{}) error {
|
|||
return nil
|
||||
}
|
||||
if sc, ok := component.(Scanner); ok {
|
||||
for _, x := range sc.Scan() {
|
||||
/*for _, x := range sc.Scan() {
|
||||
if err := d.Register(x, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}*/
|
||||
scv := func(x interface{}) error {
|
||||
return d.Register(x, nil)
|
||||
}
|
||||
return sc.Scan(scv)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -232,9 +239,14 @@ func (d *DrawDAG) Unregister(component interface{}) {
|
|||
return
|
||||
}
|
||||
if sc, ok := component.(Scanner); ok {
|
||||
for _, x := range sc.Scan() {
|
||||
/*for _, x := range sc.Scan() {
|
||||
d.Unregister(x)
|
||||
}*/
|
||||
scv := func(x interface{}) error {
|
||||
d.Unregister(x)
|
||||
return nil
|
||||
}
|
||||
sc.Scan(scv)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,10 +46,18 @@ func (d *DrawDFS) draw(component interface{}, screen *ebiten.Image, opts ebiten.
|
|||
}
|
||||
// Has subcomponents? recurse
|
||||
if sc, ok := component.(Scanner); ok {
|
||||
for _, ch := range sc.Scan() {
|
||||
/*for _, ch := range sc.Scan() {
|
||||
d.draw(ch, screen, opts)
|
||||
}*/
|
||||
scv := func(x interface{}) error {
|
||||
d.draw(x, screen, opts)
|
||||
return nil
|
||||
}
|
||||
sc.Scan(scv)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DrawDFS) Scan() []interface{} { return []interface{}{d.Child} }
|
||||
//func (d *DrawDFS) Scan() []interface{} { return []interface{}{d.Child} }
|
||||
func (d *DrawDFS) Scan(visit func(interface{}) error) error {
|
||||
return visit(d.Child)
|
||||
}
|
||||
|
|
|
@ -75,11 +75,15 @@ func (g *Game) updateRecursive(c interface{}) error {
|
|||
return nil
|
||||
}
|
||||
if sc, ok := c.(Scanner); ok {
|
||||
for _, x := range sc.Scan() {
|
||||
/*for _, x := range sc.Scan() {
|
||||
if err := g.updateRecursive(x); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*/
|
||||
if err := sc.Scan(g.updateRecursive); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if c == g { // prevent infinite recursion
|
||||
return nil
|
||||
|
@ -167,7 +171,10 @@ func (g *Game) Query(ancestor interface{}, behaviour reflect.Type) map[interface
|
|||
}
|
||||
|
||||
// Scan returns g.Root.
|
||||
func (g *Game) Scan() []interface{} { return []interface{}{g.Root} }
|
||||
//func (g *Game) Scan() []interface{} { return []interface{}{g.Root} }
|
||||
func (g *Game) Scan(visit func(interface{}) error) error {
|
||||
return visit(g.Root)
|
||||
}
|
||||
|
||||
// PreorderWalk calls visit with every component and its parent, reachable from
|
||||
// the given component via Scan, for as long as visit returns nil. The parent
|
||||
|
@ -185,12 +192,15 @@ func preorderWalk(component, parent interface{}, visit func(component, parent in
|
|||
if !ok {
|
||||
return nil
|
||||
}
|
||||
for _, c := range sc.Scan() {
|
||||
/*for _, c := range sc.Scan() {
|
||||
if err := preorderWalk(c, component, visit); err != nil {
|
||||
return err
|
||||
}
|
||||
}*/
|
||||
scv := func(c interface{}) error {
|
||||
return preorderWalk(c, component, visit)
|
||||
}
|
||||
return nil
|
||||
return sc.Scan(scv)
|
||||
}
|
||||
|
||||
// PostorderWalk calls visit with every component and its parent, reachable from
|
||||
|
@ -203,10 +213,16 @@ func PostorderWalk(component interface{}, visit func(component, parent interface
|
|||
|
||||
func postorderWalk(component, parent interface{}, visit func(component, parent interface{}) error) error {
|
||||
if sc, ok := component.(Scanner); ok {
|
||||
for _, c := range sc.Scan() {
|
||||
scv := func(c interface{}) error {
|
||||
return postorderWalk(c, component, visit)
|
||||
}
|
||||
/*for _, c := range sc.Scan() {
|
||||
if err := postorderWalk(c, component, visit); err != nil {
|
||||
return err
|
||||
}
|
||||
}*/
|
||||
if err := sc.Scan(scv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return visit(component, parent)
|
||||
|
|
|
@ -144,10 +144,12 @@ type Saver interface {
|
|||
}
|
||||
|
||||
// Scanner components can be scanned. It is called when the game tree is walked
|
||||
// (such as when the game component database is constructed).
|
||||
// Scan should return a slice containing all immediate subcomponents.
|
||||
// (such as when the game component database is constructed) and various times
|
||||
// afterward (such as during Update).
|
||||
// Scan should visit each immediate subcomponent, aborting early if an error is
|
||||
// returned from the visitor.
|
||||
type Scanner interface {
|
||||
Scan() []interface{}
|
||||
Scan(visit func(interface{}) error) error
|
||||
}
|
||||
|
||||
// Transformer components can provide draw options to apply to themselves and
|
||||
|
|
|
@ -39,7 +39,10 @@ func (p *Parallax) Prepare(game *Game) error {
|
|||
}
|
||||
|
||||
// Scan returns the child component.
|
||||
func (p *Parallax) Scan() []interface{} { return []interface{}{p.Child} }
|
||||
//func (p *Parallax) Scan() []interface{} { return []interface{}{p.Child} }
|
||||
func (p *Parallax) Scan(visit func(interface{}) error) error {
|
||||
return visit(p.Child)
|
||||
}
|
||||
|
||||
// Transform returns a GeoM translation of Factor * camera.Centre.
|
||||
func (p *Parallax) Transform() (opts ebiten.DrawImageOptions) {
|
||||
|
|
|
@ -113,13 +113,24 @@ func (m *PrismMap) Prepare(g *Game) error {
|
|||
}
|
||||
|
||||
// Scan returns the Sheet and all the Prisms.
|
||||
func (m *PrismMap) Scan() []interface{} {
|
||||
/*func (m *PrismMap) Scan() []interface{} {
|
||||
c := make([]interface{}, 1, len(m.Map)+1)
|
||||
c[0] = &m.Sheet
|
||||
for _, prism := range m.Map {
|
||||
c = append(c, prism)
|
||||
}
|
||||
return c
|
||||
}*/
|
||||
func (m *PrismMap) Scan(visit func(interface{}) error) error {
|
||||
if err := visit(&m.Sheet); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, prism := range m.Map {
|
||||
if err := visit(prism); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Transform retrurns a translation by the draw offset.
|
||||
|
|
|
@ -38,7 +38,10 @@ type Scene struct {
|
|||
Hides
|
||||
}
|
||||
|
||||
func (s *Scene) Scan() []interface{} { return []interface{}{s.Child} }
|
||||
//func (s *Scene) Scan() []interface{} { return []interface{}{s.Child} }
|
||||
func (s *Scene) Scan(visit func(interface{}) error) error {
|
||||
return visit(s.Child)
|
||||
}
|
||||
|
||||
// SceneRef loads a gzipped, gob-encoded Scene from the asset FS.
|
||||
// After Load, Scene is usable.
|
||||
|
|
|
@ -47,7 +47,10 @@ func (s *Sheet) Prepare(*Game) error {
|
|||
}
|
||||
|
||||
// Scan returns the Src.
|
||||
func (s *Sheet) Scan() []interface{} { return []interface{}{&s.Src} }
|
||||
//func (s *Sheet) Scan() []interface{} { return []interface{}{&s.Src} }
|
||||
func (s *Sheet) Scan(visit func(interface{}) error) error {
|
||||
return visit(&s.Src)
|
||||
}
|
||||
|
||||
// SubImage returns an *ebiten.Image corresponding to the given cell index.
|
||||
func (s *Sheet) SubImage(i int) *ebiten.Image {
|
||||
|
|
|
@ -41,11 +41,17 @@ func (s *Sprite) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
|||
}
|
||||
|
||||
// Scan returns the Actor and the Sheet.
|
||||
func (s *Sprite) Scan() []interface{} {
|
||||
/*func (s *Sprite) Scan() []interface{} {
|
||||
return []interface{}{
|
||||
&s.Actor,
|
||||
&s.Sheet,
|
||||
}
|
||||
}*/
|
||||
func (s *Sprite) Scan(visit func(interface{}) error) error {
|
||||
if err := visit(&s.Actor); err != nil {
|
||||
return err
|
||||
}
|
||||
return visit(&s.Sheet)
|
||||
}
|
||||
|
||||
// SetAnim sets the Anim to use for the sprite. If it is not the same as the
|
||||
|
|
|
@ -100,13 +100,24 @@ func (t *Tilemap) Load(fs.FS) error {
|
|||
}
|
||||
|
||||
// Scan returns a slice containing Src and all non-nil tiles.
|
||||
func (t *Tilemap) Scan() []interface{} {
|
||||
/*func (t *Tilemap) Scan() []interface{} {
|
||||
c := make([]interface{}, 1, len(t.Map)+1)
|
||||
c[0] = &t.Sheet
|
||||
for _, tile := range t.Map {
|
||||
c = append(c, tile)
|
||||
}
|
||||
return c
|
||||
}*/
|
||||
func (t *Tilemap) Scan(visit func(interface{}) error) error {
|
||||
if err := visit(&t.Sheet); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, tile := range t.Map {
|
||||
if err := visit(tile); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Transform returns a translation by t.Offset.
|
||||
|
@ -152,4 +163,7 @@ type AnimatedTile struct {
|
|||
func (a *AnimatedTile) Cell() int { return a.anim.Cell() }
|
||||
|
||||
// Scan returns a.anim.
|
||||
func (a *AnimatedTile) Scan() []interface{} { return []interface{}{a.anim} }
|
||||
//func (a *AnimatedTile) Scan() []interface{} { return []interface{}{a.anim} }
|
||||
func (a *AnimatedTile) Scan(visit func(interface{}) error) error {
|
||||
return visit(a.anim)
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ func (w *Wall) CollidesWith(b geom.Box) bool {
|
|||
}
|
||||
|
||||
// Scan returns the Sheet and all WallUnits.
|
||||
/*
|
||||
func (w *Wall) Scan() []interface{} {
|
||||
c := make([]interface{}, 1, len(w.Units)+1)
|
||||
c[0] = &w.Sheet
|
||||
|
@ -69,6 +70,18 @@ func (w *Wall) Scan() []interface{} {
|
|||
}
|
||||
return c
|
||||
}
|
||||
*/
|
||||
func (w *Wall) Scan(visit func(interface{}) error) error {
|
||||
if err := visit(&w.Sheet); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, unit := range w.Units {
|
||||
if err := visit(unit); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Prepare makes sure all WallUnits know about Wall and where they are, for
|
||||
// drawing.
|
||||
|
@ -103,7 +116,10 @@ func (u *WallUnit) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
|||
}
|
||||
|
||||
// Scan returns the Tile.
|
||||
func (u *WallUnit) Scan() []interface{} { return []interface{}{u.Tile} }
|
||||
//func (u *WallUnit) Scan() []interface{} { return []interface{}{u.Tile} }
|
||||
func (u *WallUnit) Scan(visit func(interface{}) error) error {
|
||||
return visit(u.Tile)
|
||||
}
|
||||
|
||||
func (u *WallUnit) Transform() (opts ebiten.DrawImageOptions) {
|
||||
opts.GeoM.Translate(geom.CFloat(
|
||||
|
|
|
@ -270,8 +270,9 @@ func (aw *Awakeman) Prepare(game *engine.Game) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (aw *Awakeman) Scan() []interface{} {
|
||||
return []interface{}{&aw.Sprite}
|
||||
//func (aw *Awakeman) Scan() []interface{} { return []interface{}{&aw.Sprite} }
|
||||
func (aw *Awakeman) Scan(visit func(interface{}) error) error {
|
||||
return visit(&aw.Sprite)
|
||||
}
|
||||
|
||||
func (aw *Awakeman) String() string {
|
||||
|
|
|
@ -55,8 +55,9 @@ func NewBubble(pos geom.Int3) *Bubble {
|
|||
}
|
||||
}
|
||||
|
||||
func (b *Bubble) Scan() []interface{} {
|
||||
return []interface{}{&b.Sprite}
|
||||
//func (b *Bubble) Scan() []interface{} { return []interface{}{&b.Sprite} }
|
||||
func (b *Bubble) Scan(visit func(interface{}) error) error {
|
||||
return visit(&b.Sprite)
|
||||
}
|
||||
|
||||
func (b *Bubble) String() string {
|
||||
|
|
Loading…
Reference in a new issue