File size: 3,053 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
-- Supports storing of editor data via :EditorData() and tracking dirty status

DefineClass("GedEditedObject")

if FirstLoad then
	g_GedEditorData = setmetatable({}, weak_keys_meta)
	g_DirtyObjects = {}
	g_DirtyObjectsById = {}
end

local function notify_dirty_status(obj, dirty)
	g_DirtyObjects[obj] = dirty or nil
	GedUpdateDirtyObjectsById()
	GedNotify(obj, "OnEditorDirty", dirty)
	for id, ged in pairs(GedConnections) do
		GedUpdateObjectValue(ged, nil, "root|dirty_objects")
	end
end

function GedEditedObject:EditorData()
	local data = g_GedEditorData[self]
	if not data then
		data = {}
		g_GedEditorData[self] = data
	end
	return data
end

-- calculate original hash when the object is displayed in Ged for editing
function OnMsg.GedBindObj(obj)
	while obj do
		if IsKindOf(obj, "GedEditedObject") then
			obj:TrackDirty()
		end
		obj = ParentTableCache[obj]
	end
end

-- update current hash when the object is modified in Ged
function OnMsg.ObjModified(obj)
	while obj do
		if IsKindOf(obj, "GedEditedObject") and obj:IsOpenInGed() then
			obj:UpdateDirtyStatus()
		end
		obj = ParentTableCache[obj] and GetParentTableOfKind(obj, "GedEditedObject")
	end
end

function GedEditedObject:IsOpenInGed()
	assert(false, "Not implemented") -- please implement in the children classes
end

function GedEditedObject:TrackDirty()
	local data = self:EditorData()
	if not data.old_hash then
		data.old_hash = self:CalculatePersistHash()
		data.current_hash = data.old_hash
	end
end

function GedEditedObject:UpdateDirtyStatus()
	local data = self:EditorData()
	local old_hash = data.old_hash
	if old_hash then
		local new_hash = self:CalculatePersistHash()
		if data.current_hash ~= new_hash then
			data.current_hash = new_hash
			notify_dirty_status(self, old_hash ~= new_hash)
		end
	end
end

function GedEditedObject:IsDirty()
	local data = self:EditorData()
	local old_hash = data.old_hash
	return old_hash and (old_hash == 0 or old_hash ~= data.current_hash)
end

function GedEditedObject:MarkDirty(notify)
	if not self:IsDirty() then
		self:EditorData().old_hash = 0
		if notify ~= false then
			notify_dirty_status(self, true)
		end
	end
end

function GedEditedObject:MarkClean()
	local data = self:EditorData()
	data.current_hash = self:CalculatePersistHash()
	if self:IsDirty() then
		data.old_hash = data.current_hash
		notify_dirty_status(self, false)
	end
end


----- Send dirty objects to Ged, so * modified marks can be displayed for them

function GedUpdateDirtyObjectsById()
	local dirty = {}
	for obj in pairs(g_DirtyObjects) do
		dirty[tostring(obj)] = true
		-- mark a preset as dirty if any of its linked presets (defined via a linked_presets property) are dirty
		for parent_preset, linked_presets in pairs(LinkedPresetClasses) do
			if table.find(linked_presets, obj.class) then
				local obj = FindLinkedPresetOfClass(obj, parent_preset)
				if obj then
					dirty[tostring(obj)] = true
				end
			end
		end
	end
	g_DirtyObjectsById = dirty
end

function GedGetDirtyObjects(obj, filter, preset_class)
	return g_DirtyObjectsById
end