Skip to content
graphics.go 4.58 KiB
Newer Older
package pixel

import (
// TrianglesData specifies a list of Triangles vertices with three common properties: Position,
// Color and Texture.
type TrianglesData []struct {
	Position Vec
	Color    color.Color
	Texture  Vec
faiface's avatar
faiface committed
}

// Len returns the number of vertices in TrianglesData.
func (td *TrianglesData) Len() int {
	return len(*td)
faiface's avatar
faiface committed
}

// Draw is unimplemented for TrianglesData and panics.
func (td *TrianglesData) Draw() {
	panic(fmt.Errorf("%T.Draw: invalid operation", td))
faiface's avatar
faiface committed
}

// Update copies vertex properties from the supplied Triangles into this TrianglesData.
faiface's avatar
faiface committed
//
// TrianglesPosition, TrianglesColor and TrianglesTexture are supported.
func (td *TrianglesData) Update(t Triangles) {
	if t.Len() > td.Len() {
		*td = append(*td, make(TrianglesData, t.Len()-td.Len())...)
faiface's avatar
faiface committed
	}
	if t.Len() < td.Len() {
		*td = (*td)[:t.Len()]
faiface's avatar
faiface committed
	}

	// fast path optimization
	if t, ok := t.(*TrianglesData); ok {
		copy(*td, *t)
		return
	}
	if t, ok := t.(*TrianglesColorData); ok {
		copy(*td, *(*TrianglesData)(t))
		return
	}
	if t, ok := t.(*TrianglesTextureData); ok {
		copy(*td, *(*TrianglesData)(t))
		return
	}
	// slow path manual copy
	if t, ok := t.(TrianglesPosition); ok {
		for i := range *td {
			(*td)[i].Position = t.Position(i)
	}
	if t, ok := t.(TrianglesColor); ok {
		for i := range *td {
			(*td)[i].Color = t.Color(i)
faiface's avatar
faiface committed
		}
	}
	if t, ok := t.(TrianglesTexture); ok {
		for i := range *td {
			(*td)[i].Texture = t.Texture(i)
faiface's avatar
faiface committed
		}
faiface's avatar
faiface committed
	}
faiface's avatar
faiface committed
}

// Position returns the position property of i-th vertex.
func (td *TrianglesData) Position(i int) Vec {
	return (*td)[i].Position
faiface's avatar
faiface committed

// Color returns the color property of i-th vertex.
func (td *TrianglesData) Color(i int) color.Color {
	return (*td)[i].Color
faiface's avatar
faiface committed
}

// Texture returns the texture property of i-th vertex.
func (td *TrianglesData) Texture(i int) Vec {
	return (*td)[i].Texture
faiface's avatar
faiface committed
}

// TrianglesColorData is same as TrianglesData, except is lacks Texture property.
type TrianglesColorData TrianglesData
faiface's avatar
faiface committed

// Len returns the number of vertices in TrianglesColorData.
func (td *TrianglesColorData) Len() int {
	return (*TrianglesData)(td).Len()
faiface's avatar
faiface committed
}

// Draw is unimplemented for TrianglesColorData and panics.
func (td *TrianglesColorData) Draw() {
	(*TrianglesData)(td).Draw()
faiface's avatar
faiface committed
}

// Update copies vertex properties from the supplied Triangles into this TrianglesColorData.
func (td *TrianglesColorData) Update(t Triangles) {
	(*TrianglesData)(td).Update(t)
faiface's avatar
faiface committed
}

// Position returns the position property of i-th vertex.
func (td *TrianglesColorData) Position(i int) Vec {
	return (*TrianglesData)(td).Position(i)
faiface's avatar
faiface committed
}

// Color returns the color property of i-th vertex.
func (td *TrianglesColorData) Color(i int) color.Color {
	return (*TrianglesData)(td).Color(i)
faiface's avatar
faiface committed
}

// TrianglesTextureData is same as TrianglesData, except is lacks Color property.
type TrianglesTextureData TrianglesData
faiface's avatar
faiface committed

// Len returns the number of vertices in TrianglesTextureData.
func (td *TrianglesTextureData) Len() int {
	return (*TrianglesData)(td).Len()
faiface's avatar
faiface committed
}

// Draw is unimplemented for TrianglesTextureData and panics.
func (td *TrianglesTextureData) Draw() {
	(*TrianglesData)(td).Draw()
// Update copies vertex properties from the supplied Triangles into this TrianglesTextureData.
func (td *TrianglesTextureData) Update(t Triangles) {
	(*TrianglesData)(td).Update(t)
// Position returns the position property of i-th vertex.
func (td *TrianglesTextureData) Position(i int) Vec {
	return (*TrianglesData)(td).Position(i)
// Texture returns the texture property of i-th vertex.
func (td *TrianglesTextureData) Texture(i int) Vec {
	return (*TrianglesData)(td).Texture(i)
// 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]Triangles
	dirty bool
faiface's avatar
faiface committed
}

func (td *TrianglesDrawer) flush() {
	if !td.dirty {
		return
faiface's avatar
faiface committed
	}
	for _, t := range td.tris {
		t.Update(td.Triangles)
faiface's avatar
faiface committed

// 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)
	}
faiface's avatar
faiface committed

	tri := td.tris[target]
	if tri == nil {
		tri = target.MakeTriangles(td.Triangles)
		td.tris[target] = tri
	}
	tri.Draw()
faiface's avatar
faiface committed
}

// 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)
faiface's avatar
faiface committed
}