|
local height_tile = const.HeightTileSize |
|
local table_find = table.find |
|
|
|
local function CheckProp(name, value) |
|
value = value or false |
|
return function(self) return self[name] == value end |
|
end |
|
local OVRLP_DEL_NONE, OVRLP_DEL_ALL, OVRLP_DEL_IGNORE, OVRLP_DEL_PARTIAL, OVRLP_DEL_SINGLE = false, 0, 1, 2, 3 |
|
local function OnObjOverlapItems() |
|
return { |
|
{ value = OVRLP_DEL_NONE, text = "Do nothing" }, |
|
{ value = OVRLP_DEL_ALL, text = "Delete the entire collection" }, |
|
{ value = OVRLP_DEL_IGNORE, text = "Delete ignoring collections" }, |
|
{ value = OVRLP_DEL_PARTIAL, text = "Delete if the collection is outside" }, |
|
{ value = OVRLP_DEL_SINGLE, text = "Delete if not in collection" }, |
|
} |
|
end |
|
|
|
function PrefabRadiusEstimItems() |
|
return { |
|
{ value = "incircle", text = "Incircle (Min)", color = red }, |
|
{ value = "excircle", text = "Excircle (Max)", color = green }, |
|
{ value = "amean", text = "Arithmetic Mean (Average)", color = yellow }, |
|
{ value = "gmean", text = "Geometric Mean (Ellipse)", color = blue }, |
|
{ value = "bestfit", text = "Best Fit (Circle)", color = cyan }, |
|
} |
|
end |
|
function PrefabRadiusEstimators() |
|
return { |
|
incircle = function(prefab) return prefab.min_radius end, |
|
excircle = function(prefab) return prefab.max_radius end, |
|
amean = function(prefab) return (prefab.min_radius + prefab.max_radius) / 2 end, |
|
gmean = function(prefab) return sqrt(prefab.min_radius * prefab.max_radius) end, |
|
bestfit = function(prefab) return sqrt(prefab.total_area * 7 / 22) end, |
|
} |
|
end |
|
|
|
DefineClass.PrefabType = { |
|
__parents = { "Preset", }, |
|
properties = { |
|
{ category = "General", id = "OnObjOverlap", name = "On Object Overlap", editor = "choice", default = OVRLP_DEL_ALL, items = OnObjOverlapItems }, |
|
{ category = "General", id = "RespectBounds", name = "Respect Type Bounds", editor = "bool", default = true, help = "Disable prefab objects spill beyond the their prefab type boundaries. Doesn't affect POI prefabs as they can share multiple prefab types." }, |
|
{ category = "General", id = "OverlapReduct", name = "Lim Excircle Overlap", editor = "number", default = 1, min = 0, max = 4, slider = true, help = "Prioritize prefabs with better incircle to excircle radius ratio (the best being 1, a perfect circle)" }, |
|
{ category = "General", id = "FitEffort", name = "Prefab Fit Effort", editor = "number", default = 1, min = 0, max = 4, slider = true, help = "Prioritize prefabs fitting better the available space (using the radius estimate)" }, |
|
{ category = "General", id = "RadiusEstim", name = "Radius Estimate", editor = "choice", default = "bestfit", items = PrefabRadiusEstimItems, help = "Used to estimate the prefab real form by a circle when fitting prefabs" }, |
|
{ category = "General", id = "PlaceRadius", name = "Min Prefab Radius", editor = "number", default = height_tile, scale = "m", help = "Ignore prefabs with radius estimate below that value" }, |
|
{ category = "General", id = "FitPasses", name = "Max Fit Passes", editor = "number", default = 5, min = 1, max = 5, slider = true, help = "Maximum number of prefab fitting passes" }, |
|
{ category = "General", id = "MinFillRatio", name = "Min Fill Ratio (%)", editor = "number", default = 100, min = 0, max = 100, slider = true, help = "How much of the prefab type surface would be filled at least (actual value can be bigger, but not lesser)" }, |
|
{ category = "General", id = "MaxFillError", name = "Max Fill Err (%)", editor = "number", default = 10, min = 0, max = 1000, scale = 10, slider = true, help = "How much of the prefab type surface specified to be filled could remain unfilled" }, |
|
{ category = "General", id = "Tags", name = "Tags", editor = "set", default = empty_table, items = PrefabTagsCombo }, |
|
|
|
{ category = "Terrain", id = "Transition", name = "Transition", editor = "number", default = 0, scale = "m", granularity = height_tile, help = "Transition zone for texture dithering" }, |
|
{ category = "Terrain", id = "TexturingOrder", name = "Texturing Order", editor = "number", default = 0, help = "Sort key used when applying prefab type terrain. Types with equal order are compared based on the descending transition dist." }, |
|
{ category = "Terrain", id = "TextureMain", name = "Main Texture", editor = "choice", default = "", items = GetTerrainNamesCombo(), }, |
|
{ category = "Terrain", id = "GrassMain", name = "Main Grass (%)", editor = "number", default = 100, min = 0, max = 200, slider = true, no_edit = CheckProp("TextureMain", "") }, |
|
{ category = "Terrain", id = "PreviewMain", name = "Main Preview", editor = "image", default = false, img_size = 128, img_box = 1, base_color_map = true, dont_save = true, no_edit = CheckProp("TextureMain", "") }, |
|
|
|
{ category = "Terrain", id = "TextureFlow", name = "Flow Texture", editor = "choice", default = "", items = GetTerrainNamesCombo(), }, |
|
{ category = "Terrain", id = "GrassFlow", name = "Flow Grass (%)", editor = "number", default = 100, min = 0, max = 200, slider = true, no_edit = CheckProp("TextureFlow", "") }, |
|
{ category = "Terrain", id = "FlowStrength", name = "Flow Strength", editor = "number", default = 100, min = 0, max = 200, scale = 100, slider = true }, |
|
{ category = "Terrain", id = "FlowContrast", name = "Flow Contrast", editor = "number", default = 100, min = 0, max = 300, scale = 100, slider = true }, |
|
{ category = "Terrain", id = "PreviewFlow", name = "Flow Preview", editor = "image", default = false, img_size = 128, img_box = 1, base_color_map = true, dont_save = true, no_edit = CheckProp("TextureFlow", "") }, |
|
|
|
{ category = "Terrain", id = "TextureNoise", name = "Noise Texture", editor = "choice", default = "", items = GetTerrainNamesCombo(), }, |
|
{ category = "Terrain", id = "GrassNoise", name = "Noise Grass (%)", editor = "number", default = 100, min = 0, max = 200, slider = true, no_edit = CheckProp("TextureNoise", "") }, |
|
{ category = "Terrain", id = "PreviewNoise", name = "Noise Preview", editor = "image", default = false, img_size = 128, img_box = 1, base_color_map = true, dont_save = true, no_edit = CheckProp("TextureNoise", "") }, |
|
{ category = "Terrain", id = "HeightModulated",name = "Height Modulated", editor = "bool", default = false, }, |
|
{ category = "Terrain", id = "NoiseStrength", name = "Noise Strength", editor = "number", default = 100, min = 0, max = 200, scale = 100, slider = true }, |
|
{ category = "Terrain", id = "NoiseContrast", name = "Noise Contrast", editor = "number", default = 100, min = 0, max = 300, scale = 100, slider = true }, |
|
{ category = "Terrain", id = "NoisePreset", name = "Noise Pattern", editor = "preset_id", default = "", preset_class = "NoisePreset" }, |
|
{ category = "Terrain", id = "NoisePreview", name = "Noise Preview", editor = "grid", default = false, no_edit = function(self) return self.NoisePreset == "" end, frame = 1, min = 64, dont_save = true, read_only = true }, |
|
|
|
{ category = "Editor", id = "OverlayColor", name = "Overlay Color", editor = "color", default = false, alpha = false }, |
|
{ category = "Editor", id = "FillPrefabList", name = "Fill Prefab List", editor = "string_list", default = false, read_only = true, dont_save = true }, |
|
{ category = "Editor", id = "POIPrefabList", name = "POI Prefab List", editor = "string_list", default = false, read_only = true, dont_save = true }, |
|
{ category = "Editor", id = "POIList", name = "POI List", editor = "string_list", default = false, read_only = true, dont_save = true }, |
|
}, |
|
EditorMenubarName = "Prefab Types", |
|
EditorMenubar = "Map.Generate", |
|
EditorIcon = "CommonAssets/UI/Icons/puzzle.png", |
|
EditorView = Untranslated("<Id> <style GedConsole>[<SortKey>]</style>"), |
|
|
|
StoreAsTable = false, |
|
GlobalMap = "PrefabTypeToPreset", |
|
HasSortKey = true, |
|
|
|
GetPreviewMain = function(self) return GetTerrainTexturePreview(self.TextureMain) end, |
|
GetPreviewFlow = function(self) return GetTerrainTexturePreview(self.TextureFlow) end, |
|
GetPreviewNoise = function(self) return GetTerrainTexturePreview(self.TextureNoise) end, |
|
GetNoisePreview = function(self) return GetNoisePreview(self.NoisePreset) end, |
|
} |
|
|
|
function PrefabType:Compare(other) |
|
local sa, sb = self.SortKey, other.SortKey |
|
if sa ~= sb then |
|
return sa < sb |
|
end |
|
local ba, bb = self.RespectBounds and 1 or 0, other.RespectBounds and 1 or 0 |
|
if ba ~= bb then |
|
return ba > bb |
|
end |
|
local ooa, oob = (self.OnObjOverlap or -1), (other.OnObjOverlap or -1) |
|
if ooa ~= oob then |
|
return ooa > oob |
|
end |
|
return self.id < other.id |
|
end |
|
|
|
function PrefabType:GetPOIPrefabList() |
|
local names = {} |
|
local prefabs = PrefabMarkers or empty_table |
|
local poi_to_preset = PrefabPoiToPreset or empty_table |
|
local ptype = self.id |
|
for _, prefab in ipairs(prefabs) do |
|
local poi_type = prefab and prefab.poi_type or "" |
|
if poi_type ~= "" then |
|
local preset = poi_to_preset[poi_type] |
|
for _, group in pairs(preset and preset.PrefabTypeGroups) do |
|
if table_find(group.types, ptype) then |
|
names[#names + 1] = prefabs[prefab] |
|
break |
|
end |
|
end |
|
end |
|
end |
|
if #names == 0 then return end |
|
table.sort(names) |
|
return names |
|
end |
|
|
|
function PrefabType:GetPOIList() |
|
local ptype = self.id |
|
local list = {} |
|
for name, preset in pairs(PrefabPoiToPreset) do |
|
for _, group in pairs(preset.PrefabTypeGroups) do |
|
if table_find(group.types, ptype) then |
|
list[#list + 1] = name |
|
break |
|
end |
|
end |
|
end |
|
table.sort(list) |
|
return list |
|
end |
|
|
|
function PrefabType:GetFullPrefabList() |
|
local names = {} |
|
local prefabs = PrefabMarkers or empty_table |
|
local ptype = self.id |
|
for _, prefab in ipairs(prefabs) do |
|
local poi_type = prefab and prefab.poi_type or "" |
|
if poi_type == "" and (prefab.type == "" or prefab.type == ptype) then |
|
names[#names + 1] = prefabs[prefab] |
|
end |
|
end |
|
if #names == 0 then return end |
|
table.sort(names) |
|
return names |
|
end |
|
|
|
function GetPrefabTypeList() |
|
return table.keys(PrefabTypeToPreset, true) |
|
end |
|
|
|
function GetPrefabTypeTags(add_empty) |
|
local tags = {} |
|
for ptype, preset in pairs(PrefabTypeToPreset) do |
|
for tag in pairs(preset and preset.Tags or empty_table) do |
|
if tag ~= "" then |
|
tags[tag] = true |
|
end |
|
end |
|
end |
|
tags = table.keys(tags, true) |
|
if add_empty then |
|
table.insert(tags, 1, add_empty) |
|
end |
|
return tags |
|
end |
|
|
|
function OnMsg.GedPropertyEdited(_, obj) |
|
if IsKindOf(obj, "NoisePreset") then |
|
ForEachPreset("PrefabType", function(ptype) |
|
if ptype.NoisePreset == obj.id then |
|
ObjModified(ptype) |
|
end |
|
end) |
|
end |
|
end |