Renamed Image{,s} to Texture{,s}.
This commit is contained in:
parent
2c9007ce9b
commit
48aaf30182
@ -7,24 +7,24 @@ import (
|
|||||||
"opslag.de/schobers/zntg/ui"
|
"opslag.de/schobers/zntg/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ ui.Image = &uiImage{}
|
var _ ui.Texture = &texture{}
|
||||||
|
|
||||||
type uiImage struct {
|
type texture struct {
|
||||||
bmp *allg5.Bitmap
|
bmp *allg5.Bitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *uiImage) Destroy() {
|
func (t *texture) Destroy() {
|
||||||
i.bmp.Destroy()
|
t.bmp.Destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *uiImage) Height() float32 {
|
func (t *texture) Height() float32 {
|
||||||
return float32(i.bmp.Height())
|
return float32(t.bmp.Height())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *uiImage) Image() image.Image {
|
func (t *texture) Texture() image.Image {
|
||||||
return i.bmp.Image()
|
return t.bmp.Image()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *uiImage) Width() float32 {
|
func (t *texture) Width() float32 {
|
||||||
return float32(i.bmp.Width())
|
return float32(t.bmp.Width())
|
||||||
}
|
}
|
||||||
|
@ -130,44 +130,44 @@ func (r *Renderer) Clear(c color.Color) {
|
|||||||
allg5.ClearToColor(newColor(c))
|
allg5.ClearToColor(newColor(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) CreateImage(im image.Image) (ui.Image, error) {
|
func (r *Renderer) CreateTexture(im image.Image) (ui.Texture, error) {
|
||||||
bmp, err := allg5.NewBitmapFromImage(im, true)
|
bmp, err := allg5.NewBitmapFromImage(im, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &uiImage{bmp}, nil
|
return &texture{bmp}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) CreateImagePath(path string) (ui.Image, error) {
|
func (r *Renderer) CreateTexturePath(path string) (ui.Texture, error) {
|
||||||
bmp, err := allg5.LoadBitmap(path)
|
bmp, err := allg5.LoadBitmap(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &uiImage{bmp}, nil
|
return &texture{bmp}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) CreateImageSize(w, h float32) (ui.Image, error) {
|
func (r *Renderer) CreateTextureSize(w, h float32) (ui.Texture, error) {
|
||||||
bmp, err := allg5.NewVideoBitmap(int(w), int(h))
|
bmp, err := allg5.NewVideoBitmap(int(w), int(h))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &uiImage{bmp}, nil
|
return &texture{bmp}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) DefaultTarget() ui.Image {
|
func (r *Renderer) DefaultTarget() ui.Texture {
|
||||||
return &uiImage{r.disp.Target()}
|
return &texture{r.disp.Target()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) Display() *allg5.Display { return r.disp }
|
func (r *Renderer) Display() *allg5.Display { return r.disp }
|
||||||
|
|
||||||
func (r *Renderer) DrawImage(im ui.Image, p geom.PointF32) {
|
func (r *Renderer) DrawTexture(texture ui.Texture, p geom.PointF32) {
|
||||||
bmp := r.mustGetBitmap(im)
|
bmp := r.mustGetBitmap(texture)
|
||||||
x, y := snap(p)
|
x, y := snap(p)
|
||||||
bmp.Draw(x, y)
|
bmp.Draw(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) DrawImageOptions(im ui.Image, p geom.PointF32, opts ui.DrawOptions) {
|
func (r *Renderer) DrawTextureOptions(texture ui.Texture, p geom.PointF32, opts ui.DrawOptions) {
|
||||||
bmp := r.mustGetBitmap(im)
|
bmp := r.mustGetBitmap(texture)
|
||||||
var o allg5.DrawOptions
|
var o allg5.DrawOptions
|
||||||
if opts.Tint != nil {
|
if opts.Tint != nil {
|
||||||
tint := newColor(opts.Tint)
|
tint := newColor(opts.Tint)
|
||||||
@ -188,12 +188,12 @@ func (r *Renderer) Font(name string) ui.Font {
|
|||||||
return r.ft[name]
|
return r.ft[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) mustGetBitmap(im ui.Image) *allg5.Bitmap {
|
func (r *Renderer) mustGetBitmap(t ui.Texture) *allg5.Bitmap {
|
||||||
m, ok := im.(*uiImage)
|
texture, ok := t.(*texture)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic("image must be created on same renderer")
|
panic("image must be created on same renderer")
|
||||||
}
|
}
|
||||||
return m.bmp
|
return texture.bmp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) Rectangle(rect geom.RectangleF32, c color.Color, thickness float32) {
|
func (r *Renderer) Rectangle(rect geom.RectangleF32, c color.Color, thickness float32) {
|
||||||
@ -225,8 +225,8 @@ func (r *Renderer) RegisterFonts(path string, fonts ...FontDefinition) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) RenderTo(im ui.Image) {
|
func (r *Renderer) RenderTo(texture ui.Texture) {
|
||||||
bmp := r.mustGetBitmap(im)
|
bmp := r.mustGetBitmap(texture)
|
||||||
bmp.SetAsTarget()
|
bmp.SetAsTarget()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,8 +238,8 @@ func (r *Renderer) Size() geom.PointF32 {
|
|||||||
return geom.PtF32(float32(r.disp.Width()), float32(r.disp.Height()))
|
return geom.PtF32(float32(r.disp.Width()), float32(r.disp.Height()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) SetIcon(im ui.Image) {
|
func (r *Renderer) SetIcon(texture ui.Texture) {
|
||||||
bmp := r.mustGetBitmap(im)
|
bmp := r.mustGetBitmap(texture)
|
||||||
r.disp.SetIcon(bmp)
|
r.disp.SetIcon(bmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,8 +255,8 @@ func (r *Renderer) SetWindowTitle(t string) {
|
|||||||
r.disp.SetWindowTitle(t)
|
r.disp.SetWindowTitle(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) Target() ui.Image {
|
func (r *Renderer) Target() ui.Texture {
|
||||||
return &uiImage{allg5.CurrentTarget()}
|
return &texture{allg5.CurrentTarget()}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) text(p geom.PointF32, font string, c color.Color, t string, align allg5.HorizontalAlignment) {
|
func (r *Renderer) text(p geom.PointF32, font string, c color.Color, t string, align allg5.HorizontalAlignment) {
|
||||||
|
18
ui/buffer.go
18
ui/buffer.go
@ -5,38 +5,38 @@ import "opslag.de/schobers/geom"
|
|||||||
type RenderBufferFn func(ctx Context, size geom.PointF32)
|
type RenderBufferFn func(ctx Context, size geom.PointF32)
|
||||||
|
|
||||||
type Buffer struct {
|
type Buffer struct {
|
||||||
im Image
|
texture Texture
|
||||||
size geom.PointF32
|
size geom.PointF32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Buffer) Update(ctx Context, size geom.PointF32) error {
|
func (b *Buffer) Update(ctx Context, size geom.PointF32) error {
|
||||||
if b.im != nil {
|
if b.texture != nil {
|
||||||
if size == b.size {
|
if size == b.size {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
b.im.Destroy()
|
b.texture.Destroy()
|
||||||
b.im = nil
|
b.texture = nil
|
||||||
b.size = geom.ZeroPtF32
|
b.size = geom.ZeroPtF32
|
||||||
}
|
}
|
||||||
im, err := ctx.Renderer().CreateImageSize(size.X, size.Y)
|
texture, err := ctx.Renderer().CreateTextureSize(size.X, size.Y)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b.im = im
|
b.texture = texture
|
||||||
b.size = size
|
b.size = size
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Buffer) Render(ctx Context, pos geom.PointF32, fn RenderBufferFn) {
|
func (b *Buffer) Render(ctx Context, pos geom.PointF32, fn RenderBufferFn) {
|
||||||
if b.im == nil {
|
if b.texture == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
renderer := ctx.Renderer()
|
renderer := ctx.Renderer()
|
||||||
currTarget := renderer.Target()
|
currTarget := renderer.Target()
|
||||||
renderer.RenderTo(b.im)
|
renderer.RenderTo(b.texture)
|
||||||
fn(ctx, b.size)
|
fn(ctx, b.size)
|
||||||
renderer.RenderTo(currTarget)
|
renderer.RenderTo(currTarget)
|
||||||
renderer.DrawImage(b.im, pos)
|
renderer.DrawTexture(b.texture, pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
type BufferControl struct {
|
type BufferControl struct {
|
||||||
|
10
ui/button.go
10
ui/button.go
@ -10,7 +10,7 @@ type Button struct {
|
|||||||
ControlBase
|
ControlBase
|
||||||
|
|
||||||
HoverColor color.Color
|
HoverColor color.Color
|
||||||
Icon Image
|
Icon Texture
|
||||||
IconScale float32
|
IconScale float32
|
||||||
Text string
|
Text string
|
||||||
Type ButtonType
|
Type ButtonType
|
||||||
@ -27,8 +27,8 @@ const (
|
|||||||
|
|
||||||
func BuildButton(text string, fn func(b *Button)) *Button { return BuildIconButton(nil, text, fn) }
|
func BuildButton(text string, fn func(b *Button)) *Button { return BuildIconButton(nil, text, fn) }
|
||||||
|
|
||||||
func BuildIconButton(i Image, text string, fn func(b *Button)) *Button {
|
func BuildIconButton(icon Texture, text string, fn func(b *Button)) *Button {
|
||||||
var b = &Button{Text: text, Icon: i}
|
var b = &Button{Text: text, Icon: icon}
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
fn(b)
|
fn(b)
|
||||||
}
|
}
|
||||||
@ -133,9 +133,9 @@ func (b *Button) Render(ctx Context) {
|
|||||||
bounds = bounds.Inset(pad)
|
bounds = bounds.Inset(pad)
|
||||||
pos := bounds.Min
|
pos := bounds.Min
|
||||||
if b.Icon != nil && b.Icon.Height() > 0 {
|
if b.Icon != nil && b.Icon.Height() > 0 {
|
||||||
icon, _ := ctx.Images().ScaledHeight(b.Icon, b.scale(bounds.Dy()))
|
icon, _ := ctx.Textures().ScaledHeight(b.Icon, b.scale(bounds.Dy()))
|
||||||
if icon != nil {
|
if icon != nil {
|
||||||
ctx.Renderer().DrawImageOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: textColor})
|
ctx.Renderer().DrawTextureOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: textColor})
|
||||||
pos.X += icon.Width() + pad
|
pos.X += icon.Width() + pad
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,12 @@ func (c *Checkbox) desiredSize(ctx Context) geom.PointF32 {
|
|||||||
if len(c.Text) != 0 {
|
if len(c.Text) != 0 {
|
||||||
w += pad + font.WidthOf(c.Text)
|
w += pad + font.WidthOf(c.Text)
|
||||||
}
|
}
|
||||||
icon, _ := ctx.Images().ScaledHeight(c.getOrCreateNormalIcon(ctx), h)
|
icon, _ := ctx.Textures().ScaledHeight(c.getOrCreateNormalIcon(ctx), h)
|
||||||
w += pad + icon.Width()
|
w += pad + icon.Width()
|
||||||
return geom.PtF32(w+pad, pad+h+pad)
|
return geom.PtF32(w+pad, pad+h+pad)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Checkbox) icon(ctx Context) Image {
|
func (c *Checkbox) icon(ctx Context) Texture {
|
||||||
if c.Selected {
|
if c.Selected {
|
||||||
return GetOrCreateIcon(ctx, "ui-default-checkbox-selected", c.selectedIcon)
|
return GetOrCreateIcon(ctx, "ui-default-checkbox-selected", c.selectedIcon)
|
||||||
} else if c.over {
|
} else if c.over {
|
||||||
@ -44,7 +44,7 @@ func (c *Checkbox) icon(ctx Context) Image {
|
|||||||
return c.getOrCreateNormalIcon(ctx)
|
return c.getOrCreateNormalIcon(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Checkbox) getOrCreateNormalIcon(ctx Context) Image {
|
func (c *Checkbox) getOrCreateNormalIcon(ctx Context) Texture {
|
||||||
return GetOrCreateIcon(ctx, "ui-default-checkbox", c.normalIcon)
|
return GetOrCreateIcon(ctx, "ui-default-checkbox", c.normalIcon)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,13 +125,13 @@ func (c *Checkbox) Render(ctx Context) {
|
|||||||
var pad = style.Dimensions.TextPadding
|
var pad = style.Dimensions.TextPadding
|
||||||
bounds = bounds.Inset(pad)
|
bounds = bounds.Inset(pad)
|
||||||
pos := bounds.Min
|
pos := bounds.Min
|
||||||
icon, _ := ctx.Images().ScaledHeight(c.icon(ctx), bounds.Dy())
|
icon, _ := ctx.Textures().ScaledHeight(c.icon(ctx), bounds.Dy())
|
||||||
if icon != nil {
|
if icon != nil {
|
||||||
iconColor := fore
|
iconColor := fore
|
||||||
if c.Selected && c.Font.Color == nil {
|
if c.Selected && c.Font.Color == nil {
|
||||||
iconColor = palette.Primary
|
iconColor = palette.Primary
|
||||||
}
|
}
|
||||||
ctx.Renderer().DrawImageOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: iconColor})
|
ctx.Renderer().DrawTextureOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: iconColor})
|
||||||
pos.X += icon.Width() + pad
|
pos.X += icon.Width() + pad
|
||||||
}
|
}
|
||||||
if len(c.Text) != 0 {
|
if len(c.Text) != 0 {
|
||||||
|
@ -3,7 +3,7 @@ package ui
|
|||||||
type Context interface {
|
type Context interface {
|
||||||
Animate()
|
Animate()
|
||||||
HasQuit() bool
|
HasQuit() bool
|
||||||
Images() *Images
|
Textures() *Textures
|
||||||
Quit()
|
Quit()
|
||||||
Renderer() Renderer
|
Renderer() Renderer
|
||||||
Style() *Style
|
Style() *Style
|
||||||
@ -17,7 +17,7 @@ type context struct {
|
|||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
r Renderer
|
r Renderer
|
||||||
view Control
|
view Control
|
||||||
ims *Images
|
textures *Textures
|
||||||
style *Style
|
style *Style
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ func (c *context) HasQuit() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) Images() *Images { return c.ims }
|
func (c *context) Textures() *Textures { return c.textures }
|
||||||
|
|
||||||
func (c *context) Quit() {
|
func (c *context) Quit() {
|
||||||
if !c.HasQuit() {
|
if !c.HasQuit() {
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
type basic struct {
|
type basic struct {
|
||||||
ui.StackPanel
|
ui.StackPanel
|
||||||
|
|
||||||
plus ui.Image
|
plus ui.Texture
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *basic) Init(ctx ui.Context) error {
|
func (b *basic) Init(ctx ui.Context) error {
|
||||||
@ -73,7 +73,7 @@ func run() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
plus, err := render.CreateImagePath("../resources/images/plus.png")
|
plus, err := render.CreateTexturePath("../resources/images/plus.png")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
34
ui/icon.go
34
ui/icon.go
@ -10,27 +10,27 @@ import (
|
|||||||
type ImagePixelTestFn func(geom.PointF32) bool
|
type ImagePixelTestFn func(geom.PointF32) bool
|
||||||
type ImageAlphaPixelTestFn func(geom.PointF32) uint8
|
type ImageAlphaPixelTestFn func(geom.PointF32) uint8
|
||||||
|
|
||||||
func createImage(ctx Context, image image.Image) Image {
|
func createTexture(ctx Context, image image.Image) Texture {
|
||||||
im, err := ctx.Renderer().CreateImage(image)
|
texture, err := ctx.Renderer().CreateTexture(image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return im
|
return texture
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateIcon(ctx Context, test ImagePixelTestFn) Image {
|
func CreateIcon(ctx Context, test ImagePixelTestFn) Texture {
|
||||||
icon := DrawIcon(test)
|
icon := DrawIcon(test)
|
||||||
return createImage(ctx, icon)
|
return createTexture(ctx, icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateImage(ctx Context, size geom.Point, test ImagePixelTestFn) Image {
|
func CreateTexture(ctx Context, size geom.Point, test ImagePixelTestFn) Texture {
|
||||||
image := DrawImage(size, test)
|
image := DrawImage(size, test)
|
||||||
return createImage(ctx, image)
|
return createTexture(ctx, image)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateImageAlpha(ctx Context, size geom.Point, test ImageAlphaPixelTestFn) Image {
|
func CreateTextureAlpha(ctx Context, size geom.Point, test ImageAlphaPixelTestFn) Texture {
|
||||||
image := DrawImageAlpha(size, test)
|
image := DrawImageAlpha(size, test)
|
||||||
return createImage(ctx, image)
|
return createTexture(ctx, image)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DrawIcon(test ImagePixelTestFn) image.Image {
|
func DrawIcon(test ImagePixelTestFn) image.Image {
|
||||||
@ -66,18 +66,18 @@ func DrawImageAlpha(size geom.Point, test ImageAlphaPixelTestFn) image.Image {
|
|||||||
return icon
|
return icon
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetOrCreateIcon(ctx Context, name string, testFactory func() ImagePixelTestFn) Image {
|
func GetOrCreateIcon(ctx Context, name string, testFactory func() ImagePixelTestFn) Texture {
|
||||||
im := ctx.Images().Image(name)
|
texture := ctx.Textures().Texture(name)
|
||||||
if im != nil {
|
if texture != nil {
|
||||||
return im
|
return texture
|
||||||
}
|
}
|
||||||
test := testFactory()
|
test := testFactory()
|
||||||
im = CreateIcon(ctx, test)
|
texture = CreateIcon(ctx, test)
|
||||||
if im == nil {
|
if texture == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ctx.Images().AddImage(name, im)
|
ctx.Textures().AddTexture(name, texture)
|
||||||
return im
|
return texture
|
||||||
}
|
}
|
||||||
|
|
||||||
func IconSize() geom.Point {
|
func IconSize() geom.Point {
|
||||||
|
123
ui/images.go
123
ui/images.go
@ -1,123 +0,0 @@
|
|||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
|
|
||||||
"github.com/nfnt/resize"
|
|
||||||
"opslag.de/schobers/geom"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CreateImageFn func() (image.Image, error)
|
|
||||||
|
|
||||||
func ScaleImage(render Renderer, im Image, scale float32) Image {
|
|
||||||
w := uint(im.Width() * scale)
|
|
||||||
if w == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
scaled := resize.Resize(w, 0, im.Image(), resize.Bilinear)
|
|
||||||
res, err := render.CreateImage(scaled)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
type Images struct {
|
|
||||||
render Renderer
|
|
||||||
ims map[string]Image
|
|
||||||
scaled map[Image]ScaledImages
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewImages(render Renderer) *Images {
|
|
||||||
return &Images{render, map[string]Image{}, map[Image]ScaledImages{}}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Images) AddImage(name string, im Image) {
|
|
||||||
curr := i.ims[name]
|
|
||||||
if curr != nil {
|
|
||||||
curr.Destroy()
|
|
||||||
}
|
|
||||||
i.ims[name] = im
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Images) AddImageFn(name string, create CreateImageFn) error {
|
|
||||||
im, err := create()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return i.AddImageNative(name, im)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Images) AddImageNative(name string, im image.Image) error {
|
|
||||||
m, err := i.render.CreateImage(im)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
i.AddImage(name, m)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Images) Destroy() {
|
|
||||||
for _, im := range i.ims {
|
|
||||||
im.Destroy()
|
|
||||||
}
|
|
||||||
i.ims = nil
|
|
||||||
for _, ims := range i.scaled {
|
|
||||||
ims.Destroy()
|
|
||||||
}
|
|
||||||
i.scaled = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Images) Image(name string) Image {
|
|
||||||
im, ok := i.ims[name]
|
|
||||||
if ok {
|
|
||||||
return im
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Images) Scaled(im Image, scale float32) Image {
|
|
||||||
if scale <= 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if scale == 1 {
|
|
||||||
return im
|
|
||||||
}
|
|
||||||
ims := i.scaled[im]
|
|
||||||
if ims == nil {
|
|
||||||
ims = make(ScaledImages)
|
|
||||||
} else {
|
|
||||||
scaled := ims[scale]
|
|
||||||
if scaled != nil {
|
|
||||||
return scaled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scaled := ScaleImage(i.render, im, scale)
|
|
||||||
ims[scale] = scaled
|
|
||||||
i.scaled[im] = ims
|
|
||||||
return scaled
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Images) ScaledHeight(im Image, height float32) (Image, float32) {
|
|
||||||
scale := height / im.Height()
|
|
||||||
if geom.IsNaN32(scale) {
|
|
||||||
return nil, 0
|
|
||||||
}
|
|
||||||
return i.Scaled(im, scale), scale
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Images) ScaledByName(name string, scale float32) Image {
|
|
||||||
im := i.Image(name)
|
|
||||||
if im == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return i.Scaled(im, scale)
|
|
||||||
}
|
|
||||||
|
|
||||||
type ScaledImages map[float32]Image
|
|
||||||
|
|
||||||
func (i ScaledImages) Destroy() {
|
|
||||||
for _, im := range i {
|
|
||||||
im.Destroy()
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,21 +17,21 @@ type Renderer interface {
|
|||||||
|
|
||||||
// Drawing
|
// Drawing
|
||||||
Clear(c color.Color)
|
Clear(c color.Color)
|
||||||
CreateImage(m image.Image) (Image, error)
|
CreateTexture(m image.Image) (Texture, error)
|
||||||
CreateImagePath(path string) (Image, error)
|
CreateTexturePath(path string) (Texture, error)
|
||||||
CreateImageSize(w, h float32) (Image, error)
|
CreateTextureSize(w, h float32) (Texture, error)
|
||||||
DefaultTarget() Image
|
DefaultTarget() Texture
|
||||||
DrawImage(im Image, p geom.PointF32)
|
DrawTexture(t Texture, p geom.PointF32)
|
||||||
DrawImageOptions(im Image, p geom.PointF32, opts DrawOptions)
|
DrawTextureOptions(t Texture, p geom.PointF32, opts DrawOptions)
|
||||||
FillRectangle(r geom.RectangleF32, c color.Color)
|
FillRectangle(r geom.RectangleF32, c color.Color)
|
||||||
Font(name string) Font
|
Font(name string) Font
|
||||||
Rectangle(r geom.RectangleF32, c color.Color, thickness float32)
|
Rectangle(r geom.RectangleF32, c color.Color, thickness float32)
|
||||||
RegisterFont(name, path string, size int) error
|
RegisterFont(name, path string, size int) error
|
||||||
RenderTo(Image)
|
RenderTo(Texture)
|
||||||
RenderToDisplay()
|
RenderToDisplay()
|
||||||
SetMouseCursor(c MouseCursor)
|
SetMouseCursor(c MouseCursor)
|
||||||
Size() geom.PointF32
|
Size() geom.PointF32
|
||||||
Target() Image
|
Target() Texture
|
||||||
Text(p geom.PointF32, font string, color color.Color, text string)
|
Text(p geom.PointF32, font string, color color.Color, text string)
|
||||||
TextAlign(p geom.PointF32, font string, color color.Color, text string, align HorizontalAlignment)
|
TextAlign(p geom.PointF32, font string, color color.Color, text string, align HorizontalAlignment)
|
||||||
}
|
}
|
||||||
|
@ -134,17 +134,17 @@ func (s *Slider) OnValueChanged(fn func(float32)) {
|
|||||||
type sliderHandle struct {
|
type sliderHandle struct {
|
||||||
ControlBase
|
ControlBase
|
||||||
|
|
||||||
handle Image
|
handle Texture
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *sliderHandle) im(ctx Context) Image {
|
func (h *sliderHandle) texture(ctx Context) Texture {
|
||||||
if h.handle != nil {
|
if h.handle != nil {
|
||||||
return h.handle
|
return h.handle
|
||||||
}
|
}
|
||||||
size := h.Bounds().Size()
|
size := h.Bounds().Size()
|
||||||
center := geom.PtF32(.5*size.X-.5, .5*size.Y-.5)
|
center := geom.PtF32(.5*size.X-.5, .5*size.Y-.5)
|
||||||
radius := 0.5 * geom.Min32(size.X, size.Y)
|
radius := 0.5 * geom.Min32(size.X, size.Y)
|
||||||
h.handle = CreateImageAlpha(ctx, geom.Pt(int(size.X), int(size.Y)), func(p geom.PointF32) uint8 {
|
h.handle = CreateTextureAlpha(ctx, geom.Pt(int(size.X), int(size.Y)), func(p geom.PointF32) uint8 {
|
||||||
dist := center.Distance(p)
|
dist := center.Distance(p)
|
||||||
if dist < radius {
|
if dist < radius {
|
||||||
if dist < (radius - 1) {
|
if dist < (radius - 1) {
|
||||||
@ -169,5 +169,5 @@ func (h *sliderHandle) Render(ctx Context) {
|
|||||||
if h.IsOver() {
|
if h.IsOver() {
|
||||||
color = ctx.Style().Palette.PrimaryLight
|
color = ctx.Style().Palette.PrimaryLight
|
||||||
}
|
}
|
||||||
ctx.Renderer().DrawImageOptions(h.im(ctx), h.Bounds().Min, DrawOptions{Tint: color})
|
ctx.Renderer().DrawTextureOptions(h.texture(ctx), h.Bounds().Min, DrawOptions{Tint: color})
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@ package ui
|
|||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
|
|
||||||
type Image interface {
|
type Texture interface {
|
||||||
Destroy()
|
Destroy()
|
||||||
Height() float32
|
Height() float32
|
||||||
Image() image.Image
|
Texture() image.Image
|
||||||
Width() float32
|
Width() float32
|
||||||
}
|
}
|
123
ui/textures.go
Normal file
123
ui/textures.go
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"github.com/nfnt/resize"
|
||||||
|
"opslag.de/schobers/geom"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateImageFn func() (image.Image, error)
|
||||||
|
|
||||||
|
func ScaleTexture(render Renderer, texture Texture, scale float32) Texture {
|
||||||
|
w := uint(texture.Width() * scale)
|
||||||
|
if w == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
scaled := resize.Resize(w, 0, texture.Texture(), resize.Bilinear)
|
||||||
|
res, err := render.CreateTexture(scaled)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
type Textures struct {
|
||||||
|
render Renderer
|
||||||
|
textures map[string]Texture
|
||||||
|
scaled map[Texture]ScaledTextures
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTextures(render Renderer) *Textures {
|
||||||
|
return &Textures{render, map[string]Texture{}, map[Texture]ScaledTextures{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) AddTexture(name string, texture Texture) {
|
||||||
|
curr := t.textures[name]
|
||||||
|
if curr != nil {
|
||||||
|
curr.Destroy()
|
||||||
|
}
|
||||||
|
t.textures[name] = texture
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) AddTextureFn(name string, create CreateImageFn) error {
|
||||||
|
im, err := create()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return t.AddTextureNative(name, im)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) AddTextureNative(name string, im image.Image) error {
|
||||||
|
texture, err := t.render.CreateTexture(im)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.AddTexture(name, texture)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) Destroy() {
|
||||||
|
for _, texture := range t.textures {
|
||||||
|
texture.Destroy()
|
||||||
|
}
|
||||||
|
t.textures = nil
|
||||||
|
for _, textures := range t.scaled {
|
||||||
|
textures.Destroy()
|
||||||
|
}
|
||||||
|
t.scaled = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) Texture(name string) Texture {
|
||||||
|
texture, ok := t.textures[name]
|
||||||
|
if ok {
|
||||||
|
return texture
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) Scaled(texture Texture, scale float32) Texture {
|
||||||
|
if scale <= 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if scale == 1 {
|
||||||
|
return texture
|
||||||
|
}
|
||||||
|
textures := t.scaled[texture]
|
||||||
|
if textures == nil {
|
||||||
|
textures = make(ScaledTextures)
|
||||||
|
} else {
|
||||||
|
scaled := textures[scale]
|
||||||
|
if scaled != nil {
|
||||||
|
return scaled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scaled := ScaleTexture(t.render, texture, scale)
|
||||||
|
textures[scale] = scaled
|
||||||
|
t.scaled[texture] = textures
|
||||||
|
return scaled
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) ScaledHeight(textures Texture, height float32) (Texture, float32) {
|
||||||
|
scale := height / textures.Height()
|
||||||
|
if geom.IsNaN32(scale) {
|
||||||
|
return nil, 0
|
||||||
|
}
|
||||||
|
return t.Scaled(textures, scale), scale
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Textures) ScaledByName(name string, scale float32) Texture {
|
||||||
|
textures := t.Texture(name)
|
||||||
|
if textures == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return t.Scaled(textures, scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ScaledTextures map[float32]Texture
|
||||||
|
|
||||||
|
func (t ScaledTextures) Destroy() {
|
||||||
|
for _, textures := range t {
|
||||||
|
textures.Destroy()
|
||||||
|
}
|
||||||
|
}
|
2
ui/ui.go
2
ui/ui.go
@ -13,7 +13,7 @@ func Run(r Renderer, s *Style, view Control) error {
|
|||||||
|
|
||||||
// RunWait runs the application loop and conditionally waits on events before rendering.
|
// RunWait runs the application loop and conditionally waits on events before rendering.
|
||||||
func RunWait(r Renderer, s *Style, view Control, wait bool) error {
|
func RunWait(r Renderer, s *Style, view Control, wait bool) error {
|
||||||
ctx := &context{quit: make(chan struct{}), r: r, style: s, view: view, ims: NewImages(r)}
|
ctx := &context{quit: make(chan struct{}), r: r, style: s, view: view, textures: NewTextures(r)}
|
||||||
root, ok := view.(RootControl)
|
root, ok := view.(RootControl)
|
||||||
if ok {
|
if ok {
|
||||||
err := root.Init(ctx)
|
err := root.Init(ctx)
|
||||||
|
Loading…
Reference in New Issue
Block a user