view BuffAnchors.lua @ 12:8238cddaddb1

ObjectiveUI - fillers for 'Hidden' objective widgets
author Nenue
date Sat, 02 Apr 2016 05:01:54 -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