Mercurial > wow > buffalo2
changeset 0:3dbcad2b387d
initial push
author | Nenue |
---|---|
date | Wed, 30 Mar 2016 02:24:56 -0400 |
parents | |
children | b0447b382f36 |
files | BuffAnchors.lua BuffButton.lua BuffFrame.xml Config.lua Constants.lua Core.xml Init.lua ObjectiveInfo.lua ObjectiveTracker.lua ObjectiveTracker.xml ObjectiveUI.lua RaidBuffTray.lua Veneer.toc |
diffstat | 13 files changed, 3386 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BuffAnchors.lua Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,302 @@ +--- ${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 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BuffButton.lua Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,440 @@ +--- Actual BlizzUI modifications are applied here +-- @file-author@ +-- @project-revision@ @project-hash@ +-- @file-revision@ @file-hash@ +-- Created: 3/12/2016 12:47 AM +local MODULE = 'BuffFrame' +local _, A = ... +local B, _G = A.frame, _G +local type, unpack, select, pairs, ipairs = _G.type, _G.unpack, _G.select, _G.pairs, _G.ipairs +local min, ceil, mod, tonumber, tostring = _G.min, _G.ceil, _G.mod, _G.tonumber, _G.tostring +local floor, wipe, max = _G.math.floor, _G.table.wipe, _G.math.max +local CreateFrame, IsInGroup, GetCVarBool = _G.CreateFrame, _G.IsInGroup, _G.GetCVarBool +local BuffFrame, ConsolidatedBuffs = _G.BuffFrame, _G.ConsolidatedBuffs +local print, gprint, aprint, fprint = B.print('Buff'), B.print('SetGuides'), B.print('SetAnchors'), B.fprint +local displays, anchors, guides, decors, positioned, drawn, zoom = B.displays, {}, {}, {}, {}, {}, {} +local UnitAura, UnitName, RegisterStateDriver = _G.UnitAura, _G.UnitName, _G.RegisterStateDriver + +local M = B:RegisterModule(MODULE) + +M.GetBuffZoom = function(buffName) + local zoom = tonumber(B.displays[buffName].conf['Zoom']) / 100 / 2 + local zoomL, zoomU, zoomR, zoomD = zoom, zoom, 1-zoom, 1-zoom + print(buffName, zoom) + return function(self, ...) + if select('#',...) == 4 then + zoomL, zoomR, zoomU, zoomD = ... + end + self:SetTexCoord(zoomL, zoomR, zoomU, zoomD) + return zoomL, zoomR, zoomU, zoomD + end +end + + + +M.UpdateButtonAlpha = function(self) + if not self.parent.timeLeft or not self:IsVisible() then + self:SetScript('OnUpdate', nil) + return + end + + if self.parent.timeLeft < _G.BUFF_WARNING_TIME then + self:SetAlpha(BuffFrame.BuffAlphaValue) + else + self:SetAlpha(1) + end +end + +--- Called infrequently to align stencil frames +local refreshCount = 0 +M.UpdateGuideFrames = function(buffName) + refreshCount = refreshCount + 1 + local print = fprint() + + + local anchor = anchors[buffName] + local c, g, d = displays[buffName].conf, guides[buffName], decors[buffName] + local perRow = c['PerRow'] + local buffSpacing, buffSize, buffBorder, buffDurationSize, buffCountSize, relativeX, relativeY = c['Spacing'], c['Size'], c['Border'], c['DurationSize'], c['CountSize'], c['RelativeX'], c['RelativeY'] + local consolidated = (anchors[buffName].contains and IsInGroup()) + local consolidatedPosition = (consolidated and anchors[buffName].containPosition or 0) + + + print('|cFF00FF00Setting Guides ('..refreshCount..'):|r', buffName, 'user max:',c['Max'], 'hard max:', displays[buffName].maxIcons) + + local buffMax = min(c['Max'], displays[buffName].maxIcons) + local anchorFrom, anchorTo = c.Point[1], c.Point[2] + anchor.Zoom = M.GetBuffZoom(buffName) + + + + if consolidated then + buffMax = buffMax + 1 + end + + local legend = {} + legend.r, legend.g, legend.b, legend.a = unpack(displays[buffName].legendColor) + local horizFrom = (relativeX < 0) and 'RIGHT' or 'LEFT' + local horizTo = (relativeX < 0) and 'LEFT' or 'RIGHT' + local vertFrom = (relativeY < 0) and 'TOP' or 'BOTTOM' + local vertTo = (relativeY < 0) and 'BOTTOM' or 'TOP' + local previous, up + local bottom_extent = 0 + for i = 1, buffMax do + print('update idx', i) + if not g[i] then + g[i] = CreateFrame('Frame', buffName..'Guide'..i, anchor, displays[buffName].template or 'VeneerGuideTemplate') + RegisterStateDriver(g[i], "visibility", "[petbattle] [vehicleui] hide; show") + end + + local guide = g[i] + + local row = ceil(i / perRow) + local col = mod(i, perRow) + if col == 0 then + col = perRow + end + + guide.previous = previous + guide.up = up + local x, y, parent = 0, 0, anchor + if i == 1 then + parent = anchor + up = guide + elseif col == 1 then + parent = g[i-perRow] + y = (buffSpacing + bottom_extent) * relativeY + up = guide + anchorFrom = vertFrom .. horizFrom + anchorTo = vertFrom .. horizFrom + bottom_extent = 0 + else + parent = g[i-1] + x = buffSpacing * relativeX + anchorFrom = vertFrom .. horizFrom + anchorTo = vertFrom .. horizTo + end + previous = guide + guide.parent = parent + + --------------------------------- + -- Positioning layer + if i ~= consolidatedPosition or not consolidated then + guide:SetSize(buffSize, buffSize + buffDurationSize) + -- RaidBuffTray will fix the sizing + end + bottom_extent = max(bottom_extent, guide:GetHeight()) + + guide.info = {} -- UnitAura cache + + if i == consolidatedPosition then + guide.legend:SetTexture(1,1,0,0.5) + else + guide.legend:SetTexture(legend.r, legend.g, legend.b, legend.a) + end + + guide.idText:SetText(i) -- needs to reflect the current position + + guide:ClearAllPoints() + guide:SetPoint(anchorFrom, parent, anchorTo, x, y) + print(anchorFrom, parent, anchorTo, x, y) + + guide.icon:SetSize(buffSize - buffBorder * 2, buffSize - buffBorder * 2) + guide.icon:ClearAllPoints() + guide.icon:SetPoint('TOPLEFT', guide, 'TOPLEFT', buffBorder, -buffBorder ) + + local anchorTo, anchorFrom, x, y = unpack(c.DurationPoint) + guide.duration:ClearAllPoints() + guide.duration:SetPoint(anchorTo, guide, anchorFrom, x, y) + --guide.duration:SetSize(buffSize, buffDurationSize) + print(' duration ->', anchorFrom, anchorTo, x, y) + + local anchorTo, anchorFrom, x, y = unpack(c.CountPoint) + guide.count:ClearAllPoints() + guide.count:SetPoint(anchorTo, guide.icon, anchorFrom, x, y) + --guide.count:SetSize(buffSize, c.CountSize) + print(' count ->', anchorFrom, anchorTo, x, y) + + ----------------------------------- + -- Background decorations layer + if not d[i] then + d[i] = CreateFrame('Frame', buffName..i..'Decor', _G.UIParent, 'VeneerDecorTemplate') + RegisterStateDriver(d[i], "visibility", "[petbattle] [vehicleui] hide") + end + + d[i]:SetPoint('BOTTOMLEFT', guide.icon, 'BOTTOMLEFT', -buffBorder, -buffBorder) + d[i]:SetPoint('TOPRIGHT', guide.icon, 'TOPRIGHT', buffBorder, buffBorder) + + + guide:Show() + B.SetConfigLayers(guide) + end + + + if #guides[buffName] > buffMax then + local lim = #guides[buffName] + for i = buffMax+1, lim do + + local g = guides[buffName][i] + if g:IsVisible() then + print('cleaning up #', i, buffName) + g:Hide() + B.RemoveConfigLayers(g) + end + + end + end + + anchor.last = previous + anchor.up = up + + print(anchor:GetName(), anchor:GetSize()) +end + +M.UpdateButtonPositions = function(buffName, auraType) + local print = fprint() + local c = auraType.conf + local numBuffs = 0 + local actualIcons = auraType.actualIcons() + local maxIcons = auraType.maxIcons + local anchor = anchors[buffName] + local buffMax = c['Max'] + local consolidated = (anchor.contains and IsInGroup()) + local consolidatedPosition = (consolidated and anchor.containPosition or 0) + + for k,v in pairs(decors[buffName]) do + print(v) + end + + if consolidated then + decors[buffName][1]:Hide() + numBuffs = numBuffs + 1 + buffMax = buffMax + 1 + end + + print(' ', 'frame count:', auraType.actualIcons(), 'hardmax:', maxIcons) + if auraType.actualIcons() > 0 then + for i = 1, actualIcons do + + + local buff = _G[buffName .. i] + local buffIcon = _G[buffName .. i .. 'Icon'] + local buffBorder = c['Border'] + local buffDuration = _G[buffName .. i .. 'Duration'] + local buffCount = _G[buffName .. i .. 'Count'] + local buffDurationSize = c['DurationSize'] + local debuffBorder = _G[buffName .. i .. 'Border'] + + + if buff and not buff.consolidated then + numBuffs = numBuffs + 1 + local guide = guides[buffName][numBuffs] + local deco = decors[buffName][numBuffs] + if numBuffs > buffMax then + -- if a limit is reached, start hiding + if guide then + guide.info = nil + end + if deco then + deco:Hide() + end + buff:Hide() + else + local buffData = guide.info + buffData.name, buffData.rank, buffData.icon, buffData.count, buffData.dispelType, buffData.duration, buffData.expires, buffData.caster, buffData.isStealable, buffData.shouldConsolidate, buffData.spellID, buffData.canApplyAura, buffData.isBossDebuff, buffData.value1, buffData.value2, buffData.value3 + = UnitAura(buff.unit, buff:GetID(), nil, buff.filters) + + if guide.caster and buffData.caster then + if (buffData.caster ~= 'player' or c.ShowSelfCast) then + guide.caster:SetText(UnitName(buffData.caster)) + else + guide.caster:SetText(nil) + end + end + + + print(numBuffs, i, buff:GetName(), buff:GetID(), decors[buffName][numBuffs]:GetName()) + + buff:SetAllPoints(guide) + buffIcon:ClearAllPoints() + buffIcon:SetPoint('TOPLEFT', guide.icon, 'TOPLEFT', 0, 0) + buffIcon:SetPoint('BOTTOMRIGHT', guide.icon, 'BOTTOMRIGHT', 0, 0) + + deco.parent = buff + -- make sure so they aren't re-shown in pet battle + if not C_PetBattles.IsInBattle() then + deco:Show() + deco:SetAlpha(1) + end + + if debuffBorder then + deco.background:SetTexture(debuffBorder:GetVertexColor()) + debuffBorder:Hide() + else + if guide.info.caster == 'player' then + print(guide.info.caster) + deco.background:SetTexture(unpack(c.PlayerColor)) + elseif buffData.isBossDebuff then + print(guide.info.isBossDebuff) + deco.background:SetTexture(unpack(c.BossColor)) + else + print(guide.info.caster) + deco.background:SetTexture(unpack(c.Color)) + end + end + + + buffDuration:ClearAllPoints() + local from, to = unpack(c.DurationPoint) + buffDuration:SetPoint(from, guide.duration, to) + buffDuration:SetText('WHAT') + + if buff.timeLeft and c.WarningFade then + deco:SetScript('OnUpdate', M.UpdateButtonAlpha) + else + deco:SetScript('OnUpdate', nil) + deco:SetAlpha(1.0) + end + + buffCount:ClearAllPoints() + local from, to = unpack(c.CountPoint) + buffCount:SetPoint(from, guide.count, to) + + if not drawn[buffName][numBuffs] then + anchors[buffName].Zoom(buffIcon) + + if buffDuration then + local font = buffDuration:GetFont() + buffDuration:SetFont(font, c.DurationSize, 'OUTLINE') + + end + + if buffCount then + local font = buffCount:GetFont() + buffCount:SetFont(font, c.CountSize, 'OUTLINE') + end + drawn[buffName][numBuffs] = true + end + end + end + + end + end + -- clear any outliers + for i = numBuffs+1, buffMax do + if guides[buffName][i].caster then + guides[buffName][i].caster:SetText(nil) + end + --if not decors[buffName][i].parent or + + decors[buffName][i].parent = nil + decors[buffName][i]:SetAlpha(1.0) + decors[buffName][i]:SetScript('OnUpdate', nil) + decors[buffName][i]:Hide() + end + + -- parametric occlusion data for compacted anchor points + if numBuffs == 0 then + anchor.cutout_X = 0 + anchor.cutout_Y = 0 + anchor.outer_X = 0 + anchor.outer_Y = 0 + elseif numBuffs <= buffMax then + local sX, sY = guides[buffName][numBuffs]:GetWidth(), guides[buffName][numBuffs]:GetHeight() + local p = c.PerRow + local lX = mod(numBuffs, p) + local lY = floor(numBuffs / p) + local oX = min(numBuffs, c.PerRow) + local oY = ceil(numBuffs / p) + anchor.cutout_X = lX * sX + lX * c.Spacing -- max clearance to fit alongside the row + anchor.cutout_Y = lY * sY + lY * c.Spacing + anchor.outer_Y = oY * sY + oY * c.Spacing -- distance of farthest row + anchor.outer_X = oX * sX + oX * c.Spacing + + + print('|cFF0088FF', 'inner corner', lX, lY, 'outer corners', oX, oY) + print('cutout delta =', anchor.cutout_X, anchor.cutout_Y, 'out of', floor(anchor:GetWidth()), floor(anchor:GetHeight())) + print('extent delta =', anchor.outer_X, anchor.outer_Y) + else + anchor.cutout_X = 0 + anchor.cutout_Y = 0 + anchor.outer_X = 0 + anchor.outer_Y = 0 + end + + if anchor.attached then + M.UpdateAnchorChild(anchor, anchor.attached, anchor.attachmentConf) + end + +end + +M.PostBuffAnchors = function() + local print = fprint() + if M.ShowConsolidatedBuffs then + M.UpdateRaidBuffs() + end + for buttonName, auraType in pairs(displays) do + print('sending', buttonName, auraType) + -- if waiting for anchors + if not anchors[buttonName] then + return + end + + --if positioned[buttonName] == 0 then + print('possibly reloaded UI, check positions') + M.UpdateGuideFrames(buttonName) + --end + + M.UpdateButtonPositions(buttonName, auraType) + end +end + +M.UpdateBuffs = function(buttonName, forced) + local print = B.fprint(buttonName) + local c = displays[buttonName].conf + if drawn[buttonName] then + wipe(drawn[buttonName]) + else + drawn[buttonName] = {} + end + + M.UpdateAnchorFrames(buttonName) + M.UpdateGuideFrames(buttonName) + M.UpdateButtonPositions(buttonName, displays[buttonName]) +end + +--- should only be called from user input +print('init def') +function M:OnInitialize () + drawn = B.Abstract(B.displays, 'drawn') + -- Lesser extent of guide frames that have been positioned + positioned = B.Abstract(B.displays, 'positioned', positioned) + -- Backdrop style frame + decors = B.Abstract(B.displays, 'decorator', decors) + -- Static positioning frames + guides = B.Abstract(B.displays, 'guides', guides) + -- Anchor points for guides + anchors = B.Abstract(B.displays, 'anchor') + -- Stored functions for doing icon texture adjustments + zoom = B.Abstract(B.displays, 'zoom', zoom) + + B:RegisterUnitEvent("UNIT_AURA", "player", "vehicle") + B:RegisterEvent("GROUP_ROSTER_UPDATE") + B:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED") + hooksecurefunc("BuffFrame_UpdateAllBuffAnchors", M.PostBuffAnchors) + hooksecurefunc("RaidBuffTray_Update", M.UpdateRaidBuffs) +end +print('update def') +function M:OnUpdate () + M.ShowConsolidated = (IsInGroup() and GetCVarBool("consolidateBuffs")) + M.ShowMissingBuffs = (IsInGroup() and B.Conf.RaidShowMissing) + + for name, auraType in pairs(displays) do + print(name, auraType) + M.UpdateBuffs(auraType.buffName, true) + end + + M.UpdateAnchorAnchors() + M.UpdateRaidBuffs() + M.UpdateBuffsTodo() +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BuffFrame.xml Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,9 @@ +<Ui> + <!-- + Veneer + BuffFrame module + --> + <Script file="BuffAnchors.lua" /> + <Script file="RaidBuffTray.lua" /> + <Script file="BuffButton.lua" /> +</Ui> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Config.lua Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,388 @@ +--- All the control GUI stuff, including chat command functions +-- @file-author@ +-- @project-revision@ @project-hash@ +-- @file-revision@ @file-hash@ +-- Created: 3/12/2016 12:49 AM +local B, _G = select(2,...).frame, _G +local M = B:RegisterModule("Options") +local tostring, tonumber, floor, format = tostring, tonumber, floor, string.format +local unpack, select, pairs, ipairs, type, wipe = unpack, select, pairs, ipairs, type, table.wipe +local CreateFrame, IsControlKeyDown = _G.CreateFrame, _G.IsControlKeyDown +local max = math.max +local OpacitySliderFrame, ColorPickerFrame = _G.OpacitySliderFrame, _G.ColorPickerFrame +local print = B.print('Cfgl') +local function round(number, decimals) + if floor(number) == number then + return ('%d'):format(number) + end + + return (("%%.%df"):format(decimals)):format(number) +end + +--- STATE VARIABLES +local configInit +--- Dummies for addon table upvalues +local configFrames = {} -- actual frame objects +local displays = B.displays -- anchor objects dummy + + +--- Returns a value retreival function and the current value stored in config +-- @paramsig value, previousValue = configInteger(key) +-- @param key Name of the config field being represented. +local defaultGroup = 'BuffButton' +local configInteger = function(group, key) + return function(self ,display) + return floor(tonumber(self:GetValue()) + 0.5) + end, (B.Conf[group ..key] or B.Conf[defaultGroup..key]) +end +local configPercent = function(group, key) + return function(self, display) + local value = self:GetValue() + if display then + return tostring(floor(value*100+0.5))..' %' + else + return floor((value*100+0.5))/100 + end + end, (B.Conf[group ..key] or B.Conf[defaultGroup..key]) +end +local configColor = function(group, key) + -- table for config, color value list for text + return function(self, display) + if display then + return "|cFFFF4444" .. round(self.rgba[1], 1) .. "|r, |cFF44FF44" .. round(self.rgba[2], 1) .. "|r, |cFF4488FF" .. + round(self.rgba[3], 1) .. "|r, " .. round(self.rgba[4], 1) + else + return self.rgba + end + end, (B.Conf[group ..key] or B.Conf[defaultGroup..key]) +end +local configCheck = function(group, key) + return function(self) return self:GetChecked() end, B.Conf[group ..key] or B.Conf[defaultGroup..key] +end +-- initializes the corresponding type of config field +local frameTypeConv = { + Color = 'Button', + Font = 'Frame', +} +local configTypeParams = { + Slider = function(frame, optionInfo) + frame:SetMinMaxValues(optionInfo[5], optionInfo[6]) + frame:SetValueStep(optionInfo[7]) + frame:SetStepsPerPage(optionInfo[8]) + print(frame.OptName, '\n {', optionInfo[5], optionInfo[6], optionInfo[7], optionInfo[8], '}') + end, + CheckButton = function(frame, optionInfo) + frame.SetValue = function(self, ...) + self:SetChecked(...) + B.Conf[self.OptName] = self:GetChecked() + print(self.OptTab) + B.UpdateAll() + end + frame:SetScript("OnClick",function(self) + B.Conf[self.OptName] = self:GetChecked() + print(B.Conf[self.OptName], self:GetChecked()) + B.UpdateAll() + end) + end, + Color = function(frame, optionInfo) + frame.rgba = { frame.current:GetVertexColor() } + local colorPickerCallback = function(restore) + local newR, newG, newB, newA + if restore then + newR, newG, newB, newA = unpack(restore) + else + newA, newR, newG, newB = OpacitySliderFrame:GetValue(), ColorPickerFrame:GetColorRGB() + print('not cancel', newA, newR, newB, newG) + end + frame:SetValue({newR, newG, newB, newA}) + B.UpdateBuffs(frame.OptTab) + end + frame:SetScript("OnClick", function(self) + print('got a click') + local r, g, b, a = frame.current:GetVertexColor() + ColorPickerFrame:SetColorRGB(r, g, b) + ColorPickerFrame.hasOpacity = (a ~= nil) + ColorPickerFrame.opacity = a + ColorPickerFrame.previousValues = {r,g,b,a} + ColorPickerFrame.func, ColorPickerFrame.opacityFunc, ColorPickerFrame.cancelFunc = + colorPickerCallback, colorPickerCallback,colorPickerCallback + ColorPickerFrame:Hide() + ColorPickerFrame:Show() + end) + frame.SetValue = function(self, rgba) + print(rgba) + frame.rgba = rgba + B.Conf[self.OptName] = rgba + frame.current:SetVertexColor(unpack(rgba)) + frame.fieldvalue:SetText(frame.OptValue(frame, true)) + end + end +} +--- configDialog +-- @usage tinsert(configDialog, {prefix, row, [...] }) +-- Each top level member defines a group of config value handlers, structured as an iterative table where the +-- first member is a key prefix, the second member is an integer row value, and all following members are treated +-- as a widget resource, defined initially as a complete sub-table, which can be re-used further down by passing +-- the string literal widget suffix. +-- widget table: ... {'suffix', 'description', valueCallback, 'template', [widget parameters]} +-- widget copy: ... 'suffix', ... +local configDialog = { + {'BuffButton', 1, + + {'Max', 'Max', configInteger, 'Slider', + 1, _G.BUFF_MAX_DISPLAY, 1, 1}, -- valueMin, valueMax, valueStep, stepsPerPage + {'PerRow', 'Per Row', configInteger, 'Slider', + 1, _G.BUFF_MAX_DISPLAY, 1, 1}, -- valueMin, valueMax, valueStep, stepsPerPage, + {'Size', 'Icon Size', configInteger, 'Slider', + 1, 256, 1, 1}, + {'Spacing', 'Icon Spacing', configInteger, 'Slider', + 1, 50, 1, 1}, + {'DurationSize', 'Duration Text Height', configInteger, 'Slider', + 1, 72, 1, 1}, + {'Zoom', 'Icon Zoom', configInteger, 'Slider', + 0, 100, 1, 1}, + {'Border', 'Border', configInteger, 'Slider', + 1, 16, 1, 1}, + {'Color', 'Default Border', configColor, 'Color'}, + {'RaidColor', 'RaidBuff Border', configColor, 'Color'}, + {'PlayerColor', 'Player Buffs', configColor, 'Color'}, + {'BossColor', 'Encounter Buffs', configColor, 'Color'}, + {'ShowSelfCast', 'Show name for self-casts', configCheck, 'CheckButton'} + }, + { 'DebuffButton', 1, + {'Max', 'Max', configInteger, 'Slider', + 1, _G.DEBUFF_MAX_DISPLAY, 1, 1 } + , + {'PerRow', 'Per Row', configInteger, 'Slider', + 1, _G.DEBUFF_MAX_DISPLAY, 1, 1 }, + 'Size', 'Spacing', 'DurationSize', 'Zoom', 'Border', + 'Color', 'RaidColor', 'PlayerColor', 'BossColor', + }, + { 'TempEnchant', 1, + {'Max', 'Max', configInteger, 'Slider', + 1, _G.NUM_TEMP_ENCHANT_FRAMES, 1, 1 }, + {'PerRow', 'Per Row', configInteger, 'Slider', + 1, _G.NUM_TEMP_ENCHANT_FRAMES, 1, 1}, + 'Size', 'Spacing', 'DurationSize', 'Zoom', 'Border', + 'Color', 'RaidColor', 'PlayerColor', 'BossColor', + }, + { 'ConsolidatedBuff', 2, + {'Position', 'Slot Position', configInteger, 'Slider', + 1, _G.BUFF_MAX_DISPLAY, 1, 1 } + + }, + { 'ConsolidatedBuff', 2, + 'Size' + }, + { 'Raid', 3, + {'ShowMissing', 'Verbose missing raid buffs', configCheck, 'CheckButton'} + } +} + + + + +local configFrame +local optionTemplates = {} +local configPadding, configSpacing = 3, 3 + +--- Walks the structure table to generate a pretty config panel +local InitConfig = function() + configInit = true + local configWidth = B:GetWidth() + local optionWidth = (configWidth - configPadding) / 3 - configSpacing + local configHeight = 0 + local bottom_extent = 0 + local clusterHeight = 0 + local clusterOffset = 0 + local lastCluster + local cluster = 1 + local col = 0 + for t, taboptions in ipairs(configDialog) do + local group = taboptions[1] + cluster = taboptions[2] + col = col + 1 + + + if not configFrames[t] then + configFrames[t] = {} + end + + + if cluster ~= lastCluster then + configHeight = configHeight + clusterHeight + print('|cFFFF8800## new cluster|r, advancing offset from', clusterOffset, 'to', clusterOffset + clusterHeight) + clusterOffset = clusterOffset + clusterHeight + col = 1 + clusterHeight = 0 + lastCluster = cluster + end + + print('processing tab', group) + local row = 0 + for i = 3, #taboptions do + row = row + 1 + local optionInfo = taboptions[i] + if type(optionInfo) == 'string' then + optionInfo = optionTemplates[optionInfo] + end + local key, fieldname, valueFuncGenerator, configType = unpack(optionInfo) + + if not optionTemplates[key] then + optionTemplates[key] = optionInfo + end + + local fullkey = group .. key + print(fullkey, fieldname) + + if not configFrames[t][row] then + print('building frame', t, group, row) + local frameTemplate = 'VeneerConfig'..configType + local frameType = frameTypeConv[configType] or configType + configFrames[t][row] = CreateFrame(frameType, fullkey, B, frameTemplate) + local f = configFrames[t][row] + f.OptKey = key + f.OptTab = group + f.OptName = fullkey + local valueFunc, initialValue = valueFuncGenerator(group, key) + print(' value getter', fullkey,'->', valueFunc,initialValue) + configTypeParams[configType](f, optionInfo) + f.OptValue = valueFunc + + --- Enclosing these to + -- a) make the panel easy to bring up externally + -- b) limit gameplay risk from config frame errors + -- c) milk the iterator scope for all its worth + f.OnChange = function(self) + + -- holding control; mirror this setting in other categories + if IsControlKeyDown() and not (configInit) then + configInit = true + for optTab, opts in pairs(configFrames) do + for _, opt in ipairs(opts) do + if opt.OptKey == key then + if optTab ~= group then + print('mapping to', optTab, opt.OptKey) + opt:SetValue(self:GetValue()) + end + + end + end + end + configInit = nil + end + local newValue = valueFunc(self) + if newValue ~= B.Conf[fullkey] then + print(newValue, fullkey) + f.fieldvalue:SetText(valueFunc(self, true)) + B.Conf[fullkey] = valueFunc(self) + -- prepare to update + wipe(B.drawn[f.OptTab]) + B.UpdateBuffs(self.OptTab) + B.UpdateConfigLayers() + end + + end + + f:SetValue(initialValue) + local yBuffer = configPadding + if f.fieldname then + f.fieldname:SetText(fieldname) + yBuffer = yBuffer + f.fieldname:GetHeight() + end + if f.fieldvalue then + f.fieldvalue:SetText(f:OptValue(true)) + end + + local point, relative, x, y = 'TOPLEFT', 'BOTTOMLEFT', 0, -3 + + local base + if (row == 1) then + bottom_extent = 0 + base = B.header + x = (col-1) * (optionWidth+configSpacing) + y = -configPadding + else + base = configFrames[t][row-1] + end + + print('|cFFFF0088'..cluster..'|r |cFF00FF00'.. row..'|r', col, base:GetName(), x, y - clusterOffset) + + if frameType ~= 'CheckButton' then + f:SetWidth(optionWidth) + end + + f:SetPoint(point, base, relative, x, y-yBuffer-clusterOffset) + --print('creating', frameType, fieldname) + f:Show() + + bottom_extent = bottom_extent + f:GetHeight() + yBuffer + configSpacing + + + + clusterHeight = max(clusterHeight, bottom_extent) + --print('y', floor(yBuffer+0.5), 'f:H', floor(f:GetHeight()+0.5), 'hTally', floor(bottom_extent+0.5), 'hMax', floor(configHeight+0.5)) + end + end + end + + -- grab the last cluster + if lastCluster == cluster then + print('|cFF00FF00##scooping up last cluster info') + configHeight = configHeight + clusterHeight + end + + if not B.configFramesCreated then + B.configFramesCreated = true + B:SetHeight(B.header:GetStringHeight() + configSpacing*3 + configHeight) + end + if configInit then configInit = nil end +end + +M.Command = function(enable, editbox) + displays = B.displays + if type(enable) == 'boolean' then + B.Conf.ConfigMode = enable + else + B.Conf.ConfigMode = (B.Conf.ConfigMode == false) and true or false + end + + print('/BUFF', B.Conf.ConfigMode, type(B.Conf.ConfigMode)) + if B.Conf.ConfigMode then + if not B.configFramesCreated then + InitConfig() + end + print('Veneer config') + B:Show() + else + B:Hide() + end + B.UpdateAll() + B.UpdateConfigLayers() +end + +B.Close = function () + M.Command() +end + +B.ToggleGuides = function(_, self) + B.Conf.GuidesMode = (not B.Conf.GuidesMode) + if B.Conf.GuidesMode then + self:GetNormalTexture():SetTexture(0.94, 0.21, 0.21, 1) + else + self:GetNormalTexture():SetTexture(0, 0, 0, 1) + end + + B.UpdateConfigLayers() +end + +M.OnEnable = function() + M.Command(B.Conf.ConfigMode) +end + +M.OnInitialize = function() + DEFAULT_CHAT_FRAME:AddMessage("|cFF22D822Veneer|r") + SLASH_BUFFALO1, SLASH_BUFFALO2 = "/buffalo", "/buff" + SlashCmdList.BUFFALO = M.Command + +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Constants.lua Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,347 @@ +--- ${PACKAGE_NAME} +-- @file-author@ +-- @project-revision@ @project-hash@ +-- @file-revision@ @file-hash@ +-- Created: 3/22/2016 3:14 PM +local _, A = ... +local B = A.frame + +----------------------- +-- Buff frames metadata +----------------------- +local legendAlpha = 0.5 +B.displays.BuffButton = { + legendColor = {0, 1, 0, legendAlpha}, + maxIcons = BUFF_MAX_DISPLAY, + actualIcons = function () return _G.BUFF_ACTUAL_DISPLAY end, + buffName = 'BuffButton', + drawCount = {}, + filters = 'HELPFUL', + anchorTemplate = 'VeneerAnchorTemplate', +} +B.displays.DebuffButton = { + legendColor = {1, 0, 0, legendAlpha}, + maxIcons = DEBUFF_MAX_DISPLAY, + actualIcons = function () return _G.DEBUFF_ACTUAL_DISPLAY end, + buffName = 'DebuffButton', + drawCount = {}, + filters = 'HARMFUL', + anchorTemplate = 'VeneerAnchorTemplate', +} +B.displays.TempEnchant = { + legendColor = {1, 0, 0.5, legendAlpha}, + maxIcons = NUM_TEMP_ENCHANT_FRAMES, + actualIcons = function () return BuffFrame.numEnchants end, + buffName = 'TempEnchant', + drawCount = {}, + anchorTemplate = 'VeneerAnchorTemplate', +} +B.displays.ConsolidatedBuff = { + legendColor = {0.5, 0.5, 0.5, legendAlpha}, + maxIcons = 9, + actualIcons = function() return select(2, GetRaidBuffInfo()) end, + buffName = 'ConsolidatedBuff', + anchorTemplate = 'VeneerConsolidatedBuffsAnchor', + buffTemplate = 'VeneerRaidBuffTemplate', + drawCount = {}, + filters = 'HELPFUL', +} + +----------------------- +-- RaidBuff visual args +----------------------- +B.BuffStyles = { + ["active"] = { + SetDesaturated = false, + Color = {1, 1, 1, 1}, + SetBlendMode = 'BLEND', + TextColor = {1,1,1,1}, + }, + ["missing"] = { + SetDesaturated = false, + Color = {1, 0, 0, 0.5}, + SetBlendMode = 'ADD', + TextColor = {1,0,0,1}, + }, + ["available"] = { + SetDesaturated = true, + Color = {0.35, 1, 0.35, 0.5}, + SetBlendMode = 'ADD', + TextColor = {1, 1, 0, 1}, + }, +} + +--- RaidBuff availability criteria +-- @field spellID - UnitAura() == true +-- @field spec - test for spec choice +-- @field auraType - UnitAura() == true, and no other tests of the same value have returned true prior +-- @field talent - test for talent selection +-- @field petFamily - test pet family +-- @field [true] - passive group aura +B.ClassRaidBuffs = { + -- stats + [1] = { + ['HUNTER'] = { + {talent = {155228}, spellID = 160206, spellName = 'Lone Wolf: Power of the Primates', auraType = 'lonewolf'}, + {petFamily = 'Dog'}, -- active pet family + {petFamily = 'Gorilla'}, + {petFamily = 'Shale Spider'}, + {petFamily = 'Worm'}, + }, + ['DRUID'] = { + {spellID = 1126, spellName = 'Mark of the Wild'}, + }, + ['MONK'] = { + {spellID = 115921, spellName = 'Legacy of the Emperor'}, + {spellID = 116781, spellName = 'Legacy of the White Tiger'} -- windwalker, replaces emperor internally + }, + ['PALADIN'] = {spellID = 20217, spellName = 'Blessing of Kings', auraType = 'blessing'}, + }, + + -- stamina + [2] = { + ['HUNTER'] = { + {talent = {155228}, spellID = 160199, spellName = 'Lone Wolf: Fortitude of the Bear', auraType = 'lonewolf'}, + {petFamily = 'Bear'}, -- active pet family + {petFamily = 'Goat'}, + {petFamily = 'Rylak'}, + {petFamily = 'Silithid'}, + }, + ['PRIEST'] = { + {spellID = 21562, 'Power Word: Fortitude'} + }, + ['WARRIOR'] = { + {spellID = 469, spellName = 'Commanding Shout', auraType = 'shout'} + }, + ['WARLOCK'] = { + {true} + } + }, + + -- attack power + [3] = { + ['HUNTER'] = { + {true}, + }, + ['DEATHKNIGHT'] = { + {spec = 2}, + {spec = 3}, + }, + ['WARRIOR'] = { + {spellName = 'Battle Shout', auraType = 'shout'} + } + }, + + -- HASTE + [4] = { + ['HUNTER'] = { + {talent = {155228}, spellID = 160203, spellName = 'Lone Wolf: Haste of the Hyena', auraType = 'lonewolf'}, + {petFamily = 'Hyena'}, -- active pet family + {petFamily = 'Sporebat'}, + {petFamily = 'Rylak'}, + {petFamily = 'Wasp'}, + }, + ['DEATHKNIGHT'] = { + {spec = 2}, -- unholy aura + {spec = 3}, + }, + ['PRIEST'] = { + {spec = 3}, -- mind quickening + }, + ['ROGUE'] = { + true -- swiftblade's + }, + ['SHAMAN'] = { + true -- grace of air + }, + }, + + -- SPELL POWER + [5] = { + ['HUNTER'] = { + {talent = {155228}, spellID = 160205, spellName = 'Lone Wolf: Wisdom of the Serpent', auraType = 'lonewolf'}, + {petFamily = 'Waterstrider'}, -- active pet family + {petFamily = 'Serpent'}, + {petFamily = 'Silithid'}, + }, + ['MAGE'] = { + {spellID = 1459, spellName = 'Arcane Brilliance'}, -- arcane brilliance + {spellID = 61316, spellName = 'Dalaran Brilliance'}, -- dalaran brilliance + }, + ['WARLOCK'] = { + {spellID = 109773,spellName = 'Dark Intent' } + }, + }, + + -- CRITICAL STRIKE + [6] = { + ['HUNTER'] = { + {talent = {155228}, spellID = 160200, spellName = 'Lone Wolf: Ferocity of the Raptor', auraType = 'lonewolf'}, + {petFamily = 'Devilsaur'}, -- active pet family + {petFamily = 'Quilen'}, + {petFamily = 'Raptor'}, + {petFamily = 'Shale Spider'}, + {petFamily = 'Waterstrider'}, + {petFamily = 'Wolf'}, + }, + ['DRUID'] = { + {spec = 2, spellID = 17007, auraType = 'druidform'} + }, + ['MAGE'] = { + {spellID = 1459, spellName = 'Arcane Brilliance'}, -- arcane brilliance + {spellID = 61316, spellName = 'Dalaran Brilliance'}, -- dalaran brilliance + }, + ['MONK'] = { + {spellID = 116781, spellName = 'Legacy of the White Tiger', spec = 2} -- windwalker + } + }, + + -- MASTERY + [7] = { + ['HUNTER'] = { + {talent = {155228}, spellID = 160198, spellName = 'Lone Wolf: Grace of the Cat', auraType = 'lonewolf'}, + {petFamily = 'Cat'}, -- active pet family + {petFamily = 'Hydra'}, + {petFamily = 'Spirit Beast'}, + {petFamily = 'Tallstrider'}, + }, + ['DEATHKNIGHT'] = { + {spec = 1} + }, + ['DRUID'] = { + {spec = 1, spellID = 24907, auraType = 'druidform'}, + }, + ['PALADIN'] = { + {spec = 1, spellID = 19740, spellName = 'Blessing of Might', auraType = 'blessing'} + }, + ['SHAMAN'] = {true}, + }, + + -- MULTISTRIKE + [8] = { + ['HUNTER'] = { + {talent = {155228}, spellID = 172968, spellName = 'Lone Wolf: Quickness of the Dragonhawk', auraType = 'lonewolf'}, + {petFamily = 'Bat'}, -- active pet family + {petFamily = 'Clefthoof'}, + {petFamily = 'Corehound'}, + {petFamily = 'Dragonhawk'}, + {petFamily = 'Wind Serpent'}, + }, + ['MONK'] = { + {spec = 2 } + }, -- Windflurry, + ['PRIEST'] = { + {spec = 3 } + }, -- quickening, + ['ROGUE'] = {true}, -- swiftblade's + ['WARLOCK'] = { + {spellID = 109773,spellName = 'Dark Intent' } + }, + }, + + -- VERSATILITY + [9] = { + ['HUNTER'] = { + {talent = {155228}, spellID = 172967, spellName = 'Lone Wolf: Versatility of the Ravager', auraType = 'lonewolf'}, + {petFamily = 'Ravager'}, -- active pet family + {petFamily = 'Boar'}, + {petFamily = 'Porcupine'}, + {petFamily = 'Clefthoof'}, + {petFamily = 'Stag'}, + {petFamily = 'Worm'}, + {petFamily = 'Bird of Prey'}, + }, + ['DEATH KNIGHT'] = { + {spec = 2}, -- unholy aura + {spec = 3}, + }, + ['DRUID'] = { + {spellID = 1126, spellName = 'Mark of the Wild'}, + }, + ['PALADIN'] = { + {spec = 2}, -- retribution + }, + ['WARRIOR'] = { + {spec = 2}, -- arms or fury + {spec = 3}, + }, + } +} + +------------------------- +-- Default config values +------------------------- +B.ConfDefaults = { + -- defaulted to on for first-time setup + ConfigMode = true, + GuidesMode = true, + + BuffButtonAnchor = {'TOPRIGHT', 'UIParent', 'TOPRIGHT', -200, -5}, + BuffButtonMax = 24, + BuffButtonPerRow = 10, + BuffButtonSize = 50, + BuffButtonSpacing = 4, + BuffButtonZoom = 15, + BuffButtonVertexColor = {}, + BuffButtonPoint = {'TOPRIGHT', 'TOPRIGHT'}, + BuffButtonDurationSize = 16, + BuffButtonDurationPoint = {'BOTTOM', 'BOTTOM', 0, -1}, + BuffButtonCountSize = 18, + BuffButtonCountPoint = {'TOPRIGHT', 'TOPRIGHT', -3, -3}, + BuffButtonRelativeX = -1, + BuffButtonRelativeY = -1, + + BuffButtonColor = {1, 1, 1, 1}, + BuffButtonPlayerColor = {1,1,1,1}, + BuffButtonRaidColor = {0.25,1,0.25,1}, + BuffButtonBossColor = {1,0.5,0,1}, + BuffButtonBorder = 1, + + BuffButtonWarningFade = true, + BuffButtonShowSelfCast = true, + + DebuffButtonAnchor = {'TOPRIGHT', 'UIParent', 'TOPRIGHT', -200, -200}, + DebuffButtonMax = 12, + DebuffButtonPerRow = 10, + DebuffButtonSize = 50, + DebuffButtonSpacing = 4, + DebuffButtonDurationSize = 16, + DebuffButtonZoom = 15, + DebuffButtonVertexColor = {}, + DebuffButtonPoint = {'TOPRIGHT','TOPRIGHT'}, + DebuffButtonRelativeX = -1, + DebuffButtonRelativeY = -1, + + + TempEnchantAnchor = {'TOPRIGHT', 'UIParent', 'TOPRIGHT', -200, -300}, + TempEnchantMax = 2, + TempEnchantPerRow = 10, + TempEnchantSize = 50, + TempEnchantSpacing = 4, + TempEnchantDurationSize = 16, + TempEnchantZoom = 15, + TempEnchantVertexColor = {}, + TempEnchantPoint = {'TOPRIGHT', 'TOPRIGHT'}, + TempEnchantRelativeX = -1, + TempEnchantRelativeY = -1, + TempEnchantColor = {1,0,0.5,1}, + + ConsolidatedBuffAnchor = {'TOPRIGHT', 'UIParent', 'TOPRIGHT', 0, 0}, + ConsolidatedBuffIcon = false, + ConsolidatedBuffMax = 9, + ConsolidatedBuffSize = 16, + ConsolidatedBuffParent = 'BuffButton', + ConsolidatedBuffPosition = 1, + ConsolidatedBuffSpacing = 1, + ConsolidatedBuffBorder = 0, + ConsolidatedBuffPerRow = 3, + ConsolidatedBuffPoint = {'TOPRIGHT', 'TOPRIGHT'}, + ConsolidatedBuffRelativeX = -1, + ConsolidatedBuffRelativeY = -1, + ConsolidatedBuffDurationSize = 0, + ConsolidatedBuffDurationPoint = {'BOTTOM', 'BOTTOM', 0, 0}, + ConsolidatedBuffCountPoint = {'BOTTOM', 'BOTTOM', 0, 0}, + + RaidShowMissing = true, + +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core.xml Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,477 @@ +<Ui> + <Font name="VeneerFont" /> + + <Font name="VeneerFont_Small" font="Fonts\FRIZQT__.TTF" outline="NORMAL" height="16" /> + <Font name="VeneerFont_Large" font="Fonts\FRIZQT__.TTF" outline="NORMAL" height="24" /> + + <Font name="VeneerFontNormal" inherits="VeneerFont_Small"> + <Color r="1" g="1" b="1" a="1" /> + </Font> + + <Font name="VeneerFontHighlight" inherits="VeneerFont_Small" outline="NORMAL"> + <Color r="0" g=".7" b="1" a="1" /> + </Font> + <Font name="VeneerFontHighlightLarge" inherits="VeneerFont_Large"> + <Color r="0" g=".7" b="1" a="1" /> + </Font> + + <!-- Defining here so interfaces are easy to spot --> + <Frame name="VeneerHandlerTemplate" virtual="true"> + <KeyValues> + </KeyValues> + </Frame> + + <!-- Buff-button underlay --> + <Frame name="VeneerDecorTemplate" virtual="true" enableMouse="true" movable="true" frameStrata="BACKGROUND" hidden="true"> + <Size x="30" y="30" /> + <Layers> + <Layer level="BACKGROUND"> + <Texture name="$parentButtonArea" setAllPoints="true" parentKey="background" alphaMode="BLEND"> + <Color r="1" g="1" b="1" a="1" /> + </Texture> + <Texture name="$parentButtonBackdrop" parentKey="backgroundFill" alphaMode="BLEND"> + <Anchors> + <Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT" x="1" y="1" relativeKey="$parent.background" /> + <Anchor point="TOPRIGHT" relativePoint="TOPRIGHT" x="-1" y="-1" relativeKey="$parent.background" /> + </Anchors> + <Color r="0" g="0" b="0" a="1" /> + </Texture> + </Layer> + </Layers> + </Frame> + + <!-- Buff button overlay, and positioning anchor --> + <Frame name="VeneerGuideTemplate" virtual="true" movable="true" frameStrata="LOW"> + <Scripts> + <OnShow> + self.mouseover = self:IsMouseOver() + </OnShow> + <OnUpdate> + if self:IsMouseOver() and not self.contains then + self.caster:Show() + else + self.caster:Hide() + end + </OnUpdate> + </Scripts> + <Layers> + <Layer level="ARTWORK"> + <Texture name="$parentLegend" parentKey="legend" parentArray="config" setAllPoints="true" hidden="true"> + <Color a="0.5" r="0" g="1" b="0" /> + </Texture> + <Texture name="$parentCountLegend" parentKey="count" parentArray="config" hidden="true"> + <Color a="0.75" r="1" g=".5" b="0" /> + </Texture> + + + <Texture name="$parentIconArea" parentKey="icon" alphaMode="ADD"> + <Color r="0" g="0" b="0" a="0" /> + </Texture> + <Texture name="$parentTextLegend" parentKey="duration" parentArray="config" hidden="true" alphaMode="BLEND"> + <Color a="0.25" r="1" g="1" b="1" /> + </Texture> + </Layer> + <Layer level="OVERLAY"> + <FontString inherits="VeneerFontNormal" parentArray="config" name="$parentID" parentKey="idText" hidden="true" outline="NORMAL"> + <Anchors> + <Anchor point="CENTER" /> + </Anchors> + </FontString> + <FontString inherits="VeneerFontNormal" parentKey="caster" outline="NORMAL"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeKey="$parent.icon" /> + </Anchors> + </FontString> + </Layer> + <Layer level="HIGHLIGHT"> + + </Layer> + </Layers> + </Frame> + + <!-- Anchor frame orientation-setting widget; click handler copies frame anchors over to buff buttons --> + <Button name="VeneerAnchorButton" virtual="true" parentArray="anchorButton" hidden="true"> + <Scripts> + <OnClick> + self:GetParent():SetChildAnchors(self) + </OnClick> + </Scripts> + <Size x="15" y="15" /> + <Layers> + <Layer level="BACKGROUND"> + <Texture setAllPoints="true"> + <Color r="0" g="0" b="0" a="1" /> + </Texture> + </Layer> + <Layer level="OVERLAY"> + <Texture> + <Color r="0" g="1" b="0.5" a="1" /> + <Anchors> + <Anchor point="BOTTOMLEFT" x="1" y="1" /> + <Anchor point="TOPRIGHT" x="-1" y="-1" /> + </Anchors> + </Texture> + </Layer> + </Layers> + </Button> + + <Frame name="VeneerAnchorTemplate" virtual="true" enableMouse="false" movable="true" sizable="true" clampedToScreen="true"> + <Layers> + <Layer level="BACKGROUND"> + <Texture name="$parentBackground" setAllPoints="true" parentArray="config" hidden="true"> + <Color r="0" g="0.2" b="1" a="0.2" /> + </Texture> + <FontString name="$parentHeading" inherits="VeneerFontHighlight" parentArray="config" parentKey="heading" hidden="true"> + <Anchors> + <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" /> + </Anchors> + </FontString> + <FontString name="$parentDebug" inherits="VeneerFontNormal" parentArray="debug" parentKey="debug"> + <Anchors> + <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" /> + </Anchors> + </FontString> + </Layer> + <Layer level="OVERLAY"> + + <Texture name="$parentCutJoint" parentKey="alignedJoint" hidden="true"> + <Size x="4" y="4" /> + <Color r="1" g="0" b="0" a="1" /> + </Texture> + <Texture name="$parentCutY" parentKey="cuttingJointX" hidden="true"> + <Size x="4" y="48" /> + <Color r="1" g="1" b="0" a="1" /> + </Texture> + <Texture name="$parentCutX" parentKey="cuttingJointY" hidden="true"> + <Size x="48" y="4" /> + <Color r="1" g="1" b="0" a="1" /> + </Texture> + <Texture name="$parentPoppedY" parentKey="poppingJointX" hidden="true"> + <Size x="4" y="48" /> + <Color r="0" g="1" b="1" a="1" /> + </Texture> + <Texture name="$parentPoppedX" parentKey="poppingJointY" hidden="true"> + <Size x="48" y="4" /> + <Color r="0" g="1" b="1" a="1" /> + </Texture> + <Texture name="$parentChildSpace" parentKey="childSpace" hidden="true"> + <Color r="0" g=".5" b="1" a="0.5" /> + </Texture> + </Layer> + <Layer level="HIGHLIGHT"> + <Texture name="$parentHighlight" setAllPoints="true" parentArray="config" hidden="true"> + <Color r="1" g="1" b="0" a="0.2" /> + </Texture> + </Layer> + </Layers> + <Frames> + <Button name="$parentAnchorUL" inherits="VeneerAnchorButton"> + <Anchors> + <Anchor point="TOPLEFT" /> + </Anchors> + </Button> + <Button name="$parentAnchorUR" inherits="VeneerAnchorButton"> + <Anchors> + <Anchor point="TOPRIGHT" /> + </Anchors> + </Button> + <Button name="$parentAnchorUR" inherits="VeneerAnchorButton"> + <Anchors> + <Anchor point="BOTTOMRIGHT" /> + </Anchors> + </Button> + <Button name="$parentAnchorUR" inherits="VeneerAnchorButton"> + <Anchors> + <Anchor point="BOTTOMLEFT" /> + </Anchors> + </Button> + </Frames> + </Frame> + + <Frame name="VeneerConsolidatedBuffsAnchor" inherits="VeneerAnchorTemplate" virtual="true"> + <Layers> + <Layer level="OVERLAY"> + <!-- need to make our own number label since the original is buried under secure layer --> + <FontString inherits="VeneerFontNormal" name="$parentLabel" parentKey="label"> + <Anchors> + <Anchor point="TOP" relativePoint="BOTTOM" x="0" y="-2" /> + </Anchors> + </FontString> + <!-- + <Texture name="$parentBackdrop" parentKey="background" setAllPoints="true" alphaMode="BLEND"> + <Color r="0" g="0" b="0" a="1" /> + <Anchors> + <Anchor point="BOTTOMLEFT" x="1" y="1" /> + <Anchor point="TOPRIGHT" x="-1" y="-1" /> + </Anchors> + </Texture> + <Texture name="$parentIcon" parentKey="border" setAllPoints="true" alphaMode="BLEND"> + <Color r="1" g="1" b="1" a="1" /> + </Texture> + --> + </Layer> + </Layers> + </Frame> + + <Frame name="VeneerRaidBuffTemplate" virtual="true" enableMouse="false"> + <Layers> + <Layer level="ARTWORK"> + <Texture name="$parentLegend" parentKey="legend" parentArray="config" setAllPoints="true" hidden="true"> + <Color a="0.5" r="0" g="1" b="0" /> + </Texture> + <Texture name="$parentCountLegend" parentKey="count" parentArray="config" hidden="true"> + <Color a="0.75" r="1" g=".5" b="0" /> + </Texture> + + + <Texture name="$parentIconArea" parentKey="icon" alphaMode="ADD"> + <Color r="0" g="0" b="0" a="0" /> + </Texture> + <Texture name="$parentTextLegend" parentKey="duration" parentArray="config" hidden="true" alphaMode="BLEND"> + <Color a="0.25" r="1" g="1" b="1" /> + </Texture> + </Layer> + <Layer level="OVERLAY"> + <FontString inherits="VeneerFontNormal" parentArray="config" name="$parentSymbol" parentKey="symbol"> + <Anchors> + <Anchor point="TOP" /> + </Anchors> + </FontString> + <FontString inherits="VeneerFontNormal" parentArray="config" name="$parentID" parentKey="idText" hidden="true"> + <Anchors> + <Anchor point="BOTTOM" /> + </Anchors> + </FontString> + </Layer> + </Layers> + </Frame> + + <Button name="VeneerMissingBuffTemplate" virtual="true"> + <Scripts> + <OnClick> + if self.spell and not InCombatLockdown() then + CastSpellByID(self.spell) + end + </OnClick> + </Scripts> + <Layers> + <Layer level="BORDER"> + <Texture setAllPoints="true"> + <Color r="1" g="1" b="1" a="0.25" /> + </Texture> + </Layer> + <Layer level="ARTWORK"> + <Texture name="$parentIcon" parentKey="icon"> + <Size x="20" y="20" /> + <Anchors> + <Anchor point="LEFT" /> + </Anchors> + </Texture> + </Layer> + <Layer level="OVERLAY"> + <FontString name="$parentLabel" parentKey="label" inherits="VeneerFontNormal" justifyH="LEFT"> + <Anchors> + <Anchor point="LEFT" relativePoint="RIGHT" relativeKey="icon" /> + </Anchors> + </FontString> + </Layer> + </Layers> + </Button> + + <FontString virtual="true" name="VeneerFieldName" parentKey="fieldname" inherits="VeneerFontHighlight" justifyV="TOP" justifyH="LEFT" /> + <FontString virtual="true" name="VeneerFieldValue" parentKey="fieldvalue" inherits="VeneerFontNormal" justifyV="TOP" justifyH="LEFT" /> + <Slider virtual="true" orientation="HORIZONTAL" name="VeneerConfigSlider"> + <Size x="250" y="18" /> + <Thumbtexture name="$parentThumb" alphaMode="BLEND" parentKey="thumb"> + <Size x="12" y="18" /> + <Color r="0.25" g="0.25" b="0.25" a="1" /> + </Thumbtexture> + <Layers> + <Layer level="BACKGROUND"> + <Texture> + <Anchors> + <Anchor point="LEFT" /> + <Anchor point="RIGHT" /> + </Anchors> + <Size y="7" /> + <Color r="0" g="0" b="0" a="1" /> + </Texture> + + </Layer> + <Layer level="OVERLAY"> + + + <FontString name="$parentOptText" inherits="VeneerFieldName"> + <Anchors> + <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" /> + </Anchors> + </FontString> + + <FontString name="$parentOptText" inherits="VeneerFieldValue"> + <Anchors> + <Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT" x="0" y="0" /> + </Anchors> + </FontString> + </Layer> + </Layers> + <Scripts> + <OnValueChanged> + self:OnChange() + </OnValueChanged> + </Scripts> + </Slider> + + <CheckButton virtual="true" orientation="HORIZONTAL" name="VeneerConfigCheckButton"> + <Size x="24" y="24" /> + <NormalTexture file="Interface\Buttons\UI-CheckBox-Up"/> + <PushedTexture file="Interface\Buttons\UI-CheckBox-Down"/> + <HighlightTexture file="Interface\Buttons\UI-CheckBox-Highlight" alphaMode="ADD"/> + <CheckedTexture file="Interface\Buttons\UI-CheckBox-Check"/> + <Layers> + <Layer level="BACKGROUND"> + <Texture setAllPoints="true"> + <Size y="24" /> + <Color r="0" g="0.7" b="1" a="1" /> + </Texture> + + <FontString name="$parentOptText" inherits="VeneerFieldName" > + <Anchors> + <Anchor point="LEFT" relativePoint="LEFT" x="24" y="0" /> + </Anchors> + </FontString> + + </Layer> + </Layers> + <Scripts> + <OnValueChanged> + self:OnChange() + </OnValueChanged> + </Scripts> + </CheckButton> + + + <Button virtual="true" name="VeneerConfigColor"> + <Size x="400" y="20" /> + <Layers> + <Layer level="BACKGROUND"> + <Texture setAllPoints="true"> + <Color r="0.15" g="0.15" b="0.15" a="0.5" /> + </Texture> + <Texture> + <Anchors> + <Anchor point="BOTTOMLEFT" x="0" y="0" /> + </Anchors> + <Size x="18" y="18" /> + <Color r="0" g="0" b="0" a="1" /> + </Texture> + </Layer> + <Layer level="ARTWORK"> + <Texture name="$parentCurrentColor" parentKey="current"> + <Anchors> + <Anchor point="BOTTOMLEFT" x="1" y="1" /> + </Anchors> + <Size x="16" y="16" /> + <Color r="1" g="1" b="1" a="1" /> + </Texture> + </Layer> + <Layer level="OVERLAY"> + + <FontString name="$parentOptText" inherits="VeneerFieldName"> + <Anchors> + <Anchor point="BOTTOMLEFT" relativePoint="TOPLEFT" x="0" y="0" /> + </Anchors> + </FontString> + + <FontString parentKey="fieldvalue" name="$parentOptText" inherits="VeneerFontNormal" text=""> + <Anchors> + <Anchor point="CENTER" relativePoint="CENTER" relativeKey="$thumb" x="0" y="0" /> + </Anchors> + </FontString> + + </Layer> + </Layers> + </Button> + + + <Frame name="Veneer" hidden="true" enableMouse="true" movable="true" parent="UIParent"> + <Size x="400" y="400" /> + <Anchors> + <Anchor point="CENTER" relativePoint="CENTER" x="0" y="0" /> + </Anchors> + <Scripts> + <OnLoad> + self:RegisterForDrag('LeftButton') + </OnLoad> + <OnDragStart> + self:StartMoving() + </OnDragStart> + <OnDragStop> + self:StopMovingOrSizing() + </OnDragStop> + </Scripts> + <Layers> + <Layer level="BACKGROUND"> + <Texture setAllPoints="true"> + <Color r="0" g="0" b="0" a="0.7" /> + </Texture> + </Layer> + <Layer level="ARTWORK"> + <FontString name="$parentHeader" parentKey="header" inherits="VeneerFontHighlightLarge" text="Veneer"> + <Anchors> + <Anchor point="TOPLEFT" x="3" y="-4" /> + </Anchors> + </FontString> + </Layer> + </Layers> + <Frames> + <Button name="$parentCloseButton" parentKey="close" text="X"> + <ButtonText inherits="SystemFont_Small" /> + <Scripts> + <OnClick> + self:GetParent():Close() + </OnClick> + </Scripts> + <Size x="24" y="24" /> + <Anchors> + <Anchor point="TOPRIGHT" x="-5" y="-5" /> + </Anchors> + <NormalTexture parentKey="normal" setAllPoints="true"> + <Color a="1" r="0" g="0" b="0" /> + </NormalTexture> + <PushedTexture setAllPoints="true"> + <Color a="1" r="1" g="0" b="0" /> + </PushedTexture> + <HighlightTexture setAllPoints="true" alphaMode="ADD"> + <Color a=".5" r="1" g=".7" b="0.5" /> + </HighlightTexture> + </Button> + <Button name="$parentGuidesButton" parentKey="guides" text="Guides"> + <ButtonText inherits="SystemFont_Small" /> + <Scripts> + <OnClick> + self:GetParent():ToggleGuides(self) + </OnClick> + </Scripts> + <Size x="36" y="24" /> + <Anchors> + <Anchor point="RIGHT" relativePoint="LEFT" relativeTo="$parentCloseButton" x="-5" y="0" /> + </Anchors> + <NormalTexture parentKey="normal" setAllPoints="true"> + <Color a="1" r="0" g="0" b="0" /> + </NormalTexture> + <PushedTexture setAllPoints="true"> + <Color a="1" r="1" g="0" b="0" /> + </PushedTexture> + <HighlightTexture setAllPoints="true" alphaMode="ADD"> + <Color a=".5" r="1" g=".7" b="0.5" /> + </HighlightTexture> + </Button> + </Frames> + </Frame> + + + <Script file="Init.lua" /> + <Script file="Constants.lua" /> + <Script file="Config.lua" /> + +</Ui> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Init.lua Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,371 @@ +--- Modulizer framework +-- OnInitialize +-- OnUpdate +-- OnEnable -- run when GetSpecialization() returns true + +local ADDON, A = ... +Veneer = Veneer or CreateFrame('Frame', 'Veneer', UIParent) +local B = Veneer +local wipe, min, max, random, tinsert = table.wipe, math.min, math.max, math.random, table.insert +local pairs, ipairs, select, unpack, _G = pairs, ipairs, select, unpack, _G +local type, tostring, format = type, tostring, string.format +A.frame = B + +--- Cache tables +local initOnced +local modules = {} +local queuedModules = {} +local moduleStack = { +} + +--- Various region categories +B.displays = {} +B.configLayers = {} +B.configLayersRef = {} + +--@debug@ +--- Generates a print handler pointing to a static channel signature +-- @usage func = B.print(sig) +-- @param sig channel name or number +local printfuncs = {} +B.print = function(pref, ...) + if Devian and Devian.InWorkspace() then + printfuncs[pref] = printfuncs[pref] or function(...) print(pref, ...) end + + return printfuncs[pref] + else + return function () end + end +end + +local rgb = {} +local getcolor = function() + local n, p = 0, 4 + for i = 1, 3 do + rgb[i] = min(random(n,p) * 64, 255) + if rgb[i] == 255 then + p = 4 + elseif rgb[i] > 0 then + n = 2 + end + end + return unpack(rgb) +end + +local color = {} +local fprints = {} +B.fprint = function() + if not (Devian and Devian.InWorkspace()) then + return function() end + end + + + local sig = debugstack(2,1) + if fprints[sig] then + return fprints[sig] + end + + local func = sig:match("%`(%a+)%'") + if not func then + func = sig:match("<(.-)>") + end + func = func:gsub('(%l+)(%u)', function(a, b) return a:sub(0,2) .. b end, 1) + func = func:gsub('^.+%\\', '') + if not func then + func = 'noname' + end + + local r, g, b = getcolor() + color[sig] = color[sig] or format('|cFF%02X%02X%02X%s|r', r, g, b, func) + + --print(color[func] .. ' ( ' .. table.concat(args, ', ')..' )' ) + func = B.print(func) + fprints[sig] = func + return func +end + +--@end-debug@ +--[=[@non-debug@ +B.print = function() end +--@end-non-debug@]=] + +-- for the Mikk script +-- GLOBALS: NUM_LE_RAID_BUFF_TYPES +-- GLOBALS: BUFF_FLASH_TIME_ON, BUFF_FLASH_TIME_OFF, BUFF_MIN_ALPHA, BUFF_WARNING_TIME, BUFF_DURATION_WARNING_TIME +-- GLOBALS: BUFFS_PER_ROW, BUFF_MAX_DISPLAY, BUFF_ACTUAL_DISPLAY, DEBUFF_MAX_DISPLAY, DEBUFF_ACTUAL_DISPLAY, BUFF_ROW_SPACING +-- GLOBALS: CONSOLIDATED_BUFFS_PER_ROW, CONSOLIDATED_BUFF_ROW_HEIGHT, NUM_TEMP_ENCHANT_FRAMES +-- GLOBALS: BUFF_BUTTON_HEIGHT, BUFF_FRAME_BASE_EXTENT, BUFF_HORIZ_SPACING + +local print = B.print('Bfl') + +--- Template for making perpendicular traversals of the displays structure; also makes sure the table is there +B.Abstract = function(dest, key, table) + if table then + for _, v in pairs(dest) do + v[key] = {} + end + end + B[key] = setmetatable({}, { + __index = function(t, k) + return dest[k][key] + end, + __newindex = function(_, k, v) + print('abstract write ('..key..'):', k) + dest[k][key] = v + end, + __tostring = function() return 'Abstract:'..key..'' end + }) + + + return B[key] +end + + +--- localize for speed +local layers, refs, displays = B.configLayers, B.configLayersRef, B.displays + +local ModulesCall = function(func) + + local n = 0 + for i = 1, #moduleStack do + print('calling level '..i) + local stackset = moduleStack[i] + + for name, module in pairs(stackset) do + n = n + 1 + print(n..' '..name..'.'..func..'()') + + + if module[func] then + module[func](module) + end + end + end +end + + +local Enable = function() +end + +--- The things that happen repeatedly +local Init = function () +end + + +--- Things that happen immediately upon entering world +local InitOnce = function() + print('entering world first time') + local defaults = B.ConfDefaults + print('|cFFFFFF00Veneer|r') + if not VeneerData then + VeneerData = {} + for k,v in pairs(defaults) do + VeneerData[k] = v + end + print('Veneer defaults being used.') + end + + B.Conf = setmetatable(VeneerData, {__index = function(_, k) return defaults[k] end}) + + -- suffix tables + for name, display in pairs(displays) do + display.conf = setmetatable({}, { + __index = function(_, k) + --print('config check '.. name .. k) + return B.Conf[name .. k] or B.Conf['BuffButton' .. k] + end, + __newindex = function(_, k , v) + B.Conf[name..k] = v + end, + }) + end + + -- To ensure that modules are run in controlled order, walk the dependency list; if the dep shows up + -- in the loaded manifest, remove the value. If the dep list isn't empty, move that module to the next + -- layer. + local loaded = {} + local stackLevels = #moduleStack + local i = 1 + moduleStack[1] = modules + repeat + print('setting init level '.. i) + local queue = moduleStack[i] + for name, module in pairs(queue) do + + if queuedModules[name] and #queuedModules[name] > 0 then + local p = #queuedModules[name] + for j = 1, p do + local dep = queuedModules[name][j] + + if loaded[dep] then + print( ' ' .. dep .. ' OK') + queuedModules[name][j] = nil + for k = j, p do + print(' shift ' .. (k+1) .. ' ('..tostring(queuedModules[name][k+1])..') to ' .. k ..'') + queuedModules[name][k] = queuedModules[name][k+1] + end + end + end + + if #queuedModules[name] == 0 then + queuedModules[name] = nil + print(' |cFF00FFFF'.. name ..'|r deps OK') + loaded[name] = true + else + + print(' |cFFFF8800' .. name ..'|r pending') + local next = i+1 + if not moduleStack[next] then + moduleStack[next] = {} + end + stackLevels = next + moduleStack[next][name] = module + queue[name] = nil + end + + else + print(' |cFF00FF00'.. name ..'|r no deps') + loaded[name] = true + end + end + i = i + 1 + until i > stackLevels + + + for level, batch in ipairs(moduleStack) do + print('config level', level) + for name, module in pairs(batch) do + print('integrity check', name) + + --[===[@non-debug@ + if module.defaults and not VeneerData[name] then + --@end-non-debug@]===] + print('Adding defaults from module ', name) + VeneerData[name] = module.default + --[===[@non-debug@ + end + --@end-non-debug@]===] + end + end + -- remove from existing +end + +--- Fires an update to all modules +local lastUpdate +function B.UpdateAll(...) + lastUpdate = GetTime() + ModulesCall('OnUpdate', lastUpdate) +end + +B:RegisterEvent('PLAYER_ENTERING_WORLD') +B:SetScript('OnEvent', function(self, event) + if event == 'PLAYER_ENTERING_WORLD' then + if not initOnced then + InitOnce() + ModulesCall('OnInitialize') + initOnced = true + C_Timer.After(1, function() + if GetSpecialization() then + print(GetSpecialization(), 'enabling') + ModulesCall('OnEnable') + B:SetScript('OnUpdate', nil) + end + + end) + end + + end + + B.UpdateAll() +end) + +--- Modulizer method +-- +function B:RegisterModule (name, module, ...) + if modules[name] then + print('pulling modules[|cFFFF8800'.. tostring(name) ..'|r]') + return modules[name] + end + + print('new module |cFF00BBFF'.. tostring(name) ..'|r') + if module then + if modules[name] then + error("Module table for '"..tostring(name).."' already exists.") + end + else + module = CreateFrame('Frame', 'Veneer' .. tostring(name) .. 'Handler', B, 'VeneerHandlerTemplate') + end + modules[name] = module + if select('#', ...) >= 1 then + local numDeps = select('#', ...) + print(' '..numDeps..' deps detected') + for i = 1, numDeps do + local dep = select(i, ...) + -- means that init/enable funcs are ordered to run after deps do their things + queuedModules[name] = queuedModules[name] or {} + tinsert(queuedModules[name], dep) + print(' needs '..dep) + end + end + return module +end + + +B.SetConfigLayers = function(frame) + local print = B.fprint() + if not frame.config then + print(frame:GetName(), 'has no config layers') + return + end + print('Registering config layers from', frame:GetName()) + + for i, subframe in ipairs(frame.config) do + -- make sure there are no duplicates + if not refs[subframe] then + local key = #layers+1 + layers[key] = subframe + refs[subframe] = key + end + print(' ', i, subframe:GetName()) + end +end + +B.RemoveConfigLayers = function(frame) + local print = B.fprint() + print('|cFFFF0000RemoveConfigLayers', frame:GetName()) + for i, subframe in pairs(layers) do + if subframe:GetParent() == frame then + print('|cFFFF8800 ', subframe:GetParent():GetName(), '|cFFFFFF00', subframe:GetName()) + layers[i]:Hide() + layers[i] = nil + refs[subframe] = nil + end + end +end + +B.UpdateConfigLayers = function() + local print = B.fprint() + local func = B.Conf.GuidesMode and 'Show' or 'Hide' + local numAnchors = 0 + for name, display in pairs(displays) do + numAnchors = numAnchors + 1 + display.anchor:EnableMouse(B.Conf.GuidesMode) + if B.Conf.GuidesMode then + display.anchor:SetScript('OnUpdate', display.anchor.OnUpdate) + else + display.anchor:SetScript('OnUpdate', nil) + + for i, anchorButton in ipairs(display.anchor.anchorButton) do + anchorButton:Hide() + end + + end + + end + for id, region in pairs(layers) do + print(id, region:GetName(), func) + region[func](region) + end + + print('['..func..'] updated', #layers, 'regions,', numAnchors, 'frames') +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ObjectiveInfo.lua Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,135 @@ +local B = select(2,...).frame +local wipe, pairs, ipairs, min, max, unpack = table.wipe, pairs, ipairs, min, max, unpack +local GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo = GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo +local GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo = GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo +local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') +local print = B.print('Objectives') + +local Tracker, AutoQuest, Quest, Cheevs = mod.Tracker, mod.AutoQuest, mod.Quest, mod.Cheevs +-------------------------------------------------------------------- +--- Tracker-specific data retrieval functions +-------------------------------------------------------------------- + +Quest.GetNumWatched = function() + return GetNumQuestWatches () +end +Quest.GetInfo = function (self, watchIndex) + print('|cFF00DDFFQuest|r.|cFF0088FFGetInfo(|r'.. tostring(watchIndex)..'|r)') + local questID, title, questLogIndex, numObjectives, requiredMoney, isComplete, + startEvent, isAutoComplete, failureTime, timeElapsed, questType, isTask, isStory, isOnMap, hasLocalPOI = GetQuestWatchInfo(watchIndex) +print(GetQuestWatchInfo(watchIndex)) + if not questID then + return + end + print(self.Info) + self.Info[questID] = self.Info[questID] or {} + + local q = self.Info[questID] + q.watchIndex = watchIndex + q.type = 'Quest' + q.questID = questID + q.title = title + q.questLogIndex = questLogIndex + q.numObjectives = numObjectives + q.requiredMoney = requiredMoney + q.isComplete = isComplete + q.startEvent = startEvent + q.isAutoComplete = isAutoComplete + q.failureTime = failureTime + q.timeElapsed = timeElapsed + q.questType = questType + q.isTask = isTask + q.isStory = isStory + q.isOnMap = isOnMap + q.hasLocalPOI = hasLocalPOI + + --- Start QuestLogEntry calls + ----------------------------------------- + SelectQuestLogEntry(questLogIndex) + q.greenRange = GetQuestGreenRange() + q.isDaily = QuestIsDaily() + q.isWeekly = QuestIsWeekly() + ----------------------------------------- + + --- End QuestLogEntry calls + print(' |cFF0088FF', q.isDaily, q.isWeekly) + + q.isComplete = IsQuestComplete(questID) + q.isBreadCrumb = IsBreadcrumbQuest(questID) + q.isStoryQuest = IsStoryQuest(questID) + q.completionText= GetQuestLogCompletionText(questLogIndex) + q.trackingID = questID + q.superTracked = (questID == GetSuperTrackedQuestID()) -- call directly so artifact data doesn't become an issue + q.numObjectives = GetNumQuestLeaderBoards(questLogIndex) + q.objectives = {} + for i = 1, q.numObjectives do + local text, type, finished = GetQuestLogLeaderBoard(i, questLogIndex) + q.objectives[i] = { + type = type, + text = text, + finished = finished + } + if type == 'event' then + elseif type == 'monster' then + elseif type == 'object' then + elseif type == 'reputation' then + elseif type == 'item' then + end + end + + local link, icon, charges = GetQuestLogSpecialItemInfo(questLogIndex) + local start, duration, enable = GetQuestLogSpecialItemCooldown(questLogIndex) + if link or icon or charges then + q.specialItem = { + link = link, + charges = charges, + icon = icon, + start = start, + duration = duration, + enable = enable, + } + end + + self.LogInfo[questLogIndex] = q + print('|cFF0088FFGetQuestInfo('..questID..')|r', questLogIndex, title) + return q +end + +Cheevs.GetNumWatched = function(self) + Cheevs.trackedCheevs = {GetTrackedAchievements()} + return GetNumTrackedAchievements() +end +Cheevs.GetInfo = function(self, index) + local cheevID = Cheevs.trackedCheevs[index] + local id, name, points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy = GetAchievementInfo(cheevID) + + print('|cFF00FF00', GetAchievementNumCriteria(cheevID)) + self.Info[cheevID] = {} + local c = self.Info[cheevID] + c.type = 'Cheevs' + c.watchIndex = index + c.cheevID = cheevID + c.title = name + c.points, c.completed, c.month, c.day, c.year, c.description, c.flags, c.icon, c.rewardText, c.isGuildAch, c.wasEarnedByMe, c.earnedBy = + points, completed, month, day, year, description, flags, icon, rewardText, isGuildAch, wasEarnedByMe, earnedBy + c.numObjectives = GetAchievementNumCriteria(cheevID) + c.objectives = {} + for i = 1, c.numObjectives do + local description, type, completed, quantity, requiredQuantity, characterName, flags, assetID, quantityString, criteriaID = GetAchievementCriteriaInfo(cheevID, i) + c.objectives[i] = { + text = description, + type = type, + finished = completed, + quantity = quantity, + requiredQuantity = requiredQuantity, + characterName = characterName, + flags = flags, + assetID = assetID, + quantityString = quantityString, + criteriaID = criteriaID, + } + end + + self.WatchInfo[index] = c + return self.Info[cheevID] +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ObjectiveTracker.lua Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,249 @@ +--- ${PACKAGE_NAME} +-- @file-author@ +-- @project-revision@ @project-hash@ +-- @file-revision@ @file-hash@ +-- Created: 3/26/2016 1:51 AM +local B = select(2,...).frame +local wipe, pairs, ipairs, min, max, unpack = table.wipe, pairs, ipairs, min, max, unpack +local setmetatable, type = setmetatable, type +local GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo = GetNumQuestLeaderBoards, GetAchievementNumCriteria, GetQuestLogLeaderBoard, GetAchievementCriteriaInfo +local GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo = GetQuestLogIndexByID, GetSuperTrackedQuestID, SetSuperTrackedQuestID, GetQuestWatchInfo +local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') +local print = B.print('Objectives') +local ObjectiveTrackerFrame = ObjectiveTrackerFrame + +--[[ + Full quest info is available if: + - It's in the player quest log, or is available from the Gossip interface + - It's being shared from another player and is acceptible + - It's an auto-quest that is available in the current location + Partial quest info is availabe if: + - It's already completed (i.e. it appears in CompletedQuestInfo()). + - It's an scheduled interval quest (daily, weekly, etc.) + - It's contained in a quest link received from chat + Under any other circumstances, only minimal info can be pulled: + - Its availability to the player + - Its relation with the currently engaged NPC + - Its binary completion status + +]] +--- Global Frames +local Wrapper = _G.VeneerObjectiveWrapper +local Scroller = Wrapper.scrollArea +local Scroll = _G.VeneerObjectiveScroll + +--- list used to make things happen +mod.orderedNames = {[1] = 'AutoQuest', [2] = 'Quest', [3] = 'Cheevs'} + +--- ipairs() list of handlers for wrapper update +mod.orderedHandlers = {} +mod.orderedTrackers = {} +mod.indexedTrackers = {} +--- pairs() list of handler frames for tracker updates +mod.namedTrackers = {} + +--- Handler stubs +mod.AutoQuest = { + name = "AutoQuest" +} +mod.Quest = { + name = "Quest" +} +mod.Cheevs = { + name = "Cheevs" +} + + +--- Temp values set during updates +local wrapperWidth, wrapperHeight +local scrollWidth, scrollHeight +local previousBlock +local currentBlock + +local frame_guide_init = function(self) + self.testU = self.testU or self:CreateTexture('TestU', 'OVERLAY', 'VnTestLine') + self.testB = self.testB or self:CreateTexture('TestB', 'OVERLAY', 'VnTestLine') + self.testL = self.testL or self:CreateTexture('TestL', 'OVERLAY', 'VnTestLine') + self.testR = self.testR or self:CreateTexture('TestR', 'OVERLAY', 'VnTestLine') +end +local frame_guide = function(self, target) + if not target then return end + if target:IsDragging() then return end + local thickness = 1 + local midX, midY = target:GetCenter() + local width, height = target:GetWidth() * 1.5, target:GetHeight() * 1.5 + --print('frame', target:GetLeft(), target:GetTop(), target:GetRight(), target:GetBottom()) + self.testB:ClearAllPoints() + self.testB:SetPoint('TOP', UIParent, 'BOTTOMLEFT', midX, target:GetBottom()) + self.testB:SetSize(width,thickness) + + self.testU:ClearAllPoints() + self.testU:SetPoint('BOTTOM', UIParent, 'BOTTOMLEFT', midX, target:GetTop()) + self.testU:SetSize(width,thickness) + + self.testL:ClearAllPoints() + self.testL:SetPoint('RIGHT', UIParent, 'BOTTOMLEFT', target:GetLeft(), midY) + self.testL:SetSize(thickness,height) + + self.testR:ClearAllPoints() + self.testR:SetPoint('LEFT', UIParent, 'BOTTOMLEFT', target:GetRight(), midY) + self.testR:SetSize(thickness,height) +end + +--- Handler template +local CreateHandler = function (self, name, index) + print(self, name) + local handler = setmetatable({}, { + __tostring = function() return name end, + __call = function (self) mod.UpdateTracker(self) end + }) + if type(mod.orderedHandlers[index]) == 'table' then + return mod.orderedHandlers[index] + end + + print('take up locals first') + local preset = {} + for k,v in pairs(mod[name]) do + preset[k] = true + if type(v) == 'table' then + handler[k] = {} + else + handler[k] = v + end + end + + print('resulting handler contents') + for k, v in pairs(self) do + if not handler[k] then + if type(v) == 'table' then + -- assume all tables to be local data; don't inherit or ref + handler[k] = {} + else + handler[k] = mod.Tracker[k] + end + else + print(name, 'has its own', k) + end + end + print('|cFFFF4400'..tostring(name)..'|r:') + for k, v in pairs(handler) do + print(string.format("%24s %8s %s", (preset[k] and '|cFFFFFFFF' or '|cFFFFFF00') .. k .. '|r', type(v), tostring(v))) + end + mod[name] = handler + mod.orderedHandlers[index] = handler + return true +end + +mod.Tracker = setmetatable({}, { + __call = CreateHandler, + __tostring = function() return 'DEFAULT_TRACKING_HANDLER' end +}) +local Tracker = mod.Tracker +Tracker.numWatched = 0 --- number of entries being handled +Tracker.numBlocks = 0 --- number of blocks created +Tracker.actualBlocks = 0 --- number of blocks in use + +Tracker.freeBlocks = {} --- block heap +Tracker.usedBlocks = {} + +Tracker.Watched = {} -- find by watchIndex +Tracker.Info = {} -- find by data ID +Tracker.BlockInfo = {} -- find by block ID +Tracker.LogInfo = {} -- find by log ID (quest log mainly) +Tracker.WatchBlock = {} +Tracker.LogBlock = {} + + + +Tracker.GetBlock = function(handler, blockIndex) + local block = handler.usedBlocks[blockIndex] + if not handler.usedBlocks[blockIndex] then + if #handler.freeBlocks >= 1 then + block = handler.freeBlocks[#handler.freeBlocks] + handler.freeBlocks[#handler.freeBlocks] = nil + else + block = CreateFrame('Frame', 'Veneer'..tostring(handler)..'Block'..blockIndex, Scroll, 'VeneerTrackerBlock') + block.SetStyle = mod.SetBlockStyle + block:ClearAllPoints() -- making sure the anchors are clear in case they get added for some other template usage + end + + handler.usedBlocks[blockIndex] = block + end + return handler.usedBlocks[blockIndex] +end +local SmallEvents = { + QUEST_ACCEPTED = 'OnQuestAccepted' +} + +local HandlerEvents = { + QUEST_ACCEPTED = mod.Quest, + QUEST_WATCH_LIST_CHANGED = mod.Quest, + SUPER_TRACKED_QUEST_CHANGED = mod.Quest, + QUEST_LOG_UPDATE = mod.Quest, + TRACKED_ACHIEVEMENT_LIST_CHANGED = mod.Cheevs, + TRACKED_ACHIEVEMENT_UPDATE = mod.Cheevs +} + +function mod:OnEvent (event, ...) + local isHandled + if SmallEvents[event] then + print('|cFF00FF00'..SmallEvents[event]..'(' ..event..'|r', ...) + mod[SmallEvents[event]](event, ...) + isHandled = true + end + if HandlerEvents[event] then + print('|cFF0088FF'..event..'|r wrapper update') + mod.UpdateWrapper() + isHandled = true + end + if not isHandled then + print('|cFFFF4400'..event..'|r', ...) + end + --@debug@ + if Devian and Devian.InWorkspace() then + frame_guide_init(Scroller) + frame_guide(Scroller, Scroller) + end +end + +function mod:OnInitialize() + + self.InitializeTrackers() + for event, _ in pairs(SmallEvents) do + self:RegisterEvent(event) + end + for event, _ in pairs(HandlerEvents) do + self:RegisterEvent(event) + end + self:SetScript('OnEvent', mod.OnEvent) + + ObjectiveTrackerFrame:UnregisterAllEvents() + ObjectiveTrackerFrame:Hide() +end + +--[[ +QUESTLINE_UPDATE This event is not yet documented +QUESTTASK_UPDATE This event is not yet documented +QUEST_ACCEPTED Fires when a new quest is added to the player's quest log (which is what happens after a player accepts a quest). +QUEST_ACCEPT_CONFIRM Fires when certain kinds of quests (e.g. NPC escort quests) are started by another member of the player's group +QUEST_AUTOCOMPLETE Fires when a quest is automatically completed (remote handin available) +QUEST_BOSS_EMOTE This event is not yet documented +QUEST_CHOICE_CLOSE This event is not yet documented +QUEST_CHOICE_UPDATE This event is not yet documented +QUEST_COMPLETE Fires when the player is looking at the "Complete" page for a quest, at a questgiver. +QUEST_DETAIL Fires when details of an available quest are presented by a questgiver +QUEST_FINISHED Fires when the player ends interaction with a questgiver or ends a stage of the questgiver dialog +QUEST_GREETING Fires when a questgiver presents a greeting along with a list of active or available quests +QUEST_ITEM_UPDATE Fires when information about items in a questgiver dialog is updated +QUEST_LOG_UPDATE Fires when the game client receives updates relating to the player's quest log (this event is not just related to the quests inside it) +QUEST_POI_UPDATE This event is not yet documented +QUEST_PROGRESS Fires when interacting with a questgiver about an active quest +QUEST_REMOVED This event is not yet documented +QUEST_TURNED_IN Fired when a quest is turned in +QUEST_WATCH_LIST_CHANGED This event is not yet documented +QUEST_WATCH_OBJECTIVES_CHANGED This event is not yet documented +QUEST_WATCH_UPDATE Fires when the player's status regarding a quest's objectives changes, for instance picking up a required object or killing a mob for that quest. All forms of (quest objective) progress changes will trigger this event.] + +TRACKED_ACHIEVEMENT_LIST_CHANGED This event is not yet documented +TRACKED_ACHIEVEMENT_UPDATE Fires when the player's progress changes on an achievement marked for watching in the objectives tracker + ]] \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ObjectiveTracker.xml Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,237 @@ +<Ui> + + + <Texture name="VnTestLine" virtual="true"> + <Color r="1" g="1" b="0" a="1" /> + </Texture> + + <Frame name="VeneerObjectiveWrapper" parent="UIParent" movable="true" enableMouse="true"> + <Scripts> + <OnLoad> + self.toggle = true + self:RegisterForDrag('LeftButton') + </OnLoad> + <OnShow> + </OnShow> + <OnDragStart> + self:StartMoving() + </OnDragStart> + <OnDragStop> + self:StopMovingOrSizing() + </OnDragStop> + <!--@debug@--> + <!--@end-debug@--> + </Scripts> + <Anchors> + <Anchor point="TOPRIGHT" x="-60" y="-240" /> + </Anchors> + <Layers> + + <Layer level="ARTWORK"> + <Texture parentKey="headerbg" /> + <Texture parentKey="Background" hidden="false" alpha="1" atlas="Objective-Header" useAtlasSize="false"> + <Size y="84" x="210" /> + <TexCoords up="0" down="1" left="0" right="0.7" /> + <Anchors> + <Anchor point="TOPLEFT" x="-30" y="12"/> + </Anchors> + </Texture> + <Texture parentKey="BackgroundR" hidden="false" alpha="1" atlas="Objective-Header" useAtlasSize="false"> + <Size y="84" x="210" /> + <TexCoords up="0" down="1" left="0.3" right="1" /> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPRIGHT" relativeKey="$parent.Background" /> + <Anchor point="RIGHT" relativePoint="RIGHT" x="24" /> + </Anchors> + </Texture> + <!--<Texture desatuated="true" parentKey="LineGlow" hidden="false" alpha="0" alphaMode="ADD" atlas="OBJFX_LineGlow" useAtlasSize="true"> + <Anchors> + <Anchor point="LEFT" relativeKey="$parent.Background" x="-21" y="18"/> + </Anchors> + </Texture> + <Texture parentKey="SoftGlow" hidden="false" alpha="0" alphaMode="ADD" atlas="OBJFX_Glow" useAtlasSize="true"> + <Anchors> + <Anchor point="CENTER" relativeKey="$parent.Background" relativePoint="LEFT" x="49" y="20"/> + </Anchors> + </Texture> + <Texture parentKey="StarBurst" hidden="false" alpha="0" alphaMode="ADD" atlas="OBJFX_StarBurst" useAtlasSize="true"> + <Anchors> + <Anchor point="CENTER" relativeKey="$parent.SoftGlow" x="29"/> + </Anchors> + </Texture> + <Texture parentKey="LineSheen" hidden="false" alpha="0" alphaMode="ADD" atlas="OBJFX_LineBurst"> + <Size x="60" y="15"/> + <Anchors> + <Anchor point="CENTER" relativeKey="$parent.SoftGlow" x="29" y="-13"/> + </Anchors> + </Texture>--> + </Layer> + <Layer level="OVERLAY"> + + </Layer> + </Layers> + <Frames> + + <Button name="$parentClose" parentKey="close" inherits="UIPanelCloseButtonNoScripts"> + <Size x="25" y="20" /> + <Anchors> + <Anchor point="TOPRIGHT" x="-4" y="-2" /> + </Anchors> + </Button> + + <ScrollFrame name="$parentScrollFrame" enableMouseWheel="true" parentKey="scrollArea"> + <Layers> + <Layer level="BACKGROUND"> + <Texture setAllPoints="true"> + <Color r="0.15" g=".3" b=".3" a="0" /> + </Texture> + </Layer> + </Layers> + <Frames> + + + <!-- Can't get it to work as 'Slider'; implement as click frame + <Slider name="$parentBar" parentKey="scrollBar" minValue="1" maxValue="100" valueStep="1" stepsPerPage="1" defaultValue="1" orientation="VERTICAL"> + <HitRectInsets top="-1" bottom="1" right="1" left="0" /> + <ThumbTexture name="$parentThumb"> + <Color r="1" g="1" b="1" a="0.85" /> + </ThumbTexture> + <Layers> + <Layer level="BACKGROUND"> + <Texture setAllPoints="true"> + <Color r="1" g="0" b="0" a=".5" /> + </Texture> + </Layer> + </Layers> + </Slider> + --> + </Frames> + </ScrollFrame> + </Frames> + </Frame> + + <Frame name="VeneerObjectiveScroll" parent="VeneerObjectiveWrapperScrollFrame"> + <Anchors> + <Anchor point="TOPLEFT" /> + </Anchors> + <Layers> + <Layer level="BACKGROUND"> + <Texture setAllPoints="true"> + <Color r="1" g="1" b="1" a="1" /> + <Gradient orientation="HORIZONTAL"> + <MinColor r="0" g="0.5" b="0.5" a="0" /> + <MaxColor r="0" g="0.5" b="0.5" a="0" /> + </Gradient> + </Texture> + </Layer> + </Layers> + </Frame> + + <Frame name="VeneerTrackerTemplate" parent="UIParent" virtual="true"> + <Layers> + <Layer level="BACKGROUND"> + <Texture name="$parentHeaderBG" parentKey="headerbg"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPLEFT" /> + </Anchors> + <Color r="1" g="1" b="1" a="1" /> + <Gradient orientation="HORIZONTAL"> + <MinColor r="0" g="0" b="0" a="0.1" /> + <MaxColor r="0" g="0" b="0" a="0" /> + </Gradient> + </Texture> + </Layer> + <Layer level="OVERLAY"> + <FontString name="$parentHeader" inherits="VeneerFontHighlight" text="OBJ" parentKey="header"> + <Anchors> + <Anchor point="TOPLEFT" /> + </Anchors> + </FontString> + + + </Layer> + </Layers> + </Frame> + + + <Frame name="VeneerTrackerBlock" parent="VeneerObjectiveScroll" virtual="true" enableMouse="true"> + <Layers> + <Layer level="BACKGROUND"> + </Layer> + <Layer level="ARTWORK"> + <Texture name="$parentTitleBackground" parentKey="titlebg"> + <Color r="1" g="1" b="1" a="1" /> + <Anchors> + <Anchor point="TOPLEFT" /> + </Anchors> + </Texture> + <Texture name="$parentBackground" parentKey="bg"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.titlebg" /> + </Anchors> + <Color r="1" g="1" b="1" a="1" /> + <Gradient orientation="HORIZONTAL"> + <MinColor r="0" g="0" b="0" a=".15" /> + <MaxColor r="0" g="0" b="0" a=".35" /> + </Gradient> + </Texture> + <Texture name="$parentItemTile" parentKey="icon" hidden="true"> + <Size x="24" y="24" /> + <Anchors> + <Anchor point="TOPRIGHT" x="-1" y="-1" /> + </Anchors> + </Texture> + <Texture name="$parentMoneyTile" parentKey="money" hidden="true" /> + </Layer> + <Layer level="HIGHLIGHT"> + <Texture name="$parentHighLight" parentKey="highlight"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeKey="$parent.titlebg" /> + <Anchor point="BOTTOM" relativePoint="TOP" relativeKey="$parent.titlebg" x="0" y="-4"/> + <Anchor point="RIGHT" relativePoint="RIGHT" /> + </Anchors> + <Color r="1" g="1" b="1" a="1" /> + <Gradient orientation="VERTICAL"> + <MaxColor r="1" g="1" b="1" a=".15" /> + <MinColor r="1" g="1" b="1" a="0" /> + </Gradient> + </Texture> + <Texture name="$parentLowLight" parentKey="highlight2"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="BOTTOMLEFT" relativeKey="$parent.bg" x="0" y="14" /> + <Anchor point="BOTTOM" relativePoint="BOTTOM" relativeKey="$parent.bg" x="0" y="0"/> + <Anchor point="RIGHT" relativePoint="RIGHT" relativeKey="$parent" /> + </Anchors> + <Color r="1" g="1" b="1" a="1" /> + <Gradient orientation="VERTICAL"> + <MaxColor r="1" g="1" b="1" a="0" /> + <MinColor r="1" g="1" b="1" a="0.15" /> + </Gradient> + </Texture> + </Layer> + <Layer level="OVERLAY"> + <FontString name="$parentTitle" parentKey="title" inherits="VeneerFontHighlight" justifyH="LEFT" justifyV="MIDDLE"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeKey="$parent.titlebg" /> + </Anchors> + </FontString> + <FontString name="$parentLeaderBoard" parentKey="objectives" inherits="VeneerFontNormal" justifyH="LEFT" justifyV="MIDDLE" wordwrap="true"> + <Anchors> + <Anchor point="TOPLEFT" relativePoint="TOPLEFT" relativeKey="$parent.bg" x="5" y="0" /> + <Anchor point="RIGHT" relativeKey="$parent" /> + </Anchors> + </FontString> + </Layer> + </Layers> + </Frame> + + <Button name="VeneerItemButton" inherits="SecureActionButtonTemplate"> + + </Button> + + <Script file="ObjectiveTracker.lua" /> + <Script file="ObjectiveInfo.lua" /> + <Script file="ObjectiveUI.lua" /> + <Script file="ObjectiveFrame.lua" /> + <Script file="ObjectiveEvents.lua" /> +</Ui> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ObjectiveUI.lua Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,64 @@ +--- ${PACKAGE_NAME} +-- @file-author@ +-- @project-revision@ @project-hash@ +-- @file-revision@ @file-hash@ +-- Created: 3/29/2016 7:07 PM +local B = select(2,...).frame +local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame') +local print = B.print('Objectives') +local Tracker, AutoQuest, Quest, Cheevs = mod.Tracker, mod.AutoQuest, mod.Quest, mod.Cheevs + +-------------------------------------------------------------------- +--- Tracker-specific widget functions +-------------------------------------------------------------------- + +Tracker.Select = function(self) end +Tracker.Open = function(self) end +Tracker.Remove = function(self) end +Tracker.Report = function(self) + print('Stats:', self.numWatched,'items tracked,', self.numBlocks,'blocks assigned.') +end + +Tracker.OnMouseUp = function(self, button) + if button == 'LeftButton' then + self:Select() + mod.UpdateWrapper() + elseif button == 'RightButton' then + self:Open() + end + print('|cFFFF8800'..tostring(self:GetName())..':MouseUp()|r ->',self.info.trackingID) +end + +Tracker.OnMouseDown = function(self, button) + if button == 'LeftButton' then + self:SetStyle('Active') + end + print(self.info.title) +end + +----------------------------- +--- AUTO_QUEST +AutoQuest.name = "Remote Quests" +AutoQuest.GetNumWatched = GetNumAutoQuestPopUps + +----------------------------- +--- QUEST +Quest.name = "Quests" +Quest.Select = function(self) + SetSuperTrackedQuestID(self.info.questID) +end +Quest.Open = function(self) + print('something something quest log') + QuestMapFrame_ShowQuestDetails(self.info.questID) + ToggleQuestLog() +end + + +----------------------------- +--- CHEEVS +Cheevs.Select = function(self) +end + +Cheevs.Open = function(self) +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RaidBuffTray.lua Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,354 @@ +--- ${PACKAGE_NAME} +-- @file-author@ +-- @project-revision@ @project-hash@ +-- @file-revision@ @file-hash@ +-- Created: 3/20/2016 10:00 PM + +local _, A = ... +local B = A.frame +local MODULE = 'BuffFrame' +local M = B:RegisterModule(MODULE) +local displays = B.displays + +local parentAnchor, parentFrame, raidbuffsFrame +local band, lshift, CreateFrame = bit.band, bit.lshift, CreateFrame +local raidBuffs = {} +local raidBuffSymbols = {'St', 'HP', 'AP', 'Ha', 'SP', 'Cr', 'Ma', 'MS', 'V' } +local missingBuffs = {} +local playerBuffing, playerCurrentBuff +local playerBuffs = {} +local c, ac, frameSize, frameSpacing, framePosition +local fprint = B.fprint +local NUM_LE_MISSING_RAID_BUFFS = 0 +local missingBuffsAnchor + + +--- Takes a given icon texture and calls the pre-defined function set +M.UpdateBuffStyle = function(buff, style, path) + local print = fprint() + local icon = buff.icon + local symbol = buff.symbol + path = path or icon.iconPath + --print(style, icon.iconStyle) + + if style ~= buff.iconStyle or path ~= buff.iconPath then + print('|cFF0088FFUpdateBuffStyle(|r', icon:GetName(), style, path) + icon.iconStyle = style + icon.iconPath = path + else + --print('|cFF00FF88UpdateBuffStyle(|r', icon:GetName(), style, path, ') same values, ignore') + return + end + local styleset = B.BuffStyles[style] + if not path or path == '' then + print('path is nil/empty') + icon:SetTexture(1, 1, 1, 1) + icon:SetVertexColor(unpack(styleset.Color)) + else + icon:SetTexture(path or icon:GetTexture()) + icon:SetVertexColor(unpack(styleset.Color)) + end + + if symbol and symbol.GetText then + symbol:SetTextColor(unpack(styleset.TextColor)) + symbol:SetText(buff.symbolName or 'NaW') + end + + icon:SetBlendMode(styleset.SetBlendMode) + icon:SetDesaturated(styleset.SetDesaturated) +end + +--- Populates a list of targets needing a buff, fired by a handler +local PlayerBuffTodo ={} +M.UpdateBuffStatus = function(aura, filters) + if not PlayerBuffStatus[aura] then + PlayerBuffStatus[aura] = {} + end + + + print(UnitClass('player')) + if IsInGroup() then + local numBuffed = 0 + local partySize = GetNumGroupMembers() + local missing = {} + for i = 1, partySize do + local unit = 'raid'..i + if UnitAura(unit, aura, nil, filters) then + numBuffed = numBuffed + 1 + else + tinsert(missing, unit) + end + end + + PlayerBuffTodo[aura] = missing + + end +end + +--- Evaluates buff availability criteria +-- Uses hard returns to avoid over-iterating conditionals, particularly pet family +local function IsBuffAvailable(criteria) + local available, active = false, false + local result + for _, test in ipairs(criteria) do + if test == true then + -- it's a passive effect that is always on + return true, true + else + if c.spec then + if not (result and c.spec == B.PlayerSpec) then + return false + end + end + + if c.talent then + local talentID, name, texture, selected, available = GetTalentInfoByID(c.talent, GetActiveSpecGroup()) + if not (result and selected) then + return false + end + end + + if c.petFamily then + local lim = min(5, NUM_PET_STABLE_SLOTS) -- to avoid volatile loop condition + for p = 1, lim do + local hasPet = false + local icon, name, level, family, talent = GetStablePetInfo(p) + if family == c.petFamily then + hasPet = true + end + if not (result and hasPet) then + return false + end + end + end + + end + end + return true, false +end + +--- events: PLAYER_SPECIALIZATION_CHANGED +function M:UpdateBuffsTodo (unit) + -- buffs vs. auras + if unit ~= 'player' then + -- look for changes in the GIST manifest and sort them out + return + end + + local class = UnitClass('player') + local spec = GetSpecialization() + if not class or + not spec or + not IsInGroup() or + not B.PlayerBuffStatus[class] then + -- if just logging in, info won't be available for several seconds + -- if not grouped, don't calc + -- hide frame + B.PlayerBuffsActive = function() return false end + return + end + + -- verify change + if B.PlayerCurrentSpec == spec or B.PlayerClass == class then + return + end + B.PlayerCurrentSpec = spec + B.PlayerClass = class + + local test = B.ClassRaidBuffs + local buffTypes = {} + local auraTypes = {} + for i = 1, NUM_LE_RAID_BUFF_TYPES do + local name, filters + if test[i] and test[i][class] then + playerBuffs[i], name, filters = IsBuffAvailable(test[i][class]) + else + playerBuffs[i] = nil + end + + if name then + B.UpdateBuffStatus(name, filters) + end + end +end + +-- Called once to setup the ConsolidatedBuffs stencil +local consolidatedBuffsLoaded +M.SetConsolidatedBuffs = function() + local print = fprint() + c = displays.ConsolidatedBuff.conf + parentFrame = B.guides[c.Parent][c.Position] + raidbuffsFrame = B.anchor.ConsolidatedBuff + + B.SetConfigLayers(raidbuffsFrame) + consolidatedBuffsLoaded = true + ConsolidatedBuffs:ClearAllPoints() + ConsolidatedBuffs:SetAllPoints(parentFrame.icon) + if c.Icon then + ConsolidatedBuffsIcon:SetAllPoints(parentFrame.icon) + ConsolidatedBuffsIcon:SetTexCoord(0.609,0.89,0.215,0.78) + else + ConsolidatedBuffsIcon:Hide() + end + + ConsolidatedBuffsCount:Hide() +end + +local missingTypes = {} +local raidBuffsInitialized +M.UpdateRaidBuffs = function() + local print = fprint() + if not consolidatedBuffsLoaded then + M.SetConsolidatedBuffs() + end + + if not M.ShowConsolidated or not parentFrame.contains then + print(' hiding raid buffs square') + if raidBuffsInitialized then + for i = 1, 9 do + if raidBuffs[i] then + raidBuffs[i]:Hide() + end + end + raidBuffsInitialized = nil + end + if parentFrame then + print(c.Parent, c.Position) + print('de-flagging parent') + parentFrame.contains = nil + end + raidbuffsFrame:Hide() + return + end + + local c = B.displays.ConsolidatedBuff.conf + if parentFrame and not parentFrame.contains then + raidBuffsInitialized = true + print('re-flagging parent', parentFrame:GetName()) + parentFrame.contains = parentFrame + B.decors[c.Parent][c.Position]:Hide() + raidbuffsFrame:Show() + + -- make sure parent icon is updated + local w = c.Size*c.PerRow+c.Spacing*(c.PerRow-1)+c.Border*2 + parentFrame:SetSize(w, w) + parentFrame.icon:SetSize(w - c.Border*2, w - c.Border*2) + parentFrame.contains = raidbuffsFrame + + M.UpdateBuffs(c.Parent) + end + + -- have to loop again due to tainting restrictions + -- could compare the tooltip font object pointers, but that may change + local buffStack = GetRaidBuffInfo() + print(GetRaidBuffInfo()) + local guides = B.guides.ConsolidatedBuff + local numBuffs = 0 + local numAvailable = 0 + local mask = 1 + if buffStack == nil then + return -- discard + end + + + for i = 1, NUM_LE_RAID_BUFF_TYPES do + local available = (band(buffStack, mask) > 0) + local name, _, icon, start, duration, spellID, slot = GetRaidBuffTrayAuraInfo(i) + print(i, name, icon, available) + + raidBuffs[i] = raidBuffs[i] or CreateFrame('Frame', 'VeneerRaidBuff' .. i, raidbuffsFrame, 'VeneerRaidBuffTemplate') + local buff = raidBuffs[i] + if not raidBuffs[i].stylized then + print(' setting style', i) + buff.stylized = true + buff.symbol:SetText(raidBuffSymbols[i]) + buff.symbol:SetFont("Fonts\\FRIZQT__.TTF", 10, 'OUTLINE') + buff:SetSize(parentFrame.icon:GetWidth()/c.PerRow,parentFrame.icon:GetWidth()/c.PerRow) + buff.symbolName = raidBuffSymbols[i] + + buff.icon:SetAllPoints(guides[i].icon) + buff:SetAllPoints(guides[i]) + raidbuffsFrame.Zoom(buff.icon) + end + + buff:Show() + local buffStyle = 'missing' + if name then + buff:Show() + buff.symbol:Hide() + missingTypes[i] = nil + numBuffs = numBuffs + 1 + numAvailable = numAvailable + 1 + buffStyle = 'active' + else + buff.symbol:Show() + if band(buffStack, mask) > 0 then + buffStyle = 'available' + numAvailable = numAvailable + 1 + else + buffStyle = 'missing' + icon = '' + end + end + mask = lshift(mask, 1) + + M.UpdateBuffStyle(buff, buffStyle, icon) + end + + -- todo: filter by castable and suppress for non-overlapping auras + + raidbuffsFrame.label:SetText(numBuffs..'/'..numAvailable) + print(parentFrame:GetName(), parentFrame:GetSize()) + + if B.ShowMissingBuffs then + B.UpdateMissingBuffs() + elseif missingBuffsAnchor and missingBuffsAnchor:IsVisible() then + for i = 1, NUM_LE_MISSING_RAID_BUFFS do + missingBuffs[i]:Hide() + end + end +end + +B.UpdateMissingBuffs = function() + local print = B.fprint() + local numMissing = 0 + + local firstMissing, lastMissing + for i = 1, NUM_LE_RAID_BUFF_TYPES do + local name, _, icon, start, duration, spellID, slot = GetRaidBuffTrayAuraInfo(i) + + if not name then + numMissing = numMissing + 1 + + print('missing buff', i, numMissing) + B.UpdateBuffStyle(raidBuffs[i].icon, 'missing', "") + + missingBuffs[numMissing] = missingBuffs[numMissing] or CreateFrame('Button', 'VeneerMissingBuff' .. numMissing, raidbuffsFrame, 'VeneerMissingBuffTemplate') + + local missing = missingBuffs[numMissing] + + missing:Show() + missing:SetSize(c.Size*c.PerRow, c.Size) + if numMissing == 1 then + firstMissing = missing + else + missing:SetPoint('TOP', lastMissing, 'BOTTOM', 0, -c.Spacing) + end + + missing.label:SetText(_G['RAID_BUFF_'.. i]) + lastMissing = missing + + end + end + + if firstMissing then + print(firstMissing:GetName(), raidbuffsFrame) + firstMissing:SetPoint('TOPRIGHT', raidbuffsFrame.label, 'BOTTOMRIGHT', 0, c.Spacing) + missingBuffsAnchor = firstMissing + end + + for i = numMissing +1, NUM_LE_MISSING_RAID_BUFFS do + missingBuffs[i]:Hide() + end + NUM_LE_MISSING_RAID_BUFFS = numMissing +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Veneer.toc Wed Mar 30 02:24:56 2016 -0400 @@ -0,0 +1,13 @@ +## Interface: 60200 +## Title: Veneer +## Notes: Buff button management +## Author: Krakyn +## Version: 1.0-@project-revision@ +## SavedVariables: VeneerData +## X-Category: Interface Enhancements +## DefaultState: Enabled +## LoadOnDemand: 0 +## OptionalDeps: Devian +Core.xml +BuffFrame.xml +ObjectiveTracker.xml \ No newline at end of file