Download CommonLua/Classes/ClassDefSubItem.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 61.7 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/Classes/ClassDefSubItem.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/CommonLua/Classes/ClassDefSubItem.lua
-
curl -L -o ClassDefSubItem.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/CommonLua/Classes/ClassDefSubItem.lua
61.7 kB
| DefineClass.ClassDefSubItem = { | |
| __parents = { "PropertyObject" }, | |
| } | |
| function ClassDefSubItem:ToStringWithColor(value, t) | |
| local text = t and value or ValueToLuaCode(value) | |
| t = t or type(value) | |
| local color | |
| if t == "string" or IsT(value) then | |
| color = RGB(60, 140, 40) | |
| elseif t == "boolean" or t == "nil" then | |
| color = RGB(75, 105, 198) | |
| elseif t == "number" then | |
| color = RGB(150, 50, 20) | |
| elseif t == "function" then | |
| text = string.gsub(text, "^function ", "<color 75 105 198>function</color><color 92 92 92>") | |
| text = string.gsub(text, "end$", "<color 75 105 198>end</color>") | |
| end | |
| if not color then | |
| return text | |
| end | |
| local r, g, b = GetRGB(color) | |
| return string.format("<color %s %s %s><tags off>%s<tags on></color>", r, g, b, text) | |
| end | |
| ----- PropertyDef | |
| local function GetCategoryItems(self) | |
| local categories = PresetGroupCombo("PropertyCategory", "Default")() | |
| local parent | |
| ForEachPreset("ClassDef", function(preset) | |
| parent = parent or table.find(preset, self) and preset | |
| end) | |
| if parent then | |
| local tmp = table.invert(categories) | |
| for _, prop in ipairs(parent) do | |
| if IsKindOf(prop, "PropertyDef") then | |
| tmp[prop.category or ""] = true | |
| end | |
| end | |
| categories = table.keys(tmp) | |
| end | |
| table.sort(categories, function(a, b) | |
| if a and b then | |
| return a < b | |
| else | |
| return b | |
| end | |
| end) | |
| return categories | |
| end | |
| local reusable_expressions = { | |
| dont_save = "Don't save", | |
| read_only = "Read only", | |
| no_edit = "Hidden", | |
| no_validate = "No validation", | |
| } | |
| local function reusable_expressions_combo(self) | |
| local ret = { | |
| { text = "true", value = true }, | |
| { text = "false", value = false }, | |
| { text = "expression", value = "expression"}, | |
| } | |
| local preset = GetParentTableOfKind(self, "ClassDef") | |
| for _, property_def in ipairs(preset) do | |
| if IsKindOf(property_def, "PropertyDef") then | |
| for id, name in pairs(reusable_expressions) do | |
| if property_def[id] == "expression" then | |
| table.insert(ret, { | |
| text = "Reuse " .. name .. " from " .. property_def.id, | |
| value = property_def.id .. "." .. id | |
| }) | |
| end | |
| end | |
| end | |
| end | |
| return ret | |
| end | |
| function ValidateIdentifier(self, value) | |
| return (type(value) ~= "string" or not value:match("^[%a_][%w_]*$")) and "Please enter a valid identifier" | |
| end | |
| DefineClass.PropertyDef = { | |
| __parents = { "ClassDefSubItem" }, | |
| properties = { | |
| { category = "Property", id = "category", name = "Category", editor = "combo", items = GetCategoryItems, default = false, }, | |
| { category = "Property", id = "id", name = "Id", editor = "text", default = "", validate = ValidateIdentifier }, | |
| { category = "Property", id = "name", name = "Name", editor = "text", translate = function(self) return self.translate_in_ged end, default = false }, | |
| { category = "Property", id = "help", name = "Help", editor = "text", translate = function(self) return self.translate_in_ged end, lines = 1, max_lines = 3, default = false }, | |
| { category = "Property", id = "dont_save", name = "Don't save", editor = "choice", default = false, items = reusable_expressions_combo }, | |
| { category = "Property", id = "dont_save_expression", name = "Don't save", editor = "expression", default = return_true, params = "self, prop_meta", | |
| no_edit = function(self) return type(self.dont_save) == "boolean" end, | |
| read_only = function(self) return self.dont_save ~= "expression" end, | |
| dont_save = function(self) return self.dont_save ~= "expression" end, }, | |
| { category = "Property", id = "read_only", name = "Read only", editor = "choice", default = false, items = reusable_expressions_combo }, | |
| { category = "Property", id = "read_only_expression", name = "Read only", editor = "expression", default = return_true, params = "self, prop_meta", | |
| no_edit = function(self) return type(self.read_only) == "boolean" end, | |
| read_only = function(self) return self.read_only ~= "expression" end, | |
| dont_save = function(self) return self.read_only ~= "expression" end, }, | |
| { category = "Property", id = "no_edit", name = "Hidden", editor = "choice", default = false, items = reusable_expressions_combo }, | |
| { category = "Property", id = "no_edit_expression", name = "Hidden", editor = "expression", default = return_true, params = "self, prop_meta", | |
| no_edit = function(self) return type(self.no_edit) == "boolean" end, | |
| read_only = function(self) return self.no_edit ~= "expression" end, | |
| dont_save = function(self) return self.no_edit ~= "expression" end, }, | |
| { category = "Property", id = "no_validate", name = "No validation", editor = "choice", default = false, items = reusable_expressions_combo }, | |
| { category = "Property", id = "no_validate_expression", name = "No validation", editor = "expression", default = return_true, params = "self, prop_meta", | |
| no_edit = function(self) return type(self.no_validate) == "boolean" end, | |
| read_only = function(self) return self.no_validate ~= "expression" end, | |
| dont_save = function(self) return self.no_validate ~= "expression" end, }, | |
| { category = "Property", id = "buttons", name = "Buttons", editor = "nested_list", base_class = "PropertyDefPropButton", default = false, inclusive = true, | |
| help = "Button function is searched by name in the object, the root parent (Preset?), and then globally.\n\nParameters are (self, root, prop_id, ged) for the object method, (root, obj, prop_id, ged) otherwise." }, | |
| { category = "Property", id = "template", name = "Template", editor = "bool", default = false, help = "Marks template properties for classes which inherit 'ClassTemplate'"}, | |
| { category = "Property", id = "validate", name = "Validate", editor = "expression", params = "self, value", help = "A function called by Ged when changing the value. Returns error, updated_value."}, | |
| { category = "Property", id = "extra_code", name = "Extra Code", editor = "text", lines = 1, max_lines = 5, default = false, help = "Additional code to insert in the property metadata" }, | |
| }, | |
| editor = false, | |
| validate = false, | |
| context = false, | |
| gender = false, | |
| os_path = false, | |
| translate_in_ged = false, | |
| } | |
| function PropertyDef:GetEditorView() | |
| local category = "" | |
| if self.category then | |
| category = string.format("<color 45 138 138>[%s]</color> ", self.category) | |
| end | |
| return string.format("%s<color 75 105 198>%s</color> %s <color 158 158 158>=</color> <color 150 90 40>%s", | |
| category, self.editor, self.id, self:ToStringWithColor(self.default)) | |
| end | |
| local function getTranslatableValue(text, translate) | |
| if not text or text == "" then return end | |
| if text then | |
| assert(IsT(text) == translate) | |
| end | |
| return text | |
| end | |
| local reuse_error_fn = function() return "Unable to locate expression to reuse." end | |
| local reuse_prop_ids = { dont_save_expression = "dont_save", read_only_expression = "read_only", no_edit_expression = "no_edit", no_validate_expression = "no_validate" } | |
| function PropertyDef:GetProperty(prop) | |
| local main_prop_id = reuse_prop_ids[prop] | |
| if main_prop_id then | |
| local value = self:GetProperty(main_prop_id) | |
| if type(value) == "string" and value ~= "expression" then | |
| local reuse_prop_id, reuse = value:match("([%w_]+)%.([%w_]+)") | |
| if reuse then | |
| local preset = GetParentTableOfKind(self, "ClassDef") | |
| local property_def = table.find_value(preset, "id", reuse_prop_id) | |
| return property_def and property_def[reuse .. "_expression"] or reuse_error_fn | |
| end | |
| end | |
| end | |
| return ClassDefSubItem.GetProperty(self, prop) | |
| end | |
| function PropertyDef:GenerateExpressionSettingCode(code, id) | |
| local value = self[id] | |
| if type(value) ~= "boolean" then | |
| local expr = self:GetProperty(id .. "_expression") | |
| if expr ~= reuse_error_fn then | |
| code:appendf("%s = function(self) %s end, ", id, GetFuncBody(expr)) | |
| end | |
| elseif value then | |
| code:appendf("%s = true, ", id) | |
| end | |
| end | |
| function PropertyDef:GenerateCode(code, translate, extra_code_fn) | |
| if self.id == "" then return end | |
| code:append("\t\t{ ") | |
| if self.category and self.category ~= "" then | |
| code:appendf("category = \"%s\", ", self.category) | |
| end | |
| code:append("id = \"", self.id, "\", ") | |
| local name, help = getTranslatableValue(self.name, translate), getTranslatableValue(self.help, translate) | |
| if name then | |
| code:append("name = ", ValueToLuaCode(name), ", ") | |
| end | |
| if help then | |
| code:append("help = ", ValueToLuaCode(help), ", ") | |
| end | |
| code:append("\n\t\t\t") | |
| code:appendf("editor = \"%s\", default = %s, ", self.editor, self:GenerateDefaultValueCode()) | |
| self:GenerateExpressionSettingCode(code, "dont_save") | |
| self:GenerateExpressionSettingCode(code, "read_only") | |
| self:GenerateExpressionSettingCode(code, "no_edit") | |
| self:GenerateExpressionSettingCode(code, "no_validate") | |
| if self.validate then | |
| code:appendf("validate = function(self, value) %s end, ", GetFuncBody(self.validate)) | |
| end | |
| if self.buttons and #self.buttons > 0 then | |
| code:append("buttons = {") | |
| for _, data in ipairs(self.buttons) do | |
| if data.Name ~= "" then | |
| if data.IsHidden ~= empty_func then | |
| code:appendf([[ {name = "%s", func = "%s", is_hidden = function(self) %s end }, ]], data.Name, data.FuncName, GetFuncBody(data.IsHidden)) | |
| else | |
| code:appendf([[ {name = "%s", func = "%s"}, ]], data.Name, data.FuncName) | |
| end | |
| end | |
| end | |
| code:append("}, ") | |
| end | |
| if self.template then code:append("template = true, ") end | |
| if self.extra_code and self.extra_code ~= "" or extra_code_fn then | |
| local ext_code = self.extra_code and self.extra_code:gsub(",$", "") | |
| if extra_code_fn then | |
| ext_code = ext_code and (ext_code .. ", " .. extra_code_fn(self)) or extra_code_fn(self) | |
| ext_code = ext_code:gsub(",$", "") | |
| end | |
| if ext_code and ext_code ~= "" then | |
| code:append("\n\t\t\t", ext_code) | |
| code:append(", ") | |
| end | |
| end | |
| self:GenerateAdditionalPropCode(code, translate) | |
| code:append("},\n") | |
| end | |
| function PropertyDef:GenerateDefaultValueCode() | |
| return ValueToLuaCode(self.default, ' ', nil, {} --[[ enable property injection ]]) | |
| end | |
| function PropertyDef:ValidateProperty(prop_meta) | |
| if not self.no_validate then | |
| return PropertyObject.ValidateProperty(self, prop_meta) | |
| end | |
| end | |
| function PropertyDef:GenerateAdditionalPropCode(code, translate) | |
| end | |
| function PropertyDef:AppendFunctionCode(code, prop_name) | |
| if not self[prop_name] then return end | |
| local name, params, body = GetFuncSource(self[prop_name]) | |
| code:appendf("%s = function (%s)\n", prop_name, params) | |
| if type(body) == "string" then | |
| body = string.split(body, "\n") | |
| end | |
| code:append("\t", body and table.concat(body, "\n\t") or "", "\n") | |
| code:append("end, \n") | |
| end | |
| function PropertyDef:GetError() | |
| if not self.no_validate and self.extra_code and (self.extra_code:find("[^%w_]items%s*=") or self.extra_code:find("^items%s*=")) then | |
| return "Please don't define 'items' as extra code. Use the dedicated Items property instead.\nThis is to make items appear in the default value property." | |
| end | |
| end | |
| function PropertyDef:CleanupForSave() | |
| end | |
| function PropertyDef:EmulatePropEval(metadata_id, default, prop_meta, validate_fn) | |
| local prop_meta = self | |
| local classdef_preset = GetParentTableOfKind(self, "ClassDef") | |
| if not classdef_preset then return default end | |
| local obj_class = g_Classes[classdef_preset.id] | |
| local instance = obj_class and not obj_class:IsKindOf("CObject") and obj_class:new() or {} | |
| if validate_fn then | |
| return eval_items(prop_meta[metadata_id], instance, prop_meta) | |
| end | |
| return prop_eval(prop_meta[metadata_id], instance, prop_meta, default) | |
| end | |
| local function EmulatePropEval(metadata_id, default) | |
| return function(self, prop_meta, validate_fn) | |
| return self:EmulatePropEval(metadata_id, default, prop_meta, validate_fn) | |
| end | |
| end | |
| DefineClass.PropertyDefPropButton = { | |
| __parents = { "PropertyObject" }, | |
| properties = { | |
| { id = "Name", editor = "text", default = ""}, | |
| { id = "FuncName", editor = "text", default = ""}, | |
| { id = "IsHidden", editor = "expression", default = empty_func}, | |
| }, | |
| EditorView = Untranslated("[<Name>] = <FuncName>"), | |
| } | |
| DefineClass.PropertyDefButtons = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { id = "default", name = "Default value", editor = false, default = false, }, | |
| }, | |
| editor = "buttons", | |
| EditorName = "Buttons property", | |
| EditorSubmenu = "Extras", | |
| } | |
| DefineClass.PropertyDefBool = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Bool", id = "default", name = "Default value", editor = "bool", default = false, }, | |
| }, | |
| editor = "bool", | |
| EditorName = "Bool property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| DefineClass.PropertyDefTable = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Table", id = "default", name = "Default value", editor = "prop_table", default = false, }, | |
| { category = "Table", id = "lines", name = "Lines", editor = "number", default = 1, }, | |
| }, | |
| editor = "prop_table", | |
| EditorName = "Table property", | |
| EditorSubmenu = "Objects", | |
| } | |
| function PropertyDefTable:GenerateAdditionalPropCode(code, translate) | |
| if self.lines > 1 then | |
| code:append("indent = \"\", lines = 1, max_lines = ", self.lines, ", ") | |
| end | |
| end | |
| DefineClass.PropertyDefPoint = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Point", id = "default", name = "Default value", editor = "point", default = false, }, | |
| }, | |
| editor = "point", | |
| EditorName = "Point property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| DefineClass.PropertyDefPoint2D = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Point2D", id = "default", name = "Default value", editor = "point2d", default = false, }, | |
| }, | |
| editor = "point2d", | |
| EditorName = "Point2D property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| DefineClass.PropertyDefRect = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Rect", id = "default", name = "Default value", editor = "rect", default = false, }, | |
| }, | |
| editor = "rect", | |
| EditorName = "Rect property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| DefineClass.PropertyDefMargins = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Margins", id = "default", name = "Default value", editor = "margins", default = false, }, | |
| }, | |
| editor = "margins", | |
| EditorName = "Margins property", | |
| EditorSubmenu = "Extras", | |
| } | |
| DefineClass.PropertyDefPadding = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Padding", id = "default", name = "Default value", editor = "padding", default = false, }, | |
| }, | |
| editor = "padding", | |
| EditorName = "Padding property", | |
| EditorSubmenu = "Extras", | |
| } | |
| DefineClass.PropertyDefBox = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Box", id = "default", name = "Default value", editor = "box", default = false, }, | |
| }, | |
| editor = "box", | |
| EditorName = "Box property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| DefineClass.PropertyDefNumber = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Number", id = "default", name = "Default value", editor = "number", default = false, scale = function(obj) return obj.scale end, min = function(obj) return obj.min end, max = function(obj) return obj.max end, }, | |
| { category = "Number", id = "scale", name = "Scale", editor = "choice", default = 1, items = function() return table.keys2(const.Scale, true, 1, 10, 100, 1000, 1000000) end, }, | |
| { category = "Number", id = "step", name = "Step", editor = "number", default = 1, scale = function(obj) return obj.scale end, }, | |
| { category = "Number", id = "float", name = "Float", editor = "bool", default = false, }, | |
| { category = "Number", id = "slider", name = "Slider", editor = "bool", default = false, }, | |
| { category = "Number", id = "min", name = "Min", editor = "number", default = min_int64, scale = function(obj) return obj.scale end, no_edit = PropChecker("custom_lims", true)}, | |
| { category = "Number", id = "max", name = "Max", editor = "number", default = max_int64, scale = function(obj) return obj.scale end, no_edit = PropChecker("custom_lims", true) }, | |
| { category = "Number", id = "custom_min", name = "Min", editor = "expression", default = false, no_edit = PropChecker("custom_lims", false) }, | |
| { category = "Number", id = "custom_max", name = "Max", editor = "expression", default = false, no_edit = PropChecker("custom_lims", false) }, | |
| { category = "Number", id = "custom_lims", name = "Custom Lims", editor = "bool", default = false, help = "Use custom limits"}, | |
| { category = "Number", id = "modifiable", name = "Modifiable", editor = "bool", default = false, help = "Marks modifiable properties for classes which inherit 'Modifiable' class"}, | |
| }, | |
| editor = "number", | |
| EditorName = "Number property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| function PropertyDefNumber:GenerateAdditionalPropCode(code, translate) | |
| local scale = self.scale | |
| if scale ~= 1 then | |
| code:appendf(type(scale) == "number" and "scale = %d, " or "scale = \"%s\", ", scale) | |
| end | |
| if self.step ~= 1 then code:appendf("step = %d, ", self.step) end | |
| if self.slider then code:append("slider = true, ") end | |
| if self.custom_lims then | |
| if self.custom_min ~= PropertyDefNumber.custom_min then | |
| local name, params, body = GetFuncSource(self.custom_min) | |
| body = type(body) == "table" and table.concat(body, "\n") or body | |
| code:appendf("min = function(self) %s end, ", body) | |
| end | |
| if self.custom_max ~= PropertyDefNumber.custom_max then | |
| local name, params, body = GetFuncSource(self.custom_max) | |
| body = type(body) == "table" and table.concat(body, "\n") or body | |
| code:appendf("max = function(self) %s end, ", body) | |
| end | |
| else | |
| if self.min ~= PropertyDefNumber.min then code:appendf("min = %d, ", self.min) end | |
| if self.max ~= PropertyDefNumber.max then code:appendf("max = %d, ", self.max) end | |
| end | |
| if self.modifiable then code:append("modifiable = true, ") end | |
| end | |
| function PropertyDefNumber:OnEditorSetProperty(prop_id, old_value, ged) | |
| if prop_id == "slider" and self.slider then | |
| if self.min == PropertyDefNumber.min then self.min = 0 end | |
| if self.max == PropertyDefNumber.max then self.max = 100 * (const.Scale[self.scale] or self.scale) end | |
| end | |
| end | |
| DefineClass.PropertyDefRange = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Range", id = "default", name = "Default value", editor = "range", scale = function(obj) return obj.scale end, min = function(obj) return obj.min end, max = function(obj) return obj.max end, default = false, }, | |
| { category = "Range", id = "scale", name = "Scale", editor = "choice", default = 1, items = function() return table.keys2(const.Scale, true, 1, 10, 100, 1000, 1000000) end, }, | |
| { category = "Range", id = "step", name = "Step", editor = "number", default = 1, scale = function(obj) return obj.scale end, }, | |
| { category = "Range", id = "slider", name = "Slider", editor = "bool", default = false, }, | |
| { category = "Range", id = "min", name = "Min", editor = "number", default = min_int64 }, | |
| { category = "Range", id = "max", name = "Max", editor = "number", default = max_int64 }, | |
| }, | |
| editor = "range", | |
| EditorName = "Range property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| function PropertyDefRange:GenerateAdditionalPropCode(code, translate) | |
| if self.scale ~= 1 then | |
| code:appendf(type(self.scale) == "number" and "scale = %d, " or "scale = \"%s\", ", self.scale) | |
| end | |
| if self.step ~= 1 then code:appendf("step = %d, ", self.step) end | |
| if self.slider then code:append("slider = true, ") end | |
| if self.min ~= PropertyDefRange.min then code:appendf("min = %d, ", self.min) end | |
| if self.max ~= PropertyDefRange.max then code:appendf("max = %d, ", self.max) end | |
| end | |
| function PropertyDefRange:OnEditorSetProperty(prop_id, old_value, ged) | |
| if prop_id == "slider" and self.slider then | |
| if self.min == PropertyDefRange.min then self.min = 0 end | |
| if self.max == PropertyDefRange.max then self.max = 100 * (const.Scale[self.scale] or self.scale) end | |
| end | |
| end | |
| local function translate_only(obj) return not obj.translate end | |
| TextGenderOptions = { | |
| {value = false, text = "None"}, | |
| {value = "ask", text = "Request translation gender for each language (for nouns)"}, | |
| {value = "variants", text = "Generate separate translation texts for each gender"}, | |
| } | |
| DefineClass.PropertyDefText = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Text", id = "default", name = "Default value", editor = "text", default = false, translate = function (obj) return obj.translate end, }, | |
| { category = "Text", id = "translate", name = "Translate", editor = "bool", default = true, }, | |
| { category = "Text", id = "wordwrap", name = "Wordwrap", editor = "bool", default = false, }, | |
| { category = "Text", id = "gender", name = "Gramatical gender", editor = "choice", default = false, items = TextGenderOptions, | |
| no_edit = translate_only, dont_save = translate_only }, | |
| { category = "Text", id = "lines", name = "Lines", editor = "number", default = false, }, | |
| { category = "Text", id = "max_lines", name = "Max lines", editor = "number", default = false, }, | |
| { category = "Text", id = "trim_spaces", name = "Trim Spaces", editor = "bool", default = true, }, | |
| { category = "Text", id = "context", name = "Context", editor = "text", default = "", | |
| no_edit = translate_only, dont_save = translate_only } | |
| }, | |
| editor = "text", | |
| EditorName = "Text property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| function PropertyDefText:OnEditorSetProperty(prop_id, old_value, ged) | |
| if prop_id == "translate" then | |
| self:UpdateLocalizedProperty("default", self.translate) | |
| end | |
| end | |
| function PropertyDefText:GenerateAdditionalPropCode(code, translate) | |
| if self.translate then code:append("translate = true, ") end | |
| if self.wordwrap then code:append("wordwrap = true, ") end | |
| if self.lines then code:appendf("lines = %d, ", self.lines) end | |
| if self.max_lines then code:appendf("max_lines = %d, ", self.max_lines) end | |
| if self.trim_spaces==false then code:append("trim_spaces = false, ") end | |
| local context = self.translate and self.context or "" | |
| if context ~= "" then | |
| assert(not self.gender, "Custom context code is not compatible with gender specification") -- you should include |gender-ask or |gender-variants in the function result | |
| code:append("context = ", context, ", ") | |
| elseif self.gender then | |
| code:append('context = "|gender-', self.gender, '", ') | |
| end | |
| end | |
| DefineClass.PropertyDefChoice = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Choice", id = "default", name = "Default value", editor = "choice", default = false, items = EmulatePropEval("items", {""}) }, | |
| { category = "Choice", id = "items", name = "Items", editor = "expression", default = false, }, | |
| { category = "Choice", id = "show_recent_items", name = "Show recent items", editor = "number", default = 0, }, | |
| }, | |
| translate = false, | |
| editor = "choice", | |
| EditorName = "Choice property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| function PropertyDefChoice:GenerateAdditionalPropCode(code, translate) | |
| if self.items then | |
| code:append("items = ") | |
| ValueToLuaCode(self.items, nil, code) | |
| code:append(", ") | |
| end | |
| if self.show_recent_items and self.show_recent_items ~= 0 then | |
| code:appendf("show_recent_items = %d,", self.show_recent_items) | |
| end | |
| end | |
| function PropertyDefChoice:GetConvertToPresetIdClass() | |
| local preset_class | |
| if self.items then | |
| local src = GetFuncSourceString(self.items) | |
| local _, _, capture = string.find(src, 'PresetsCombo%("([%w_+-]*)"%)') | |
| preset_class = capture | |
| end | |
| return preset_class | |
| end | |
| DefineClass.PropertyDefCombo = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Combo", id = "default", name = "Default value", editor = "combo", default = false, items = EmulatePropEval("items", {""}) }, | |
| { category = "Combo", id = "items", name = "Items", editor = "expression", default = false, }, | |
| { category = "Combo", id = "translate", name = "Translate", editor = "bool", default = false, }, | |
| { category = "Combo", id = "show_recent_items", name = "Show recent items", editor = "number", default = 0, }, | |
| }, | |
| editor = "combo", | |
| EditorName = "Combo property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| PropertyDefCombo.GenerateAdditionalPropCode = PropertyDefChoice.GenerateAdditionalPropCode | |
| DefineClass.PropertyDefPickerBase = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Picker", id = "default", name = "Default value", editor = "combo", default = false, items = EmulatePropEval("items", {""}) }, | |
| { category = "Picker", id = "items", name = "Items", editor = "expression", default = false, }, | |
| { category = "Picker", id = "max_rows", name = "Max rows", editor = "number", default = false, help = "Maximum number of rows displayed." }, | |
| { category = "Picker", id = "multiple", name = "Multiple selection", editor = "bool", default = false, }, | |
| { category = "Picker", id = "small_font", name = "Small font", editor = "bool", default = false, }, | |
| { category = "Picker", id = "filter_by_prop", name = "Filter by prop", editor = "text", default = false, help = "Links this property to a text property with the specified id that serves as a filter." }, | |
| }, | |
| } | |
| function PropertyDefPickerBase:GenerateAdditionalPropCode(code, translate) | |
| PropertyDefChoice.GenerateAdditionalPropCode(self, code, translate) | |
| if self.max_rows then code:appendf("max_rows = %d, ", self.max_rows) end | |
| if self.multiple then code:append ("multiple = true, ") end | |
| if self.small_font then code:append ("small_font = true, ") end | |
| if self.filter_by_prop then code:appendf("filter_by_prop = \"%s\", ", self.filter_by_prop) end | |
| end | |
| DefineClass.PropertyDefTextPicker = { | |
| __parents = { "PropertyDefPickerBase" }, | |
| properties = { | |
| { category = "Picker", id = "horizontal", name = "Horizontal", editor = "bool", default = false, help = "Display items horizontally." }, | |
| }, | |
| editor = "text_picker", | |
| EditorName = "Text picker property", | |
| EditorSubmenu = "Extras", | |
| } | |
| function PropertyDefTextPicker:GenerateAdditionalPropCode(code, translate) | |
| PropertyDefPickerBase.GenerateAdditionalPropCode(self, code, translate) | |
| if self.horizontal then code:append("horizontal = true, ") end | |
| end | |
| DefineClass.PropertyDefTexturePicker = { | |
| __parents = { "PropertyDefPickerBase" }, | |
| properties = { | |
| { category = "Picker", id = "thumb_width", name = "Width", editor = "number", default = false, }, | |
| { category = "Picker", id = "thumb_height", name = "Height", editor = "number", default = false, }, | |
| { category = "Picker", id = "thumb_zoom", name = "Zoom", editor = "number", min = 100, max = 200, slider = true, default = false, help = "Scale the texture up, displaying only the middle part with Width x Height dimensions.", }, | |
| { category = "Picker", id = "alt_prop", name = "Alt prop", editor = "text", default = false, help = "Id of another property that gets set by Alt-click on this property.", }, | |
| { category = "Picker", id = "base_color_map", name = "Base color map", editor = "bool", default = false, help = "Use to display a base color map texture in the correct colors.", }, | |
| }, | |
| editor = "texture_picker", | |
| EditorName = "Texture picker property", | |
| EditorSubmenu = "Extras", | |
| } | |
| function PropertyDefTexturePicker:GenerateAdditionalPropCode(code, translate) | |
| PropertyDefPickerBase.GenerateAdditionalPropCode(self, code, translate) | |
| if self.thumb_width then code:appendf("thumb_width = %d, ", self.thumb_width) end | |
| if self.thumb_height then code:appendf("thumb_height = %d, ", self.thumb_height) end | |
| if self.thumb_zoom then code:appendf("thumb_zoom = %d, ", self.thumb_zoom) end | |
| if self.alt_prop then code:appendf("alt_prop = \"%s\", ", self.alt_prop) end | |
| if self.base_color_map then code:append ("base_color_map = true, ") end | |
| end | |
| DefineClass.PropertyDefSet = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Set", id = "default", name = "Default value", editor = "set", default = false, items = EmulatePropEval("items", {""}), three_state = function(obj) return obj.three_state end, max_items_in_set = function(obj) return obj.max_items_in_set end, }, | |
| { category = "Set", id = "items", name = "Items", editor = "expression", default = false, }, | |
| { category = "Set", id = "arbitrary_value", name = "Allow arbitrary value", editor = "bool", default = false, }, | |
| { category = "Set", id = "three_state", name = "Three-state", editor = "bool", default = false, help = "Each set item can have one of the three value 'nil', 'true', or 'false'." }, | |
| { category = "Set", id = "max_items_in_set", name = "Max items", editor = "number", default = 0, help = "Max number of items in the set (0 = no limit)." }, | |
| }, | |
| translate = false, | |
| editor = "set", | |
| EditorName = "Set property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| function PropertyDefSet:GenerateAdditionalPropCode(code, translate) | |
| if self.three_state then code:append("three_state = true, ") end | |
| if self.arbitrary_value then code:append("arbitrary_value = true, ") end | |
| if self.max_items_in_set ~= 0 then code:appendf("max_items_in_set = %d, ", self.max_items_in_set) end | |
| if self.items then | |
| code:append("items = ") | |
| ValueToLuaCode(self.items, nil, code) | |
| code:append(", ") | |
| end | |
| end | |
| DefineClass.PropertyDefGameStatefSet = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Set", id = "default", name = "Default value", editor = "set", default = false, items = function() return GetGameStateFilter() end, three_state = true, }, | |
| }, | |
| translate = false, | |
| editor = "set", | |
| EditorName = "GameState Set property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| function PropertyDefGameStatefSet:GenerateAdditionalPropCode(code, translate) | |
| code:append("three_state = true, items = function (self) return GetGameStateFilter() end, ") | |
| code:append('buttons = { {name = "Check Game States", func = "PropertyDefGameStatefSetCheck"}, },') | |
| end | |
| function PropertyDefGameStatefSetCheck(_, obj, prop_id, ged) | |
| ged:ShowMessage("Test Result", GetMismatchGameStates(obj[prop_id])) | |
| end | |
| DefineClass.PropertyDefColor = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Color", id = "default", name = "Default value", editor = "color", default = RGB(0, 0, 0), }, | |
| }, | |
| editor = "color", | |
| EditorName = "Color property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| DefineClass.PropertyDefImage = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Image", id = "default", name = "Default value", editor = "image", default = false, }, | |
| { category = "Image", id = "img_size", name = "Image box", editor = "number", default = 200, }, | |
| { category = "Image", id = "img_box", name = "Image border", editor = "number", default = 1, }, | |
| { category = "Image", id = "base_color_map", name = "Base color", editor = "bool", default = false, }, | |
| }, | |
| editor = "image", | |
| EditorName = "Image preview property", | |
| EditorSubmenu = "Extras", | |
| } | |
| function PropertyDefImage:GenerateAdditionalPropCode(code, translate) | |
| code:appendf("img_size = %d, img_box = %d, base_color_map = %s, ", self.img_size, self.img_box, tostring(self.base_color_map)) | |
| end | |
| DefineClass.PropertyDefGrid = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Grid", id = "default", name = "Default value", editor = "grid", default = false, }, | |
| { category = "Grid", id = "frame", name = "Frame", editor = "number", default = 0, }, | |
| { category = "Grid", id = "color", name = "Color", editor = "bool", default = false }, | |
| { category = "Grid", id = "min", name = "Min Size", editor = "number", default = 0, }, | |
| { category = "Grid", id = "max", name = "Max Size", editor = "number", default = 0 }, | |
| }, | |
| editor = "grid", | |
| EditorName = "Grid property", | |
| EditorSubmenu = "Extras", | |
| } | |
| function PropertyDefGrid:GenerateAdditionalPropCode(code, translate) | |
| if self.frame > 0 then code:appendf("frame = %d, ", self.frame) end | |
| if self.min > 0 then code:appendf("min = %d, ", self.min) end | |
| if self.max > 0 then code:appendf("max = %d, ", self.max) end | |
| if self.color then code:append("color = true, ") end | |
| end | |
| DefineClass.PropertyDefMaterial = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Color", id = "default", name = "Default value", editor = "rgbrm", default = RGBRM(200, 200, 200, 0, 0) }, | |
| }, | |
| editor = "rgbrm", | |
| EditorName = "Material property", | |
| EditorSubmenu = "Extras", | |
| } | |
| DefineClass.PropertyDefBrowse = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Browse", id = "default", name = "Default value", editor = "browse", default = false, }, | |
| { category = "Browse", id = "folder", name = "Folder", editor = "text", default = "UI", }, | |
| { category = "Browse", id = "filter", name = "Filter", editor = "text", default = "Image files|*.tga", }, | |
| { category = "Browse", id = "extension", name = "Force extension", editor = "text", default = false, | |
| buttons = { { name = "No extension", func = function(self) self.extension = "" ObjModified(self) end, } }, | |
| }, | |
| { category = "Browse", id = "image_preview_size", name = "Image preview size", editor = "number", default = 0, }, | |
| }, | |
| editor = "browse", | |
| EditorName = "Browse property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| function PropertyDefBrowse:GenerateAdditionalPropCode(code, translate) | |
| local folder, filter = self.folder or "", self.filter or "" | |
| if folder ~= "" then | |
| -- detect if we have a table or a single string for self.folder | |
| if folder:match("^%s*[{\"]") then | |
| code:appendf("folder = %s, ", self.folder) | |
| else | |
| code:appendf("folder = \"%s\", ", self.folder) | |
| end | |
| end | |
| if self.filter ~= "" then code:appendf("filter = \"%s\", ", self.filter) end | |
| if self.extension ~= PropertyDefBrowse.extension then code:appendf("force_extension = \"%s\", ", self.extension) end | |
| if self.image_preview_size > 0 then code:appendf("image_preview_size = %i, ", self.image_preview_size) end | |
| end | |
| DefineClass.PropertyDefUIImage = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Browse", id = "default", name = "Default value", editor = "ui_image", default = false, }, | |
| { category = "Browse", id = "filter", name = "Filter", editor = "text", default = "All files|*.*", }, | |
| { category = "Browse", id = "extension", name = "Force extension", editor = "text", default = false, | |
| buttons = { { name = "No extension", func = function(self) self.extension = "" ObjModified(self) end, } }, | |
| }, | |
| { category = "Browse", id = "image_preview_size", name = "Image preview size", editor = "number", default = 0, }, | |
| }, | |
| editor = "ui_image", | |
| EditorName = "UI image property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| function PropertyDefUIImage:GenerateAdditionalPropCode(code, translate) | |
| if self.filter ~= PropertyDefUIImage.filter then code:appendf("filter = \"%s\", ", self.filter) end | |
| if self.extension ~= PropertyDefUIImage.extension then code:appendf("force_extension = \"%s\", ", self.extension) end | |
| if self.image_preview_size > 0 then code:appendf("image_preview_size = %i, ", self.image_preview_size) end | |
| end | |
| DefineClass.PropertyDefFunc = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Func", id = "params", name = "Params", editor = "text", default = "self", }, | |
| { category = "Func", id = "default", name = "Default value", editor = "func", default = empty_func, lines = 1, max_lines = 20, params = function (self) return self.params end, }, | |
| }, | |
| editor = "func", | |
| EditorName = "Func property", | |
| EditorSubmenu = "Code", | |
| } | |
| function PropertyDefFunc:ToStringWithColor(value) | |
| if value == empty_func then | |
| return PropertyDef.ToStringWithColor(self, string.format("function (%s) end", self.params), "function") | |
| end | |
| return PropertyDef.ToStringWithColor(self, value) | |
| end | |
| function PropertyDefFunc:GenerateDefaultValueCode() | |
| if not self.default then return "false" end | |
| return GetFuncSourceString(self.default, "", self.params or "self") | |
| end | |
| function PropertyDefFunc:GenerateAdditionalPropCode(code, translate) | |
| if self.params and self.params ~= "self" then | |
| code:appendf("params = \"%s\", ", self.params) | |
| end | |
| end | |
| DefineClass.PropertyDefExpression = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Expression", id = "params", name = "Params", editor = "text", default = "self", }, | |
| { category = "Expression", id = "default", name = "Default value", editor = "expression", default = false, params = function(self) return self.params end, }, | |
| }, | |
| editor = "expression", | |
| EditorName = "Expression property", | |
| EditorSubmenu = "Code", | |
| } | |
| function PropertyDefExpression:GenerateDefaultValueCode() | |
| if not self.default then return "false" end | |
| return GetFuncSourceString(self.default, "", self.params or "self") | |
| end | |
| function PropertyDefExpression:GenerateAdditionalPropCode(code, translate) | |
| if self.params and self.params ~= "self" then | |
| code:appendf("params = \"%s\", ", self.params) | |
| end | |
| end | |
| DefineClass.PropertyDefShortcut = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Expression", id = "shortcut_type", name = "Shortcut type", editor = "choice", default = "keyboard&mouse", items = { | |
| "keyboard&mouse", | |
| "keyboard", | |
| "gamepad" | |
| }, }, | |
| { category = "Expression", id = "default", name = "Default value", editor = "text", default = "", no_edit = true, }, | |
| }, | |
| editor = "shortcut", | |
| EditorName = "Shortcut property", | |
| EditorSubmenu = "Extras", | |
| } | |
| function PropertyDefShortcut:GenerateAdditionalPropCode(code, translate) | |
| code:appendf("shortcut_type = \"%s\", ", self.shortcut_type) | |
| end | |
| ----- Presets - preset_id & preset_id_list | |
| function IsPresetWithConstantGroup(classdef) | |
| if not classdef then return end | |
| local prop = classdef:GetPropertyMetadata("Group") | |
| return not prop or prop_eval(prop.no_edit, classdef, prop, true) or prop_eval(prop.read_only, classdef, prop, true) | |
| end | |
| DefineClass.PropertyDefPresetIdBase = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "PresetId", id = "preset_class", name = "Preset class", editor = "choice", default = "", | |
| items = ClassDescendantsCombo("Preset", false, function(name, class) | |
| return not IsKindOfClasses(class, "ClassDef", "ClassDefSubItem") | |
| end), | |
| }, | |
| { category = "PresetId", id = "preset_group", name = "Preset group", editor = "choice", default = "", | |
| help = "Restricts the choice to the specified group of the preset class.", | |
| items = function(obj) | |
| local class = g_Classes[obj.preset_class] | |
| local preset_class = class.PresetClass or obj.preset_class | |
| return class and PresetGroupsCombo(preset_class) or empty_table | |
| end, | |
| no_edit = function(obj) -- disable group restriction for classes with uneditable "Group" property | |
| local class = g_Classes[obj.preset_class] | |
| return not class or IsPresetWithConstantGroup(class) | |
| end, }, | |
| { category = "PresetId", id = "preset_filter", name = "PresetFilter", editor = "func", params = "preset, obj, prop_meta", lines = 1, max_lines = 20, default = false }, | |
| { category = "PresetId", id = "extra_item", name = "Extra item", editor = "text", default = false }, | |
| { category = "PresetId", id = "default", name = "Default value", editor = "choice", | |
| items = function(obj) | |
| local class = g_Classes[obj.preset_class] | |
| if class and (class.GlobalMap or IsPresetWithConstantGroup(class) or obj.preset_group ~= "") then | |
| return PresetsCombo(obj.preset_class, obj.preset_group ~= "" and obj.preset_group, {"", obj.extra_item or nil}) | |
| end | |
| return { false } | |
| end, default = false }, | |
| }, | |
| editor = "preset_id", | |
| EditorName = "PresetId property", | |
| EditorSubmenu = "Basic property", | |
| } | |
| function PropertyDefPresetIdBase:GenerateAdditionalPropCode(code, translate) | |
| if self.preset_class ~= "" then code:appendf("preset_class = \"%s\", ", self.preset_class) end | |
| if self.preset_group ~= "" then code:appendf("preset_group = \"%s\", ", self.preset_group) end | |
| if self.extra_item then code:appendf("extra_item = \"%s\", ", self.extra_item) end | |
| self:AppendFunctionCode(code, "preset_filter") | |
| end | |
| function PropertyDefPresetIdBase:OnEditorSetProperty(prop_id, old_value, ...) | |
| if prop_id == "preset_class" then | |
| self.preset_group = nil | |
| self.default = nil | |
| elseif prop_id == "preset_group" then | |
| self.default = nil | |
| end | |
| ObjModified(self) | |
| end | |
| function PropertyDefPresetIdBase:GetError() | |
| local class = g_Classes[self.preset_class] | |
| if class and not (class.GlobalMap or IsPresetWithConstantGroup(class) or self.preset_group ~= "") then | |
| return string.format("%s doesn't have GlobalMap - all presets can't be listed. Please specify a Preset group.\n\nIf you want all presets to be selectable, either add GlobalMap, or create two properties - one for selecting a preset group and another for selecting a preset from that group.", self.preset_class) | |
| end | |
| end | |
| DefineClass.PropertyDefPresetId = { | |
| __parents = { "PropertyDefPresetIdBase" }, | |
| } | |
| DefineClass.PropertyDefPresetIdList = { | |
| __parents = { "PropertyDefPresetIdBase", "WeightedListProps" }, | |
| properties = { | |
| { category = "PresetId", id = "default", name = "Default value", editor = "preset_id_list", | |
| preset_class = function(obj) return obj.preset_class end, | |
| preset_group = function(obj) return obj.preset_group end, | |
| extra_item = function(obj) return obj.extra_item end, | |
| default = {}, }, | |
| }, | |
| editor = "preset_id_list", | |
| EditorName = "PresetId list property", | |
| EditorSubmenu = "Lists", | |
| } | |
| function PropertyDefPresetIdList:GenerateAdditionalPropCode(code, translate) | |
| PropertyDefPresetIdBase.GenerateAdditionalPropCode(self, code, translate) | |
| code:append("item_default = \"\"") | |
| self:GenerateWeightPropCode(code) | |
| code:append(", ") | |
| end | |
| ----- Nested object & nested list | |
| local function BaseClassCombo(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) | |
| local class = g_Classes[value] | |
| return value == "" or IsKindOf(class, "PropertyObject") and not IsKindOf(class, "CObject") | |
| end | |
| end | |
| return ClassDescendantsList("PropertyObject", function(name, def) | |
| return not def.__ancestors.CObject and name ~= "CObject" | |
| end, "") | |
| end | |
| DefineClass.PropertyDefObject = { | |
| __parents = { "PropertyDef" }, | |
| default = false, | |
| editor = "object", | |
| properties = { | |
| { category = "Property", id = "base_class", name = "Base class", editor = "choice", items = function() return ClassDescendantsListInclusive("Object") end, default = "Object" }, | |
| { category = "Property", id = "format_func", name = "Format", editor = "func", default = GetObjectPropEditorFormatFuncDefault, lines = 1, max_lines = 10, params = "gameobj"}, | |
| }, | |
| EditorName = "Object property", | |
| EditorSubmenu = "Objects", | |
| } | |
| function PropertyDefObject:GenerateAdditionalPropCode(code, translate) | |
| code:appendf("base_class = \"%s\", ", self.base_class) | |
| self:AppendFunctionCode(code, "format_func") | |
| end | |
| DefineClass.PropertyDefNestedObj = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Nested Object", id = "base_class", name = "Base class", editor = "choice", items = BaseClassCombo, default = "PropertyObject" }, | |
| { category = "Nested Object", id = "inclusive", name = "Allow base class", editor = "bool", default = false, }, | |
| { category = "Nested Object", id = "no_descendants", name = "No descendants", editor = "bool", default = false, }, | |
| { category = "Nested Object", id = "all_descendants", name = "Allow all descendants", editor = "bool", default = false, no_edit = function (self) return self.no_descendants end, }, | |
| { category = "Nested Object", id = "class_filter", name = "ClassFilter", editor = "func", default = false, lines = 1, max_lines = 20, params = "name, class, obj"}, | |
| { category = "Nested Object", id = "format", name = "Format in Ged", editor = "text", default = "<EditorView>", }, | |
| { category = "Nested Object", id = "auto_expand", name = "Auto Expand", editor = "bool", default = false, }, | |
| { category = "Nested Object", id = "default", name = "Default value", editor = "bool", default = false, no_edit = true, }, | |
| }, | |
| editor = "nested_obj", | |
| EditorName = "Nested object property", | |
| EditorSubmenu = "Objects", | |
| } | |
| function PropertyDefNestedObj:GenerateAdditionalPropCode(code, translate) | |
| code:appendf("base_class = \"%s\", ", self.base_class) | |
| if self.inclusive then code:append("inclusive = true, ") end | |
| if self.no_descendants then code:append("no_descendants = true, ") | |
| elseif self.all_descendants then code:append("all_descendants = true, ") end | |
| if self.auto_expand then code:appendf("auto_expand = true, ") end | |
| if self.format ~= PropertyDefNestedObj.format then code:appendf("format = \"%s\"", self.format) end | |
| self:AppendFunctionCode(code, "class_filter") | |
| end | |
| function PropertyDefNestedObj:GetError() | |
| if self.base_class == "PropertyObject" then | |
| return "Please specify base class for the nested object(s)." | |
| end | |
| end | |
| DefineClass.PropertyDefNestedList = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Nested List", id = "base_class", name = "Base class", editor = "choice", items = BaseClassCombo, default = "PropertyObject" }, | |
| { category = "Nested List", id = "inclusive", name = "Allow base class", editor = "bool", default = false, }, | |
| { category = "Nested List", id = "no_descendants", name = "No descendants", editor = "bool", default = false, }, | |
| { category = "Nested List", id = "all_descendants", name = "Allow all descendants", editor = "bool", default = false, no_edit = function (self) return self.no_descendants end, }, | |
| { category = "Nested List", id = "class_filter", name = "ClassFilter", editor = "func", default = false, lines = 1, max_lines = 20, params = "name, class, obj"}, | |
| { category = "Nested List", id = "format", name = "Format in Ged", editor = "text", default = "<EditorView>", }, | |
| { category = "Nested List", id = "auto_expand", name = "Auto Expand", editor = "bool", default = false, }, | |
| { category = "Nested List", id = "default", name = "Default value", editor = "bool", default = false, no_edit = true, }, | |
| }, | |
| editor = "nested_list", | |
| EditorName = "Nested list property", | |
| EditorSubmenu = "Lists", | |
| } | |
| PropertyDefNestedList.GenerateAdditionalPropCode = PropertyDefNestedObj.GenerateAdditionalPropCode | |
| PropertyDefNestedList.GetError = PropertyDefNestedObj.GetError | |
| DefineClass.PropertyDefPropertyArray = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Dynamic Props", id = "from", name = "Generate id from", editor = "choice", default = false, | |
| items = { "Table keys", "Table values", "Table field values", "Preset ids" }, | |
| }, | |
| { category = "Dynamic Props", id = "field", name = "Table field", editor = "text", translate = false, default = "", | |
| no_edit = function(self) return self.from ~= "Table field values" end, | |
| }, | |
| { category = "Dynamic Props", id = "items", name = "Items", editor = "expression", default = false, | |
| no_edit = function(self) return self.from == "Preset ids" end, | |
| }, | |
| { category = "Dynamic Props", id = "preset", name = "Preset class", editor = "choice", default = "", | |
| items = ClassDescendantsCombo("Preset"), | |
| no_edit = function(self) return self.from ~= "Preset ids" end, | |
| }, | |
| { category = "Dynamic Props", id = "prop_meta_update", name = "Update prop_meta", editor = "func", params = "self, prop_meta", default = false, | |
| help = "Update the prop_meta of each generated property from prop_meta.id, prop_meta.index (consecutive number), and prop_meta.prest/value.", | |
| }, | |
| { category = "Dynamic Props", id = "prop", name = "Property template", editor = "nested_obj", base_class = "PropertyDef", auto_expand = true, default = false, | |
| suppress_props = { id = true, name = true, category = true, dont_save = true, no_edit = true, template = true, }, | |
| }, | |
| }, | |
| editor = "property_array", | |
| EditorName = "Property array", | |
| EditorSubmenu = "Objects", | |
| default = false, | |
| } | |
| function PropertyDefPropertyArray:GenerateAdditionalPropCode(code, translate) | |
| local from_preset = self.from == "Preset ids" and self.preset ~= "" and self.preset | |
| if self.prop and (from_preset or not from_preset and self.items ~= false) then | |
| if from_preset then | |
| code:appendf("from = '%s', ", self.preset) | |
| else | |
| code:append("items = ") | |
| ValueToLuaCode(self.items, nil, code) | |
| code:appendf(", from = '%s', ", self.from) | |
| if self.from == "Table field values" then | |
| code:appendf("field = '%s', ", self.field) | |
| end | |
| if self.prop_meta_update then | |
| code:appendf("prop_meta_update = ") | |
| ValueToLuaCode(self.prop_meta_update, nil, code) | |
| code:appendf(", ") | |
| end | |
| end | |
| code:append("\nprop_meta =\n") | |
| self.prop.id = " " | |
| self.prop:GenerateCode(code, translate) | |
| end | |
| end | |
| DefineClass.PropertyDefScript = { | |
| __parents = { "PropertyDef" }, | |
| properties = { | |
| { category = "Script", id = "condition", name = "Is condition list", editor = "bool", default = false, }, | |
| { category = "Script", id = "params_exp", name = "Params is an expression", editor = "bool", default = false, }, | |
| { category = "Script", id = "params", name = "Params", editor = "text", default = "self", }, | |
| { category = "Script", id = "script_domain", name = "Script domain", editor = "choice", default = false, items = function() return ScriptDomainsCombo() end }, | |
| }, | |
| default = false, | |
| editor = "script", | |
| EditorName = "Script", | |
| EditorSubmenu = "Code", | |
| } | |
| function PropertyDefScript:GenerateAdditionalPropCode(code, translate) | |
| if self.condition then | |
| code:append('class = "ScriptConditionList", ') | |
| end | |
| if self.params_exp then | |
| code:appendf('params = function(self) return %s end, ', self.params) | |
| else | |
| code:appendf('params = "%s", ', self.params) | |
| end | |
| if self.script_domain then | |
| code:appendf('script_domain = "%s", ', self.script_domain) | |
| end | |
| end | |
| ----- Primitive lists | |
| DefineClass.WeightedListProps = { | |
| __parents = { "PropertyObject" }, | |
| properties = { | |
| { category = "Weights", id = "weights", name = "Weights", editor = "bool", default = false, | |
| no_edit = function(obj) return obj:DisableWeights() end, help = "Associates weights to the list items"}, | |
| { category = "Weights", id = "weight_default", name = "Default Weight", editor = "number", default = 100, | |
| no_edit = function(obj) return not obj.weights end, help = "Default weight for each list item" }, | |
| { category = "Weights", id = "value_key", name = "Value Key", editor = "text", default = "value", | |
| no_edit = function(obj) return not obj.weights end, help = "Name of the 'value' key in each list item. Can be a number too." }, | |
| { category = "Weights", id = "weight_key", name = "Weight Key", editor = "text", default = "weight", | |
| no_edit = function(obj) return not obj.weights end, help = "Name of the 'weight' key in each list item. Can be a number too." }, | |
| }, | |
| DisableWeights = empty_func, | |
| } | |
| function WeightedListProps:GetItemKeys() | |
| local value_key = self.value_key | |
| if value_key == "" then | |
| value_key = "value" | |
| end | |
| value_key = tonumber(value_key) or value_key | |
| local weight_key = self.weight_key | |
| if weight_key == "" then | |
| weight_key = "weight" | |
| end | |
| weight_key = tonumber(weight_key) or weight_key | |
| return value_key, weight_key | |
| end | |
| function WeightedListProps:GenerateWeightPropCode(code) | |
| if not self.weights then | |
| return | |
| end | |
| code:append(", weights = true") | |
| local value_key, weight_key = self:GetItemKeys() | |
| if value_key ~= "value" then | |
| code:append(", value_key = ") | |
| ValueToLuaCode(value_key, nil, code) | |
| end | |
| if weight_key ~= "weight" then | |
| code:append(", weight_key = ") | |
| ValueToLuaCode(weight_key, nil, code) | |
| end | |
| if self.weight_default ~= 100 then | |
| code:append(", weight_default = ") | |
| ValueToLuaCode(self.weight_default, nil, code) | |
| end | |
| end | |
| DefineClass.PropertyDefPrimitiveList = { | |
| __parents = { "PropertyDef", "WeightedListProps" }, | |
| properties = { | |
| { category = "List", id = "item_default", name = "Item Default", editor = "text", default = false, }, | |
| { category = "List", id = "items", name = "Items", editor = "expression", default = false, }, | |
| { category = "List", id = "max_items", name = "Max number of items", editor = "number", default = -1, }, | |
| }, | |
| editor = "", | |
| EditorName = "", | |
| } | |
| function PropertyDefPrimitiveList:DisableWeights() | |
| return self.editor ~= "number_list" and self.editor ~= "string_list" | |
| end | |
| function PropertyDefPrimitiveList:GenerateAdditionalPropCode(code, translate) | |
| code:append("item_default = ") | |
| ValueToLuaCode(self.item_default, nil, code) | |
| code:append(", items = ") | |
| ValueToLuaCode(self.items, nil, code) | |
| if self.arbitrary_value then | |
| code:append(", arbitrary_value = true") | |
| end | |
| if self.max_items >= 0 then | |
| code:append(", max_items = ") | |
| ValueToLuaCode(self.max_items, nil, code) | |
| end | |
| self:GenerateWeightPropCode(code) | |
| code:append(", ") | |
| end | |
| DefineClass.PropertyDefNumberList = { | |
| __parents = { "PropertyDefPrimitiveList" }, | |
| properties = { | |
| { category = "List", id = "default", name = "Default value", editor = "number_list", | |
| default = {}, item_default = function(self) return self.item_default end, items = EmulatePropEval("items", {0}) }, | |
| { category = "List", id = "item_default", name = "Item Default", editor = "number", default = 0, }, | |
| }, | |
| editor = "number_list", | |
| EditorName = "Number list property", | |
| EditorSubmenu = "Lists", | |
| } | |
| DefineClass.PropertyDefStringList = { | |
| __parents = { "PropertyDefPrimitiveList" }, | |
| properties = { | |
| { category = "List", id = "default", name = "Default value", editor = "string_list", | |
| default = {}, items = EmulatePropEval("items", {""}), | |
| item_default = function(self) return self.item_default end, | |
| arbitrary_value = function(self) return self.arbitrary_value end, }, | |
| { category = "List", id = "item_default", name = "Item default", editor = "combo", | |
| default = "", items = EmulatePropEval("items", {""}) }, | |
| { category = "List", id = "arbitrary_value", name = "Allow arbitrary value", editor = "bool", default = false, }, | |
| }, | |
| editor = "string_list", | |
| EditorName = "String list property", | |
| EditorSubmenu = "Lists", | |
| } | |
| DefineClass.PropertyDefTList = { | |
| __parents = { "PropertyDefPrimitiveList" }, | |
| properties = { | |
| { category = "List", id = "default", name = "Default value", editor = "T_list", | |
| default = {}, item_default = function(self) return self.item_default end, items = EmulatePropEval("items", {""}) }, | |
| { category = "List", id = "item_default", name = "Item default", editor = "text", default = "", translate = true}, | |
| { category = "Text", id = "context", name = "Context", editor = "text", default = "", } | |
| }, | |
| editor = "T_list", | |
| EditorName = "Translated list property", | |
| EditorSubmenu = "Lists", | |
| } | |
| function PropertyDefTList:GenerateAdditionalPropCode(code, translate) | |
| PropertyDefPrimitiveList.GenerateAdditionalPropCode(self, code, translate) | |
| if self.context and self.context ~= "" then | |
| code:append("context = " .. self.context .. ", ") | |
| end | |
| end | |
| DefineClass.PropertyDefHelp = { | |
| __parents = { "PropertyDef" }, | |
| default = false, | |
| editor = "help", | |
| EditorName = "Help text", | |
| EditorSubmenu = "Extras", | |
| } | |
| ----- ClassConstDef | |
| local const_items = { | |
| { text = "Bool", value = "bool" }, | |
| { text = "Number", value = "number" }, | |
| { text = "Text", value = "text" }, | |
| { text = "Translated Text", value = "translate" }, | |
| { text = "Point", value = "point" }, | |
| { text = "Box", value = "rect" }, | |
| { text = "Color", value = "color" }, | |
| { text = "Range", value = "range" }, | |
| { text = "Image", value = "browse" }, | |
| { text = "Table", value = "prop_table" }, | |
| { text = "String List", value = "string_list" }, | |
| { text = "Number List", value = "number_list" }, | |
| } | |
| DefineClass.ClassConstDef = { | |
| __parents = { "ClassDefSubItem" }, | |
| properties = { | |
| { category = "Const", id = "name", name = "Name", editor = "text", default = "", validate = ValidateIdentifier }, | |
| { category = "Const", id = "type", name = "Type", editor = "choice", default = "bool", items = const_items, }, | |
| { category = "Const", id = "value", name = "Value", editor = function(self) return self.type == "translate" and "text" or self.type end, | |
| translate = function(self) return self.type == "translate" end, default = false, | |
| lines = function(self) return self.type == "prop_table" and 3 or self.type == "text" and 1 end, | |
| max_lines = function(self) return self.type == "text" and 256 end, }, | |
| { category = "Const", id = "untranslated", name = "Untranslated", editor = "bool", | |
| no_edit = function(self) return self.type ~= "translate" and self.type ~= "text" end, default = false, } | |
| }, | |
| EditorName = "Class member", | |
| EditorSubmenu = "Code", | |
| } | |
| function ClassConstDef:OnEditorSetProperty(prop_id, old_value, ged) | |
| if prop_id == "type" then | |
| local value = self.type | |
| if value == "text" and old_value == "translate" then | |
| self:UpdateLocalizedProperty("value", false) | |
| elseif value == "translate" and old_value == "text" then | |
| self:UpdateLocalizedProperty("value", true) | |
| else | |
| self.value = nil | |
| end | |
| end | |
| end | |
| function ClassConstDef:GetValue() | |
| if not self.value and (self.type == "text" or self.type == "translate") then | |
| return "" | |
| end | |
| return self.value | |
| end | |
| function ClassConstDef:GetEditorView() | |
| local result = "<color 45 138 138>Class.</color>" | |
| if self.type == "translate" then | |
| result = result .. string.format(self.untranslated and '%s = Untranslated(%s)' or '%s = T(%s)', self.name, self:ToStringWithColor(TDevModeGetEnglishText(self:GetValue()))) | |
| else | |
| result = result .. string.format("%s = %s", self.name, self:ToStringWithColor(self:GetValue())) | |
| end | |
| return result | |
| end | |
| function ClassConstDef:GenerateCode(code) | |
| if not self.name:match("^[%w_]+$") then return end | |
| if self.untranslated then | |
| code:append("\t", self.name, " = Untranslated(" ) | |
| if self.type == "text" then | |
| ValueToLuaCode(self:GetValue(), nil, code) | |
| elseif self.type == "translate" then | |
| ValueToLuaCode(TDevModeGetEnglishText(self:GetValue()), nil, code) | |
| end | |
| code:append("),\n") | |
| return | |
| end | |
| code:append("\t", self.name, " = ") | |
| ValueToLuaCode(self:GetValue(), nil, code) | |
| code:append(",\n") | |
| end | |
| ----- ClassMethodDef | |
| local default_methods = { | |
| "", | |
| "GetEditorView()", | |
| "GetError()", | |
| "GetWarning()", | |
| "OnEditorSetProperty(prop_id, old_value, ged)", | |
| "OnEditorNew(parent, ged, is_paste)", | |
| "OnEditorDelete(parent, ged)", | |
| "OnEditorSelect(selected, ged)", | |
| } | |
| function ClassMethodDefKnownMethodsCombo(method_def) | |
| local defaults = { delete = true } | |
| for _, method in ipairs(default_methods) do | |
| local name = method:match("(.+)%(") | |
| if name then defaults[name] = true end | |
| end | |
| local methods = {} | |
| local class_def = GetParentTableOfKind(method_def, "ClassDef") | |
| for _, parent in ipairs(class_def.DefParentClassList) do | |
| local class = g_Classes[parent] | |
| while class and class.class ~= "PropertyObject" and class.class ~= "Preset" do | |
| for k, v in pairs(class) do | |
| if type(v) == "function" then | |
| local name, params, body = GetFuncSource(v) | |
| local sep_idx = name and name:find(":", 1, true) | |
| if sep_idx then | |
| name = name:sub(sep_idx + 1) | |
| if not defaults[name] then | |
| methods[#methods + 1] = string.format("%s(%s)", name, params:trim_spaces()) | |
| end | |
| end | |
| end | |
| end | |
| class = getmetatable(class) | |
| end | |
| end | |
| table.sort(methods) | |
| return #methods == 0 and default_methods or table.iappend(table.iappend(table.copy(default_methods), {"---"}), methods) | |
| end | |
| DefineClass.ClassMethodDef = { | |
| __parents = { "ClassDefSubItem" }, | |
| properties = { | |
| { category = "Method", id = "name", name = "Name", editor = "combo", default = "", | |
| items = ClassMethodDefKnownMethodsCombo, | |
| validate = function (self, value) | |
| local sep_idx = type(value) == "string" and value:find("(", 1, true) | |
| local name = sep_idx and value:sub(1, sep_idx - 1) or value | |
| if type(value) ~= "string" or not name:match("^[%w_]*$") then | |
| return "Value must be a valid identifier or a function prototype." | |
| end | |
| end, }, | |
| { category = "Method", id = "params", name = "Params", editor = "text", default = "", }, | |
| { category = "Method", id = "comment", name = "Comment", editor = "text", default = "", lines = 1, max_lines = 5, }, | |
| { category = "Method", id = "code", name = "Code", editor = "func", default = false, lines = 1, max_lines = 100, | |
| params = function (self) return self.params == "" and "self" or "self, " .. self.params end, }, | |
| }, | |
| EditorName = "Method", | |
| EditorSubmenu = "Code", | |
| } | |
| function ClassMethodDef:GetEditorView() | |
| local ret = string.format("<color 75 105 198>function</color> <color 45 138 138>Class:</color>%s(%s)", self.name, self.params) | |
| if self.comment ~= "" then | |
| ret = string.format("%s <color 0 128 0> -- %s", ret, self.comment) | |
| end | |
| return ret | |
| end | |
| function ClassMethodDef:GenerateCode(code, class_name) | |
| if not self.name:match("^[%w_]+$") then return end | |
| code:appendf("function %s:%s(%s)\n", class_name, self.name, self.params) | |
| local name, params, body = GetFuncSource(self.code) | |
| if type(body) == "string" then | |
| body = string.split(body, "\n") | |
| end | |
| code:append("\t", body and table.concat(body, "\n\t") or "", "\n") | |
| code:append("end\n\n") | |
| end | |
| function ClassMethodDef:ContainsCode(snippet) | |
| local name, params, body = GetFuncSource(self.code) | |
| if type(body) == "table" then | |
| body = table.concat(body, "\n") | |
| end | |
| return body and body:find(snippet, 1, true) | |
| end | |
| function ClassMethodDef:OnEditorSetProperty(prop_id, old_value, ged) | |
| local method = self.name | |
| if prop_id == "name" and method:find("(", 1, true) then | |
| self.name = method:match("(.+)%(") | |
| self.params = method:sub(#self.name + 2, -2) | |
| end | |
| end | |
| ----- ClassGlobalCodeDef | |
| DefineClass.ClassGlobalCodeDef = { | |
| __parents = { "ClassDefSubItem" }, | |
| properties = { | |
| { id = "comment", name = "Comment", editor = "text", default = "", }, | |
| { id = "code", name = "Code", editor = "func", default = false, lines = 1, max_lines = 100, params = "", }, | |
| }, | |
| EditorName = "Code", | |
| EditorSubmenu = "Code", | |
| } | |
| function ClassGlobalCodeDef:GetEditorView() | |
| if self.comment == "" then | |
| return "code" | |
| end | |
| return string.format("code <color 0 128 0>-- %s</color>", self.comment) | |
| end | |
| function ClassGlobalCodeDef:GenerateCode(code, class_name) | |
| local name, params, body = GetFuncSource(self.code) | |
| if not body then return end | |
| code:append("----- ", class_name, " ", self.comment, "\n\n") | |
| if type(body) == "table" then | |
| for _, line in ipairs(body) do | |
| code:append(line, "\n") | |
| end | |
| else | |
| code:append(body) | |
| end | |
| code:append("\n") | |
| end | |