view 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
line wrap: on
line source
--- ${PACKAGE_NAME}
-- @file-author@
-- @project-revision@ @project-hash@
-- @file-revision@ @file-hash@
-- Created: 3/22/2016 3:10 AM

local MODULE = 'BuffFrame'
local _, A = ...
local B, _G = A.frame, _G
local M = B:RegisterModule(MODULE)
local type, unpack, select, pairs, ipairs, wipe = type, unpack, select, pairs, ipairs, table.wipe
local min, ceil, mod, tonumber, tostring = min, ceil, mod, tonumber, tostring
local CreateFrame = CreateFrame
local print = B.print('Anchor')
local fprint = B.fprint
local bprint = B.print('AnchorFrame')

local GetAnchorFrame = function(name)
  local c = B.displays[name].conf
  local anchorFrom, anchorParent, anchorTo, offsetX, offsetY = unpack(c.Anchor)
  local print = bprint
  if B.anchor[name] then
    print('get', B.anchor[name]:GetName())
    return B.anchor[name], anchorFrom, anchorParent, anchorTo, offsetX, offsetY
  end
  print('new frame', name)
  local frame = CreateFrame('Frame', name..'Anchor', UIParent, B.displays[name].anchorTemplate)
  frame.conf = c

  local x, dx, y, dy
  local Anchor_OnMouseDown =  function()
    if c['Parent'] then
      return
    end

    x = frame:GetLeft()
    y = frame:GetTop()
    frame:StartMoving()
    frame.isMoving = true
  end

  local Anchor_OnMouseUp = function()
    if c['Parent'] then
      return
    end

    frame:StopMovingOrSizing()
    dx = frame:GetLeft() - x
    dy = frame:GetTop() - y
    -- update config
    print('|cFFFFFF00**changing', name, 'anchor by', dx, dy)
    offsetX = offsetX + dx
    offsetY = offsetY + dy
    B.Conf[name .. 'Anchor'] = {anchorFrom, anchorParent, anchorTo, offsetX, offsetY }
    frame:SetPoint(anchorFrom, _G[anchorParent], anchorTo, offsetX, offsetY)
    frame.isMoving = nil
  end

  local AnchorButton_OnClick = function(self, anchor)
    local point, parent, relative = anchor:GetPoint(1)
    print('resetting anchors', point, parent:GetName(), relative)
    B.Conf[name..'Point'] = {point, relative}
    B.Conf[name..'RelativeX'] = (point:match('RIGHT')) and -1 or 1
    B.Conf[name..'RelativeY'] = (point:match('TOP')) and -1 or 1
    wipe(B.drawn[name])
    B.UpdateBuffs(name)
  end

  frame.OnUpdate = function(self, elapsed)
    print(self:GetName(), elapsed)
    if self:IsMouseOver() then
      for i, anchorButton in ipairs(frame.anchorButton) do
        anchorButton:Show()
      end
    else
      for i, anchorButton in ipairs(frame.anchorButton) do
        anchorButton:Hide()
      end
    end
  end

  frame:SetScript('OnMouseDown', Anchor_OnMouseDown)
  frame:SetScript("OnMouseUp", Anchor_OnMouseUp)
  -- table addition
  for i, anchorButton in ipairs(frame.anchorButton) do
    anchorButton:SetScript('OnClick', AnchorButton_OnClick)
  end

  B.displays[name].anchor = frame
  print(B.displays[name].anchor:GetName())
  print(B.anchor[name]:GetName())
  return frame, anchorFrom, anchorParent, anchorTo, offsetX, offsetY
end

--- Handles the preliminary positioning calculation for buff guide anchors
M.UpdateAnchorFrames = function(name)
  local print = fprint(name)
  local c = B.displays[name].conf
  local frame, anchorFrom, anchorParent, anchorTo, offsetX, offsetY = GetAnchorFrame(name)
  print('got', frame:GetName())
  frame.buffs = B.guides[name]
  frame.heading:SetText(name)
  B.SetConfigLayers(frame)

  local buffMax = c['Max'] or 3
  local perRow = c['PerRow'] or 2
  local buffSpacing = c['Spacing']
  local buffSize = c['Size']
  local buffDurationSize = c['DurationSize']

  if not frame.isMoving then
    if not B.Conf[name .. 'Parent'] then
      frame:SetPoint(anchorFrom, _G[anchorParent], anchorTo, offsetX, offsetY)
    end
  end

  if frame.contains then buffMax = buffMax + 1 end
  local cols, rows = min(perRow, buffMax), ceil(buffMax/perRow)
  local spaces, breaks = (cols - 1), (rows - 1)
  frame.columns = cols
  frame.rows = rows
  frame.spaces = cols - 1
  frame.breaks = rows - 1

  local width = cols*buffSize + spaces*buffSpacing
  local height = rows * (buffSize + buffDurationSize) + (breaks * (buffSpacing))

  frame:SetSize(width, height)
  frame:Show()
  print(frame:GetName(), frame:GetSize())
  print(frame:GetPoint(1))
end

--- Handles placement of anchors embedded within anchors (consolidated buffs, maybe temp enchant)
M.UpdateAnchorAnchors = function()
  local print = fprint()
  for buttonName, d in pairs(B.displays) do
    local c = B.displays[buttonName].conf
    local frame =  B.anchor[buttonName]
    local parent, child = c.Parent, c.Position

    frame.parent = nil
    if B.Conf[buttonName .. 'Parent'] and _G[B.Conf[buttonName .. 'Parent']..'Anchor'] then

      local anchorAnchor = _G[B.Conf[buttonName .. 'Parent']..'Anchor']
      local anchorTarget = B.guides[parent][child]
      if anchorTarget then
        print('link', buttonName, 'to', parent, child)
        print(parent, child, B.displays[parent].guides[child])
        local ac = B.displays[parent].conf
        local anchorFrom, anchorTo = unpack(ac.Point)
        frame:ClearAllPoints()
        frame:SetPoint(anchorFrom, anchorTarget, anchorTo)
        frame.parent = anchorTarget
        anchorTarget.contains = frame
        anchorAnchor.contains = frame
        anchorAnchor.containPosition = child
      else
        frame.parent = anchorAnchor
        anchorAnchor.contains = frame
        anchorAnchor.containPosition = nil
      end
    else
      frame.parent = nil
    end

  end
