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.
This commit is contained in:
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
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ type EditorScene struct {
|
|||
// DrawingType.
|
||||
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)
|
||||
|
|
113
pkg/editor_ui.go
113
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.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)
|
||||
|
|
210
pkg/editor_ui_popups.go
Normal file
210
pkg/editor_ui_popups.go
Normal file
|
@ -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(),
|
||||
|
@ -78,6 +82,7 @@ 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",
|
||||
NoDoodad: true,
|
||||
Click: func() {
|
||||
u.Canvas.Tool = drawtool.ActorTool
|
||||
u.doodadWindow.Show()
|
||||
|
@ -89,6 +94,7 @@ 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",
|
||||
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
|
||||
|
|
|
@ -44,6 +44,7 @@ func NewDoodadDropper(config DoodadDropper) *ui.Window {
|
|||
page = 1
|
||||
pages int
|
||||
perPage = 20
|
||||
maxPageButtons = 10
|
||||
)
|
||||
|
||||
window := ui.NewWindow(title)
|
||||
|
@ -180,9 +181,11 @@ func NewDoodadDropper(config DoodadDropper) *ui.Window {
|
|||
|
||||
// Pager for the doodads.
|
||||
pager := ui.NewPager(ui.Pager{
|
||||
Name: "Doodad Dropper Pager",
|
||||
Page: page,
|
||||
Pages: pages,
|
||||
PerPage: perPage,
|
||||
MaxPageButtons: maxPageButtons,
|
||||
Font: balance.MenuFont,
|
||||
OnChange: func(newPage, perPage int) {
|
||||
page = newPage
|
||||
|
|
296
pkg/windows/layers_window.go
Normal file
296
pkg/windows/layers_window.go
Normal file
|
@ -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,6 +229,9 @@ func NewPaletteEditor(config PaletteEditor) *ui.Window {
|
|||
Var: &swatch.Water,
|
||||
},
|
||||
}
|
||||
|
||||
// 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{
|
||||
|
@ -241,6 +249,7 @@ func NewPaletteEditor(config PaletteEditor) *ui.Window {
|
|||
Side: ui.W,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Pack all the widgets.
|
||||
row.Pack(idLabel, ui.Pack{
|
||||
|
@ -281,11 +290,13 @@ 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,
|
||||
MaxPageButtons: 6,
|
||||
Font: balance.MenuFont,
|
||||
OnChange: func(newPage, perPage int) {
|
||||
page = newPage
|
||||
|
|
Loading…
Reference in New Issue
Block a user