Mercurial > wow > reaction
comparison Overlay.lua @ 245:65f2805957a0
No real reason to store some of the code in a subdirectory.
author | Flick |
---|---|
date | Sat, 26 Mar 2011 12:35:08 -0700 |
parents | classes/Overlay.lua@c24ac8ee1e45 |
children | 2897480842dd |
comparison
equal
deleted
inserted
replaced
244:f255cd69e890 | 245:65f2805957a0 |
---|---|
1 local addonName, addonTable = ... | |
2 local ReAction = addonTable.ReAction | |
3 local L = ReAction.L | |
4 local LKB = ReAction.LKB | |
5 local CreateFrame = CreateFrame | |
6 local InCombatLockdown = InCombatLockdown | |
7 local floor = math.floor | |
8 local min = math.min | |
9 local format = string.format | |
10 local GameTooltip = GameTooltip | |
11 local Bar = ReAction.Bar | |
12 local GetSize = Bar.GetSize | |
13 local SetSize = Bar.SetSize | |
14 local GetButtonSize = Bar.GetButtonSize | |
15 local GetButtonGrid = Bar.GetButtonGrid | |
16 local SetButtonSize = Bar.SetButtonSize | |
17 local SetButtonGrid = Bar.SetButtonGrid | |
18 local ApplyAnchor = Bar.ApplyAnchor | |
19 local GameTooltipTextRight1 = GameTooltipTextRight1 | |
20 local GameTooltipTextRight2 = GameTooltipTextRight2 | |
21 local GameTooltipTextRight3 = GameTooltipTextRight3 | |
22 | |
23 -- | |
24 -- Wrap some of the bar manipulators to make them state-aware | |
25 -- | |
26 local function SetAnchor( bar, point, frame, relPoint, x, y ) | |
27 local state = bar:GetSecureState() | |
28 if state then | |
29 local anchorstate = bar:GetStateProperty(state, "anchorEnable") | |
30 if anchorstate then | |
31 bar:SetStateProperty(state, "anchorFrame", frame) | |
32 bar:SetStateProperty(state, "anchorPoint", point) | |
33 bar:SetStateProperty(state, "anchorRelPoint", relPoint) | |
34 bar:SetStateProperty(state, "anchorX", x or 0) | |
35 bar:SetStateProperty(state, "anchorY", y or 0) | |
36 bar:SetAnchor(bar:GetAnchor()) | |
37 return | |
38 end | |
39 end | |
40 bar:SetAnchor(point, frame, relPoint, x, y) | |
41 end | |
42 | |
43 local function GetStateScale( bar ) | |
44 local state = bar:GetSecureState() | |
45 if state and bar:GetStateProperty(state, "enableScale") then | |
46 return bar:GetStateProperty(state, "scale") | |
47 end | |
48 end | |
49 | |
50 local function SetStateScale( bar, scale ) | |
51 local state = bar:GetSecureState() | |
52 if state and bar:GetStateProperty(state, "enableScale") then | |
53 bar:SetStateProperty(state, "scale", scale) | |
54 end | |
55 end | |
56 | |
57 | |
58 -- | |
59 -- Bar config overlay | |
60 -- | |
61 | |
62 local function GetNormalTextColor() | |
63 return 1.0, 1.0, 1.0, 1.0 | |
64 end | |
65 | |
66 local function GetAnchoredTextColor() | |
67 return 1.0, 1.0, 1.0, 1.0 | |
68 end | |
69 | |
70 local function GetNormalBgColor() | |
71 return 0.7, 0.7, 1.0, 0.3 | |
72 end | |
73 | |
74 local function GetAnchoredBgColor() | |
75 return 0.9, 0.2, 0.7, 0.3 | |
76 end | |
77 | |
78 local function StoreSize(bar) | |
79 local f = bar:GetFrame() | |
80 SetSize( bar, f:GetWidth(), f:GetHeight() ) | |
81 end | |
82 | |
83 local function StoreExtents(bar) | |
84 local f = bar:GetFrame() | |
85 local p, fr, rp, x, y = f:GetPoint(1) | |
86 fr = fr and fr:GetName() or "UIParent" | |
87 SetAnchor( bar, p, fr, rp, x, y ) | |
88 SetSize( bar, f:GetWidth(), f:GetHeight() ) | |
89 end | |
90 | |
91 local function RecomputeButtonSize(bar) | |
92 local w, h = GetSize(bar) | |
93 local bw, bh = GetButtonSize(bar) | |
94 local r, c, s = GetButtonGrid(bar) | |
95 | |
96 local scaleW = (floor(w/c) - s) / bw | |
97 local scaleH = (floor(h/r) - s) / bh | |
98 local scale = min(scaleW, scaleH) | |
99 | |
100 SetButtonSize(bar, scale * bw, scale * bh, s) | |
101 end | |
102 | |
103 local function ComputeBarScale(bar, overlay) | |
104 local w, h = overlay:GetWidth() - 8, overlay:GetHeight() - 8 | |
105 local bw, bh = GetButtonSize(bar) | |
106 local r, c, s = GetButtonGrid(bar) | |
107 | |
108 local scaleW = w / (c*(bw+s)) | |
109 local scaleH = h / (r*(bh+s)) | |
110 local scale = min(scaleW, scaleH) | |
111 | |
112 if scale > 2.5 then | |
113 scale = 2.5 | |
114 elseif scale < 0.25 then | |
115 scale = 0.25 | |
116 end | |
117 | |
118 return scale | |
119 end | |
120 | |
121 local function RecomputeButtonSpacing(bar) | |
122 local w, h = GetSize(bar) | |
123 local bw, bh = GetButtonSize(bar) | |
124 local r, c, s = GetButtonGrid(bar) | |
125 | |
126 SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh)) | |
127 end | |
128 | |
129 local function RecomputeGrid(bar) | |
130 local w, h = GetSize(bar) | |
131 local bw, bh = GetButtonSize(bar) | |
132 local r, c, s = GetButtonGrid(bar) | |
133 | |
134 SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s) | |
135 end | |
136 | |
137 local function ClampToButtons(bar) | |
138 local bw, bh = GetButtonSize(bar) | |
139 local r, c, s = GetButtonGrid(bar) | |
140 SetSize(bar, (bw+s)*c + 1, (bh+s)*r + 1) | |
141 end | |
142 | |
143 local function HideGameTooltip() | |
144 GameTooltip:Hide() | |
145 end | |
146 | |
147 local anchorInside = { inside = true } | |
148 local anchorOutside = { outside = true } | |
149 local edges = { "BOTTOM", "TOP", "LEFT", "RIGHT" } | |
150 local oppositeEdges = { | |
151 TOP = "BOTTOM", | |
152 BOTTOM = "TOP", | |
153 LEFT = "RIGHT", | |
154 RIGHT = "LEFT" | |
155 } | |
156 local pointsOnEdge = { | |
157 BOTTOM = { "BOTTOM", "BOTTOMLEFT", "BOTTOMRIGHT", }, | |
158 TOP = { "TOP", "TOPLEFT", "TOPRIGHT", }, | |
159 RIGHT = { "RIGHT", "BOTTOMRIGHT", "TOPRIGHT", }, | |
160 LEFT = { "LEFT", "BOTTOMLEFT", "TOPLEFT", }, | |
161 } | |
162 local edgeSelector = { | |
163 BOTTOM = 1, -- select x of x,y | |
164 TOP = 1, -- select x of x,y | |
165 LEFT = 2, -- select y of x,y | |
166 RIGHT = 2, -- select y of x,y | |
167 } | |
168 local snapPoints = { | |
169 [anchorOutside] = { | |
170 BOTTOMLEFT = {"BOTTOMRIGHT","TOPLEFT","TOPRIGHT"}, | |
171 BOTTOM = {"TOP"}, | |
172 BOTTOMRIGHT = {"BOTTOMLEFT","TOPRIGHT","TOPLEFT"}, | |
173 RIGHT = {"LEFT"}, | |
174 TOPRIGHT = {"TOPLEFT","BOTTOMRIGHT","BOTTOMLEFT"}, | |
175 TOP = {"BOTTOM"}, | |
176 TOPLEFT = {"TOPRIGHT","BOTTOMLEFT","BOTTOMRIGHT"}, | |
177 LEFT = {"RIGHT"}, | |
178 CENTER = {"CENTER"} | |
179 }, | |
180 [anchorInside] = { | |
181 BOTTOMLEFT = {"BOTTOMLEFT"}, | |
182 BOTTOM = {"BOTTOM"}, | |
183 BOTTOMRIGHT = {"BOTTOMRIGHT"}, | |
184 RIGHT = {"RIGHT"}, | |
185 TOPRIGHT = {"TOPRIGHT"}, | |
186 TOP = {"TOP"}, | |
187 TOPLEFT = {"TOPLEFT"}, | |
188 LEFT = {"LEFT"}, | |
189 CENTER = {"CENTER"} | |
190 } | |
191 } | |
192 local insidePointOffsetFuncs = { | |
193 BOTTOMLEFT = function(x, y) return x, y end, | |
194 BOTTOM = function(x, y) return 0, y end, | |
195 BOTTOMRIGHT = function(x, y) return -x, y end, | |
196 RIGHT = function(x, y) return -x, 0 end, | |
197 TOPRIGHT = function(x, y) return -x, -y end, | |
198 TOP = function(x, y) return 0, -y end, | |
199 TOPLEFT = function(x, y) return x, -y end, | |
200 LEFT = function(x, y) return x, 0 end, | |
201 CENTER = function(x, y) return x, y end, | |
202 } | |
203 local pointCoordFuncs = { | |
204 BOTTOMLEFT = function(f) return f:GetLeft(), f:GetBottom() end, | |
205 BOTTOM = function(f) return nil, f:GetBottom() end, | |
206 BOTTOMRIGHT = function(f) return f:GetRight(), f:GetBottom() end, | |
207 RIGHT = function(f) return f:GetRight(), nil end, | |
208 TOPRIGHT = function(f) return f:GetRight(), f:GetTop() end, | |
209 TOP = function(f) return nil, f:GetTop() end, | |
210 TOPLEFT = function(f) return f:GetLeft(), f:GetTop() end, | |
211 LEFT = function(f) return f:GetLeft(), nil end, | |
212 CENTER = function(f) return f:GetCenter() end, | |
213 } | |
214 local edgeBoundsFuncs = { | |
215 BOTTOM = function(f) return f:GetLeft(), f:GetRight() end, | |
216 LEFT = function(f) return f:GetBottom(), f:GetTop() end | |
217 } | |
218 edgeBoundsFuncs.TOP = edgeBoundsFuncs.BOTTOM | |
219 edgeBoundsFuncs.RIGHT = edgeBoundsFuncs.LEFT | |
220 local cornerTexCoords = { | |
221 -- ULx, ULy, LLx, LLy, URx, URy, LRx, LRy | |
222 TOPLEFT = { 1, 1, 1, 0, 0, 1, 0, 0 }, | |
223 TOPRIGHT = { 1, 0, 0, 0, 1, 1, 0, 1 }, | |
224 BOTTOMLEFT = { 0, 1, 1, 1, 0, 0, 1, 0 }, | |
225 BOTTOMRIGHT = { 0, 0, 0, 1, 1, 0, 1, 1 }, | |
226 } | |
227 | |
228 -- Returns absolute coordinates x,y of the named point 'p' of frame 'f' | |
229 local function GetPointCoords( f, p ) | |
230 local x, y = pointCoordFuncs[p](f) | |
231 if not(x and y) then | |
232 local cx, cy = f:GetCenter() | |
233 x = x or cx | |
234 y = y or cy | |
235 end | |
236 return x, y | |
237 end | |
238 | |
239 | |
240 -- Returns true if frame 'f1' can be anchored to frame 'f2' | |
241 local function CheckAnchorable( f1, f2 ) | |
242 -- can't anchor a frame to itself or to nil | |
243 if f1 == f2 or f2 == nil then | |
244 return false | |
245 end | |
246 | |
247 -- can always anchor to UIParent | |
248 if f2 == UIParent then | |
249 return true | |
250 end | |
251 | |
252 -- also can't do circular anchoring of frames | |
253 -- walk the anchor chain, which generally shouldn't be that expensive | |
254 -- (who nests draggables that deep anyway?) | |
255 for i = 1, f2:GetNumPoints() do | |
256 local _, f = f2:GetPoint(i) | |
257 if not f then f = f2:GetParent() end | |
258 return CheckAnchorable(f1,f) | |
259 end | |
260 | |
261 return true | |
262 end | |
263 | |
264 -- Returns true if frames f1 and f2 specified edges overlap | |
265 local function CheckEdgeOverlap( f1, f2, e ) | |
266 local l1, u1 = edgeBoundsFuncs[e](f1) | |
267 local l2, u2 = edgeBoundsFuncs[e](f2) | |
268 return l1 <= l2 and l2 <= u1 or l2 <= l1 and l1 <= u2 | |
269 end | |
270 | |
271 -- Returns true if point p1 on frame f1 overlaps edge e2 on frame f2 | |
272 local function CheckPointEdgeOverlap( f1, p1, f2, e2 ) | |
273 local l, u = edgeBoundsFuncs[e2](f2) | |
274 local x, y = GetPointCoords(f1,p1) | |
275 x = select(edgeSelector[e2], x, y) | |
276 return l <= x and x <= u | |
277 end | |
278 | |
279 -- Returns the distance between corresponding edges. It is | |
280 -- assumed that the passed in edges e1 and e2 are the same or opposites | |
281 local function GetEdgeDistance( f1, f2, e1, e2 ) | |
282 local x1, y1 = pointCoordFuncs[e1](f1) | |
283 local x2, y2 = pointCoordFuncs[e2](f2) | |
284 return math.abs((x1 or y1) - (x2 or y2)) | |
285 end | |
286 | |
287 local globalSnapTargets = { [UIParent] = anchorInside } | |
288 | |
289 local function GetClosestFrameEdge(f1,f2,a) | |
290 local dist, edge, opp | |
291 if f2:IsVisible() and CheckAnchorable(f1,f2) then | |
292 for _, e in pairs(edges) do | |
293 local o = a.inside and e or oppositeEdges[e] | |
294 if CheckEdgeOverlap(f1,f2,e) then | |
295 local d = GetEdgeDistance(f1, f2, e, o) | |
296 if not dist or (d < dist) then | |
297 dist, edge, opp = d, e, o | |
298 end | |
299 end | |
300 end | |
301 end | |
302 return dist, edge, opp | |
303 end | |
304 | |
305 local function GetClosestVisibleEdge( f ) | |
306 local r, o, e1, e2 | |
307 local a = anchorOutside | |
308 for _, b in ReAction:IterateBars() do | |
309 local d, e, opp = GetClosestFrameEdge(f,b:GetFrame(),a) | |
310 if d and (not r or d < r) then | |
311 r, o, e1, e2 = d, b:GetFrame(), e, opp | |
312 end | |
313 end | |
314 for f2, a2 in pairs(globalSnapTargets) do | |
315 local d, e, opp = GetClosestFrameEdge(f,f2,a2) | |
316 if d and (not r or d < r) then | |
317 r, o, e1, e2, a = d, f2, e, opp, a2 | |
318 end | |
319 end | |
320 return o, e1, e2, a | |
321 end | |
322 | |
323 local function GetClosestVisiblePoint(f1) | |
324 local f2, e1, e2, a = GetClosestVisibleEdge(f1) | |
325 if f2 then | |
326 local rsq, p, rp, x, y | |
327 -- iterate pointsOnEdge in order and use < to prefer edge centers to corners | |
328 for _, p1 in ipairs(pointsOnEdge[e1]) do | |
329 if CheckPointEdgeOverlap(f1,p1,f2,e2) then | |
330 for _, p2 in pairs(snapPoints[a][p1]) do | |
331 local x1, y1 = GetPointCoords(f1,p1) | |
332 local x2, y2 = GetPointCoords(f2,p2) | |
333 local dx = x1 - x2 | |
334 local dy = y1 - y2 | |
335 local rsq2 = dx*dx + dy*dy | |
336 if not rsq or rsq2 < rsq then | |
337 rsq, p, rp, x, y = rsq2, p1, p2, dx, dy | |
338 end | |
339 end | |
340 end | |
341 end | |
342 return f2, p, rp, x, y | |
343 end | |
344 end | |
345 | |
346 local function GetClosestPointSnapped(f1, rx, ry, xOff, yOff) | |
347 local o, p, rp, x, y = GetClosestVisiblePoint(f1) | |
348 local s = false | |
349 | |
350 local insideOffsetFunc = p and insidePointOffsetFuncs[p] | |
351 local coordFunc = p and pointCoordFuncs[p] | |
352 if not insideOffsetFunc or not coordFunc then | |
353 return | |
354 end | |
355 | |
356 local sx, sy = insideOffsetFunc(xOff or 0, yOff or 0) | |
357 local xx, yy = coordFunc(f1) | |
358 if xx and yy then | |
359 if math.abs(x) <= rx then | |
360 if math.abs(y) <= ry then | |
361 x = sx | |
362 y = sy | |
363 s = true | |
364 elseif CheckEdgeOverlap(f1,o,"LEFT") then | |
365 x = sx | |
366 s = true | |
367 end | |
368 elseif math.abs(y) <= ry and CheckEdgeOverlap(f1,o,"TOP") then | |
369 y = sy | |
370 s = true | |
371 end | |
372 elseif xx then | |
373 if math.abs(x) <= rx then | |
374 x = sx | |
375 s = true | |
376 if math.abs(y) <= ry then | |
377 y = sy | |
378 end | |
379 end | |
380 elseif yy then | |
381 if math.abs(y) <= ry then | |
382 y = sy | |
383 s = true | |
384 if math.abs(x) <= rx then | |
385 x = sx | |
386 end | |
387 end | |
388 end | |
389 | |
390 -- correct for some Lua oddities with doubles | |
391 if x == -0 then x = 0 end | |
392 if y == -0 then y = 0 end | |
393 | |
394 if s then | |
395 return o, p, rp, math.floor(x), math.floor(y) | |
396 end | |
397 end | |
398 | |
399 local function CreateSnapIndicator() | |
400 local si = CreateFrame("Frame",nil,UIParent) | |
401 si:SetFrameStrata("HIGH") | |
402 si:SetHeight(16) | |
403 si:SetWidth(16) | |
404 local tex = si:CreateTexture() | |
405 tex:SetAllPoints() | |
406 tex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock") | |
407 tex:SetBlendMode("ADD") | |
408 tex:SetDrawLayer("OVERLAY") | |
409 return si | |
410 end | |
411 | |
412 local si1 = CreateSnapIndicator() | |
413 local si2 = CreateSnapIndicator() | |
414 | |
415 local function DisplaySnapIndicator( f, rx, ry, xOff, yOff ) | |
416 local o, p, rp, x, y, snap = GetClosestPointSnapped(f, rx, ry, xOff, yOff) | |
417 if o then | |
418 si1:ClearAllPoints() | |
419 si2:ClearAllPoints() | |
420 si1:SetPoint("CENTER", f, p, 0, 0) | |
421 local xx, yy = pointCoordFuncs[rp](o) | |
422 x = math.abs(x) <=rx and xx and 0 or x | |
423 y = math.abs(y) <=ry and yy and 0 or y | |
424 si2:SetPoint("CENTER", o, rp, x, y) | |
425 si1:Show() | |
426 si2:Show() | |
427 else | |
428 if si1:IsVisible() then | |
429 si1:Hide() | |
430 si2:Hide() | |
431 end | |
432 end | |
433 return o, p | |
434 end | |
435 | |
436 local function HideSnapIndicator() | |
437 if si1:IsVisible() then | |
438 si1:Hide() | |
439 si2:Hide() | |
440 end | |
441 end | |
442 | |
443 local function UpdateLabelString(overlay) | |
444 local label = overlay.labelString | |
445 if label then | |
446 local name = overlay.labelName | |
447 if name and overlay.labelSubtext then | |
448 name = format("%s (%s)", name, overlay.labelSubtext) | |
449 end | |
450 label:SetText(name or "") | |
451 end | |
452 end | |
453 | |
454 local function CreateControls(bar) | |
455 local f = bar:GetFrame() | |
456 | |
457 f:SetMovable(true) | |
458 f:SetResizable(true) | |
459 | |
460 -- child of UIParent so that alpha and scale doesn't propagate to it | |
461 local overlay = CreateFrame("Button", nil, UIParent) | |
462 overlay:EnableMouse(true) | |
463 overlay:SetFrameLevel(10) -- set it above the buttons | |
464 overlay:SetPoint("TOPLEFT", f, "TOPLEFT", -4, 4) | |
465 overlay:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 4, -4) | |
466 overlay:SetBackdrop({ | |
467 edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", | |
468 tile = true, | |
469 tileSize = 16, | |
470 edgeSize = 16, | |
471 insets = { left = 0, right = 0, top = 0, bottom = 0 }, | |
472 }) | |
473 | |
474 -- textures | |
475 local bgTex = overlay:CreateTexture(nil,"BACKGROUND") | |
476 bgTex:SetTexture(0.7,0.7,1.0,0.2) | |
477 bgTex:SetPoint("TOPLEFT",4,-4) | |
478 bgTex:SetPoint("BOTTOMRIGHT",-4,4) | |
479 local hTex = overlay:CreateTexture(nil,"HIGHLIGHT") | |
480 hTex:SetTexture(0.7,0.7,1.0,0.2) | |
481 hTex:SetPoint("TOPLEFT",4,-4) | |
482 hTex:SetPoint("BOTTOMRIGHT",-4,4) | |
483 hTex:SetBlendMode("ADD") | |
484 local aTex = overlay:CreateTexture(nil,"ARTWORK") | |
485 aTex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock") | |
486 aTex:SetWidth(16) | |
487 aTex:SetHeight(16) | |
488 aTex:Hide() | |
489 | |
490 -- label | |
491 local label = overlay:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") | |
492 label:SetAllPoints() | |
493 label:SetJustifyH("CENTER") | |
494 label:SetShadowColor(0,0,0,1) | |
495 label:SetShadowOffset(3,-3) | |
496 label:SetTextColor(GetNormalTextColor()) | |
497 label:SetText(bar:GetName()) | |
498 label:Show() | |
499 overlay.labelString = label | |
500 overlay.labelName = bar:GetName() | |
501 | |
502 local function UpdateAnchorDecoration() | |
503 local point, anchor, relPoint, x, y = f:GetPoint(1) | |
504 if point then | |
505 local ofsx, ofsy = insidePointOffsetFuncs[point](x,y) | |
506 if (anchor and anchor ~= UIParent) or (ofsx == 0 and ofsy == 0) then | |
507 bgTex:SetTexture( GetAnchoredBgColor() ) | |
508 hTex:SetTexture( GetAnchoredBgColor() ) | |
509 label:SetTextColor( GetAnchoredTextColor() ) | |
510 aTex:ClearAllPoints() | |
511 aTex:SetPoint(point) | |
512 aTex:Show() | |
513 return | |
514 end | |
515 end | |
516 bgTex:SetTexture( GetNormalBgColor() ) | |
517 hTex:SetTexture( GetNormalBgColor() ) | |
518 label:SetTextColor( GetNormalTextColor() ) | |
519 aTex:Hide() | |
520 end | |
521 | |
522 local function StopResize() | |
523 f:StopMovingOrSizing() | |
524 f.isMoving = false | |
525 f:SetScript("OnUpdate",nil) | |
526 StoreSize(bar) | |
527 ClampToButtons(bar) | |
528 ReAction:RefreshEditor() | |
529 end | |
530 | |
531 local function CornerUpdate() | |
532 local bw, bh = GetButtonSize(bar) | |
533 local r, c, s = GetButtonGrid(bar) | |
534 local ss = GetStateScale(bar) | |
535 if IsShiftKeyDown() then | |
536 if ss then | |
537 f:SetMinResize( ((s+bw)*c*0.25)/ss, ((s+bh)*r*0.25)/ss ) | |
538 f:SetMaxResize( ((s+bw)*c*2.5 + 1)/ss, ((s+bh)*r*2.5 + 1)/ss ) | |
539 scale = ComputeBarScale(bar, overlay) | |
540 else | |
541 f:SetMinResize( (s+12)*c+1, (s+12)*r+1 ) | |
542 f:SetMaxResize( (s+128)*c+1, (s+128)*r+1 ) | |
543 RecomputeButtonSize(bar) | |
544 end | |
545 elseif not ss and IsAltKeyDown() then | |
546 f:SetMinResize( bw*c, bh*r ) | |
547 f:SetMaxResize( 2*bw*c, 2*bh*r ) | |
548 RecomputeButtonSpacing(bar) | |
549 else | |
550 f:SetMinResize( bw+s+1, bh+s+1 ) | |
551 f:SetMaxResize( 50*(bw+s)+1, 50*(bh+s)+1 ) | |
552 RecomputeGrid(bar) | |
553 end | |
554 GameTooltipTextRight2:SetText(format("%d x %d",r,c)) | |
555 | |
556 local ss = GetStateScale(bar) | |
557 if ss then | |
558 GameTooltipTextRight4:SetText(format("%d%%", scale*100)) | |
559 else | |
560 local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh) | |
561 GameTooltipTextRight3:SetText(size) | |
562 GameTooltipTextRight4:SetText(tostring(s)) | |
563 end | |
564 end | |
565 | |
566 -- corner drag handles | |
567 for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do | |
568 local corner = CreateFrame("Frame",nil,overlay) | |
569 corner:EnableMouse(true) | |
570 corner:SetWidth(16) | |
571 corner:SetHeight(16) | |
572 corner:SetPoint(point) | |
573 | |
574 local tex = corner:CreateTexture(nil,"HIGHLIGHT") | |
575 tex:SetTexture("Interface\\AddOns\\ReAction\\img\\corner") | |
576 tex:SetTexCoord(unpack(cornerTexCoords[point])) | |
577 tex:SetBlendMode("ADD") | |
578 tex:SetAlpha(0.6) | |
579 tex:SetAllPoints() | |
580 | |
581 corner:SetScript("OnMouseDown", | |
582 function(_,btn) | |
583 f:SetScript("OnUpdate", CornerUpdate) | |
584 f:StartSizing(point) | |
585 end | |
586 ) | |
587 corner:SetScript("OnMouseUp", | |
588 function() | |
589 local ss = GetStateScale(bar) | |
590 if ss then | |
591 SetStateScale(bar, ComputeBarScale(bar, overlay)) | |
592 end | |
593 StopResize() | |
594 end) | |
595 corner:SetScript("OnEnter", | |
596 function() | |
597 local bw, bh = GetButtonSize(bar) | |
598 local r, c, s = bar:GetButtonGrid() | |
599 local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh) | |
600 local ss = GetStateScale(bar) | |
601 local state = bar:GetSecureState() | |
602 GameTooltip:SetOwner(f, "ANCHOR_"..point) | |
603 if ss then | |
604 GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state)) | |
605 else | |
606 GameTooltip:AddLine(bar:GetName()) | |
607 end | |
608 GameTooltip:AddDoubleLine(format("|cffcccccc%s|r %s",L["Drag"],L["to add/remove buttons:"]), format("%d x %d",r,c)) | |
609 if ss then | |
610 GameTooltip:AddLine(L["State Scale Override"]) | |
611 GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to change scale:"]), format("%d%%", bar:GetStateProperty(state,"scale")*100)) | |
612 else | |
613 GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to resize buttons:"]), tostring(floor(size))) | |
614 GameTooltip:AddDoubleLine(format("|cff0033cc%s|r %s",L["Hold Alt"], L["to change spacing:"]), tostring(floor(s))) | |
615 end | |
616 GameTooltip:Show() | |
617 end | |
618 ) | |
619 corner:SetScript("OnLeave", | |
620 function() | |
621 GameTooltip:Hide() | |
622 f:SetScript("OnUpdate",nil) | |
623 end | |
624 ) | |
625 end | |
626 | |
627 overlay:RegisterForDrag("LeftButton") | |
628 overlay:RegisterForClicks("RightButtonUp") | |
629 | |
630 overlay:SetScript("OnDragStart", | |
631 function() | |
632 f:StartMoving() | |
633 f.isMoving = true | |
634 local w,h = bar:GetButtonSize() | |
635 f:ClearAllPoints() | |
636 UpdateAnchorDecoration() | |
637 f:SetScript("OnUpdate", function() | |
638 if IsShiftKeyDown() then | |
639 local f, p = DisplaySnapIndicator(f,w,h) | |
640 else | |
641 HideSnapIndicator() | |
642 end | |
643 end) | |
644 end | |
645 ) | |
646 | |
647 local function UpdateDragTooltip() | |
648 GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT") | |
649 local ss = GetStateScale(bar) | |
650 local state = bar:GetSecureState() | |
651 if ss then | |
652 GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state)) | |
653 else | |
654 GameTooltip:AddLine(bar:GetName()) | |
655 end | |
656 GameTooltip:AddLine(format("|cffcccccc%s|r %s",L["Drag"],L["to move"])) | |
657 GameTooltip:AddLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to anchor to nearby frames"])) | |
658 GameTooltip:AddLine(format("|cff00cccc%s|r %s",L["Right-click"],L["for options..."])) | |
659 local point, frame, relpoint, x, y = bar:GetFrame():GetPoint(1) | |
660 if point then | |
661 local ofsx, ofsy = insidePointOffsetFuncs[point](x,y) | |
662 if (frame and frame ~= UIParent) or (ofsx == 0 and ofsy == 0) then | |
663 frame = frame or UIParent | |
664 GameTooltip:AddLine(format("%s <%s>",L["Currently anchored to"],frame:GetName())) | |
665 end | |
666 end | |
667 GameTooltip:Show() | |
668 end | |
669 | |
670 overlay:SetScript("OnDragStop", | |
671 function() | |
672 f:StopMovingOrSizing() | |
673 f.isMoving = false | |
674 f:SetScript("OnUpdate",nil) | |
675 | |
676 if IsShiftKeyDown() then | |
677 local w, h = bar:GetButtonSize() | |
678 local a, p, rp, x, y = GetClosestPointSnapped(f,w,h) | |
679 if a then | |
680 f:ClearAllPoints() | |
681 f:SetPoint(p,a,rp,x,y) | |
682 end | |
683 HideSnapIndicator() | |
684 end | |
685 | |
686 StoreExtents(bar) | |
687 ReAction:RefreshEditor() | |
688 UpdateDragTooltip() | |
689 UpdateAnchorDecoration() | |
690 end | |
691 ) | |
692 | |
693 overlay:SetScript("OnEnter", | |
694 function() | |
695 UpdateDragTooltip() | |
696 end | |
697 ) | |
698 | |
699 overlay:SetScript("OnLeave", HideGameTooltip) | |
700 | |
701 overlay:SetScript("OnClick", | |
702 function() | |
703 ReAction:ShowEditor(bar) | |
704 end | |
705 ) | |
706 | |
707 function overlay:RefreshControls() | |
708 UpdateAnchorDecoration() | |
709 end | |
710 | |
711 overlay:SetScript("OnShow", overlay.RefreshControls) | |
712 | |
713 if ReAction:GetKeybindMode() then | |
714 overlay:SetFrameLevel(1) | |
715 end | |
716 | |
717 UpdateLabelString(overlay) | |
718 UpdateAnchorDecoration() | |
719 | |
720 return overlay | |
721 end | |
722 | |
723 | |
724 -- export methods to the Bar prototype | |
725 Bar.Overlay = { } | |
726 function Bar.Overlay:New( bar ) | |
727 return setmetatable( {frame = CreateControls(bar)}, {__index=self} ) | |
728 end | |
729 | |
730 function Bar.Overlay:SetLabel(name) | |
731 self.frame.labelName = name | |
732 UpdateLabelString(self.frame) | |
733 end | |
734 | |
735 function Bar.Overlay:SetLabelSubtext(text) | |
736 self.frame.labelSubtext = text | |
737 UpdateLabelString(self.frame) | |
738 end | |
739 | |
740 function Bar.Overlay:Show() | |
741 self.frame:Show() | |
742 end | |
743 | |
744 function Bar.Overlay:Hide() | |
745 self.frame:Hide() | |
746 end | |
747 | |
748 function Bar.Overlay:IsShown() | |
749 return self.frame:IsShown() | |
750 end | |
751 | |
752 function Bar.Overlay:RefreshControls() | |
753 self.frame:RefreshControls() | |
754 end |