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.
|
// Draw draws all objects that are currently in the Batch onto another Target.
|
||||||
func (b *Batch) Draw(t Target) {
|
func (b *Batch) Draw(t Target) {
|
||||||
t.SetPicture(b.fixpic)
|
|
||||||
b.cont.Draw(t)
|
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].Position = V(float64(transPos.X()), float64(transPos.Y()))
|
||||||
bt.data[i].Color = bt.data[i].Color.Mul(bt.batch.col)
|
bt.data[i].Color = bt.data[i].Color.Mul(bt.batch.col)
|
||||||
if bt.batch.pic != nil && bt.data[i].Texture != V(-1, -1) {
|
if bt.batch.pic != nil && bt.data[i].Picture != V(-1, -1) {
|
||||||
bt.data[i].Texture = pictureBounds(bt.batch.pic, bt.data[i].Texture)
|
bt.data[i].Picture = pictureBounds(bt.batch.pic, bt.data[i].Picture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bt.trans.Update(&bt.data)
|
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 {
|
type TrianglesData []struct {
|
||||||
Position Vec
|
Position Vec
|
||||||
Color NRGBA
|
Color NRGBA
|
||||||
Texture Vec
|
Picture Vec
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeTrianglesData creates TrianglesData of length len initialized with default property values.
|
// 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 {
|
*td = append(*td, struct {
|
||||||
Position Vec
|
Position Vec
|
||||||
Color NRGBA
|
Color NRGBA
|
||||||
Texture Vec
|
Picture Vec
|
||||||
}{V(0, 0), NRGBA{1, 1, 1, 1}, V(-1, -1)})
|
}{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)
|
(*td)[i].Color = t.Color(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if t, ok := t.(TrianglesTexture); ok {
|
if t, ok := t.(TrianglesPicture); ok {
|
||||||
for i := range *td {
|
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
|
return (*td)[i].Color
|
||||||
}
|
}
|
||||||
|
|
||||||
// Texture returns the texture property of i-th vertex.
|
// Picture returns the picture property of i-th vertex.
|
||||||
func (td *TrianglesData) Texture(i int) Vec {
|
func (td *TrianglesData) Picture(i int) Vec {
|
||||||
return (*td)[i].Texture
|
return (*td)[i].Picture
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sprite is a picture that can be drawn onto a Target. To change the position/rotation/scale of
|
// 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 {
|
func NewSprite(pic *GLPicture) *Sprite {
|
||||||
s := &Sprite{
|
s := &Sprite{
|
||||||
data: TrianglesData{
|
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}, Picture: 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}, Picture: 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}, Picture: 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}, Picture: 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}, Picture: 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, 1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s.td = TrianglesDrawer{Triangles: &s.data}
|
s.td = TrianglesDrawer{Triangles: &s.data}
|
||||||
|
@ -207,7 +162,6 @@ func (s *Sprite) Picture() *GLPicture {
|
||||||
|
|
||||||
// Draw draws the Sprite onto the provided Target.
|
// Draw draws the Sprite onto the provided Target.
|
||||||
func (s *Sprite) Draw(t Target) {
|
func (s *Sprite) Draw(t Target) {
|
||||||
t.SetPicture(s.pic)
|
|
||||||
s.td.Draw(t)
|
s.td.Draw(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +231,5 @@ func (p *Polygon) Points() []Vec {
|
||||||
|
|
||||||
// Draw draws the Polygon onto the Target.
|
// Draw draws the Polygon onto the Target.
|
||||||
func (p *Polygon) Draw(t Target) {
|
func (p *Polygon) Draw(t Target) {
|
||||||
t.SetPicture(nil)
|
|
||||||
p.td.Draw(t)
|
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}
|
white := pixel.NRGBA{R: 1, G: 1, B: 1, A: 1}
|
||||||
c.drawTd = pixel.TrianglesDrawer{Triangles: &pixel.TrianglesData{
|
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, Picture: pixel.V(0, 0)},
|
||||||
{Position: pixel.V(1, -1), Color: white, Texture: pixel.V(1, 0)},
|
{Position: pixel.V(1, -1), Color: white, Picture: pixel.V(1, 0)},
|
||||||
{Position: pixel.V(1, 1), Color: white, Texture: pixel.V(1, 1)},
|
{Position: pixel.V(1, 1), Color: white, Picture: pixel.V(1, 1)},
|
||||||
{Position: pixel.V(-1, -1), Color: white, Texture: pixel.V(0, 0)},
|
{Position: pixel.V(-1, -1), Color: white, Picture: pixel.V(0, 0)},
|
||||||
{Position: pixel.V(1, 1), Color: white, Texture: pixel.V(1, 1)},
|
{Position: pixel.V(1, 1), Color: white, Picture: 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, 1)},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
c.pic = nil
|
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
|
// Draw draws the content of the Canvas onto another Target. If no transform is applied, the content
|
||||||
// is fully stretched to fit the Target.
|
// is fully stretched to fit the Target.
|
||||||
func (c *Canvas) Draw(t pixel.Target) {
|
func (c *Canvas) Draw(t pixel.Target) {
|
||||||
t.SetPicture(c.Content())
|
|
||||||
c.drawTd.Draw(t)
|
c.drawTd.Draw(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ func (gt *glTriangles) updateData(t pixel.Triangles) {
|
||||||
var (
|
var (
|
||||||
px, py = (*t)[i].Position.XY()
|
px, py = (*t)[i].Position.XY()
|
||||||
col = (*t)[i].Color
|
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()+0] = float32(px)
|
||||||
gt.data[i*gt.vs.Stride()+1] = float32(py)
|
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)
|
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++ {
|
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()+6] = float32(tx)
|
||||||
gt.data[i*gt.vs.Stride()+7] = float32(ty)
|
gt.data[i*gt.vs.Stride()+7] = float32(ty)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue