local love = assert( love ) local lg = assert( love ).graphics local utf8 = require 'utf8' local button = require 'ui.button' local textinput = require 'ui.textinput' local modal = require 'ui.modal' local map = require 'map.map' local camera = require 'ui.camera' local t = {} local city local function keypressed( key, code, isRepeat ) if code == 'escape' then return modal.current:stop() end if modal.previous then return modal.previous.keypressed( key, code, isRepeat ) end end --select modal: as normal, but clicking a city will proceed to the previously selected mode, --and clicking escape will clear the previously selected mode local selectModal = modal.new{} local textModal = modal.new{} local numberModal = modal.new{} local editModal = modal.new{ mousepressed = button.mousepressed, keypressed = keypressed, } local moveModal = modal.new{ mousepressed = button.mousepressed, keypressed = keypressed, mousemoved = button.selectIn } local deleteModal = modal.new{ keypressed = keypressed } local currentMode button.new{ name = "NEW CITY", group = t, icon = lg.newImage("icons/city-new.png"), x = 615, y = 0, callback = function() city = map.cities.newCity() city:add() return editModal:start() end } moveModal.button = button.new{ name = "MOVE CITY", group = t, icon = lg.newImage("icons/city-move.png"), x = 615, y = button.h + 4, callback = function( self ) self.lit = true selectModal.mode = moveModal return selectModal:start() end, } editModal.button = button.new{ name = "EDIT CITY", group = t, x = 615, y = (button.h + 4) * 2, callback = function( self ) self.lit = true selectModal.mode = editModal return selectModal:start() end, } deleteModal.button = button.new{ name = "DELETE CITY", group = t, icon = lg.newImage("icons/city-delete.png"), x = 615, y = (button.h + 4) * 3, callback = function( self ) self.lit = true return deleteModal:start() end, } --editButtons local function editText( self ) print( "editing: ", self.field, city.name ) self.lit = true return textModal:start( self.field ) end local function editNumber( self ) print( "editing: ", self.field, city.name ) self.lit = true return numberModal:start( self.field ) end local editButtons = { save = button.new{ icon = lg.newImage( "icons/check.png" ), callback = function() return editModal:stop() end,}, name = button.new{ callback = editText }, country = button.new{ callback = editText }, x = button.new{ callback = editNumber }, y = button.new{ callback = editNumber }, capital = button.new{ callback = function( self ) if city then self.name = tostring( not( city.capital ) ) return city:toggleCapital() end end }, } do local i = 0 for _, key in ipairs{ "save", "name", "country", "x", "y", "capital" } do local b = assert( editButtons[ key ] ) b.align = "right" b.field = key b.name = tostring( key ) --bools must be cast to string before getting passed to printf b.group = editModal b.x = lg.getWidth() / 2 - button.w / 2 b.y = (button.h + 4) * i i = i + 1 end end function editModal:start() modal.start( self ) button.displayGroup( self, false, true ) for k, b in pairs( editButtons ) do b.name = tostring( city[k] or b.name ) end if city.capital == false then editButtons.capital.name = "false" end end function editModal:stop() return modal.stop( self ) end function editModal.draw() lg.setColor( 1, 1, 1, 0.5 ) return button:draw() end function moveModal.update( dt ) local x, y = love.mouse.getPosition() if y > t.menuHeight 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 < t.menuHeight 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 deleteModal.mousepressed( x, y, mouseButton, istouch, presses ) if map.selected then map.selected:delete() end if y < t.menuHeight then deleteModal.button.lit = false deleteModal:stop() return button.mousepressed( x, y, mouseButton, istouch, presses ) end end function numberModal:start( field ) self.field = field return modal.start( self ) end function numberModal.keypressed( key, code, isrepeat ) if code == "backspace" then local text = tostring( city[numberModal.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). local newstr = text:sub( 1, byteoffset - 1) if newstr == "" then newstr = 0 end city[numberModal.field] = tonumber( newstr ) or city[numberModal.field] editButtons[numberModal.field].name = city[numberModal.field] end end if code == "escape" or code == "return" then return numberModal:stop() end end function numberModal.textinput( char ) local str = tostring( city[ numberModal.field ] ) local plus = str..char print( "text input: ", 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" or code == "return" 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 < t.menuHeight 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 function t.setMenuHeight( h ) t.menuHeight = h end return t