|
|
|
const.ContoursOffset = -80 |
|
const.ContoursOffset_Merc = -85 |
|
const.ContoursOffset_BorderlineAttack = const.ContoursOffset -90 |
|
const.ContoursOffset_BorderlineTurn = const.ContoursOffset |
|
|
|
const.ContoursOffsetZ = 15*guic |
|
const.ContoursOffsetZ_Merc = const.ContoursOffsetZ +30 |
|
const.ContoursOffsetZ_BorderlineAttack = const.ContoursOffsetZ |
|
const.ContoursOffsetZ_BorderlineTurn = const.ContoursOffsetZ |
|
|
|
const.ContoursWidth = 480 / 5 |
|
const.ContoursWidth_Merc = const.ContoursWidth |
|
const.ContoursWidth_BorderlineAttack = const.ContoursWidth |
|
const.ContoursWidth_BorderlineTurn = const.ContoursWidth |
|
|
|
const.ContoursRadius2D = 180 |
|
const.ContoursRadius2D_Merc = 180 |
|
const.ContoursRadius2D_Merc_Exploration = 500 |
|
const.ContoursRadiusVertical = 80 |
|
const.ContoursRadiusSteps = 8 |
|
|
|
const.ContoursPassConnection = false |
|
const.ContoursTunnelMask = |
|
const.TunnelMaskWalk |
|
| const.TunnelMaskClimbDrop |
|
| const.TunnelTypeLadder |
|
| const.TunnelTypeJumpOver1 |
|
| const.TunnelTypeDoor |
|
| const.TunnelTypeWindow |
|
|
|
|
|
function GetRangeContour(voxels, contour_width, radius2D, offset, offsetz, voxel_pass_connection, tunnels_mask, exclude_voxels) |
|
if not voxels or #voxels == 0 then |
|
return |
|
end |
|
contour_width = contour_width or const.ContoursWidth |
|
radius2D = radius2D or const.ContoursRadius2D |
|
local radius_vertical = const.ContoursRadiusVertical |
|
offset = offset or const.ContoursOffset |
|
offsetz = offsetz or const.ContoursOffsetZ |
|
voxel_pass_connection = voxel_pass_connection or const.ContoursPassConnection |
|
tunnels_mask = tunnels_mask or const.ContoursTunnelMask |
|
local contours = GetContoursPStr(voxels, voxel_pass_connection, tunnels_mask, contour_width, radius2D, radius_vertical, offset, offsetz) |
|
return contours |
|
end |
|
|
|
|
|
local function RGBToModifier(r, g, b) |
|
local r = MulDivRound(r, 100, 255) |
|
local g = MulDivRound(g, 100, 255) |
|
local b = MulDivRound(b, 100, 255) |
|
return RGB(r, g, b) |
|
end |
|
function PlaceContourPolyline(contour, color, shader) |
|
local meshes = { |
|
SetVisible = function(self, value) |
|
for _, m in ipairs(self) do |
|
m:SetVisible(value) |
|
end |
|
end |
|
} |
|
shader = shader or "range_contour" |
|
if type(color) == "string" then |
|
color = Mesh.ColorFromTextStyle(color) |
|
else |
|
local r, g, b, opacity = GetRGBA(color) |
|
color = RGBToModifier(r, g, b) |
|
end |
|
for _, v_pstr in ipairs(contour) do |
|
local mesh = PlaceObject("Mesh") |
|
mesh:SetColorModifier(color) |
|
mesh:SetMesh(v_pstr) |
|
if not ProceduralMeshShaders[shader] then |
|
mesh:SetCRMaterial(shader) |
|
else |
|
mesh:SetShader(ProceduralMeshShaders[shader]) |
|
end |
|
mesh:SetPos(0, 0, 0) |
|
table.insert(meshes, mesh) |
|
end |
|
return meshes |
|
end |
|
|
|
function PlaceSingleTileStaticContourMesh(color_textstyle_id, pos, exploration) |
|
local r = const.SlabSizeX / 2 + const.ContoursOffset_Merc |
|
local z = const.ContoursOffsetZ_Merc |
|
local contour = GetRectContourPStr(box(-r, -r, z, r, r, z), const.ContoursWidth_Merc, exploration and const.ContoursRadius2D_Merc_Exploration or const.ContoursRadius2D_Merc) |
|
local polyline = PlaceContourPolyline({contour}, color_textstyle_id) |
|
if pos then |
|
polyline[1]:SetPos(pos) |
|
end |
|
return polyline[1] |
|
end |
|
|
|
function DestroyMesh(mesh) |
|
if IsValid(mesh) then |
|
mesh:delete() |
|
end |
|
end |
|
|
|
function DestroyContourPolyline(meshes) |
|
if not meshes then return end |
|
for _, mesh in ipairs(meshes) do |
|
DestroyMesh(mesh) |
|
end |
|
table.iclear(meshes) |
|
end |
|
|
|
function ContourPolylineSetVisible(meshes, visible) |
|
for _, mesh in ipairs(meshes) do |
|
if IsValid(mesh) then |
|
if visible then |
|
mesh:SetEnumFlags(const.efVisible) |
|
else |
|
mesh:ClearEnumFlags(const.efVisible) |
|
end |
|
end |
|
end |
|
end |
|
|
|
function ContourPolylineSetColor(meshes, color_textstyle_id) |
|
for _, mesh in ipairs(meshes) do |
|
mesh:SetColorFromTextStyle(color_textstyle_id) |
|
end |
|
end |
|
|
|
function ContourPolylineSetShader(meshes, shader) |
|
shader = ProceduralMeshShaders[shader] |
|
for _, mesh in ipairs(meshes) do |
|
if mesh.shader ~= shader then |
|
mesh:SetShader(shader) |
|
end |
|
end |
|
end |
|
|
|
function PlaceGroundRectMesh(v_pstr, color_textstyle_id, shader) |
|
shader = shader or "ground_strokes" |
|
local mesh = PlaceObject("Mesh") |
|
if color_textstyle_id then |
|
mesh:SetColorFromTextStyle(color_textstyle_id) |
|
end |
|
mesh:SetMesh(v_pstr) |
|
mesh:SetPos(0, 0, 0) |
|
if IsKindOf(shader, "CRMaterial") then |
|
mesh:SetCRMaterial(shader) |
|
else |
|
mesh:SetShader(ProceduralMeshShaders[shader]) |
|
end |
|
mesh:SetDepthTest(true) |
|
return mesh |
|
end |
|
|
|
local reload_prop_ids = {TextColor = true, ShadowColor = true, ShadowSize = true, } |
|
function TextStyle:OnEditorSetProperty(prop_id, old_value, ged) |
|
if self.group == "Zulu Ingame" and reload_prop_ids[prop_id] then |
|
DelayedCall(300, MapForEach, "map", "Mesh", function(mesh) |
|
if mesh.textstyle_id == self.id then |
|
mesh:SetColorFromTextStyle(self.id) |
|
end |
|
end) |
|
end |
|
end |
|
|
|
DefineClass.CRM_RangeContourPreset = { |
|
__parents = { "CRMaterial" }, |
|
group = "RangeContourPreset", |
|
properties = { |
|
{ uniform = true, id = "depth_softness", editor = "number", default = 0, scale = 1000, min = -2000, max = 2000, slider = true, }, |
|
{ uniform = true, id = "fill_color", editor = "color", default = RGB(0, 255, 0) }, |
|
{ uniform = true, id = "border_color", editor = "color", default = RGB(255, 255, 255) }, |
|
{ uniform = true, id = "dash_color", editor = "color", default = RGB(255, 255, 255) }, |
|
|
|
{ uniform = true, id = "fill_width", editor = "number", default = 200, scale = 1000, min = 0, max = 1000, slider = true, }, |
|
{ uniform = true, id = "border_width", editor = "number", default = 200, scale = 1000, min = 0, max = 1000, slider = true, }, |
|
{ uniform = true, id = "border_softness", editor = "number", default = 200, scale = 1000, min = 0, max = 1000, slider = true, }, |
|
|
|
{ uniform = true, id = "dash_density", editor = "number", scale = 1000, default = 1000, slider = true, min = 0, max = 1000}, |
|
{ uniform = true, id = "dash_segment", editor = "number", scale = 1000, default = 1000, slider = true, min = 0, max = 100000}, |
|
|
|
{ uniform = true, id = "anim_speed", editor = "number", scale = 1000, default = 1000, slider = true, min = 0, max = 10000}, |
|
{ uniform = true, id = "grain_strength", editor = "number", scale = 1000, default = 200, slider = true, min = 0, max = 1000}, |
|
{ uniform = true, id = "interlacing_strength", editor = "number", scale = 1000, default = 200, slider = true, min = 0, max = 1000}, |
|
}, |
|
|
|
shader_id = "range_contour_default", |
|
} |
|
|
|
DefineClass.CRM_RangeContourControllerPreset = { |
|
__parents = { "CRMaterial" }, |
|
group = "RangeContourControllerPreset", |
|
|
|
shader_id = "combat_border", |
|
properties = { |
|
{ id = "contour_base_inside", editor = "preset_id", preset_class = "CRM_RangeContourPreset", default = false, }, |
|
{ id = "contour_base_outside", editor = "preset_id", preset_class = "CRM_RangeContourPreset", default = false, }, |
|
{ id = "contour_fx_inside", editor = "preset_id", preset_class = "CRM_RangeContourPreset", default = false, }, |
|
{ id = "contour_fx_outside", editor = "preset_id", preset_class = "CRM_RangeContourPreset", default = false, }, |
|
|
|
{ uniform = "integer", id = "fade_inout_start", editor = "number", scale = 1, default = 0, no_edit = true, dont_save = true, }, |
|
{ uniform = true, id = "fade_in", editor = "number", scale = 1000, default = 200, min = 0, max = 2000, slider = true, }, |
|
{ uniform = true, id = "cursor_alpha_distance", editor = "number", scale = 1000, default = 1000, min = 0, max = 3000, slider = true, }, |
|
{ uniform = true, id = "cursor_alpha_falloff", editor = "number", scale = 1000, default = 1000, min = 0, max = 25000, slider = true, }, |
|
|
|
{ uniform = "integer", id = "pop_in_start", editor = "number", scale = 1, default = 0, no_edit = true, dont_save = true, }, |
|
{ id = "pop_delay", editor = "number", scale = 1, default = 0, }, |
|
{ uniform = true, id = "pop_in_time", editor = "number", scale = 1000, default = 500, slider = true, min = 0, max = 1200, }, |
|
{ uniform = true, id = "pop_in_freq", editor = "number", scale = 1000, default = 200, slider = true, min = 0, max = 1200, }, |
|
|
|
{ id = "is_inside", editor = "bool", default = false, no_edit = true, dont_save = true, }, |
|
|
|
{ uniform = true, id = "ZOffset", editor = "number", default = false, scale = 1000, no_edit = true, default = 0, } |
|
}, |
|
} |
|
|
|
function CRM_RangeContourControllerPreset:Recreate() |
|
self.dirty = false |
|
|
|
local pstr_buffer = self.pstr_buffer |
|
|
|
local preset = CRM_RangeContourPreset:GetById(self.is_inside and self.contour_base_inside or self.contour_base_outside) |
|
pstr_buffer = preset:WriteBuffer(pstr_buffer) |
|
|
|
local preset2 = CRM_RangeContourPreset:GetById(self.is_inside and self.contour_fx_inside or self.contour_fx_outside) |
|
pstr_buffer = preset2:WriteBuffer(pstr_buffer, 4 * 12) |
|
|
|
self:WriteBuffer(pstr_buffer, 4 * 12 * 2 ) |
|
self.pstr_buffer = pstr_buffer |
|
end |
|
|
|
function CRM_RangeContourControllerPreset:SetIsInside(value, notimereset) |
|
value = value and true or false |
|
if self.is_inside ~= value then |
|
self.is_inside = value |
|
if not notimereset then |
|
self.fade_inout_start = RealTime() |
|
end |
|
self.dirty = true |
|
end |
|
end |
|
|
|
|
|
DefineClass.RangeContourMesh = { |
|
__parents = {"Mesh"}, |
|
|
|
preset_id = false, |
|
|
|
polyline = false, |
|
exclude_polyline = false, |
|
use_exclude_polyline = true, |
|
|
|
meshes = false, |
|
dirty_geometry = false, |
|
} |
|
|
|
function RangeContourMesh:SetPolyline(polyline, exclude_polyline) |
|
self.polyline = polyline |
|
self.exclude_polyline = exclude_polyline |
|
end |
|
|
|
function RangeContourMesh:SetPreset(preset) |
|
if type(preset) == "string" then |
|
preset = CRM_RangeContourControllerPreset:GetById(preset) |
|
end |
|
if self.CRMaterial and preset.id == self.CRMaterial.id then |
|
return |
|
end |
|
self:SetCRMaterial(preset:Clone()) |
|
end |
|
|
|
function RangeContourMesh:SetVisible(value) |
|
if not g_PhotoMode then |
|
for _, mesh in ipairs(self.meshes or empty_table) do |
|
mesh:SetVisible(value) |
|
end |
|
if self.visible ~= value then |
|
self.CRMaterial.pop_in_start = RealTime() + self.CRMaterial.pop_delay |
|
self.visible = value |
|
self.CRMaterial.dirty = true |
|
end |
|
end |
|
end |
|
|
|
function RangeContourMesh:SetIsInside(value) |
|
self.CRMaterial:SetIsInside(value) |
|
end |
|
|
|
function RangeContourMesh:SetUseExcludePolyline(value) |
|
if self.use_exclude_polyline ~= value then |
|
self.use_exclude_polyline = value |
|
self.dirty_geometry = true |
|
end |
|
end |
|
|
|
function RangeContourMesh:Recreate(force_geometry) |
|
if #(self.meshes or empty_table) == 0 then |
|
force_geometry = true |
|
end |
|
if force_geometry or self.dirty_geometry then |
|
self.dirty_geometry = false |
|
for _, mesh in ipairs(self.meshes) do |
|
mesh:delete() |
|
end |
|
|
|
self.meshes = PlaceContourPolyline(self.polyline, RGB(255, 255, 255), self.CRMaterial, self.use_exclude_polyline and self.exclude_polyline) |
|
else |
|
for _, mesh in ipairs(self.meshes) do |
|
mesh:SetCRMaterial(self.CRMaterial) |
|
end |
|
end |
|
end |
|
|
|
function RangeContourMesh:delete() |
|
for _, mesh in ipairs(self.meshes or empty_table) do |
|
mesh:delete() |
|
end |
|
self.meshes = false |
|
Mesh.delete(self) |
|
end |
|
|
|
function CRM_RangeContourPreset:Apply() |
|
CRMaterial.Apply(self) |
|
self.cached_uniform_buf = self:GetDataPstr() |
|
if CurrentMap ~= "" then |
|
MapGet("map", "RangeContourMesh", function(o) |
|
if o.preset_id == self.id then |
|
o:Recreate() |
|
end |
|
end) |
|
end |
|
end |
|
|
|
RegisterSceneParam({ |
|
id = "CursorPos", type = "float", elements = 3, default = { 0, 0, 0 }, scale = 1000, prop_id = false, |
|
}) |
|
local cursor_pos_table = {0,0,0} |
|
MapRealTimeRepeat("RangeContourSceneParam", 33, function() |
|
local pos = GetCursorPos() |
|
if pos then |
|
cursor_pos_table[1], cursor_pos_table[2], cursor_pos_table[3] = pos:xyz() |
|
local interp_time = next(PauseReasons) and 0 or 33 |
|
SetSceneParamEx(1, "CursorPos", cursor_pos_table, interp_time) |
|
end |
|
end) |
|
|