Layer Selection Window for Doodad Editor
* When editing a doodad in the Editor Mode, the toolbar has a "Lyr." button that opens the Layers window. * The Layers window allows switching the active doodad layer that you are drawing on, as well as create and rename layers. * With this feature, Doodads may be fully drawn in-game, including adding alternate named layers for animations and multiple-state doodads. * Update the Pager component to have a configurable MaxPageButtons. Controls that have more pages than this limit will stop having buttons drawn after the limit. The "Forward" and "Next" buttons can still navigate into the extra pages. * Refactored and centralized the various popup windows in Editor Mode into editor_ui_popups.go; the SetupPopups() and various methods such as ShowPaletteWindow() and ShowDoodadDropper() make management of popups simple for the editor_ui! * The Menu Bar in Editor Mode now has context-specific tools in the Tools menu: the Doodad Dropper for levels and Layers for doodads. * Bugfix the Palette Editor window to work equally between Levels and Doodads, by only having it care about the Palette and not the Level that owns it.loading-screen
parent
336a949ed0
commit
190d4be1b6
11
go.mod
11
go.mod
|
@ -3,24 +3,35 @@ module git.kirsle.net/apps/doodle
|
|||
go 1.15
|
||||
|
||||
replace git.kirsle.net/go/render => /home/kirsle/SketchyMaze/render
|
||||
|
||||
replace git.kirsle.net/go/ui => /home/kirsle/SketchyMaze/ui
|
||||
|
||||
require (
|
||||
4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a // indirect
|
||||
4d63.com/gochecknoinits v0.0.0-20200108094044-eb73b47b9fc4 // indirect
|
||||
dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 // indirect
|
||||
git.kirsle.net/go/audio v0.0.0-20200429055451-ae3b0695ba6f
|
||||
git.kirsle.net/go/log v0.0.0-20200902035305-70ac2848949b
|
||||
git.kirsle.net/go/render v0.0.0-20200710023247-e5f4c3a16860
|
||||
git.kirsle.net/go/ui v0.0.0-20200710023146-e2a561fbd04c
|
||||
github.com/alecthomas/gocyclo v0.0.0-20150208221726-aa8f8b160214 // indirect
|
||||
github.com/google/uuid v1.1.2
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20201107091007-3b93a8888063 // indirect
|
||||
github.com/jgautheron/goconst v0.0.0-20201108215931-f8e4fe8351cd // indirect
|
||||
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
|
||||
github.com/mdempsky/maligned v0.0.0-20201101000000-d73c43cb16d0 // indirect
|
||||
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac
|
||||
github.com/tomnomnom/xtermcolor v0.0.0-20160428124646-b78803f00a7e // indirect
|
||||
github.com/urfave/cli v1.22.5
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/veandco/go-sdl2 v0.4.4
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible
|
||||
github.com/walle/lll v1.0.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 // indirect
|
||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect
|
||||
mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7 // indirect
|
||||
)
|
||||
|
|
42
go.sum
42
go.sum
|
@ -1,3 +1,9 @@
|
|||
4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a h1:wFEQiK85fRsEVF0CRrPAos5LoAryUsIX1kPW/WrIqFw=
|
||||
4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo=
|
||||
4d63.com/gochecknoinits v0.0.0-20200108094044-eb73b47b9fc4 h1:bf5qocEKjrY58JO2GwywfLsb1199lIVs7qHkiplwHy0=
|
||||
4d63.com/gochecknoinits v0.0.0-20200108094044-eb73b47b9fc4/go.mod h1:4o1i5aXtIF5tJFt3UD1knCVmWOXg7fLYdHVu6jeNcnM=
|
||||
dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 h1:o4lAkfETerCnr1kF9/qwkwjICnU+YLHNDCM8h2xj7as=
|
||||
dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363/go.mod h1:WG7q7swWsS2f9PYpt5DoEP/EBYWx8We5UoRltn9vJl8=
|
||||
git.kirsle.net/go/audio v0.0.0-20200429055451-ae3b0695ba6f h1:OTxRqv7JdRpmR4gm3pG7Mzv+GyG0ig2mJWluu5NOkro=
|
||||
git.kirsle.net/go/audio v0.0.0-20200429055451-ae3b0695ba6f/go.mod h1:iESedHfXAOnbqiDDVs7Va+KQWkZG0Asc+452hw9TX9w=
|
||||
git.kirsle.net/go/log v0.0.0-20200902035305-70ac2848949b h1:TDxEEWOJqMzsu9JW8/QgmT1lgQ9WD2KWlb2lKN/Ql2o=
|
||||
|
@ -8,17 +14,29 @@ git.kirsle.net/go/render v0.0.0-20200710023247-e5f4c3a16860/go.mod h1:ss7pvZbGWr
|
|||
git.kirsle.net/go/ui v0.0.0-20200710023146-e2a561fbd04c h1:8fvCXsFGK91WtiTIAdklAN3gHVNYD0hvFvWfznCLMGc=
|
||||
git.kirsle.net/go/ui v0.0.0-20200710023146-e2a561fbd04c/go.mod h1:Q93RpHNXvbGr3dQ9mmcEN8ZC3dtNQ4FwivSx53tKOVA=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/alecthomas/gocyclo v0.0.0-20150208221726-aa8f8b160214 h1:YI/8G3uLbYyowJeOPVL6BMKe2wbL54h0FdEKmncU6lU=
|
||||
github.com/alecthomas/gocyclo v0.0.0-20150208221726-aa8f8b160214/go.mod h1:Ef5UOtJdJ5rVFObdOVsrNgKV/Wf4I+daTCSk8GTrHIk=
|
||||
github.com/alexflint/go-arg v0.0.0-20160306200701-e71d6514f40a h1:Bc+P30eTWphhueyACA/fjiHJXRDq/kGiqO38nGxvml0=
|
||||
github.com/alexflint/go-arg v0.0.0-20160306200701-e71d6514f40a/go.mod h1:PHxo6ZWOLVMZZgWSAqBynb/KhIqoGO6WKwOVX7rM9dg=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20201107091007-3b93a8888063 h1:dKprcOvlsvqfWn/iGvz+oYuC2axESeSMuF8dDrWMNsE=
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20201107091007-3b93a8888063/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||
github.com/jgautheron/goconst v0.0.0-20201108215931-f8e4fe8351cd h1:xfrCuNSOStubQgCjSKriU45JXwfj2Ew5PZgoPgWm6OQ=
|
||||
github.com/jgautheron/goconst v0.0.0-20201108215931-f8e4fe8351cd/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4=
|
||||
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f h1:dKccXx7xA56UNqOcFIbuqFjAWPVtP688j5QMgmo6OHU=
|
||||
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f/go.mod h1:4rEELDSfUAlBSyUjPG0JnaNGjf13JySHFeRdD/3dLP0=
|
||||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mdempsky/maligned v0.0.0-20201101000000-d73c43cb16d0 h1:+6XJvFZBYbNv/nSekNWFZyaGNMXcPnZ4n/HHoCXn+Ms=
|
||||
github.com/mdempsky/maligned v0.0.0-20201101000000-d73c43cb16d0/go.mod h1:3UB4iTzhLciyWcrrvXSkrtCIU+IJ5GCfEmnleHRsxL4=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac h1:kYPjbEN6YPYWWHI6ky1J813KzIq/8+Wg4TO4xU7A/KU=
|
||||
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
|
||||
|
@ -38,35 +56,55 @@ github.com/veandco/go-sdl2 v0.4.4 h1:coOJGftOdvNvGoUIZmm4XD+ZRQF4mg9ZVHmH3/42zFQ
|
|||
github.com/veandco/go-sdl2 v0.4.4/go.mod h1:FB+kTpX9YTE+urhYiClnRzpOXbiWgaU3+5F2AB78DPg=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible h1:wapg9xDUZDzGCNFlwc5SqI1rvcciqcxEHac4CYj89xI=
|
||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||
github.com/walle/lll v1.0.1 h1:lbK8008fOXbQNYt8daBGUrjvElvlwlE7D7N/9dLP5IQ=
|
||||
github.com/walle/lll v1.0.1/go.mod h1:lYxcXzoPhiAHR9eaq+Yv7RYg1nIipLloBCIfPUzfaWQ=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU=
|
||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
|
||||
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b h1:zSzQJAznWxAh9fZxiPy2FZo+ZZEYoYFYYDYdOrU7AaM=
|
||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||
golang.org/x/tools v0.0.0-20201030204249-4fc0492b8eca h1:KWfVIHfTHZf4IQhrLjrbG+kLyoSym7yYp0WgqtOVH9s=
|
||||
golang.org/x/tools v0.0.0-20201030204249-4fc0492b8eca/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -77,5 +115,9 @@ gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
|||
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I=
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||
mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7 h1:kAREL6MPwpsk1/PQPFD3Eg7WAQR5mPTWZJaBiG5LDbY=
|
||||
mvdan.cc/unparam v0.0.0-20200501210554-b37ab49443f7/go.mod h1:HGC5lll35J70Y5v7vCGb9oLhHoScFwkHDJm/05RdSTc=
|
||||
|
|
|
@ -43,6 +43,9 @@ var (
|
|||
PadX: 4,
|
||||
}
|
||||
|
||||
// Modal backdrop color.
|
||||
ModalBackdrop = render.RGBA(1, 1, 1, 42)
|
||||
|
||||
// StatusFont is the font for the status bar.
|
||||
StatusFont = render.Text{
|
||||
Size: 12,
|
||||
|
|
|
@ -136,7 +136,6 @@ func (d *Doodle) Run() error {
|
|||
} else {
|
||||
// Global event handlers.
|
||||
if ev.Escape {
|
||||
log.Error("Escape key pressed, shutting down")
|
||||
d.ConfirmExit()
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -31,8 +31,9 @@ type EditorScene struct {
|
|||
|
||||
// The current level or doodad object being edited, based on the
|
||||
// DrawingType.
|
||||
Level *level.Level
|
||||
Doodad *doodads.Doodad
|
||||
Level *level.Level
|
||||
Doodad *doodads.Doodad
|
||||
ActiveLayer int // which layer (of a doodad) is being edited now?
|
||||
|
||||
// Custom debug overlay values.
|
||||
debTool *string
|
||||
|
@ -170,8 +171,8 @@ func (s *EditorScene) ConfirmUnload(fn func()) {
|
|||
}
|
||||
|
||||
modal.Confirm(
|
||||
"This level has unsaved changes. Are you sure you\nwant to continue and lose your changes?",
|
||||
).WithTitle("Confirm Closing Level").Then(fn)
|
||||
"This drawing has unsaved changes. Are you sure you\nwant to continue and lose your changes?",
|
||||
).WithTitle("Confirm Closing Drawing").Then(fn)
|
||||
}
|
||||
|
||||
// Loop the editor scene.
|
||||
|
@ -322,7 +323,7 @@ func (s *EditorScene) SaveDoodad(filename string) error {
|
|||
|
||||
// TODO: is this copying necessary?
|
||||
d.Palette = s.UI.Canvas.Palette
|
||||
d.Layers[0].Chunker = s.UI.Canvas.Chunker()
|
||||
d.Layers[s.ActiveLayer].Chunker = s.UI.Canvas.Chunker()
|
||||
|
||||
// Clear the modified flag on the level.
|
||||
s.UI.Canvas.SetModified(false)
|
||||
|
|
119
pkg/editor_ui.go
119
pkg/editor_ui.go
|
@ -48,6 +48,7 @@ type EditorUI struct {
|
|||
aboutWindow *ui.Window
|
||||
doodadWindow *ui.Window
|
||||
paletteEditor *ui.Window
|
||||
layersWindow *ui.Window
|
||||
|
||||
// Palette window.
|
||||
Palette *ui.Window
|
||||
|
@ -481,7 +482,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
|||
////////
|
||||
// File menu
|
||||
fileMenu := menu.AddMenu("File")
|
||||
fileMenu.AddItemAccel("New level", "Ctrl-N", func() {
|
||||
fileMenu.AddItemAccel("New level", "Ctrl-N*", func() {
|
||||
u.Scene.ConfirmUnload(func() {
|
||||
d.GotoNewMenu()
|
||||
})
|
||||
|
@ -504,7 +505,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
|||
})
|
||||
})
|
||||
}
|
||||
fileMenu.AddItemAccel("Save", "Ctrl-S", func() {
|
||||
fileMenu.AddItemAccel("Save", "Ctrl-S*", func() {
|
||||
if u.Scene.filename != "" {
|
||||
saveFunc(u.Scene.filename)
|
||||
} else {
|
||||
|
@ -522,7 +523,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
|||
}
|
||||
})
|
||||
})
|
||||
fileMenu.AddItemAccel("Open...", "Ctrl-O", func() {
|
||||
fileMenu.AddItemAccel("Open...", "Ctrl-O*", func() {
|
||||
u.Scene.ConfirmUnload(func() {
|
||||
d.GotoLoadMenu()
|
||||
})
|
||||
|
@ -533,7 +534,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
|||
d.Goto(&MainScene{})
|
||||
})
|
||||
})
|
||||
fileMenu.AddItemAccel("Quit", "Ctrl-Q", func() {
|
||||
fileMenu.AddItemAccel("Quit", "Escape", func() {
|
||||
d.ConfirmExit()
|
||||
})
|
||||
|
||||
|
@ -543,7 +544,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
|||
editMenu.AddItemAccel("Undo", "Ctrl-Z", func() {
|
||||
u.Canvas.UndoStroke()
|
||||
})
|
||||
editMenu.AddItemAccel("Redo", "Shift-Ctrl-Y", func() {
|
||||
editMenu.AddItemAccel("Redo", "Ctrl-Y", func() {
|
||||
u.Canvas.RedoStroke()
|
||||
})
|
||||
editMenu.AddSeparator()
|
||||
|
@ -559,7 +560,7 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
|||
|
||||
////////
|
||||
// Level menu
|
||||
if drawingType == "level" {
|
||||
if u.Scene.DrawingType == enum.LevelDrawing {
|
||||
levelMenu := menu.AddMenu("Level")
|
||||
levelMenu.AddItemAccel("Playtest", "P", func() {
|
||||
u.Scene.Playtest()
|
||||
|
@ -578,10 +579,20 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
|||
toolMenu.AddItemAccel("Command shell", "Enter", func() {
|
||||
d.shell.Open = true
|
||||
})
|
||||
toolMenu.AddItemAccel("Doodads", "d", func() {
|
||||
log.Info("Open the DoodadDropper")
|
||||
u.doodadWindow.Show()
|
||||
toolMenu.AddSeparator()
|
||||
toolMenu.AddItem("Edit Palette", func() {
|
||||
u.OpenPaletteWindow()
|
||||
})
|
||||
if u.Scene.DrawingType == enum.LevelDrawing {
|
||||
toolMenu.AddItemAccel("Doodads", "d", func() {
|
||||
log.Info("Open the DoodadDropper")
|
||||
u.doodadWindow.Show()
|
||||
})
|
||||
} else if u.Scene.DrawingType == enum.DoodadDrawing {
|
||||
toolMenu.AddItem("Layers", func() {
|
||||
u.OpenLayersWindow()
|
||||
})
|
||||
}
|
||||
|
||||
////////
|
||||
// Help menu
|
||||
|
@ -615,96 +626,6 @@ func (u *EditorUI) SetupMenuBar(d *Doodle) *ui.MenuBar {
|
|||
return menu
|
||||
}
|
||||
|
||||
// SetupPopups preloads popup windows like the DoodadDropper.
|
||||
func (u *EditorUI) SetupPopups(d *Doodle) {
|
||||
// Common window configure function.
|
||||
var configure = func(window *ui.Window) {
|
||||
var size = window.Size()
|
||||
window.Compute(d.Engine)
|
||||
window.Supervise(u.Supervisor)
|
||||
|
||||
// Center the window.
|
||||
window.MoveTo(render.Point{
|
||||
X: (d.width / 2) - (size.W / 2),
|
||||
Y: (d.height / 2) - (size.H / 2),
|
||||
})
|
||||
}
|
||||
|
||||
// Doodad Dropper.
|
||||
if u.doodadWindow == nil {
|
||||
u.doodadWindow = windows.NewDoodadDropper(windows.DoodadDropper{
|
||||
Supervisor: u.Supervisor,
|
||||
Engine: d.Engine,
|
||||
|
||||
OnStartDragActor: u.startDragActor,
|
||||
OnCancel: func() {
|
||||
u.doodadWindow.Hide()
|
||||
},
|
||||
})
|
||||
configure(u.doodadWindow)
|
||||
}
|
||||
|
||||
// Page Settings
|
||||
if u.levelSettingsWindow == nil {
|
||||
scene, _ := d.Scene.(*EditorScene)
|
||||
|
||||
u.levelSettingsWindow = windows.NewAddEditLevel(windows.AddEditLevel{
|
||||
Supervisor: u.Supervisor,
|
||||
Engine: d.Engine,
|
||||
EditLevel: scene.Level,
|
||||
|
||||
OnChangePageTypeAndWallpaper: func(pageType level.PageType, wallpaper string) {
|
||||
log.Info("OnChangePageTypeAndWallpaper called: %+v, %+v", pageType, wallpaper)
|
||||
scene.Level.PageType = pageType
|
||||
scene.Level.Wallpaper = wallpaper
|
||||
u.Canvas.LoadLevel(d.Engine, scene.Level)
|
||||
},
|
||||
OnCancel: func() {
|
||||
u.levelSettingsWindow.Hide()
|
||||
},
|
||||
})
|
||||
configure(u.levelSettingsWindow)
|
||||
}
|
||||
|
||||
// Palette Editor.
|
||||
if u.paletteEditor == nil {
|
||||
scene, _ := d.Scene.(*EditorScene)
|
||||
|
||||
u.paletteEditor = windows.NewPaletteEditor(windows.PaletteEditor{
|
||||
Supervisor: u.Supervisor,
|
||||
Engine: d.Engine,
|
||||
EditLevel: scene.Level,
|
||||
|
||||
OnChange: func() {
|
||||
// Reload the level.
|
||||
log.Warn("RELOAD LEVEL")
|
||||
u.Canvas.LoadLevel(d.Engine, scene.Level)
|
||||
scene.Level.Chunker.Redraw()
|
||||
|
||||
// Reload the palette frame to reflect the changed data.
|
||||
u.Palette.Hide()
|
||||
u.Palette = u.SetupPalette(d)
|
||||
u.Resized(d)
|
||||
},
|
||||
OnAddColor: func() {
|
||||
// Adding a new color to the palette.
|
||||
sw := scene.Level.Palette.AddSwatch()
|
||||
log.Info("Added new palette color: %+v", sw)
|
||||
|
||||
// Awkward but... reload this very same window.
|
||||
u.paletteEditor.Hide()
|
||||
u.paletteEditor = nil
|
||||
u.SetupPopups(d)
|
||||
u.paletteEditor.Show()
|
||||
},
|
||||
OnCancel: func() {
|
||||
u.paletteEditor.Hide()
|
||||
},
|
||||
})
|
||||
configure(u.paletteEditor)
|
||||
}
|
||||
}
|
||||
|
||||
// SetupStatusBar sets up the status bar widget along the bottom of the window.
|
||||
func (u *EditorUI) SetupStatusBar(d *Doodle) *ui.Frame {
|
||||
frame := ui.NewFrame("Status Bar")
|
||||
|
|
|
@ -89,11 +89,7 @@ func (u *EditorUI) setupPaletteFrame(window *ui.Window) *ui.Frame {
|
|||
Font: balance.MenuFont,
|
||||
}))
|
||||
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
// TODO: recompute the window so the actual loaded level palette gets in
|
||||
u.paletteEditor.Hide()
|
||||
u.paletteEditor = nil
|
||||
u.SetupPopups(u.d)
|
||||
u.paletteEditor.Show()
|
||||
u.OpenPaletteWindow()
|
||||
return nil
|
||||
})
|
||||
u.Supervisor.Add(btn)
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
package doodle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.kirsle.net/apps/doodle/pkg/doodads"
|
||||
"git.kirsle.net/apps/doodle/pkg/level"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
"git.kirsle.net/apps/doodle/pkg/windows"
|
||||
"git.kirsle.net/go/render"
|
||||
"git.kirsle.net/go/ui"
|
||||
)
|
||||
|
||||
/*
|
||||
Functions to manage popup windows in the Editor Mode, such as:
|
||||
|
||||
* The Palette Editor
|
||||
* The Layers Window
|
||||
* etc.
|
||||
*/
|
||||
|
||||
// Opens the "Layers" window (for editing doodads)
|
||||
func (u *EditorUI) OpenLayersWindow() {
|
||||
u.layersWindow.Hide()
|
||||
u.layersWindow = nil
|
||||
u.SetupPopups(u.d)
|
||||
u.layersWindow.Show()
|
||||
}
|
||||
|
||||
// OpenPaletteWindow opens the Palette Editor window.
|
||||
func (u *EditorUI) OpenPaletteWindow() {
|
||||
// TODO: recompute the window so the actual loaded level palette gets in
|
||||
u.paletteEditor.Hide()
|
||||
u.paletteEditor = nil
|
||||
u.SetupPopups(u.d)
|
||||
u.paletteEditor.Show()
|
||||
}
|
||||
|
||||
// OpenDoodadDropper opens the Doodad Dropper window.
|
||||
func (u *EditorUI) OpenDoodadDropper() {
|
||||
// NOTE: most places in the code call this directly, nice
|
||||
// and simple window :) but OpenDoodadDropper() added for consistency.
|
||||
u.doodadWindow.Show()
|
||||
}
|
||||
|
||||
// SetupPopups preloads popup windows like the DoodadDropper.
|
||||
func (u *EditorUI) SetupPopups(d *Doodle) {
|
||||
// Common window configure function.
|
||||
var configure = func(window *ui.Window) {
|
||||
var size = window.Size()
|
||||
window.Compute(d.Engine)
|
||||
window.Supervise(u.Supervisor)
|
||||
|
||||
// Center the window.
|
||||
window.MoveTo(render.Point{
|
||||
X: (d.width / 2) - (size.W / 2),
|
||||
Y: (d.height / 2) - (size.H / 2),
|
||||
})
|
||||
}
|
||||
|
||||
// Doodad Dropper.
|
||||
if u.doodadWindow == nil {
|
||||
u.doodadWindow = windows.NewDoodadDropper(windows.DoodadDropper{
|
||||
Supervisor: u.Supervisor,
|
||||
Engine: d.Engine,
|
||||
|
||||
OnStartDragActor: u.startDragActor,
|
||||
OnCancel: func() {
|
||||
u.doodadWindow.Hide()
|
||||
},
|
||||
})
|
||||
configure(u.doodadWindow)
|
||||
}
|
||||
|
||||
// Page Settings
|
||||
if u.levelSettingsWindow == nil {
|
||||
scene, _ := d.Scene.(*EditorScene)
|
||||
|
||||
u.levelSettingsWindow = windows.NewAddEditLevel(windows.AddEditLevel{
|
||||
Supervisor: u.Supervisor,
|
||||
Engine: d.Engine,
|
||||
EditLevel: scene.Level,
|
||||
|
||||
OnChangePageTypeAndWallpaper: func(pageType level.PageType, wallpaper string) {
|
||||
log.Info("OnChangePageTypeAndWallpaper called: %+v, %+v", pageType, wallpaper)
|
||||
scene.Level.PageType = pageType
|
||||
scene.Level.Wallpaper = wallpaper
|
||||
u.Canvas.LoadLevel(d.Engine, scene.Level)
|
||||
},
|
||||
OnCancel: func() {
|
||||
u.levelSettingsWindow.Hide()
|
||||
},
|
||||
})
|
||||
configure(u.levelSettingsWindow)
|
||||
}
|
||||
|
||||
// Palette Editor.
|
||||
if u.paletteEditor == nil {
|
||||
scene, _ := d.Scene.(*EditorScene)
|
||||
|
||||
// Which palette?
|
||||
var pal *level.Palette
|
||||
if scene.Level != nil {
|
||||
pal = scene.Level.Palette
|
||||
} else if scene.Doodad != nil {
|
||||
pal = scene.Doodad.Palette
|
||||
}
|
||||
|
||||
u.paletteEditor = windows.NewPaletteEditor(windows.PaletteEditor{
|
||||
Supervisor: u.Supervisor,
|
||||
Engine: d.Engine,
|
||||
IsDoodad: scene.Doodad != nil,
|
||||
EditPalette: pal,
|
||||
|
||||
OnChange: func() {
|
||||
// Reload the level.
|
||||
if scene.Level != nil {
|
||||
log.Warn("RELOAD LEVEL")
|
||||
u.Canvas.LoadLevel(d.Engine, scene.Level)
|
||||
scene.Level.Chunker.Redraw()
|
||||
} else if scene.Doodad != nil {
|
||||
log.Warn("RELOAD DOODAD")
|
||||
u.Canvas.LoadDoodadToLayer(u.Scene.Doodad, u.Scene.ActiveLayer)
|
||||
u.Scene.Doodad.Layers[u.Scene.ActiveLayer].Chunker.Redraw()
|
||||
}
|
||||
|
||||
// Reload the palette frame to reflect the changed data.
|
||||
u.Palette.Hide()
|
||||
u.Palette = u.SetupPalette(d)
|
||||
u.Resized(d)
|
||||
},
|
||||
OnAddColor: func() {
|
||||
// Adding a new color to the palette.
|
||||
sw := pal.AddSwatch()
|
||||
log.Info("Added new palette color: %+v", sw)
|
||||
|
||||
// Awkward but... reload this very same window.
|
||||
u.paletteEditor.Hide()
|
||||
u.paletteEditor = nil
|
||||
u.SetupPopups(d)
|
||||
u.paletteEditor.Show()
|
||||
},
|
||||
OnCancel: func() {
|
||||
u.paletteEditor.Hide()
|
||||
},
|
||||
})
|
||||
configure(u.paletteEditor)
|
||||
}
|
||||
|
||||
// Layers window (doodad editor)
|
||||
if u.layersWindow == nil {
|
||||
scene, _ := d.Scene.(*EditorScene)
|
||||
|
||||
u.layersWindow = windows.NewLayerWindow(windows.Layers{
|
||||
Supervisor: u.Supervisor,
|
||||
Engine: d.Engine,
|
||||
EditDoodad: scene.Doodad,
|
||||
ActiveLayer: scene.ActiveLayer,
|
||||
|
||||
OnChange: func(self *doodads.Doodad) {
|
||||
// Reload the level.
|
||||
log.Warn("RELOAD LEVEL")
|
||||
u.Canvas.LoadDoodad(u.Scene.Doodad)
|
||||
|
||||
for i := range self.Layers {
|
||||
scene.Doodad.Layers[i] = self.Layers[i]
|
||||
}
|
||||
|
||||
// Awkward but... reload this very same window.
|
||||
// Otherwise, the window doesn't update to show the new
|
||||
// layer having been added.
|
||||
u.layersWindow.Hide()
|
||||
u.layersWindow = nil
|
||||
u.SetupPopups(d)
|
||||
u.layersWindow.Show()
|
||||
},
|
||||
OnAddLayer: func() {
|
||||
layer := doodads.Layer{
|
||||
Name: fmt.Sprintf("layer %d", len(scene.Doodad.Layers)),
|
||||
Chunker: level.NewChunker(scene.DoodadSize),
|
||||
}
|
||||
scene.Doodad.Layers = append(scene.Doodad.Layers, layer)
|
||||
log.Info("Added new layer: %d %s",
|
||||
len(scene.Doodad.Layers), layer.Name)
|
||||
|
||||
// Awkward but... reload this very same window.
|
||||
// Otherwise, the window doesn't update to show the new
|
||||
// layer having been added.
|
||||
u.layersWindow.Hide()
|
||||
u.layersWindow = nil
|
||||
u.SetupPopups(d)
|
||||
u.layersWindow.Show()
|
||||
},
|
||||
OnChangeLayer: func(index int) {
|
||||
if index < 0 || index >= len(scene.Doodad.Layers) {
|
||||
d.Flash("OnChangeLayer: layer %d out of range", index)
|
||||
return
|
||||
}
|
||||
|
||||
log.Info("CHANGE DOODAD LAYER TO %d", index)
|
||||
u.Canvas.LoadDoodadToLayer(u.Scene.Doodad, index)
|
||||
u.Scene.ActiveLayer = index
|
||||
},
|
||||
OnCancel: func() {
|
||||
u.layersWindow.Hide()
|
||||
},
|
||||
})
|
||||
configure(u.layersWindow)
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package doodle
|
|||
import (
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
||||
"git.kirsle.net/apps/doodle/pkg/enum"
|
||||
"git.kirsle.net/apps/doodle/pkg/sprites"
|
||||
"git.kirsle.net/go/render"
|
||||
"git.kirsle.net/go/ui"
|
||||
|
@ -33,6 +34,9 @@ func (u *EditorUI) SetupToolbar(d *Doodle) *ui.Frame {
|
|||
Icon string
|
||||
Tooltip string
|
||||
Click func()
|
||||
|
||||
// Optional fields.
|
||||
NoDoodad bool // tool not available for Doodad editing (Levels only)
|
||||
}{
|
||||
{
|
||||
Value: drawtool.PencilTool.String(),
|
||||
|
@ -75,9 +79,10 @@ func (u *EditorUI) SetupToolbar(d *Doodle) *ui.Frame {
|
|||
},
|
||||
|
||||
{
|
||||
Value: drawtool.ActorTool.String(),
|
||||
Icon: "assets/sprites/actor-tool.png",
|
||||
Tooltip: "Doodad Tool\nDrag-and-drop objects into your map",
|
||||
Value: drawtool.ActorTool.String(),
|
||||
Icon: "assets/sprites/actor-tool.png",
|
||||
Tooltip: "Doodad Tool\nDrag-and-drop objects into your map",
|
||||
NoDoodad: true,
|
||||
Click: func() {
|
||||
u.Canvas.Tool = drawtool.ActorTool
|
||||
u.doodadWindow.Show()
|
||||
|
@ -86,9 +91,10 @@ func (u *EditorUI) SetupToolbar(d *Doodle) *ui.Frame {
|
|||
},
|
||||
|
||||
{
|
||||
Value: drawtool.LinkTool.String(),
|
||||
Icon: "assets/sprites/link-tool.png",
|
||||
Tooltip: "Link Tool\nConnect doodads to each other",
|
||||
Value: drawtool.LinkTool.String(),
|
||||
Icon: "assets/sprites/link-tool.png",
|
||||
Tooltip: "Link Tool\nConnect doodads to each other",
|
||||
NoDoodad: true,
|
||||
Click: func() {
|
||||
u.Canvas.Tool = drawtool.LinkTool
|
||||
u.doodadWindow.Show()
|
||||
|
@ -116,6 +122,10 @@ func (u *EditorUI) SetupToolbar(d *Doodle) *ui.Frame {
|
|||
}
|
||||
for _, button := range buttons {
|
||||
button := button
|
||||
if button.NoDoodad && u.Scene.DrawingType == enum.DoodadDrawing {
|
||||
continue
|
||||
}
|
||||
|
||||
image, err := sprites.LoadImage(d.Engine, button.Icon)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -148,6 +158,23 @@ func (u *EditorUI) SetupToolbar(d *Doodle) *ui.Frame {
|
|||
})
|
||||
}
|
||||
|
||||
// Doodad Editor: show the Layers button.
|
||||
if u.Scene.DrawingType == enum.DoodadDrawing {
|
||||
btn := ui.NewButton("Layers Button", ui.NewLabel(ui.Label{
|
||||
Text: "Lyr.",
|
||||
Font: balance.MenuFont,
|
||||
}))
|
||||
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
u.OpenLayersWindow()
|
||||
return nil
|
||||
})
|
||||
u.Supervisor.Add(btn)
|
||||
btnFrame.Pack(btn, ui.Pack{
|
||||
Side: ui.N,
|
||||
PadY: 2,
|
||||
})
|
||||
}
|
||||
|
||||
// Spacer frame.
|
||||
frame.Pack(ui.NewFrame("spacer"), ui.Pack{
|
||||
Side: ui.N,
|
||||
|
|
|
@ -95,7 +95,7 @@ func (p *Palette) AddSwatch() *Swatch {
|
|||
|
||||
var (
|
||||
index = len(p.Swatches)
|
||||
name = fmt.Sprintf("color %d", len(p.Swatches)+1)
|
||||
name = fmt.Sprintf("color %d", len(p.Swatches))
|
||||
)
|
||||
|
||||
p.Swatches = append(p.Swatches, &Swatch{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
package modal
|
||||
|
||||
import (
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/go/render"
|
||||
"git.kirsle.net/go/render/event"
|
||||
"git.kirsle.net/go/ui"
|
||||
|
@ -27,7 +28,7 @@ func Initialize(e render.Engine) {
|
|||
window = render.NewRect(width, height)
|
||||
|
||||
screen = ui.NewFrame("Modal Screen")
|
||||
screen.SetBackground(render.RGBA(1, 1, 1, 128))
|
||||
screen.SetBackground(balance.ModalBackdrop)
|
||||
screen.Resize(window)
|
||||
screen.Compute(e)
|
||||
|
||||
|
|
|
@ -175,6 +175,16 @@ func (w *Canvas) LoadDoodad(d *doodads.Doodad) {
|
|||
w.Load(d.Palette, d.Layers[0].Chunker)
|
||||
}
|
||||
|
||||
// LoadDoodadToLayer initializes a Canvas from a Doodad object and picks
|
||||
// a layer to load.
|
||||
func (w *Canvas) LoadDoodadToLayer(d *doodads.Doodad, index int) {
|
||||
if index < 0 || index > len(d.Layers) {
|
||||
log.Error("LoadDoodadToLayer: index %d out of range", index)
|
||||
return
|
||||
}
|
||||
w.Load(d.Palette, d.Layers[index].Chunker)
|
||||
}
|
||||
|
||||
// SetSwatch changes the currently selected swatch for editing.
|
||||
func (w *Canvas) SetSwatch(s *level.Swatch) {
|
||||
w.Palette.ActiveSwatch = s
|
||||
|
|
|
@ -41,9 +41,10 @@ func NewDoodadDropper(config DoodadDropper) *ui.Window {
|
|||
height = (buttonSize * rows) + 64 // account for button borders :(
|
||||
|
||||
// pagination values
|
||||
page = 1
|
||||
pages int
|
||||
perPage = 20
|
||||
page = 1
|
||||
pages int
|
||||
perPage = 20
|
||||
maxPageButtons = 10
|
||||
)
|
||||
|
||||
window := ui.NewWindow(title)
|
||||
|
@ -180,10 +181,12 @@ func NewDoodadDropper(config DoodadDropper) *ui.Window {
|
|||
|
||||
// Pager for the doodads.
|
||||
pager := ui.NewPager(ui.Pager{
|
||||
Page: page,
|
||||
Pages: pages,
|
||||
PerPage: perPage,
|
||||
Font: balance.MenuFont,
|
||||
Name: "Doodad Dropper Pager",
|
||||
Page: page,
|
||||
Pages: pages,
|
||||
PerPage: perPage,
|
||||
MaxPageButtons: maxPageButtons,
|
||||
Font: balance.MenuFont,
|
||||
OnChange: func(newPage, perPage int) {
|
||||
page = newPage
|
||||
log.Info("Page: %d, %d", page, perPage)
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
package windows
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/doodads"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
"git.kirsle.net/apps/doodle/pkg/shmem"
|
||||
"git.kirsle.net/go/render"
|
||||
"git.kirsle.net/go/ui"
|
||||
)
|
||||
|
||||
// Layers shows the layers when editing a doodad file.
|
||||
type Layers struct {
|
||||
Supervisor *ui.Supervisor
|
||||
Engine render.Engine
|
||||
|
||||
// Pointer to the currently edited level.
|
||||
EditDoodad *doodads.Doodad
|
||||
ActiveLayer int // pointer to selected layer
|
||||
activeLayer string // cached string for radio button
|
||||
|
||||
// Callback functions.
|
||||
OnChange func(*doodads.Doodad) // Doodad data was modified, reload the Canvas etc.
|
||||
OnAddLayer func() // "Add Layer" button was clicked
|
||||
OnCancel func() // Close button was clicked.
|
||||
|
||||
// Editor should change the active layer
|
||||
OnChangeLayer func(index int)
|
||||
}
|
||||
|
||||
// NewLayerWindow initializes the window.
|
||||
func NewLayerWindow(config Layers) *ui.Window {
|
||||
// Default options.
|
||||
var (
|
||||
title = "Layers"
|
||||
rows = []*ui.Frame{}
|
||||
|
||||
// size of the popup window
|
||||
width = 320
|
||||
height = 300
|
||||
|
||||
// Column sizes of the palette table.
|
||||
col1 = 40 // Index
|
||||
col3 = 120 // Name
|
||||
col4 = 60 // Edit button
|
||||
// col5 = 150 // Delete
|
||||
|
||||
// pagination values
|
||||
page = 1
|
||||
perPage = 5
|
||||
)
|
||||
|
||||
config.activeLayer = fmt.Sprintf("%d", config.ActiveLayer)
|
||||
log.Warn("config.activeLayer=%s", config.activeLayer)
|
||||
|
||||
window := ui.NewWindow(title)
|
||||
window.SetButtons(ui.CloseButton)
|
||||
window.Configure(ui.Config{
|
||||
Width: width,
|
||||
Height: height,
|
||||
Background: render.Grey,
|
||||
})
|
||||
|
||||
frame := ui.NewFrame("Window Body Frame")
|
||||
window.Pack(frame, ui.Pack{
|
||||
Side: ui.N,
|
||||
Fill: true,
|
||||
Expand: true,
|
||||
})
|
||||
|
||||
log.Info("SETUP PALETTE WINDOW")
|
||||
|
||||
// Draw the header row.
|
||||
headers := []struct {
|
||||
Name string
|
||||
Size int
|
||||
}{
|
||||
{"Index", col1},
|
||||
{"Name", col3},
|
||||
{"Edit", col4},
|
||||
}
|
||||
header := ui.NewFrame("Header")
|
||||
for _, col := range headers {
|
||||
labelFrame := ui.NewFrame(col.Name)
|
||||
labelFrame.Configure(ui.Config{
|
||||
Width: col.Size,
|
||||
Height: 24,
|
||||
})
|
||||
|
||||
label := ui.NewLabel(ui.Label{
|
||||
Text: col.Name,
|
||||
Font: balance.MenuFontBold,
|
||||
})
|
||||
labelFrame.Pack(label, ui.Pack{
|
||||
Side: ui.N,
|
||||
})
|
||||
|
||||
header.Pack(labelFrame, ui.Pack{
|
||||
Side: ui.W,
|
||||
Padding: 2,
|
||||
})
|
||||
}
|
||||
|
||||
header.Compute(config.Engine)
|
||||
frame.Pack(header, ui.Pack{
|
||||
Side: ui.N,
|
||||
})
|
||||
|
||||
// Draw the rows for each Layer in the given doodad.
|
||||
if doodad := config.EditDoodad; doodad != nil {
|
||||
for i, _ := range doodad.Layers {
|
||||
i := i // rescope
|
||||
var idStr = fmt.Sprintf("%d", i)
|
||||
|
||||
row := ui.NewFrame("Layer " + idStr)
|
||||
rows = append(rows, row)
|
||||
|
||||
// Off the end of the first page?
|
||||
if i >= perPage {
|
||||
row.Hide()
|
||||
}
|
||||
|
||||
// ID label.
|
||||
idLabel := ui.NewLabel(ui.Label{
|
||||
Text: idStr + ".",
|
||||
Font: balance.MenuFont,
|
||||
})
|
||||
idLabel.Configure(ui.Config{
|
||||
Width: col1,
|
||||
Height: 24,
|
||||
})
|
||||
|
||||
// Name button (click to rename the swatch)
|
||||
btnName := ui.NewButton("Name", ui.NewLabel(ui.Label{
|
||||
TextVariable: &doodad.Layers[i].Name,
|
||||
}))
|
||||
btnName.Configure(ui.Config{
|
||||
Width: col3,
|
||||
Height: 24,
|
||||
})
|
||||
btnName.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
shmem.Prompt("New layer name ["+doodad.Layers[i].Name+"]: ", func(answer string) {
|
||||
log.Warn("Answer: %s", answer)
|
||||
if answer != "" {
|
||||
doodad.Layers[i].Name = answer
|
||||
if config.OnChange != nil {
|
||||
config.OnChange(config.EditDoodad)
|
||||
}
|
||||
}
|
||||
})
|
||||
return nil
|
||||
})
|
||||
config.Supervisor.Add(btnName)
|
||||
|
||||
// Edit button (open layer for editing)
|
||||
// btnEdit := ui.NewButton("Edit", ui.NewLabel(ui.Label{
|
||||
// Text: "Edit",
|
||||
// }))
|
||||
btnEdit := ui.NewRadioButton("Edit",
|
||||
&config.activeLayer, idStr, ui.NewLabel(ui.Label{
|
||||
Text: "Edit",
|
||||
}))
|
||||
btnEdit.Configure(ui.Config{
|
||||
Width: col4,
|
||||
Height: 24,
|
||||
})
|
||||
btnEdit.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
if config.OnChangeLayer != nil {
|
||||
config.OnChangeLayer(i)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
config.Supervisor.Add(btnEdit)
|
||||
|
||||
// Pack all the widgets.
|
||||
row.Pack(idLabel, ui.Pack{
|
||||
Side: ui.W,
|
||||
PadX: 2,
|
||||
})
|
||||
row.Pack(btnName, ui.Pack{
|
||||
Side: ui.W,
|
||||
PadX: 2,
|
||||
})
|
||||
row.Pack(btnEdit, ui.Pack{
|
||||
Side: ui.W,
|
||||
PadX: 2,
|
||||
})
|
||||
|
||||
row.Compute(config.Engine)
|
||||
frame.Pack(row, ui.Pack{
|
||||
Side: ui.N,
|
||||
PadY: 2,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/******************
|
||||
* Confirm/cancel buttons.
|
||||
******************/
|
||||
|
||||
bottomFrame := ui.NewFrame("Button Frame")
|
||||
frame.Pack(bottomFrame, ui.Pack{
|
||||
Side: ui.S,
|
||||
FillX: true,
|
||||
})
|
||||
|
||||
// Pager for the doodads.
|
||||
pager := ui.NewPager(ui.Pager{
|
||||
Name: "Layers Window Pager",
|
||||
Page: page,
|
||||
Pages: int(math.Ceil(
|
||||
float64(len(rows)) / float64(perPage),
|
||||
)),
|
||||
PerPage: perPage,
|
||||
MaxPageButtons: 10,
|
||||
Font: balance.MenuFont,
|
||||
OnChange: func(newPage, perPage int) {
|
||||
page = newPage
|
||||
log.Info("Page: %d, %d", page, perPage)
|
||||
|
||||
// Re-evaluate which rows are shown/hidden for this page.
|
||||
var (
|
||||
minRow = (page - 1) * perPage
|
||||
visible = 0
|
||||
)
|
||||
for i, row := range rows {
|
||||
if visible >= perPage {
|
||||
row.Hide()
|
||||
continue
|
||||
}
|
||||
|
||||
if i < minRow {
|
||||
row.Hide()
|
||||
} else {
|
||||
row.Show()
|
||||
visible++
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
pager.Compute(config.Engine)
|
||||
pager.Supervise(config.Supervisor)
|
||||
bottomFrame.Place(pager, ui.Place{
|
||||
Top: 20,
|
||||
Left: 20,
|
||||
})
|
||||
|
||||
btnFrame := ui.NewFrame("Window Buttons")
|
||||
var buttons = []struct {
|
||||
Label string
|
||||
F func(ui.EventData) error
|
||||
}{
|
||||
{"Add Layer", func(ed ui.EventData) error {
|
||||
if config.OnAddLayer != nil {
|
||||
config.OnAddLayer()
|
||||
}
|
||||
|
||||
if config.OnChange != nil {
|
||||
config.OnChange(config.EditDoodad)
|
||||
}
|
||||
return nil
|
||||
}},
|
||||
{"Close", func(ed ui.EventData) error {
|
||||
if config.OnCancel != nil {
|
||||
config.OnCancel()
|
||||
}
|
||||
return nil
|
||||
}},
|
||||
}
|
||||
for _, t := range buttons {
|
||||
btn := ui.NewButton(t.Label, ui.NewLabel(ui.Label{
|
||||
Text: t.Label,
|
||||
Font: balance.MenuFont,
|
||||
}))
|
||||
btn.Handle(ui.Click, t.F)
|
||||
btn.Compute(config.Engine)
|
||||
config.Supervisor.Add(btn)
|
||||
|
||||
btnFrame.Pack(btn, ui.Pack{
|
||||
Side: ui.W,
|
||||
PadX: 4,
|
||||
})
|
||||
}
|
||||
bottomFrame.Place(btnFrame, ui.Place{
|
||||
Top: 60,
|
||||
Center: true,
|
||||
})
|
||||
}
|
||||
|
||||
window.Hide()
|
||||
return window
|
||||
}
|
|
@ -17,9 +17,11 @@ import (
|
|||
type PaletteEditor struct {
|
||||
Supervisor *ui.Supervisor
|
||||
Engine render.Engine
|
||||
IsDoodad bool // you're editing a doodad instead of a level?
|
||||
|
||||
// Pointer to the currently edited level.
|
||||
EditLevel *level.Level
|
||||
// Pointer to the currently edited palette, be it
|
||||
// from a level or a doodad.
|
||||
EditPalette *level.Palette
|
||||
|
||||
// Callback functions.
|
||||
OnChange func()
|
||||
|
@ -44,7 +46,7 @@ func NewPaletteEditor(config PaletteEditor) *ui.Window {
|
|||
// Column sizes of the palette table.
|
||||
col1 = 30 // ID no.
|
||||
col2 = 24 // Color
|
||||
col3 = 120 // Name
|
||||
col3 = 130 // Name
|
||||
col4 = 140 // Attributes
|
||||
// col5 = 150 // Delete
|
||||
|
||||
|
@ -52,6 +54,9 @@ func NewPaletteEditor(config PaletteEditor) *ui.Window {
|
|||
page = 1
|
||||
perPage = 5
|
||||
)
|
||||
if config.IsDoodad {
|
||||
title = "Doodad Palette"
|
||||
}
|
||||
|
||||
window := ui.NewWindow(title)
|
||||
window.SetButtons(ui.CloseButton)
|
||||
|
@ -109,8 +114,8 @@ func NewPaletteEditor(config PaletteEditor) *ui.Window {
|
|||
})
|
||||
|
||||
// Draw the main table of Palette rows.
|
||||
if level := config.EditLevel; level != nil {
|
||||
for i, swatch := range level.Palette.Swatches {
|
||||
if pal := config.EditPalette; pal != nil {
|
||||
for i, swatch := range pal.Swatches {
|
||||
var idStr = fmt.Sprintf("%d", i)
|
||||
swatch := swatch
|
||||
|
||||
|
@ -201,7 +206,7 @@ func NewPaletteEditor(config PaletteEditor) *ui.Window {
|
|||
})
|
||||
config.Supervisor.Add(btnColor)
|
||||
|
||||
// Attribute flags
|
||||
// Attribute flags.
|
||||
attrFrame := ui.NewFrame("Attributes")
|
||||
attrFrame.Configure(ui.Config{
|
||||
Width: col4,
|
||||
|
@ -224,22 +229,26 @@ func NewPaletteEditor(config PaletteEditor) *ui.Window {
|
|||
Var: &swatch.Water,
|
||||
},
|
||||
}
|
||||
for _, attr := range attributes {
|
||||
attr := attr
|
||||
btn := ui.NewCheckButton(attr.Label, attr.Var, ui.NewLabel(ui.Label{
|
||||
Text: attr.Label,
|
||||
Font: balance.MenuFont,
|
||||
}))
|
||||
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
if config.OnChange != nil {
|
||||
config.OnChange()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
config.Supervisor.Add(btn)
|
||||
attrFrame.Pack(btn, ui.Pack{
|
||||
Side: ui.W,
|
||||
})
|
||||
|
||||
// Do not show in Doodad editing mode.
|
||||
if !config.IsDoodad {
|
||||
for _, attr := range attributes {
|
||||
attr := attr
|
||||
btn := ui.NewCheckButton(attr.Label, attr.Var, ui.NewLabel(ui.Label{
|
||||
Text: attr.Label,
|
||||
Font: balance.MenuFont,
|
||||
}))
|
||||
btn.Handle(ui.Click, func(ed ui.EventData) error {
|
||||
if config.OnChange != nil {
|
||||
config.OnChange()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
config.Supervisor.Add(btn)
|
||||
attrFrame.Pack(btn, ui.Pack{
|
||||
Side: ui.W,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Pack all the widgets.
|
||||
|
@ -281,12 +290,14 @@ func NewPaletteEditor(config PaletteEditor) *ui.Window {
|
|||
|
||||
// Pager for the doodads.
|
||||
pager := ui.NewPager(ui.Pager{
|
||||
Name: "Palette Editor Pager",
|
||||
Page: page,
|
||||
Pages: int(math.Ceil(
|
||||
float64(len(rows)) / float64(perPage),
|
||||
)),
|
||||
PerPage: perPage,
|
||||
Font: balance.MenuFont,
|
||||
PerPage: perPage,
|
||||
MaxPageButtons: 6,
|
||||
Font: balance.MenuFont,
|
||||
OnChange: func(newPage, perPage int) {
|
||||
page = newPage
|
||||
log.Info("Page: %d, %d", page, perPage)
|
||||
|
|
Loading…
Reference in New Issue