Compare commits

..

No commits in common. "1f2899077c7ae4d553ea982cd364b10b28b803e1" and "97f21e192f2c4b533bfd1e1bf21b6549216749ee" have entirely different histories.

22 changed files with 66 additions and 384 deletions

View File

@ -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 = 1024 -- The window width (number)
t.window.width = 1000 -- 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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 B

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 B

After

Width:  |  Height:  |  Size: 301 B

View File

@ -2,7 +2,7 @@ local love = assert( love, "This tool requires LOVE: love2d.org" )
--assert( require('mobdebug') ).start() --remote debugger
local map = require 'map.map'
local button = require 'ui.button'
local mainmenu = require 'ui.menu.mainmenu'
local mainmenu = require 'ui.mainmenu'
local Camera = require 'ui.camera'
function love.load()
@ -58,7 +58,10 @@ end
function love.mousepressed( x, y, mouseButton, istouch, presses )
local wx, wy = Camera.GetWorldCoordinate( x, y )
return button.mousepressed( x, y )
if button.selected and button.selected:contains( x, y ) then
button.callback( button.selected )
return button.selected:callback()
end
end
function love.mousemoved( x, y, dx, dy, istouch )
@ -86,6 +89,9 @@ function love.keypressed(key, code, isRepeat)
end
end
function love.textinput()
do
end

View File

@ -53,48 +53,6 @@ function city:formatDisplayInfo()
CAPITAL: %s]]):format( self.name, self.country, self.x, self.y, self.pop, tostring(self.capital) )
end
function city:delete()
end
function city:add()
local n = #cities + 1
cities[ n ] = self
self.n = n
local idxPoints = #points + 1
self.points = idxPoints
points[ idxPoints ], points[ idxPoints + 1 ] = self.x, self.y
end
function city:moveTo(x, y)
self.x, self.y = x, y
if self.points then
points[ self.points ] = x
points[ self.points + 1 ] = y
end
if self.capital then
caps[ self.caps ] = x
caps[ self.caps + 1 ] = y
end
end
function city:toggleCapital()
self.capital = not( self.capital )
end
function t.newCity( tbl )
return setmetatable({
name = "",
country = "",
x = 0,
y = 0,
pop = 0,
capital = false,
}, citymt )
end
function t.load( filename )
print( "=== LOADING CITIES. ===" )
@ -114,8 +72,7 @@ function t.load( filename )
local city = setmetatable({
name = line:sub( 1, 39 ):gsub("%s+$",""),
country = line:sub( 42, 82 ):gsub("%s+$",""),
x = x, y = y, pop = pop, capital = capital,
n = n, points = idxPts, caps = capital and idxCaps
x = x, y = y, pop = pop, capital = capital
}, citymt )
cities[n] = city
n = n + 1

View File

@ -12,7 +12,7 @@ function polygon:formatDisplayInfo()
y: %f
X: %f
Y: %f
Length: %d]]):format( self.x, self.y, self.X, self.Y, #self / 4 )
N: %d]]):format( self.x, self.y, self.X, self.Y, #self )
end
function polygon:drawDirection()
@ -73,9 +73,8 @@ function t.selectNearest( lines, wx, wy )
poly.X + 5 > wx and
poly.y - 5 < wy and
poly.Y + 5 > wy then
for k = 1, #poly - 3, 4 do
--find the midpoint of each line segment
local x, y = 0.5 * (poly[k] + poly[k + 2]), 0.5 * (poly[k + 1] + poly[k + 3])
for k = 1, #poly, 2 do
local x, y = poly[k], poly[k + 1]
local r = ( x - wx ) * ( x - wx ) + ( y - wy ) * ( y - wy )
if r < d then
d = r

View File

@ -1,5 +1 @@
Map editor for DEFCON, the strategy game, written in LOVE2D, the engine.
Currently does not do anything besides read the files and write them back out.
Need to make a more structured UI, rewriting menu.lua and button.lua for this purpose.

View File

@ -4,13 +4,12 @@ local t = {
name = "",
tooltip = "",
icon = false,
lit = false,
x = 8,
y = 250,
w = 13 * 28 - 4,
w = 176,
h = 24,
group = false,
visible = false,
group = "",
visible = true,
callback = function( self ) return print( "clicked button: ", self.name, self.x, self.y, self.w, self.h, self.visible ) end
}
t.selected, t.next, t.prev = t, t, t
@ -53,7 +52,7 @@ function t.draw( b )
0,
b.h / h )
end
if b.lit or t.selected == b then
if t.selected == b then
b:highlight()
end
end
@ -93,27 +92,15 @@ function t.selectPrevInGroup()
repeat t.selectPrev() until group == t.selected.group
end
--show/hide all buttons in a group
--passing hide=true will hide the group, hide=false or nil will show the group
--solo=true will hide all buttons outside the group
function t.displayGroup( group, hide, solo )
function t.displayGroup( group, show )
local b = t
repeat
b = b.next
local inGroup = (group == b.group)
if solo or inGroup then
b.visible = not(hide) and inGroup
end
b.visible = ( b.group == group )
until b == t
t.visible = true
end
function t.mousepressed( x, y )
if t.selected and t.selected:contains( x, y ) then
return t.selected:callback()
end
end
function t.deselect( b )
t.selected = t
end

