From 3fbfbcf2fc0845451e0bf5e31e7e28b34be27082 Mon Sep 17 00:00:00 2001 From: olebeck <31539311+olebeck@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:32:18 +0100 Subject: [PATCH] add a basic zoom and pan --- subcommands/world/map_item.go | 1 + ui/gui/pages/worlds/map.go | 71 +++++++++++++++++++++++++++-------- ui/gui/pages/worlds/worlds.go | 4 +- utils/messages.go | 1 + 4 files changed, 61 insertions(+), 16 deletions(-) diff --git a/subcommands/world/map_item.go b/subcommands/world/map_item.go index ebbc71f..3676568 100644 --- a/subcommands/world/map_item.go +++ b/subcommands/world/map_item.go @@ -232,6 +232,7 @@ func (m *MapUI) Redraw() { min, max := m.GetBounds() m.w.gui.Message(utils.UpdateMapName, utils.UpdateMapPayload{ ChunkCount: ChunkCount, + Rotation: m.w.PlayerPos.Yaw, UpdatedTiles: updatedChunks, Tiles: m.renderedChunks, BoundsMin: min, diff --git a/ui/gui/pages/worlds/map.go b/ui/gui/pages/worlds/map.go index 022dff9..b4c5ebf 100644 --- a/ui/gui/pages/worlds/map.go +++ b/ui/gui/pages/worlds/map.go @@ -3,41 +3,76 @@ package worlds import ( "image" "image/draw" + "time" + "gioui.org/f32" + "gioui.org/gesture" "gioui.org/io/pointer" "gioui.org/layout" + "gioui.org/op" "gioui.org/op/paint" - "gioui.org/widget" "github.com/bedrock-tool/bedrocktool/utils" "github.com/sandertv/gophertunnel/minecraft/protocol" ) type Map struct { - pressed bool + click f32.Point + mapPos f32.Point + pos f32.Point + imageOp paint.ImageOp + zoom float32 + + drag gesture.Drag + scroll gesture.Scroll MapImage *image.RGBA BoundsMin protocol.ChunkPos BoundsMax protocol.ChunkPos + Rotation float32 } func (m *Map) Layout(gtx layout.Context) layout.Dimensions { // here we loop through all the events associated with this button. - for _, e := range gtx.Events(m) { - if e, ok := e.(pointer.Event); ok { - switch e.Type { - case pointer.Press: - m.pressed = true - case pointer.Release: - m.pressed = false - } + for _, e := range m.drag.Events(gtx.Metric, gtx.Queue, gesture.Both) { + switch e.Type { + case pointer.Press: + m.click = e.Position + case pointer.Drag: + m.pos = m.mapPos.Sub(m.click).Add(e.Position) + case pointer.Release: + m.mapPos = m.pos } } - return layout.Center.Layout(gtx, widget.Image{ - Src: paint.NewImageOp(m.MapImage), - Fit: widget.Contain, - Position: layout.Center, - }.Layout) + scrollDist := m.scroll.Scroll(gtx.Metric, gtx.Queue, time.Now(), gesture.Vertical) + + m.zoom -= float32(scrollDist) / 20 + if m.zoom < 0.2 { + m.zoom = 0.2 + } + + size := gtx.Constraints.Max + + if m.MapImage != nil { + m.imageOp.Add(gtx.Ops) + b := m.MapImage.Bounds() + sx := float32(b.Dx() / 2) + sy := float32(b.Dy() / 2) + + op.Affine( + f32.Affine2D{}. + Scale(f32.Pt(sx, sy), f32.Pt(m.zoom, m.zoom)). + Offset(m.pos), + ).Add(gtx.Ops) + paint.PaintOp{}.Add(gtx.Ops) + } + + m.drag.Add(gtx.Ops) + m.scroll.Add(gtx.Ops, image.Rect(-size.X, -size.Y, size.X, size.Y)) + + return layout.Dimensions{ + Size: size, + } } func drawTile(img *image.RGBA, min, pos protocol.ChunkPos, tile *image.RGBA) { @@ -52,6 +87,10 @@ func drawTile(img *image.RGBA, min, pos protocol.ChunkPos, tile *image.RGBA) { } func (m *Map) Update(u *utils.UpdateMapPayload) { + if m.MapImage == nil { + m.zoom = 1 + } + needNewImage := false if m.BoundsMin != u.BoundsMin { needNewImage = true @@ -75,4 +114,6 @@ func (m *Map) Update(u *utils.UpdateMapPayload) { drawTile(m.MapImage, m.BoundsMin, pos, tile) } } + + m.imageOp = paint.NewImageOp(m.MapImage) } diff --git a/ui/gui/pages/worlds/worlds.go b/ui/gui/pages/worlds/worlds.go index 25fa43e..b3ae910 100644 --- a/ui/gui/pages/worlds/worlds.go +++ b/ui/gui/pages/worlds/worlds.go @@ -71,7 +71,9 @@ func (p *Page) Layout(gtx C, th *material.Theme) D { Axis: layout.Vertical, }.Layout(gtx, layout.Rigid(material.Label(th, 20, "World Downloader Basic UI").Layout), - layout.Flexed(1, p.worldMap.Layout), + layout.Flexed(1, func(gtx layout.Context) layout.Dimensions { + return layout.Center.Layout(gtx, p.worldMap.Layout) + }), ) }) } diff --git a/utils/messages.go b/utils/messages.go index 1482ee0..c6e5a71 100644 --- a/utils/messages.go +++ b/utils/messages.go @@ -40,6 +40,7 @@ var UpdateMapName = "update_map" type UpdateMapPayload struct { ChunkCount int + Rotation float32 UpdatedTiles []protocol.ChunkPos Tiles map[protocol.ChunkPos]*image.RGBA BoundsMin protocol.ChunkPos