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.
|
||||
type Sprite struct {
|
||||
data TrianglesData
|
||||
td TrianglesDrawer
|
||||
pic *GLPicture
|
||||
d Drawer
|
||||
}
|
||||
|
||||
// NewSprite creates a Sprite with the supplied Picture. The dimensions of the returned Sprite match
|
||||
// the dimensions of the Picture.
|
||||
func NewSprite(pic *GLPicture) *Sprite {
|
||||
func NewSprite(pic Picture) *Sprite {
|
||||
s := &Sprite{
|
||||
data: TrianglesData{
|
||||
{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)},
|
||||
},
|
||||
}
|
||||
s.td = TrianglesDrawer{Triangles: &s.data}
|
||||
s.d = Drawer{Triangles: &s.data}
|
||||
s.SetPicture(pic)
|
||||
return s
|
||||
}
|
||||
|
||||
// SetPicture changes the Picture of the Sprite and resizes it accordingly.
|
||||
func (s *Sprite) SetPicture(pic *GLPicture) {
|
||||
oldPic := s.pic
|
||||
s.pic = pic
|
||||
func (s *Sprite) SetPicture(pic Picture) {
|
||||
oldPic := s.d.Picture
|
||||
s.d.Picture = pic
|
||||
if oldPic != nil && oldPic.Bounds().Size == pic.Bounds().Size {
|
||||
return
|
||||
}
|
||||
|
@ -152,23 +151,23 @@ func (s *Sprite) SetPicture(pic *GLPicture) {
|
|||
s.data[3].Position = V(0, 0)
|
||||
s.data[4].Position = V(w, h)
|
||||
s.data[5].Position = V(0, h)
|
||||
s.td.Dirty()
|
||||
s.d.Dirty()
|
||||
}
|
||||
|
||||
// Picture returns the current Picture of the Sprite.
|
||||
func (s *Sprite) Picture() *GLPicture {
|
||||
return s.pic
|
||||
func (s *Sprite) Picture() Picture {
|
||||
return s.d.Picture
|
||||
}
|
||||
|
||||
// Draw draws the Sprite onto the provided 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.
|
||||
type Polygon struct {
|
||||
data TrianglesData
|
||||
td TrianglesDrawer
|
||||
d Drawer
|
||||
col NRGBA
|
||||
}
|
||||
|
||||
|
@ -178,7 +177,7 @@ func NewPolygon(c color.Color, points ...Vec) *Polygon {
|
|||
p := &Polygon{
|
||||
data: TrianglesData{},
|
||||
}
|
||||
p.td = TrianglesDrawer{Triangles: &p.data}
|
||||
p.d = Drawer{Triangles: &p.data}
|
||||
p.SetColor(c)
|
||||
p.SetPoints(points...)
|
||||
return p
|
||||
|
@ -193,7 +192,7 @@ func (p *Polygon) SetColor(c color.Color) {
|
|||
for i := range p.data {
|
||||
p.data[i].Color = p.col
|
||||
}
|
||||
p.td.Dirty()
|
||||
p.d.Dirty()
|
||||
}
|
||||
|
||||
// Color returns the current color of the Polygon.
|
||||
|
@ -217,7 +216,7 @@ func (p *Polygon) SetPoints(points ...Vec) {
|
|||
for i := range p.data {
|
||||
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.
|
||||
|
@ -231,5 +230,5 @@ func (p *Polygon) Points() []Vec {
|
|||
|
||||
// Draw draws the Polygon onto the 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.
|
||||
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.
|
||||
SetMaskColor(color.Color)
|
||||
SetColorMask(color.Color)
|
||||
}
|
||||
|
||||
// Triangles represents a list of vertices, where each three vertices form a triangle. (First,
|
||||
|
@ -69,14 +69,8 @@ type Triangles interface {
|
|||
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
|
||||
// onto that Target.
|
||||
// onto that (no other) Target.
|
||||
type TargetTriangles interface {
|
||||
Triangles
|
||||
|
||||
|
@ -84,13 +78,6 @@ type TargetTriangles interface {
|
|||
Draw()
|
||||
}
|
||||
|
||||
//TODO: doc
|
||||
type TargetPicture interface {
|
||||
Picture
|
||||
|
||||
Draw(TargetTriangles)
|
||||
}
|
||||
|
||||
// TrianglesPosition specifies Triangles with Position property.
|
||||
type TrianglesPosition interface {
|
||||
Triangles
|
||||
|
@ -110,3 +97,32 @@ type TrianglesPicture interface {
|
|||
Triangles
|
||||
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
|
||||
}
|
||||
|
||||
func pictureBounds(p *GLPicture, v Vec) Vec {
|
||||
w, h := float64(p.Texture().Width()), float64(p.Texture().Height())
|
||||
func pictureBounds(p Picture, v Vec) Vec {
|
||||
w, h := p.Bounds().Size.XY()
|
||||
a := p.Bounds().Pos
|
||||
b := p.Bounds().Pos + p.Bounds().Size
|
||||
u := lerp2d(v, a, b)
|
||||
|
|
Loading…
Reference in New Issue