let's give a little more info in the changelog
[QuestHelper.git] / recycle.lua
blobaf187cbc7e5c076d1511fedb562cecbaf377dc38
1 QuestHelper_File["recycle.lua"] = "Development Version"
2 QuestHelper_Loadtime["recycle.lua"] = GetTime()
4 QuestHelper.used_tables = 0
5 QuestHelper.free_tables = {}
7 local unused_meta = {__index=error, __newindex=error}
9 QuestHelper.used_textures = 0
10 QuestHelper.free_textures = {}
12 QuestHelper.used_text = 0
13 QuestHelper.free_text = {}
15 QuestHelper.used_frames = 0
16 QuestHelper.free_frames = {}
18 -- This little table rigs up a basic typing system to assist with debugging. It has weak-reference keys so it shouldn't ever lead to leaks of any kind.
19 QuestHelper.recycle_tabletyping = setmetatable({}, {__mode="k"})
21 function QuestHelper:CreateTable(tag)
22 local tbl = next(self.free_tables)
23 self.used_tables = self.used_tables + 1
25 if not tbl then
26 tbl = {}
27 else
28 self.free_tables[tbl] = nil
29 setmetatable(tbl, nil)
30 end
32 --self.recycle_tabletyping[tbl] = tag or "untyped"
33 self.recycle_tabletyping[tbl] = tag or string.gsub(debugstack(2, 1, 1), "\n.*", "")
34 return tbl
35 end
37 function QuestHelper:ReleaseTable(tbl)
38 assert(type(tbl) == "table")
39 assert(not self.free_tables[tbl])
41 for key in pairs(tbl) do
42 tbl[key] = nil
43 end
45 self.used_tables = self.used_tables - 1
46 self.free_tables[setmetatable(tbl, unused_meta)] = true
47 self.recycle_tabletyping[tbl] = nil
48 end
50 function QuestHelper:DumpTableTypeFrequencies()
51 local freq = {}
52 for k, v in pairs(self.recycle_tabletyping) do
53 freq[v] = (freq[v] or 0) + 1
54 end
56 local flist = {}
57 for k, v in pairs(freq) do
58 table.insert(flist, {count=v, name=k})
59 end
61 table.sort(flist, function(a, b) return a.count < b.count end)
63 for k, v in pairs(flist) do
64 self:TextOut(v.count .. ": " .. v.name)
65 end
66 end
68 function QuestHelper:CreateFrame(parent)
69 self.used_frames = self.used_frames + 1
70 local frame = table.remove(self.free_frames)
72 if frame then
73 frame:SetParent(parent)
74 else
75 frame = CreateFrame("Button", string.format("QuestHelperFrame%d",self.used_frames), parent)
76 end
78 frame:SetFrameLevel((parent or UIParent):GetFrameLevel()+1)
79 frame:SetFrameStrata("MEDIUM")
80 frame:Show()
82 return frame
83 end
85 local frameScripts =
87 "OnChar",
88 "OnClick",
89 "OnDoubleClick",
90 "OnDragStart",
91 "OnDragStop",
92 "OnEnter",
93 "OnEvent",
94 "OnHide",
95 "OnKeyDown",
96 "OnKeyUp",
97 "OnLeave",
98 "OnLoad",
99 "OnMouseDown",
100 "OnMouseUp",
101 "OnMouseWheel",
102 "OnReceiveDrag",
103 "OnShow",
104 "OnSizeChanged",
105 "OnUpdate",
106 "PostClick",
107 "PreClick"
110 function QuestHelper:ReleaseFrame(frame)
111 assert(type(frame) == "table")
112 for i,t in ipairs(self.free_frames) do assert(t ~= frame) end
114 for key in pairs(frame) do
115 -- Remove all keys except 0, which seems to hold some special data.
116 if key ~= 0 then
117 frame[key] = nil
121 for i, script in ipairs(frameScripts) do
122 frame:SetScript(script, nil)
125 frame:Hide()
126 frame:SetParent(QuestHelper)
127 frame:ClearAllPoints()
128 frame:SetMovable(false)
129 frame:RegisterForDrag()
130 frame:RegisterForClicks()
131 frame:SetBackdrop(nil)
132 frame:SetScale(1)
133 frame:SetAlpha(1)
135 self.used_frames = self.used_frames - 1
136 table.insert(self.free_frames, frame)
139 function QuestHelper:CreateText(parent, text_str, text_size, text_font, r, g, b, a)
140 self.used_text = self.used_text + 1
141 local text = table.remove(self.free_text)
143 if text then
144 text:SetParent(parent)
145 else
146 text = parent:CreateFontString()
149 text:SetFont(text_font or QuestHelper.font.sans or ChatFontNormal:GetFont(), text_size or 12)
150 text:SetDrawLayer("OVERLAY")
151 text:SetJustifyH("CENTER")
152 text:SetJustifyV("MIDDLE")
153 text:SetTextColor(r or 1, g or 1, b or 1, a or 1)
154 text:SetText(text_str or "")
155 text:SetShadowColor(0, 0, 0, 0.3)
156 text:SetShadowOffset(1, -1)
157 text:Show()
159 return text
162 function QuestHelper:ReleaseText(text)
163 assert(type(text) == "table")
164 for i,t in ipairs(self.free_text) do assert(t ~= text) end
166 for key in pairs(text) do
167 -- Remove all keys except 0, which seems to hold some special data.
168 if key ~= 0 then
169 text[key] = nil
173 text:Hide()
174 text:SetParent(UIParent)
175 text:ClearAllPoints()
176 self.used_text = self.used_text - 1
177 table.insert(self.free_text, text)
180 function QuestHelper:CreateTexture(parent, r, g, b, a)
181 self.used_textures = self.used_textures + 1
182 local tex = table.remove(self.free_textures)
184 if tex then
185 tex:SetParent(parent)
186 else
187 tex = parent:CreateTexture()
190 if not tex:SetTexture(r, g, b, a) and
191 not tex:SetTexture("Interface\\Icons\\Temp.blp") then
192 tex:SetTexture(1, 0, 1, 0.5)
195 tex:ClearAllPoints()
196 tex:SetTexCoord(0, 1, 0, 1)
197 tex:SetVertexColor(1, 1, 1, 1)
198 tex:SetDrawLayer("ARTWORK")
199 tex:SetBlendMode("BLEND")
200 tex:SetWidth(12)
201 tex:SetHeight(12)
202 tex:Show()
204 return tex
207 function QuestHelper:CreateIconTexture(parent, id)
208 local icon = self:CreateTexture(parent, "Interface\\AddOns\\QuestHelper\\Art\\Icons.tga")
210 local w, h = 1/8, 1/8
211 local x, y = ((id-1)%8)*w, math.floor((id-1)/8)*h
213 icon:SetTexCoord(x, x+w, y, y+h)
215 return icon
218 function QuestHelper:CreateDotTexture(parent)
219 local icon = self:CreateIconTexture(parent, 13)
220 icon:SetWidth(5)
221 icon:SetHeight(5)
222 icon:SetVertexColor(0, 0, 0, 0.35)
223 return icon
226 function QuestHelper:CreateGlowTexture(parent)
227 local tex = self:CreateTexture(parent, "Interface\\Addons\\QuestHelper\\Art\\Glow.tga")
229 local angle = math.random()*6.28318530717958647692528676655900576839433879875021164
230 local x, y = math.cos(angle)*0.707106781186547524400844362104849039284835937688474036588339869,
231 math.sin(angle)*0.707106781186547524400844362104849039284835937688474036588339869
233 -- Randomly rotate the texture, so they don't all look the same.
234 tex:SetTexCoord(x+0.5, y+0.5, y+0.5, 0.5-x, 0.5-y, x+0.5, 0.5-x, 0.5-y)
235 tex:ClearAllPoints()
237 return tex
240 function QuestHelper:ReleaseTexture(tex)
241 assert(type(tex) == "table")
242 for i,t in ipairs(self.free_textures) do assert(t ~= tex) end
244 for key in pairs(tex) do
245 -- Remove all keys except 0, which seems to hold some special data.
246 if key ~= 0 then
247 tex[key] = nil
251 tex:Hide()
252 tex:SetParent(UIParent)
253 tex:ClearAllPoints()
254 self.used_textures = self.used_textures - 1
255 table.insert(self.free_textures, tex)
258 QuestHelper.recycle_active_cached_tables = {}
259 QuestHelper.recycle_decache_queue = {}
261 function QuestHelper:CacheRegister(obj)
262 if not self.recycle_active_cached_tables[obj] then
263 self.recycle_active_cached_tables[obj] = true
264 table.insert(self.recycle_decache_queue, obj)
268 function QuestHelper:CacheCleanup(obj)
269 local target = self.recycle_decache_queue[1]
271 if not target then return end
272 table.remove(self.recycle_decache_queue, 1)
273 self.recycle_active_cached_tables[target] = nil
275 if target.distance_cache then
276 for k, v in pairs(target.distance_cache) do
277 self:ReleaseTable(v)
279 self:ReleaseTable(target.distance_cache)
280 target.distance_cache = self:CreateTable("objective.distance_cache cleaned")
284 function QuestHelper:DumpCacheData(obj)
285 local caches = 0
286 local cached = 0
287 for k, v in pairs(self.recycle_decache_queue) do
288 caches = caches + 1
289 if v.distance_cache then
290 for q, w in pairs(v.distance_cache) do
291 cached = cached + 1
296 self:TextOut(caches .. " queued caches with a total of " .. cached .. " cached items")