rework Triangles API and adapt it
This commit is contained in:
parent
e7a2af61fb
commit
63339235b7
12
batch.go
12
batch.go
|
@ -35,7 +35,8 @@ func NewBatch(pic *Picture, container Triangles) *Batch {
|
|||
|
||||
// Clear removes all objects from the Batch.
|
||||
func (b *Batch) Clear() {
|
||||
b.cont.Update(&TrianglesData{})
|
||||
b.cont.SetLen(0)
|
||||
b.cont.Dirty()
|
||||
}
|
||||
|
||||
// Draw draws all objects that are currently in the Batch onto another Target.
|
||||
|
@ -45,10 +46,11 @@ func (b *Batch) Draw(t Target) {
|
|||
}
|
||||
|
||||
// MakeTriangles returns a specialized copy of the provided Triangles, that draws onto this Batch.
|
||||
func (b *Batch) MakeTriangles(t Triangles) Triangles {
|
||||
func (b *Batch) MakeTriangles(t Triangles) TargetTriangles {
|
||||
return &batchTriangles{
|
||||
Triangles: t.Copy(),
|
||||
trans: t.Copy(),
|
||||
data: MakeTrianglesData(t.Len()),
|
||||
batch: b,
|
||||
}
|
||||
}
|
||||
|
@ -101,5 +103,9 @@ func (bt *batchTriangles) Draw() {
|
|||
}
|
||||
}
|
||||
bt.trans.Update(&bt.data)
|
||||
bt.batch.cont.Append(bt.trans)
|
||||
|
||||
cont := bt.batch.cont
|
||||
cont.SetLen(cont.Len() + bt.trans.Len())
|
||||
cont.Slice(cont.Len()-bt.trans.Len(), cont.Len()).Update(bt.trans)
|
||||
cont.Dirty()
|
||||
}
|
||||
|
|
19
canvas.go
19
canvas.go
|
@ -129,11 +129,11 @@ func (c *Canvas) Draw(t Target) {
|
|||
}
|
||||
|
||||
// MakeTriangles returns Triangles that draw onto this Canvas.
|
||||
func (c *Canvas) MakeTriangles(t Triangles) Triangles {
|
||||
tpcs := NewGLTriangles(c.s, t).(trianglesPositionColorTexture)
|
||||
func (c *Canvas) MakeTriangles(t Triangles) TargetTriangles {
|
||||
gt := NewGLTriangles(c.s, t).(*glTriangles)
|
||||
return &canvasTriangles{
|
||||
c: c,
|
||||
trianglesPositionColorTexture: tpcs,
|
||||
glTriangles: gt,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,16 +170,9 @@ func (c *Canvas) SetMaskColor(col color.Color) {
|
|||
c.col = mgl32.Vec4{r, g, b, a}
|
||||
}
|
||||
|
||||
type trianglesPositionColorTexture interface {
|
||||
Triangles
|
||||
Position(i int) Vec
|
||||
Color(i int) NRGBA
|
||||
Texture(i int) Vec
|
||||
}
|
||||
|
||||
type canvasTriangles struct {
|
||||
c *Canvas
|
||||
trianglesPositionColorTexture
|
||||
*glTriangles
|
||||
}
|
||||
|
||||
func (ct *canvasTriangles) Draw() {
|
||||
|
@ -199,10 +192,10 @@ func (ct *canvasTriangles) Draw() {
|
|||
|
||||
if pic != nil {
|
||||
pic.Texture().Begin()
|
||||
ct.trianglesPositionColorTexture.Draw()
|
||||
ct.glTriangles.Draw()
|
||||
pic.Texture().End()
|
||||
} else {
|
||||
ct.trianglesPositionColorTexture.Draw()
|
||||
ct.glTriangles.Draw()
|
||||
}
|
||||
|
||||
ct.c.s.End()
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package pixel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/faiface/mainthread"
|
||||
"github.com/faiface/pixel/pixelgl"
|
||||
)
|
||||
|
@ -13,7 +15,7 @@ import (
|
|||
// Draw method simply draws the underlying pixelgl.VertexSlice. It needs to be called in the main
|
||||
// thread manually. Also, you need to take care of additional Target initialization or setting of
|
||||
// uniform attributes.
|
||||
func NewGLTriangles(shader *pixelgl.Shader, t Triangles) Triangles {
|
||||
func NewGLTriangles(shader *pixelgl.Shader, t Triangles) TargetTriangles {
|
||||
var gt *glTriangles
|
||||
mainthread.Call(func() {
|
||||
gt = &glTriangles{
|
||||
|
@ -21,6 +23,7 @@ func NewGLTriangles(shader *pixelgl.Shader, t Triangles) Triangles {
|
|||
shader: shader,
|
||||
}
|
||||
})
|
||||
gt.SetLen(t.Len())
|
||||
gt.Update(t)
|
||||
return gt
|
||||
}
|
||||
|
@ -35,13 +38,7 @@ func (gt *glTriangles) Len() int {
|
|||
return len(gt.data) / gt.vs.Stride()
|
||||
}
|
||||
|
||||
func (gt *glTriangles) Draw() {
|
||||
gt.vs.Begin()
|
||||
gt.vs.Draw()
|
||||
gt.vs.End()
|
||||
}
|
||||
|
||||
func (gt *glTriangles) resize(len int) {
|
||||
func (gt *glTriangles) SetLen(len int) {
|
||||
if len > gt.Len() {
|
||||
needAppend := len - gt.Len()
|
||||
for i := 0; i < needAppend; i++ {
|
||||
|
@ -57,10 +54,24 @@ func (gt *glTriangles) resize(len int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (gt *glTriangles) updateData(offset int, t Triangles) {
|
||||
func (gt *glTriangles) Slice(i, j int) Triangles {
|
||||
return &glTriangles{
|
||||
vs: gt.vs.Slice(i, j),
|
||||
data: gt.data[i*gt.vs.Stride() : j*gt.vs.Stride()],
|
||||
shader: gt.shader,
|
||||
}
|
||||
}
|
||||
|
||||
func (gt *glTriangles) updateData(t Triangles) {
|
||||
// glTriangles short path
|
||||
if t, ok := t.(*glTriangles); ok {
|
||||
copy(gt.data, t.data)
|
||||
return
|
||||
}
|
||||
|
||||
// TrianglesData short path
|
||||
if t, ok := t.(*TrianglesData); ok {
|
||||
for i := offset; i < offset+t.Len(); i++ {
|
||||
for i := 0; i < gt.Len(); i++ {
|
||||
var (
|
||||
px, py = (*t)[i].Position.XY()
|
||||
col = (*t)[i].Color
|
||||
|
@ -79,14 +90,14 @@ func (gt *glTriangles) updateData(offset int, t Triangles) {
|
|||
}
|
||||
|
||||
if t, ok := t.(TrianglesPosition); ok {
|
||||
for i := offset; i < offset+t.Len(); i++ {
|
||||
for i := 0; i < gt.Len(); i++ {
|
||||
px, py := t.Position(i).XY()
|
||||
gt.data[i*gt.vs.Stride()+0] = float32(px)
|
||||
gt.data[i*gt.vs.Stride()+1] = float32(py)
|
||||
}
|
||||
}
|
||||
if t, ok := t.(TrianglesColor); ok {
|
||||
for i := offset; i < offset+t.Len(); i++ {
|
||||
for i := 0; i < gt.Len(); i++ {
|
||||
col := t.Color(i)
|
||||
gt.data[i*gt.vs.Stride()+2] = float32(col.R)
|
||||
gt.data[i*gt.vs.Stride()+3] = float32(col.G)
|
||||
|
@ -95,7 +106,7 @@ func (gt *glTriangles) updateData(offset int, t Triangles) {
|
|||
}
|
||||
}
|
||||
if t, ok := t.(TrianglesTexture); ok {
|
||||
for i := offset; i < offset+t.Len(); i++ {
|
||||
for i := 0; i < gt.Len(); i++ {
|
||||
tx, ty := t.Texture(i).XY()
|
||||
gt.data[i*gt.vs.Stride()+6] = float32(tx)
|
||||
gt.data[i*gt.vs.Stride()+7] = float32(ty)
|
||||
|
@ -120,14 +131,10 @@ func (gt *glTriangles) submitData() {
|
|||
}
|
||||
|
||||
func (gt *glTriangles) Update(t Triangles) {
|
||||
gt.resize(t.Len())
|
||||
gt.updateData(0, t)
|
||||
gt.submitData()
|
||||
if gt.Len() != t.Len() {
|
||||
panic(fmt.Errorf("%T.Update: invalid triangles len", gt))
|
||||
}
|
||||
|
||||
func (gt *glTriangles) Append(t Triangles) {
|
||||
gt.resize(gt.Len() + t.Len())
|
||||
gt.updateData(gt.Len()-t.Len(), t)
|
||||
gt.updateData(t)
|
||||
gt.submitData()
|
||||
}
|
||||
|
||||
|
@ -135,6 +142,12 @@ func (gt *glTriangles) Copy() Triangles {
|
|||
return NewGLTriangles(gt.shader, gt)
|
||||
}
|
||||
|
||||
func (gt *glTriangles) Draw() {
|
||||
gt.vs.Begin()
|
||||
gt.vs.Draw()
|
||||
gt.vs.End()
|
||||
}
|
||||
|
||||
func (gt *glTriangles) Position(i int) Vec {
|
||||
px := gt.data[i*gt.vs.Stride()+0]
|
||||
py := gt.data[i*gt.vs.Stride()+1]
|
||||
|
|
79
graphics.go
79
graphics.go
|
@ -13,6 +13,21 @@ type TrianglesData []struct {
|
|||
Texture Vec
|
||||
}
|
||||
|
||||
// MakeTrianglesData creates TrianglesData of length len initialized with default property values.
|
||||
//
|
||||
// Prefer this function to make(TrianglesData, len), because make zeros them, while this function
|
||||
// does a correct intialization.
|
||||
func MakeTrianglesData(len int) TrianglesData {
|
||||
td := TrianglesData{}
|
||||
td.SetLen(len)
|
||||
return td
|
||||
}
|
||||
|
||||
// Len returns the number of vertices in TrianglesData.
|
||||
func (td *TrianglesData) Len() int {
|
||||
return len(*td)
|
||||
}
|
||||
|
||||
// SetLen resizes TrianglesData to len, while keeping the original content.
|
||||
//
|
||||
// If len is greater than TrianglesData's current length, the new data is filled with default
|
||||
|
@ -33,36 +48,32 @@ func (td *TrianglesData) SetLen(len int) {
|
|||
}
|
||||
}
|
||||
|
||||
// Len returns the number of vertices in TrianglesData.
|
||||
func (td *TrianglesData) Len() int {
|
||||
return len(*td)
|
||||
// Slice returns a sub-Triangles of this TrianglesData.
|
||||
func (td *TrianglesData) Slice(i, j int) Triangles {
|
||||
s := TrianglesData((*td)[i:j])
|
||||
return &s
|
||||
}
|
||||
|
||||
// Draw is unimplemented for TrianglesData and panics.
|
||||
func (td *TrianglesData) Draw() {
|
||||
panic(fmt.Errorf("%T.Draw: invalid operation", td))
|
||||
}
|
||||
|
||||
func (td *TrianglesData) updateData(offset int, t Triangles) {
|
||||
func (td *TrianglesData) updateData(t Triangles) {
|
||||
// fast path optimization
|
||||
if t, ok := t.(*TrianglesData); ok {
|
||||
copy((*td)[offset:], *t)
|
||||
copy(*td, *t)
|
||||
return
|
||||
}
|
||||
|
||||
// slow path manual copy
|
||||
if t, ok := t.(TrianglesPosition); ok {
|
||||
for i := offset; i < len(*td); i++ {
|
||||
for i := range *td {
|
||||
(*td)[i].Position = t.Position(i)
|
||||
}
|
||||
}
|
||||
if t, ok := t.(TrianglesColor); ok {
|
||||
for i := offset; i < len(*td); i++ {
|
||||
for i := range *td {
|
||||
(*td)[i].Color = t.Color(i)
|
||||
}
|
||||
}
|
||||
if t, ok := t.(TrianglesTexture); ok {
|
||||
for i := offset; i < len(*td); i++ {
|
||||
for i := range *td {
|
||||
(*td)[i].Texture = t.Texture(i)
|
||||
}
|
||||
}
|
||||
|
@ -72,19 +83,16 @@ func (td *TrianglesData) updateData(offset int, t Triangles) {
|
|||
//
|
||||
// TrianglesPosition, TrianglesColor and TrianglesTexture are supported.
|
||||
func (td *TrianglesData) Update(t Triangles) {
|
||||
td.SetLen(t.Len())
|
||||
td.updateData(0, t)
|
||||
if td.Len() != t.Len() {
|
||||
panic(fmt.Errorf("%T.Update: invalid triangles length", td))
|
||||
}
|
||||
|
||||
// Append adds supplied Triangles to the end of the TrianglesData.
|
||||
func (td *TrianglesData) Append(t Triangles) {
|
||||
td.SetLen(td.Len() + t.Len())
|
||||
td.updateData(td.Len()-t.Len(), t)
|
||||
td.updateData(t)
|
||||
}
|
||||
|
||||
// Copy returns an exact independent copy of this TrianglesData.
|
||||
func (td *TrianglesData) Copy() Triangles {
|
||||
copyTd := make(TrianglesData, td.Len())
|
||||
copyTd := TrianglesData{}
|
||||
copyTd.SetLen(td.Len())
|
||||
copyTd.Update(td)
|
||||
return ©Td
|
||||
}
|
||||
|
@ -111,7 +119,7 @@ func (td *TrianglesData) Texture(i int) Vec {
|
|||
type TrianglesDrawer struct {
|
||||
Triangles
|
||||
|
||||
tris map[Target]Triangles
|
||||
tris map[Target]TargetTriangles
|
||||
dirty bool
|
||||
}
|
||||
|
||||
|
@ -129,7 +137,7 @@ func (td *TrianglesDrawer) flush() {
|
|||
// Draw draws the wrapped Triangles onto the provided Target.
|
||||
func (td *TrianglesDrawer) Draw(target Target) {
|
||||
if td.tris == nil {
|
||||
td.tris = make(map[Target]Triangles)
|
||||
td.tris = make(map[Target]TargetTriangles)
|
||||
}
|
||||
|
||||
td.flush()
|
||||
|
@ -142,27 +150,8 @@ func (td *TrianglesDrawer) Draw(target Target) {
|
|||
tri.Draw()
|
||||
}
|
||||
|
||||
// Update updates the wrapped Triangles with the supplied Triangles.
|
||||
//
|
||||
// Call only this method to update the wrapped Triangles, otherwise the TrianglesDrawer will not
|
||||
// work correctly.
|
||||
func (td *TrianglesDrawer) Update(t Triangles) {
|
||||
td.dirty = true
|
||||
td.Triangles.Update(t)
|
||||
}
|
||||
|
||||
// Append appends the supplied Triangles to the wrapped Triangles.
|
||||
//
|
||||
// Call only this method to append to the wrapped Triangles, otherwise the TrianglesDrawer will not
|
||||
// work correctly.
|
||||
func (td *TrianglesDrawer) Append(t Triangles) {
|
||||
td.dirty = true
|
||||
td.Triangles.Append(t)
|
||||
}
|
||||
|
||||
// Dirty marks the underlying container as changed (dirty). If you, despite all warnings, updated
|
||||
// the underlying container in a way different from td.Update or td.Append, call Dirty and
|
||||
// everything will be fine :)
|
||||
// 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
|
||||
}
|
||||
|
@ -232,7 +221,7 @@ type Polygon struct {
|
|||
// counter-clock-wise order, it doesn't matter. They should however form a convex polygon.
|
||||
func NewPolygon(c color.Color, points ...Vec) *Polygon {
|
||||
p := &Polygon{
|
||||
data: make(TrianglesData, len(points)),
|
||||
data: TrianglesData{},
|
||||
}
|
||||
p.td = TrianglesDrawer{Triangles: &p.data}
|
||||
p.SetColor(c)
|
||||
|
|
49
interface.go
49
interface.go
|
@ -11,13 +11,13 @@ import "image/color"
|
|||
type Target interface {
|
||||
// MakeTriangles generates a specialized copy of the provided Triangles.
|
||||
//
|
||||
// When calling Draw method on the returned Triangles, the Triangles will be drawn onto the
|
||||
// target that generated them.
|
||||
// When calling Draw method on the returned TargetTriangles, the TargetTriangles will be
|
||||
// drawn onto the Target that generated them.
|
||||
//
|
||||
// Note, that not every Target has to recognize all possible types of triangles. Some may
|
||||
// Note, that not every Target has to recognize all possible types of Triangles. Some may
|
||||
// only recognize TrianglesPosition and TrianglesColor and ignore all other properties (if
|
||||
// present) when making new Triangles. This varies from Target to Target.
|
||||
MakeTriangles(Triangles) Triangles
|
||||
// present) when making new TargetTriangles. This varies from Target to Target.
|
||||
MakeTriangles(Triangles) TargetTriangles
|
||||
|
||||
// These are the most basic Target "adjustment" methods.
|
||||
SetPicture(*Picture)
|
||||
|
@ -32,33 +32,39 @@ type Triangles interface {
|
|||
// divided by 3.
|
||||
Len() int
|
||||
|
||||
// Draw draws Triangles onto an associated Target (if any).
|
||||
// SetLen resizes Triangles to len vertices. If Triangles B were obtained by calling Slice
|
||||
// method on Triangles A, the relationship between A and B is undefined after calling SetLen
|
||||
// on either one of them.
|
||||
SetLen(len int)
|
||||
|
||||
// Slice returns a sub-Triangles of this Triangles, covering vertices in range [i, j).
|
||||
//
|
||||
// Note, that this method does not have to be implemented, however it is always implemented
|
||||
// for Triangles generated by a Target.
|
||||
Draw()
|
||||
// If Triangles B were obtained by calling Slice(4, 9) on Triangles A, then A and B must
|
||||
// share the same underlying data. Modifying B must change the contents of A in range
|
||||
// [4, 9). The vertex with index 0 at B is the vertex with index 4 in A, and so on.
|
||||
//
|
||||
// Returned Triangles must have the same underlying type.
|
||||
Slice(i, j int) Triangles
|
||||
|
||||
// Update copies vertex properties from the supplied Triangles into this Triangles.
|
||||
//
|
||||
// Properies not supported by these Triangles should be ignored. Properties not supported by
|
||||
// the supplied Triangles should be left untouched.
|
||||
//
|
||||
// If these Triangles and supplied Triangles have different lengths, these Triangles should
|
||||
// be resized.
|
||||
// The two Triangles need to have the same Len.
|
||||
Update(Triangles)
|
||||
|
||||
// Append adds supplied Triangles to the end of these Triangles.
|
||||
//
|
||||
// Behavior regarding unsupported properties should be same as with Update.
|
||||
Append(Triangles)
|
||||
|
||||
// Copy creates an exact independent copy of this Triangles (with the same underlying type).
|
||||
Copy() Triangles
|
||||
}
|
||||
|
||||
// Drawer is something that can be drawn onto any Target.
|
||||
type Drawer interface {
|
||||
Draw(Target)
|
||||
// TargetTriangles are Triangles generated by a Target with MakeTriangles method. They can be drawn
|
||||
// onto that Target.
|
||||
type TargetTriangles interface {
|
||||
Triangles
|
||||
|
||||
// Draw draws Triangles onto an associated Target.
|
||||
Draw()
|
||||
}
|
||||
|
||||
// TrianglesPosition specifies Triangles with Position property.
|
||||
|
@ -86,3 +92,8 @@ type TrianglesTexture interface {
|
|||
Triangles
|
||||
Texture(i int) Vec
|
||||
}
|
||||
|
||||
// Drawer is something that can be drawn onto any Target.
|
||||
type Drawer interface {
|
||||
Draw(Target)
|
||||
}
|
||||
|
|
|
@ -369,7 +369,7 @@ func (w *Window) end() {
|
|||
// Window.
|
||||
//
|
||||
// Window supports TrianglesPosition, TrianglesColor and TrianglesTexture.
|
||||
func (w *Window) MakeTriangles(t Triangles) Triangles {
|
||||
func (w *Window) MakeTriangles(t Triangles) TargetTriangles {
|
||||
return w.canvas.MakeTriangles(t)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue