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.
|
// 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 {
|
func (b *Billboard) String() string {
|
||||||
return fmt.Sprintf("Billboard@%v", b.Pos)
|
return fmt.Sprintf("Billboard@%v", b.Pos)
|
||||||
|
|
|
@ -86,7 +86,10 @@ func (c *Camera) Prepare(game *Game) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan returns s.Child.
|
// 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.
|
// Transform returns the camera transform.
|
||||||
func (c *Camera) Transform() (opts ebiten.DrawImageOptions) {
|
func (c *Camera) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
|
|
|
@ -1,10 +1,23 @@
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
|
var _ interface {
|
||||||
|
Registrar
|
||||||
|
Scanner
|
||||||
|
} = &Container{}
|
||||||
|
|
||||||
// Container contains many components.
|
// Container contains many components.
|
||||||
type Container []interface{}
|
type Container []interface{}
|
||||||
|
|
||||||
// Scan returns c.
|
// 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.
|
// Register records component in the slice, if parent is the container.
|
||||||
func (c *Container) Register(component, parent interface{}) error {
|
func (c *Container) Register(component, parent interface{}) error {
|
||||||
|
|
|
@ -114,7 +114,10 @@ func (d *DrawDAG) Prepare(game *Game) error {
|
||||||
return d.Register(d, nil)
|
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
|
// Update checks for any changes to descendants, and updates its internal
|
||||||
// data structures accordingly.
|
// data structures accordingly.
|
||||||
|
@ -160,11 +163,15 @@ func (d *DrawDAG) Register(component, _ interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if sc, ok := component.(Scanner); ok {
|
if sc, ok := component.(Scanner); ok {
|
||||||
for _, x := range sc.Scan() {
|
/*for _, x := range sc.Scan() {
|
||||||
if err := d.Register(x, nil); err != nil {
|
if err := d.Register(x, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
scv := func(x interface{}) error {
|
||||||
|
return d.Register(x, nil)
|
||||||
}
|
}
|
||||||
|
return sc.Scan(scv)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -232,9 +239,14 @@ func (d *DrawDAG) Unregister(component interface{}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sc, ok := component.(Scanner); ok {
|
if sc, ok := component.(Scanner); ok {
|
||||||
for _, x := range sc.Scan() {
|
/*for _, x := range sc.Scan() {
|
||||||
d.Unregister(x)
|
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
|
// Has subcomponents? recurse
|
||||||
if sc, ok := component.(Scanner); ok {
|
if sc, ok := component.(Scanner); ok {
|
||||||
for _, ch := range sc.Scan() {
|
/*for _, ch := range sc.Scan() {
|
||||||
d.draw(ch, screen, opts)
|
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
|
return nil
|
||||||
}
|
}
|
||||||
if sc, ok := c.(Scanner); ok {
|
if sc, ok := c.(Scanner); ok {
|
||||||
for _, x := range sc.Scan() {
|
/*for _, x := range sc.Scan() {
|
||||||
if err := g.updateRecursive(x); err != nil {
|
if err := g.updateRecursive(x); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
if err := sc.Scan(g.updateRecursive); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if c == g { // prevent infinite recursion
|
if c == g { // prevent infinite recursion
|
||||||
return nil
|
return nil
|
||||||
|
@ -167,7 +171,10 @@ func (g *Game) Query(ancestor interface{}, behaviour reflect.Type) map[interface
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan returns g.Root.
|
// 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
|
// 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
|
// 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 {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, c := range sc.Scan() {
|
/*for _, c := range sc.Scan() {
|
||||||
if err := preorderWalk(c, component, visit); err != nil {
|
if err := preorderWalk(c, component, visit); err != nil {
|
||||||
return err
|
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
|
// 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 {
|
func postorderWalk(component, parent interface{}, visit func(component, parent interface{}) error) error {
|
||||||
if sc, ok := component.(Scanner); ok {
|
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 {
|
if err := postorderWalk(c, component, visit); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
if err := sc.Scan(scv); err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return visit(component, parent)
|
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
|
// Scanner components can be scanned. It is called when the game tree is walked
|
||||||
// (such as when the game component database is constructed).
|
// (such as when the game component database is constructed) and various times
|
||||||
// Scan should return a slice containing all immediate subcomponents.
|
// afterward (such as during Update).
|
||||||
|
// Scan should visit each immediate subcomponent, aborting early if an error is
|
||||||
|
// returned from the visitor.
|
||||||
type Scanner interface {
|
type Scanner interface {
|
||||||
Scan() []interface{}
|
Scan(visit func(interface{}) error) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transformer components can provide draw options to apply to themselves and
|
// 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.
|
// 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.
|
// Transform returns a GeoM translation of Factor * camera.Centre.
|
||||||
func (p *Parallax) Transform() (opts ebiten.DrawImageOptions) {
|
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.
|
// 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 := make([]interface{}, 1, len(m.Map)+1)
|
||||||
c[0] = &m.Sheet
|
c[0] = &m.Sheet
|
||||||
for _, prism := range m.Map {
|
for _, prism := range m.Map {
|
||||||
c = append(c, prism)
|
c = append(c, prism)
|
||||||
}
|
}
|
||||||
return c
|
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.
|
// Transform retrurns a translation by the draw offset.
|
||||||
|
|
|
@ -38,7 +38,10 @@ type Scene struct {
|
||||||
Hides
|
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.
|
// SceneRef loads a gzipped, gob-encoded Scene from the asset FS.
|
||||||
// After Load, Scene is usable.
|
// After Load, Scene is usable.
|
||||||
|
|
|
@ -47,7 +47,10 @@ func (s *Sheet) Prepare(*Game) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan returns the Src.
|
// 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.
|
// SubImage returns an *ebiten.Image corresponding to the given cell index.
|
||||||
func (s *Sheet) SubImage(i int) *ebiten.Image {
|
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.
|
// Scan returns the Actor and the Sheet.
|
||||||
func (s *Sprite) Scan() []interface{} {
|
/*func (s *Sprite) Scan() []interface{} {
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
&s.Actor,
|
&s.Actor,
|
||||||
&s.Sheet,
|
&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
|
// 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.
|
// 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 := make([]interface{}, 1, len(t.Map)+1)
|
||||||
c[0] = &t.Sheet
|
c[0] = &t.Sheet
|
||||||
for _, tile := range t.Map {
|
for _, tile := range t.Map {
|
||||||
c = append(c, tile)
|
c = append(c, tile)
|
||||||
}
|
}
|
||||||
return c
|
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.
|
// Transform returns a translation by t.Offset.
|
||||||
|
@ -152,4 +163,7 @@ type AnimatedTile struct {
|
||||||
func (a *AnimatedTile) Cell() int { return a.anim.Cell() }
|
func (a *AnimatedTile) Cell() int { return a.anim.Cell() }
|
||||||
|
|
||||||
// Scan returns a.anim.
|
// 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.
|
// Scan returns the Sheet and all WallUnits.
|
||||||
|
/*
|
||||||
func (w *Wall) Scan() []interface{} {
|
func (w *Wall) Scan() []interface{} {
|
||||||
c := make([]interface{}, 1, len(w.Units)+1)
|
c := make([]interface{}, 1, len(w.Units)+1)
|
||||||
c[0] = &w.Sheet
|
c[0] = &w.Sheet
|
||||||
|
@ -69,6 +70,18 @@ func (w *Wall) Scan() []interface{} {
|
||||||
}
|
}
|
||||||
return c
|
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
|
// Prepare makes sure all WallUnits know about Wall and where they are, for
|
||||||
// drawing.
|
// drawing.
|
||||||
|
@ -103,7 +116,10 @@ func (u *WallUnit) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan returns the Tile.
|
// 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) {
|
func (u *WallUnit) Transform() (opts ebiten.DrawImageOptions) {
|
||||||
opts.GeoM.Translate(geom.CFloat(
|
opts.GeoM.Translate(geom.CFloat(
|
||||||
|
|
|
@ -270,8 +270,9 @@ func (aw *Awakeman) Prepare(game *engine.Game) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aw *Awakeman) Scan() []interface{} {
|
//func (aw *Awakeman) Scan() []interface{} { return []interface{}{&aw.Sprite} }
|
||||||
return []interface{}{&aw.Sprite}
|
func (aw *Awakeman) Scan(visit func(interface{}) error) error {
|
||||||
|
return visit(&aw.Sprite)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (aw *Awakeman) String() string {
|
func (aw *Awakeman) String() string {
|
||||||
|
|
|
@ -55,8 +55,9 @@ func NewBubble(pos geom.Int3) *Bubble {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bubble) Scan() []interface{} {
|
//func (b *Bubble) Scan() []interface{} { return []interface{}{&b.Sprite} }
|
||||||
return []interface{}{&b.Sprite}
|
func (b *Bubble) Scan(visit func(interface{}) error) error {
|
||||||
|
return visit(&b.Sprite)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Bubble) String() string {
|
func (b *Bubble) String() string {
|
||||||
|
|
Loading…
Reference in a new issue