diff --git a/Titan/TitanGame.lua b/Titan/TitanGame.lua index 923007c..2d4d3be 100644 --- a/Titan/TitanGame.lua +++ b/Titan/TitanGame.lua @@ -1,8 +1,8 @@ --[===[ File NAME: TitanGame.lua -DESC: This file contains the 'game version' Titan or Titan. Used to set up libs, locale, ... +DESC: This file contains the 'game version' Titan or TitanClassic. Used to set up libs, locale, ... Different folders are required because Titan used Titan as a name (& folder) for the Classic WoW versions. -The saved variables for Classic WoW are in Titan.lua - not Titan.lua. +The saved variables for Classic WoW are in TitanClassic.lua - not Titan.lua. :DESC --]===] diff --git a/Titan/TitanHistory.lua b/Titan/TitanHistory.lua index 6106877..b3245fc 100644 --- a/Titan/TitanHistory.lua +++ b/Titan/TitanHistory.lua @@ -15,7 +15,7 @@ Green - 'header' - Titan or plugin Highlight - notes. tips. and details --]] Titan_Global.recent_changes = "" -.. TitanUtils_GetGoldText("8.3.0 : 2025/07/15\n") +.. TitanUtils_GetGoldText("8.3.0 : 2025/07/2\n") .. TitanUtils_GetGreenText("Titan : \n") .. TitanUtils_GetHighlightText("" .. "- Major change : \n" diff --git a/Titan/_ATitanDoc.lua b/Titan/_ATitanDoc.lua index d19e186..68d4c7f 100644 --- a/Titan/_ATitanDoc.lua +++ b/Titan/_ATitanDoc.lua @@ -38,7 +38,7 @@ These are routines Titan will keep stable. Changes to these varaibles and routines will be broadcast to developers via Discord at a minimum. Dev : -These are global routines Tian uses. These may change at any time per Titan needs and design. +These are global routines Titan uses. These may change at any time per Titan needs and design. File : Each file has a terse description of its contents. diff --git a/TitanBag/TitanBag.toc b/TitanBag/TitanBag.toc new file mode 100644 index 0000000..2c413f6 --- /dev/null +++ b/TitanBag/TitanBag.toc @@ -0,0 +1,9 @@ +## Interface: 110105, 40402, 11507 +## Title: Titan Panel [|cffeda55fBag|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## IconTexture: Interface\AddOns\TitanBag\TitanBag +## Notes: Adds bag and free slot information to Titan Panel +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: +## Dependencies: Titan +TitanBag.lua diff --git a/TitanBag/TitanBag_Mainline.toc b/TitanBag/TitanBag_Mainline.toc deleted file mode 100644 index dbf89cf..0000000 --- a/TitanBag/TitanBag_Mainline.toc +++ /dev/null @@ -1,9 +0,0 @@ -## Interface: 110107 -## Title: Titan Panel [|cffeda55fBag|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## IconTexture: Interface\AddOns\TitanBag\TitanBag -## Notes: Adds bag and free slot information to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## Dependencies: Titan -TitanBag.lua diff --git a/TitanBag/TitanBag_Vanilla.toc b/TitanBag/TitanBag_Vanilla.toc deleted file mode 100644 index 8ebc4ee..0000000 --- a/TitanBag/TitanBag_Vanilla.toc +++ /dev/null @@ -1,9 +0,0 @@ -## Interface: 11507, 50500 -## Title: Titan Panel [|cffeda55fBag|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## Notes: Adds bag and free slot information to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanBag.lua diff --git a/TitanClock/TitanClock.toc b/TitanClock/TitanClock.toc new file mode 100644 index 0000000..e4b816a --- /dev/null +++ b/TitanClock/TitanClock.toc @@ -0,0 +1,10 @@ +## Interface: 110105, 40402, 11507 +## Title: Titan Panel [|cffeda55fClock|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## IconTexture: Interface\Icons\Spell_Nature_TimeStop +## Notes: Adds a clock to Titan Panel +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: +## OptionalDeps: +## Dependencies: Titan +TitanClock.lua diff --git a/TitanClock/TitanClock_Mainline.toc b/TitanClock/TitanClock_Mainline.toc deleted file mode 100644 index 710ed98..0000000 --- a/TitanClock/TitanClock_Mainline.toc +++ /dev/null @@ -1,10 +0,0 @@ -## Interface: 110107 -## Title: Titan Panel [|cffeda55fClock|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## IconTexture: Interface\Icons\Spell_Nature_TimeStop -## Notes: Adds a clock to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanClock.lua diff --git a/TitanClock/TitanClock_Vanilla.toc b/TitanClock/TitanClock_Vanilla.toc deleted file mode 100644 index fcdb12b..0000000 --- a/TitanClock/TitanClock_Vanilla.toc +++ /dev/null @@ -1,9 +0,0 @@ -## Interface: 11507, 50500 -## Title: Titan Panel [|cffeda55fClock|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## Notes: Adds a clock to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanClock.lua diff --git a/TitanGold/TitanGold.toc b/TitanGold/TitanGold.toc new file mode 100644 index 0000000..5bf41d9 --- /dev/null +++ b/TitanGold/TitanGold.toc @@ -0,0 +1,10 @@ +## Interface: 110105, 40402, 11507 +## Title: Titan Panel [|cffeda55fGold|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## IconTexture: Interface\AddOns\TitanGold\Artwork\TitanGold +## Notes: Keeps track of all gold held by a player's toons on a per server/faction basis. +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: GoldSave +## OptionalDeps: +## Dependencies: Titan +TitanGold.lua diff --git a/TitanGold/TitanGold_Mainline.toc b/TitanGold/TitanGold_Mainline.toc deleted file mode 100644 index d8d594f..0000000 --- a/TitanGold/TitanGold_Mainline.toc +++ /dev/null @@ -1,10 +0,0 @@ -## Interface: 110107 -## Title: Titan Panel [|cffeda55fGold|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## IconTexture: Interface\AddOns\TitanGold\Artwork\TitanGold -## Notes: Keeps track of all gold held by a player's toons on a per server/faction basis. -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: GoldSave -## OptionalDeps: -## Dependencies: Titan -TitanGold.lua diff --git a/TitanGold/TitanGold_Vanilla.toc b/TitanGold/TitanGold_Vanilla.toc deleted file mode 100644 index c3788b1..0000000 --- a/TitanGold/TitanGold_Vanilla.toc +++ /dev/null @@ -1,9 +0,0 @@ -## Interface: 11507, 50500 -## Title: Titan Panel [|cffeda55fGold|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## Notes: Keeps track of all gold held by a player's toons on a per server/faction basis. -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: GoldSave -## OptionalDeps: -## Dependencies: Titan -TitanGold.lua diff --git a/TitanLDB/Artwork/Bag_Blue.blp b/TitanLDB/Artwork/Bag_Blue.blp new file mode 100644 index 0000000..5e7bde1 Binary files /dev/null and b/TitanLDB/Artwork/Bag_Blue.blp differ diff --git a/TitanLDB/Artwork/Bag_Red.blp b/TitanLDB/Artwork/Bag_Red.blp new file mode 100644 index 0000000..31579e7 Binary files /dev/null and b/TitanLDB/Artwork/Bag_Red.blp differ diff --git a/TitanLDB/Artwork/Starter.tga b/TitanLDB/Artwork/Starter.tga new file mode 100644 index 0000000..6a7ddda Binary files /dev/null and b/TitanLDB/Artwork/Starter.tga differ diff --git a/TitanLDB/DevReadMe.lua b/TitanLDB/DevReadMe.lua new file mode 100644 index 0000000..8ec059d --- /dev/null +++ b/TitanLDB/DevReadMe.lua @@ -0,0 +1,156 @@ +--[[ Example +This example is intended to introduce LDB (LibDataBroker) essentials by using an example loosely based on Titan Bag. +A display addon is needed to show this addon. Titan is recommended :). + +This example is intended to be small and light for easy understanding and editting. + +Important notes are denoted with ***: +*** The 'official' LDB spec is here : https://github.com/tekkub/libdatabroker-1-1 . +*** This example is provided as is and without restrictions. +*** Timers are outside the scope of this example. +- Titan built-in addons use timers (AceTimer). +*** Localized strings are outside the scope of this example. +- Titan and built-in plugins use localized strings (AceLocale). + +There are sites that have deeper explanations about addon development such as wowhead or wow wiki (warcraft.wiki.gg). +Please use these or other sites for more detailed addon information. +--]] + +--[[ Folder Structure +This addon folder must be added to the Addon folder to be considered for loading into WoW. +Inside this folder you will notice : +- Artwork folder : icon(s) used by the addon +- libs folder +- .toc files +- one .lua file : for your great idea +- This read me file + +=== .toc +The folder and the .toc files MUST have the same name! +Sort of... the name prior to the underscore(_) must be the same as the folder name. +The name after that (postfix) has meaning to the WoW addon loader. +https://warcraft.wiki.gg/wiki/TOC_format : Contains the full list and A LOT more detail about .toc files + +If your addon is only for Classic Era leave <addon>_Vanilla. Delete (or rename) the other .toc files. + +*** The ## Interface value should match the current interface value of the corresponding WoW version. +If the interface value is higher or lower, WoW will complain that you are running 'out of date' addons. +In the BattleNet app this typically shown below the 'Play' button. +- DragonFlight 10.2.7 is represented without dots - 100207 - in the .toc file. +- Cataclysm 4.4.0 is represented without dots - 40401 - in the .toc file. + +=== Artwork folder: icons and artwork +Anyone can extract the Blizzard UI code and art from WoW. This can be handy to get code examples. +My understanding is any WoW icon can be used within an addon without violating the ToS (Terms of Service). +Wowhead has a searchable list of WoW icons : https://www.wowhead.com/icons + +WoW icons tend to be .blp files. These files are NOT easy to look at or manipulate!! +BLPView (Windows only) from wowinterface is light and easy to view blp files as thumbnails in File Explorer. +You will need to research third party tools to manipulate .blp files. My advice is convert .blp to another format. + +=== libs folder +*** The libraries required for a LDB addon are in the LDB/libs folder. +- WoW does not guarentee the load order of addons. +- If the LDB addon were loaded before the display addon, the loader would throw errors if the libs were not found. +- If the LDB addon requires additional libraries, please include them in libs folder and update the .toc appropriately. + +--]] + +--[[ LDB attributes +The list of required attributes depend on the type of LDB being created. + +Attributes used in this addon: +.type : Required : data source | launcher +.icon : Path to the icon to be used. Place the icon in the addon folder, even if copied from WoW folder. +.label : The label for the addon text +.text : The addon text to display +.OnTooltipShow : The function to use for the tool tip, if any +.OnClick : The function to to handle mouse clicks, if any + + +Available Titan extensions: +.category : The general grouping this addon is in. +- Titan attempts to grab X-Category from the addon TOC first. +- The complete category list is in +- TITAN_PANEL_BUTTONS_PLUGIN_CATEGORY (TitanGlobal.lua) "Built-ins" is reserved for addons that Titan releases! +.version : Addon version shown in Titan menus and config. +- Titan attempts to grab Version from the addon TOC first. +.OnDoubleClick : Implemented by orig dev, not sure this is used by any addon. + +The three data elements are: +- icon +- label +- text + +When any of these are changed, the LDB lib initiates a callback to the display addon. +The display addon registers for these callbacks and creates any frame(s) it needs to display the LDB addon data. +--]] + +--[[ Editing +Before you start changing this example it is HIGHLY recommended to install the following addons: +- BugGrabber : Grabs errors and stores them +- BugSack : The visual part of BugGrabber +- WowLua : Allows you to try Lua code directly in WoW. + +It is recommended you make small changes then check your coding. +When testing just start or /reload WoW. All versions now check and load new files on reload. + +Routines: +GetBagSlotInfo will be replaced by your code. + +Button_OnEvent will be changed to react to any events your addon needs. +- All events registered for should be handled here. +- The display addon is not directly involved in any event handling of this addon. +--]] + +--[[ Code flow within WoW +First step: ==== Starting WoW +Wow will load addons in the Addons folder. +Order is not guaranteed, however dependencies (## Dependencies) are honored. + +When this addon is loaded any code outside the Lua functions will be run. +Examples: +- local VERSION = GetAddOnMetadata(add_on, "Version") will set VERSION +- ... +- Create_Frames is called + +Create_Frames will create the addon frame StarterLDBExample. +- All created frames will be in the global namespace. +- All created frames are forever – they are not touched by the Lua garbage collection. + +Then Create_frames sets the frame OnEvent script handler. This is the only handler required in this addon. + +Then local LDB_Init will initialize the required LDB object. +This routine should be small : +- Set the LDB object +- Set required local variables +- Register for PLAYER_ENTERING_WORLD +- *** DO NOT rely on any saved variables (## SavedVariables) being ready here + +Next: ==== Waiting for WoW +WoW fires a bunch of events as addons are loaded. + +Eventually the game and all addons are loaded and addons receive the PLAYER_ENTERING_WORLD event via the frame script OnEvent. +When processing PLAYER_ENTERING_WORLD, register for additional events your addon requires. +Any saved variables should be ready. + +Next: ==== Still waiting for WoW +The display addon (such as Titan) shows the user requested bars with the user requested addons. + +The addon is now ready for the user. + +Next: ==== Ready to play WoW! Yeah! +The addon is 'idle' until one of the following occur: +- Any registered event is received - OnEvent +- User clicks on this addon - OnClick via display addon +- User mouses over addon - OnTooltipShow via display addon +- User mouse leaves addon - OnLeave via display addon + +Next: ==== +The above steps continues until: +- The user logs out the character or exits WoW or reloads UI - Onhide + +On logout or exit any saved variables are saved to the local system. +No additional actions are required. + +--]] diff --git a/TitanLDB/StarterLDB.lua b/TitanLDB/StarterLDB.lua new file mode 100644 index 0000000..c0ceadb --- /dev/null +++ b/TitanLDB/StarterLDB.lua @@ -0,0 +1,253 @@ +--[[ StarterLDB.lua +By: The Titan Panel Development Team +--]] + + +-- Intended for Intellisense if an IDE supports and is used +-- Lines starting with triple dash are usually Intellisense +---@class Frame WoW frame to get events +---@field obj table For LDB object + +-- ******************************** Constants ******************************* +local ADDON_NAME = ... +-- Set the name we want in the global name space. Ensure the name is unique across all addons. +StarterLDB = {} + +-- NOTE: The 'id' and the 'addon' name are different! +-- Typically they are the same to reduce user confusion but they do not need to be the same. +local id = "LDBStarter"; -- Name the user dhould see in the display addon +local addon = ADDON_NAME -- addon name / folder name / toc name + +-- Localized strings are outside the scope of this example. + +--[[ +The artwork path must start with Interface\\AddOns +Then the name of the plugin +Then any additional folder(s) to your artwork / icons. +Double backslash will for for Windows; forward slash works fine. +--]] +local artwork_path = "Interface/AddOns/TitanLDB/Artwork/" +---@diagnostic disable-next-line: deprecated, undefined-global +local GetAddOnMetadata = C_AddOns.GetAddOnMetadata or GetAddOnMetadata + +-- Get data from the TOC file. +local version = tostring(GetAddOnMetadata(addon, "Version")) or "Unknown" +local author = GetAddOnMetadata(addon, "Author") or "Unknown" +-- NOTE: GetAddOnMetadata expects the addon name : +-- The addon folder name or .toc name needs to be the same. + +-- ******************************** Variables ******************************* +local trace = false -- toggle to show / hide debug statements in this addon + +-- ******************************** Functions ******************************* + +---Output a debug statement to Chat with timestamp. +---@param debug_message string +---@param debug_type string +local function Debug(debug_message, debug_type) + if trace then + local dtype = "" + local time_stamp = "" + local msg = "" + if debug_type == "error" then + dtype = "Error: " + elseif debug_type == "warning" then + dtype = "Warning: " + end + time_stamp = date("%H:%M:%S") .. ": " + + msg = + tostring(addon) .. ": " + .. time_stamp + .. dtype + .. debug_message + + _G["DEFAULT_CHAT_FRAME"]:AddMessage(msg) + else + -- not requested + end + --date("%m/%d/%y %H:%M:%S") +end + +--- Calculate bag space then return text and icon to display +---@return string bagText display text +---@return string icon path to +local function GetBagSlotInfo() + local totalSlots, usedSlots, availableSlots, icon + totalSlots = 0; + usedSlots = 0; + for bag = 0, 4 do + local size = C_Container.GetContainerNumSlots(bag); + if (size and size > 0) then + totalSlots = totalSlots + size; + local free = C_Container.GetContainerNumFreeSlots(bag) + local used = size - free + usedSlots = usedSlots + used; + end + end + availableSlots = totalSlots - usedSlots; + + local i, r = math.modf(availableSlots / 2) + -- Simple example of changing the icon : even blue - odd red + -- wowhead.com/icons was searched and these selected + -- The art was extracted : ../_retail_/BliizardInterfaceArt + -- These were found in /Interface/ICONS of the extracted folder by the name used on wowhead + -- Copied into /Artwork in case Blizz ever renames or removes these icons. + if (r == 0) then + icon = artwork_path .. "Bag_Blue.blp" + else + icon = artwork_path .. "Bag_Red.blp" + end + + local bagText + bagText = format("%d/%d", availableSlots, totalSlots); + + bagText = HIGHLIGHT_FONT_COLOR_CODE .. bagText .. FONT_COLOR_CODE_CLOSE + + return bagText, icon +end + +--- Create the tooltip +---@param tooltip GameTooltip From display addon +local function LDB_OnTooltipShow(tooltip) + tooltip = tooltip or GameTooltip -- for safety + local tt_str = "" + + tt_str = + GREEN_FONT_COLOR_CODE + .. id .. " Info" + .. FONT_COLOR_CODE_CLOSE + tooltip:AddLine(tt_str) + + local text, icon = GetBagSlotInfo() + tt_str = "Available bag slots" + .. " " .. text .. "\n" + .. "\n" .. "Hint: Left-click to open all bags." + + tooltip:AddLine(tt_str) +end + +--- Initialize the LDB obj and initial set up +---@param LDB_frame Frame Addon frame +local function LDB_Init(LDB_frame) + Debug(id .. " Init ...", "normal"); + --[[ + Initialize the Data Broker 'button'. + This is the heart of a LDB plugin. It determines how the display addon is to treat this addon. + + Setting the type is required so the LDB lib and display addon know what to do. See the LDB spec. + + id will be the name Titan uses for the plugin. You can find it in the Titan Config or Titan right click menu. + --]] + + LDB_frame.obj = + LibStub("LibDataBroker-1.1"):NewDataObject(id, -- Name used within Titan + { + type = "data source", -- required + -- LDB spec: The two options are: + -- "data source" - Expected to show some type of info + -- "launcher" - Expected to open another window or perform some action + icon = artwork_path .. "Starter.tga", -- The icon to display on the display addon + label = id, -- label for the text + text = "nyl", -- will be updated as needed by this plugin + OnTooltipShow = function(tooltip) + LDB_OnTooltipShow(tooltip) + end, + OnClick = function(self, button) + if (button == "LeftButton") then + -- Just a simple action to illustrate an LDB addon. + ToggleAllBags(); + elseif (button == "RightButton") then + -- There is no action to take in this example. + --[[ Add code here if your addon needs to do something on right click. + Typically an options menu which is outside the scope of this example. + --]] + end + end, + -- Titan specific!! + category = "Information", -- Otherwise defaults to General : TITAN_PANEL_BUTTONS_PLUGIN_CATEGORY + }) + + -- After player entering world it is safe + -- - to look at any saved variables + -- - register for more events; registering here may cause errors if data is not ready + LDB_frame:RegisterEvent("PLAYER_ENTERING_WORLD"); + + Debug(id .. " Init fini.", "normal"); +end + +--- Update the Bags Data Broker 'button' +---@param LDB_frame Frame +local function LDB_Update(LDB_frame) + local text, icon = GetBagSlotInfo() + LDB_frame.obj.text = text + LDB_frame.obj.icon = icon +end + +--- Parse events registered events and act on them +---@param self Button +---@param event string +---@param ... any +local function Button_OnEvent(self, event, ...) + -- https://warcraft.wiki.gg/wiki/UIHANDLER_OnEvent + + Debug("OnEvent" + .. " " .. tostring(event) .. "" + , "normal") + if (event == "PLAYER_ENTERING_WORLD") then + -- Do any additional set up needed + -- + -- Now that events have settled, register the one(s) we really want. + -- Registering here may reduce churn and possible timing issues wrt data being ready + self:RegisterEvent("BAG_UPDATE"); + + -- Unregister events no longer needed. + -- Good practice to avoid init again - this is fired on /reload + self:UnregisterEvent("PLAYER_ENTERING_WORLD"); + + -- Update the text (bag numbers) + LDB_Update(self) + + end + if event == "BAG_UPDATE" then + LDB_Update(self) + end +end + +--- Create needed frames +local function Create_Frames() + -- general container frame to get events from WoW. + -- The display addon will create frame(s) needed to display data set by this addon. + local window = CreateFrame("Frame", "StarterLDBExample", UIParent) + -- window:Hide() + + -- Set strata as desired + window:SetFrameStrata("FULLSCREEN") + -- https://warcraft.wiki.gg/wiki/Frame_Strata + + window:SetScript("OnEvent", function(self, event, ...) + Button_OnEvent(self, event, ...) + end) + -- https://warcraft.wiki.gg/wiki/API_ScriptObject_SetScript + + -- Using SetScript("OnLoad", does not work + LDB_Init(window) + + -- shamelessly print a load message to chat window + DEFAULT_CHAT_FRAME:AddMessage( + GREEN_FONT_COLOR_CODE + .. addon .. id .. " " .. version + .. " by " + .. FONT_COLOR_CODE_CLOSE + .. "|cFFFFFF00" .. author .. FONT_COLOR_CODE_CLOSE); +end + +Create_Frames() -- Create WoW frames to get events + +--[[ +print("" + .." "..tostring(id).."" + .." "..tostring(version).."" + .." by "..tostring(author).."" + ) +--]] diff --git a/TitanLDB/TitanLDB.toc b/TitanLDB/TitanLDB.toc new file mode 100644 index 0000000..94e79e1 --- /dev/null +++ b/TitanLDB/TitanLDB.toc @@ -0,0 +1,13 @@ +## Interface: 110000 +## Title: StarterLDB +## Notes: LDB example +## Author: Titan Dev Team +## DefaultState: Enabled +## SavedVariables: +## OptionalDeps: +## Dependencies: +## Version: 1.1 +## X-Child-Of: +libs/CallbackHandler-1.0/CallbackHandler-1.0.xml +libs/LibDataBroker-1.1.lua +StarterLDB.lua diff --git a/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua b/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua new file mode 100644 index 0000000..01287bd --- /dev/null +++ b/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua @@ -0,0 +1,202 @@ +--[[ $Id: CallbackHandler-1.0.lua 1298 2022-12-12 15:10:10Z nevcairiel $ ]] +local MAJOR, MINOR = "CallbackHandler-1.0", 8 +local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) + +if not CallbackHandler then return end -- No upgrade needed + +local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end} + +-- Lua APIs +local securecallfunction, error = securecallfunction, error +local setmetatable, rawget = setmetatable, rawget +local next, select, pairs, type, tostring = next, select, pairs, type, tostring + + +local function Dispatch(handlers, ...) + local index, method = next(handlers) + if not method then return end + repeat + securecallfunction(method, ...) + index, method = next(handlers, index) + until not method +end + +-------------------------------------------------------------------------- +-- CallbackHandler:New +-- +-- target - target object to embed public APIs in +-- RegisterName - name of the callback registration API, default "RegisterCallback" +-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback" +-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API. + +function CallbackHandler.New(_self, target, RegisterName, UnregisterName, UnregisterAllName) + + RegisterName = RegisterName or "RegisterCallback" + UnregisterName = UnregisterName or "UnregisterCallback" + if UnregisterAllName==nil then -- false is used to indicate "don't want this method" + UnregisterAllName = "UnregisterAllCallbacks" + end + + -- we declare all objects and exported APIs inside this closure to quickly gain access + -- to e.g. function names, the "target" parameter, etc + + + -- Create the registry object + local events = setmetatable({}, meta) + local registry = { recurse=0, events=events } + + -- registry:Fire() - fires the given event/message into the registry + function registry:Fire(eventname, ...) + if not rawget(events, eventname) or not next(events[eventname]) then return end + local oldrecurse = registry.recurse + registry.recurse = oldrecurse + 1 + + Dispatch(events[eventname], eventname, ...) + + registry.recurse = oldrecurse + + if registry.insertQueue and oldrecurse==0 then + -- Something in one of our callbacks wanted to register more callbacks; they got queued + for event,callbacks in pairs(registry.insertQueue) do + local first = not rawget(events, event) or not next(events[event]) -- test for empty before. not test for one member after. that one member may have been overwritten. + for object,func in pairs(callbacks) do + events[event][object] = func + -- fire OnUsed callback? + if first and registry.OnUsed then + registry.OnUsed(registry, target, event) + first = nil + end + end + end + registry.insertQueue = nil + end + end + + -- Registration of a callback, handles: + -- self["method"], leads to self["method"](self, ...) + -- self with function ref, leads to functionref(...) + -- "addonId" (instead of self) with function ref, leads to functionref(...) + -- all with an optional arg, which, if present, gets passed as first argument (after self if present) + target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]]) + if type(eventname) ~= "string" then + error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2) + end + + method = method or eventname + + local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. + + if type(method) ~= "string" and type(method) ~= "function" then + error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2) + end + + local regfunc + + if type(method) == "string" then + -- self["method"] calling style + if type(self) ~= "table" then + error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2) + elseif self==target then + error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2) + elseif type(self[method]) ~= "function" then + error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2) + end + + if select("#",...)>=1 then -- this is not the same as testing for arg==nil! + local arg=select(1,...) + regfunc = function(...) self[method](self,arg,...) end + else + regfunc = function(...) self[method](self,...) end + end + else + -- function ref with self=object or self="addonId" or self=thread + if type(self)~="table" and type(self)~="string" and type(self)~="thread" then + error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2) + end + + if select("#",...)>=1 then -- this is not the same as testing for arg==nil! + local arg=select(1,...) + regfunc = function(...) method(arg,...) end + else + regfunc = method + end + end + + + if events[eventname][self] or registry.recurse<1 then + -- if registry.recurse<1 then + -- we're overwriting an existing entry, or not currently recursing. just set it. + events[eventname][self] = regfunc + -- fire OnUsed callback? + if registry.OnUsed and first then + registry.OnUsed(registry, target, eventname) + end + else + -- we're currently processing a callback in this registry, so delay the registration of this new entry! + -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency + registry.insertQueue = registry.insertQueue or setmetatable({},meta) + registry.insertQueue[eventname][self] = regfunc + end + end + + -- Unregister a callback + target[UnregisterName] = function(self, eventname) + if not self or self==target then + error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2) + end + if type(eventname) ~= "string" then + error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2) + end + if rawget(events, eventname) and events[eventname][self] then + events[eventname][self] = nil + -- Fire OnUnused callback? + if registry.OnUnused and not next(events[eventname]) then + registry.OnUnused(registry, target, eventname) + end + end + if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then + registry.insertQueue[eventname][self] = nil + end + end + + -- OPTIONAL: Unregister all callbacks for given selfs/addonIds + if UnregisterAllName then + target[UnregisterAllName] = function(...) + if select("#",...)<1 then + error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2) + end + if select("#",...)==1 and ...==target then + error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2) + end + + + for i=1,select("#",...) do + local self = select(i,...) + if registry.insertQueue then + for eventname, callbacks in pairs(registry.insertQueue) do + if callbacks[self] then + callbacks[self] = nil + end + end + end + for eventname, callbacks in pairs(events) do + if callbacks[self] then + callbacks[self] = nil + -- Fire OnUnused callback? + if registry.OnUnused and not next(callbacks) then + registry.OnUnused(registry, target, eventname) + end + end + end + end + end + end + + return registry +end + + +-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it +-- try to upgrade old implicit embeds since the system is selfcontained and +-- relies on closures to work. + diff --git a/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml b/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml new file mode 100644 index 0000000..a5b22a7 --- /dev/null +++ b/TitanLDB/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml @@ -0,0 +1,4 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ +..\FrameXML\UI.xsd"> + <Script file="CallbackHandler-1.0.lua"/> +</Ui> diff --git a/TitanLDB/libs/LibDataBroker-1.1.lua b/TitanLDB/libs/LibDataBroker-1.1.lua new file mode 100644 index 0000000..4182f2e --- /dev/null +++ b/TitanLDB/libs/LibDataBroker-1.1.lua @@ -0,0 +1,90 @@ + +assert(LibStub, "LibDataBroker-1.1 requires LibStub") +assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0") + +local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4) +if not lib then return end +oldminor = oldminor or 0 + + +lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib) +lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {} +local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks + +if oldminor < 2 then + lib.domt = { + __metatable = "access denied", + __index = function(self, key) return attributestorage[self] and attributestorage[self][key] end, + } +end + +if oldminor < 3 then + lib.domt.__newindex = function(self, key, value) + if not attributestorage[self] then attributestorage[self] = {} end + if attributestorage[self][key] == value then return end + attributestorage[self][key] = value + local name = namestorage[self] + if not name then return end + callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self) + callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self) + callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self) + callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self) + end +end + +if oldminor < 2 then + function lib:NewDataObject(name, dataobj) + if self.proxystorage[name] then return end + + if dataobj then + assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table") + self.attributestorage[dataobj] = {} + for i,v in pairs(dataobj) do + self.attributestorage[dataobj][i] = v + dataobj[i] = nil + end + end + dataobj = setmetatable(dataobj or {}, self.domt) + self.proxystorage[name], self.namestorage[dataobj] = dataobj, name + self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj) + return dataobj + end +end + +if oldminor < 1 then + function lib:DataObjectIterator() + return pairs(self.proxystorage) + end + + function lib:GetDataObjectByName(dataobjectname) + return self.proxystorage[dataobjectname] + end + + function lib:GetNameByDataObject(dataobject) + return self.namestorage[dataobject] + end +end + +if oldminor < 4 then + local next = pairs(attributestorage) + function lib:pairs(dataobject_or_name) + local t = type(dataobject_or_name) + assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)") + + local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name + assert(attributestorage[dataobj], "Data object not found") + + return next, attributestorage[dataobj], nil + end + + local ipairs_iter = ipairs(attributestorage) + function lib:ipairs(dataobject_or_name) + local t = type(dataobject_or_name) + assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)") + + local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name + assert(attributestorage[dataobj], "Data object not found") + + return ipairs_iter, attributestorage[dataobj], 0 + end +end diff --git a/TitanLocation/TitanLocation.toc b/TitanLocation/TitanLocation.toc new file mode 100644 index 0000000..f4afce2 --- /dev/null +++ b/TitanLocation/TitanLocation.toc @@ -0,0 +1,10 @@ +## Interface: 110105, 40402, 11507 +## Title: Titan Panel [|cffeda55fLocation|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## IconTexture: Interface\AddOns\TitanLocation\TitanLocation +## Notes: Adds coordinates and location information to Titan Panel +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: +## OptionalDeps: +## Dependencies: Titan +TitanLocation.lua diff --git a/TitanLocation/TitanLocation_Mainline.toc b/TitanLocation/TitanLocation_Mainline.toc deleted file mode 100644 index 0f24b24..0000000 --- a/TitanLocation/TitanLocation_Mainline.toc +++ /dev/null @@ -1,10 +0,0 @@ -## Interface: 110107 -## Title: Titan Panel [|cffeda55fLocation|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## IconTexture: Interface\AddOns\TitanLocation\TitanLocation -## Notes: Adds coordinates and location information to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanLocation.lua diff --git a/TitanLocation/TitanLocation_Vanilla.toc b/TitanLocation/TitanLocation_Vanilla.toc deleted file mode 100644 index 24545fd..0000000 --- a/TitanLocation/TitanLocation_Vanilla.toc +++ /dev/null @@ -1,9 +0,0 @@ -## Interface: 11507, 50500 -## Title: Titan Panel [|cffeda55fLocation|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## Notes: Adds coordinates and location information to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanLocation.lua diff --git a/TitanLootType/TitanLootType.toc b/TitanLootType/TitanLootType.toc new file mode 100644 index 0000000..2b61c9f --- /dev/null +++ b/TitanLootType/TitanLootType.toc @@ -0,0 +1,10 @@ +## Interface: 110105, 40402, 11507 +## Title: Titan Panel [|cffeda55fLootType|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## IconTexture: Interface\AddOns\TitanLootType\TitanLootType +## Notes: Adds group loot and instance difficulty information to Titan Panel +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: +## OptionalDeps: +## Dependencies: Titan +TitanLootType.lua diff --git a/TitanLootType/TitanLootType_Classic.toc b/TitanLootType/TitanLootType_Classic.toc index 3f0d33c..a07b439 100644 --- a/TitanLootType/TitanLootType_Classic.toc +++ b/TitanLootType/TitanLootType_Classic.toc @@ -1,9 +1,9 @@ -## Interface: 11507, 50500 -## Title: Titan Panel [|cffeda55fLootType|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## Notes: Adds group loot and instance difficulty information to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: TitanClassicLootTypeSaved -## OptionalDeps: -## Dependencies: Titan -TitanClassicLootType.xml +## Interface: 11507, 40401 +## Title: Titan Panel [|cffeda55fLootType|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## Notes: Adds group loot and instance difficulty information to Titan Panel +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: TitanClassicLootTypeSaved +## OptionalDeps: +## Dependencies: Titan +TitanClassicLootType.xml diff --git a/TitanLootType/TitanLootType_Mainline.toc b/TitanLootType/TitanLootType_Mainline.toc deleted file mode 100644 index 4ceb153..0000000 --- a/TitanLootType/TitanLootType_Mainline.toc +++ /dev/null @@ -1,10 +0,0 @@ -## Interface: 110107 -## Title: Titan Panel [|cffeda55fLootType|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## IconTexture: Interface\AddOns\TitanLootType\TitanLootType -## Notes: Adds group loot and instance difficulty information to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanLootType.lua diff --git a/TitanPerformance/TitanPerformance.toc b/TitanPerformance/TitanPerformance.toc new file mode 100644 index 0000000..b44c307 --- /dev/null +++ b/TitanPerformance/TitanPerformance.toc @@ -0,0 +1,10 @@ +## Interface: 110105, 40402, 11507 +## Title: Titan Panel [|cffeda55fPerformance|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## IconTexture: Interface\AddOns\TitanPerformance\TitanPerformance +## Notes: Adds FPS and Garbage collection information to Titan Panel +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: +## OptionalDeps: +## Dependencies: Titan +TitanPerformance.lua diff --git a/TitanPerformance/TitanPerformance_Mainline.toc b/TitanPerformance/TitanPerformance_Mainline.toc deleted file mode 100644 index 64ffe84..0000000 --- a/TitanPerformance/TitanPerformance_Mainline.toc +++ /dev/null @@ -1,10 +0,0 @@ -## Interface: 110107 -## Title: Titan Panel [|cffeda55fPerformance|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## IconTexture: Interface\AddOns\TitanPerformance\TitanPerformance -## Notes: Adds FPS and Garbage collection information to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanPerformance.lua diff --git a/TitanPerformance/TitanPerformance_Vanilla.toc b/TitanPerformance/TitanPerformance_Vanilla.toc deleted file mode 100644 index b0e1efe..0000000 --- a/TitanPerformance/TitanPerformance_Vanilla.toc +++ /dev/null @@ -1,9 +0,0 @@ -## Interface: 11507, 50500 -## Title: Titan Panel [|cffeda55fPerformance|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## Notes: Adds FPS and Garbage collection information to Titan Panel -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanPerformance.lua diff --git a/TitanPlugin/Artwork/TitanStarter.tga b/TitanPlugin/Artwork/TitanStarter.tga new file mode 100644 index 0000000..6a7ddda Binary files /dev/null and b/TitanPlugin/Artwork/TitanStarter.tga differ diff --git a/TitanPlugin/DevReadMe.lua b/TitanPlugin/DevReadMe.lua new file mode 100644 index 0000000..c0a438d --- /dev/null +++ b/TitanPlugin/DevReadMe.lua @@ -0,0 +1,539 @@ +--[[ Titan Example with Explanation + +This example will introduce Titan plugin essentials using a Titan plugin loosely based on Titan Bag. +The intent is to clarify what may appear to be a daunting experience. + +We suggest you grab your favorite beverage, read this doc, and relax! +Many of Titan mysteries will be explained. Helping you create a tool your audience will enjoy. 🙂 + +The Titan team and its users are available to answer questions. +The two most used ways are : +- The Titan Discord community - https://discord.gg/e93sxuSPwC +- Curse comments under Titan Panel addon + +Using a text editor with code folding features will make this file easier to read and find information. +Notepad++ is a popular Windows code editor. +Visual Studio Code with a couple extensions can be used to develop WoW addons. +--]] + +--[[ Titan Panel Notes: +- Use the current version of Titan to ensure no errors. +- You may freely use this example for addon development and publish it on WoW addon sites like Curseforge. If published, please add the Titan tag for users. +- The terms addon and plugin are essentially the same. Within this document, plugin is used when the addon is displayed by Titan. +- Titan includes several libraries under the Titan/libs folder. You are free to use these. +If you require additional libraries, please include them within your addon. + +=== Out of Scope Notes: +- A discussion on Lua syntax. A basic understanding of Lua is assumed. +- Timers are outside the scope of this example. See other Titan built-in plugins that use timers (AceTimer) such as TitanClock. +- Localization of strings presented to the user. Titan uses AceLocale; other addons use different schemes. +- Ace library information. Titan includes the Ace libraries it uses - not the entire library. (https://www.wowace.com) +- The API for LDB (LibDataBroker) : (https://github.com/tekkub/libdatabroker-1-1) +- WoW images : Some image type info (https://warcraft.wiki.gg/wiki/API_TextureBase_SetTexture) +--]] + +--[[ “Best Practices” When Creating Your Addon/Plugin +=== Naming Convention +When publishing your addon/plugin please use this naming convention : + +Titan Panel [Name] + +Using this naming format, most Titan users will understand this plugin is intended for Titan Panel. +They should know to contact you first instead of the Titan Panel team. +The Titan team does receive comments and errors from time to time. We usually tell them to contact the plugin developer. + +=== Additional Help For You +A good Lua resource is https://www.lua.org/docs.html +NOTE: WoW uses Lua version 5.1 as its base. +NOTE: WoW does restrict, add, or even remove some Lua features. For example the file routines and many OS routines are not available to an addon. + +There are sites that have deeper explanations about addon development, such as +- Wowhead.com +- Warcraft wiki (Warcraft.Wiki.gg). +Please use these or other sites for more detailed addon and API information. The API information changes over time for several reasons. +--]] + +--[[ Running right now! +The folder and .toc file prefix MUST be the same to be considered for loading into WoW! +See the .toc section under Example Folder Structure. + +=== Steps needed to run this example: +- Unzip this example to your WoW installation: ../World of Warcraft/_retail_/Interface/AddOns +- Ensure the folder name is TitanPlugin +- Start or reload WoW + +That is it! +You should see another Titan Bag icon in any version of WoW you are running. +You are now ready to start changing code. +--]] + +--[[ Example Folder Structure +Inside this folder you will notice : +- Artwork folder : with one .tga file - the icon used by the plugin +- libs : empty, ready for any library routines you may need +- three .toc files +- one .lua file – for your great idea +- a ReadMe file - This file + +=== .toc + +The folder and the .toc files MUST have the same name! +Sort of... the name prior to the underscore(_) must be the same as the folder name. +The part after (postfix) has meaning to the WoW addon loader. +https://warcraft.wiki.gg/wiki/TOC_format : Contains the full list and A LOT more detail about .toc files + +If your addon is only for Classic Era leave <addon>_Vanilla. Delete (or rename) the other .toc files. +Titan uses this TOC method. Notice TitanAmmo and TitanRegen. +This allows Titan to load differently so plugins (built-in or 3rd party) intended for Classic versions can run without change. + +=== .toc internals +NOTE: The ## Interface value should match the current interface value of the corresponding WoW version. +In BattleNet this is typically shown below the 'Play' button. +DragonFlight 10.02.05 is represented without dots - 100207 - in the .toc. + +If the interface value is higher or lower, WoW will complain that you are running 'out of date' addons. + +== .lua + +This is the code for the plugin. + +Titan specific details will be noted and explained within the Lua file. +The comments will specify where names are important. + +The plugin starts with local constants used throughout. +Then local variables; then functions. + +Suggestion is start with Create_Frames routine at the bottom of the file. It is where the magic starts. + +NOTES: +- Titan locale strings (using AceLocale) were left in the code so the example will run as is. Please use your own strings - localized or not. +- Feel free to look at Titan code for Lua examples. +- Any routine marked with ---API can be used by a plugin. +Titan API routines will be maintained and the functionality expected to remain stable. +Any parameter or functionality changes to API will be 'broadcast' on delivery sites and our sites (Discord, our web page). + +=== .tga + +This file is the icon used by the plugin. +This file is also specified in the .registry of the Lua file – detailed later in this doc. +--]] + +--[[ Start editing + +Before you start changing this example, it is HIGHLY recommended to install the following WoW addons: +- BugGrabber : Grabs errors and stores them +- BugSack : The visual part of BugGrabber +- WowLua : This allows you to try Lua code directly in WoW. + +Install a code / text editor. Notepad++ is a very popular editor. + +Small changes are recommended; then test your coding. +When testing, just start or /reload WoW. All versions now check and load new files on reload. + +First Routines to change: +- GetBagData will be replaced by your code. It uses the local function IsProfessionBagID. +- ToggleBags is called from OnClick. This will be replaced by your code that handles mouse clicks. +- CreateMenu will be changed to implement your right click menu, if one is needed. + +Other routines may be modified to implement your idea. + +--]] + +--[[ Addon code flow + +First step: ==== Starting WoW +Wow will load this addon after Titan is loaded. + +NOTE: The .toc states Titan is required [## Dependencies: Titan]. +WoW will load Titan BEFORE this addon. + +Any code outside the Lua functions will be run. +Examples: +- local VERSION = GetAddOnMetadata(add_on, "Version") will run GetAddOnMetadata +- bag_info will be populated +- ... +- Create_Frames is called + +Create_Frames will create the addon frame and name it the string in TITAN_BUTTON. +All created frames will be in the global namespace. +All created frames are forever – they are not touched by the Lua garbage collection. + +Then local OnLoad is called when WoW loads the frame into memory. + +OnLoad does two important things +1) Sets the .registry of the addon - See the .registry comment block +2) Registers for event PLAYER_ENTERING_WORLD + +NOTE: OnLoad should : +- Be small +- NOT assume plugin saved variable data are ready / loaded yet + +Then Create_frames sets the frame scripts for the addon. See Frame Scripts block. + +Next: ==== Waiting for WoW +WoW fires a bunch of events as this and other addons are loaded. + +Eventually the game and all addons are loaded and this plugin receives the PLAYER_ENTERING_WORLD event via the frame script OnEvent. +When processing PLAYER_ENTERING_WORLD, only register for events and access local data this plugin needs. +Do NOT assume saved variables from the registry or any server data are ready. + +Titan also receives the PLAYER_ENTERING_WORLD event. +It is best to assume there is NO guarantee this plugin receives the event before or after Titan! + +Titan then processes its own data, creates Titan bars, registers Titan plugins and LDB addons, and syncs plugin saved variables. +Titan will process any saved variables specified in the .registry of this plugin! + +Next: ==== Still waiting for WoW +Titan shows the user requested bars with the user requested plugins. +OnShow is called by Titan only if the user has requested the plugin to be shown. +It is best to assume any saved variables in .registry are NOT ready until OnShow! + +OnShow now does the processing to set up this plugin and its data properly. +Lastly OnShow needs to call TitanPanelButton_UpdateButton to update the plugin text. +The plugin is now ready for the user. + +Next: ==== Ready to play WoW, Yeah! +The plugin will be 'idle' until one of the following occur: +- Titan needs to (re)display this plugin - TitanPanelButton_UpdateButton +- User selects to show this plugin via Titan Config or menu - TitanPanelButton_UpdateButton +- User changes a plugin option using the Titan plugin menu : TitanPanelButton_UpdateButton +- User clicks on this plugin - Right click .menuTextFunction; any other OnClick +- Any registered event is received - OnEvent +- User mouses over plugin - OnEnter +- User mouse leaves plugin - OnLeave +- A timer or callback calls a plugin routine – AceTimer + +Next: ==== +The above steps continue until: +- User hides the plugin - OnHide +- The user logs out the character or exits WoW or reloads UI - Onhide + +On logout or exit the saved variables are saved to the local system - .registry.savedVariables . +No additional actions are required. + +==== Using OnShow to set up this addon is good practice : +It should: +- Register any events the plugin will react to +- Process any saved variable data such as user options +- Create any timers +- Set the initial plugin - icon, label, text + +This ensures: +- All saved variable data is set and ready +- Less processing if the user never selects the plugin + +==== Using OnHide to clean up is good practice : +It should: +- Unregister any events the plugin registered for +- Cancel any timers +- Cleanup any plugin specific data or objects + +This ensures: +- Less processing after the user clicks Hide + +==== TitanPanelButton_UpdateButton(TITAN_PLUGIN) should be called by this plugin whenever the plugin text could change : +- On processing an event registered for +- On user left click – some action taken +- On user right click – plugin menu + +NOTE: TitanPanelButton_UpdateButton expects label - value pairs (up to 4). +TitanPerformance uses and shows multiple label - value pairs, based on user selection. + +Titan uses ShowLabelText to control showing the label or not. This plugin only returns the expected label(s). + +==== OnEnter and OnLeave +NOTE: The Titan template handles OnEnter and OnLeave to show or hide the tooltip. +Titan calls the specified routine to show the tooltip – .registry.tooltipTextFunction. +Titan expects a formatted string as the return from the function. + +==== Additional saved variables specific to this addon must be handled by this addon and are outside the scope of this example. +Titan Gold is a Titan plugin that has its own saved variables. +--]] + +--[[ Frame Scripts + +The frame scripts are how WoW and Titan interact with this addon. +NOTE: The creation of the frame also creates scripts handlers. This is a bit hidden by the 'inherits' "TitanPanelComboTemplate" below. + local window = CreateFrame("Button", TITAN_BUTTON, f, "TitanPanelComboTemplate") +TitanTemplate.xml defines TitanPanelButtonTemplate as the base for each of its plugin types - Combo / Text / Icon. +TitanPanelButtonTemplate sets OnLoad / OnShow / OnClick / OnEnter / OnLeave where each calls TitanPanelButton_On*. +If the script is overriden in the plugin, it should call the appropriate TitanPanelButton_On* routine as shown below. +In a few cases, the default is not called because the plugin replaces what Titan would do. +TitanPerformance, for example overrides OnClick to create a custom right click menu. + +==== OnShow script : +This is triggered when this plugin (frame) is shown. +Technically : +- WoW calls the now registered plugin frame - TITAN_BUTTON:OnShow() as set in Create_Frames +- Which calls the local OnShow to init the plugin +- Then calls TitanPanelButton_OnShow to update the plugin button text + +==== OnClick script : +This is triggered when this plugin (frame) has been clicked by the mouse. +Technically : +- WoW calls the now registered plugin frame - TITAN_BUTTON:OnClick() as set in Create_Frames +- Which calls the local OnClick to handle left click (or any click / mod-click other than right click) +- Then calls TitanPanelButton_OnClick to handle right click (plugin menu) – see ‘Right Click’ below + +== Right click: +TitanPanelButton_OnClick is called to handle right click generically because it will +- Close any open control frame +- Close any tooltip +- Position the menu relative to the plugin on whatever Titan bar it is on +- Call the plugin routine to create the actual menu content + +The plugin routine here is local CreateMenu. + +The plugin can inform Titan of the routine in one of two ways: +1) Specify in .registry.menuTextFunction - preferred +2) Named routine in the global namespace with the expected name of - TitanPanelRightClickMenu_Prepare<id>Menu +- For this plugin the name would be TitanPanelRightClickMenu_PrepareStarterMenu +Titan will use the registry over the created routine. It will not use both. + +==== OnEnter script : +OnEnter is handled by the Titan template to show the tooltip next to the plugin wherever it may be. +It calls the routine specified in .registry.tooltipTextFunction. +This routine is expected to return a formatted string to be shown inthe tooltip. + +==== OnLeave script : +OnLeave is handled by the Titan template to hide the tooltip. + +==== OnHide script : +This is triggered when this plugin (frame) has been hidden by the user : +- via the plugin menu +- via Titan config +- On exit or logout or /reload +Technically : +- WoW calls the now registered plugin frame - TITAN_BUTTON:OnHide() as set in Create_Frames +- Which calls the local OnHide +The local OnHide should : +- Do any cleanup your plugin needs +- Stop any timers +- Unregister any events +These steps keep processing to a minimum and reduce the chance of errors to the user. + +==== OnEvent script : +This is triggered when any event this plugin (frame) has registered for is fired. +Technically : +- WoW calls the now registered plugin frame - TITAN_BUTTON:OnEvent() as set in Create_Frames +- Which calls the local OnEvent to handle all registered events + +Titan Bag uses PLAYER_ENTERING_WORLD to handle a difference between Retail and Classic versions when opening bags via the addon. + +BAG_UPDATE just updates the text (count) whenever this event is fired. +NOTE: The event also fires when moving items within the bag... +--]] + +--[[ .registry attributes +This is the GUTS of a Titan plugin. The .registry table on the frame contains all the information to register the plugin for display. + +Every plugin registry with an id should appear in Titan > Configuration > Attempts. +Information about the plugin is shown there along with pass / fail. +If the plugin failed to register, the error is shown there. + +NOTE: Titan looks for 3 routines. See .registry Routines. + +Attributes: +.id : Required : must be unique across Titan plugins. If there are duplicates, the first one 'wins'. +.category : The general grouping this plugin is in. + The complete category list is in TITAN_PANEL_BUTTONS_PLUGIN_CATEGORY (TitanGlobal.lua) + "Built-ins" is reserved for plugins that Titan releases. +.version : plugin version shown in menus and config. +.menuText : Used as the title for the right click menu. +.menuTextFunction : See .registry Routines. +.buttonTextFunction : See .registry Routines. +.tooltipTitle : Used as the title for the tool tip +.tooltipTextFunction : See .registry Routines. +.icon : Allowed path to the icon to be used. + It is recommended to store the icon in the plugin folder, even if exists within WoW. +.iconWidth : Best left at 16... +.notes : This is shown in Titan > Config > Plugins when this plugin is selected. +.controlVariables : This list is controls whether the variable is shown. See below. +.savedVariables : These are the variables stored in Titan saved variables. + The initial values are used only if that particular entry is 'new' to + that character (new Titan install, new character, character new to Titan). + If a value is removed then it is removed from the saved variables as Titan is run for each character. + +== .controlVariables +These are used to show or hide 'controls' in the Titan config or Titan right click menu. +- ShowIcon +- ShowLabelText +- ShowColoredText +- DisplayOnRightSide +- ShowRegularText (LDB only) +If true, the control is shown to the user. +If false, the control is not shown to the user. +--]] + +--[[ .registry Saved Variables + +All saved variables for this plugin are listed within savedVariables +- ShowUsedSlots = 1, +- ShowDetailedInfo = false, +- CountProfBagSlots = false, +- ShowIcon = 1, +- ShowLabelText = 1, +- ShowColoredText = 1, +- DisplayOnRightSide = false, +- OpenBags = false, +- OpenBagsClassic = "new_install", + +Plugin variables : +- ShowUsedSlots : Show used versus available slots +- ShowDetailedInfo : Show bag details in the tooltip +- CountProfBagSlots : Whether to include, or not, profession bags in the counts +- OpenBags : Whether to open bags on left click or not. Included due to a taint issue introduced by WoW +- OpenBagsClassic : Used to determine a new install / new character (to Titan or just created) + +Titan uses the below to control display of the plugin : +- ShowIcon : Whether the icon,if specified is shown +- ShowLabelText : Whether the labels returned by buttonTextFunction are shown +- ShowColoredText : Whether the text is 'colored' or not +- DisplayOnRightSide : Put this plugin in the right side of the Titan bar + +ShowColoredText is plugin specific. Generally used to indicate a range such as your bags are empty (green) to nearly full (red). +If the plugin does not need this then please set controlVariables > ShowColoredText to false to prevent the user from seeing +the option and potentially getting confused. + +NOTE: Titan routines have used 1 as true since inception so be careful on 'true checks'. +"if ShowUsedSlots then " *should* work fine if ShowUsedSlots is true or 1 + +=== Where are these saved variables????? +The saved variables are specified in the Titan toc : +## SavedVariables: TitanAll, TitanSettings, TitanSkins, ServerTimeOffsets, ServerHourFormat + +TitanSettings contains all the plugin saved variables. +Titan uses the single table structure to store the saved variables across a user account. +This makes the setup code rather cumbersome and not straight forward - just warning... + +The saved variables can be found here: .../World of Warcraft/_retail_/WTF/Account/(account name>/SavedVariables/Titan.lua +There is a Titan.lua.bak which is the prior save (logout / exit / reload). + +It is HIGHLY recommended opening the saved variables file in an editor with code folding features! +This file could be quite large with many lines. +I have 20+ characters on one server. Even though I do not use many addons, I do test with addons on some characters. +A plugin such as Titan Panel [Reputation] can create 100+ plugins. My file is nearly 90,000 lines long! + +Say we want to find a character named Embic on Staghelm being used for testing to examine the saved variables. +This would under +TitanSettings = { + ["Players"] = { + ["Embic@Staghelm"] = { + ["Panel"] = { + -- Holds all the Titan settings for this character + } + ["BarVars"] = { + -- Holds all the Titan bar settings for this character + } + ["Plugins"] = { + -- Each registered plugin will be here + ["Starter"] = { + ["notes"] = "Adds bag and free slot information to Titan Panel.\n", + ["menuTextFunction"] = nil, + ["id"] = "Starter", + ["menuText"] = "Bag", + ["iconWidth"] = 16, + ["savedVariables"] = { + ["ShowColoredText"] = 1, + ["CustomLabel3Text"] = "", + ["ShowIcon"] = 1, + ["OpenBags"] = false, + ["CustomLabel3TextShow"] = false, + ["CustomLabelTextShow"] = false, + ["CustomLabel4Text"] = "", + ["CustomLabel2Text"] = "", + ["OpenBagsClassic"] = "new_install", + ["ShowLabelText"] = 1, + ["CustomLabel4TextShow"] = false, + ["CountProfBagSlots"] = false, + ["ShowUsedSlots"] = 1, + ["DisplayOnRightSide"] = false, + ["ShowDetailedInfo"] = false, + ["CustomLabel2TextShow"] = false, + ["CustomLabelText"] = "", + }, + ["controlVariables"] = { + ["DisplayOnRightSide"] = true, + ["ShowColoredText"] = true, + ["ShowIcon"] = true, + ["ShowLabelText"] = true, + }, + ["version"] = "1.0.0", + ["category"] = "Information", + ["buttonTextFunction"] = nil , + ["tooltipTextFunction"] = nil , + ["icon"] = "Interface\\AddOns\\TitanPlugin\\Artwork\\TitanStarter", + ["tooltipTitle"] = "Bags Info", + }, + } + ["Adjust"] = { + -- Holds offsets for frames the user may adjust - Retail and Classic have different list of frames + } + ["Register"] = { + -- Holds data as each plugin and LDB is attempted to be registered. + -- There may be helpful debug data here under your plugin name if the plugin is not shown as expected. + -- Titan > Configuration > Attempts shows some of this data, including errors. + } + +NOTES: +- "Starter" index under Plugins is also .registry.id !! +- This lists the last saved contents of .registry - NOT what is in memory! +- This file contains all the tables specified in the Titan .toc file. + +--]] +--[[ .registry Routines + +Titan looks for 3 routines specified in the .registry : +- .buttonTextFunction : Routine that updates the plugin text. +- .tooltipTextFunction : Routine that generates the tool tip text. +- .menuTextFunction : Routine that creates the options for the menu (right click) OR "TitanPanelRightClickMenu_Prepare"<id>"Menu" + +.menuTextFunction : This is the routine called by Titan on right click so the plugin can create its menu. + 1) This is the newer, preferred method which makes the options menu routine explicit (changed 2024 Feb). + If found, this will be used over the older method - both will not be used. + NOTE: Routine can be specified : + --- As a string, it MUST be in the global namespace. Strings were the only method for a long time. + --- As a function, it may be in the global namespace but could be local. This example uses a local routine which is preferred. + + 2) The older method is still supported! + Titan builds the expected routine name as "TitanPanelRightClickMenu_Prepare"<id>"Menu". + In this example it would be : TitanPanelRightClickMenu_PrepareStarterMenu + +.buttonTextFunction : This is called whenever the button is to be updated. + This is called from within the plugin and from Titan by calling TitanPanelButton_UpdateButton(TITAN_PLUGIN) . + Titan will usually return "<?>" if the routine dies. + If you need to see the error, search for this attribute in the Titan folder and uncomment the print of the error message. + This may generate a LOT of messages! +.tooltipTextFunction : This is called when the mouse enters the plugin frame is triggered. + The Titan templates set the OnEnter script for the plugin frame. + On a tooltip error, Titan will usually show part of the error in the tool tip. + If you need to see the full error, search for this attribute in the Titan folder and uncomment the print of the error message. + +NOTE: The .registry routines are called securely using pcall to protect Titan. +These routines are expected to have NO parameters. Handling parameters was not implemented in any version of Titan. +--]] +--[[ Special Icons and Artwork + +Anyone can extract the Blizzard UI code and art from WoW. This can be handy to get code examples. +And to grab icons to use for a plugin. My understanding is any icon can be used within WoW without violating the ToS. +WoW icons tend to be .blp files. These files are NOT easy to look at or manipulate!! +You will need to research third party tools to manipulate .blp files. +BLPView (Windows only) from wowinterface is light and easy to view blp files as thumbnail pics in File Explorer. + +==== Extracting art and code +Add the switch -console when starting WoW. +In BattleNet click the Settings (next to Play) then Game Settintgs. Add as an additional command line argument. + +Start WoW but stay on the character screen. +Hit the ~ (tilde) key to open a text console which will appear from the top of the screen. +Type exportInterfaceFiles (can tab to auto fill) with parameter code or art +exportInterfaceFiles code +exportInterfaceFiles art + +These must be run separately. Code should take a second or so; art may take some time and appear to hang the game. + +For retail, the result will be here : +.../World of Warcraft/_retail_/BlizzardInterfaceCode +.../World of Warcraft/_retail_/BlizzardInterfaceArt +--]] + diff --git a/TitanPlugin/TitanPlugin.toc b/TitanPlugin/TitanPlugin.toc new file mode 100644 index 0000000..7b177cd --- /dev/null +++ b/TitanPlugin/TitanPlugin.toc @@ -0,0 +1,9 @@ +## Interface: 110000 +## Title: Titan Starter +## Version: 1.0.0 +## Notes: Adds bag and free slot information to Titan Panel +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: +## Dependencies: Titan +## DefaultState: Enabled +TitanStarter.lua diff --git a/TitanPlugin/TitanStarter.lua b/TitanPlugin/TitanStarter.lua new file mode 100644 index 0000000..c8edc4b --- /dev/null +++ b/TitanPlugin/TitanStarter.lua @@ -0,0 +1,569 @@ +---@diagnostic disable: duplicate-set-field +--[[ +-- ************************************************************************** +-- * TitanStarter.lua +-- * +-- * By: The Titan Panel Development Team +-- ************************************************************************** +--]] +-- ******************************** Constants ******************************* +local add_on = ... +local _G = _G --getfenv(0); +local artwork_path = "Interface\\AddOns\\TitanPlugin\\Artwork\\" +-- NOTE: The plugin id needs be unique across Titan plugins +-- It does not need to match the addon id. +local TITAN_PLUGIN = "Starter" +-- NOTE: The convention is TitanPanel<id>Button +local TITAN_BUTTON = "TitanPanel" .. TITAN_PLUGIN .. "Button" +local VERSION = C_AddOns.GetAddOnMetadata(add_on, "Version") + +local TITAN_BAG_THRESHOLD_TABLE = { + Values = { 0.5, 0.75, 0.9 }, + Colors = { HIGHLIGHT_FONT_COLOR, NORMAL_FONT_COLOR, ORANGE_FONT_COLOR, RED_FONT_COLOR }, +} + +-- ******************************** Variables ******************************* +local L = LibStub("AceLocale-3.0"):GetLocale(TITAN_ID, true) + +local bag_info = { -- itemType : warcraft.wiki.gg/wiki/itemType + [1] = -- Soul bag + { color = { r = 0.96, g = 0.55, b = 0.73 } }, -- PINK + [2] = -- HERBALISM = + { color = { r = 0, g = 1, b = 0 } }, -- GREEN + [3] = -- ENCHANTING = + { color = { r = 0, g = 0, b = 1 } }, -- BLUE + [4] = -- ENGINEERING = + { color = { r = 1, g = 0.49, b = 0.04 } }, -- ORANGE + [5] = -- JEWELCRAFTING = + { color = { r = 1, g = 0, b = 0 } }, -- RED + [6] = -- MINING = + { color = { r = 1, g = 1, b = 1 } }, -- WHITE + [7] = -- LEATHERWORKING = + { color = { r = 0.78, g = 0.61, b = 0.43 } }, -- TAN + [8] = -- INSCRIPTION = + { color = { r = 0.58, g = 0.51, b = 0.79 } }, -- PURPLE + [9] = -- FISHING = + { color = { r = 0.41, g = 0.8, b = 0.94 } }, -- LIGHT_BLUE + [10] = -- COOKING = + { color = { r = 0.96, g = 0.55, b = 0.73 } }, -- PINK + -- These are Classic arrow or bullet bags + [22] = -- Classic arrow + { color = { r = 1, g = .4, b = 0 } }, -- copper + [23] = -- Classic bullet + { color = { r = 0.8, g = 0.8, b = 0.8 } }, -- silver +} + +local trace = false -- true / false Make true when debug output is needed. + +local MIN_BAGS = 0 +local MAX_BAGS = Constants.InventoryConstants.NumBagSlots +local bag_data = {} -- to hold the user bag data + +-- ******************************** Functions ******************************* +---@diagnostic disable-next-line: deprecated +local GetInstant = C_Item.GetItemInfoInstant or GetItemInfoInstant + +local function IsProfessionBagID(slot) + -- The info needed is available using GetItemInfoInstant; only the bag / item id is required + -- itemType : warcraft.wiki.gg/wiki/itemType + local res = false + local style = 0 + local info, itemId, itemType, itemSubType, itemEquipLoc, itemTexture, classID, subclassID + local inv_id = C_Container.ContainerIDToInventoryID(slot) + + if inv_id == nil then + -- Only works on bag and bank bags NOT backpack! + else + info = GetInventoryItemLink("player", inv_id) + itemId, itemType, itemSubType, itemEquipLoc, itemTexture, classID, subclassID = GetInstant(info) + style = subclassID + + if classID == 1 then -- is a container / bag + if subclassID >= 1 then + -- profession bag of some type [2 - 10] Jan 2024 (DragonFlight / Wrath / Classic Era) + -- OR soul bag [1] + res = true + else + -- is a arrow or bullet; only two options + end + elseif classID == 6 then -- is a 'projectile' holder + res = true + -- is a ammo bag or quiver; only two options + elseif classID == 11 then -- is a 'quiver'; Wrath and CE + res = true + -- is a ammo pouch or quiver; only two options + style = subclassID + 20 -- change to get local color for name + else + -- not a bag + end + end + + if trace then + TitanPluginDebug(TITAN_PLUGIN, "T isP:" + .. " " .. tostring(res) .. "" + .. " " .. tostring(style) .. "" + .. " " .. tostring(itemId) .. "" + .. " " .. tostring(classID) .. "" + .. " " .. tostring(subclassID) .. "" + .. " " .. tostring(inv_id) .. "" + ) + end + + return res, style +end + +local function ToggleBags() + if TitanGetVar(TITAN_PLUGIN, "OpenBags") then + ToggleAllBags() + else + end +end + +--[[ +Where the magic happens! +It is good practice - and good memory - to document the 'why' the code does what it does. +And give details that are not obvious to the reader who did not write the code. +--]] +local function GetBagData(id) + --[[ + The bag name is not always available when player entering world + Grabbing the total slots is available though to determine if a bag exists. + The user may see bag name as UNKNOWN until an event triggers a bag check AND the name is available. + --]] + + local total_slots = 0 + local total_free = 0 + local total_used = 0 + + local count_prof = TitanGetVar(TITAN_PLUGIN, "CountProfBagSlots") + + for bag_slot = MIN_BAGS, MAX_BAGS do -- assuming 0 (Backpack) will not be a profession bag + local slots = C_Container.GetContainerNumSlots(bag_slot) + + -- Ensure a blank structure exists + bag_data[bag_slot] = { + has_bag = false, + name = "", + maxi_slots = 0, + free_slots = 0, + used_slots = 0, + style = "", + color = "", + } + + if slots > 0 then + bag_data[bag_slot].has_bag = true + + local bag_name = (C_Container.GetBagName(bag_slot) or UNKNOWN) + bag_data[bag_slot].name = bag_name + bag_data[bag_slot].maxi_slots = slots + + local free = C_Container.GetContainerNumFreeSlots(bag_slot) + local used = slots - free + bag_data[bag_slot].free_slots = free + bag_data[bag_slot].used_slots = used + + -- some info is not known until the name is available... + -- The API requires name to get the bag ID. + local bag_type = "none" + local color = { r = 0, g = 0, b = 0 } -- black (should never be used...) + + -- Jan 2024 : Moved away from named based to an id based. Allows name to come later from server + local is_prof_bag, style = IsProfessionBagID(bag_slot) + + if is_prof_bag then + color = bag_info[style].color + bag_type = "profession" + else + bag_type = "normal" + end + bag_data[bag_slot].style = bag_type + bag_data[bag_slot].color = color + + -- add to total + if bag_data[bag_slot].style == "profession" then + if count_prof then + total_slots = total_slots + slots + total_free = total_free + free + total_used = total_used + used + else + -- ignore in totals + end + else + total_slots = total_slots + slots + total_free = total_free + free + total_used = total_used + used + end + else + bag_data[bag_slot].has_bag = false + end + + if trace then + TitanPluginDebug(TITAN_PLUGIN, "T info" + .. " " .. tostring(bag_slot) .. "" + .. " ?:" .. tostring(bag_data[bag_slot].has_bag) .. "" + .. " max: " .. tostring(bag_data[bag_slot].maxi_slots) .. "" + .. " used: " .. tostring(bag_data[bag_slot].used_slots) .. "" + .. " free: " .. tostring(bag_data[bag_slot].free_slots) .. "" + .. " type: " .. tostring(bag_data[bag_slot].style) .. "" + .. " count: " .. tostring(count_prof) .. "" + .. " '" .. tostring(bag_data[bag_slot].name) .. "'" + ) + end + end + + bag_data.total_slots = total_slots + bag_data.total_free = total_free + bag_data.total_used = total_used + + local bagText = "" + if (TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots")) then + bagText = format(L["TITAN_BAG_FORMAT"], total_used, total_slots); + else + bagText = format(L["TITAN_BAG_FORMAT"], total_free, total_slots); + end + + local bagRichText = "" + if (TitanGetVar(TITAN_PLUGIN, "ShowColoredText")) then + local color = "" + color = TitanUtils_GetThresholdColor(TITAN_BAG_THRESHOLD_TABLE, total_used / total_slots); + bagRichText = TitanUtils_GetColoredText(bagText, color); + else + bagRichText = TitanUtils_GetHighlightText(bagText); + end + + bagRichText = + bagRichText --..bagRichTextProf[1]..bagRichTextProf[2]..bagRichTextProf[3]..bagRichTextProf[4]..bagRichTextProf[5]; + + return L["TITAN_BAG_BUTTON_LABEL"], bagRichText +end + +-- Create the right click menu for this plugin +local function CreateMenu() + if trace then + TitanPluginDebug(TITAN_PLUGIN, "TS event" + .. " " .. tostring(TitanPanelRightClickMenu_GetDropdownLevel()) .. "" + .. " '" .. tostring(TitanPanelRightClickMenu_GetDropdMenuValue()) .. "'" + ) + end + local info = {} + -- level 2 + if TitanPanelRightClickMenu_GetDropdownLevel() == 2 then + if TitanPanelRightClickMenu_GetDropdMenuValue() == "Options" then + TitanPanelRightClickMenu_AddTitle(L["TITAN_PANEL_OPTIONS"], TitanPanelRightClickMenu_GetDropdownLevel()) + info = {}; + info.text = L["TITAN_BAG_MENU_SHOW_USED_SLOTS"]; + info.func = function() + TitanSetVar(TITAN_PLUGIN, "ShowUsedSlots", 1); + TitanPanelButton_UpdateButton(TITAN_PLUGIN); + end + info.checked = TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots"); + TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); + + info = {}; + info.text = L["TITAN_BAG_MENU_SHOW_AVAILABLE_SLOTS"]; + info.func = function() + TitanSetVar(TITAN_PLUGIN, "ShowUsedSlots", nil); + TitanPanelButton_UpdateButton(TITAN_PLUGIN); + end + info.checked = TitanUtils_Toggle(TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots")); + TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); + + info = {}; + info.text = L["TITAN_BAG_MENU_SHOW_DETAILED"]; + info.func = function() + TitanToggleVar(TITAN_PLUGIN, "ShowDetailedInfo"); + end + info.checked = TitanGetVar(TITAN_PLUGIN, "ShowDetailedInfo"); + TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); + + info = {}; + info.text = L["TITAN_BAG_MENU_OPEN_BAGS"] + info.func = function() + TitanToggleVar(TITAN_PLUGIN, "OpenBags") + end + info.checked = TitanGetVar(TITAN_PLUGIN, "OpenBags"); + TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); + end + return + end + + -- level 1 + TitanPanelRightClickMenu_AddTitle(TitanPlugins[TITAN_PLUGIN].menuText); + + info = {}; + info.notCheckable = true + info.text = L["TITAN_PANEL_OPTIONS"]; + info.value = "Options" + info.hasArrow = 1; + TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); + + TitanPanelRightClickMenu_AddSpacer(); + info = {}; + info.text = L["TITAN_BAG_MENU_IGNORE_PROF_BAGS_SLOTS"]; + info.func = function() + TitanToggleVar(TITAN_PLUGIN, "CountProfBagSlots"); + TitanPanelButton_UpdateButton(TITAN_PLUGIN); + end + info.checked = not TitanGetVar(TITAN_PLUGIN, "CountProfBagSlots") + TitanPanelRightClickMenu_AddButton(info, TitanPanelRightClickMenu_GetDropdownLevel()); + + TitanPanelRightClickMenu_AddControlVars(TITAN_PLUGIN) +end + +-- Grab the button text to display +local function GetButtonText(id) + local strA, strB = GetBagData(id) + return strA, strB +end + +-- Create the tooltip string +local function GetTooltipText() + local returnstring = ""; + + if trace then + TitanPluginDebug(TITAN_PLUGIN, "TS tool tip" + .. " detail " .. tostring(TitanGetVar(TITAN_PLUGIN, "ShowDetailedInfo")) .. "" + .. " used " .. tostring(TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots")) .. "" + .. " prof " .. tostring(TitanGetVar(TITAN_PLUGIN, "CountProfBagSlots")) .. "" + .. " color " .. tostring(TitanGetVar(TITAN_PLUGIN, "ShowColoredText")) .. "" + .. " open " .. tostring(TitanGetVar(TITAN_PLUGIN, "OpenBags")) .. "" + ) + end + + if TitanGetVar(TITAN_PLUGIN, "ShowDetailedInfo") then + returnstring = "\n"; + if TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots") then + returnstring = returnstring .. TitanUtils_GetNormalText(L["TITAN_BAG_MENU_TEXT"]) + .. ":\t" .. TitanUtils_GetNormalText(L["TITAN_BAG_USED_SLOTS"]) .. ":\n"; + else + returnstring = returnstring .. TitanUtils_GetNormalText(L["TITAN_BAG_MENU_TEXT"]) + .. ":\t" .. TitanUtils_GetNormalText(L["TITAN_BAG_FREE_SLOTS"]) .. ":\n"; + end + + for bag = MIN_BAGS, MAX_BAGS do + local bagText, bagRichText, color; + + if bag_data[bag] and bag_data[bag].has_bag then + if (TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots")) then + bagText = format(L["TITAN_BAG_FORMAT"], bag_data[bag].used_slots, bag_data[bag].maxi_slots); + else + bagText = format(L["TITAN_BAG_FORMAT"], bag_data[bag].free_slots, bag_data[bag].maxi_slots); + end + + if bag_data[bag].style == "profession" + and not TitanGetVar(TITAN_PLUGIN, "CountProfBagSlots") + then + bagRichText = "|cffa0a0a0" .. bagText .. "|r" -- show as gray + elseif (TitanGetVar(TITAN_PLUGIN, "ShowColoredText")) then + if bag_data[bag].maxi_slots == 0 then + color = TitanUtils_GetThresholdColor(TITAN_BAG_THRESHOLD_TABLE, 1); + else + color = TitanUtils_GetThresholdColor(TITAN_BAG_THRESHOLD_TABLE, + bag_data[bag].used_slots / bag_data[bag].maxi_slots); + end + bagRichText = TitanUtils_GetColoredText(bagText, color); + else + -- use without color + bagRichText = TitanUtils_GetHighlightText(bagText); + end + + local name_text = bag_data[bag].name + if bag_data[bag].style == "profession" + then + name_text = TitanUtils_GetColoredText(name_text, bag_data[bag].color) + else + -- use without color + end + returnstring = returnstring .. name_text .. "\t" .. bagRichText .. "\n"; + else + returnstring = returnstring .. NONE .. "\n"; + end + end + returnstring = returnstring .. "\n"; + end + + if TitanGetVar(TITAN_PLUGIN, "ShowUsedSlots") then + local xofy = "" .. tostring(bag_data.total_used) + .. "/" .. tostring(bag_data.total_slots) .. "\n" + returnstring = returnstring .. TitanUtils_GetNormalText(L["TITAN_BAG_USED_SLOTS"]) + .. ":\t" .. xofy + else + local xofy = "" .. tostring(bag_data.total_free) + .. "/" .. tostring(bag_data.total_slots) .. "\n" + returnstring = returnstring .. TitanUtils_GetNormalText(L["TITAN_BAG_USED_SLOTS"]) + .. ":\t" .. xofy + end + + -- Add Hint + if TitanGetVar(TITAN_PLUGIN, "OpenBags") then + returnstring = returnstring .. TitanUtils_GetGreenText(L["TITAN_BAG_TOOLTIP_HINTS"]) + else + -- nop + end + return returnstring +end + +-- Create the .registry for Titan so it can register and place the plugin +local function OnLoad(self) + local notes = "" + .. "Adds bag and free slot information to Titan Panel.\n" + -- .."- xxx.\n" + self.registry = { + id = TITAN_PLUGIN, + category = "Information", + version = VERSION, + menuText = L["TITAN_BAG_MENU_TEXT"], + menuTextFunction = CreateMenu, + buttonTextFunction = GetButtonText, + tooltipTitle = L["TITAN_BAG_TOOLTIP"], + tooltipTextFunction = GetTooltipText, + icon = artwork_path .. "TitanStarter", + iconWidth = 16, + notes = notes, + controlVariables = { + ShowIcon = true, + ShowLabelText = true, + ShowColoredText = true, + DisplayOnRightSide = true, + }, + savedVariables = { + ShowUsedSlots = 1, + ShowDetailedInfo = false, + CountProfBagSlots = false, + ShowIcon = 1, + ShowLabelText = 1, + ShowColoredText = 1, + DisplayOnRightSide = false, + OpenBags = false, + OpenBagsClassic = "new_install", + } + }; + + self:RegisterEvent("PLAYER_ENTERING_WORLD"); + + if trace then + TitanPluginDebug(TITAN_PLUGIN, "TS OnLoad" + .. " complete" + ) + end +end + +-- Parse and react to registered events +local function OnEvent(self, event, a1, a2, ...) + if trace then + TitanPluginDebug(TITAN_PLUGIN, "TS event" + .. " " .. tostring(event) .. "" + .. " " .. tostring(a1) .. "" + ) + end + + if event == "PLAYER_ENTERING_WORLD" then + end + + if event == "BAG_UPDATE" then + -- update the plugin text + TitanPanelButton_UpdateButton(TITAN_PLUGIN); + end +end + +-- Handle mouse clicks; here L click opens all bags +local function OnClick(self, button) + if trace then + TitanPluginDebug(TITAN_PLUGIN, "TS click" + .. " " .. tostring(button) .. "" + ) + end + + if (button == "LeftButton") then + ToggleBags(); + end +end + +local function OnShow(self) + if trace then + TitanPluginDebug(TITAN_PLUGIN, "TS OnShow" + .. " register" + ) + end + -- Register for bag updates and update the plugin text + self:RegisterEvent("BAG_UPDATE") + TitanPanelButton_UpdateButton(TITAN_PLUGIN); +end + +local function OnHide(self) + if trace then + TitanPluginDebug(TITAN_PLUGIN, "TS OnShow" + .. " unregister" + ) + end + self:UnregisterEvent("BAG_UPDATE") +end + +-- ====== Create needed frames +local function Create_Frames() + if _G[TITAN_BUTTON] then + return -- if already created + end + + if trace then + TitanPluginDebug(TITAN_PLUGIN, "TS frames" + .. " '" .. tostring(TITAN_BUTTON) .. "'" + ) + end + + -- general container frame + local f = CreateFrame("Frame", nil, UIParent) + -- f:Hide() + + -- Titan plugin button + --[[ + The plugin frame is created here. The typical plugin is a 'combo' which includes + - an icon (can be shown or hidden) + - label - value pair where the label can be turned off + There can be multiple label - value pairs; TitanPerformance uses this scheme. + + The frame is 'forever' as are most of WoW game frames. + --]] + local window = CreateFrame("Button", TITAN_BUTTON, f, "TitanPanelComboTemplate") + window:SetFrameStrata("FULLSCREEN") + -- Using SetScript to set "OnLoad" does not work + -- + -- This routine sets the guts of the plugin - the .registry + OnLoad(window); + + --[[ + Below are the frame 'events' that need to be processed. + A couple have Titan routines that ensure the plugin is properly on / off a Titan bar. + + The combined Titan changed design to register for events when the user places the plugin + on the bar (OnShow) and unregister events when the user hids the plugin (OnHide). + This reduces cycles the plugin uses when the user does not want the plugin. + + NOTE: If a Titan bar is hidden, the plugins on it will still run. + NOTE: Titan plugins are NOT child frames!! Meaning plugins are not automatically hidden when the + bar they are on is hidden! + --]] + window:SetScript("OnShow", function(self) + OnShow(self) + -- This routine ensures the plugin is put where the user requested it. + -- Titan saves the bar the plugin was on. It does not save the relative order. + TitanPanelButton_OnShow(self); + end) + window:SetScript("OnHide", function(self) + OnHide(self) + -- We use the Blizzard frame hide to visually remove the frame + end) + window:SetScript("OnEvent", function(self, event, ...) + -- Handle any events the plugin is interested in + OnEvent(self, event, ...) + end) + window:SetScript("OnClick", function(self, button) + -- Typically this routine handles actions on left click + OnClick(self, button); + -- Typically this routine handles the menu creation on right click + TitanPanelButton_OnClick(self, button); + end) +end + +Create_Frames() -- do the work diff --git a/TitanRepair/TitanRepair.toc b/TitanRepair/TitanRepair.toc new file mode 100644 index 0000000..4dfeb9c --- /dev/null +++ b/TitanRepair/TitanRepair.toc @@ -0,0 +1,10 @@ +## Interface: 110105, 40402, 11507 +## Title: Titan Panel [|cffeda55fRepair|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## IconTexture: Interface\AddOns\TitanRepair\TitanRepair +## Notes: Provides a configurable durability display. Also adds the ability to auto repair items and inventory at vendors. Adds selling of grey items. +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: +## OptionalDeps: +## Dependencies: Titan +TitanRepair.lua diff --git a/TitanRepair/TitanRepair_Mainline.toc b/TitanRepair/TitanRepair_Mainline.toc deleted file mode 100644 index de2d4dd..0000000 --- a/TitanRepair/TitanRepair_Mainline.toc +++ /dev/null @@ -1,10 +0,0 @@ -## Interface: 110107 -## Title: Titan Panel [|cffeda55fRepair|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## IconTexture: Interface\AddOns\TitanRepair\TitanRepair -## Notes: Provides a configurable durability display. Also adds the ability to auto repair items and inventory at vendors. Adds selling of grey items. -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanRepair.lua diff --git a/TitanRepair/TitanRepair_Vanilla.toc b/TitanRepair/TitanRepair_Vanilla.toc deleted file mode 100644 index 05aff95..0000000 --- a/TitanRepair/TitanRepair_Vanilla.toc +++ /dev/null @@ -1,9 +0,0 @@ -## Interface: 11507, 50500 -## Title: Titan Panel [|cffeda55fRepair|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## Notes: Provides a configurable durability display. Also adds the ability to auto repair items and inventory at vendors. Adds selling of grey items. -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanRepair.lua diff --git a/TitanVolume/TitanVolume.toc b/TitanVolume/TitanVolume.toc new file mode 100644 index 0000000..2134129 --- /dev/null +++ b/TitanVolume/TitanVolume.toc @@ -0,0 +1,11 @@ +## Interface: 110105, 40402, 11507 +## Title: Titan Panel [|cffeda55fVolume|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## IconTexture: Interface\AddOns\TitanVolume\Artwork\TitanVolumeHigh +## Notes: Adds a volume control icon on your Titan Bar +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: +## OptionalDeps: +## OptionalDeps: +## Dependencies: Titan +TitanVolume.lua diff --git a/TitanVolume/TitanVolume_Mainline.toc b/TitanVolume/TitanVolume_Mainline.toc deleted file mode 100644 index 63d99ac..0000000 --- a/TitanVolume/TitanVolume_Mainline.toc +++ /dev/null @@ -1,11 +0,0 @@ -## Interface: 110107 -## Title: Titan Panel [|cffeda55fVolume|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## IconTexture: Interface\AddOns\TitanVolume\Artwork\TitanVolumeHigh -## Notes: Adds a volume control icon on your Titan Bar -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## OptionalDeps: -## Dependencies: Titan -TitanVolume.lua diff --git a/TitanVolume/TitanVolume_Vanilla.toc b/TitanVolume/TitanVolume_Vanilla.toc deleted file mode 100644 index fba8739..0000000 --- a/TitanVolume/TitanVolume_Vanilla.toc +++ /dev/null @@ -1,9 +0,0 @@ -## Interface: 11507, 50500 -## Title: Titan Panel [|cffeda55fVolume|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## Notes: Adds a volume control icon on your Titan Bar -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanVolume.lua diff --git a/TitanXP/TitanXP.toc b/TitanXP/TitanXP.toc new file mode 100644 index 0000000..5089fe0 --- /dev/null +++ b/TitanXP/TitanXP.toc @@ -0,0 +1,10 @@ +## Interface: 110105, 40402, 11507 +## Title: Titan Panel [|cffeda55fXP|r] |cff00aa008.3.0|r +## Version: 8.3.0 +## IconTexture: Interface\Icons\xp_icon +## Notes: Adds information to Titan Panel about XP earned and time to level +## Author: Titan Panel Development Team (http://www.titanpanel.org) +## SavedVariables: +## OptionalDeps: +## Dependencies: Titan +TitanXP.lua diff --git a/TitanXP/TitanXP_Mainline.toc b/TitanXP/TitanXP_Mainline.toc deleted file mode 100644 index 2cc2572..0000000 --- a/TitanXP/TitanXP_Mainline.toc +++ /dev/null @@ -1,10 +0,0 @@ -## Interface: 110107 -## Title: Titan Panel [|cffeda55fXP|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## IconTexture: Interface\Icons\xp_icon -## Notes: Adds information to Titan Panel about XP earned and time to level -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanXP.lua diff --git a/TitanXP/TitanXP_Vanilla.toc b/TitanXP/TitanXP_Vanilla.toc deleted file mode 100644 index b41ba9e..0000000 --- a/TitanXP/TitanXP_Vanilla.toc +++ /dev/null @@ -1,9 +0,0 @@ -## Interface: 11507, 50500 -## Title: Titan Panel [|cffeda55fXP|r] |cff00aa008.3.0|r -## Version: 8.3.0 -## Notes: Adds information to Titan Panel about XP earned and time to level -## Author: Titan Panel Development Team (http://www.titanpanel.org) -## SavedVariables: -## OptionalDeps: -## Dependencies: Titan -TitanXP.lua