DrawLayer -> DrawManager, iface assertions, etc
This commit is contained in:
parent
fe40073407
commit
045ab20cd5
5 changed files with 51 additions and 45 deletions
|
@ -9,6 +9,15 @@ import (
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ interface {
|
||||||
|
Drawer
|
||||||
|
DrawManager
|
||||||
|
Hider
|
||||||
|
Prepper
|
||||||
|
Scanner
|
||||||
|
Updater
|
||||||
|
} = &DrawDAG{}
|
||||||
|
|
||||||
// DrawDAG is a DrawLayer that organises DrawBoxer descendants in a directed
|
// DrawDAG is a DrawLayer that organises DrawBoxer descendants in a directed
|
||||||
// acyclic graph (DAG), in order to draw them according to ordering constraints.
|
// acyclic graph (DAG), in order to draw them according to ordering constraints.
|
||||||
// It combines a DAG with a spatial index used when updating vertices to reduce
|
// It combines a DAG with a spatial index used when updating vertices to reduce
|
||||||
|
@ -26,7 +35,7 @@ type DrawDAG struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw draws everything in the DAG in topological order.
|
// Draw draws everything in the DAG in topological order.
|
||||||
func (d *DrawDAG) DrawAll(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
func (d *DrawDAG) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
if d.Hidden() {
|
if d.Hidden() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -89,6 +98,9 @@ func (d *DrawDAG) DrawAll(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// exists to satisfy interface
|
||||||
|
func (DrawDAG) ManagesDrawingSubcomponents() {}
|
||||||
|
|
||||||
// Prepare adds all subcomponents to the DAG.
|
// Prepare adds all subcomponents to the DAG.
|
||||||
func (d *DrawDAG) Prepare(game *Game) error {
|
func (d *DrawDAG) Prepare(game *Game) error {
|
||||||
d.dag = newDAG()
|
d.dag = newDAG()
|
||||||
|
|
|
@ -2,6 +2,12 @@ package engine
|
||||||
|
|
||||||
import "github.com/hajimehoshi/ebiten/v2"
|
import "github.com/hajimehoshi/ebiten/v2"
|
||||||
|
|
||||||
|
var _ interface {
|
||||||
|
Drawer
|
||||||
|
DrawManager
|
||||||
|
Scanner
|
||||||
|
} = &DrawDFS{}
|
||||||
|
|
||||||
// DrawDFS is a DrawLayer that does not add any structure. Components are
|
// DrawDFS is a DrawLayer that does not add any structure. Components are
|
||||||
// drawn in the order in which they are encountered by a depth-first search
|
// drawn in the order in which they are encountered by a depth-first search
|
||||||
// through the game tree, without any extra sorting based on Z values or
|
// through the game tree, without any extra sorting based on Z values or
|
||||||
|
@ -11,7 +17,7 @@ type DrawDFS struct {
|
||||||
Hides
|
Hides
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DrawDFS) DrawAll(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
func (d *DrawDFS) Draw(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
if d.Hidden() {
|
if d.Hidden() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -20,6 +26,9 @@ func (d *DrawDFS) DrawAll(screen *ebiten.Image, opts *ebiten.DrawImageOptions) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// exists to satisfy interface
|
||||||
|
func (DrawDFS) ManagesDrawingSubcomponents() {}
|
||||||
|
|
||||||
func (d *DrawDFS) draw(component interface{}, screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
func (d *DrawDFS) draw(component interface{}, screen *ebiten.Image, opts ebiten.DrawImageOptions) {
|
||||||
// Hidden? stop drawing
|
// Hidden? stop drawing
|
||||||
if h, ok := component.(Hider); ok && h.Hidden() {
|
if h, ok := component.(Hider); ok && h.Hidden() {
|
||||||
|
@ -29,16 +38,14 @@ func (d *DrawDFS) draw(component interface{}, screen *ebiten.Image, opts ebiten.
|
||||||
if tf, ok := component.(Transformer); ok {
|
if tf, ok := component.(Transformer); ok {
|
||||||
opts = concatOpts(tf.Transform(), opts)
|
opts = concatOpts(tf.Transform(), opts)
|
||||||
}
|
}
|
||||||
// Is it a DrawLayer? draw all and return
|
|
||||||
if dl, ok := component.(DrawLayer); ok {
|
|
||||||
dl.DrawAll(screen, &opts)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// Not a draw layer.
|
|
||||||
// Does it draw itself? Draw
|
// Does it draw itself? Draw
|
||||||
if dr, ok := component.(Drawer); ok {
|
if dr, ok := component.(Drawer); ok {
|
||||||
dr.Draw(screen, &opts)
|
dr.Draw(screen, &opts)
|
||||||
}
|
}
|
||||||
|
// Is it a DrawManager? return early (don't recurse)
|
||||||
|
if _, ok := component.(DrawManager); ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 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() {
|
||||||
|
|
|
@ -39,7 +39,7 @@ type Game struct {
|
||||||
Disables
|
Disables
|
||||||
Hides
|
Hides
|
||||||
ScreenSize image.Point
|
ScreenSize image.Point
|
||||||
Roots []DrawLayer
|
Root Drawer // usually a DrawManager
|
||||||
Projection geom.Projector
|
Projection geom.Projector
|
||||||
VoxelScale geom.Float3
|
VoxelScale geom.Float3
|
||||||
|
|
||||||
|
@ -54,12 +54,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
||||||
if g.Hidden() {
|
if g.Hidden() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
g.Root.Draw(screen, &ebiten.DrawImageOptions{})
|
||||||
// Make all draw managers draw, in order.
|
|
||||||
opts := &ebiten.DrawImageOptions{}
|
|
||||||
for _, dm := range g.Roots {
|
|
||||||
dm.DrawAll(screen, opts)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Layout returns the configured screen width/height.
|
// Layout returns the configured screen width/height.
|
||||||
|
@ -158,14 +153,8 @@ func (g *Game) Query(ancestor interface{}, behaviour reflect.Type) map[interface
|
||||||
return g.byAB[abKey{ancestor, behaviour}]
|
return g.byAB[abKey{ancestor, behaviour}]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan implements Scanner.
|
// Scan returns g.Root.
|
||||||
func (g *Game) Scan() []interface{} {
|
func (g *Game) Scan() []interface{} { return []interface{}{g.Root} }
|
||||||
rs := make([]interface{}, 0, len(g.Roots))
|
|
||||||
for _, r := range g.Roots {
|
|
||||||
rs = append(rs, r)
|
|
||||||
}
|
|
||||||
return rs
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
|
|
|
@ -17,7 +17,7 @@ var (
|
||||||
BoundingBoxerType = reflect.TypeOf((*BoundingBoxer)(nil)).Elem()
|
BoundingBoxerType = reflect.TypeOf((*BoundingBoxer)(nil)).Elem()
|
||||||
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
|
ColliderType = reflect.TypeOf((*Collider)(nil)).Elem()
|
||||||
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
|
DisablerType = reflect.TypeOf((*Disabler)(nil)).Elem()
|
||||||
DrawLayerType = reflect.TypeOf((*DrawLayer)(nil)).Elem()
|
DrawLayerType = reflect.TypeOf((*DrawManager)(nil)).Elem()
|
||||||
DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem()
|
DrawerType = reflect.TypeOf((*Drawer)(nil)).Elem()
|
||||||
DrawBoxerType = reflect.TypeOf((*DrawBoxer)(nil)).Elem()
|
DrawBoxerType = reflect.TypeOf((*DrawBoxer)(nil)).Elem()
|
||||||
DrawOrdererType = reflect.TypeOf((*DrawOrderer)(nil)).Elem()
|
DrawOrdererType = reflect.TypeOf((*DrawOrderer)(nil)).Elem()
|
||||||
|
@ -73,11 +73,11 @@ type Disabler interface {
|
||||||
Enable()
|
Enable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DrawLayer is a component responsible for calling Draw on all Drawer
|
// DrawManager is a component responsible for calling Draw on all Drawer
|
||||||
// components beneath it, except those beneath another DrawLayer (it calls
|
// components beneath it, except those beneath another DrawManager (it might
|
||||||
// DrawAll on those).
|
// call Draw on the DrawManager, but that's it).
|
||||||
type DrawLayer interface {
|
type DrawManager interface {
|
||||||
DrawAll(*ebiten.Image, *ebiten.DrawImageOptions)
|
ManagesDrawingSubcomponents()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Drawer components can draw themselves. Draw is called often. Draw is not
|
// Drawer components can draw themselves. Draw is called often. Draw is not
|
||||||
|
|
30
main.go
30
main.go
|
@ -67,25 +67,23 @@ func main() {
|
||||||
Y: 1,
|
Y: 1,
|
||||||
Z: math.Sqrt(3),
|
Z: math.Sqrt(3),
|
||||||
},
|
},
|
||||||
Roots: []engine.DrawLayer{
|
Root: &engine.DrawDFS{
|
||||||
&engine.DrawDFS{
|
Components: []interface{}{
|
||||||
Components: []interface{}{
|
&engine.Fill{
|
||||||
&engine.Fill{
|
ID: "bg_fill",
|
||||||
ID: "bg_fill",
|
Color: color.Gray{100},
|
||||||
Color: color.Gray{100},
|
},
|
||||||
},
|
&engine.DrawDAG{
|
||||||
&engine.DrawDAG{
|
ChunkSize: 16,
|
||||||
ChunkSize: 16,
|
Components: []interface{}{
|
||||||
Components: []interface{}{
|
&engine.Camera{
|
||||||
&engine.Camera{
|
ID: "game_camera",
|
||||||
ID: "game_camera",
|
Child: lev1,
|
||||||
Child: lev1,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&engine.DebugToast{ID: "toast", Pos: image.Pt(0, 15)},
|
|
||||||
engine.PerfDisplay{},
|
|
||||||
},
|
},
|
||||||
|
&engine.DebugToast{ID: "toast", Pos: image.Pt(0, 15)},
|
||||||
|
engine.PerfDisplay{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue