Mercurial > wow > devian
view UI.lua @ 72:da5ff1fc9fb6
- Fixed an issue with creating more than one output channel per UI session.
- Cleanup of globals for slightly better performance when printing to a lot of channels at once
author | Nenue |
---|---|
date | Sat, 09 Apr 2016 05:51:19 -0400 |
parents | d73b883b415b |
children | 80ad43c94033 |
line wrap: on
line source
--- Devian - UI.lua -- @file-author@ -- @project-revision@ @project-hash@ -- @file-revision@ @file-hash@ -- Created: 12/27/2015 3:01 AM if not LibStub then print('Something has happened...') end local _, D = ... local DEVIAN_FRAME = 'DevianConsole' local insert, tonumber, pairs, concat = tinsert, tonumber, pairs, table.concat local L = D.L local print = D.print local Console_OnMovementChanged = function(self, event) local db = D.db if self.enabled then if event == 'PLAYER_STARTED_MOVING' then self.moveFade:Stop() local F1 = self.moveFade.alphaOut F1:SetFromAlpha(db.movement_fade_from) F1:SetToAlpha(db.movement_fade_to) F1:SetDuration(db.movement_fade_time) self.moveFade:Play() self:EnableMouse(false) else self.moveFade:Stop() local F1 = self.moveFade.alphaOut F1:SetToAlpha(db.movement_fade_from) F1:SetFromAlpha(db.movement_fade_to) F1:SetDuration(db.movement_fade_time) self.moveFade:Play() self:EnableMouse(true) end end end local function Console_MinMax(self) if self.minimized then self:Maximize() else self:Minimize() end end local function Console_Minimize(self) self:SetHeight(20) self:SetMaxResize(GetScreenWidth(),20) self.minimized = true self.out:Hide() self:Save() end local function Console_Maximize(self) local db = D.channels[self.index] self:SetHeight(db.height) self:SetMaxResize(GetScreenWidth(),GetScreenHeight()) self.minimized = nil self.out:Show() self:Save() end local function Console_Save(self) local db = D.currentProfile.channels[self.index] db.x = self:GetLeft() db.y = (self:GetTop() - GetScreenHeight()) db.width = self:GetWidth() if not self.minimized then db.height = self:GetHeight() self:SetHeight(db.height) end db.dockedTo = self.dockedTo db.docked = self.docked db.minimized = self.minimized db.enabled = self.enabled db.active = self.active self:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.x, db.y) self:SetWidth(db.width) end --- Brings the console to the front. -- Frame method used to bring a console frame to the front of the display stack. local function Console_ToFront(c) local db = D.db local profile = D.currentProfile c:Raise() c:SetAlpha(db.frontalpha) c.out.backdrop:SetTexture(unpack(db.frontdrop)) c.out.backdrop:SetGradientAlpha(unpack(db.frontgrad)) c.out.backdrop:SetBlendMode(db.frontblend) c.dropmenu.icon:SetVertexColor(unpack(db.frontheader)) c.title:SetTextColor(unpack(db.frontborder)) --oldprint('changing current toplevel from', db.current_channel, 'to', c.index) profile.current_channel = c.index --oldprint('toplevel is now', db.current_channel) c:Save() -- update dock buttons local beacon = D.dock.buttons[c.index] beacon.selected = true beacon.newMessage = nil D.UpdateBeacon(beacon) for _, part in pairs(c.border) do part:SetTexture(unpack(db.frontborder)) end for id, bc in pairs(D.console) do if id ~= c.index then bc:SetAlpha(db.backalpha) bc.out.backdrop:SetTexture(unpack(db.backdrop)) bc.out.backdrop:SetGradientAlpha(unpack(db.backgrad)) bc.out.backdrop:SetBlendMode(db.backblend) bc.dropmenu.icon:SetVertexColor(unpack(db.backheader)) bc.title:SetTextColor(unpack(db.backborder)) local beacon = D.dock.buttons[bc.index] beacon.raised = nil beacon.showName = nil beacon.selected = nil D.UpdateBeacon(beacon) for _, part in pairs(bc.border) do part:SetTexture(unpack(db.backborder)) end end end end local function Console_MouseDown(self, button, up) if button == 'LeftButton' then if up then self:StopMovingOrSizing() self:ToFront() self:Save() elseif self.out.grip:IsMouseOver() then self:StartSizing() else self:StartMoving() end else if up then self:MinMax() end end end local function Console_MouseUp(self, button) return Console_MouseDown(self, button, true) end --- Constructs the frame object for a console channel -- Initializes the console channel at a specified index. -- Configuration data can be overridden by passing a desired settings table. -- @param i Numeric index of the channel as it manifests in db.channels -- @param vars Optional settings table to be used. local function CreateConsole(i, vars) local db = D.db if tonumber(i) == nil or math.floor(i) ~= i then error('Non-integer index value.') end if not vars then vars = D.channels[i] and D.channels[i] or D.channels[db.primary_channel] end local f f = CreateFrame('Frame', 'DevianChannelFrame' .. i, UIParent, DEVIAN_FRAME) --@debug@ --print(f:GetName()) --print('create(2)') for k,v in pairs(vars) do f[k] = v --@debug@ --print(' f['..type(k)..' '..tostring(k)..'] = '..type(v)..' '..tostring(v)) end f:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', vars.x, vars.y) f:SetSize(vars.width, vars.height) f:Lower() f.out:SetFont(db.font, db.fontsize, db.fontoutline) if (db.current_channel == i) then f.out.backdrop:SetTexture(unpack(db.frontdrop)) f.dropmenu.icon:SetVertexColor(unpack(db.headerfontcolor)) f.title:SetTextColor(unpack(db.headerfontcolor)) f.header:SetAlpha(db.headeralpha) else f.out.backdrop:SetTexture(unpack(db.backdrop)) end f.Save = Console_Save f.Minimize = Console_Minimize f.Maximize = Console_Maximize f.MinMax = Console_MinMax f.ToFront = Console_ToFront f.Toggle = D.Console_Toggle f:SetScript('OnMouseDown', Console_MouseDown) f:SetScript('OnMouseUp', Console_MouseUp) f.profileID = db.current_profile UIDropDownMenu_Initialize(f.menuFrame, function() local info = { { text= "Close", value = "OptClose", func = function () f.enabled = nil f:Hide() f:Save() end },--[[ { text = "Dock", value = "OptDock", func = function() print('Dvn', 'docking shenanary') end }]] } for _, v in ipairs(info) do UIDropDownMenu_AddButton(v) end end, 'MENU') if db.movement_fade then f:RegisterEvent('PLAYER_STARTED_MOVING') f:RegisterEvent('PLAYER_STOPPED_MOVING') f:SetScript('OnEvent', Console_OnMovementChanged) end D.dock.buttons[i] = CreateFrame('Button', 'Channel'..i..'Beacon', UIParent, 'DevianBeacon') D.dock.buttons[i].icon:SetVertexColor(math.random(),math.random(),math.random()) D.dock.buttons[i].console = f D.dock.buttons[i].index = i D.dock.buttons[i].caption.name:SetText(vars.signature) D.dock.buttons[i]:Show() if vars.minimized then f:Minimize() else f:Maximize() end if db.enabled then f.enabled = true f:Show() end return f end --- Updates console information and returns the handle of the channel object that was worked on. -- When key is nil or not a valid handle, a new channel is created using whatever signature can be found in cinfo. -- The signature can be passed as a string, or as a table entry under the key 'signature' -- If the signature of a new channel is also a tag, the channel will be added to that tag -- @param cinfo string signature of a new channel, or a table of config variables to be imposed on the channel -- @param key string signature or index number of channel to operate on -- @usage channel = D:SetChannel('new', nil) -- creates a new channel -- @usage channel = D:SetChannel({x = 200, y = 100}, 4) -- updates channel #4 function D:SetChannel(cinfo, key) local profile = D.currentProfile local t_info = {} local channel, isNew, id, sig, t_id --@debug@ --print('setchan(0) cinfo, key', cinfo, key)--@end-debug@ -- obtain source data if tonumber(key) ~= nil and D.channels[key] then id = tonumber(key) elseif D.sigID[tostring(key)] then id = D.sigID[tostring(key)] else id = profile.default_channel isNew = true end local dbvars = D.channels[id] t_id = id -- overridden later if new t_info.index = t_id -- --@debug@ --print('setchan(1) cinfo, key, id=', cinfo, key, id)--@end-debug@ -- obtain config info if type(cinfo) == 'string' then sig = cinfo cinfo = {signature = sig} elseif type(cinfo) ~= 'table' then -- stop here if a table wans't passed error('Expecting table of string as arg1') elseif cinfo.signature then -- new sig sig = cinfo.signature elseif isNew then -- new channel sig sig = 'Ch' else -- old sig sig = D.channels[id].signature end t_info.signature = sig --@debug@ --print('setchan(2) sig,id,isNew=', sig, id, isNew)--@end-debug@ for k,v in pairs(cinfo) do -- allow all cinfo to pass t_info[k] = v end local blocked = { -- ignore these vars: ['docked'] = true, -- table ['dockedTo'] = true, -- table-related ['signature'] = true} -- already determined for k,v in pairs(dbvars) do if not t_info[k] and not blocked[k] then -- already set or blocked? --print('assign', k, '=', v) t_info[k] = v end end -- new channel overrides if isNew then if D.sigID[sig] then -- find a non-clashing signature local result, i = sig, 1 while D.sigID[result] do result = sig .. i i = i + 1 end t_info.signature = result end t_id = self.max_channel + 1 t_info.index = t_id self.max_channel = t_id --@debug@ --print('setchan(3a) t_id, isNew, sig, t_info.signature=', t_id, isNew, sig, t_info.signature)--@end-debug@ else --@debug@ --print('setchan(3b) t_id, isNew, sig, t_info.signature=', t_id, isNew, sig, t_info.signature)--@end-debug@ end local channel if not self.console[t_id] then -- create a frame if isNew then -- position the channel frame profile.max_channel = t_id t_info.x = t_info.x + 20 t_info.y = t_info.y - 20 profile.channels[t_id] = t_info --@debug@ --print('setchan(4a)', 't_id, x, y=', t_id, t_info.x, t_info.y)--@end-debug@ end channel = CreateConsole(t_id, t_info) self.console[t_id] = channel self.sig[t_info.signature] = channel self.sigID[t_info.signature] = t_id self.IDsig[t_id] = t_info.signature end channel = self.console[t_id] if channel.minimized then channel:Minimize() else channel:Maximize() end if channel.enabled then -- hide or show last since Min/Max mess with visibility --print('setchan(5a) enable') channel:Show() --channel:ToFront() else --print('setchan(5a) disable') channel:Hide() end --@debug@ --print('setchan(end); c:IsVisible(), c.enabled, db.enabled=', channel:IsVisible(), channel.enabled, profile.enabled)--@end-debug@ return channel end --- Console frame toggler -- @paramsig [...] -- @param ... one or more space-seperated channel keys function D:Console_Toggle(input, force) local profile = D.currentProfile local setAll local search = {} local key local n = 0 -- resolve key/sig values from args while self:GetArgs(input,1,n) and n < 255 do key, n = self:GetArgs(input,1,n) if self.sig[key] then --print(key, self.sigID[key]) insert(search, self.sigID[key]) elseif self.console[tonumber(key)] then --print(key, tonumber(key)) insert(search, tonumber(key)) end --oldprint(#search, key, n) end -- if nothing was found, then do an all toggle if #search < 1 then search = self.sigID -- using this since it lists frame ID's setAll = true end -- sort global enable state if setAll then --oldprint('setall', setAll) profile.enabled = (not profile.enabled) and true or nil if force == 0 then profile.enabled = nil end end -- sort local enable states: if global enable, apply that change to channel -- else, channel enable takes precedence for i, id in pairs(search) do local c = self.console[id] if setAll then c.enabled = profile.enabled else c.enabled = (not c.enabled) and true or nil if force == 0 then c.enabled = nil end end if c.enabled then profile.enabled = true c:Show() else c:Hide() end c:Save() end if setAll then if profile.enabled then self:Print('toggled all consoles ON') if D.console[profile.current_channel] then D.console[profile.current_channel]:ToFront() end else self:Print('toggled all consoles OFF') end else local result = {} for i, id in pairs(search) do result[i] = tostring(id) .. ' = ' .. (self.console[id].enabled and 'ON' or 'OFF') end self:Print('toggled: '..concat(result, ', ')) end end local frame_helper = CreateFrame('Frame', 'DevianFrameHelper', UIParent) frame_helper.fill = frame_helper:CreateTexture(nil, 'BACKGROUND') frame_helper.fill:SetTexture(1,0,0,1) frame_helper.fill:SetAllPoints(frame_helper) D.FrameHelper_Update = function(input, editbox) local frame, func = D:GetArgs(input,2) if type(frame) == 'string' then if not _G[frame] then return end frame = _G[frame] elseif type(frame) == 'table' and frame.IsVisible then local x, y = frame:GetCenter() if not (x or y) then frame_helper:ClearAllPoints() frame_helper:SetPoint('CENTER') end else local frame = EnumerateFrames(); -- Get the first frame while frame do if ( frame:IsVisible() and MouseIsOver(frame) ) then print(frame:GetName() or string.format("[Unnamed Frame: %s]", tostring(frame))); end frame = EnumerateFrames(frame); -- Get the next frame end end frame_helper:SetPoint('TOPLEFT', UIParent, 'BOTTOMLEFT', frameHandle:GetLeft(), frameHandle:GetTop()) frame_helper:SetPoint('BOTTOMRIGHT', UIParent, 'BOTTOMLEFT', frameHandle:GetRight(), frameHandle:GetBottom()) end 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