This commit is contained in:
Florian Brinker 2016-10-10 21:48:47 +02:00
commit c2ced38961
24 changed files with 3498 additions and 0 deletions

41
AchievementInfo.lua Normal file
View File

@ -0,0 +1,41 @@
--[[
AchievementInfo
@author Asto, @Astarax
]]
-- Init
AchievementInfo.hijackedFirstLoad = false
function AchievementInfo.initialize(eventCode, addOnName)
if (addOnName ~= AchievementInfo.name) then return end
--
if AchievementInfo.hijackedFirstLoad == false then
AchievementInfo.hijackedFirstLoad = true
-- Load Saved Variables
AchievementInfo.savedVars = AchievementInfo.loadSavedVars()
-- Load Language Data
LANG = AchievementInfo.loadLanguage()
-- Settings Panel
AchievementInfo.createSettingsPanel()
-- Register Events
AchievementInfo.registerEvent(EVENT_ACHIEVEMENT_UPDATED, AchievementInfo.onAchievementUpdated)
end
-- Status Output (debug mode only)
if AchievementInfo.settingGet("devDebug") then
zo_callLater(function()
AchievementInfo.echo(AchievementInfo.name .. " initialized in DEBUG MODE :)")
end, 500)
end
end
-- Register the Init Event
AchievementInfo.registerEvent(EVENT_ADD_ON_LOADED, AchievementInfo.initialize)

23
AchievementInfo.txt Normal file
View File

@ -0,0 +1,23 @@
## Title: AchievementInfo
## Description: Displays progress updates for achievements in the chat. You can display update-details like 'Slay 25/100 Monsters' if interested. |cFF0000Important:|r The messages appear only when an achievement is updated. This is no permanent tracking tool.
## Version: 2.10
## Author: |c87B7CCAsto|r, @Astarax
## Contact: mail@coded-with-heart.com
## APIVersion: 100016
## SavedVariables: ACHIEVEMENT_INFO_DB
## OptionalDependsOn: LibAddonMenu-2.0, LibStub
## Libraries:
Libs/LibStub/LibStub.lua
Libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua
## Helper:
AchievementInfoCommon.lua
AchievementInfoLangStore.lua
## Core:
AchievementInfo.lua
AchievementInfoSettings.lua
AchievementInfoApplication.lua

View File

@ -0,0 +1,193 @@
--[[
AchievementInfo
@author Asto, @Astarax
]]
-- Do the magic
function AchievementInfo.onAchievementUpdated(eventCode, achId)
local output = ""
-- addOn enabled?
if AchievementInfo.settingGet("genEnabled") == false then
if AchievementInfo.settingGet("devDebug") == false then
return
else
output = output .. "DEBUG (AddOn Disabled): "
end
end
--
local categoryId = AchievementInfo.getCorrectAchievementCategoryId(achId)
-- ignore unwanted achievements ...
if categoryId == false then
if AchievementInfo.settingGet("devDebug") == false then
return
else
output = output .. "DEBUG (Not Next): "
end
end
--
-- achievement category enabled?
if categoryId ~= false and AchievementInfo.settingGet("cat"..categoryId) == false then
if AchievementInfo.settingGet("devDebug") == false then
return
else
output = output .. "DEBUG (Category Off): "
end
end
--
-- okay continue with the message
local detailOutput = {}
local detailOutputCount = 1
local percentageCmpSum = 0
local percentageReqSum = 0
local percentageStep = false
local percentageStepSize = AchievementInfo.settingGet("genShowUpdateSteps")
local link = GetAchievementLink(achId, LINK_STYLE_BRACKET)
local name, description = GetAchievementInfo(achId)
local catName = "/"
if categoryId ~= false then
catName = GetAchievementCategoryInfo(categoryId)
end
output = output .. "" .. link .. " (" .. catName .. ")"
local numCriteria = GetAchievementNumCriteria(achId)
for i = 1, numCriteria, 1 do
local name, numCompleted, numRequired = GetAchievementCriterion(achId, i)
local tmpOutput = ""
if i > 1 and AchievementInfo.settingGet("genOnePerLine") == false then
tmpOutput = tmpOutput .. ", "
end
tmpOutput = tmpOutput .. name .. " "
tmpOutput = tmpOutput .. AchievementInfo.calcCriteriaColor(numCompleted, numRequired) .. numCompleted .. "|r"
tmpOutput = tmpOutput .. AchievementInfo.clrDefault .. "/" .. "|r"
tmpOutput = tmpOutput .. AchievementInfo.clrCriteriaComplete .. numRequired .. "|r"
tmpOutput = tmpOutput .. AchievementInfo.clrDefault
if AchievementInfo.settingGet("genShowOpenDetailsOnly") == true and numCompleted ~= numRequired then
detailOutput[detailOutputCount] = tmpOutput
detailOutputCount = detailOutputCount + 1
end
-- show the achievement on every special achievement because it's a rare event
if numRequired == 1 and numCompleted == 1 then
percentageStep = true
-- collect the numbers to calculate the correct percentage
else
percentageReqSum = percentageReqSum + numRequired
percentageCmpSum = percentageCmpSum + numCompleted
end
end
if percentageStep == false then
-- show at percent value
local percentage = 100 / percentageReqSum * percentageCmpSum
local percentageNext = 100 / percentageReqSum * (percentageCmpSum + 1)
-- if percentage of percentageStepSize is hit or the value is next to it and the next value will be higher
if --[[percentage > 0 and]] percentage % percentageStepSize == 0 or (percentage % percentageStepSize > percentageNext % percentageStepSize and percentageNext % percentageStepSize ~= 0) then
percentageStep = true
-- show if this is the first numCompleted value
elseif percentageCmpSum == 1 then
percentageStep = true
end
end
-- show details?
local detailsCount = AchievementInfo.tableLength(detailOutput)
if AchievementInfo.settingGet("genShowDetails") == true and detailsCount > 0 and AchievementInfo.settingGet("genOnePerLine") == false then
output = output .. " - "
for i = 1, detailsCount, 1 do
output = output .. detailOutput[i]
end
else
output = output .. "."
end
--
-- output on every step OR when its a defined percentage step
if AchievementInfo.settingGet("genShowEveryUpdate") == false and percentageStep == false then
if AchievementInfo.settingGet("devDebug") == false then
return
else
output = "DEBUG (" .. AchievementInfo.settingGet("genShowUpdateSteps") .. "% Rule): " .. output
end
end
--
--
if percentageReqSum == percentageCmpSum then
output = LANG.Completed .. ": " .. output
else
output = LANG.Updated .. ": " .. output
end
--
AchievementInfo.echo(output)
-- output the details line by line - start @2 because the normal output happend before (achievement name)
if AchievementInfo.settingGet("genShowDetails") == true and AchievementInfo.settingGet("genOnePerLine") == true then
for i = 1, AchievementInfo.tableLength(detailOutput), 1 do
AchievementInfo.echo(detailOutput[i])
end
end
end
-- Check if the category of an achievement is valid (reverse check)
function AchievementInfo.checkForValidCategory(achId)
local categoryTopLevelIndex, categoryIndex, achievementIndex = GetCategoryInfoFromAchievementId(achId)
local reverseAchievementId = GetAchievementId(categoryTopLevelIndex, categoryIndex, achievementIndex)
if achId == reverseAchievementId then
return true
end
return false
end
-- Get the correct achievement category
function AchievementInfo.getCorrectAchievementCategoryId(achId)
local previousAchievementId = GetPreviousAchievementInLine(achId)
local categoryId = 0
if AchievementInfo.checkForValidCategory(achId) == false and previousAchievementId ~= 0 then
return AchievementInfo.getCorrectAchievementCategoryId(previousAchievementId)
elseif AchievementInfo.checkForValidCategory(achId) then
categoryId = GetCategoryInfoFromAchievementId(achId)
return categoryId
else
return false
end
end
-- Calculates the percentage of the achievement completition to define the color
function AchievementInfo.calcCriteriaColor(completed, required)
local percentage = 100 / required * completed
if completed == required then
return AchievementInfo.clrCriteriaComplete
elseif percentage <= 33 then
return AchievementInfo.clrCriteriaFar
elseif percentage <= 66 then
return AchievementInfo.clrCriteriaMedi
else
return AchievementInfo.clrCriteriaClose
end
end

65
AchievementInfoCommon.lua Normal file
View File

@ -0,0 +1,65 @@
--[[
AchievementInfo
@author Asto, @Astarax
]]
AchievementInfo = {}
AchievementInfo.name = "AchievementInfo"
AchievementInfo.author = "Asto, @Astarax"
AchievementInfo.version = 2.10
AchievementInfo.savedVars = nil
AchievementInfo.LangStore = {}
local clrPrefix = "|c"
AchievementInfo.clrDefault = clrPrefix .. "87B7CC"
AchievementInfo.clrCriteriaFar = clrPrefix .. "F27C7C"
AchievementInfo.clrCriteriaMedi = clrPrefix .. "EDE858"
AchievementInfo.clrCriteriaClose = clrPrefix .. "CCF048"
AchievementInfo.clrCriteriaComplete = clrPrefix .. "71DE73"
AchievementInfo.clrSettingsHeader = clrPrefix .. "F0C91A"
-- Load the correct language
function AchievementInfo.loadLanguage()
local lang = GetCVar("language.2")
if lang == "de" then
return LANG_STORE.DE
elseif lang == "fr" then
return LANG_STORE.FR
else
return LANG_STORE.EN
end
end
-- Event Registration Shortcut
function AchievementInfo.registerEvent(event, handler)
EVENT_MANAGER:RegisterForEvent(AchievementInfo.name, event, handler)
end
-- Message Output Shortcut
function AchievementInfo.echo(message)
-- addOn enabled?
if AchievementInfo.settingGet("genEnabled") == false then return end
if message ~= nil then
CHAT_SYSTEM:AddMessage(AchievementInfo.clrDefault..message.."|r")
end
end
-- Helper method to count a lua table
function AchievementInfo.tableLength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end

View File

