├── AI_VoiceOver
├── Textures
│ ├── StopGossip.tga
│ ├── MinimapButton.tga
│ ├── SettingsButton.tga
│ ├── SizeGrabber-Up.blp
│ ├── StopGossipMore.tga
│ ├── PortraitFrameAtlas.tga
│ ├── SizeGrabber-Down.blp
│ ├── PortraitFrameBackground.blp
│ ├── SizeGrabber-Highlight.blp
│ ├── SoundQueueBulletAccept.blp
│ ├── SoundQueueBulletDelete.tga
│ ├── SoundQueueBulletGossip.blp
│ ├── SoundQueueBulletQueue.tga
│ ├── SoundQueueBulletComplete.blp
│ ├── SoundQueueBulletProgress.blp
│ └── spacer.tga
├── AI_VoiceOver.toc
├── Libs
│ ├── AceDB-3.0
│ │ └── AceDB-3.0.xml
│ ├── AceAddon-3.0
│ │ └── AceAddon-3.0.xml
│ ├── AceEvent-3.0
│ │ ├── AceEvent-3.0.xml
│ │ └── AceEvent-3.0.lua
│ ├── AceTimer-3.0
│ │ └── AceTimer-3.0.xml
│ ├── AceConsole-3.0
│ │ ├── AceConsole-3.0.xml
│ │ └── AceConsole-3.0.lua
│ ├── LibDBIcon-1.0
│ │ └── lib.xml
│ ├── AceDBOptions-3.0
│ │ └── AceDBOptions-3.0.xml
│ ├── CallbackHandler-1.0
│ │ ├── CallbackHandler-1.0.xml
│ │ └── CallbackHandler-1.0.lua
│ ├── AceConfig-3.0
│ │ ├── AceConfigCmd-3.0
│ │ │ └── AceConfigCmd-3.0.xml
│ │ ├── AceConfigDialog-3.0
│ │ │ └── AceConfigDialog-3.0.xml
│ │ ├── AceConfigRegistry-3.0
│ │ │ └── AceConfigRegistry-3.0.xml
│ │ ├── AceConfig-3.0.xml
│ │ └── AceConfig-3.0.lua
│ ├── LibDataBroker-1.1
│ │ ├── README.textile
│ │ └── LibDataBroker-1.1.lua
│ ├── LibStub
│ │ └── LibStub.lua
│ └── AceGUI-3.0
│ │ ├── AceGUI-3.0.xml
│ │ └── widgets
│ │ ├── AceGUIContainer-SimpleGroup.lua
│ │ ├── AceGUIWidget-Heading.lua
│ │ ├── AceGUIWidget-Button.lua
│ │ ├── AceGUIWidget-InteractiveLabel.lua
│ │ ├── AceGUIContainer-InlineGroup.lua
│ │ ├── AceGUIContainer-BlizOptionsGroup.lua
│ │ ├── AceGUIWidget-Icon.lua
│ │ ├── AceGUIWidget-Label.lua
│ │ ├── AceGUIContainer-DropDownGroup.lua
│ │ ├── AceGUIWidget-ColorPicker.lua
│ │ ├── AceGUIWidget-Keybinding.lua
│ │ ├── AceGUIContainer-ScrollFrame.lua
│ │ ├── AceGUIWidget-EditBox.lua
│ │ ├── AceGUIWidget-CheckBox.lua
│ │ ├── AceGUIWidget-Slider.lua
│ │ ├── AceGUIContainer-Frame.lua
│ │ ├── AceGUIWidget-MultiLineEditBox.lua
│ │ ├── AceGUIContainer-Window.lua
│ │ └── AceGUIContainer-TabGroup.lua
├── Debug.lua
├── addon.xml
├── embeds.xml
├── Interface.lua
├── Environment.lua
├── Common
│ ├── FuzzySearch.lua
│ ├── Enums.lua
│ └── DataModules.lua
├── SoundQueue.lua
├── QuestOverlayUI.lua
├── VoiceOver.lua
└── Utils.lua
├── AI_VoiceOverData_Vanilla
├── Module.lua
└── AI_VoiceOverData_Vanilla.toc
└── README.md
/AI_VoiceOver/Textures/StopGossip.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/StopGossip.tga
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/MinimapButton.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/MinimapButton.tga
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SettingsButton.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SettingsButton.tga
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SizeGrabber-Up.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SizeGrabber-Up.blp
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/StopGossipMore.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/StopGossipMore.tga
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/PortraitFrameAtlas.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/PortraitFrameAtlas.tga
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SizeGrabber-Down.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SizeGrabber-Down.blp
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/PortraitFrameBackground.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/PortraitFrameBackground.blp
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SizeGrabber-Highlight.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SizeGrabber-Highlight.blp
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SoundQueueBulletAccept.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SoundQueueBulletAccept.blp
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SoundQueueBulletDelete.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SoundQueueBulletDelete.tga
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SoundQueueBulletGossip.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SoundQueueBulletGossip.blp
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SoundQueueBulletQueue.tga:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SoundQueueBulletQueue.tga
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SoundQueueBulletComplete.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SoundQueueBulletComplete.blp
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/SoundQueueBulletProgress.blp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/s0h2x/AI_VoiceOver-WotLK/HEAD/AI_VoiceOver/Textures/SoundQueueBulletProgress.blp
--------------------------------------------------------------------------------
/AI_VoiceOver/AI_VoiceOver.toc:
--------------------------------------------------------------------------------
1 | ## Interface: 30300
2 | ## Title: VoiceOver
3 | ## Notes: Adds voiceovers to npcs.
4 | ## Version: 1.3.0
5 | ## SavedVariables: VoiceOverDB
6 | ## X-Part-Of: VoiceOver
7 |
8 | embeds.xml
9 | addon.xml
10 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceDB-3.0/AceDB-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceAddon-3.0/AceAddon-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceEvent-3.0/AceEvent-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceTimer-3.0/AceTimer-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceConsole-3.0/AceConsole-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/LibDBIcon-1.0/lib.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceDBOptions-3.0/AceDBOptions-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/CallbackHandler-1.0/CallbackHandler-1.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceConfig-3.0/AceConfig-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Debug.lua:
--------------------------------------------------------------------------------
1 | setfenv(1, VoiceOver)
2 | Debug = {}
3 |
4 | function Debug:Print(msg, header)
5 | if Addon.db.profile.DebugEnabled then
6 | if header then
7 | print(Utils:ColorizeText("VoiceOver", NORMAL_FONT_COLOR_CODE) ..
8 | Utils:ColorizeText(" (" .. header .. ")", GRAY_FONT_COLOR_CODE) ..
9 | " - " .. msg)
10 | else
11 | print(Utils:ColorizeText("VoiceOver", NORMAL_FONT_COLOR_CODE) ..
12 | " - " .. msg)
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/AI_VoiceOverData_Vanilla/Module.lua:
--------------------------------------------------------------------------------
1 | if not VoiceOver or not VoiceOver.DataModules then return end
2 |
3 | AI_VoiceOverData_Vanilla = {}
4 |
5 | function AI_VoiceOverData_Vanilla:GetSoundPath(fileName, event)
6 | setfenv(1, VoiceOver)
7 | if Enums.SoundEvent:IsQuestEvent(event) then
8 | return format([[generated\sounds\quests\%s.mp3]], fileName)
9 | elseif Enums.SoundEvent:IsGossipEvent(event) then
10 | return format([[generated\sounds\gossip\%s.mp3]], fileName)
11 | end
12 | end
13 |
14 | VoiceOver.DataModules:Register("AI_VoiceOverData_Vanilla", AI_VoiceOverData_Vanilla)
15 |
--------------------------------------------------------------------------------
/AI_VoiceOver/addon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/AI_VoiceOverData_Vanilla/AI_VoiceOverData_Vanilla.toc:
--------------------------------------------------------------------------------
1 | ## Interface: 30300
2 | ## Title: VoiceOver Data - Vanilla
3 | ## Version: 0.1
4 | ## LoadOnDemand: 1
5 | ## OptionalDeps: AI_VoiceOver_112, AI_VoiceOver
6 | ## X-Part-Of: VoiceOver
7 | ## X-Child-Of: VoiceOver
8 | ## X-VoiceOver-DataModule-Version: 1
9 | ## X-VoiceOver-DataModule-Priority: 100
10 | ## X-VoiceOver-DataModule-Maps: 0, 1, 30, 33, 43, 47, 48, 70, 90, 109, 129, 189, 209, 229, 230, 289, 309, 329, 349, 369, 389, 429, 469, 509, 531, 533
11 |
12 | Module.lua
13 | #generated\gossip_file_lookups.lua
14 | generated\npc_name_gossip_file_lookups.lua
15 | generated\npc_name_lookups.lua
16 | generated\quest_id_lookups.lua
17 | generated\questlog_npc_lookups.lua
18 | generated\sound_length_table.lua
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AI_VoiceOver-WotLK
2 | By popular requests and my interest, im backported this addon for 3.3.5
3 |
Demo: https://www.youtube.com/watch?v=mZEQKrIiS1Q
4 |
5 | ## About
6 | >**VoiceOver: Plays high quality AI generated voices for NPCs.**
7 |
8 | >**Original project and authors: https://github.com/mrthinger/wow-voiceover**
9 |
10 | ## Install
11 | - **[Download this file](https://www.curseforge.com/wow/addons/voiceover-sounds-vanilla/files)** first and move it to addons folder ***(need data of sounds)***
12 | - After first step **[download file](https://github.com/s0h2x/AI_VoiceOver-WotLK/archive/refs/heads/master.zip)** from this repo
13 | - Install addons with **replace** ***(need to replace AI_VoiceOverData_Vanilla with repo version)***
14 | - Enjoy!
15 |
--------------------------------------------------------------------------------
/AI_VoiceOver/embeds.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Textures/spacer.tga:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Interface.lua:
--------------------------------------------------------------------------------
1 | ----------------------------------
2 | -- Compatibility part
3 | ----------------------------------
4 |
5 | SOUNDKIT_SFX = {
6 | U_CHAT_SCROLL_BUTTON = 1115,
7 | IG_MAINMENU_CLOSE = 851,
8 | IG_MAINMENU_OPEN = 850,
9 | }
10 |
11 | if not C_GossipInfo then
12 | C_GossipInfo = {}
13 | function C_GossipInfo:GetText(...)
14 | if GetGossipText then return GetGossipText(...) end
15 | -- return C_GossipInfo.GetText()
16 | end
17 |
18 | function C_GossipInfo:GetNumAvailableQuests(...)
19 | if GetNumGossipAvailableQuests then return GetNumGossipAvailableQuests(...) end
20 | -- return C_GossipInfo.GetNumAvailableQuests(...)
21 | end
22 |
23 | function C_GossipInfo:GetNumActiveQuests(...)
24 | if GetNumGossipActiveQuests then return GetNumGossipActiveQuests(...) end
25 | -- return C_GossipInfo.GetNumActiveQuests(...)
26 | end
27 |
28 | function C_GossipInfo:SelectGossipOption(...)
29 | if SelectGossipOption then return SelectGossipOption(...) end
30 | -- return C_GossipInfo.SelectOption(...)
31 | end
32 | end
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/LibDataBroker-1.1/README.textile:
--------------------------------------------------------------------------------
1 | LibDataBroker is a small WoW addon library designed to provide a "MVC":http://en.wikipedia.org/wiki/Model-view-controller interface for use in various addons.
2 | LDB's primary goal is to "detach" plugins for TitanPanel and FuBar from the display addon.
3 | Plugins can provide data into a simple table, and display addons can receive callbacks to refresh their display of this data.
4 | LDB also provides a place for addons to register "quicklaunch" functions, removing the need for authors to embed many large libraries to create minimap buttons.
5 | Users who do not wish to be "plagued" by these buttons simply do not install an addon to render them.
6 |
7 | Due to it's simple generic design, LDB can be used for any design where you wish to have an addon notified of changes to a table.
8 |
9 | h2. Links
10 |
11 | * "API documentation":http://github.com/tekkub/libdatabroker-1-1/wikis/api
12 | * "Data specifications":http://github.com/tekkub/libdatabroker-1-1/wikis/data-specifications
13 | * "Addons using LDB":http://github.com/tekkub/libdatabroker-1-1/wikis/addons-using-ldb
14 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Environment.lua:
--------------------------------------------------------------------------------
1 | --[[
2 | Use the addon's private table as an isolated environment.
3 | By using { __index = _G } metatable we're allowing all global lookups to transparently fallback to the game-wide
4 | globals table, while the private table itself will act as a thin layer on top of the game-wide globals table,
5 | allowing us to have our own global variables isolated from the rest of the game.
6 |
7 | This accomplishes several goals:
8 | 1. Prevents addon-specific "globals" from leaking to game-wide global namespace _G
9 | 2. Optionally retains the ability to access these "globals" via the only exposed global variable "VoiceOver"
10 | 3. Allows us to make overrides for WoW API's global funtions and variables without actually touching
11 | the real global namespace, making these overrides visible only to this addon.
12 | This will be useful mainly for adding backwards-compatibility with older WoW clients.
13 |
14 | setfenv(1, VoiceOver) must be added to every .lua file to allow it to work within this environment,
15 | and this Environment file must be loaded before all others
16 | ]]
17 |
18 | VoiceOver = setmetatable({}, { __index = _G })
19 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Common/FuzzySearch.lua:
--------------------------------------------------------------------------------
1 | setfenv(1, VoiceOver)
2 | local function jaccardSimilarity(a, b)
3 | local tokens_a, tokens_b = {}, {}
4 | for token in string.gmatch(a, "%S+") do tokens_a[token] = true end
5 | for token in string.gmatch(b, "%S+") do tokens_b[token] = true end
6 |
7 | local intersection, union = 0, 0
8 | for token in pairs(tokens_a) do
9 | union = union + 1
10 | if tokens_b[token] then
11 | intersection = intersection + 1
12 | end
13 | end
14 | for token in pairs(tokens_b) do
15 | if not tokens_a[token] then
16 | union = union + 1
17 | end
18 | end
19 |
20 | return intersection / union
21 | end
22 |
23 | function FuzzySearchBestKeys(query, tableVar)
24 | local best_result = nil
25 | local max_similarity = -1
26 |
27 | for entry, value in pairs(tableVar) do
28 | local similarity = jaccardSimilarity(query, entry)
29 | if similarity > max_similarity then
30 | max_similarity = similarity
31 | best_result = {
32 | value = value,
33 | text = entry,
34 | similarity = similarity
35 | }
36 | end
37 | end
38 |
39 | return best_result
40 | end
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/LibStub/LibStub.lua:
--------------------------------------------------------------------------------
1 | -- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
2 | -- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
3 | local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
4 | local LibStub = _G[LIBSTUB_MAJOR]
5 |
6 | if not LibStub or LibStub.minor < LIBSTUB_MINOR then
7 | LibStub = LibStub or {libs = {}, minors = {} }
8 | _G[LIBSTUB_MAJOR] = LibStub
9 | LibStub.minor = LIBSTUB_MINOR
10 |
11 | function LibStub:NewLibrary(major, minor)
12 | assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
13 | minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
14 |
15 | local oldminor = self.minors[major]
16 | if oldminor and oldminor >= minor then return nil end
17 | self.minors[major], self.libs[major] = minor, self.libs[major] or {}
18 | return self.libs[major], oldminor
19 | end
20 |
21 | function LibStub:GetLibrary(major, silent)
22 | if not self.libs[major] and not silent then
23 | error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
24 | end
25 | return self.libs[major], self.minors[major]
26 | end
27 |
28 | function LibStub:IterateLibraries() return pairs(self.libs) end
29 | setmetatable(LibStub, { __call = LibStub.GetLibrary })
30 | end
31 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/AceGUI-3.0.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIContainer-SimpleGroup.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | SimpleGroup Container
3 | Simple container widget that just groups widgets.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "SimpleGroup", 20
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local CreateFrame, UIParent = CreateFrame, UIParent
14 |
15 |
16 | --[[-----------------------------------------------------------------------------
17 | Methods
18 | -------------------------------------------------------------------------------]]
19 | local methods = {
20 | ["OnAcquire"] = function(self)
21 | self:SetWidth(300)
22 | self:SetHeight(100)
23 | end,
24 |
25 | -- ["OnRelease"] = nil,
26 |
27 | ["LayoutFinished"] = function(self, width, height)
28 | if self.noAutoHeight then return end
29 | self:SetHeight(height or 0)
30 | end,
31 |
32 | ["OnWidthSet"] = function(self, width)
33 | local content = self.content
34 | content:SetWidth(width)
35 | content.width = width
36 | end,
37 |
38 | ["OnHeightSet"] = function(self, height)
39 | local content = self.content
40 | content:SetHeight(height)
41 | content.height = height
42 | end
43 | }
44 |
45 | --[[-----------------------------------------------------------------------------
46 | Constructor
47 | -------------------------------------------------------------------------------]]
48 | local function Constructor()
49 | local frame = CreateFrame("Frame", nil, UIParent)
50 | frame:SetFrameStrata("FULLSCREEN_DIALOG")
51 |
52 | --Container Support
53 | local content = CreateFrame("Frame", nil, frame)
54 | content:SetPoint("TOPLEFT")
55 | content:SetPoint("BOTTOMRIGHT")
56 |
57 | local widget = {
58 | frame = frame,
59 | content = content,
60 | type = Type
61 | }
62 | for method, func in pairs(methods) do
63 | widget[method] = func
64 | end
65 |
66 | return AceGUI:RegisterAsContainer(widget)
67 | end
68 |
69 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
70 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceConfig-3.0/AceConfig-3.0.lua:
--------------------------------------------------------------------------------
1 | --- AceConfig-3.0 wrapper library.
2 | -- Provides an API to register an options table with the config registry,
3 | -- as well as associate it with a slash command.
4 | -- @class file
5 | -- @name AceConfig-3.0
6 | -- @release $Id: AceConfig-3.0.lua 969 2010-10-07 02:11:48Z shefki $
7 |
8 | --[[
9 | AceConfig-3.0
10 |
11 | Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole.
12 |
13 | ]]
14 |
15 | local MAJOR, MINOR = "AceConfig-3.0", 2
16 | local AceConfig = LibStub:NewLibrary(MAJOR, MINOR)
17 |
18 | if not AceConfig then return end
19 |
20 | local cfgreg = LibStub("AceConfigRegistry-3.0")
21 | local cfgcmd = LibStub("AceConfigCmd-3.0")
22 | --TODO: local cfgdlg = LibStub("AceConfigDialog-3.0", true)
23 | --TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0", true)
24 |
25 | -- Lua APIs
26 | local pcall, error, type, pairs = pcall, error, type, pairs
27 |
28 | -- -------------------------------------------------------------------
29 | -- :RegisterOptionsTable(appName, options, slashcmd, persist)
30 | --
31 | -- - appName - (string) application name
32 | -- - options - table or function ref, see AceConfigRegistry
33 | -- - slashcmd - slash command (string) or table with commands, or nil to NOT create a slash command
34 |
35 | --- Register a option table with the AceConfig registry.
36 | -- You can supply a slash command (or a table of slash commands) to register with AceConfigCmd directly.
37 | -- @paramsig appName, options [, slashcmd]
38 | -- @param appName The application name for the config table.
39 | -- @param options The option table (or a function to generate one on demand). http://www.wowace.com/addons/ace3/pages/ace-config-3-0-options-tables/
40 | -- @param slashcmd A slash command to register for the option table, or a table of slash commands.
41 | -- @usage
42 | -- local AceConfig = LibStub("AceConfig-3.0")
43 | -- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"})
44 | function AceConfig:RegisterOptionsTable(appName, options, slashcmd)
45 | local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options)
46 | if not ok then error(msg, 2) end
47 |
48 | if slashcmd then
49 | if type(slashcmd) == "table" then
50 | for _,cmd in pairs(slashcmd) do
51 | cfgcmd:CreateChatCommand(cmd, appName)
52 | end
53 | else
54 | cfgcmd:CreateChatCommand(slashcmd, appName)
55 | end
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/LibDataBroker-1.1/LibDataBroker-1.1.lua:
--------------------------------------------------------------------------------
1 |
2 | assert(LibStub, "LibDataBroker-1.1 requires LibStub")
3 | assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
4 |
5 | local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 3)
6 | if not lib then return end
7 | oldminor = oldminor or 0
8 |
9 |
10 | lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
11 | lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
12 | local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
13 |
14 | if oldminor < 2 then
15 | lib.domt = {
16 | __metatable = "access denied",
17 | __index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
18 | }
19 | end
20 |
21 | if oldminor < 3 then
22 | lib.domt.__newindex = function(self, key, value)
23 | if not attributestorage[self] then attributestorage[self] = {} end
24 | if attributestorage[self][key] == value then return end
25 | attributestorage[self][key] = value
26 | local name = namestorage[self]
27 | if not name then return end
28 | callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
29 | callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
30 | callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
31 | callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
32 | end
33 | end
34 |
35 | if oldminor < 2 then
36 | function lib:NewDataObject(name, dataobj)
37 | if self.proxystorage[name] then return end
38 |
39 | if dataobj then
40 | assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
41 | self.attributestorage[dataobj] = {}
42 | for i,v in pairs(dataobj) do
43 | self.attributestorage[dataobj][i] = v
44 | dataobj[i] = nil
45 | end
46 | end
47 | dataobj = setmetatable(dataobj or {}, self.domt)
48 | self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
49 | self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
50 | return dataobj
51 | end
52 | end
53 |
54 | if oldminor < 1 then
55 | function lib:DataObjectIterator()
56 | return pairs(self.proxystorage)
57 | end
58 |
59 | function lib:GetDataObjectByName(dataobjectname)
60 | return self.proxystorage[dataobjectname]
61 | end
62 |
63 | function lib:GetNameByDataObject(dataobject)
64 | return self.namestorage[dataobject]
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Heading Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "Heading", 20
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local pairs = pairs
10 |
11 | -- WoW APIs
12 | local CreateFrame, UIParent = CreateFrame, UIParent
13 |
14 | --[[-----------------------------------------------------------------------------
15 | Methods
16 | -------------------------------------------------------------------------------]]
17 | local methods = {
18 | ["OnAcquire"] = function(self)
19 | self:SetText()
20 | self:SetFullWidth()
21 | self:SetHeight(18)
22 | end,
23 |
24 | -- ["OnRelease"] = nil,
25 |
26 | ["SetText"] = function(self, text)
27 | self.label:SetText(text or "")
28 | if text and text ~= "" then
29 | self.left:SetPoint("RIGHT", self.label, "LEFT", -5, 0)
30 | self.right:Show()
31 | else
32 | self.left:SetPoint("RIGHT", -3, 0)
33 | self.right:Hide()
34 | end
35 | end
36 | }
37 |
38 | --[[-----------------------------------------------------------------------------
39 | Constructor
40 | -------------------------------------------------------------------------------]]
41 | local function Constructor()
42 | local frame = CreateFrame("Frame", nil, UIParent)
43 | frame:Hide()
44 |
45 | local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
46 | label:SetPoint("TOP")
47 | label:SetPoint("BOTTOM")
48 | label:SetJustifyH("CENTER")
49 |
50 | local left = frame:CreateTexture(nil, "BACKGROUND")
51 | left:SetHeight(8)
52 | left:SetPoint("LEFT", 3, 0)
53 | left:SetPoint("RIGHT", label, "LEFT", -5, 0)
54 | left:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
55 | left:SetTexCoord(0.81, 0.94, 0.5, 1)
56 |
57 | local right = frame:CreateTexture(nil, "BACKGROUND")
58 | right:SetHeight(8)
59 | right:SetPoint("RIGHT", -3, 0)
60 | right:SetPoint("LEFT", label, "RIGHT", 5, 0)
61 | right:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
62 | right:SetTexCoord(0.81, 0.94, 0.5, 1)
63 |
64 | local widget = {
65 | label = label,
66 | left = left,
67 | right = right,
68 | frame = frame,
69 | type = Type
70 | }
71 | for method, func in pairs(methods) do
72 | widget[method] = func
73 | end
74 |
75 | return AceGUI:RegisterAsWidget(widget)
76 | end
77 |
78 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
79 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-Button.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Button Widget
3 | Graphical Button.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "Button", 20
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local _G = _G
14 | local PlaySound, CreateFrame, UIParent = PlaySound, CreateFrame, UIParent
15 |
16 | --[[-----------------------------------------------------------------------------
17 | Scripts
18 | -------------------------------------------------------------------------------]]
19 | local function Button_OnClick(frame, ...)
20 | PlaySound("igMainMenuOption")
21 | frame.obj:Fire("OnClick", ...)
22 | AceGUI:ClearFocus()
23 | end
24 |
25 | local function Control_OnEnter(frame)
26 | frame.obj:Fire("OnEnter")
27 | end
28 |
29 | local function Control_OnLeave(frame)
30 | frame.obj:Fire("OnLeave")
31 | end
32 |
33 | --[[-----------------------------------------------------------------------------
34 | Methods
35 | -------------------------------------------------------------------------------]]
36 | local methods = {
37 | ["OnAcquire"] = function(self)
38 | -- restore default values
39 | self:SetHeight(24)
40 | self:SetWidth(200)
41 | self:SetDisabled(false)
42 | self:SetText()
43 | end,
44 |
45 | -- ["OnRelease"] = nil,
46 |
47 | ["SetText"] = function(self, text)
48 | self.text:SetText(text)
49 | end,
50 |
51 | ["SetDisabled"] = function(self, disabled)
52 | self.disabled = disabled
53 | if disabled then
54 | self.frame:Disable()
55 | else
56 | self.frame:Enable()
57 | end
58 | end
59 | }
60 |
61 | --[[-----------------------------------------------------------------------------
62 | Constructor
63 | -------------------------------------------------------------------------------]]
64 | local function Constructor()
65 | local name = "AceGUI30Button" .. AceGUI:GetNextWidgetNum(Type)
66 | local frame = CreateFrame("Button", name, UIParent, "UIPanelButtonTemplate2")
67 | frame:Hide()
68 |
69 | frame:EnableMouse(true)
70 | frame:SetScript("OnClick", Button_OnClick)
71 | frame:SetScript("OnEnter", Control_OnEnter)
72 | frame:SetScript("OnLeave", Control_OnLeave)
73 |
74 | local text = frame:GetFontString()
75 | text:ClearAllPoints()
76 | text:SetPoint("TOPLEFT", 15, -1)
77 | text:SetPoint("BOTTOMRIGHT", -15, 1)
78 | text:SetJustifyV("MIDDLE")
79 |
80 | local widget = {
81 | text = text,
82 | frame = frame,
83 | type = Type
84 | }
85 | for method, func in pairs(methods) do
86 | widget[method] = func
87 | end
88 |
89 | return AceGUI:RegisterAsWidget(widget)
90 | end
91 |
92 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
93 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Common/Enums.lua:
--------------------------------------------------------------------------------
1 | setfenv(1, VoiceOver)
2 | ---@type table
3 | Enums = {}
4 |
5 | ---@enum SoundEvent
6 | Enums.SoundEvent =
7 | {
8 | QuestAccept = 1,
9 | QuestProgress = 2,
10 | QuestComplete = 3,
11 | QuestGreeting = 4,
12 | Gossip = 5,
13 | }
14 | function Enums.SoundEvent:IsQuestEvent(event)
15 | return event == self.QuestAccept or event == self.QuestProgress or event == self.QuestComplete
16 | end
17 | function Enums.SoundEvent:IsGossipEvent(event)
18 | return event == self.Gossip or event == self.QuestGreeting
19 | end
20 |
21 | function Enums.SoundEvent:ToString(event)
22 | if event == self.QuestAccept then
23 | return "accept"
24 | elseif event == self.QuestProgress then
25 | return "progress"
26 | elseif event == self.QuestComplete then
27 | return "complete"
28 | elseif event == self.QuestGreeting then
29 | return "greeting"
30 | elseif event == self.Gossip then
31 | return "gossip"
32 | else
33 | return nil
34 | end
35 | end
36 |
37 | ---@enum GossipFrequency
38 | Enums.GossipFrequency =
39 | {
40 | Always = 1,
41 | OncePerQuestNPC = 2,
42 | OncePerNPC = 3,
43 | Never = 4,
44 | }
45 |
46 | ---@enum SoundChannel
47 | Enums.SoundChannel =
48 | {
49 | Master = 1,
50 | Sound = 2,
51 | Music = 3,
52 | Ambience = 4,
53 | Dialog = 5,
54 | }
55 |
56 | ---@enum GUID
57 | Enums.GUID =
58 | {
59 | Player = 2,
60 | Item = 3,
61 | Creature = 8,
62 | Vehicle = 9,
63 | GameObject = 11,
64 | }
65 | function Enums.GUID:IsCreature(type)
66 | return type == self.Creature or type == self.Vehicle
67 | end
68 | function Enums.GUID:CanHaveID(type)
69 | return type == self.Creature or type == self.Vehicle or type == self.GameObject
70 | end
71 |
72 |
73 |
74 | ---@class Enum
75 | local Enum = {}
76 | Enum.__index = Enum
77 |
78 | ---@param value number Enum element value
79 | ---@return string|nil name Enum element name
80 | function Enum:GetName(value)
81 | for k, v in pairs(self) do
82 | if v == value then
83 | return k
84 | end
85 | end
86 | end
87 |
88 | ---@return table
89 | function Enum:GetValueToNameMap()
90 | local result = {}
91 | for k, v in pairs(self) do
92 | result[v] = k
93 | end
94 | return result
95 | end
96 |
97 | for name, enum in pairs(Enums) do
98 | if type(enum) == "table" then
99 | local metatable
100 | for k, v in pairs(enum) do
101 | -- Move all functions from the enum to its metatable (which also "inherits" from Enum)
102 | if type(v) == "function" then
103 | if not metatable then
104 | metatable = setmetatable({}, { __index = Enum })
105 | metatable.__index = metatable
106 | end
107 | metatable[k] = v
108 | enum[k] = nil
109 | end
110 | end
111 | Enums[name] = setmetatable(enum, metatable or Enum)
112 | end
113 | end
114 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-InteractiveLabel.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | InteractiveLabel Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "InteractiveLabel", 20
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local select, pairs = select, pairs
10 |
11 | -- WoW APIs
12 | local CreateFrame, UIParent = CreateFrame, UIParent
13 |
14 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
15 | -- List them here for Mikk's FindGlobals script
16 | -- GLOBALS: GameFontHighlightSmall
17 |
18 | --[[-----------------------------------------------------------------------------
19 | Scripts
20 | -------------------------------------------------------------------------------]]
21 | local function Control_OnEnter(frame)
22 | frame.obj:Fire("OnEnter")
23 | end
24 |
25 | local function Control_OnLeave(frame)
26 | frame.obj:Fire("OnLeave")
27 | end
28 |
29 | local function Label_OnClick(frame, button)
30 | frame.obj:Fire("OnClick", button)
31 | AceGUI:ClearFocus()
32 | end
33 |
34 | --[[-----------------------------------------------------------------------------
35 | Methods
36 | -------------------------------------------------------------------------------]]
37 | local methods = {
38 | ["OnAcquire"] = function(self)
39 | self:LabelOnAcquire()
40 | self:SetHighlight()
41 | self:SetHighlightTexCoord()
42 | self:SetDisabled(false)
43 | end,
44 |
45 | -- ["OnRelease"] = nil,
46 |
47 | ["SetHighlight"] = function(self, ...)
48 | self.highlight:SetTexture(...)
49 | end,
50 |
51 | ["SetHighlightTexCoord"] = function(self, ...)
52 | local c = select("#", ...)
53 | if c == 4 or c == 8 then
54 | self.highlight:SetTexCoord(...)
55 | else
56 | self.highlight:SetTexCoord(0, 1, 0, 1)
57 | end
58 | end,
59 |
60 | ["SetDisabled"] = function(self,disabled)
61 | self.disabled = disabled
62 | if disabled then
63 | self.frame:EnableMouse(false)
64 | self.label:SetTextColor(0.5, 0.5, 0.5)
65 | else
66 | self.frame:EnableMouse(true)
67 | self.label:SetTextColor(1, 1, 1)
68 | end
69 | end
70 | }
71 |
72 | --[[-----------------------------------------------------------------------------
73 | Constructor
74 | -------------------------------------------------------------------------------]]
75 | local function Constructor()
76 | -- create a Label type that we will hijack
77 | local label = AceGUI:Create("Label")
78 |
79 | local frame = label.frame
80 | frame:EnableMouse(true)
81 | frame:SetScript("OnEnter", Control_OnEnter)
82 | frame:SetScript("OnLeave", Control_OnLeave)
83 | frame:SetScript("OnMouseDown", Label_OnClick)
84 |
85 | local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
86 | highlight:SetTexture(nil)
87 | highlight:SetAllPoints()
88 | highlight:SetBlendMode("ADD")
89 |
90 | label.highlight = highlight
91 | label.type = Type
92 | label.LabelOnAcquire = label.OnAcquire
93 | for method, func in pairs(methods) do
94 | label[method] = func
95 | end
96 |
97 | return label
98 | end
99 |
100 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
101 |
102 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIContainer-InlineGroup.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | InlineGroup Container
3 | Simple container widget that creates a visible "box" with an optional title.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "InlineGroup", 20
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local CreateFrame, UIParent = CreateFrame, UIParent
14 |
15 | --[[-----------------------------------------------------------------------------
16 | Methods
17 | -------------------------------------------------------------------------------]]
18 | local methods = {
19 | ["OnAcquire"] = function(self)
20 | self:SetWidth(300)
21 | self:SetHeight(100)
22 | end,
23 |
24 | -- ["OnRelease"] = nil,
25 |
26 | ["SetTitle"] = function(self,title)
27 | self.titletext:SetText(title)
28 | end,
29 |
30 |
31 | ["LayoutFinished"] = function(self, width, height)
32 | if self.noAutoHeight then return end
33 | self:SetHeight((height or 0) + 40)
34 | end,
35 |
36 | ["OnWidthSet"] = function(self, width)
37 | local content = self.content
38 | local contentwidth = width - 20
39 | if contentwidth < 0 then
40 | contentwidth = 0
41 | end
42 | content:SetWidth(contentwidth)
43 | content.width = contentwidth
44 | end,
45 |
46 | ["OnHeightSet"] = function(self, height)
47 | local content = self.content
48 | local contentheight = height - 20
49 | if contentheight < 0 then
50 | contentheight = 0
51 | end
52 | content:SetHeight(contentheight)
53 | content.height = contentheight
54 | end
55 | }
56 |
57 | --[[-----------------------------------------------------------------------------
58 | Constructor
59 | -------------------------------------------------------------------------------]]
60 | local PaneBackdrop = {
61 | bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
62 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
63 | tile = true, tileSize = 16, edgeSize = 16,
64 | insets = { left = 3, right = 3, top = 5, bottom = 3 }
65 | }
66 |
67 | local function Constructor()
68 | local frame = CreateFrame("Frame", nil, UIParent)
69 | frame:SetFrameStrata("FULLSCREEN_DIALOG")
70 |
71 | local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
72 | titletext:SetPoint("TOPLEFT", 14, 0)
73 | titletext:SetPoint("TOPRIGHT", -14, 0)
74 | titletext:SetJustifyH("LEFT")
75 | titletext:SetHeight(18)
76 |
77 | local border = CreateFrame("Frame", nil, frame)
78 | border:SetPoint("TOPLEFT", 0, -17)
79 | border:SetPoint("BOTTOMRIGHT", -1, 3)
80 | border:SetBackdrop(PaneBackdrop)
81 | border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
82 | border:SetBackdropBorderColor(0.4, 0.4, 0.4)
83 |
84 | --Container Support
85 | local content = CreateFrame("Frame", nil, border)
86 | content:SetPoint("TOPLEFT", 10, -10)
87 | content:SetPoint("BOTTOMRIGHT", -10, 10)
88 |
89 | local widget = {
90 | frame = frame,
91 | content = content,
92 | titletext = titletext,
93 | type = Type
94 | }
95 | for method, func in pairs(methods) do
96 | widget[method] = func
97 | end
98 |
99 | return AceGUI:RegisterAsContainer(widget)
100 | end
101 |
102 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
103 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIContainer-BlizOptionsGroup.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | BlizOptionsGroup Container
3 | Simple container widget for the integration of AceGUI into the Blizzard Interface Options
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "BlizOptionsGroup", 20
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local CreateFrame = CreateFrame
14 |
15 | --[[-----------------------------------------------------------------------------
16 | Scripts
17 | -------------------------------------------------------------------------------]]
18 |
19 | local function OnShow(frame)
20 | frame.obj:Fire("OnShow")
21 | end
22 |
23 | local function OnHide(frame)
24 | frame.obj:Fire("OnHide")
25 | end
26 |
27 | --[[-----------------------------------------------------------------------------
28 | Support functions
29 | -------------------------------------------------------------------------------]]
30 |
31 | local function okay(frame)
32 | frame.obj:Fire("okay")
33 | end
34 |
35 | local function cancel(frame)
36 | frame.obj:Fire("cancel")
37 | end
38 |
39 | local function defaults(frame)
40 | frame.obj:Fire("defaults")
41 | end
42 |
43 | --[[-----------------------------------------------------------------------------
44 | Methods
45 | -------------------------------------------------------------------------------]]
46 |
47 | local methods = {
48 | ["OnAcquire"] = function(self)
49 | self:SetName()
50 | self:SetTitle()
51 | end,
52 |
53 | -- ["OnRelease"] = nil,
54 |
55 | ["OnWidthSet"] = function(self, width)
56 | local content = self.content
57 | local contentwidth = width - 63
58 | if contentwidth < 0 then
59 | contentwidth = 0
60 | end
61 | content:SetWidth(contentwidth)
62 | content.width = contentwidth
63 | end,
64 |
65 | ["OnHeightSet"] = function(self, height)
66 | local content = self.content
67 | local contentheight = height - 26
68 | if contentheight < 0 then
69 | contentheight = 0
70 | end
71 | content:SetHeight(contentheight)
72 | content.height = contentheight
73 | end,
74 |
75 | ["SetName"] = function(self, name, parent)
76 | self.frame.name = name
77 | self.frame.parent = parent
78 | end,
79 |
80 | ["SetTitle"] = function(self, title)
81 | local content = self.content
82 | content:ClearAllPoints()
83 | if not title or title == "" then
84 | content:SetPoint("TOPLEFT", 10, -10)
85 | self.label:SetText("")
86 | else
87 | content:SetPoint("TOPLEFT", 10, -40)
88 | self.label:SetText(title)
89 | end
90 | content:SetPoint("BOTTOMRIGHT", -10, 10)
91 | end
92 | }
93 |
94 | --[[-----------------------------------------------------------------------------
95 | Constructor
96 | -------------------------------------------------------------------------------]]
97 | local function Constructor()
98 | local frame = CreateFrame("Frame")
99 | frame:Hide()
100 |
101 | -- support functions for the Blizzard Interface Options
102 | frame.okay = okay
103 | frame.cancel = cancel
104 | frame.defaults = defaults
105 |
106 | frame:SetScript("OnHide", OnHide)
107 | frame:SetScript("OnShow", OnShow)
108 |
109 | local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
110 | label:SetPoint("TOPLEFT", 10, -15)
111 | label:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", 10, -45)
112 | label:SetJustifyH("LEFT")
113 | label:SetJustifyV("TOP")
114 |
115 | --Container Support
116 | local content = CreateFrame("Frame", nil, frame)
117 | content:SetPoint("TOPLEFT", 10, -10)
118 | content:SetPoint("BOTTOMRIGHT", -10, 10)
119 |
120 | local widget = {
121 | label = label,
122 | frame = frame,
123 | content = content,
124 | type = Type
125 | }
126 | for method, func in pairs(methods) do
127 | widget[method] = func
128 | end
129 |
130 | return AceGUI:RegisterAsContainer(widget)
131 | end
132 |
133 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
134 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Icon Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "Icon", 20
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local select, pairs, print = select, pairs, print
10 |
11 | -- WoW APIs
12 | local CreateFrame, UIParent, GetBuildInfo = CreateFrame, UIParent, GetBuildInfo
13 |
14 | --[[-----------------------------------------------------------------------------
15 | Scripts
16 | -------------------------------------------------------------------------------]]
17 | local function Control_OnEnter(frame)
18 | frame.obj:Fire("OnEnter")
19 | end
20 |
21 | local function Control_OnLeave(frame)
22 | frame.obj:Fire("OnLeave")
23 | end
24 |
25 | local function Button_OnClick(frame, button)
26 | frame.obj:Fire("OnClick", button)
27 | AceGUI:ClearFocus()
28 | end
29 |
30 | --[[-----------------------------------------------------------------------------
31 | Methods
32 | -------------------------------------------------------------------------------]]
33 | local methods = {
34 | ["OnAcquire"] = function(self)
35 | self:SetHeight(110)
36 | self:SetWidth(110)
37 | self:SetLabel()
38 | self:SetImage(nil)
39 | self:SetImageSize(64, 64)
40 | self:SetDisabled(false)
41 | end,
42 |
43 | -- ["OnRelease"] = nil,
44 |
45 | ["SetLabel"] = function(self, text)
46 | if text and text ~= "" then
47 | self.label:Show()
48 | self.label:SetText(text)
49 | self:SetHeight(self.image:GetHeight() + 25)
50 | else
51 | self.label:Hide()
52 | self:SetHeight(self.image:GetHeight() + 10)
53 | end
54 | end,
55 |
56 | ["SetImage"] = function(self, path, ...)
57 | local image = self.image
58 | image:SetTexture(path)
59 |
60 | if image:GetTexture() then
61 | local n = select("#", ...)
62 | if n == 4 or n == 8 then
63 | image:SetTexCoord(...)
64 | else
65 | image:SetTexCoord(0, 1, 0, 1)
66 | end
67 | end
68 | end,
69 |
70 | ["SetImageSize"] = function(self, width, height)
71 | self.image:SetWidth(width)
72 | self.image:SetHeight(height)
73 | --self.frame:SetWidth(width + 30)
74 | if self.label:IsShown() then
75 | self:SetHeight(height + 25)
76 | else
77 | self:SetHeight(height + 10)
78 | end
79 | end,
80 |
81 | ["SetDisabled"] = function(self, disabled)
82 | self.disabled = disabled
83 | if disabled then
84 | self.frame:Disable()
85 | self.label:SetTextColor(0.5, 0.5, 0.5)
86 | self.image:SetVertexColor(0.5, 0.5, 0.5, 0.5)
87 | else
88 | self.frame:Enable()
89 | self.label:SetTextColor(1, 1, 1)
90 | self.image:SetVertexColor(1, 1, 1)
91 | end
92 | end
93 | }
94 |
95 | --[[-----------------------------------------------------------------------------
96 | Constructor
97 | -------------------------------------------------------------------------------]]
98 | local function Constructor()
99 | local frame = CreateFrame("Button", nil, UIParent)
100 | frame:Hide()
101 |
102 | frame:EnableMouse(true)
103 | frame:SetScript("OnEnter", Control_OnEnter)
104 | frame:SetScript("OnLeave", Control_OnLeave)
105 | frame:SetScript("OnClick", Button_OnClick)
106 |
107 | local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlight")
108 | label:SetPoint("BOTTOMLEFT")
109 | label:SetPoint("BOTTOMRIGHT")
110 | label:SetJustifyH("CENTER")
111 | label:SetJustifyV("TOP")
112 | label:SetHeight(18)
113 |
114 | local image = frame:CreateTexture(nil, "BACKGROUND")
115 | image:SetWidth(64)
116 | image:SetHeight(64)
117 | image:SetPoint("TOP", 0, -5)
118 |
119 | local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
120 | highlight:SetAllPoints(image)
121 | highlight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
122 | highlight:SetTexCoord(0, 1, 0.23, 0.77)
123 | highlight:SetBlendMode("ADD")
124 |
125 | local widget = {
126 | label = label,
127 | image = image,
128 | frame = frame,
129 | type = Type
130 | }
131 | for method, func in pairs(methods) do
132 | widget[method] = func
133 | end
134 | -- SetText is deprecated, but keep it around for a while. (say, to WoW 4.0)
135 | if (select(4, GetBuildInfo()) < 40000) then
136 | widget.SetText = widget.SetLabel
137 | else
138 | widget.SetText = function(self, ...) print("AceGUI-3.0-Icon: SetText is deprecated! Use SetLabel instead!"); self:SetLabel(...) end
139 | end
140 |
141 | return AceGUI:RegisterAsWidget(widget)
142 | end
143 |
144 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
145 |
--------------------------------------------------------------------------------
/AI_VoiceOver/SoundQueue.lua:
--------------------------------------------------------------------------------
1 | setfenv(1, VoiceOver)
2 | SoundQueue = {}
3 | SoundQueue.__index = SoundQueue
4 |
5 | function SoundQueue:new()
6 | local soundQueue = {}
7 | setmetatable(soundQueue, SoundQueue)
8 |
9 | soundQueue.soundIdCounter = 0
10 | soundQueue.sounds = {}
11 | soundQueue.ui = SoundQueueUI:new(soundQueue)
12 |
13 | return soundQueue
14 | end
15 |
16 | function SoundQueue:AddSoundToQueue(soundData)
17 | DataModules:PrepareSound(soundData)
18 |
19 | if soundData.fileName == nil or not Utils:WillSoundPlay(soundData) then
20 |
21 | if Addon.db.profile.DebugEnabled then
22 | print("Sound does not exist for: ", soundData.title or soundData.name)
23 | end
24 |
25 | if soundData.stopCallback then
26 | soundData.stopCallback()
27 | end
28 | return
29 | end
30 |
31 | -- Check if the sound is already in the queue
32 | for _, queuedSound in ipairs(self.sounds) do
33 | if queuedSound.fileName == soundData.fileName then
34 | return
35 | end
36 | end
37 |
38 | -- Don't play gossip if there are quest sounds in the queue
39 | local questSoundExists = false
40 | for _, queuedSound in ipairs(self.sounds) do
41 | if queuedSound.questID ~= nil then
42 | questSoundExists = true
43 | break
44 | end
45 | end
46 |
47 | if soundData.questID == nil and questSoundExists then
48 | return
49 | end
50 |
51 | self.soundIdCounter = self.soundIdCounter + 1
52 | soundData.id = self.soundIdCounter
53 |
54 | table.insert(self.sounds, soundData)
55 | self.ui:UpdateSoundQueueDisplay()
56 |
57 | -- If the sound queue only contains one sound, play it immediately
58 | if #self.sounds == 1 and not Addon.db.char.IsPaused then
59 | self:PlaySound(soundData)
60 | end
61 | end
62 |
63 | function SoundQueue:PlaySound(soundData)
64 | SetCVar("Sound_MusicVolume", 1)
65 | SetCVar("Sound_EnableMusic", 1)
66 |
67 | local channel = Enums.SoundChannel:GetName(Addon.db.profile.Audio.SoundChannel)
68 | -- local willPlay, handle = PlaySoundFile(soundData.filePath, channel)
69 | local willPlay, handle = PlayMusic(soundData.filePath, channel)
70 |
71 | if Addon.db.profile.Audio.AutoToggleDialog then
72 | -- SetCVar("Sound_EnableDialog", 0)
73 | end
74 |
75 | if soundData.startCallback then
76 | soundData.startCallback()
77 | end
78 | local nextSoundTimer = Addon:ScheduleTimer(function()
79 | self:RemoveSoundFromQueue(soundData)
80 | SetCVar("Sound_MusicVolume", 0)
81 | end, soundData.length + 0.05)
82 |
83 | soundData.nextSoundTimer = nextSoundTimer
84 | soundData.handle = handle
85 | end
86 |
87 | function SoundQueue:PauseQueue()
88 | if Addon.db.char.IsPaused then
89 | return
90 | end
91 |
92 | Addon.db.char.IsPaused = true
93 |
94 | if #self.sounds > 0 then
95 | local currentSound = self.sounds[1]
96 | StopSound(currentSound.handle)
97 | Addon:CancelTimer(currentSound.nextSoundTimer)
98 | end
99 |
100 | self.ui:UpdatePauseDisplay()
101 | end
102 |
103 | function SoundQueue:ResumeQueue()
104 | if not Addon.db.char.IsPaused then
105 | return
106 | end
107 |
108 | Addon.db.char.IsPaused = false
109 | if #self.sounds > 0 then
110 | local currentSound = self.sounds[1]
111 | self:PlaySound(currentSound)
112 | end
113 |
114 | self.ui:UpdatePauseDisplay()
115 | end
116 |
117 | function SoundQueue:TogglePauseQueue()
118 | if Addon.db.char.IsPaused then
119 | self:ResumeQueue()
120 | else
121 | self:PauseQueue()
122 | end
123 | end
124 |
125 | function SoundQueue:RemoveSoundFromQueue(soundData)
126 | local removedIndex = nil
127 | for index, queuedSound in ipairs(self.sounds) do
128 | if queuedSound.id == soundData.id then
129 | removedIndex = index
130 | table.remove(self.sounds, index)
131 | break
132 | end
133 | end
134 |
135 | if soundData.stopCallback then
136 | soundData.stopCallback()
137 | end
138 |
139 | if removedIndex == 1 and not Addon.db.char.IsPaused then
140 | StopSound(soundData.handle)
141 | Addon:CancelTimer(soundData.nextSoundTimer)
142 |
143 | if #self.sounds > 0 then
144 | local nextSoundData = self.sounds[1]
145 | self:PlaySound(nextSoundData)
146 | end
147 | end
148 |
149 | if #self.sounds == 0 and Addon.db.profile.Audio.AutoToggleDialog then
150 | -- SetCVar("Sound_EnableDialog", 1)
151 | end
152 |
153 | self.ui:UpdateSoundQueueDisplay()
154 | end
155 |
156 | function SoundQueue:RemoveAllSoundsFromQueue()
157 | for i = #self.sounds, 1, -1 do
158 | if (self.sounds[i]) then
159 | self:RemoveSoundFromQueue(self.sounds[i])
160 | end
161 | end
162 | end
163 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Label Widget
3 | Displays text and optionally an icon.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "Label", 21
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local max, select, pairs = math.max, select, pairs
11 |
12 | -- WoW APIs
13 | local CreateFrame, UIParent = CreateFrame, UIParent
14 |
15 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
16 | -- List them here for Mikk's FindGlobals script
17 | -- GLOBALS: GameFontHighlightSmall
18 |
19 | --[[-----------------------------------------------------------------------------
20 | Support functions
21 | -------------------------------------------------------------------------------]]
22 |
23 | local function UpdateImageAnchor(self)
24 | if self.resizing then return end
25 | local frame = self.frame
26 | local width = frame.width or frame:GetWidth() or 0
27 | local image = self.image
28 | local label = self.label
29 | local height
30 |
31 | label:ClearAllPoints()
32 | image:ClearAllPoints()
33 |
34 | if self.imageshown then
35 | local imagewidth = image:GetWidth()
36 | if (width - imagewidth) < 200 or (label:GetText() or "") == "" then
37 | -- image goes on top centered when less than 200 width for the text, or if there is no text
38 | image:SetPoint("TOP")
39 | label:SetPoint("TOP", image, "BOTTOM")
40 | label:SetPoint("LEFT")
41 | label:SetWidth(width)
42 | height = image:GetHeight() + label:GetHeight()
43 | else
44 | -- image on the left
45 | image:SetPoint("TOPLEFT")
46 | label:SetPoint("TOPLEFT", image, "TOPRIGHT", 4, 0)
47 | label:SetWidth(width - imagewidth - 4)
48 | height = max(image:GetHeight(), label:GetHeight())
49 | end
50 | else
51 | -- no image shown
52 | label:SetPoint("TOPLEFT")
53 | label:SetWidth(width)
54 | height = label:GetHeight()
55 | end
56 |
57 | self.resizing = true
58 | frame:SetHeight(height)
59 | frame.height = height
60 | self.resizing = nil
61 | end
62 |
63 | --[[-----------------------------------------------------------------------------
64 | Methods
65 | -------------------------------------------------------------------------------]]
66 | local methods = {
67 | ["OnAcquire"] = function(self)
68 | -- set the flag to stop constant size updates
69 | self.resizing = true
70 | -- height is set dynamically by the text and image size
71 | self:SetWidth(200)
72 | self:SetText()
73 | self:SetImage(nil)
74 | self:SetImageSize(16, 16)
75 | self:SetColor()
76 | self:SetFontObject()
77 |
78 | -- reset the flag
79 | self.resizing = nil
80 | -- run the update explicitly
81 | UpdateImageAnchor(self)
82 | end,
83 |
84 | -- ["OnRelease"] = nil,
85 |
86 | ["OnWidthSet"] = function(self, width)
87 | UpdateImageAnchor(self)
88 | end,
89 |
90 | ["SetText"] = function(self, text)
91 | self.label:SetText(text)
92 | UpdateImageAnchor(self)
93 | end,
94 |
95 | ["SetColor"] = function(self, r, g, b)
96 | if not (r and g and b) then
97 | r, g, b = 1, 1, 1
98 | end
99 | self.label:SetVertexColor(r, g, b)
100 | end,
101 |
102 | ["SetImage"] = function(self, path, ...)
103 | local image = self.image
104 | image:SetTexture(path)
105 |
106 | if image:GetTexture() then
107 | self.imageshown = true
108 | local n = select("#", ...)
109 | if n == 4 or n == 8 then
110 | image:SetTexCoord(...)
111 | else
112 | image:SetTexCoord(0, 1, 0, 1)
113 | end
114 | else
115 | self.imageshown = nil
116 | end
117 | UpdateImageAnchor(self)
118 | end,
119 |
120 | ["SetFont"] = function(self, font, height, flags)
121 | self.label:SetFont(font, height, flags)
122 | end,
123 |
124 | ["SetFontObject"] = function(self, font)
125 | self:SetFont((font or GameFontHighlightSmall):GetFont())
126 | end,
127 |
128 | ["SetImageSize"] = function(self, width, height)
129 | self.image:SetWidth(width)
130 | self.image:SetHeight(height)
131 | UpdateImageAnchor(self)
132 | end,
133 | }
134 |
135 | --[[-----------------------------------------------------------------------------
136 | Constructor
137 | -------------------------------------------------------------------------------]]
138 | local function Constructor()
139 | local frame = CreateFrame("Frame", nil, UIParent)
140 | frame:Hide()
141 |
142 | local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightSmall")
143 | label:SetJustifyH("LEFT")
144 | label:SetJustifyV("TOP")
145 |
146 | local image = frame:CreateTexture(nil, "BACKGROUND")
147 |
148 | -- create widget
149 | local widget = {
150 | label = label,
151 | image = image,
152 | frame = frame,
153 | type = Type
154 | }
155 | for method, func in pairs(methods) do
156 | widget[method] = func
157 | end
158 |
159 | return AceGUI:RegisterAsWidget(widget)
160 | end
161 |
162 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
163 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceEvent-3.0/AceEvent-3.0.lua:
--------------------------------------------------------------------------------
1 | --- AceEvent-3.0 provides event registration and secure dispatching.
2 | -- All dispatching is done using **CallbackHandler-1.0**. AceEvent is a simple wrapper around
3 | -- CallbackHandler, and dispatches all game events or addon message to the registrees.
4 | --
5 | -- **AceEvent-3.0** can be embeded into your addon, either explicitly by calling AceEvent:Embed(MyAddon) or by
6 | -- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
7 | -- and can be accessed directly, without having to explicitly call AceEvent itself.\\
8 | -- It is recommended to embed AceEvent, otherwise you'll have to specify a custom `self` on all calls you
9 | -- make into AceEvent.
10 | -- @class file
11 | -- @name AceEvent-3.0
12 | -- @release $Id: AceEvent-3.0.lua 877 2009-11-02 15:56:50Z nevcairiel $
13 | local MAJOR, MINOR = "AceEvent-3.0", 3
14 | local AceEvent = LibStub:NewLibrary(MAJOR, MINOR)
15 |
16 | if not AceEvent then return end
17 |
18 | -- Lua APIs
19 | local pairs = pairs
20 |
21 | local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
22 |
23 | AceEvent.frame = AceEvent.frame or CreateFrame("Frame", "AceEvent30Frame") -- our event frame
24 | AceEvent.embeds = AceEvent.embeds or {} -- what objects embed this lib
25 |
26 | -- APIs and registry for blizzard events, using CallbackHandler lib
27 | if not AceEvent.events then
28 | AceEvent.events = CallbackHandler:New(AceEvent,
29 | "RegisterEvent", "UnregisterEvent", "UnregisterAllEvents")
30 | end
31 |
32 | function AceEvent.events:OnUsed(target, eventname)
33 | AceEvent.frame:RegisterEvent(eventname)
34 | end
35 |
36 | function AceEvent.events:OnUnused(target, eventname)
37 | AceEvent.frame:UnregisterEvent(eventname)
38 | end
39 |
40 |
41 | -- APIs and registry for IPC messages, using CallbackHandler lib
42 | if not AceEvent.messages then
43 | AceEvent.messages = CallbackHandler:New(AceEvent,
44 | "RegisterMessage", "UnregisterMessage", "UnregisterAllMessages"
45 | )
46 | AceEvent.SendMessage = AceEvent.messages.Fire
47 | end
48 |
49 | --- embedding and embed handling
50 | local mixins = {
51 | "RegisterEvent", "UnregisterEvent",
52 | "RegisterMessage", "UnregisterMessage",
53 | "SendMessage",
54 | "UnregisterAllEvents", "UnregisterAllMessages",
55 | }
56 |
57 | --- Register for a Blizzard Event.
58 | -- The callback will always be called with the event as the first argument, and if supplied, the `arg` as second argument.
59 | -- Any arguments to the event will be passed on after that.
60 | -- @name AceEvent:RegisterEvent
61 | -- @class function
62 | -- @paramsig event[, callback [, arg]]
63 | -- @param event The event to register for
64 | -- @param callback The callback function to call when the event is triggered (funcref or method, defaults to a method with the event name)
65 | -- @param arg An optional argument to pass to the callback function
66 |
67 | --- Unregister an event.
68 | -- @name AceEvent:UnregisterEvent
69 | -- @class function
70 | -- @paramsig event
71 | -- @param event The event to unregister
72 |
73 | --- Register for a custom AceEvent-internal message.
74 | -- The callback will always be called with the event as the first argument, and if supplied, the `arg` as second argument.
75 | -- Any arguments to the event will be passed on after that.
76 | -- @name AceEvent:RegisterMessage
77 | -- @class function
78 | -- @paramsig message[, callback [, arg]]
79 | -- @param message The message to register for
80 | -- @param callback The callback function to call when the message is triggered (funcref or method, defaults to a method with the event name)
81 | -- @param arg An optional argument to pass to the callback function
82 |
83 | --- Unregister a message
84 | -- @name AceEvent:UnregisterMessage
85 | -- @class function
86 | -- @paramsig message
87 | -- @param message The message to unregister
88 |
89 | --- Send a message over the AceEvent-3.0 internal message system to other addons registered for this message.
90 | -- @name AceEvent:SendMessage
91 | -- @class function
92 | -- @paramsig message, ...
93 | -- @param message The message to send
94 | -- @param ... Any arguments to the message
95 |
96 |
97 | -- Embeds AceEvent into the target object making the functions from the mixins list available on target:..
98 | -- @param target target object to embed AceEvent in
99 | function AceEvent:Embed(target)
100 | for k, v in pairs(mixins) do
101 | target[v] = self[v]
102 | end
103 | self.embeds[target] = true
104 | return target
105 | end
106 |
107 | -- AceEvent:OnEmbedDisable( target )
108 | -- target (object) - target object that is being disabled
109 | --
110 | -- Unregister all events messages etc when the target disables.
111 | -- this method should be called by the target manually or by an addon framework
112 | function AceEvent:OnEmbedDisable(target)
113 | target:UnregisterAllEvents()
114 | target:UnregisterAllMessages()
115 | end
116 |
117 | -- Script to fire blizzard events into the event listeners
118 | local events = AceEvent.events
119 | AceEvent.frame:SetScript("OnEvent", function(this, event, ...)
120 | events:Fire(event, ...)
121 | end)
122 |
123 | --- Finally: upgrade our old embeds
124 | for target, v in pairs(AceEvent.embeds) do
125 | AceEvent:Embed(target)
126 | end
127 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIContainer-DropDownGroup.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | DropdownGroup Container
3 | Container controlled by a dropdown on the top.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "DropdownGroup", 20
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local assert, pairs, type = assert, pairs, type
11 |
12 | -- WoW APIs
13 | local CreateFrame = CreateFrame
14 |
15 | --[[-----------------------------------------------------------------------------
16 | Scripts
17 | -------------------------------------------------------------------------------]]
18 | local function SelectedGroup(self, event, value)
19 | local group = self.parentgroup
20 | local status = group.status or group.localstatus
21 | status.selected = value
22 | self.parentgroup:Fire("OnGroupSelected", value)
23 | end
24 |
25 | --[[-----------------------------------------------------------------------------
26 | Methods
27 | -------------------------------------------------------------------------------]]
28 | local methods = {
29 | ["OnAcquire"] = function(self)
30 | self.dropdown:SetText("")
31 | self:SetDropdownWidth(200)
32 | self:SetTitle("")
33 | end,
34 |
35 | ["OnRelease"] = function(self)
36 | self.dropdown.list = nil
37 | self.status = nil
38 | for k in pairs(self.localstatus) do
39 | self.localstatus[k] = nil
40 | end
41 | end,
42 |
43 | ["SetTitle"] = function(self, title)
44 | self.titletext:SetText(title)
45 | self.dropdown.frame:ClearAllPoints()
46 | if title and title ~= "" then
47 | self.dropdown.frame:SetPoint("TOPRIGHT", -2, 0)
48 | else
49 | self.dropdown.frame:SetPoint("TOPLEFT", -1, 0)
50 | end
51 | end,
52 |
53 | ["SetGroupList"] = function(self,list)
54 | self.dropdown:SetList(list)
55 | end,
56 |
57 | ["SetStatusTable"] = function(self, status)
58 | assert(type(status) == "table")
59 | self.status = status
60 | end,
61 |
62 | ["SetGroup"] = function(self,group)
63 | self.dropdown:SetValue(group)
64 | local status = self.status or self.localstatus
65 | status.selected = group
66 | self:Fire("OnGroupSelected", group)
67 | end,
68 |
69 | ["OnWidthSet"] = function(self, width)
70 | local content = self.content
71 | local contentwidth = width - 26
72 | if contentwidth < 0 then
73 | contentwidth = 0
74 | end
75 | content:SetWidth(contentwidth)
76 | content.width = contentwidth
77 | end,
78 |
79 | ["OnHeightSet"] = function(self, height)
80 | local content = self.content
81 | local contentheight = height - 63
82 | if contentheight < 0 then
83 | contentheight = 0
84 | end
85 | content:SetHeight(contentheight)
86 | content.height = contentheight
87 | end,
88 |
89 | ["LayoutFinished"] = function(self, width, height)
90 | self:SetHeight((height or 0) + 63)
91 | end,
92 |
93 | ["SetDropdownWidth"] = function(self, width)
94 | self.dropdown:SetWidth(width)
95 | end
96 | }
97 |
98 | --[[-----------------------------------------------------------------------------
99 | Constructor
100 | -------------------------------------------------------------------------------]]
101 | local PaneBackdrop = {
102 | bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
103 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
104 | tile = true, tileSize = 16, edgeSize = 16,
105 | insets = { left = 3, right = 3, top = 5, bottom = 3 }
106 | }
107 |
108 | local function Constructor()
109 | local frame = CreateFrame("Frame")
110 | frame:SetHeight(100)
111 | frame:SetWidth(100)
112 | frame:SetFrameStrata("FULLSCREEN_DIALOG")
113 |
114 | local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
115 | titletext:SetPoint("TOPLEFT", 4, -5)
116 | titletext:SetPoint("TOPRIGHT", -4, -5)
117 | titletext:SetJustifyH("LEFT")
118 | titletext:SetHeight(18)
119 |
120 | local dropdown = AceGUI:Create("Dropdown")
121 | dropdown.frame:SetParent(frame)
122 | dropdown.frame:SetFrameLevel(dropdown.frame:GetFrameLevel() + 2)
123 | dropdown:SetCallback("OnValueChanged", SelectedGroup)
124 | dropdown.frame:SetPoint("TOPLEFT", -1, 0)
125 | dropdown.frame:Show()
126 | dropdown:SetLabel("")
127 |
128 | local border = CreateFrame("Frame", nil, frame)
129 | border:SetPoint("TOPLEFT", 0, -26)
130 | border:SetPoint("BOTTOMRIGHT", 0, 3)
131 | border:SetBackdrop(PaneBackdrop)
132 | border:SetBackdropColor(0.1,0.1,0.1,0.5)
133 | border:SetBackdropBorderColor(0.4,0.4,0.4)
134 |
135 | --Container Support
136 | local content = CreateFrame("Frame", nil, border)
137 | content:SetPoint("TOPLEFT", 10, -10)
138 | content:SetPoint("BOTTOMRIGHT", -10, 10)
139 |
140 | local widget = {
141 | frame = frame,
142 | localstatus = {},
143 | titletext = titletext,
144 | dropdown = dropdown,
145 | border = border,
146 | content = content,
147 | type = Type
148 | }
149 | for method, func in pairs(methods) do
150 | widget[method] = func
151 | end
152 | dropdown.parentgroup = widget
153 |
154 | return AceGUI:RegisterAsContainer(widget)
155 | end
156 |
157 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
158 |
--------------------------------------------------------------------------------
/AI_VoiceOver/QuestOverlayUI.lua:
--------------------------------------------------------------------------------
1 | setfenv(1, VoiceOver)
2 | QuestOverlayUI = {}
3 | QuestOverlayUI.__index = QuestOverlayUI
4 |
5 | function QuestOverlayUI:new(soundQueue)
6 | local questOverlayUI = {}
7 | setmetatable(questOverlayUI, QuestOverlayUI)
8 |
9 | questOverlayUI.soundQueue = soundQueue
10 | questOverlayUI.questPlayButtons = {}
11 | questOverlayUI.playingStates = {}
12 | questOverlayUI.displayedButtons = {}
13 | return questOverlayUI
14 | end
15 |
16 | function QuestOverlayUI:CreatePlayButton(questID)
17 | local playButton = CreateFrame("Button", nil, QuestLogFrame)
18 | playButton:SetWidth(20)
19 | playButton:SetHeight(20)
20 | playButton:SetHitRectInsets(2, 2, 2, 2)
21 | playButton:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up")
22 | playButton:SetDisabledTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up")
23 | playButton:GetDisabledTexture():SetDesaturated(true)
24 | playButton:GetDisabledTexture():SetAlpha(0.33)
25 | playButton:SetHighlightTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Highlight")
26 | self.questPlayButtons[questID] = playButton
27 | end
28 |
29 | function QuestOverlayUI:UpdateQuestTitle(questLogTitleFrame, playButton, normalText, questCheck)
30 | playButton:SetPoint("LEFT", normalText, "LEFT", 4, 0)
31 |
32 | local formatedText = [[|TInterface\AddOns\AI_VoiceOver\Textures\spacer:1:24|t]] .. (normalText:GetText() or ""):trim()
33 |
34 | normalText:SetText(formatedText)
35 | QuestLogDummyText:SetText(formatedText)
36 |
37 | questCheck:SetPoint("LEFT", normalText, "LEFT", normalText:GetStringWidth(), 0)
38 | end
39 |
40 | function QuestOverlayUI:UpdatePlayButtonTexture(questID, isPlaying)
41 | local texturePath = isPlaying and "Interface\\TIMEMANAGER\\ResetButton" or
42 | "Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up"
43 |
44 | if self.questPlayButtons[questID] then
45 | self.questPlayButtons[questID]:SetNormalTexture(texturePath)
46 | end
47 | end
48 |
49 | function QuestOverlayUI:UpdatePlayButton(soundTitle, questID, questLogTitleFrame, normalText, questCheck)
50 | self.questPlayButtons[questID]:SetParent(questLogTitleFrame:GetParent())
51 | self.questPlayButtons[questID]:SetFrameLevel(questLogTitleFrame:GetFrameLevel() + 2)
52 |
53 | QuestOverlayUI:UpdateQuestTitle(questLogTitleFrame, self.questPlayButtons[questID], normalText, questCheck)
54 |
55 | local questOverlayUI = self
56 | self.questPlayButtons[questID]:SetScript("OnClick", function(self)
57 | if questOverlayUI.questPlayButtons[questID].soundData == nil then
58 | local npcID = DataModules:GetQuestLogNPCID(questID) -- TODO: Add fallbacks to item and object questgivers once VO for them is made
59 | questOverlayUI.questPlayButtons[questID].soundData = {
60 | event = Enums.SoundEvent.QuestAccept,
61 | questID = questID,
62 | name = npcID and DataModules:GetNPCName(npcID) or "Unknown Name",
63 | title = soundTitle,
64 | unitGUID = npcID and Utils:MakeGUID(Enums.GUID.Creature, npcID)
65 | }
66 | end
67 |
68 | local button = self
69 | local soundData = button.soundData
70 | local questID = soundData.questID
71 | local isPlaying = questOverlayUI.playingStates[questID] or false
72 |
73 | if not isPlaying then
74 | questOverlayUI.soundQueue:AddSoundToQueue(soundData)
75 | questOverlayUI.playingStates[questID] = true
76 | questOverlayUI:UpdatePlayButtonTexture(questID, true)
77 |
78 | soundData.stopCallback = function()
79 | questOverlayUI.playingStates[questID] = false
80 | questOverlayUI:UpdatePlayButtonTexture(questID, false)
81 | button.soundData = nil
82 | end
83 | else
84 | questOverlayUI.soundQueue:RemoveSoundFromQueue(soundData)
85 | end
86 | end)
87 | end
88 |
89 |
90 | function QuestOverlayUI:UpdateQuestOverlayUI()
91 | local numEntries, numQuests = GetNumQuestLogEntries()
92 |
93 | -- Hide all buttons in displayedButtons
94 | for _, button in pairs(self.displayedButtons) do
95 | button:Hide()
96 | end
97 |
98 | if numEntries == 0 then
99 | return
100 | end
101 |
102 | -- Clear displayedButtons
103 | table.wipe(self.displayedButtons)
104 |
105 | -- Traverse through the quests displayed in the UI
106 | for i = 1, GetNumQuestLogEntries() do
107 | local questIndex = i + Utils:GetQuestLogScrollOffset();
108 | if questIndex > numEntries then
109 | break
110 | end
111 |
112 | -- Get quest title
113 | local questLogTitleFrame = Utils:GetQuestLogTitleFrame(i)
114 | local normalText = Utils:GetQuestLogTitleNormalText(i)
115 | local questCheck = Utils:GetQuestLogTitleCheck(i)
116 | local title, _, _, _, isHeader, isCollapsed, isComplete, isDaily, questID, displayQuestID = GetQuestLogTitle(
117 | questIndex)
118 |
119 | if not self.questPlayButtons[questID] then
120 | self:CreatePlayButton(questID)
121 | end
122 |
123 | if not isHeader then
124 | if DataModules:PrepareSound({ event = Enums.SoundEvent.QuestAccept, questID = questID }) then
125 | self:UpdatePlayButton(title, questID, questLogTitleFrame, normalText, questCheck)
126 | self.questPlayButtons[questID]:Enable()
127 | else
128 | self:UpdateQuestTitle(questLogTitleFrame, self.questPlayButtons[questID], normalText, questCheck)
129 | self.questPlayButtons[questID]:Disable()
130 | end
131 |
132 | self.questPlayButtons[questID]:Show()
133 | local isPlaying = self.playingStates[questID] or false
134 | self:UpdatePlayButtonTexture(questID, isPlaying)
135 |
136 | -- Add the button to displayedButtons
137 | table.insert(self.displayedButtons, self.questPlayButtons[questID])
138 | end
139 | end
140 | end
141 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | ColorPicker Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "ColorPicker", 20
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local pairs = pairs
10 |
11 | -- WoW APIs
12 | local CreateFrame, UIParent = CreateFrame, UIParent
13 |
14 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
15 | -- List them here for Mikk's FindGlobals script
16 | -- GLOBALS: ShowUIPanel, HideUIPanel, ColorPickerFrame, OpacitySliderFrame
17 |
18 | --[[-----------------------------------------------------------------------------
19 | Support functions
20 | -------------------------------------------------------------------------------]]
21 | local function ColorCallback(self, r, g, b, a, isAlpha)
22 | if not self.HasAlpha then
23 | a = 1
24 | end
25 | self:SetColor(r, g, b, a)
26 | if ColorPickerFrame:IsVisible() then
27 | --colorpicker is still open
28 | self:Fire("OnValueChanged", r, g, b, a)
29 | else
30 | --colorpicker is closed, color callback is first, ignore it,
31 | --alpha callback is the final call after it closes so confirm now
32 | if isAlpha then
33 | self:Fire("OnValueConfirmed", r, g, b, a)
34 | end
35 | end
36 | end
37 |
38 | --[[-----------------------------------------------------------------------------
39 | Scripts
40 | -------------------------------------------------------------------------------]]
41 | local function Control_OnEnter(frame)
42 | frame.obj:Fire("OnEnter")
43 | end
44 |
45 | local function Control_OnLeave(frame)
46 | frame.obj:Fire("OnLeave")
47 | end
48 |
49 | local function ColorSwatch_OnClick(frame)
50 | HideUIPanel(ColorPickerFrame)
51 | local self = frame.obj
52 | if not self.disabled then
53 | ColorPickerFrame:SetFrameStrata("FULLSCREEN_DIALOG")
54 |
55 | ColorPickerFrame.func = function()
56 | local r, g, b = ColorPickerFrame:GetColorRGB()
57 | local a = 1 - OpacitySliderFrame:GetValue()
58 | ColorCallback(self, r, g, b, a)
59 | end
60 |
61 | ColorPickerFrame.hasOpacity = self.HasAlpha
62 | ColorPickerFrame.opacityFunc = function()
63 | local r, g, b = ColorPickerFrame:GetColorRGB()
64 | local a = 1 - OpacitySliderFrame:GetValue()
65 | ColorCallback(self, r, g, b, a, true)
66 | end
67 |
68 | local r, g, b, a = self.r, self.g, self.b, self.a
69 | if self.HasAlpha then
70 | ColorPickerFrame.opacity = 1 - (a or 0)
71 | end
72 | ColorPickerFrame:SetColorRGB(r, g, b)
73 |
74 | ColorPickerFrame.cancelFunc = function()
75 | ColorCallback(self, r, g, b, a, true)
76 | end
77 |
78 | ShowUIPanel(ColorPickerFrame)
79 | end
80 | AceGUI:ClearFocus()
81 | end
82 |
83 | --[[-----------------------------------------------------------------------------
84 | Methods
85 | -------------------------------------------------------------------------------]]
86 | local methods = {
87 | ["OnAcquire"] = function(self)
88 | self:SetHeight(24)
89 | self:SetWidth(200)
90 | self:SetHasAlpha(false)
91 | self:SetColor(0, 0, 0, 1)
92 | self:SetDisabled(nil)
93 | self:SetLabel(nil)
94 | end,
95 |
96 | -- ["OnRelease"] = nil,
97 |
98 | ["SetLabel"] = function(self, text)
99 | self.text:SetText(text)
100 | end,
101 |
102 | ["SetColor"] = function(self, r, g, b, a)
103 | self.r = r
104 | self.g = g
105 | self.b = b
106 | self.a = a or 1
107 | self.colorSwatch:SetVertexColor(r, g, b, a)
108 | end,
109 |
110 | ["SetHasAlpha"] = function(self, HasAlpha)
111 | self.HasAlpha = HasAlpha
112 | end,
113 |
114 | ["SetDisabled"] = function(self, disabled)
115 | self.disabled = disabled
116 | if self.disabled then
117 | self.frame:Disable()
118 | self.text:SetTextColor(0.5, 0.5, 0.5)
119 | else
120 | self.frame:Enable()
121 | self.text:SetTextColor(1, 1, 1)
122 | end
123 | end
124 | }
125 |
126 | --[[-----------------------------------------------------------------------------
127 | Constructor
128 | -------------------------------------------------------------------------------]]
129 | local function Constructor()
130 | local frame = CreateFrame("Button", nil, UIParent)
131 | frame:Hide()
132 |
133 | frame:EnableMouse(true)
134 | frame:SetScript("OnEnter", Control_OnEnter)
135 | frame:SetScript("OnLeave", Control_OnLeave)
136 | frame:SetScript("OnClick", ColorSwatch_OnClick)
137 |
138 | local colorSwatch = frame:CreateTexture(nil, "OVERLAY")
139 | colorSwatch:SetWidth(19)
140 | colorSwatch:SetHeight(19)
141 | colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch")
142 | colorSwatch:SetPoint("LEFT")
143 |
144 | local texture = frame:CreateTexture(nil, "BACKGROUND")
145 | texture:SetWidth(16)
146 | texture:SetHeight(16)
147 | texture:SetTexture(1, 1, 1)
148 | texture:SetPoint("CENTER", colorSwatch)
149 | texture:Show()
150 |
151 | local checkers = frame:CreateTexture(nil, "BACKGROUND")
152 | checkers:SetWidth(14)
153 | checkers:SetHeight(14)
154 | checkers:SetTexture("Tileset\\Generic\\Checkers")
155 | checkers:SetTexCoord(.25, 0, 0.5, .25)
156 | checkers:SetDesaturated(true)
157 | checkers:SetVertexColor(1, 1, 1, 0.75)
158 | checkers:SetPoint("CENTER", colorSwatch)
159 | checkers:Show()
160 |
161 | local text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
162 | text:SetHeight(24)
163 | text:SetJustifyH("LEFT")
164 | text:SetTextColor(1, 1, 1)
165 | text:SetPoint("LEFT", colorSwatch, "RIGHT", 2, 0)
166 | text:SetPoint("RIGHT")
167 |
168 | --local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
169 | --highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
170 | --highlight:SetBlendMode("ADD")
171 | --highlight:SetAllPoints(frame)
172 |
173 | local widget = {
174 | colorSwatch = colorSwatch,
175 | text = text,
176 | frame = frame,
177 | type = Type
178 | }
179 | for method, func in pairs(methods) do
180 | widget[method] = func
181 | end
182 |
183 | return AceGUI:RegisterAsWidget(widget)
184 | end
185 |
186 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
187 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Keybinding Widget
3 | Set Keybindings in the Config UI.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "Keybinding", 21
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs = pairs
11 |
12 | -- WoW APIs
13 | local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown
14 | local CreateFrame, UIParent = CreateFrame, UIParent
15 |
16 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
17 | -- List them here for Mikk's FindGlobals script
18 | -- GLOBALS: NOT_BOUND
19 |
20 | --[[-----------------------------------------------------------------------------
21 | Scripts
22 | -------------------------------------------------------------------------------]]
23 |
24 | local function Control_OnEnter(frame)
25 | frame.obj:Fire("OnEnter")
26 | end
27 |
28 | local function Control_OnLeave(frame)
29 | frame.obj:Fire("OnLeave")
30 | end
31 |
32 | local function Keybinding_OnClick(frame, button)
33 | if button == "LeftButton" or button == "RightButton" then
34 | local self = frame.obj
35 | if self.waitingForKey then
36 | frame:EnableKeyboard(false)
37 | self.msgframe:Hide()
38 | frame:UnlockHighlight()
39 | self.waitingForKey = nil
40 | else
41 | frame:EnableKeyboard(true)
42 | self.msgframe:Show()
43 | frame:LockHighlight()
44 | self.waitingForKey = true
45 | end
46 | end
47 | AceGUI:ClearFocus()
48 | end
49 |
50 | local ignoreKeys = {
51 | ["BUTTON1"] = true, ["BUTTON2"] = true,
52 | ["UNKNOWN"] = true,
53 | ["LSHIFT"] = true, ["LCTRL"] = true, ["LALT"] = true,
54 | ["RSHIFT"] = true, ["RCTRL"] = true, ["RALT"] = true,
55 | }
56 | local function Keybinding_OnKeyDown(frame, key)
57 | local self = frame.obj
58 | if self.waitingForKey then
59 | local keyPressed = key
60 | if keyPressed == "ESCAPE" then
61 | keyPressed = ""
62 | else
63 | if ignoreKeys[keyPressed] then return end
64 | if IsShiftKeyDown() then
65 | keyPressed = "SHIFT-"..keyPressed
66 | end
67 | if IsControlKeyDown() then
68 | keyPressed = "CTRL-"..keyPressed
69 | end
70 | if IsAltKeyDown() then
71 | keyPressed = "ALT-"..keyPressed
72 | end
73 | end
74 |
75 | frame:EnableKeyboard(false)
76 | self.msgframe:Hide()
77 | frame:UnlockHighlight()
78 | self.waitingForKey = nil
79 |
80 | if not self.disabled then
81 | self:SetKey(keyPressed)
82 | self:Fire("OnKeyChanged", keyPressed)
83 | end
84 | end
85 | end
86 |
87 | local function Keybinding_OnMouseDown(frame, button)
88 | if button == "LeftButton" or button == "RightButton" then
89 | return
90 | elseif button == "MiddleButton" then
91 | button = "BUTTON3"
92 | elseif button == "Button4" then
93 | button = "BUTTON4"
94 | elseif button == "Button5" then
95 | button = "BUTTON5"
96 | end
97 | Keybinding_OnKeyDown(frame, button)
98 | end
99 |
100 | --[[-----------------------------------------------------------------------------
101 | Methods
102 | -------------------------------------------------------------------------------]]
103 | local methods = {
104 | ["OnAcquire"] = function(self)
105 | self:SetWidth(200)
106 | self:SetLabel("")
107 | self:SetKey("")
108 | self.waitingForKey = nil
109 | self.msgframe:Hide()
110 | self:SetDisabled(false)
111 | end,
112 |
113 | -- ["OnRelease"] = nil,
114 |
115 | ["SetDisabled"] = function(self, disabled)
116 | self.disabled = disabled
117 | if disabled then
118 | self.button:Disable()
119 | self.label:SetTextColor(0.5,0.5,0.5)
120 | else
121 | self.button:Enable()
122 | self.label:SetTextColor(1,1,1)
123 | end
124 | end,
125 |
126 | ["SetKey"] = function(self, key)
127 | if (key or "") == "" then
128 | self.button:SetText(NOT_BOUND)
129 | self.button:SetNormalFontObject("GameFontNormal")
130 | else
131 | self.button:SetText(key)
132 | self.button:SetNormalFontObject("GameFontHighlight")
133 | end
134 | end,
135 |
136 | ["GetKey"] = function(self)
137 | local key = self.button:GetText()
138 | if key == NOT_BOUND then
139 | key = nil
140 | end
141 | return key
142 | end,
143 |
144 | ["SetLabel"] = function(self, label)
145 | self.label:SetText(label or "")
146 | if (label or "") == "" then
147 | self.alignoffset = nil
148 | self:SetHeight(24)
149 | else
150 | self.alignoffset = 30
151 | self:SetHeight(44)
152 | end
153 | end,
154 | }
155 |
156 | --[[-----------------------------------------------------------------------------
157 | Constructor
158 | -------------------------------------------------------------------------------]]
159 |
160 | local ControlBackdrop = {
161 | bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
162 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
163 | tile = true, tileSize = 16, edgeSize = 16,
164 | insets = { left = 3, right = 3, top = 3, bottom = 3 }
165 | }
166 |
167 | local function keybindingMsgFixWidth(frame)
168 | frame:SetWidth(frame.msg:GetWidth() + 10)
169 | frame:SetScript("OnUpdate", nil)
170 | end
171 |
172 | local function Constructor()
173 | local name = "AceGUI30KeybindingButton" .. AceGUI:GetNextWidgetNum(Type)
174 |
175 | local frame = CreateFrame("Frame", nil, UIParent)
176 | local button = CreateFrame("Button", name, frame, "UIPanelButtonTemplate2")
177 |
178 | button:EnableMouse(true)
179 | button:RegisterForClicks("AnyDown")
180 | button:SetScript("OnEnter", Control_OnEnter)
181 | button:SetScript("OnLeave", Control_OnLeave)
182 | button:SetScript("OnClick", Keybinding_OnClick)
183 | button:SetScript("OnKeyDown", Keybinding_OnKeyDown)
184 | button:SetScript("OnMouseDown", Keybinding_OnMouseDown)
185 | button:SetPoint("BOTTOMLEFT")
186 | button:SetPoint("BOTTOMRIGHT")
187 | button:SetHeight(24)
188 |
189 | local text = button:GetFontString()
190 | text:SetPoint("LEFT", 7, 0)
191 | text:SetPoint("RIGHT", -7, 0)
192 |
193 | local label = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
194 | label:SetPoint("TOPLEFT")
195 | label:SetPoint("TOPRIGHT")
196 | label:SetJustifyH("CENTER")
197 | label:SetHeight(18)
198 |
199 | local msgframe = CreateFrame("Frame", nil, UIParent)
200 | msgframe:SetHeight(30)
201 | msgframe:SetBackdrop(ControlBackdrop)
202 | msgframe:SetBackdropColor(0,0,0)
203 | msgframe:SetFrameStrata("FULLSCREEN_DIALOG")
204 | msgframe:SetFrameLevel(1000)
205 |
206 | local msg = msgframe:CreateFontString(nil, "OVERLAY", "GameFontNormal")
207 | msg:SetText("Press a key to bind, ESC to clear the binding or click the button again to cancel.")
208 | msgframe.msg = msg
209 | msg:SetPoint("TOPLEFT", 5, -5)
210 | msgframe:SetScript("OnUpdate", keybindingMsgFixWidth)
211 | msgframe:SetPoint("BOTTOM", button, "TOP")
212 | msgframe:Hide()
213 |
214 | local widget = {
215 | button = button,
216 | label = label,
217 | msgframe = msgframe,
218 | frame = frame,
219 | alignoffset = 30,
220 | type = Type
221 | }
222 | for method, func in pairs(methods) do
223 | widget[method] = func
224 | end
225 | button.obj = widget
226 |
227 | return AceGUI:RegisterAsWidget(widget)
228 | end
229 |
230 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
231 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIContainer-ScrollFrame.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | ScrollFrame Container
3 | Plain container that scrolls its content and doesn't grow in height.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "ScrollFrame", 21
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs, assert, type = pairs, assert, type
11 | local min, max, floor, abs = math.min, math.max, math.floor, math.abs
12 |
13 | -- WoW APIs
14 | local CreateFrame, UIParent = CreateFrame, UIParent
15 |
16 | --[[-----------------------------------------------------------------------------
17 | Support functions
18 | -------------------------------------------------------------------------------]]
19 | local function FixScrollOnUpdate(frame)
20 | frame:SetScript("OnUpdate", nil)
21 | frame.obj:FixScroll()
22 | end
23 |
24 | --[[-----------------------------------------------------------------------------
25 | Scripts
26 | -------------------------------------------------------------------------------]]
27 | local function ScrollFrame_OnMouseWheel(frame, value)
28 | frame.obj:MoveScroll(value)
29 | end
30 |
31 | local function ScrollFrame_OnSizeChanged(frame)
32 | frame:SetScript("OnUpdate", FixScrollOnUpdate)
33 | end
34 |
35 | local function ScrollBar_OnScrollValueChanged(frame, value)
36 | frame.obj:SetScroll(value)
37 | end
38 |
39 | --[[-----------------------------------------------------------------------------
40 | Methods
41 | -------------------------------------------------------------------------------]]
42 | local methods = {
43 | ["OnAcquire"] = function(self)
44 | self:SetScroll(0)
45 | end,
46 |
47 | ["OnRelease"] = function(self)
48 | self.status = nil
49 | for k in pairs(self.localstatus) do
50 | self.localstatus[k] = nil
51 | end
52 | self.scrollframe:SetPoint("BOTTOMRIGHT")
53 | self.scrollbar:Hide()
54 | self.scrollBarShown = nil
55 | self.content.height, self.content.width = nil, nil
56 | end,
57 |
58 | ["SetScroll"] = function(self, value)
59 | local status = self.status or self.localstatus
60 | local viewheight = self.scrollframe:GetHeight()
61 | local height = self.content:GetHeight()
62 | local offset
63 |
64 | if viewheight > height then
65 | offset = 0
66 | else
67 | offset = floor((height - viewheight) / 1000.0 * value)
68 | end
69 | self.content:ClearAllPoints()
70 | self.content:SetPoint("TOPLEFT", 0, offset)
71 | self.content:SetPoint("TOPRIGHT", 0, offset)
72 | status.offset = offset
73 | status.scrollvalue = value
74 | end,
75 |
76 | ["MoveScroll"] = function(self, value)
77 | local status = self.status or self.localstatus
78 | local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
79 |
80 | if self.scrollBarShown then
81 | local diff = height - viewheight
82 | local delta = 1
83 | if value < 0 then
84 | delta = -1
85 | end
86 | self.scrollbar:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
87 | end
88 | end,
89 |
90 | ["FixScroll"] = function(self)
91 | if self.updateLock then return end
92 | self.updateLock = true
93 | local status = self.status or self.localstatus
94 | local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
95 | local offset = status.offset or 0
96 | local curvalue = self.scrollbar:GetValue()
97 | -- Give us a margin of error of 2 pixels to stop some conditions that i would blame on floating point inaccuracys
98 | -- No-one is going to miss 2 pixels at the bottom of the frame, anyhow!
99 | if viewheight < height + 2 then
100 | if self.scrollBarShown then
101 | self.scrollBarShown = nil
102 | self.scrollbar:Hide()
103 | self.scrollbar:SetValue(0)
104 | self.scrollframe:SetPoint("BOTTOMRIGHT")
105 | self:DoLayout()
106 | end
107 | else
108 | if not self.scrollBarShown then
109 | self.scrollBarShown = true
110 | self.scrollbar:Show()
111 | self.scrollframe:SetPoint("BOTTOMRIGHT", -20, 0)
112 | self:DoLayout()
113 | end
114 | local value = (offset / (viewheight - height) * 1000)
115 | if value > 1000 then value = 1000 end
116 | self.scrollbar:SetValue(value)
117 | self:SetScroll(value)
118 | if value < 1000 then
119 | self.content:ClearAllPoints()
120 | self.content:SetPoint("TOPLEFT", 0, offset)
121 | self.content:SetPoint("TOPRIGHT", 0, offset)
122 | status.offset = offset
123 | end
124 | end
125 | self.updateLock = nil
126 | end,
127 |
128 | ["LayoutFinished"] = function(self, width, height)
129 | self.content:SetHeight(height or 0 + 20)
130 | self.scrollframe:SetScript("OnUpdate", FixScrollOnUpdate)
131 | end,
132 |
133 | ["SetStatusTable"] = function(self, status)
134 | assert(type(status) == "table")
135 | self.status = status
136 | if not status.scrollvalue then
137 | status.scrollvalue = 0
138 | end
139 | end,
140 |
141 | ["OnWidthSet"] = function(self, width)
142 | local content = self.content
143 | content.width = width
144 | end,
145 |
146 | ["OnHeightSet"] = function(self, height)
147 | local content = self.content
148 | content.height = height
149 | end
150 | }
151 | --[[-----------------------------------------------------------------------------
152 | Constructor
153 | -------------------------------------------------------------------------------]]
154 | local function Constructor()
155 | local frame = CreateFrame("Frame", nil, UIParent)
156 | local num = AceGUI:GetNextWidgetNum(Type)
157 |
158 | local scrollframe = CreateFrame("ScrollFrame", nil, frame)
159 | scrollframe:SetPoint("TOPLEFT")
160 | scrollframe:SetPoint("BOTTOMRIGHT")
161 | scrollframe:EnableMouseWheel(true)
162 | scrollframe:SetScript("OnMouseWheel", ScrollFrame_OnMouseWheel)
163 | scrollframe:SetScript("OnSizeChanged", ScrollFrame_OnSizeChanged)
164 |
165 | local scrollbar = CreateFrame("Slider", ("AceConfigDialogScrollFrame%dScrollBar"):format(num), scrollframe, "UIPanelScrollBarTemplate")
166 | scrollbar:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, -16)
167 | scrollbar:SetPoint("BOTTOMLEFT", scrollframe, "BOTTOMRIGHT", 4, 16)
168 | scrollbar:SetMinMaxValues(0, 1000)
169 | scrollbar:SetValueStep(1)
170 | scrollbar:SetValue(0)
171 | scrollbar:SetWidth(16)
172 | scrollbar:Hide()
173 | -- set the script as the last step, so it doesn't fire yet
174 | scrollbar:SetScript("OnValueChanged", ScrollBar_OnScrollValueChanged)
175 |
176 | local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
177 | scrollbg:SetAllPoints(scrollbar)
178 | scrollbg:SetTexture(0, 0, 0, 0.4)
179 |
180 | --Container Support
181 | local content = CreateFrame("Frame", nil, scrollframe)
182 | content:SetPoint("TOPLEFT")
183 | content:SetPoint("TOPRIGHT")
184 | content:SetHeight(400)
185 | scrollframe:SetScrollChild(content)
186 |
187 | local widget = {
188 | localstatus = { scrollvalue = 0 },
189 | scrollframe = scrollframe,
190 | scrollbar = scrollbar,
191 | content = content,
192 | frame = frame,
193 | type = Type
194 | }
195 | for method, func in pairs(methods) do
196 | widget[method] = func
197 | end
198 | scrollframe.obj, scrollbar.obj = widget, widget
199 |
200 | return AceGUI:RegisterAsContainer(widget)
201 | end
202 |
203 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
204 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | EditBox Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "EditBox", 22
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local tostring, pairs = tostring, pairs
10 |
11 | -- WoW APIs
12 | local PlaySound = PlaySound
13 | local GetCursorInfo, ClearCursor, GetSpellName = GetCursorInfo, ClearCursor, GetSpellName
14 | local CreateFrame, UIParent = CreateFrame, UIParent
15 | local _G = _G
16 |
17 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
18 | -- List them here for Mikk's FindGlobals script
19 | -- GLOBALS: AceGUIEditBoxInsertLink, ChatFontNormal, OKAY
20 |
21 | --[[-----------------------------------------------------------------------------
22 | Support functions
23 | -------------------------------------------------------------------------------]]
24 | if not AceGUIEditBoxInsertLink then
25 | -- upgradeable hook
26 | hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIEditBoxInsertLink(...) end)
27 | end
28 |
29 | function _G.AceGUIEditBoxInsertLink(text)
30 | for i = 1, AceGUI:GetWidgetCount(Type) do
31 | local editbox = _G["AceGUI-3.0EditBox"..i]
32 | if editbox and editbox:IsVisible() and editbox:HasFocus() then
33 | editbox:Insert(text)
34 | return true
35 | end
36 | end
37 | end
38 |
39 | local function ShowButton(self)
40 | if not self.disablebutton then
41 | self.button:Show()
42 | self.editbox:SetTextInsets(0, 20, 3, 3)
43 | end
44 | end
45 |
46 | local function HideButton(self)
47 | self.button:Hide()
48 | self.editbox:SetTextInsets(0, 0, 3, 3)
49 | end
50 |
51 | --[[-----------------------------------------------------------------------------
52 | Scripts
53 | -------------------------------------------------------------------------------]]
54 | local function Control_OnEnter(frame)
55 | frame.obj:Fire("OnEnter")
56 | end
57 |
58 | local function Control_OnLeave(frame)
59 | frame.obj:Fire("OnLeave")
60 | end
61 |
62 | local function EditBox_OnEscapePressed(frame)
63 | AceGUI:ClearFocus()
64 | end
65 |
66 | local function EditBox_OnEnterPressed(frame)
67 | local self = frame.obj
68 | local value = frame:GetText()
69 | local cancel = self:Fire("OnEnterPressed", value)
70 | if not cancel then
71 | PlaySound("igMainMenuOptionCheckBoxOn")
72 | HideButton(self)
73 | end
74 | end
75 |
76 | local function EditBox_OnReceiveDrag(frame)
77 | local self = frame.obj
78 | local type, id, info = GetCursorInfo()
79 | if type == "item" then
80 | self:SetText(info)
81 | self:Fire("OnEnterPressed", info)
82 | ClearCursor()
83 | elseif type == "spell" then
84 | local name, rank = GetSpellName(id, info)
85 | if rank and rank:match("%d") then
86 | name = name.."("..rank..")"
87 | end
88 | self:SetText(name)
89 | self:Fire("OnEnterPressed", name)
90 | ClearCursor()
91 | end
92 | HideButton(self)
93 | AceGUI:ClearFocus()
94 | end
95 |
96 | local function EditBox_OnTextChanged(frame)
97 | local self = frame.obj
98 | local value = frame:GetText()
99 | if tostring(value) ~= tostring(self.lasttext) then
100 | self:Fire("OnTextChanged", value)
101 | self.lasttext = value
102 | ShowButton(self)
103 | end
104 | end
105 |
106 | local function Button_OnClick(frame)
107 | local editbox = frame.obj.editbox
108 | editbox:ClearFocus()
109 | EditBox_OnEnterPressed(editbox)
110 | end
111 |
112 | --[[-----------------------------------------------------------------------------
113 | Methods
114 | -------------------------------------------------------------------------------]]
115 | local methods = {
116 | ["OnAcquire"] = function(self)
117 | -- height is controlled by SetLabel
118 | self:SetWidth(200)
119 | self:SetDisabled(false)
120 | self:SetLabel()
121 | self:SetText()
122 | self:DisableButton(false)
123 | self:SetMaxLetters(0)
124 | end,
125 |
126 | -- ["OnRelease"] = nil,
127 |
128 | ["SetDisabled"] = function(self, disabled)
129 | self.disabled = disabled
130 | if disabled then
131 | self.editbox:EnableMouse(false)
132 | self.editbox:ClearFocus()
133 | self.editbox:SetTextColor(0.5,0.5,0.5)
134 | self.label:SetTextColor(0.5,0.5,0.5)
135 | else
136 | self.editbox:EnableMouse(true)
137 | self.editbox:SetTextColor(1,1,1)
138 | self.label:SetTextColor(1,.82,0)
139 | end
140 | end,
141 |
142 | ["SetText"] = function(self, text)
143 | self.lasttext = text or ""
144 | self.editbox:SetText(text or "")
145 | self.editbox:SetCursorPosition(0)
146 | HideButton(self)
147 | end,
148 |
149 | ["GetText"] = function(self, text)
150 | return self.editbox:GetText()
151 | end,
152 |
153 | ["SetLabel"] = function(self, text)
154 | if text and text ~= "" then
155 | self.label:SetText(text)
156 | self.label:Show()
157 | self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,-18)
158 | self:SetHeight(44)
159 | self.alignoffset = 30
160 | else
161 | self.label:SetText("")
162 | self.label:Hide()
163 | self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,0)
164 | self:SetHeight(26)
165 | self.alignoffset = 12
166 | end
167 | end,
168 |
169 | ["DisableButton"] = function(self, disabled)
170 | self.disablebutton = disabled
171 | if disabled then
172 | HideButton(self)
173 | end
174 | end,
175 |
176 | ["SetMaxLetters"] = function (self, num)
177 | self.editbox:SetMaxLetters(num or 0)
178 | end
179 | }
180 |
181 | --[[-----------------------------------------------------------------------------
182 | Constructor
183 | -------------------------------------------------------------------------------]]
184 | local function Constructor()
185 | local num = AceGUI:GetNextWidgetNum(Type)
186 | local frame = CreateFrame("Frame", nil, UIParent)
187 | frame:Hide()
188 |
189 | local editbox = CreateFrame("EditBox", "AceGUI-3.0EditBox"..num, frame, "InputBoxTemplate")
190 | editbox:SetAutoFocus(false)
191 | editbox:SetFontObject(ChatFontNormal)
192 | editbox:SetScript("OnEnter", Control_OnEnter)
193 | editbox:SetScript("OnLeave", Control_OnLeave)
194 | editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
195 | editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
196 | editbox:SetScript("OnTextChanged", EditBox_OnTextChanged)
197 | editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
198 | editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
199 | editbox:SetTextInsets(0, 0, 3, 3)
200 | editbox:SetMaxLetters(256)
201 | editbox:SetPoint("BOTTOMLEFT", 6, 0)
202 | editbox:SetPoint("BOTTOMRIGHT")
203 | editbox:SetHeight(19)
204 |
205 | local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
206 | label:SetPoint("TOPLEFT", 0, -2)
207 | label:SetPoint("TOPRIGHT", 0, -2)
208 | label:SetJustifyH("LEFT")
209 | label:SetHeight(18)
210 |
211 | local button = CreateFrame("Button", nil, editbox, "UIPanelButtonTemplate")
212 | button:SetWidth(40)
213 | button:SetHeight(20)
214 | button:SetPoint("RIGHT", -2, 0)
215 | button:SetText(OKAY)
216 | button:SetScript("OnClick", Button_OnClick)
217 | button:Hide()
218 |
219 | local widget = {
220 | alignoffset = 30,
221 | editbox = editbox,
222 | label = label,
223 | button = button,
224 | frame = frame,
225 | type = Type
226 | }
227 | for method, func in pairs(methods) do
228 | widget[method] = func
229 | end
230 | editbox.obj, button.obj = widget, widget
231 |
232 | return AceGUI:RegisterAsWidget(widget)
233 | end
234 |
235 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
236 |
--------------------------------------------------------------------------------
/AI_VoiceOver/VoiceOver.lua:
--------------------------------------------------------------------------------
1 | setfenv(1, VoiceOver)
2 |
3 | Addon = LibStub("AceAddon-3.0"):NewAddon("VoiceOver", "AceEvent-3.0", "AceTimer-3.0")
4 |
5 | local defaults = {
6 | profile = {
7 | SoundQueueUI = {
8 | LockFrame = false,
9 | FrameScale = 0.7,
10 | FrameStrata = "HIGH",
11 | HidePortrait = false,
12 | HideFrame = false,
13 | },
14 | Audio = {
15 | GossipFrequency = Enums.GossipFrequency.OncePerQuestNPC,
16 | SoundChannel = Enums.SoundChannel.Master,
17 | AutoToggleDialog = true,
18 | },
19 | MinimapButton = {
20 | LibDBIcon = {}, -- Table used by LibDBIcon to store position (minimapPos), dragging lock (lock) and hidden state (hide)
21 | Commands = {
22 | -- References keys from Options.table.args.SlashCommands.args table
23 | LeftButton = "Options",
24 | MiddleButton = "PlayPause",
25 | RightButton = "Clear",
26 | }
27 | },
28 | DebugEnabled = false,
29 | },
30 | char = {
31 | IsPaused = false,
32 | hasSeenGossipForNPC = {},
33 | }
34 | }
35 |
36 | local lastGossipOptions
37 | local selectedGossipOption
38 |
39 | function Addon:OnInitialize()
40 | self.db = LibStub("AceDB-3.0"):New("VoiceOverDB", defaults)
41 | self.db.RegisterCallback(self, "OnProfileChanged", "RefreshConfig")
42 |
43 | self.soundQueue = SoundQueue:new()
44 | self.questOverlayUI = QuestOverlayUI:new(self.soundQueue)
45 |
46 | DataModules:EnumerateAddons()
47 | Options:Initialize()
48 |
49 | self:RegisterEvent("QUEST_DETAIL")
50 | self:RegisterEvent("GOSSIP_SHOW")
51 | self:RegisterEvent("GOSSIP_CLOSED")
52 | self:RegisterEvent("QUEST_COMPLETE")
53 | -- self:RegisterEvent("QUEST_PROGRESS")
54 |
55 | StaticPopupDialogs["VOICEOVER_DUPLICATE_ADDON"] =
56 | {
57 | text =
58 | "VoiceOver\n\nTo fix the quest autoaccept bugs we had to rename the addon folder. If you're seeing this popup, it means the old one wasn't automatically removed.\n\nYou can safely delete \"VoiceOver\" from your Addons folder. \"AI_VoiceOver\" is the new folder.",
59 | button1 = OKAY,
60 | timeout = 0,
61 | whileDead = 1,
62 | OnAccept = function()
63 | self.db.profile.main.SeenDuplicateDialog = true
64 | end,
65 | };
66 |
67 | if select(5, GetAddOnInfo("VoiceOver")) ~= "MISSING" then
68 | DisableAddOn("VoiceOver")
69 | if not self.db.profile.main.SeenDuplicateDialog then
70 | StaticPopup_Show("VOICEOVER_DUPLICATE_ADDON")
71 | end
72 | end
73 |
74 | hooksecurefunc("AbandonQuest", function()
75 | local questName = GetAbandonQuestName()
76 | local soundsToRemove = {}
77 | for _, soundData in pairs(self.soundQueue.sounds) do
78 | if soundData.title == questName then
79 | table.insert(soundsToRemove, soundData)
80 | end
81 | end
82 |
83 | for _, soundData in pairs(soundsToRemove) do
84 | self.soundQueue:RemoveSoundFromQueue(soundData)
85 | end
86 | end)
87 |
88 | hooksecurefunc("QuestLog_Update", function()
89 | self.questOverlayUI:UpdateQuestOverlayUI()
90 | end)
91 |
92 | if C_GossipInfo and C_GossipInfo.SelectOption then
93 | hooksecurefunc(C_GossipInfo, "SelectOption", function(optionID)
94 | if lastGossipOptions then
95 | for _, info in ipairs(lastGossipOptions) do
96 | if info.gossipOptionID == optionID then
97 | selectedGossipOption = info.name
98 | break
99 | end
100 | end
101 | lastGossipOptions = nil
102 | end
103 | end)
104 | elseif SelectGossipOption then
105 | hooksecurefunc("SelectGossipOption", function(index)
106 | if lastGossipOptions then
107 | selectedGossipOption = lastGossipOptions[1 + (index - 1) * 2]
108 | lastGossipOptions = nil
109 | end
110 | end)
111 | end
112 | end
113 |
114 | function Addon:RefreshConfig()
115 | self.soundQueue.ui:RefreshConfig()
116 | end
117 |
118 | function Addon:QUEST_DETAIL()
119 | local questID = GetQuestID()
120 | if questID == 0 then
121 | return
122 | end
123 | local questTitle = GetTitleText()
124 | local questText = GetQuestText()
125 | local guid = Utils:GetNPCGUID()
126 | local targetName = Utils:GetNPCName()
127 |
128 | local type = guid and Utils:GetGUIDType(guid)
129 | if type == Enums.GUID.Item then
130 | -- Allow quests started from items to have VO, book icon will be displayed for them
131 | elseif not type or not Enums.GUID:CanHaveID(type) then
132 | -- If the quest is started by something that we cannot extract the ID of (e.g. Player, when sharing a quest) - try to fallback to a questgiver from a module's database
133 | local npcID = DataModules:GetQuestLogNPCID(questID) -- TODO: Add fallbacks to item and object questgivers once VO for them is made
134 | if npcID then
135 | type = Enums.GUID.Creature
136 | guid = Utils:MakeGUID(type, npcID)
137 | targetName = DataModules:GetNPCName(npcID) or "Unknown Name"
138 | else
139 | -- return
140 | Debug:Print("npcID not found", "NPCID")
141 | end
142 | end
143 |
144 | -- print("QUEST_DETAIL", questID, questTitle);
145 | local soundData = {
146 | event = Enums.SoundEvent.QuestAccept,
147 | questID = questID,
148 | name = targetName,
149 | title = questTitle,
150 | text = questText,
151 | unitGUID = guid
152 | }
153 | self.soundQueue:AddSoundToQueue(soundData)
154 | end
155 |
156 | function Addon:QUEST_COMPLETE()
157 | local questID = GetQuestID()
158 | if questID == 0 then
159 | return
160 | end
161 | local questTitle = GetTitleText()
162 | local questText = GetRewardText()
163 | local guid = Utils:GetNPCGUID()
164 | local targetName = Utils:GetNPCName()
165 | -- print("QUEST_COMPLETE", questID, questTitle);
166 | local soundData = {
167 | event = Enums.SoundEvent.QuestComplete,
168 | questID = questID,
169 | name = targetName,
170 | title = questTitle,
171 | text = questText,
172 | unitGUID = guid
173 | }
174 | self.soundQueue:AddSoundToQueue(soundData)
175 | end
176 |
177 | function Addon:GOSSIP_SHOW()
178 | local guid = Utils:GetNPCGUID()
179 | local targetName = Utils:GetNPCName()
180 | local npcKey = guid or "unknown"
181 |
182 | local gossipSeenForNPC = self.db.char.hasSeenGossipForNPC[npcKey]
183 |
184 | if self.db.profile.Audio.GossipFrequency == Enums.GossipFrequency.OncePerQuestNPC then
185 | local numActiveQuests = GetNumGossipActiveQuests()
186 | local numAvailableQuests = GetNumGossipAvailableQuests()
187 | local npcHasQuests = (numActiveQuests > 0 or numAvailableQuests > 0)
188 | if npcHasQuests and gossipSeenForNPC then
189 | return
190 | end
191 | elseif self.db.profile.Audio.GossipFrequency == Enums.GossipFrequency.OncePerNPC then
192 | if gossipSeenForNPC then
193 | return
194 | end
195 | elseif self.db.profile.Audio.GossipFrequency == Enums.GossipFrequency.Never then
196 | return
197 | end
198 |
199 | -- Play the gossip sound
200 | local gossipText = GetGossipText()
201 | local soundData = {
202 | event = Enums.SoundEvent.Gossip,
203 | name = targetName,
204 | title = selectedGossipOption and format([["%s"]], selectedGossipOption),
205 | text = gossipText,
206 | unitGUID = guid,
207 | startCallback = function()
208 | self.db.char.hasSeenGossipForNPC[npcKey] = true
209 | end
210 | }
211 | self.soundQueue:AddSoundToQueue(soundData)
212 |
213 | selectedGossipOption = nil
214 | lastGossipOptions = nil
215 | if C_GossipInfo and C_GossipInfo.GetOptions then
216 | lastGossipOptions = C_GossipInfo.GetOptions()
217 | elseif GetGossipOptions then
218 | lastGossipOptions = { GetGossipOptions() }
219 | end
220 | end
221 |
222 | function Addon:GOSSIP_CLOSED()
223 | selectedGossipOption = nil
224 | end
225 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Utils.lua:
--------------------------------------------------------------------------------
1 | setfenv(1, VoiceOver)
2 | Utils = {}
3 |
4 | function Utils:GetGUIDType(guid)
5 | return guid and Enums.GUID[select(1, strsplit("-", guid, 2))]
6 | end
7 |
8 | function Utils:GetIDFromGUID(guid)
9 | if not guid then
10 | return
11 | end
12 | local type, rest = strsplit("-", guid, 2)
13 | type = assert(Enums.GUID[type], format("Unknown GUID type %s", type))
14 | assert(Enums.GUID:CanHaveID(type), format([[GUID "%s" does not contain ID]], guid))
15 | return tonumber((select(5, strsplit("-", rest))))
16 | end
17 |
18 | function Utils:MakeGUID(type, id)
19 | assert(Enums.GUID:CanHaveID(type), format("GUID of type %d (%s) cannot contain ID", type, Enums.GUID:GetName(type) or "Unknown"))
20 | type = assert(Enums.GUID:GetName(type), format("Unknown GUID type %d", type))
21 | return format("%s-%d-%d-%d-%d-%d-%d", type, 0, 0, 0, 0, id, 0)
22 | end
23 |
24 | function Utils:GetNPCName()
25 | return UnitName("questnpc") or UnitName("npc")
26 | end
27 |
28 | -- function Utils:GetNPCGUID()
29 | -- return UnitGUID("questnpc") or UnitGUID("npc")
30 | -- end
31 | function Utils:GetNPCGUID()
32 | local unit, guid
33 | if (UnitExists("questnpc") and not UnitIsUnit("questnpc", "player") and not UnitIsDead("questnpc")) then
34 | unit = "questnpc"
35 | elseif (UnitExists("npc") and not UnitIsUnit("npc", "player") and not UnitIsDead("npc")) then
36 | unit = "npc"
37 | end
38 | guid = unit and UnitGUID(unit)
39 | return guid and select(6, strsplit("-", guid))
40 | end
41 |
42 | function Utils:IsNPCPlayer()
43 | return UnitIsPlayer("questnpc") or UnitIsPlayer("npc")
44 | end
45 |
46 | function Utils:WillSoundPlay(soundData)
47 | if not soundData.filePath then
48 | return false
49 | end
50 |
51 | -- local willPlay, handle = PlaySoundFile(soundData.filePath)
52 | local willPlay, handle = PlayMusic(soundData.filePath)
53 | SetCVar("Sound_MusicVolume", 1)
54 | if willPlay then
55 | StopSound(handle)
56 | end
57 | return willPlay
58 | end
59 |
60 | function Utils:GetQuestLogScrollOffset()
61 | return FauxScrollFrame_GetOffset(QuestLogListScrollFrame)
62 | end
63 |
64 | function Utils:GetQuestLogTitleFrame(index)
65 | return _G["QuestLogTitle" .. index]
66 | end
67 |
68 | function Utils:GetQuestLogTitleNormalText(index)
69 | return _G["QuestLogTitle" .. index .. "NormalText"]
70 | end
71 |
72 | function Utils:GetQuestLogTitleCheck(index)
73 | return _G["QuestLogTitle" .. index .. "Check"]
74 | end
75 |
76 | function Utils:ColorizeText(text, color)
77 | return color .. text .. "|r"
78 | end
79 |
80 | function Utils:Ordered(tbl, sorter)
81 | local orderedIndex = {}
82 | for key in pairs(tbl) do
83 | table.insert(orderedIndex, key)
84 | end
85 | if sorter then
86 | table.sort(orderedIndex, function(a, b)
87 | return sorter(tbl[a], tbl[b], a, b)
88 | end)
89 | else
90 | table.sort(orderedIndex)
91 | end
92 |
93 | local i = 0
94 | local function orderedNext(t)
95 | i = i + 1
96 | return orderedIndex[i], t[orderedIndex[i]]
97 | end
98 |
99 | return orderedNext, tbl, nil
100 | end
101 |
102 | local animationDurations = {
103 | ["Original"] = {
104 | [130737] = { [60] = 1533 }, -- interface/buttons/talktomequestion_white
105 |
106 | [116921] = { [60] = 4000 }, -- character/bloodelf/female/bloodelffemale
107 | [1100258] = { [60] = 4000 }, -- character/bloodelf/female/bloodelffemale_hd
108 | [117170] = { [60] = 2000 }, -- character/bloodelf/male/bloodelfmale
109 | [1100087] = { [60] = 2000 }, -- character/bloodelf/male/bloodelfmale_hd
110 | [117400] = { [60] = 2934 }, -- character/broken/female/brokenfemale
111 | [117412] = { [60] = 2934 }, -- character/broken/male/brokenmale
112 | [117437] = { [60] = 3000 }, -- character/draenei/female/draeneifemale
113 | [1022598] = { [60] = 3000 }, -- character/draenei/female/draeneifemale_hd
114 | [117721] = { [60] = 3334 }, -- character/draenei/male/draeneimale
115 | [1005887] = { [60] = 3334 }, -- character/draenei/male/draeneimale_hd
116 | [118135] = { [60] = 2000 }, -- character/dwarf/female/dwarffemale
117 | [950080] = { [60] = 2000 }, -- character/dwarf/female/dwarffemale_hd
118 | [118355] = { [60] = 2000 }, -- character/dwarf/male/dwarfmale
119 | [878772] = { [60] = 2000 }, -- character/dwarf/male/dwarfmale_hd
120 | [118652] = { [60] = 2000 }, -- character/felorc/female/felorcfemale
121 | [118653] = { [60] = 2000 }, -- character/felorc/male/felorcmale
122 | [118654] = { [60] = 2000 }, -- character/felorc/male/felorcmaleaxe
123 | [118667] = { [60] = 2000 }, -- character/felorc/male/felorcmalesword
124 | [118798] = { [60] = 2500 }, -- character/foresttroll/male/foresttrollmale
125 | [119063] = { [60] = 4000 }, -- character/gnome/female/gnomefemale
126 | [940356] = { [60] = 4000 }, -- character/gnome/female/gnomefemale_hd
127 | [119159] = { [60] = 4000 }, -- character/gnome/male/gnomemale
128 | [900914] = { [60] = 4000 }, -- character/gnome/male/gnomemale_hd
129 | [119369] = { [60] = 1800 }, -- character/goblin/female/goblinfemale
130 | [119376] = { [60] = 1800 }, -- character/goblin/male/goblinmale
131 | [119563] = { [60] = 2667 }, -- character/human/female/humanfemale
132 | [1000764] = { [60] = 2667 }, -- character/human/female/humanfemale_hd
133 | [119940] = { [60] = 2000 }, -- character/human/male/humanmale
134 | [1011653] = { [60] = 2000 }, -- character/human/male/humanmale_hd
135 | [232863] = { [60] = 2500 }, -- character/icetroll/male/icetrollmale
136 | [120263] = { [60] = 3000 }, -- character/naga_/female/naga_female
137 | [120294] = { [60] = 3000 }, -- character/naga_/male/naga_male
138 | [120590] = { [60] = 2100 }, -- character/nightelf/female/nightelffemale
139 | [921844] = { [60] = 2100 }, -- character/nightelf/female/nightelffemale_hd
140 | [120791] = { [60] = 2000 }, -- character/nightelf/male/nightelfmale
141 | [974343] = { [60] = 2000 }, -- character/nightelf/male/nightelfmale_hd
142 | [233367] = { [60] = 3600 }, -- character/northrendskeleton/male/northrendskeletonmale
143 | [121087] = { [60] = 2000 }, -- character/orc/female/orcfemale
144 | [949470] = { [60] = 2000 }, -- character/orc/female/orcfemale_hd
145 | [121287] = { [60] = 2000 }, -- character/orc/male/orcmale
146 | [917116] = { [60] = 2000 }, -- character/orc/male/orcmale_hd
147 | [121608] = { [60] = 2000 }, -- character/scourge/female/scourgefemale
148 | [997378] = { [60] = 2467 }, -- character/scourge/female/scourgefemale_hd
149 | [121768] = { [60] = 2667 }, -- character/scourge/male/scourgemale
150 | [959310] = { [60] = 2667 }, -- character/scourge/male/scourgemale_hd
151 | [121942] = { [60] = 2667 }, -- character/skeleton/male/skeletonmale
152 | [233878] = { [60] = 2934 }, -- character/taunka/male/taunkamale
153 | [121961] = { [60] = 2934 }, -- character/tauren/female/taurenfemale
154 | [986648] = { [60] = 2934 }, -- character/tauren/female/taurenfemale_hd
155 | [122055] = { [60] = 2934 }, -- character/tauren/male/taurenmale
156 | [968705] = { [60] = 2934 }, -- character/tauren/male/taurenmale_hd
157 | [122414] = { [60] = 2500 }, -- character/troll/female/trollfemale
158 | [1018060] = { [60] = 2500 }, -- character/troll/female/trollfemale_hd
159 | [122560] = { [60] = 2500 }, -- character/troll/male/trollmale
160 | [1022938] = { [60] = 2500 }, -- character/troll/male/trollmale_hd
161 | [122738] = { [60] = 3000 }, -- character/tuskarr/male/tuskarrmale
162 | [122815] = { [60] = 3600 }, -- character/vrykul/male/vrykulmale
163 | },
164 | -- HD overrides for model files which didn't get a separate HD version
165 | ["HD"] = {
166 | [119369] = { [60] = 4667 }, -- character/goblin/female/goblinfemale
167 | [119376] = { [60] = 4667 }, -- character/goblin/male/goblinmale
168 | },
169 | }
170 | function Utils:GetCurrentModelSet()
171 | return "Original"
172 | end
173 | function Utils:GetModelAnimationDuration(model, animation)
174 | if not model or model == 123 then return end
175 | local models = animationDurations[Utils:GetCurrentModelSet()] or animationDurations["Original"]
176 | local animations = models[model] or animationDurations["Original"][model]
177 | local duration = animations and animations[animation]
178 | return duration and duration / 1000
179 | end
180 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Checkbox Widget
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "CheckBox", 21
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local select, pairs = select, pairs
10 |
11 | -- WoW APIs
12 | local PlaySound = PlaySound
13 | local CreateFrame, UIParent = CreateFrame, UIParent
14 |
15 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
16 | -- List them here for Mikk's FindGlobals script
17 | -- GLOBALS: SetDesaturation, GameFontHighlight
18 |
19 | --[[-----------------------------------------------------------------------------
20 | Support functions
21 | -------------------------------------------------------------------------------]]
22 | local function AlignImage(self)
23 | local img = self.image:GetTexture()
24 | self.text:ClearAllPoints()
25 | if not img then
26 | self.text:SetPoint("LEFT", self.checkbg, "RIGHT")
27 | self.text:SetPoint("RIGHT")
28 | else
29 | self.text:SetPoint("LEFT", self.image,"RIGHT", 1, 0)
30 | self.text:SetPoint("RIGHT")
31 | end
32 | end
33 |
34 | --[[-----------------------------------------------------------------------------
35 | Scripts
36 | -------------------------------------------------------------------------------]]
37 | local function Control_OnEnter(frame)
38 | frame.obj:Fire("OnEnter")
39 | end
40 |
41 | local function Control_OnLeave(frame)
42 | frame.obj:Fire("OnLeave")
43 | end
44 |
45 | local function CheckBox_OnMouseDown(frame)
46 | local self = frame.obj
47 | if not self.disabled then
48 | if self.image:GetTexture() then
49 | self.text:SetPoint("LEFT", self.image,"RIGHT", 2, -1)
50 | else
51 | self.text:SetPoint("LEFT", self.checkbg, "RIGHT", 1, -1)
52 | end
53 | end
54 | AceGUI:ClearFocus()
55 | end
56 |
57 | local function CheckBox_OnMouseUp(frame)
58 | local self = frame.obj
59 | if not self.disabled then
60 | self:ToggleChecked()
61 |
62 | if self.checked then
63 | PlaySound("igMainMenuOptionCheckBoxOn")
64 | else -- for both nil and false (tristate)
65 | PlaySound("igMainMenuOptionCheckBoxOff")
66 | end
67 |
68 | self:Fire("OnValueChanged", self.checked)
69 | AlignImage(self)
70 | end
71 | end
72 |
73 | --[[-----------------------------------------------------------------------------
74 | Methods
75 | -------------------------------------------------------------------------------]]
76 | local methods = {
77 | ["OnAcquire"] = function(self)
78 | self:SetType()
79 | self:SetValue(false)
80 | self:SetTriState(nil)
81 | -- height is calculated from the width and required space for the description
82 | self:SetWidth(200)
83 | self:SetImage()
84 | self:SetDisabled(nil)
85 | self:SetDescription(nil)
86 | end,
87 |
88 | -- ["OnRelease"] = nil,
89 |
90 | ["OnWidthSet"] = function(self, width)
91 | if self.desc then
92 | self.desc:SetWidth(width - 30)
93 | if self.desc:GetText() and self.desc:GetText() ~= "" then
94 | self:SetHeight(28 + self.desc:GetHeight())
95 | end
96 | end
97 | end,
98 |
99 | ["SetDisabled"] = function(self, disabled)
100 | self.disabled = disabled
101 | if disabled then
102 | self.frame:Disable()
103 | self.text:SetTextColor(0.5, 0.5, 0.5)
104 | SetDesaturation(self.check, true)
105 | else
106 | self.frame:Enable()
107 | self.text:SetTextColor(1, 1, 1)
108 | if self.tristate and self.checked == nil then
109 | SetDesaturation(self.check, true)
110 | else
111 | SetDesaturation(self.check, false)
112 | end
113 | end
114 | end,
115 |
116 | ["SetValue"] = function(self,value)
117 | local check = self.check
118 | self.checked = value
119 | if value then
120 | SetDesaturation(self.check, false)
121 | self.check:Show()
122 | else
123 | --Nil is the unknown tristate value
124 | if self.tristate and value == nil then
125 | SetDesaturation(self.check, true)
126 | self.check:Show()
127 | else
128 | SetDesaturation(self.check, false)
129 | self.check:Hide()
130 | end
131 | end
132 | self:SetDisabled(self.disabled)
133 | end,
134 |
135 | ["GetValue"] = function(self)
136 | return self.checked
137 | end,
138 |
139 | ["SetTriState"] = function(self, enabled)
140 | self.tristate = enabled
141 | self:SetValue(self:GetValue())
142 | end,
143 |
144 | ["SetType"] = function(self, type)
145 | local checkbg = self.checkbg
146 | local check = self.check
147 | local highlight = self.highlight
148 |
149 | local size
150 | if type == "radio" then
151 | size = 16
152 | checkbg:SetTexture("Interface\\Buttons\\UI-RadioButton")
153 | checkbg:SetTexCoord(0, 0.25, 0, 1)
154 | check:SetTexture("Interface\\Buttons\\UI-RadioButton")
155 | check:SetTexCoord(0.25, 0.5, 0, 1)
156 | check:SetBlendMode("ADD")
157 | highlight:SetTexture("Interface\\Buttons\\UI-RadioButton")
158 | highlight:SetTexCoord(0.5, 0.75, 0, 1)
159 | else
160 | size = 24
161 | checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
162 | checkbg:SetTexCoord(0, 1, 0, 1)
163 | check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
164 | check:SetTexCoord(0, 1, 0, 1)
165 | check:SetBlendMode("BLEND")
166 | highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
167 | highlight:SetTexCoord(0, 1, 0, 1)
168 | end
169 | checkbg:SetHeight(size)
170 | checkbg:SetWidth(size)
171 | end,
172 |
173 | ["ToggleChecked"] = function(self)
174 | local value = self:GetValue()
175 | if self.tristate then
176 | --cycle in true, nil, false order
177 | if value then
178 | self:SetValue(nil)
179 | elseif value == nil then
180 | self:SetValue(false)
181 | else
182 | self:SetValue(true)
183 | end
184 | else
185 | self:SetValue(not self:GetValue())
186 | end
187 | end,
188 |
189 | ["SetLabel"] = function(self, label)
190 | self.text:SetText(label)
191 | end,
192 |
193 | ["SetDescription"] = function(self, desc)
194 | if desc then
195 | if not self.desc then
196 | local desc = self.frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
197 | desc:ClearAllPoints()
198 | desc:SetPoint("TOPLEFT", self.checkbg, "TOPRIGHT", 5, -21)
199 | desc:SetWidth(self.frame.width - 30)
200 | desc:SetJustifyH("LEFT")
201 | desc:SetJustifyV("TOP")
202 | self.desc = desc
203 | end
204 | self.desc:Show()
205 | --self.text:SetFontObject(GameFontNormal)
206 | self.desc:SetText(desc)
207 | self:SetHeight(28 + self.desc:GetHeight())
208 | else
209 | if self.desc then
210 | self.desc:SetText("")
211 | self.desc:Hide()
212 | end
213 | --self.text:SetFontObject(GameFontHighlight)
214 | self:SetHeight(24)
215 | end
216 | end,
217 |
218 | ["SetImage"] = function(self, path, ...)
219 | local image = self.image
220 | image:SetTexture(path)
221 |
222 | if image:GetTexture() then
223 | local n = select("#", ...)
224 | if n == 4 or n == 8 then
225 | image:SetTexCoord(...)
226 | else
227 | image:SetTexCoord(0, 1, 0, 1)
228 | end
229 | end
230 | AlignImage(self)
231 | end
232 | }
233 |
234 | --[[-----------------------------------------------------------------------------
235 | Constructor
236 | -------------------------------------------------------------------------------]]
237 | local function Constructor()
238 | local frame = CreateFrame("Button", nil, UIParent)
239 | frame:Hide()
240 |
241 | frame:EnableMouse(true)
242 | frame:SetScript("OnEnter", Control_OnEnter)
243 | frame:SetScript("OnLeave", Control_OnLeave)
244 | frame:SetScript("OnMouseDown", CheckBox_OnMouseDown)
245 | frame:SetScript("OnMouseUp", CheckBox_OnMouseUp)
246 |
247 | local checkbg = frame:CreateTexture(nil, "ARTWORK")
248 | checkbg:SetWidth(24)
249 | checkbg:SetHeight(24)
250 | checkbg:SetPoint("TOPLEFT")
251 | checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
252 |
253 | local check = frame:CreateTexture(nil, "OVERLAY")
254 | check:SetAllPoints(checkbg)
255 | check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
256 |
257 | local text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
258 | text:SetJustifyH("LEFT")
259 | text:SetHeight(18)
260 | text:SetPoint("LEFT", checkbg, "RIGHT")
261 | text:SetPoint("RIGHT")
262 |
263 | local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
264 | highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
265 | highlight:SetBlendMode("ADD")
266 | highlight:SetAllPoints(checkbg)
267 |
268 | local image = frame:CreateTexture(nil, "OVERLAY")
269 | image:SetHeight(16)
270 | image:SetWidth(16)
271 | image:SetPoint("LEFT", checkbg, "RIGHT", 1, 0)
272 |
273 | local widget = {
274 | checkbg = checkbg,
275 | check = check,
276 | text = text,
277 | highlight = highlight,
278 | image = image,
279 | frame = frame,
280 | type = Type
281 | }
282 | for method, func in pairs(methods) do
283 | widget[method] = func
284 | end
285 |
286 | return AceGUI:RegisterAsWidget(widget)
287 | end
288 |
289 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
290 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Slider Widget
3 | Graphical Slider, like, for Range values.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "Slider", 20
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local min, max, floor = math.min, math.max, math.floor
11 | local tonumber, pairs = tonumber, pairs
12 |
13 | -- WoW APIs
14 | local PlaySound = PlaySound
15 | local CreateFrame, UIParent = CreateFrame, UIParent
16 |
17 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
18 | -- List them here for Mikk's FindGlobals script
19 | -- GLOBALS: GameFontHighlightSmall
20 |
21 | --[[-----------------------------------------------------------------------------
22 | Support functions
23 | -------------------------------------------------------------------------------]]
24 | local function UpdateText(self)
25 | local value = self.value or 0
26 | if self.ispercent then
27 | self.editbox:SetText(("%s%%"):format(floor(value * 1000 + 0.5) / 10))
28 | else
29 | self.editbox:SetText(floor(value * 100 + 0.5) / 100)
30 | end
31 | end
32 |
33 | local function UpdateLabels(self)
34 | local min, max = (self.min or 0), (self.max or 100)
35 | if self.ispercent then
36 | self.lowtext:SetFormattedText("%s%%", (min * 100))
37 | self.hightext:SetFormattedText("%s%%", (max * 100))
38 | else
39 | self.lowtext:SetText(min)
40 | self.hightext:SetText(max)
41 | end
42 | end
43 |
44 | --[[-----------------------------------------------------------------------------
45 | Scripts
46 | -------------------------------------------------------------------------------]]
47 | local function Control_OnEnter(frame)
48 | frame.obj:Fire("OnEnter")
49 | end
50 |
51 | local function Control_OnLeave(frame)
52 | frame.obj:Fire("OnLeave")
53 | end
54 |
55 | local function Frame_OnMouseDown(frame)
56 | frame.obj.slider:EnableMouseWheel(true)
57 | AceGUI:ClearFocus()
58 | end
59 |
60 | local function Slider_OnValueChanged(frame)
61 | local self = frame.obj
62 | if not frame.setup then
63 | local newvalue = frame:GetValue()
64 | if newvalue ~= self.value and not self.disabled then
65 | self.value = newvalue
66 | self:Fire("OnValueChanged", newvalue)
67 | end
68 | if self.value then
69 | UpdateText(self)
70 | end
71 | end
72 | end
73 |
74 | local function Slider_OnMouseUp(frame)
75 | local self = frame.obj
76 | self:Fire("OnMouseUp", self.value)
77 | end
78 |
79 | local function Slider_OnMouseWheel(frame, v)
80 | local self = frame.obj
81 | if not self.disabled then
82 | local value = self.value
83 | if v > 0 then
84 | value = min(value + (self.step or 1), self.max)
85 | else
86 | value = max(value - (self.step or 1), self.min)
87 | end
88 | self.slider:SetValue(value)
89 | end
90 | end
91 |
92 | local function EditBox_OnEscapePressed(frame)
93 | frame:ClearFocus()
94 | end
95 |
96 | local function EditBox_OnEnterPressed(frame)
97 | local self = frame.obj
98 | local value = frame:GetText()
99 | if self.ispercent then
100 | value = value:gsub('%%', '')
101 | value = tonumber(value) / 100
102 | else
103 | value = tonumber(value)
104 | end
105 |
106 | if value then
107 | PlaySound("igMainMenuOptionCheckBoxOn")
108 | self.slider:SetValue(value)
109 | self:Fire("OnMouseUp", value)
110 | end
111 | end
112 |
113 | local function EditBox_OnEnter(frame)
114 | frame:SetBackdropBorderColor(0.5, 0.5, 0.5, 1)
115 | end
116 |
117 | local function EditBox_OnLeave(frame)
118 | frame:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
119 | end
120 |
121 | --[[-----------------------------------------------------------------------------
122 | Methods
123 | -------------------------------------------------------------------------------]]
124 | local methods = {
125 | ["OnAcquire"] = function(self)
126 | self:SetWidth(200)
127 | self:SetHeight(44)
128 | self:SetDisabled(false)
129 | self:SetIsPercent(nil)
130 | self:SetSliderValues(0,100,1)
131 | self:SetValue(0)
132 | self.slider:EnableMouseWheel(false)
133 | end,
134 |
135 | -- ["OnRelease"] = nil,
136 |
137 | ["SetDisabled"] = function(self, disabled)
138 | self.disabled = disabled
139 | if disabled then
140 | self.slider:EnableMouse(false)
141 | self.label:SetTextColor(.5, .5, .5)
142 | self.hightext:SetTextColor(.5, .5, .5)
143 | self.lowtext:SetTextColor(.5, .5, .5)
144 | --self.valuetext:SetTextColor(.5, .5, .5)
145 | self.editbox:SetTextColor(.5, .5, .5)
146 | self.editbox:EnableMouse(false)
147 | self.editbox:ClearFocus()
148 | else
149 | self.slider:EnableMouse(true)
150 | self.label:SetTextColor(1, .82, 0)
151 | self.hightext:SetTextColor(1, 1, 1)
152 | self.lowtext:SetTextColor(1, 1, 1)
153 | --self.valuetext:SetTextColor(1, 1, 1)
154 | self.editbox:SetTextColor(1, 1, 1)
155 | self.editbox:EnableMouse(true)
156 | end
157 | end,
158 |
159 | ["SetValue"] = function(self, value)
160 | self.slider.setup = true
161 | self.slider:SetValue(value)
162 | self.value = value
163 | UpdateText(self)
164 | self.slider.setup = nil
165 | end,
166 |
167 | ["GetValue"] = function(self)
168 | return self.value
169 | end,
170 |
171 | ["SetLabel"] = function(self, text)
172 | self.label:SetText(text)
173 | end,
174 |
175 | ["SetSliderValues"] = function(self, min, max, step)
176 | local frame = self.slider
177 | frame.setup = true
178 | self.min = min
179 | self.max = max
180 | self.step = step
181 | frame:SetMinMaxValues(min or 0,max or 100)
182 | UpdateLabels(self)
183 | frame:SetValueStep(step or 1)
184 | if self.value then
185 | frame:SetValue(self.value)
186 | end
187 | frame.setup = nil
188 | end,
189 |
190 | ["SetIsPercent"] = function(self, value)
191 | self.ispercent = value
192 | UpdateLabels(self)
193 | UpdateText(self)
194 | end
195 | }
196 |
197 | --[[-----------------------------------------------------------------------------
198 | Constructor
199 | -------------------------------------------------------------------------------]]
200 | local SliderBackdrop = {
201 | bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
202 | edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
203 | tile = true, tileSize = 8, edgeSize = 8,
204 | insets = { left = 3, right = 3, top = 6, bottom = 6 }
205 | }
206 |
207 | local ManualBackdrop = {
208 | bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
209 | edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
210 | tile = true, edgeSize = 1, tileSize = 5,
211 | }
212 |
213 | local function Constructor()
214 | local frame = CreateFrame("Frame", nil, UIParent)
215 |
216 | frame:EnableMouse(true)
217 | frame:SetScript("OnMouseDown", Frame_OnMouseDown)
218 |
219 | local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
220 | label:SetPoint("TOPLEFT")
221 | label:SetPoint("TOPRIGHT")
222 | label:SetJustifyH("CENTER")
223 | label:SetHeight(15)
224 |
225 | local slider = CreateFrame("Slider", nil, frame)
226 | slider:SetOrientation("HORIZONTAL")
227 | slider:SetHeight(15)
228 | slider:SetHitRectInsets(0, 0, -10, 0)
229 | slider:SetBackdrop(SliderBackdrop)
230 | slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Horizontal")
231 | slider:SetPoint("TOP", label, "BOTTOM")
232 | slider:SetPoint("LEFT", 3, 0)
233 | slider:SetPoint("RIGHT", -3, 0)
234 | slider:SetValue(0)
235 | slider:SetScript("OnValueChanged",Slider_OnValueChanged)
236 | slider:SetScript("OnEnter", Control_OnEnter)
237 | slider:SetScript("OnLeave", Control_OnLeave)
238 | slider:SetScript("OnMouseUp", Slider_OnMouseUp)
239 | slider:SetScript("OnMouseWheel", Slider_OnMouseWheel)
240 |
241 | local lowtext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
242 | lowtext:SetPoint("TOPLEFT", slider, "BOTTOMLEFT", 2, 3)
243 |
244 | local hightext = slider:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
245 | hightext:SetPoint("TOPRIGHT", slider, "BOTTOMRIGHT", -2, 3)
246 |
247 | local editbox = CreateFrame("EditBox", nil, frame)
248 | editbox:SetAutoFocus(false)
249 | editbox:SetFontObject(GameFontHighlightSmall)
250 | editbox:SetPoint("TOP", slider, "BOTTOM")
251 | editbox:SetHeight(14)
252 | editbox:SetWidth(70)
253 | editbox:SetJustifyH("CENTER")
254 | editbox:EnableMouse(true)
255 | editbox:SetBackdrop(ManualBackdrop)
256 | editbox:SetBackdropColor(0, 0, 0, 0.5)
257 | editbox:SetBackdropBorderColor(0.3, 0.3, 0.30, 0.80)
258 | editbox:SetScript("OnEnter", EditBox_OnEnter)
259 | editbox:SetScript("OnLeave", EditBox_OnLeave)
260 | editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
261 | editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
262 |
263 | local widget = {
264 | label = label,
265 | slider = slider,
266 | lowtext = lowtext,
267 | hightext = hightext,
268 | editbox = editbox,
269 | alignoffset = 25,
270 | frame = frame,
271 | type = Type
272 | }
273 | for method, func in pairs(methods) do
274 | widget[method] = func
275 | end
276 | slider.obj, editbox.obj = widget, widget
277 |
278 | return AceGUI:RegisterAsWidget(widget)
279 | end
280 |
281 | AceGUI:RegisterWidgetType(Type,Constructor,Version)
282 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceConsole-3.0/AceConsole-3.0.lua:
--------------------------------------------------------------------------------
1 | --- **AceConsole-3.0** provides registration facilities for slash commands.
2 | -- You can register slash commands to your custom functions and use the `GetArgs` function to parse them
3 | -- to your addons individual needs.
4 | --
5 | -- **AceConsole-3.0** can be embeded into your addon, either explicitly by calling AceConsole:Embed(MyAddon) or by
6 | -- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
7 | -- and can be accessed directly, without having to explicitly call AceConsole itself.\\
8 | -- It is recommended to embed AceConsole, otherwise you'll have to specify a custom `self` on all calls you
9 | -- make into AceConsole.
10 | -- @class file
11 | -- @name AceConsole-3.0
12 | -- @release $Id: AceConsole-3.0.lua 878 2009-11-02 18:51:58Z nevcairiel $
13 | local MAJOR,MINOR = "AceConsole-3.0", 7
14 |
15 | local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
16 |
17 | if not AceConsole then return end -- No upgrade needed
18 |
19 | AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in.
20 | AceConsole.commands = AceConsole.commands or {} -- table containing commands registered
21 | AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable
22 |
23 | -- Lua APIs
24 | local tconcat, tostring, select = table.concat, tostring, select
25 | local type, pairs, error = type, pairs, error
26 | local format, strfind, strsub = string.format, string.find, string.sub
27 | local max = math.max
28 |
29 | -- WoW APIs
30 | local _G = _G
31 |
32 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
33 | -- List them here for Mikk's FindGlobals script
34 | -- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
35 |
36 | local tmp={}
37 | local function Print(self,frame,...)
38 | local n=0
39 | if self ~= AceConsole then
40 | n=n+1
41 | tmp[n] = "|cff33ff99"..tostring( self ).."|r:"
42 | end
43 | for i=1, select("#", ...) do
44 | n=n+1
45 | tmp[n] = tostring(select(i, ...))
46 | end
47 | frame:AddMessage( tconcat(tmp," ",1,n) )
48 | end
49 |
50 | --- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
51 | -- @paramsig [chatframe ,] ...
52 | -- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
53 | -- @param ... List of any values to be printed
54 | function AceConsole:Print(...)
55 | local frame = ...
56 | if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
57 | return Print(self, frame, select(2,...))
58 | else
59 | return Print(self, DEFAULT_CHAT_FRAME, ...)
60 | end
61 | end
62 |
63 |
64 | --- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
65 | -- @paramsig [chatframe ,] "format"[, ...]
66 | -- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
67 | -- @param format Format string - same syntax as standard Lua format()
68 | -- @param ... Arguments to the format string
69 | function AceConsole:Printf(...)
70 | local frame = ...
71 | if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
72 | return Print(self, frame, format(select(2,...)))
73 | else
74 | return Print(self, DEFAULT_CHAT_FRAME, format(...))
75 | end
76 | end
77 |
78 |
79 |
80 |
81 | --- Register a simple chat command
82 | -- @param command Chat command to be registered WITHOUT leading "/"
83 | -- @param func Function to call when the slash command is being used (funcref or methodname)
84 | -- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
85 | function AceConsole:RegisterChatCommand( command, func, persist )
86 | if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand( "command", func[, persist ]): 'command' - expected a string]], 2) end
87 |
88 | if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk
89 |
90 | local name = "ACECONSOLE_"..command:upper()
91 |
92 | if type( func ) == "string" then
93 | SlashCmdList[name] = function(input, editBox)
94 | self[func](self, input, editBox)
95 | end
96 | else
97 | SlashCmdList[name] = func
98 | end
99 | _G["SLASH_"..name.."1"] = "/"..command:lower()
100 | AceConsole.commands[command] = name
101 | -- non-persisting commands are registered for enabling disabling
102 | if not persist then
103 | if not AceConsole.weakcommands[self] then AceConsole.weakcommands[self] = {} end
104 | AceConsole.weakcommands[self][command] = func
105 | end
106 | return true
107 | end
108 |
109 | --- Unregister a chatcommand
110 | -- @param command Chat command to be unregistered WITHOUT leading "/"
111 | function AceConsole:UnregisterChatCommand( command )
112 | local name = AceConsole.commands[command]
113 | if name then
114 | SlashCmdList[name] = nil
115 | _G["SLASH_" .. name .. "1"] = nil
116 | hash_SlashCmdList["/" .. command:upper()] = nil
117 | AceConsole.commands[command] = nil
118 | end
119 | end
120 |
121 | --- Get an iterator over all Chat Commands registered with AceConsole
122 | -- @return Iterator (pairs) over all commands
123 | function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end
124 |
125 |
126 | local function nils(n, ...)
127 | if n>1 then
128 | return nil, nils(n-1, ...)
129 | elseif n==1 then
130 | return nil, ...
131 | else
132 | return ...
133 | end
134 | end
135 |
136 |
137 | --- Retreive one or more space-separated arguments from a string.
138 | -- Treats quoted strings and itemlinks as non-spaced.
139 | -- @param string The raw argument string
140 | -- @param numargs How many arguments to get (default 1)
141 | -- @param startpos Where in the string to start scanning (default 1)
142 | -- @return Returns arg1, arg2, ..., nextposition\\
143 | -- Missing arguments will be returned as nils. 'nextposition' is returned as 1e9 at the end of the string.
144 | function AceConsole:GetArgs(str, numargs, startpos)
145 | numargs = numargs or 1
146 | startpos = max(startpos or 1, 1)
147 |
148 | local pos=startpos
149 |
150 | -- find start of new arg
151 | pos = strfind(str, "[^ ]", pos)
152 | if not pos then -- whoops, end of string
153 | return nils(numargs, 1e9)
154 | end
155 |
156 | if numargs<1 then
157 | return pos
158 | end
159 |
160 | -- quoted or space separated? find out which pattern to use
161 | local delim_or_pipe
162 | local ch = strsub(str, pos, pos)
163 | if ch=='"' then
164 | pos = pos + 1
165 | delim_or_pipe='([|"])'
166 | elseif ch=="'" then
167 | pos = pos + 1
168 | delim_or_pipe="([|'])"
169 | else
170 | delim_or_pipe="([| ])"
171 | end
172 |
173 | startpos = pos
174 |
175 | while true do
176 | -- find delimiter or hyperlink
177 | local ch,_
178 | pos,_,ch = strfind(str, delim_or_pipe, pos)
179 |
180 | if not pos then break end
181 |
182 | if ch=="|" then
183 | -- some kind of escape
184 |
185 | if strsub(str,pos,pos+1)=="|H" then
186 | -- It's a |H....|hhyper link!|h
187 | pos=strfind(str, "|h", pos+2) -- first |h
188 | if not pos then break end
189 |
190 | pos=strfind(str, "|h", pos+2) -- second |h
191 | if not pos then break end
192 | elseif strsub(str,pos, pos+1) == "|T" then
193 | -- It's a |T....|t texture
194 | pos=strfind(str, "|t", pos+2)
195 | if not pos then break end
196 | end
197 |
198 | pos=pos+2 -- skip past this escape (last |h if it was a hyperlink)
199 |
200 | else
201 | -- found delimiter, done with this arg
202 | return strsub(str, startpos, pos-1), AceConsole:GetArgs(str, numargs-1, pos+1)
203 | end
204 |
205 | end
206 |
207 | -- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink)
208 | return strsub(str, startpos), nils(numargs-1, 1e9)
209 | end
210 |
211 |
212 | --- embedding and embed handling
213 |
214 | local mixins = {
215 | "Print",
216 | "Printf",
217 | "RegisterChatCommand",
218 | "UnregisterChatCommand",
219 | "GetArgs",
220 | }
221 |
222 | -- Embeds AceConsole into the target object making the functions from the mixins list available on target:..
223 | -- @param target target object to embed AceBucket in
224 | function AceConsole:Embed( target )
225 | for k, v in pairs( mixins ) do
226 | target[v] = self[v]
227 | end
228 | self.embeds[target] = true
229 | return target
230 | end
231 |
232 | function AceConsole:OnEmbedEnable( target )
233 | if AceConsole.weakcommands[target] then
234 | for command, func in pairs( AceConsole.weakcommands[target] ) do
235 | target:RegisterChatCommand( command, func, false, true ) -- nonpersisting and silent registry
236 | end
237 | end
238 | end
239 |
240 | function AceConsole:OnEmbedDisable( target )
241 | if AceConsole.weakcommands[target] then
242 | for command, func in pairs( AceConsole.weakcommands[target] ) do
243 | target:UnregisterChatCommand( command ) -- TODO: this could potentially unregister a command from another application in case of command conflicts. Do we care?
244 | end
245 | end
246 | end
247 |
248 | for addon in pairs(AceConsole.embeds) do
249 | AceConsole:Embed(addon)
250 | end
251 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua:
--------------------------------------------------------------------------------
1 | --[[ $Id: CallbackHandler-1.0.lua 965 2010-08-09 00:47:52Z mikk $ ]]
2 | local MAJOR, MINOR = "CallbackHandler-1.0", 6
3 | local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
4 |
5 | if not CallbackHandler then return end -- No upgrade needed
6 |
7 | local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
8 |
9 | -- Lua APIs
10 | local tconcat = table.concat
11 | local assert, error, loadstring = assert, error, loadstring
12 | local setmetatable, rawset, rawget = setmetatable, rawset, rawget
13 | local next, select, pairs, type, tostring = next, select, pairs, type, tostring
14 |
15 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
16 | -- List them here for Mikk's FindGlobals script
17 | -- GLOBALS: geterrorhandler
18 |
19 | local xpcall = xpcall
20 |
21 | local function errorhandler(err)
22 | return geterrorhandler()(err)
23 | end
24 |
25 | local function CreateDispatcher(argCount)
26 | local code = [[
27 | local next, xpcall, eh = ...
28 |
29 | local method, ARGS
30 | local function call() method(ARGS) end
31 |
32 | local function dispatch(handlers, ...)
33 | local index
34 | index, method = next(handlers)
35 | if not method then return end
36 | local OLD_ARGS = ARGS
37 | ARGS = ...
38 | repeat
39 | xpcall(call, eh)
40 | index, method = next(handlers, index)
41 | until not method
42 | ARGS = OLD_ARGS
43 | end
44 |
45 | return dispatch
46 | ]]
47 |
48 | local ARGS, OLD_ARGS = {}, {}
49 | for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
50 | code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
51 | return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
52 | end
53 |
54 | local Dispatchers = setmetatable({}, {__index=function(self, argCount)
55 | local dispatcher = CreateDispatcher(argCount)
56 | rawset(self, argCount, dispatcher)
57 | return dispatcher
58 | end})
59 |
60 | --------------------------------------------------------------------------
61 | -- CallbackHandler:New
62 | --
63 | -- target - target object to embed public APIs in
64 | -- RegisterName - name of the callback registration API, default "RegisterCallback"
65 | -- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
66 | -- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
67 |
68 | function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
69 | -- TODO: Remove this after beta has gone out
70 | assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
71 |
72 | RegisterName = RegisterName or "RegisterCallback"
73 | UnregisterName = UnregisterName or "UnregisterCallback"
74 | if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
75 | UnregisterAllName = "UnregisterAllCallbacks"
76 | end
77 |
78 | -- we declare all objects and exported APIs inside this closure to quickly gain access
79 | -- to e.g. function names, the "target" parameter, etc
80 |
81 |
82 | -- Create the registry object
83 | local events = setmetatable({}, meta)
84 | local registry = { recurse=0, events=events }
85 |
86 | -- registry:Fire() - fires the given event/message into the registry
87 | function registry:Fire(eventname, ...)
88 | if not rawget(events, eventname) or not next(events[eventname]) then return end
89 | local oldrecurse = registry.recurse
90 | registry.recurse = oldrecurse + 1
91 |
92 | Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
93 |
94 | registry.recurse = oldrecurse
95 |
96 | if registry.insertQueue and oldrecurse==0 then
97 | -- Something in one of our callbacks wanted to register more callbacks; they got queued
98 | for eventname,callbacks in pairs(registry.insertQueue) do
99 | 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.
100 | for self,func in pairs(callbacks) do
101 | events[eventname][self] = func
102 | -- fire OnUsed callback?
103 | if first and registry.OnUsed then
104 | registry.OnUsed(registry, target, eventname)
105 | first = nil
106 | end
107 | end
108 | end
109 | registry.insertQueue = nil
110 | end
111 | end
112 |
113 | -- Registration of a callback, handles:
114 | -- self["method"], leads to self["method"](self, ...)
115 | -- self with function ref, leads to functionref(...)
116 | -- "addonId" (instead of self) with function ref, leads to functionref(...)
117 | -- all with an optional arg, which, if present, gets passed as first argument (after self if present)
118 | target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
119 | if type(eventname) ~= "string" then
120 | error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
121 | end
122 |
123 | method = method or eventname
124 |
125 | 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.
126 |
127 | if type(method) ~= "string" and type(method) ~= "function" then
128 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
129 | end
130 |
131 | local regfunc
132 |
133 | if type(method) == "string" then
134 | -- self["method"] calling style
135 | if type(self) ~= "table" then
136 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
137 | elseif self==target then
138 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
139 | elseif type(self[method]) ~= "function" then
140 | error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
141 | end
142 |
143 | if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
144 | local arg=select(1,...)
145 | regfunc = function(...) self[method](self,arg,...) end
146 | else
147 | regfunc = function(...) self[method](self,...) end
148 | end
149 | else
150 | -- function ref with self=object or self="addonId" or self=thread
151 | if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
152 | error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
153 | end
154 |
155 | if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
156 | local arg=select(1,...)
157 | regfunc = function(...) method(arg,...) end
158 | else
159 | regfunc = method
160 | end
161 | end
162 |
163 |
164 | if events[eventname][self] or registry.recurse<1 then
165 | -- if registry.recurse<1 then
166 | -- we're overwriting an existing entry, or not currently recursing. just set it.
167 | events[eventname][self] = regfunc
168 | -- fire OnUsed callback?
169 | if registry.OnUsed and first then
170 | registry.OnUsed(registry, target, eventname)
171 | end
172 | else
173 | -- we're currently processing a callback in this registry, so delay the registration of this new entry!
174 | -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
175 | registry.insertQueue = registry.insertQueue or setmetatable({},meta)
176 | registry.insertQueue[eventname][self] = regfunc
177 | end
178 | end
179 |
180 | -- Unregister a callback
181 | target[UnregisterName] = function(self, eventname)
182 | if not self or self==target then
183 | error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
184 | end
185 | if type(eventname) ~= "string" then
186 | error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
187 | end
188 | if rawget(events, eventname) and events[eventname][self] then
189 | events[eventname][self] = nil
190 | -- Fire OnUnused callback?
191 | if registry.OnUnused and not next(events[eventname]) then
192 | registry.OnUnused(registry, target, eventname)
193 | end
194 | end
195 | if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
196 | registry.insertQueue[eventname][self] = nil
197 | end
198 | end
199 |
200 | -- OPTIONAL: Unregister all callbacks for given selfs/addonIds
201 | if UnregisterAllName then
202 | target[UnregisterAllName] = function(...)
203 | if select("#",...)<1 then
204 | error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
205 | end
206 | if select("#",...)==1 and ...==target then
207 | error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
208 | end
209 |
210 |
211 | for i=1,select("#",...) do
212 | local self = select(i,...)
213 | if registry.insertQueue then
214 | for eventname, callbacks in pairs(registry.insertQueue) do
215 | if callbacks[self] then
216 | callbacks[self] = nil
217 | end
218 | end
219 | end
220 | for eventname, callbacks in pairs(events) do
221 | if callbacks[self] then
222 | callbacks[self] = nil
223 | -- Fire OnUnused callback?
224 | if registry.OnUnused and not next(callbacks) then
225 | registry.OnUnused(registry, target, eventname)
226 | end
227 | end
228 | end
229 | end
230 | end
231 | end
232 |
233 | return registry
234 | end
235 |
236 |
237 | -- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
238 | -- try to upgrade old implicit embeds since the system is selfcontained and
239 | -- relies on closures to work.
240 |
241 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIContainer-Frame.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | Frame Container
3 | -------------------------------------------------------------------------------]]
4 | local Type, Version = "Frame", 21
5 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
6 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
7 |
8 | -- Lua APIs
9 | local pairs, assert, type = pairs, assert, type
10 | local wipe = table.wipe
11 |
12 | -- WoW APIs
13 | local PlaySound = PlaySound
14 | local CreateFrame, UIParent = CreateFrame, UIParent
15 |
16 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
17 | -- List them here for Mikk's FindGlobals script
18 | -- GLOBALS: CLOSE
19 |
20 | --[[-----------------------------------------------------------------------------
21 | Scripts
22 | -------------------------------------------------------------------------------]]
23 | local function Button_OnClick(frame)
24 | PlaySound("gsTitleOptionExit")
25 | frame.obj:Hide()
26 | end
27 |
28 | local function Frame_OnClose(frame)
29 | frame.obj:Fire("OnClose")
30 | end
31 |
32 | local function Frame_OnMouseDown(frame)
33 | AceGUI:ClearFocus()
34 | end
35 |
36 | local function Title_OnMouseDown(frame)
37 | frame:GetParent():StartMoving()
38 | AceGUI:ClearFocus()
39 | end
40 |
41 | local function MoverSizer_OnMouseUp(mover)
42 | local frame = mover:GetParent()
43 | frame:StopMovingOrSizing()
44 | local self = frame.obj
45 | local status = self.status or self.localstatus
46 | status.width = frame:GetWidth()
47 | status.height = frame:GetHeight()
48 | status.top = frame:GetTop()
49 | status.left = frame:GetLeft()
50 | end
51 |
52 | local function SizerSE_OnMouseDown(frame)
53 | frame:GetParent():StartSizing("BOTTOMRIGHT")
54 | AceGUI:ClearFocus()
55 | end
56 |
57 | local function SizerS_OnMouseDown(frame)
58 | frame:GetParent():StartSizing("BOTTOM")
59 | AceGUI:ClearFocus()
60 | end
61 |
62 | local function SizerE_OnMouseDown(frame)
63 | frame:GetParent():StartSizing("RIGHT")
64 | AceGUI:ClearFocus()
65 | end
66 |
67 | local function StatusBar_OnEnter(frame)
68 | frame.obj:Fire("OnEnterStatusBar")
69 | end
70 |
71 | local function StatusBar_OnLeave(frame)
72 | frame.obj:Fire("OnLeaveStatusBar")
73 | end
74 |
75 | --[[-----------------------------------------------------------------------------
76 | Methods
77 | -------------------------------------------------------------------------------]]
78 | local methods = {
79 | ["OnAcquire"] = function(self)
80 | self.frame:SetParent(UIParent)
81 | self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
82 | self:SetTitle()
83 | self:SetStatusText()
84 | self:ApplyStatus()
85 | self:Show()
86 | end,
87 |
88 | ["OnRelease"] = function(self)
89 | self.status = nil
90 | wipe(self.localstatus)
91 | end,
92 |
93 | ["OnWidthSet"] = function(self, width)
94 | local content = self.content
95 | local contentwidth = width - 34
96 | if contentwidth < 0 then
97 | contentwidth = 0
98 | end
99 | content:SetWidth(contentwidth)
100 | content.width = contentwidth
101 | end,
102 |
103 | ["OnHeightSet"] = function(self, height)
104 | local content = self.content
105 | local contentheight = height - 57
106 | if contentheight < 0 then
107 | contentheight = 0
108 | end
109 | content:SetHeight(contentheight)
110 | content.height = contentheight
111 | end,
112 |
113 | ["SetTitle"] = function(self, title)
114 | self.titletext:SetText(title)
115 | end,
116 |
117 | ["SetStatusText"] = function(self, text)
118 | self.statustext:SetText(text)
119 | end,
120 |
121 | ["Hide"] = function(self)
122 | self.frame:Hide()
123 | end,
124 |
125 | ["Show"] = function(self)
126 | self.frame:Show()
127 | end,
128 |
129 | -- called to set an external table to store status in
130 | ["SetStatusTable"] = function(self, status)
131 | assert(type(status) == "table")
132 | self.status = status
133 | self:ApplyStatus()
134 | end,
135 |
136 | ["ApplyStatus"] = function(self)
137 | local status = self.status or self.localstatus
138 | local frame = self.frame
139 | self:SetWidth(status.width or 700)
140 | self:SetHeight(status.height or 500)
141 | frame:ClearAllPoints()
142 | if status.top and status.left then
143 | frame:SetPoint("TOP", UIParent, "BOTTOM", 0, status.top)
144 | frame:SetPoint("LEFT", UIParent, "LEFT", status.left, 0)
145 | else
146 | frame:SetPoint("CENTER")
147 | end
148 | end
149 | }
150 |
151 | --[[-----------------------------------------------------------------------------
152 | Constructor
153 | -------------------------------------------------------------------------------]]
154 | local FrameBackdrop = {
155 | bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
156 | edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
157 | tile = true, tileSize = 32, edgeSize = 32,
158 | insets = { left = 8, right = 8, top = 8, bottom = 8 }
159 | }
160 |
161 | local PaneBackdrop = {
162 | bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
163 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
164 | tile = true, tileSize = 16, edgeSize = 16,
165 | insets = { left = 3, right = 3, top = 5, bottom = 3 }
166 | }
167 |
168 | local function Constructor()
169 | local frame = CreateFrame("Frame", nil, UIParent)
170 | frame:Hide()
171 |
172 | frame:EnableMouse(true)
173 | frame:SetMovable(true)
174 | frame:SetResizable(true)
175 | frame:SetFrameStrata("FULLSCREEN_DIALOG")
176 | frame:SetBackdrop(FrameBackdrop)
177 | frame:SetBackdropColor(0, 0, 0, 1)
178 | frame:SetMinResize(400, 200)
179 | frame:SetToplevel(true)
180 | frame:SetScript("OnHide", Frame_OnClose)
181 | frame:SetScript("OnMouseDown", Frame_OnMouseDown)
182 |
183 | local closebutton = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
184 | closebutton:SetScript("OnClick", Button_OnClick)
185 | closebutton:SetPoint("BOTTOMRIGHT", -27, 17)
186 | closebutton:SetHeight(20)
187 | closebutton:SetWidth(100)
188 | closebutton:SetText(CLOSE)
189 |
190 | local statusbg = CreateFrame("Button", nil, frame)
191 | statusbg:SetPoint("BOTTOMLEFT", 15, 15)
192 | statusbg:SetPoint("BOTTOMRIGHT", -132, 15)
193 | statusbg:SetHeight(24)
194 | statusbg:SetBackdrop(PaneBackdrop)
195 | statusbg:SetBackdropColor(0.1,0.1,0.1)
196 | statusbg:SetBackdropBorderColor(0.4,0.4,0.4)
197 | statusbg:SetScript("OnEnter", StatusBar_OnEnter)
198 | statusbg:SetScript("OnLeave", StatusBar_OnLeave)
199 |
200 | local statustext = statusbg:CreateFontString(nil, "OVERLAY", "GameFontNormal")
201 | statustext:SetPoint("TOPLEFT", 7, -2)
202 | statustext:SetPoint("BOTTOMRIGHT", -7, 2)
203 | statustext:SetHeight(20)
204 | statustext:SetJustifyH("LEFT")
205 | statustext:SetText("")
206 |
207 | local titlebg = frame:CreateTexture(nil, "OVERLAY")
208 | titlebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
209 | titlebg:SetTexCoord(0.31, 0.67, 0, 0.63)
210 | titlebg:SetPoint("TOP", 0, 12)
211 | titlebg:SetWidth(100)
212 | titlebg:SetHeight(40)
213 |
214 | local title = CreateFrame("Frame", nil, frame)
215 | title:EnableMouse(true)
216 | title:SetScript("OnMouseDown", Title_OnMouseDown)
217 | title:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
218 | title:SetAllPoints(titlebg)
219 |
220 | local titletext = title:CreateFontString(nil, "OVERLAY", "GameFontNormal")
221 | titletext:SetPoint("TOP", titlebg, "TOP", 0, -14)
222 |
223 | local titlebg_l = frame:CreateTexture(nil, "OVERLAY")
224 | titlebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
225 | titlebg_l:SetTexCoord(0.21, 0.31, 0, 0.63)
226 | titlebg_l:SetPoint("RIGHT", titlebg, "LEFT")
227 | titlebg_l:SetWidth(30)
228 | titlebg_l:SetHeight(40)
229 |
230 | local titlebg_r = frame:CreateTexture(nil, "OVERLAY")
231 | titlebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
232 | titlebg_r:SetTexCoord(0.67, 0.77, 0, 0.63)
233 | titlebg_r:SetPoint("LEFT", titlebg, "RIGHT")
234 | titlebg_r:SetWidth(30)
235 | titlebg_r:SetHeight(40)
236 |
237 | local sizer_se = CreateFrame("Frame", nil, frame)
238 | sizer_se:SetPoint("BOTTOMRIGHT")
239 | sizer_se:SetWidth(25)
240 | sizer_se:SetHeight(25)
241 | sizer_se:EnableMouse()
242 | sizer_se:SetScript("OnMouseDown",SizerSE_OnMouseDown)
243 | sizer_se:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
244 |
245 | local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
246 | line1:SetWidth(14)
247 | line1:SetHeight(14)
248 | line1:SetPoint("BOTTOMRIGHT", -8, 8)
249 | line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
250 | local x = 0.1 * 14/17
251 | line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
252 |
253 | local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
254 | line2:SetWidth(8)
255 | line2:SetHeight(8)
256 | line2:SetPoint("BOTTOMRIGHT", -8, 8)
257 | line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
258 | local x = 0.1 * 8/17
259 | line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
260 |
261 | local sizer_s = CreateFrame("Frame", nil, frame)
262 | sizer_s:SetPoint("BOTTOMRIGHT", -25, 0)
263 | sizer_s:SetPoint("BOTTOMLEFT")
264 | sizer_s:SetHeight(25)
265 | sizer_s:EnableMouse(true)
266 | sizer_s:SetScript("OnMouseDown", SizerS_OnMouseDown)
267 | sizer_s:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
268 |
269 | local sizer_e = CreateFrame("Frame", nil, frame)
270 | sizer_e:SetPoint("BOTTOMRIGHT", 0, 25)
271 | sizer_e:SetPoint("TOPRIGHT")
272 | sizer_e:SetWidth(25)
273 | sizer_e:EnableMouse(true)
274 | sizer_e:SetScript("OnMouseDown", SizerE_OnMouseDown)
275 | sizer_e:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
276 |
277 | --Container Support
278 | local content = CreateFrame("Frame", nil, frame)
279 | content:SetPoint("TOPLEFT", 17, -27)
280 | content:SetPoint("BOTTOMRIGHT", -17, 40)
281 |
282 | local widget = {
283 | localstatus = {},
284 | titletext = titletext,
285 | statustext = statustext,
286 | content = content,
287 | frame = frame,
288 | type = Type
289 | }
290 | for method, func in pairs(methods) do
291 | widget[method] = func
292 | end
293 | closebutton.obj, statusbg.obj = widget, widget
294 |
295 | return AceGUI:RegisterAsContainer(widget)
296 | end
297 |
298 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
299 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua:
--------------------------------------------------------------------------------
1 | local Type, Version = "MultiLineEditBox", 23
2 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
3 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
4 |
5 | -- Lua APIs
6 | local pairs = pairs
7 |
8 | -- WoW APIs
9 | local GetCursorInfo, GetSpellName, ClearCursor = GetCursorInfo, GetSpellName, ClearCursor
10 | local CreateFrame, UIParent = CreateFrame, UIParent
11 | local _G = _G
12 |
13 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
14 | -- List them here for Mikk's FindGlobals script
15 | -- GLOBALS: ACCEPT, ChatFontNormal
16 |
17 | --[[-----------------------------------------------------------------------------
18 | Support functions
19 | -------------------------------------------------------------------------------]]
20 | local function Layout(self)
21 | self:SetHeight(self.numlines * 14 + (self.disablebutton and 19 or 41) + self.labelHeight)
22 |
23 | if self.labelHeight == 0 then
24 | self.scrollBar:SetPoint("TOP", self.frame, "TOP", 0, -23)
25 | else
26 | self.scrollBar:SetPoint("TOP", self.label, "BOTTOM", 0, -19)
27 | end
28 |
29 | if self.disablebutton then
30 | self.scrollBar:SetPoint("BOTTOM", self.frame, "BOTTOM", 0, 21)
31 | self.scrollBG:SetPoint("BOTTOMLEFT", 0, 4)
32 | else
33 | self.scrollBar:SetPoint("BOTTOM", self.button, "TOP", 0, 18)
34 | self.scrollBG:SetPoint("BOTTOMLEFT", self.button, "TOPLEFT")
35 | end
36 | end
37 |
38 | --[[-----------------------------------------------------------------------------
39 | Scripts
40 | -------------------------------------------------------------------------------]]
41 | local function OnClick(self) -- Button
42 | self = self.obj
43 | self.editBox:ClearFocus()
44 | if not self:Fire("OnEnterPressed", self.editBox:GetText()) then
45 | self.button:Disable()
46 | end
47 | end
48 |
49 | local function OnCursorChanged(self, _, y, _, cursorHeight) -- EditBox
50 | self, y = self.obj.scrollFrame, -y
51 | local offset = self:GetVerticalScroll()
52 | if y < offset then
53 | self:SetVerticalScroll(y)
54 | else
55 | y = y + cursorHeight - self:GetHeight()
56 | if y > offset then
57 | self:SetVerticalScroll(y)
58 | end
59 | end
60 | end
61 |
62 | local function OnEditFocusLost(self) -- EditBox
63 | self:HighlightText(0, 0)
64 | end
65 |
66 | local function OnEnter(self) -- EditBox / ScrollFrame
67 | self = self.obj
68 | if not self.entered then
69 | self.entered = true
70 | self:Fire("OnEnter")
71 | end
72 | end
73 |
74 | local function OnLeave(self) -- EditBox / ScrollFrame
75 | self = self.obj
76 | if self.entered then
77 | self.entered = nil
78 | self:Fire("OnLeave")
79 | end
80 | end
81 |
82 | local function OnMouseUp(self) -- ScrollFrame
83 | self = self.obj.editBox
84 | self:SetFocus()
85 | self:SetCursorPosition(self:GetNumLetters())
86 | end
87 |
88 | local function OnReceiveDrag(self) -- EditBox / ScrollFrame
89 | local type, id, info = GetCursorInfo()
90 | if type == "spell" then
91 | info, id = GetSpellName(id, info)
92 | if id and id:match("%d") then
93 | info = info .. "(" .. id .. ")"
94 | end
95 | elseif type ~= "item" then
96 | return
97 | end
98 | ClearCursor()
99 | self = self.obj
100 | local editBox = self.editBox
101 | if not editBox:HasFocus() then
102 | editBox:SetFocus()
103 | editBox:SetCursorPosition(editBox:GetNumLetters())
104 | end
105 | editBox:Insert(info)
106 | self.button:Enable()
107 | end
108 |
109 | local function OnSizeChanged(self, width, height) -- ScrollFrame
110 | self.obj.editBox:SetWidth(width)
111 | end
112 |
113 | local function OnTextChanged(self, userInput) -- EditBox
114 | if userInput then
115 | self = self.obj
116 | self:Fire("OnTextChanged", self.editBox:GetText())
117 | self.button:Enable()
118 | end
119 | end
120 |
121 | local function OnTextSet(self) -- EditBox
122 | self:HighlightText(0, 0)
123 | self:SetCursorPosition(self:GetNumLetters())
124 | self:SetCursorPosition(0)
125 | self.obj.button:Disable()
126 | end
127 |
128 | local function OnVerticalScroll(self, offset) -- ScrollFrame
129 | local editBox = self.obj.editBox
130 | editBox:SetHitRectInsets(0, 0, offset, editBox:GetHeight() - offset - self:GetHeight())
131 | end
132 |
133 | --[[-----------------------------------------------------------------------------
134 | Methods
135 | -------------------------------------------------------------------------------]]
136 | local methods = {
137 | ["OnAcquire"] = function(self)
138 | self.editBox:SetText("")
139 | self:SetDisabled(false)
140 | self:SetWidth(200)
141 | self:DisableButton(false)
142 | self:SetNumLines()
143 | self.entered = nil
144 | self:SetMaxLetters(0)
145 | end,
146 |
147 | -- ["OnRelease"] = nil,
148 |
149 | ["SetDisabled"] = function(self, disabled)
150 | local editBox = self.editBox
151 | if disabled then
152 | editBox:ClearFocus()
153 | editBox:EnableMouse(false)
154 | editBox:SetTextColor(0.5, 0.5, 0.5)
155 | self.label:SetTextColor(0.5, 0.5, 0.5)
156 | self.scrollFrame:EnableMouse(false)
157 | self.button:Disable()
158 | else
159 | editBox:EnableMouse(true)
160 | editBox:SetTextColor(1, 1, 1)
161 | self.label:SetTextColor(1, 0.82, 0)
162 | self.scrollFrame:EnableMouse(true)
163 | end
164 | end,
165 |
166 | ["SetLabel"] = function(self, text)
167 | if text and text ~= "" then
168 | self.label:SetText(text)
169 | if self.labelHeight ~= 10 then
170 | self.labelHeight = 10
171 | self.label:Show()
172 | end
173 | elseif self.labelHeight ~= 0 then
174 | self.labelHeight = 0
175 | self.label:Hide()
176 | end
177 | Layout(self)
178 | end,
179 |
180 | ["SetNumLines"] = function(self, value)
181 | if not value or value < 4 then
182 | value = 4
183 | end
184 | self.numlines = value
185 | Layout(self)
186 | end,
187 |
188 | ["SetText"] = function(self, text)
189 | self.editBox:SetText(text)
190 | end,
191 |
192 | ["GetText"] = function(self)
193 | return self.editBox:GetText()
194 | end,
195 |
196 | ["SetMaxLetters"] = function (self, num)
197 | self.editBox:SetMaxLetters(num or 0)
198 | end,
199 |
200 | ["DisableButton"] = function(self, disabled)
201 | self.disablebutton = disabled
202 | if disabled then
203 | self.button:Hide()
204 | else
205 | self.button:Show()
206 | end
207 | Layout(self)
208 | end
209 | }
210 |
211 | --[[-----------------------------------------------------------------------------
212 | Constructor
213 | -------------------------------------------------------------------------------]]
214 | local backdrop = {
215 | bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
216 | edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
217 | insets = { left = 4, right = 3, top = 4, bottom = 3 }
218 | }
219 |
220 | local function Constructor()
221 | local frame = CreateFrame("Frame", nil, UIParent)
222 | frame:Hide()
223 |
224 | local widgetNum = AceGUI:GetNextWidgetNum(Type)
225 |
226 | local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
227 | label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, -4)
228 | label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -4)
229 | label:SetJustifyH("LEFT")
230 | label:SetText(ACCEPT)
231 | label:SetHeight(10)
232 |
233 | local button = CreateFrame("Button", ("%s%dButton"):format(Type, widgetNum), frame, "UIPanelButtonTemplate2")
234 | button:SetPoint("BOTTOMLEFT", 0, 4)
235 | button:SetHeight(22)
236 | button:SetWidth(label:GetStringWidth() + 24)
237 | button:SetText(ACCEPT)
238 | button:SetScript("OnClick", OnClick)
239 | button:Disable()
240 |
241 | local text = button:GetFontString()
242 | text:ClearAllPoints()
243 | text:SetPoint("TOPLEFT", button, "TOPLEFT", 5, -5)
244 | text:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -5, 1)
245 | text:SetJustifyV("MIDDLE")
246 |
247 | local scrollBG = CreateFrame("Frame", nil, frame)
248 | scrollBG:SetBackdrop(backdrop)
249 | scrollBG:SetBackdropColor(0, 0, 0)
250 | scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4)
251 |
252 | local scrollFrame = CreateFrame("ScrollFrame", ("%s%dScrollFrame"):format(Type, widgetNum), frame, "UIPanelScrollFrameTemplate")
253 |
254 | local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"]
255 | scrollBar:ClearAllPoints()
256 | scrollBar:SetPoint("TOP", label, "BOTTOM", 0, -19)
257 | scrollBar:SetPoint("BOTTOM", button, "TOP", 0, 18)
258 | scrollBar:SetPoint("RIGHT", frame, "RIGHT")
259 |
260 | scrollBG:SetPoint("TOPRIGHT", scrollBar, "TOPLEFT", 0, 19)
261 | scrollBG:SetPoint("BOTTOMLEFT", button, "TOPLEFT")
262 |
263 | scrollFrame:SetPoint("TOPLEFT", scrollBG, "TOPLEFT", 5, -6)
264 | scrollFrame:SetPoint("BOTTOMRIGHT", scrollBG, "BOTTOMRIGHT", -4, 4)
265 | scrollFrame:SetScript("OnEnter", OnEnter)
266 | scrollFrame:SetScript("OnLeave", OnLeave)
267 | scrollFrame:SetScript("OnMouseUp", OnMouseUp)
268 | scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag)
269 | scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
270 | scrollFrame:HookScript("OnVerticalScroll", OnVerticalScroll)
271 |
272 | local editBox = CreateFrame("EditBox", nil, scrollFrame)
273 | editBox:SetAllPoints()
274 | editBox:SetFontObject(ChatFontNormal)
275 | editBox:SetMultiLine(true)
276 | editBox:EnableMouse(true)
277 | editBox:SetAutoFocus(false)
278 | editBox:SetCountInvisibleLetters(false)
279 | editBox:SetScript("OnCursorChanged", OnCursorChanged)
280 | editBox:SetScript("OnEditFocusLost", OnEditFocusLost)
281 | editBox:SetScript("OnEnter", OnEnter)
282 | editBox:SetScript("OnEscapePressed", editBox.ClearFocus)
283 | editBox:SetScript("OnLeave", OnLeave)
284 | editBox:SetScript("OnMouseDown", OnReceiveDrag)
285 | editBox:SetScript("OnReceiveDrag", OnReceiveDrag)
286 | editBox:SetScript("OnTextChanged", OnTextChanged)
287 | editBox:SetScript("OnTextSet", OnTextSet)
288 |
289 | scrollFrame:SetScrollChild(editBox)
290 |
291 | local widget = {
292 | button = button,
293 | editBox = editBox,
294 | frame = frame,
295 | label = label,
296 | labelHeight = 10,
297 | numlines = 4,
298 | scrollBar = scrollBar,
299 | scrollBG = scrollBG,
300 | scrollFrame = scrollFrame,
301 | type = Type
302 | }
303 | for method, func in pairs(methods) do
304 | widget[method] = func
305 | end
306 | button.obj, editBox.obj, scrollFrame.obj = widget, widget, widget
307 |
308 | return AceGUI:RegisterAsWidget(widget)
309 | end
310 |
311 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
312 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIContainer-Window.lua:
--------------------------------------------------------------------------------
1 | local AceGUI = LibStub("AceGUI-3.0")
2 |
3 | -- Lua APIs
4 | local pairs, assert, type = pairs, assert, type
5 |
6 | -- WoW APIs
7 | local PlaySound = PlaySound
8 | local CreateFrame, UIParent = CreateFrame, UIParent
9 |
10 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
11 | -- List them here for Mikk's FindGlobals script
12 | -- GLOBALS: GameFontNormal
13 |
14 | ----------------
15 | -- Main Frame --
16 | ----------------
17 | --[[
18 | Events :
19 | OnClose
20 |
21 | ]]
22 | do
23 | local Type = "Window"
24 | local Version = 4
25 |
26 | local function frameOnClose(this)
27 | this.obj:Fire("OnClose")
28 | end
29 |
30 | local function closeOnClick(this)
31 | PlaySound("gsTitleOptionExit")
32 | this.obj:Hide()
33 | end
34 |
35 | local function frameOnMouseDown(this)
36 | AceGUI:ClearFocus()
37 | end
38 |
39 | local function titleOnMouseDown(this)
40 | this:GetParent():StartMoving()
41 | AceGUI:ClearFocus()
42 | end
43 |
44 | local function frameOnMouseUp(this)
45 | local frame = this:GetParent()
46 | frame:StopMovingOrSizing()
47 | local self = frame.obj
48 | local status = self.status or self.localstatus
49 | status.width = frame:GetWidth()
50 | status.height = frame:GetHeight()
51 | status.top = frame:GetTop()
52 | status.left = frame:GetLeft()
53 | end
54 |
55 | local function sizerseOnMouseDown(this)
56 | this:GetParent():StartSizing("BOTTOMRIGHT")
57 | AceGUI:ClearFocus()
58 | end
59 |
60 | local function sizersOnMouseDown(this)
61 | this:GetParent():StartSizing("BOTTOM")
62 | AceGUI:ClearFocus()
63 | end
64 |
65 | local function sizereOnMouseDown(this)
66 | this:GetParent():StartSizing("RIGHT")
67 | AceGUI:ClearFocus()
68 | end
69 |
70 | local function sizerOnMouseUp(this)
71 | this:GetParent():StopMovingOrSizing()
72 | end
73 |
74 | local function SetTitle(self,title)
75 | self.titletext:SetText(title)
76 | end
77 |
78 | local function SetStatusText(self,text)
79 | -- self.statustext:SetText(text)
80 | end
81 |
82 | local function Hide(self)
83 | self.frame:Hide()
84 | end
85 |
86 | local function Show(self)
87 | self.frame:Show()
88 | end
89 |
90 | local function OnAcquire(self)
91 | self.frame:SetParent(UIParent)
92 | self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
93 | self:ApplyStatus()
94 | self:EnableResize(true)
95 | self:Show()
96 | end
97 |
98 | local function OnRelease(self)
99 | self.status = nil
100 | for k in pairs(self.localstatus) do
101 | self.localstatus[k] = nil
102 | end
103 | end
104 |
105 | -- called to set an external table to store status in
106 | local function SetStatusTable(self, status)
107 | assert(type(status) == "table")
108 | self.status = status
109 | self:ApplyStatus()
110 | end
111 |
112 | local function ApplyStatus(self)
113 | local status = self.status or self.localstatus
114 | local frame = self.frame
115 | self:SetWidth(status.width or 700)
116 | self:SetHeight(status.height or 500)
117 | if status.top and status.left then
118 | frame:SetPoint("TOP",UIParent,"BOTTOM",0,status.top)
119 | frame:SetPoint("LEFT",UIParent,"LEFT",status.left,0)
120 | else
121 | frame:SetPoint("CENTER",UIParent,"CENTER")
122 | end
123 | end
124 |
125 | local function OnWidthSet(self, width)
126 | local content = self.content
127 | local contentwidth = width - 34
128 | if contentwidth < 0 then
129 | contentwidth = 0
130 | end
131 | content:SetWidth(contentwidth)
132 | content.width = contentwidth
133 | end
134 |
135 |
136 | local function OnHeightSet(self, height)
137 | local content = self.content
138 | local contentheight = height - 57
139 | if contentheight < 0 then
140 | contentheight = 0
141 | end
142 | content:SetHeight(contentheight)
143 | content.height = contentheight
144 | end
145 |
146 | local function EnableResize(self, state)
147 | local func = state and "Show" or "Hide"
148 | self.sizer_se[func](self.sizer_se)
149 | self.sizer_s[func](self.sizer_s)
150 | self.sizer_e[func](self.sizer_e)
151 | end
152 |
153 | local function Constructor()
154 | local frame = CreateFrame("Frame",nil,UIParent)
155 | local self = {}
156 | self.type = "Window"
157 |
158 | self.Hide = Hide
159 | self.Show = Show
160 | self.SetTitle = SetTitle
161 | self.OnRelease = OnRelease
162 | self.OnAcquire = OnAcquire
163 | self.SetStatusText = SetStatusText
164 | self.SetStatusTable = SetStatusTable
165 | self.ApplyStatus = ApplyStatus
166 | self.OnWidthSet = OnWidthSet
167 | self.OnHeightSet = OnHeightSet
168 | self.EnableResize = EnableResize
169 |
170 | self.localstatus = {}
171 |
172 | self.frame = frame
173 | frame.obj = self
174 | frame:SetWidth(700)
175 | frame:SetHeight(500)
176 | frame:SetPoint("CENTER",UIParent,"CENTER",0,0)
177 | frame:EnableMouse()
178 | frame:SetMovable(true)
179 | frame:SetResizable(true)
180 | frame:SetFrameStrata("FULLSCREEN_DIALOG")
181 | frame:SetScript("OnMouseDown", frameOnMouseDown)
182 |
183 | frame:SetScript("OnHide",frameOnClose)
184 | frame:SetMinResize(240,240)
185 | frame:SetToplevel(true)
186 |
187 | local titlebg = frame:CreateTexture(nil, "BACKGROUND")
188 | titlebg:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Title-Background]])
189 | titlebg:SetPoint("TOPLEFT", 9, -6)
190 | titlebg:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", -28, -24)
191 |
192 | local dialogbg = frame:CreateTexture(nil, "BACKGROUND")
193 | dialogbg:SetTexture([[Interface\Tooltips\UI-Tooltip-Background]])
194 | dialogbg:SetPoint("TOPLEFT", 8, -24)
195 | dialogbg:SetPoint("BOTTOMRIGHT", -6, 8)
196 | dialogbg:SetVertexColor(0, 0, 0, .75)
197 |
198 | local topleft = frame:CreateTexture(nil, "BORDER")
199 | topleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
200 | topleft:SetWidth(64)
201 | topleft:SetHeight(64)
202 | topleft:SetPoint("TOPLEFT")
203 | topleft:SetTexCoord(0.501953125, 0.625, 0, 1)
204 |
205 | local topright = frame:CreateTexture(nil, "BORDER")
206 | topright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
207 | topright:SetWidth(64)
208 | topright:SetHeight(64)
209 | topright:SetPoint("TOPRIGHT")
210 | topright:SetTexCoord(0.625, 0.75, 0, 1)
211 |
212 | local top = frame:CreateTexture(nil, "BORDER")
213 | top:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
214 | top:SetHeight(64)
215 | top:SetPoint("TOPLEFT", topleft, "TOPRIGHT")
216 | top:SetPoint("TOPRIGHT", topright, "TOPLEFT")
217 | top:SetTexCoord(0.25, 0.369140625, 0, 1)
218 |
219 | local bottomleft = frame:CreateTexture(nil, "BORDER")
220 | bottomleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
221 | bottomleft:SetWidth(64)
222 | bottomleft:SetHeight(64)
223 | bottomleft:SetPoint("BOTTOMLEFT")
224 | bottomleft:SetTexCoord(0.751953125, 0.875, 0, 1)
225 |
226 | local bottomright = frame:CreateTexture(nil, "BORDER")
227 | bottomright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
228 | bottomright:SetWidth(64)
229 | bottomright:SetHeight(64)
230 | bottomright:SetPoint("BOTTOMRIGHT")
231 | bottomright:SetTexCoord(0.875, 1, 0, 1)
232 |
233 | local bottom = frame:CreateTexture(nil, "BORDER")
234 | bottom:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
235 | bottom:SetHeight(64)
236 | bottom:SetPoint("BOTTOMLEFT", bottomleft, "BOTTOMRIGHT")
237 | bottom:SetPoint("BOTTOMRIGHT", bottomright, "BOTTOMLEFT")
238 | bottom:SetTexCoord(0.376953125, 0.498046875, 0, 1)
239 |
240 | local left = frame:CreateTexture(nil, "BORDER")
241 | left:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
242 | left:SetWidth(64)
243 | left:SetPoint("TOPLEFT", topleft, "BOTTOMLEFT")
244 | left:SetPoint("BOTTOMLEFT", bottomleft, "TOPLEFT")
245 | left:SetTexCoord(0.001953125, 0.125, 0, 1)
246 |
247 | local right = frame:CreateTexture(nil, "BORDER")
248 | right:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
249 | right:SetWidth(64)
250 | right:SetPoint("TOPRIGHT", topright, "BOTTOMRIGHT")
251 | right:SetPoint("BOTTOMRIGHT", bottomright, "TOPRIGHT")
252 | right:SetTexCoord(0.1171875, 0.2421875, 0, 1)
253 |
254 | local close = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
255 | close:SetPoint("TOPRIGHT", 2, 1)
256 | close:SetScript("OnClick", closeOnClick)
257 | self.closebutton = close
258 | close.obj = self
259 |
260 | local titletext = frame:CreateFontString(nil, "ARTWORK")
261 | titletext:SetFontObject(GameFontNormal)
262 | titletext:SetPoint("TOPLEFT", 12, -8)
263 | titletext:SetPoint("TOPRIGHT", -32, -8)
264 | self.titletext = titletext
265 |
266 | local title = CreateFrame("Button", nil, frame)
267 | title:SetPoint("TOPLEFT", titlebg)
268 | title:SetPoint("BOTTOMRIGHT", titlebg)
269 | title:EnableMouse()
270 | title:SetScript("OnMouseDown",titleOnMouseDown)
271 | title:SetScript("OnMouseUp", frameOnMouseUp)
272 | self.title = title
273 |
274 | local sizer_se = CreateFrame("Frame",nil,frame)
275 | sizer_se:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
276 | sizer_se:SetWidth(25)
277 | sizer_se:SetHeight(25)
278 | sizer_se:EnableMouse()
279 | sizer_se:SetScript("OnMouseDown",sizerseOnMouseDown)
280 | sizer_se:SetScript("OnMouseUp", sizerOnMouseUp)
281 | self.sizer_se = sizer_se
282 |
283 | local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
284 | self.line1 = line1
285 | line1:SetWidth(14)
286 | line1:SetHeight(14)
287 | line1:SetPoint("BOTTOMRIGHT", -8, 8)
288 | line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
289 | local x = 0.1 * 14/17
290 | line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
291 |
292 | local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
293 | self.line2 = line2
294 | line2:SetWidth(8)
295 | line2:SetHeight(8)
296 | line2:SetPoint("BOTTOMRIGHT", -8, 8)
297 | line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
298 | local x = 0.1 * 8/17
299 | line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
300 |
301 | local sizer_s = CreateFrame("Frame",nil,frame)
302 | sizer_s:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-25,0)
303 | sizer_s:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
304 | sizer_s:SetHeight(25)
305 | sizer_s:EnableMouse()
306 | sizer_s:SetScript("OnMouseDown",sizersOnMouseDown)
307 | sizer_s:SetScript("OnMouseUp", sizerOnMouseUp)
308 | self.sizer_s = sizer_s
309 |
310 | local sizer_e = CreateFrame("Frame",nil,frame)
311 | sizer_e:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,25)
312 | sizer_e:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
313 | sizer_e:SetWidth(25)
314 | sizer_e:EnableMouse()
315 | sizer_e:SetScript("OnMouseDown",sizereOnMouseDown)
316 | sizer_e:SetScript("OnMouseUp", sizerOnMouseUp)
317 | self.sizer_e = sizer_e
318 |
319 | --Container Support
320 | local content = CreateFrame("Frame",nil,frame)
321 | self.content = content
322 | content.obj = self
323 | content:SetPoint("TOPLEFT",frame,"TOPLEFT",12,-32)
324 | content:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-12,13)
325 |
326 | AceGUI:RegisterAsContainer(self)
327 | return self
328 | end
329 |
330 | AceGUI:RegisterWidgetType(Type,Constructor,Version)
331 | end
332 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Libs/AceGUI-3.0/widgets/AceGUIContainer-TabGroup.lua:
--------------------------------------------------------------------------------
1 | --[[-----------------------------------------------------------------------------
2 | TabGroup Container
3 | Container that uses tabs on top to switch between groups.
4 | -------------------------------------------------------------------------------]]
5 | local Type, Version = "TabGroup", 30
6 | local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
7 | if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
8 |
9 | -- Lua APIs
10 | local pairs, ipairs, assert, type, wipe = pairs, ipairs, assert, type, wipe
11 |
12 | -- WoW APIs
13 | local PlaySound = PlaySound
14 | local CreateFrame, UIParent = CreateFrame, UIParent
15 | local _G = _G
16 |
17 | -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
18 | -- List them here for Mikk's FindGlobals script
19 | -- GLOBALS: PanelTemplates_TabResize, PanelTemplates_SetDisabledTabState, PanelTemplates_SelectTab, PanelTemplates_DeselectTab
20 |
21 | -- local upvalue storage used by BuildTabs
22 | local widths = {}
23 | local rowwidths = {}
24 | local rowends = {}
25 |
26 | --[[-----------------------------------------------------------------------------
27 | Support functions
28 | -------------------------------------------------------------------------------]]
29 | local function UpdateTabLook(frame)
30 | if frame.disabled then
31 | PanelTemplates_SetDisabledTabState(frame)
32 | elseif frame.selected then
33 | PanelTemplates_SelectTab(frame)
34 | else
35 | PanelTemplates_DeselectTab(frame)
36 | end
37 | end
38 |
39 | local function Tab_SetText(frame, text)
40 | frame:_SetText(text)
41 | local width = frame.obj.frame.width or frame.obj.frame:GetWidth() or 0
42 | PanelTemplates_TabResize(frame, 0, nil, width)
43 | end
44 |
45 | local function Tab_SetSelected(frame, selected)
46 | frame.selected = selected
47 | UpdateTabLook(frame)
48 | end
49 |
50 | local function Tab_SetDisabled(frame, disabled)
51 | frame.disabled = disabled
52 | UpdateTabLook(frame)
53 | end
54 |
55 | local function BuildTabsOnUpdate(frame)
56 | local self = frame.obj
57 | self:BuildTabs()
58 | frame:SetScript("OnUpdate", nil)
59 | end
60 |
61 | --[[-----------------------------------------------------------------------------
62 | Scripts
63 | -------------------------------------------------------------------------------]]
64 | local function Tab_OnClick(frame)
65 | if not (frame.selected or frame.disabled) then
66 | PlaySound("igCharacterInfoTab")
67 | frame.obj:SelectTab(frame.value)
68 | end
69 | end
70 |
71 | local function Tab_OnEnter(frame)
72 | local self = frame.obj
73 | self:Fire("OnTabEnter", self.tabs[frame.id].value, frame)
74 | end
75 |
76 | local function Tab_OnLeave(frame)
77 | local self = frame.obj
78 | self:Fire("OnTabLeave", self.tabs[frame.id].value, frame)
79 | end
80 |
81 | local function Tab_OnShow(frame)
82 | _G[frame:GetName().."HighlightTexture"]:SetWidth(frame:GetTextWidth() + 30)
83 | end
84 |
85 | --[[-----------------------------------------------------------------------------
86 | Methods
87 | -------------------------------------------------------------------------------]]
88 | local methods = {
89 | ["OnAcquire"] = function(self)
90 | self:SetTitle()
91 | end,
92 |
93 | ["OnRelease"] = function(self)
94 | self.status = nil
95 | for k in pairs(self.localstatus) do
96 | self.localstatus[k] = nil
97 | end
98 | self.tablist = nil
99 | for _, tab in pairs(self.tabs) do
100 | tab:Hide()
101 | end
102 | end,
103 |
104 | ["CreateTab"] = function(self, id)
105 | local tabname = ("AceGUITabGroup%dTab%d"):format(self.num, id)
106 | local tab = CreateFrame("Button", tabname, self.border, "OptionsFrameTabButtonTemplate")
107 | tab.obj = self
108 | tab.id = id
109 |
110 | tab.text = _G[tabname .. "Text"]
111 | tab.text:ClearAllPoints()
112 | tab.text:SetPoint("LEFT", 14, -3)
113 | tab.text:SetPoint("RIGHT", -12, -3)
114 |
115 | tab:SetScript("OnClick", Tab_OnClick)
116 | tab:SetScript("OnEnter", Tab_OnEnter)
117 | tab:SetScript("OnLeave", Tab_OnLeave)
118 | tab:SetScript("OnShow", Tab_OnShow)
119 |
120 | tab._SetText = tab.SetText
121 | tab.SetText = Tab_SetText
122 | tab.SetSelected = Tab_SetSelected
123 | tab.SetDisabled = Tab_SetDisabled
124 |
125 | return tab
126 | end,
127 |
128 | ["SetTitle"] = function(self, text)
129 | self.titletext:SetText(text or "")
130 | if text and text ~= "" then
131 | self.alignoffset = 25
132 | else
133 | self.alignoffset = 18
134 | end
135 | self:BuildTabs()
136 | end,
137 |
138 | ["SetStatusTable"] = function(self, status)
139 | assert(type(status) == "table")
140 | self.status = status
141 | end,
142 |
143 | ["SelectTab"] = function(self, value)
144 | local status = self.status or self.localstatus
145 | local found
146 | for i, v in ipairs(self.tabs) do
147 | if v.value == value then
148 | v:SetSelected(true)
149 | found = true
150 | else
151 | v:SetSelected(false)
152 | end
153 | end
154 | status.selected = value
155 | if found then
156 | self:Fire("OnGroupSelected",value)
157 | end
158 | end,
159 |
160 | ["SetTabs"] = function(self, tabs)
161 | self.tablist = tabs
162 | self:BuildTabs()
163 | end,
164 |
165 |
166 | ["BuildTabs"] = function(self)
167 | local hastitle = (self.titletext:GetText() and self.titletext:GetText() ~= "")
168 | local status = self.status or self.localstatus
169 | local tablist = self.tablist
170 | local tabs = self.tabs
171 |
172 | if not tablist then return end
173 |
174 | local width = self.frame.width or self.frame:GetWidth() or 0
175 |
176 | wipe(widths)
177 | wipe(rowwidths)
178 | wipe(rowends)
179 |
180 | --Place Text into tabs and get thier initial width
181 | for i, v in ipairs(tablist) do
182 | local tab = tabs[i]
183 | if not tab then
184 | tab = self:CreateTab(i)
185 | tabs[i] = tab
186 | end
187 |
188 | tab:Show()
189 | tab:SetText(v.text)
190 | tab:SetDisabled(v.disabled)
191 | tab.value = v.value
192 |
193 | widths[i] = tab:GetWidth() - 6 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing, but add a fixed 4px padding for the text
194 | end
195 |
196 | for i = (#tablist)+1, #tabs, 1 do
197 | tabs[i]:Hide()
198 | end
199 |
200 | --First pass, find the minimum number of rows needed to hold all tabs and the initial tab layout
201 | local numtabs = #tablist
202 | local numrows = 1
203 | local usedwidth = 0
204 |
205 | for i = 1, #tablist do
206 | --If this is not the first tab of a row and there isn't room for it
207 | if usedwidth ~= 0 and (width - usedwidth - widths[i]) < 0 then
208 | rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
209 | rowends[numrows] = i - 1
210 | numrows = numrows + 1
211 | usedwidth = 0
212 | end
213 | usedwidth = usedwidth + widths[i]
214 | end
215 | rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
216 | rowends[numrows] = #tablist
217 |
218 | --Fix for single tabs being left on the last row, move a tab from the row above if applicable
219 | if numrows > 1 then
220 | --if the last row has only one tab
221 | if rowends[numrows-1] == numtabs-1 then
222 | --if there are more than 2 tabs in the 2nd last row
223 | if (numrows == 2 and rowends[numrows-1] > 2) or (rowends[numrows] - rowends[numrows-1] > 2) then
224 | --move 1 tab from the second last row to the last, if there is enough space
225 | if (rowwidths[numrows] + widths[numtabs-1]) <= width then
226 | rowends[numrows-1] = rowends[numrows-1] - 1
227 | rowwidths[numrows] = rowwidths[numrows] + widths[numtabs-1]
228 | rowwidths[numrows-1] = rowwidths[numrows-1] - widths[numtabs-1]
229 | end
230 | end
231 | end
232 | end
233 |
234 | --anchor the rows as defined and resize tabs to fill thier row
235 | local starttab = 1
236 | for row, endtab in ipairs(rowends) do
237 | local first = true
238 | for tabno = starttab, endtab do
239 | local tab = tabs[tabno]
240 | tab:ClearAllPoints()
241 | if first then
242 | tab:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 0, -(hastitle and 14 or 7)-(row-1)*20 )
243 | first = false
244 | else
245 | tab:SetPoint("LEFT", tabs[tabno-1], "RIGHT", -10, 0)
246 | end
247 | end
248 |
249 | -- equal padding for each tab to fill the available width,
250 | -- if the used space is above 75% already
251 | local padding = 0
252 | if not (numrows == 1 and rowwidths[1] < width*0.75) then
253 | padding = (width - rowwidths[row]) / (endtab - starttab+1)
254 | end
255 |
256 | for i = starttab, endtab do
257 | PanelTemplates_TabResize(tabs[i], padding + 4, nil, width)
258 | end
259 | starttab = endtab + 1
260 | end
261 |
262 | self.borderoffset = (hastitle and 17 or 10)+((numrows)*20)
263 | self.border:SetPoint("TOPLEFT", 1, -self.borderoffset)
264 | end,
265 |
266 | ["OnWidthSet"] = function(self, width)
267 | local content = self.content
268 | local contentwidth = width - 60
269 | if contentwidth < 0 then
270 | contentwidth = 0
271 | end
272 | content:SetWidth(contentwidth)
273 | content.width = contentwidth
274 | self:BuildTabs(self)
275 | self.frame:SetScript("OnUpdate", BuildTabsOnUpdate)
276 | end,
277 |
278 | ["OnHeightSet"] = function(self, height)
279 | local content = self.content
280 | local contentheight = height - (self.borderoffset + 23)
281 | if contentheight < 0 then
282 | contentheight = 0
283 | end
284 | content:SetHeight(contentheight)
285 | content.height = contentheight
286 | end,
287 |
288 | ["LayoutFinished"] = function(self, width, height)
289 | if self.noAutoHeight then return end
290 | self:SetHeight((height or 0) + (self.borderoffset + 23))
291 | end
292 | }
293 |
294 | --[[-----------------------------------------------------------------------------
295 | Constructor
296 | -------------------------------------------------------------------------------]]
297 | local PaneBackdrop = {
298 | bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
299 | edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
300 | tile = true, tileSize = 16, edgeSize = 16,
301 | insets = { left = 3, right = 3, top = 5, bottom = 3 }
302 | }
303 |
304 | local function Constructor()
305 | local num = AceGUI:GetNextWidgetNum(Type)
306 | local frame = CreateFrame("Frame",nil,UIParent)
307 | frame:SetHeight(100)
308 | frame:SetWidth(100)
309 | frame:SetFrameStrata("FULLSCREEN_DIALOG")
310 |
311 | local titletext = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
312 | titletext:SetPoint("TOPLEFT", 14, 0)
313 | titletext:SetPoint("TOPRIGHT", -14, 0)
314 | titletext:SetJustifyH("LEFT")
315 | titletext:SetHeight(18)
316 | titletext:SetText("")
317 |
318 | local border = CreateFrame("Frame", nil, frame)
319 | border:SetPoint("TOPLEFT", 1, -27)
320 | border:SetPoint("BOTTOMRIGHT", -1, 3)
321 | border:SetBackdrop(PaneBackdrop)
322 | border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
323 | border:SetBackdropBorderColor(0.4, 0.4, 0.4)
324 |
325 | local content = CreateFrame("Frame", nil, border)
326 | content:SetPoint("TOPLEFT", 10, -7)
327 | content:SetPoint("BOTTOMRIGHT", -10, 7)
328 |
329 | local widget = {
330 | num = num,
331 | frame = frame,
332 | localstatus = {},
333 | alignoffset = 18,
334 | titletext = titletext,
335 | border = border,
336 | borderoffset = 27,
337 | tabs = {},
338 | content = content,
339 | type = Type
340 | }
341 | for method, func in pairs(methods) do
342 | widget[method] = func
343 | end
344 |
345 | return AceGUI:RegisterAsContainer(widget)
346 | end
347 |
348 | AceGUI:RegisterWidgetType(Type, Constructor, Version)
349 |
--------------------------------------------------------------------------------
/AI_VoiceOver/Common/DataModules.lua:
--------------------------------------------------------------------------------
1 | setfenv(1, VoiceOver)
2 |
3 | local CURRENT_MODULE_VERSION = 1
4 | local FORCE_ENABLE_DISABLED_MODULES = true
5 | local LOAD_ALL_MODULES = true
6 |
7 | DataModules =
8 | {
9 | availableModules = {}, -- To store the list of modules present in Interface\AddOns folder, whether they're loaded or not
10 | availableModulesOrdered = {}, -- To store the list of modules present in Interface\AddOns folder, whether they're loaded or not
11 | registeredModules = {}, -- To keep track of which module names were already registered
12 | registeredModulesOrdered = {}, -- To have a consistent ordering of modules (which key-value hashmaps don't provide) to avoid bugs that can only be reproduced randomly
13 | }
14 |
15 | local function SortModules(a, b)
16 | a = a.METADATA or a
17 | b = b.METADATA or b
18 | if a.ModulePriority ~= b.ModulePriority then
19 | return a.ModulePriority > b.ModulePriority
20 | end
21 | return a.AddonName < b.AddonName
22 | end
23 |
24 | function DataModules:Register(name, module)
25 | assert(not self.registeredModules[name], format([[Module "%s" already registered]], name))
26 |
27 | local metadata = assert(self.availableModules[name],
28 | format([[Module "%s" attempted to register but wasn't detected during addon enumeration]], name))
29 | local moduleVersion = assert(tonumber(GetAddOnMetadata(name, "X-VoiceOver-DataModule-Version")),
30 | format([[Module "%s" is missing data format version]], name))
31 |
32 | -- Ideally if module format would ever change - there should be fallbacks in place to handle outdated formats
33 | assert(moduleVersion == CURRENT_MODULE_VERSION,
34 | format([[Module "%s" contains outdated data format (version %d, expected %d)]], name, moduleVersion,
35 | CURRENT_MODULE_VERSION))
36 |
37 | module.METADATA = metadata
38 |
39 | self.registeredModules[name] = module
40 | table.insert(self.registeredModulesOrdered, module)
41 |
42 | -- Order the modules by priority (higher first) then by name (case-sensitive alphabetical)
43 | -- Modules with higher priority will be iterated through first, so one can create a module with "overrides" for data in other modules by simply giving it a higher priority
44 | table.sort(self.registeredModulesOrdered, SortModules)
45 | end
46 |
47 | function DataModules:GetModule(name)
48 | return self.registeredModules[name]
49 | end
50 |
51 | function DataModules:GetModules()
52 | return ipairs(self.registeredModulesOrdered)
53 | end
54 |
55 | function DataModules:GetAvailableModules()
56 | return ipairs(self.availableModulesOrdered)
57 | end
58 |
59 | function DataModules:EnumerateAddons()
60 | local playerName = UnitName("player")
61 | for i = 1, GetNumAddOns() do
62 | local moduleVersion = tonumber(GetAddOnMetadata(i, "X-VoiceOver-DataModule-Version"))
63 | if moduleVersion and (FORCE_ENABLE_DISABLED_MODULES or GetAddOnEnableState(playerName, i) ~= 0) then
64 | local name = GetAddOnInfo(i)
65 | local mapsString = GetAddOnMetadata(i, "X-VoiceOver-DataModule-Maps")
66 | local maps = {}
67 | if mapsString then
68 | for _, mapString in ipairs({ strsplit(",", mapsString) }) do
69 | local map = tonumber(mapString)
70 | if map then
71 | maps[map] = true
72 | end
73 | end
74 | end
75 | local module =
76 | {
77 | AddonName = name,
78 | LoadOnDemand = IsAddOnLoadOnDemand(name),
79 | ModuleVersion = moduleVersion,
80 | ModulePriority = tonumber(GetAddOnMetadata(name, "X-VoiceOver-DataModule-Priority")) or 0,
81 | ContentVersion = GetAddOnMetadata(name, "Version"),
82 | Title = GetAddOnMetadata(name, "Title") or name,
83 | Maps = maps,
84 | }
85 | self.availableModules[name] = module
86 | table.insert(self.availableModulesOrdered, module)
87 |
88 | -- Maybe in the future we can load modules based on the map the player is in (select(8, GetInstanceInfo())), but for now - just load everything
89 | if LOAD_ALL_MODULES and IsAddOnLoadOnDemand(name) then
90 | DataModules:LoadModule(module)
91 | end
92 | end
93 | end
94 |
95 | table.sort(self.availableModulesOrdered, SortModules)
96 | for order, module in self:GetAvailableModules() do
97 | Options:AddDataModule(module, order)
98 | end
99 | end
100 |
101 | function DataModules:LoadModule(module)
102 | if not module.LoadOnDemand or self:GetModule(module.AddonName) or IsAddOnLoaded(module.AddonName) then
103 | return false
104 | end
105 |
106 | if FORCE_ENABLE_DISABLED_MODULES and GetAddOnEnableState(UnitName("player"), module.AddonName) == 0 then
107 | EnableAddOn(module.AddonName)
108 | end
109 |
110 | -- We deliberately use a high ##Interface version in TOC to ensure that all clients will load it.
111 | -- Otherwise pre-classic-rerelease clients will refuse to load addons with version < 20000.
112 | -- Here we temporarily enable "Load out of date AddOns" to load the module, and restore the user's setting afterwards.
113 | local oldLoadOutOfDateAddons = GetCVar("checkAddonVersion")
114 | SetCVar("checkAddonVersion", 0)
115 | local loaded = LoadAddOn(module.AddonName)
116 | SetCVar("checkAddonVersion", oldLoadOutOfDateAddons)
117 | return loaded
118 | end
119 |
120 | function DataModules:GetNPCGossipTextHash(soundData)
121 | -- local table = soundData.unitGUID and "GossipLookupByNPCID" or "GossipLookupByNPCName"
122 | local table = soundData.unitGUID and "NPCNameLookupByNPCID" or "GossipLookupByNPCName"
123 | local npc = soundData.unitGUID and Utils:GetIDFromGUID(soundData.unitGUID) or soundData.name
124 | local text = soundData.text
125 |
126 | local text_entries = {}
127 |
128 | for _, module in self:GetModules() do
129 | local data = module[table]
130 | if data then
131 | local npc_gossip_table = data[npc]
132 | if npc_gossip_table then
133 | for text, hash in pairs(npc_gossip_table) do
134 | text_entries[text] = text_entries[text] or
135 | hash -- Respect module priority, don't overwrite the entry if there is already one
136 | end
137 | end
138 | end
139 | end
140 |
141 | local best_result = FuzzySearchBestKeys(text, text_entries)
142 | return best_result and best_result.value
143 | end
144 |
145 | local function replaceDoubleQuotes(text)
146 | return string.gsub(text, '"', "'")
147 | end
148 |
149 | local function getFirstNWords(text, n)
150 | local firstNWords = {}
151 | local count = 0
152 |
153 | for word in string.gmatch(text, "%S+") do
154 | count = count + 1
155 | table.insert(firstNWords, word)
156 | if count >= n then
157 | break
158 | end
159 | end
160 |
161 | return table.concat(firstNWords, " ")
162 | end
163 |
164 | local function getLastNWords(text, n)
165 | local lastNWords = {}
166 | local count = 0
167 |
168 | for word in string.gmatch(text, "%S+") do
169 | table.insert(lastNWords, word)
170 | count = count + 1
171 | end
172 |
173 | local startIndex = math.max(1, count - n + 1)
174 | local endIndex = count
175 |
176 | return table.concat(lastNWords, " ", startIndex, endIndex)
177 | end
178 |
179 | function DataModules:GetQuestID(source, title, npcName, text)
180 | local cleanedTitle = replaceDoubleQuotes(title)
181 | local cleanedNPCName = replaceDoubleQuotes(npcName)
182 | local cleanedText = replaceDoubleQuotes(getFirstNWords(text, 15)) ..
183 | " " .. replaceDoubleQuotes(getLastNWords(text, 15))
184 | local text_entries = {}
185 |
186 | for _, module in self:GetModules() do
187 | local data = module.QuestIDLookup
188 | if data then
189 | local titleLookup = data[source][cleanedTitle]
190 | if titleLookup then
191 | if type(titleLookup) == "number" then
192 | return titleLookup
193 | else
194 | -- else titleLookup is a table and we need to search it further
195 | local npcLookup = titleLookup[cleanedNPCName]
196 | if npcLookup then
197 | if type(npcLookup) == "number" then
198 | return npcLookup
199 | else
200 | for text, ID in pairs(npcLookup) do
201 | text_entries[text] = text_entries[text] or
202 | ID -- Respect module priority, don't overwrite the entry if there is already one
203 | end
204 | end
205 | end
206 | end
207 | end
208 | end
209 | end
210 |
211 | local best_result = FuzzySearchBestKeys(cleanedText, text_entries)
212 | return best_result and best_result.value
213 | end
214 |
215 | function DataModules:GetQuestLogNPCID(questID)
216 | for _, module in self:GetModules() do
217 | local data = module.NPCIDLookupByQuestID
218 | if data then
219 | local npcID = data[questID]
220 | if npcID then
221 | return npcID
222 | end
223 | end
224 | end
225 | end
226 |
227 | function DataModules:GetNPCName(npcID)
228 | for _, module in self:GetModules() do
229 | local data = module.NPCNameLookupByNPCID
230 | if data then
231 | local npcName = data[npcID]
232 | if npcName then
233 | return npcName
234 | end
235 | end
236 | end
237 | end
238 |
239 | local getFileNameForEvent =
240 | {
241 | [Enums.SoundEvent.QuestAccept] = function(soundData) return format("%d-%s", soundData.questID, "accept") end,
242 | [Enums.SoundEvent.QuestProgress] = function(soundData) return format("%d-%s", soundData.questID, "progress") end,
243 | [Enums.SoundEvent.QuestComplete] = function(soundData) return format("%d-%s", soundData.questID, "complete") end,
244 | [Enums.SoundEvent.QuestGreeting] = function(soundData) return DataModules:GetNPCGossipTextHash(soundData) end,
245 | [Enums.SoundEvent.Gossip] = function(soundData) return DataModules:GetNPCGossipTextHash(soundData) end,
246 | }
247 | setmetatable(getFileNameForEvent,
248 | {
249 | __index = function(self, event)
250 | error(format([[Unhandled VoiceOver sound event %d "%s"]], event,
251 | Enums.SoundEvent:GetName(event) or "???"))
252 | end
253 | })
254 |
255 | function DataModules:PrepareSound(soundData)
256 | soundData.fileName = getFileNameForEvent[soundData.event](soundData)
257 |
258 | if soundData.fileName == nil then
259 | return false
260 | end
261 |
262 | for _, module in self:GetModules() do
263 | local data = module.SoundLengthLookupByFileName
264 | if data then
265 | local playerGenderedFileName = DataModules:AddPlayerGenderToFilename(soundData.fileName)
266 | if data[playerGenderedFileName] then
267 | soundData.fileName = playerGenderedFileName
268 | end
269 | local length = data[soundData.fileName]
270 | if length then
271 | soundData.filePath = format([[Interface\AddOns\%s\%s]], module.METADATA.AddonName,
272 | module.GetSoundPath and module:GetSoundPath(soundData.fileName, soundData.event) or
273 | soundData.fileName)
274 | soundData.length = length
275 | soundData.module = module
276 | return true
277 | end
278 | end
279 | end
280 |
281 | return false
282 | end
283 |
284 | function DataModules:AddPlayerGenderToFilename(fileName)
285 | local playerGender = UnitSex("player")
286 |
287 | if playerGender == 2 then -- male
288 | return "m-" .. fileName
289 | elseif playerGender == 3 then -- female
290 | return "f-" .. fileName
291 | else -- unknown or error
292 | return fileName
293 | end
294 | end
295 |
--------------------------------------------------------------------------------