annotate BuffAnchors.lua @ 37:e84d645c8ab8

- revised the tracker update function to build its complete data list up front and use the values as points of comparison for determining possible out of place blocks, which will be iterated over afterward to remove what wasn't re-used - also entailed revising the exact role of global event handlers and function hooks, limiting their directions of communication so one doesn't end up calling the other multiple or inifinity times - schema handling polish
author Nenue
date Mon, 18 Apr 2016 07:56:23 -0400
parents 66b927b46776
children
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@24 82 frame:EnableMouse(B.Conf.ConfigMode and B.Conf.ConfigMode or false)
Nenue@0 83 frame:SetScript('OnMouseDown', Anchor_OnMouseDown)
Nenue@0 84 frame:SetScript("OnMouseUp", Anchor_OnMouseUp)
Nenue@0 85 -- table addition
Nenue@0 86 for i, anchorButton in ipairs(frame.anchorButton) do
Nenue@0 87 anchorButton:SetScript('OnClick', AnchorButton_OnClick)
Nenue@0 88 end
Nenue@0 89
Nenue@0 90 B.displays[name].anchor = frame
Nenue@0 91 print(B.displays[name].anchor:GetName())
Nenue@0 92 print(B.anchor[name]:GetName())
Nenue@0 93 return frame, anchorFrom, anchorParent, anchorTo, offsetX, offsetY
Nenue@0 94 end
Nenue@0 95
Nenue@0 96 --- Handles the preliminary positioning calculation for buff guide anchors
Nenue@0 97 M.UpdateAnchorFrames = function(name)
Nenue@0 98 local print = fprint(name)
Nenue@0 99 local c = B.displays[name].conf
Nenue@0 100 local frame, anchorFrom, anchorParent, anchorTo, offsetX, offsetY = GetAnchorFrame(name)
Nenue@0 101 print('got', frame:GetName())
Nenue@0 102 frame.buffs = B.guides[name]
Nenue@0 103 frame.heading:SetText(name)
Nenue@0 104 B.SetConfigLayers(frame)
Nenue@0 105
Nenue@0 106 local buffMax = c['Max'] or 3
Nenue@0 107 local perRow = c['PerRow'] or 2
Nenue@0 108 local buffSpacing = c['Spacing']
Nenue@0 109 local buffSize = c['Size']
Nenue@0 110 local buffDurationSize = c['DurationSize']
Nenue@0 111
Nenue@0 112 if not frame.isMoving then
Nenue@0 113 if not B.Conf[name .. 'Parent'] then
Nenue@0 114 frame:SetPoint(anchorFrom, _G[anchorParent], anchorTo, offsetX, offsetY)
Nenue@0 115 end
Nenue@0 116 end
Nenue@0 117
Nenue@0 118 if frame.contains then buffMax = buffMax + 1 end
Nenue@0 119 local cols, rows = min(perRow, buffMax), ceil(buffMax/perRow)
Nenue@0 120 local spaces, breaks = (cols - 1), (rows - 1)
Nenue@0 121 frame.columns = cols
Nenue@0 122 frame.rows = rows
Nenue@0 123 frame.spaces = cols - 1
Nenue@0 124 frame.breaks = rows - 1
Nenue@0 125
Nenue@0 126 local width = cols*buffSize + spaces*buffSpacing
Nenue@0 127 local height = rows * (buffSize + buffDurationSize) + (breaks * (buffSpacing))
Nenue@0 128
Nenue@0 129 frame:SetSize(width, height)
Nenue@0 130 frame:Show()
Nenue@0 131 print(frame:GetName(), frame:GetSize())
Nenue@0 132 print(frame:GetPoint(1))
Nenue@0 133 end
Nenue@0 134
Nenue@0 135 --- Handles placement of anchors embedded within anchors (consolidated buffs, maybe temp enchant)
Nenue@0 136 M.UpdateAnchorAnchors = function()
Nenue@0 137 local print = fprint()
Nenue@0 138 for buttonName, d in pairs(B.displays) do
Nenue@0 139 local c = B.displays[buttonName].conf
Nenue@0 140 local frame = B.anchor[buttonName]
Nenue@0 141 local parent, child = c.Parent, c.Position
Nenue@0 142
Nenue@0 143 frame.parent = nil
Nenue@0 144 if B.Conf[buttonName .. 'Parent'] and _G[B.Conf[buttonName .. 'Parent']..'Anchor'] then
Nenue@0 145
Nenue@0 146 local anchorAnchor = _G[B.Conf[buttonName .. 'Parent']..'Anchor']
Nenue@0 147 local anchorTarget = B.guides[parent][child]
Nenue@0 148 if anchorTarget then
Nenue@0 149 print('link', buttonName, 'to', parent, child)
Nenue@0 150 print(parent, child, B.displays[parent].guides[child])
Nenue@0 151 local ac = B.displays[parent].conf
Nenue@0 152 local anchorFrom, anchorTo = unpack(ac.Point)
Nenue@0 153 frame:ClearAllPoints()
Nenue@0 154 frame:SetPoint(anchorFrom, anchorTarget, anchorTo)
Nenue@0 155 frame.parent = anchorTarget
Nenue@0 156 anchorTarget.contains = frame
Nenue@0 157 anchorAnchor.contains = frame
Nenue@0 158 anchorAnchor.containPosition = child
Nenue@0 159 else
Nenue@0 160 frame.parent = anchorAnchor
Nenue@0 161 anchorAnchor.contains = frame
Nenue@0 162 anchorAnchor.containPosition = nil
Nenue@0 163 end
Nenue@0 164 else
Nenue@0 165 frame.parent = nil
Nenue@0 166 end
Nenue@0 167
Nenue@0 168 end
Nenue@0 169 end
Nenue@0 170
Nenue@0 171 -- if facing key direction, anchor point [1] to parent's point [2]
Nenue@0 172 local childFacing = {
Nenue@0 173 ['TOP'] = {'TOP', 'BOTTOM'},
Nenue@0 174 ['BOTTOM'] = {'BOTTOM', 'TOP'},
Nenue@0 175 ['RIGHT'] = {'LEFT', 'RIGHT'},
Nenue@0 176 ['LEFT'] = {'RIGHT', 'LEFT'},
Nenue@0 177 }
Nenue@0 178 -- if align in key position, concatenate value with facing point
Nenue@0 179 local childAlign = {
Nenue@0 180 ['TOP'] = 'TOP%s',
Nenue@0 181 ['BOTTOM'] = 'BOTTOM%s',
Nenue@0 182 ['MIDDLE'] = '%s',
Nenue@0 183 ['LEFT'] = '%sLEFT',
Nenue@0 184 ['RIGHT'] = '%sRIGHT',
Nenue@0 185 ['CENTER'] = '%s',
Nenue@0 186 }
Nenue@0 187
Nenue@0 188 --- dep handlers
Nenue@0 189 B.UpdateAnchorChild = function (frame, child, c)
Nenue@0 190 if frame.attached ~= child then
Nenue@0 191 B.SetAnchorChild(frame, child, c)
Nenue@0 192 end
Nenue@0 193
Nenue@0 194 print('positioning|cFFFF0088', child, '|r of |cFF00FF00', frame, '|r')
Nenue@0 195
Nenue@0 196 local frameAnchor = unpack(B.Conf[c.Parent.. 'Anchor'])
Nenue@0 197 local childAnchor, childPoint = 'BOTTOMRIGHT', 'TOPRIGHT'
Nenue@0 198 local direction, position = unpack(c.Anchor)
Nenue@0 199 if direction and position then
Nenue@0 200 childAnchor = childAlign[position]:format(childFacing[direction][2])
Nenue@0 201 childPoint = childAlign[position]:format(childFacing[direction][1])
Nenue@0 202 print('align toward', position,'on', direction, 'edge')
Nenue@0 203 end
Nenue@0 204
Nenue@0 205 print(frameAnchor, direction, position)
Nenue@0 206 local lX, lY, cX, cY = frame.outer_X, frame.outer_Y, frame.cutout_X, frame.cutout_Y
Nenue@0 207 local mX, mY = 0, 0 -- alignment modifiers
Nenue@0 208 local pX, pY = 0, 0 -- position value
Nenue@0 209 print('|cFFFF0088PUSHOUTS|r:', lX, lY, '|cFFFF8800PULL-IN|r:', cX, cY)
Nenue@0 210
Nenue@0 211 -- if attachment is on a moving edge
Nenue@0 212 if not frameAnchor:match(direction) then
Nenue@0 213 print(' child anchors to a growing edge |cFFFF8800', direction,'|r')
Nenue@0 214 if direction == 'BOTTOM' then
Nenue@0 215 -- horizontal edge
Nenue@0 216
Nenue@0 217 else
Nenue@0 218 -- vertical edge
Nenue@0 219 pX = lX
Nenue@0 220 end
Nenue@0 221
Nenue@0 222 if frameAnchor:match(position) then
Nenue@0 223
Nenue@0 224 print('close alignment', lX, cX)
Nenue@0 225 if position == 'RIGHT' then
Nenue@0 226 -- and far X val
Nenue@0 227 pX = 0
Nenue@0 228 lX = -lX
Nenue@0 229 cX = -cX
Nenue@0 230 pY = lY
Nenue@0 231 else
Nenue@0 232 end
Nenue@0 233 else
Nenue@0 234 print('far alignment', position)
Nenue@0 235 end
Nenue@0 236 else
Nenue@0 237 print(' child anchors to a static edge |cFF0088FF', direction,'|r')
Nenue@0 238 -- use no Y offset, position doesn't interfere
Nenue@0 239 if direction == 'BOTTOM' or direction == 'TOP' then
Nenue@0 240 pY = 0
Nenue@0 241 else
Nenue@0 242 pX = 0
Nenue@0 243 end
Nenue@0 244 end
Nenue@0 245
Nenue@0 246 local frameWidth = frame:GetWidth()
Nenue@0 247 local frameHeight = frame:GetHeight()
Nenue@0 248
Nenue@0 249 local overlapY, overlapX
Nenue@0 250
Nenue@0 251 -- right and bottom anchors offsets need to be inverted
Nenue@0 252 if direction == 'BOTTOM' then
Nenue@0 253 print('inverting Y values for anchor on BOTTOM edge, options:', cY, lY, 'actual:', pY)
Nenue@0 254 pY = frameHeight - pY
Nenue@0 255 cY = frameHeight - cY
Nenue@0 256 lY = frameHeight - lY
Nenue@0 257 print(' new values:', cY, lY, pY)
Nenue@0 258 elseif direction == 'RIGHT' then
Nenue@0 259 pX = frameWidth -pX
Nenue@0 260 cX = frameWidth-cX
Nenue@0 261 lX = frameWidth-lX
Nenue@0 262 end
Nenue@0 263
Nenue@0 264
Nenue@0 265 print(child, '|cFFFFFF00', childAnchor, '|r', frame, '|cFFFF0088', childPoint, '|r', pX, pY)
Nenue@0 266 child:ClearAllPoints()
Nenue@0 267 child:SetPoint(childAnchor, frame, childPoint, pX, pY)
Nenue@0 268 frame.attachPoint = {childAnchor, childPoint }
Nenue@0 269
Nenue@0 270 if Devian and Devian.InWorkspace() then
Nenue@0 271 frame.alignedJoint:ClearAllPoints()
Nenue@0 272 frame.poppingJointX:ClearAllPoints()
Nenue@0 273 frame.poppingJointY:ClearAllPoints()
Nenue@0 274 frame.cuttingJointX:ClearAllPoints()
Nenue@0 275 frame.cuttingJointY:ClearAllPoints()
Nenue@0 276 frame.childSpace:ClearAllPoints()
Nenue@0 277
Nenue@0 278 frame.alignedJoint:SetPoint(childAnchor, frame, childPoint, pX, pY)
Nenue@0 279 frame.poppingJointY:SetPoint(childAnchor, frame, childPoint, lX, lY) -- should really only differ when rows exceed 1
Nenue@0 280 frame.poppingJointX:SetPoint(childAnchor, frame, childPoint, lX, lY)
Nenue@0 281 frame.cuttingJointY:SetPoint(childAnchor, frame, childPoint, cX, cY) -- should really only differ when rows exceed 1
Nenue@0 282 frame.cuttingJointX:SetPoint(childAnchor, frame, childPoint, cX, cY)
Nenue@0 283 frame.childSpace:SetAllPoints(child)
Nenue@0 284
Nenue@0 285 frame.alignedJoint:Show()
Nenue@0 286 frame.poppingJointX:Show()
Nenue@0 287 frame.poppingJointY:Show()
Nenue@0 288 frame.cuttingJointX:Show()
Nenue@0 289 frame.cuttingJointY:Show()
Nenue@0 290 frame.childSpace:Show()
Nenue@0 291
Nenue@0 292 print('|cFFFF0000MIN |r', childAnchor, childPoint, pX, pY)
Nenue@0 293 print('|cFF00FFFFFAR |r', childAnchor, childPoint, cX, cY)
Nenue@0 294 print('|cFFFFFF00CLOSE|r', childAnchor, childPoint, lX, lY)
Nenue@0 295
Nenue@0 296 end
Nenue@0 297 end
Nenue@0 298
Nenue@0 299 B.SetAnchorChild = function(frame, child, c)
Nenue@0 300 print('linking', child)
Nenue@0 301 frame.attached = child
Nenue@0 302 frame.attachmentConf = c
Nenue@0 303 end