Compare commits
No commits in common. "03e45194cf16a5bf5ef3831aefc4a400189658d1" and "0fbbbe4409fd0ea8bc816cf87786571c1072621f" have entirely different histories.
03e45194cf
...
0fbbbe4409
5
ai.lua
5
ai.lua
|
@ -20,7 +20,6 @@ end
|
||||||
function t.load( filename )
|
function t.load( filename )
|
||||||
local img, imgd = bmp.load( filename )
|
local img, imgd = bmp.load( filename )
|
||||||
local nodes = {
|
local nodes = {
|
||||||
filename = filename,
|
|
||||||
visible = true,
|
visible = true,
|
||||||
all = {},
|
all = {},
|
||||||
att = {},
|
att = {},
|
||||||
|
@ -78,8 +77,8 @@ function t.draw( nodes )
|
||||||
lg.points( nodes.ptsDef )
|
lg.points( nodes.ptsDef )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.save( nodes )
|
function t.save( nodes, filename )
|
||||||
return bmp.savePoints( nodes.all, "512rgb24" )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return t
|
return t
|
122
bmp.lua
122
bmp.lua
|
@ -7,41 +7,6 @@ local lfs = love.filesystem
|
||||||
local ffi = require 'ffi'
|
local ffi = require 'ffi'
|
||||||
local bit = require 'bit'
|
local bit = require 'bit'
|
||||||
|
|
||||||
local function getHeader( filename )
|
|
||||||
local offset = love.data.unpack( "<I4", assert(love.filesystem.read( "data", filename, 14 )), 11 )
|
|
||||||
local header, size = assert( love.filesystem.read( filename, offset ) )
|
|
||||||
print( "BMP HEADER", filename, size, "\n", header )
|
|
||||||
return header
|
|
||||||
end
|
|
||||||
|
|
||||||
local formats = {
|
|
||||||
["512rgb24"] = {
|
|
||||||
header = getHeader( "data/earth/africa.bmp" ),
|
|
||||||
encode = function( r ) return math.floor( r * 255 ) end,
|
|
||||||
bytesPerPixel = 3,
|
|
||||||
w = 512,
|
|
||||||
h = 285,
|
|
||||||
},
|
|
||||||
["512r4"] = {
|
|
||||||
header = getHeader( "data/earth/sailable.bmp" ),
|
|
||||||
encode = function( r ) return math.floor( r * 255 / 16 ) end,
|
|
||||||
bytesPerPixel = 0.5,
|
|
||||||
w = 512,
|
|
||||||
h = 285,
|
|
||||||
},
|
|
||||||
["800r4"] = {
|
|
||||||
header = getHeader( "data/earth/travel_nodes.bmp" ),
|
|
||||||
encode = function( r ) return math.floor( r * 255 / 16 ) end,
|
|
||||||
bytesPerPixel = 0.5,
|
|
||||||
w = 512,
|
|
||||||
h = 285,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function t.header( format )
|
|
||||||
return formats[format] and formats[format].header
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.load( filename )
|
function t.load( filename )
|
||||||
local imgd = love.image.newImageData( filename )
|
local imgd = love.image.newImageData( filename )
|
||||||
print( "LOADING BITMAP: ", filename, imgd:getSize(), imgd:getFormat(), imgd:getDimensions() )
|
print( "LOADING BITMAP: ", filename, imgd:getSize(), imgd:getFormat(), imgd:getDimensions() )
|
||||||
|
@ -50,93 +15,8 @@ function t.load( filename )
|
||||||
return img, imgd
|
return img, imgd
|
||||||
end
|
end
|
||||||
|
|
||||||
--maps an array of 1-byte pixel values (numbers 0 to 15 inclusive)
|
function t.save( data, filename )
|
||||||
--to an array of half-byte pixel values (which can be concatenated into a string)
|
|
||||||
--BUT don't touch the first element (which is assumed to be a header or something)
|
|
||||||
local function foldByteArray( bytes )
|
|
||||||
local nybbles = { bytes[1] }
|
|
||||||
for j = 2, #bytes / 2 do
|
|
||||||
local a, b = bytes[ 2 * j - 2 ], bytes[ 2 * j - 1 ]
|
|
||||||
nybbles[j] = string.char( 16 * a + b )
|
|
||||||
end
|
|
||||||
return nybbles
|
|
||||||
end
|
|
||||||
|
|
||||||
local function packTwentyFour( bytes )
|
|
||||||
local twentyFour = { bytes[1] }
|
|
||||||
for j = 2, #bytes do
|
|
||||||
bytes[j] = string.char( bytes[j], bytes[j], bytes[j] )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.save( data, format )
|
|
||||||
local w, h = data:getDimensions()
|
local w, h = data:getDimensions()
|
||||||
format = assert( formats[format] )
|
|
||||||
local bytes = { format.header }
|
|
||||||
format.byte = 0
|
|
||||||
local i = 2
|
|
||||||
for x = 0, w - 1 do
|
|
||||||
for y = 0, h - 1 do
|
|
||||||
bytes[i] = format.encode( data:getPixel(x, y) )
|
|
||||||
i = i + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if format.bytesPerPixel < 1 then bytes = foldByteArray( bytes )
|
|
||||||
else packTwentyFour( bytes ) end
|
|
||||||
return table.concat( bytes )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--takes an array of world-space points in [-180, 180] x [-100, 100]
|
|
||||||
--e.g { { x = 0.5, y = 0.5 }, { x = 0.4, y = 0.6 }, }, etc.
|
|
||||||
--and a function which maps points to colours
|
|
||||||
function t.savePoints( points, format )
|
|
||||||
format = assert( formats[format] )
|
|
||||||
|
|
||||||
--set up bitmap as an array of pixels
|
|
||||||
local w, h = format.w, format.h
|
|
||||||
local size = 2 + format.w * format.h
|
|
||||||
local bitmap = { format.header }
|
|
||||||
for j = 2, size do bitmap[j] = 0 end
|
|
||||||
|
|
||||||
--this is black-and-white only. easy case
|
|
||||||
if format.bytesPerPixel < 1 then
|
|
||||||
for i, point in ipairs( points ) do
|
|
||||||
local wx, wy = point.x, point.y
|
|
||||||
--get bitmap coordinates
|
|
||||||
local x, y = math.floor(format.w * (wx + 180) / 360), math.floor(format.h * (1.0 - (wy + 100) / 200))
|
|
||||||
--get index into byte array
|
|
||||||
local idx = 2 + x * format.h + y
|
|
||||||
bitmap[idx] = 0x0f --0b00001111
|
|
||||||
end
|
|
||||||
--now map pixels to 4-bit strings, slap on the header, and pass it back up
|
|
||||||
return table.concat( foldByteArray( bitmap ) )
|
|
||||||
end
|
|
||||||
|
|
||||||
--cf. ai.lua: these points can be red or green
|
|
||||||
for i, point in ipairs( points ) do
|
|
||||||
local wx, wy = point.x, point.y
|
|
||||||
--get bitmap coordinates
|
|
||||||
local x, y = math.floor(format.w * (wx + 180) / 360), math.floor(format.h * (1.0 - (wy + 100) / 200))
|
|
||||||
--get index into byte array
|
|
||||||
local idx = 2 + x * format.h + y
|
|
||||||
--in-editor we could have two points in the same place, possibly of the same or different types
|
|
||||||
--in case we miss something upstream, don't corrupt these duplicate points,
|
|
||||||
--just saturate the attack/defense value
|
|
||||||
if bitmap[idx] == 0 then bitmap[idx] = { attack = point.attacking, place = not(point.attacking)}
|
|
||||||
else
|
|
||||||
bitmap[idx].attack = bitmap[idx].attack or point.attacking
|
|
||||||
bitmap[idx].place = bitmap[idx].place or not(point.attacking)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--now map pixels to 3-byte strings
|
|
||||||
for j = 2, size do
|
|
||||||
if bitmap[j] == 0
|
|
||||||
then bitmap[j] = "\0\0\0"
|
|
||||||
else bitmap[j] = string.char( bitmap[j].attack and 0xff or 0, bitmap[j].place and 0xff or 0, 0 )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return table.concat( bitmap )
|
|
||||||
end
|
|
||||||
return t
|
return t
|
109
button.lua
109
button.lua
|
@ -1,101 +1,32 @@
|
||||||
local lg = love.graphics
|
local t = {}
|
||||||
|
|
||||||
local t = {
|
function t.onHover( button )
|
||||||
name = "",
|
|
||||||
tooltip = "button",
|
|
||||||
icon = lg.newImage( "icons/eye.bmp" ),
|
|
||||||
x = 8,
|
|
||||||
y = 250,
|
|
||||||
w = 176,
|
|
||||||
h = 24,
|
|
||||||
group = false,
|
|
||||||
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
|
|
||||||
|
|
||||||
function t.contains( button, x, y )
|
|
||||||
return x < button.x + button.w and x > button.x
|
|
||||||
and y < button.y + button.h and y > button.y
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.new( b )
|
function t.onClick( button )
|
||||||
b = setmetatable( b or {}, t )
|
|
||||||
b.next = t
|
|
||||||
t.prev.next = b
|
|
||||||
b.prev = t.prev
|
|
||||||
t.prev = b
|
|
||||||
return b
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local drawPassOngoing = false
|
function t.newButton( name, tooltip, icon, x, y, w, h, callback )
|
||||||
function t.draw( b )
|
return setmetatable( {
|
||||||
if b == t then
|
name = name,
|
||||||
drawPassOngoing = not( drawPassOngoing )
|
tooltip = tooltip,
|
||||||
if not drawPassOngoing then return end
|
icon = icon,
|
||||||
elseif b.visible then
|
x = x,
|
||||||
lg.rectangle( "line", b.x, b.y, b.w, b.h, 6 )
|
y = y,
|
||||||
lg.printf( b.name,
|
w = w,
|
||||||
b.x,
|
h = h,
|
||||||
b.y + 0.5 * ( b.h- lg.getFont():getHeight() ),
|
callback = callback },
|
||||||
b.w - 5,
|
t )
|
||||||
"right" )
|
|
||||||
if b.icon then lg.draw( b.icon,
|
|
||||||
b.x, b.y + 0.5 * (b.h - b.icon:getHeight()),
|
|
||||||
0,
|
|
||||||
0.5, 0.5 )
|
|
||||||
end
|
|
||||||
if t.selected == b then
|
|
||||||
lg.rectangle( "fill", b.x, b.y, b.w, b.h, 6 )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return t.draw( b.next )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.select( b )
|
function t.draw( button )
|
||||||
t.selected = b
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.selectNext()
|
t.__index = t
|
||||||
repeat t.selected = t.selected.next until t.selected.visible
|
t.__call = t.newButton
|
||||||
end
|
|
||||||
|
|
||||||
function t.selectPrev()
|
|
||||||
repeat t.selected = t.selected.prev until t.selected.visible
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.selectIn( x, y )
|
|
||||||
t.selected = t
|
|
||||||
repeat t.selected = t.selected.next until (t.selected == t) or (t.selected.visible and t.selected:contains( x, y ))
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.selectNextInGroup()
|
|
||||||
local group = t.selected and t.selected.group
|
|
||||||
if not group then return t.selectNext() end
|
|
||||||
repeat t.selectNext() until group == t.selected.group
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.selectPrevInGroup()
|
|
||||||
local group = t.selected and t.selected.group
|
|
||||||
if not group then return t.selectPrev() end
|
|
||||||
repeat t.selectPrev() until group == t.selected.group
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.displayGroup( group, show )
|
|
||||||
local b = t
|
|
||||||
repeat
|
|
||||||
b = b.next
|
|
||||||
b.visible = ( b.group == group )
|
|
||||||
until b == t
|
|
||||||
t.visible = true
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.deselect( b )
|
|
||||||
t.selected = t
|
|
||||||
end
|
|
||||||
|
|
||||||
setmetatable( t, t )
|
setmetatable( t, t )
|
||||||
t.__index = t
|
|
||||||
t.__call = t.new
|
|
||||||
|
|
||||||
return t
|
return t
|
|
@ -47,8 +47,8 @@ function Camera.Set( x, y, w, h )
|
||||||
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
|
||||||
|
|
||||||
|
|
32
cities.lua
32
cities.lua
|
@ -45,19 +45,19 @@ local citymt = {__index = city}
|
||||||
function city:formatDisplayInfo()
|
function city:formatDisplayInfo()
|
||||||
return (
|
return (
|
||||||
[[
|
[[
|
||||||
NAME: %s
|
NAME: %s
|
||||||
COUNTRY: %s
|
COUNTRY: %s
|
||||||
LONGITUDE: %3.2f
|
LONGITUDE: %3.2f
|
||||||
LATITUDE: %3.2f
|
LATITUDE: %3.2f
|
||||||
POP: %d
|
POP: %d
|
||||||
CAPITAL: %s]]):format( self.name, self.country, self.x, self.y, self.pop, tostring(self.capital) )
|
CAPITAL: %s]]):format( self.name, self.country, self.x, self.y, self.pop, tostring(self.capital) )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.load( filename )
|
function t.load( filename )
|
||||||
|
|
||||||
print( "=== LOADING CITIES. ===" )
|
print( "=== LOADING CITIES. ===" )
|
||||||
|
|
||||||
cities = { visible = true, active = false, filename = filename }
|
cities = { visible = true, active = false }
|
||||||
local n = 1
|
local n = 1
|
||||||
local idxPts = 1
|
local idxPts = 1
|
||||||
local idxCaps = 1
|
local idxCaps = 1
|
||||||
|
@ -97,13 +97,23 @@ function t.load( filename )
|
||||||
return cities
|
return cities
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.save( cities )
|
function t.save( cities, filename )
|
||||||
|
print( "=== SAVING CITIES ===" )
|
||||||
local str = {}
|
local str = {}
|
||||||
for n, city in ipairs( cities ) do
|
for n, city in ipairs( cities ) do
|
||||||
str[n] = ("%-41s%-41s%-14f%-14f%-19d %d"):format(
|
str[n] = ("%-41s%-41s%-14f%-14f%-19d %d"):format( city.name, city.country, city.x, city.y, city.pop, city.capital and 1 or 0 )
|
||||||
city.name, city.country, city.x, city.y, city.pop, city.capital and 1 or 0 )
|
|
||||||
end
|
end
|
||||||
return assert(table.concat( str, "\n" ))
|
str = assert(table.concat( str, "\n" ))
|
||||||
|
local file = assert( io.open( filename, "w+" ) )
|
||||||
|
assert( file:write( str ) )
|
||||||
|
file:close()
|
||||||
|
--[[local tmpname = os.tmpname()
|
||||||
|
local tmpfile = assert( io.open( tmpname, "w+" ) )
|
||||||
|
assert( tmpfile:write( str ) )
|
||||||
|
tmpfile:close()
|
||||||
|
os.remove( filename ) --ooh this is probably pretty bad
|
||||||
|
os.rename( tmpname, filename )]]
|
||||||
|
print( "=== CITIES SAVED ===" )
|
||||||
end
|
end
|
||||||
|
|
||||||
return t
|
return t
|
2
conf.lua
2
conf.lua
|
@ -13,7 +13,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 = 800 -- The window width (number)
|
||||||
t.window.height = 640 -- The window height (number)
|
t.window.height = 600 -- 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)
|
||||||
t.window.minwidth = 512 -- Minimum window width if the window is resizable (number)
|
t.window.minwidth = 512 -- Minimum window width if the window is resizable (number)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 144 KiB |
BIN
icons/city.bmp
BIN
icons/city.bmp
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
BIN
icons/undo.bmp
BIN
icons/undo.bmp
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
BIN
icons/up.bmp
BIN
icons/up.bmp
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
61
lines.lua
61
lines.lua
|
@ -3,28 +3,16 @@ local t = {}
|
||||||
local lfs = love.filesystem
|
local lfs = love.filesystem
|
||||||
local lg = love.graphics
|
local lg = love.graphics
|
||||||
|
|
||||||
local polygon = { x = 180, X = -180, y = 100, Y = -100 } --default empty bounding box
|
|
||||||
local polymt = { __index = polygon }
|
|
||||||
|
|
||||||
function polygon:formatDisplayInfo()
|
|
||||||
return ([[
|
|
||||||
x: %f
|
|
||||||
y: %f
|
|
||||||
X: %f
|
|
||||||
Y: %f
|
|
||||||
N: %d]]):format( self.x, self.y, self.X, self.Y, #self )
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.load( filename )
|
function t.load( filename )
|
||||||
local polys = { visible = true, filename = filename }
|
local polys = { visible = true }
|
||||||
local poly = {}
|
local poly = {}
|
||||||
local n = 1
|
local n = 0
|
||||||
local k = 1
|
local k = 1
|
||||||
for line in assert( lfs.lines( filename ) ) do
|
for line in assert( lfs.lines( filename ) ) do
|
||||||
if line:find "b" then
|
if line:find "b" then
|
||||||
k = 1
|
k = 1
|
||||||
if #poly > 2 then n = n + 1 end
|
if #poly > 2 then n = n + 1 end
|
||||||
poly = setmetatable({}, polymt) --axis-aligned bounding box
|
poly = {}
|
||||||
polys[n] = poly
|
polys[n] = poly
|
||||||
else
|
else
|
||||||
local _, _, x, y = line:find( "(%g+)%s+(%g+)" )
|
local _, _, x, y = line:find( "(%g+)%s+(%g+)" )
|
||||||
|
@ -32,16 +20,12 @@ function t.load( filename )
|
||||||
if x and y then
|
if x and y then
|
||||||
poly[k], poly[ k + 1 ] = x, y
|
poly[k], poly[ k + 1 ] = x, y
|
||||||
k = k + 2
|
k = k + 2
|
||||||
if x < poly.x then poly.x = x end
|
|
||||||
if x > poly.X then poly.X = x end
|
|
||||||
if y < poly.y then poly.y = y end
|
|
||||||
if y > poly.Y then poly.Y = y end
|
|
||||||
else
|
else
|
||||||
print( "LINES: malformed line:", filename, line )
|
print( "LINES: malformed line:", filename, line )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not polys[n] or (#(polys[n]) < 3) then
|
if not polys[n] or (#(polys[n]) < 3) then
|
||||||
polys[n] = nil
|
polys[n] = nil
|
||||||
n = n - 1
|
n = n - 1
|
||||||
|
@ -51,50 +35,25 @@ function t.load( filename )
|
||||||
return setmetatable( polys, {__index = t } )
|
return setmetatable( polys, {__index = t } )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.selectNearest( lines, wx, wy )
|
function t.save( lines, filename )
|
||||||
local d = math.huge
|
|
||||||
local nearest
|
|
||||||
for i, poly in ipairs( lines ) do
|
|
||||||
if poly.x - 5 < wx and
|
|
||||||
poly.X + 5 > wx and
|
|
||||||
poly.y - 5 < wy and
|
|
||||||
poly.Y + 5 > wy then
|
|
||||||
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
|
|
||||||
nearest = poly
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nearest
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.save( lines )
|
|
||||||
local str = {}
|
|
||||||
for i, poly in ipairs( lines ) do
|
|
||||||
str[i] = table.concat( poly, " " )
|
|
||||||
end
|
|
||||||
str = table.concat( str, "\nb\n" ):gsub("(%S+) (%S+) ", "%1 %2\n")
|
|
||||||
return str
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.newPolygon( x, y )
|
function t.newPolygon( x, y )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.addToCurrentPolygon( x, y )
|
function t.addToCurrentPolygon( x, y )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.deletePolygon( poly )
|
function t.deletePolygon( poly )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.drawPolygonEditHandles( poly )
|
function t.drawPolygonEditHandles( poly )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.draw( lines )
|
function t.draw( lines )
|
||||||
|
|
289
main.lua
289
main.lua
|
@ -1,10 +1,10 @@
|
||||||
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'
|
||||||
local savemodal = require 'savemodal'
|
|
||||||
local button = require 'button'
|
local button = require 'button'
|
||||||
local SAVEDIRECTORY = "out/"
|
local SAVEDIRECTORY = "out/"
|
||||||
local Camera = require 'camera'
|
local Camera = require 'camera'
|
||||||
|
local wasKeyPressed
|
||||||
|
|
||||||
function love.load()
|
function love.load()
|
||||||
|
|
||||||
|
@ -13,15 +13,12 @@ function love.load()
|
||||||
assert( lfs.createDirectory( SAVEDIRECTORY.."data/earth" ))
|
assert( lfs.createDirectory( SAVEDIRECTORY.."data/earth" ))
|
||||||
assert( lfs.createDirectory( SAVEDIRECTORY.."data/graphics" ))
|
assert( lfs.createDirectory( SAVEDIRECTORY.."data/graphics" ))
|
||||||
|
|
||||||
love.keyboard.setKeyRepeat( true )
|
|
||||||
love.graphics.setNewFont( 14 )--, "mono" )
|
love.graphics.setNewFont( 12, "mono" )
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.directorydropped( path )
|
function love.directorydropped( path )
|
||||||
if map.path then
|
if map.path then assert( love.filesystem.unmount( map.path ) ) end
|
||||||
assert( love.filesystem.unmount( map.path ) )
|
|
||||||
map.loaded = false
|
|
||||||
end
|
|
||||||
love.filesystem.mount( path, "" )
|
love.filesystem.mount( path, "" )
|
||||||
return map.load( path )
|
return map.load( path )
|
||||||
end
|
end
|
||||||
|
@ -40,35 +37,72 @@ function love.update( dt )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local toolButtons = {
|
||||||
|
"Brush",
|
||||||
|
"Move Nodes",
|
||||||
|
"Add Nodes",
|
||||||
|
"Edit Node",
|
||||||
|
"Draw Polygon",
|
||||||
|
"Erase Polygon"
|
||||||
|
}
|
||||||
|
|
||||||
|
local layerButtons = {
|
||||||
|
"Africa",
|
||||||
|
"Europe",
|
||||||
|
"North America",
|
||||||
|
"South America",
|
||||||
|
"Asia",
|
||||||
|
"Russia",
|
||||||
|
"Travel Nodes",
|
||||||
|
"AI Markers",
|
||||||
|
"Cities",
|
||||||
|
"Coastlines",
|
||||||
|
"Coastlines Low",
|
||||||
|
"Sailable"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function love.draw()
|
function love.draw()
|
||||||
if not map.loaded then
|
if not map.loaded then
|
||||||
local w, h = love.graphics.getDimensions()
|
return love.graphics.print( "Drag and drop folder to begin.")
|
||||||
return love.graphics.printf( "Drag and drop folder to begin.", w / 2 - 200, h / 2 - 128, 400, "center")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
love.graphics.push( "all" )
|
love.graphics.push( "all" )
|
||||||
map.draw()
|
map.draw()
|
||||||
love.graphics.pop()
|
love.graphics.pop()
|
||||||
|
|
||||||
|
--Layer buttons.
|
||||||
|
do
|
||||||
|
love.graphics.setColor( 1, 1, 1, 1 )
|
||||||
|
local h = love.graphics.getHeight() - 60
|
||||||
|
for x = 0, 300, 30 do
|
||||||
|
love.graphics.rectangle( "line", x, h, 30, 30 )
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--Status bar.
|
--Status bar.
|
||||||
local x, y = love.mouse.getPosition()
|
local x, y = love.mouse.getPosition()
|
||||||
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
||||||
local bx, by = Camera.GetBitmapCoordinate( x, y )
|
local bx, by = Camera.GetBitmapCoordinate( x, y )
|
||||||
local h = love.graphics.getHeight() - 60
|
local h = love.graphics.getHeight() - 30
|
||||||
love.graphics.setColor( 0.1, 0.1, 0.5, 0.8 )
|
love.graphics.setColor( 0.2, 0.1, 0.1, 1.0 )
|
||||||
love.graphics.rectangle( "fill", 0, 0, 250, love.graphics.getHeight() )
|
love.graphics.rectangle( "fill", 0, h, love.graphics.getWidth() / 2, 30 )
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
love.graphics.setColor( 1, 1, 1, 1 )
|
||||||
love.graphics.print(([[
|
love.graphics.rectangle( "line", 0, h, love.graphics.getWidth() / 2, 30 )
|
||||||
SCREEN %-12d %-12d
|
love.graphics.print(("SCREEN\t%d\t%d\nWORLD \t%5.2f\t%5.2f"):format(x, y, wx, wy), 0, h)
|
||||||
WORLD %-12.2f%-12.2f
|
love.graphics.print(("BITMAP\t%5.2f\t%5.2f"):format(bx, by), 200, h )
|
||||||
BITMAP %-12.2f%-12.2f
|
|
||||||
%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
|
--Edit box.
|
||||||
if map.selectionLocked then end
|
love.graphics.rectangle( "line", love.graphics.getWidth() / 2, h, love.graphics.getWidth() / 2, 30 )
|
||||||
|
if map.selected then
|
||||||
love.graphics.setColor( 1, 1, 1, 0.8 )
|
love.graphics.setColor( 0.2, 0.1, 0.1, 1.0 )
|
||||||
button:draw()
|
love.graphics.rectangle( "fill", 0, 0, 150 ,100 )
|
||||||
|
love.graphics.setColor( 1, 1, 1, 1 )
|
||||||
|
love.graphics.rectangle( "line", 0, 0, 150 ,100 )
|
||||||
|
love.graphics.setColor( 1.2, 1.1, 1.1, 1.5 )
|
||||||
|
love.graphics.print( map.selected:formatDisplayInfo(), 0, 0 )
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.resize(w, h)
|
function love.resize(w, h)
|
||||||
|
@ -76,185 +110,62 @@ function love.resize(w, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.wheelmoved(x, y)
|
function love.wheelmoved(x, y)
|
||||||
Camera.Zoom( (y > 0) and 0.1 or -0.1 )
|
Camera.Zoom( (y > 0) and 0.5 or -0.5 )
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.mousepressed( x, y, mouseButton, istouch, presses )
|
function love.mousepressed( x, y, button, istouch, presses )
|
||||||
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
||||||
|
if map.loaded then
|
||||||
if button.selected and button.selected:contains( x, y ) then
|
if button == 1 then
|
||||||
print( ("MOUSE\tx %f\ty %f\twx %f\twy %f"):format(x, y, wx, wy) )
|
map.cities.lockSelection()
|
||||||
return button.selected:callback()
|
else
|
||||||
|
map.cities.unlockSelection()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
print( ("MOUSE\tx %f\ty %f\twx %f\twy %f"):format(x, y, wx, wy) )
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.mousemoved( x, y, dx, dy, istouch )
|
function love.mousemoved( x, y, dx, dy, istouch )
|
||||||
if not map.loaded then return end
|
local wx, wy = Camera.GetWorldCoordinate( x, y )
|
||||||
--mouse over menu
|
if map.loaded then
|
||||||
button.selectIn( x, y )
|
if map.cities.visible then map.selected = map.cities:selectNearest( wx, wy )
|
||||||
|
elseif map.travelnodes.visible then map.selected = map.travelnodes:selectNearest( wx, wy )
|
||||||
--mouse on map
|
elseif map.ainodes.visible then map.selected = map.ainodes:selectNearest( wx, wy )
|
||||||
if map.selectionLocked then return end
|
end
|
||||||
if map.editLayer and map.editLayer.selectNearest then
|
|
||||||
map.selected = map.editLayer:selectNearest( Camera.GetWorldCoordinate( x, y ) )
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function love.keypressed(key, code, isRepeat)
|
local function ToggleVisibility( layer )
|
||||||
|
if not layer then return end
|
||||||
if code == "left" then return button.selectPrev() end
|
local ml
|
||||||
if code == "right" then return button.selectNext() end
|
if map[layer] then ml = map[layer] end
|
||||||
if code == "down" then return button.selectNextInGroup() end
|
if map.territory[layer] then ml = map.territory[layer] end
|
||||||
if code == "up" then return button.selectPrevInGroup() end
|
assert( ml )
|
||||||
if code == "return" then return button.selected:callback() end
|
ml.visible = not( ml.visible )
|
||||||
|
print( layer, ml.visible )
|
||||||
if key == "c" then
|
|
||||||
map.selectionLocked = not( map.selectionLocked )
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local layerVisibilityKeybinds = {
|
||||||
|
["1"] = "africa",
|
||||||
|
["2"] = "europe",
|
||||||
|
["3"] = "northamerica",
|
||||||
|
["4"] = "southamerica",
|
||||||
|
["5"] = "southasia",
|
||||||
|
["6"] = "russia",
|
||||||
|
["7"] = "sailable",
|
||||||
|
["8"] = "coastlines",
|
||||||
|
["9"] = "coastlinesLow",
|
||||||
|
["0"] = "international",
|
||||||
|
["-"] = "cities",
|
||||||
|
["="] = "travelnodes",
|
||||||
|
["backspace"] = "ainodes",
|
||||||
|
}
|
||||||
|
|
||||||
|
function love.keypressed(key)
|
||||||
do
|
ToggleVisibility( layerVisibilityKeybinds[key] )
|
||||||
|
wasKeyPressed = true
|
||||||
local function toolCallback( self )
|
|
||||||
local f = (map.layers[self.layer])[self.name]
|
if key == "l" then
|
||||||
if f then return f(self) end
|
return map.save()
|
||||||
end
|
end
|
||||||
|
|
||||||
local 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 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" },
|
|
||||||
{ name = "AI", layer = "ainodes" },
|
|
||||||
{ name = "CITY", layer = "cities" },
|
|
||||||
{ name = "COAST", layer = "coastlines" },
|
|
||||||
{ name = "LOW", layer = "coastlinesLow"},
|
|
||||||
{ name = "SAIL", layer = "sailable" },
|
|
||||||
}
|
|
||||||
|
|
||||||
local visibilityIcon = love.graphics.newImage( "icons/eye.bmp" )
|
|
||||||
local function toggleVisibleLayer( self )
|
|
||||||
if not (self and self.layer) then return end
|
|
||||||
local ml = map.layers[ self.layer ]
|
|
||||||
ml.visible = not( ml.visible )
|
|
||||||
self.icon = ml.visible and visibilityIcon
|
|
||||||
end
|
|
||||||
|
|
||||||
local soloIcon = love.graphics.newImage( "icons/eye.bmp" )
|
|
||||||
local function soloVisibleLayer( self )
|
|
||||||
--hide icons for disabled invisible layers
|
|
||||||
print( "===SOLO LAYER===", self.layer )
|
|
||||||
for i, button in ipairs( layerButtons ) do
|
|
||||||
if button.layer ~= self.layer then
|
|
||||||
button.icon = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.icon = soloIcon
|
|
||||||
|
|
||||||
for k, layer in pairs( map.layers ) do
|
|
||||||
print( "invisible layer, map:", k, layer)
|
|
||||||
layer.visible = false
|
|
||||||
end
|
|
||||||
map.layers[ self.layer ].visible = true
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local backButton
|
|
||||||
local function editLayer( self )
|
|
||||||
map.editLayer = map.layers[ self.layer ]
|
|
||||||
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
|
|
||||||
return soloVisibleLayer( self )
|
|
||||||
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 showButtons = {}
|
|
||||||
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 = "V",
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
backButton = button.new{
|
|
||||||
name = "UP",
|
|
||||||
visible = false,
|
|
||||||
y = 250 + button.h + 4,
|
|
||||||
icon = love.graphics.newImage( "icons/up.bmp" ),
|
|
||||||
callback = back,
|
|
||||||
}
|
|
||||||
|
|
||||||
button.new{ name = "UNDO", y = 250, callback = map.undo, icon = love.graphics.newImage( "icons/undo.bmp" ) }
|
|
||||||
button.new{ name = "SAVE", y = 222, callback = savemodal.start, icon = false }
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
87
map.lua
87
map.lua
|
@ -6,31 +6,11 @@ local Nodes = require 'travelNodes'
|
||||||
local Camera = require 'camera'
|
local Camera = require 'camera'
|
||||||
local Territory = require 'territory'
|
local Territory = require 'territory'
|
||||||
|
|
||||||
--flat list of editable layers for convenience
|
local map = {
|
||||||
local layers = {
|
loaded = false,
|
||||||
coastlines = false,
|
coastlines = false,
|
||||||
coastlinesLow = false,
|
coastlinesLow = false,
|
||||||
international = false,
|
international = false,
|
||||||
africa = false,
|
|
||||||
europe = false,
|
|
||||||
northamerica = false,
|
|
||||||
russia = false,
|
|
||||||
southamerica = false,
|
|
||||||
southasia = false,
|
|
||||||
travelnodes = false,
|
|
||||||
sailable = false,
|
|
||||||
ainodes = false,
|
|
||||||
cities = false,
|
|
||||||
}
|
|
||||||
|
|
||||||
local map = {
|
|
||||||
layers = layers,
|
|
||||||
path = false,
|
|
||||||
loaded = false,
|
|
||||||
selected = false,
|
|
||||||
selectionLocked = false,
|
|
||||||
editLayer = false,
|
|
||||||
|
|
||||||
territory = {
|
territory = {
|
||||||
africa = false,
|
africa = false,
|
||||||
europe = false,
|
europe = false,
|
||||||
|
@ -39,11 +19,6 @@ local map = {
|
||||||
southamerica = false,
|
southamerica = false,
|
||||||
southasia = false
|
southasia = false
|
||||||
},
|
},
|
||||||
|
|
||||||
background = false,
|
|
||||||
coastlines = false,
|
|
||||||
coastlinesLow = false,
|
|
||||||
international = false,
|
|
||||||
travelnodes = false,
|
travelnodes = false,
|
||||||
sailable = false,
|
sailable = false,
|
||||||
ainodes = false,
|
ainodes = false,
|
||||||
|
@ -51,7 +26,6 @@ local map = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function map.load( path )
|
function map.load( path )
|
||||||
map.background = lg.newImage( "data/graphics/blur.bmp" )
|
|
||||||
map.cities = Cities.load( "data/earth/cities.dat" )
|
map.cities = Cities.load( "data/earth/cities.dat" )
|
||||||
map.coastlines = Lines.load( "data/earth/coastlines.dat" )
|
map.coastlines = Lines.load( "data/earth/coastlines.dat" )
|
||||||
map.coastlinesLow = Lines.load( "data/earth/coastlines-low.dat" )
|
map.coastlinesLow = Lines.load( "data/earth/coastlines-low.dat" )
|
||||||
|
@ -64,11 +38,6 @@ function map.load( path )
|
||||||
end
|
end
|
||||||
map.loaded = true
|
map.loaded = true
|
||||||
map.path = path
|
map.path = path
|
||||||
|
|
||||||
--update references
|
|
||||||
for k, v in pairs( layers ) do
|
|
||||||
layers[k] = map[k] or map.territory[k]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function map.draw()
|
function map.draw()
|
||||||
|
@ -76,13 +45,10 @@ function map.draw()
|
||||||
if not map.loaded then return end
|
if not map.loaded then return end
|
||||||
|
|
||||||
do --territory
|
do --territory
|
||||||
|
lg.setColor( 1,1,1,1)
|
||||||
lg.setLineJoin( "none" )
|
lg.setLineJoin( "none" )
|
||||||
lg.replaceTransform( Camera.tfTerritory )
|
lg.replaceTransform( Camera.tfTerritory )
|
||||||
lg.setBlendMode( "add" )
|
lg.setBlendMode( "add" )
|
||||||
|
|
||||||
lg.setColor( 1, 1, 1, 0.2 )
|
|
||||||
lg.draw( map.background )
|
|
||||||
lg.setColor( 1, 1, 1, 0.5 )
|
|
||||||
for k, v in pairs(map.territory) do
|
for k, v in pairs(map.territory) do
|
||||||
if v.visible then
|
if v.visible then
|
||||||
v:draw()
|
v:draw()
|
||||||
|
@ -112,21 +78,12 @@ function map.draw()
|
||||||
do --all this stuff is drawn in world coordinates, ( -180, 180 ) x ( -100, 100 )
|
do --all this stuff is drawn in world coordinates, ( -180, 180 ) x ( -100, 100 )
|
||||||
|
|
||||||
lg.replaceTransform( Camera.tf )
|
lg.replaceTransform( Camera.tf )
|
||||||
|
|
||||||
if map.selected then
|
if map.selected then
|
||||||
if map.selected[1] then --lines
|
lg.setColor( 1.0, 0.5, 0.5, 0.9 )
|
||||||
local p = map.selected
|
lg.setLineJoin( "miter" )
|
||||||
lg.setColor( 0.4, 0.5, 0.8, 0.5 )
|
lg.setLineWidth( 1.0 / Camera.zoom )
|
||||||
lg.setLineWidth( 0.2 / Camera.zoom )
|
lg.circle( "line", map.selected.x, map.selected.y, 0.2 + 1.0 / Camera.zoom )
|
||||||
lg.rectangle( "fill", p.x, p.y, p.X - p.x, p.Y - p.y )
|
|
||||||
lg.setColor( 1.0, 0, 0, 1 )
|
|
||||||
lg.line( p )
|
|
||||||
else --points
|
|
||||||
lg.setColor( 1.0, 0.5, 0.5, 0.9 )
|
|
||||||
lg.setLineJoin( "miter" )
|
|
||||||
lg.setLineWidth( 1.0 / Camera.zoom )
|
|
||||||
lg.circle( "line", map.selected.x, map.selected.y, 0.2 + 1.0 / Camera.zoom )
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if map.cities.visible then --points
|
if map.cities.visible then --points
|
||||||
|
@ -137,7 +94,7 @@ function map.draw()
|
||||||
|
|
||||||
lg.setColor( 1, 1, 0.0, 0.5 )
|
lg.setColor( 1, 1, 0.0, 0.5 )
|
||||||
map.cities.drawCapitals()
|
map.cities.drawCapitals()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if map.ainodes.visible then
|
if map.ainodes.visible then
|
||||||
|
@ -171,24 +128,22 @@ function map.draw()
|
||||||
map.travelnodes:draw()
|
map.travelnodes:draw()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function write( filename, string )
|
|
||||||
print( "Pretending to write", string:len(), "bytes to", filename )
|
|
||||||
--[[ os.rename( filename, filename..".bak" ) --just in case :^)
|
|
||||||
local file = assert( io.open( filename, "w+" ) )
|
|
||||||
assert( file:write( string ) )
|
|
||||||
file:close()]]
|
|
||||||
end
|
|
||||||
|
|
||||||
function map.save()
|
function map.save()
|
||||||
for k, layer in pairs( layers ) do
|
map.cities:save( map.path.."/data/earth/cities.dat" )
|
||||||
print( "SAVING:", k, tostring( layer.filename ) )
|
map.coastlines.save()
|
||||||
write( map.path..tostring( layer.filename ), assert( layer:save() ) )
|
map.coastlinesLow.save()
|
||||||
|
map.international.save()
|
||||||
|
map.sailable.save()
|
||||||
|
map.travelnodes.save()
|
||||||
|
map.ainodes.save()
|
||||||
|
for k, v in pairs(map.territory) do
|
||||||
|
map.territory[k].save()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -196,8 +151,4 @@ function map.hover(x, y)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function map.undo()
|
|
||||||
print( "=== UNDO ===" )
|
|
||||||
end
|
|
||||||
|
|
||||||
return map
|
return map
|
||||||
|
|
51
modal.lua
51
modal.lua
|
@ -1,51 +0,0 @@
|
||||||
local love = assert( love )
|
|
||||||
local button = require( "button" )
|
|
||||||
local t = {}
|
|
||||||
t.__index = t
|
|
||||||
|
|
||||||
local i = 0
|
|
||||||
function t.start( self )
|
|
||||||
i = i + 1
|
|
||||||
t[i] = t[i] or {}
|
|
||||||
|
|
||||||
--store callbacks
|
|
||||||
for name in pairs( self ) do
|
|
||||||
if love[name] then
|
|
||||||
t[i][name] = love[name]
|
|
||||||
love[name] = self[name]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--store menus
|
|
||||||
local b = button.next
|
|
||||||
repeat
|
|
||||||
t[i][b] = b.visible
|
|
||||||
b = b.next
|
|
||||||
until b == button
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.stop( self )
|
|
||||||
--restore callbacks
|
|
||||||
for name in pairs( self ) do
|
|
||||||
if love[name] then
|
|
||||||
love[name] = t[i][name]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--restore menus
|
|
||||||
local b = button
|
|
||||||
repeat
|
|
||||||
b = b.next
|
|
||||||
b.visible = t[i][b]
|
|
||||||
until b == button
|
|
||||||
|
|
||||||
t[i] = nil
|
|
||||||
i = i - 1
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.new( modal )
|
|
||||||
return setmetatable( modal or {}, t )
|
|
||||||
end
|
|
||||||
|
|
||||||
return t
|
|
|
@ -1,52 +0,0 @@
|
||||||
local love = assert( love )
|
|
||||||
local modal = require( "modal" )
|
|
||||||
local button = require( "button" )
|
|
||||||
local map = require( "map" )
|
|
||||||
local t = {}
|
|
||||||
|
|
||||||
local saveLocation = map.path
|
|
||||||
local saveButton = button.new{
|
|
||||||
group = "saveModal",
|
|
||||||
name = "save",
|
|
||||||
callback = function() map.save(); return t:stop() end,
|
|
||||||
visible = false,
|
|
||||||
x = 20,
|
|
||||||
y = 20,
|
|
||||||
w = 400,
|
|
||||||
h = 100,
|
|
||||||
}
|
|
||||||
|
|
||||||
local cancelButton = button.new{
|
|
||||||
group = "saveModal",
|
|
||||||
name = "cancel",
|
|
||||||
visible = false,
|
|
||||||
callback = function() return t:stop() end,
|
|
||||||
x = 20,
|
|
||||||
y = 150,
|
|
||||||
w = 400,
|
|
||||||
h = 100
|
|
||||||
}
|
|
||||||
|
|
||||||
function t.start()
|
|
||||||
modal.start( t )
|
|
||||||
button.selected = saveButton
|
|
||||||
saveButton.name = "save to "..map.path
|
|
||||||
button.displayGroup( "saveModal", true )
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.draw()
|
|
||||||
love.graphics.clear( 0,0,0,1 )
|
|
||||||
love.graphics.setColor( 1, 1, 1, 0.5 )
|
|
||||||
button:draw()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.directorydropped( path )
|
|
||||||
saveLocation = path
|
|
||||||
map.path = path
|
|
||||||
saveButton.name = "save to "..map.path
|
|
||||||
return love.filesystem.mount( path, "" )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return modal.new( t )
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
local jit = require 'jit'
|
||||||
|
for k, v in pairs( jit.opt ) do print(k , v ) end
|
|
@ -18,7 +18,6 @@ function t.load( filename, name )
|
||||||
local territory = {
|
local territory = {
|
||||||
visible = true,
|
visible = true,
|
||||||
name = name,
|
name = name,
|
||||||
filename = filename,
|
|
||||||
colour = colours[name],
|
colour = colours[name],
|
||||||
border = {},
|
border = {},
|
||||||
img = img,
|
img = img,
|
||||||
|
@ -145,8 +144,12 @@ function t.computeBorder( territory, threshold, key )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.save( territory )
|
function t.drawConnections( nodes )
|
||||||
return bmp.save( territory.imgd, "512rgb24" )
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function t.save( nodes, filename )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return t
|
return t
|
|
@ -1,64 +0,0 @@
|
||||||
local love = assert( love )
|
|
||||||
local utf8 = require("utf8")
|
|
||||||
local modal = require( "modal" )
|
|
||||||
local t = modal.new{ }
|
|
||||||
|
|
||||||
function t.setCurrentModal( fields )
|
|
||||||
t.currentModal = assert( fields )
|
|
||||||
t.currentIdx = 1
|
|
||||||
return t:start()
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.draw()
|
|
||||||
if not t.currentModal then return end
|
|
||||||
love.graphics.setColor( 0, 0, 0, 0.3 )
|
|
||||||
love.graphics.rectangle("fill", 0, 0, love.graphics.getDimensions())
|
|
||||||
|
|
||||||
|
|
||||||
-- other fields
|
|
||||||
for i, field in ipairs( t.currentModal ) do
|
|
||||||
love.graphics.setColor( 1, 1, 1, 0.2 )
|
|
||||||
local mode = (i == t.currentIdx) and "fill" or "line"
|
|
||||||
love.graphics.rectangle( mode, 200, i * 28, 200, 14, 4 )
|
|
||||||
love.graphics.setColor( 1, 1, 1, 1 )
|
|
||||||
love.graphics.print( field.name, 8, i * 28 )
|
|
||||||
love.graphics.print( field.value, 216, i * 28 )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.textinput( char )
|
|
||||||
if t.currentModal then
|
|
||||||
local field = t.currentModal.currentFieldIdx
|
|
||||||
t.currentModal.currentField.value = t.currentModal.currentField.value .. char
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.keypressed(key, code, isRepeat)
|
|
||||||
if code == "down" then
|
|
||||||
t.currentIdx = t.currentIdx + 1
|
|
||||||
if t.currentIdx > #(t.currentModal) then
|
|
||||||
t.currentIdx = 1
|
|
||||||
end
|
|
||||||
elseif code == "up" then
|
|
||||||
t.currentIdx = t.currentIdx - 1
|
|
||||||
if t.currentIdx < 1 then
|
|
||||||
t.currentIdx = #(t.currentModal)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if key == "backspace" then
|
|
||||||
-- 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).
|
|
||||||
text = string.sub(text, 1, byteoffset - 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if key == "escape" then
|
|
||||||
return t:stop()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return t
|
|
|
@ -14,17 +14,17 @@ local function isConnected( startNode, endNode )
|
||||||
local ix, iy, fx, fy = startNode.x, startNode.y, endNode.x, endNode.y
|
local ix, iy, fx, fy = startNode.x, startNode.y, endNode.x, endNode.y
|
||||||
if fx < -180 then fx = fx + 180 end
|
if fx < -180 then fx = fx + 180 end
|
||||||
if fx > 180 then fx = fx - 180 end
|
if fx > 180 then fx = fx - 180 end
|
||||||
|
|
||||||
local dx, dy = fx - ix, fy - iy
|
local dx, dy = fx - ix, fy - iy
|
||||||
local mag = math.sqrt( dx * dx + dy * dy )
|
local mag = math.sqrt( dx * dx + dy * dy )
|
||||||
local n = 2 * math.floor( mag )
|
local n = 2 * math.floor( mag )
|
||||||
dx, dy = 0.5 * dx / mag, 0.5 * dy / mag
|
dx, dy = 0.5 * dx / mag, 0.5 * dy / mag
|
||||||
|
|
||||||
for i = 1, n do
|
for i = 1, n do
|
||||||
ix, iy = ix + dx, iy + dy
|
ix, iy = ix + dx, iy + dy
|
||||||
if not( isSailable( ix, -iy ) ) then return nil end
|
if not( isSailable( ix, -iy ) ) then return nil end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -41,43 +41,39 @@ function travelNode:formatDisplayInfo()
|
||||||
LATITUDE: %3.2f]]):format( self.idx, self.x, self.y )
|
LATITUDE: %3.2f]]):format( self.idx, self.x, self.y )
|
||||||
end
|
end
|
||||||
|
|
||||||
local function worldToBitmap( x, y )
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local function bitmapToWorld( x, y )
|
|
||||||
return 360 * ( x - 800 ) / 800 - 360 / 2 + 360,
|
|
||||||
360 * ( 600 / 800 ) * ( y - 600 ) / 600 + 180
|
|
||||||
end
|
|
||||||
|
|
||||||
function t.load( filename, sailable )
|
function t.load( filename, sailable )
|
||||||
|
|
||||||
isSailable = sailable
|
isSailable = sailable
|
||||||
local img, imgd = bmp.load( filename )
|
local img, imgd = bmp.load( filename )
|
||||||
local nodes = { filename = filename, visible = true, nodes = {}, points = {}, connections = {}, img = img }
|
local nodes = { visible = true, nodes = {}, points = {}, connections = {}, img = img }
|
||||||
|
|
||||||
|
print( "=== Loading Nodes: ===" )
|
||||||
local n = 1
|
local n = 1
|
||||||
for x = 0, 799 do
|
for x = 0, 799 do
|
||||||
for y = 0, 399 do
|
for y = 0, 399 do
|
||||||
if imgd:getPixel( x, 399 - y ) > 0 then
|
if imgd:getPixel( x, 399 - y ) > 0 then
|
||||||
local long, lat = bitmapToWorld( x, y )
|
local long = 360 * ( x - 800 ) / 800 - 360 / 2 + 360
|
||||||
nodes.nodes[n] = setmetatable({x = long, y = lat, idx = n}, mtTravelNode )
|
local lat = 360 * ( 600 / 800 ) * ( 600 - y ) / 600 - 180
|
||||||
|
nodes.nodes[n] = setmetatable({x = long, y = -lat, idx = n}, mtTravelNode )
|
||||||
|
print( nodes.nodes[n]:formatDisplayInfo() )
|
||||||
nodes.points[ 2 * n - 1 ] = long
|
nodes.points[ 2 * n - 1 ] = long
|
||||||
nodes.points[ 2 * n ] = lat
|
nodes.points[ 2 * n ] = lat
|
||||||
n = n + 1
|
n = n + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for i, srcNode in ipairs( nodes.nodes ) do
|
for i, srcNode in ipairs( nodes.nodes ) do
|
||||||
local adjacent = {}
|
local adjacent = {}
|
||||||
|
|
||||||
for j, destNode in ipairs( nodes.nodes ) do
|
for j, destNode in ipairs( nodes.nodes ) do
|
||||||
adjacent[j] = isConnected( srcNode, destNode )
|
adjacent[j] = isConnected( srcNode, destNode )
|
||||||
end
|
end
|
||||||
|
|
||||||
nodes.connections[i] = adjacent
|
nodes.connections[i] = adjacent
|
||||||
end
|
end
|
||||||
|
|
||||||
|
print( "=== Nodes Loaded ===" )
|
||||||
nodes.nodes = locationQuery.New( nodes.nodes )
|
nodes.nodes = locationQuery.New( nodes.nodes )
|
||||||
setmetatable( nodes, {__index = t} )
|
setmetatable( nodes, {__index = t} )
|
||||||
return nodes
|
return nodes
|
||||||
|
@ -85,7 +81,7 @@ end
|
||||||
|
|
||||||
--Determine if graph has more than one connected component.
|
--Determine if graph has more than one connected component.
|
||||||
function t.isConnected( nodes )
|
function t.isConnected( nodes )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.draw( nodes )
|
function t.draw( nodes )
|
||||||
|
@ -96,18 +92,18 @@ function t.draw( nodes )
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.drawConnections( nodes )
|
function t.drawConnections( nodes )
|
||||||
|
|
||||||
for i, connection in pairs( nodes.connections ) do
|
for i, connection in pairs( nodes.connections ) do
|
||||||
for j in pairs( connection ) do
|
for j in pairs( connection ) do
|
||||||
local ix, iy, fx, fy = nodes.nodes[i].x, nodes.nodes[i].y, nodes.nodes[j].x, nodes.nodes[j].y
|
local ix, iy, fx, fy = nodes.nodes[i].x, nodes.nodes[i].y, nodes.nodes[j].x, nodes.nodes[j].y
|
||||||
lg.line( ix, iy, fx, fy )
|
lg.line( ix, -iy, fx, -fy )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function t.save( nodes )
|
function t.save( nodes, filename )
|
||||||
return bmp.savePoints( nodes.nodes, "800r4")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return t
|
return t
|
Loading…
Reference in New Issue