2017-01-12 06:47:44 -06:00
|
|
|
package pixel
|
|
|
|
|
|
|
|
import (
|
2017-02-24 07:25:35 -06:00
|
|
|
"fmt"
|
2017-01-12 06:47:44 -06:00
|
|
|
"image/color"
|
|
|
|
|
2017-03-06 12:58:24 -06:00
|
|
|
"github.com/go-gl/mathgl/mgl64"
|
2017-01-12 06:47:44 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
// Batch is a Target that allows for efficient drawing of many objects with the same Picture (but
|
|
|
|
// different slices of the same Picture are allowed).
|
|
|
|
//
|
|
|
|
// To put an object into a Batch, just draw it onto it:
|
|
|
|
// object.Draw(batch)
|
|
|
|
type Batch struct {
|
2017-02-23 18:21:23 -06:00
|
|
|
cont Drawer
|
2017-01-12 06:47:44 -06:00
|
|
|
|
2017-03-06 12:58:24 -06:00
|
|
|
mat Matrix
|
2017-01-12 06:47:44 -06:00
|
|
|
col NRGBA
|
|
|
|
}
|
|
|
|
|
2017-02-23 18:21:23 -06:00
|
|
|
var _ BasicTarget = (*Batch)(nil)
|
|
|
|
|
2017-01-12 06:47:44 -06:00
|
|
|
// NewBatch creates an empty Batch with the specified Picture and container.
|
|
|
|
//
|
2017-03-14 16:50:46 -05:00
|
|
|
// The container is where objects get accumulated. Batch will support precisely those Triangles
|
|
|
|
// properties, that the supplied container supports. If you retain access to the container and
|
|
|
|
// change it, call Dirty to notify Batch about the change.
|
2017-01-12 06:47:44 -06:00
|
|
|
//
|
|
|
|
// Note, that if the container does not support TrianglesColor, color masking will not work.
|
2017-02-23 18:21:23 -06:00
|
|
|
func NewBatch(container Triangles, pic Picture) *Batch {
|
2017-01-12 06:47:44 -06:00
|
|
|
return &Batch{
|
2017-02-23 18:21:23 -06:00
|
|
|
cont: Drawer{Triangles: container, Picture: pic},
|
2017-03-14 07:15:53 -05:00
|
|
|
mat: IM,
|
2017-03-08 16:58:20 -06:00
|
|
|
col: NRGBA{1, 1, 1, 1},
|
2017-01-12 06:47:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-14 16:50:46 -05:00
|
|
|
// Dirty notifies Batch about an external modification of it's container. If you retain access to
|
|
|
|
// the Batch's container and change it, call Dirty to notify Batch about the change.
|
|
|
|
//
|
|
|
|
// container := &pixel.TrianglesData{}
|
|
|
|
// batch := pixel.NewBatch(container, nil)
|
2017-03-14 16:51:45 -05:00
|
|
|
// container.SetLen(10) // container changed from outside of Batch
|
2017-03-14 16:50:46 -05:00
|
|
|
// batch.Dirty() // notify Batch about the change
|
|
|
|
func (b *Batch) Dirty() {
|
|
|
|
b.cont.Dirty()
|
|
|
|
}
|
|
|
|
|
2017-01-12 06:47:44 -06:00
|
|
|
// Clear removes all objects from the Batch.
|
|
|
|
func (b *Batch) Clear() {
|
2017-02-23 18:21:23 -06:00
|
|
|
b.cont.Triangles.SetLen(0)
|
2017-01-28 13:01:59 -06:00
|
|
|
b.cont.Dirty()
|
2017-01-12 06:47:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Draw draws all objects that are currently in the Batch onto another Target.
|
|
|
|
func (b *Batch) Draw(t Target) {
|
|
|
|
b.cont.Draw(t)
|
|
|
|
}
|
|
|
|
|
2017-03-06 12:58:24 -06:00
|
|
|
// SetMatrix sets a Matrix that every point will be projected by.
|
|
|
|
func (b *Batch) SetMatrix(m Matrix) {
|
|
|
|
b.mat = m
|
2017-01-12 06:47:44 -06:00
|
|
|
}
|
|
|
|
|
2017-02-23 18:21:23 -06:00
|
|
|
// SetColorMask sets a mask color used in the following draws onto the Batch.
|
|
|
|
func (b *Batch) SetColorMask(c color.Color) {
|
2017-01-12 06:47:44 -06:00
|
|
|
if c == nil {
|
|
|
|
b.col = NRGBA{1, 1, 1, 1}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
b.col = NRGBAModel.Convert(c).(NRGBA)
|
|
|
|
}
|
|
|
|
|
2017-02-23 18:21:23 -06:00
|
|
|
// MakeTriangles returns a specialized copy of the provided Triangles that draws onto this Batch.
|
|
|
|
func (b *Batch) MakeTriangles(t Triangles) TargetTriangles {
|
|
|
|
bt := &batchTriangles{
|
|
|
|
Triangles: t.Copy(),
|
|
|
|
orig: MakeTrianglesData(t.Len()),
|
|
|
|
trans: MakeTrianglesData(t.Len()),
|
2017-03-08 09:26:09 -06:00
|
|
|
dst: b,
|
2017-02-23 18:21:23 -06:00
|
|
|
}
|
|
|
|
bt.orig.Update(t)
|
2017-03-05 17:44:16 -06:00
|
|
|
bt.trans.Update(bt.orig)
|
2017-02-23 18:21:23 -06:00
|
|
|
return bt
|
|
|
|
}
|
|
|
|
|
|
|
|
// MakePicture returns a specialized copy of the provided Picture that draws onto this Batch.
|
|
|
|
func (b *Batch) MakePicture(p Picture) TargetPicture {
|
2017-03-08 16:51:53 -06:00
|
|
|
if p.Original() != b.cont.Picture.Original() {
|
|
|
|
panic(fmt.Errorf("(%T).MakePicture: Picture is not a slice of Batch's Picture", b))
|
|
|
|
}
|
2017-03-06 12:58:24 -06:00
|
|
|
bp := &batchPicture{
|
2017-02-23 18:21:23 -06:00
|
|
|
Picture: p,
|
2017-03-08 09:26:09 -06:00
|
|
|
dst: b,
|
2017-02-23 18:21:23 -06:00
|
|
|
}
|
2017-03-08 09:26:09 -06:00
|
|
|
bp.orig = bp
|
2017-03-06 12:58:24 -06:00
|
|
|
return bp
|
2017-02-23 18:21:23 -06:00
|
|
|
}
|
|
|
|
|
2017-01-12 06:47:44 -06:00
|
|
|
type batchTriangles struct {
|
|
|
|
Triangles
|
2017-03-05 17:44:16 -06:00
|
|
|
orig, trans *TrianglesData
|
2017-01-12 06:47:44 -06:00
|
|
|
|
2017-03-08 09:26:09 -06:00
|
|
|
dst *Batch
|
2017-01-12 06:47:44 -06:00
|
|
|
}
|
|
|
|
|
2017-02-23 18:21:23 -06:00
|
|
|
func (bt *batchTriangles) draw(bp *batchPicture) {
|
2017-03-05 17:44:16 -06:00
|
|
|
for i := range *bt.trans {
|
2017-03-08 09:26:09 -06:00
|
|
|
transPos := mgl64.Mat3(bt.dst.mat).Mul3x1(mgl64.Vec3{
|
2017-03-06 12:58:24 -06:00
|
|
|
(*bt.orig)[i].Position.X(),
|
|
|
|
(*bt.orig)[i].Position.Y(),
|
2017-01-12 06:47:44 -06:00
|
|
|
1,
|
|
|
|
})
|
2017-03-05 17:44:16 -06:00
|
|
|
(*bt.trans)[i].Position = V(float64(transPos.X()), float64(transPos.Y()))
|
2017-03-08 09:26:09 -06:00
|
|
|
(*bt.trans)[i].Color = (*bt.orig)[i].Color.Mul(bt.dst.col)
|
2017-03-06 12:58:24 -06:00
|
|
|
(*bt.trans)[i].Picture = (*bt.orig)[i].Picture
|
|
|
|
(*bt.trans)[i].Intensity = (*bt.orig)[i].Intensity
|
2017-01-12 06:47:44 -06:00
|
|
|
}
|
2017-01-28 13:01:59 -06:00
|
|
|
|
2017-03-05 17:44:16 -06:00
|
|
|
bt.Triangles.Update(bt.trans)
|
2017-02-23 18:21:23 -06:00
|
|
|
|
2017-03-08 09:26:09 -06:00
|
|
|
cont := bt.dst.cont.Triangles
|
2017-02-23 18:21:23 -06:00
|
|
|
cont.SetLen(cont.Len() + bt.Triangles.Len())
|
|
|
|
cont.Slice(cont.Len()-bt.Triangles.Len(), cont.Len()).Update(bt.Triangles)
|
2017-03-08 09:26:09 -06:00
|
|
|
bt.dst.cont.Dirty()
|
2017-02-23 18:21:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (bt *batchTriangles) Draw() {
|
|
|
|
bt.draw(nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
type batchPicture struct {
|
|
|
|
Picture
|
2017-02-24 07:25:35 -06:00
|
|
|
|
2017-03-08 09:26:09 -06:00
|
|
|
orig *batchPicture
|
|
|
|
dst *Batch
|
2017-02-23 18:21:23 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (bp *batchPicture) Slice(r Rect) Picture {
|
|
|
|
return &batchPicture{
|
2017-03-08 09:26:09 -06:00
|
|
|
Picture: bp.Picture.Slice(r),
|
|
|
|
orig: bp.orig,
|
2017-03-08 16:58:20 -06:00
|
|
|
dst: bp.dst,
|
2017-02-23 18:21:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-06 12:58:24 -06:00
|
|
|
func (bp *batchPicture) Original() Picture {
|
2017-03-08 09:26:09 -06:00
|
|
|
return bp.orig
|
2017-03-06 12:58:24 -06:00
|
|
|
}
|
|
|
|
|
2017-02-23 18:21:23 -06:00
|
|
|
func (bp *batchPicture) Draw(t TargetTriangles) {
|
2017-02-24 07:25:35 -06:00
|
|
|
bt := t.(*batchTriangles)
|
2017-03-08 09:26:09 -06:00
|
|
|
if bp.dst != bt.dst {
|
2017-03-08 16:51:53 -06:00
|
|
|
panic(fmt.Errorf("(%T).Draw: TargetTriangles generated by different Batch", bp))
|
2017-02-24 07:25:35 -06:00
|
|
|
}
|
|
|
|
bt.draw(bp)
|
2017-01-12 06:47:44 -06:00
|
|
|
}
|