File size: 10,109 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 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
DefineClass.PropertyTabDef = {
__parents = { "PropertyObject" },
properties = {
{ id = "TabName", editor = "text", default = "" },
{ id = "Categories", editor = "set", default = {}, items = function(self)
local class_def = GetParentTableOfKind(self, "ClassDef")
local categories = {}
for _, classname in ipairs(class_def.DefParentClassList) do
local base = g_Classes[classname]
for _, prop_meta in ipairs(base and base:GetProperties()) do
categories[prop_meta.category or "Misc"] = true
end
end
for _, subitem in ipairs(class_def) do
if IsKindOf(subitem, "PropertyDef") then
categories[subitem.category or "Misc"] = true
end
end
return table.keys2(categories, "sorted")
end
}
},
GetEditorView = function(self)
return string.format("%s - %s", self.TabName, table.concat(table.keys2(self.Categories or empty_table), ", "))
end,
}
DefineClass.ClassDef = {
__parents = { "Preset" },
properties = {
{ id = "DefParentClassList", name = "Parent classes", editor = "string_list", items = function(obj, prop_meta, validate_fn)
if validate_fn == "validate_fn" then
-- function for preset validation, checks whether the property value is from "items"
return "validate_fn", function(value, obj, prop_meta)
return value == "" or g_Classes[value]
end
end
return table.keys2(g_Classes, true, "")
end
},
{ id = "DefPropertyTranslation", name = "Translate property names", editor = "bool", default = false, },
{ id = "DefStoreAsTable", name = "Store as table", editor = "choice", default = "inherit", items = { "inherit", "true", "false" } },
{ id = "DefPropertyTabs", name = "Property tabs", editor = "nested_list", base_class = "PropertyTabDef", inclusive = true, default = false, },
{ id = "DefUndefineClass", name = "Undefine class", editor = "bool", default = false, },
},
DefParentClassList = { "PropertyObject" },
ContainerClass = "ClassDefSubItem",
PresetClass = "ClassDef",
FilePerGroup = true,
HasCompanionFile = true,
GeneratesClass = true,
DefineKeyword = "DefineClass",
GedEditor = "ClassDefEditor",
EditorMenubarName = "Class definitions",
EditorIcon = "CommonAssets/UI/Icons/cpu.png",
EditorMenubar = "Editors.Engine",
EditorShortcut = "Ctrl-Alt-F3",
EditorViewPresetPrefix = "<color 75 105 198>[Class]</color> ",
}
function ClassDef:FindSubitem(name)
for _, subitem in ipairs(self) do
if subitem:HasMember("name") and subitem.name == name or subitem:IsKindOf("PropertyDef") and subitem.id == name then
return subitem
end
end
end
function ClassDef:GetDefaultPropertyValue(prop_id, prop_meta)
if prop_id:starts_with("Def") then
local class_prop_id = prop_id:sub(4)
-- try to find the default property value from the parent list
-- this is not correct if there are multiple parent classes that have different default values for the property
for i, class_name in ipairs(self.DefParentClassList) do
local class = g_Classes[class_name]
if class then
local default = class:GetDefaultPropertyValue(class_prop_id)
if default ~= nil then
return default
end
end
end
end
return Preset.GetDefaultPropertyValue(self, prop_id, prop_meta)
end
function ClassDef:PostLoad()
for key, prop_def in ipairs(self) do
prop_def.translate_in_ged = self.DefPropertyTranslation
end
Preset.PostLoad(self)
end
function ClassDef:OnPreSave()
-- convert texts to/from Ts if the 'translated' value changed
local translate = self.DefPropertyTranslation
for key, prop_def in ipairs(self) do
if IsKindOf(prop_def, "PropertyDef") then
local convert_text = function(value)
local prop_translated = not value or IsT(value)
if prop_translated and not translate then
return value and TDevModeGetEnglishText(value) or false
elseif not prop_translated and translate then
return value and value ~= "" and T(value) or false
end
return value
end
prop_def.name = convert_text(prop_def.name)
prop_def.help = convert_text(prop_def.help)
prop_def.translate_in_ged = translate
end
end
end
function ClassDef:GenerateCompanionFileCode(code)
if self.DefUndefineClass then
code:append("UndefineClass('", self.id, "')\n")
end
code:append(self.DefineKeyword, ".", self.id, " = {\n")
self:GenerateParents(code)
self:AppendGeneratedByProps(code)
self:GenerateProps(code)
self:GenerateConsts(code)
code:append("}\n\n")
self:GenerateMethods(code)
self:GenerateGlobalCode(code)
end
function ClassDef:GenerateParents(code)
local parents = self.DefParentClassList
if #(parents or "") > 0 then
code:append("\t__parents = { \"", table.concat(parents, "\", \""), "\", },\n")
end
end
function ClassDef:GenerateProps(code)
local extra_code_fn = self.GeneratePropExtraCode ~= ClassDef.GeneratePropExtraCode and
function(prop_def) return self:GeneratePropExtraCode(prop_def) end
self:GenerateSubItemsCode(code, "PropertyDef", "\tproperties = {\n", "\t},\n", self.DefPropertyTranslation, extra_code_fn )
end
function ClassDef:GeneratePropExtraCode(prop_def)
end
function ClassDef:AppendConst(code, prop_id, alternative_default, def_prop_id)
def_prop_id = def_prop_id or "Def" .. prop_id
local value = rawget(self, def_prop_id)
if value == nil then return end
local def_value = self:GetDefaultPropertyValue(def_prop_id)
if value ~= alternative_default and value ~= def_value then
code:append("\t", prop_id, " = ")
code:appendv(value)
code:append(",\n")
end
end
function ClassDef:GenerateConsts(code)
if self.DefStoreAsTable ~= "inherit" then
code:append("\tStoreAsTable = ", self.DefStoreAsTable, ",\n")
end
if self.DefPropertyTabs then
code:append("\tPropertyTabs = ")
code:appendv(self.DefPropertyTabs, "\t")
code:append(",\n")
end
self:GenerateSubItemsCode(code, "ClassConstDef")
end
function ClassDef:GenerateMethods(code)
self:GenerateSubItemsCode(code, "ClassMethodDef", "", "", self.id)
end
function ClassDef:GenerateGlobalCode(code)
self:GenerateSubItemsCode(code, "ClassGlobalCodeDef", "", "", self.id)
end
function ClassDef:GenerateSubItemsCode(code, subitem_class, prefix, suffix, ...)
local has_subitems
for i, prop in ipairs(self) do
if prop:IsKindOf(subitem_class) then
has_subitems = true
break
end
end
if has_subitems then
if prefix then code:append(prefix) end
for i, prop in ipairs(self) do
if prop:IsKindOf(subitem_class) then
prop:GenerateCode(code, ...)
end
end
if suffix then code:append(suffix) end
end
end
function ClassDef:GetCompanionFileSavePath(path)
if path:starts_with("Data") then
path = path:gsub("^Data", "Lua/ClassDefs") -- save in the game folder
elseif path:starts_with("CommonLua/Data") then
path = path:gsub("^CommonLua/Data", "CommonLua/Classes/ClassDefs") -- save in common lua
elseif path:starts_with("CommonLua/Libs/") then -- lib
path = path:gsub("/Data/", "/ClassDefs/")
else
path = path:gsub("^(svnProject/Dlc/[^/]*)/Presets", "%1/Code/ClassDefs") -- save in a DLC
end
return path:gsub(".lua$", ".generated.lua")
end
function ClassDef:GetError()
local names = {}
for _, element in ipairs(self or empty_table) do
local id = rawget(element, "id") or rawget(element, "id")
if id then
if names[id] then
return "Some class members have matching ids - '"..element.id.."'"
else
names[id] = true
end
end
end
end
function GetTextFilePreview(path, lines_count, filter_func)
if lines_count and lines_count > 0 then
local file, err = io.open(path, "r")
if not err then
local count = 1
local lines = {}
local line
while count <= lines_count do
line = file:read()
if line == nil then break end
for subline in line:gmatch("[^%\r?~%\n?]+") do
if count == lines_count + 1 or (filter_func and filter_func(subline)) then
break
end
lines[#lines + 1] = subline
count = count + 1
end
end
lines[#lines + 1] = ""
lines[#lines + 1] = "..."
file:close()
return table.concat(lines, "\n")
end
end
end
local function CleanUpHTMLTags(text)
text = text:gsub("<br>", "\n")
text = text:gsub("<br/>", "\n")
text = text:gsub("<script(.+)/script>", "")
text = text:gsub("<style(.+)/style>", "")
text = text:gsub("<!--(.+)-->", "")
text = text:gsub("<link(.+)/>", "")
return text
end
function GetDocumentation(obj)
if type(obj) == "table" and PropObjHasMember(obj, "Documentation") and obj.Documentation and obj.Documentation ~= "" then
return obj.Documentation
end
end
function GetDocumentationLink(obj)
if type(obj) == "table" and PropObjHasMember(obj, "DocumentationLink") and obj.DocumentationLink and obj.DocumentationLink ~= "" then
local link = obj.DocumentationLink
assert(link:starts_with("Docs/"))
if not link:starts_with("http") then
link = ConvertToOSPath(link)
end
link = string.gsub(link, "[\n\r]", "")
link = string.gsub(link, " ", "%%20")
return link
end
end
function GedOpenDocumentationLink(root, obj, prop_id, ged, btn_param, idx)
OpenUrl(GetDocumentationLink(obj), "force external browser")
end
----- AppendClassDef
DefineClass.AppendClassDef = {
__parents = { "ClassDef" },
properties = {
{ id = "DefUndefineClass", editor = false, },
},
GeneratesClass = false,
DefParentClassList = false,
DefineKeyword = "AppendClass",
}
----- ListPreset
DefineClass.ListPreset = {
__parents = { "Preset", },
HasGroups = false,
HasSortKey = true,
EditorMenubar = "Editors.Lists",
}
-- deprecated and left for compatibility reasons, to be removed
DefineClass.ListItem = {
__parents = { "Preset", },
properties = {
{ id = "Group", no_edit = false, },
},
HasSortKey = true,
PresetClass = "ListItem",
}
-----
if Platform.developer and not Platform.ged then
function RemoveUnversionedClassdefs()
local err, files = AsyncListFiles("svnProject/../", "*.lua", "recursive")
local removed = 0
for _, file in ipairs(files) do
if string.match(file, "ClassDef%-.*%.lua$") and not SVNLocalInfo(file) then
print("removing", file)
os.remove(file)
removed = removed + 1
end
end
print(removed, "files removed")
end
end |