View File

@ -8,7 +8,7 @@ local loadLocation = false
local folder = love.graphics.newImage( "icons/load.png" )
folder:setFilter( "nearest", "nearest" )
local loadButton = button.new{
group = t,
group = "loadModal",
name = "load",
callback = function()
if not loadLocation then return end
@ -25,7 +25,7 @@ local loadButton = button.new{
local xIcon = love.graphics.newImage( "icons/x.png" )
xIcon:setFilter( "nearest", "nearest" )
local cancelButton = button.new{
group = t,
group = "loadModal",
name = "cancel load",
visible = false,
icon = xIcon,
@ -41,7 +41,7 @@ function t.start()
loadLocation = loadLocation or map.path
button.selected = loadButton
loadButton.name = "save to "..loadLocation
button.displayGroup( t, true )
button.displayGroup( "loadModal", true )
end
function t.draw()

View File

@ -5,44 +5,40 @@ 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 = {
{ name = "AF", layer = "africa" , menu = require 'ui.menu.territory' },
{ name = "EU", layer = "europe" , menu = require 'ui.menu.territory' },
{ name = "NA", layer = "northamerica" , menu = require 'ui.menu.territory' },
{ name = "SA", layer = "southamerica" , menu = require 'ui.menu.territory' },
{ name = "AS", layer = "southasia" , menu = require 'ui.menu.territory' },
{ name = "RU", layer = "russia" , menu = require 'ui.menu.territory' },
{ name = "PATH", layer = "travelnodes" , menu = require 'ui.menu.travelnodes', icon = loadImg( "icons/layer-travelnodes.png" )},
{ name = "AI", layer = "ainodes" , menu = require 'ui.menu.ainodes', icon = loadImg( "icons/layer-ainodes.png" )},
{ name = "CITY", layer = "cities" , menu = require 'ui.menu.cities', icon = loadImg( "icons/layer-cities.png" )},
{ name = "COAST", layer = "coastlines" , menu = require 'ui.menu.lines', icon = loadImg( "icons/layer-coastlines.png" )},
{ name = "LOW", layer = "coastlinesLow", menu = require 'ui.menu.lines', icon = loadImg( "icons/layer-coastlines-low.png" )},
{ name = "INT", layer = "international", menu = require 'ui.menu.lines', icon = loadImg( "icons/layer-international.png" )},
{ name = "SAIL", layer = "sailable" , menu = require 'ui.menu.territory', icon = loadImg( "icons/layer-sailable.png" )},
}
button.new{
name = "LOAD", x = 250, y = 0,
group = t,
w = 28 * 13,
callback = loadmodal.start,
icon = love.graphics.newImage( "icons/load.png" )}
button.new{
name = "SAVE", x = 250, y = 28,
group = t,
w = 28 * 13,
callback = savemodal.start,
icon = love.graphics.newImage( "icons/save.png" )}
button.new{
name = "UNDO", x = 250, y = 2 * 28,
group = t,
w = 28 * 13,
callback = map.undo,
icon = love.graphics.newImage( "icons/undo.bmp" ) }
local editButtons = {}
local layerButtons = {}
local layers = {
{ name = "AF", layer = "africa" },
{ name = "EU", layer = "europe" },
{ name = "NA", layer = "northamerica" },
{ name = "SA", layer = "southamerica" },
{ name = "AS", layer = "southasia" },
{ name = "RU", layer = "russia" },
{ name = "PATH", layer = "travelnodes" , icon = love.graphics.newImage( "icons/layer-travelnodes.png" )},
{ name = "AI", layer = "ainodes" , icon = love.graphics.newImage( "icons/layer-ainodes.png" )},
{ name = "CITY", layer = "cities" , icon = love.graphics.newImage( "icons/layer-cities.png" )},
{ name = "COAST", layer = "coastlines" , icon = love.graphics.newImage( "icons/layer-coastlines.png" )},
{ name = "LOW", layer = "coastlinesLow", icon = love.graphics.newImage( "icons/layer-coastlines-low.png" )},
{ name = "INT", layer = "international", icon = love.graphics.newImage( "icons/layer-international.png" )},
{ name = "SAIL", layer = "sailable" , icon = love.graphics.newImage( "icons/layer-sailable.png" )},
}
local showButtons = {}
local visibilityIcon = love.graphics.newImage( "icons/eye.bmp" )
local function updateVisibilityIcons()
@ -61,17 +57,9 @@ end
local activeLayerButton
local function back( self )
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
map.setEditLayer()
activeLayerButton = nil
return updateVisibilityIcons()
end
@ -80,18 +68,13 @@ 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
@ -103,15 +86,18 @@ local function copy( i, target )
return target
end
local x = 250
for i = 1, #layers do
local layerButtons = {}
local x = 250
local soloButtons = {}
local editButtons = {}
for i = 1, #layers do
editButtons[i] = button.new( copy( i, {
y = 3 * 28,
x = x + (button.h + 4) * ( i - 1 ),
w = 24,
callback = editLayer,
group = editButtons,
group = "edit",
tooltip = "edit "..layers[i].layer
}))
layerButtons[ 2 * i - 2 ] = editButtons[i]
@ -123,13 +109,14 @@ for i = 1, #layers do
name = "",
callback = toggleVisibleLayer,
icon = visibilityIcon,
group = showButtons,
group = "show",
tooltip = "show "..layers[i].layer
}))
layerButtons[ 2 * i - 1 ] = showButtons[i]
end
local t = {}
function t.draw()
--Status bar.
@ -156,22 +143,16 @@ function t.draw()
if map.selected then love.graphics.print( map.selected:formatDisplayInfo(), 0, 80 ) end
if map.selectionLocked then end
love.graphics.setScissor( 250, 0, love.graphics.getWidth() - 250, 200 )
love.graphics.setScissor( 0, 0, love.graphics.getWidth(), 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 )
end
do --button visibility
button.displayGroup( t, false, true )
button.displayGroup( editButtons, false, false )
button.displayGroup( layerButtons, false, false )
button.displayGroup( showButtons, false, false )
love.graphics.setColor( 1, 0, 0, 0.4 )
if activeLayerButton then activeLayerButton:highlight() end
end
return t

