File size: 4,306 Bytes
b6a38d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
----- Lua-defined saved in maps
--
-- To add a new grid that a part of the map data, call DefineMapGrid:
--  * the grid will be saved in the map folder if 'save_in_map' is true (otherwise, it gets recreated when the map changes)
--  * the OnMapGridChanged message is invoked when the grid is changed via the Map Editor

if FirstLoad then
	MapGridDefs = {}
end

function DefineMapGrid(name, bits, tile_size, patch_size, save_in_map)
	assert(type(bits) == "number" and type(tile_size) == "number" and tile_size >= 50*guic) -- just a reasonable tile size limit, feel free to lower
	MapGridDefs[name] = {
		bits = bits,
		tile_size = tile_size,
		patch_size = patch_size,
		save_in_map = save_in_map,
	}
end

function DefineMapHexGrid(name, bits, patch_size, save_in_map)
	assert(const.HexWidth)
	MapGridDefs[name] = {
		bits = bits,
		tile_size = const.HexWidth,
		patch_size = patch_size,
		save_in_map = save_in_map,
		hex_grid = true,
	}
end


----- Utilities

function MapGridTileSize(name)
	return MapGridDefs[name] and MapGridDefs[name].tile_size
end

function MapGridSize(name, mapdata)
	-- can't use GetMapBox, the realm might not have been created yet
	mapdata = mapdata or _G.mapdata
	local map_size = point(mapdata.Width - 1, mapdata.Height - 1) * const.HeightTileSize
	
	local data = MapGridDefs[name]
	local tile_size = data.tile_size
	if data.hex_grid then
		local tile_x = tile_size
		local tile_y = MulDivRound(tile_size, const.HexGridVerticalSpacing, const.HexWidth)
		local width  = (map_size:x() + tile_x - 1) / tile_x
		local height = (map_size:y() + tile_y - 1) / tile_y
		return point(width, height)
	end
	return map_size / tile_size
end

function MapGridWorldToStorageBox(name, bbox)
	if not bbox then
		return sizebox(point20, MapGridSize(name))
	end
	
	local data = MapGridDefs[name]
	if data.hex_grid then
		return HexWorldToStore(bbox)
	end
	return bbox / data.tile_size
end


---- Grid saving/loading with map

function OnMsg.MapFolderMounted(map, mapdata)
	for name, data in pairs(MapGridDefs) do
		if rawget(_G, name) then
			_G[name]:free()
		end
		
		local grid
		local filename = string.format("Maps/%s/%s", map, name:lower():gsub("grid", ".grid"))
		if data.save_in_map and io.exists(filename) then
			grid = GridReadFile(filename)
		else
			local width, height = MapGridSize(name, mapdata):xy()
			if data.patch_size then
				grid = NewHierarchicalGrid(width, height, data.patch_size, data.bits)
			else
				grid = NewGrid(width, height, data.bits)
			end
		end
		rawset(_G, name, grid)
	end
end

function OnMsg.SaveMap(folder)
	for name, data in pairs(MapGridDefs) do
		local filename = string.format("%s/%s", folder, name:lower():gsub("grid", ".grid"))
		if data.save_in_map and not _G[name]:equals(0) then
			GridWriteFile(_G[name], filename)
			SVNAddFile(filename)
		else
			SVNDeleteFile(filename)
		end
	end
end


----- Engine function overrides

if Platform.editor then

local old_GetGridNames = editor.GetGridNames
function editor.GetGridNames()
	local grids = old_GetGridNames()
	for name in sorted_pairs(MapGridDefs) do
		table.insert_unique(grids, name)
	end
	return grids
end

local old_GetGrid = editor.GetGrid
function editor.GetGrid(name, bbox, source_grid, mask_grid, mask_grid_tile_size)
	local data = MapGridDefs[name]
	if data then
		local bxgrid = MapGridWorldToStorageBox(name, bbox)
		local new_grid = _G[name]:new_instance(bxgrid:sizex(), bxgrid:sizey())
		new_grid:copyrect(_G[name], bxgrid, point20)
		return new_grid
	end
	return old_GetGrid(name, bbox, source_grid, mask_grid, mask_grid_tile_size)
end

local old_SetGrid = editor.SetGrid
function editor.SetGrid(name, source_grid, bbox, mask_grid, mask_grid_tile_size)
	local data = MapGridDefs[name]
	if data then
		local bxgrid = MapGridWorldToStorageBox(name, bbox)
		_G[name]:copyrect(source_grid, bxgrid - bxgrid:min(), bxgrid:min())
		DbgInvalidateTerrainOverlay(bbox)
		Msg("OnMapGridChanged", name, bbox)
		return
	end
	old_SetGrid(name, source_grid, bbox, mask_grid, mask_grid_tile_size)
end

local old_GetGridDifferenceBoxes = editor.GetGridDifferenceBoxes
function editor.GetGridDifferenceBoxes(name, grid1, grid2, bbox)
	local data = MapGridDefs[name]
	return old_GetGridDifferenceBoxes(name, grid1, grid2, bbox or empty_box, data and data.tile_size or 0)
end

end -- Platform.editor