@ -0,0 +1,165 @@
--[[
AchievementInfo
@author Asto, @Astarax
]]
LANG_STORE = {}
LANG_STORE.EN = {} -- English version by Asto
LANG_STORE.DE = {} -- German version by Asto (native)
LANG_STORE.FR = {} -- French version open
--[[
English version
@author Asto
]]
-- AddOn Output
LANG_STORE.EN.Updated = "Updated"
LANG_STORE.EN.Completed = "Completed"
-- AddOn Settings Header
LANG_STORE.EN.SettingsHeader = {}
LANG_STORE.EN.SettingsHeader.General = "General"
LANG_STORE.EN.SettingsHeader.Categories = "Categories"
LANG_STORE.EN.SettingsHeader.CategoriesDescription = "Here you can setup the notifications per category"
LANG_STORE.EN.SettingsHeader.Development = "Development"
-- AddOn Settings General Options
LANG_STORE.EN.SettingsOption = {}
LANG_STORE.EN.SettingsOption.AddOnEnabled = "AddOn enabled"
LANG_STORE.EN.SettingsOption.AddOnEnabledTooltip = "Enable or disable this AddOn"
LANG_STORE.EN.SettingsOption.AddOnEnabledWarning = "Only the output messages can be disabled here"
LANG_STORE.EN.SettingsOption.ShowEveryUpdate = "Show every update"
LANG_STORE.EN.SettingsOption.ShowEveryUpdateTooltip = "Shows a message on every status update of an achievement. Otherwise the messages appear only in steps of x%"
LANG_STORE.EN.SettingsOption.ShowUpdateSteps = "Notification steps (%)"
LANG_STORE.EN.SettingsOption.ShowUpdateStepsTooltip = "Defines the step width of notifications, if '" .. LANG_STORE.EN.SettingsOption.ShowEveryUpdate .. "' is disabled"
LANG_STORE.EN.SettingsOption.ShowDetails = "Show details"
LANG_STORE.EN.SettingsOption.ShowDetailsTooltip = "Shows progress details in each update message"
LANG_STORE.EN.SettingsOption.ShowOpenDetailsOnly = "Show incomplete details only"
LANG_STORE.EN.SettingsOption.ShowOpenDetailsOnlyTooltip = "Shows only the incomplete tasks of an achiemevent in the details"
-- pCHat compatibility option
LANG_STORE.EN.SettingsOption.OneElementPerLine = "Output line by line"
LANG_STORE.EN.SettingsOption.OneElementPerLineTooltip = "Shows each part of an achievement in a single line"
LANG_STORE.EN.SettingsOption.OneElementPerLineWarning = "Necessary for pChat compatibility"
-- AddOn Settings Category Options
-- The categories are taken from the game language files
LANG_STORE.EN.SettingsOption.CategoryTooltip = "Show messages for the category"
-- AddOn Settings Development Options
LANG_STORE.EN.SettingsOption.DebugMode = "Debug Mode"
LANG_STORE.EN.SettingsOption.DebugModeTooltip = "Shows hidden messages to check if they are hidden by mistake"
LANG_STORE.EN.SettingsOption.DebugModeWarning = "In most cases you don't need to activate this option"
--[[
German version
@author Asto
]]
-- AddOn Output
LANG_STORE.DE.Updated = "Aktualisiert"
LANG_STORE.DE.Completed = "Abgeschlossen"
-- AddOn Settings Header
LANG_STORE.DE.SettingsHeader = {}
LANG_STORE.DE.SettingsHeader.General = "Allgemein"
LANG_STORE.DE.SettingsHeader.Categories = "Kategorien"
LANG_STORE.DE.SettingsHeader.CategoriesDescription = "Hier können die Benachrichtigungen je Kategorie eingestellt werden"
LANG_STORE.DE.SettingsHeader.Development = "Entwicklung"
-- AddOn Settings General Options
LANG_STORE.DE.SettingsOption = {}
LANG_STORE.DE.SettingsOption.AddOnEnabled = "AddOn aktiviert"
LANG_STORE.DE.SettingsOption.AddOnEnabledTooltip = "Aktiviere oder deaktiviere dieses AddOn"
LANG_STORE.DE.SettingsOption.AddOnEnabledWarning = "An dieser Stelle können nur die Ausgaben deaktiviert werden."
LANG_STORE.DE.SettingsOption.ShowEveryUpdate = "Zeige alle Fortschritte"
LANG_STORE.DE.SettingsOption.ShowEveryUpdateTooltip = "Zeigt bei jeder Aktualisierung eines Erfolgs einen Hinweis. Alternativ wird nur in x% Schritten ein Status ausgegeben"
LANG_STORE.DE.SettingsOption.ShowUpdateSteps = "Benachrichtigungsschritte (%)"
LANG_STORE.DE.SettingsOption.ShowUpdateStepsTooltip = "Definiert die Schrittweite (Häufigkeit) der Benachrichtigungen, wenn '" .. LANG_STORE.DE.SettingsOption.ShowEveryUpdate .. "' deaktiviert ist"
LANG_STORE.DE.SettingsOption.ShowDetails = "Zeige Details"
LANG_STORE.DE.SettingsOption.ShowDetailsTooltip = "Zeigt die Fortschritt-Details des Erfolgs im Hinweis an"
LANG_STORE.DE.SettingsOption.ShowOpenDetailsOnly = "Zeige nur unerledigte Details"
LANG_STORE.DE.SettingsOption.ShowOpenDetailsOnlyTooltip = "Zeigt nur offene Aufgaben in den Fortschritt-Details an"
-- pCHat compatibility option
LANG_STORE.DE.SettingsOption.OneElementPerLine = "Zeilenweise Ausgabe"
LANG_STORE.DE.SettingsOption.OneElementPerLineTooltip = "Zeigt jeden Unterpunkt eines Erfolgs als eigene Zeile im Chat"
LANG_STORE.DE.SettingsOption.OneElementPerLineWarning = "Voraussetzung für eine pChat Kompatibilität"
-- AddOn Settings Category Options
-- The categories are taken from the game language files
LANG_STORE.DE.SettingsOption.CategoryTooltip = "Zeige Nachrichten für die Kategorie"
-- AddOn Settings Development Options
LANG_STORE.DE.SettingsOption.DebugMode = "Debug Modus"
LANG_STORE.DE.SettingsOption.DebugModeTooltip = "Zeigt versteckte Nachrichten, um zu prüfen ob ggf. Nachrichten unrechtmäßig unterdrückt werden"
LANG_STORE.DE.SettingsOption.DebugModeWarning = "In den meißten Fällen muss diese Option nicht aktiviert werden"
--[[
French version
@author Llwydd
]]
-- AddOn Output
LANG_STORE.FR.Updated = "Mis à jour"
LANG_STORE.FR.Completed = "Terminé"
-- AddOn Settings Header
LANG_STORE.FR.SettingsHeader = {}
LANG_STORE.FR.SettingsHeader.General = "Général"
LANG_STORE.FR.SettingsHeader.Categories = "Catégories"
LANG_STORE.FR.SettingsHeader.CategoriesDescription = "Ici vous pouvez gérer les notifications par catégories"
LANG_STORE.FR.SettingsHeader.Development = "Développement"
-- AddOn Settings General Options
LANG_STORE.FR.SettingsOption = {}
LANG_STORE.FR.SettingsOption.AddOnEnabled = "Extension activée"
LANG_STORE.FR.SettingsOption.AddOnEnabledTooltip = "Active ou désactive cette extension"
LANG_STORE.FR.SettingsOption.AddOnEnabledWarning = "Seul les messages sortants peuvent être désactivés"
LANG_STORE.FR.SettingsOption.ShowEveryUpdate = "Affichage de chaque mise à jour"
LANG_STORE.FR.SettingsOption.ShowEveryUpdateTooltip = "Affiche un message pour chaque mise à jour d'un succès. Le reste du temps les messages n'apparaissent que sous forme de plage de x%"
LANG_STORE.FR.SettingsOption.ShowUpdateSteps = "Etapes de notification (%)"
LANG_STORE.FR.SettingsOption.ShowUpdateStepsTooltip = "Définie la plage des notifications, si '" .. LANG_STORE.FR.SettingsOption.ShowEveryUpdate .. "' est désactivé"
LANG_STORE.FR.SettingsOption.ShowDetails = "Affichage des détails"
LANG_STORE.FR.SettingsOption.ShowDetailsTooltip = "Affiche les détails de progression de chaque message de mise à jour"
LANG_STORE.FR.SettingsOption.ShowOpenDetailsOnly = "Affichage des détails incomplets"
LANG_STORE.FR.SettingsOption.ShowOpenDetailsOnlyTooltip = "Affiche, dans les détails, uniquement les taches incomplètes d'un succès"
-- pCHat compatibility option
LANG_STORE.FR.SettingsOption.OneElementPerLine = "Sortie ligne par ligne"
LANG_STORE.FR.SettingsOption.OneElementPerLineTooltip = "Affiche chaque partie d'un succès sur une simple ligne"
LANG_STORE.FR.SettingsOption.OneElementPerLineWarning = "Nécessite la compatibilité avec pChat"
-- AddOn Settings Category Options
-- The categories are taken from the game language files
LANG_STORE.FR.SettingsOption.CategoryTooltip = "Affiche les messages pour la catégorie"
-- AddOn Settings Development Options
LANG_STORE.FR.SettingsOption.DebugMode = "Mode de débogage"
LANG_STORE.FR.SettingsOption.DebugModeTooltip = "Affiche les messages cachés pour vérifier s'ils n'ont pas été cachés par erreur"
LANG_STORE.FR.SettingsOption.DebugModeWarning = "Dans la majorité des cas vous n'avez pas besoin d'activer cette option"

175
AchievementInfoSettings.lua Normal file
View File

@ -0,0 +1,175 @@
--[[
AchievementInfo
@author Asto, @Astarax
]]
-- Function to set and load the Saved Variables
function AchievementInfo.loadSavedVars()
local defaults = {
genEnabled = true,
genShowEveryUpdate = true,
genShowUpdateSteps = 25,
genShowDetails = false,
genShowOpenDetailsOnly = true,
genOnePerLine = true,
cat1 = true,
cat2 = true,
cat3 = true,
cat4 = true,
cat5 = true,
cat6 = true,
cat7 = true,
cat8 = true,
cat9 = true,
cat10 = true,
devDebug = false
}
return ZO_SavedVars:New("ACHIEVEMENT_INFO_DB", 1, nil, defaults)
end
-- Function to create the settings panel
function AchievementInfo.createSettingsPanel()
local LAM = LibStub("LibAddonMenu-2.0")
local panelData = {
type = "panel",
name = AchievementInfo.name,
displayName = AchievementInfo.clrDefault..AchievementInfo.name,
author = AchievementInfo.author,
version = string.format("%.1f", AchievementInfo.version),
slashCommand = "/achievementInfo"
}
local optionsTable = {
[1] = {
type = "header",
name = AchievementInfo.clrSettingsHeader..LANG.SettingsHeader.General
},
[2] = {
type = "checkbox",
name = LANG.SettingsOption.AddOnEnabled,
tooltip = LANG.SettingsOption.AddOnEnabledTooltip,
getFunc = function() return AchievementInfo.settingGet("genEnabled") end,
setFunc = function() AchievementInfo.settingToogle("genEnabled") end,
warning = LANG.SettingsOption.AddOnEnabledWarning
},
[3] = {
type = "checkbox",
name = LANG.SettingsOption.ShowEveryUpdate,
tooltip = LANG.SettingsOption.ShowEveryUpdateTooltip,
getFunc = function() return AchievementInfo.settingGet("genShowEveryUpdate") end,
setFunc = function() AchievementInfo.settingToogle("genShowEveryUpdate") end
},
[4] = {
type = "slider",
name = LANG.SettingsOption.ShowUpdateSteps,
tooltip = LANG.SettingsOption.ShowUpdateStepsTooltip,
min = 1,
max = 100,
step = 1,
getFunc = function() return AchievementInfo.settingGet("genShowUpdateSteps") end,
setFunc = function(value) AchievementInfo.settingSet("genShowUpdateSteps", value) end,
default = 25
},
[5] = {
type = "checkbox",
name = LANG.SettingsOption.ShowDetails,
tooltip = LANG.SettingsOption.ShowDetailsTooltip,
getFunc = function() return AchievementInfo.settingGet("genShowDetails") end,
setFunc = function() AchievementInfo.settingToogle("genShowDetails") end
},
[6] = {
type = "checkbox",
name = LANG.SettingsOption.ShowOpenDetailsOnly,
tooltip = LANG.SettingsOption.ShowOpenDetailsOnlyTooltip,
getFunc = function() return AchievementInfo.settingGet("genShowOpenDetailsOnly") end,
setFunc = function() AchievementInfo.settingToogle("genShowOpenDetailsOnly") end
},
[7] = {
type = "checkbox",
name = LANG.SettingsOption.OneElementPerLine,
tooltip = LANG.SettingsOption.OneElementPerLineTooltip,
getFunc = function() return AchievementInfo.settingGet("genOnePerLine") end,
setFunc = function() AchievementInfo.settingToogle("genOnePerLine") end,
warning = LANG.SettingsOption.OneElementPerLineWarning
},
[8] = {
type = "header",
name = AchievementInfo.clrSettingsHeader .. LANG.SettingsHeader.Categories
},
[9] = {
type = "description",
text = LANG.SettingsHeader.CategoriesDescription .. ":"
}
}
-- Add categories dynamically
local numCats = GetNumAchievementCategories()
local catCount = 1
for i = 1, numCats, 1 do
catName, numSubCats = GetAchievementCategoryInfo(i)
table.insert(optionsTable, {
type = "checkbox",
name = catName,
tooltip = LANG.SettingsOption.CategoryTooltip .. " '" .. catName .. "'",
getFunc = function() return AchievementInfo.settingGet("cat"..i) end,
setFunc = function() AchievementInfo.settingToogle("cat"..i) end
})
end
-- Debug setting at the end
table.insert(optionsTable, {
type = "header",
name = AchievementInfo.clrSettingsHeader .. LANG.SettingsHeader.Development
})
table.insert(optionsTable, {
type = "checkbox",
name = LANG.SettingsOption.DebugMode,
tooltip = LANG.SettingsOption.DebugModeTooltip,
getFunc = function() return AchievementInfo.settingGet("devDebug") end,
setFunc = function() AchievementInfo.settingToogle("devDebug") end,
warning = LANG.SettingsOption.DebugModeWarning
})
-- Register
LAM:RegisterAddonPanel(AchievementInfo.name.."SettingsPanel", panelData)
LAM:RegisterOptionControls(AchievementInfo.name.."SettingsPanel", optionsTable)
end
-- Function to retrieve settings
function AchievementInfo.settingGet(id)
if AchievementInfo.savedVars[id] == nil then
AchievementInfo.savedVars[id] = false
return false
else
return AchievementInfo.savedVars[id]
end
end
-- Function to toggle Checkbox values
function AchievementInfo.settingToogle(id)
if AchievementInfo.savedVars[id] == false then
AchievementInfo.savedVars[id] = true
else
AchievementInfo.savedVars[id] = false
end
end
-- Function to set settings
function AchievementInfo.settingSet(id, value)
AchievementInfo.savedVars[id] = value
end

25
Libs/LibAddonMenu-2.0.txt Normal file
View File

@ -0,0 +1,25 @@
## APIVersion: 100011
## Title: LibAddonMenu-2.0
## Version: 2.0 r18
## Author: Seerah, sirinsidiator, et al.
## Contributors: votan, merlight, Garkin
## Description: A library to aid in the creation of option panels.
LibStub\LibStub.lua
LibAddonMenu-2.0\LibAddonMenu-2.0.lua
LibAddonMenu-2.0\controls\panel.lua
LibAddonMenu-2.0\controls\submenu.lua
LibAddonMenu-2.0\controls\button.lua
LibAddonMenu-2.0\controls\checkbox.lua
LibAddonMenu-2.0\controls\colorpicker.lua
LibAddonMenu-2.0\controls\custom.lua
LibAddonMenu-2.0\controls\description.lua
LibAddonMenu-2.0\controls\dropdown.lua
LibAddonMenu-2.0\controls\editbox.lua
LibAddonMenu-2.0\controls\header.lua
LibAddonMenu-2.0\controls\slider.lua
LibAddonMenu-2.0\controls\texture.lua
LibAddonMenu-2.0\controls\iconpicker.lua

View File

