Mercurial > wow > buffalo2
view Config/Config.lua @ 54:ed74c5cabe98
Core
- updated comment notes
Objectives
- force hide blocks when their tracker is hidden
Clock
- convert clock into its own module
- display zone coordinates alongside time
author | Nenue |
---|---|
date | Wed, 01 Jun 2016 20:48:14 -0400 |
parents | 16465f3fd919 |
children | 07ef62fe201f |
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 vn, _G = select(2,...).frame, _G local M = vn:RegisterModule("Options") local tostring, tonumber, floor, max, assert = tostring, tonumber, floor, math.max, assert local unpack, setmetatable, pairs, ipairs, type, wipe = unpack, setmetatable, pairs, ipairs, type, table.wipe local CreateFrame, IsControlKeyDown = _G.CreateFrame, _G.IsControlKeyDown local OpacitySliderFrame, ColorPickerFrame = _G.OpacitySliderFrame, _G.ColorPickerFrame local print = vn.print('Cfgl') local function round(number, decimals) if floor(number) == number then return ('%d'):format(number) end return (("%%.%df"):format(decimals)):format(number) end --- Set up this way to ensure that all the necessary data exists before things domino into something inscrutable M.prototypes = { value = setmetatable({}, {__call = function(self, frame) assert(frame, 'Expected table (received '..type(frame.OptInfo)..')') assert(frame.OptRoot, 'Invalid config table for frame '.. frame:GetName().. '') return self[frame.ValueType](frame.OptTab, frame.OptKey, frame.OptRoot) end}), reset = setmetatable({}, {__call = function(self, frame) assert(frame.GetName, 'Invalid frame reference (received '..type(frame.OptInfo)..')') assert(frame.OptInfo, 'Expecting a table (received '..type(frame.OptInfo)..')') return self[frame.OptType](frame, frame.OptInfo) end}) } M.config = {} M.defaults = { enable = true } local GetValue = M.prototypes.value local ResetField = M.prototypes.reset --- STATE VARIABLES local configInit --- Dummies for addon table upvalues local configFrames = {} -- actual frame objects local displays = vn.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' GetValue.Integer = function(group, key, parent) return function(self) return floor(tonumber(self:GetValue()) + 0.5) end, (parent[group ..key] or parent[defaultGroup..key]) end GetValue.Percent = function(group, key, parent) 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, (parent[group ..key] or parent[defaultGroup..key]) end GetValue.Color = function(group, key, parent) -- 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, (parent[group ..key] or parent[defaultGroup..key]) end GetValue.Check = function(group, key, parent) return function(self) return self:GetChecked() end, parent[group ..key] or vn.Conf[defaultGroup..key] end -- initializes the corresponding type of config field local frameTypeConv = { Color = 'Button', Font = 'Frame', } ResetField.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 ResetField.CheckButton = function(frame, optionInfo) frame.SetValue = function(self, ...) self:SetChecked(...) self.OptRoot[self.OptName] = self:GetChecked() print(self.OptTab) vn.UpdateAll() end frame:SetScript("OnClick",function(self) self.OptRoot[self.OptName] = self:GetChecked() print(self.OptRoot[self.OptName], self:GetChecked()) vn.UpdateAll() end) end ResetField.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}) vn.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 self.OptRoot[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', ... M.config.BuffFrame = { {'BuffButton', 1, {'Max', 'Max', 'Integer', 'Slider', 1, _G.BUFF_MAX_DISPLAY, 1, 1}, -- valueMin, valueMax, valueStep, stepsPerPage {'PerRow', 'Per Row', 'Integer', 'Slider', 1, _G.BUFF_MAX_DISPLAY, 1, 1}, -- valueMin, valueMax, valueStep, stepsPerPage, {'Size', 'Icon Size', 'Integer', 'Slider', 1, 256, 1, 1}, {'Spacing', 'Icon Spacing', 'Integer', 'Slider', 1, 50, 1, 1}, {'DurationSize', 'Duration Text Height', 'Integer', 'Slider', 1, 72, 1, 1}, {'Zoom', 'Icon Zoom', 'Integer', 'Slider', 0, 100, 1, 1}, {'Border', 'Border', 'Integer', 'Slider', 1, 16, 1, 1}, {'Color', 'Default Border', 'Color', 'Color'}, {'RaidColor', 'RaidBuff Border', 'Color', 'Color'}, {'PlayerColor', 'Player Buffs', 'Color', 'Color'}, {'BossColor', 'Encounter Buffs', 'Color', 'Color'}, {'ShowSelfCast', 'Show name for self-casts', 'Check', 'CheckButton'} }, { 'DebuffButton', 1, {'Max', 'Max', 'Integer', 'Slider', 1, _G.DEBUFF_MAX_DISPLAY, 1, 1 } , {'PerRow', 'Per Row', 'Integer', 'Slider', 1, _G.DEBUFF_MAX_DISPLAY, 1, 1 }, 'Size', 'Spacing', 'DurationSize', 'Zoom', 'Border', 'Color', 'RaidColor', 'PlayerColor', 'BossColor', }, { 'TempEnchant', 1, {'Max', 'Max', 'Integer', 'Slider', 1, _G.NUM_TEMP_ENCHANT_FRAMES, 1, 1 }, {'PerRow', 'Per Row', 'Integer', 'Slider', 1, _G.NUM_TEMP_ENCHANT_FRAMES, 1, 1}, 'Size', 'Spacing', 'DurationSize', 'Zoom', 'Border', 'Color', 'RaidColor', 'PlayerColor', 'BossColor', }, { 'ConsolidatedBuff', 2, {'Position', 'Slot Position', 'Integer', 'Slider', 1, _G.BUFF_MAX_DISPLAY, 1, 1 } }, { 'ConsolidatedBuff', 2, 'Size' }, { 'Raid', 3, {'ShowMissing', 'Verbose missing raid buffs', 'Check', '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 = vn: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 moduleName, moduleOpts in pairs(M.config) do for t, taboptions in ipairs(moduleOpts) 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, valueType, configType = unpack(optionInfo) assert(GetValue[valueType], 'Invalid valueType \''..tostring(valueType)..'\' ('..type(valueType)..')') assert(ResetField[configType], 'Invalid fieldType \''..tostring(configType)..'\' ('..type(configType)..')') 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, 'Vn_'.. moduleName ..'_'.. fullkey, vn, frameTemplate) local f = configFrames[t][row] f.ValueType = valueType f.OptType = configType f.FrameType = frameType f.OptKey = key f.OptRoot = vn.Conf[moduleName] f.OptTab = group f.OptName = fullkey f.OptInfo = optionInfo local valueFunc, initialValue = GetValue(f) print(' value getter', '|cFFFFFF00'..moduleName..'|r.|cFF00FFFF'.. tostring(fullkey),'|r->', valueFunc,initialValue) ResetField(f) 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 ~= self.OptRoot[fullkey] then print(newValue, fullkey) f.fieldvalue:SetText(valueFunc(self, true)) self.OptRoot[fullkey] = valueFunc(self) -- prepare to update vn[moduleName]:OnUpdate() vn.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 = vn.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 end -- grab the last cluster if lastCluster == cluster then print('|cFF00FF00##scooping up last cluster info') configHeight = configHeight + clusterHeight end if not vn.configFramesCreated then vn.configFramesCreated = true vn:SetHeight(vn.header:GetStringHeight() + configSpacing*3 + configHeight) end if configInit then configInit = nil end end M.Command = function(enable, editbox) displays = vn.displays if type(enable) == 'boolean' then vn.Conf.ConfigMode = enable else vn.Conf.ConfigMode = (vn.Conf.ConfigMode == false) and true or false end print('/BUFF', vn.Conf.ConfigMode, type(vn.Conf.ConfigMode)) if vn.Conf.ConfigMode then if not vn.configFramesCreated then InitConfig() end print('Veneer config') vn:Show() else vn:Hide() end vn.UpdateAll() vn.UpdateConfigLayers() end vn.Close = function () M.Command() end vn.ToggleGuides = function(_, self) vn.Conf.GuidesMode = (not vn.Conf.GuidesMode) if vn.Conf.GuidesMode then self:GetNormalTexture():SetTexture(0.94, 0.21, 0.21, 1) else self:GetNormalTexture():SetTexture(0, 0, 0, 1) end vn.UpdateConfigLayers() end M.OnEnable = function() print('|cFFFF0088config module', vn.Conf.ConfigMode) M.Command(vn.Conf.ConfigMode) end M.OnInitialize = function() DEFAULT_CHAT_FRAME:AddMessage("|cFF22D822Veneer|r confogulator loaded. Type |cFF00FFFF/vn|r to begin.") SLASH_VENEER1, SLASH_VENEER2 = "/veneer", "/vn" SlashCmdList.VENEER = M.Command end