move UI for horizontal aspect ratio, add load modal and new icons, tweak camera
2
conf.lua
|
@ -12,7 +12,7 @@ function love.conf(t)
|
||||||
|
|
||||||
t.window.title = "dcEarth" -- The window title (string)
|
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.icon = "icons/favicon.png" -- Filepath to an image to use as the window's icon (string)
|
||||||
t.window.width = 800 -- The window width (number)
|
t.window.width = 1000 -- The window width (number)
|
||||||
t.window.height = 640 -- The window height (number)
|
t.window.height = 640 -- The window height (number)
|
||||||
t.window.borderless = false -- Remove all border visuals from the window (boolean)
|
t.window.borderless = false -- Remove all border visuals from the window (boolean)
|
||||||
t.window.resizable = true -- Let the window be user-resizable (boolean)
|
t.window.resizable = true -- Let the window be user-resizable (boolean)
|
||||||
|
|
BIN
icons/eye.bmp
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 341 B |
After Width: | Height: | Size: 341 B |
After Width: | Height: | Size: 424 B |
After Width: | Height: | Size: 383 B |
After Width: | Height: | Size: 300 B |
After Width: | Height: | Size: 301 B |
After Width: | Height: | Size: 3.1 KiB |
BIN
icons/undo.bmp
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
@ -17,14 +17,7 @@ local exists, mkdir, PATH_SEPARATOR
|
||||||
if ffi.os == "Windows" then
|
if ffi.os == "Windows" then
|
||||||
ffi.cdef[[
|
ffi.cdef[[
|
||||||
bool CreateDirectoryA(const char *path, void *lpSecurityAttributes);
|
bool CreateDirectoryA(const char *path, void *lpSecurityAttributes);
|
||||||
int _access(const char *path, int mode);
|
|
||||||
]]
|
]]
|
||||||
function exists(path)
|
|
||||||
assert(type(path) == "string", "path isn't a string")
|
|
||||||
local result = C._access(path, 0) -- Check existence
|
|
||||||
return result == 0
|
|
||||||
end
|
|
||||||
|
|
||||||
function mkdir(path, _)
|
function mkdir(path, _)
|
||||||
assert(type(path) == "string", "path isn't a string")
|
assert(type(path) == "string", "path isn't a string")
|
||||||
if not C.CreateDirectoryA(path, nil) then
|
if not C.CreateDirectoryA(path, nil) then
|
||||||
|
@ -36,13 +29,7 @@ if ffi.os == "Windows" then
|
||||||
elseif ffi.os == "Linux" or ffi.os == "OSX" then
|
elseif ffi.os == "Linux" or ffi.os == "OSX" then
|
||||||
ffi.cdef[[
|
ffi.cdef[[
|
||||||
int mkdir(const char *path, int mode);
|
int mkdir(const char *path, int mode);
|
||||||
int access(const char *path, int amode);
|
|
||||||
]]
|
]]
|
||||||
function exists(path)
|
|
||||||
assert(type(path) == "string", "path isn't a string")
|
|
||||||
local result = C.access(path, 0) -- Check existence
|
|
||||||
return result == 0
|
|
||||||
end
|
|
||||||
function mkdir(path, mode)
|
function mkdir(path, mode)
|
||||||
assert(type(path) == "string", "path isn't a string")
|
assert(type(path) == "string", "path isn't a string")
|
||||||
local mode = tonumber(mode or "755", 8)
|
local mode = tonumber(mode or "755", 8)
|
||||||
|
@ -94,6 +81,18 @@ local function mkdirs(path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if a file or directory exists in this path
|
||||||
|
function exists(file)
|
||||||
|
local ok, err, code = os.rename(file, file)
|
||||||
|
if not ok then
|
||||||
|
if code == 13 then
|
||||||
|
-- Permission denied, but it exists
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ok, err
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
exists = exists,
|
exists = exists,
|
||||||
join = join,
|
join = join,
|
||||||
|
|
41
main.lua
|
@ -1,9 +1,9 @@
|
||||||
local love = assert( love, "This tool requires LOVE: love2d.org" )
|
local love = assert( love, "This tool requires LOVE: love2d.org" )
|
||||||
--assert( require('mobdebug') ).start() --remote debugger
|
--assert( require('mobdebug') ).start() --remote debugger
|
||||||
local map = require 'map'
|
local map = require 'map.map'
|
||||||
local button = require 'button'
|
local button = require 'ui.button'
|
||||||
require 'mainmenu'
|
local mainmenu = require 'ui.mainmenu'
|
||||||
local Camera = require 'camera'
|
local Camera = require 'ui.camera'
|
||||||
|
|
||||||
function love.load()
|
function love.load()
|
||||||
love.filesystem.setIdentity( "dcearth", false )
|
love.filesystem.setIdentity( "dcearth", false )
|
||||||
|
@ -44,29 +44,7 @@ function love.draw()
|
||||||
map.draw()
|
map.draw()
|
||||||
love.graphics.pop()
|
love.graphics.pop()
|
||||||
|
|
||||||
--Status bar.
|
mainmenu.draw()
|
||||||
local x, y = love.mouse.getPosition()
|
|
||||||
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
|
||||||
local bx, by = Camera.GetBitmapCoordinate( x, y )
|
|
||||||
local h = love.graphics.getHeight() - 60
|
|
||||||
love.graphics.setColor( 0, 0, 0, 0.9 )
|
|
||||||
love.graphics.rectangle( "fill", 0, 0, 250, love.graphics.getHeight() )
|
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
|
||||||
love.graphics.print(([[
|
|
||||||
SCREEN %-12d %-12d
|
|
||||||
WORLD %-12.2f%-12.2f
|
|
||||||
BITMAP %-12d %-12d
|
|
||||||
%s]]):format(x, y, wx, wy, bx, by, map.editLayer and map.editLayer.filename or ""), 0, 0)
|
|
||||||
|
|
||||||
if map.selected then love.graphics.print( map.selected:formatDisplayInfo(), 0, 80 ) end
|
|
||||||
if map.selectionLocked then end
|
|
||||||
|
|
||||||
|
|
||||||
love.graphics.rectangle( "line", 0, 0 , 250, 218 )
|
|
||||||
love.graphics.rectangle( "line", 0, 218, 250, love.graphics.getHeight() )
|
|
||||||
|
|
||||||
love.graphics.setColor( 1, 1, 1, 0.6 )
|
|
||||||
button:draw()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.resize(w, h)
|
function love.resize(w, h)
|
||||||
|
@ -81,7 +59,6 @@ function love.mousepressed( x, y, mouseButton, istouch, presses )
|
||||||
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
||||||
|
|
||||||
if button.selected and button.selected:contains( x, y ) then
|
if button.selected and button.selected:contains( x, y ) then
|
||||||
print( ("MOUSE\tx %f\ty %f\twx %f\twy %f"):format(x, y, wx, wy) )
|
|
||||||
button.callback( button.selected )
|
button.callback( button.selected )
|
||||||
return button.selected:callback()
|
return button.selected:callback()
|
||||||
end
|
end
|
||||||
|
@ -101,10 +78,10 @@ end
|
||||||
|
|
||||||
function love.keypressed(key, code, isRepeat)
|
function love.keypressed(key, code, isRepeat)
|
||||||
|
|
||||||
if code == "left" then return button.selectPrev() end
|
if code == "up" then return button.selectPrev() end
|
||||||
if code == "right" then return button.selectNext() end
|
if code == "down" then return button.selectNext() end
|
||||||
if code == "down" then return button.selectNextInGroup() end
|
if code == "right" then return button.selectNextInGroup() end
|
||||||
if code == "up" then return button.selectPrevInGroup() end
|
if code == "left" then return button.selectPrevInGroup() end
|
||||||
if code == "return" then return button.selected:callback() end
|
if code == "return" then return button.selected:callback() end
|
||||||
|
|
||||||
if key == "c" then
|
if key == "c" then
|
||||||
|
|
142
mainmenu.lua
|
@ -1,142 +0,0 @@
|
||||||
|
|
||||||
local love = assert( love )
|
|
||||||
local button = require 'button'
|
|
||||||
local savemodal = require 'savemodal'
|
|
||||||
local map = require 'map'
|
|
||||||
|
|
||||||
button.new{ name = "SAVE", y = 222, callback = savemodal.start, icon = love.graphics.newImage( "icons/save.png" )}
|
|
||||||
button.new{ name = "UNDO", y = 250, callback = map.undo, icon = love.graphics.newImage( "icons/undo.bmp" ) }
|
|
||||||
|
|
||||||
local tools
|
|
||||||
local layerButtons = {}
|
|
||||||
local function back( self )
|
|
||||||
for k, button in pairs( tools ) do button.visible = false end
|
|
||||||
for k, button in pairs( layerButtons ) do button.visible = true end
|
|
||||||
self.visible = false
|
|
||||||
map.editLayer = false
|
|
||||||
end
|
|
||||||
|
|
||||||
local backButton = button.new{
|
|
||||||
name = "UP",
|
|
||||||
visible = false,
|
|
||||||
y = 250 + button.h + 4,
|
|
||||||
icon = love.graphics.newImage( "icons/up.bmp" ),
|
|
||||||
callback = back,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function toolCallback( self )
|
|
||||||
local f = (map.layers[self.layer])[self.name]
|
|
||||||
if f then return f(self) end
|
|
||||||
end
|
|
||||||
|
|
||||||
tools = {
|
|
||||||
button.new{ name = "SELECT"},
|
|
||||||
button.new{ name = "ERASE",},
|
|
||||||
button.new{ name = "MOVE", },
|
|
||||||
button.new{ name = "ADD", },
|
|
||||||
button.new{ name = "EDIT", },
|
|
||||||
button.new{ name = "DRAW", },
|
|
||||||
}
|
|
||||||
for i, v in ipairs( tools ) do
|
|
||||||
v.callback = toolCallback
|
|
||||||
v.y = 250 + (v.h + 4) * ( i + 1 )
|
|
||||||
v.visible = false
|
|
||||||
end
|
|
||||||
|
|
||||||
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" },
|
|
||||||
{ name = "AI", layer = "ainodes" },
|
|
||||||
{ name = "CITY", layer = "cities" },
|
|
||||||
{ name = "COAST", layer = "coastlines" },
|
|
||||||
{ name = "LOW", layer = "coastlinesLow"},
|
|
||||||
{ name = "INT", layer = "international"},
|
|
||||||
{ name = "SAIL", layer = "sailable" },
|
|
||||||
}
|
|
||||||
|
|
||||||
local showButtons = {}
|
|
||||||
local visibilityIcon = love.graphics.newImage( "icons/eye.bmp" )
|
|
||||||
local function updateVisibilityIcons()
|
|
||||||
for i = 1, #showButtons do
|
|
||||||
showButtons[i].icon = map.layers[ showButtons[i].layer ].visible and visibilityIcon
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function toggleVisibleLayer( self )
|
|
||||||
if not (self and self.layer) then return end
|
|
||||||
local ml = map.layers[ self.layer ]
|
|
||||||
ml.visible = not( ml.visible )
|
|
||||||
return updateVisibilityIcons()
|
|
||||||
end
|
|
||||||
|
|
||||||
local soloIcon = false--love.graphics.newImage( "icons/eye.bmp" )
|
|
||||||
local function soloVisibleLayer( self )
|
|
||||||
for k, layer in pairs( map.layers ) do
|
|
||||||
print( "invisible layer, map:", k, layer)
|
|
||||||
layer.visible = false
|
|
||||||
end
|
|
||||||
map.layers[ self.layer ].visible = true
|
|
||||||
return updateVisibilityIcons()
|
|
||||||
end
|
|
||||||
|
|
||||||
local function editLayer( self )
|
|
||||||
map.editLayer = map.layers[ self.layer ]
|
|
||||||
map.editLayer.visible = true
|
|
||||||
for k, button in pairs( layerButtons ) do button.visible = false end
|
|
||||||
for k, button in pairs( tools ) do
|
|
||||||
button.visible = true
|
|
||||||
button.layer = self.layer
|
|
||||||
end
|
|
||||||
backButton.visible = true
|
|
||||||
print( "EDITING LAYER", self.layer )
|
|
||||||
return updateVisibilityIcons()
|
|
||||||
end
|
|
||||||
|
|
||||||
local function copy( i, target )
|
|
||||||
for k, v in pairs( layers[i] ) do
|
|
||||||
target[k] = target[k] or v
|
|
||||||
end
|
|
||||||
return target
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local y = 250
|
|
||||||
local soloButtons = {}
|
|
||||||
local editButtons = {}
|
|
||||||
for i = 1, #layers do
|
|
||||||
editButtons[i] = button.new( copy( i, {
|
|
||||||
x = 8,
|
|
||||||
y = y + (button.h + 4) * i,
|
|
||||||
w = 112,
|
|
||||||
callback = editLayer,
|
|
||||||
group = "edit",
|
|
||||||
}))
|
|
||||||
layerButtons[ 3 * i - 2 ] = editButtons[i]
|
|
||||||
|
|
||||||
showButtons[i] = button.new( copy( i, {
|
|
||||||
x = 128,
|
|
||||||
y = y + (button.h + 4) * i,
|
|
||||||
w = 24,
|
|
||||||
name = "",
|
|
||||||
callback = toggleVisibleLayer,
|
|
||||||
icon = visibilityIcon,
|
|
||||||
group = "show",
|
|
||||||
}))
|
|
||||||
layerButtons[ 3 * i - 1 ] = showButtons[i]
|
|
||||||
|
|
||||||
soloButtons[i] = button.new( copy( i, {
|
|
||||||
x = 160,
|
|
||||||
y = y + (button.h + 4) * i,
|
|
||||||
w = 24,
|
|
||||||
name = "S",
|
|
||||||
callback = soloVisibleLayer,
|
|
||||||
icon = soloIcon,
|
|
||||||
group = "solo",
|
|
||||||
}))
|
|
||||||
layerButtons[ 3 * i ] = soloButtons[i]
|
|
||||||
end
|
|
|
@ -1,7 +1,7 @@
|
||||||
--Manage the AI nodes used by DEFCON.
|
--Manage the AI nodes used by DEFCON.
|
||||||
local bmp = require 'bmp'
|
local bmp = require 'map.bmp'
|
||||||
local lg = assert( love.graphics )
|
local lg = assert( love.graphics )
|
||||||
local locationQuery = require 'locationQuery'
|
local locationQuery = require 'map.locationQuery'
|
||||||
|
|
||||||
local t = setmetatable( {}, {__index = locationQuery } )
|
local t = setmetatable( {}, {__index = locationQuery } )
|
||||||
local print = print
|
local print = print
|
|
@ -6,7 +6,7 @@ local table = table
|
||||||
local tonumber = tonumber
|
local tonumber = tonumber
|
||||||
local lfs = love.filesystem
|
local lfs = love.filesystem
|
||||||
local lg = love.graphics
|
local lg = love.graphics
|
||||||
local locationQuery = require 'locationQuery'
|
local locationQuery = require 'map.locationQuery'
|
||||||
local cities
|
local cities
|
||||||
local points = {}
|
local points = {}
|
||||||
local caps = {}
|
local caps = {}
|
|
@ -87,11 +87,14 @@ function t.selectNearest( lines, wx, wy )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.save( lines )
|
function t.save( lines )
|
||||||
local str = { "b" }
|
local str = { "b" } --initial B
|
||||||
for i, poly in ipairs( lines ) do
|
for i, poly in ipairs( lines ) do
|
||||||
str[i + 1] = table.concat( poly, " " )
|
str[i + 1] = table.concat( poly, " " )
|
||||||
end
|
end
|
||||||
str = table.concat( str, "\nb\n" ):gsub("(%S+) (%S+) ", "%1 %2\n")
|
--concatenate into one big string, one line per polygon
|
||||||
|
--then put each pair of numbers on their own line (without concatenating)
|
||||||
|
--we use CRLF line breaks here because that's what's in the original game files
|
||||||
|
str = table.concat( str, "\13\nb\13\n" ):gsub("(%S+) (%S+) ", "%1 %2\13\n")
|
||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,12 +2,12 @@ local love = assert( love )
|
||||||
local io = io
|
local io = io
|
||||||
local mkdir = assert( require 'lib.mkdir' )
|
local mkdir = assert( require 'lib.mkdir' )
|
||||||
local lg = love.graphics
|
local lg = love.graphics
|
||||||
local AI = require 'ai'
|
local AI = require 'map.ai'
|
||||||
local Cities = require 'cities'
|
local Cities = require 'map.cities'
|
||||||
local Lines = require 'lines'
|
local Lines = require 'map.lines'
|
||||||
local Nodes = require 'travelNodes'
|
local Nodes = require 'map.travelNodes'
|
||||||
local Camera = require 'camera'
|
local Camera = require 'ui.camera'
|
||||||
local Territory = require 'territory'
|
local Territory = require 'map.territory'
|
||||||
|
|
||||||
--flat list of editable layers for convenience
|
--flat list of editable layers for convenience
|
||||||
local layers = {
|
local layers = {
|
||||||
|
@ -75,6 +75,7 @@ function map.load( path )
|
||||||
end
|
end
|
||||||
|
|
||||||
function map.draw()
|
function map.draw()
|
||||||
|
love.graphics.setScissor( 0, 200, love.graphics.getWidth(), love.graphics.getHeight() - 200 )
|
||||||
lg.clear( 0, 0, 0, 1 )
|
lg.clear( 0, 0, 0, 1 )
|
||||||
if not map.loaded then return end
|
if not map.loaded then return end
|
||||||
|
|
||||||
|
@ -192,7 +193,8 @@ end
|
||||||
function map.save()
|
function map.save()
|
||||||
--should be cross platform-ish
|
--should be cross platform-ish
|
||||||
for _, folder in ipairs{ "/data/", "/data/earth/", "/data/graphics/" } do
|
for _, folder in ipairs{ "/data/", "/data/earth/", "/data/graphics/" } do
|
||||||
assert( mkdir.exists( map.path ) )
|
--getInfo checks if a directory exists
|
||||||
|
assert( mkdir.exists( map.path ), map.path )
|
||||||
local path = map.path..folder
|
local path = map.path..folder
|
||||||
if not mkdir.exists( path ) then mkdir.mkdir( path ) end
|
if not mkdir.exists( path ) then mkdir.mkdir( path ) end
|
||||||
end
|
end
|
||||||
|
@ -211,4 +213,17 @@ function map.undo()
|
||||||
print( "=== UNDO ===" )
|
print( "=== UNDO ===" )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function map.setEditLayer( layerName )
|
||||||
|
if not layerName then
|
||||||
|
map.editLayer = nil
|
||||||
|
for name, layer in pairs( layers ) do layer.visible = true end
|
||||||
|
else
|
||||||
|
for name, layer in pairs( layers ) do
|
||||||
|
layer.visible = false
|
||||||
|
end
|
||||||
|
map.editLayer = layers[ layerName ]
|
||||||
|
if map.editLayer then map.editLayer.visible = true end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return map
|
return map
|
|
@ -1,5 +1,5 @@
|
||||||
local t = {}
|
local t = {}
|
||||||
local bmp = require 'bmp'
|
local bmp = require 'map.bmp'
|
||||||
local lg = assert( love.graphics )
|
local lg = assert( love.graphics )
|
||||||
|
|
||||||
local colours = {
|
local colours = {
|
|
@ -2,8 +2,8 @@
|
||||||
--This is important for a mapping tool because the DEFCON client will not load a map unless
|
--This is important for a mapping tool because the DEFCON client will not load a map unless
|
||||||
--the pathfinding nodes form a connected graph.
|
--the pathfinding nodes form a connected graph.
|
||||||
|
|
||||||
local bmp = require 'bmp'
|
local bmp = require 'map.bmp'
|
||||||
local locationQuery = require 'locationQuery'
|
local locationQuery = require 'map.locationQuery'
|
||||||
local lg = assert( love.graphics )
|
local lg = assert( love.graphics )
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,13 @@ local lg = love.graphics
|
||||||
|
|
||||||
local t = {
|
local t = {
|
||||||
name = "",
|
name = "",
|
||||||
tooltip = "button",
|
tooltip = "",
|
||||||
icon = false,
|
icon = false,
|
||||||
x = 8,
|
x = 8,
|
||||||
y = 250,
|
y = 250,
|
||||||
w = 176,
|
w = 176,
|
||||||
h = 24,
|
h = 24,
|
||||||
group = false,
|
group = "",
|
||||||
visible = true,
|
visible = true,
|
||||||
callback = function( self ) return print( "clicked button: ", self.name, self.x, self.y, self.w, self.h, self.visible ) end
|
callback = function( self ) return print( "clicked button: ", self.name, self.x, self.y, self.w, self.h, self.visible ) end
|
||||||
}
|
}
|
||||||
|
@ -29,13 +29,17 @@ function t.new( b )
|
||||||
return b
|
return b
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function t.highlight( b )
|
||||||
|
lg.rectangle( "fill", b.x, b.y, b.w, b.h )
|
||||||
|
end
|
||||||
|
|
||||||
local drawPassOngoing = false
|
local drawPassOngoing = false
|
||||||
function t.draw( b )
|
function t.draw( b )
|
||||||
if b == t then
|
if b == t then
|
||||||
drawPassOngoing = not( drawPassOngoing )
|
drawPassOngoing = not( drawPassOngoing )
|
||||||
if not drawPassOngoing then return end
|
if not drawPassOngoing then return end
|
||||||
elseif b.visible then
|
elseif b.visible then
|
||||||
lg.rectangle( "line", b.x, b.y, b.w, b.h, 6 )
|
lg.rectangle( "line", b.x, b.y, b.w, b.h )
|
||||||
lg.printf( b.name,
|
lg.printf( b.name,
|
||||||
b.x + (b.icon and b.h or 0),
|
b.x + (b.icon and b.h or 0),
|
||||||
b.y + 0.5 * ( b.h - lg.getFont():getHeight() ),
|
b.y + 0.5 * ( b.h - lg.getFont():getHeight() ),
|
||||||
|
@ -49,7 +53,7 @@ function t.draw( b )
|
||||||
b.h / h )
|
b.h / h )
|
||||||
end
|
end
|
||||||
if t.selected == b then
|
if t.selected == b then
|
||||||
lg.rectangle( "fill", b.x, b.y, b.w, b.h, 6 )
|
b:highlight()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return t.draw( b.next )
|
return t.draw( b.next )
|
||||||
|
@ -74,7 +78,9 @@ end
|
||||||
|
|
||||||
function t.selectNextInGroup()
|
function t.selectNextInGroup()
|
||||||
--make sure our group is visible, otherwise the loop doesn't end
|
--make sure our group is visible, otherwise the loop doesn't end
|
||||||
local group = t.selected and t.selected.visible and t.selected.group
|
local group = t.selected
|
||||||
|
group = group and t.selected.visible
|
||||||
|
group = group and t.selected.group
|
||||||
if not group then return t.selectNext() end
|
if not group then return t.selectNext() end
|
||||||
repeat t.selectNext() until group == t.selected.group
|
repeat t.selectNext() until group == t.selected.group
|
||||||
end
|
end
|
|
@ -3,7 +3,7 @@ local tfTerritory = love.math.newTransform()
|
||||||
local tfNodes = love.math.newTransform()
|
local tfNodes = love.math.newTransform()
|
||||||
local lg = assert( love.graphics )
|
local lg = assert( love.graphics )
|
||||||
local Camera = {
|
local Camera = {
|
||||||
x = -90, y = 45,
|
x = 0, y = 70,
|
||||||
w = 360, h = 200,
|
w = 360, h = 200,
|
||||||
zoom = 1, tf = tf,
|
zoom = 1, tf = tf,
|
||||||
tfTerritory = tfTerritory, tfNodes = tfNodes }
|
tfTerritory = tfTerritory, tfNodes = tfNodes }
|
||||||
|
@ -37,7 +37,9 @@ end
|
||||||
function Camera.Translate( x, y )
|
function Camera.Translate( x, y )
|
||||||
x = x or 0
|
x = x or 0
|
||||||
y = y or 0
|
y = y or 0
|
||||||
return Camera.Set( math.max(-180, math.min(360, Camera.x + x)), math.min(100, Camera.y + y), Camera.w, Camera.h)
|
return Camera.Set(
|
||||||
|
math.max(-360, math.min(360, Camera.x + x)),
|
||||||
|
math.max(-140, math.min(140, Camera.y + y)), Camera.w, Camera.h)
|
||||||
end
|
end
|
||||||
|
|
||||||
--In world coordinates: top left corner at x, y, extent of 1/w, 1/h.
|
--In world coordinates: top left corner at x, y, extent of 1/w, 1/h.
|
||||||
|
@ -48,14 +50,17 @@ function Camera.Set( x, y, w, h )
|
||||||
tf:scale( w / 360, -h / 200 )
|
tf:scale( w / 360, -h / 200 )
|
||||||
tf:translate( 180 - x, -y - 100 )
|
tf:translate( 180 - x, -y - 100 )
|
||||||
|
|
||||||
|
|
||||||
tfTerritory:reset()
|
tfTerritory:reset()
|
||||||
tfTerritory:scale( w / 512, h / 285 )
|
tfTerritory:scale( w / 512, h / 285 )
|
||||||
tfTerritory:translate( -x * 512 / 360, y * 512 / 360 )
|
tfTerritory:translate( -x * 512 / 360, y * 512 / 360 )
|
||||||
|
|
||||||
|
|
||||||
tfNodes:reset()
|
tfNodes:reset()
|
||||||
tfNodes:scale( w / 360, -h / 200 )
|
tfNodes:scale( w / 360, -h / 200 )
|
||||||
tfNodes:translate( 180 - x , -y - 100 )
|
tfNodes:translate( 180 - x , -y - 100 )
|
||||||
--tfNodes:translate( -x * 800 / 360, y * 400 / 200 )
|
--tfNodes:translate( -x * 800 / 360, y * 400 / 200 )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Camera.Resize( w, h )
|
function Camera.Resize( w, h )
|
|
@ -0,0 +1,61 @@
|
||||||
|
local love = assert( love )
|
||||||
|
local modal = require( "ui.modal" )
|
||||||
|
local button = require( "ui.button" )
|
||||||
|
local map = require( "map.map" )
|
||||||
|
local t = {}
|
||||||
|
|
||||||
|
local loadLocation = false
|
||||||
|
local folder = love.graphics.newImage( "icons/load.png" )
|
||||||
|
folder:setFilter( "nearest", "nearest" )
|
||||||
|
local loadButton = button.new{
|
||||||
|
group = "loadModal",
|
||||||
|
name = "load",
|
||||||
|
callback = function()
|
||||||
|
if not loadLocation then return end
|
||||||
|
map.load( loadLocation )
|
||||||
|
return t:stop() end,
|
||||||
|
visible = false,
|
||||||
|
icon = folder,
|
||||||
|
x = love.graphics.getWidth() / 2 - 300,
|
||||||
|
y = love.graphics.getHeight() / 2 - 150,
|
||||||
|
w = 600,
|
||||||
|
h = 100,
|
||||||
|
}
|
||||||
|
|
||||||
|
local xIcon = love.graphics.newImage( "icons/x.png" )
|
||||||
|
xIcon:setFilter( "nearest", "nearest" )
|
||||||
|
local cancelButton = button.new{
|
||||||
|
group = "loadModal",
|
||||||
|
name = "cancel load",
|
||||||
|
visible = false,
|
||||||
|
icon = xIcon,
|
||||||
|
callback = function() return t:stop() end,
|
||||||
|
x = love.graphics.getWidth() / 2 - 300,
|
||||||
|
y = love.graphics.getHeight() / 2,
|
||||||
|
w = 600,
|
||||||
|
h = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
function t.start()
|
||||||
|
modal.start( t )
|
||||||
|
loadLocation = loadLocation or map.path
|
||||||
|
button.selected = loadButton
|
||||||
|
loadButton.name = "save to "..loadLocation
|
||||||
|
button.displayGroup( "loadModal", true )
|
||||||
|
end
|
||||||
|
|
||||||
|
function t.draw()
|
||||||
|
love.graphics.clear( 0,0,0,1 )
|
||||||
|
love.graphics.setColor( 0, 0, 1, 0.4 )
|
||||||
|
button:draw()
|
||||||
|
end
|
||||||
|
|
||||||
|
function t.directorydropped( path )
|
||||||
|
loadLocation = path
|
||||||
|
map.path = path
|
||||||
|
loadButton.name = "load from "..map.path
|
||||||
|
return love.filesystem.mount( path, "" )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return modal.new( t )
|
|
@ -0,0 +1,158 @@
|
||||||
|
|
||||||
|
local love = assert( love )
|
||||||
|
local button = require 'ui.button'
|
||||||
|
local savemodal = require 'ui.savemodal'
|
||||||
|
local loadmodal = require 'ui.loadmodal'
|
||||||
|
local Camera = require 'ui.camera'
|
||||||
|
local map = require 'map.map'
|
||||||
|
|
||||||
|
button.new{
|
||||||
|
name = "LOAD", x = 250, y = 0,
|
||||||
|
w = 28 * 13,
|
||||||
|
callback = loadmodal.start,
|
||||||
|
icon = love.graphics.newImage( "icons/load.png" )}
|
||||||
|
button.new{
|
||||||
|
name = "SAVE", x = 250, y = 28,
|
||||||
|
w = 28 * 13,
|
||||||
|
callback = savemodal.start,
|
||||||
|
icon = love.graphics.newImage( "icons/save.png" )}
|
||||||
|
button.new{
|
||||||
|
name = "UNDO", x = 250, y = 2 * 28,
|
||||||
|
w = 28 * 13,
|
||||||
|
callback = map.undo,
|
||||||
|
icon = love.graphics.newImage( "icons/undo.bmp" ) }
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
for i = 1, #showButtons do
|
||||||
|
showButtons[i].icon = map.layers[ showButtons[i].layer ].visible and visibilityIcon
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function toggleVisibleLayer( self )
|
||||||
|
if not (self and self.layer) then return end
|
||||||
|
local ml = map.layers[ self.layer ]
|
||||||
|
ml.visible = not( ml.visible )
|
||||||
|
return updateVisibilityIcons()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local activeLayerButton
|
||||||
|
local function back( self )
|
||||||
|
self.visible = false
|
||||||
|
map.setEditLayer()
|
||||||
|
activeLayerButton = nil
|
||||||
|
return updateVisibilityIcons()
|
||||||
|
end
|
||||||
|
|
||||||
|
local backButton = button.new{
|
||||||
|
name = "UP",
|
||||||
|
visible = false,
|
||||||
|
y = 5 * 28,
|
||||||
|
x = 250,
|
||||||
|
icon = love.graphics.newImage( "icons/up.bmp" ),
|
||||||
|
callback = back,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function editLayer( self )
|
||||||
|
map.setEditLayer( self.layer )
|
||||||
|
activeLayerButton = self
|
||||||
|
backButton.visible = true
|
||||||
|
return updateVisibilityIcons()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function copy( i, target )
|
||||||
|
for k, v in pairs( layers[i] ) do
|
||||||
|
target[k] = target[k] or v
|
||||||
|
end
|
||||||
|
return target
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
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 = "edit",
|
||||||
|
tooltip = "edit "..layers[i].layer
|
||||||
|
}))
|
||||||
|
layerButtons[ 2 * i - 2 ] = editButtons[i]
|
||||||
|
|
||||||
|
showButtons[i] = button.new( copy( i, {
|
||||||
|
y = 4 * 28,
|
||||||
|
x = x + (button.h + 4) * ( i - 1 ),
|
||||||
|
w = 24,
|
||||||
|
name = "",
|
||||||
|
callback = toggleVisibleLayer,
|
||||||
|
icon = visibilityIcon,
|
||||||
|
group = "show",
|
||||||
|
tooltip = "show "..layers[i].layer
|
||||||
|
}))
|
||||||
|
layerButtons[ 2 * i - 1 ] = showButtons[i]
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local t = {}
|
||||||
|
|
||||||
|
function t.draw()
|
||||||
|
--Status bar.
|
||||||
|
love.graphics.setScissor( 0, 0, 250, 200 )
|
||||||
|
local x, y = love.mouse.getPosition()
|
||||||
|
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
||||||
|
local bx, by = Camera.GetBitmapCoordinate( x, y )
|
||||||
|
local h = love.graphics.getHeight() - 60
|
||||||
|
love.graphics.setColor( 0, 0, 0, 1 )
|
||||||
|
love.graphics.rectangle( "fill", 0, 0, 250, love.graphics.getHeight() )
|
||||||
|
love.graphics.setColor( 1, 1, 1, 1 )
|
||||||
|
love.graphics.print(([[
|
||||||
|
SCREEN %-12d %-12d
|
||||||
|
WORLD %-12.2f%-12.2f
|
||||||
|
BITMAP %-12d %-12d
|
||||||
|
%s
|
||||||
|
%s]]):format(
|
||||||
|
x, y,
|
||||||
|
wx, wy,
|
||||||
|
bx, by,
|
||||||
|
button.selected and button.selected.tooltip or "",
|
||||||
|
map.editLayer and map.editLayer.filename or ""), 0, 0)
|
||||||
|
|
||||||
|
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.rectangle( "line", 0, 0 , 250, 200 )
|
||||||
|
love.graphics.rectangle( "line", 250, 0, love.graphics.getWidth() - 250, 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
|
||||||
|
|
||||||
|
return t
|
|
@ -1,10 +1,12 @@
|
||||||
local love = assert( love )
|
local love = assert( love )
|
||||||
local button = require( "button" )
|
local button = require( "ui.button" )
|
||||||
local t = {}
|
local t = {}
|
||||||
t.__index = t
|
t.__index = t
|
||||||
|
|
||||||
local i = 0
|
local i = 0
|
||||||
function t.start( self )
|
function t.start( self )
|
||||||
|
love.graphics.setScissor( 0, 0, love.graphics.getDimensions() )
|
||||||
|
|
||||||
i = i + 1
|
i = i + 1
|
||||||
t[i] = t[i] or {}
|
t[i] = t[i] or {}
|
||||||
|
|
||||||
|
@ -34,10 +36,10 @@ function t.stop( self )
|
||||||
|
|
||||||
--restore menus
|
--restore menus
|
||||||
local b = button
|
local b = button
|
||||||
button.selected = button
|
button.deselect()
|
||||||
repeat
|
repeat
|
||||||
b = b.next
|
b = b.next
|
||||||
b.visible = t[i][b]
|
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
|
until b == button
|
||||||
|
|
||||||
t[i] = nil
|
t[i] = nil
|
|
@ -1,7 +1,7 @@
|
||||||
local love = assert( love )
|
local love = assert( love )
|
||||||
local modal = require( "modal" )
|
local modal = require( "ui.modal" )
|
||||||
local button = require( "button" )
|
local button = require( "ui.button" )
|
||||||
local map = require( "map" )
|
local map = require( "map.map" )
|
||||||
local t = {}
|
local t = {}
|
||||||
|
|
||||||
local saveLocation = false
|
local saveLocation = false
|
|
@ -1,6 +1,6 @@
|
||||||
local love = assert( love )
|
local love = assert( love )
|
||||||
local utf8 = require("utf8")
|
local utf8 = require("utf8")
|
||||||
local modal = require( "modal" )
|
local modal = require( "ui.modal" )
|
||||||
local t = modal.new{ }
|
local t = modal.new{ }
|
||||||
|
|
||||||
function t.setCurrentModal( fields )
|
function t.setCurrentModal( fields )
|