From 1f2899077c7ae4d553ea982cd364b10b28b803e1 Mon Sep 17 00:00:00 2001 From: wan-may Date: Sat, 20 Jul 2024 00:09:53 -0300 Subject: [PATCH] Adding UI for city editing --- conf.lua | 2 +- icons/check.png | Bin 0 -> 3126 bytes icons/layer-ainodes.png | Bin 3126 -> 3126 bytes icons/layer-cities.png | Bin 341 -> 357 bytes icons/layer-sailable.png | Bin 300 -> 390 bytes icons/layer-travelnodes.png | Bin 301 -> 381 bytes main.lua | 12 +- map/cities.lua | 45 ++++++- ui/button.lua | 25 +++- ui/loadmodal.lua | 6 +- ui/menu.lua | 0 ui/menu/cities.lua | 232 +++++++++++++++++++++++++++++++++++- ui/menu/mainmenu.lua | 48 +++++--- ui/modal.lua | 18 ++- ui/savemodal.lua | 6 +- ui/textinput.lua | 2 +- 16 files changed, 351 insertions(+), 45 deletions(-) create mode 100644 icons/check.png delete mode 100644 ui/menu.lua diff --git a/conf.lua b/conf.lua index 826d89e..6fbf427 100644 --- a/conf.lua +++ b/conf.lua @@ -12,7 +12,7 @@ function love.conf(t) t.window.title = "dcEarth" -- The window title (string) t.window.icon = "icons/favicon.png" -- Filepath to an image to use as the window's icon (string) - t.window.width = 1000 -- The window width (number) + t.window.width = 1024 -- The window width (number) t.window.height = 640 -- The window height (number) t.window.borderless = false -- Remove all border visuals from the window (boolean) t.window.resizable = true -- Let the window be user-resizable (boolean) diff --git a/icons/check.png b/icons/check.png new file mode 100644 index 0000000000000000000000000000000000000000..eabbeadd10fc880281b1cfe7faf5a05045be729a GIT binary patch literal 3126 zcmeH^K@P$&5ChAd2XN%b3;KZG`TuiZMXJiOMy(4$aA>4NYu7ugq|<#o53e=Wd8>V$ z_i4CPRcrpJHXj)?^5rt+5v>2k$w8l^(3e6B`F+`zhjiE#onjz3)h(gmELy0IfL!iYFg{C!z z5>aS|K#L)&nfYl+oKqydU!1 z*XJ_aM9Et7B`ELdPu5SS6-fD9gbLMu!`YZ~f<-it8P$ZCeY0I4BeI0kAN&!VFd}kv zm=R8ucp|nf0Y74!ReGU+E|f}@&@`Bvbva~&^01FkhRzTyq7zt`3poYP`s~;i)ef~-;82k2Ws zC*?c;{a#qsv>MSHMo_t4kOkoxM=k);5Z-a*1|SI$8Al-iDiP6f6b2w7 eqT?y0^aTm-GEU!>FtOCv*bkDYX;1glh*DdV3nNI`$fQNIk|hTfPY=?ByAUO)Yr>^cAd O002ovPDHLkU;%`pIO zEes7jnI6zfkb&01Wgx45kEVg_`dJIZpK!K`)#fe(a3>9j5zo+UV{DfDMx+_2x8a=H zJR2!<`rmH7l3AvDGlC{_8qfv;Z6kxt@%B>#vdJ>G1L!oDAX3>bpaqTLIUvF~A-e(4 z7!d088Aj@P<}+QugpJcxv;deDz72P^(96+FkOj*cZXk0SD!@HXn$#_b8iP{zodHjYQj6*hXTWM(+H%kk?#j$ch)w}2guL4I81@MN5CsdQ ZbOFxUI8}qT?xO$z002ovPDHLkV1fqFV-x@Y diff --git a/icons/layer-travelnodes.png b/icons/layer-travelnodes.png index 1037d11b9c533c1731dc13f1ba88d58c6427a9d5..67ce08cda043f1f6286d7b67f89ecf9d38dd1645 100644 GIT binary patch delta 305 zcmV-10nYxd0{sGzReu2zNkl z+XUDJKD^unGVLci)GJ}0fs=Fr861_UNSDt5!Z9{II(a6ZxcwY+F>mIz#p-hj*2YzxlL@I^@w*biold`}LtW6vhu-NuZnB%%W8kn;*3A4hw00000NkvXXu0mjf Dmkfur delta 224 zcmV<603ZMT0<8j&Reu1&Nkl?fZ zMojzmHat^6&UuRn6apl1gox)^5M2~z8IlcGiZU%A@+)%z$^k8c_Blq;)d^dKUYp=5 zuvY7R8X;xKcGW~e0?^gf=IOEG7|8)t018QYx&?G|85ZC&L|IUqr^obhND>k$hXyR5 zcCmzY{s^v5GMSWKVus5CCLJXwgycXAzkqiN;3_zyMRyA*UM7Pg{v7BQpqtNVGy3}9 aaY_rfm|!UY2R5|;0000 200 and love.mouse.isDown( 1 ) then + local wx, wy = camera.GetWorldCoordinate( x, y ) + city:moveTo( wx, wy ) + end +end + +function moveModal.mousemoved( x, y, dx, dy, istouch ) + return button.selectIn( x, y ) +end + +function moveModal.mousepressed( x, y, mouseButton, istouch, presses ) + if y < 200 then + moveModal:stop() + return button.mousepressed( x, y, mouseButton, istouch, presses ) + end + if map.selected and mouseButton == 2 then + city = map.selected + end +end + +function numberModal:start( field ) + self.field = field + return modal.start( self ) +end + +function numberModal.keypressed( key, code, isrepeat ) + if code == 'backspace' then end + if code == 'escape' then return numberModal:stop() end +end + +function numberModal.textinput( char ) + local str = tostring( city[ numberModal.field ] ) + local plus = str..char + if tonumber( plus ) then + city[ numberModal.field ] = plus + editButtons[ numberModal.field ].name = plus + end +end + +function textModal.textinput( char ) + print( "text input: ", char ) + city[textModal.field] = city[textModal.field] .. char + editButtons[textModal.field].name = city[textModal.field] +end + +function textModal.mousepressed() +end + +function textModal:stop() + self.field = nil + return modal.stop( self ) +end + +function textModal:start( field ) + self.field = field + return modal.start( self ) +end + + +function textModal.keypressed( key, code, isRepeat ) + if code == "backspace" then + local text = city[textModal.field] + -- get the byte offset to the last UTF-8 character in the string. + local byteoffset = utf8.offset(text, -1) + print( "textmodal: backspace", byteoffset ) + + if byteoffset then + -- remove the last UTF-8 character. + -- string.sub operates on bytes rather than UTF-8 characters, so we couldn't do string.sub(text, 1, -2). + city[textModal.field] = text:sub( 1, byteoffset - 1) + editButtons[textModal.field].name = city[textModal.field] + end + end + if code == "escape" then + return textModal:stop() + end +end + +function selectModal.keypressed( key, code, isRepeat ) + if code == 'escape' then return selectModal:stop() end + if modal.previous then return modal.previous.keypressed( key, code, isRepeat ) end +end + +function selectModal:stop() + local mode = selectModal.mode + if mode then + mode.button.lit = false + end + return modal.stop( self ) +end + +function selectModal.mousepressed( x, y, mouseButton, istouch, presses ) + if y < 200 then + selectModal:stop() + return button.mousepressed( x, y, mouseButton, istouch, presses ) + end + + if map.selected then + city = map.selected + return selectModal.mode:start() + end +end + + + +return t \ No newline at end of file diff --git a/ui/menu/mainmenu.lua b/ui/menu/mainmenu.lua index 54f011a..7f8aeec 100644 --- a/ui/menu/mainmenu.lua +++ b/ui/menu/mainmenu.lua @@ -5,6 +5,7 @@ local savemodal = require 'ui.savemodal' local loadmodal = require 'ui.loadmodal' local Camera = require 'ui.camera' local map = require 'map.map' +local t = {} local loadImg = love.graphics.newImage local layers = { @@ -25,20 +26,23 @@ local layers = { button.new{ name = "LOAD", x = 250, y = 0, - w = 28 * 13, + group = t, callback = loadmodal.start, icon = love.graphics.newImage( "icons/load.png" )} button.new{ name = "SAVE", x = 250, y = 28, - w = 28 * 13, + group = t, callback = savemodal.start, icon = love.graphics.newImage( "icons/save.png" )} button.new{ name = "UNDO", x = 250, y = 2 * 28, - w = 28 * 13, + group = t, callback = map.undo, icon = love.graphics.newImage( "icons/undo.bmp" ) } + +local editButtons = {} +local layerButtons = {} local showButtons = {} local visibilityIcon = love.graphics.newImage( "icons/eye.bmp" ) local function updateVisibilityIcons() @@ -57,9 +61,17 @@ end local activeLayerButton local function back( self ) - self.visible = false - map.setEditLayer() + activeLayerButton.lit = false activeLayerButton = nil + map.setEditLayer() + button.displayGroup( t, false, true ) + for i, b in ipairs( editButtons ) do + b.visible = true + end + for i, b in ipairs( showButtons ) do + b.visible = true + end + self.visible = false return updateVisibilityIcons() end @@ -68,13 +80,18 @@ local backButton = button.new{ visible = false, y = 5 * 28, x = 250, + group = false, icon = love.graphics.newImage( "icons/up.bmp" ), callback = back, } local function editLayer( self ) + self.lit = true map.setEditLayer( self.layer ) activeLayerButton = self + if self.menu then + button.displayGroup( self.menu ) + end backButton.visible = true return updateVisibilityIcons() end @@ -86,11 +103,7 @@ local function copy( i, target ) return target end - -local layerButtons = {} local x = 250 -local soloButtons = {} -local editButtons = {} for i = 1, #layers do editButtons[i] = button.new( copy( i, { @@ -98,7 +111,7 @@ for i = 1, #layers do x = x + (button.h + 4) * ( i - 1 ), w = 24, callback = editLayer, - group = "edit", + group = editButtons, tooltip = "edit "..layers[i].layer })) layerButtons[ 2 * i - 2 ] = editButtons[i] @@ -110,14 +123,13 @@ for i = 1, #layers do name = "", callback = toggleVisibleLayer, icon = visibilityIcon, - group = "show", + group = showButtons, tooltip = "show "..layers[i].layer })) layerButtons[ 2 * i - 1 ] = showButtons[i] end -local t = {} function t.draw() --Status bar. @@ -144,16 +156,22 @@ function t.draw() if map.selected then love.graphics.print( map.selected:formatDisplayInfo(), 0, 80 ) end if map.selectionLocked then end - love.graphics.setScissor( 0, 0, love.graphics.getWidth(), 200 ) + love.graphics.setScissor( 250, 0, love.graphics.getWidth() - 250, 200 ) love.graphics.rectangle( "line", 0, 0 , 250, 200 ) love.graphics.rectangle( "line", 250, 0, love.graphics.getWidth() - 250, 200 ) + love.graphics.rectangle( "line", 250, 0, button.w, 200 ) love.graphics.setColor( 1, 1, 1, 0.8 ) button:draw() - love.graphics.setColor( 1, 0, 0, 0.4 ) - if activeLayerButton then activeLayerButton:highlight() end +end + +do --button visibility + button.displayGroup( t, false, true ) + button.displayGroup( editButtons, false, false ) + button.displayGroup( layerButtons, false, false ) + button.displayGroup( showButtons, false, false ) end return t \ No newline at end of file diff --git a/ui/modal.lua b/ui/modal.lua index f6e457e..57c7219 100644 --- a/ui/modal.lua +++ b/ui/modal.lua @@ -5,14 +5,17 @@ t.__index = t local i = 0 function t.start( self ) + print( "starting modal:", i + 1) love.graphics.setScissor( self.x or 0, self.y or 0, self.w or love.graphics.getWidth(), - self.h or love.graphics.getDimensions()) + self.h or love.graphics.getHeight()) i = i + 1 - t[i] = t[i] or {} + t[i] = { modal = self } + t.previous = t[i] + t.current = self --store callbacks for name in pairs( self ) do @@ -24,17 +27,18 @@ function t.start( self ) --store menus local b = button.next - repeat + repeat t[i][b] = b.visible b = b.next until b == button end function t.stop( self ) + print( "stopping modal:", i ) --restore callbacks for name in pairs( self ) do if love[name] then - love[name] = t[i][name] + love[name] = t[i][name] or love[name] end end @@ -43,12 +47,16 @@ function t.stop( self ) button.deselect() repeat b = b.next - b.visible = t[i][b] or false --accessing a button's nil field is an error, so make sure that b.visible is a boolean + b.visible = t[i][b] or false until b == button + + t.current = t[i].modal t[i] = nil i = i - 1 + t.previous = t[i - 1] + love.graphics.setScissor(0, 0, love.graphics.getDimensions()) end function t.new( modal ) diff --git a/ui/savemodal.lua b/ui/savemodal.lua index cce7052..780676d 100644 --- a/ui/savemodal.lua +++ b/ui/savemodal.lua @@ -8,7 +8,7 @@ local saveLocation = false local floppy = love.graphics.newImage( "icons/save.png" ) floppy:setFilter( "nearest", "nearest" ) local saveButton = button.new{ - group = "saveModal", + group = t, name = "save", callback = function() map.save(); return t:stop() end, visible = false, @@ -22,7 +22,7 @@ local saveButton = button.new{ local xIcon = love.graphics.newImage( "icons/x.png" ) xIcon:setFilter( "nearest", "nearest" ) local cancelButton = button.new{ - group = "saveModal", + group = t, name = "cancel", visible = false, icon = xIcon, @@ -38,7 +38,7 @@ function t.start() saveLocation = saveLocation or map.path button.selected = saveButton saveButton.name = "save to "..saveLocation - button.displayGroup( "saveModal", true ) + button.displayGroup( t, false, true ) end function t.draw() diff --git a/ui/textinput.lua b/ui/textinput.lua index 543f515..a17a7c2 100644 --- a/ui/textinput.lua +++ b/ui/textinput.lua @@ -54,7 +54,7 @@ function t.keypressed(key, code, isRepeat) if byteoffset then -- remove the last UTF-8 character. -- string.sub operates on bytes rather than UTF-8 characters, so we couldn't do string.sub(text, 1, -2). - text = string.sub(text, 1, byteoffset - 1) + t.currentModal.currentField = text:sub( 1, byteoffset - 1) end end if code == "escape" then