A World of Warcraft Experience Bar addon
worldofwarcraft wow addon midnight

expand options with quest toggle sizing and colors

bdbch 2d49027e dd06af32

+284 -24
+11
Config.lua
··· 4 4 -- Display Options 5 5 showAtMaxLevel = false, 6 6 showIncompleteQuestBar = true, 7 + questTrackingEnabled = true, 7 8 -- Master visibility toggle (can be flipped with /nxp toggle) 8 9 enabled = true, 10 + 11 + -- Bar Size 12 + barWidth = 600, 13 + barHeight = 24, 14 + 15 + -- Bar Colors (RGBA) 16 + colorMain = { r = 0.76, g = 0.38, b = 1, a = 1 }, 17 + colorRested = { r = 0.34, g = 0.61, b = 0.99, a = 0.8 }, 18 + colorQuest = { r = 1, g = 0.64, b = 0.0078, a = 0.25 }, 19 + colorQuestComplete = { r = 1, g = 0.64, b = 0.0078, a = 0.8 }, 9 20 10 21 -- Text Toggles 11 22 showLevelText = true,
+1
NixxnuxXPBar.toc
··· 15 15 ## Author: Nixxnux 16 16 ## Category: Interface Enhancements 17 17 ## IconTexture: Interface\Icons\Inv_cape_special_treasure_c_01 18 + ## SavedVariables: NXP_DB 18 19 19 20 Init.lua 20 21 Config.lua
+234 -18
Options.lua
··· 3 3 F.Options = F.Options or {} 4 4 5 5 local panel 6 + local content 6 7 local controls = {} 8 + local questRelatedKeys = { 9 + trackedOnly = true, 10 + showQuestRestedText = true, 11 + showIncompleteQuestXPText = true, 12 + showCompletedQuestXPText = true, 13 + showIncompleteQuestBar = true, 14 + colorQuest = true, 15 + colorQuestComplete = true, 16 + } 7 17 8 18 local function SetOption(key, value) 9 19 if F.InitDB then F.InitDB() end ··· 25 35 end 26 36 27 37 if F.UpdateUI then F.UpdateUI() end 38 + 39 + if key == "questTrackingEnabled" or key == "trackedOnly" then 40 + if F.State and F.State.UpdateQuestXP then 41 + F.State:UpdateQuestXP() 42 + end 43 + if key == "questTrackingEnabled" and panel and panel:IsShown() then 44 + F.Options.Refresh() 45 + end 46 + end 47 + end 48 + 49 + local function SetNumericOption(key, value) 50 + if F.InitDB then F.InitDB() end 51 + if not F.DB then return end 52 + F.DB[key] = value 53 + if F.UpdateUI then F.UpdateUI() end 54 + end 55 + 56 + local function SetColorOption(key, r, g, b, a) 57 + if F.InitDB then F.InitDB() end 58 + if not F.DB then return end 59 + F.DB[key] = { r = r, g = g, b = b, a = a } 60 + if F.UpdateUI then F.UpdateUI() end 61 + end 62 + 63 + local function GetColorOption(key, fallback) 64 + if F.InitDB then F.InitDB() end 65 + if not F.DB then return fallback[1], fallback[2], fallback[3], fallback[4] end 66 + local color = F.DB[key] 67 + if type(color) == "table" then 68 + if color.r then 69 + return color.r or 1, color.g or 1, color.b or 1, color.a or 1 70 + end 71 + if color[1] then 72 + return color[1] or 1, color[2] or 1, color[3] or 1, color[4] or 1 73 + end 74 + end 75 + return fallback[1], fallback[2], fallback[3], fallback[4] 28 76 end 29 77 30 78 local function CreateHeader(parent, text, y) ··· 42 90 SetOption(key, self:GetChecked()) 43 91 end) 44 92 45 - controls[key] = cb 93 + controls[key] = { type = "checkbox", widget = cb } 46 94 return y - 28 47 95 end 48 96 97 + local function CreateSlider(parent, key, label, y, minValue, maxValue, step) 98 + local name = "NXP_Options_" .. key .. "Slider" 99 + local slider = CreateFrame("Slider", name, parent, "OptionsSliderTemplate") 100 + slider:SetPoint("TOPLEFT", parent, "TOPLEFT", 16, y) 101 + slider:SetMinMaxValues(minValue, maxValue) 102 + slider:SetValueStep(step) 103 + slider:SetObeyStepOnDrag(true) 104 + 105 + local labelText = _G[name .. "Text"] 106 + local lowText = _G[name .. "Low"] 107 + local highText = _G[name .. "High"] 108 + if labelText then labelText:SetText(label) end 109 + if lowText then lowText:SetText(tostring(minValue)) end 110 + if highText then highText:SetText(tostring(maxValue)) end 111 + 112 + slider:SetScript("OnValueChanged", function(self, value) 113 + if self._updating then return end 114 + local rounded = math.floor(value + 0.5) 115 + if step and step < 1 then 116 + rounded = value 117 + end 118 + self._updating = true 119 + self:SetValue(rounded) 120 + self._updating = false 121 + SetNumericOption(key, rounded) 122 + end) 123 + 124 + controls[key] = { type = "slider", widget = slider } 125 + return y - 52 126 + end 127 + 128 + local function CreateColorPicker(parent, key, label, y, fallback) 129 + local labelText = parent:CreateFontString(nil, "ARTWORK", "GameFontHighlight") 130 + labelText:SetPoint("TOPLEFT", parent, "TOPLEFT", 16, y) 131 + labelText:SetText(label) 132 + 133 + local swatch = CreateFrame("Button", nil, parent) 134 + swatch:SetSize(16, 16) 135 + swatch:SetPoint("LEFT", labelText, "RIGHT", 8, 0) 136 + swatch:SetNormalTexture("Interface\\Buttons\\WHITE8x8") 137 + swatch:SetHighlightTexture("Interface\\Buttons\\WHITE8x8", "ADD") 138 + local swatchTex = swatch:GetNormalTexture() 139 + 140 + local border = swatch:CreateTexture(nil, "BORDER") 141 + border:SetPoint("TOPLEFT", swatch, "TOPLEFT", -1, 1) 142 + border:SetPoint("BOTTOMRIGHT", swatch, "BOTTOMRIGHT", 1, -1) 143 + border:SetColorTexture(0, 0, 0, 1) 144 + if swatchTex then 145 + swatchTex:SetPoint("TOPLEFT", swatch, "TOPLEFT", 1, -1) 146 + swatchTex:SetPoint("BOTTOMRIGHT", swatch, "BOTTOMRIGHT", -1, 1) 147 + end 148 + 149 + swatch:SetScript("OnClick", function() 150 + local r, g, b, a = GetColorOption(key, fallback) 151 + local previous = { r = r, g = g, b = b, a = a } 152 + 153 + local function getPickerAlpha() 154 + if ColorPickerFrame.GetColorAlpha then 155 + return ColorPickerFrame:GetColorAlpha() 156 + end 157 + return 1 - (ColorPickerFrame.opacity or 0) 158 + end 159 + 160 + local function applyColor() 161 + local nr, ng, nb = ColorPickerFrame:GetColorRGB() 162 + local na = getPickerAlpha() 163 + SetColorOption(key, nr, ng, nb, na) 164 + F.Options.Refresh() 165 + end 166 + 167 + local function cancelColor() 168 + local pv = previous 169 + if pv then 170 + SetColorOption(key, pv.r, pv.g, pv.b, pv.a) 171 + F.Options.Refresh() 172 + end 173 + end 174 + 175 + if ColorPickerFrame.SetupColorPickerAndShow then 176 + ColorPickerFrame:SetupColorPickerAndShow({ 177 + r = r, 178 + g = g, 179 + b = b, 180 + opacity = 1 - (a or 1), 181 + hasOpacity = true, 182 + swatchFunc = applyColor, 183 + opacityFunc = applyColor, 184 + cancelFunc = cancelColor, 185 + }) 186 + else 187 + ColorPickerFrame.hasOpacity = true 188 + ColorPickerFrame.opacity = 1 - (a or 1) 189 + ColorPickerFrame.previousValues = previous 190 + ColorPickerFrame.func = applyColor 191 + ColorPickerFrame.opacityFunc = applyColor 192 + ColorPickerFrame.cancelFunc = cancelColor 193 + ColorPickerFrame:SetColorRGB(r, g, b) 194 + ColorPickerFrame:Hide() 195 + ColorPickerFrame:Show() 196 + end 197 + end) 198 + 199 + controls[key] = { type = "color", widget = swatch, label = labelText, fallback = fallback } 200 + return y - 24 201 + end 202 + 49 203 function F.Options.Refresh() 50 204 if F.InitDB then F.InitDB() end 51 205 if not F.DB then return end 52 206 53 - for key, cb in pairs(controls) do 54 - cb:SetChecked(F.DB[key] and true or false) 207 + local defaults = F.Config or {} 208 + 209 + for key, control in pairs(controls) do 210 + if control.type == "checkbox" then 211 + control.widget:SetChecked(F.DB[key] and true or false) 212 + elseif control.type == "slider" then 213 + local value = F.DB[key] 214 + if value == nil then value = defaults[key] end 215 + if value == nil then value = 0 end 216 + control.widget._updating = true 217 + control.widget:SetValue(tonumber(value) or 0) 218 + control.widget._updating = false 219 + elseif control.type == "color" then 220 + local r, g, b, a = GetColorOption(key, control.fallback) 221 + local tex = control.widget:GetNormalTexture() 222 + if tex then tex:SetColorTexture(r, g, b, a) end 223 + end 224 + end 225 + 226 + local questEnabled = F.DB.questTrackingEnabled ~= false 227 + for key, _ in pairs(questRelatedKeys) do 228 + local control = controls[key] 229 + if control then 230 + if control.type == "checkbox" or control.type == "slider" then 231 + control.widget:SetEnabled(questEnabled) 232 + if control.widget.Text then 233 + local color = questEnabled and NORMAL_FONT_COLOR or GRAY_FONT_COLOR 234 + control.widget.Text:SetTextColor(color.r, color.g, color.b) 235 + end 236 + elseif control.type == "color" then 237 + if questEnabled then 238 + control.widget:Enable() 239 + control.label:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b) 240 + else 241 + control.widget:Disable() 242 + control.label:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b) 243 + end 244 + end 245 + end 55 246 end 56 247 end 57 248 ··· 72 263 panel = CreateFrame("Frame", "NXP_OptionsPanel", UIParent) 73 264 panel.name = "NixxnuxXPBar" 74 265 75 - local title = panel:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge") 76 - title:SetPoint("TOPLEFT", panel, "TOPLEFT", 16, -16) 266 + local scroll = CreateFrame("ScrollFrame", "NXP_OptionsScrollFrame", panel, "UIPanelScrollFrameTemplate") 267 + scroll:SetPoint("TOPLEFT", panel, "TOPLEFT", 0, -8) 268 + scroll:SetPoint("BOTTOMRIGHT", panel, "BOTTOMRIGHT", -30, 8) 269 + 270 + content = CreateFrame("Frame", nil, scroll) 271 + content:SetSize(1, 1) 272 + scroll:SetScrollChild(content) 273 + 274 + local title = content:CreateFontString(nil, "ARTWORK", "GameFontNormalLarge") 275 + title:SetPoint("TOPLEFT", content, "TOPLEFT", 16, -8) 77 276 title:SetText("NixxnuxXPBar") 78 277 79 - local y = -48 80 - y = CreateHeader(panel, "General", y) 81 - y = CreateCheckbox(panel, "enabled", "Enable addon", y) 82 - y = CreateCheckbox(panel, "trackedOnly", "Count tracked (pinned) quests only", y) 278 + local y = -40 279 + y = CreateHeader(content, "General", y) 280 + y = CreateCheckbox(content, "enabled", "Enable addon", y) 281 + y = CreateCheckbox(content, "questTrackingEnabled", "Enable quest tracking", y) 282 + y = CreateCheckbox(content, "trackedOnly", "Count tracked (pinned) quests only", y) 283 + y = CreateCheckbox(content, "showIncompleteQuestBar", "Show uncompleted quest XP bar", y) 284 + 285 + y = y - 10 286 + y = CreateHeader(content, "Bar Size", y) 287 + y = y - 6 288 + y = CreateSlider(content, "barWidth", "Bar width", y, 200, 900, 1) 289 + y = CreateSlider(content, "barHeight", "Bar height", y, 8, 60, 1) 290 + 291 + y = y - 6 292 + y = CreateHeader(content, "Bar Colors", y) 293 + y = CreateColorPicker(content, "colorMain", "Normal XP", y, { 0.76, 0.38, 1, 1 }) 294 + y = CreateColorPicker(content, "colorRested", "Rested XP", y, { 0.34, 0.61, 0.99, 0.8 }) 295 + y = CreateColorPicker(content, "colorQuest", "Uncompleted Quest XP", y, { 1, 0.64, 0.0078, 0.25 }) 296 + y = CreateColorPicker(content, "colorQuestComplete", "Completed Quest XP", y, { 1, 0.64, 0.0078, 0.8 }) 83 297 84 298 y = y - 10 85 - y = CreateHeader(panel, "Text Labels", y) 86 - y = CreateCheckbox(panel, "showLevelText", "Level text", y) 87 - y = CreateCheckbox(panel, "showXPText", "XP text", y) 88 - y = CreateCheckbox(panel, "showPercentText", "Percent text", y) 89 - y = CreateCheckbox(panel, "showQuestRestedText", "Quest/rested percent text", y) 90 - y = CreateCheckbox(panel, "showLevelingText", "Leveling info text", y) 91 - y = CreateCheckbox(panel, "showIncompleteQuestXPText", "Uncompleted quest XP text", y) 92 - y = CreateCheckbox(panel, "showCompletedQuestXPText", "Completed quest XP text", y) 93 - y = CreateCheckbox(panel, "showRestedXPText", "Rested XP text", y) 299 + y = CreateHeader(content, "Text Labels", y) 300 + y = CreateCheckbox(content, "showLevelText", "Level text", y) 301 + y = CreateCheckbox(content, "showXPText", "XP text", y) 302 + y = CreateCheckbox(content, "showPercentText", "Percent text", y) 303 + y = CreateCheckbox(content, "showQuestRestedText", "Quest/rested percent text", y) 304 + y = CreateCheckbox(content, "showLevelingText", "Leveling info text", y) 305 + y = CreateCheckbox(content, "showIncompleteQuestXPText", "Uncompleted quest XP text", y) 306 + y = CreateCheckbox(content, "showCompletedQuestXPText", "Completed quest XP text", y) 307 + y = CreateCheckbox(content, "showRestedXPText", "Rested XP text", y) 308 + 309 + content:SetHeight(-y + 20) 94 310 95 311 panel:SetScript("OnShow", function() 96 312 F.Options.Refresh()
+7
State.lua
··· 65 65 end 66 66 67 67 function F.State:UpdateQuestXP() 68 + if F.DB and F.DB.questTrackingEnabled == false then 69 + self.questXP = 0 70 + self.completeXP = 0 71 + self.incompleteXP = 0 72 + return 73 + end 74 + 68 75 local numEntries = C_QuestLog.GetNumQuestLogEntries() 69 76 local qXP, cXP, iXP = 0, 0, 0 70 77
+31 -6
UI.lua
··· 216 216 local s = F.State 217 217 local db = F.DB 218 218 219 + if db and db.barWidth and db.barHeight then 220 + F.Frame:SetSize(db.barWidth, db.barHeight) 221 + end 222 + 223 + local function resolveColor(color, fallback) 224 + if type(color) == "table" then 225 + if color.r then 226 + return color.r or 1, color.g or 1, color.b or 1, color.a or 1 227 + end 228 + if color[1] then 229 + return color[1] or 1, color[2] or 1, color[3] or 1, color[4] or 1 230 + end 231 + end 232 + return fallback[1], fallback[2], fallback[3], fallback[4] 233 + end 234 + 235 + if db then 236 + F.BarMain:SetStatusBarColor(resolveColor(db.colorMain, CFG.colorMain)) 237 + F.BarRested:SetStatusBarColor(resolveColor(db.colorRested, CFG.colorRested)) 238 + F.BarQuest:SetStatusBarColor(resolveColor(db.colorQuest, CFG.colorQuest)) 239 + F.BarQuestComplete:SetStatusBarColor(resolveColor(db.colorQuestComplete, CFG.colorQuestComplete)) 240 + end 241 + 219 242 if s.isMaxLevel and not db.showAtMaxLevel then 220 243 F.Frame:Hide() 221 244 return ··· 316 339 local infoParts = {} 317 340 318 341 if db.showQuestRestedText and s.maxXP > 0 then 319 - if (s.completeXP or 0) > 0 then 342 + if db.questTrackingEnabled ~= false and (s.completeXP or 0) > 0 then 320 343 table.insert(infoParts, string.format("Completed Quests: %.1f%%", ((s.completeXP or 0) / s.maxXP * 100))) 321 344 end 322 345 if (s.restedXP or 0) > 0 then ··· 350 373 351 374 do 352 375 local xpParts = {} 353 - if db.showIncompleteQuestXPText and (s.incompleteXP or 0) > 0 then 354 - table.insert(xpParts, string.format("Uncompleted Quest XP: %s", FormatLargeNumber(s.incompleteXP or 0))) 355 - end 356 - if db.showCompletedQuestXPText and (s.completeXP or 0) > 0 then 357 - table.insert(xpParts, string.format("Completed Quest XP: %s", FormatLargeNumber(s.completeXP or 0))) 376 + if db.questTrackingEnabled ~= false then 377 + if db.showIncompleteQuestXPText and (s.incompleteXP or 0) > 0 then 378 + table.insert(xpParts, string.format("Uncompleted Quest XP: %s", FormatLargeNumber(s.incompleteXP or 0))) 379 + end 380 + if db.showCompletedQuestXPText and (s.completeXP or 0) > 0 then 381 + table.insert(xpParts, string.format("Completed Quest XP: %s", FormatLargeNumber(s.completeXP or 0))) 382 + end 358 383 end 359 384 if db.showRestedXPText and (s.restedXP or 0) > 0 then 360 385 table.insert(xpParts, string.format("Rested XP: %s", FormatLargeNumber(s.restedXP or 0)))