Compare commits
No commits in common. "30add82f6a33600d804308dc31519cfff1f7b86f" and "4b57ace9d65a89b5964382df426cd5cf68e72c2c" have entirely different histories.
30add82f6a
...
4b57ace9d6
63
buttonbar.go
Normal file
63
buttonbar.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
"opslag.de/schobers/zntg/ui"
|
||||||
|
)
|
||||||
|
|
||||||
|
// import "github.com/veandco/go-sdl2/sdl"
|
||||||
|
|
||||||
|
type ButtonBar struct {
|
||||||
|
ui.StackPanel
|
||||||
|
|
||||||
|
Background color.Color
|
||||||
|
ButtonLength float32
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonBarWidth = 96
|
||||||
|
|
||||||
|
// func (b *ButtonBar) Init(ctx ui.Context) error {
|
||||||
|
// for i := range b.Buttons {
|
||||||
|
// b.AddChild(b.Buttons[i])
|
||||||
|
// }
|
||||||
|
// return b.Container.Init(ctx)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (b *ButtonBar) Arrange(ctx ui.Context, bounds Rectangle) {
|
||||||
|
// b.Container.Arrange(ctx, bounds)
|
||||||
|
// length := b.ButtonLength
|
||||||
|
// switch b.Orientation {
|
||||||
|
// case OrientationHorizontal:
|
||||||
|
// if length == 0 {
|
||||||
|
// length = bounds.H
|
||||||
|
// }
|
||||||
|
// offset := bounds.X
|
||||||
|
// for i := range b.Buttons {
|
||||||
|
// b.Buttons[i].Arrange(ctx, Rect(offset, bounds.Y, length, bounds.H))
|
||||||
|
// offset += length
|
||||||
|
// }
|
||||||
|
// default:
|
||||||
|
// if length == 0 {
|
||||||
|
// length = bounds.W
|
||||||
|
// }
|
||||||
|
// offset := bounds.Y
|
||||||
|
// for i := range b.Buttons {
|
||||||
|
// b.Buttons[i].Arrange(ctx, Rect(bounds.X, offset, bounds.W, length))
|
||||||
|
// offset += length
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (b *ButtonBar) Render(ctx ui.Context) {
|
||||||
|
// SetDrawColor(ctx.Renderer, b.Background)
|
||||||
|
// ctx.Renderer.FillRect(b.Bounds.SDLPtr())
|
||||||
|
// b.Container.Render(ctx)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// type Orientation int
|
||||||
|
|
||||||
|
// const (
|
||||||
|
// OrientationVertical Orientation = iota
|
||||||
|
// OrientationHorizontal
|
||||||
|
// )
|
@ -1,148 +1,123 @@
|
|||||||
package tins2020
|
package tins2020
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"image/color"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"opslag.de/schobers/geom"
|
|
||||||
"opslag.de/schobers/zntg"
|
"opslag.de/schobers/zntg"
|
||||||
"opslag.de/schobers/zntg/ui"
|
"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 {
|
type BuyFlowerButton struct {
|
||||||
IconButton
|
IconButton
|
||||||
|
|
||||||
IconDisabled string
|
|
||||||
FlowerID string
|
FlowerID string
|
||||||
Flower FlowerDescriptor
|
Flower FlowerDescriptor
|
||||||
|
|
||||||
upToDate bool
|
upToDate bool
|
||||||
hoverAnimation zntg.Animation
|
hoverAnimation *zntg.Animation
|
||||||
hoverOffset float32
|
hoverOffset int32
|
||||||
hoverTexture TextureCache
|
hoverTexture ui.Texture
|
||||||
priceTexture TextureCache
|
priceTexture ui.Texture
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBuyFlowerButton(icon, iconDisabled, flowerID string, flower FlowerDescriptor, click ui.EventEmptyFn) *BuyFlowerButton {
|
func NewBuyFlowerButton(icon, iconDisabled, flowerID string, flower FlowerDescriptor, click ui.EventEmptyFn) *BuyFlowerButton {
|
||||||
return &BuyFlowerButton{
|
return &BuyFlowerButton{
|
||||||
IconButton: *NewIconButtonConfigure(icon, click, func(b *IconButton) {
|
IconButton: *NewIconButtonConfigure(icon, click, func(b *IconButton) {
|
||||||
b.Disabled = !flower.Unlocked
|
// b.IconDisabled = iconDisabled
|
||||||
|
// b.Disabled = !flower.Unlocked
|
||||||
}),
|
}),
|
||||||
IconDisabled: iconDisabled,
|
|
||||||
FlowerID: flowerID,
|
FlowerID: flowerID,
|
||||||
Flower: flower,
|
Flower: flower,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BuyFlowerButton) animate() {
|
// func (b *BuyFlowerButton) animate() {
|
||||||
b.hoverOffset++
|
// b.hoverOffset++
|
||||||
if b.hoverOffset > b.hoverTexture.Width()+b.Bounds().Dx() {
|
// if b.hoverOffset > b.hoverTexture.Size().X+b.Bounds.W {
|
||||||
b.hoverOffset = 0
|
// b.hoverOffset = 0
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (b *BuyFlowerButton) fmtTooltipText() string {
|
// func (b *BuyFlowerButton) fmtTooltipText() string {
|
||||||
if !b.Flower.Unlocked {
|
// 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, "Traits are not known yet.")
|
||||||
}
|
// }
|
||||||
return fmt.Sprintf("%s - %s - %s", FmtMoney(b.Flower.BuyPrice), b.Flower.Name, b.Flower.Description)
|
// return fmt.Sprintf("%s - %s - %s", FmtMoney(b.Flower.BuyPrice), b.Flower.Name, b.Flower.Description)
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (b *BuyFlowerButton) updateTexts(ctx ui.Context) error {
|
func (b *BuyFlowerButton) updateTexts(ctx ui.Context) error {
|
||||||
if b.upToDate {
|
if b.upToDate {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
text := b.fmtTooltipText()
|
|
||||||
font := ctx.Fonts().Font("small")
|
// text := b.fmtTooltipText()
|
||||||
color := zntg.MustHexColor("#FFFFFF")
|
// font := ctx.Fonts.Font("small")
|
||||||
if err := b.hoverTexture.Update(textUpdate(ctx.Renderer(), font, color, text)); err != nil {
|
// color := MustHexColor("#ffffff")
|
||||||
return err
|
// texture, err := font.Render(ctx.Renderer, text, color)
|
||||||
}
|
// if err != nil {
|
||||||
if err := b.priceTexture.Update(textUpdate(ctx.Renderer(), font, color, FmtMoney(b.Flower.BuyPrice))); err != nil {
|
// return err
|
||||||
return err
|
// }
|
||||||
}
|
// if b.hoverTexture != nil {
|
||||||
|
// b.hoverTexture.Destroy()
|
||||||
|
// }
|
||||||
|
// b.hoverTexture = texture
|
||||||
|
// texture, err = font.Render(ctx.Renderer, FmtMoney(b.Flower.BuyPrice), color)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// if b.priceTexture != nil {
|
||||||
|
// b.priceTexture.Destroy()
|
||||||
|
// }
|
||||||
|
// b.priceTexture = texture
|
||||||
b.upToDate = true
|
b.upToDate = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BuyFlowerButton) Handle(ctx ui.Context, e ui.Event) bool {
|
// func (b *BuyFlowerButton) Init(ctx ui.Context) error {
|
||||||
|
// return b.updateTexts(ctx)
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (b *BuyFlowerButton) Handle(ctx ui.Context, event ui.Event) bool {
|
||||||
b.updateTexts(ctx)
|
b.updateTexts(ctx)
|
||||||
b.IconButton.Handle(ctx, e)
|
// if b.IconButton.Handle(ctx, event) {
|
||||||
if b.IsOver() && !b.hoverAnimation.IsActive() {
|
// return true
|
||||||
b.hoverAnimation.Interval = 10 * time.Millisecond
|
// }
|
||||||
b.hoverAnimation.Start()
|
// if b.IsMouseOver && b.hoverAnimation == nil {
|
||||||
b.hoverOffset = b.priceTexture.Width()
|
// b.hoverAnimation = NewAnimationPtr(10 * time.Millisecond)
|
||||||
} else if !b.IsOver() {
|
// b.hoverOffset = b.priceTexture.Size().X
|
||||||
b.hoverAnimation.Pause()
|
// } else if !b.IsMouseOver {
|
||||||
}
|
// b.hoverAnimation = nil
|
||||||
|
// }
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BuyFlowerButton) Render(ctx ui.Context) {
|
func (b *BuyFlowerButton) Render(ctx ui.Context) {
|
||||||
|
if !b.upToDate {
|
||||||
b.updateTexts(ctx)
|
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
|
|
||||||
}
|
}
|
||||||
}
|
// iconTexture := b.activeTexture(ctx)
|
||||||
ctx.Renderer().DrawTexture(icon, geom.RectRelF32(pos.X, pos.Y-60, bounds.Dx(), 120))
|
|
||||||
b.RenderActive(ctx)
|
|
||||||
|
|
||||||
b.hoverAnimation.AnimateFn(b.animate)
|
// pos := Pt(b.Bounds.X, b.Bounds.Y)
|
||||||
|
// iconTexture.CopyResize(ctx.Renderer, Rect(pos.X, pos.Y-60, b.Bounds.W, 120))
|
||||||
|
// if (b.IsMouseOver && !b.Disabled) || b.IsActive {
|
||||||
|
// SetDrawColor(ctx.Renderer, TransparentWhite)
|
||||||
|
// ctx.Renderer.FillRect(b.Bounds.SDLPtr())
|
||||||
|
// }
|
||||||
|
|
||||||
if b.IsOver() {
|
// if b.hoverAnimation != nil {
|
||||||
left := bounds.Dx() - 8 - b.hoverOffset
|
// b.hoverAnimation.AnimateFn(b.animate)
|
||||||
top := pos.Y + bounds.Dy() - 20
|
// }
|
||||||
if left < 0 {
|
|
||||||
part := geom.RectF32(-left, 0, b.hoverTexture.Width(), b.hoverTexture.Height())
|
// if b.IsMouseOver {
|
||||||
ctx.Renderer().DrawTexturePointOptions(b.hoverTexture.Value, geom.PtF32(pos.X, top), ui.DrawOptions{Source: &part})
|
// left := b.Bounds.W - 8 - b.hoverOffset
|
||||||
} else {
|
// top := pos.Y + b.Bounds.H - 20
|
||||||
ctx.Renderer().DrawTexturePoint(b.hoverTexture.Value, geom.PtF32(pos.X+left, top))
|
// if left < 0 {
|
||||||
}
|
// part := RectAbs(-left, 0, b.hoverTexture.Size().X, b.hoverTexture.Size().Y)
|
||||||
} else {
|
// b.hoverTexture.CopyPart(ctx.Renderer, part, Pt(pos.X, top))
|
||||||
ctx.Renderer().DrawTexturePoint(b.priceTexture.Value, geom.PtF32(pos.X+bounds.Dx()-8-b.priceTexture.Width(), pos.Y+bounds.Dy()-20))
|
// } else {
|
||||||
}
|
// b.hoverTexture.Copy(ctx.Renderer, Pt(pos.X+left, top))
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// b.priceTexture.Copy(ctx.Renderer, Pt(pos.X+b.Bounds.W-8-b.priceTexture.Size().X, pos.Y+b.Bounds.H-20))
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BuyFlowerButton) Update(desc FlowerDescriptor) {
|
func (b *BuyFlowerButton) Update(desc FlowerDescriptor) {
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"opslag.de/schobers/geom"
|
"opslag.de/schobers/geom"
|
||||||
"opslag.de/schobers/zntg"
|
"opslag.de/schobers/zntg"
|
||||||
"opslag.de/schobers/zntg/addons/res"
|
"opslag.de/schobers/zntg/addons/res"
|
||||||
"opslag.de/schobers/zntg/play"
|
|
||||||
"opslag.de/schobers/zntg/ui"
|
"opslag.de/schobers/zntg/ui"
|
||||||
|
|
||||||
_ "opslag.de/schobers/zntg/sdlui" // rendering backend
|
_ "opslag.de/schobers/zntg/sdlui" // rendering backend
|
||||||
@ -75,13 +74,13 @@ func (a *app) Init(ctx ui.Context) error {
|
|||||||
textureLoader := tins2020.NewResourceLoader()
|
textureLoader := tins2020.NewResourceLoader()
|
||||||
textures := ctx.Textures()
|
textures := ctx.Textures()
|
||||||
if err := textureLoader.LoadFromFile(ctx.Resources(), "textures.txt", func(name, content string) error {
|
if err := textureLoader.LoadFromFile(ctx.Resources(), "textures.txt", func(name, content string) error {
|
||||||
_, err := textures.CreateTexturePath(name, content, true)
|
_, err := textures.CreateTexturePath(name, content, false)
|
||||||
return err
|
return err
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Overlays().AddOnTop("fps", &play.FPS{}, false)
|
// ctx.Overlays().AddOnTop("fps", &tins2020.FPS{Show: &a.game.Debug})
|
||||||
|
|
||||||
content := tins2020.NewContent(a.dialogs)
|
content := tins2020.NewContent(a.dialogs)
|
||||||
content.AddChild(tins2020.NewTerrainRenderer(a.game))
|
content.AddChild(tins2020.NewTerrainRenderer(a.game))
|
||||||
@ -169,9 +168,8 @@ func run() error {
|
|||||||
}
|
}
|
||||||
style := ui.DefaultStyle()
|
style := ui.DefaultStyle()
|
||||||
style.Palette = &ui.Palette{
|
style.Palette = &ui.Palette{
|
||||||
Background: zntg.MustHexColor(`#356DAD`),
|
Background: zntg.MustHexColor(`#5388C3`),
|
||||||
Disabled: zntg.MustHexColor(`#DEDEDE`),
|
Primary: zntg.MustHexColor(`#5388C3`),
|
||||||
Primary: zntg.MustHexColor(`#356DAD`),
|
|
||||||
PrimaryDark: zntg.MustHexColor(`#15569F`),
|
PrimaryDark: zntg.MustHexColor(`#15569F`),
|
||||||
PrimaryLight: zntg.MustHexColor(`#ABCAED`),
|
PrimaryLight: zntg.MustHexColor(`#ABCAED`),
|
||||||
Secondary: zntg.MustHexColor(`#4AC69A`),
|
Secondary: zntg.MustHexColor(`#4AC69A`),
|
||||||
@ -180,8 +178,8 @@ func run() error {
|
|||||||
Text: color.White,
|
Text: color.White,
|
||||||
TextOnPrimary: color.White,
|
TextOnPrimary: color.White,
|
||||||
TextOnSecondary: color.White,
|
TextOnSecondary: color.White,
|
||||||
TextNegative: zntg.MustHexColor(`#F3590E`),
|
TextNegative: zntg.MustHexColor(`F3590E`),
|
||||||
TextPositive: zntg.MustHexColor(`#65D80D`),
|
TextPositive: zntg.MustHexColor(`65D80D`),
|
||||||
}
|
}
|
||||||
return ui.Run(renderer, style, app)
|
return ui.Run(renderer, style, app)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import (
|
|||||||
"opslag.de/schobers/zntg/ui"
|
"opslag.de/schobers/zntg/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// import "github.com/veandco/go-sdl2/sdl"
|
||||||
|
|
||||||
// Content shortcuts events when a dialog is opened.
|
// Content shortcuts events when a dialog is opened.
|
||||||
type Content struct {
|
type Content struct {
|
||||||
ui.Proxy
|
ui.Proxy
|
||||||
|
46
context.go
Normal file
46
context.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
// import (
|
||||||
|
// rice "github.com/GeertJohan/go.rice"
|
||||||
|
// "github.com/veandco/go-sdl2/sdl"
|
||||||
|
// )
|
||||||
|
|
||||||
|
// type Context struct {
|
||||||
|
// Renderer *sdl.Renderer
|
||||||
|
// Fonts Fonts
|
||||||
|
// Resources Resources
|
||||||
|
// Textures Textures
|
||||||
|
// Settings Settings
|
||||||
|
// MousePosition geom.Point
|
||||||
|
// ShouldQuit bool
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func NewContext(res *rice.Box) (ui.Context, error) {
|
||||||
|
// ctx := &Context{}
|
||||||
|
// err := ctx.Settings.Init()
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// err = ctx.Resources.Open(res)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// return ctx, nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (c ui.Context) Destroy() {
|
||||||
|
// c.Fonts.Destroy()
|
||||||
|
// c.Resources.Destroy()
|
||||||
|
// c.Textures.Destroy()
|
||||||
|
// c.Settings.Store()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (c ui.Context) Init(renderer *sdl.Renderer) {
|
||||||
|
// c.Renderer = renderer
|
||||||
|
// c.Fonts.Init(c.Resources.Copy())
|
||||||
|
// c.Textures.Init(renderer, c.Resources.Copy())
|
||||||
|
|
||||||
|
// c.Renderer.SetDrawBlendMode(sdl.BLENDMODE_BLEND)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (c ui.Context) Quit() { c.ShouldQuit = true }
|
46
fpsrenderer.go
Normal file
46
fpsrenderer.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
// import (
|
||||||
|
// "fmt"
|
||||||
|
// "time"
|
||||||
|
|
||||||
|
// "github.com/veandco/go-sdl2/sdl"
|
||||||
|
// )
|
||||||
|
|
||||||
|
// type FPS struct {
|
||||||
|
// ControlBase
|
||||||
|
|
||||||
|
// Show *bool
|
||||||
|
// start time.Time
|
||||||
|
// stamp time.Duration
|
||||||
|
// slot int
|
||||||
|
// ticks []int
|
||||||
|
// total int
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (f *FPS) Init(ui.Context) error {
|
||||||
|
// f.start = time.Now()
|
||||||
|
// f.stamp = 0
|
||||||
|
// f.ticks = make([]int, 51)
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (f *FPS) Render(ctx ui.Context) {
|
||||||
|
// if f.Show == nil || !*f.Show {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// elapsed := time.Since(f.start)
|
||||||
|
// stamp := elapsed / (20 * time.Millisecond)
|
||||||
|
// for f.stamp < stamp {
|
||||||
|
// f.total += f.ticks[f.slot]
|
||||||
|
// f.slot = (f.slot + 1) % len(f.ticks)
|
||||||
|
// f.total -= f.ticks[f.slot]
|
||||||
|
// f.ticks[f.slot] = 0
|
||||||
|
// f.stamp++
|
||||||
|
// }
|
||||||
|
// f.ticks[f.slot]++
|
||||||
|
|
||||||
|
// font := ctx.Fonts.Font("debug")
|
||||||
|
// font.RenderCopy(ctx.Renderer, fmt.Sprintf("FPS: %d", f.total), Pt(5, 17), sdl.Color{R: 255, G: 255, B: 255, A: 255})
|
||||||
|
// }
|
1
game.go
1
game.go
@ -163,7 +163,6 @@ func (g *Game) Load(ctx ui.Context) {
|
|||||||
}
|
}
|
||||||
g.Terrain.Center = state.View.Center
|
g.Terrain.Center = state.View.Center
|
||||||
g.centerChanged.Notify(ctx, g.Terrain.Center)
|
g.centerChanged.Notify(ctx, g.Terrain.Center)
|
||||||
g.setSpeed(ctx, state.Speed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) Pause(ctx ui.Context) { g.setSpeed(ctx, GameSpeedPaused) }
|
func (g *Game) Pause(ctx ui.Context) { g.setSpeed(ctx, GameSpeedPaused) }
|
||||||
|
@ -3,22 +3,19 @@ package tins2020
|
|||||||
import (
|
import (
|
||||||
"opslag.de/schobers/geom"
|
"opslag.de/schobers/geom"
|
||||||
"opslag.de/schobers/zntg"
|
"opslag.de/schobers/zntg"
|
||||||
"opslag.de/schobers/zntg/play"
|
|
||||||
"opslag.de/schobers/zntg/ui"
|
"opslag.de/schobers/zntg/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
const fpsOverlayName = "fps"
|
|
||||||
|
|
||||||
type GameControls struct {
|
type GameControls struct {
|
||||||
ui.ContainerBase
|
ui.ContainerBase
|
||||||
|
|
||||||
game *Game
|
game *Game
|
||||||
dialogs *Dialogs
|
dialogs *Dialogs
|
||||||
|
|
||||||
menu ui.StackPanel
|
menu ButtonBar
|
||||||
top ui.StackPanel
|
top ButtonBar
|
||||||
flowers ui.StackPanel
|
flowers ButtonBar
|
||||||
otherTools ui.StackPanel
|
otherTools ButtonBar
|
||||||
|
|
||||||
pause *IconButton
|
pause *IconButton
|
||||||
run *IconButton
|
run *IconButton
|
||||||
@ -33,7 +30,6 @@ func NewGameControls(game *Game, dialogs *Dialogs) *GameControls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *GameControls) Init(ctx ui.Context) {
|
func (c *GameControls) Init(ctx ui.Context) {
|
||||||
ctx.Overlays().AddOnTop(fpsOverlayName, &play.FPS{}, false)
|
|
||||||
c.game.SpeedChanged().AddHandler(c.speedChanged)
|
c.game.SpeedChanged().AddHandler(c.speedChanged)
|
||||||
c.game.ToolChanged().AddHandler(c.toolChanged)
|
c.game.ToolChanged().AddHandler(c.toolChanged)
|
||||||
c.dialogs.DialogOpened().AddHandlerEmpty(func(ctx ui.Context) { c.game.Pause(ctx) })
|
c.dialogs.DialogOpened().AddHandlerEmpty(func(ctx ui.Context) { c.game.Pause(ctx) })
|
||||||
@ -42,7 +38,8 @@ func (c *GameControls) Init(ctx ui.Context) {
|
|||||||
c.game.Resume(ctx)
|
c.game.Resume(ctx)
|
||||||
})
|
})
|
||||||
|
|
||||||
c.flowers.Background = zntg.MustHexColor("#356DAD")
|
c.flowers.Background = zntg.MustHexColor("#356dad")
|
||||||
|
c.flowers.ButtonLength = 64
|
||||||
|
|
||||||
for _, id := range c.game.Herbarium.Flowers() {
|
for _, id := range c.game.Herbarium.Flowers() {
|
||||||
c.flowers.Children = append(c.flowers.Children, c.createBuyFlowerButton(id))
|
c.flowers.Children = append(c.flowers.Children, c.createBuyFlowerButton(id))
|
||||||
@ -52,29 +49,29 @@ func (c *GameControls) Init(ctx ui.Context) {
|
|||||||
c.pause = NewIconButtonConfigure("control-pause", func(ctx ui.Context) {
|
c.pause = NewIconButtonConfigure("control-pause", func(ctx ui.Context) {
|
||||||
c.game.Pause(ctx)
|
c.game.Pause(ctx)
|
||||||
}, func(b *IconButton) {
|
}, func(b *IconButton) {
|
||||||
b.DisabledColor = ctx.Style().Palette.Secondary
|
b.IconDisabled = "control-pause-disabled"
|
||||||
b.Tooltip = "Pause game"
|
b.Tooltip = "Pause game"
|
||||||
})
|
})
|
||||||
c.run = NewIconButtonConfigure("control-run", func(ctx ui.Context) {
|
c.run = NewIconButtonConfigure("control-run", func(ctx ui.Context) {
|
||||||
c.game.Run(ctx)
|
c.game.Run(ctx)
|
||||||
}, func(b *IconButton) {
|
}, func(b *IconButton) {
|
||||||
b.DisabledColor = ctx.Style().Palette.Secondary
|
b.IconDisabled = "control-run-disabled"
|
||||||
b.Tooltip = "Run game at normal speed"
|
b.Tooltip = "Run game at normal speed"
|
||||||
})
|
})
|
||||||
c.runFast = NewIconButtonConfigure("control-run-fast", func(ctx ui.Context) {
|
c.runFast = NewIconButtonConfigure("control-run-fast", func(ctx ui.Context) {
|
||||||
c.game.RunFast(ctx)
|
c.game.RunFast(ctx)
|
||||||
}, func(b *IconButton) {
|
}, func(b *IconButton) {
|
||||||
b.DisabledColor = ctx.Style().Palette.Secondary
|
b.IconDisabled = "control-run-fast-disabled"
|
||||||
b.Tooltip = "Run game at fast speed"
|
b.Tooltip = "Run game at fast speed"
|
||||||
})
|
})
|
||||||
c.speedChanged(nil, c.game.Speed)
|
c.speedChanged(nil, c.game.Speed)
|
||||||
c.top.Children = []ui.Control{c.pause, c.run, c.runFast}
|
c.top.Children = []ui.Control{c.pause, c.run, c.runFast}
|
||||||
|
|
||||||
c.menu.Background = zntg.MustHexColor("#356DAD")
|
c.menu.Background = zntg.MustHexColor("#356dad")
|
||||||
c.menu.Children = []ui.Control{
|
c.menu.Children = []ui.Control{
|
||||||
NewIconButtonConfigure("control-settings", c.dialogs.ShowSettings, func(b *IconButton) {
|
NewIconButtonConfigure("control-settings", c.dialogs.ShowSettings, func(b *IconButton) {
|
||||||
b.Disabled = true
|
b.Disabled = true
|
||||||
b.DisabledColor = zntg.MustHexColor("#AFAFAF")
|
b.IconDisabled = "#afafaf"
|
||||||
}),
|
}),
|
||||||
NewIconButtonConfigure("control-save", func(ui.Context) { c.game.Save() }, func(b *IconButton) {
|
NewIconButtonConfigure("control-save", func(ui.Context) { c.game.Save() }, func(b *IconButton) {
|
||||||
b.Tooltip = "Save game (overwrites previous save; no confirmation)"
|
b.Tooltip = "Save game (overwrites previous save; no confirmation)"
|
||||||
@ -95,20 +92,16 @@ func (c *GameControls) Init(ctx ui.Context) {
|
|||||||
b.Tooltip = "Show information/intro"
|
b.Tooltip = "Show information/intro"
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
for i, child := range c.menu.Children {
|
|
||||||
c.menu.Children[i] = ui.FixedHeight(child, 96)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.shovel = NewIconButtonConfigure("control-shovel", func(ctx ui.Context) { c.game.SelectShovel(ctx) }, func(b *IconButton) {
|
c.shovel = NewIconButtonConfigure("control-shovel", func(ctx ui.Context) { c.game.SelectShovel(ctx) }, func(b *IconButton) {
|
||||||
|
b.IconHeight = 32
|
||||||
b.Tooltip = "Select harvest tool (key: H)"
|
b.Tooltip = "Select harvest tool (key: H)"
|
||||||
})
|
})
|
||||||
c.research = NewIconButtonConfigure("control-research", c.dialogs.ShowResearch, func(b *IconButton) {
|
c.research = NewIconButtonConfigure("control-research", c.dialogs.ShowResearch, func(b *IconButton) {
|
||||||
|
b.IconHeight = 32
|
||||||
b.Tooltip = "Conduct research (key: R)"
|
b.Tooltip = "Conduct research (key: R)"
|
||||||
})
|
})
|
||||||
c.otherTools.Children = []ui.Control{c.shovel, c.research}
|
c.otherTools.Children = []ui.Control{c.shovel, c.research}
|
||||||
for i, child := range c.otherTools.Children {
|
|
||||||
c.otherTools.Children[i] = ui.FixedHeight(child, 96)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.AddChild(&c.menu)
|
c.AddChild(&c.menu)
|
||||||
c.AddChild(&c.top)
|
c.AddChild(&c.top)
|
||||||
@ -147,11 +140,11 @@ func (c *GameControls) toolChanged(_ ui.Context, state interface{}) {
|
|||||||
}
|
}
|
||||||
for _, control := range c.flowers.Children {
|
for _, control := range c.flowers.Children {
|
||||||
button := control.(*BuyFlowerButton)
|
button := control.(*BuyFlowerButton)
|
||||||
button.Active = button.FlowerID == flowerID
|
button.IsActive = button.FlowerID == flowerID
|
||||||
button.Disabled = !c.game.Herbarium.IsUnlocked(button.FlowerID)
|
button.Disabled = !c.game.Herbarium.IsUnlocked(button.FlowerID)
|
||||||
}
|
}
|
||||||
_, shovel := tool.(*ShovelTool)
|
_, shovel := tool.(*ShovelTool)
|
||||||
c.shovel.Active = shovel
|
c.shovel.IsActive = shovel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GameControls) updateFlowerControls() {
|
func (c *GameControls) updateFlowerControls() {
|
||||||
@ -164,16 +157,13 @@ func (c *GameControls) updateFlowerControls() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttonBarWidth = 96
|
|
||||||
|
|
||||||
func (c *GameControls) Arrange(ctx ui.Context, bounds geom.RectangleF32, offset geom.PointF32, parent ui.Control) {
|
func (c *GameControls) Arrange(ctx ui.Context, bounds geom.RectangleF32, offset geom.PointF32, parent ui.Control) {
|
||||||
c.ContainerBase.Arrange(ctx, bounds, offset, parent)
|
c.ContainerBase.Arrange(ctx, bounds, offset, parent)
|
||||||
|
|
||||||
c.menu.Arrange(ctx, geom.RectRelF32(bounds.Min.X, bounds.Min.Y, buttonBarWidth, bounds.Dy()), offset, c)
|
c.menu.Arrange(ctx, geom.RectRelF32(bounds.Min.X, bounds.Min.Y, buttonBarWidth, bounds.Dy()), offset, c)
|
||||||
c.top.Arrange(ctx, geom.RectF32(bounds.Min.X+bounds.Dx()/2+8, bounds.Min.Y, bounds.Max.X, bounds.Min.Y+64), offset, c)
|
c.top.Arrange(ctx, geom.RectF32(bounds.Min.X+bounds.Dx()/2+8, bounds.Min.Y, bounds.Max.X, bounds.Min.Y+64), offset, c)
|
||||||
c.flowers.Arrange(ctx, geom.RectRelF32(bounds.Max.X-buttonBarWidth, bounds.Min.Y, buttonBarWidth, bounds.Dy()), offset, c)
|
c.flowers.Arrange(ctx, geom.RectRelF32(bounds.Max.X-buttonBarWidth, bounds.Min.Y, buttonBarWidth, bounds.Dy()), offset, c)
|
||||||
otherToolsSize := c.otherTools.DesiredSize(ctx, bounds.Size())
|
c.otherTools.Arrange(ctx, geom.RectRelF32(bounds.Max.X-buttonBarWidth, bounds.Max.Y-2*buttonBarWidth, buttonBarWidth, 2*buttonBarWidth), offset, c)
|
||||||
c.otherTools.Arrange(ctx, geom.RectRelF32(bounds.Max.X-buttonBarWidth, bounds.Max.Y-otherToolsSize.Y, buttonBarWidth, 2*buttonBarWidth), offset, c)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GameControls) Handle(ctx ui.Context, event ui.Event) bool {
|
func (c *GameControls) Handle(ctx ui.Context, event ui.Event) bool {
|
||||||
@ -201,18 +191,17 @@ func (c *GameControls) Handle(ctx ui.Context, event ui.Event) bool {
|
|||||||
c.game.CancelTool(ctx)
|
c.game.CancelTool(ctx)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
case ui.KeyF4:
|
case ui.KeyF3:
|
||||||
c.game.Debug = !c.game.Debug
|
c.game.Debug = !c.game.Debug
|
||||||
ctx.Overlays().Toggle(fpsOverlayName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *GameControls) Render(ctx ui.Context) {
|
func (c *GameControls) Render(ctx ui.Context) {
|
||||||
topBar := zntg.MustHexColor("#0000007F")
|
topBar := zntg.MustHexColor("#0000007f")
|
||||||
ctx.Renderer().FillRectangle(geom.RectF32(c.menu.Bounds().Max.X, 0, c.flowers.Bounds().Min.X, 64), topBar)
|
ctx.Renderer().FillRectangle(geom.RectF32(c.menu.Bounds().Max.X, 0, c.flowers.Bounds().Min.X, 64), topBar)
|
||||||
ctx.Fonts().TextAlign("balance", geom.PtF32(c.top.Bounds().Min.X-8, 4), zntg.MustHexColor("#4AC69A"), FmtMoney(c.game.Balance), ui.AlignRight)
|
ctx.Fonts().TextAlign("balance", geom.PtF32(c.top.Bounds().Min.X-8, 58), zntg.MustHexColor("#4AC69A"), FmtMoney(c.game.Balance), ui.AlignRight)
|
||||||
|
|
||||||
c.ContainerBase.Render(ctx)
|
c.ContainerBase.Render(ctx)
|
||||||
}
|
}
|
||||||
|
119
iconbutton.go
119
iconbutton.go
@ -1,29 +1,41 @@
|
|||||||
package tins2020
|
package tins2020
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image/color"
|
|
||||||
|
|
||||||
"opslag.de/schobers/zntg"
|
|
||||||
"opslag.de/schobers/zntg/ui"
|
"opslag.de/schobers/zntg/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// import (
|
||||||
|
// "github.com/veandco/go-sdl2/sdl"
|
||||||
|
// )
|
||||||
|
|
||||||
|
// type HoverEffect int
|
||||||
|
|
||||||
|
// const (
|
||||||
|
// HoverEffectLigthen HoverEffect = iota
|
||||||
|
// HoverEffectColor
|
||||||
|
// )
|
||||||
|
|
||||||
type IconButton struct {
|
type IconButton struct {
|
||||||
ui.Button
|
ui.Button
|
||||||
|
|
||||||
Active bool
|
IconDisabled string
|
||||||
|
// IconScale Scale
|
||||||
|
// IconWidth int32
|
||||||
|
|
||||||
|
// IconActive HoverEffect
|
||||||
|
// IconHover HoverEffect
|
||||||
|
|
||||||
|
// Tooltip Tooltip
|
||||||
|
IsActive bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIconButton(icon string, click ui.EventEmptyFn) *IconButton {
|
func NewIconButton(icon string, click ui.EventEmptyFn) *IconButton {
|
||||||
b := &IconButton{
|
b := &IconButton{
|
||||||
Button: ui.Button{
|
Button: ui.Button{
|
||||||
Icon: icon,
|
Icon: icon,
|
||||||
IconHeight: 48,
|
|
||||||
Type: ui.ButtonTypeText,
|
|
||||||
HoverColor: hoverTransparentColor,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
b.Font.Color = color.White
|
b.ControlClicked().AddHandler(func(ctx ui.Context, _ ui.ControlClickedArgs) { click(ctx) })
|
||||||
b.ButtonClicked().AddHandler(func(ctx ui.Context, _ ui.ControlClickedArgs) { click(ctx) })
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,15 +45,84 @@ func NewIconButtonConfigure(icon string, click ui.EventEmptyFn, configure func(*
|
|||||||
return button
|
return button
|
||||||
}
|
}
|
||||||
|
|
||||||
var hoverTransparentColor = zntg.MustHexColor(`#FFFFFF1F`)
|
// func (b *IconButton) activeTexture(ctx ui.Context) *Texture {
|
||||||
|
// if b.Disabled {
|
||||||
|
// texture := ctx.Textures.Texture(b.IconDisabled)
|
||||||
|
// if texture != nil {
|
||||||
|
// return texture
|
||||||
|
// }
|
||||||
|
|
||||||
func (b *IconButton) Render(ctx ui.Context) {
|
// texture = ctx.Textures.Texture(b.Icon)
|
||||||
b.RenderActive(ctx)
|
// if len(b.IconDisabled) == 0 {
|
||||||
b.Button.Render(ctx)
|
// return texture
|
||||||
}
|
// }
|
||||||
|
// color, err := HexColor(b.IconDisabled)
|
||||||
|
// if err == nil {
|
||||||
|
// texture.SetColor(color)
|
||||||
|
// }
|
||||||
|
// return texture
|
||||||
|
// }
|
||||||
|
// return ctx.Textures.Texture(b.Icon)
|
||||||
|
// }
|
||||||
|
|
||||||
func (b *IconButton) RenderActive(ctx ui.Context) {
|
// func (b *IconButton) Arrange(ctx ui.Context, bounds Rectangle) {
|
||||||
if b.Active && !b.Disabled && !b.IsOver() {
|
// b.ControlBase.Arrange(ctx, bounds)
|
||||||
ctx.Renderer().FillRectangle(b.Bounds(), hoverTransparentColor)
|
// b.Tooltip.Arrange(ctx, bounds)
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
|
// func (b *IconButton) Handle(ctx ui.Context, event sdl.Event) bool {
|
||||||
|
// if b.ControlBase.Handle(ctx, event) {
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
// if b.Tooltip.Handle(ctx, event) {
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (b *IconButton) Init(ctx ui.Context) error {
|
||||||
|
// if err := b.ControlBase.Init(ctx); err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// if err := b.Tooltip.Init(ctx); err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (b *IconButton) Render(ctx ui.Context) {
|
||||||
|
// iconTexture := b.activeTexture(ctx)
|
||||||
|
|
||||||
|
// hover := b.IsMouseOver && !b.Disabled
|
||||||
|
// if (hover && b.IconHover == HoverEffectColor) || (b.IsActive && b.IconActive == HoverEffectColor) {
|
||||||
|
// iconTexture.SetColor(MustHexColor("#15569F"))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if b.IconScale == ScaleCenter {
|
||||||
|
// size := iconTexture.Size()
|
||||||
|
// if b.IconWidth != 0 {
|
||||||
|
// size = Pt(b.IconWidth, b.IconWidth*size.Y/size.X)
|
||||||
|
// } else if b.IconHeight != 0 {
|
||||||
|
// size = Pt(b.IconHeight*size.X/size.Y, b.IconHeight)
|
||||||
|
// }
|
||||||
|
// iconTexture.CopyResize(ctx.Renderer, Rect(b.Bounds.X+(b.Bounds.W-size.X)/2, b.Bounds.Y+(b.Bounds.H-size.Y)/2, size.X, size.Y))
|
||||||
|
// } else {
|
||||||
|
// iconTexture.CopyResize(ctx.Renderer, b.Bounds)
|
||||||
|
// }
|
||||||
|
// if (hover && b.IconHover == HoverEffectLigthen) || (b.IsActive && b.IconActive == HoverEffectLigthen) {
|
||||||
|
// SetDrawColor(ctx.Renderer, TransparentWhite)
|
||||||
|
// ctx.Renderer.FillRect(b.Bounds.SDLPtr())
|
||||||
|
// }
|
||||||
|
// iconTexture.SetColor(White)
|
||||||
|
|
||||||
|
// if len(b.Tooltip.Text) > 0 && b.IsMouseOver {
|
||||||
|
// b.Tooltip.Render(ctx)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// type Scale int
|
||||||
|
|
||||||
|
// const (
|
||||||
|
// ScaleCenter Scale = iota
|
||||||
|
// ScaleStretch
|
||||||
|
// )
|
||||||
|
@ -8,8 +8,6 @@ import (
|
|||||||
"opslag.de/schobers/zntg/ui"
|
"opslag.de/schobers/zntg/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
const titleBarHeight = 64
|
|
||||||
|
|
||||||
type LargeDialog struct {
|
type LargeDialog struct {
|
||||||
ui.StackPanel
|
ui.StackPanel
|
||||||
|
|
||||||
@ -26,7 +24,7 @@ func NewLargeDialog(title string, content ui.Control) *LargeDialog {
|
|||||||
dialog.titleBar = NewLargeDialogTitleBar(title, func(ctx ui.Context, state interface{}) {
|
dialog.titleBar = NewLargeDialogTitleBar(title, func(ctx ui.Context, state interface{}) {
|
||||||
dialog.closeRequested.Notify(ctx, state)
|
dialog.closeRequested.Notify(ctx, state)
|
||||||
})
|
})
|
||||||
dialog.content.Content = ui.Margins(content, titleBarHeight, 20, titleBarHeight, 0)
|
dialog.content.Content = content
|
||||||
dialog.Children = []ui.Control{dialog.titleBar, &dialog.content}
|
dialog.Children = []ui.Control{dialog.titleBar, &dialog.content}
|
||||||
|
|
||||||
return dialog
|
return dialog
|
||||||
@ -34,6 +32,11 @@ func NewLargeDialog(title string, content ui.Control) *LargeDialog {
|
|||||||
|
|
||||||
func (d *LargeDialog) CloseRequested() ui.EventHandler { return &d.closeRequested }
|
func (d *LargeDialog) CloseRequested() ui.EventHandler { return &d.closeRequested }
|
||||||
|
|
||||||
|
// func (d *LargeDialog) Arrange(ctx ui.Context, bounds geom.RectangleF32, offset geom.PointF32, parent ui.Control) {
|
||||||
|
// d.titleBar.Arrange(ctx, bounds.Min.RectRel2D(bounds.Dx(), titleHeight), offset, d)
|
||||||
|
// d.content.Arrange(ctx, geom.RectRelF32(bounds.Min.X+titleHeight, bounds.Min.Y, bounds.Dx(), bounds.Dy()-titleHeight), offset, d)
|
||||||
|
// }
|
||||||
|
|
||||||
func (d *LargeDialog) Handle(ctx ui.Context, e ui.Event) bool {
|
func (d *LargeDialog) Handle(ctx ui.Context, e ui.Event) bool {
|
||||||
if d.StackPanel.Handle(ctx, e) {
|
if d.StackPanel.Handle(ctx, e) {
|
||||||
return true
|
return true
|
||||||
@ -83,7 +86,6 @@ func NewLargeDialogTitleBar(title string, closeRequested ui.EventFn) *LargeDialo
|
|||||||
titleBar.close.Icon = "control-cancel"
|
titleBar.close.Icon = "control-cancel"
|
||||||
titleBar.close.IconHeight = 32
|
titleBar.close.IconHeight = 32
|
||||||
titleBar.close.Type = ui.ButtonTypeIcon
|
titleBar.close.Type = ui.ButtonTypeIcon
|
||||||
titleBar.close.HoverColor = zntg.MustHexColor(`#ABCAED`)
|
|
||||||
|
|
||||||
return titleBar
|
return titleBar
|
||||||
}
|
}
|
||||||
@ -93,8 +95,10 @@ func (b *LargeDialogTitleBar) Arrange(ctx ui.Context, bounds geom.RectangleF32,
|
|||||||
b.title.Arrange(ctx, bounds, offset, parent)
|
b.title.Arrange(ctx, bounds, offset, parent)
|
||||||
height := bounds.Dy()
|
height := bounds.Dy()
|
||||||
b.close.Arrange(ctx, geom.RectRelF32(bounds.Max.X-height, bounds.Min.Y, height, height), offset, parent)
|
b.close.Arrange(ctx, geom.RectRelF32(bounds.Max.X-height, bounds.Min.Y, height, height), offset, parent)
|
||||||
|
b.close.HoverColor = ctx.Style().Palette.PrimaryDark
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *LargeDialogTitleBar) DesiredSize(ctx ui.Context, size geom.PointF32) geom.PointF32 {
|
func (b *LargeDialogTitleBar) DesiredSize(ctx ui.Context, size geom.PointF32) geom.PointF32 {
|
||||||
return geom.PtF32(size.X, titleBarHeight)
|
const titleHeight = 64
|
||||||
|
return geom.PtF32(size.X, titleHeight)
|
||||||
}
|
}
|
||||||
|
127
projection.go
Normal file
127
projection.go
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
import (
|
||||||
|
"opslag.de/schobers/geom"
|
||||||
|
"opslag.de/schobers/zntg/ui"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mapToTile(q geom.PointF32) geom.Point {
|
||||||
|
return geom.Pt(int(geom.Round32(q.X)), int(geom.Round32(q.Y)))
|
||||||
|
}
|
||||||
|
|
||||||
|
type projection struct {
|
||||||
|
center geom.PointF32
|
||||||
|
zoom float32
|
||||||
|
zoomInv float32
|
||||||
|
|
||||||
|
windowInteractRect geom.Rectangle
|
||||||
|
windowVisibleRect geom.Rectangle
|
||||||
|
tileScreenDelta geom.PointF32
|
||||||
|
tileScreenDeltaInv geom.PointF32
|
||||||
|
tileScreenOffset geom.Point
|
||||||
|
tileScreenSize geom.Point
|
||||||
|
tileFitScreenSize geom.Point
|
||||||
|
windowCenter geom.Point
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProjection() projection {
|
||||||
|
return projection{zoom: 1, tileScreenDelta: geom.PtF32(64, 32), tileScreenDeltaInv: geom.PtF32(1./64, 1./32)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) mapToScreen(x, y int) geom.Point {
|
||||||
|
return p.mapToScreenF(float32(x), float32(y))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) mapToScreenF(x, y float32) geom.Point {
|
||||||
|
translated := geom.PtF32(x-p.center.X, y-p.center.Y)
|
||||||
|
return geom.Pt(p.windowCenter.X+int((translated.X-translated.Y)*64*p.zoom), p.windowCenter.Y+int((translated.X+translated.Y)*32*p.zoom))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) screenToMap(x, y int) geom.PointF32 {
|
||||||
|
pos := p.screenToMapRel(x-p.windowCenter.X, y-p.windowCenter.Y)
|
||||||
|
return p.center.Add(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) screenToMapInt(x, y int) geom.Point {
|
||||||
|
pos := p.screenToMap(x, y)
|
||||||
|
return mapToTile(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) screenToMapRel(x, y int) geom.PointF32 {
|
||||||
|
normX := p.zoomInv * float32(x)
|
||||||
|
normY := p.zoomInv * float32(y)
|
||||||
|
return geom.PtF32(.5*(p.tileScreenDeltaInv.X*normX+p.tileScreenDeltaInv.Y*normY), .5*(-p.tileScreenDeltaInv.X*normX+p.tileScreenDeltaInv.Y*normY))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) screenToTileFitRect(pos geom.Point) geom.Rectangle {
|
||||||
|
return geom.RectRel(pos.X-p.tileFitScreenSize.X, pos.Y-p.tileFitScreenSize.Y, 2*p.tileFitScreenSize.X, 2*p.tileFitScreenSize.Y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) screenToTileRect(pos geom.Point) geom.Rectangle {
|
||||||
|
return geom.RectRel(pos.X-p.tileScreenOffset.X, pos.Y-p.tileScreenOffset.Y, p.tileScreenSize.X, p.tileScreenSize.Y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) update(renderer ui.Renderer) {
|
||||||
|
p.zoomInv = 1 / p.zoom
|
||||||
|
|
||||||
|
p.tileScreenOffset = geom.Pt(int(p.zoom*64), int(p.zoom*112))
|
||||||
|
p.tileScreenSize = geom.Pt(int(p.zoom*128), int(p.zoom*160))
|
||||||
|
p.tileFitScreenSize = geom.Pt(int(p.zoom*64), int(p.zoom*32))
|
||||||
|
|
||||||
|
windowF32 := renderer.Size()
|
||||||
|
window := geom.Pt(int(windowF32.X), int(windowF32.Y))
|
||||||
|
p.windowCenter = geom.Pt(window.X/2, window.Y/2)
|
||||||
|
p.windowInteractRect = geom.Rect(buttonBarWidth, 64, window.X-buttonBarWidth, window.Y)
|
||||||
|
p.windowVisibleRect = geom.Rect(buttonBarWidth, 0, window.X-buttonBarWidth, window.Y+p.tileScreenSize.Y) // Adding a tile height to the bottom for trees that stick out from the cells below.
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) visibleTiles(action func(int, int, geom.Point)) {
|
||||||
|
visible := p.windowVisibleRect
|
||||||
|
topLeft := p.screenToMap(visible.Min.X, visible.Min.Y)
|
||||||
|
topRight := p.screenToMap(visible.Max.X, visible.Min.Y)
|
||||||
|
bottomLeft := p.screenToMap(visible.Min.X, visible.Max.Y)
|
||||||
|
bottomRight := p.screenToMap(visible.Max.Y, visible.Max.Y)
|
||||||
|
minY, maxY := int(Floor32(topRight.Y)), int(Ceil32(bottomLeft.Y))
|
||||||
|
minX, maxX := int(Floor32(topLeft.X)), int(Ceil32(bottomRight.X))
|
||||||
|
for y := minY; y <= maxY; y++ {
|
||||||
|
for x := minX; x <= maxX; x++ {
|
||||||
|
pos := p.mapToScreen(x, y)
|
||||||
|
rectFit := p.screenToTileFitRect(pos)
|
||||||
|
if rectFit.Max.X < visible.Min.X || rectFit.Max.Y < visible.Min.Y {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if rectFit.Min.X > visible.Max.X || rectFit.Min.Y > visible.Max.Y {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
action(x, y, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) Pan(ctx ui.Context, delta geom.PointF32) {
|
||||||
|
p.center = p.center.Add(delta.Mul(p.zoomInv))
|
||||||
|
p.update(ctx.Renderer())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) SetZoom(ctx ui.Context, center geom.PointF32, zoom float32) {
|
||||||
|
if p.zoom == zoom {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.center = center.Sub(center.Sub(p.center).Mul(p.zoom / zoom))
|
||||||
|
p.zoom = zoom
|
||||||
|
p.update(ctx.Renderer())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) ZoomOut(ctx ui.Context, center geom.PointF32) {
|
||||||
|
if p.zoom <= .25 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.SetZoom(ctx, center, .5*p.zoom)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *projection) ZoomIn(ctx ui.Context, center geom.PointF32) {
|
||||||
|
if p.zoom >= 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
p.SetZoom(ctx, center, 2*p.zoom)
|
||||||
|
}
|
48
proxy.go
Normal file
48
proxy.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package tins2020
|
||||||
|
|
||||||
|
// import "github.com/veandco/go-sdl2/sdl"
|
||||||
|
|
||||||
|
// var _ Control = &Proxy{}
|
||||||
|
|
||||||
|
// type Proxy struct {
|
||||||
|
// Proxied Control
|
||||||
|
|
||||||
|
// bounds Rectangle
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (p *Proxy) Arrange(ctx ui.Context, bounds Rectangle) {
|
||||||
|
// p.bounds = bounds
|
||||||
|
// if p.Proxied == nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// p.Proxied.Arrange(ctx, bounds)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (p *Proxy) Handle(ctx ui.Context, event sdl.Event) bool {
|
||||||
|
// if p.Proxied == nil {
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// return p.Proxied.Handle(ctx, event)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (p *Proxy) Init(ctx ui.Context) error {
|
||||||
|
// if p.Proxied == nil {
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
// return p.Proxied.Init(ctx)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (p *Proxy) Render(ctx ui.Context) {
|
||||||
|
// if p.Proxied == nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// p.Proxied.Render(ctx)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (p *Proxy) SetContent(ctx ui.Context, content Control) {
|
||||||
|
// p.Proxied = content
|
||||||
|
// if content == nil {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// content.Arrange(ctx, p.bounds)
|
||||||
|
// }
|
@ -57,6 +57,10 @@ type Specialist struct {
|
|||||||
func (r *Research) Arrange(ctx ui.Context, bounds geom.RectangleF32, offset geom.PointF32, parent ui.Control) {
|
func (r *Research) Arrange(ctx ui.Context, bounds geom.RectangleF32, offset geom.PointF32, parent ui.Control) {
|
||||||
r.input.TextAlignment = ui.AlignCenter
|
r.input.TextAlignment = ui.AlignCenter
|
||||||
r.StackPanel.Arrange(ctx, bounds, offset, parent)
|
r.StackPanel.Arrange(ctx, bounds, offset, parent)
|
||||||
|
|
||||||
|
// size := bounds.Size()
|
||||||
|
// r.specialists.Arrange(ctx, geom.RectRelF32(bounds.Min.X, bounds.Min.Y+40, size.X, size.Y-40), offset, r)
|
||||||
|
// r.input.Arrange(ctx, geom.RectRelF32(bounds.Min.X, bounds.Min.X+size.Y-48, size.X, 24), offset, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Research) CanUserType(digit int) bool {
|
func (r *Research) CanUserType(digit int) bool {
|
||||||
|
@ -3,8 +3,6 @@ package tins2020
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"opslag.de/schobers/zntg/play"
|
|
||||||
|
|
||||||
"opslag.de/schobers/geom"
|
"opslag.de/schobers/geom"
|
||||||
"opslag.de/schobers/zntg/ui"
|
"opslag.de/schobers/zntg/ui"
|
||||||
)
|
)
|
||||||
@ -14,40 +12,43 @@ type terrainRenderer struct {
|
|||||||
|
|
||||||
game *Game
|
game *Game
|
||||||
hover *geom.Point
|
hover *geom.Point
|
||||||
viewBounds geom.RectangleF32
|
project projection
|
||||||
interactBounds geom.RectangleF32
|
|
||||||
isometric *play.IsometricProjection
|
|
||||||
|
|
||||||
drag ui.Dragable
|
drag ui.Dragable
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTerrainRenderer(game *Game) ui.Control {
|
func NewTerrainRenderer(game *Game) ui.Control {
|
||||||
renderer := &terrainRenderer{game: game, isometric: play.NewIsometricProjection(geom.PtF32(128, 64), geom.RectF32(0, 0, 100, 100))}
|
renderer := &terrainRenderer{game: game, project: newProjection()}
|
||||||
|
|
||||||
renderer.game.CenterChanged().AddHandler(func(ctx ui.Context, state interface{}) {
|
renderer.game.CenterChanged().AddHandler(func(ctx ui.Context, state interface{}) {
|
||||||
center := state.(geom.Point)
|
center := state.(geom.Point)
|
||||||
renderer.isometric.MoveCenterTo(center.ToF32())
|
renderer.project.center = center.ToF32()
|
||||||
|
renderer.project.update(ctx.Renderer())
|
||||||
})
|
})
|
||||||
|
// renderer.project.update(ctx.Renderer)
|
||||||
return renderer
|
return renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *terrainRenderer) Arrange(ctx ui.Context, bounds geom.RectangleF32, _ geom.PointF32, _ ui.Control) {
|
func (r *terrainRenderer) Arrange(ctx ui.Context, _ geom.RectangleF32, _ geom.PointF32, _ ui.Control) {
|
||||||
r.viewBounds = geom.RectF32(buttonBarWidth, 0, bounds.Dx()-buttonBarWidth, bounds.Dy())
|
r.project.update(ctx.Renderer())
|
||||||
r.isometric.SetViewBounds(r.viewBounds)
|
}
|
||||||
r.interactBounds = r.viewBounds
|
|
||||||
r.interactBounds.Min.Y += 64
|
func (r *terrainRenderer) Init(ctx ui.Context) error {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isControlKeyDown(ctx ui.Context) bool {
|
func isControlKeyDown(ctx ui.Context) bool {
|
||||||
modifiers := ctx.KeyModifiers()
|
return false
|
||||||
return modifiers&(ui.KeyModifierControl|ui.KeyModifierOSCommand) != 0
|
// ctx.MousePosition()
|
||||||
|
// state := ui.GetKeyboardState()
|
||||||
|
// return state[ui.SCANCODE_LCTRL] == 1 || state[ui.SCANCODE_RCTRL] == 1 || state[ui.SCANCODE_LGUI] == 1 || state[ui.SCANCODE_RGUI] == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *terrainRenderer) Handle(ctx ui.Context, event ui.Event) bool {
|
func (r *terrainRenderer) Handle(ctx ui.Context, event ui.Event) bool {
|
||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *ui.MouseButtonDownEvent:
|
case *ui.MouseButtonDownEvent:
|
||||||
pos := e.Pos()
|
pos := e.Pos()
|
||||||
if pos.In(r.interactBounds) {
|
if pos.ToInt().In(r.project.windowInteractRect) {
|
||||||
controlKeyDown := isControlKeyDown(ctx)
|
controlKeyDown := isControlKeyDown(ctx)
|
||||||
if e.Button == ui.MouseButtonMiddle || (e.Button == ui.MouseButtonLeft && controlKeyDown) {
|
if e.Button == ui.MouseButtonMiddle || (e.Button == ui.MouseButtonLeft && controlKeyDown) {
|
||||||
if _, ok := r.drag.IsDragging(); !ok {
|
if _, ok := r.drag.IsDragging(); !ok {
|
||||||
@ -55,7 +56,7 @@ func (r *terrainRenderer) Handle(ctx ui.Context, event ui.Event) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if e.Button == ui.MouseButtonLeft && !controlKeyDown {
|
if e.Button == ui.MouseButtonLeft && !controlKeyDown {
|
||||||
pos := r.isometric.ViewToTileInt(pos)
|
pos := r.project.screenToMapInt(int(e.X), int(e.Y))
|
||||||
r.game.UserClickedTile(pos)
|
r.game.UserClickedTile(pos)
|
||||||
}
|
}
|
||||||
if e.Button == ui.MouseButtonRight {
|
if e.Button == ui.MouseButtonRight {
|
||||||
@ -63,67 +64,68 @@ func (r *terrainRenderer) Handle(ctx ui.Context, event ui.Event) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ui.MouseButtonUpEvent:
|
case *ui.MouseButtonUpEvent:
|
||||||
pos := e.Pos()
|
pos := e.Pos().ToInt()
|
||||||
if pos.In(r.interactBounds) {
|
if pos.In(r.project.windowInteractRect) {
|
||||||
if _, ok := r.drag.IsDragging(); ok {
|
if _, ok := r.drag.IsDragging(); ok {
|
||||||
r.game.Terrain.Center = r.isometric.TileInt(r.isometric.Center())
|
r.game.Terrain.Center = mapToTile(r.project.center)
|
||||||
r.drag.Cancel()
|
r.drag.Cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ui.MouseMoveEvent:
|
case *ui.MouseMoveEvent:
|
||||||
pos := e.Pos()
|
pos := e.Pos()
|
||||||
if pos.In(r.interactBounds) {
|
if pos.ToInt().In(r.project.windowInteractRect) {
|
||||||
hover := r.isometric.ViewToTileInt(pos)
|
hover := r.project.screenToMapInt(int(e.X), int(e.Y))
|
||||||
r.hover = &hover
|
r.hover = &hover
|
||||||
} else {
|
} else {
|
||||||
r.hover = nil
|
r.hover = nil
|
||||||
}
|
}
|
||||||
if _, ok := r.drag.IsDragging(); ok {
|
if _, ok := r.drag.IsDragging(); ok {
|
||||||
delta, _ := r.drag.Move(pos)
|
delta, _ := r.drag.Move(pos)
|
||||||
r.isometric.Pan(r.isometric.ViewToTileRelative(delta.Invert()))
|
r.project.center = r.project.center.Sub(r.project.screenToMapRel(int(delta.X), int(delta.Y)))
|
||||||
|
r.project.update(ctx.Renderer())
|
||||||
}
|
}
|
||||||
if r.hover != nil {
|
if r.hover != nil {
|
||||||
if e.MouseWheel < 0 {
|
if e.Y < 0 {
|
||||||
r.isometric.ZoomOut(r.hover.ToF32())
|
r.project.ZoomOut(ctx, r.hover.ToF32())
|
||||||
} else if e.MouseWheel > 0 {
|
} else {
|
||||||
r.isometric.ZoomIn(r.hover.ToF32())
|
r.project.ZoomIn(ctx, r.hover.ToF32())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ui.MouseLeaveEvent:
|
case *ui.MouseLeaveEvent:
|
||||||
r.hover = nil
|
r.hover = nil
|
||||||
|
r.project.update(ctx.Renderer())
|
||||||
case *ui.KeyDownEvent:
|
case *ui.KeyDownEvent:
|
||||||
switch e.Key {
|
switch e.Key {
|
||||||
case ui.KeyPadPlus:
|
case ui.KeyPadPlus:
|
||||||
r.isometric.ZoomIn(r.isometric.Center())
|
r.project.ZoomIn(ctx, r.project.center)
|
||||||
case ui.KeyMinus:
|
case ui.KeyMinus:
|
||||||
r.isometric.ZoomOut(r.isometric.Center())
|
r.project.ZoomOut(ctx, r.project.center)
|
||||||
case ui.KeyPadMinus:
|
case ui.KeyPadMinus:
|
||||||
r.isometric.ZoomOut(r.isometric.Center())
|
r.project.ZoomOut(ctx, r.project.center)
|
||||||
case ui.KeyW:
|
case ui.KeyW:
|
||||||
r.isometric.Pan(geom.PtF32(-1, -1))
|
r.project.Pan(ctx, geom.PtF32(-1, -1))
|
||||||
case ui.KeyA:
|
case ui.KeyA:
|
||||||
r.isometric.Pan(geom.PtF32(-1, 1))
|
r.project.Pan(ctx, geom.PtF32(-1, 1))
|
||||||
case ui.KeyS:
|
case ui.KeyS:
|
||||||
r.isometric.Pan(geom.PtF32(1, 1))
|
r.project.Pan(ctx, geom.PtF32(1, 1))
|
||||||
case ui.KeyD:
|
case ui.KeyD:
|
||||||
r.isometric.Pan(geom.PtF32(1, -1))
|
r.project.Pan(ctx, geom.PtF32(1, -1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *terrainRenderer) Render(ctx ui.Context) {
|
func (r *terrainRenderer) Render(ctx ui.Context) {
|
||||||
zoom := r.isometric.Zoom()
|
|
||||||
terrain := r.game.Terrain
|
terrain := r.game.Terrain
|
||||||
toTileTexture := func(tile geom.Point) ui.Texture {
|
toTileTexture := func(x, y int) ui.Texture {
|
||||||
temp := terrain.Temp.Value(tile.X, tile.Y)
|
temp := terrain.Temp.Value(x, y)
|
||||||
if temp < .35 {
|
if temp < .35 {
|
||||||
return ctx.Textures().ScaledByName("tile-snow", zoom)
|
return ctx.Textures().Texture("tile-snow")
|
||||||
}
|
}
|
||||||
if temp > .65 {
|
if temp > .65 {
|
||||||
return ctx.Textures().ScaledByName("tile-dirt", zoom)
|
return ctx.Textures().Texture("tile-dirt")
|
||||||
}
|
}
|
||||||
return ctx.Textures().ScaledByName("tile-grass", zoom)
|
return ctx.Textures().Texture("tile-grass")
|
||||||
}
|
}
|
||||||
|
|
||||||
variantToInt := func(variant float64) int {
|
variantToInt := func(variant float64) int {
|
||||||
@ -144,8 +146,9 @@ func (r *terrainRenderer) Render(ctx ui.Context) {
|
|||||||
|
|
||||||
variantToTexture := func(format string, variant float64) ui.Texture {
|
variantToTexture := func(format string, variant float64) ui.Texture {
|
||||||
textName := fmt.Sprintf(format, variantToInt(variant))
|
textName := fmt.Sprintf(format, variantToInt(variant))
|
||||||
return ctx.Textures().ScaledByName(textName, zoom)
|
return ctx.Textures().Texture(textName)
|
||||||
}
|
}
|
||||||
|
|
||||||
stretch := func(x, from, to float64) float64 { return (x - from) * 1 / (to - from) }
|
stretch := func(x, from, to float64) float64 { return (x - from) * 1 / (to - from) }
|
||||||
|
|
||||||
toPropTexture := func(temp, humid, variant float64) ui.Texture {
|
toPropTexture := func(temp, humid, variant float64) ui.Texture {
|
||||||
@ -183,7 +186,7 @@ func (r *terrainRenderer) Render(ctx ui.Context) {
|
|||||||
flower, ok := terrain.Flowers[geom.Pt(x, y)]
|
flower, ok := terrain.Flowers[geom.Pt(x, y)]
|
||||||
if ok {
|
if ok {
|
||||||
desc, _ := r.game.Herbarium.Find(flower.ID)
|
desc, _ := r.game.Herbarium.Find(flower.ID)
|
||||||
return ctx.Textures().ScaledByName(desc.IconTemplate.Variant(variantToInt(variant)), zoom)
|
return ctx.Textures().Texture(desc.IconTemplate.Variant(variantToInt(variant)))
|
||||||
}
|
}
|
||||||
temp := terrain.Temp.Value(x, y)
|
temp := terrain.Temp.Value(x, y)
|
||||||
humid := terrain.Humid.Value(x, y)
|
humid := terrain.Humid.Value(x, y)
|
||||||
@ -194,35 +197,25 @@ func (r *terrainRenderer) Render(ctx ui.Context) {
|
|||||||
// vertical (tile): [96,160) = 64
|
// vertical (tile): [96,160) = 64
|
||||||
// vertical (total): [0,160) = 160
|
// vertical (total): [0,160) = 160
|
||||||
|
|
||||||
topLeft := geom.PtF32(-64*zoom, -112*zoom)
|
r.project.visibleTiles(func(x, y int, pos geom.Point) {
|
||||||
bottomRight := geom.PtF32(64*zoom, 48*zoom)
|
text := toTileTexture(x, y)
|
||||||
textureRect := func(center geom.PointF32) geom.RectangleF32 {
|
rect := r.project.screenToTileRect(pos)
|
||||||
return geom.RectangleF32{Min: center.Add(topLeft), Max: center.Add(bottomRight)}
|
ctx.Renderer().DrawTexture(text, rect.ToF32())
|
||||||
}
|
|
||||||
hoverTexture := ctx.Textures().ScaledByName("tile-hover", zoom)
|
|
||||||
|
|
||||||
r.isometric.EnumerateInt(func(tile geom.Point, view geom.PointF32) {
|
if r.hover != nil && x == r.hover.X && y == r.hover.Y {
|
||||||
text := toTileTexture(tile)
|
ctx.Renderer().DrawTexture(ctx.Textures().Texture("tile-hover"), rect.ToF32())
|
||||||
rect := textureRect(view)
|
|
||||||
ctx.Renderer().DrawTexture(text, rect)
|
|
||||||
// if r.game.Debug {
|
|
||||||
// ctx.Renderer().FillRectangle(view.Add2D(-1, -1).RectRel2D(2, 2), color.White)
|
|
||||||
// ctx.Fonts().TextAlign("debug", view, color.White, fmt.Sprintf("%d, %d", tile.X, tile.Y), ui.AlignCenter)
|
|
||||||
// }
|
|
||||||
if r.hover != nil && tile.X == r.hover.X && tile.Y == r.hover.Y {
|
|
||||||
ctx.Renderer().DrawTexture(hoverTexture, rect)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
r.isometric.EnumerateInt(func(tile geom.Point, view geom.PointF32) {
|
r.project.visibleTiles(func(x, y int, pos geom.Point) {
|
||||||
text := toItemTexture(tile.X, tile.Y)
|
text := toItemTexture(x, y)
|
||||||
if text == nil {
|
if text == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
placeX, placeY := terrain.PlaceX.Value(tile.X, tile.Y), terrain.PlaceY.Value(tile.X, tile.Y)
|
placeX, placeY := terrain.PlaceX.Value(x, y), terrain.PlaceY.Value(x, y)
|
||||||
displaced := r.isometric.TileToView(tile.ToF32().Add2D(-.2+.9*float32(placeX)-.45, -.2+.9*float32(placeY)-.45))
|
pos = r.project.mapToScreenF(float32(x)-.2+float32(.9*placeX-.45), float32(y)-.2+float32(.9*placeY-.45))
|
||||||
rect := textureRect(displaced)
|
rect := r.project.screenToTileRect(pos)
|
||||||
ctx.Renderer().DrawTexture(text, rect)
|
ctx.Renderer().DrawTexture(text, rect.ToF32())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user