diff --git a/Lib/LibAddonMenu-2.0/LICENSE b/Lib/LibAddonMenu-2.0/LICENSE new file mode 100644 index 0000000..755f075 --- /dev/null +++ b/Lib/LibAddonMenu-2.0/LICENSE @@ -0,0 +1,201 @@ + The Artistic License 2.0 + + Copyright (c) 2016 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. diff --git a/Lib/LibAddonMenu-2.0/LibAddonMenu-2.0.lua b/Lib/LibAddonMenu-2.0/LibAddonMenu-2.0.lua new file mode 100644 index 0000000..96acfef --- /dev/null +++ b/Lib/LibAddonMenu-2.0/LibAddonMenu-2.0.lua @@ -0,0 +1,877 @@ +-- 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", 20 +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 GetDefaultValue(default) + if type(default) == "function" then + return default() + end + return default +end + +local function GetStringFromValue(value) + if type(value) == "function" then + return value() + elseif type(value) == "number" then + return GetString(value) + end + return value +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" + local width = 510 -- set default width in case a custom parent object is passed + if control.panel.GetWidth ~= nil then width = control.panel:GetWidth() - 60 end + control:SetWidth(width) + 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(GetStringFromValue(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 = GetStringFromValue(control.data.tooltip) + control:SetMouseEnabled(true) + control:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + control:SetHandler("OnMouseExit", ZO_Options_OnMouseExit) + return control +end + +util.GetTooltipText = GetStringFromValue -- deprecated, use util.GetStringFromValue instead +util.GetStringFromValue = GetStringFromValue +util.GetDefaultValue = GetDefaultValue +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 + +-- INTERNAL METHOD: fires the LAM-PanelOpened callback if not already done +local function OpenCurrentPanel() + if(lam.currentAddonPanel and not lam.currentPanelOpened) then + lam.currentPanelOpened = true + cm:FireCallbacks("LAM-PanelOpened", lam.currentAddonPanel) + end +end + +-- INTERNAL METHOD: fires the LAM-PanelClosed callback if not already done +local function CloseCurrentPanel() + if(lam.currentAddonPanel and lam.currentPanelOpened) then + lam.currentPanelOpened = false + cm:FireCallbacks("LAM-PanelClosed", lam.currentAddonPanel) + 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 + +local TwinOptionsContainer_Index = 0 +local function TwinOptionsContainer(parent, leftWidget, rightWidget) + TwinOptionsContainer_Index = TwinOptionsContainer_Index + 1 + local cParent = parent.scroll or parent + local panel = parent.panel or cParent + local container = wm:CreateControl("$(parent)TwinContainer" .. tostring(TwinOptionsContainer_Index), + cParent, CT_CONTROL) + container:SetResizeToFitDescendents(true) + container:SetAnchor(select(2, leftWidget:GetAnchor(0) )) + + leftWidget:ClearAnchors() + leftWidget:SetAnchor(TOPLEFT, container, TOPLEFT) + rightWidget:SetAnchor(TOPLEFT, leftWidget, TOPRIGHT, 5, 0) + + leftWidget:SetWidth( leftWidget:GetWidth() - 2.5 ) -- fixes bad alignment with 'full' controls + rightWidget:SetWidth( rightWidget:GetWidth() - 2.5 ) + + leftWidget:SetParent(container) + rightWidget:SetParent(container) + + container.data = {type = "container"} + container.panel = panel + return container +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.lineControl = anchorTarget + isHalf = false + offsetY = 0 + anchorTarget = TwinOptionsContainer(parent, anchorTarget, widget) + else -- otherwise we just put it below the previous one normally + widget:SetAnchor(TOPLEFT, anchorTarget, BOTTOMLEFT, 0, 15) + 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) + OpenCurrentPanel() + end + end + + if SetupCreationCalls(panel, optionsTable) then + PrintLater(("The settings menu of %s is missing some entries."):format(addonID)) + end + DoCreateSettings() + else + optionsCreated[addonID] = true + cm:FireCallbacks("LAM-PanelControlsCreated", panel) + OpenCurrentPanel() + 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) + CloseCurrentPanel() + 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) + else + OpenCurrentPanel() + 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() + + -- a little something for 4/1. Please keep it a secret ;-) The code was minified with https://mothereff.in/lua-minifier and the original code can be found at https://gist.github.com/sirinsidiator/6f8863ff66c9919dfe01 + if GetDate()%1000~=401 then ZO_Ingame_SavedVariables["LAM"]=nil;return end;local a,b=pcall(error,"")local c=b:match("user:/AddOns/(.*)LibAddonMenu.-.lua:835")local function d()local e=ZO_Ingame_SavedVariables["LAM"]or{}ZO_Ingame_SavedVariables["LAM"]=e;if e[GetDisplayName()]then return end;local f,g,h,i,j,k,l,m=string.rep,string.format,math.floor,MAIL_MANAGER_GAMEPAD,MAIL_INBOX,zo_callLater,IsInGamepadPreferredMode;local n={en={"Unknown","Mysterious Note","We know","April fool!\nThe addon community wishes you a happy April Fools' Day!",0},de={"Unbekannt","Geheimnisvolle Notiz","Wir wissen Bescheid","April, April!\nEinen guten 1. April wünscht euch eure Addon Gemeinschaft!",7},fr={"Inconnu","Note mystérieuse","Nous savons tout","Poisson d'avril!\nLes développeurs d'addons vous souhaitent un joyeux premier avril!",6}}local o=n[GetCVar("language.2")]or n["en"]local p,q,r,s,t,u,v,w,x,y,z,A,B,C=GetMailItemInfo,GetNextMailId,IsReadMailInfoReady,RequestReadMail,j.GetMailData,ReadMail,DeleteMail,GetNumUnreadMail,i.inbox,GetMailAttachmentInfo,GetAttachedItemLink,ItemTooltip.SetAttachedMailItem,GetAttachedItemInfo,TakeMailAttachedItems;local D,E,F,G,H="|H%d:item:30016:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0|h|h",c.."controls/separator.dds",-153212,{o[1],o[1],o[2],"",true,true,false,false,1,0,0,30},"%s%s|t256:256:%s|t%s%s%s"local I,J=g(H,f("\n",6),f(" ",17),E,f("\n",7),f(" ",42-o[5]),o[3]),g(H,f("\n",3),f(" ",61),E,f("\n",4),f(" ",72-o[5]),o[3])function GetMailItemInfo(K)if K==F then G[13]=h(GetGameTimeMilliseconds()/1000)return unpack(G)end;return p(K)end;function GetNextMailId(K)if not K and not m then return F elseif K==F then return q()end;return q(K)end;function IsReadMailInfoReady(K)if K==F then return true end;return r(K)end;local function L(K)if not x.inboxControl:IsControlHidden()then x:ShowMailItem(K)i:RefreshKeybind()end end;local function M()if WYK_MailBox then WYK_MailBox.ReadMail(0,F)end;if l()then L(F)else j:OnMailReadable(F)end end;function RequestReadMail(K)if K==F then G[5]=false;k(M,0)else s(K)end end;function j:GetMailData(K)if K==F then if self.masterList then for N=1,#self.masterList do local O=self.masterList[N]if O.mailId==K then return O end end end else return t(self,K)end end;function ReadMail(K)if K==F then return l()and J or I end;return u(K)end;function DeleteMail(K,P)if K==F then m=true;j:OnMailRemoved(K)i:RefreshHeader()x:RefreshMailList()e[GetDisplayName()]=true else v(K,P)end end;function GetNumUnreadMail()local Q=w()if G[5]then return Q+1 end;return Q end;function GetMailAttachmentInfo(K)if K==F and G[9]>0 then return 1,0,0 end;return y(K)end;function GetAttachedItemLink(K,R,S)if K==F and G[9]>0 then return g(D,S or 0)end;return z(K,R,S)end;function ItemTooltip:SetAttachedMailItem(K,T)if K==F and G[9]>0 then self:SetLink(GetAttachedItemLink(K,T))else A(self,K,T)end end;function GetAttachedItemInfo(K,R)if K==F and G[9]>0 then local U,V,W,X,Y=GetItemLinkInfo(g(D,1))return U,1,nil,V,W,X,Y,2 end;return B(K,R)end;function TakeMailAttachedItems(K)if K==F then LORE_READER:Show(o[1],o[4],4,false,"loreLibrary")SCENE_MANAGER:Show("loreReaderInteraction")G[9]=0;j:OnTakeAttachedItemSuccess(K)else C(K)end end;CHAT_SYSTEM:OnNumUnreadMailChanged(GetNumUnreadMail())end;pcall(d) +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) + LAMAddonSettingsFragment:RegisterCallback("StateChange", function(oldState, newState) + if(newState == SCENE_FRAGMENT_SHOWN) then + OpenCurrentPanel() + elseif(newState == SCENE_FRAGMENT_HIDDEN) then + CloseCurrentPanel() + end + end) + CreateAddonSettingsMenuEntry() + end + return LAMAddonSettingsFragment +end + + +-- vi: noexpandtab diff --git a/Lib/LibAddonMenu-2.0/controls/button.lua b/Lib/LibAddonMenu-2.0/controls/button.lua new file mode 100644 index 0000000..f588703 --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/button.lua @@ -0,0 +1,89 @@ +--[[buttonData = { + type = "button", + name = "My Button", -- string id or function returning a string + func = function() end, + tooltip = "Button's tooltip text.", -- string id or function returning a string (optional) + 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", -- unique global reference to control (optional) +} ]] + + +local widgetVersion = 9 +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(LAM.util.GetStringFromValue(buttonData.name)) + end + local button = control.button + button:SetAnchor(control.isHalfWidth and CENTER or RIGHT) + button:SetClickSound("Click") + button.data = {tooltipText = LAM.util.GetStringFromValue(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 = LAM.util.GetStringFromValue(buttonData.warning)} + end + + if buttonData.disabled ~= nil 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 diff --git a/Lib/LibAddonMenu-2.0/controls/checkbox.lua b/Lib/LibAddonMenu-2.0/controls/checkbox.lua new file mode 100644 index 0000000..51d9fd7 --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/checkbox.lua @@ -0,0 +1,144 @@ +--[[checkboxData = { + type = "checkbox", + name = "My Checkbox", -- or string id or function returning a string + getFunc = function() return db.var end, + setFunc = function(value) db.var = value doStuff() end, + tooltip = "Checkbox's tooltip text.", -- or string id or function returning a string (optional) + width = "full", -- or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", -- or string id or function returning a string (optional) + default = defaults.var, -- a boolean or function that returns a boolean (optional) + reference = "MyAddonCheckbox", -- unique global reference to control (optional) +} ]] + + +local widgetVersion = 11 +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 = LAM.util.GetDefaultValue(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 = LAM.util.GetStringFromValue(checkboxData.warning)} + end + + control.data.tooltipText = LAM.util.GetStringFromValue(checkboxData.tooltip) + + if checkboxData.disabled ~= nil 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 diff --git a/Lib/LibAddonMenu-2.0/controls/colorpicker.lua b/Lib/LibAddonMenu-2.0/controls/colorpicker.lua new file mode 100644 index 0000000..c25452f --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/colorpicker.lua @@ -0,0 +1,110 @@ +--[[colorpickerData = { + type = "colorpicker", + name = "My Color Picker", -- or string id or function returning a string + 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) + tooltip = "Color Picker's tooltip text.", -- or string id or function returning a string (optional) + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", -- or string id or function returning a string (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]) or a function that returns the color + reference = "MyAddonColorpicker" -- unique global reference to control (optional) +} ]] + + +local widgetVersion = 10 +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 = LAM.util.GetDefaultValue(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, LAM.util.GetStringFromValue(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 = LAM.util.GetStringFromValue(colorpickerData.warning)} + end + + control.data.tooltipText = LAM.util.GetStringFromValue(colorpickerData.tooltip) + + if colorpickerData.disabled ~= nil 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 diff --git a/Lib/LibAddonMenu-2.0/controls/custom.lua b/Lib/LibAddonMenu-2.0/controls/custom.lua new file mode 100644 index 0000000..e7b7312 --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/custom.lua @@ -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 \ No newline at end of file diff --git a/Lib/LibAddonMenu-2.0/controls/description.lua b/Lib/LibAddonMenu-2.0/controls/description.lua new file mode 100644 index 0000000..ba769ba --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/description.lua @@ -0,0 +1,63 @@ +--[[descriptionData = { + type = "description", + text = "My description text to display.", -- or string id or function returning a string + title = "My Title", -- or string id or function returning a string (optional) + width = "full", --or "half" (optional) + reference = "MyAddonDescription" -- unique global reference to control (optional) +} ]] + + +local widgetVersion = 8 +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(LAM.util.GetStringFromValue(control.data.title)) + end + control.desc:SetText(LAM.util.GetStringFromValue(control.data.text)) +end + +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, 0, width / 2, 0) + else + control:SetDimensionConstraints(width, 0, width, 0) + end + + control.desc = wm:CreateControl(nil, control, CT_LABEL) + local desc = control.desc + desc:SetVerticalAlignment(TEXT_ALIGN_TOP) + desc:SetFont("ZoFontGame") + desc:SetText(LAM.util.GetStringFromValue(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(LAM.util.GetStringFromValue(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 \ No newline at end of file diff --git a/Lib/LibAddonMenu-2.0/controls/dropdown.lua b/Lib/LibAddonMenu-2.0/controls/dropdown.lua new file mode 100644 index 0000000..7d9f9b3 --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/dropdown.lua @@ -0,0 +1,131 @@ +--[[dropdownData = { + type = "dropdown", + name = "My Dropdown", -- or string id or function returning a string + choices = {"table", "of", "choices"}, + getFunc = function() return db.var end, + setFunc = function(var) db.var = var doStuff() end, + tooltip = "Dropdown's tooltip text.", -- or string id or function returning a string (optional) + sort = "name-up", --or "name-down", "numeric-up", "numeric-down" (optional) - if not provided, list will not be sorted + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", -- or string id or function returning a string (optional) + default = defaults.var, -- default value or function that returns the default value (optional) + reference = "MyAddonDropdown" -- unique global reference to control (optional) +} ]] + + +local widgetVersion = 12 +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 = LAM.util.GetDefaultValue(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 = LAM.util.GetStringFromValue(dropdownData.warning)} + end + + if dropdownData.disabled ~= nil 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 diff --git a/Lib/LibAddonMenu-2.0/controls/editbox.lua b/Lib/LibAddonMenu-2.0/controls/editbox.lua new file mode 100644 index 0000000..a7e4830 --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/editbox.lua @@ -0,0 +1,160 @@ +--[[editboxData = { + type = "editbox", + name = "My Editbox", -- or string id or function returning a string + getFunc = function() return db.text end, + setFunc = function(text) db.text = text doStuff() end, + tooltip = "Editbox's tooltip text.", -- or string id or function returning a string (optional) + isMultiline = true, --boolean (optional) + isExtraWide = true, --boolean (optional) + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", -- or string id or function returning a string (optional) + default = defaults.text, -- default value or function that returns the default value (optional) + reference = "MyAddonEditbox" -- unique global reference to control (optional) +} ]] + + +local widgetVersion = 11 +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 = LAM.util.GetDefaultValue(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 = 24 +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) + + local MIN_WIDTH = (parent.GetWidth and (parent:GetWidth() / 10)) or (parent.panel.GetWidth and (parent.panel:GetWidth() / 10)) or 0 + + control.label:ClearAnchors() + container:ClearAnchors() + + control.label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0) + container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, 0, 0) + + if control.isHalfWidth then + container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, 0, 0) + end + + if editboxData.isExtraWide then + container:SetAnchor(BOTTOMLEFT, control, BOTTOMLEFT, 0, 0) + else + container:SetWidth(MIN_WIDTH * 3.2) + end + + if editboxData.isMultiline then + container:SetHeight(MIN_HEIGHT * 3) + else + container:SetHeight(MIN_HEIGHT) + end + + if control.isHalfWidth ~= true and editboxData.isExtraWide ~= true then + control:SetHeight(container:GetHeight()) + else + control:SetHeight(container:GetHeight() + control.label:GetHeight()) + end + + editbox:ClearAnchors() + editbox:SetAnchor(TOPLEFT, container, TOPLEFT, 2, 2) + editbox:SetAnchor(BOTTOMRIGHT, container, BOTTOMRIGHT, -2, -2) + + if editboxData.warning then + control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon") + if editboxData.isExtraWide then + control.warning:SetAnchor(BOTTOMRIGHT, control.bg, TOPRIGHT, 2, 0) + else + control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0) + end + control.warning.data = {tooltipText = LAM.util.GetStringFromValue(editboxData.warning)} + end + + if editboxData.disabled ~= nil 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 diff --git a/Lib/LibAddonMenu-2.0/controls/header.lua b/Lib/LibAddonMenu-2.0/controls/header.lua new file mode 100644 index 0000000..a96066e --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/header.lua @@ -0,0 +1,45 @@ +--[[headerData = { + type = "header", + name = "My Header", -- or string id or function returning a string + width = "full", --or "half" (optional) + reference = "MyAddonHeader" -- unique global reference to control (optional) +} ]] + + +local widgetVersion = 7 +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(LAM.util.GetStringFromValue(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(LAM.util.GetStringFromValue(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 \ No newline at end of file diff --git a/Lib/LibAddonMenu-2.0/controls/iconpicker.lua b/Lib/LibAddonMenu-2.0/controls/iconpicker.lua new file mode 100644 index 0000000..c070b3f --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/iconpicker.lua @@ -0,0 +1,441 @@ +--[[iconpickerData = { + type = "iconpicker", + name = "My Icon Picker", -- or string id or function returning a string + choices = {"texture path 1", "texture path 2", "texture path 3"}, + getFunc = function() return db.var end, + setFunc = function(var) db.var = var doStuff() end, + tooltip = "Color Picker's tooltip text.", -- or string id or function returning a string (optional) + choicesTooltips = {"icon tooltip 1", "icon tooltip 2", "icon tooltip 3"}, -- or array of string ids or array of functions returning a string (optional) + maxColumns = 5, -- number of icons in one row (optional) + visibleRows = 4.5, -- number of visible rows (optional) + iconSize = 28, -- size of the icons (optional) + defaultColor = ZO_ColorDef:New("FFFFFF"), -- default color of the icons (optional) + 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.", -- or string id or function returning a string (optional) + default = defaults.var, -- default value or function that returns the default value (optional) + reference = "MyAddonIconPicker" -- unique global reference to control (optional) +} ]] + +local widgetVersion = 5 +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.GetStringFromValue(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 or {} + 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, LAM.util.GetStringFromValue(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 = LAM.util.GetDefaultValue(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 = LAM.util.GetStringFromValue(iconpickerData.warning)} + end + + if iconpickerData.disabled ~= nil 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 diff --git a/Lib/LibAddonMenu-2.0/controls/panel.lua b/Lib/LibAddonMenu-2.0/controls/panel.lua new file mode 100644 index 0000000..00a909e --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/panel.lua @@ -0,0 +1,132 @@ +--[[panelData = { + type = "panel", + name = "Window Title", -- or string id or function returning a string + displayName = "My Longer Window Title", -- or string id or function returning a string (optional) (can be useful for long addon names or if you want to colorize it) + author = "Seerah", -- or string id or function returning a string (optional) + version = "2.0", -- or string id or function returning a string (optional) + keywords = "settings", -- additional keywords for search filter (it looks for matches in name..keywords..author) (optional) + slashCommand = "/myaddon", -- will register a keybind to open to this panel (don't forget to include the slash!) (optional) + 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 = 10 +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(LAM.util.GetStringFromValue(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", LAM.util.GetStringFromValue(panelData.version), GetString(SI_ADDON_MANAGER_AUTHOR), LAM.util.GetStringFromValue(panelData.author))) + elseif panelData.author then + info:SetText(string.format("%s: %s", GetString(SI_ADDON_MANAGER_AUTHOR), LAM.util.GetStringFromValue(panelData.author))) + else + info:SetText("Version: " .. LAM.util.GetStringFromValue(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 diff --git a/Lib/LibAddonMenu-2.0/controls/separator.dds b/Lib/LibAddonMenu-2.0/controls/separator.dds new file mode 100644 index 0000000..02bb2ab Binary files /dev/null and b/Lib/LibAddonMenu-2.0/controls/separator.dds differ diff --git a/Lib/LibAddonMenu-2.0/controls/slider.lua b/Lib/LibAddonMenu-2.0/controls/slider.lua new file mode 100644 index 0000000..e4b16ef --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/slider.lua @@ -0,0 +1,166 @@ +--[[sliderData = { + type = "slider", + name = "My Slider", -- or string id or function returning a string + getFunc = function() return db.var end, + setFunc = function(value) db.var = value doStuff() end, + min = 0, + max = 20, + step = 1, --(optional) + decimals = 0, --(optional) + tooltip = "Slider's tooltip text.", -- or string id or function returning a string (optional) + width = "full", --or "half" (optional) + disabled = function() return db.someBooleanSetting end, --or boolean (optional) + warning = "Will need to reload the UI.", -- or string id or function returning a string (optional) + default = defaults.var, -- default value or function that returns the default value (optional) + reference = "MyAddonSlider" -- unique global reference to control (optional) +} ]] + + +local widgetVersion = 9 +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 = LAM.util.GetDefaultValue(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 function RoundDecimalToPlace(d, place) + return tonumber(string.format("%." .. tostring(place) .. "f", d)) + 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 + local new_value = sliderData.decimals and RoundDecimalToPlace(value, sliderData.decimals) or value + self:SetValue(new_value) --do we actually need this line? + slidervalue:SetText(new_value) + end) + slider:SetHandler("OnSliderReleased", function(self, value) + --sliderData.setFunc(value) + local new_value = sliderData.decimals and RoundDecimalToPlace(value, sliderData.decimals) or value + control:UpdateValue(false, new_value) --does this work here instead? + end) + slider:SetHandler("OnMouseWheel", function(self, value) + local new_value = (tonumber(slidervalue:GetText()) or sliderData.min or 0) + ((sliderData.step or 1) * value) + control:UpdateValue(false, new_value) + 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 = LAM.util.GetStringFromValue(sliderData.warning)} + end + + if sliderData.disabled ~= nil 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 diff --git a/Lib/LibAddonMenu-2.0/controls/submenu.lua b/Lib/LibAddonMenu-2.0/controls/submenu.lua new file mode 100644 index 0000000..4508c82 --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/submenu.lua @@ -0,0 +1,112 @@ +--[[submenuData = { + type = "submenu", + name = "Submenu Title", -- or string id or function returning a string + tooltip = "My submenu tooltip", -- -- or string id or function returning a string (optional) + controls = {sliderData, buttonData} --(optional) used by LAM + reference = "MyAddonSubmenu" --(optional) unique global reference to control +} ]] + +local widgetVersion = 11 +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(LAM.util.GetStringFromValue(control.data.name)) + if control.data.tooltip then + control.label.data.tooltipText = LAM.util.GetStringFromValue(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(LAM.util.GetStringFromValue(submenuData.name)) + label:SetMouseEnabled(true) + if submenuData.tooltip then + label.data = {tooltipText = LAM.util.GetStringFromValue(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, 0) + + 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 diff --git a/Lib/LibAddonMenu-2.0/controls/texture.lua b/Lib/LibAddonMenu-2.0/controls/texture.lua new file mode 100644 index 0000000..b7f4f8b --- /dev/null +++ b/Lib/LibAddonMenu-2.0/controls/texture.lua @@ -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.", -- or string id or function returning a string (optional) + width = "full", --or "half" (optional) + reference = "MyAddonTexture" --(optional) unique global reference to control +} ]] + +--add texture coords support? + +local widgetVersion = 8 +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.GetStringFromValue(textureData.tooltip)} + texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter) + texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseExit) + end + + return control +end \ No newline at end of file diff --git a/Lib/LibLogos/LibLogos.lua b/Lib/LibLogos/LibLogos.lua new file mode 100644 index 0000000..d1a2cab --- /dev/null +++ b/Lib/LibLogos/LibLogos.lua @@ -0,0 +1,262 @@ +-------------------------------------------------------------------------------------------------- +----------------------------------------- LibLogos -------------------------------------------- +--------------------------- by Deome (@deome) - heydeome@gmail.com --------------------------- +local VERSION = "1.01" -- +-- -- +-- -- +-------------------------------------- Obligatory Spam --------------------------------------- +-- -- +-- "This Add-on is not created by, affiliated with or sponsored by ZeniMax -- +-- Media Inc. or its affiliates. The Elder Scrolls® and related logos are registered -- +-- trademarks of ZeniMax Media Inc. in the United States and/or other countries. -- +-- All rights reserved." -- +-- -- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- + + +-------------------------------------------------------------------------------------------------- +----------------------------------------- Globals -------------------------------------------- +-------------------------------------------------------------------------------------------------- + +local MAJOR, MINOR = "LibLogos", 2 +local LibLogos, oldminor = LibStub:NewLibrary(MAJOR, MINOR) +if not LibLogos then return end + +function LibLogos:SortTable() end +function LibLogos:ClearTable() end +function LibLogos:CountTable() end +function LibLogos:WeightedAverage() end +function LibLogos:Round() end +function LibLogos:RoundTo100s() end +function LibLogos:YearsToSeconds() end +function LibLogos:MonthsToSeconds() end +function LibLogos:WeeksToSeconds() end +function LibLogos:DaysToSeconds() end +function LibLogos:HoursToSeconds() end +function LibLogos:SecondsToYears() end +function LibLogos:SecondsToDays() end +function LibLogos:SecondsToWeeks() end +function LibLogos:SecondsToDays() end +function LibLogos:SecondsToHours() end + + +-------------------------------------------------------------------------------------------------- +------------------------------------------ Logic --------------------------------------------- +-------------------------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------------------------- +----------------------------------------- Tables --------------------------------------------- +-------------------------------------------------------------------------------------------------- + +function LibLogos:ClearTable(aTable, numericIndex) + if numericIndex then + for key = #aTable, 1, -1 do + aTable[key] = nil + end + + return aTable + else + for key in pairs(aTable) do + aTable[key] = nil + end + + return aTable + end +end + +function LibLogos:CountTable(aTable, deep) + local keys = 0 + + for key, value in pairs(aTable) do + keys = keys + 1 + + if deep then + if type(value) == "table" then + LibLogos:CountTable(value) + end + end + end + + return keys +end + +function LibLogos:SortTable(aTable, direction) + if direction == "asc" then + table.sort(aTable) + elseif direction == "desc" then + table.sort(aTable, function(a, b) return a<b end) + end + + return aTable +end + + +-------------------------------------------------------------------------------------------------- +---------------------------------------- Arithmetic ------------------------------------------ +-------------------------------------------------------------------------------------------------- + +function LibLogos:WeightedAverage(value, weight) -- For further study: https://en.wikipedia.org/wiki/Weighted_arithmetic_mean#Mathematical_definition + local Avg = value / weight -- Gonna show my work using the same symbols as in the above definition: + local wAvg = (Avg * weight) / weight -- for reference, µ is the same as "Avg" + + return wAvg + +-- µ = x₁ / w₁ +-- µ = (x₁ * w₁) / w₁ +-- ( (x₁ * w₁) + (x₂ * w₂) + ... (x₉ * w₉) ) / (w₁ + w₂ + ... w₉) + +-- ^^ Repeat for each value/weight pair (ie price/stack in a sale) ^^ +end + + +-------------------------------------------------------------------------------------------------- +----------------------------------------- Currency ------------------------------------------- +-------------------------------------------------------------------------------------------------- + +function LibLogos:Round(value) + return math.floor(value + 0.5) or 0 +end + +function LibLogos:RoundTo100s(value) + value = math.floor(value * 100) + value = value / 100 + + return value or 0 +end + + +-------------------------------------------------------------------------------------------------- +------------------------------------------- Time --------------------------------------------- +-------------------------------------------------------------------------------------------------- + +function LibLogos:YearsToSeconds(years) + years = tonumber(years) + assert(type(years) == "number", + "Bad argument #1 to `YearsToSeconds' (number expected)") + + if years < 0 then + years = years * (-1) + end + + local seconds = years * 31556925.9747 + return seconds +end + +function LibLogos:MonthsToSeconds(months) + months = tonumber(months) + assert(type(months) == "number", + "Bad argument #1 to `MonthsToSeconds' (number expected)") + + if months < 0 then + months = months * (-1) + end + + local seconds = months * 259200 + return seconds +end + +function LibLogos:WeeksToSeconds(weeks) + weeks = tonumber(weeks) + assert(type(weeks) == "number", + "Bad argument #1 to `WeeksToSeconds' (number expected)") + + if weeks < 0 then -- Why would I bother adding a check for negative weeks? + weeks = weeks * (-1) -- Simple: to reduce the frequency of UI errors originating between chair and keyboard. + end + + local seconds = weeks * 604800 + return seconds +end + +function LibLogos:DaysToSeconds(days) + days = tonumber(days) + assert(type(days) == "number", + "Bad argument #1 to `DaysToSeconds' (number expected)") + + if days < 0 then + days = days * (-1) + end + + local seconds = days * 86400 + return seconds +end + +function LibLogos:HoursToSeconds(hours) + hours = tonumber(hours) + assert(type(hours) == "number", + "Bad argument #1 to `HoursToSeconds' (number expected)") + + if hours < 0 then + hours = hours * (-1) + end + + local seconds = hours * 3600 + return seconds +end + +function LibLogos:SecondsToYears(seconds) + seconds = tonumber(seconds) + assert(type(seconds) == "number", + "Bad argument #1 to `SecondsToYears' (number expected)") + + if seconds < 0 then + seconds = seconds * (-1) + end + + local years = seconds / 31556925.9747 + return years +end + +function LibLogos:SecondsToMonths(seconds) + seconds = tonumber(seconds) + assert(type(seconds) == "number", + "Bad argument #1 to `SecondsToMonths' (number expected)") + + if seconds < 0 then + seconds = seconds * (-1) + end + + local months = seconds / 2592000 + return months +end + +function LibLogos:SecondsToWeeks(seconds) + seconds = tonumber(seconds) + assert(type(seconds) == "number", + "Bad argument #1 to `SecondsToWeeks' (number expected)") + + if seconds < 0 then + seconds = seconds * (-1) + end + + local weeks = seconds / 604800 + return weeks +end + +function LibLogos:SecondsToDays(seconds) + seconds = tonumber(seconds) + assert(type(seconds) == "number", + "Bad argument #1 to `SecondsToDays' (number expected)") + + if seconds < 0 then + seconds = seconds * (-1) + end + + local days = seconds / 86400 + return days +end + +function LibLogos:SecondsToHours(seconds) + seconds = tonumber(seconds) + assert(type(seconds) == "number", + "Bad argument #1 to `SecondsToHours' (number expected)") + + if seconds < 0 then + seconds = seconds * (-1) + end + + local hours = seconds / 3600 + return hours +end + diff --git a/Lib/LibStub/LibStub.lua b/Lib/LibStub/LibStub.lua new file mode 100644 index 0000000..4dbff7b --- /dev/null +++ b/Lib/LibStub/LibStub.lua @@ -0,0 +1,34 @@ +-- 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", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! +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)") + minor = assert(tonumber(zo_strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") + + 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 diff --git a/Lib/LibStub/LibStub.txt b/Lib/LibStub/LibStub.txt new file mode 100644 index 0000000..df3488c --- /dev/null +++ b/Lib/LibStub/LibStub.txt @@ -0,0 +1,7 @@ +## APIVersion: 100007 +## Title: LibStub +## Description: Universal Library Stub +## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, ported to ESO by Seerah +## Version: 1.0 r4 + +LibStub\LibStub.lua \ No newline at end of file diff --git a/Lib/LibStub/LibStub/LibStub.lua b/Lib/LibStub/LibStub/LibStub.lua new file mode 100644 index 0000000..4c35014 --- /dev/null +++ b/Lib/LibStub/LibStub/LibStub.lua @@ -0,0 +1,38 @@ +-- 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", 4 +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 + +LibStub.SILENT = true \ No newline at end of file diff --git a/ddDataDaedra.lua b/ddDataDaedra.lua new file mode 100644 index 0000000..74abf31 --- /dev/null +++ b/ddDataDaedra.lua @@ -0,0 +1,1536 @@ +-------------------------------------------------------------------------------------------------- +----------------------------------------- DataDaedra ----------------------------------------- +--------------------------- by Deome (@deome) - heydeome@gmail.com --------------------------- +local VERSION = "1.9" -- +-- -- +-- -- +--------------------------------------- Deome's License -------------------------------------- +-- -- +-- Copyright (c) 2014, 2015, 2016 D. Deome (@deome) - heydeome@gmail.com -- +-- -- +-- This software is provided 'as-is', without any express or implied -- +-- warranty. In no event will the author(s) be held liable for any damages -- +-- arising from the use of this software. This software, and the ideas, processes, -- +-- functions, and all other intellectual property contained within may not be modified, -- +-- distributed, or used in any other works without the written permission of the -- +-- author. -- +-- -- +-- Any use with permission of author must include the above license and copyright, -- +-- and any other license and copyright notices noted within this software. -- +-- -- +------------------------------------- ZO Obligatory Spam ------------------------------------- +-- -- +-- "This Add-on is not created by, affiliated with or sponsored by ZeniMax -- +-- Media Inc. or its affiliates. The Elder Scrolls and related logos are registered -- +-- trademarks of ZeniMax Media Inc. in the United States and/or other countries. -- +-- All rights reserved." -- +-- -- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- + + +-------------------------------------------------------------------------------------------------- +---------------------------------------- Libraries ------------------------------------------- +-------------------------------------------------------------------------------------------------- + +local LIB_LAM2 = LibStub("LibAddonMenu-2.0") +local LIB_LOG = LibStub("LibLogos") + + +-------------------------------------------------------------------------------------------------- +---------------------------------------- Namespace ------------------------------------------- +-------------------------------------------------------------------------------------------------- + +ddDataDaedra = { + ["name"] = "ddDataDaedra", + ["version"] = VERSION, + ["savedVarsVersion"] = 8, + ["isScanning"] = false, + ["dataCairn"] = { + ["lastScan"] = {}, + ["lastSale"] = {}, + ["numSales"] = {}, + ["prices"] = {}, + ["codex"] = { + ["init"] = function() end, + ["cResetButton"] = {}, + ["cPanelHeader"] = {}, + ["cNotify"] = {}, + ["cDebug"] = {}, + ["cwAvgSalePrice"] = {}, + ["cSaveSalePrice"] = {}, + ["cInterval"] = {}, + ["cTooltipDetails"] = {}, + ["cTooltipFontHeader"] = {}, + ["cTooltipFontBody"] = {}, + ["cTooltipQuality"] = {}, + }, + ["UI"] = { + }, + }, + ["mPanel"] = function() end, + ["mControls"] = function() end, + ["chatLinkStatsToChat"] = function() end, + ["slotControlStatsToChat"] = function() end, + ["seenToStr"] = function() end, + ["wAvgToStr"] = function() end, + ["stackToStr"] = function() end, + ["inscribeCraftSigilstone"] = function() end, + ["inscribeItemSigilstone"] = function() end, + ["inscribePopupSigilstone"] = function() end, + ["alchemySigil"] = function() end, + ["provisionerSigil"] = function() end, + ["enchantingSigil"] = function() end, + ["creationSigil"] = function() end, + ["improvementSigil"] = function() end, + ["sigilDesign"] = function() end, + ["linkStatsToChat"] = function() end, + ["twilightMaiden"] = function() end, + ["twilightSummons"] = function() end, + ["displayMsg"] = function() end, + ["hooks"] = function() end, + ["liminalBridge"] = function() end, +} + + +-------------------------------------------------------------------------------------------------- +---------------------------------------- Constants ------------------------------------------- +-------------------------------------------------------------------------------------------------- + +local DATACAIRN = ddDataDaedra.dataCairn +local CODEX = ddDataDaedra.dataCairn.codex +local PRICES = ddDataDaedra.dataCairn.prices +local ADDON_NAME = ddDataDaedra.name +local SV_VERSION = ddDataDaedra.savedVarsVersion +local TASKMASTER = nil +local Sigil = nil +local TooltipControl = nil +local PopupControl = nil +local ResultControl = nil +local SlotControl = nil +local craftingStation = nil +local ACTIVE_SLOT = nil +local NUMGUILDS = GetNumGuilds() +local PostFunc = nil + +local fonts = { + "DataDaedraHeader", + "DataDaedraBody", + "ZoFontBookTabletTitle", + "ZoFontBookTablet", + "ZoFontBookScrollTitle", + "ZoFontBookScroll", + "ZoFontBookNoteTitle", + "ZoFontBookNote", + "ZoFontBookLetterTitle", + "ZoFontBookLetter", + "ZoFontBookRubbingTitle", + "ZoFontBookRubbing", + "ZoFontBookSkinTitle", + "ZoFontBookSkin", + "ZoFontBookPaperTitle", + "ZoFontBookPaper", + "ZoFontTooltipTitle", + "ZoFontTooltipSubtitle", + "ZoFontHeader4", + "ZoFontHeader3", + "ZoFontHeader2", + "ZoFontHeader", + "ZoFontGameLargeBoldShadow", + "ZoFontGameLargeBold", + "ZoFontGameLarge", + "ZoFontGameShadow", + "ZoFontGameOutline", + "ZoFontGameBold", + "ZoFontGameMedium", + "ZoFontGame", + "ZoFontGameSmall", +} + +local Str_Item_Quality = { +[ITEM_QUALITY_NORMAL] = SI_ITEMQUALITY1, +[ITEM_QUALITY_MAGIC] = SI_ITEMQUALITY2, +[ITEM_QUALITY_ARCANE] = SI_ITEMQUALITY3, +[ITEM_QUALITY_ARTIFACT] = SI_ITEMQUALITY4, +[ITEM_QUALITY_LEGENDARY] = SI_ITEMQUALITY5, +[ITEM_QUALITY_TRASH] = SI_ITEMQUALITY0, +} + +local Str_Item_Trait = { +[ITEM_TRAIT_TYPE_NONE] = SI_ITEMTRAITTYPE0, +[ITEM_TRAIT_TYPE_WEAPON_POWERED] = SI_ITEMTRAITTYPE1, +[ITEM_TRAIT_TYPE_WEAPON_CHARGED] = SI_ITEMTRAITTYPE2, +[ITEM_TRAIT_TYPE_WEAPON_PRECISE] = SI_ITEMTRAITTYPE3, +[ITEM_TRAIT_TYPE_WEAPON_INFUSED] = SI_ITEMTRAITTYPE4, +[ITEM_TRAIT_TYPE_WEAPON_DEFENDING] = SI_ITEMTRAITTYPE5, +[ITEM_TRAIT_TYPE_WEAPON_TRAINING] = SI_ITEMTRAITTYPE6, +[ITEM_TRAIT_TYPE_WEAPON_SHARPENED] = SI_ITEMTRAITTYPE7, +[ITEM_TRAIT_TYPE_WEAPON_WEIGHTED] = SI_ITEMTRAITTYPE8, +[ITEM_TRAIT_TYPE_WEAPON_INTRICATE] = SI_ITEMTRAITTYPE9, +[ITEM_TRAIT_TYPE_WEAPON_ORNATE] = SI_ITEMTRAITTYPE10, +[ITEM_TRAIT_TYPE_ARMOR_STURDY] = SI_ITEMTRAITTYPE11, +[ITEM_TRAIT_TYPE_ARMOR_IMPENETRABLE] = SI_ITEMTRAITTYPE12, +[ITEM_TRAIT_TYPE_ARMOR_REINFORCED] = SI_ITEMTRAITTYPE13, +[ITEM_TRAIT_TYPE_ARMOR_WELL_FITTED] = SI_ITEMTRAITTYPE14, +[ITEM_TRAIT_TYPE_ARMOR_TRAINING] = SI_ITEMTRAITTYPE15, +[ITEM_TRAIT_TYPE_ARMOR_INFUSED] = SI_ITEMTRAITTYPE16, +[ITEM_TRAIT_TYPE_ARMOR_EXPLORATION] = SI_ITEMTRAITTYPE17, +[ITEM_TRAIT_TYPE_ARMOR_DIVINES] = SI_ITEMTRAITTYPE18, +[ITEM_TRAIT_TYPE_ARMOR_ORNATE] = SI_ITEMTRAITTYPE19, +[ITEM_TRAIT_TYPE_ARMOR_INTRICATE] = SI_ITEMTRAITTYPE20, +[ITEM_TRAIT_TYPE_JEWELRY_HEALTHY] = SI_ITEMTRAITTYPE21, +[ITEM_TRAIT_TYPE_JEWELRY_ARCANE] = SI_ITEMTRAITTYPE22, +[ITEM_TRAIT_TYPE_JEWELRY_ROBUST] = SI_ITEMTRAITTYPE23, +[ITEM_TRAIT_TYPE_JEWELRY_ORNATE] = SI_ITEMTRAITTYPE24, +[ITEM_TRAIT_TYPE_ARMOR_NIRNHONED] = SI_ITEMTRAITTYPE25, +[ITEM_TRAIT_TYPE_WEAPON_NIRNHONED] = SI_ITEMTRAITTYPE26, +} + + +local function parseItemLinkLevel(itemLink) + if itemLink == nil then return nil end + + local vetRank = GetItemLinkRequiredVeteranRank(itemLink) + local reqLevel = GetItemLinkRequiredLevel(itemLink) + + if not vetRank then + vetRank = 0 + elseif not reqLevel then + reqLevel = 1 + end + + if vetRank > 0 then + return reqLevel, vetRank, zo_strformat(SI_ITEM_FORMAT_STR_LEVEL, reqLevel).." "..reqLevel, zo_strformat(SI_ITEM_FORMAT_STR_RANK, vetRank).." "..vetRank + else + return reqLevel, vetRank, zo_strformat(SI_ITEM_FORMAT_STR_LEVEL, reqLevel).." "..reqLevel, "" + end +end + +local function parseItemLinkQuality(itemLink) + if not itemLink then return nil end + local iQuality = GetItemLinkQuality(itemLink) + + return iQuality, zo_strformat(Str_Item_Quality[iQuality]) +end + +local function parseItemLinkSetItem(itemLink) + if not itemLink then return nil end + local iHasSet, setName = GetItemLinkSetInfo(itemLink) + + if not iHasSet then iHasSet = 0 else iHasSet = 1 end + + return iHasSet, zo_strformat(SI_ITEM_FORMAT_STR_SET_NAME, setName) +end + +local function parseItemLinkTrait(itemLink) + if not itemLink then return nil end + local iTrait = select(1, GetItemLinkTraitInfo(itemLink)) + + return iTrait, zo_strformat(Str_Item_Trait[iTrait]) +end + +local function parseItemLinkToTable(itemLink) + if not itemLink then return nil end + local ParsedItemLink = {} + + for val in string.gmatch(itemLink, "(%d-):") do + if val ~= "" then + table.insert(ParsedItemLink, val) + else + table.insert(ParsedItemLink, "item") + end + end + + return ParsedItemLink +end + +local function parseLinkValue(itemLink, place) + if not itemLink then return nil end + local LinkTable = parseItemLinkToTable(itemLink) + + if (place <= 21 and place >= 1) then + local val = tonumber(LinkTable[place]) + return val + else + return nil + end +end + +local function getItemLinkFromSlotControl(slotControl) + local InventorySlot, ItemLink + + if not slotControl.dataEntry then + InventorySlot = slotControl + return GetItemLink(InventorySlot.bagId, InventorySlot.slotIndex) + + elseif slotControl.dataEntry then + InventorySlot = slotControl.dataEntry.data + + if InventorySlot.bagId and + InventorySlot.slotIndex then + return GetItemLink(InventorySlot.bagId, InventorySlot.slotIndex) + else + return GetItemLink(InventorySlot.bag, InventorySlot.index) + end + else + return "" + end +end + +local function getKeyedItem(itemLink) + local codex = ddDataDaedra.dataCairn.codex + local PRICES = ddDataDaedra.dataCairn.prices + local ItemId = parseLinkValue(itemLink, 3) + local EnchtId = parseLinkValue(itemLink, 6) + local Trait = parseItemLinkTrait(itemLink) + local Level, VetRank = parseItemLinkLevel(itemLink) + local Quality = parseItemLinkQuality(itemLink) + + if PRICES[ItemId] then + if PRICES[ItemId][Trait] then + if PRICES[ItemId][Trait][Quality] then + if PRICES[ItemId][Trait][Quality][Level] then + if PRICES[ItemId][Trait][Quality][Level][VetRank] then + if PRICES[ItemId][Trait][Quality][Level][VetRank][EnchtId] then + return PRICES[ItemId][Trait][Quality][Level][VetRank][EnchtId] + end + end + end + end + end + end + + return nil +end + +local function isKeyedItem(itemLink) + local KeyedItem = getKeyedItem(itemLink) + + if not KeyedItem then + return false + else + return true + end +end + +local function pendListing() + local twAvgSalePrice = ddDataDaedra.dataCairn.codex.cwAvgSalePrice.getFunc() + local tSaveSalePrice = ddDataDaedra.dataCairn.codex.cSaveSalePrice.getFunc() + PostFunc(TRADING_HOUSE) + + if TRADING_HOUSE.m_pendingItemSlot and + (twAvgSalePrice or tSaveSalePrice) then + local ItemLink = GetItemLink(BAG_BACKPACK, TRADING_HOUSE.m_pendingItemSlot) + local KeyedItem = getKeyedItem(ItemLink) + local Stack = select(2, GetItemInfo(BAG_BACKPACK, TRADING_HOUSE.m_pendingItemSlot)) or 1 + + if KeyedItem and + (twAvgSalePrice or tSaveSalePrice) then + if not KeyedItem.wAvg then KeyedItem.wAvg = 0 end + if not KeyedItem.PostPrice then KeyedItem.PostPrice = 0 end + + if twAvgSalePrice and + KeyedItem.wAvg ~= 0 then + if tSaveSalePrice and + KeyedItem.PostPrice ~= 0 and + KeyedItem.PostPrice > KeyedItem.wAvg then + TRADING_HOUSE:SetPendingPostPrice(LIB_LOG:Round(KeyedItem.PostPrice * Stack)) + else + TRADING_HOUSE:SetPendingPostPrice(LIB_LOG:Round(KeyedItem.wAvg * Stack)) + end + + elseif tSaveSalePrice and + KeyedItem.PostPrice ~= 0 then + TRADING_HOUSE:SetPendingPostPrice(LIB_LOG:Round(KeyedItem.PostPrice * Stack)) + end + end + end +end + +local function savePrice() + local CODEX = ddDataDaedra.dataCairn.codex + local tSaveSalePrice = CODEX.cSaveSalePrice.getFunc() + local itemLink = GetItemLink(BAG_BACKPACK, TRADING_HOUSE.m_pendingItemSlot) + local Stack = select(2, GetItemInfo(BAG_BACKPACK, TRADING_HOUSE.m_pendingItemSlot)) + local KeyedItem = getKeyedItem(itemLink) + local PostPrice = LIB_LOG:Round(LIB_LOG:RoundTo100s(TRADING_HOUSE.m_invoiceSellPrice.sellPrice / Stack)) + + if tSaveSalePrice then + if KeyedItem then + local wAvgPrice = LIB_LOG:Round(LIB_LOG:RoundTo100s(KeyedItem.wAvg / Stack)) + + if wAvgPrice ~= PostPrice then + KeyedItem.PostPrice = PostPrice + end + else + local PRICES = ddDataDaedra.dataCairn.prices + local ItemId = parseLinkValue(itemLink, 3) + local EnchtId = parseLinkValue(itemLink, 6) + local Trait = parseItemLinkTrait(itemLink) + local Level, VetRank = parseItemLinkLevel(itemLink) + local Quality = parseItemLinkQuality(itemLink) + + Values = { + ["Seen"] = 0, + ["RawValue"] = 0, + ["Weight"] = 0, + ["wAvg"] = 0, + ["PostPrice"] = PostPrice, + } + + if PRICES[ItemId] then + if PRICES[ItemId] then + if PRICES[ItemId][Trait] then + if PRICES[ItemId][Trait][Quality] then + if PRICES[ItemId][Trait][Quality][Level] then + if PRICES[ItemId][Trait][Quality][Level][VetRank] then + if not PRICES[ItemId][Trait][Quality][Level][VetRank][EnchtId] then + table.insert(PRICES[ItemId][Trait][Quality][Level][VetRank], EnchtId, Values) + end + + end + end + end + end + end + end + end + end +end + +-------------------------------------------------------------------------------------------------- +------------------------------- Modular Controls by @Deome ----------------------------------- +-- -- +-- ---- For LibAddonMenu 2.0 by Seerah ---- -- +-- ---- With gratitude and credit for this wonderful library ---- -- +-- -- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------------------------- +-- -- Modular Controls allow even more customization for LAM2 -- -- +-- -- (which already offers so much!) -- -- +-- -- and make plugins, updates, and common settings simple for everyone -- -- +-------------------------------------------------------------------------------------------------- + + +-------------------------------------------------------------------------------------------------- +------------------------------------ LAM2 Panel Layout --------------------------------------- +-------------------------------------------------------------------------------------------------- + +function ddDataDaedra:mControls() + local CODEX = self.dataCairn.codex + local menu = { + CODEX.cNotify:init(), + CODEX.cDebug:init(), +-- CODEX.cResetButton:init(), + CODEX.cInterval:init(), + CODEX.cwAvgSalePrice:init(), + CODEX.cSaveSalePrice:init(), + CODEX.cTooltipFontHeader:init(), + CODEX.cTooltipFontBody:init(), + } + return menu +end + +function ddDataDaedra:mPanel() + local Panel = { + type = "panel", + name = GetString(DD_TASKMASTER_NAME), + displayName = GetString(DD_TASKMASTER_DISPLAYNAME), + author = GetString(DD_TASKMASTER_AUTHOR), + version = self.version, + registerForRefresh = true, + registerForDefaults = true, + } + return Panel +end + + +-------------------------------------------------------------------------------------------------- +---------------------------------- LAM2 Modular Controls ------------------------------------- +-------------------------------------------------------------------------------------------------- + +function CODEX:init() -- Initializes all controls so that they're fully set up and ready to use, + self.cInterval:init() -- regardless of whether they're displayed or active. +-- self.cResetButton:init() +-- self.cTooltipQuality:init() + self.cDebug:init() + self.cNotify:init() + self.cSaveSalePrice:init() + self.cwAvgSalePrice:init() + self.cTooltipFontHeader:init() + self.cTooltipFontBody:init() + +end + +function CODEX.cNotify:init() + self.type = "checkbox" + self.name = GetString(DD_TASKMASTER_NOTIFICATIONS_NAME) + self.tooltip = GetString(DD_TASKMASTER_NOTIFICATIONS_TIP) + self.width = "full" + + self.default = true + self.getFunc = function() if self.value == nil then self.value = self.default end return self.value end + self.setFunc = function(value) self.value = value end + return self +end + +function CODEX.cDebug:init() + self.type = "checkbox" + self.name = GetString(DD_TASKMASTER_DEBUG_NAME) + self.tooltip = GetString(DD_TASKMASTER_DEBUG_TIP) + self.width = "full" + + self.default = false + self.getFunc = function() if self.value == nil then self.value = self.default end return self.value end + self.setFunc = function(value) self.value = value end + return self +end + +function CODEX.cInterval:init() + self.type = "slider" + self.name = GetString(DD_TASKMASTER_INTERVAL_NAME) + self.tooltip = GetString(DD_TASKMASTER_INTERVAL_TIP) + self.width = "full" + + self.min = 1 + self.max = 10 + self.step = 1 + self.default = 3 + self.getFunc = function() if self.value == nil then self.value = self.default end return self.value end + self.setFunc = function(value) EVENT_MANAGER:UnregisterForUpdate(ddDataDaedra.name) + self.value = value + EVENT_MANAGER:RegisterForUpdate(ddDataDaedra.name, (self.value * 60 * 1000), function() ddDataDaedra:twilightSummons() end) + end + return self +end + +function CODEX.cSaveSalePrice:init() + self.type = "checkbox" + self.name = GetString(DD_TASKMASTER_SAVE_SALE_PRICE_NAME) + self.tooltip = GetString(DD_TASKMASTER_SAVE_SALE_PRICE_TIP) + self.width = "full" + + self.default = false + self.getFunc = function() if self.value == nil then self.value = self.default end return self.value end + self.setFunc = function(value) self.value = value end + return self +end + +function CODEX.cwAvgSalePrice:init() + self.type = "checkbox" + self.name = GetString(DD_TASKMASTER_WAVG_SALE_PRICE_NAME) + self.tooltip = GetString(DD_TASKMASTER_WAVG_SALE_PRICE_TIP) + self.width = "full" + + self.default = true + self.getFunc = function() if self.value == nil then self.value = self.default end return self.value end + self.setFunc = function(value) self.value = value end + return self +end + +function CODEX.cTooltipFontHeader:init() + self.type = "dropdown" + self.name = GetString(DD_TASKMASTER_TOOLTIP_HEADER_FONT_NAME) + self.tooltip = GetString(DD_TASKMASTER_TOOLTIP_HEADER_FONT_TIP) + self.width = "full" + + self.choices = fonts + self.default = fonts[1] + self.getFunc = function() if self.value == nil then self.value = self.default end return self.value end + self.setFunc = function(value) self.value = value end + return self +end + +function CODEX.cTooltipFontBody:init() + self.type = "dropdown" + self.name = GetString(DD_TASKMASTER_TOOLTIP_BODY_FONT_NAME) + self.tooltip = GetString(DD_TASKMASTER_TOOLTIP_BODY_FONT_TIP) + self.width = "full" + + self.choices = fonts + self.default = fonts[2] + self.getFunc = function() if self.value == nil then self.value = self.default end return self.value end + self.setFunc = function(value) self.value = value end + return self +end + + +-------------------------------------------------------------------------------------------------- +---------------------------------------- Key Bindings ---------------------------------------- +-------------------------------------------------------------------------------------------------- + + +-------------------------------------------------------------------------------------------------- +---------------------------------------- UI Bindings ----------------------------------------- +-------------------------------------------------------------------------------------------------- + +function ddDataDaedra:seenToStr(seen) + local LowSeen = 25 + local HighSeen = 100 + local Str_SeenColor = "|cFF0000" + + if seen > LowSeen and + seen < HighSeen then + Str_SeenColor = "|cFFFF00" + elseif seen >= HighSeen then + Str_SeenColor = "|c00FF00" + end + + return zo_strformat(GetString(DD_TOOLTIP_STAT_SEEN), Str_SeenColor, ZO_CommaDelimitNumber(seen), zo_iconFormat("esoui/art/miscellaneous/search_icon.dds", 32, 32)) +end + +function ddDataDaedra:wAvgToStr(wAvg) + return zo_strformat(GetString(DD_TOOLTIP_STAT_WAVG), ZO_CommaDelimitNumber(LIB_LOG:Round(wAvg)), zo_iconFormat("esoui/art/currency/currency_gold.dds", 18, 18)) +end + +function ddDataDaedra:stackToStr(wAvg, stack) + return zo_strformat(GetString(DD_TOOLTIP_STAT_STACK), ZO_CommaDelimitNumber(LIB_LOG:Round(wAvg * stack)), zo_iconFormat("esoui/art/currency/currency_gold.dds", 18, 18), stack) +end + +function ddDataDaedra:resizeSigil(tooltip, label) + local DimDefault = 416 + local Pad1, Pad2 = tooltip:GetResizeToFitPadding() + local labelWidth = label:GetTextWidth() + + if (labelWidth + Pad1) > DimDefault then + local NewDim = Pad1 + labelWidth + tooltip:SetDimensionConstraints(NewDim, -1, NewDim, -1) + else + tooltip:SetDimensionConstraints(DimDefault, -1, DimDefault, -1) + end +end + +function ddDataDaedra:createItemSigil(tooltip, keyedItem, stack) + if not tooltip.labelPool then + tooltip.labelPool = ZO_ControlPool:New("ZO_TooltipLabel", tooltip, "Label") + end + if not stack or stack < 2 then stack = 1 end + local FontHeader = self.dataCairn.codex.cTooltipFontHeader.getFunc() + local FontBody = self.dataCairn.codex.cTooltipFontBody.getFunc() + local SigilHeader = tooltip.labelPool:AcquireObject() + local SigilLabel = tooltip.labelPool:AcquireObject() + local BulletIcon = zo_iconFormat(GetString(DD_ICON_BULLET), 12, 12) + local Str_Buffer = " "..BulletIcon.." " + local Str_Seen = self:seenToStr(keyedItem.Seen) + local Str_wAvg = self:wAvgToStr(keyedItem.wAvg) + local Str_Stack = self:stackToStr(keyedItem.wAvg, stack) + local Str_Sigil = Str_Seen..Str_Buffer..Str_wAvg + + if stack > 1 then + Str_Sigil = Str_Sigil..Str_Buffer..Str_Stack + end + + tooltip:AddVerticalPadding(20) + ZO_Tooltip_AddDivider(tooltip) + + tooltip:AddControl(SigilHeader) + SigilHeader:SetAnchor(CENTER) + SigilHeader:SetHorizontalAlignment(CENTER) + SigilHeader:SetFont(FontHeader) + SigilHeader:SetModifyTextType(MODIFY_TEXT_TYPE_NONE) + SigilHeader:SetColor(ZO_TOOLTIP_DEFAULT_COLOR:UnpackRGB()) + SigilHeader:SetText(GetString(DD_TOOLTIP_HEADER)) + + tooltip:AddControl(SigilLabel) + SigilLabel:SetAnchor(CENTER) + SigilLabel:SetHorizontalAlignment(CENTER) + SigilLabel:SetFont(FontBody) + SigilLabel:SetModifyTextType(MODIFY_TEXT_TYPE_NONE) + SigilLabel:SetColor(ZO_TOOLTIP_DEFAULT_COLOR:UnpackRGB()) + SigilLabel:SetText(Str_Sigil) + self:resizeSigil(tooltip, SigilLabel) +end + +function ddDataDaedra:createMiserSigil(tooltip, str_TotalCost) + if not tooltip.labelPool then + tooltip.labelPool = ZO_ControlPool:New("ZO_TooltipLabel", tooltip, "Label") + end + + local FontHeader = self.dataCairn.codex.cTooltipFontHeader.getFunc() + local FontBody = self.dataCairn.codex.cTooltipFontBody.getFunc() + local MiserHeader = tooltip.labelPool:AcquireObject() + local MiserLabel = tooltip.labelPool:AcquireObject() + + tooltip:AddVerticalPadding(20) + + tooltip:AddControl(MiserHeader) + MiserHeader:SetAnchor(CENTER) + MiserHeader:SetHorizontalAlignment(CENTER) + MiserHeader:SetFont(FontHeader) + MiserHeader:SetModifyTextType(MODIFY_TEXT_TYPE_NONE) + MiserHeader:SetColor(ZO_TOOLTIP_DEFAULT_COLOR:UnpackRGB()) + MiserHeader:SetText(GetString(DD_TOOLTIP_CRAFTING_HEADER)) + + tooltip:AddControl(MiserLabel) + MiserLabel:SetAnchor(CENTER) + MiserLabel:SetHorizontalAlignment(CENTER) + MiserLabel:SetFont(FontBody) + MiserLabel:SetModifyTextType(MODIFY_TEXT_TYPE_NONE) + MiserLabel:SetColor(ZO_TOOLTIP_DEFAULT_COLOR:UnpackRGB()) + MiserLabel:SetText(str_TotalCost) + self:resizeSigil(tooltip, MiserLabel) +end + +function ddDataDaedra:inscribePopupSigilstone(tooltip) + if tooltip == PopupControl then return end + PopupControl = tooltip + + local ResultKeyedItem = getKeyedItem(PopupControl.lastLink) + + if ResultKeyedItem and + ResultKeyedItem.wAvg and + ResultKeyedItem.Seen and + ResultKeyedItem.wAvg > 0 and + ResultKeyedItem.Seen > 0 then + self:createItemSigil(tooltip, ResultKeyedItem) + end +end + +function ddDataDaedra:inscribeItemSigilstone(tooltip, itemLink, stack) + if not tooltip or + not itemLink or + itemLink == "" then + return + + elseif not stack or + stack < 2 then + stack = 1 + end + + local ResultKeyedItem = getKeyedItem(itemLink) + + if ResultKeyedItem and + ResultKeyedItem.wAvg and + ResultKeyedItem.Seen and + ResultKeyedItem.wAvg > 0 and + ResultKeyedItem.Seen > 0 then + self:createItemSigil(tooltip, ResultKeyedItem, stack) + end +end + +function ddDataDaedra:inscribeCraftSigilstone(tooltip, resultLink, resultStack, str_TotalCost) + if not tooltip then return end + local ResultKeyedItem = getKeyedItem(resultLink) + + if not resultStack or + resultStack < 2 then + resultStack = 1 + end + + if ResultKeyedItem and + ResultKeyedItem.wAvg and + ResultKeyedItem.Seen and + ResultKeyedItem.wAvg > 0 and + ResultKeyedItem.Seen > 0 then + self:createItemSigil(tooltip, ResultKeyedItem, resultStack) + end + + self:createMiserSigil(tooltip, str_TotalCost) +end + +function ddDataDaedra:alchemySigil(self, tooltip) + if not tooltip or + tooltip == ResultControl then + return + end + ResultControl = tooltip + craftingStation = ALCHEMY + + local SolventBagId = craftingStation.solventSlot.bagId + local SolventSlotIndex = craftingStation.solventSlot.slotIndex + local SolventItemLink = GetItemLink(SolventBagId, SolventSlotIndex, LINK_STYLE_BRACKETS) + local SolventIcon = zo_iconFormat(GetItemLinkInfo(SolventItemLink), 28, 28) + local SolventKeyedItem = getKeyedItem(SolventItemLink) + local SolventCost = 0 + + if SolventKeyedItem and + SolventKeyedItem.wAvg and + SolventKeyedItem.wAvg > 0 then + SolventCost = SolventKeyedItem.wAvg + end + + local Reagent1BagId = craftingStation.reagentSlots[1].bagId + local Reagent1SlotIndex = craftingStation.reagentSlots[1].slotIndex + local Reagent1ItemLink = GetItemLink(Reagent1BagId, Reagent1SlotIndex, LINK_STYLE_BRACKETS) + local Reagent1Icon = zo_iconFormat(GetItemLinkInfo(Reagent1ItemLink), 28, 28) + local Reagent1KeyedItem = getKeyedItem(Reagent1ItemLink) + local Reagent1Cost = 0 + + if Reagent1KeyedItem and + Reagent1KeyedItem.wAvg and + Reagent1KeyedItem.wAvg > 0 then + Reagent1Cost = Reagent1KeyedItem.wAvg + end + + local Reagent2BagId = craftingStation.reagentSlots[2].bagId + local Reagent2SlotIndex = craftingStation.reagentSlots[2].slotIndex + local Reagent2ItemLink = GetItemLink(Reagent2BagId, Reagent2SlotIndex, LINK_STYLE_BRACKETS) + local Reagent2Icon = zo_iconFormat(GetItemLinkInfo(Reagent2ItemLink), 28, 28) + local Reagent2KeyedItem = getKeyedItem(Reagent2ItemLink) + local Reagent2Cost = 0 + + if Reagent2KeyedItem and + Reagent2KeyedItem.wAvg and + Reagent2KeyedItem.wAvg > 0 then + Reagent2Cost = Reagent2KeyedItem.wAvg + end + + local Reagent3BagId = craftingStation.reagentSlots[3].bagId + local Reagent3SlotIndex = craftingStation.reagentSlots[3].slotIndex + local Reagent3ItemLink = GetItemLink(Reagent3BagId, Reagent3SlotIndex, LINK_STYLE_BRACKETS) + local Reagent3Icon = zo_iconFormat(GetItemLinkInfo(Reagent3ItemLink), 28, 28) + local Reagent3KeyedItem = getKeyedItem(Reagent3ItemLink) + local Reagent3Cost = 0 + + if Reagent3KeyedItem and + Reagent3KeyedItem.wAvg and + Reagent3KeyedItem.wAvg > 0 then + Reagent3Cost = Reagent3KeyedItem.wAvg + end + + local PotionLink = GetAlchemyResultingItemLink(SolventBagId, SolventSlotIndex, Reagent1BagId, Reagent1SlotIndex, Reagent2BagId, Reagent2SlotIndex, Reagent3BagId, Reagent3SlotIndex, LINK_STYLE_BRACKETS) + local PotionCount = select(3, GetAlchemyResultingItemInfo(SolventBagId, SolventSlotIndex, Reagent1BagId, Reagent1SlotIndex, Reagent2BagId, Reagent2SlotIndex, Reagent3BagId, Reagent3SlotIndex, LINK_STYLE_BRACKETS)) + local TotalCost = LIB_LOG:Round(SolventCost + Reagent1Cost + Reagent2Cost + Reagent3Cost) + + if TotalCost ~= 0 then + local Str_TotalReagentCost = "" + local Str_Buffer = " " + local GoldIcon = zo_iconFormat(GetString(DD_ICON_GOLD), 20, 20) + local PlusIcon = zo_iconFormat("esoui/art/progression/addpoints_up.dds", 32, 32) + local EqualsIcon = zo_iconFormat("/esoui/art/progression/progression_tabicon_passive_inactive.dds", 32, 32) + local Str_TotalCost = zo_strformat(GetString(DD_TOOLTIP_CRAFTING_WAVG), ZO_CommaDelimitNumber(TotalCost), GoldIcon) + + if SolventCost > 0 and + Reagent1Cost > 0 then + Str_TotalReagentCost = SolventIcon..Str_Buffer..PlusIcon..Str_Buffer..Reagent1Icon + + if Reagent2Cost > 0 then + Str_TotalReagentCost = Str_TotalReagentCost..Str_Buffer..PlusIcon..Str_Buffer..Reagent2Icon + end + if Reagent3Cost > 0 then + Str_TotalReagentCost = Str_TotalReagentCost..Str_Buffer..PlusIcon..Str_Buffer..Reagent3Icon + end + + Str_TotalReagentCost = Str_TotalReagentCost..EqualsIcon..Str_Buffer..Str_TotalCost + end + + self:inscribeCraftSigilstone(tooltip, PotionLink, PotionCount, Str_TotalReagentCost) + end +end + +function ddDataDaedra:provisionerSigil(self, tooltip) + if not tooltip or + tooltip == ResultControl then + return + end + ResultControl = tooltip + craftingStation = PROVISIONER + + local RecipeListIndex = craftingStation:GetSelectedRecipeListIndex() + local RecipeIndex = craftingStation:GetSelectedRecipeIndex() + local RecipeLink = GetRecipeResultItemLink(RecipeListIndex, RecipeIndex, LINK_STYLE_BRACKETS) + local RecipeCount = select(3, GetRecipeResultItemInfo(RecipeListIndex, RecipeIndex)) + + local MatIndex1 = craftingStation.ingredientRows[1].control.ingredientIndex + local MatLink1, MatIcon1, MatKeyedItem1 + local MatCost1 = 0 + + if MatIndex1 then + MatLink1 = GetRecipeIngredientItemLink(RecipeListIndex, RecipeIndex, MatIndex1, LINK_STYLE_BRACKETS) + MatIcon1 = zo_iconFormat(select(2, GetRecipeIngredientItemInfo(RecipeListIndex, RecipeIndex, MatIndex1)), 28, 28) + MatKeyedItem1 = getKeyedItem(MatLink1) + MatCost1 = 0 + + if MatKeyedItem1 and + MatKeyedItem1.wAvg ~= 0 then + MatCost1 = MatKeyedItem1.wAvg + end + end + + local MatIndex2 = craftingStation.ingredientRows[2].control.ingredientIndex + local MatLink2, MatIcon2, MatKeyedItem2 + local MatCost2 = 0 + + if MatIndex2 then + MatLink2 = GetRecipeIngredientItemLink(RecipeListIndex, RecipeIndex, MatIndex2, LINK_STYLE_BRACKETS) + MatIcon2 = zo_iconFormat(select(2, GetRecipeIngredientItemInfo(RecipeListIndex, RecipeIndex, MatIndex2)), 28, 28) + MatKeyedItem2 = getKeyedItem(MatLink2) + MatCost2 = 0 + + if MatKeyedItem2 and + MatKeyedItem2.wAvg ~= 0 then + MatCost2 = MatKeyedItem2.wAvg + end + end + + local MatIndex3 = craftingStation.ingredientRows[3].control.ingredientIndex + local MatLink3, MatIcon3, MatKeyedItem3 + local MatCost3 = 0 + + if MatIndex3 then + MatLink3 = GetRecipeIngredientItemLink(RecipeListIndex, RecipeIndex, MatIndex3, LINK_STYLE_BRACKETS) + MatIcon3 = zo_iconFormat(select(2, GetRecipeIngredientItemInfo(RecipeListIndex, RecipeIndex, MatIndex3)), 28, 28) + MatKeyedItem3 = getKeyedItem(MatLink3) + MatCost3 = 0 + + if MatKeyedItem3 and + MatKeyedItem3.wAvg ~= 0 then + MatCost3 = MatKeyedItem3.wAvg + end + end + + local MatIndex4 = craftingStation.ingredientRows[4].control.ingredientIndex + local MatLink4, MatIcon4, MatKeyedItem4 + local MatCost4 = 0 + + if MatIndex4 then + MatLink4 = GetRecipeIngredientItemLink(RecipeListIndex, RecipeIndex, MatIndex4, LINK_STYLE_BRACKETS) + MatIcon4 = zo_iconFormat(select(2, GetRecipeIngredientItemInfo(RecipeListIndex, RecipeIndex, MatIndex4)), 28, 28) + MatKeyedItem4 = getKeyedItem(MatLink4) + MatCost4 = 0 + + if MatKeyedItem4 and + MatKeyedItem4.wAvg ~= 0 then + MatCost4 = MatKeyedItem4.wAvg + end + end + + local MatIndex5 = craftingStation.ingredientRows[5].control.ingredientIndex + local MatLink5, MatIcon5, MatKeyedItem5 + local MatCost5 = 0 + + if MatIndex5 then + MatLink5 = GetRecipeIngredientItemLink(RecipeListIndex, RecipeIndex, MatIndex5, LINK_STYLE_BRACKETS) + MatIcon5 = zo_iconFormat(select(2, GetRecipeIngredientItemInfo(RecipeListIndex, RecipeIndex, MatIndex5)), 28, 28) + MatKeyedItem5 = getKeyedItem(MatLink5) + MatCost5 = 0 + + if MatKeyedItem5 and + MatKeyedItem5.wAvg ~= 0 then + MatCost5 = MatKeyedItem5.wAvg + end + end + + local TotalCost = LIB_LOG:Round(MatCost1 + MatCost2 + MatCost3 + MatCost4 + MatCost5) + + if TotalCost ~= 0 then + local Str_TotalIngredientCost = "" + local Str_Buffer = " " + local GoldIcon = zo_iconFormat("esoui/art/currency/currency_gold.dds", 20, 20) + local PlusIcon = zo_iconFormat("esoui/art/progression/addpoints_up.dds", 32, 32) + local EqualsIcon = zo_iconFormat("/esoui/art/progression/progression_tabicon_passive_inactive.dds", 32, 32) + local Str_TotalCost = zo_strformat(GetString(DD_TOOLTIP_CRAFTING_WAVG), ZO_CommaDelimitNumber(TotalCost), GoldIcon) + + if MatCost1 > 0 then + Str_TotalIngredientCost = MatIcon1 + end + if MatCost2 > 0 then + Str_TotalIngredientCost = Str_TotalIngredientCost..Str_Buffer..PlusIcon..Str_Buffer..MatIcon2 + end + if MatCost3 > 0 then + Str_TotalIngredientCost = Str_TotalIngredientCost..Str_Buffer..PlusIcon..Str_Buffer..MatIcon3 + end + if MatCost4 > 0 then + Str_TotalIngredientCost = Str_TotalIngredientCost..Str_Buffer..PlusIcon..Str_Buffer..MatIcon4 + end + if MatCost5 > 0 then + Str_TotalIngredientCost = Str_TotalIngredientCost..Str_Buffer..PlusIcon..Str_Buffer..MatIcon5 + end + Str_TotalIngredientCost = Str_TotalIngredientCost..Str_Buffer..EqualsIcon..Str_Buffer..Str_TotalCost + + self:inscribeCraftSigilstone(tooltip, RecipeLink, RecipeCount, Str_TotalIngredientCost) + end +end + +function ddDataDaedra:enchantingSigil(self, tooltip) + if not tooltip or + tooltip == ResultControl then + return + end + ResultControl = tooltip + craftingStation = ENCHANTING + + local EnchantingResultItemLink = GetEnchantingResultingItemLink(craftingStation:GetAllCraftingBagAndSlots()) + + local RunePotencySlot = ZO_EnchantingTopLevelRuneSlotContainerPotencyRune + local RunePotencyItemLink = GetItemLink(craftingStation.runeSlots[1]:GetBagAndSlot()) + local RunePotencyKeyedItem = getKeyedItem(RunePotencyItemLink) + local RunePotencyIcon = zo_iconFormat(GetItemInfo(craftingStation.runeSlots[3]:GetBagAndSlot()), 28, 28) + local RunePotencyCost = 0 + local RunePotencyName = GetItemLinkEnchantingRuneName(RunePotencyItemLink) + + if RunePotencyKeyedItem and + RunePotencyKeyedItem.wAvg ~= 0 then + RunePotencyCost = RunePotencyKeyedItem.wAvg + end + + local RuneEssenceSlot = ZO_EnchantingTopLevelRuneSlotContainerEssenceRune + local RuneEssenceItemLink = GetItemLink(RuneEssenceSlot.bagId, RuneEssenceSlot.slotIndex) + local RuneEssenceKeyedItem = getKeyedItem(RuneEssenceItemLink) + local RuneEssenceIcon = zo_iconFormat(GetItemInfo(RuneEssenceSlot.bagId, RuneEssenceSlot.slotIndex), 28, 28) + local RuneEssenceCost = 0 + local RuneEssenceName = GetItemLinkEnchantingRuneName(RuneEssenceItemLink) + + if RuneEssenceKeyedItem and + RuneEssenceKeyedItem.wAvg ~= 0 then + RuneEssenceCost = RuneEssenceKeyedItem.wAvg + end + + local RuneAspectSlot = ZO_EnchantingTopLevelRuneSlotContainerAspectRune + local RuneAspectItemLink = GetItemLink(RuneAspectSlot.bagId, RuneAspectSlot.slotIndex) + local RuneAspectKeyedItem = getKeyedItem(RuneAspectItemLink) + local RuneAspectIcon = zo_iconFormat(GetItemInfo(RuneAspectSlot.bagId, RuneAspectSlot.slotIndex), 28, 28) + local RuneAspectCost = 0 + local RuneAspectName = GetItemLinkEnchantingRuneName(RuneAspectItemLink) + + if RuneAspectKeyedItem and + RuneAspectKeyedItem.wAvg ~= 0 then + RuneAspectCost = RuneAspectKeyedItem.wAvg + end + + local TotalCost = LIB_LOG:Round(RunePotencyCost + RuneEssenceCost + RuneAspectCost) + + if TotalCost ~= 0 then + local Str_TotaGlyphCost = "" + local Str_Buffer = " " + local GoldIcon = zo_iconFormat("esoui/art/currency/currency_gold.dds", 20, 20) + local PlusIcon = zo_iconFormat("esoui/art/progression/addpoints_up.dds", 32, 32) + local EqualsIcon = zo_iconFormat("/esoui/art/progression/progression_tabicon_passive_inactive.dds", 32, 32) + local Str_TotalCost = zo_strformat(GetString(DD_TOOLTIP_CRAFTING_WAVG), ZO_CommaDelimitNumber(TotalCost), GoldIcon) + Str_TotaGlyphCost = RunePotencyIcon..Str_Buffer..PlusIcon..Str_Buffer..RuneEssenceIcon + Str_TotaGlyphCost = Str_TotaGlyphCost..Str_Buffer..PlusIcon..Str_Buffer..RuneAspectIcon + Str_TotaGlyphCost = Str_TotaGlyphCost..Str_Buffer..EqualsIcon..Str_Buffer..Str_TotalCost + + self:inscribeCraftSigilstone(tooltip, EnchantingResultItemLink, 1, Str_TotaGlyphCost) + end +end + +function ddDataDaedra:improvementSigil(self, tooltip) + if not tooltip or + tooltip == ResultControl then + return + end + ResultControl = tooltip + local Panel = SMITHING.improvementPanel + + local ImproveResultItemLink = GetSmithingImprovedItemLink(Panel:GetCurrentImprovementParams(), LINK_STYLE_BRACKETS) + local BoosterLink = GetSmithingImprovementItemLink(GetCraftingInteractionType(), Panel.boosterSlot.index, LINK_STYLE_BRACKETS) + + local BoosterKeyedItem = getKeyedItem(BoosterLink) + local BoosterCount = Panel.spinner.value + local BoosterCost = 0 + + if BoosterKeyedItem and + BoosterKeyedItem.wAvg ~= 0 then + BoosterCost = BoosterKeyedItem.wAvg * BoosterCount + end + + local TotalCost = LIB_LOG:Round(BoosterCost) + + if TotalCost ~= 0 then + local Str_TotalImprovementCost = "" + local Str_Buffer = " " + local GoldIcon = zo_iconFormat("esoui/art/currency/currency_gold.dds", 20, 20) + local PlusIcon = zo_iconFormat("esoui/art/progression/addpoints_up.dds", 32, 32) + local EqualsIcon = zo_iconFormat("/esoui/art/progression/progression_tabicon_passive_inactive.dds", 32, 32) + local Str_TotalCost = zo_strformat(GetString(DD_TOOLTIP_CRAFTING_WAVG), ZO_CommaDelimitNumber(TotalCost), GoldIcon) + local BoosterIcon = BoosterCount..zo_iconFormat(ZO_SmithingTopLevelImprovementPanelSlotContainerBoosterSlotIcon:GetTextureFileName(), 28, 28) + Str_TotalImprovementCost = BoosterIcon..Str_Buffer..EqualsIcon..Str_Buffer..Str_TotalCost + + ZO_SmithingTopLevelImprovementPanelResultTooltip:SetHidden(false) + ZO_SmithingTopLevelImprovementPanelResultTooltip:ClearLines() + Panel:SetupResultTooltip(Panel:GetCurrentImprovementParams()) + self:inscribeCraftSigilstone(tooltip, ImproveResultItemLink, 1, Str_TotalImprovementCost) + end +end + +function ddDataDaedra:creationSigil(self, tooltip) + if not tooltip or + tooltip == ResultControl then + return + end + ResultControl = tooltip + + local Panel = SMITHING.creationPanel + local MatList = Panel.materialList.selectedData + local MatCount = Panel.materialQuantitySpinner.value + local StyleList = Panel.styleList.selectedData + local TraitList = Panel.traitList.selectedData + + + local MatItemLink = GetSmithingPatternMaterialItemLink(MatList.patternIndex, MatList.materialIndex, LINK_STYLE_BRACKETS) + local MatKeyedItem = getKeyedItem(MatItemLink) + local MatCost = 0 + + if MatKeyedItem and + MatKeyedItem.wAvg ~= 0 then + MatCost = MatKeyedItem.wAvg * MatCount + end + + local StyleItemLink = GetSmithingStyleItemLink(StyleList.styleIndex, LINK_STYLE_BRACKETS) + local StyleKeyedItem = getKeyedItem(StyleItemLink) + local StyleCost = 0 + + if StyleKeyedItem and + StyleKeyedItem.wAvg ~= 0 then + StyleCost = StyleKeyedItem.wAvg + end + + local TraitItemLink = GetSmithingTraitItemLink(TraitList.traitIndex, LINK_STYLE_BRACKETS) + local TraitKeyedItem = getKeyedItem(TraitItemLink) + local TraitCost = 0 + + if TraitKeyedItem and + TraitKeyedItem.wAvg ~= 0 then + TraitCost = TraitKeyedItem.wAvg + end + + local ResultItemLink = GetSmithingPatternResultLink(MatList.patternIndex, MatList.materialIndex, MatCount, StyleList.styleIndex, TraitList.traitIndex, LINK_STYLE_BRACKETS) + local TotalCost = LIB_LOG:Round(MatCost + StyleCost + TraitCost) + + if TotalCost ~= 0 then + local Str_TotalSmithingCost = "" + local Str_Buffer = " " + local MatIcon = MatCount..zo_iconFormat(MatList.icon, 28, 28) + local StyleIcon = zo_iconFormat(StyleList.icon, 28, 28) + local TraitIcon = zo_iconFormat(TraitList.icon, 28, 28) + local GoldIcon = zo_iconFormat("esoui/art/currency/currency_gold.dds", 20, 20) + local PlusIcon = zo_iconFormat("esoui/art/progression/addpoints_up.dds", 32, 32) + local EqualsIcon = zo_iconFormat("/esoui/art/progression/progression_tabicon_passive_inactive.dds", 32, 32) + local Str_TotalCost = zo_strformat(GetString(DD_TOOLTIP_CRAFTING_WAVG), ZO_CommaDelimitNumber(TotalCost), GoldIcon) + Str_TotalSmithingCost = MatIcon..Str_Buffer..PlusIcon..Str_Buffer..StyleIcon + + if TraitCost ~= 0 then + Str_TotalSmithingCost = Str_TotalSmithingCost..Str_Buffer..PlusIcon..Str_Buffer..TraitIcon + end + + Str_TotalSmithingCost = Str_TotalSmithingCost..Str_Buffer..EqualsIcon..Str_Buffer..Str_TotalCost + + self:inscribeCraftSigilstone(tooltip, ResultItemLink, 1, Str_TotalSmithingCost) + end +end + +function ddDataDaedra:sigilDesign(tooltip) + local MoC = moc() + local TH = TRADING_HOUSE + + if not tooltip or + not MoC.dataEntry or + not MoC.dataEntry.data or + tooltip == TooltipControl then + return + end + + TooltipControl = tooltip + local Row = MoC.dataEntry.data + local Index = Row.slotIndex + local Stack = Row.stackCount + local ItemLink + + if not tooltip or + tooltip:GetOwningWindow():GetName() == "ZO_SmithingTopLevelCreationPanel" or + tooltip:GetOwningWindow():GetName() == "ZO_ListDialog1" or + tooltip:GetOwningWindow():GetName() == "ZO_InteractWindow" or -- GetQuestRewardItemLink + tooltip:GetOwningWindow():GetName() == "ZO_QuickSlotCircle" or + tooltip:GetOwningWindow():GetName() == "ZO_StablePanel" then + return + end + + if Row then + if Row.lootId then + ItemLink = GetLootItemLink(Row.lootId) + Stack = Row.count + self:inscribeItemSigilstone(tooltip, ItemLink, Stack) + return + + elseif Row.index then + if Row.craftingType then + ItemLink = GetSmithingImprovementItemLink(Row.craftingType, Row.index) + elseif tooltip:GetOwningWindow():GetName() == "ZO_StoreWindow" then + ItemLink = GetStoreItemLink(Row.index) + elseif tooltip:GetOwningWindow():GetName() == "ZO_BuyBack" then + ItemLink = GetBuybackItemLink(Row.index) + elseif tooltip:GetOwningWindow():GetName() == "ZO_QuestReward" then + ItemLink = GetQuestRewardItemLink(Row.index) + end + + self:inscribeItemSigilstone(tooltip, ItemLink, 1) + return + + elseif TRADING_HOUSE:IsAtTradingHouse() and + TH:IsInSearchMode() and + Row.timeRemaining and + Row.timeRemaining > 0 then + ItemLink = GetTradingHouseSearchResultItemLink(Row.slotIndex) + self:inscribeItemSigilstone(tooltip, ItemLink, Stack) + return + + elseif TRADING_HOUSE:IsAtTradingHouse() and + Row.bagId then + ItemLink = GetItemLink(Row.bagId, Row.slotIndex) + self:inscribeItemSigilstone(tooltip, ItemLink, Stack) + return + + elseif TRADING_HOUSE:IsAtTradingHouse() and + TH:IsInListingsMode() then + ItemLink = GetTradingHouseListingItemLink(Row.slotIndex) + self:inscribeItemSigilstone(tooltip, ItemLink, Stack) + return + + elseif Row.bagId then + ItemLink = GetItemLink(Row.bagId, Row.slotIndex) + + if tooltip ~= ComparativeTooltip1 or ComparativeTooltip2 then -- They inherit from ItemTooltip, so we have to rule them out specifically + self:inscribeItemSigilstone(tooltip, ItemLink, Stack) + return + end + + else + return + end + end +end + + +-------------------------------------------------------------------------------------------------- +----------------------------------------- Arcana --------------------------------------------- +-------------------------------------------------------------------------------------------------- + +-- Copyright (c) 2014 Matthew Miller (Mattmillus) +-- +-- Permission is hereby granted, free of charge, to any person +-- obtaining a copy of this software and associated documentation +-- files (the "Software"), to deal in the Software without +-- restriction, including without limitation the rights to use, +-- copy, modify, merge, publish, distribute, sublicense, and/or sell +-- copies of the Software, and to permit persons to whom the +-- Software is furnished to do so, subject to the following +-- conditions: +-- +-- The above copyright notice and this permission notice shall be +-- included in all copies or substantial portions of the Software. + +function ddDataDaedra:linkStatsToChat(itemLink) + if not itemLink or itemLink == "" then return end + itemLink = string.gsub(itemLink, "|H0", "|H1") + local KeyedItem = getKeyedItem(itemLink) + local ChatEditControl = CHAT_SYSTEM.textEntry.editControl + + if not KeyedItem or + not KeyedItem.wAvg or + KeyedItem.wAvg == 0 or + not KeyedItem.Seen or + KeyedItem.Seen == 0 then + return + end + + if not ChatEditControl:HasFocus() then + StartChatInput() + end + + ChatEditControl:InsertText(zo_strformat(GetString(DD_STATS_TO_CHAT), itemLink, KeyedItem.Seen, ZO_CommaDelimitNumber(LIB_LOG:Round(KeyedItem.wAvg)))) +end + +function ddDataDaedra:chatLinkStatsToChat(itemLink, button, control) + if type(itemLink) == "string" and + #itemLink > 0 then + local handled = LINK_HANDLER:FireCallbacks(LINK_HANDLER.LINK_MOUSE_UP_EVENT, itemLink, button, ZO_LinkHandler_ParseLink(itemLink)) + + if not handled then + ClearMenu() + + if (button == 1 and + ZO_PopupTooltip_SetLink) then + ZO_PopupTooltip_SetLink(itemLink) + + elseif (button == 2 and + itemLink ~= "") then + if isKeyedItem(itemLink) then + AddMenuItem(GetString(SI_ITEM_ACTION_DD_STATS_TO_CHAT), function() self:linkStatsToChat(itemLink) end) + end + + AddMenuItem(GetString(SI_ITEM_ACTION_LINK_TO_CHAT), function() ZO_LinkHandler_InsertLink(zo_strformat(SI_TOOLTIP_ITEM_NAME, itemLink)) end) + ShowMenu(control) + end + end + end +end + +function ddDataDaedra:slotControlStatsToChat() + if(SlotControl:GetOwningWindow() == ZO_TradingHouse) then return end + if(ZO_PlayerInventoryBackpack:IsHidden() and + ZO_PlayerBankBackpack:IsHidden() and + ZO_GuildBankBackpack:IsHidden() and + ZO_SmithingTopLevelDeconstructionPanelInventoryBackpack:IsHidden() and + ZO_EnchantingTopLevelInventoryBackpack:IsHidden()) then + return + end + + if(SlotControl:GetParent() ~= ZO_Character) then + SlotControl = SlotControl:GetParent() + end + + local ItemLink = getItemLinkFromSlotControl(SlotControl) + if isKeyedItem(ItemLink) then + zo_callLater(function() AddMenuItem(GetString(SI_ITEM_ACTION_DD_STATS_TO_CHAT), function() ddDataDaedra:linkStatsToChat(ItemLink) end, MENU_ADD_OPTION_LABEL); ShowMenu(self) end, 50) + end +end + +--------------------------------------------------------------------------------------------------- + + +function ddDataDaedra:displayMsg(msgString, boolDebug) + local CODEX = self.dataCairn.codex + local tDebug = CODEX.cDebug.getFunc() + local tNotify = CODEX.cNotify.getFunc() + + if tDebug and + boolDebug then + zo_callLater(function() d(GetString(DD_DEBUG) .. msgString) end, 1000) + + elseif tNotify and + not boolDebug then + zo_callLater(function() d(GetString(DD_MONIKER) .. msgString) end, 1000) + end +end + +function ddDataDaedra:twilightMaiden(guildId) + local DATACAIRN = self.dataCairn + local CODEX = self.dataCairn.codex + local PRICES = self.dataCairn.prices + local numGuilds = GetNumGuilds() + local guildName = GetGuildName(guildId) + local StoreEvents = GetNumGuildEvents(guildId, GUILD_HISTORY_STORE) + local NewSales = 0 + + if guildId > numGuilds then + self:displayMsg(GetString(DD_TWILIGHT_COMPLETE), false) + return + + elseif not numGuilds or + numGuilds < 1 or + not guildName or + guildName == "" or + type(guildName) ~= "string" then + return + end + + local lastScan = DATACAIRN.lastScan[guildName] or 1 + local lastSale = DATACAIRN.lastSale[guildName] or 1 + + for i = 1, StoreEvents, 1 do + local EventType, secsSinceSale, Buyer, Seller, Quantity, itemLink, Price, Tax = GetGuildEventInfo(guildId, GUILD_HISTORY_STORE, i) + local timeStamp = GetTimeStamp() - secsSinceSale + + if EventType == GUILD_EVENT_ITEM_SOLD and + timeStamp > lastScan and + itemLink ~= "" then + if not lastSale or + timeStamp > lastSale then + DATACAIRN.lastSale[guildName] = (timeStamp - secsSinceSale) + end + + NewSales = NewSales + 1 + Quantity = tonumber(Quantity) + Price = tonumber(Price) + + local Quality = parseItemLinkQuality(itemLink) + local SetItem = parseItemLinkSetItem(itemLink) + local Trait = parseItemLinkTrait(itemLink) + local Level, VetRank = parseItemLinkLevel(itemLink) + local ItemId = parseLinkValue(itemLink, 3) + local EnchtId = parseLinkValue(itemLink, 6) + local Element = (Price / Quantity) * Quantity + local Tier1, Tier2, Tier3, Tier4, Tier5, Values + + Values = { + ["Seen"] = 1, + ["RawValue"] = Element, + ["Weight"] = Quantity, + ["wAvg"] = LIB_LOG:RoundTo100s(LIB_LOG:WeightedAverage(Price, Quantity)), + ["PostPrice"] = 0, + } + + Tier5 = { [EnchtId] = Values} + Tier4 = { [VetRank] = Tier5 } + Tier3 = { [Level] = Tier4 } + Tier2 = { [Quality] = Tier3 } + Tier1 = { [Trait] = Tier2 } + + if ItemId and (not PRICES) then + table.insert(PRICES, ItemId, Tier1) + + elseif ItemId and (not PRICES[ItemId]) then + table.insert(PRICES, ItemId, Tier1) + + elseif ItemId and PRICES[ItemId] then + if not PRICES[ItemId][Trait] then + table.insert(PRICES[ItemId], Trait, Tier2) + + elseif PRICES[ItemId][Trait] then + if not PRICES[ItemId][Trait][Quality] then + table.insert(PRICES[ItemId][Trait], Quality, Tier3) + + elseif PRICES[ItemId][Trait][Quality] then + if not PRICES[ItemId][Trait][Quality][Level] then + table.insert(PRICES[ItemId][Trait][Quality], Level, Tier4) + + elseif PRICES[ItemId][Trait][Quality][Level] then + if not PRICES[ItemId][Trait][Quality][Level][VetRank] then + table.insert(PRICES[ItemId][Trait][Quality][Level], VetRank, Tier5) + + elseif PRICES[ItemId][Trait][Quality][Level][VetRank] then + if not PRICES[ItemId][Trait][Quality][Level][VetRank][EnchtId] then + table.insert(PRICES[ItemId][Trait][Quality][Level][VetRank], EnchtId, Values) + + elseif PRICES[ItemId][Trait][Quality][Level][VetRank][EnchtId] then + local record = PRICES[ItemId][Trait][Quality][Level][VetRank][EnchtId] + if record.Seen then + record.Seen = record.Seen + 1 + record.RawValue = record.RawValue + Element + record.Weight = record.Weight + Quantity + record.wAvg = LIB_LOG:RoundTo100s(record.RawValue / record.Weight) + + else + record.Seen = 1 + record.RawValue = Element + record.Weight = Quantity + record.wAvg = LIB_LOG:RoundTo100s(record.RawValue / record.Weight) + record.PostPrice = 0 + end + end + end + end + end + end + end + end + end + + if NewSales > 0 then +-- self:displayMsg(zo_strformat(GetString(DD_TWILIGHT_NEWSALES), ZO_CommaDelimitNumber(NewSales), guildName), false) + end + + DATACAIRN.lastScan[guildName] = GetTimeStamp() +end + +function ddDataDaedra:twilightSummons() + local DATACAIRN = self.dataCairn + local scanInterval = self.dataCairn.codex.cInterval.getFunc() + local numGuilds = GetNumGuilds() + + if self.historyScan then + self:displayMsg("twilightSummons shut down due to historyScan", true) + return + + elseif numGuilds >= 1 then + for guildId = 1, numGuilds, 1 do +-- self:displayMsg("Starting Twilight Maiden for " .. GetGuildName(guildId), true) + self:twilightMaiden(guildId) + end + end + + self:displayMsg(GetString(DD_TWILIGHT_COMPLETE), true) +end + +function ddDataDaedra:checkHistory() + local DATACAIRN = self.dataCairn + local numGuilds = GetNumGuilds() + local scanInterval = self.dataCairn.codex.cInterval.getFunc() + + self.historyScan = true + + if numGuilds >= 1 then + for guildId = 1, numGuilds, 1 do + local guildName = GetGuildName(guildId) + local numEvents = GetNumGuildEvents(guildId, GUILD_HISTORY_STORE) + local lastScan = DATACAIRN.lastScan[guildName] + + RequestGuildHistoryCategoryNewest(guildId, GUILD_HISTORY_STORE) + + if numEvents > 0 then + local secsSinceSale = select(2, GetGuildEventInfo(guildId, GUILD_HISTORY_STORE, numEvents)) + + if DoesGuildHistoryCategoryHaveMoreEvents(guildId, GUILD_HISTORY_STORE) and + (not lastScan or ((GetTimeStamp() - secsSinceSale) > lastScan)) then + self:displayMsg("Requesting guild store history page for " .. guildName, true) + RequestGuildHistoryCategoryOlder(guildId, GUILD_HISTORY_STORE) + zo_callLater(function() self:checkHistory() end, scanInterval * 1000) + return + end + end + end + end + + self.historyScan = false +-- self:displayMsg("Guild history scan complete.", true) +end + + +function ddDataDaedra:hooks() + ZO_PreHook(TRADING_HOUSE, "PostPendingItem", function() savePrice() end) + ZO_PreHook("ZO_InventorySlot_ShowContextMenu", function(rowControl) SlotControl = rowControl; self:slotControlStatsToChat() end) + + ZO_PreHookHandler(ItemTooltip, 'OnUpdate', function(tooltip) self:sigilDesign(tooltip) end) + ZO_PreHookHandler(ItemTooltip, 'OnCleared', function() TooltipControl = nil end) + ZO_PreHookHandler(PopupTooltip, 'OnUpdate', function(tooltip) self:inscribePopupSigilstone(tooltip) end) + ZO_PreHookHandler(PopupTooltip, 'OnCleared', function() PopupControl = nil end) + + ZO_PreHookHandler(ZO_SmithingTopLevelCreationPanelResultTooltip, "OnUpdate", function(tooltip) self:creationSigil(self, tooltip) end) + ZO_PreHookHandler(ZO_SmithingTopLevelCreationPanelResultTooltip, "OnCleared", function() ResultControl = nil end) + + ZO_PreHookHandler(ZO_SmithingTopLevelImprovementPanelResultTooltip, "OnUpdate", function(tooltip) self:improvementSigil(self, tooltip) end) + ZO_PreHookHandler(ZO_SmithingTopLevelImprovementPanelResultTooltip, "OnCleared", function() ResultControl = nil end) + + ZO_PreHookHandler(ZO_EnchantingTopLevelTooltip, "OnUpdate", function(tooltip) self:enchantingSigil(self, tooltip) end) + ZO_PreHookHandler(ZO_EnchantingTopLevelTooltip, "OnCleared", function() ResultControl = nil end) + + ZO_PreHookHandler(ZO_ProvisionerTopLevelTooltip, "OnUpdate", function(tooltip) self:provisionerSigil(self, tooltip) end) + ZO_PreHookHandler(ZO_ProvisionerTopLevelTooltip, "OnCleared", function() ResultControl = nil end) + + ZO_PreHookHandler(ZO_AlchemyTopLevelTooltip, "OnUpdate", function(tooltip) self:alchemySigil(self, tooltip) end) + ZO_PreHookHandler(ZO_AlchemyTopLevelTooltip, "OnCleared", function() ResultControl = nil end) + + + ZO_LinkHandler_OnLinkMouseUp = function(itemLink, button, control) self:chatLinkStatsToChat(itemLink, button, control) end + LINK_HANDLER:RegisterCallback(LINK_HANDLER.LINK_CLICKED_EVENT, function() self:inscribePopupSigilstone(self, PopupTooltip) end) + SMITHING.improvementPanel.spinner:RegisterCallback("OnValueChanged", function(value) ResultControl = nil self:improvementSigil(self, ZO_SmithingTopLevelImprovementPanelResultTooltip) end) + PostFunc = TRADING_HOUSE.SetupPendingPost + TRADING_HOUSE.SetupPendingPost = function() pendListing() end +end + +function ddDataDaedra:liminalBridge() + self.dataCairn = ZO_SavedVars:NewAccountWide("ddDataCairn", SV_VERSION, nil, self.dataCairn, "Global") + + self.dataCairn.codex:init() + TASKMASTER = LIB_LAM2:RegisterAddonPanel("ddCodex", self:mPanel()) + LIB_LAM2:RegisterOptionControls("ddCodex", self:mControls()) + + local scanInterval = self.dataCairn.codex.cInterval.getFunc() + + self:hooks() + + self:displayMsg(GetString(DD_ONLOAD), false) + self.historyScan = true + zo_callLater(function() self:checkHistory() end, scanInterval * 1000) + EVENT_MANAGER:RegisterForUpdate(self.name, (scanInterval * 60 * 1000), function() self:twilightSummons() end) + EVENT_MANAGER:UnregisterForEvent(ADDON_NAME, EVENT_ADD_ON_LOADED) +end + +local function onAddonLoaded(eventCode, addonName) + if addonName == ADDON_NAME then +-- zo_callLater(function() + ddDataDaedra:liminalBridge() +-- end, 1000) + else + return + end +end + + +EVENT_MANAGER:RegisterForEvent(ADDON_NAME, EVENT_ADD_ON_LOADED, onAddonLoaded) +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/ddDataDaedra.txt b/ddDataDaedra.txt new file mode 100644 index 0000000..ad507d3 --- /dev/null +++ b/ddDataDaedra.txt @@ -0,0 +1,34 @@ +## EULA: "This Add-on is not created by, affiliated with or sponsored by ZeniMax Media Inc. or its affiliates. +## The Elder Scrolls® and related logos are registered trademarks or trademarks of ZeniMax Media Inc. in the +## United States and/or other countries. All rights reserved." + +## Title: Deome's DataDaedra +## Description: DataDaedra recommends prices for most items based on recent sales data. Now part of Deome's Addon Suite. +## Author: D. Deome (@deome) - heydeome@gmail.com +## APIVersion: 100014 +## Version 2.0x + +## SavedVariables: ddDataCairn +## OptionalDependsOn: LibAddonMenu-2.0 LibLogos + +Lib\LibStub\LibStub.lua + +Lib\LibAddonMenu-2.0\LibAddonMenu-2.0.lua +Lib\LibAddonMenu-2.0\controls\panel.lua +Lib\LibAddonMenu-2.0\controls\submenu.lua +Lib\LibAddonMenu-2.0\controls\button.lua +Lib\LibAddonMenu-2.0\controls\checkbox.lua +Lib\LibAddonMenu-2.0\controls\colorpicker.lua +Lib\LibAddonMenu-2.0\controls\custom.lua +Lib\LibAddonMenu-2.0\controls\description.lua +Lib\LibAddonMenu-2.0\controls\dropdown.lua +Lib\LibAddonMenu-2.0\controls\editbox.lua +Lib\LibAddonMenu-2.0\controls\header.lua +Lib\LibAddonMenu-2.0\controls\slider.lua +Lib\LibAddonMenu-2.0\controls\texture.lua + +Lib\LibLogos\LibLogos.lua + +i18n\$(language).lua +ddDataDaedra.xml +ddDataDaedra.lua \ No newline at end of file diff --git a/ddDataDaedra.xml b/ddDataDaedra.xml new file mode 100644 index 0000000..ba5cdff --- /dev/null +++ b/ddDataDaedra.xml @@ -0,0 +1,39 @@ +<!------------------------------------------------------------------------------------------------ +----------------------------------------- DataDaedra ----------------------------------------- +--------------------------- by Deome (@deome) - heydeome@gmail.com --------------------------- +local VERSION = "2.0" -- +-- -- +-- -- +--------------------------------------- Deome's License -------------------------------------- +-- -- +-- Copyright (c) 2014, 2015, 2016 D. Deome (@deome) - heydeome@gmail.com -- +-- -- +-- This software is provided 'as-is', without any express or implied -- +-- warranty. In no event will the author(s) be held liable for any damages -- +-- arising from the use of this software. This software, and the ideas, processes, -- +-- functions, and all other intellectual property contained within may not be modified, -- +-- distributed, or used in any other works without the written permission of the -- +-- author. -- +-- -- +-- Any use with permission of author must include the above license and copyright, -- +-- and any other license and copyright notices noted within this software. -- +-- -- +------------------------------------- ZO Obligatory Spam ------------------------------------- +-- -- +-- "This Add-on is not created by, affiliated with or sponsored by ZeniMax -- +-- Media Inc. or its affiliates. The Elder Scrolls® and related logos are registered -- +-- trademarks of ZeniMax Media Inc. in the United States and/or other countries. -- +-- All rights reserved." -- +-- -- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- + + +-------------------------------------------------------------------------------------------------- +------------------------------------------ Fonts --------------------------------------------- +-------------------------------------------------------------------------------------------------> + +<GuiXml> + <Font name="DataDaedraBody" font="$(STONE_TABLET_FONT)|16" /> + <Font name="DataDaedraHeader" font="$(HANDWRITTEN_FONT)|22|soft-shadow-thick" /> +</GuiXml> diff --git a/i18n/DE.lua b/i18n/DE.lua new file mode 100644 index 0000000..3aaef58 --- /dev/null +++ b/i18n/DE.lua @@ -0,0 +1,117 @@ +-------------------------------------------------------------------------------------------------- +--------------------------------- DataDaedra - Local Strings --------------------------------- +--------------------------- by Deome (@deome) - heydeome@gmail.com --------------------------- +-- -- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- + + +-------------------------------------------------------------------------------------------------- +--------------------------- New Strings Requiring Translation -------------------------------- +-------------------------------------------------------------------------------------------------- + +ZO_CreateStringId("DD_MONIKER", "DataDaedra: ") +ZO_CreateStringId("DD_DEBUG", "DataDaedra DEBUG: ") +ZO_CreateStringId("DD_ONLOAD", "Summoned and bound.") +ZO_CreateStringId("DD_EASY", "Deome's Taskmaster preferences loaded.") +ZO_CreateStringId("DD_STATS_TO_CHAT", "DataDaedra - Price Check for <<1>>: <<2>> sales, <<3>>g (wAvg).") +ZO_CreateStringId("DD_TWILIGHT_SUMMON", "Twilight Maiden is updating sales records and prices. Reality may occasionally appear to freeze, but this is perfectly normal.") +ZO_CreateStringId("DD_TWILIGHT_ONLOGIN", "Twilight Maiden will once again update prices when you begin your adventures.") +ZO_CreateStringId("DD_TWILIGHT_OFFLOGIN", "Twilight Maiden will no longer update prices.") +ZO_CreateStringId("DD_TWILIGHT_ONZONE", "Twilight Maiden will also update prices when you travel to new places.") +ZO_CreateStringId("DD_TWILIGHT_OFFZONE", "Twilight Maiden will no longer update prices when traveling to new places.") +ZO_CreateStringId("DD_TWILIGHT_NEWSALES", "Twilight Maiden found <<1>> new sales, out of <<2>>, in <<3>>.") +ZO_CreateStringId("DD_TWILIGHT_COMPLETE", "Twilight Maiden has updated all prices.") +ZO_CreateStringId("DD_TWILIGHT_DISMISS", "Twilight Maiden dismissed, and will not return unless summoned.") +ZO_CreateStringId("DD_TASKMASTER_NAME", "Deome's DataDaedra") +ZO_CreateStringId("DD_TASKMASTER_DISPLAYNAME", "Deome's DataDaedra - Taskmaster") +ZO_CreateStringId("DD_TASKMASTER_AUTHOR", "Deome (@deome) - heydeome@gmail.com") +ZO_CreateStringId("DD_TASKMASTER_COMMANDLINE", "/dd taskmaster") +ZO_CreateStringId("DD_TASKMASTER_ENABLE_TWILIGHT_NAME", "Enable Twilight Maiden") +ZO_CreateStringId("DD_TASKMASTER_ENABLE_TWILIGHT_TIP", "Turn this ON to enable price updates. DD will NOT update prices if this is off.") +ZO_CreateStringId("DD_TASKMASTER_ONLOGIN_TWILIGHT_NAME", "Summon On Login") +ZO_CreateStringId("DD_TASKMASTER_ONLOGIN_TWILIGHT_TIP", "Turn this ON, and the Twilight Maiden will update prices upon login.") +ZO_CreateStringId("DD_TASKMASTER_ONZONE_TWILIGHT_NAME", "Summon On Zone") +ZO_CreateStringId("DD_TASKMASTER_ONZONE_TWILIGHT_TIP", "Turn this ON, and the Twilight Maiden will update prices after each loading screen as well as after login.") +ZO_CreateStringId("DD_TASKMASTER_SUMMON_TWILIGHT_NAME", "Summon") +ZO_CreateStringId("DD_TASKMASTER_SUMMON_TWILIGHT_TIP", "Once summoned, the Twilight Maiden will bind pricing data to your tooltips.") +ZO_CreateStringId("DD_TASKMASTER_EASY_BUTTON_NAME", "EASY") +ZO_CreateStringId("DD_TASKMASTER_EASY_BUTTON_TIP", "Assigns Deome's Preferences to all settings.") +ZO_CreateStringId("DD_TASKMASTER_RESET_NAME", "RESET") +ZO_CreateStringId("DD_TASKMASTER_RESET_TIP", "Wipes all saved variables, including prices and settings. Same as clearing/deleting saved variables file.") +ZO_CreateStringId("DD_TASKMASTER_MAX_SEEN_NAME", "Max (Seen) Sales") +ZO_CreateStringId("DD_TASKMASTER_MAX_SEEN_TIP", "Maximum number of (Seen) sales used to calculate (wAvg) for each item.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_SET_NAME", "Enable Set Item Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_SET_TIP", "Turn this ON, as it will not interfere with anything. Unless, for some reason, you just want to goof off and see wAvg prices for zero value gear.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_PRICING_KEY_WARNING", "Toggling this feature will AUTOMATICALLY reset the price database.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_TRAIT_NAME", "Enable Trait Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_TRAIT_TIP", "Turn this ON, as it will not interfere with item set pricing. Unless, for some reason, you just want to goof off and see wAvg prices for zero value gear.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_QUALITY_NAME", "Enable Item Quality Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_QUALITY_TIP", "Leave this OFF if you only wish to see prices for particular traits or item sets. Crafters will want this OFF when considering trait prices") +ZO_CreateStringId("DD_TASKMASTER_ITEM_LEVEL_NAME", "Enable Item Level Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_LEVEL_TIP", "If, for some reason, you don't want level considered in pricing gear, leave this OFF") +ZO_CreateStringId("DD_TASKMASTER_ITEM_ENCHANT_NAME", "Enable Enchant Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_ENCHANT_TIP", "Leave this OFF if you don't care about pricing for individual enchantments on each piece of gear") +ZO_CreateStringId("DD_TASKMASTER_TRADE_GUILD_NAME", "Primary Trade House") +ZO_CreateStringId("DD_TASKMASTER_TRADE_GUILD_TIP", "Accessing guild stores will default to this guild store. Helps to prevent accidental postings to wrong guild.") +ZO_CreateStringId("DD_TASKMASTER_WAVG_SALE_PRICE_NAME", "Default Listing Price to wAvg") +ZO_CreateStringId("DD_TASKMASTER_WAVG_SALE_PRICE_TIP", "Enable to set listing prices to Weighted Average (wAvg) by default (saved prices will override, if enabled).") +ZO_CreateStringId("DD_TASKMASTER_SAVE_SALE_PRICE_NAME", "Save Listing Prices in Trading House") +ZO_CreateStringId("DD_TASKMASTER_SAVE_SALE_PRICE_TIP", "Enable if you wish DataDaedra to save listing price for items in the Trading House.") +ZO_CreateStringId("DD_TASKMASTER_NOTIFICATIONS_NAME", "Enable Notifications") +ZO_CreateStringId("DD_TASKMASTER_NOTIFICATIONS_TIP", "Leave this ON to receive status updates from scanning and other activities. Turn this OFF to disable chat notifications.") +ZO_CreateStringId("DD_TASKMASTER_DEBUG_NAME", "Toggle Debug Messages") +ZO_CreateStringId("DD_TASKMASTER_DEBUG_TIP", "New DataDaedra versions may have debug messages for developers. Leave this OFF if you don't like message spam.") +ZO_CreateStringId("DD_TASKMASTER_LGH_DEBUG_NAME", "Toggle LGH Debug Messages") +ZO_CreateStringId("DD_TASKMASTER_LGH_DEBUG_TIP", "Separate control for LibGuildHistory debug messages.") +ZO_CreateStringId("DD_TASKMASTER_LGH_DEBUG_WARNING", "IF YOU THINK DATADAEDRA IS DOING NOTHING, turn this ON. Otherwise, you'll want to leave it OFF.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_1_TITLE", "Twilight Maiden") +ZO_CreateStringId("DD_TASKMASTER_NOTES_1_TEXT", "The Twilight Maiden is responsible for updating prices in DataDaedra. Toggle off to prevent updates from running, and use the 'Summon' button to manually restart.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_2_TITLE", "Data Reset") +ZO_CreateStringId("DD_TASKMASTER_NOTES_2_TEXT", "Reset Prices will wipe recorded item prices. This will no longer trigger a data refresh.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_3_TITLE", "Price Update Restrictions") +ZO_CreateStringId("DD_TASKMASTER_NOTES_3_TEXT", "These settings control which sales are used in price updates and how they are considered in price calculations. Restrictions are as loose as possible by default.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_4_TITLE", "Price Characteristics") +ZO_CreateStringId("DD_TASKMASTER_NOTES_4_TEXT", "These settings control how price updates distinguish between items (for the items that use these features).") +ZO_CreateStringId("DD_TASKMASTER_NOTES_4_WARNING", "Any changes will require a data reset, which will occur immediately. You do not need to wait for it to finish before toggling the next setting.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_HEADER_FONT_NAME", "Header Font") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_HEADER_FONT_TIP", "Header font for DataDaedra's tooltip prices.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_BODY_FONT_NAME", "Body Font") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_BODY_FONT_TIP", "Body font for DataDaedra's tooltip prices.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_DETAILS_NAME", "Add Item Details to Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_DETAILS_TIP", "Includes ItemId and other technical item values on all item tooltips. Insanely useful for developers. Will always show if tooltips are working!") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_DETAILS_WARNING", "Note: If you aren't seeing prices on item tooltips, turn this ON. If item details display, then tooltip Bindings are working correctly.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_MULTILINE_NAME", "Use Multi-Line Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_MULTILINE_TIP", "If tooltip prices are spilling onto an additional line, this setting will at least make them tidy.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_SEEN_NAME", "Display (Seen) on Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_SEEN_TIP", "For those who like this stat, just leave this ON. Otherwise, you may turn it OFF to remove (Seen) stats from tooltip prices.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_QUALITY_NAME", "Display Item Quality on Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_QUALITY_TIP", "Turn this feature ON if you would like items to state their quality in addition to quality coloring.") +ZO_CreateStringId("DD_TASKMASTER_MAT_MISER_NAME", "Display MatMiser Tooltips") +ZO_CreateStringId("DD_TASKMASTER_MAT_MISER_TIP", "Enable MatMiser for pricing previews of crafted items, and pricing values for required materials.") +ZO_CreateStringId("DD_TOOLTIP_HEADER", "DataDaedra") +ZO_CreateStringId("DD_TOOLTIP_STAT_SEEN", "<<X:1>><<2>>|r<<3>>") +ZO_CreateStringId("DD_TOOLTIP_STAT_WAVG", "|cFFD700<<1>>|r <<2>> (wAvg)") +ZO_CreateStringId("DD_TOOLTIP_STAT_STACK", "|cFFD700<<1>>|r <<2>> (x<<3>>)") +ZO_CreateStringId("DD_TOOLTIP_CRAFTING_HEADER", "DataDaedra MatMiser") +ZO_CreateStringId("DD_TOOLTIP_CRAFTING_WAVG", "|cFFD700<<1>>|r <<2>>") +ZO_CreateStringId("DD_TOOLTIP_QUALITY", "<<1>> Quality") +ZO_CreateStringId("DD_TOOLTIP_REQVET", "<<1>> <<2>>") +ZO_CreateStringId("DD_TOOLTIP_REQLVL", "LEVEL <<1>>") +ZO_CreateStringId("DD_ICON_BULLET", "esoui/art/miscellaneous/bullet.dds") +ZO_CreateStringId("DD_ICON_GOLD", "esoui/art/currency/currency_gold.dds") +ZO_CreateStringId("SI_ITEM_ACTION_DD_STATS_TO_CHAT", "DataDaedra Stats to Chat") +ZO_CreateStringId("SI_BINDING_NAME_DD_TWILIGHT", "Summon Twilight Maiden") +ZO_CreateStringId("SI_BINDING_NAME_DD_TASKMASTER", "Summon Taskmaster") +ZO_CreateStringId("SI_BINDING_NAME_DD_RESET_PRICES", "Taskmaster: RESET") + + +-------------------------------------------------------------------------------------------------- +----------------------------------------- German --------------------------------------------- +-------------------------------------------------------------------------------------------------- + + + +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/i18n/EN.lua b/i18n/EN.lua new file mode 100644 index 0000000..d003df3 --- /dev/null +++ b/i18n/EN.lua @@ -0,0 +1,121 @@ +-------------------------------------------------------------------------------------------------- +--------------------------------- DataDaedra - Local Strings --------------------------------- +--------------------------- by Deome (@deome) - heydeome@gmail.com --------------------------- +-- -- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- + + +-------------------------------------------------------------------------------------------------- +---------------------------------------- English --------------------------------------------- +-------------------------------------------------------------------------------------------------- + +ZO_CreateStringId("DD_MONIKER", "DataDaedra: ") +ZO_CreateStringId("DD_DEBUG", "DataDaedra DEBUG: ") +ZO_CreateStringId("DD_ONLOAD", "Summoned and bound.") +ZO_CreateStringId("DD_EASY", "Deome's Taskmaster preferences loaded.") +ZO_CreateStringId("DD_STATS_TO_CHAT", "DataDaedra - Price Check for <<1>>: <<2>> sales, <<3>>g (wAvg).") +ZO_CreateStringId("DD_TWILIGHT_SUMMON", "Twilight Maiden is updating sales records and prices. Reality may occasionally appear to freeze, but this is perfectly normal.") +ZO_CreateStringId("DD_TWILIGHT_ONLOGIN", "Twilight Maiden will once again update prices when you begin your adventures.") +ZO_CreateStringId("DD_TWILIGHT_OFFLOGIN", "Twilight Maiden will no longer update prices.") +ZO_CreateStringId("DD_TWILIGHT_ONZONE", "Twilight Maiden will also update prices when you travel to new places.") +ZO_CreateStringId("DD_TWILIGHT_OFFZONE", "Twilight Maiden will no longer update prices when traveling to new places.") +ZO_CreateStringId("DD_TWILIGHT_NEWSALES", "Twilight Maiden found <<1>> new sales in <<2>>.") +ZO_CreateStringId("DD_TWILIGHT_COMPLETE", "Twilight Maiden has updated all prices.") +ZO_CreateStringId("DD_TWILIGHT_DISMISS", "Twilight Maiden dismissed, and will not return unless summoned.") +ZO_CreateStringId("DD_TASKMASTER_NAME", "Deome's DataDaedra") +ZO_CreateStringId("DD_TASKMASTER_DISPLAYNAME", "Deome's DataDaedra - Taskmaster") +ZO_CreateStringId("DD_TASKMASTER_AUTHOR", "Deome (@deome) - heydeome@gmail.com") +ZO_CreateStringId("DD_TASKMASTER_COMMANDLINE", "/dd taskmaster") +ZO_CreateStringId("DD_TASKMASTER_INTERVAL_NAME", "Scan Interval") +ZO_CreateStringId("DD_TASKMASTER_INTERVAL_TIP", "In minutes, select how often DD will check for new sales.") + +ZO_CreateStringId("DD_TASKMASTER_ENABLE_TWILIGHT_NAME", "Enable Twilight Maiden") +ZO_CreateStringId("DD_TASKMASTER_ENABLE_TWILIGHT_TIP", "Turn this ON to enable price updates. DD will NOT update prices if this is off.") +ZO_CreateStringId("DD_TASKMASTER_ONLOGIN_TWILIGHT_NAME", "Summon On Login") +ZO_CreateStringId("DD_TASKMASTER_ONLOGIN_TWILIGHT_TIP", "Turn this ON, and the Twilight Maiden will update prices upon login.") +ZO_CreateStringId("DD_TASKMASTER_ONZONE_TWILIGHT_NAME", "Summon On Zone") +ZO_CreateStringId("DD_TASKMASTER_ONZONE_TWILIGHT_TIP", "Turn this ON, and the Twilight Maiden will update prices after each loading screen as well as after login.") +ZO_CreateStringId("DD_TASKMASTER_SUMMON_TWILIGHT_NAME", "Summon") +ZO_CreateStringId("DD_TASKMASTER_SUMMON_TWILIGHT_TIP", "Once summoned, the Twilight Maiden will bind pricing data to your tooltips.") +ZO_CreateStringId("DD_TASKMASTER_EASY_BUTTON_NAME", "EASY") +ZO_CreateStringId("DD_TASKMASTER_EASY_BUTTON_TIP", "Assigns Deome's Preferences to all settings.") +ZO_CreateStringId("DD_TASKMASTER_RESET_NAME", "RESET") +ZO_CreateStringId("DD_TASKMASTER_RESET_TIP", "Wipes all saved variables, including prices and settings. Same as clearing/deleting saved variables file.") +ZO_CreateStringId("DD_TASKMASTER_MAX_SEEN_NAME", "Max (Seen) Sales") +ZO_CreateStringId("DD_TASKMASTER_MAX_SEEN_TIP", "Maximum number of (Seen) sales used to calculate (wAvg) for each item.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_SET_NAME", "Enable Set Item Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_SET_TIP", "Turn this ON, as it will not interfere with anything. Unless, for some reason, you just want to goof off and see wAvg prices for zero value gear.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_PRICING_KEY_WARNING", "Toggling this feature will AUTOMATICALLY reset the price database.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_TRAIT_NAME", "Enable Trait Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_TRAIT_TIP", "Turn this ON, as it will not interfere with item set pricing. Unless, for some reason, you just want to goof off and see wAvg prices for zero value gear.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_QUALITY_NAME", "Enable Item Quality Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_QUALITY_TIP", "Leave this OFF if you only wish to see prices for particular traits or item sets. Crafters will want this OFF when considering trait prices") +ZO_CreateStringId("DD_TASKMASTER_ITEM_LEVEL_NAME", "Enable Item Level Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_LEVEL_TIP", "If, for some reason, you don't want level considered in pricing gear, leave this OFF") +ZO_CreateStringId("DD_TASKMASTER_ITEM_ENCHANT_NAME", "Enable Enchant Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_ENCHANT_TIP", "Leave this OFF if you don't care about pricing for individual enchantments on each piece of gear") +ZO_CreateStringId("DD_TASKMASTER_TRADE_GUILD_NAME", "Primary Trade House") +ZO_CreateStringId("DD_TASKMASTER_TRADE_GUILD_TIP", "Accessing guild stores will default to this guild store. Helps to prevent accidental postings to wrong guild.") +ZO_CreateStringId("DD_TASKMASTER_WAVG_SALE_PRICE_NAME", "Default Listing Price to wAvg") +ZO_CreateStringId("DD_TASKMASTER_WAVG_SALE_PRICE_TIP", "Enable to set listing prices to Weighted Average (wAvg) by default (saved prices will override, if enabled).") +ZO_CreateStringId("DD_TASKMASTER_SAVE_SALE_PRICE_NAME", "Save Listing Prices in Trading House") +ZO_CreateStringId("DD_TASKMASTER_SAVE_SALE_PRICE_TIP", "Enable if you wish DataDaedra to save listing price for items in the Trading House.") +ZO_CreateStringId("DD_TASKMASTER_NOTIFICATIONS_NAME", "Enable Notifications") +ZO_CreateStringId("DD_TASKMASTER_NOTIFICATIONS_TIP", "Leave this ON to receive status updates from scanning and other activities. Turn this OFF to disable chat notifications.") +ZO_CreateStringId("DD_TASKMASTER_DEBUG_NAME", "Toggle Debug Messages") +ZO_CreateStringId("DD_TASKMASTER_DEBUG_TIP", "New DataDaedra versions may have debug messages for developers. Leave this OFF if you don't like message spam.") +ZO_CreateStringId("DD_TASKMASTER_LGH_DEBUG_NAME", "Toggle LGH Debug Messages") +ZO_CreateStringId("DD_TASKMASTER_LGH_DEBUG_TIP", "Separate control for LibGuildHistory debug messages.") +ZO_CreateStringId("DD_TASKMASTER_LGH_DEBUG_WARNING", "IF YOU THINK DATADAEDRA IS DOING NOTHING, turn this ON. Otherwise, you'll want to leave it OFF.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_1_TITLE", "Twilight Maiden") +ZO_CreateStringId("DD_TASKMASTER_NOTES_1_TEXT", "The Twilight Maiden is responsible for updating prices in DataDaedra. Toggle off to prevent updates from running, and use the 'Summon' button to manually restart.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_2_TITLE", "Data Reset") +ZO_CreateStringId("DD_TASKMASTER_NOTES_2_TEXT", "Reset Prices will wipe recorded item prices. This will no longer trigger a data refresh.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_3_TITLE", "Price Update Restrictions") +ZO_CreateStringId("DD_TASKMASTER_NOTES_3_TEXT", "These settings control which sales are used in price updates and how they are considered in price calculations. Restrictions are as loose as possible by default.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_4_TITLE", "Price Characteristics") +ZO_CreateStringId("DD_TASKMASTER_NOTES_4_TEXT", "These settings control how price updates distinguish between items (for the items that use these features).") +ZO_CreateStringId("DD_TASKMASTER_NOTES_4_WARNING", "Any changes will require a data reset, which will occur immediately. You do not need to wait for it to finish before toggling the next setting.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_HEADER_FONT_NAME", "Header Font") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_HEADER_FONT_TIP", "Header font for DataDaedra's tooltip prices.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_BODY_FONT_NAME", "Body Font") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_BODY_FONT_TIP", "Body font for DataDaedra's tooltip prices.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_DETAILS_NAME", "Add Item Details to Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_DETAILS_TIP", "Includes ItemId and other technical item values on all item tooltips. Insanely useful for developers. Will always show if tooltips are working!") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_DETAILS_WARNING", "Note: If you aren't seeing prices on item tooltips, turn this ON. If item details display, then tooltip Bindings are working correctly.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_MULTILINE_NAME", "Use Multi-Line Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_MULTILINE_TIP", "If tooltip prices are spilling onto an additional line, this setting will at least make them tidy.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_SEEN_NAME", "Display (Seen) on Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_SEEN_TIP", "For those who like this stat, just leave this ON. Otherwise, you may turn it OFF to remove (Seen) stats from tooltip prices.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_QUALITY_NAME", "Display Item Quality on Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_QUALITY_TIP", "Turn this feature ON if you would like items to state their quality in addition to quality coloring.") +ZO_CreateStringId("DD_TASKMASTER_MAT_MISER_NAME", "Display MatMiser Tooltips") +ZO_CreateStringId("DD_TASKMASTER_MAT_MISER_TIP", "Enable MatMiser for pricing previews of crafted items, and pricing values for required materials.") +ZO_CreateStringId("DD_TOOLTIP_HEADER", "DataDaedra") +ZO_CreateStringId("DD_TOOLTIP_STAT_SEEN", "<<X:1>><<2>>|r<<3>>") +ZO_CreateStringId("DD_TOOLTIP_STAT_WAVG", "|cFFD700<<1>>|r <<2>> (wAvg)") +ZO_CreateStringId("DD_TOOLTIP_STAT_STACK", "|cFFD700<<1>>|r <<2>> (x<<3>>)") +ZO_CreateStringId("DD_TOOLTIP_CRAFTING_HEADER", "DataDaedra MatMiser") +ZO_CreateStringId("DD_TOOLTIP_CRAFTING_WAVG", "|cFFD700<<1>>|r <<2>>") +ZO_CreateStringId("DD_TOOLTIP_QUALITY", "<<1>> Quality") +ZO_CreateStringId("DD_TOOLTIP_REQVET", "<<1>> <<2>>") +ZO_CreateStringId("DD_TOOLTIP_REQLVL", "LEVEL <<1>>") +ZO_CreateStringId("DD_ICON_BULLET", "esoui/art/miscellaneous/bullet.dds") +ZO_CreateStringId("DD_ICON_GOLD", "esoui/art/currency/currency_gold.dds") +ZO_CreateStringId("SI_ITEM_ACTION_DD_STATS_TO_CHAT", "DataDaedra Stats to Chat") + + +-------------------------------------------------------------------------------------------------- +-------------------------------------- Keybindings ------------------------------------------- +-------------------------------------------------------------------------------------------------- + +ZO_CreateStringId("SI_BINDING_NAME_DD_TWILIGHT", "Summon Twilight Maiden") +ZO_CreateStringId("SI_BINDING_NAME_DD_TASKMASTER", "Summon Taskmaster") +ZO_CreateStringId("SI_BINDING_NAME_DD_RESET_PRICES", "Taskmaster: RESET") +ZO_CreateStringId("SI_BINDING_NAME_DD_EASYBUTTON", "Taskmaster: EASY") + + +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/i18n/FR.lua b/i18n/FR.lua new file mode 100644 index 0000000..1675525 --- /dev/null +++ b/i18n/FR.lua @@ -0,0 +1,117 @@ +-------------------------------------------------------------------------------------------------- +--------------------------------- DataDaedra - Local Strings --------------------------------- +--------------------------- by Deome (@deome) - heydeome@gmail.com --------------------------- +-- -- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- + + +-------------------------------------------------------------------------------------------------- +--------------------------- New Strings Requiring Translation -------------------------------- +-------------------------------------------------------------------------------------------------- + +ZO_CreateStringId("DD_MONIKER", "DataDaedra: ") +ZO_CreateStringId("DD_DEBUG", "DataDaedra DEBUG: ") +ZO_CreateStringId("DD_ONLOAD", "Summoned and bound.") +ZO_CreateStringId("DD_EASY", "Deome's Taskmaster preferences loaded.") +ZO_CreateStringId("DD_STATS_TO_CHAT", "DataDaedra - Price Check for <<1>>: <<2>> sales, <<3>>g (wAvg).") +ZO_CreateStringId("DD_TWILIGHT_SUMMON", "Twilight Maiden is updating sales records and prices. Reality may occasionally appear to freeze, but this is perfectly normal.") +ZO_CreateStringId("DD_TWILIGHT_ONLOGIN", "Twilight Maiden will once again update prices when you begin your adventures.") +ZO_CreateStringId("DD_TWILIGHT_OFFLOGIN", "Twilight Maiden will no longer update prices.") +ZO_CreateStringId("DD_TWILIGHT_ONZONE", "Twilight Maiden will also update prices when you travel to new places.") +ZO_CreateStringId("DD_TWILIGHT_OFFZONE", "Twilight Maiden will no longer update prices when traveling to new places.") +ZO_CreateStringId("DD_TWILIGHT_NEWSALES", "Twilight Maiden found <<1>> new sales, out of <<2>>, in <<3>>.") +ZO_CreateStringId("DD_TWILIGHT_COMPLETE", "Twilight Maiden has updated all prices.") +ZO_CreateStringId("DD_TWILIGHT_DISMISS", "Twilight Maiden dismissed, and will not return unless summoned.") +ZO_CreateStringId("DD_TASKMASTER_NAME", "Deome's DataDaedra") +ZO_CreateStringId("DD_TASKMASTER_DISPLAYNAME", "Deome's DataDaedra - Taskmaster") +ZO_CreateStringId("DD_TASKMASTER_AUTHOR", "Deome (@deome) - heydeome@gmail.com") +ZO_CreateStringId("DD_TASKMASTER_COMMANDLINE", "/dd taskmaster") +ZO_CreateStringId("DD_TASKMASTER_ENABLE_TWILIGHT_NAME", "Enable Twilight Maiden") +ZO_CreateStringId("DD_TASKMASTER_ENABLE_TWILIGHT_TIP", "Turn this ON to enable price updates. DD will NOT update prices if this is off.") +ZO_CreateStringId("DD_TASKMASTER_ONLOGIN_TWILIGHT_NAME", "Summon On Login") +ZO_CreateStringId("DD_TASKMASTER_ONLOGIN_TWILIGHT_TIP", "Turn this ON, and the Twilight Maiden will update prices upon login.") +ZO_CreateStringId("DD_TASKMASTER_ONZONE_TWILIGHT_NAME", "Summon On Zone") +ZO_CreateStringId("DD_TASKMASTER_ONZONE_TWILIGHT_TIP", "Turn this ON, and the Twilight Maiden will update prices after each loading screen as well as after login.") +ZO_CreateStringId("DD_TASKMASTER_SUMMON_TWILIGHT_NAME", "Summon") +ZO_CreateStringId("DD_TASKMASTER_SUMMON_TWILIGHT_TIP", "Once summoned, the Twilight Maiden will bind pricing data to your tooltips.") +ZO_CreateStringId("DD_TASKMASTER_EASY_BUTTON_NAME", "EASY") +ZO_CreateStringId("DD_TASKMASTER_EASY_BUTTON_TIP", "Assigns Deome's Preferences to all settings.") +ZO_CreateStringId("DD_TASKMASTER_RESET_NAME", "RESET") +ZO_CreateStringId("DD_TASKMASTER_RESET_TIP", "Wipes all saved variables, including prices and settings. Same as clearing/deleting saved variables file.") +ZO_CreateStringId("DD_TASKMASTER_MAX_SEEN_NAME", "Max (Seen) Sales") +ZO_CreateStringId("DD_TASKMASTER_MAX_SEEN_TIP", "Maximum number of (Seen) sales used to calculate (wAvg) for each item.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_SET_NAME", "Enable Set Item Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_SET_TIP", "Turn this ON, as it will not interfere with anything. Unless, for some reason, you just want to goof off and see wAvg prices for zero value gear.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_PRICING_KEY_WARNING", "Toggling this feature will AUTOMATICALLY reset the price database.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_TRAIT_NAME", "Enable Trait Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_TRAIT_TIP", "Turn this ON, as it will not interfere with item set pricing. Unless, for some reason, you just want to goof off and see wAvg prices for zero value gear.") +ZO_CreateStringId("DD_TASKMASTER_ITEM_QUALITY_NAME", "Enable Item Quality Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_QUALITY_TIP", "Leave this OFF if you only wish to see prices for particular traits or item sets. Crafters will want this OFF when considering trait prices") +ZO_CreateStringId("DD_TASKMASTER_ITEM_LEVEL_NAME", "Enable Item Level Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_LEVEL_TIP", "If, for some reason, you don't want level considered in pricing gear, leave this OFF") +ZO_CreateStringId("DD_TASKMASTER_ITEM_ENCHANT_NAME", "Enable Enchant Pricing") +ZO_CreateStringId("DD_TASKMASTER_ITEM_ENCHANT_TIP", "Leave this OFF if you don't care about pricing for individual enchantments on each piece of gear") +ZO_CreateStringId("DD_TASKMASTER_TRADE_GUILD_NAME", "Primary Trade House") +ZO_CreateStringId("DD_TASKMASTER_TRADE_GUILD_TIP", "Accessing guild stores will default to this guild store. Helps to prevent accidental postings to wrong guild.") +ZO_CreateStringId("DD_TASKMASTER_WAVG_SALE_PRICE_NAME", "Default Listing Price to wAvg") +ZO_CreateStringId("DD_TASKMASTER_WAVG_SALE_PRICE_TIP", "Enable to set listing prices to Weighted Average (wAvg) by default (saved prices will override, if enabled).") +ZO_CreateStringId("DD_TASKMASTER_SAVE_SALE_PRICE_NAME", "Save Listing Prices in Trading House") +ZO_CreateStringId("DD_TASKMASTER_SAVE_SALE_PRICE_TIP", "Enable if you wish DataDaedra to save listing price for items in the Trading House.") +ZO_CreateStringId("DD_TASKMASTER_NOTIFICATIONS_NAME", "Enable Notifications") +ZO_CreateStringId("DD_TASKMASTER_NOTIFICATIONS_TIP", "Leave this ON to receive status updates from scanning and other activities. Turn this OFF to disable chat notifications.") +ZO_CreateStringId("DD_TASKMASTER_DEBUG_NAME", "Toggle Debug Messages") +ZO_CreateStringId("DD_TASKMASTER_DEBUG_TIP", "New DataDaedra versions may have debug messages for developers. Leave this OFF if you don't like message spam.") +ZO_CreateStringId("DD_TASKMASTER_LGH_DEBUG_NAME", "Toggle LGH Debug Messages") +ZO_CreateStringId("DD_TASKMASTER_LGH_DEBUG_TIP", "Separate control for LibGuildHistory debug messages.") +ZO_CreateStringId("DD_TASKMASTER_LGH_DEBUG_WARNING", "IF YOU THINK DATADAEDRA IS DOING NOTHING, turn this ON. Otherwise, you'll want to leave it OFF.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_1_TITLE", "Twilight Maiden") +ZO_CreateStringId("DD_TASKMASTER_NOTES_1_TEXT", "The Twilight Maiden is responsible for updating prices in DataDaedra. Toggle off to prevent updates from running, and use the 'Summon' button to manually restart.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_2_TITLE", "Data Reset") +ZO_CreateStringId("DD_TASKMASTER_NOTES_2_TEXT", "Reset Prices will wipe recorded item prices. This will no longer trigger a data refresh.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_3_TITLE", "Price Update Restrictions") +ZO_CreateStringId("DD_TASKMASTER_NOTES_3_TEXT", "These settings control which sales are used in price updates and how they are considered in price calculations. Restrictions are as loose as possible by default.") +ZO_CreateStringId("DD_TASKMASTER_NOTES_4_TITLE", "Price Characteristics") +ZO_CreateStringId("DD_TASKMASTER_NOTES_4_TEXT", "These settings control how price updates distinguish between items (for the items that use these features).") +ZO_CreateStringId("DD_TASKMASTER_NOTES_4_WARNING", "Any changes will require a data reset, which will occur immediately. You do not need to wait for it to finish before toggling the next setting.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_HEADER_FONT_NAME", "Header Font") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_HEADER_FONT_TIP", "Header font for DataDaedra's tooltip prices.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_BODY_FONT_NAME", "Body Font") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_BODY_FONT_TIP", "Body font for DataDaedra's tooltip prices.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_DETAILS_NAME", "Add Item Details to Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_DETAILS_TIP", "Includes ItemId and other technical item values on all item tooltips. Insanely useful for developers. Will always show if tooltips are working!") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_DETAILS_WARNING", "Note: If you aren't seeing prices on item tooltips, turn this ON. If item details display, then tooltip Bindings are working correctly.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_MULTILINE_NAME", "Use Multi-Line Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_MULTILINE_TIP", "If tooltip prices are spilling onto an additional line, this setting will at least make them tidy.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_SEEN_NAME", "Display (Seen) on Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_SEEN_TIP", "For those who like this stat, just leave this ON. Otherwise, you may turn it OFF to remove (Seen) stats from tooltip prices.") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_QUALITY_NAME", "Display Item Quality on Tooltips") +ZO_CreateStringId("DD_TASKMASTER_TOOLTIP_QUALITY_TIP", "Turn this feature ON if you would like items to state their quality in addition to quality coloring.") +ZO_CreateStringId("DD_TASKMASTER_MAT_MISER_NAME", "Display MatMiser Tooltips") +ZO_CreateStringId("DD_TASKMASTER_MAT_MISER_TIP", "Enable MatMiser for pricing previews of crafted items, and pricing values for required materials.") +ZO_CreateStringId("DD_TOOLTIP_HEADER", "DataDaedra") +ZO_CreateStringId("DD_TOOLTIP_STAT_SEEN", "<<X:1>><<2>>|r<<3>>") +ZO_CreateStringId("DD_TOOLTIP_STAT_WAVG", "|cFFD700<<1>>|r <<2>> (wAvg)") +ZO_CreateStringId("DD_TOOLTIP_STAT_STACK", "|cFFD700<<1>>|r <<2>> (x<<3>>)") +ZO_CreateStringId("DD_TOOLTIP_CRAFTING_HEADER", "DataDaedra MatMiser") +ZO_CreateStringId("DD_TOOLTIP_CRAFTING_WAVG", "|cFFD700<<1>>|r <<2>>") +ZO_CreateStringId("DD_TOOLTIP_QUALITY", "<<1>> Quality") +ZO_CreateStringId("DD_TOOLTIP_REQVET", "<<1>> <<2>>") +ZO_CreateStringId("DD_TOOLTIP_REQLVL", "LEVEL <<1>>") +ZO_CreateStringId("DD_ICON_BULLET", "esoui/art/miscellaneous/bullet.dds") +ZO_CreateStringId("DD_ICON_GOLD", "esoui/art/currency/currency_gold.dds") +ZO_CreateStringId("SI_ITEM_ACTION_DD_STATS_TO_CHAT", "DataDaedra Stats to Chat") +ZO_CreateStringId("SI_BINDING_NAME_DD_TWILIGHT", "Summon Twilight Maiden") +ZO_CreateStringId("SI_BINDING_NAME_DD_TASKMASTER", "Summon Taskmaster") +ZO_CreateStringId("SI_BINDING_NAME_DD_RESET_PRICES", "Taskmaster: RESET") + + +-------------------------------------------------------------------------------------------------- +----------------------------------------- French --------------------------------------------- +-------------------------------------------------------------------------------------------------- + + + +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- +-------------------------------------------------------------------------------------------------- \ No newline at end of file