update changes
[QuestHelper.git] / recycle.lua
blob5cc9c08f4e4b33512fc92a15e4a36bf62bbe7de5
1 QuestHelper_File["recycle.lua"] = "Development Version"
3 QuestHelper.used_tables = 0
4 QuestHelper.free_tables = {}
6 local unused_meta = {__index=error, __newindex=error}
8 QuestHelper.used_textures = 0
9 QuestHelper.free_textures = {}
11 QuestHelper.used_text = 0
12 QuestHelper.free_text = {}
14 QuestHelper.used_frames = 0
15 QuestHelper.free_frames = {}
17 -- 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.
18 QuestHelper.recycle_tabletyping = setmetatable({}, {__mode="k"})
20 function QuestHelper:CreateTable(tag)
21 local tbl = next(self.free_tables)
22 self.used_tables = self.used_tables + 1
24 if not tbl then
25 tbl = {}
26 else
27 self.free_tables[tbl] = nil
28 setmetatable(tbl, nil)
29 end
31 --self.recycle_tabletyping[tbl] = tag or "untyped"
32 self.recycle_tabletyping[tbl] = tag or string.gsub(debugstack(2, 1, 1), "\n.*", "")
33 return tbl
34 end
36 function QuestHelper:ReleaseTable(tbl)
37 assert(type(tbl) == "table")
38 assert(not self.free_tables[tbl])
40 for key in pairs(tbl) do
41 tbl[key] = nil
42 end
44 self.used_tables = self.used_tables - 1
45 self.free_tables[setmetatable(tbl, unused_meta)] = true
46 self.recycle_tabletyping[tbl] = nil
47 end
49 function QuestHelper:DumpTableTypeFrequencies()
50 local freq = {}
51 for k, v in pairs(self.recycle_tabletyping) do
52 freq[v] = (freq[v] or 0) + 1
53 end
55 local flist = {}
56 for k, v in pairs(freq) do
57 table.insert(flist, {count=v, name=k})
58 end
60 table.sort(flist, function(a, b) return a.count < b.count end)
62 for k, v in pairs(flist) do
63 self:TextOut(v.count .. ": " .. v.name)
64 end
65 end
67 function QuestHelper:CreateFrame(parent)
68 self.used_frames = self.used_frames + 1
69 local frame = table.remove(self.free_frames)
71 if frame then
72 frame:SetParent(parent)
73 else
74 frame = CreateFrame("Button", string.format("QuestHelperFrame%d",self.used_frames), parent)
75 end
77 frame:SetFrameLevel((parent or UIParent):GetFrameLevel()+1)
78 frame:SetFrameStrata("MEDIUM")
79 frame:Show()
81 return frame
82 end
84 local frameScripts =
86 "OnChar",
87 "OnClick",
88 "OnDoubleClick",
89 "OnDragStart",
90 "OnDragStop",
91 "OnEnter",
92 "OnEvent",
93 "OnHide",
94 "OnKeyDown",
95 "OnKeyUp",
96 "OnLeave",
97 "OnLoad",
98 "OnMouseDown",
99 "OnMouseUp",
100 "OnMouseWheel",
101 "OnReceiveDrag",
102 "OnShow",
103 "OnSizeChanged",
104 "OnUpdate",
105 "PostClick",
106 "PreClick"
109 function QuestHelper:ReleaseFrame(frame)
110 assert(type(frame) == "table")
111 for i,t in ipairs(self.free_frames) do assert(t ~= frame) end
113 for key in pairs(frame) do
114 -- Remove all keys except 0, which seems to hold some special data.
115 if key ~= 0 then
116 frame[key] = nil
120 for i, script in ipairs(frameScripts) do
121 frame:SetScript(script, nil)
124 frame:Hide()
125 frame:SetParent(QuestHelper)
126 frame:ClearAllPoints()
127 frame:SetMovable(false)
128 frame:RegisterForDrag()
129 frame:RegisterForClicks()
130 frame:SetBackdrop(nil)
131 frame:SetScale(1)
132 frame:SetAlpha(1)
134 self.used_frames = self.used_frames - 1
135 table.insert(self.free_frames, frame)
138 function QuestHelper:CreateText(parent, text_str, text_size, text_font, r, g, b, a)
139 self.used_text = self.used_text + 1
140 local text = table.remove(self.free_text)
142 if text then
143 text:SetParent(parent)
144 else
145 text = parent:CreateFontString()
148 text:SetFont(text_font or QuestHelper.font.sans or ChatFontNormal:GetFont(), text_size or 12)
149 text:SetDrawLayer("OVERLAY")
150 text:SetJustifyH("CENTER")
151 text:SetJustifyV("MIDDLE")
152 text:SetTextColor(r or 1, g or 1, b or 1, a or 1)
153 text:SetText(text_str or "")
154 text:SetShadowColor(0, 0, 0, 0.3)
155 text:SetShadowOffset(1, -1)
156 text:Show()
158 return text
161 function QuestHelper:ReleaseText(text)
162 assert(type(text) == "table")
163 for i,t in ipairs(self.free_text) do assert(t ~= text) end
165 for key in pairs(text) do
166 -- Remove all keys except 0, which seems to hold some special data.
167 if key ~= 0 then
168 text[key] = nil
172 text:Hide()
173 text:SetParent(UIParent)
174 text:ClearAllPoints()
175 self.used_text = self.used_text - 1
176 table.insert(self.free_text, text)
179 function QuestHelper:CreateTexture(parent, r, g, b, a)
180 self.used_textures = self.used_textures + 1
181 local tex = table.remove(self.free_textures)
183 if tex then
184 tex:SetParent(parent)
185 else
186 tex = parent:CreateTexture()
189 if not tex:SetTexture(r, g, b, a) and
190 not tex:SetTexture("Interface\\Icons\\Temp.blp") then
191 tex:SetTexture(1, 0, 1, 0.5)
194 tex:ClearAllPoints()
195 tex:SetTexCoord(0, 1, 0, 1)
196 tex:SetVertexColor(1, 1, 1, 1)
197 tex:SetDrawLayer("ARTWORK")
198 tex:SetBlendMode("BLEND")
199 tex:SetWidth(12)
200 tex:SetHeight(12)
201 tex:Show()
203 return tex
206 function QuestHelper:CreateIconTexture(parent, id)
207 local icon = self:CreateTexture(parent, "Interface\\AddOns\\QuestHelper\\Art\\Icons.tga")
209 local w, h = 1/8, 1/8
210 local x, y = ((id-1)%8)*w, math.floor((id-1)/8)*h
212 icon:SetTexCoord(x, x+w, y, y+h)
214 return icon
217 function QuestHelper:CreateDotTexture(parent)
218 local icon = self:CreateIconTexture(parent, 13)
219 icon:SetWidth(5)
220 icon:SetHeight(5)
221 icon:SetVertexColor(0, 0, 0, 0.35)
222 return icon
225 function QuestHelper:CreateGlowTexture(parent)
226 local tex = self:CreateTexture(parent, "Interface\\Addons\\QuestHelper\\Art\\Glow.tga")
228 local angle = math.random()*6.28318530717958647692528676655900576839433879875021164
229 local x, y = math.cos(angle)*0.707106781186547524400844362104849039284835937688474036588339869,
230 math.sin(angle)*0.707106781186547524400844362104849039284835937688474036588339869
232 -- Randomly rotate the texture, so they don't all look the same.
233 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)
234 tex:ClearAllPoints()
236 return tex
239 function QuestHelper:ReleaseTexture(tex)
240 assert(type(tex) == "table")
241 for i,t in ipairs(self.free_textures) do assert(t ~= tex) end
243 for key in pairs(tex) do
244 -- Remove all keys except 0, which seems to hold some special data.
245 if key ~= 0 then
246 tex[key] = nil
250 tex:Hide()
251 tex:SetParent(UIParent)
252 tex:ClearAllPoints()
253 self.used_textures = self.used_textures - 1
254 table.insert(self.free_textures, tex)
257 QuestHelper.recycle_active_cached_tables = {}
258 QuestHelper.recycle_decache_queue = {}
260 function QuestHelper:CacheRegister(obj)
261 if not self.recycle_active_cached_tables[obj] then
262 self.recycle_active_cached_tables[obj] = true
263 table.insert(self.recycle_decache_queue, obj)
267 function QuestHelper:CacheCleanup(obj)
268 local target = self.recycle_decache_queue[1]
270 if not target then return end
271 table.remove(self.recycle_decache_queue, 1)
272 self.recycle_active_cached_tables[target] = nil
274 if target.distance_cache then
275 for k, v in pairs(target.distance_cache) do
276 self:ReleaseTable(v)
278 self:ReleaseTable(target.distance_cache)
279 target.distance_cache = self:CreateTable("objective.distance_cache cleaned")
283 function QuestHelper:DumpCacheData(obj)
284 local caches = 0
285 local cached = 0
286 for k, v in pairs(self.recycle_decache_queue) do
287 caches = caches + 1
288 if v.distance_cache then
289 for q, w in pairs(v.distance_cache) do
290 cached = cached + 1
295 self:TextOut(caches .. " queued caches with a total of " .. cached .. " cached items")