|
if FirstLoad then |
|
dbg_grid = false |
|
dbg_palette = false |
|
end |
|
|
|
function DbgShowTerrainGrid(grid, palette, forced) |
|
if hr.TerrainDebugDraw == nil then |
|
return |
|
end |
|
if not grid then |
|
if DbgGetTerrainOverlay() == "grid" then |
|
hr.TerrainDebugDraw = 0 |
|
end |
|
return |
|
end |
|
grid = grid or false |
|
palette = palette or false |
|
if forced or dbg_grid ~= grid or DbgGetTerrainOverlay() ~= "grid" or not table.iequal(palette, dbg_palette) then |
|
if dbg_grid then |
|
KeepRefForRendering(dbg_grid) |
|
end |
|
dbg_grid = grid |
|
dbg_palette = palette |
|
DbgSetTerrainOverlay("grid", palette, grid) |
|
end |
|
hr.TerrainDebugDraw = 1 |
|
end |
|
|
|
function DbgToggleTerrainGrid(grid, palette) |
|
if dbg_grid == grid and hr.TerrainDebugDraw ~= 0 then |
|
DbgShowTerrainGrid(false) |
|
else |
|
DbgShowTerrainGrid(grid, palette) |
|
end |
|
end |
|
|
|
function DbgHideTerrainGrid(grid) |
|
if dbg_grid == grid then |
|
DbgShowTerrainGrid(false) |
|
end |
|
end |
|
|
|
|
|
|
|
if FirstLoad then |
|
DbgInspectObjs = false |
|
DbgInspectThread = false |
|
end |
|
|
|
function OnMsg.ChangeMap() |
|
DbgInspectObjs = false |
|
DbgInspectThread = false |
|
end |
|
|
|
function DbgInspectRasterLine(get_height, pos1, pos0, step, zoffset) |
|
step = step or guim |
|
zoffset = zoffset or 0 |
|
if not pos0 then |
|
return |
|
end |
|
local diff = pos1 - pos0 |
|
local dist = diff:Len2D() |
|
local steps = 1 + (dist + step - 1) / step |
|
local p_pstr = pstr("") |
|
local mincol = SetA(yellow, 200) |
|
local maxcol = SetA(white, 200) |
|
local max_diff = 10*guim |
|
local x, y = 0, 0 |
|
for i=1,steps do |
|
local pos = pos0 + MulDivRound(pos1 - pos0, i - 1, steps - 1) |
|
local height = get_height(pos) + zoffset |
|
local color = InterpolateRGB(mincol, maxcol, Clamp(height - zoffset - terrain.GetHeight(pos), 0, max_diff), max_diff) |
|
local point = pos:SetZ(height) |
|
x = x + point:x() |
|
y = y + point:y() |
|
|
|
p_pstr:AppendVertex(point, color) |
|
end |
|
local line = PlaceObject("Polyline") |
|
line:SetMesh(p_pstr) |
|
line:SetDepthTest(false) |
|
line:SetPos(point(x /steps, y / steps)) |
|
DbgInspectObjs = table.create_add(DbgInspectObjs, line) |
|
end |
|
|
|
function DbgInspectRasterArea(get_height, pos, size, step, zoffset) |
|
pos = pos or GetTerrainCursor() |
|
size = size or 64*const.HeightTileSize |
|
step = step or const.HeightTileSize |
|
get_height = get_height or terrain.GetHeight |
|
local steps = 1 + (size + step - 1) / step |
|
size = steps * step |
|
pos = pos - point(size, size) / 2 |
|
for y = 0,steps do |
|
DbgInspectRasterLine(get_height, pos + point(0, y*step), pos + point(size, y*step), step, zoffset) |
|
end |
|
for x = 0,steps do |
|
DbgInspectRasterLine(get_height, pos + point(x*step, 0), pos + point(x*step, size), step, zoffset) |
|
end |
|
end |
|
|
|
function DbgInspectHeightToggle(get_height, area_size, raster_step, zoffset) |
|
if DbgStopInspect() or GetMap() == "" then |
|
return |
|
end |
|
DbgInspectThread = CreateMapRealTimeThread(function() |
|
raster_step = raster_step or const.HeightTileSize |
|
local last_pos |
|
while true do |
|
local pos = DbgGetInspectPos() |
|
if not last_pos or not IsCloser2D(last_pos, pos, raster_step) then |
|
DoneObjects(DbgInspectObjs) |
|
DbgInspectObjs = false |
|
DbgInspectRasterArea(get_height, pos, area_size, raster_step, zoffset) |
|
last_pos = pos |
|
end |
|
Sleep(100) |
|
end |
|
end) |
|
end |
|
|
|
DefineClass.DbgInspectTerminalTarget = { |
|
__parents = { "TerminalTarget" }, |
|
last_mouse_click = false, |
|
} |
|
|
|
function DbgInspectTerminalTarget:OnMouseButtonDown(pt, button, ...) |
|
if button == "L" then |
|
self.last_mouse_click = DbgGetInspectPos() |
|
end |
|
return "continue" |
|
end |
|
|
|
function DbgStopInspect() |
|
DoneObjects(DbgInspectObjs) |
|
DbgInspectObjs = false |
|
|
|
local thread = DbgInspectThread |
|
DbgInspectThread = false |
|
DeleteThread(thread, true) |
|
|
|
terminal.RemoveTarget(DbgInspectTerminalTarget) |
|
DbgInspectTerminalTarget.last_mouse_click = false |
|
|
|
return thread |
|
end |
|
|
|
function DbgDoneInspectObject(obj) |
|
if IsValid(obj) then |
|
DoneObject(obj) |
|
table.remove_value(DbgInspectObjs, obj) |
|
end |
|
end |
|
|
|
function DbgGetInspectPos() |
|
local terrain_pos = GetTerrainCursor() |
|
local ef_all = const.efVisible | const.efCollision |
|
local eye_pos = camera.GetEye() |
|
local obj, pos |
|
if eye_pos:IsValid() then |
|
obj, pos = IntersectSegmentWithClosestObj(eye_pos, terrain_pos, ef_all) |
|
end |
|
return pos or terrain_pos:SetInvalidZ() |
|
end |
|
|
|
function DbgStartInspectPos(callbacks, ...) |
|
DbgStopInspect() |
|
if GetMap() == "" then |
|
return |
|
end |
|
local on_move, on_click |
|
if type(callbacks) == "table" then |
|
if callbacks.on_move then |
|
on_move = callbacks.on_move |
|
on_click = callbacks.on_click |
|
else |
|
on_move = callbacks[1] |
|
on_click = callbacks[2] |
|
end |
|
elseif type(callbacks) == "function" then |
|
on_move = callbacks |
|
end |
|
if type(on_move) ~= "function" and type(on_click) ~= "function" then |
|
return |
|
end |
|
if type(on_click) == "function" then |
|
terminal.AddTarget(DbgInspectTerminalTarget) |
|
end |
|
DbgInspectThread = CreateMapRealTimeThread(function(...) |
|
local last_pos, last_click |
|
local text_obj |
|
local marker_obj, click_seg, click_circle |
|
local IsPointInBounds = terrain.IsPointInBounds |
|
local DbgGetInspectPos = DbgGetInspectPos |
|
local IsValid = IsValid |
|
local thread = CurrentThread() |
|
while DbgInspectThread == thread do |
|
if on_move then |
|
local pos = DbgGetInspectPos() |
|
if last_pos ~= pos then |
|
last_pos = pos |
|
local text = IsPointInBounds(pos) and on_move(pos, ...) |
|
if text then |
|
if not IsValid(text_obj) then |
|
text_obj = Text:new{text_style = "ConsoleLog"} |
|
DbgInspectObjs = table.create_add(DbgInspectObjs, text_obj) |
|
end |
|
if not IsValid(marker_obj) then |
|
marker_obj = Segment:new() |
|
DbgInspectObjs = table.create_add(DbgInspectObjs, marker_obj) |
|
end |
|
text_obj:SetText(text) |
|
text_obj:SetPos(pos) |
|
marker_obj:Set(pos, pos:SetTerrainZ()) |
|
else |
|
DbgDoneInspectObject(text_obj) |
|
DbgDoneInspectObject(marker_obj) |
|
end |
|
end |
|
end |
|
if on_click then |
|
local pos = DbgInspectTerminalTarget.last_mouse_click |
|
if not pos or not IsPointInBounds(pos) then |
|
last_click = nil |
|
DbgDoneInspectObject(click_seg) |
|
DbgDoneInspectObject(click_circle) |
|
elseif pos ~= last_click then |
|
last_click = pos |
|
on_click(pos, ...) |
|
if not IsValid(click_seg) then |
|
click_seg = Segment:new() |
|
DbgInspectObjs = table.create_add(DbgInspectObjs, click_seg) |
|
click_circle = CreateCircleMesh(const.HeightTileSize/2, point30, white) |
|
DbgInspectObjs = table.create_add(DbgInspectObjs, click_circle) |
|
end |
|
pos = ValidateZ(pos) |
|
click_seg:SetPos(pos) |
|
click_seg:Set(pos, pos:AddZ(3*guim)) |
|
click_circle:SetPos(pos) |
|
end |
|
end |
|
WaitNextFrame() |
|
end |
|
end, ...) |
|
return DbgInspectThread |
|
end |
|
|
|
|
|
|
|
MapVar("DbgOverlayMode", false) |
|
MapVar("DbgOverlayFunc", false) |
|
PersistableGlobals.DbgOverlayMode = false |
|
PersistableGlobals.DbgOverlayFunc = false |
|
|
|
OverlayFuncs = { |
|
type = function() |
|
Presets.MapGen.Tools.ShowTerrainTypes:Run() |
|
return { |
|
RenderMapObjects = 0, |
|
RenderClutter = false, |
|
RenderBillboards = 0, |
|
} |
|
end, |
|
grass_density = function() |
|
Presets.MapGen.Tools.ShowGrassDensity:Run() |
|
end, |
|
} |
|
|
|
function OnMsg.DoneMap() |
|
DbgToggleOverlay(false) |
|
end |
|
|
|
function DbgToggleOverlay(mode, setter) |
|
hr.TerrainDebugDraw = 0 |
|
hr.TerrainDebug3DDraw = 0 |
|
if table.changed(hr, "DbgOverlay") then |
|
table.restore(hr, "DbgOverlay") |
|
end |
|
if mode and DbgOverlayMode ~= mode then |
|
DbgOverlayMode = mode |
|
DbgOverlayFunc = setter or false |
|
DbgUpdateOverlay(mode) |
|
else |
|
DbgOverlayMode = false |
|
end |
|
if mode then |
|
print("Overlay", mode, DbgOverlayMode == mode) |
|
end |
|
end |
|
|
|
function DbgUpdateOverlay(mode) |
|
mode = mode or DbgOverlayMode |
|
if not mode or DbgOverlayMode ~= mode then |
|
return |
|
end |
|
local func = DbgOverlayFunc or OverlayFuncs[mode] or empty_func |
|
local hr_change = func() |
|
if hr_change then |
|
table.change(hr, "DbgOverlay", hr_change) |
|
end |
|
end |
|
|
|
|
|
|