Mercurial > wow > buffalo2
view Veneer.lua @ 118:a86b99c84ccc
Added tag v720.0 for changeset 589045559484
author | Nenue |
---|---|
date | Wed, 17 May 2017 08:23:57 -0400 |
parents | 8c94bee4fdfc |
children | 1f68c46bc4de |
line wrap: on
line source
-- Veneer Custom Interface Framework -- 1. vn OnLoad -- 2. OnEvent where IsLoggedIn() == true -- 3. Setup() where (not self.initialized) -- 4. Update() -- 5. Reanchor() local ADDON, Veneer = ... local VENEER_VERSION = 703 local LE_FREE_FRAMES_GROUP = 1 local type, strrep, ipairs, tinsert, tostring, select = type, string.rep, ipairs, tinsert, tostring, select local pairs, tremove = pairs, tremove local print = DEVIAN_WORKSPACE and function(...) _G.print('Veneer', ...) end or nop local eprint = DEVIAN_WORKSPACE and function(...) _G.print('VeneerEvent', ...) end or nop local wipe = table.wipe SLASH_VENEER1 = "/veneer" SLASH_VENEER2 = "/vn" SlashCmdList.VENEER = function(cmd) if Veneer.ConfigMode then Veneer.ConfigMode = false else Veneer.ConfigMode = true end Veneer:UpdateConfigLayers() end Veneer.modules = {} Veneer.Frames = {} Veneer.ConfigLayers = {} Veneer.FrameClusters = { [LE_FREE_FRAMES_GROUP] = {} } Veneer.parserDepth = 0 Veneer.pendingCalls = {} Veneer.AddOnCheck = {} local defaults = { enableAll = true, ConfigMode = true } local configMode local anonID = 0 local IsFrameHandle = IsFrameHandle local GetAnonymousName = function(key) if not key then anonID = anonID + 1 key = anonID end return 'VN' .. key end local GetTableName = function(table) return (IsFrameHandle(table) and table:GetName()) or tostring(table) end local OFFSET_PARALLELS = { TOP = {'LEFT', 'RIGHT', 'SetHeight'}, BOTTOM = {'LEFT', 'RIGHT', 'SetHeight'}, LEFT = {'TOP', 'BOTTOM', 'SetWidth'}, RIGHT = {'TOP', 'BOTTOM', 'SetWidth'}, } local ANCHOR_OFFSET_POINT = { TOP = 'BOTTOM', TOPLEFT = 'BOTTOMRIGHT', TOPRIGHT = 'BOTTOMLEFT', LEFT = 'RIGHT', RIGHT = 'LEFT', CENTER = 'CENTER', BOTTOM = 'TOP', BOTTOMRIGHT = 'TOPLEFT', BOTTOMLEFT = 'TOPRIGHT', } local ANCHOR_INSET_DELTA = { TOP = {0, -1}, TOPLEFT = {1, -1}, TOPRIGHT = {-1,-1}, LEFT = {1, 0}, BOTTOMLEFT = {1, 1}, BOTTOM = {0, 1}, BOTTOMRIGHT = {-1, 1}, RIGHT = {-1, 0}, CENTER = {0, 0}, } function Veneer:print(...) local txt = '|cFFFFFF00Veneer|r:' for i = 1, select('#', ...) do txt = txt .. ' '.. tostring(select(i, ...)) end DEFAULT_CHAT_FRAME:AddMessage(txt) end function Veneer:OnLoad() print('|cFFFFFF00Veneer!|r') self:RegisterEvent('ADDON_LOADED') self:RegisterEvent('PLAYER_LOGIN') self:RegisterEvent('PLAYER_REGEN_ENABLED') self:RegisterEvent('PLAYER_REGEN_DISABLED') self.DEVIAN_PNAME = 'Veneer' self:RegisterForDrag('LeftButton') end local select, IsAddOnLoaded, IsLoggedIn = select, IsAddOnLoaded, IsLoggedIn function Veneer:OnEvent(event, ...) local print = eprint print('|cFFFF0088OnEvent()|r',event, ...) if (event == 'PLAYER_LOGIN') or (event == 'ADDON_LOADED') then print(IsLoggedIn(), self.initialized) if IsLoggedIn() and not self.intialized then self:Setup() self.intialized = true print('popping init sequence', self.intialized) end if self.intialized then local addon = ... if self.AddOnCheck[addon] then print(' - setting up '..addon..' dependent modules:') local keepChecking = false for index, handler in ipairs(self.AddOnCheck[addon]) do print(' -', handler:GetName(), (not handler.initialized) and (handler.addonFrame and not _G[handler.addonFrame])) if not handler.initialized then print(' '..handler:GetName()..':Setup()') handler:Setup() handler.initialized = true end end if not keepChecking then self.AddOnCheck[addon] = nil end end end elseif event == 'PLAYER_REGEN_ENABLED' then for _, module in pairs(self.modules) do if module:IsShown() and module.hideCombat then module:Hide() end end elseif event == 'PLAYER_REGEN_DISABLED' then for _, module in pairs(self.modules) do if module:IsShown() and module.hideCombat then module:Show() end end end end function Veneer:OnDragStart() self:StartMoving() end function Veneer:OnDragStop() self:StopMovingOrSizing() end local VeneerModule_Setup = function(frame) if not frame.initialized then local doSetup = (not frame.addonTrigger) or select(2, IsAddOnLoaded(frame.addonTrigger)) print(' '..frame:GetName()..'.doSetup =', doSetup) if doSetup then frame:Setup() frame.initialized = true else frame:RegisterEvent('ADDON_LOADED') end end end function Veneer:Setup () print('|cFFFF0088Setup()|r') local resetConfig = (not VeneerData) if (not VeneerData) then VeneerData = defaults VeneerData.version = VENEER_VERSION end self.data = VeneerData self:ExecuteOnClusters(nil, VeneerModule_Setup) self.ConfigMode = VeneerData.ConfigMode self:UpdateConfigLayers() self:Reanchor() self:Update() end function Veneer:UpdateConfigLayers() if VeneerData then VeneerData.ConfigMode = self.ConfigMode end self:print('Config mode '..(self.ConfigMode and '|cFF00FF00ON|r' or '|cFFFF0000OFF|r')..'.') self:ExecuteOnClusters(nil, function(frame) if frame.UpdateConfigLayers then frame:UpdateConfigLayers(self.ConfigMode) end if type(frame.ConfigLayer) == 'table' then for index, region in ipairs(frame.ConfigLayer) do print('setting', frame:GetName() .. '['.. index..']', 'to', self.ConfigMode) region:SetShown(self.ConfigMode) end end self.ConfigLayers[frame] = frame:IsShown() if self.ConfigMode then print(frame:GetName(), self.ConfigLayers[frame]) frame:SetShown(self.ConfigMode) else frame:SetShown(self.ConfigLayers[frame]) end end) end function Veneer:GetClusterFromArgs (...) return primaryAnchor, clusterTable, insertPosition end -- args: frame object, list of anchor groups, true for forced top, number for priority layer local mixins = {} function Veneer:AddHandler(handler, ...) print('|cFFFFFF00'..handler:GetName()..':|r', handler.moduleName, ...) wipe(mixins) for k,v in pairs(VeneerHandlerMixin) do if not handler[k] then tinsert(mixins, k) handler[k] = v end end if #mixins >= 1 then print('* Mixins:|cFF00FF88', table.concat(mixins, ', ')) end self.modules[handler] = handler if not handler.anchorFrame then local primaryAnchor = handler.anchorPoint or 'CENTER' local clusterPriority = handler.anchorPriority self.FrameClusters[primaryAnchor] = self.FrameClusters[primaryAnchor] or {} local clusterTable = self.FrameClusters[primaryAnchor] local clusterIndex if clusterPriority then for i = 1, #clusterTable do if clusterTable[i].anchorPriority and (clusterTable[i].anchorPriority > clusterPriority) then clusterIndex = i print('|cFF00BB00insert position:', clusterPriority, clusterIndex) break else print('pass', clusterTable[i]) clusterIndex = i+1 end end else print('|cFF00BB00inserting at front') clusterIndex = #clusterTable + 1 end if not clusterIndex then clusterIndex = #clusterTable + 1 end tinsert(clusterTable, clusterIndex, handler) print(' cluster', (clusterDepth or 1) .. '.' .. primaryAnchor, clusterTable, 'priority', clusterPriority, 'position', clusterIndex) handler.anchorCluster = clusterTable handler.anchorIndex = clusterIndex else local clusterTable = self.FrameClusters[LE_FREE_FRAMES_GROUP] handler.anchorCluster = clusterTable handler.anchorIndex = #clusterTable+1 tinsert(clusterTable, handler.anchorIndex, handler) print(' free frame') end if handler.addonTrigger and not IsAddOnLoaded(handler.addonTrigger) then print('|cFFFF4400 -- dependency:', handler.addonTrigger) self.AddOnCheck[handler.addonTrigger] = self.AddOnCheck[handler.addonTrigger] or {} tinsert(self.AddOnCheck[handler.addonTrigger], handler) end if self.initialized then print(' -- initialization check') if handler.Setup then local doInit = (not handler.initialized) if handler.addonTrigger and not IsAddOnLoaded(handler.addonTrigger) then doInit = false end -- room to add other checks if doInit then handler:Setup() handler.initialized = true self:InternalReanchor(handler) end end end end function Veneer:Reanchor() self:ExecuteOnClusters(nil, 'Reanchor') self:DynamicReanchor(self) end function Veneer:Update() self:ExecuteOnClusters(nil, function(frame) if frame.initialized and frame.Update then frame:Update() end end) self:Reanchor() end -- updates anchor relations to and from the target handler function Veneer:GetAnchor(...) end -- Recursives updates frame group anchors function Veneer:EvaluateAnchors(parent) parent = parent or self local print = eprint print('|cFF88FF00DynamicReanchor()') for anchorPoint, cluster in pairs(parent.FrameClusters) do if anchorPoint ~= LE_FREE_FRAMES_GROUP then local lastFrame for index, frame in ipairs(cluster) do print(' |cFF00FF00'..index, frame:GetName(), frame:IsShown(), (lastFrame and ('|cFFFFFF00'..lastFrame:GetName()..'|r') or '|cFF00FFFFUIParent')) if frame:IsShown() then if frame.anchorFrame then print(frame.anchorPoint) frame:SetPoint(frame.anchorPoint, frame.anchorFrame, frame.anchorFrom, frame.anchorX, frame.anchorY) print('anchored to', frame.anchorFrame,frame:GetTop(), frame:GetRight()) else anchorPoint = frame.anchorPoint or anchorPoint frame:ClearAllPoints() if lastFrame then frame:SetPoint(anchorPoint, lastFrame, ANCHOR_OFFSET_POINT[anchorPoint], 0, 0) print('moved after', lastFrame,frame:GetTop(), frame:GetRight()) else frame:SetPoint(anchorPoint, UIParent, anchorPoint, frame.anchorX, frame.anchorY) print('stub', anchorPoint, frame.anchorX, frame.anchorY) end lastFrame = frame end end end end end end Veneer.DynamicReanchor = Veneer.EvaluateAnchors -- Evaluates the current visibility state and re-anchors adjacent blocks accordingly function Veneer:InternalReanchor(handler, printFunc) local print = eprint print('|cFF00FFFFVeneer:InternalReanchor('..handler:GetName()..')') if handler.anchorFrame then handler:SetPoint(handler.anchorPoint, handler.anchorFrame, handler.anchorFrom, handler.anchorX, handler.anchorY) return end local anchorPoint = handler.anchorPath or handler.anchorPoint local anchorParent, anchorTo = UIParent, anchorPoint local subPoint, subTo local nextFrame for index, frame in ipairs(handler.anchorCluster) do print(' |cFF00FF00'..index, frame:GetName(), frame:IsVisible()) if frame:IsShown() then if frame ~= handler then anchorParent = frame anchorTo = ANCHOR_OFFSET_POINT[anchorPoint] else nextFrame = handler.anchorCluster[index+1] if nextFrame then subPoint = nextFrame.anchorPath or nextFrame.anchorPoint subTo = ANCHOR_OFFSET_POINT[subPoint] nextFrame:ClearAllPoints() nextFrame:SetPoint(subPoint, handler, subTo, 0, 0) print(' -- pushing '..nextFrame:GetName()..' down the anchor chain', subPoint, subTo) end break end end end if handler:IsShown() then handler:SetPoint(anchorPoint, anchorParent, anchorTo, 0, 0) else if anchorParent and nextFrame then nextFrame:SetPoint(subPoint, handler, subTo, 0, 0) end end print(handler.anchorPoint, anchorParent, anchorTo) if printFunc then printFunc('|cFF88FF00'..handler:GetName()..':SetPoint(', handler.anchorPoint, anchorParent, anchorTo) end end function Veneer:SlideBlock(frame, ...) local print = eprint local aX, aY = frame:GetLeft(), frame:GetTop() frame:SetPoint('TOPLEFT', frame, 'BOTTOMLEFT', aX, aY) frame.animation = frame.animation or {} frame.animation.startX = aX frame.animation.startY = aY local targetPoint, targetParent, targetAnchor, offsetX, offsetY = ... frame.BlockSlide:SetScript('OnFinished', function() frame:SetPoint(targetPoint, targetParent, targetAnchor, offsetX, offsetY) VeneerAnimationMixin.OnFinished(frame) end) end -- execute a function on all clusters in display order function Veneer:ExecuteOnClusters(layer, method) local print = eprint self.parserDepth = self.parserDepth + 1 if not layer then if self.parserDepth > 1 then tinsert(self.pendingCalls, method) print('delaying walk for', method) return end print('|cFF00FF00ExecuteOnClusters|r('..tostring(layer)..', '..tostring(method)..')') else print(' Level '..self.parserDepth) end layer = layer or self.FrameClusters for anchor, cluster in pairs(layer) do for index, frame in ipairs(cluster) do print(' '..anchor..'.'..index..' = '..frame:GetName()) if type(method) == 'function' then method(frame, true) elseif frame[method] then print(' |cFF00FF00'..frame:GetName()) frame[method](frame, true) end end if cluster.FrameClusters then self:ExecuteOnClusters(cluster.FrameClusters, method) end end self.parserDepth = self.parserDepth - 1 if (self.parserDepth == 0) and (#self.pendingCalls >= 1) then local delayedMethod = tremove(self.pendingCalls, 1) print('starting delayed walk for', delayedMethod) self:ExecuteOnClusters(nil, delayedMethod) end end -- Takes frame handle and assigns a block to it function Veneer:Acquire (frame, template) local print = eprint if not frame then print('|cFFFF4400Unable to acquire frame...|r') return end local veneer = self.Frames[frame] if not veneer then local name = GetAnonymousName() veneer = CreateFrame('Frame', name, frame, template) print(self:GetName()..':Acquire()', frame:GetName(), template) veneer:SetAllPoints(frame) veneer:SetParent(frame) veneer.label:SetText(name) veneer.bg:SetColorTexture(0,0,0,0) veneer:Hide() veneer:EnableMouse(false) -- find current X/Y veneer.currentLeft = frame:GetLeft() veneer.currentTop = frame:GetTop() self.Frames[frame] = veneer end return veneer end VeneerCore = Veneer