mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-11 19:48:54 +01:00
graphics: Add DrawImageOptions.SourceRect
This commit is contained in:
parent
8614599c5c
commit
de7215f3fc
@ -76,25 +76,6 @@ func (s *Sprites) Update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Sprites) Len() int {
|
|
||||||
return s.num
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sprites) Dst(i int) (x0, y0, x1, y1 int) {
|
|
||||||
if s.num <= i {
|
|
||||||
return 0, 0, 0, 0
|
|
||||||
}
|
|
||||||
ss := s.sprites[i]
|
|
||||||
return ss.x, ss.y, ss.x + ebitenImageWidth, ss.y + ebitenImageHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sprites) Src(i int) (x0, y0, x1, y1 int) {
|
|
||||||
if s.num <= i {
|
|
||||||
return 0, 0, 0, 0
|
|
||||||
}
|
|
||||||
return 0, 0, ebitenImageWidth, ebitenImageHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MinSprites = 0
|
MinSprites = 0
|
||||||
MaxSprites = 50000
|
MaxSprites = 50000
|
||||||
@ -102,6 +83,13 @@ const (
|
|||||||
|
|
||||||
var sprites = &Sprites{make([]*Sprite, MaxSprites), 500}
|
var sprites = &Sprites{make([]*Sprite, MaxSprites), 500}
|
||||||
|
|
||||||
|
var op *ebiten.DrawImageOptions
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
op = &ebiten.DrawImageOptions{}
|
||||||
|
op.ColorM.Scale(1.0, 1.0, 1.0, 0.5)
|
||||||
|
}
|
||||||
|
|
||||||
func update(screen *ebiten.Image) error {
|
func update(screen *ebiten.Image) error {
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyLeft) {
|
if ebiten.IsKeyPressed(ebiten.KeyLeft) {
|
||||||
sprites.num -= 20
|
sprites.num -= 20
|
||||||
@ -120,15 +108,18 @@ func update(screen *ebiten.Image) error {
|
|||||||
if ebiten.IsRunningSlowly() {
|
if ebiten.IsRunningSlowly() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
op := &ebiten.DrawImageOptions{
|
for i := 0; i < sprites.num; i++ {
|
||||||
ImageParts: sprites,
|
s := sprites.sprites[i]
|
||||||
|
op.GeoM = ebiten.GeoM{}
|
||||||
|
op.GeoM.Translate(float64(s.x), float64(s.y))
|
||||||
|
screen.DrawImage(ebitenImage, op)
|
||||||
}
|
}
|
||||||
op.ColorM.Scale(1.0, 1.0, 1.0, 0.5)
|
|
||||||
screen.DrawImage(ebitenImage, op)
|
|
||||||
msg := fmt.Sprintf(`FPS: %0.2f
|
msg := fmt.Sprintf(`FPS: %0.2f
|
||||||
Num of sprites: %d
|
Num of sprites: %d
|
||||||
Press <- or -> to change the number of sprites`, ebiten.CurrentFPS(), sprites.Len())
|
Press <- or -> to change the number of sprites`, ebiten.CurrentFPS(), sprites.num)
|
||||||
ebitenutil.DebugPrint(screen, msg)
|
if err := ebitenutil.DebugPrint(screen, msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
image.go
61
image.go
@ -79,8 +79,7 @@ func (i *Image) Fill(clr color.Color) error {
|
|||||||
// After determining parts to draw, this applies the geometry matrix and the color matrix.
|
// After determining parts to draw, this applies the geometry matrix and the color matrix.
|
||||||
//
|
//
|
||||||
// Here are the default values:
|
// Here are the default values:
|
||||||
// ImageParts: (0, 0) - (source width, source height) to (0, 0) - (source width, source height)
|
// SourceRect: nil. When SourceRect is nil, the whole source image is used.
|
||||||
// (i.e. the whole source image)
|
|
||||||
// GeoM: Identity matrix
|
// GeoM: Identity matrix
|
||||||
// ColorM: Identity matrix (that changes no colors)
|
// ColorM: Identity matrix (that changes no colors)
|
||||||
// CompositeMode: CompositeModeSourceOver (regular alpha blending)
|
// CompositeMode: CompositeModeSourceOver (regular alpha blending)
|
||||||
@ -94,7 +93,7 @@ func (i *Image) Fill(clr color.Color) error {
|
|||||||
// When image is as same as i, DrawImage panics.
|
// When image is as same as i, DrawImage panics.
|
||||||
//
|
//
|
||||||
// DrawImage always returns nil as of 1.5.0-alpha.
|
// DrawImage always returns nil as of 1.5.0-alpha.
|
||||||
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) error {
|
func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error {
|
||||||
if i.restorable == nil {
|
if i.restorable == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -104,26 +103,45 @@ func (i *Image) DrawImage(image *Image, options *DrawImageOptions) error {
|
|||||||
options = &DrawImageOptions{}
|
options = &DrawImageOptions{}
|
||||||
}
|
}
|
||||||
parts := options.ImageParts
|
parts := options.ImageParts
|
||||||
if parts == nil {
|
// Parts is deprecated. This implementations is for backward compatibility.
|
||||||
// Check options.Parts for backward-compatibility.
|
if parts == nil && options.Parts != nil {
|
||||||
dparts := options.Parts
|
parts = imageParts(options.Parts)
|
||||||
if dparts != nil {
|
|
||||||
parts = imageParts(dparts)
|
|
||||||
} else {
|
|
||||||
w, h := image.restorable.Size()
|
|
||||||
parts = &wholeImage{w, h}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
w, h := image.restorable.Size()
|
// ImageParts is deprecated. This implementations is for backward compatibility.
|
||||||
vs := vertices(parts, w, h, &options.GeoM.impl)
|
if parts != nil {
|
||||||
if len(vs) == 0 {
|
l := parts.Len()
|
||||||
|
for idx := 0; idx < l; idx++ {
|
||||||
|
sx0, sy0, sx1, sy1 := parts.Src(idx)
|
||||||
|
dx0, dy0, dx1, dy1 := parts.Dst(idx)
|
||||||
|
op := &DrawImageOptions{
|
||||||
|
ColorM: options.ColorM,
|
||||||
|
CompositeMode: options.CompositeMode,
|
||||||
|
}
|
||||||
|
r := image.Rect(sx0, sy0, sx1, sy1)
|
||||||
|
op.SourceRect = &r
|
||||||
|
op.GeoM.Scale(
|
||||||
|
float64(dx1-dx0)/float64(sx1-sx0),
|
||||||
|
float64(dy1-dy0)/float64(sy1-sy0))
|
||||||
|
op.GeoM.Translate(float64(dx0), float64(dy0))
|
||||||
|
op.GeoM.Concat(options.GeoM)
|
||||||
|
i.DrawImage(img, op)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if i == image {
|
w, h := img.restorable.Size()
|
||||||
panic("ebiten: Image.DrawImage: image must be different from the receiver")
|
sx0, sy0, sx1, sy1 := 0, 0, w, h
|
||||||
|
if r := options.SourceRect; r != nil {
|
||||||
|
sx0 = r.Min.X
|
||||||
|
sy0 = r.Min.Y
|
||||||
|
sx1 = r.Max.X
|
||||||
|
sy1 = r.Max.Y
|
||||||
|
}
|
||||||
|
vs := vertices(sx0, sy0, sx1, sy1, w, h, &options.GeoM.impl)
|
||||||
|
if i == img {
|
||||||
|
panic("ebiten: Image.DrawImage: img must be different from the receiver")
|
||||||
}
|
}
|
||||||
mode := opengl.CompositeMode(options.CompositeMode)
|
mode := opengl.CompositeMode(options.CompositeMode)
|
||||||
i.restorable.DrawImage(image.restorable, vs, &options.ColorM.impl, mode)
|
i.restorable.DrawImage(img.restorable, vs, &options.ColorM.impl, mode)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,12 +221,15 @@ func (i *Image) ReplacePixels(p []uint8) error {
|
|||||||
|
|
||||||
// A DrawImageOptions represents options to render an image on an image.
|
// A DrawImageOptions represents options to render an image on an image.
|
||||||
type DrawImageOptions struct {
|
type DrawImageOptions struct {
|
||||||
ImageParts ImageParts
|
SourceRect *image.Rectangle
|
||||||
GeoM GeoM
|
GeoM GeoM
|
||||||
ColorM ColorM
|
ColorM ColorM
|
||||||
CompositeMode CompositeMode
|
CompositeMode CompositeMode
|
||||||
|
|
||||||
// Deprecated (as of 1.1.0-alpha): Use ImageParts instead.
|
// Deprecated (as of 1.5.0-alpha): Use Part instead.
|
||||||
|
ImageParts ImageParts
|
||||||
|
|
||||||
|
// Deprecated (as of 1.1.0-alpha): Use Part instead.
|
||||||
Parts []ImagePart
|
Parts []ImagePart
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
)
|
)
|
||||||
|
|
||||||
// An ImagePart is deprecated (as of 1.1.0-alpha): Use ImageParts instead.
|
// An ImagePart is deprecated (as of 1.1.0-alpha): Use SourceRect instead.
|
||||||
type ImagePart struct {
|
type ImagePart struct {
|
||||||
Dst image.Rectangle
|
Dst image.Rectangle
|
||||||
Src image.Rectangle
|
Src image.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
// An ImageParts represents the parts of the destination image and the parts of the source image.
|
// An ImageParts is deprecated (as of 1.5.0-alpha): Use SourceRect instead.
|
||||||
type ImageParts interface {
|
type ImageParts interface {
|
||||||
Len() int
|
Len() int
|
||||||
Dst(i int) (x0, y0, x1, y1 int)
|
Dst(i int) (x0, y0, x1, y1 int)
|
||||||
@ -47,20 +47,3 @@ func (p imageParts) Src(i int) (x0, y0, x1, y1 int) {
|
|||||||
src := &p[i].Src
|
src := &p[i].Src
|
||||||
return src.Min.X, src.Min.Y, src.Max.X, src.Max.Y
|
return src.Min.X, src.Min.Y, src.Max.X, src.Max.Y
|
||||||
}
|
}
|
||||||
|
|
||||||
type wholeImage struct {
|
|
||||||
width int
|
|
||||||
height int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *wholeImage) Len() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *wholeImage) Dst(i int) (x0, y0, x1, y1 int) {
|
|
||||||
return 0, 0, w.width, w.height
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *wholeImage) Src(i int) (x0, y0, x1, y1 int) {
|
|
||||||
return 0, 0, w.width, w.height
|
|
||||||
}
|
|
||||||
|
110
vertices.go
110
vertices.go
@ -27,10 +27,12 @@ const texelAdjustment = 256
|
|||||||
|
|
||||||
var quadFloat32Num = graphics.QuadVertexSizeInBytes() / 4
|
var quadFloat32Num = graphics.QuadVertexSizeInBytes() / 4
|
||||||
|
|
||||||
func vertices(parts ImageParts, width, height int, geo *affine.GeoM) []float32 {
|
func vertices(sx0, sy0, sx1, sy1 int, width, height int, geo *affine.GeoM) []float32 {
|
||||||
|
if sx0 == sx1 || sy0 == sy1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// TODO: This function should be in graphics package?
|
// TODO: This function should be in graphics package?
|
||||||
l := parts.Len()
|
vs := make([]float32, quadFloat32Num)
|
||||||
vs := make([]float32, l*quadFloat32Num)
|
|
||||||
a, b, c, d, tx, ty := geo.Elements()
|
a, b, c, d, tx, ty := geo.Elements()
|
||||||
g0 := float32(a)
|
g0 := float32(a)
|
||||||
g1 := float32(b)
|
g1 := float32(b)
|
||||||
@ -48,66 +50,54 @@ func vertices(parts ImageParts, width, height int, geo *affine.GeoM) []float32 {
|
|||||||
}
|
}
|
||||||
wf := float32(w)
|
wf := float32(w)
|
||||||
hf := float32(h)
|
hf := float32(h)
|
||||||
n := 0
|
x0, y0, x1, y1 := float32(0), float32(0), float32(sx1-sx0), float32(sy1-sy0)
|
||||||
for i := 0; i < l; i++ {
|
u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf
|
||||||
dx0, dy0, dx1, dy1 := parts.Dst(i)
|
// Adjust texels to fix a problem that outside texels are used (#317).
|
||||||
if dx0 == dx1 || dy0 == dy1 {
|
u1 -= 1.0 / wf / texelAdjustment
|
||||||
continue
|
v1 -= 1.0 / hf / texelAdjustment
|
||||||
}
|
vs[0] = x0
|
||||||
x0, y0, x1, y1 := float32(dx0), float32(dy0), float32(dx1), float32(dy1)
|
vs[1] = y0
|
||||||
sx0, sy0, sx1, sy1 := parts.Src(i)
|
vs[2] = u0
|
||||||
if sx0 == sx1 || sy0 == sy1 {
|
vs[3] = v0
|
||||||
continue
|
vs[4] = g0
|
||||||
}
|
vs[5] = g1
|
||||||
u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf
|
vs[6] = g2
|
||||||
// Adjust texels to fix a problem that outside texels are used (#317).
|
vs[7] = g3
|
||||||
u1 -= 1.0 / wf / texelAdjustment
|
vs[8] = g4
|
||||||
v1 -= 1.0 / hf / texelAdjustment
|
vs[9] = g5
|
||||||
vs[n] = x0
|
|
||||||
vs[n+1] = y0
|
|
||||||
vs[n+2] = u0
|
|
||||||
vs[n+3] = v0
|
|
||||||
vs[n+4] = g0
|
|
||||||
vs[n+5] = g1
|
|
||||||
vs[n+6] = g2
|
|
||||||
vs[n+7] = g3
|
|
||||||
vs[n+8] = g4
|
|
||||||
vs[n+9] = g5
|
|
||||||
|
|
||||||
vs[n+10] = x1
|
vs[10] = x1
|
||||||
vs[n+11] = y0
|
vs[11] = y0
|
||||||
vs[n+12] = u1
|
vs[12] = u1
|
||||||
vs[n+13] = v0
|
vs[13] = v0
|
||||||
vs[n+14] = g0
|
vs[14] = g0
|
||||||
vs[n+15] = g1
|
vs[15] = g1
|
||||||
vs[n+16] = g2
|
vs[16] = g2
|
||||||
vs[n+17] = g3
|
vs[17] = g3
|
||||||
vs[n+18] = g4
|
vs[18] = g4
|
||||||
vs[n+19] = g5
|
vs[19] = g5
|
||||||
|
|
||||||
vs[n+20] = x0
|
vs[20] = x0
|
||||||
vs[n+21] = y1
|
vs[21] = y1
|
||||||
vs[n+22] = u0
|
vs[22] = u0
|
||||||
vs[n+23] = v1
|
vs[23] = v1
|
||||||
vs[n+24] = g0
|
vs[24] = g0
|
||||||
vs[n+25] = g1
|
vs[25] = g1
|
||||||
vs[n+26] = g2
|
vs[26] = g2
|
||||||
vs[n+27] = g3
|
vs[27] = g3
|
||||||
vs[n+28] = g4
|
vs[28] = g4
|
||||||
vs[n+29] = g5
|
vs[29] = g5
|
||||||
|
|
||||||
vs[n+30] = x1
|
vs[30] = x1
|
||||||
vs[n+31] = y1
|
vs[31] = y1
|
||||||
vs[n+32] = u1
|
vs[32] = u1
|
||||||
vs[n+33] = v1
|
vs[33] = v1
|
||||||
vs[n+34] = g0
|
vs[34] = g0
|
||||||
vs[n+35] = g1
|
vs[35] = g1
|
||||||
vs[n+36] = g2
|
vs[36] = g2
|
||||||
vs[n+37] = g3
|
vs[37] = g3
|
||||||
vs[n+38] = g4
|
vs[38] = g4
|
||||||
vs[n+39] = g5
|
vs[39] = g5
|
||||||
|
|
||||||
n += quadFloat32Num
|
|
||||||
}
|
|
||||||
return vs
|
return vs
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user