Mercurial > wow > buffalo2
view Config.lua @ 37:e84d645c8ab8
- revised the tracker update function to build its complete data list up front and use the values as points of comparison for determining possible out of place blocks, which will be iterated over afterward to remove what wasn't re-used
- also entailed revising the exact role of global event handlers and function hooks, limiting their directions of communication so one doesn't end up calling the other multiple or inifinity times
- schema handling polish
author | Nenue |
---|---|
date | Mon, 18 Apr 2016 07:56:23 -0400 |
parents | 66b927b46776 |
children |
line wrap: on
line source
--- 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 M.defaults = { enable = true } --- 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() print('|cFFFF0088config module', B.Conf.ConfigMode) 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