@ -0,0 +1,201 @@
The Artistic License 2.0
Copyright (c) 2015 Ryan Lakanen (Seerah)
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
This license establishes the terms under which a given free software
Package may be copied, modified, distributed, and/or redistributed.
The intent is that the Copyright Holder maintains some artistic
control over the development of that Package while still keeping the
Package available as open source and free software.
You are always permitted to make arrangements wholly outside of this
license directly with the Copyright Holder of a given Package. If the
terms of this license do not permit the full use that you propose to
make of the Package, you should contact the Copyright Holder and seek
a different licensing arrangement.
Definitions
"Copyright Holder" means the individual(s) or organization(s)
named in the copyright notice for the entire Package.
"Contributor" means any party that has contributed code or other
material to the Package, in accordance with the Copyright Holder's
procedures.
"You" and "your" means any person who would like to copy,
distribute, or modify the Package.
"Package" means the collection of files distributed by the
Copyright Holder, and derivatives of that collection and/or of
those files. A given Package may consist of either the Standard
Version, or a Modified Version.
"Distribute" means providing a copy of the Package or making it
accessible to anyone else, or in the case of a company or
organization, to others outside of your company or organization.
"Distributor Fee" means any fee that you charge for Distributing
this Package or providing support for this Package to another
party. It does not mean licensing fees.
"Standard Version" refers to the Package if it has not been
modified, or has been modified only in ways explicitly requested
by the Copyright Holder.
"Modified Version" means the Package, if it has been changed, and
such changes were not explicitly requested by the Copyright
Holder.
"Original License" means this Artistic License as Distributed with
the Standard Version of the Package, in its current version or as
it may be modified by The Perl Foundation in the future.
"Source" form means the source code, documentation source, and
configuration files for the Package.
"Compiled" form means the compiled bytecode, object code, binary,
or any other form resulting from mechanical transformation or
translation of the Source form.
Permission for Use and Modification Without Distribution
(1) You are permitted to use the Standard Version and create and use
Modified Versions for any purpose without restriction, provided that
you do not Distribute the Modified Version.
Permissions for Redistribution of the Standard Version
(2) You may Distribute verbatim copies of the Source form of the
Standard Version of this Package in any medium without restriction,
either gratis or for a Distributor Fee, provided that you duplicate
all of the original copyright notices and associated disclaimers. At
your discretion, such verbatim copies may or may not include a
Compiled form of the Package.
(3) You may apply any bug fixes, portability changes, and other
modifications made available from the Copyright Holder. The resulting
Package will still be considered the Standard Version, and as such
will be subject to the Original License.
Distribution of Modified Versions of the Package as Source
(4) You may Distribute your Modified Version as Source (either gratis
or for a Distributor Fee, and with or without a Compiled form of the
Modified Version) provided that you clearly document how it differs
from the Standard Version, including, but not limited to, documenting
any non-standard features, executables, or modules, and provided that
you do at least ONE of the following:
(a) make the Modified Version available to the Copyright Holder
of the Standard Version, under the Original License, so that the
Copyright Holder may include your modifications in the Standard
Version.
(b) ensure that installation of your Modified Version does not
prevent the user installing or running the Standard Version. In
addition, the Modified Version must bear a name that is different
from the name of the Standard Version.
(c) allow anyone who receives a copy of the Modified Version to
make the Source form of the Modified Version available to others
under
(i) the Original License or
(ii) a license that permits the licensee to freely copy,
modify and redistribute the Modified Version using the same
licensing terms that apply to the copy that the licensee
received, and requires that the Source form of the Modified
Version, and of any works derived from it, be made freely
available in that license fees are prohibited but Distributor
Fees are allowed.
Distribution of Compiled Forms of the Standard Version
or Modified Versions without the Source
(5) You may Distribute Compiled forms of the Standard Version without
the Source, provided that you include complete instructions on how to
get the Source of the Standard Version. Such instructions must be
valid at the time of your distribution. If these instructions, at any
time while you are carrying out such distribution, become invalid, you
must provide new instructions on demand or cease further distribution.
If you provide valid instructions or cease distribution within thirty
days after you become aware that the instructions are invalid, then
you do not forfeit any of your rights under this license.
(6) You may Distribute a Modified Version in Compiled form without
the Source, provided that you comply with Section 4 with respect to
the Source of the Modified Version.
Aggregating or Linking the Package
(7) You may aggregate the Package (either the Standard Version or
Modified Version) with other packages and Distribute the resulting
aggregation provided that you do not charge a licensing fee for the
Package. Distributor Fees are permitted, and licensing fees for other
components in the aggregation are permitted. The terms of this license
apply to the use and Distribution of the Standard or Modified Versions
as included in the aggregation.
(8) You are permitted to link Modified and Standard Versions with
other works, to embed the Package in a larger work of your own, or to
build stand-alone binary or bytecode versions of applications that
include the Package, and Distribute the result without restriction,
provided the result does not expose a direct interface to the Package.
Items That are Not Considered Part of a Modified Version
(9) Works (including, but not limited to, modules and scripts) that
merely extend or make use of the Package, do not, by themselves, cause
the Package to be a Modified Version. In addition, such works are not
considered parts of the Package itself, and are not subject to the
terms of this license.
General Provisions
(10) Any use, modification, and distribution of the Standard or
Modified Versions is governed by this Artistic License. By using,
modifying or distributing the Package, you accept this license. Do not
use, modify, or distribute the Package, if you do not accept this
license.
(11) If your Modified Version has been derived from a Modified
Version made by someone other than you, you are nevertheless required
to ensure that your Modified Version complies with the requirements of
this license.
(12) This license does not grant you the right to use any trademark,
service mark, tradename, or logo of the Copyright Holder.
(13) This license includes the non-exclusive, worldwide,
free-of-charge patent license to make, have made, use, offer to sell,
sell, import and otherwise transfer the Package with respect to any
patent claims licensable by the Copyright Holder that are necessarily
infringed by the Package. If you institute patent litigation
(including a cross-claim or counterclaim) against any party alleging
that the Package constitutes direct or contributory patent
infringement, then this Artistic License to you shall terminate on the
date that such litigation is filed.
(14) Disclaimer of Warranty:
THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,809 @@
-- LibAddonMenu-2.0 & its files © Ryan Lakanen (Seerah) --
-- Distributed under The Artistic License 2.0 (see LICENSE) --
------------------------------------------------------------------
--Register LAM with LibStub
local MAJOR, MINOR = "LibAddonMenu-2.0", 18
local lam, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not lam then return end --the same or newer version of this lib is already loaded into memory
local messages = {}
local MESSAGE_PREFIX = "[LAM2] "
local function PrintLater(msg)
if CHAT_SYSTEM.primaryContainer then
d(MESSAGE_PREFIX .. msg)
else
messages[#messages + 1] = msg
end
end
local function FlushMessages()
for i = 1, #messages do
d(MESSAGE_PREFIX .. messages[i])
end
messages = {}
end
if LAMSettingsPanelCreated and not LAMCompatibilityWarning then
PrintLater("An old version of LibAddonMenu with compatibility issues was detected. For more information on how to proceed search for LibAddonMenu on esoui.com")
LAMCompatibilityWarning = true
end
--UPVALUES--
local wm = WINDOW_MANAGER
local em = EVENT_MANAGER
local sm = SCENE_MANAGER
local cm = CALLBACK_MANAGER
local tconcat = table.concat
local tinsert = table.insert
local addonsForList = {}
local addonToOptionsMap = {}
local optionsCreated = {}
lam.widgets = lam.widgets or {}
local widgets = lam.widgets
lam.util = {}
local util = lam.util
local function GetTooltipText(tooltip)
if type(tooltip) == "string" then
return tooltip
elseif type(tooltip) == "function" then
return tostring(tooltip())
end
return nil
end
local function CreateBaseControl(parent, controlData, controlName)
local control = wm:CreateControl(controlName or controlData.reference, parent.scroll or parent, CT_CONTROL)
control.panel = parent.panel or parent -- if this is in a submenu, panel is the submenu's parent
control.data = controlData
control.isHalfWidth = controlData.width == "half"
control:SetWidth(control.panel:GetWidth() - 60)
return control
end
local MIN_HEIGHT = 26
local HALF_WIDTH_LINE_SPACING = 2
local function CreateLabelAndContainerControl(parent, controlData, controlName)
local control = CreateBaseControl(parent, controlData, controlName)
local width = control:GetWidth()
local container = wm:CreateControl(nil, control, CT_CONTROL)
container:SetDimensions(width / 3, MIN_HEIGHT)
control.container = container
local label = wm:CreateControl(nil, control, CT_LABEL)
label:SetFont("ZoFontWinH4")
label:SetHeight(MIN_HEIGHT)
label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
label:SetText(controlData.name)
control.label = label
if control.isHalfWidth then
control:SetDimensions(width / 2, MIN_HEIGHT * 2 + HALF_WIDTH_LINE_SPACING)
label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0)
label:SetAnchor(TOPRIGHT, control, TOPRIGHT, 0, 0)
container:SetAnchor(TOPRIGHT, control.label, BOTTOMRIGHT, 0, HALF_WIDTH_LINE_SPACING)
else
control:SetDimensions(width, MIN_HEIGHT)
container:SetAnchor(TOPRIGHT, control, TOPRIGHT, 0, 0)
label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0)
label:SetAnchor(TOPRIGHT, container, TOPLEFT, 5, 0)
end
control.data.tooltipText = GetTooltipText(control.data.tooltip)
control:SetMouseEnabled(true)
control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
return control
end
util.GetTooltipText = GetTooltipText
util.CreateBaseControl = CreateBaseControl
util.CreateLabelAndContainerControl = CreateLabelAndContainerControl
local ADDON_DATA_TYPE = 1
local RESELECTING_DURING_REBUILD = true
local USER_REQUESTED_OPEN = true
--INTERNAL FUNCTION
--scrolls ZO_ScrollList `list` to move the row corresponding to `data`
-- into view (does nothing if there is no such row in the list)
--unlike ZO_ScrollList_ScrollDataIntoView, this function accounts for
-- fading near the list's edges - it avoids the fading area by scrolling
-- a little further than the ZO function
local function ScrollDataIntoView(list, data)
local targetIndex = data.sortIndex
if not targetIndex then return end
local scrollMin, scrollMax = list.scrollbar:GetMinMax()
local scrollTop = list.scrollbar:GetValue()
local controlHeight = list.controlHeight
local targetMin = controlHeight * (targetIndex - 1) - 64
-- subtracting 64 ain't arbitrary, it's the maximum fading height
-- (libraries/zo_templates/scrolltemplates.lua/UpdateScrollFade)
if targetMin < scrollTop then
ZO_ScrollList_ScrollAbsolute(list, zo_max(targetMin, scrollMin))
else
local listHeight = ZO_ScrollList_GetHeight(list)
local targetMax = controlHeight * targetIndex + 64 - listHeight
if targetMax > scrollTop then
ZO_ScrollList_ScrollAbsolute(list, zo_min(targetMax, scrollMax))
end
end
end
--INTERNAL FUNCTION
--constructs a string pattern from the text in `searchEdit` control
-- * metacharacters are escaped, losing their special meaning
-- * whitespace matches anything (including empty substring)
--if there is nothing but whitespace, returns nil
--otherwise returns a filter function, which takes a `data` table argument
-- and returns true iff `data.filterText` matches the pattern
local function GetSearchFilterFunc(searchEdit)
local text = searchEdit:GetText():lower()
local pattern = text:match("(%S+.-)%s*$")
if not pattern then -- nothing but whitespace
return nil
end
-- escape metacharacters, e.g. "ESO-Datenbank.de" => "ESO%-Datenbank%.de"
pattern = pattern:gsub("[-*+?^$().[%]%%]", "%%%0")
-- replace whitespace with "match shortest anything"
pattern = pattern:gsub("%s+", ".-")
return function(data)
return data.filterText:lower():find(pattern) ~= nil
end
end
--INTERNAL FUNCTION
--populates `addonList` with entries from `addonsForList`
-- addonList = ZO_ScrollList control
-- filter = [optional] function(data)
local function PopulateAddonList(addonList, filter)
local entryList = ZO_ScrollList_GetDataList(addonList)
local numEntries = 0
local selectedData = nil
ZO_ScrollList_Clear(addonList)
for i, data in ipairs(addonsForList) do
if not filter or filter(data) then
local dataEntry = ZO_ScrollList_CreateDataEntry(ADDON_DATA_TYPE, data)
numEntries = numEntries + 1
data.sortIndex = numEntries
entryList[numEntries] = dataEntry
-- select the first panel passing the filter, or the currently
-- shown panel, but only if it passes the filter as well
if selectedData == nil or data.panel == lam.currentAddonPanel then
selectedData = data
end
else
data.sortIndex = nil
end
end
ZO_ScrollList_Commit(addonList)
if selectedData then
if selectedData.panel == lam.currentAddonPanel then
ZO_ScrollList_SelectData(addonList, selectedData, nil, RESELECTING_DURING_REBUILD)
else
ZO_ScrollList_SelectData(addonList, selectedData, nil)
end
ScrollDataIntoView(addonList, selectedData)
end
end
--METHOD: REGISTER WIDGET--
--each widget has its version checked before loading,
--so we only have the most recent one in memory
--Usage:
-- widgetType = "string"; the type of widget being registered
-- widgetVersion = integer; the widget's version number
LAMCreateControl = LAMCreateControl or {}
local lamcc = LAMCreateControl
function lam:RegisterWidget(widgetType, widgetVersion)
if widgets[widgetType] and widgets[widgetType] >= widgetVersion then
return false
else
widgets[widgetType] = widgetVersion
return true
end
end
--METHOD: OPEN TO ADDON PANEL--
--opens to a specific addon's option panel
--Usage:
-- panel = userdata; the panel returned by the :RegisterOptionsPanel method
local locSettings = GetString(SI_GAME_MENU_SETTINGS)
function lam:OpenToPanel(panel)
-- find and select the panel's row in addon list
local addonList = lam.addonList
local selectedData = nil
for _, addonData in ipairs(addonsForList) do
if addonData.panel == panel then
selectedData = addonData
ScrollDataIntoView(addonList, selectedData)
break
end
end
ZO_ScrollList_SelectData(addonList, selectedData)
ZO_ScrollList_RefreshVisible(addonList, selectedData)
local srchEdit = LAMAddonSettingsWindow:GetNamedChild("SearchFilterEdit")
srchEdit:Clear()
-- note that ZO_ScrollList doesn't require `selectedData` to be actually
-- present in the list, and that the list will only be populated once LAM
-- "Addon Settings" menu entry is selected for the first time
local function openAddonSettingsMenu()
local gameMenu = ZO_GameMenu_InGame.gameMenu
local settingsMenu = gameMenu.headerControls[locSettings]
if settingsMenu then -- an instance of ZO_TreeNode
local children = settingsMenu:GetChildren()
for i = 1, (children and #children or 0) do
local childNode = children[i]
local data = childNode:GetData()
if data and data.id == lam.panelId then
-- found LAM "Addon Settings" node, yay!
childNode:GetTree():SelectNode(childNode)
break
end
end
end
end
if sm:GetScene("gameMenuInGame"):GetState() == SCENE_SHOWN then
openAddonSettingsMenu()
else
sm:CallWhen("gameMenuInGame", SCENE_SHOWN, openAddonSettingsMenu)
sm:Show("gameMenuInGame")
end
end
--INTERNAL FUNCTION
--creates controls when options panel is first shown
--controls anchoring of these controls in the panel
local function CreateOptionsControls(panel)
local addonID = panel:GetName()
local optionsTable = addonToOptionsMap[addonID]
if optionsTable then
local function CreateAndAnchorWidget(parent, widgetData, offsetX, offsetY, anchorTarget, wasHalf)
local widget
local status, err = pcall(function() widget = LAMCreateControl[widgetData.type](parent, widgetData) end)
if not status then
return err or true, offsetY, anchorTarget, wasHalf
else
local isHalf = (widgetData.width == "half")
if not anchorTarget then -- the first widget in a panel is just placed in the top left corner
widget:SetAnchor(TOPLEFT)
anchorTarget = widget
elseif wasHalf and isHalf then -- when the previous widget was only half width and this one is too, we place it on the right side
widget:SetAnchor(TOPLEFT, anchorTarget, TOPRIGHT, 5 + (offsetX or 0), 0)
widget.lineControl = anchorTarget
offsetY = zo_max(0, widget:GetHeight() - anchorTarget:GetHeight()) -- we need to get the common height of both widgets to know where the next row starts
isHalf = false
else -- otherwise we just put it below the previous one normally
widget:SetAnchor(TOPLEFT, anchorTarget, BOTTOMLEFT, 0, 15 + offsetY)
offsetY = 0
anchorTarget = widget
end
return false, offsetY, anchorTarget, isHalf
end
end
local THROTTLE_TIMEOUT, THROTTLE_COUNT = 10, 20
local fifo = {}
local anchorOffset, lastAddedControl, wasHalf
local CreateWidgetsInPanel, err
local function PrepareForNextPanel()
anchorOffset, lastAddedControl, wasHalf = 0, nil, false
end
local function SetupCreationCalls(parent, widgetDataTable)
fifo[#fifo + 1] = PrepareForNextPanel
local count = #widgetDataTable
for i = 1, count, THROTTLE_COUNT do
fifo[#fifo + 1] = function()
CreateWidgetsInPanel(parent, widgetDataTable, i, zo_min(i + THROTTLE_COUNT - 1, count))
end
end
return count ~= NonContiguousCount(widgetDataTable)
end
CreateWidgetsInPanel = function(parent, widgetDataTable, startIndex, endIndex)
for i=startIndex,endIndex do
local widgetData = widgetDataTable[i]
if not widgetData then
PrintLater("Skipped creation of missing entry in the settings menu of " .. addonID .. ".")
else
local widgetType = widgetData.type
local offsetX = 0
local isSubmenu = (widgetType == "submenu")
if isSubmenu then
wasHalf = false
offsetX = 5
end
err, anchorOffset, lastAddedControl, wasHalf = CreateAndAnchorWidget(parent, widgetData, offsetX, anchorOffset, lastAddedControl, wasHalf)
if err then
PrintLater(("Could not create %s '%s' of %s."):format(widgetData.type, widgetData.name or "unnamed", addonID))
end
if isSubmenu then
if SetupCreationCalls(lastAddedControl, widgetData.controls) then
PrintLater(("The sub menu '%s' of %s is missing some entries."):format(widgetData.name or "unnamed", addonID))
end
end
end
end
end
local function DoCreateSettings()
if #fifo > 0 then
local nextCall = table.remove(fifo, 1)
nextCall()
if(nextCall == PrepareForNextPanel) then
DoCreateSettings()
else
zo_callLater(DoCreateSettings, THROTTLE_TIMEOUT)
end
else
optionsCreated[addonID] = true
cm:FireCallbacks("LAM-PanelControlsCreated", panel)
end
end
if SetupCreationCalls(panel, optionsTable) then
PrintLater(("The settings menu of %s is missing some entries."):format(addonID))
end
DoCreateSettings()
end
end
--INTERNAL FUNCTION
--handles switching between panels
local function ToggleAddonPanels(panel) --called in OnShow of newly shown panel
local currentlySelected = lam.currentAddonPanel
if currentlySelected and currentlySelected ~= panel then
currentlySelected:SetHidden(true)
end
lam.currentAddonPanel = panel
-- refresh visible rows to reflect panel IsHidden status
ZO_ScrollList_RefreshVisible(lam.addonList)
if not optionsCreated[panel:GetName()] then --if this is the first time opening this panel, create these options
CreateOptionsControls(panel)
end
cm:FireCallbacks("LAM-RefreshPanel", panel)
end
local CheckSafetyAndInitialize
--METHOD: REGISTER ADDON PANEL
--registers your addon with LibAddonMenu and creates a panel
--Usage:
-- addonID = "string"; unique ID which will be the global name of your panel
-- panelData = table; data object for your panel - see controls\panel.lua
function lam:RegisterAddonPanel(addonID, panelData)
CheckSafetyAndInitialize(addonID)
local container = lam:GetAddonPanelContainer()
local panel = lamcc.panel(container, panelData, addonID) --addonID==global name of panel
panel:SetHidden(true)
panel:SetAnchorFill(container)
panel:SetHandler("OnShow", ToggleAddonPanels)
local function stripMarkup(str)
return str:gsub("|[Cc]%x%x%x%x%x%x", ""):gsub("|[Rr]", "")
end
local filterParts = {panelData.name, nil, nil}
-- append keywords and author separately, the may be nil
filterParts[#filterParts + 1] = panelData.keywords
filterParts[#filterParts + 1] = panelData.author
local addonData = {
panel = panel,
name = stripMarkup(panelData.name),
filterText = stripMarkup(tconcat(filterParts, "\t")):lower(),
}
tinsert(addonsForList, addonData)
if panelData.slashCommand then
SLASH_COMMANDS[panelData.slashCommand] = function()
lam:OpenToPanel(panel)
end
end
return panel --return for authors creating options manually
end
--METHOD: REGISTER OPTION CONTROLS
--registers the options you want shown for your addon
--these are stored in a table where each key-value pair is the order
--of the options in the panel and the data for that control, respectively
--see exampleoptions.lua for an example
--see controls\<widget>.lua for each widget type
--Usage:
-- addonID = "string"; the same string passed to :RegisterAddonPanel
-- optionsTable = table; the table containing all of the options controls and their data
function lam:RegisterOptionControls(addonID, optionsTable) --optionsTable = {sliderData, buttonData, etc}
addonToOptionsMap[addonID] = optionsTable
end
--INTERNAL FUNCTION
--creates LAM's Addon Settings entry in ZO_GameMenu
local function CreateAddonSettingsMenuEntry()
--Russian for TERAB1T's RuESO addon, which creates an "ru" locale
--game font does not support Cyrillic, so they are using custom fonts + extended latin charset
--Spanish provided by Luisen75 for their translation project
local controlPanelNames = {
en = "Addon Settings",
fr = "Extensions",
de = "Erweiterungen",
ru = "Îacòpoéêè äoïoìîeîèé",
es = "Configura Addons",
}
local panelData = {
id = KEYBOARD_OPTIONS.currentPanelId,
name = controlPanelNames[GetCVar("Language.2")] or controlPanelNames["en"],
}
KEYBOARD_OPTIONS.currentPanelId = panelData.id + 1
KEYBOARD_OPTIONS.panelNames[panelData.id] = panelData.name
lam.panelId = panelData.id
local addonListSorted = false
function panelData.callback()
sm:AddFragment(lam:GetAddonSettingsFragment())
KEYBOARD_OPTIONS:ChangePanels(lam.panelId)
local title = LAMAddonSettingsWindow:GetNamedChild("Title")
title:SetText(panelData.name)
if not addonListSorted and #addonsForList > 0 then
local searchEdit = LAMAddonSettingsWindow:GetNamedChild("SearchFilterEdit")
--we're about to show our list for the first time - let's sort it
table.sort(addonsForList, function(a, b) return a.name < b.name end)
PopulateAddonList(lam.addonList, GetSearchFilterFunc(searchEdit))
addonListSorted = true
end
end
function panelData.unselectedCallback()
sm:RemoveFragment(lam:GetAddonSettingsFragment())
if SetCameraOptionsPreviewModeEnabled then -- available since API version 100011
SetCameraOptionsPreviewModeEnabled(false)
end
end
ZO_GameMenu_AddSettingPanel(panelData)
end
--INTERNAL FUNCTION
--creates the left-hand menu in LAM's window
local function CreateAddonList(name, parent)
local addonList = wm:CreateControlFromVirtual(name, parent, "ZO_ScrollList")
local function addonListRow_OnMouseDown(control, button)
if button == 1 then
local data = ZO_ScrollList_GetData(control)
ZO_ScrollList_SelectData(addonList, data, control)
end
end
local function addonListRow_OnMouseEnter(control)
ZO_ScrollList_MouseEnter(addonList, control)
end
local function addonListRow_OnMouseExit(control)
ZO_ScrollList_MouseExit(addonList, control)
end
local function addonListRow_Select(previouslySelectedData, selectedData, reselectingDuringRebuild)
if not reselectingDuringRebuild then
if previouslySelectedData then
previouslySelectedData.panel:SetHidden(true)
end
if selectedData then
selectedData.panel:SetHidden(false)
PlaySound(SOUNDS.MENU_SUBCATEGORY_SELECTION)
end
end
end
local function addonListRow_Setup(control, data)
control:SetText(data.name)
control:SetSelected(not data.panel:IsHidden())
end
ZO_ScrollList_AddDataType(addonList, ADDON_DATA_TYPE, "ZO_SelectableLabel", 28, addonListRow_Setup)
-- I don't know how to make highlights clear properly; they often
-- get stuck and after a while the list is full of highlighted rows
--ZO_ScrollList_EnableHighlight(addonList, "ZO_ThinListHighlight")
ZO_ScrollList_EnableSelection(addonList, "ZO_ThinListHighlight", addonListRow_Select)
local addonDataType = ZO_ScrollList_GetDataTypeTable(addonList, ADDON_DATA_TYPE)
local addonListRow_CreateRaw = addonDataType.pool.m_Factory
local function addonListRow_Create(pool)
local control = addonListRow_CreateRaw(pool)
control:SetHandler("OnMouseDown", addonListRow_OnMouseDown)
--control:SetHandler("OnMouseEnter", addonListRow_OnMouseEnter)
--control:SetHandler("OnMouseExit", addonListRow_OnMouseExit)
control:SetHeight(28)
control:SetFont("ZoFontHeader")
control:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
control:SetVerticalAlignment(TEXT_ALIGN_CENTER)
control:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
return control
end
addonDataType.pool.m_Factory = addonListRow_Create
return addonList
end
--INTERNAL FUNCTION
local function CreateSearchFilterBox(name, parent)
local boxControl = wm:CreateControl(name, parent, CT_CONTROL)
local srchButton = wm:CreateControl("$(parent)Button", boxControl, CT_BUTTON)
srchButton:SetDimensions(32, 32)
srchButton:SetAnchor(LEFT, nil, LEFT, 2, 0)
srchButton:SetNormalTexture("EsoUI/Art/LFG/LFG_tabIcon_groupTools_up.dds")
srchButton:SetPressedTexture("EsoUI/Art/LFG/LFG_tabIcon_groupTools_down.dds")
srchButton:SetMouseOverTexture("EsoUI/Art/LFG/LFG_tabIcon_groupTools_over.dds")
local srchEdit = wm:CreateControlFromVirtual("$(parent)Edit", boxControl, "ZO_DefaultEdit")
srchEdit:SetAnchor(LEFT, srchButton, RIGHT, 4, 1)
srchEdit:SetAnchor(RIGHT, nil, RIGHT, -4, 1)
srchEdit:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
local srchBg = wm:CreateControl("$(parent)Bg", boxControl, CT_BACKDROP)
srchBg:SetAnchorFill()
srchBg:SetAlpha(0)
srchBg:SetCenterColor(0, 0, 0, 0.5)
srchBg:SetEdgeColor(ZO_DISABLED_TEXT:UnpackRGBA())
srchBg:SetEdgeTexture("", 1, 1, 0, 0)
-- search backdrop should appear whenever you hover over either
-- the magnifying glass button or the edit field (which is only
-- visible when it contains some text), and also while the edit
-- field has keyboard focus
local srchActive = false
local srchHover = false
local function srchBgUpdateAlpha()
if srchActive or srchEdit:HasFocus() then
srchBg:SetAlpha(srchHover and 0.8 or 0.6)
else
srchBg:SetAlpha(srchHover and 0.6 or 0.0)
end
end
local function srchMouseEnter(control)
srchHover = true
srchBgUpdateAlpha()
end
local function srchMouseExit(control)
srchHover = false
srchBgUpdateAlpha()
end
boxControl:SetMouseEnabled(true)
boxControl:SetHitInsets(1, 1, -1, -1)
boxControl:SetHandler("OnMouseEnter", srchMouseEnter)
boxControl:SetHandler("OnMouseExit", srchMouseExit)
srchButton:SetHandler("OnMouseEnter", srchMouseEnter)
srchButton:SetHandler("OnMouseExit", srchMouseExit)
local focusLostTime = 0
srchButton:SetHandler("OnClicked", function(self)
srchEdit:Clear()
if GetFrameTimeMilliseconds() - focusLostTime < 100 then
-- re-focus the edit box if it lost focus due to this
-- button click (note that this handler may run a few
-- frames later)
srchEdit:TakeFocus()
end
end)
srchEdit:SetHandler("OnMouseEnter", srchMouseEnter)
srchEdit:SetHandler("OnMouseExit", srchMouseExit)
srchEdit:SetHandler("OnFocusGained", srchBgUpdateAlpha)
srchEdit:SetHandler("OnFocusLost", function()
focusLostTime = GetFrameTimeMilliseconds()
srchBgUpdateAlpha()
end)
srchEdit:SetHandler("OnEscape", function(self)
self:Clear()
self:LoseFocus()
end)
srchEdit:SetHandler("OnTextChanged", function(self)
local filterFunc = GetSearchFilterFunc(self)
if filterFunc then
srchActive = true
srchBg:SetEdgeColor(ZO_SECOND_CONTRAST_TEXT:UnpackRGBA())
srchButton:SetState(BSTATE_PRESSED)
else
srchActive = false
srchBg:SetEdgeColor(ZO_DISABLED_TEXT:UnpackRGBA())
srchButton:SetState(BSTATE_NORMAL)
end
srchBgUpdateAlpha()
PopulateAddonList(lam.addonList, filterFunc)
PlaySound(SOUNDS.SPINNER_DOWN)
end)
return boxControl
end
--INTERNAL FUNCTION
--creates LAM's Addon Settings top-level window
local function CreateAddonSettingsWindow()
local tlw = wm:CreateTopLevelWindow("LAMAddonSettingsWindow")
tlw:SetHidden(true)
tlw:SetDimensions(1010, 914) -- same height as ZO_OptionsWindow
ZO_ReanchorControlForLeftSidePanel(tlw)
-- create black background for the window (mimic ZO_RightFootPrintBackground)
local bgLeft = wm:CreateControl("$(parent)BackgroundLeft", tlw, CT_TEXTURE)
bgLeft:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_left.dds")
bgLeft:SetDimensions(1024, 1024)
bgLeft:SetAnchor(TOPLEFT, nil, TOPLEFT)
bgLeft:SetDrawLayer(DL_BACKGROUND)
bgLeft:SetExcludeFromResizeToFitExtents(true)
local bgRight = wm:CreateControl("$(parent)BackgroundRight", tlw, CT_TEXTURE)
bgRight:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_right.dds")
bgRight:SetDimensions(64, 1024)
bgRight:SetAnchor(TOPLEFT, bgLeft, TOPRIGHT)
bgRight:SetDrawLayer(DL_BACKGROUND)
bgRight:SetExcludeFromResizeToFitExtents(true)
-- create gray background for addon list (mimic ZO_TreeUnderlay)
local underlayLeft = wm:CreateControl("$(parent)UnderlayLeft", tlw, CT_TEXTURE)
underlayLeft:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_indexArea_left.dds")
underlayLeft:SetDimensions(256, 1024)
underlayLeft:SetAnchor(TOPLEFT, bgLeft, TOPLEFT)
underlayLeft:SetDrawLayer(DL_BACKGROUND)
underlayLeft:SetExcludeFromResizeToFitExtents(true)
local underlayRight = wm:CreateControl("$(parent)UnderlayRight", tlw, CT_TEXTURE)
underlayRight:SetTexture("EsoUI/Art/Miscellaneous/centerscreen_indexArea_right.dds")
underlayRight:SetDimensions(128, 1024)
underlayRight:SetAnchor(TOPLEFT, underlayLeft, TOPRIGHT)
underlayRight:SetDrawLayer(DL_BACKGROUND)
underlayRight:SetExcludeFromResizeToFitExtents(true)
-- create title bar (mimic ZO_OptionsWindow)
local title = wm:CreateControl("$(parent)Title", tlw, CT_LABEL)
title:SetAnchor(TOPLEFT, nil, TOPLEFT, 65, 70)
title:SetFont("ZoFontWinH1")
title:SetModifyTextType(MODIFY_TEXT_TYPE_UPPERCASE)
local divider = wm:CreateControlFromVirtual("$(parent)Divider", tlw, "ZO_Options_Divider")
divider:SetAnchor(TOPLEFT, nil, TOPLEFT, 65, 108)
-- create search filter box
local srchBox = CreateSearchFilterBox("$(parent)SearchFilter", tlw)
srchBox:SetAnchor(TOPLEFT, nil, TOPLEFT, 63, 120)
srchBox:SetDimensions(260, 30)
-- create scrollable addon list
local addonList = CreateAddonList("$(parent)AddonList", tlw)
addonList:SetAnchor(TOPLEFT, nil, TOPLEFT, 65, 160)
addonList:SetDimensions(285, 665)
lam.addonList = addonList -- for easy access from elsewhere
-- create container for option panels
local panelContainer = wm:CreateControl("$(parent)PanelContainer", tlw, CT_CONTROL)
panelContainer:SetAnchor(TOPLEFT, nil, TOPLEFT, 365, 120)
panelContainer:SetDimensions(645, 675)
return tlw
end
--INITIALIZING
local safeToInitialize = false
local hasInitialized = false
local eventHandle = table.concat({MAJOR, MINOR}, "r")
local function OnLoad(_, addonName)
-- wait for the first loaded event
em:UnregisterForEvent(eventHandle, EVENT_ADD_ON_LOADED)
safeToInitialize = true
end
em:RegisterForEvent(eventHandle, EVENT_ADD_ON_LOADED, OnLoad)
local function OnActivated(_, addonName)
em:UnregisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED)
FlushMessages()
end
em:RegisterForEvent(eventHandle, EVENT_PLAYER_ACTIVATED, OnActivated)
function CheckSafetyAndInitialize(addonID)
if not safeToInitialize then
local msg = string.format("The panel with id '%s' was registered before addon loading has completed. This might break the AddOn Settings menu.", addonID)
PrintLater(msg)
end
if not hasInitialized then
hasInitialized = true
end
end
--TODO documentation
function lam:GetAddonPanelContainer()
local fragment = lam:GetAddonSettingsFragment()
local window = fragment:GetControl()
return window:GetNamedChild("PanelContainer")
end
--TODO documentation
function lam:GetAddonSettingsFragment()
assert(hasInitialized or safeToInitialize)
if not LAMAddonSettingsFragment then
local window = CreateAddonSettingsWindow()
LAMAddonSettingsFragment = ZO_FadeSceneFragment:New(window, true, 100)
CreateAddonSettingsMenuEntry()
end
return LAMAddonSettingsFragment
end
-- vi: noexpandtab

View File

@ -0,0 +1,89 @@
--[[buttonData = {
type = "button",
name = "My Button",
tooltip = "Button's tooltip text.",
func = function() end,
width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional)
icon = "icon\\path.dds", --(optional)
warning = "Will need to reload the UI.", --(optional)
reference = "MyAddonButton" --(optional) unique global reference to control
} ]]
local widgetVersion = 7
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("button", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
control.button:SetEnabled(not disable)
end
--controlName is optional
local MIN_HEIGHT = 28 -- default_button height
local HALF_WIDTH_LINE_SPACING = 2
function LAMCreateControl.button(parent, buttonData, controlName)
local control = LAM.util.CreateBaseControl(parent, buttonData, controlName)
control:SetMouseEnabled(true)
local width = control:GetWidth()
if control.isHalfWidth then
control:SetDimensions(width / 2, MIN_HEIGHT * 2 + HALF_WIDTH_LINE_SPACING)
else
control:SetDimensions(width, MIN_HEIGHT)
end
if buttonData.icon then
control.button = wm:CreateControl(nil, control, CT_BUTTON)
control.button:SetDimensions(26, 26)
control.button:SetNormalTexture(buttonData.icon)
control.button:SetPressedOffset(2, 2)
else
--control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton")
control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton")
control.button:SetWidth(width / 3)
control.button:SetText(buttonData.name)
end
local button = control.button
button:SetAnchor(control.isHalfWidth and CENTER or RIGHT)
button:SetClickSound("Click")
button.data = {tooltipText = LAM.util.GetTooltipText(buttonData.tooltip)}
button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
button:SetHandler("OnClicked", function(self, ...)
buttonData.func(self, ...)
if control.panel.data.registerForRefresh then
cm:FireCallbacks("LAM-RefreshPanel", control)
end
end)
if buttonData.warning then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, button, LEFT, -5, 0)
control.warning.data = {tooltipText = buttonData.warning}
end
if buttonData.disabled then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
--this is here because buttons don't have an UpdateValue method
if control.panel.data.registerForRefresh then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
end
return control
end

View File

@ -0,0 +1,144 @@
--[[checkboxData = {
type = "checkbox",
name = "My Checkbox",
tooltip = "Checkbox's tooltip text.",
getFunc = function() return db.var end,
setFunc = function(value) db.var = value doStuff() end,
width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional)
default = defaults.var, --(optional)
reference = "MyAddonCheckbox" --(optional) unique global reference to control
} ]]
local widgetVersion = 9
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("checkbox", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
--label
local enabledColor = ZO_DEFAULT_ENABLED_COLOR
local enabledHLcolor = ZO_HIGHLIGHT_TEXT
local disabledColor = ZO_DEFAULT_DISABLED_COLOR
local disabledHLcolor = ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR
--checkbox
local checkboxColor = ZO_NORMAL_TEXT
local checkboxHLcolor = ZO_HIGHLIGHT_TEXT
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
control.label:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or control.value and ZO_DEFAULT_ENABLED_COLOR or ZO_DEFAULT_DISABLED_COLOR):UnpackRGBA())
control.checkbox:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or ZO_NORMAL_TEXT):UnpackRGBA())
--control:SetMouseEnabled(not disable)
--control:SetMouseEnabled(true)
control.isDisabled = disable
end
local function ToggleCheckbox(control)
if control.value then
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.checkbox:SetText(control.checkedText)
else
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.checkbox:SetText(control.uncheckedText)
end
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = control.data.default
control.data.setFunc(value)
elseif value ~= nil then --our value could be false
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
if control.panel.data.registerForRefresh then
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else
value = control.data.getFunc()
end
control.value = value
ToggleCheckbox(control)
end
local function OnMouseEnter(control)
ZO_Options_OnMouseEnter(control)
if control.isDisabled then return end
local label = control.label
if control.value then
label:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
else
label:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
end
control.checkbox:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
end
local function OnMouseExit(control)
ZO_Options_OnMouseExit(control)
if control.isDisabled then return end
local label = control.label
if control.value then
label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
else
label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
end
control.checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
end
--controlName is optional
function LAMCreateControl.checkbox(parent, checkboxData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, checkboxData, controlName)
control:SetHandler("OnMouseEnter", OnMouseEnter)
control:SetHandler("OnMouseExit", OnMouseExit)
control:SetHandler("OnMouseUp", function(control)
if control.isDisabled then return end
PlaySound(SOUNDS.DEFAULT_CLICK)
control.value = not control.value
control:UpdateValue(false, control.value)
end)
control.checkbox = wm:CreateControl(nil, control.container, CT_LABEL)
local checkbox = control.checkbox
checkbox:SetAnchor(LEFT, control.container, LEFT, 0, 0)
checkbox:SetFont("ZoFontGameBold")
checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper()
control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper()
if checkboxData.warning then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, checkbox, LEFT, -5, 0)
control.warning.data = {tooltipText = checkboxData.warning}
end
control.data.tooltipText = LAM.util.GetTooltipText(checkboxData.tooltip)
if checkboxData.disabled then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
control.UpdateValue = UpdateValue
control:UpdateValue()
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,110 @@
--[[colorpickerData = {
type = "colorpicker",
name = "My Color Picker",
tooltip = "Color Picker's tooltip text.",
getFunc = function() return db.r, db.g, db.b, db.a end, --(alpha is optional)
setFunc = function(r,g,b,a) db.r=r, db.g=g, db.b=b, db.a=a end, --(alpha is optional)
width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional)
default = {r = defaults.r, g = defaults.g, b = defaults.b, a = defaults.a}, --(optional) table of default color values (or default = defaultColor, where defaultColor is a table with keys of r, g, b[, a])
reference = "MyAddonColorpicker" --(optional) unique global reference to control
} ]]
local widgetVersion = 7
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
control.isDisabled = disable
end
local function UpdateValue(control, forceDefault, valueR, valueG, valueB, valueA)
if forceDefault then --if we are forcing defaults
local color = control.data.default
valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a
control.data.setFunc(valueR, valueG, valueB, valueA)
elseif valueR and valueG and valueB then
control.data.setFunc(valueR, valueG, valueB, valueA or 1)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
if control.panel.data.registerForRefresh then
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else
valueR, valueG, valueB, valueA = control.data.getFunc()
end
control.thumb:SetColor(valueR, valueG, valueB, valueA or 1)
end
function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, colorpickerData, controlName)
control.color = control.container
local color = control.color
control.thumb = wm:CreateControl(nil, color, CT_TEXTURE)
local thumb = control.thumb
thumb:SetDimensions(36, 18)
thumb:SetAnchor(LEFT, color, LEFT, 4, 0)
color.border = wm:CreateControl(nil, color, CT_TEXTURE)
local border = color.border
border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds")
border:SetTextureCoords(0, .625, 0, .8125)
border:SetDimensions(40, 22)
border:SetAnchor(CENTER, thumb, CENTER, 0, 0)
local function ColorPickerCallback(r, g, b, a)
control:UpdateValue(false, r, g, b, a)
end
control:SetHandler("OnMouseUp", function(self, btn, upInside)
if self.isDisabled then return end
if upInside then
local r, g, b, a = colorpickerData.getFunc()
COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, colorpickerData.name)
end
end)
if colorpickerData.warning then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0)
control.warning.data = {tooltipText = colorpickerData.warning}
end
control.data.tooltipText = LAM.util.GetTooltipText(colorpickerData.tooltip)
if colorpickerData.disabled then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
control.UpdateValue = UpdateValue
control:UpdateValue()
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,40 @@
--[[customData = {
type = "custom",
reference = "MyAddonCustomControl", --(optional) unique name for your control to use as reference
refreshFunc = function(customControl) end, --(optional) function to call when panel/controls refresh
width = "full", --or "half" (optional)
} ]]
local widgetVersion = 6
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("custom", widgetVersion) then return end
local wm = WINDOW_MANAGER
local tinsert = table.insert
local function UpdateValue(control)
if control.data.refreshFunc then
control.data.refreshFunc(control)
end
end
local MIN_HEIGHT = 26
function LAMCreateControl.custom(parent, customData, controlName)
local control = LAM.util.CreateBaseControl(parent, customData, controlName)
local width = control:GetWidth()
control:SetResizeToFitDescendents(true)
if control.isHalfWidth then --note these restrictions
control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4)
else
control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4)
end
control.UpdateValue = UpdateValue
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,64 @@
--[[descriptionData = {
type = "description",
title = "My Title", --(optional)
text = "My description text to display.",
width = "full", --or "half" (optional)
reference = "MyAddonDescription" --(optional) unique global reference to control
} ]]
local widgetVersion = 6
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("description", widgetVersion) then return end
local wm = WINDOW_MANAGER
local tinsert = table.insert
local function UpdateValue(control)
if control.title then
control.title:SetText(control.data.title)
end
control.desc:SetText(control.data.text)
end
local MIN_HEIGHT = 26
function LAMCreateControl.description(parent, descriptionData, controlName)
local control = LAM.util.CreateBaseControl(parent, descriptionData, controlName)
local isHalfWidth = control.isHalfWidth
local width = control:GetWidth()
control:SetResizeToFitDescendents(true)
if isHalfWidth then
control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4)
else
control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4)
end
control.desc = wm:CreateControl(nil, control, CT_LABEL)
local desc = control.desc
desc:SetVerticalAlignment(TEXT_ALIGN_TOP)
desc:SetFont("ZoFontGame")
desc:SetText(descriptionData.text)
desc:SetWidth(isHalfWidth and width / 2 or width)
if descriptionData.title then
control.title = wm:CreateControl(nil, control, CT_LABEL)
local title = control.title
title:SetWidth(isHalfWidth and width / 2 or width)
title:SetAnchor(TOPLEFT, control, TOPLEFT)
title:SetFont("ZoFontWinH4")
title:SetText(descriptionData.title)
desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT)
else
desc:SetAnchor(TOPLEFT)
end
control.UpdateValue = UpdateValue
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,131 @@
--[[dropdownData = {
type = "dropdown",
name = "My Dropdown",
tooltip = "Dropdown's tooltip text.",
choices = {"table", "of", "choices"},
sort = "name-up", --or "name-down", "numeric-up", "numeric-down" (optional) - if not provided, list will not be sorted
getFunc = function() return db.var end,
setFunc = function(var) db.var = var doStuff() end,
width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional)
default = defaults.var, --(optional)
reference = "MyAddonDropdown" --(optional) unique global reference to control
} ]]
local widgetVersion = 9
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("dropdown", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
control.dropdown:SetEnabled(not disable)
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = control.data.default
control.data.setFunc(value)
control.dropdown:SetSelectedItem(value)
elseif value then
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
if control.panel.data.registerForRefresh then
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else
value = control.data.getFunc()
control.dropdown:SetSelectedItem(value)
end
end
local function DropdownCallback(control, choiceText, choice)
choice.control:UpdateValue(false, choiceText)
end
local function UpdateChoices(control, choices)
control.dropdown:ClearItems() --remove previous choices --(need to call :SetSelectedItem()?)
--build new list of choices
local choices = choices or control.data.choices
for i = 1, #choices do
local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback)
entry.control = control
control.dropdown:AddItem(entry, not control.data.sort and ZO_COMBOBOX_SUPRESS_UPDATE) --if sort type/order isn't specified, then don't sort
end
end
local function GrabSortingInfo(sortInfo)
local t, i = {}, 1
for info in string.gmatch(sortInfo, "([^%-]+)") do
t[i] = info
i = i + 1
end
return t
end
function LAMCreateControl.dropdown(parent, dropdownData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, dropdownData, controlName)
local countControl = parent
local name = parent:GetName()
if not name or #name == 0 then
countControl = LAMCreateControl
name = "LAM"
end
local comboboxCount = (countControl.comboboxCount or 0) + 1
countControl.comboboxCount = comboboxCount
control.combobox = wm:CreateControlFromVirtual(zo_strjoin(nil, name, "Combobox", comboboxCount), control.container, "ZO_ComboBox")
local combobox = control.combobox
combobox:SetAnchor(TOPLEFT)
combobox:SetDimensions(control.container:GetDimensions())
combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox)
local dropdown = control.dropdown
if dropdownData.sort then
local sortInfo = GrabSortingInfo(dropdownData.sort)
local sortType, sortOrder = sortInfo[1], sortInfo[2]
dropdown:SetSortOrder(sortOrder == "up" and ZO_SORT_ORDER_UP or ZO_SORT_ORDER_DOWN, sortType == "name" and ZO_SORT_BY_NAME or ZO_SORT_BY_NAME_NUMERIC)
end
if dropdownData.warning then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0)
control.warning.data = {tooltipText = dropdownData.warning}
end
if dropdownData.disabled then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
control.UpdateChoices = UpdateChoices
control:UpdateChoices(dropdownData.choices)
control.UpdateValue = UpdateValue
control:UpdateValue()
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,136 @@
--[[editboxData = {
type = "editbox",
name = "My Editbox",
tooltip = "Editbox's tooltip text.",
getFunc = function() return db.text end,
setFunc = function(text) db.text = text doStuff() end,
isMultiline = true, --boolean
width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional)
default = defaults.text, --(optional)
reference = "MyAddonEditbox" --(optional) unique global reference to control
} ]]
local widgetVersion = 8
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("editbox", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.editbox:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.editbox:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
--control.editbox:SetEditEnabled(not disable)
control.editbox:SetMouseEnabled(not disable)
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = control.data.default
control.data.setFunc(value)
control.editbox:SetText(value)
elseif value then
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
if control.panel.data.registerForRefresh then
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else
value = control.data.getFunc()
control.editbox:SetText(value)
end
end
local MIN_HEIGHT = 26
local HALF_WIDTH_LINE_SPACING = 2
function LAMCreateControl.editbox(parent, editboxData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, editboxData, controlName)
local container = control.container
control.bg = wm:CreateControlFromVirtual(nil, container, "ZO_EditBackdrop")
local bg = control.bg
bg:SetAnchorFill()
if editboxData.isMultiline then
control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditMultiLineForBackdrop")
control.editbox:SetHandler("OnMouseWheel", function(self, delta)
if self:HasFocus() then --only set focus to new spots if the editbox is currently in use
local cursorPos = self:GetCursorPosition()
local text = self:GetText()
local textLen = text:len()
local newPos
if delta > 0 then --scrolling up
local reverseText = text:reverse()
local revCursorPos = textLen - cursorPos
local revPos = reverseText:find("\n", revCursorPos+1)
newPos = revPos and textLen - revPos
else --scrolling down
newPos = text:find("\n", cursorPos+1)
end
if newPos then --if we found a new line, then scroll, otherwise don't
self:SetCursorPosition(newPos)
end
end
end)
else
control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditForBackdrop")
end
local editbox = control.editbox
editbox:SetText(editboxData.getFunc())
editbox:SetMaxInputChars(3000)
editbox:SetHandler("OnFocusLost", function(self) control:UpdateValue(false, self:GetText()) end)
editbox:SetHandler("OnEscape", function(self) self:LoseFocus() control:UpdateValue(false, self:GetText()) end)
editbox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
editbox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
if not editboxData.isMultiline then
container:SetHeight(24)
else
local width = container:GetWidth()
local height = control.isHalfWidth and 74 or 100
container:SetHeight(height)
editbox:SetDimensionConstraints(width, height, width, 500)
if control.lineControl then
control.lineControl:SetHeight(MIN_HEIGHT + height + HALF_WIDTH_LINE_SPACING)
else
control:SetHeight(height)
end
end
if editboxData.warning then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0)
control.warning.data = {tooltipText = editboxData.warning}
end
if editboxData.disabled then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
control.UpdateValue = UpdateValue
control:UpdateValue()
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,45 @@
--[[headerData = {
type = "header",
name = "My Header",
width = "full", --or "half" (optional)
reference = "MyAddonHeader" --(optional) unique global reference to control
} ]]
local widgetVersion = 6
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("header", widgetVersion) then return end
local wm = WINDOW_MANAGER
local tinsert = table.insert
local function UpdateValue(control)
control.header:SetText(control.data.name)
end
local MIN_HEIGHT = 30
function LAMCreateControl.header(parent, headerData, controlName)
local control = LAM.util.CreateBaseControl(parent, headerData, controlName)
local isHalfWidth = control.isHalfWidth
local width = control:GetWidth()
control:SetDimensions(isHalfWidth and width / 2 or width, MIN_HEIGHT)
control.divider = wm:CreateControlFromVirtual(nil, control, "ZO_Options_Divider")
local divider = control.divider
divider:SetWidth(isHalfWidth and width / 2 or width)
divider:SetAnchor(TOPLEFT)
control.header = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
local header = control.header
header:SetAnchor(TOPLEFT, divider, BOTTOMLEFT)
header:SetAnchor(BOTTOMRIGHT)
header:SetText(headerData.name)
control.UpdateValue = UpdateValue
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,441 @@
--[[iconpickerData = {
type = "iconpicker",
name = "My Icon Picker",
tooltip = "Color Picker's tooltip text.",
choices = {"texture path 1", "texture path 2", "texture path 3"},
choicesTooltips = {"icon tooltip 1", "icon tooltip 2", "icon tooltip 3"}, --(optional)
getFunc = function() return db.var end,
setFunc = function(var) db.var = var doStuff() end,
maxColumns = 5, --(optional) number of icons in one row
visibleRows = 4.5, --(optional) number of visible rows
iconSize = 28, --(optional) size of the icons
defaultColor = ZO_ColorDef:New("FFFFFF"), --(optional) default color of the icons
width = "full", --or "half" (optional)
beforeShow = function(control, iconPicker) return preventShow end, --(optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional)
default = defaults.var, --(optional)
reference = "MyAddonIconPicker" --(optional) unique global reference to control
} ]]
local widgetVersion = 2
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("iconpicker", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local tinsert = table.insert
local IconPickerMenu = ZO_Object:Subclass()
local iconPicker
LAM.util.GetIconPickerMenu = function()
if not iconPicker then
iconPicker = IconPickerMenu:New("LAMIconPicker")
local sceneFragment = LAM:GetAddonSettingsFragment()
ZO_PreHook(sceneFragment, "OnHidden", function()
if not iconPicker.control:IsHidden() then
iconPicker:Clear()
end
end)
end
return iconPicker
end
function IconPickerMenu:New(...)
local object = ZO_Object.New(self)
object:Initialize(...)
return object
end
function IconPickerMenu:Initialize(name)
local control = wm:CreateTopLevelWindow(name)
control:SetDrawTier(DT_HIGH)
control:SetHidden(true)
self.control = control
local scrollContainer = wm:CreateControlFromVirtual(name .. "ScrollContainer", control, "ZO_ScrollContainer")
-- control:SetDimensions(control.container:GetWidth(), height) -- adjust to icon size / col count
scrollContainer:SetAnchorFill()
ZO_Scroll_SetUseFadeGradient(scrollContainer, false)
ZO_Scroll_SetHideScrollbarOnDisable(scrollContainer, false)
ZO_VerticalScrollbarBase_OnMouseExit(scrollContainer:GetNamedChild("ScrollBar")) -- scrollbar initialization seems to be broken so we force it to update the correct alpha value
local scroll = GetControl(scrollContainer, "ScrollChild")
self.scroll = scroll
self.scrollContainer = scrollContainer
local bg = wm:CreateControl(nil, scrollContainer, CT_BACKDROP)
bg:SetAnchor(TOPLEFT, scrollContainer, TOPLEFT, 0, -3)
bg:SetAnchor(BOTTOMRIGHT, scrollContainer, BOTTOMRIGHT, 2, 5)
bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16)
bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds")
bg:SetInsets(16, 16, -16, -16)
local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE)
mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds")
mungeOverlay:SetDrawLevel(1)
mungeOverlay:SetAddressMode(TEX_MODE_WRAP)
mungeOverlay:SetAnchorFill()
local mouseOver = wm:CreateControl(nil, scrollContainer, CT_TEXTURE)
mouseOver:SetDrawLevel(2)
mouseOver:SetTexture("EsoUI/Art/Buttons/minmax_mouseover.dds")
mouseOver:SetHidden(true)
local function IconFactory(pool)
local icon = wm:CreateControl(name .. "Entry" .. pool:GetNextControlId(), scroll, CT_TEXTURE)
icon:SetMouseEnabled(true)
icon:SetDrawLevel(3)
icon:SetHandler("OnMouseEnter", function()
mouseOver:SetAnchor(TOPLEFT, icon, TOPLEFT, 0, 0)
mouseOver:SetAnchor(BOTTOMRIGHT, icon, BOTTOMRIGHT, 0, 0)
mouseOver:SetHidden(false)
if self.customOnMouseEnter then
self.customOnMouseEnter(icon)
else
self:OnMouseEnter(icon)
end
end)
icon:SetHandler("OnMouseExit", function()
mouseOver:ClearAnchors()
mouseOver:SetHidden(true)
if self.customOnMouseExit then
self.customOnMouseExit(icon)
else
self:OnMouseExit(icon)
end
end)
icon:SetHandler("OnMouseUp", function(control, ...)
PlaySound("Click")
icon.OnSelect(icon, icon.texture)
self:Clear()
end)
return icon
end
local function ResetFunction(icon)
icon:ClearAnchors()
end
self.iconPool = ZO_ObjectPool:New(IconFactory, ResetFunction)
self:SetMaxColumns(1)
self.icons = {}
self.color = ZO_DEFAULT_ENABLED_COLOR
EVENT_MANAGER:RegisterForEvent(name .. "_OnGlobalMouseUp", EVENT_GLOBAL_MOUSE_UP, function()
if self.refCount ~= nil then
local moc = wm:GetMouseOverControl()
if(moc:GetOwningWindow() ~= control) then
self.refCount = self.refCount - 1
if self.refCount <= 0 then
self:Clear()
end
end
end
end)
end
function IconPickerMenu:OnMouseEnter(icon)
InitializeTooltip(InformationTooltip, icon, TOPLEFT, 0, 0, BOTTOMRIGHT)
SetTooltipText(InformationTooltip, LAM.util.GetTooltipText(icon.tooltip))
InformationTooltipTopLevel:BringWindowToTop()
end
function IconPickerMenu:OnMouseExit(icon)
ClearTooltip(InformationTooltip)
end
function IconPickerMenu:SetMaxColumns(value)
self.maxCols = value ~= nil and value or 5
end
local DEFAULT_SIZE = 28
function IconPickerMenu:SetIconSize(value)
local iconSize = DEFAULT_SIZE
if value ~= nil then iconSize = math.max(iconSize, value) end
self.iconSize = iconSize
end
function IconPickerMenu:SetVisibleRows(value)
self.visibleRows = value ~= nil and value or 4.5
end
function IconPickerMenu:SetMouseHandlers(onEnter, onExit)
self.customOnMouseEnter = onEnter
self.customOnMouseExit = onExit
end
function IconPickerMenu:UpdateDimensions()
local iconSize = self.iconSize
local width = iconSize * self.maxCols + 20
local height = iconSize * self.visibleRows
self.control:SetDimensions(width, height)
local icons = self.icons
for i = 1, #icons do
local icon = icons[i]
icon:SetDimensions(iconSize, iconSize)
end
end
function IconPickerMenu:UpdateAnchors()
local iconSize = self.iconSize
local col, maxCols = 1, self.maxCols
local previousCol, previousRow
local scroll = self.scroll
local icons = self.icons
for i = 1, #icons do
local icon = icons[i]
icon:ClearAnchors()
if i == 1 then
icon:SetAnchor(TOPLEFT, scroll, TOPLEFT, 0, 0)
previousRow = icon
elseif col == 1 then
icon:SetAnchor(TOPLEFT, previousRow, BOTTOMLEFT, 0, 0)
previousRow = icon
else
icon:SetAnchor(TOPLEFT, previousCol, TOPRIGHT, 0, 0)
end
previousCol = icon
col = col >= maxCols and 1 or col + 1
end
end
function IconPickerMenu:Clear()
self.icons = {}
self.iconPool:ReleaseAllObjects()
self.control:SetHidden(true)
self.color = ZO_DEFAULT_ENABLED_COLOR
self.refCount = nil
self.parent = nil
self.customOnMouseEnter = nil
self.customOnMouseExit = nil
end
function IconPickerMenu:AddIcon(texturePath, callback, tooltip)
local icon, key = self.iconPool:AcquireObject()
icon:SetTexture(texturePath)
icon:SetColor(self.color:UnpackRGBA())
icon.texture = texturePath
icon.tooltip = tooltip
icon.OnSelect = callback
self.icons[#self.icons + 1] = icon
end
function IconPickerMenu:Show(parent)
if #self.icons == 0 then return false end
if not self.control:IsHidden() then self:Clear() return false end
self:UpdateDimensions()
self:UpdateAnchors()
local control = self.control
control:ClearAnchors()
control:SetAnchor(TOPLEFT, parent, BOTTOMLEFT, 0, 8)
control:SetHidden(false)
control:BringWindowToTop()
self.parent = parent
self.refCount = 2
return true
end
function IconPickerMenu:SetColor(color)
local icons = self.icons
self.color = color
for i = 1, #icons do
local icon = icons[i]
icon:SetColor(color:UnpackRGBA())
end
end
-------------------------------------------------------------
local function UpdateChoices(control, choices, choicesTooltips)
local data = control.data
if not choices then
choices, choicesTooltips = data.choices, data.choicesTooltips
end
local addedChoices = {}
local iconPicker = LAM.util.GetIconPickerMenu()
iconPicker:Clear()
for i = 1, #choices do
local texture = choices[i]
if not addedChoices[texture] then -- remove duplicates
iconPicker:AddIcon(choices[i], function(self, texture)
control.icon:SetTexture(texture)
data.setFunc(texture)
if control.panel.data.registerForRefresh then
cm:FireCallbacks("LAM-RefreshPanel", control)
end
end, choicesTooltips[i])
addedChoices[texture] = true
end
end
end
local function IsDisabled(control)
if type(control.data.disabled) == "function" then
return control.data.disabled()
else
return control.data.disabled
end
end
local function SetColor(control, color)
local icon = control.icon
if IsDisabled(control) then
icon:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
icon.color = color or control.data.defaultColor or ZO_DEFAULT_ENABLED_COLOR
icon:SetColor(icon.color:UnpackRGBA())
end
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then
iconPicker:SetColor(icon.color)
end
end
local function UpdateDisabled(control)
local disable = IsDisabled(control)
control.dropdown:SetMouseEnabled(not disable)
control.dropdownButton:SetEnabled(not disable)
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then
iconPicker:Clear()
end
SetColor(control)
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = control.data.default
control.data.setFunc(value)
control.icon:SetTexture(value)
elseif value then
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
if control.panel.data.registerForRefresh then
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else
value = control.data.getFunc()
control.icon:SetTexture(value)
end
end
local MIN_HEIGHT = 26
local HALF_WIDTH_LINE_SPACING = 2
local function SetIconSize(control, size)
local icon = control.icon
icon.size = size
icon:SetDimensions(size, size)
local height = size + 4
control.dropdown:SetDimensions(size + 20, height)
height = math.max(height, MIN_HEIGHT)
control.container:SetHeight(height)
if control.lineControl then
control.lineControl:SetHeight(MIN_HEIGHT + size + HALF_WIDTH_LINE_SPACING)
else
control:SetHeight(height)
end
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then
iconPicker:SetIconSize(size)
iconPicker:UpdateDimensions()
iconPicker:UpdateAnchors()
end
end
function LAMCreateControl.iconpicker(parent, iconpickerData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, iconpickerData, controlName)
local function ShowIconPicker()
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container then
iconPicker:Clear()
else
iconPicker:SetMaxColumns(iconpickerData.maxColumns)
iconPicker:SetVisibleRows(iconpickerData.visibleRows)
iconPicker:SetIconSize(control.icon.size)
UpdateChoices(control)
iconPicker:SetColor(control.icon.color)
if iconpickerData.beforeShow then
if iconpickerData.beforeShow(control, iconPicker) then
iconPicker:Clear()
return
end
end
iconPicker:Show(control.container)
end
end
local iconSize = iconpickerData.iconSize ~= nil and iconpickerData.iconSize or DEFAULT_SIZE
control.dropdown = wm:CreateControl(nil, control.container, CT_CONTROL)
local dropdown = control.dropdown
dropdown:SetAnchor(LEFT, control.container, LEFT, 0, 0)
dropdown:SetMouseEnabled(true)
dropdown:SetHandler("OnMouseUp", ShowIconPicker)
dropdown:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
dropdown:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
control.icon = wm:CreateControl(nil, dropdown, CT_TEXTURE)
local icon = control.icon
icon:SetAnchor(LEFT, dropdown, LEFT, 3, 0)
icon:SetDrawLevel(2)
local dropdownButton = wm:CreateControlFromVirtual(nil, dropdown, "ZO_DropdownButton")
dropdownButton:SetDimensions(16, 16)
dropdownButton:SetHandler("OnClicked", ShowIconPicker)
dropdownButton:SetAnchor(RIGHT, dropdown, RIGHT, -3, 0)
control.dropdownButton = dropdownButton
control.bg = wm:CreateControl(nil, dropdown, CT_BACKDROP)
local bg = control.bg
bg:SetAnchor(TOPLEFT, dropdown, TOPLEFT, 0, -3)
bg:SetAnchor(BOTTOMRIGHT, dropdown, BOTTOMRIGHT, 2, 5)
bg:SetEdgeTexture("EsoUI/Art/Tooltips/UI-Border.dds", 128, 16)
bg:SetCenterTexture("EsoUI/Art/Tooltips/UI-TooltipCenter.dds")
bg:SetInsets(16, 16, -16, -16)
local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE)
mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds")
mungeOverlay:SetDrawLevel(1)
mungeOverlay:SetAddressMode(TEX_MODE_WRAP)
mungeOverlay:SetAnchorFill()
if iconpickerData.warning then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, control.container, LEFT, -5, 0)
control.warning.data = {tooltipText = iconpickerData.warning}
end
if iconpickerData.disabled then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
control.UpdateChoices = UpdateChoices
control.UpdateValue = UpdateValue
control:UpdateValue()
control.SetColor = SetColor
control:SetColor()
control.SetIconSize = SetIconSize
control:SetIconSize(iconSize)
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,132 @@
--[[panelData = {
type = "panel",
name = "Window Title",
displayName = "My Longer Window Title", --(optional) (can be useful for long addon names or if you want to colorize it)
author = "Seerah", --(optional)
version = "2.0", --(optional)
keywords = "settings", --(optional) additional keywords for search filter (it looks for matches in name..keywords..author)
slashCommand = "/myaddon", --(optional) will register a keybind to open to this panel (don't forget to include the slash!)
registerForRefresh = true, --boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown)
registerForDefaults = true, --boolean (optional) (will set all options controls back to default values)
resetFunc = function() print("defaults reset") end, --(optional) custom function to run after settings are reset to defaults
} ]]
local widgetVersion = 9
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("panel", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local function RefreshPanel(control)
local panel = control.panel or control --callback can be fired by a single control or by the panel showing
local panelControls = panel.controlsToRefresh
for i = 1, #panelControls do
local updateControl = panelControls[i]
if updateControl ~= control then
if updateControl.UpdateValue then
updateControl:UpdateValue()
end
if updateControl.UpdateDisabled then
updateControl:UpdateDisabled()
end
end
end
end
local function ForceDefaults(panel)
local panelControls = panel.controlsToRefresh
for i = 1, #panelControls do
local updateControl = panelControls[i]
if updateControl.UpdateValue and updateControl.data.default ~= nil then
updateControl:UpdateValue(true)
end
end
if panel.data.resetFunc then
panel.data.resetFunc()
end
cm:FireCallbacks("LAM-RefreshPanel", panel)
end
ESO_Dialogs["LAM_DEFAULTS"] = {
title = {
text = SI_INTERFACE_OPTIONS_RESET_TO_DEFAULT_TOOLTIP,
},
mainText = {
text = SI_OPTIONS_RESET_PROMPT,
align = TEXT_ALIGN_CENTER,
},
buttons = {
[1] = {
text = SI_OPTIONS_RESET,
callback = function(dialog) ForceDefaults(dialog.data[1]) end,
},
[2] = {
text = SI_DIALOG_CANCEL,
},
},
}
local callbackRegistered = false
LAMCreateControl.scrollCount = LAMCreateControl.scrollCount or 1
function LAMCreateControl.panel(parent, panelData, controlName)
local control = wm:CreateControl(controlName, parent, CT_CONTROL)
control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
local label = control.label
label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 4)
label:SetText(panelData.displayName or panelData.name)
if panelData.author or panelData.version then
control.info = wm:CreateControl(nil, control, CT_LABEL)
local info = control.info
info:SetFont("$(CHAT_FONT)|14|soft-shadow-thin")
info:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, -2)
if panelData.author and panelData.version then
info:SetText(string.format("Version: %s - %s: %s", panelData.version, GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author))
elseif panelData.author then
info:SetText(string.format("%s: %s", GetString(SI_ADDON_MANAGER_AUTHOR), panelData.author))
else
info:SetText("Version: "..panelData.version)
end
end
control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..LAMCreateControl.scrollCount, control, "ZO_ScrollContainer")
LAMCreateControl.scrollCount = LAMCreateControl.scrollCount + 1
local container = control.container
container:SetAnchor(TOPLEFT, control.info or label, BOTTOMLEFT, 0, 20)
container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, -3, -3)
control.scroll = GetControl(control.container, "ScrollChild")
control.scroll:SetResizeToFitPadding(0, 20)
if panelData.registerForDefaults then
control.defaultButton = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultTextButton")
local defaultButton = control.defaultButton
defaultButton:SetFont("ZoFontDialogKeybindDescription")
defaultButton:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
--defaultButton:SetText("Reset To Defaults")
defaultButton:SetText(GetString(SI_OPTIONS_DEFAULTS))
defaultButton:SetDimensions(200, 30)
defaultButton:SetAnchor(TOPLEFT, control, BOTTOMLEFT, 0, 2)
defaultButton:SetHandler("OnClicked", function()
ZO_Dialogs_ShowDialog("LAM_DEFAULTS", {control})
end)
end
if panelData.registerForRefresh and not callbackRegistered then --don't want to register our callback more than once
cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel)
callbackRegistered = true
end
control.data = panelData
control.controlsToRefresh = {}
return control
end
-- vi: noexpandtab

