Mercurial > wow > reaction
view Overlay.lua @ 100:9715174ff220
removed unimplemented stuff
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Fri, 24 Oct 2008 23:37:24 +0000 |
parents | f200bcb193d6 |
children | 890e4c4ab143 |
line wrap: on
line source
local ReAction = ReAction local L = ReAction.L local CreateFrame = CreateFrame local InCombatLockdown = InCombatLockdown local floor = math.floor local min = math.min local format = string.format local GameTooltip = GameTooltip local Bar = ReAction.Bar local GetSize = Bar.GetSize local GetButtonSize = Bar.GetButtonSize local GetButtonGrid = Bar.GetButtonGrid local SetSize = Bar.SetSize local SetAnchor = Bar.SetAnchor local SetButtonSize = Bar.SetButtonSize local SetButtonGrid = Bar.SetButtonGrid local ApplyAnchor = Bar.ApplyAnchor local GameTooltipTextRight1 = GameTooltipTextRight1 local GameTooltipTextRight2 = GameTooltipTextRight2 local GameTooltipTextRight3 = GameTooltipTextRight3 local KB = LibStub("LibKeyBound-1.0") ReAction:UpdateRevision("$Revision$") -- -- Bar config overlay -- local function GetNormalTextColor() return 1.0, 1.0, 1.0, 1.0 end local function GetAnchoredTextColor() return 1.0, 1.0, 1.0, 1.0 end local function GetNormalBgColor() return 0.7, 0.7, 1.0, 0.3 end local function GetAnchoredBgColor() return 0.9, 0.2, 0.7, 0.3 end local function StoreSize(bar) local f = bar:GetFrame() SetSize( bar, f:GetWidth(), f:GetHeight() ) end local function StoreExtents(bar) local f = bar:GetFrame() local p, fr, rp, x, y = f:GetPoint(1) fr = fr or UIParent SetAnchor( bar, p, fr, rp, x, y ) SetSize( bar, f:GetWidth(), f:GetHeight() ) end local function RecomputeButtonSize(bar) local w, h = GetSize(bar) local bw, bh = GetButtonSize(bar) local r, c, s = GetButtonGrid(bar) local scaleW = (floor(w/c) - s) / bw local scaleH = (floor(h/r) - s) / bh local scale = min(scaleW, scaleH) SetButtonSize(bar, scale * bw, scale * bh, s) end local function RecomputeButtonSpacing(bar) local w, h = GetSize(bar) local bw, bh = GetButtonSize(bar) local r, c, s = GetButtonGrid(bar) SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh)) end local function RecomputeGrid(bar) local w, h = GetSize(bar) local bw, bh = GetButtonSize(bar) local r, c, s = GetButtonGrid(bar) SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s) end local function ClampToButtons(bar) local bw, bh = GetButtonSize(bar) local r, c, s = GetButtonGrid(bar) SetSize(bar, (bw+s)*c + 1, (bh+s)*r + 1) end local function HideGameTooltip() GameTooltip:Hide() end local anchorInside = { inside = true } local anchorOutside = { outside = true } local edges = { "BOTTOM", "TOP", "LEFT", "RIGHT" } local oppositeEdges = { TOP = "BOTTOM", BOTTOM = "TOP", LEFT = "RIGHT", RIGHT = "LEFT" } local pointsOnEdge = { BOTTOM = { "BOTTOM", "BOTTOMLEFT", "BOTTOMRIGHT", }, TOP = { "TOP", "TOPLEFT", "TOPRIGHT", }, RIGHT = { "RIGHT", "BOTTOMRIGHT", "TOPRIGHT", }, LEFT = { "LEFT", "BOTTOMLEFT", "TOPLEFT", }, } local edgeSelector = { BOTTOM = 1, -- select x of x,y TOP = 1, -- select x of x,y LEFT = 2, -- select y of x,y RIGHT = 2, -- select y of x,y } local snapPoints = { [anchorOutside] = { BOTTOMLEFT = {"BOTTOMRIGHT","TOPLEFT","TOPRIGHT"}, BOTTOM = {"TOP"}, BOTTOMRIGHT = {"BOTTOMLEFT","TOPRIGHT","TOPLEFT"}, RIGHT = {"LEFT"}, TOPRIGHT = {"TOPLEFT","BOTTOMRIGHT","BOTTOMLEFT"}, TOP = {"BOTTOM"}, TOPLEFT = {"TOPRIGHT","BOTTOMLEFT","BOTTOMRIGHT"}, LEFT = {"RIGHT"}, CENTER = {"CENTER"} }, [anchorInside] = { BOTTOMLEFT = {"BOTTOMLEFT"}, BOTTOM = {"BOTTOM"}, BOTTOMRIGHT = {"BOTTOMRIGHT"}, RIGHT = {"RIGHT"}, TOPRIGHT = {"TOPRIGHT"}, TOP = {"TOP"}, TOPLEFT = {"TOPLEFT"}, LEFT = {"LEFT"}, CENTER = {"CENTER"} } } local insidePointOffsetFuncs = { BOTTOMLEFT = function(x, y) return x, y end, BOTTOM = function(x, y) return 0, y end, BOTTOMRIGHT = function(x, y) return -x, y end, RIGHT = function(x, y) return -x, 0 end, TOPRIGHT = function(x, y) return -x, -y end, TOP = function(x, y) return 0, -y end, TOPLEFT = function(x, y) return x, -y end, LEFT = function(x, y) return x, 0 end, CENTER = function(x, y) return x, y end, } local pointCoordFuncs = { BOTTOMLEFT = function(f) return f:GetLeft(), f:GetBottom() end, BOTTOM = function(f) return nil, f:GetBottom() end, BOTTOMRIGHT = function(f) return f:GetRight(), f:GetBottom() end, RIGHT = function(f) return f:GetRight(), nil end, TOPRIGHT = function(f) return f:GetRight(), f:GetTop() end, TOP = function(f) return nil, f:GetTop() end, TOPLEFT = function(f) return f:GetLeft(), f:GetTop() end, LEFT = function(f) return f:GetLeft(), nil end, CENTER = function(f) return f:GetCenter() end, } local edgeBoundsFuncs = { BOTTOM = function(f) return f:GetLeft(), f:GetRight() end, LEFT = function(f) return f:GetBottom(), f:GetTop() end } edgeBoundsFuncs.TOP = edgeBoundsFuncs.BOTTOM edgeBoundsFuncs.RIGHT = edgeBoundsFuncs.LEFT local cornerTexCoords = { -- ULx, ULy, LLx, LLy, URx, URy, LRx, LRy TOPLEFT = { 1, 1, 1, 0, 0, 1, 0, 0 }, TOPRIGHT = { 1, 0, 0, 0, 1, 1, 0, 1 }, BOTTOMLEFT = { 0, 1, 1, 1, 0, 0, 1, 0 }, BOTTOMRIGHT = { 0, 0, 0, 1, 1, 0, 1, 1 }, } -- Returns absolute coordinates x,y of the named point 'p' of frame 'f' local function GetPointCoords( f, p ) local x, y = pointCoordFuncs[p](f) if not(x and y) then local cx, cy = f:GetCenter() x = x or cx y = y or cy end return x, y end -- Returns true if frame 'f1' can be anchored to frame 'f2' local function CheckAnchorable( f1, f2 ) -- can't anchor a frame to itself or to nil if f1 == f2 or f2 == nil then return false end -- can always anchor to UIParent if f2 == UIParent then return true end -- also can't do circular anchoring of frames -- walk the anchor chain, which generally shouldn't be that expensive -- (who nests draggables that deep anyway?) for i = 1, f2:GetNumPoints() do local _, f = f2:GetPoint(i) if not f then f = f2:GetParent() end return CheckAnchorable(f1,f) end return true end -- Returns true if frames f1 and f2 specified edges overlap local function CheckEdgeOverlap( f1, f2, e ) local l1, u1 = edgeBoundsFuncs[e](f1) local l2, u2 = edgeBoundsFuncs[e](f2) return l1 <= l2 and l2 <= u1 or l2 <= l1 and l1 <= u2 end -- Returns true if point p1 on frame f1 overlaps edge e2 on frame f2 local function CheckPointEdgeOverlap( f1, p1, f2, e2 ) local l, u = edgeBoundsFuncs[e2](f2) local x, y = GetPointCoords(f1,p1) x = select(edgeSelector[e2], x, y) return l <= x and x <= u end -- Returns the distance between corresponding edges. It is -- assumed that the passed in edges e1 and e2 are the same or opposites local function GetEdgeDistance( f1, f2, e1, e2 ) local x1, y1 = pointCoordFuncs[e1](f1) local x2, y2 = pointCoordFuncs[e2](f2) return math.abs((x1 or y1) - (x2 or y2)) end local globalSnapTargets = { [UIParent] = anchorInside } local function GetClosestFrameEdge(f1,f2,a) local dist, edge, opp if f2:IsVisible() and CheckAnchorable(f1,f2) then for _, e in pairs(edges) do local o = a.inside and e or oppositeEdges[e] if CheckEdgeOverlap(f1,f2,e) then local d = GetEdgeDistance(f1, f2, e, o) if not dist or (d < dist) then dist, edge, opp = d, e, o end end end end return dist, edge, opp end local function GetClosestVisibleEdge( f ) local r, o, e1, e2 local a = anchorOutside for _, b in ReAction:IterateBars() do local d, e, opp = GetClosestFrameEdge(f,b:GetFrame(),a) if d and (not r or d < r) then r, o, e1, e2 = d, b:GetFrame(), e, opp end end for f2, a2 in pairs(globalSnapTargets) do local d, e, opp = GetClosestFrameEdge(f,f2,a2) if d and (not r or d < r) then r, o, e1, e2, a = d, f2, e, opp, a2 end end return o, e1, e2, a end local function GetClosestVisiblePoint(f1) local f2, e1, e2, a = GetClosestVisibleEdge(f1) if f2 then local rsq, p, rp, x, y -- iterate pointsOnEdge in order and use < to prefer edge centers to corners for _, p1 in ipairs(pointsOnEdge[e1]) do if CheckPointEdgeOverlap(f1,p1,f2,e2) then for _, p2 in pairs(snapPoints[a][p1]) do local x1, y1 = GetPointCoords(f1,p1) local x2, y2 = GetPointCoords(f2,p2) local dx = x1 - x2 local dy = y1 - y2 local rsq2 = dx*dx + dy*dy if not rsq or rsq2 < rsq then rsq, p, rp, x, y = rsq2, p1, p2, dx, dy end end end end return f2, p, rp, x, y end end local function GetClosestPointSnapped(f1, rx, ry, xOff, yOff) local o, p, rp, x, y = GetClosestVisiblePoint(f1) local s = false local insideOffsetFunc = p and insidePointOffsetFuncs[p] local coordFunc = p and pointCoordFuncs[p] if not insideOffsetFunc or not coordFunc then return end local sx, sy = insideOffsetFunc(xOff or 0, yOff or 0) local xx, yy = coordFunc(f1) if xx and yy then if math.abs(x) <= rx then if math.abs(y) <= ry then x = sx y = sy s = true elseif CheckEdgeOverlap(f1,o,"LEFT") then x = sx s = true end elseif math.abs(y) <= ry and CheckEdgeOverlap(f1,o,"TOP") then y = sy s = true end elseif xx then if math.abs(x) <= rx then x = sx s = true if math.abs(y) <= ry then y = sy end end elseif yy then if math.abs(y) <= ry then y = sy s = true if math.abs(x) <= rx then x = sx end end end -- correct for some Lua oddities with doubles if x == -0 then x = 0 end if y == -0 then y = 0 end if s then return o, p, rp, math.floor(x), math.floor(y) end end local function CreateSnapIndicator() local si = CreateFrame("Frame",nil,UIParent) si:SetFrameStrata("HIGH") si:SetHeight(16) si:SetWidth(16) local tex = si:CreateTexture() tex:SetAllPoints() tex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock") tex:SetBlendMode("ADD") tex:SetDrawLayer("OVERLAY") return si end local si1 = CreateSnapIndicator() local si2 = CreateSnapIndicator() local function DisplaySnapIndicator( f, rx, ry, xOff, yOff ) local o, p, rp, x, y, snap = GetClosestPointSnapped(f, rx, ry, xOff, yOff) if o then si1:ClearAllPoints() si2:ClearAllPoints() si1:SetPoint("CENTER", f, p, 0, 0) local xx, yy = pointCoordFuncs[rp](o) x = math.abs(x) <=rx and xx and 0 or x y = math.abs(y) <=ry and yy and 0 or y si2:SetPoint("CENTER", o, rp, x, y) si1:Show() si2:Show() else if si1:IsVisible() then si1:Hide() si2:Hide() end end return o, p end local function HideSnapIndicator() if si1:IsVisible() then si1:Hide() si2:Hide() end end local function UpdateLabelString(bar) local label = bar.controlLabelString if label then local name = bar.labelName if name and bar.labelSubtext then name = format("%s (%s)", name, bar.labelSubtext) end label:SetText(name or "") end end local function CreateControls(bar) local f = bar:GetFrame() f:SetMovable(true) f:SetResizable(true) local overlay = CreateFrame("Button", nil, f) overlay:EnableMouse(true) overlay:SetFrameLevel(3) -- set it above the buttons overlay:SetPoint("TOPLEFT", -4, 4) overlay:SetPoint("BOTTOMRIGHT", 4, -4) overlay:SetBackdrop({ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = true, tileSize = 16, edgeSize = 16, insets = { left = 0, right = 0, top = 0, bottom = 0 }, }) -- textures local bgTex = overlay:CreateTexture(nil,"BACKGROUND") bgTex:SetTexture(0.7,0.7,1.0,0.2) bgTex:SetPoint("TOPLEFT",4,-4) bgTex:SetPoint("BOTTOMRIGHT",-4,4) local hTex = overlay:CreateTexture(nil,"HIGHLIGHT") hTex:SetTexture(0.7,0.7,1.0,0.2) hTex:SetPoint("TOPLEFT",4,-4) hTex:SetPoint("BOTTOMRIGHT",-4,4) hTex:SetBlendMode("ADD") local aTex = overlay:CreateTexture(nil,"ARTWORK") aTex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock") aTex:SetWidth(16) aTex:SetHeight(16) aTex:Hide() -- label local label = overlay:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") label:SetAllPoints() label:SetJustifyH("CENTER") label:SetShadowColor(0,0,0,1) label:SetShadowOffset(3,-3) label:SetTextColor(GetNormalTextColor()) label:SetText(bar:GetName()) label:Show() bar.controlLabelString = label -- so that bar:SetLabel() can update it local function UpdateAnchorDecoration() local point, anchor, relPoint, x, y = f:GetPoint(1) if point then local ofsx, ofsy = insidePointOffsetFuncs[point](x,y) if (anchor and anchor ~= UIParent) or (ofsx == 0 and ofsy == 0) then bgTex:SetTexture( GetAnchoredBgColor() ) hTex:SetTexture( GetAnchoredBgColor() ) label:SetTextColor( GetAnchoredTextColor() ) aTex:ClearAllPoints() aTex:SetPoint(point) aTex:Show() return end end bgTex:SetTexture( GetNormalBgColor() ) hTex:SetTexture( GetNormalBgColor() ) label:SetTextColor( GetNormalTextColor() ) aTex:Hide() end local function StopResize() f:StopMovingOrSizing() f.isMoving = false f:SetScript("OnUpdate",nil) StoreSize(bar) ClampToButtons(bar) --ApplyAnchor(bar) ReAction:RefreshOptions() end local function CornerUpdate() local bw, bh = GetButtonSize(bar) local r, c, s = GetButtonGrid(bar) if IsShiftKeyDown() then f:SetMinResize( (s+12)*c+1, (s+12)*r+1 ) RecomputeButtonSize(bar) elseif IsAltKeyDown() then f:SetMinResize( bw*c, bh*r ) RecomputeButtonSpacing(bar) else f:SetMinResize( bw+s+1, bh+s+1 ) RecomputeGrid(bar) end local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh) GameTooltipTextRight1:SetText(format("%d x %d",r,c)) GameTooltipTextRight2:SetText(size) GameTooltipTextRight3:SetText(tostring(s)) end -- corner drag handles for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do local corner = CreateFrame("Frame",nil,overlay) corner:EnableMouse(true) corner:SetWidth(16) corner:SetHeight(16) corner:SetPoint(point) local tex = corner:CreateTexture(nil,"HIGHLIGHT") tex:SetTexture("Interface\\AddOns\\ReAction\\img\\corner") tex:SetTexCoord(unpack(cornerTexCoords[point])) tex:SetBlendMode("ADD") tex:SetAlpha(0.6) tex:SetAllPoints() --corner:RegisterForDrag("LeftButton") corner:SetScript("OnMouseDown", function(_,btn) f:SetScript("OnUpdate", CornerUpdate) f:StartSizing(point) end ) corner:SetScript("OnMouseUp",StopResize) corner:SetScript("OnEnter", function() local bw, bh = GetButtonSize(bar) local r, c, s = bar:GetButtonGrid() local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh) GameTooltip:SetOwner(f, "ANCHOR_"..point) GameTooltip:AddDoubleLine(format("|cffcccccc%s|r %s",L["Drag"],L["to add/remove buttons:"]), format("%d x %d",r,c)) GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to resize buttons:"]), size) GameTooltip:AddDoubleLine(format("|cff0033cc%s|r %s",L["Hold Alt"],L["to change spacing:"]), tostring(s)) GameTooltip:Show() end ) corner:SetScript("OnLeave", function() GameTooltip:Hide() f:SetScript("OnUpdate",nil) end ) end overlay:RegisterForDrag("LeftButton") overlay:RegisterForClicks("RightButtonUp") overlay:SetScript("OnDragStart", function() f:StartMoving() f.isMoving = true local w,h = bar:GetButtonSize() f:ClearAllPoints() UpdateAnchorDecoration() f:SetScript("OnUpdate", function() if IsShiftKeyDown() then local f, p = DisplaySnapIndicator(f,w,h) else HideSnapIndicator() end end) end ) local function UpdateDragTooltip() GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT") GameTooltip:AddLine(bar.name) GameTooltip:AddLine(format("|cffcccccc%s|r %s",L["Drag"],L["to move"])) GameTooltip:AddLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to anchor to nearby frames"])) GameTooltip:AddLine(format("|cff00cccc%s|r %s",L["Right-click"],L["for options..."])) local point, anchor, relpoint, x, y = bar:GetAnchor() if point then local ofsx, ofsy = insidePointOffsetFuncs[point](x,y) if (anchor and anchor ~= "UIParent") or (ofsx == 0 and ofsy == 0) then --anchor = anchor or "UIParent" GameTooltip:AddLine(format("%s <%s>",L["Currently anchored to"],anchor)) end end GameTooltip:Show() end overlay:SetScript("OnDragStop", function() f:StopMovingOrSizing() f.isMoving = false f:SetScript("OnUpdate",nil) if IsShiftKeyDown() then local w, h = bar:GetButtonSize() local a, p, rp, x, y = GetClosestPointSnapped(f,w,h) if a then f:ClearAllPoints() f:SetPoint(p,a,rp,x,y) end HideSnapIndicator() end StoreExtents(bar) ReAction:RefreshOptions() UpdateDragTooltip() UpdateAnchorDecoration() end ) overlay:SetScript("OnEnter", function() UpdateDragTooltip() end ) overlay:SetScript("OnLeave", HideGameTooltip) overlay:SetScript("OnClick", function() ReAction:ShowEditor(bar) end ) function overlay:LIBKEYBOUND_ENABLED(evt) self:SetFrameLevel(1) end function overlay:LIBKEYBOUND_DISABLED(evt) self:SetFrameLevel(3) end KB.RegisterCallback(overlay,"LIBKEYBOUND_ENABLED") KB.RegisterCallback(overlay,"LIBKEYBOUND_DISABLED") if ReAction:GetKeybindMode() then overlay:SetFrameLevel(1) end bar:SetLabel(bar:GetName()) UpdateLabelString(bar) UpdateAnchorDecoration() return overlay end -- export methods to the Bar prototype function Bar:ShowControls(show) local f = self.controlFrame if show then if not f then f = CreateControls(self) self.controlFrame = f end f:Show() elseif f then f:Hide() end end function Bar:SetLabel(name) self.labelName = name UpdateLabelString(self) end function Bar:SetLabelSubtext(text) self.labelSubtext = text UpdateLabelString(self) end