package tins2020 import ( "fmt" "image/color" "time" "opslag.de/schobers/geom" "opslag.de/schobers/zntg" "opslag.de/schobers/zntg/ui" ) type TextureCache struct { Value ui.Texture } func (c *TextureCache) Height() float32 { if c.Value == nil { return 0 } return c.Value.Height() } func (c *TextureCache) Update(update func() (ui.Texture, error)) error { texture, err := update() if err != nil { return err } if c.Value != nil { c.Value.Destroy() } c.Value = texture return nil } func (c *TextureCache) Width() float32 { if c.Value == nil { return 0 } return c.Value.Width() } func textUpdate(render ui.Renderer, font ui.Font, color color.Color, text string) func() (ui.Texture, error) { return func() (ui.Texture, error) { return render.TextTexture(font, color, text) } } type BuyFlowerButton struct { IconButton IconDisabled string FlowerID string Flower FlowerDescriptor upToDate bool hoverAnimation zntg.Animation hoverOffset float32 hoverTexture TextureCache priceTexture TextureCache } func NewBuyFlowerButton(icon, iconDisabled, flowerID string, flower FlowerDescriptor, click ui.EventEmptyFn) *BuyFlowerButton { return &BuyFlowerButton{ IconButton: *NewIconButtonConfigure(icon, click, func(b *IconButton) { b.Disabled = !flower.Unlocked }), IconDisabled: iconDisabled, FlowerID: flowerID, Flower: flower, } } func (b *BuyFlowerButton) animate() { b.hoverOffset++ if b.hoverOffset > b.hoverTexture.Width()+b.Bounds().Dx() { b.hoverOffset = 0 } } func (b *BuyFlowerButton) fmtTooltipText() string { if !b.Flower.Unlocked { return fmt.Sprintf("%s - %s - %s", FmtMoney(b.Flower.BuyPrice), b.Flower.Name, "Traits are not known yet.") } return fmt.Sprintf("%s - %s - %s", FmtMoney(b.Flower.BuyPrice), b.Flower.Name, b.Flower.Description) } func (b *BuyFlowerButton) updateTexts(ctx ui.Context) error { if b.upToDate { return nil } text := b.fmtTooltipText() font := ctx.Fonts().Font("small") color := zntg.MustHexColor("#FFFFFF") if err := b.hoverTexture.Update(textUpdate(ctx.Renderer(), font, color, text)); err != nil { return err } if err := b.priceTexture.Update(textUpdate(ctx.Renderer(), font, color, FmtMoney(b.Flower.BuyPrice))); err != nil { return err } b.upToDate = true return nil } func (b *BuyFlowerButton) Handle(ctx ui.Context, e ui.Event) bool { b.updateTexts(ctx) b.IconButton.Handle(ctx, e) if b.IsOver() && !b.hoverAnimation.IsActive() { b.hoverAnimation.Interval = 10 * time.Millisecond b.hoverAnimation.Start() b.hoverOffset = b.priceTexture.Width() } else if !b.IsOver() { b.hoverAnimation.Pause() } return false } func (b *BuyFlowerButton) Render(ctx ui.Context) { b.updateTexts(ctx) bounds := b.Bounds() pos := bounds.Min icon := ctx.Textures().Texture(b.Icon) if !b.Flower.Unlocked { disabled := ctx.Textures().Texture(b.IconDisabled) if disabled != nil { icon = disabled } } ctx.Renderer().DrawTexture(icon, geom.RectRelF32(pos.X, pos.Y-60, bounds.Dx(), 120)) b.RenderActive(ctx) b.hoverAnimation.AnimateFn(b.animate) if b.IsOver() { left := bounds.Dx() - 8 - b.hoverOffset top := pos.Y + bounds.Dy() - 20 if left < 0 { part := geom.RectF32(-left, 0, b.hoverTexture.Width(), b.hoverTexture.Height()) ctx.Renderer().DrawTexturePointOptions(b.hoverTexture.Value, geom.PtF32(pos.X, top), ui.DrawOptions{Source: &part}) } else { ctx.Renderer().DrawTexturePoint(b.hoverTexture.Value, geom.PtF32(pos.X+left, top)) } } else { ctx.Renderer().DrawTexturePoint(b.priceTexture.Value, geom.PtF32(pos.X+bounds.Dx()-8-b.priceTexture.Width(), pos.Y+bounds.Dy()-20)) } } func (b *BuyFlowerButton) Update(desc FlowerDescriptor) { b.Flower = desc b.upToDate = false }