View File

@ -0,0 +1,157 @@
--[[sliderData = {
type = "slider",
name = "My Slider",
tooltip = "Slider's tooltip text.",
min = 0,
max = 20,
step = 1, --(optional)
getFunc = function() return db.var end,
setFunc = function(value) db.var = value doStuff() end,
width = "full", --or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "Will need to reload the UI.", --(optional)
default = defaults.var, --(optional)
reference = "MyAddonSlider" --(optional) unique global reference to control
} ]]
local widgetVersion = 7
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("slider", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local round = zo_round
local strformat = string.format
local tinsert = table.insert
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
control.slider:SetEnabled(not disable)
control.slidervalue:SetEditEnabled(not disable)
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.minText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.maxText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.slidervalue:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.minText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.maxText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.slidervalue:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = control.data.default
control.data.setFunc(value)
elseif value and value >= control.data.min and value <= control.data.max then
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
if control.panel.data.registerForRefresh then
cm:FireCallbacks("LAM-RefreshPanel", control)
end
else
value = control.data.getFunc()
end
control.slider:SetValue(value)
control.slidervalue:SetText(value)
end
function LAMCreateControl.slider(parent, sliderData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, sliderData, controlName)
--skipping creating the backdrop... Is this the actual slider texture?
control.slider = wm:CreateControl(nil, control.container, CT_SLIDER)
local slider = control.slider
slider:SetAnchor(TOPLEFT)
slider:SetAnchor(TOPRIGHT)
slider:SetHeight(14)
slider:SetMouseEnabled(true)
slider:SetOrientation(ORIENTATION_HORIZONTAL)
--put nil for highlighted texture file path, and what look to be texture coords
slider:SetThumbTexture("EsoUI\\Art\\Miscellaneous\\scrollbox_elevator.dds", "EsoUI\\Art\\Miscellaneous\\scrollbox_elevator_disabled.dds", nil, 8, 16)
local minValue = sliderData.min
local maxValue = sliderData.max
slider:SetMinMax(minValue, maxValue)
slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseExit(control) end)
slider.bg = wm:CreateControl(nil, slider, CT_BACKDROP)
local bg = slider.bg
bg:SetCenterColor(0, 0, 0)
bg:SetAnchor(TOPLEFT, slider, TOPLEFT, 0, 4)
bg:SetAnchor(BOTTOMRIGHT, slider, BOTTOMRIGHT, 0, -4)
bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4)
control.minText = wm:CreateControl(nil, slider, CT_LABEL)
local minText = control.minText
minText:SetFont("ZoFontGameSmall")
minText:SetAnchor(TOPLEFT, slider, BOTTOMLEFT)
minText:SetText(sliderData.min)
control.maxText = wm:CreateControl(nil, slider, CT_LABEL)
local maxText = control.maxText
maxText:SetFont("ZoFontGameSmall")
maxText:SetAnchor(TOPRIGHT, slider, BOTTOMRIGHT)
maxText:SetText(sliderData.max)
control.slidervalueBG = wm:CreateControlFromVirtual(nil, slider, "ZO_EditBackdrop")
control.slidervalueBG:SetDimensions(50, 16)
control.slidervalueBG:SetAnchor(TOP, slider, BOTTOM, 0, 0)
control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop")
local slidervalue = control.slidervalue
slidervalue:ClearAnchors()
slidervalue:SetAnchor(TOPLEFT, control.slidervalueBG, TOPLEFT, 3, 1)
slidervalue:SetAnchor(BOTTOMRIGHT, control.slidervalueBG, BOTTOMRIGHT, -3, -1)
slidervalue:SetTextType(TEXT_TYPE_NUMERIC)
slidervalue:SetFont("ZoFontGameSmall")
slidervalue:SetHandler("OnEscape", function(self)
self:LoseFocus()
control:UpdateValue()
end)
slidervalue:SetHandler("OnEnter", function(self)
self:LoseFocus()
control:UpdateValue(false, tonumber(self:GetText()))
end)
local range = maxValue - minValue
slider:SetValueStep(sliderData.step or 1)
slider:SetHandler("OnValueChanged", function(self, value, eventReason)
if eventReason == EVENT_REASON_SOFTWARE then return end
self:SetValue(value) --do we actually need this line?
slidervalue:SetText(value)
end)
slider:SetHandler("OnSliderReleased", function(self, value)
--sliderData.setFunc(value)
control:UpdateValue(false, value) --does this work here instead?
end)
if sliderData.warning then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, slider, LEFT, -5, 0)
control.warning.data = {tooltipText = sliderData.warning}
end
if sliderData.disabled then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
control.UpdateValue = UpdateValue
control:UpdateValue()
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,112 @@
--[[submenuData = {
type = "submenu",
name = "Submenu Title",
tooltip = "My submenu tooltip", --(optional)
controls = {sliderData, buttonData} --(optional) used by LAM
reference = "MyAddonSubmenu" --(optional) unique global reference to control
} ]]
local widgetVersion = 9
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("submenu", widgetVersion) then return end
local wm = WINDOW_MANAGER
local am = ANIMATION_MANAGER
local tinsert = table.insert
local function UpdateValue(control)
control.label:SetText(control.data.name)
if control.data.tooltip then
control.label.data.tooltipText = LAM.util.GetTooltipText(control.data.tooltip)
end
end
local function AnimateSubmenu(clicked)
local control = clicked:GetParent()
control.open = not control.open
if control.open then
control.animation:PlayFromStart()
else
control.animation:PlayFromEnd()
end
end
function LAMCreateControl.submenu(parent, submenuData, controlName)
local width = parent:GetWidth() - 45
local control = wm:CreateControl(controlName or submenuData.reference, parent.scroll or parent, CT_CONTROL)
control.panel = parent
control.data = submenuData
control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
local label = control.label
label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5)
label:SetDimensions(width, 30)
label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
label:SetText(submenuData.name)
label:SetMouseEnabled(true)
if submenuData.tooltip then
label.data = {tooltipText = LAM.util.GetTooltipText(submenuData.tooltip)}
label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
end
control.scroll = wm:CreateControl(nil, control, CT_SCROLL)
local scroll = control.scroll
scroll:SetParent(control)
scroll:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, 10)
scroll:SetDimensionConstraints(width + 5, 0, width + 5, 2500)
control.bg = wm:CreateControl(nil, label, CT_BACKDROP)
local bg = control.bg
bg:SetAnchor(TOPLEFT, label, TOPLEFT, -5, -5)
bg:SetAnchor(BOTTOMRIGHT, scroll, BOTTOMRIGHT, -7, 0)
bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16)
bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds")
bg:SetInsets(16, 16, -16, -16)
control.arrow = wm:CreateControl(nil, bg, CT_TEXTURE)
local arrow = control.arrow
arrow:SetDimensions(28, 28)
arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") --list_sortup for the other way
arrow:SetAnchor(TOPRIGHT, bg, TOPRIGHT, -5, 5)
--figure out the cool animation later...
control.animation = am:CreateTimeline()
local animation = control.animation
animation:SetPlaybackType(ANIMATION_SIZE, 0) --2nd arg = loop count
control:SetResizeToFitDescendents(true)
control.open = false
label:SetHandler("OnMouseUp", AnimateSubmenu)
animation:SetHandler("OnStop", function(self, completedPlaying)
scroll:SetResizeToFitDescendents(control.open)
if control.open then
control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortup.dds")
scroll:SetResizeToFitPadding(5, 20)
else
control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds")
scroll:SetResizeToFitPadding(5, 0)
scroll:SetHeight(0)
end
end)
--small strip at the bottom of the submenu that you can click to close it
control.btmToggle = wm:CreateControl(nil, control, CT_TEXTURE)
local btmToggle = control.btmToggle
btmToggle:SetMouseEnabled(true)
btmToggle:SetAnchor(BOTTOMLEFT, control.scroll, BOTTOMLEFT)
btmToggle:SetAnchor(BOTTOMRIGHT, control.scroll, BOTTOMRIGHT)
btmToggle:SetHeight(15)
btmToggle:SetAlpha(0)
btmToggle:SetHandler("OnMouseUp", AnimateSubmenu)
control.UpdateValue = UpdateValue
if control.panel.data.registerForRefresh or control.panel.data.registerForDefaults then --if our parent window wants to refresh controls, then add this to the list
tinsert(control.panel.controlsToRefresh, control)
end
return control
end

