diff --git a/allg5ui/renderer.go b/allg5ui/renderer.go index 7d77db1..3b9a43e 100644 --- a/allg5ui/renderer.go +++ b/allg5ui/renderer.go @@ -237,7 +237,10 @@ func (r *Renderer) DrawTexture(texture ui.Texture, p geom.RectangleF32) { } func (r *Renderer) DrawTextureOptions(texture ui.Texture, p geom.RectangleF32, opts ui.DrawOptions) { - bmp := r.mustGetBitmap(texture) + bmp, ok := r.mustGetSubBitmap(texture, opts.Source) + if ok { + defer bmp.Destroy() + } x, y := snap(p.Min) var o allg5.DrawOptions if opts.Tint != nil { @@ -259,7 +262,10 @@ func (r *Renderer) DrawTexturePoint(texture ui.Texture, p geom.PointF32) { } func (r *Renderer) DrawTexturePointOptions(texture ui.Texture, p geom.PointF32, opts ui.DrawOptions) { - bmp := r.mustGetBitmap(texture) + bmp, ok := r.mustGetSubBitmap(texture, opts.Source) + if ok { + defer bmp.Destroy() + } var o allg5.DrawOptions if opts.Tint != nil { tint := newColor(opts.Tint) @@ -281,6 +287,18 @@ func (r *Renderer) mustGetBitmap(t ui.Texture) *allg5.Bitmap { return texture.bmp } +func (r *Renderer) mustGetSubBitmap(t ui.Texture, source *geom.RectangleF32) (*allg5.Bitmap, bool) { + texture, ok := t.(*texture) + if !ok { + panic("texture must be created on same renderer") + } + if source == nil { + return texture.bmp, false + } + src := source.ToInt() + return texture.bmp.Sub(src.Min.X, src.Min.Y, src.Dx(), src.Dy()), true +} + func (r *Renderer) Rectangle(rect geom.RectangleF32, c color.Color, thickness float32) { minX, minY := snap(rect.Min) maxX, maxY := snap(rect.Max) diff --git a/sdlui/renderer.go b/sdlui/renderer.go index fe38d39..8d39454 100644 --- a/sdlui/renderer.go +++ b/sdlui/renderer.go @@ -311,11 +311,17 @@ func (r *Renderer) DrawTextureOptions(t ui.Texture, dst geom.RectangleF32, opts if !ok { return } - width, height, err := texture.Size() - if err != nil { - return + var source sdl.Rect + if opts.Source != nil { + source = RectAbs(int32(opts.Source.Min.X), int32(opts.Source.Min.Y), int32(opts.Source.Max.X), int32(opts.Source.Max.Y)) + } else { + width, height, err := texture.Size() + if err != nil { + return + } + source = Rect(0, 0, width, height) } - r.drawTexture(texture, Rect(0, 0, width, height), RectAbs(int32(dst.Min.X), int32(dst.Min.Y), int32(dst.Max.X), int32(dst.Max.Y)), opts) + r.drawTexture(texture, source, RectAbs(int32(dst.Min.X), int32(dst.Min.Y), int32(dst.Max.X), int32(dst.Max.Y)), opts) } func (r *Renderer) DrawTexturePoint(t ui.Texture, dst geom.PointF32) { @@ -327,11 +333,19 @@ func (r *Renderer) DrawTexturePointOptions(t ui.Texture, dst geom.PointF32, opts if !ok { return } - width, height, err := texture.Size() - if err != nil { - return + var source, destination sdl.Rect + if opts.Source != nil { + source = RectAbs(int32(opts.Source.Min.X), int32(opts.Source.Min.Y), int32(opts.Source.Max.X), int32(opts.Source.Max.Y)) + destination = Rect(int32(dst.X), int32(dst.Y), source.W, source.H) + } else { + width, height, err := texture.Size() + if err != nil { + return + } + source = Rect(0, 0, width, height) + destination = Rect(int32(dst.X), int32(dst.Y), width, height) } - r.drawTexture(texture, Rect(0, 0, width, height), Rect(int32(dst.X), int32(dst.Y), width, height), opts) + r.drawTexture(texture, source, destination, opts) } func (r *Renderer) FillRectangle(rect geom.RectangleF32, c color.Color) { diff --git a/ui/drawoptions.go b/ui/drawoptions.go index bd5f925..a222af8 100644 --- a/ui/drawoptions.go +++ b/ui/drawoptions.go @@ -7,7 +7,8 @@ import ( ) type DrawOptions struct { - Tint color.Color + Source *geom.RectangleF32 + Tint color.Color } func ScaleToHeight(size geom.PointF32, height float32) (*geom.PointF32, float32) {