end

-- if facing key direction, anchor point [1] to parent's point [2]
local childFacing = {
  ['TOP'] = {'TOP', 'BOTTOM'},
  ['BOTTOM'] = {'BOTTOM', 'TOP'},
  ['RIGHT'] = {'LEFT', 'RIGHT'},
  ['LEFT'] = {'RIGHT', 'LEFT'},
}
-- if align in key position, concatenate value with facing point
local childAlign = {
  ['TOP'] = 'TOP%s',
  ['BOTTOM'] = 'BOTTOM%s',
  ['MIDDLE'] = '%s',
  ['LEFT'] = '%sLEFT',
  ['RIGHT'] = '%sRIGHT',
  ['CENTER'] = '%s',
}

--- dep handlers
B.UpdateAnchorChild = function (frame, child, c)
  if frame.attached ~= child then
    B.SetAnchorChild(frame, child, c)
  end

  print('positioning|cFFFF0088', child, '|r of |cFF00FF00', frame, '|r')

  local frameAnchor = unpack(B.Conf[c.Parent.. 'Anchor'])
  local childAnchor, childPoint = 'BOTTOMRIGHT', 'TOPRIGHT'
  local direction, position = unpack(c.Anchor)
  if direction and position then
    childAnchor = childAlign[position]:format(childFacing[direction][2])
    childPoint = childAlign[position]:format(childFacing[direction][1])
    print('align toward', position,'on', direction, 'edge')
  end

  print(frameAnchor, direction, position)
  local lX, lY, cX, cY = frame.outer_X, frame.outer_Y, frame.cutout_X, frame.cutout_Y
  local mX, mY = 0, 0 -- alignment modifiers
  local pX, pY = 0, 0 -- position value
  print('|cFFFF0088PUSHOUTS|r:', lX, lY, '|cFFFF8800PULL-IN|r:', cX, cY)

  -- if attachment is on a moving edge
  if not frameAnchor:match(direction) then
    print('  child anchors to a growing edge |cFFFF8800', direction,'|r')
    if direction == 'BOTTOM' then
      -- horizontal edge

    else
      -- vertical edge
      pX = lX
    end

    if frameAnchor:match(position) then

      print('close alignment', lX, cX)
      if position == 'RIGHT' then
        -- and far X val
        pX = 0
        lX = -lX
        cX = -cX
        pY = lY
      else
      end
    else
      print('far alignment', position)
    end
  else
    print('  child anchors to a static edge |cFF0088FF', direction,'|r')
    -- use no Y offset, position doesn't interfere
    if direction == 'BOTTOM' or direction == 'TOP' then
      pY = 0
    else
      pX = 0
    end
  end

  local frameWidth = frame:GetWidth()
  local frameHeight = frame:GetHeight()

  local overlapY, overlapX

  -- right and bottom anchors offsets need to be inverted
  if direction == 'BOTTOM' then
    print('inverting Y values for anchor on BOTTOM edge, options:', cY, lY, 'actual:', pY)
    pY = frameHeight - pY
    cY = frameHeight - cY
    lY = frameHeight - lY
    print('  new values:', cY, lY, pY)
  elseif direction == 'RIGHT' then
    pX = frameWidth -pX
    cX = frameWidth-cX
    lX = frameWidth-lX
  end


  print(child, '|cFFFFFF00', childAnchor, '|r', frame, '|cFFFF0088', childPoint, '|r', pX, pY)
  child:ClearAllPoints()
  child:SetPoint(childAnchor, frame, childPoint, pX, pY)
  frame.attachPoint = {childAnchor, childPoint }

  if Devian and Devian.InWorkspace() then
    frame.alignedJoint:ClearAllPoints()
    frame.poppingJointX:ClearAllPoints()
    frame.poppingJointY:ClearAllPoints()
    frame.cuttingJointX:ClearAllPoints()
    frame.cuttingJointY:ClearAllPoints()
    frame.childSpace:ClearAllPoints()

    frame.alignedJoint:SetPoint(childAnchor, frame, childPoint, pX, pY)
    frame.poppingJointY:SetPoint(childAnchor, frame, childPoint, lX, lY) -- should really only differ when rows exceed 1
    frame.poppingJointX:SetPoint(childAnchor, frame, childPoint, lX, lY)
    frame.cuttingJointY:SetPoint(childAnchor, frame, childPoint, cX, cY) -- should really only differ when rows exceed 1
    frame.cuttingJointX:SetPoint(childAnchor, frame, childPoint, cX, cY)
    frame.childSpace:SetAllPoints(child)

    frame.alignedJoint:Show()
    frame.poppingJointX:Show()
    frame.poppingJointY:Show()
    frame.cuttingJointX:Show()
    frame.cuttingJointY:Show()
    frame.childSpace:Show()

    print('|cFFFF0000MIN  |r', childAnchor, childPoint, pX, pY)
    print('|cFF00FFFFFAR  |r', childAnchor, childPoint, cX, cY)
    print('|cFFFFFF00CLOSE|r', childAnchor, childPoint, lX, lY)

  end
end

B.SetAnchorChild = function(frame, child, c)
  print('linking', child)
  frame.attached = child
  frame.attachmentConf = c
end