View File

@ -0,0 +1,45 @@
--[[textureData = {
type = "texture",
image = "file/path.dds",
imageWidth = 64, --max of 250 for half width, 510 for full
imageHeight = 32, --max of 100
tooltip = "Image's tooltip text.", --(optional)
width = "full", --or "half" (optional)
reference = "MyAddonTexture" --(optional) unique global reference to control
} ]]
--add texture coords support?
local widgetVersion = 7
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("texture", widgetVersion) then return end
local wm = WINDOW_MANAGER
local MIN_HEIGHT = 26
function LAMCreateControl.texture(parent, textureData, controlName)
local control = LAM.util.CreateBaseControl(parent, textureData, controlName)
local width = control:GetWidth()
control:SetResizeToFitDescendents(true)
if control.isHalfWidth then --note these restrictions
control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4)
else
control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4)
end
control.texture = wm:CreateControl(nil, control, CT_TEXTURE)
local texture = control.texture
texture:SetAnchor(CENTER)
texture:SetDimensions(textureData.imageWidth, textureData.imageHeight)
texture:SetTexture(textureData.image)
if textureData.tooltip then
texture:SetMouseEnabled(true)
texture.data = {tooltipText = LAM.util.GetTooltipText(textureData.tooltip)}
texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseExit)
end
return control
end

