add Drawer struct
This commit is contained in:
parent
6dc55b8746
commit
c1843b8608
5
batch.go
5
batch.go
|
@ -41,7 +41,6 @@ func (b *Batch) Clear() {
|
|||
|
||||
// Draw draws all objects that are currently in the Batch onto another Target.
|
||||
func (b *Batch) Draw(t Target) {
|
||||
t.SetPicture(b.fixpic)
|
||||
b.cont.Draw(t)
|
||||
}
|
||||
|
||||
|
@ -98,8 +97,8 @@ func (bt *batchTriangles) Draw() {
|
|||
})
|
||||
bt.data[i].Position = V(float64(transPos.X()), float64(transPos.Y()))
|
||||
bt.data[i].Color = bt.data[i].Color.Mul(bt.batch.col)
|
||||
if bt.batch.pic != nil && bt.data[i].Texture != V(-1, -1) {
|
||||
bt.data[i].Texture = pictureBounds(bt.batch.pic, bt.data[i].Texture)
|
||||
if bt.batch.pic != nil && bt.data[i].Picture != V(-1, -1) {
|
||||
bt.data[i].Picture = pictureBounds(bt.batch.pic, bt.data[i].Picture)
|
||||
}
|
||||
}
|
||||
bt.trans.Update(&bt.data)
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package pixel
|
||||
|
||||
// Drawer glues all the fundamental interfaces (Target, Triangles, Picture) into a coherent and the
|
||||
// only intended usage pattern.
|
||||
//
|
||||
// Drawer makes it possible to draw any combination of Triangles and Picture onto any Target
|
||||
// efficiently.
|
||||
//
|
||||
// To create a Drawer, just assign it's Triangles and Picture fields:
|
||||
// d := pixel.Drawer{Triangles: t, Picture: p}
|
||||
//
|
||||
// If Triangles is nil, nothing will be drawn. If Picture is nil, Triangles will be drawn without a
|
||||
// Picture.
|
||||
//
|
||||
// Whenever you change the Triangles, call Dirty to notify Drawer that Triangles changed. You don't
|
||||
// need to notify Drawer about a change of Picture.
|
||||
type Drawer struct {
|
||||
Triangles Triangles
|
||||
Picture Picture
|
||||
|
||||
tris map[Target]TargetTriangles
|
||||
clean map[Target]bool
|
||||
pics map[targetPicturePair]TargetPicture
|
||||
inited bool
|
||||
}
|
||||
|
||||
type targetPicturePair struct {
|
||||
Target Target
|
||||
Picture Picture
|
||||
}
|
||||
|
||||
func (d *Drawer) lazyInit() {
|
||||
if !d.inited {
|
||||
d.tris = make(map[Target]TargetTriangles)
|
||||
d.clean = make(map[Target]bool)
|
||||
d.pics = make(map[targetPicturePair]TargetPicture)
|
||||
d.inited = true
|
||||
}
|
||||
}
|
||||
|
||||
// Dirty marks the Triangles of this Drawer as changed. If not called, changes will not be visible
|
||||
// when drawing.
|
||||
func (d *Drawer) Dirty() {
|
||||
d.lazyInit()
|
||||
|
||||
for t := range d.clean {
|
||||
d.clean[t] = false
|
||||
}
|
||||
}
|
||||
|
||||
// Draw efficiently draws Triangles with Picture onto the provided Target.
|
||||
//
|
||||
// If Triangles is nil, nothing will be drawn. If Picture is nil, Triangles will be drawn without a
|
||||
// Picture.
|
||||
func (d *Drawer) Draw(t Target) {
|
||||
d.lazyInit()
|
||||
|
||||
if d.Triangles == nil {
|
||||
return
|
||||
}
|
||||
|
||||
tri := d.tris[t]
|
||||
if tri == nil {
|
||||
tri = t.MakeTriangles(d.Triangles)
|
||||
d.tris[t] = tri
|
||||
d.clean[t] = true
|
||||
}
|
||||
|
||||
if !d.clean[t] {
|
||||
tri.SetLen(d.Triangles.Len())
|
||||
tri.Update(d.Triangles)
|
||||
d.clean[t] = true
|
||||
}
|
||||
|
||||
if d.Picture == nil {
|
||||
tri.Draw()
|
||||
return
|
||||
}
|
||||
|
||||
pic := d.pics[targetPicturePair{t, d.Picture}]
|
||||
if pic == nil {
|
||||
pic = t.MakePicture(d.Picture)
|
||||
d.pics[targetPicturePair{t, d.Picture}] = pic
|
||||
}
|
||||
|
||||
pic.Draw(tri)
|
||||
}
|
73
graphics.go
73
graphics.go
|
@ -10,7 +10,7 @@ import (
|
|||
type TrianglesData []struct {
|
||||
Position Vec
|
||||
Color NRGBA
|
||||
Texture Vec
|
||||
Picture Vec
|
||||
}
|
||||
|
||||
// MakeTrianglesData creates TrianglesData of length len initialized with default property values.
|
||||
|
@ -39,7 +39,7 @@ func (td *TrianglesData) SetLen(len int) {
|
|||
*td = append(*td, struct {
|
||||
Position Vec
|
||||
Color NRGBA
|
||||
Texture Vec
|
||||
Picture Vec
|
||||
}{V(0, 0), NRGBA{1, 1, 1, 1}, V(-1, -1)})
|
||||
}
|
||||
}
|
||||
|
@ -72,9 +72,9 @@ func (td *TrianglesData) updateData(t Triangles) {
|
|||
(*td)[i].Color = t.Color(i)
|
||||
}
|
||||
}
|
||||
if t, ok := t.(TrianglesTexture); ok {
|
||||
if t, ok := t.(TrianglesPicture); ok {
|
||||
for i := range *td {
|
||||
(*td)[i].Texture = t.Texture(i)
|
||||
(*td)[i].Picture = t.Picture(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,54 +107,9 @@ func (td *TrianglesData) Color(i int) NRGBA {
|
|||
return (*td)[i].Color
|
||||
}
|
||||
|
||||
// Texture returns the texture property of i-th vertex.
|
||||
func (td *TrianglesData) Texture(i int) Vec {
|
||||
return (*td)[i].Texture
|
||||
}
|
||||
|
||||
// TrianglesDrawer is a helper type that wraps Triangles and turns them into a Drawer.
|
||||
//
|
||||
// It does so by creating a separate Triangles instance for each Target. The instances are
|
||||
// correctly updated alongside the wrapped Triangles.
|
||||
type TrianglesDrawer struct {
|
||||
Triangles
|
||||
|
||||
tris map[Target]TargetTriangles
|
||||
dirty bool
|
||||
}
|
||||
|
||||
func (td *TrianglesDrawer) flush() {
|
||||
if !td.dirty {
|
||||
return
|
||||
}
|
||||
td.dirty = false
|
||||
|
||||
for _, t := range td.tris {
|
||||
t.SetLen(td.Len())
|
||||
t.Update(td.Triangles)
|
||||
}
|
||||
}
|
||||
|
||||
// Draw draws the wrapped Triangles onto the provided Target.
|
||||
func (td *TrianglesDrawer) Draw(target Target) {
|
||||
if td.tris == nil {
|
||||
td.tris = make(map[Target]TargetTriangles)
|
||||
}
|
||||
|
||||
td.flush()
|
||||
|
||||
tri := td.tris[target]
|
||||
if tri == nil {
|
||||
tri = target.MakeTriangles(td.Triangles)
|
||||
td.tris[target] = tri
|
||||
}
|
||||
tri.Draw()
|
||||
}
|
||||
|
||||
// Dirty marks the underlying container as changed (dirty). Always call this when you change the
|
||||
// underlying Triangles (by Update, SetLen, etc.).
|
||||
func (td *TrianglesDrawer) Dirty() {
|
||||
td.dirty = true
|
||||
// Picture returns the picture property of i-th vertex.
|
||||
func (td *TrianglesData) Picture(i int) Vec {
|
||||
return (*td)[i].Picture
|
||||
}
|
||||
|
||||
// Sprite is a picture that can be drawn onto a Target. To change the position/rotation/scale of
|
||||
|
@ -170,12 +125,12 @@ type Sprite struct {
|
|||
func NewSprite(pic *GLPicture) *Sprite {
|
||||
s := &Sprite{
|
||||
data: TrianglesData{
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Texture: V(0, 0)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Texture: V(1, 0)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Texture: V(1, 1)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Texture: V(0, 0)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Texture: V(1, 1)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Texture: V(0, 1)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(0, 0)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(1, 0)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(1, 1)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(0, 0)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(1, 1)},
|
||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(0, 1)},
|
||||
},
|
||||
}
|
||||
s.td = TrianglesDrawer{Triangles: &s.data}
|
||||
|
@ -207,7 +162,6 @@ func (s *Sprite) Picture() *GLPicture {
|
|||
|
||||
// Draw draws the Sprite onto the provided Target.
|
||||
func (s *Sprite) Draw(t Target) {
|
||||
t.SetPicture(s.pic)
|
||||
s.td.Draw(t)
|
||||
}
|
||||
|
||||
|
@ -277,6 +231,5 @@ func (p *Polygon) Points() []Vec {
|
|||
|
||||
// Draw draws the Polygon onto the Target.
|
||||
func (p *Polygon) Draw(t Target) {
|
||||
t.SetPicture(nil)
|
||||
p.td.Draw(t)
|
||||
}
|
||||
|
|
|
@ -59,12 +59,12 @@ func NewCanvas(width, height float64, smooth bool) *Canvas {
|
|||
|
||||
white := pixel.NRGBA{R: 1, G: 1, B: 1, A: 1}
|
||||
c.drawTd = pixel.TrianglesDrawer{Triangles: &pixel.TrianglesData{
|
||||
{Position: pixel.V(-1, -1), Color: white, Texture: pixel.V(0, 0)},
|
||||
{Position: pixel.V(1, -1), Color: white, Texture: pixel.V(1, 0)},
|
||||
{Position: pixel.V(1, 1), Color: white, Texture: pixel.V(1, 1)},
|
||||
{Position: pixel.V(-1, -1), Color: white, Texture: pixel.V(0, 0)},
|
||||
{Position: pixel.V(1, 1), Color: white, Texture: pixel.V(1, 1)},
|
||||
{Position: pixel.V(-1, 1), Color: white, Texture: pixel.V(0, 1)},
|
||||
{Position: pixel.V(-1, -1), Color: white, Picture: pixel.V(0, 0)},
|
||||
{Position: pixel.V(1, -1), Color: white, Picture: pixel.V(1, 0)},
|
||||
{Position: pixel.V(1, 1), Color: white, Picture: pixel.V(1, 1)},
|
||||
{Position: pixel.V(-1, -1), Color: white, Picture: pixel.V(0, 0)},
|
||||
{Position: pixel.V(1, 1), Color: white, Picture: pixel.V(1, 1)},
|
||||
{Position: pixel.V(-1, 1), Color: white, Picture: pixel.V(0, 1)},
|
||||
}}
|
||||
|
||||
c.pic = nil
|
||||
|
@ -126,7 +126,6 @@ func (c *Canvas) Clear(col color.Color) {
|
|||
// Draw draws the content of the Canvas onto another Target. If no transform is applied, the content
|
||||
// is fully stretched to fit the Target.
|
||||
func (c *Canvas) Draw(t pixel.Target) {
|
||||
t.SetPicture(c.Content())
|
||||
c.drawTd.Draw(t)
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ func (gt *glTriangles) updateData(t pixel.Triangles) {
|
|||
var (
|
||||
px, py = (*t)[i].Position.XY()
|
||||
col = (*t)[i].Color
|
||||
tx, ty = (*t)[i].Texture.XY()
|
||||
tx, ty = (*t)[i].Picture.XY()
|
||||
)
|
||||
gt.data[i*gt.vs.Stride()+0] = float32(px)
|
||||
gt.data[i*gt.vs.Stride()+1] = float32(py)
|
||||
|
@ -106,9 +106,9 @@ func (gt *glTriangles) updateData(t pixel.Triangles) {
|
|||
gt.data[i*gt.vs.Stride()+5] = float32(col.A)
|
||||
}
|
||||
}
|
||||
if t, ok := t.(pixel.TrianglesTexture); ok {
|
||||
if t, ok := t.(pixel.TrianglesPicture); ok {
|
||||
for i := 0; i < gt.Len(); i++ {
|
||||
tx, ty := t.Texture(i).XY()
|
||||
tx, ty := t.Picture(i).XY()
|
||||
gt.data[i*gt.vs.Stride()+6] = float32(tx)
|
||||
gt.data[i*gt.vs.Stride()+7] = float32(ty)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue