mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +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 (
|
||||
MinSprites = 0
|
||||
MaxSprites = 50000
|
||||
@ -102,6 +83,13 @@ const (
|
||||
|
||||
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 {
|
||||
if ebiten.IsKeyPressed(ebiten.KeyLeft) {
|
||||
sprites.num -= 20
|
||||
@ -120,15 +108,18 @@ func update(screen *ebiten.Image) error {
|
||||
if ebiten.IsRunningSlowly() {
|
||||
return nil
|
||||
}
|
||||
op := &ebiten.DrawImageOptions{
|
||||
ImageParts: sprites,
|
||||
for i := 0; i < sprites.num; i++ {
|
||||
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
|
||||
Num of sprites: %d
|
||||
Press <- or -> to change the number of sprites`, ebiten.CurrentFPS(), sprites.Len())
|
||||
ebitenutil.DebugPrint(screen, msg)
|
||||
Press <- or -> to change the number of sprites`, ebiten.CurrentFPS(), sprites.num)
|
||||
if err := ebitenutil.DebugPrint(screen, msg); err != nil {
|
||||
return err
|
||||
}
|
||||
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.
|
||||
//
|
||||
// Here are the default values:
|
||||
// ImageParts: (0, 0) - (source width, source height) to (0, 0) - (source width, source height)
|
||||
// (i.e. the whole source image)
|
||||
// SourceRect: nil. When SourceRect is nil, the whole source image is used.
|
||||
// GeoM: Identity matrix
|
||||
// ColorM: Identity matrix (that changes no colors)
|
||||
// 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.
|
||||
//
|
||||
// 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 {
|
||||
return nil
|
||||
}
|
||||
@ -104,26 +103,45 @@ func (i *Image) DrawImage(image *Image, options *DrawImageOptions) error {
|
||||
options = &DrawImageOptions{}
|
||||
}
|
||||
parts := options.ImageParts
|
||||
if parts == nil {
|
||||
// Check options.Parts for backward-compatibility.
|
||||
dparts := options.Parts
|
||||
if dparts != nil {
|
||||
parts = imageParts(dparts)
|
||||
} else {
|
||||
w, h := image.restorable.Size()
|
||||
parts = &wholeImage{w, h}
|
||||
}
|
||||
// Parts is deprecated. This implementations is for backward compatibility.
|
||||
if parts == nil && options.Parts != nil {
|
||||
parts = imageParts(options.Parts)
|
||||
}
|
||||
w, h := image.restorable.Size()
|
||||
vs := vertices(parts, w, h, &options.GeoM.impl)
|
||||
if len(vs) == 0 {
|
||||
// ImageParts is deprecated. This implementations is for backward compatibility.
|
||||
if parts != nil {
|
||||
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
|
||||
}
|
||||
if i == image {
|
||||
panic("ebiten: Image.DrawImage: image must be different from the receiver")
|
||||
w, h := img.restorable.Size()
|
||||
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)
|
||||
i.restorable.DrawImage(image.restorable, vs, &options.ColorM.impl, mode)
|
||||
i.restorable.DrawImage(img.restorable, vs, &options.ColorM.impl, mode)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -203,12 +221,15 @@ func (i *Image) ReplacePixels(p []uint8) error {
|
||||
|
||||
// A DrawImageOptions represents options to render an image on an image.
|
||||
type DrawImageOptions struct {
|
||||
ImageParts ImageParts
|
||||
SourceRect *image.Rectangle
|
||||
GeoM GeoM
|
||||
ColorM ColorM
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -18,13 +18,13 @@ import (
|
||||
"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 {
|
||||
Dst 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 {
|
||||
Len() 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
|
||||
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
|
||||
|
||||
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?
|
||||
l := parts.Len()
|
||||
vs := make([]float32, l*quadFloat32Num)
|
||||
vs := make([]float32, quadFloat32Num)
|
||||
a, b, c, d, tx, ty := geo.Elements()
|
||||
g0 := float32(a)
|
||||
g1 := float32(b)
|
||||
@ -48,66 +50,54 @@ func vertices(parts ImageParts, width, height int, geo *affine.GeoM) []float32 {
|
||||
}
|
||||
wf := float32(w)
|
||||
hf := float32(h)
|
||||
n := 0
|
||||
for i := 0; i < l; i++ {
|
||||
dx0, dy0, dx1, dy1 := parts.Dst(i)
|
||||
if dx0 == dx1 || dy0 == dy1 {
|
||||
continue
|
||||
}
|
||||
x0, y0, x1, y1 := float32(dx0), float32(dy0), float32(dx1), float32(dy1)
|
||||
sx0, sy0, sx1, sy1 := parts.Src(i)
|
||||
if sx0 == sx1 || sy0 == sy1 {
|
||||
continue
|
||||
}
|
||||
u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf
|
||||
// Adjust texels to fix a problem that outside texels are used (#317).
|
||||
u1 -= 1.0 / wf / texelAdjustment
|
||||
v1 -= 1.0 / hf / texelAdjustment
|
||||
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
|
||||
x0, y0, x1, y1 := float32(0), float32(0), float32(sx1-sx0), float32(sy1-sy0)
|
||||
u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf
|
||||
// Adjust texels to fix a problem that outside texels are used (#317).
|
||||
u1 -= 1.0 / wf / texelAdjustment
|
||||
v1 -= 1.0 / hf / texelAdjustment
|
||||
vs[0] = x0
|
||||
vs[1] = y0
|
||||
vs[2] = u0
|
||||
vs[3] = v0
|
||||
vs[4] = g0
|
||||
vs[5] = g1
|
||||
vs[6] = g2
|
||||
vs[7] = g3
|
||||
vs[8] = g4
|
||||
vs[9] = g5
|
||||
|
||||
vs[n+10] = x1
|
||||
vs[n+11] = y0
|
||||
vs[n+12] = u1
|
||||
vs[n+13] = v0
|
||||
vs[n+14] = g0
|
||||
vs[n+15] = g1
|
||||
vs[n+16] = g2
|
||||
vs[n+17] = g3
|
||||
vs[n+18] = g4
|
||||
vs[n+19] = g5
|
||||
vs[10] = x1
|
||||
vs[11] = y0
|
||||
vs[12] = u1
|
||||
vs[13] = v0
|
||||
vs[14] = g0
|
||||
vs[15] = g1
|
||||
vs[16] = g2
|
||||
vs[17] = g3
|
||||
vs[18] = g4
|
||||
vs[19] = g5
|
||||
|
||||
vs[n+20] = x0
|
||||
vs[n+21] = y1
|
||||
vs[n+22] = u0
|
||||
vs[n+23] = v1
|
||||
vs[n+24] = g0
|
||||
vs[n+25] = g1
|
||||
vs[n+26] = g2
|
||||
vs[n+27] = g3
|
||||
vs[n+28] = g4
|
||||
vs[n+29] = g5
|
||||
vs[20] = x0
|
||||
vs[21] = y1
|
||||
vs[22] = u0
|
||||
vs[23] = v1
|
||||
vs[24] = g0
|
||||
vs[25] = g1
|
||||
vs[26] = g2
|
||||
vs[27] = g3
|
||||
vs[28] = g4
|
||||
vs[29] = g5
|
||||
|
||||
vs[n+30] = x1
|
||||
vs[n+31] = y1
|
||||
vs[n+32] = u1
|
||||
vs[n+33] = v1
|
||||
vs[n+34] = g0
|
||||
vs[n+35] = g1
|
||||
vs[n+36] = g2
|
||||
vs[n+37] = g3
|
||||
vs[n+38] = g4
|
||||
vs[n+39] = g5
|
||||
vs[30] = x1
|
||||
vs[31] = y1
|
||||
vs[32] = u1
|
||||
vs[33] = v1
|
||||
vs[34] = g0
|
||||
vs[35] = g1
|
||||
vs[36] = g2
|
||||
vs[37] = g3
|
||||
vs[38] = g4
|
||||
vs[39] = g5
|
||||
|
||||
n += quadFloat32Num
|
||||
}
|
||||
return vs
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user