36
Libs/LibStub/LibStub.lua Normal file
View File

@ -0,0 +1,36 @@
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
-- LibStub developed for World of Warcraft by above members of the WowAce community.
-- Ported to Elder Scrolls Online by Seerah
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 3
local LibStub = _G[LIBSTUB_MAJOR]
local strformat = string.format
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
if type(minor) ~= "number" then
minor = assert(tonumber(zo_strmatch(minor, "%d+%.?%d*")), "Minor version must either be a number or contain a number.")
end
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(strformat("Cannot find a library instance of %q.", tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end

119
Libs/exampleoptions.lua Normal file
View File

@ -0,0 +1,119 @@
local panelData = {
type = "panel",
name = "Window Title",
displayName = "Longer Window Title",
author = "Seerah",
version = "1.3",
slashCommand = "/myaddon", --(optional) will register a keybind to open to this panel
registerForRefresh = true, --boolean (optional) (will refresh all options controls when a setting is changed and when the panel is shown)
registerForDefaults = true, --boolean (optional) (will set all options controls back to default values)
}
local optionsTable = {
[1] = {
type = "header",
name = "My Header",
width = "full", --or "half" (optional)
},
[2] = {
type = "description",
--title = "My Title", --(optional)
title = nil, --(optional)
text = "My description text to display. blah blah blah blah blah blah blah - even more sample text!!",
width = "full", --or "half" (optional)
},
[3] = {
type = "dropdown",
name = "My Dropdown",
tooltip = "Dropdown's tooltip text.",
choices = {"table", "of", "choices"},
getFunc = function() return "of" end,
setFunc = function(var) print(var) end,
width = "half", --or "half" (optional)
warning = "Will need to reload the UI.", --(optional)
},
[4] = {
type = "dropdown",
name = "My Dropdown",
tooltip = "Dropdown's tooltip text.",
choices = {"table", "of", "choices"},
getFunc = function() return "of" end,
setFunc = function(var) print(var) end,
width = "half", --or "half" (optional)
warning = "Will need to reload the UI.", --(optional)
},
[5] = {
type = "slider",
name = "My Slider",
tooltip = "Slider's tooltip text.",
min = 0,
max = 20,
step = 1, --(optional)
getFunc = function() return 3 end,
setFunc = function(value) d(value) end,
width = "half", --or "half" (optional)
default = 5, --(optional)
},
[6] = {
type = "button",
name = "My Button",
tooltip = "Button's tooltip text.",
func = function() d("button pressed!") end,
width = "half", --or "half" (optional)
warning = "Will need to reload the UI.", --(optional)
},
[7] = {
type = "submenu",
name = "Submenu Title",
tooltip = "My submenu tooltip", --(optional)
controls = {
[1] = {
type = "checkbox",
name = "My Checkbox",
tooltip = "Checkbox's tooltip text.",
getFunc = function() return true end,
setFunc = function(value) d(value) end,
width = "half", --or "half" (optional)
warning = "Will need to reload the UI.", --(optional)
},
[2] = {
type = "colorpicker",
name = "My Color Picker",
tooltip = "Color Picker's tooltip text.",
getFunc = function() return 1, 0, 0, 1 end, --(alpha is optional)
setFunc = function(r,g,b,a) print(r, g, b, a) end, --(alpha is optional)
width = "half", --or "half" (optional)
warning = "warning text",
},
[3] = {
type = "editbox",
name = "My Editbox",
tooltip = "Editbox's tooltip text.",
getFunc = function() return "this is some text" end,
setFunc = function(text) print(text) end,
isMultiline = false, --boolean
width = "half", --or "half" (optional)
warning = "Will need to reload the UI.", --(optional)
default = "", --(optional)
},
},
},
[8] = {
type = "custom",
reference = "MyAddonCustomControl", --unique name for your control to use as reference
refreshFunc = function(customControl) end, --(optional) function to call when panel/controls refresh
width = "half", --or "half" (optional)
},
[9] = {
type = "texture",
image = "EsoUI\\Art\\ActionBar\\abilityframe64_up.dds",
imageWidth = 64, --max of 250 for half width, 510 for full
imageHeight = 64, --max of 100
tooltip = "Image's tooltip text.", --(optional)
width = "half", --or "half" (optional)
},
}
local LAM = LibStub("LibAddonMenu-2.0")
LAM:RegisterAddonPanel("MyAddon", panelData)
LAM:RegisterOptionControls("MyAddon", optionsTable)