add Picture interface
This commit is contained in:
parent
c1843b8608
commit
bffb3598c7
31
graphics.go
31
graphics.go
|
@ -116,13 +116,12 @@ func (td *TrianglesData) Picture(i int) Vec {
|
||||||
// the Sprite, use Target's SetTransform method.
|
// the Sprite, use Target's SetTransform method.
|
||||||
type Sprite struct {
|
type Sprite struct {
|
||||||
data TrianglesData
|
data TrianglesData
|
||||||
td TrianglesDrawer
|
d Drawer
|
||||||
pic *GLPicture
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSprite creates a Sprite with the supplied Picture. The dimensions of the returned Sprite match
|
// NewSprite creates a Sprite with the supplied Picture. The dimensions of the returned Sprite match
|
||||||
// the dimensions of the Picture.
|
// the dimensions of the Picture.
|
||||||
func NewSprite(pic *GLPicture) *Sprite {
|
func NewSprite(pic Picture) *Sprite {
|
||||||
s := &Sprite{
|
s := &Sprite{
|
||||||
data: TrianglesData{
|
data: TrianglesData{
|
||||||
{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(0, 0)},
|
||||||
|
@ -133,15 +132,15 @@ func NewSprite(pic *GLPicture) *Sprite {
|
||||||
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(0, 1)},
|
{Position: V(0, 0), Color: NRGBA{1, 1, 1, 1}, Picture: V(0, 1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s.td = TrianglesDrawer{Triangles: &s.data}
|
s.d = Drawer{Triangles: &s.data}
|
||||||
s.SetPicture(pic)
|
s.SetPicture(pic)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPicture changes the Picture of the Sprite and resizes it accordingly.
|
// SetPicture changes the Picture of the Sprite and resizes it accordingly.
|
||||||
func (s *Sprite) SetPicture(pic *GLPicture) {
|
func (s *Sprite) SetPicture(pic Picture) {
|
||||||
oldPic := s.pic
|
oldPic := s.d.Picture
|
||||||
s.pic = pic
|
s.d.Picture = pic
|
||||||
if oldPic != nil && oldPic.Bounds().Size == pic.Bounds().Size {
|
if oldPic != nil && oldPic.Bounds().Size == pic.Bounds().Size {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -152,23 +151,23 @@ func (s *Sprite) SetPicture(pic *GLPicture) {
|
||||||
s.data[3].Position = V(0, 0)
|
s.data[3].Position = V(0, 0)
|
||||||
s.data[4].Position = V(w, h)
|
s.data[4].Position = V(w, h)
|
||||||
s.data[5].Position = V(0, h)
|
s.data[5].Position = V(0, h)
|
||||||
s.td.Dirty()
|
s.d.Dirty()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Picture returns the current Picture of the Sprite.
|
// Picture returns the current Picture of the Sprite.
|
||||||
func (s *Sprite) Picture() *GLPicture {
|
func (s *Sprite) Picture() Picture {
|
||||||
return s.pic
|
return s.d.Picture
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) {
|
||||||
s.td.Draw(t)
|
s.d.Draw(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Polygon is a convex polygon shape filled with a single color.
|
// Polygon is a convex polygon shape filled with a single color.
|
||||||
type Polygon struct {
|
type Polygon struct {
|
||||||
data TrianglesData
|
data TrianglesData
|
||||||
td TrianglesDrawer
|
d Drawer
|
||||||
col NRGBA
|
col NRGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +177,7 @@ func NewPolygon(c color.Color, points ...Vec) *Polygon {
|
||||||
p := &Polygon{
|
p := &Polygon{
|
||||||
data: TrianglesData{},
|
data: TrianglesData{},
|
||||||
}
|
}
|
||||||
p.td = TrianglesDrawer{Triangles: &p.data}
|
p.d = Drawer{Triangles: &p.data}
|
||||||
p.SetColor(c)
|
p.SetColor(c)
|
||||||
p.SetPoints(points...)
|
p.SetPoints(points...)
|
||||||
return p
|
return p
|
||||||
|
@ -193,7 +192,7 @@ func (p *Polygon) SetColor(c color.Color) {
|
||||||
for i := range p.data {
|
for i := range p.data {
|
||||||
p.data[i].Color = p.col
|
p.data[i].Color = p.col
|
||||||
}
|
}
|
||||||
p.td.Dirty()
|
p.d.Dirty()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Color returns the current color of the Polygon.
|
// Color returns the current color of the Polygon.
|
||||||
|
@ -217,7 +216,7 @@ func (p *Polygon) SetPoints(points ...Vec) {
|
||||||
for i := range p.data {
|
for i := range p.data {
|
||||||
p.data[i].Color = p.col
|
p.data[i].Color = p.col
|
||||||
}
|
}
|
||||||
p.td.Dirty()
|
p.d.Dirty()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Points returns a slice of points of the Polygon in the order they where supplied.
|
// Points returns a slice of points of the Polygon in the order they where supplied.
|
||||||
|
@ -231,5 +230,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) {
|
||||||
p.td.Draw(t)
|
p.d.Draw(t)
|
||||||
}
|
}
|
||||||
|
|
48
interface.go
48
interface.go
|
@ -31,9 +31,9 @@ type BasicTarget interface {
|
||||||
// Triangles.
|
// Triangles.
|
||||||
SetTransform(...Transform)
|
SetTransform(...Transform)
|
||||||
|
|
||||||
// SetMaskColor sets a color that will be multiplied with the TrianglesColor property of all
|
// SetMColorMask sets a color that will be multiplied with the TrianglesColor property of all
|
||||||
// Triangles.
|
// Triangles.
|
||||||
SetMaskColor(color.Color)
|
SetColorMask(color.Color)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Triangles represents a list of vertices, where each three vertices form a triangle. (First,
|
// Triangles represents a list of vertices, where each three vertices form a triangle. (First,
|
||||||
|
@ -69,14 +69,8 @@ type Triangles interface {
|
||||||
Copy() Triangles
|
Copy() Triangles
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: doc
|
|
||||||
type Picture interface {
|
|
||||||
Bounds() Rect
|
|
||||||
Slice(Rect) Picture
|
|
||||||
}
|
|
||||||
|
|
||||||
// TargetTriangles are Triangles generated by a Target with MakeTriangles method. They can be drawn
|
// TargetTriangles are Triangles generated by a Target with MakeTriangles method. They can be drawn
|
||||||
// onto that Target.
|
// onto that (no other) Target.
|
||||||
type TargetTriangles interface {
|
type TargetTriangles interface {
|
||||||
Triangles
|
Triangles
|
||||||
|
|
||||||
|
@ -84,13 +78,6 @@ type TargetTriangles interface {
|
||||||
Draw()
|
Draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: doc
|
|
||||||
type TargetPicture interface {
|
|
||||||
Picture
|
|
||||||
|
|
||||||
Draw(TargetTriangles)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrianglesPosition specifies Triangles with Position property.
|
// TrianglesPosition specifies Triangles with Position property.
|
||||||
type TrianglesPosition interface {
|
type TrianglesPosition interface {
|
||||||
Triangles
|
Triangles
|
||||||
|
@ -110,3 +97,32 @@ type TrianglesPicture interface {
|
||||||
Triangles
|
Triangles
|
||||||
Picture(i int) Vec
|
Picture(i int) Vec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Picture represents a rectangular area of raster data, such as a color. It has Bounds which
|
||||||
|
// specify the rectangle where data is located.
|
||||||
|
type Picture interface {
|
||||||
|
// Bounds returns the rectangle of the Picture. All data is located witih this rectangle.
|
||||||
|
// Querying properties outside the rectangle should return default value of that property.
|
||||||
|
Bounds() Rect
|
||||||
|
|
||||||
|
// Slice returns a sub-Picture with specified Bounds.
|
||||||
|
Slice(Rect) Picture
|
||||||
|
}
|
||||||
|
|
||||||
|
// TargetPicture is a Picture generated by a Target using MakePicture method. This Picture can be drawn onto
|
||||||
|
// that (no other) Target together with a TargetTriangles generated by the same Target.
|
||||||
|
//
|
||||||
|
// The TargetTriangles specify where, shape and how the Picture should be drawn.
|
||||||
|
type TargetPicture interface {
|
||||||
|
Picture
|
||||||
|
|
||||||
|
Draw(TargetTriangles)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PictureColor specifies Picture with Color property, so that every position inside the Picture's
|
||||||
|
// Bounds has a color.
|
||||||
|
//
|
||||||
|
// Positions outside the Picture's Bounds must return opaque white (NRGBA{R: 1, G: 1, B:1, A: 1}).
|
||||||
|
type PictureColor interface {
|
||||||
|
Color(at Vec) NRGBA
|
||||||
|
}
|
||||||
|
|
113
picture.go
113
picture.go
|
@ -1,113 +0,0 @@
|
||||||
package pixel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
"image/draw"
|
|
||||||
|
|
||||||
"github.com/faiface/glhf"
|
|
||||||
"github.com/faiface/mainthread"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GLPicture is a raster picture. It is usually used with sprites.
|
|
||||||
//
|
|
||||||
// A GLPicture is created from an image.Image, that can be either loaded from a file, or
|
|
||||||
// generated. After the creation, Pictures can be sliced (slicing creates a "sub-GLPicture"
|
|
||||||
// from a GLPicture) into smaller Pictures.
|
|
||||||
type GLPicture struct {
|
|
||||||
tex *glhf.Texture
|
|
||||||
bounds Rect
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPicture creates a new Picture from an image.Image.
|
|
||||||
func NewPicture(img image.Image, smooth bool) *GLPicture {
|
|
||||||
// convert the image to NRGBA format
|
|
||||||
bounds := img.Bounds()
|
|
||||||
nrgba := image.NewNRGBA(image.Rect(0, 0, bounds.Dx(), bounds.Dy()))
|
|
||||||
draw.Draw(nrgba, nrgba.Bounds(), img, bounds.Min, draw.Src)
|
|
||||||
|
|
||||||
// flip the image vertically
|
|
||||||
tmp := make([]byte, nrgba.Stride)
|
|
||||||
for i, j := 0, bounds.Dy()-1; i < j; i, j = i+1, j-1 {
|
|
||||||
iSlice := nrgba.Pix[i*nrgba.Stride : (i+1)*nrgba.Stride]
|
|
||||||
jSlice := nrgba.Pix[j*nrgba.Stride : (j+1)*nrgba.Stride]
|
|
||||||
copy(tmp, iSlice)
|
|
||||||
copy(iSlice, jSlice)
|
|
||||||
copy(jSlice, tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
var tex *glhf.Texture
|
|
||||||
mainthread.Call(func() {
|
|
||||||
tex = glhf.NewTexture(
|
|
||||||
img.Bounds().Dx(),
|
|
||||||
img.Bounds().Dy(),
|
|
||||||
smooth,
|
|
||||||
nrgba.Pix,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
return PictureFromTexture(tex)
|
|
||||||
}
|
|
||||||
|
|
||||||
// PictureFromTexture returns a new Picture that spans the whole supplied Texture.
|
|
||||||
func PictureFromTexture(tex *glhf.Texture) *GLPicture {
|
|
||||||
return &GLPicture{
|
|
||||||
tex: tex,
|
|
||||||
bounds: R(0, 0, float64(tex.Width()), float64(tex.Height())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Image returns the content of the Picture as an image.NRGBA.
|
|
||||||
//
|
|
||||||
// Note, that this operation can be rather expensive.
|
|
||||||
func (p *GLPicture) Image() *image.NRGBA {
|
|
||||||
bounds := p.Bounds()
|
|
||||||
nrgba := image.NewNRGBA(image.Rect(0, 0, int(bounds.W()), int(bounds.H())))
|
|
||||||
|
|
||||||
mainthread.Call(func() {
|
|
||||||
p.tex.Begin()
|
|
||||||
nrgba.Pix = p.tex.Pixels(
|
|
||||||
int(bounds.X()),
|
|
||||||
int(bounds.Y()),
|
|
||||||
int(bounds.W()),
|
|
||||||
int(bounds.H()),
|
|
||||||
)
|
|
||||||
p.tex.End()
|
|
||||||
})
|
|
||||||
|
|
||||||
// flip the image vertically
|
|
||||||
tmp := make([]byte, nrgba.Stride)
|
|
||||||
for i, j := 0, nrgba.Bounds().Dy()-1; i < j; i, j = i+1, j-1 {
|
|
||||||
iSlice := nrgba.Pix[i*nrgba.Stride : (i+1)*nrgba.Stride]
|
|
||||||
jSlice := nrgba.Pix[j*nrgba.Stride : (j+1)*nrgba.Stride]
|
|
||||||
copy(tmp, iSlice)
|
|
||||||
copy(iSlice, jSlice)
|
|
||||||
copy(jSlice, tmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nrgba
|
|
||||||
}
|
|
||||||
|
|
||||||
// Texture returns a pointer to the underlying OpenGL texture of the Picture.
|
|
||||||
func (p *GLPicture) Texture() *glhf.Texture {
|
|
||||||
return p.tex
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slice returns a Picture within the supplied rectangle of the original picture. The original
|
|
||||||
// and the sliced Picture share the same texture.
|
|
||||||
//
|
|
||||||
// For example, suppose we have a 100x200 pixels Picture. If we slice it with rectangle (50,
|
|
||||||
// 100, 50, 100), we get the upper-right quadrant of the original Picture.
|
|
||||||
func (p *GLPicture) Slice(slice Rect) *GLPicture {
|
|
||||||
return &GLPicture{
|
|
||||||
tex: p.tex,
|
|
||||||
bounds: Rect{p.bounds.Pos + slice.Pos, slice.Size},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bounds returns the bounding rectangle of this Picture relative to the most original picture.
|
|
||||||
//
|
|
||||||
// If the original Picture was sliced with the return value of this method, this Picture would
|
|
||||||
// be obtained.
|
|
||||||
func (p *GLPicture) Bounds() Rect {
|
|
||||||
return p.bounds
|
|
||||||
}
|
|
4
util.go
4
util.go
|
@ -31,8 +31,8 @@ func transformToMat(t ...Transform) mgl32.Mat3 {
|
||||||
return mat
|
return mat
|
||||||
}
|
}
|
||||||
|
|
||||||
func pictureBounds(p *GLPicture, v Vec) Vec {
|
func pictureBounds(p Picture, v Vec) Vec {
|
||||||
w, h := float64(p.Texture().Width()), float64(p.Texture().Height())
|
w, h := p.Bounds().Size.XY()
|
||||||
a := p.Bounds().Pos
|
a := p.Bounds().Pos
|
||||||
b := p.Bounds().Pos + p.Bounds().Size
|
b := p.Bounds().Pos + p.Bounds().Size
|
||||||
u := lerp2d(v, a, b)
|
u := lerp2d(v, a, b)
|
||||||
|
|
Loading…
Reference in New Issue