File size: 3,842 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
if FirstLoad then
	XEditorToolSettingsUpdateThreads = {}
end

----- XEditorToolSettings
--
-- Properties with 'persisted_setting = true' are stored directly in LocalStorage (and saved when changed)
-- Generated Get/Set methods store the properties in LocalStorage[class_name][property_name]
-- 'shared_setting = true' stores in LocalStorage[property_name] instead, so that multiple tools can share the save value

DefineClass.XEditorToolSettings = {
	__parents = { "PropertyObject" },
}

local function resolve_default(value, default)
	if value == nil then
		return default
	end
	return value
end

function OnMsg.ClassesPostprocess()
	-- generate getters/setters that actually store in LocalStorage
	ClassDescendantsList("XEditorToolSettings", function(name, classdef)
		for _, prop_meta in ipairs(classdef.properties or empty_table) do
			if prop_meta.editor then
				local prop_id = prop_meta.id
				if prop_meta.shared_setting then
					rawset(classdef, "Get" .. prop_id, function(self)
						local meta = self:GetPropertyMetadata(prop_id)
						local store_as = prop_eval(prop_meta.store_as, self, prop_meta) or prop_meta.id
						return resolve_default(LocalStorage[store_as], meta.default)
					end)
					rawset(classdef, "Set" .. prop_id, function(self, value)
						local meta = self:GetPropertyMetadata(prop_id)
						local store_as = prop_eval(prop_meta.store_as, self, prop_meta) or prop_meta.id
						value = ValidateNumberPropValue(value, meta)
						if resolve_default(LocalStorage[store_as], meta.default) ~= value then
							LocalStorage[store_as] = value
							if not IsValidThread(XEditorToolSettingsUpdateThreads[self]) then
								-- Update local storage asynchronously
								XEditorToolSettingsUpdateThreads[self] = CreateRealTimeThread(function()
									Sleep(150)
									SaveLocalStorage()
									ObjModified(self)
								end)
							end
						end
					end)
					rawset(classdef, prop_id, nil)
				elseif prop_meta.persisted_setting then
					rawset(classdef, "Get" .. prop_id, function(self)
						local storage = LocalStorage[classdef.class]
						local meta = self:GetPropertyMetadata(prop_id)
						local store_as = prop_eval(prop_meta.store_as, self, prop_meta) or prop_meta.id
						return resolve_default(storage and storage[store_as], meta.default)
					end)
					rawset(classdef, "Set" .. prop_id, function(self, value)
						local meta = self:GetPropertyMetadata(prop_id)
						local store_as = prop_eval(prop_meta.store_as, self, prop_meta) or prop_meta.id
						value = ValidateNumberPropValue(value, meta)
						local storage = LocalStorage[classdef.class] or {}
						if resolve_default(storage and storage[store_as], meta.default) ~= value then
							LocalStorage[classdef.class] = storage
							storage[store_as] = value
							if not IsValidThread(XEditorToolSettingsUpdateThreads[self]) then
								-- Update local storage asynchronously
								XEditorToolSettingsUpdateThreads[self] = CreateRealTimeThread(function()
									Sleep(150)
									SaveLocalStorage()
									ObjModified(self)
								end)
							end
						end
					end)
					rawset(classdef, prop_id, nil)
				end
			end
		end
	end)
end

function OnMsg.ClassesBuilt()
	ClassDescendants("XEditorToolSettings", function(class_name, class)
		-- gather all parent properties
		local parent_props = {}
		for parent, _ in pairs(class.__ancestors) do
			if g_Classes[parent] and not IsKindOf(g_Classes[parent], "XEditorToolSettings") then
				for _, prop_meta in ipairs(g_Classes[parent].properties) do
					parent_props[prop_meta.id] = true
				end
			end
		end
		
		-- only leave our classes' properties
		local props = class.properties or empty_table
		for idx, prop_meta in ipairs(props) do
			if parent_props[prop_meta.id] then
				props[idx] = table.copy(prop_meta)
				props[idx].no_edit = true
			end
		end
	end)
end