vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | |
2 | local vmajor, vminor = "1", tonumber(string.sub("$Revision: 2706 $", 12, -3)) |
||
3 | local stubvarname = "TekLibStub" |
||
4 | local libvarname = "Metrognome" |
||
5 | |||
6 | |||
7 | -- Check to see if an update is needed |
||
8 | -- if not then just return out now before we do anything |
||
9 | local libobj = getglobal(libvarname) |
||
10 | if libobj and not libobj:NeedsUpgraded(vmajor, vminor) then return end |
||
11 | |||
12 | |||
13 | --------------------------------------------------------------------------- |
||
14 | -- Embedded Library Registration Stub |
||
15 | -- Written by Iriel <iriel@vigilance-committee.org> |
||
16 | -- Version 0.1 - 2006-03-05 |
||
17 | -- Modified by Tekkub <tekkub@gmail.com> |
||
18 | --------------------------------------------------------------------------- |
||
19 | |||
20 | local stubobj = getglobal(stubvarname) |
||
21 | if not stubobj then |
||
22 | stubobj = {} |
||
23 | setglobal(stubvarname, stubobj) |
||
24 | |||
25 | |||
26 | -- Instance replacement method, replace contents of old with that of new |
||
27 | function stubobj:ReplaceInstance(old, new) |
||
28 | for k,v in pairs(old) do old[k]=nil end |
||
29 | for k,v in pairs(new) do old[k]=v end |
||
30 | end |
||
31 | |||
32 | |||
33 | -- Get a new copy of the stub |
||
34 | function stubobj:NewStub(name) |
||
35 | local newStub = {} |
||
36 | self:ReplaceInstance(newStub, self) |
||
37 | newStub.libName = name |
||
38 | newStub.lastVersion = '' |
||
39 | newStub.versions = {} |
||
40 | return newStub |
||
41 | end |
||
42 | |||
43 | |||
44 | -- Get instance version |
||
45 | function stubobj:NeedsUpgraded(vmajor, vminor) |
||
46 | local versionData = self.versions[vmajor] |
||
47 | if not versionData or versionData.minor < vminor then return true end |
||
48 | end |
||
49 | |||
50 | |||
51 | -- Get instance version |
||
52 | function stubobj:GetInstance(version) |
||
53 | if not version then version = self.lastVersion end |
||
54 | local versionData = self.versions[version] |
||
55 | if not versionData then print(string.format("<%s> Cannot find library version: %s", self.libName, version or "")) return end |
||
56 | return versionData.instance |
||
57 | end |
||
58 | |||
59 | |||
60 | -- Register new instance |
||
61 | function stubobj:Register(newInstance) |
||
62 | local version,minor = newInstance:GetLibraryVersion() |
||
63 | self.lastVersion = version |
||
64 | local versionData = self.versions[version] |
||
65 | if not versionData then |
||
66 | -- This one is new! |
||
67 | versionData = { |
||
68 | instance = newInstance, |
||
69 | minor = minor, |
||
70 | old = {}, |
||
71 | } |
||
72 | self.versions[version] = versionData |
||
73 | newInstance:LibActivate(self) |
||
74 | return newInstance |
||
75 | end |
||
76 | -- This is an update |
||
77 | local oldInstance = versionData.instance |
||
78 | local oldList = versionData.old |
||
79 | versionData.instance = newInstance |
||
80 | versionData.minor = minor |
||
81 | local skipCopy = newInstance:LibActivate(self, oldInstance, oldList) |
||
82 | table.insert(oldList, oldInstance) |
||
83 | if not skipCopy then |
||
84 | for i, old in ipairs(oldList) do self:ReplaceInstance(old, newInstance) end |
||
85 | end |
||
86 | return newInstance |
||
87 | end |
||
88 | end |
||
89 | |||
90 | |||
91 | if not libobj then |
||
92 | libobj = stubobj:NewStub(libvarname) |
||
93 | setglobal(libvarname, libobj) |
||
94 | end |
||
95 | |||
96 | local lib = {} |
||
97 | |||
98 | |||
99 | -- Return the library's current version |
||
100 | function lib:GetLibraryVersion() |
||
101 | return vmajor, vminor |
||
102 | end |
||
103 | |||
104 | local compost |
||
105 | -- Activate a new instance of this library |
||
106 | function lib:LibActivate(stub, oldLib, oldList) |
||
107 | local maj, min = self:GetLibraryVersion() |
||
108 | |||
109 | if oldLib then |
||
110 | local omaj, omin = oldLib:GetLibraryVersion() |
||
111 | self.var = oldLib.var |
||
112 | else |
||
113 | self.var = { -- "Local" variables go here |
||
114 | frame = CreateFrame("Frame"), |
||
115 | handlers = {}, |
||
116 | } |
||
117 | self.var.frame:Hide() |
||
118 | self.var.frame.name = "Metrognome Frame" |
||
119 | end |
||
120 | self.var.frame:SetScript("OnUpdate", self.OnUpdate) |
||
121 | self.var.frame.owner = self |
||
122 | compost = CompostLib and CompostLib:GetInstance("compost-1") |
||
123 | -- nil return makes stub do object copy |
||
124 | end |
||
125 | |||
126 | |||
127 | -- Sets up a new OnUpdate handler |
||
128 | -- name - A unique name, if you only need one handler then your addon's name will suffice here |
||
129 | -- func - Function to be called |
||
130 | -- rate (optional but highly reccomended) - The rate (in seconds) at which your function should be called |
||
131 | -- a1-4 (optional) - A args to be passed to func, this is a great place to pass self |
||
132 | -- if a2 is defined then the elapsed time will not be passed to your function! |
||
133 | -- Returns true if you've been registered |
||
134 | function lib:Register(name, func, rate, a1, a2, a3, a4, a5, a6) |
||
135 | assert(name, "Register: No timer name was passed") |
||
136 | assert(func, "Register: No timer function was passed") |
||
137 | if not name or not func or self.var.handlers[name] then return end |
||
138 | local t = compost and compost:Acquire() or {} |
||
139 | t.name, t.func, t.rate = name, func, rate or 0 |
||
140 | t.a1, t.a2, t.a3, t.a4, t.a5, t.a6 = a1, a2, a3, a4, a5, a6 |
||
141 | self.var.handlers[name] = t |
||
142 | return true |
||
143 | end |
||
144 | |||
145 | |||
146 | -- Removes an OnUpdate handler |
||
147 | -- name - the hander you want to remove |
||
148 | -- Returns true if successful |
||
149 | function lib:Unregister(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) |
||
150 | assert(a1, "Unregister: No timer name was passed") |
||
151 | if not self.var.handlers[a1] then return end |
||
152 | if compost then compost:Reclaim(self.var.handlers[a1]) end |
||
153 | self.var.handlers[a1] = nil |
||
154 | if a2 then self:Unregister(a2,a3,a4,a5,a6,a7,a8,a9,a10) |
||
155 | elseif not self:HasHandlers() then self.var.frame:Hide() end |
||
156 | return true |
||
157 | end |
||
158 | |||
159 | |||
160 | -- Begins triggering updates |
||
161 | -- name - the hander you want to start |
||
162 | -- numexec (optional) - Limit the number of times the timer runs |
||
163 | -- Returns true if successful |
||
164 | function lib:Start(name, numexec) |
||
165 | assert(name, "Start: No timer name was passed") |
||
166 | if not self.var.handlers[name] then return end |
||
167 | self.var.handlers[name].limit = numexec |
||
168 | self.var.handlers[name].elapsed = 0 |
||
169 | self.var.handlers[name].running = true |
||
170 | self.var.frame:Show() |
||
171 | return true |
||
172 | end |
||
173 | |||
174 | |||
175 | -- Stops triggering updates |
||
176 | -- name - the hander you want to stop |
||
177 | -- Returns true if successful |
||
178 | function lib:Stop(name) |
||
179 | assert(name, "Stop: No timer name was passed") |
||
180 | if not self.var.handlers[name] then return end |
||
181 | self.var.handlers[name].running = nil |
||
182 | self.var.handlers[name].limit = nil |
||
183 | if not self:HasHandlers() then self.var.frame:Hide() end |
||
184 | return true |
||
185 | end |
||
186 | |||
187 | |||
188 | -- Changes the execution rate of a timer. |
||
189 | -- This will also reset the timer's elapsed time to 0 |
||
190 | -- name - The timer you wish to change |
||
191 | -- newrate (optional)- The new exec rate, in seconds. If nil or 0 default OnUpdate timing will be used |
||
192 | -- n#,r# (optional) - Recusivly calls ChangeRate to allow you to set up to 5 rates in one call. |
||
193 | -- Returns true if successful |
||
194 | function lib:ChangeRate(name, newrate, n2,r2,n3,r3,n4,r4,n5,r5) |
||
195 | assert(name, "ChangeRate: No timer name was passed") |
||
196 | if not self.var.handlers[name] then |
||
197 | if n2 then return nil, self:ChangeRate(n2,r2,n3,r3,n4,r4,n5,r5) |
||
198 | else return end |
||
199 | end |
||
200 | |||
201 | local t = self.var.handlers[name] |
||
202 | t.elapsed = 0 |
||
203 | t.rate = newrate or 0 |
||
204 | if n2 then return true, self:ChangeRate(n2,r2,n3,r3,n4,r4,n5,r5) |
||
205 | else return true end |
||
206 | end |
||
207 | |||
208 | |||
209 | -- Resets the profile stats for a timer |
||
210 | -- Accepts up to 10 timer names to clear |
||
211 | function lib:ClearStats(name, n2, n3, n4, n5, n6, n7, n8, n9, n10) |
||
212 | assert(name, "ChangeRate: No timer name was passed") |
||
213 | if not self.var.handlers[name] then |
||
214 | if n2 then return nil, self:ClearStats(n2,r2,n3,r3,n4,r4,n5,r5) |
||
215 | else return end |
||
216 | end |
||
217 | |||
218 | local t = self.var.handlers[name] |
||
219 | t.count, t.mem, t.time = 0, 0, 0 |
||
220 | if n2 then return true, self:ClearStats(n2,r2,n3,r3,n4,r4,n5,r5) |
||
221 | else return true end |
||
222 | end |
||
223 | |||
224 | |||
225 | -- Query a timer's status |
||
226 | -- Args: name - the schedule you wish to look up |
||
227 | -- Returns: registered - true if a schedule exists with this name |
||
228 | -- rate - the registered rate, if defined |
||
229 | -- running - true if this schedule is currently running |
||
230 | function lib:Status(name) |
||
231 | assert(name, "Status: No timer name was passed") |
||
232 | if not self.var.handlers[name] then return end |
||
233 | return true, self.var.handlers[name].rate, self.var.handlers[name].running, self.var.handlers[name].limit |
||
234 | end |
||
235 | |||
236 | |||
237 | -- Query a timer's profile info |
||
238 | -- Args: name - the schedule you wish to look up |
||
239 | -- Returns: mem - the total memory consumed by the timer's execution (in KiB) |
||
240 | -- time - the total time consumed by the timer's execution (in sec) |
||
241 | -- count - the number of times the timer has been triggered |
||
242 | -- rate - the rate at which the timer triggers (0 means the default OnUpdate rate) |
||
243 | function lib:Profile(name) |
||
244 | assert(name, "Profile: No timer name was passed") |
||
245 | if not self.var.handlers[name] then return end |
||
246 | local t = self.var.handlers[name] |
||
247 | return t.mem, t.time, t.count, t.rate |
||
248 | end |
||
249 | |||
250 | |||
251 | function lib:OnUpdate() |
||
252 | for i,v in pairs(this.owner.var.handlers) do |
||
253 | if v.running then |
||
254 | v.elapsed = v.elapsed + arg1 |
||
255 | if v.elapsed >= v.rate then |
||
256 | local mem, time = gcinfo(), GetTime() |
||
257 | v.func(v.a1 or v.arg, v.a2 or v.elapsed, v.a3, v.a4, v.a5, v.a6) |
||
258 | mem, time = gcinfo() - mem, GetTime() - time |
||
259 | if mem >= 0 then v.mem, v.time, v.count = (v.mem or 0) + mem, (v.time or 0) + time, (v.count or 0) + 1 end |
||
260 | v.elapsed = 0 |
||
261 | if v.limit then v.limit = v.limit - 1 end |
||
262 | if v.limit and v.limit <= 0 then this.owner:Stop(i) end |
||
263 | end |
||
264 | end |
||
265 | end |
||
266 | end |
||
267 | |||
268 | |||
269 | function lib:HasHandlers() |
||
270 | for i in pairs(self.var.handlers) do return true end |
||
271 | end |
||
272 | |||
273 | |||
274 | -------------------------------- |
||
275 | -- Load this bitch! -- |
||
276 | -------------------------------- |
||
277 | libobj:Register(lib) |