local love = assert( love ) local io = io local coroutine = coroutine local mkdir = assert( require 'lib.mkdir' ) local lg = love.graphics local AI = require 'map.ai' local Cities = require 'map.cities' local Lines = require 'map.lines' local Nodes = require 'map.travelNodes' local Camera = require 'ui.camera' local Territory = require 'map.territory' local Blur = require 'map.blur' --flat list of editable layers for convenience local layers = { coastlines = false, coastlinesLow = false, international = false, africa = false, europe = false, northamerica = false, russia = false, southamerica = false, southasia = false, travelnodes = false, sailable = false, ainodes = false, cities = false, blur = false, } local map = { layers = layers, path = false, loaded = false, selected = false, selectionLocked = false, editLayer = false, territory = { africa = false, europe = false, northamerica = false, russia = false, southamerica = false, southasia = false }, background = false, coastlines = false, coastlinesLow = false, international = false, travelnodes = false, sailable = false, ainodes = false, cities = false, blur = false, } function map.reloadLayer( path ) --Shouldn't call this before the map loads, but just in case if not map.loaded then return end for name, layer in pairs( layers ) do if layer.filename and (layer.filename:gsub( ".+[\\/]", "") == path.filename:gsub( ".+[\\/]", "" )) then local newLayer = layer:load( path ) newLayer.filename = layer.filename --we don't store the full path in there map[ name ] = newLayer layers[ name ] = newLayer return layer.filename end end return end function map.load( path ) map.background = lg.newImage( "/data/graphics/blur.bmp" ) map.cities = Cities.load( "/data/earth/cities.dat" ) map.coastlines = Lines.load( "/data/earth/coastlines.dat" ) map.coastlinesLow = Lines.load( "/data/earth/coastlines-low.dat" ) map.international = Lines.load( "/data/earth/international.dat" ) map.sailable = Territory.load( "/data/earth/sailable.bmp", "sailable" ) map.travelnodes = Nodes.load( "/data/earth/travel_nodes.bmp", map.sailable.isSailable ) --travel node adjacency matrix depends on sailable bitmap map.ainodes = AI.load( "/data/earth/ai_markers.bmp" ) map.blur = Blur.load( "/data/graphics/blur.bmp", map ) for k, v in pairs(map.territory) do map.territory[k] = Territory.load( "/data/earth/"..k..".bmp", k ) end map.loaded = true map.path = path --update references for k, v in pairs( layers ) do layers[k] = map[k] or map.territory[k] end end function map.draw() love.graphics.setScissor( 0, 200, love.graphics.getWidth(), love.graphics.getHeight() - 200 ) lg.clear( 0, 0, 0, 1 ) if not map.loaded then return end do --territory lg.setLineJoin( "none" ) lg.replaceTransform( Camera.tfTerritory ) lg.setBlendMode( "add" ) lg.setColor( 1, 1, 1, 0.2 ) --lg.draw( map.background ) lg.setColor( 1, 1, 1, 0.5 ) local sh = require 'shaders.sailable' lg.setShader( sh ) sh:send( "lowBorder", 60 ) sh:send( "highBorder", 130 ) for k, v in pairs(map.territory) do if v.visible then v:draw() --[[lg.setLineWidth( 1 / Camera.zoom ) v:drawBorder( "land" ) lg.setLineWidth( 3 / Camera.zoom ) v:drawBorder( "sea" )]] end end if map.sailable.visible then sh:send( "lowBorder", 20 ) sh:send( "highBorder", 60 ) lg.setShader( require 'shaders.sailable' ) map.sailable:draw() end lg.setShader() lg.setBlendMode( "alpha" ) lg.setColor( 1, 1, 1, 1 ) end do --all this stuff is drawn in world coordinates, ( -180, 180 ) x ( -100, 100 ) lg.replaceTransform( Camera.tf ) if map.selected then if map.selected[1] then --lines local p = map.selected lg.setColor( 0.4, 0.5, 0.8, 0.5 ) lg.setLineWidth( 0.2 / Camera.zoom ) lg.rectangle( "fill", p.x, p.y, p.X - p.x, p.Y - p.y ) lg.setColor( 1.0, 0, 0, 0.5 ) lg.line( p ) p:drawDirection() 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 if map.cities.visible then --points lg.setColor( 1, 0, 0, 0.5 ) lg.setPointSize( 5.0 ) map.cities.draw() lg.setColor( 1, 1, 0.0, 0.5 ) map.cities.drawCapitals() end if map.ainodes.visible then lg.setPointSize( 5.0 ) map.ainodes:draw() end do --line stuff lg.setColor(1, 1, 1, 0.2 ) lg.setLineJoin( "miter" ) lg.setLineWidth( 0.2 / Camera.zoom ) map.international:draw() lg.setColor(1, 1, 1, 0.5 ) map.coastlines:draw() map.coastlinesLow:draw() --International Date Line lg.line( -180, -100, -180, 100 ) lg.line( 180, -100, 180, 100 ) lg.line( -180, 90, 180, 90 ) lg.line( -180, -90, 180, -90 ) lg.line( -180, 100, 180, 100 ) lg.line( -180, -100, 180, -100 ) end do --travel nodes lg.replaceTransform( Camera.tfNodes ) if map.travelnodes.visible then map.travelnodes:draw() end end end end do local function write( filename, string ) local file = assert( io.open( filename, "wb" ) ) assert( file:write( string ) ) assert( file:flush() ) --your toilet is set to stun, not kill file:close() end local function save() --should be cross platform-ish. --race condition, unfortunately. --maybe we should do this on part on load, then keep a lockfile open in each of these folders for _, folder in ipairs{ "/data/", "/data/earth/", "/data/graphics/" } do coroutine.yield( "Creating folder ".. folder ) assert( mkdir.exists( map.path ), map.path ) local path = map.path..folder if not mkdir.exists( path ) then mkdir.mkdir( path ) end end local files = {} --Write everything to strings first, in case there are errors we don't want to half-write the map for k, layer in pairs( layers ) do coroutine.yield( "Exporting layer ".. k ) files[ map.path..tostring( layer.filename ) ] = assert( layer:save() ) end for filename, str in pairs( files ) do coroutine.yield( "Writing ".. filename ) write( filename, str ) end coroutine.yield() --yield nothing to indicate we're done return save() --save again end map.save = coroutine.wrap( save ) end function map.hover(x, y) end function map.undo() print( "=== UNDO ===" ) 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