View File

View File

@ -1,231 +0,0 @@
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{ cursor = 1 }
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{ mousepressed = button.mousepressed, keypressed = keypressed }
local currentMode
button.new{ name = "NEW CITY",
group = t,
icon = lg.newImage("icons/layer-cities.png"),
x = 615,
y = 0,
callback = function()
city = map.cities.newCity()
return editModal:start()
end
}
moveModal.button = button.new{ name = "MOVE CITY",
group = t,
x = 615,
y = 28,
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 = 28 * 2,
callback = function( self )
self.lit = true
selectModal.mode = editModal
return selectModal:start()
end,
}
deleteModal.button = button.new{ name = "DELETE CITY",
group = t,
x = 615,
y = 28 * 3,
icon = lg.newImage("icons/x.png"),
callback = function( self )
self.lit = true
selectModal.mode = deleteModal
return selectModal:start()
end,
}
--editButtons
local function editText( self )
print( "editing: ", self.field, city.name )
return textModal:start( self.field )
end
local function editNumber( self )
local field = self.field
end
local editButtons = {
save = button.new{
icon = lg.newImage( "icons/save.png" ),
callback = function() print( "stop editing city" ) 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() if city then return city:toggleCapital() end end },
}
do
local i = 0
for key, b in pairs( editButtons ) do
b.field = key
b.name = key
b.group = editModal
b.x = 0
b.y = 28 * 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 = city[k] or b.name
end
end
function editModal.draw()
return button:draw()
end
function moveModal.update( dt )
local x, y = love.mouse.getPosition()
if y > 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

View File

View File

View File

@ -5,17 +5,10 @@ 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.getHeight())
love.graphics.setScissor( 0, 0, love.graphics.getDimensions() )
i = i + 1
t[i] = { modal = self }
t.previous = t[i]
t.current = self
t[i] = t[i] or {}
--store callbacks
for name in pairs( self ) do
@ -34,11 +27,10 @@ function t.start( self )
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] or love[name]
love[name] = t[i][name]
end
end
@ -47,16 +39,12 @@ function t.stop( self )
button.deselect()
repeat
b = b.next
b.visible = t[i][b] or false
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
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 )

View File

@ -8,7 +8,7 @@ local saveLocation = false
local floppy = love.graphics.newImage( "icons/save.png" )
floppy:setFilter( "nearest", "nearest" )
local saveButton = button.new{
group = t,
group = "saveModal",
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 = t,
group = "saveModal",
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( t, false, true )
button.displayGroup( "saveModal", true )
end
function t.draw()

View File

View File

@ -47,17 +47,16 @@ function t.keypressed(key, code, isRepeat)
end
if key == "backspace" then
local text = t.currentModal.currentField
-- get the byte offset to the last UTF-8 character in the string.
local byteoffset = utf8.offset(text, -1)
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).
t.currentModal.currentField = text:sub( 1, byteoffset - 1)
text = string.sub(text, 1, byteoffset - 1)
end
end
if code == "escape" then
if key == "escape" then
return t:stop()
end
end