annotate BuffAnchors.lua @ 7:5301c68f28d8

TrackerBlock - use IsModifiedClick function to determine appropriate OnClick actions - handle 'CHATLINK' modifier - handle 'TOGGLEQUESTWATCH' modifier TrackerBlockObjectives - use a generic framework to manage frame creation for various criteria tracker types: - ProgressBar when Blizzard flag data indicates so - skip when Blizzard flag data indicates so - DynamicText otherwise - events related to the criteria are registered in the criteria frame, and unregistered when the frame is hidden, either by destruction of its parent or completion
author Nenue
date Fri, 01 Apr 2016 12:27:05 -0400
parents 3dbcad2b387d
children 66b927b46776
rev   line source
Nenue@0 1 --- ${PACKAGE_NAME}
Nenue@0 2 -- @file-author@
Nenue@0 3 -- @project-revision@ @project-hash@
Nenue@0 4 -- @file-revision@ @file-hash@
Nenue@0 5 -- Created: 3/22/2016 3:10 AM
Nenue@0 6
Nenue@0 7 local MODULE = 'BuffFrame'
Nenue@0 8 local _, A = ...
Nenue@0 9 local B, _G = A.frame, _G
Nenue@0 10 local M = B:RegisterModule(MODULE)
Nenue@0 11 local type, unpack, select, pairs, ipairs, wipe = type, unpack, select, pairs, ipairs, table.wipe
Nenue@0 12 local min, ceil, mod, tonumber, tostring = min, ceil, mod, tonumber, tostring
Nenue@0 13 local CreateFrame = CreateFrame
Nenue@0 14 local print = B.print('Anchor')
Nenue@0 15 local fprint = B.fprint
Nenue@0 16 local bprint = B.print('AnchorFrame')
Nenue@0 17
Nenue@0 18 local GetAnchorFrame = function(name)
Nenue@0 19 local c = B.displays[name].conf
Nenue@0 20 local anchorFrom, anchorParent, anchorTo, offsetX, offsetY = unpack(c.Anchor)
Nenue@0 21 local print = bprint
Nenue@0 22 if B.anchor[name] then
Nenue@0 23 print('get', B.anchor[name]:GetName())
Nenue@0 24 return B.anchor[name], anchorFrom, anchorParent, anchorTo, offsetX, offsetY
Nenue@0 25 end
Nenue@0 26 print('new frame', name)
Nenue@0 27 local frame = CreateFrame('Frame', name..'Anchor', UIParent, B.displays[name].anchorTemplate)
Nenue@0 28 frame.conf = c
Nenue@0 29
Nenue@0 30 local x, dx, y, dy
Nenue@0 31 local Anchor_OnMouseDown = function()
Nenue@0 32 if c['Parent'] then
Nenue@0 33 return
Nenue@0 34 end
Nenue@0 35
Nenue@0 36 x = frame:GetLeft()
Nenue@0 37 y = frame:GetTop()
Nenue@0 38 frame:StartMoving()
Nenue@0 39 frame.isMoving = true
Nenue@0 40 end
Nenue@0 41
Nenue@0 42 local Anchor_OnMouseUp = function()
Nenue@0 43 if c['Parent'] then
Nenue@0 44 return
Nenue@0 45 end
Nenue@0 46
Nenue@0 47 frame:StopMovingOrSizing()
Nenue@0 48 dx = frame:GetLeft() - x
Nenue@0 49 dy = frame:GetTop() - y
Nenue@0 50 -- update config
Nenue@0 51 print('|cFFFFFF00**changing', name, 'anchor by', dx, dy)
Nenue@0 52 offsetX = offsetX + dx
Nenue@0 53 offsetY = offsetY + dy
Nenue@0 54 B.Conf[name .. 'Anchor'] = {anchorFrom, anchorParent, anchorTo, offsetX, offsetY }
Nenue@0 55 frame:SetPoint(anchorFrom, _G[anchorParent], anchorTo, offsetX, offsetY)
Nenue@0 56 frame.isMoving = nil
Nenue@0 57 end
Nenue@0 58
Nenue@0 59 local AnchorButton_OnClick = function(self, anchor)
Nenue@0 60 local point, parent, relative = anchor:GetPoint(1)
Nenue@0 61 print('resetting anchors', point, parent:GetName(), relative)
Nenue@0 62 B.Conf[name..'Point'] = {point, relative}
Nenue@0 63 B.Conf[name..'RelativeX'] = (point:match('RIGHT')) and -1 or 1
Nenue@0 64 B.Conf[name..'RelativeY'] = (point:match('TOP')) and -1 or 1
Nenue@0 65 wipe(B.drawn[name])
Nenue@0 66 B.UpdateBuffs(name)
Nenue@0 67 end
Nenue@0 68
Nenue@0 69 frame.OnUpdate = function(self, elapsed)
Nenue@0 70 print(self:GetName(), elapsed)
Nenue@0 71 if self:IsMouseOver() then
Nenue@0 72 for i, anchorButton in ipairs(frame.anchorButton) do
Nenue@0 73 anchorButton:Show()
Nenue@0 74 end
Nenue@0 75 else
Nenue@0 76 for i, anchorButton in ipairs(frame.anchorButton) do
Nenue@0 77 anchorButton:Hide()
Nenue@0 78 end
Nenue@0 79 end
Nenue@0 80 end
Nenue@0 81
Nenue@0 82 frame:SetScript('OnMouseDown', Anchor_OnMouseDown)
Nenue@0 83 frame:SetScript("OnMouseUp", Anchor_OnMouseUp)
Nenue@0 84 -- table addition
Nenue@0 85 for i, anchorButton in ipairs(frame.anchorButton) do
Nenue@0 86 anchorButton:SetScript('OnClick', AnchorButton_OnClick)
Nenue@0 87 end
Nenue@0 88
Nenue@0 89 B.displays[name].anchor = frame
Nenue@0 90 print(B.displays[name].anchor:GetName())
Nenue@0 91 print(B.anchor[name]:GetName())
Nenue@0 92 return frame, anchorFrom, anchorParent, anchorTo, offsetX, offsetY
Nenue@0 93 end
Nenue@0 94
Nenue@0 95 --- Handles the preliminary positioning calculation for buff guide anchors
Nenue@0 96 M.UpdateAnchorFrames = function(name)
Nenue@0 97 local print = fprint(name)
Nenue@0 98 local c = B.displays[name].conf
Nenue@0 99 local frame, anchorFrom, anchorParent, anchorTo, offsetX, offsetY = GetAnchorFrame(name)
Nenue@0 100 print('got', frame:GetName())
Nenue@0 101 frame.buffs = B.guides[name]
Nenue@0 102 frame.heading:SetText(name)
Nenue@0 103 B.SetConfigLayers(frame)
Nenue@0 104
Nenue@0 105 local buffMax = c['Max'] or 3
Nenue@0 106 local perRow = c['PerRow'] or 2
Nenue@0 107 local buffSpacing = c['Spacing']
Nenue@0 108 local buffSize = c['Size']
Nenue@0 109 local buffDurationSize = c['DurationSize']
Nenue@0 110
Nenue@0 111 if not frame.isMoving then
Nenue@0 112 if not B.Conf[name .. 'Parent'] then
Nenue@0 113 frame:SetPoint(anchorFrom, _G[anchorParent], anchorTo, offsetX, offsetY)
Nenue@0 114 end
Nenue@0 115 end
Nenue@0 116
Nenue@0 117 if frame.contains then buffMax = buffMax + 1 end
Nenue@0 118 local cols, rows = min(perRow, buffMax), ceil(buffMax/perRow)
Nenue@0 119 local spaces, breaks = (cols - 1), (rows - 1)
Nenue@0 120 frame.columns = cols
Nenue@0 121 frame.rows = rows
Nenue@0 122 frame.spaces = cols - 1
Nenue@0 123 frame.breaks = rows - 1
Nenue@0 124
Nenue@0 125 local width = cols*buffSize + spaces*buffSpacing
Nenue@0 126 local height = rows * (buffSize + buffDurationSize) + (breaks * (buffSpacing))
Nenue@0 127
Nenue@0 128 frame:SetSize(width, height)
Nenue@0 129 frame:Show()
Nenue@0 130 print(frame:GetName(), frame:GetSize())
Nenue@0 131 print(frame:GetPoint(1))
Nenue@0 132 end
Nenue@0 133
Nenue@0 134 --- Handles placement of anchors embedded within anchors (consolidated buffs, maybe temp enchant)
Nenue@0 135 M.UpdateAnchorAnchors = function()
Nenue@0 136 local print = fprint()
Nenue@0 137 for buttonName, d in pairs(B.displays) do
Nenue@0 138 local c = B.displays[buttonName].conf
Nenue@0 139 local frame = B.anchor[buttonName]
Nenue@0 140 local parent, child = c.Parent, c.Position
Nenue@0 141
Nenue@0 142 frame.parent = nil
Nenue@0 143 if B.Conf[buttonName .. 'Parent'] and _G[B.Conf[buttonName .. 'Parent']..'Anchor'] then
Nenue@0 144
Nenue@0 145 local anchorAnchor = _G[B.Conf[buttonName .. 'Parent']..'Anchor']
Nenue@0 146 local anchorTarget = B.guides[parent][child]
Nenue@0 147 if anchorTarget then
Nenue@0 148 print('link', buttonName, 'to', parent, child)
Nenue@0 149 print(parent, child, B.displays[parent].guides[child])
Nenue@0 150 local ac = B.displays[parent].conf
Nenue@0 151 local anchorFrom, anchorTo = unpack(ac.Point)
Nenue@0 152 frame:ClearAllPoints()
Nenue@0 153 frame:SetPoint(anchorFrom, anchorTarget, anchorTo)
Nenue@0 154 frame.parent = anchorTarget
Nenue@0 155 anchorTarget.contains = frame
Nenue@0 156 anchorAnchor.contains = frame
Nenue@0 157 anchorAnchor.containPosition = child
Nenue@0 158 else
Nenue@0 159 frame.parent = anchorAnchor
Nenue@0 160 anchorAnchor.contains = frame
Nenue@0 161 anchorAnchor.containPosition = nil
Nenue@0 162 end
Nenue@0 163 else
Nenue@0 164 frame.parent = nil
Nenue@0 165 end
Nenue@0 166
Nenue@0 167 end
Nenue@0 168 end
Nenue@0 169
Nenue@0 170 -- if facing key direction, anchor point [1] to parent's point [2]
Nenue@0 171 local childFacing = {
Nenue@0 172 ['TOP'] = {'TOP', 'BOTTOM'},
Nenue@0 173 ['BOTTOM'] = {'BOTTOM', 'TOP'},
Nenue@0 174 ['RIGHT'] = {'LEFT', 'RIGHT'},
Nenue@0 175 ['LEFT'] = {'RIGHT', 'LEFT'},
Nenue@0 176 }
Nenue@0 177 -- if align in key position, concatenate value with facing point
Nenue@0 178 local childAlign = {
Nenue@0 179 ['TOP'] = 'TOP%s',
Nenue@0 180 ['BOTTOM'] = 'BOTTOM%s',
Nenue@0 181 ['MIDDLE'] = '%s',
Nenue@0 182 ['LEFT'] = '%sLEFT',
Nenue@0 183 ['RIGHT'] = '%sRIGHT',
Nenue@0 184 ['CENTER'] = '%s',
Nenue@0 185 }
Nenue@0 186
Nenue@0 187 --- dep handlers
Nenue@0 188 B.UpdateAnchorChild = function (frame, child, c)
Nenue@0 189 if frame.attached ~= child then
Nenue@0 190 B.SetAnchorChild(frame, child, c)
Nenue@0 191 end
Nenue@0 192
Nenue@0 193 print('positioning|cFFFF0088', child, '|r of |cFF00FF00', frame, '|r')
Nenue@0 194
Nenue@0 195 local frameAnchor = unpack(B.Conf[c.Parent.. 'Anchor'])
Nenue@0 196 local childAnchor, childPoint = 'BOTTOMRIGHT', 'TOPRIGHT'
Nenue@0 197 local direction, position = unpack(c.Anchor)
Nenue@0 198 if direction and position then
Nenue@0 199 childAnchor = childAlign[position]:format(childFacing[direction][2])
Nenue@0 200 childPoint = childAlign[position]:format(childFacing[direction][1])
Nenue@0 201 print('align toward', position,'on', direction, 'edge')
Nenue@0 202 end
Nenue@0 203
Nenue@0 204 print(frameAnchor, direction, position)
Nenue@0 205 local lX, lY, cX, cY = frame.outer_X, frame.outer_Y, frame.cutout_X, frame.cutout_Y
Nenue@0 206 local mX, mY = 0, 0 -- alignment modifiers
Nenue@0 207 local pX, pY = 0, 0 -- position value
Nenue@0 208 print('|cFFFF0088PUSHOUTS|r:', lX, lY, '|cFFFF8800PULL-IN|r:', cX, cY)
Nenue@0 209
Nenue@0 210 -- if attachment is on a moving edge
Nenue@0 211 if not frameAnchor:match(direction) then
Nenue@0 212 print(' child anchors to a growing edge |cFFFF8800', direction,'|r')
Nenue@0 213 if direction == 'BOTTOM' then
Nenue@0 214 -- horizontal edge
Nenue@0 215
Nenue@0 216 else
Nenue@0 217 -- vertical edge
Nenue@0 218 pX = lX
Nenue@0 219 end
Nenue@0 220
Nenue@0 221 if frameAnchor:match(position) then
Nenue@0 222
Nenue@0 223 print('close alignment', lX, cX)
Nenue@0 224 if position == 'RIGHT' then
Nenue@0 225 -- and far X val
Nenue@0 226 pX = 0
Nenue@0 227 lX = -lX
Nenue@0 228 cX = -cX
Nenue@0 229 pY = lY
Nenue@0 230 else
Nenue@0 231 end
Nenue@0 232 else
Nenue@0 233 print('far alignment', position)
Nenue@0 234 end
Nenue@0 235 else
Nenue@0 236 print(' child anchors to a static edge |cFF0088FF', direction,'|r')
Nenue@0 237 -- use no Y offset, position doesn't interfere
Nenue@0 238 if direction == 'BOTTOM' or direction == 'TOP' then
Nenue@0 239 pY = 0
Nenue@0 240 else
Nenue@0 241 pX = 0
Nenue@0 242 end
Nenue@0 243 end
Nenue@0 244
Nenue@0 245 local frameWidth = frame:GetWidth()
Nenue@0 246 local frameHeight = frame:GetHeight()
Nenue@0 247
Nenue@0 248 local overlapY, overlapX
Nenue@0 249
Nenue@0 250 -- right and bottom anchors offsets need to be inverted
Nenue@0 251 if direction == 'BOTTOM' then
Nenue@0 252 print('inverting Y values for anchor on BOTTOM edge, options:', cY, lY, 'actual:', pY)
Nenue@0 253 pY = frameHeight - pY
Nenue@0 254 cY = frameHeight - cY
Nenue@0 255 lY = frameHeight - lY
Nenue@0 256 print(' new values:', cY, lY, pY)
Nenue@0 257 elseif direction == 'RIGHT' then
Nenue@0 258 pX = frameWidth -pX
Nenue@0 259 cX = frameWidth-cX
Nenue@0 260 lX = frameWidth-lX
Nenue@0 261 end
Nenue@0 262
Nenue@0 263
Nenue@0 264 print(child, '|cFFFFFF00', childAnchor, '|r', frame, '|cFFFF0088', childPoint, '|r', pX, pY)
Nenue@0 265 child:ClearAllPoints()
Nenue@0 266 child:SetPoint(childAnchor, frame, childPoint, pX, pY)
Nenue@0 267 frame.attachPoint = {childAnchor, childPoint }
Nenue@0 268
Nenue@0 269 if Devian and Devian.InWorkspace() then
Nenue@0 270 frame.alignedJoint:ClearAllPoints()
Nenue@0 271 frame.poppingJointX:ClearAllPoints()
Nenue@0 272 frame.poppingJointY:ClearAllPoints()
Nenue@0 273 frame.cuttingJointX:ClearAllPoints()
Nenue@0 274 frame.cuttingJointY:ClearAllPoints()
Nenue@0 275 frame.childSpace:ClearAllPoints()
Nenue@0 276
Nenue@0 277 frame.alignedJoint:SetPoint(childAnchor, frame, childPoint, pX, pY)
Nenue@0 278 frame.poppingJointY:SetPoint(childAnchor, frame, childPoint, lX, lY) -- should really only differ when rows exceed 1
Nenue@0 279 frame.poppingJointX:SetPoint(childAnchor, frame, childPoint, lX, lY)
Nenue@0 280 frame.cuttingJointY:SetPoint(childAnchor, frame, childPoint, cX, cY) -- should really only differ when rows exceed 1
Nenue@0 281 frame.cuttingJointX:SetPoint(childAnchor, frame, childPoint, cX, cY)
Nenue@0 282 frame.childSpace:SetAllPoints(child)
Nenue@0 283
Nenue@0 284 frame.alignedJoint:Show()
Nenue@0 285 frame.poppingJointX:Show()
Nenue@0 286 frame.poppingJointY:Show()
Nenue@0 287 frame.cuttingJointX:Show()
Nenue@0 288 frame.cuttingJointY:Show()
Nenue@0 289 frame.childSpace:Show()
Nenue@0 290
Nenue@0 291 print('|cFFFF0000MIN |r', childAnchor, childPoint, pX, pY)
Nenue@0 292 print('|cFF00FFFFFAR |r', childAnchor, childPoint, cX, cY)
Nenue@0 293 print('|cFFFFFF00CLOSE|r', childAnchor, childPoint, lX, lY)
Nenue@0 294
Nenue@0 295 end
Nenue@0 296 end
Nenue@0 297
Nenue@0 298 B.SetAnchorChild = function(frame, child, c)
Nenue@0 299 print('linking', child)
Nenue@0 300 frame.attached = child
Nenue@0 301 frame.attachmentConf = c
Nenue@0 302 end