summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.go19
-rw-r--r--tools.go81
2 files changed, 88 insertions, 12 deletions
diff --git a/main.go b/main.go
index b300034..9d432db 100644
--- a/main.go
+++ b/main.go
@@ -7,17 +7,12 @@ import (
"github.com/mattn/go-gtk/gtk"
)
-type tool int
-
-const (
- ToolDraw tool = iota
- ToolFill
-)
-
type GUI struct {
window *gtk.Window
statusbar *gtk.Statusbar
showbiomes *gtk.CheckButton
+
+ tool Tool
}
func (g *GUI) openWorldDlg() {
@@ -145,7 +140,7 @@ func (g *GUI) mkToolbox() *gtk.ScrolledWindow {
fill := gtk.NewRadioButtonWithLabel(nil, "Fill")
fill.SetActive(true)
- fill.Connect("toggled", g.mkUpdateToolFx(fill, ToolFill))
+ fill.Connect("toggled", g.mkUpdateToolFx(fill, NewFillTool()))
draw := gtk.NewRadioButtonWithLabel(fill.GetGroup(), "Draw")
drawRadius := gtk.NewSpinButtonWithRange(1, 20, 1)
@@ -153,7 +148,7 @@ func (g *GUI) mkToolbox() *gtk.ScrolledWindow {
drawHBox.PackStart(draw, true, true, 3)
drawHBox.PackStart(gtk.NewLabel("Radius:"), false, false, 3)
drawHBox.PackEnd(drawRadius, false, false, 3)
- draw.Connect("toggled", g.mkUpdateToolFx(draw, ToolDraw))
+ draw.Connect("toggled", g.mkUpdateToolFx(draw, NewDrawTool(func() int { return int(drawRadius.GetValue()) })))
vbox.PackStart(fill, false, false, 3)
vbox.PackStart(drawHBox, false, false, 3)
@@ -206,7 +201,7 @@ func (g *GUI) Init() {
g.window.Connect("destroy", g.exitApp)
}
-func (g *GUI) mkUpdateToolFx(rb *gtk.RadioButton, t tool) func() {
+func (g *GUI) mkUpdateToolFx(rb *gtk.RadioButton, t Tool) func() {
return func() {
if rb.GetActive() {
g.setTool(t)
@@ -222,8 +217,8 @@ func (g *GUI) mkUpdateBiomeFx(rb *gtk.RadioButton, bio mcmap.Biome) func() {
}
}
-func (g *GUI) setTool(t tool) {
- fmt.Printf("Tool %d\n", t)
+func (g *GUI) setTool(t Tool) {
+ g.tool = t
}
func (g *GUI) setBiome(bio mcmap.Biome) {
diff --git a/tools.go b/tools.go
new file mode 100644
index 0000000..ffb763a
--- /dev/null
+++ b/tools.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "github.com/kch42/gomcmap/mcmap"
+)
+
+type BiomeGetter interface {
+ GetBiome(x, z int) (mcmap.Biome, bool)
+}
+
+type XZPos struct {
+ X, Z int
+}
+
+type Change map[XZPos]mcmap.Biome
+
+type Tool interface {
+ SingleClick() bool // Whether only one click should be performed (true) or the action should be repeated, if the mouse is dragged
+ Do(bio mcmap.Biome, bioget BiomeGetter, x, z int) Change
+}
+
+type drawTool struct {
+ radGetter func() int
+}
+
+func (d *drawTool) SingleClick() bool { return false }
+
+func (d *drawTool) Do(bio mcmap.Biome, bioget BiomeGetter, x, z int) Change {
+ rad := d.radGetter()
+ if rad <= 0 {
+ return nil
+ }
+
+ change := make(Change)
+ for xp := x - (rad - 1); xp < x+rad; xp++ {
+ for zp := z - (rad - 1); zp < z+rad; zp++ {
+ change[XZPos{xp, zp}] = bio
+ }
+ }
+
+ return change
+}
+
+func NewDrawTool(radGetter func() int) *drawTool {
+ return &drawTool{radGetter}
+}
+
+type fillTool struct{}
+
+func (f *fillTool) SingleClick() bool { return true }
+
+func (f *fillTool) Do(bio mcmap.Biome, bioget BiomeGetter, x, z int) Change {
+ oldbio, ok := bioget.GetBiome(x, z)
+ if !ok {
+ return nil
+ }
+
+ change := make(Change)
+ floodfill(oldbio, bio, bioget, x, z, change)
+ return change
+}
+
+func floodfill(oldbio, newbio mcmap.Biome, bioget BiomeGetter, x, z int, change Change) {
+ pos := XZPos{x, z}
+ if _, ok := change[pos]; ok {
+ return
+ }
+
+ if bio, ok := bioget.GetBiome(x, z); ok && (bio == oldbio) {
+ change[pos] = newbio
+
+ floodfill(oldbio, newbio, bioget, x-1, z, change)
+ floodfill(oldbio, newbio, bioget, x+1, z, change)
+ floodfill(oldbio, newbio, bioget, x, z-1, change)
+ floodfill(oldbio, newbio, bioget, x, z+1, change)
+ }
+}
+
+func NewFillTool() *fillTool {
+ return new(fillTool)
+}