work in progress
This commit is contained in:
BIN
Binary file not shown.
+3848
File diff suppressed because it is too large
Load Diff
+3365
File diff suppressed because it is too large
Load Diff
+544
@@ -0,0 +1,544 @@
|
||||
UIPanelWindows["ItemBrowser"] = { area = "left", pushable = 0, whileDead = 1, width = 830, xOffset = "15", yOffset = "-10"}
|
||||
|
||||
local type = type
|
||||
local mathmax = math.max
|
||||
local strfind, strlower, strtrim = string.find, string.lower, string.trim
|
||||
local tinsert, twipe = table.insert, table.wipe
|
||||
local debugprofilestop = debugprofilestop
|
||||
|
||||
local COLUMNS = {
|
||||
{
|
||||
name = "Name",
|
||||
dataProviderKey = "name",
|
||||
template = "ItemBrowserListCellNameIconTemplate",
|
||||
},
|
||||
{
|
||||
name = "ItemLevel",
|
||||
dataProviderKey = "itemLevel",
|
||||
width = 70,
|
||||
template = "ItemBrowserListCellItemLevelTemplate",
|
||||
},
|
||||
{
|
||||
name = "ID",
|
||||
dataProviderKey = "itemID",
|
||||
width = 90,
|
||||
template = "ItemBrowserListCellItemIDTemplate",
|
||||
},
|
||||
}
|
||||
|
||||
ItemBrowserMixin = {}
|
||||
|
||||
function ItemBrowserMixin:OnLoad()
|
||||
self.TitleText:SetText(ITEM_BROWSER)
|
||||
SetPortraitToTexture(self.portrait, [[Interface\Icons\Achievement_General_ClassicBattles_64]])
|
||||
|
||||
self.inset.Bgs:SetAtlas("UI-EJ-BattleforAzeroth")
|
||||
|
||||
do -- tabs
|
||||
self:RegisterCustomEvent("SERVICE_DATA_UPDATE")
|
||||
self:RegisterCustomEvent("CUSTOM_CHALLENGE_DEACTIVATED")
|
||||
|
||||
self.tab1:SetFrameLevel(1)
|
||||
self.tab2:SetFrameLevel(1)
|
||||
self.tab3:SetFrameLevel(1)
|
||||
self.tab4:SetFrameLevel(1)
|
||||
|
||||
self.maxTabWidth = (self:GetWidth() - 19) / 4
|
||||
|
||||
PanelTemplates_SetNumTabs(self, 4)
|
||||
end
|
||||
|
||||
do -- coroutine
|
||||
self.COROUTINE_HANDLER = CreateFrame("Frame")
|
||||
self.COROUTINE_HANDLER:Hide()
|
||||
|
||||
self.COROUTINE_HANDLER.FRAMETIME_TARGET = 1 / 55
|
||||
self.COROUTINE_HANDLER.FRAMETIME_AVAILABLE = 8
|
||||
self.COROUTINE_HANDLER.FRAMETIME_RESERVE = 4
|
||||
self.COROUTINE_HANDLER.DEBUG = false
|
||||
|
||||
self.COROUTINE_HANDLER:SetScript("OnUpdate", function(this, elapsed)
|
||||
local frametimeStep = this.FRAMETIME_TARGET - elapsed
|
||||
|
||||
if frametimeStep ~= 0 then
|
||||
frametimeStep = frametimeStep * 1000
|
||||
this.FRAMETIME_AVAILABLE = mathmax(5, this.FRAMETIME_AVAILABLE + frametimeStep)
|
||||
end
|
||||
|
||||
if this.COROUTINE then
|
||||
this.COROUTINE_TIMESTAMP = debugprofilestop()
|
||||
local status, result, progress = coroutine.resume(this.COROUTINE)
|
||||
if not status then
|
||||
this.COROUTINE = nil
|
||||
this:Hide()
|
||||
self.PROGRESS = 1
|
||||
error(result, 2)
|
||||
elseif not result then
|
||||
if this.DEBUG then print("ITEM_BROWSER_COROUTINE", progress) end
|
||||
self.PROGRESS = progress
|
||||
self:OnSearchResultUpdate()
|
||||
else
|
||||
if this.DEBUG then print("ITEM_BROWSER_COROUTINE", 1) end
|
||||
this.COROUTINE = nil
|
||||
this:Hide()
|
||||
self.PROGRESS = 1
|
||||
self:OnSearchResultUpdate()
|
||||
end
|
||||
else
|
||||
this:Hide()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
self.BUTTON_OFFSET_Y = 0
|
||||
self.PROGRESS = 1
|
||||
|
||||
self.results = {}
|
||||
|
||||
self.Scroll.ScrollBar:SetBackgroundShown(false)
|
||||
self.Scroll.update = function(scrollFrame)
|
||||
self:UpdateResultList()
|
||||
end
|
||||
self.Scroll.ScrollBar.doNotHide = true
|
||||
self.Scroll.scrollBar = self.Scroll.ScrollBar
|
||||
HybridScrollFrame_CreateButtons(self.Scroll, "ItemBrowserListRowButtonTemplate", 0, 0, nil, nil, nil, -self.BUTTON_OFFSET_Y)
|
||||
|
||||
self.SearchBox:ToggleOnCharFilter(true, 0.3)
|
||||
|
||||
self.tableBuilder = CreateTableBuilder(HybridScrollFrame_GetButtons(self.Scroll))
|
||||
self.tableBuilder:SetHeaderContainer(self.HeaderHolder)
|
||||
self:ConstructTable()
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:OnShow()
|
||||
SetParentFrameLevel(self.inset)
|
||||
PanelTemplates_SetTab(self, 4)
|
||||
|
||||
self.dirty = true
|
||||
self.Scroll.ScrollBar:SetValue(0)
|
||||
self:UpdateResultList()
|
||||
|
||||
self.SearchBox:SetFocus()
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:OnEvent(event, ...)
|
||||
if event == "SERVICE_DATA_UPDATE"
|
||||
or (event == "CUSTOM_CHALLENGE_DEACTIVATED" and select(2, ...) ~= Enum.HardcoreDeathReason.FAILED_DEATH)
|
||||
then
|
||||
if not C_Service.IsRenegadeRealm() then
|
||||
PanelTemplates_HideTab(self, 2)
|
||||
self.tab3:SetPoint("LEFT", self.tab1, "RIGHT", -16, 0);
|
||||
end
|
||||
if not C_Service.IsHardcoreEnabledOnRealm() then
|
||||
PanelTemplates_HideTab(self, 3)
|
||||
end
|
||||
if not C_Service.IsGMAccount() and not IsInterfaceDevClient() then
|
||||
PanelTemplates_HideTab(self, 4)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:GetRowProvider()
|
||||
return function(itemIndex)
|
||||
if itemIndex > #self.results then
|
||||
return nil
|
||||
end
|
||||
|
||||
local itemID = self.results[itemIndex]
|
||||
local itemName, itemLink, itemRarity, itemLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, vendorPrice = C_Item.GetItemInfo(itemID, false, nil, true, true)
|
||||
|
||||
return {
|
||||
itemID = itemID,
|
||||
name = itemName,
|
||||
itemLink = itemLink,
|
||||
itemLevel = itemLevel,
|
||||
itemType = itemType,
|
||||
itemSubType = itemSubType,
|
||||
icon = itemTexture,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:ConstructTable()
|
||||
local textPadding = 1
|
||||
local cellPadding = 10
|
||||
|
||||
self.tableBuilder:Reset()
|
||||
self.tableBuilder:SetDataProvider(self:GetRowProvider())
|
||||
self.tableBuilder:SetTableMargins(5)
|
||||
self.tableBuilder:SetTableWidth(self.Scroll:GetWidth() or select(3, self.Scroll:GetRect()))
|
||||
|
||||
for index, columnInfo in ipairs(COLUMNS) do
|
||||
local column = self.tableBuilder:AddColumn()
|
||||
column:ConstructHeader("Button", "ItemBrowserListHeaderButtonTemplate", columnInfo.name)
|
||||
column:ConstrainToHeader(textPadding)
|
||||
column:ConstructCells("Frame", columnInfo.template)
|
||||
|
||||
if columnInfo.width then
|
||||
column:SetFixedConstraints(columnInfo.width, cellPadding)
|
||||
else
|
||||
column:SetFillConstraints(1, cellPadding)
|
||||
end
|
||||
end
|
||||
|
||||
self.tableBuilder:Arrange()
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:GetNumItems()
|
||||
if not self.NUM_ITEMS then
|
||||
self.NUM_ITEMS = tCount(ItemsCache)
|
||||
end
|
||||
return self.NUM_ITEMS
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:SearchItem(item)
|
||||
item = strtrim(item)
|
||||
if item == "" then
|
||||
self:ClearResults()
|
||||
return
|
||||
end
|
||||
|
||||
local itemID = C_Item.GetItemIDFromString(item)
|
||||
local searchField, searchValue, useStringFind
|
||||
|
||||
if itemID then
|
||||
searchField = Enum.ItemCacheField.ITEM_ID
|
||||
searchValue = itemID
|
||||
elseif item ~= "" then
|
||||
searchField = GetLocale() == "ruRU" and Enum.ItemCacheField.NAME_RURU or Enum.ItemCacheField.NAME_ENGB
|
||||
searchValue = strlower(item)
|
||||
useStringFind = true
|
||||
end
|
||||
|
||||
if not searchField then
|
||||
self:ClearResults()
|
||||
return
|
||||
end
|
||||
|
||||
self:StartSearch(searchField, searchValue, useStringFind)
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:StartSearch(searchField, searchValue, useStringFind)
|
||||
if self.SEARCH_FIELD == searchField and self.SEARCH_VALUE == searchValue then
|
||||
return
|
||||
end
|
||||
|
||||
if self.COROUTINE then
|
||||
coroutine.close(self.COROUTINE)
|
||||
self.COROUTINE = nil
|
||||
self:ClearResults()
|
||||
end
|
||||
|
||||
self.SEARCH_FIELD = searchField
|
||||
self.SEARCH_VALUE = searchValue
|
||||
self.USE_STRING_FIND = useStringFind
|
||||
|
||||
local framerate = GetFramerate()
|
||||
self.COROUTINE_HANDLER.FRAMETIME_TARGET = framerate > 63 and (1 / 60) or (1 / 55)
|
||||
self.COROUTINE_HANDLER.FRAMETIME_BUDGET = 1000 / framerate - self.COROUTINE_HANDLER.FRAMETIME_RESERVE
|
||||
|
||||
self.COROUTINE_HANDLER.COROUTINE = coroutine.create(self.SearchProcess)
|
||||
self.COROUTINE_HANDLER.COROUTINE_TIMESTAMP = debugprofilestop()
|
||||
|
||||
local status, result, progress = coroutine.resume(self.COROUTINE_HANDLER.COROUTINE, self)
|
||||
if not status then
|
||||
self.COROUTINE_HANDLER.COROUTINE = nil
|
||||
self.COROUTINE_HANDLER:Hide()
|
||||
self.PROGRESS = 1
|
||||
self:ClearResults()
|
||||
geterrorhandler()(result)
|
||||
elseif coroutine.status(self.COROUTINE_HANDLER.COROUTINE) == "dead" then
|
||||
self.COROUTINE_HANDLER.COROUTINE = nil
|
||||
self.PROGRESS = 1
|
||||
else
|
||||
if self.COROUTINE_HANDLER.DEBUG then print("ITEM_BROWSER_COROUTINE", progress) end
|
||||
self.PROGRESS = progress
|
||||
self.COROUTINE_HANDLER:Show()
|
||||
end
|
||||
|
||||
self:OnSearchResultUpdate()
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:SearchProcess()
|
||||
twipe(self.results)
|
||||
|
||||
if not ItemsCache then
|
||||
return true, 1
|
||||
end
|
||||
|
||||
local processedEntries = 0
|
||||
local fieldValue
|
||||
|
||||
for itemID, itemInfo in pairs(ItemsCache) do
|
||||
processedEntries = processedEntries + 1
|
||||
|
||||
fieldValue = itemInfo[self.SEARCH_FIELD]
|
||||
|
||||
if type(fieldValue) == "string" then
|
||||
fieldValue = strlower(fieldValue)
|
||||
end
|
||||
|
||||
if fieldValue == self.SEARCH_VALUE
|
||||
or (self.USE_STRING_FIND and strfind(fieldValue, self.SEARCH_VALUE, 1, true))
|
||||
then
|
||||
tinsert(self.results, itemInfo[Enum.ItemCacheField.ITEM_ID])
|
||||
end
|
||||
|
||||
if (debugprofilestop() - self.COROUTINE_HANDLER.COROUTINE_TIMESTAMP) > self.COROUTINE_HANDLER.FRAMETIME_BUDGET then
|
||||
coroutine.yield(false, processedEntries / self:GetNumItems())
|
||||
end
|
||||
end
|
||||
|
||||
return true, 1
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:OnSearchResultUpdate()
|
||||
self.dirty = true
|
||||
self:UpdateSearchProgress()
|
||||
self:UpdateResultList()
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:UpdateSearchProgress()
|
||||
local progress = Clamp(self.PROGRESS or 1, 0, 1)
|
||||
self.SearchProgressBar:SetValue(progress)
|
||||
self.SearchProgressBar:SetAlpha(progress < 1 and 1 or 0)
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:ClearResults()
|
||||
twipe(self.results)
|
||||
|
||||
self.SEARCH_FIELD = nil
|
||||
self.SEARCH_VALUE = nil
|
||||
self.USE_STRING_FIND = nil
|
||||
|
||||
self.PROGRESS = 1
|
||||
self.dirty = true
|
||||
|
||||
self:UpdateSearchProgress()
|
||||
self:UpdateResultList()
|
||||
end
|
||||
|
||||
function ItemBrowserMixin:UpdateResultList()
|
||||
local scrollFrame = self.Scroll
|
||||
local offset = HybridScrollFrame_GetOffset(scrollFrame)
|
||||
local numResults = self.results and #self.results or 0
|
||||
|
||||
if self.numItems ~= numResults then
|
||||
self.numItems = numResults
|
||||
self.dirty = true
|
||||
end
|
||||
|
||||
local populateCount = math.min(#scrollFrame.buttons, numResults)
|
||||
self.tableBuilder:Populate(offset, populateCount)
|
||||
|
||||
local mouseFocus = GetMouseFocus()
|
||||
for index, button in ipairs(scrollFrame.buttons) do
|
||||
button:SetOwner(self)
|
||||
button:SetShown(index <= numResults)
|
||||
if button == mouseFocus then
|
||||
button:OnEnter()
|
||||
end
|
||||
end
|
||||
|
||||
if self.dirty then
|
||||
local buttonHeight = scrollFrame.buttons[1] and scrollFrame.buttons[1]:GetHeight() or 0
|
||||
local scrollHeight = buttonHeight * numResults + self.BUTTON_OFFSET_Y * (numResults - 1) + self.BUTTON_OFFSET_Y / 3
|
||||
HybridScrollFrame_Update(scrollFrame, scrollHeight, scrollFrame:GetHeight())
|
||||
self.dirty = nil
|
||||
end
|
||||
end
|
||||
|
||||
ItemBrowserSearchBoxMixin = CreateFromMixins(PKBT_EditBoxMixin)
|
||||
|
||||
function ItemBrowserSearchBoxMixin:OnLoad()
|
||||
PKBT_EditBoxMixin.OnLoad(self)
|
||||
|
||||
local l, r, t, b = self:GetTextInsets()
|
||||
self:SetTextInsets(l + 10, r + 10, t - 1, b)
|
||||
|
||||
self:SetInstructions(SEARCH)
|
||||
self.Instructions:ClearAllPoints()
|
||||
self.Instructions:SetPoint("LEFT", 19, -2)
|
||||
|
||||
self.searchIcon:SetVertexColor(0.6, 0.6, 0.6)
|
||||
|
||||
self:SetCustomCharFilter(function(text)
|
||||
text = string.gsub(text, "%s%s+", " ")
|
||||
text = utf8.gsub(text, "[^A-zА-я0-9':%- ]+", "")
|
||||
return text
|
||||
end)
|
||||
|
||||
self.value = ""
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:OnHide()
|
||||
self:StopOnCharSearchDelay()
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:OnEnterPressed()
|
||||
self:ClearFocus()
|
||||
self:DoSearch()
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:OnEditFocusLost()
|
||||
SearchBoxTemplate_OnEditFocusLost(self)
|
||||
self:HighlightText(0, 0)
|
||||
self:DoSearch()
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:OnUpdate(elapsed)
|
||||
self.searchDelay = self.searchDelay - elapsed
|
||||
|
||||
if self.searchDelay <= 0 then
|
||||
self:SetScript("OnUpdate", nil)
|
||||
self.searchDelay = nil
|
||||
self:DoSearch()
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:DoSearch()
|
||||
local newValue = self:GetText()
|
||||
if self.value ~= newValue and not (self.value == nil and newValue == "") then
|
||||
self.value = newValue
|
||||
self:GetParent():SearchItem(newValue)
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:ToggleOnCharFilter(state, searchUpdateDelay)
|
||||
if state then
|
||||
self.searchUpdateDelay = searchUpdateDelay
|
||||
self.searchDelay = searchUpdateDelay
|
||||
else
|
||||
self:SetScript("OnUpdate", nil)
|
||||
self.searchUpdateDelay = nil
|
||||
self.searchDelay = nil
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:OnTextChanged(userInput)
|
||||
PKBT_EditBoxMixin.OnTextChanged(self, userInput)
|
||||
SearchBoxTemplate_OnTextChanged(self)
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:OnTextValueChanged(value, userInput)
|
||||
if userInput then
|
||||
if self.searchUpdateDelay then
|
||||
self.searchDelay = self.searchUpdateDelay
|
||||
self:SetScript("OnUpdate", self.OnUpdate)
|
||||
end
|
||||
else
|
||||
self:StopOnCharSearchDelay()
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:OnUpdate(elapsed)
|
||||
self.searchDelay = self.searchDelay - elapsed
|
||||
|
||||
if self.searchDelay <= 0 then
|
||||
self:SetScript("OnUpdate", nil)
|
||||
self.searchDelay = nil
|
||||
self:DoSearch()
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:StopOnCharSearchDelay()
|
||||
self:SetScript("OnUpdate", nil)
|
||||
|
||||
if self.searchUpdateDelay then
|
||||
self.searchDelay = self.searchUpdateDelay
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserSearchBoxMixin:OnClearClick(button)
|
||||
SearchBoxTemplateClearButton_OnClick(self.clearButton, button)
|
||||
self:StopOnCharSearchDelay()
|
||||
self:DoSearch()
|
||||
end
|
||||
|
||||
ItemBrowserListHeaderButtonMixin = CreateFromMixins(TableBuilderElementMixin)
|
||||
|
||||
function ItemBrowserListHeaderButtonMixin:Init(name)
|
||||
self:SetText(name)
|
||||
end
|
||||
|
||||
function ItemBrowserListHeaderButtonMixin:OnClick(button)
|
||||
end
|
||||
|
||||
ItemBrowserListRowButton = CreateFromMixins(PKBT_OwnerMixin, TableBuilderRowMixin)
|
||||
|
||||
function ItemBrowserListRowButton:OnLoad()
|
||||
self.UpdateTooltip = self.OnEnter
|
||||
end
|
||||
|
||||
function ItemBrowserListRowButton:OnEnter()
|
||||
if self.itemLink then
|
||||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||||
GameTooltip:SetHyperlink(self.itemLink)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserListRowButton:OnLeave()
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
function ItemBrowserListRowButton:OnClick(button)
|
||||
if self.itemLink then
|
||||
HandleModifiedItemClick(self.itemLink)
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBrowserListRowButton:Populate(rowData, dataIndex)
|
||||
self:SetID(dataIndex)
|
||||
self.itemID = rowData.itemID
|
||||
self.itemLink = rowData.itemLink
|
||||
end
|
||||
|
||||
ItemBrowserListCellMixin = {}
|
||||
|
||||
function ItemBrowserListCellMixin:OnLoad()
|
||||
end
|
||||
|
||||
function ItemBrowserListCellMixin:Init(dataProviderKey)
|
||||
self.dataProviderKey = dataProviderKey
|
||||
end
|
||||
|
||||
function ItemBrowserListCellMixin:Populate(rowData, dataIndex)
|
||||
local value = rowData[self.dataProviderKey]
|
||||
self.Text:SetJustifyH(self.textAlignment or "CENTER")
|
||||
self.Text:SetText(value or "?")
|
||||
end
|
||||
|
||||
ItemBrowserListCellNameIconMixin = CreateFromMixins(ItemBrowserListCellMixin)
|
||||
|
||||
function ItemBrowserListCellNameIconMixin:Populate(rowData, dataIndex)
|
||||
local textWidth = self:GetWidth() - 10
|
||||
|
||||
self.Text:SetText(rowData.name or UNKNOWN)
|
||||
self.Text:SetWidth(textWidth)
|
||||
self.SubText:SetWidth(textWidth)
|
||||
|
||||
if rowData.itemType and rowData.itemSubType then
|
||||
self.SubText:SetFormattedText("%s - %s", rowData.itemType, rowData.itemSubType)
|
||||
elseif rowData.itemType or rowData.itemSubType then
|
||||
self.SubText:SetText(rowData.itemType or rowData.itemSubType)
|
||||
else
|
||||
self.SubText:SetText("")
|
||||
end
|
||||
|
||||
self.Icon:SetTexture(rowData.icon or QUESTION_MARK_ICON)
|
||||
local r, g, b = GetItemQualityColor(rowData.rarity or 1)
|
||||
self.Border:SetVertexColor(r, g, b)
|
||||
end
|
||||
|
||||
ItemBrowserListCellItemLevelMixin = CreateFromMixins(ItemBrowserListCellMixin)
|
||||
|
||||
function ItemBrowserListCellItemLevelMixin:Populate(rowData, dataIndex)
|
||||
self.Text:SetText(rowData.itemLevel and rowData.itemLevel ~= 0 and rowData.itemLevel or "")
|
||||
end
|
||||
|
||||
ItemBrowserListCellItemIDMixin = CreateFromMixins(ItemBrowserListCellMixin)
|
||||
|
||||
function ItemBrowserListCellItemIDMixin:Populate(rowData, dataIndex)
|
||||
self.Text:SetText(rowData.itemID)
|
||||
end
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\..\FrameXML\UI.xsd">
|
||||
<Script file="Custom_ItemBrowser.lua"/>
|
||||
|
||||
<Button name="ItemBrowserListHeaderButtonTemplate" virtual="true">
|
||||
<Size x="50" y="30"/>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture name="$parentBackground" parentKey="Background" setAllPoints="true">
|
||||
<Color r="0.2" g="0.2" b="0.2"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
<!--
|
||||
<Layer level="HIGHLIGHT">
|
||||
<Texture name="$parentHighlight" parentKey="Highlight" setAllPoints="true" alpha="0.2" alphaMode="ADD">
|
||||
<Color r="1" g="1" b="1"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
-->
|
||||
</Layers>
|
||||
|
||||
<NormalFont style="SystemFont_Shadow_Small"/>
|
||||
<PushedTextOffset x="0" y="0"/>
|
||||
<!--
|
||||
<PushedTextOffset x="1" y="-1"/>
|
||||
<ButtonText name="$parentButtonText" parentKey="ButtonText">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</ButtonText>
|
||||
-->
|
||||
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, ItemBrowserListHeaderButtonMixin)
|
||||
</OnLoad>
|
||||
<!--
|
||||
<OnClick>
|
||||
self:OnClick(button)
|
||||
</OnClick>
|
||||
-->
|
||||
</Scripts>
|
||||
</Button>
|
||||
<Button name="ItemBrowserListRowButtonTemplate" virtual="true">
|
||||
<Size x="0" y="46"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" x="1" y="0"/>
|
||||
<Anchor point="RIGHT" x="-1" y="0"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture name="$parentBackground" parentKey="Background" setAllPoints="true" inherits="_SearchBarLg"/>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<HighlightTexture file="Interface\Common\Search">
|
||||
<TexCoords left="0.001953" right="0.501953" top="0.234375" bottom="0.601562"/>
|
||||
</HighlightTexture>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, ItemBrowserListRowButton)
|
||||
self:OnLoad()
|
||||
</OnLoad>
|
||||
<OnEvent>
|
||||
self:OnEvent(event, ...)
|
||||
</OnEvent>
|
||||
<OnEnter>
|
||||
self:OnEnter()
|
||||
</OnEnter>
|
||||
<OnLeave>
|
||||
self:OnLeave()
|
||||
</OnLeave>
|
||||
<OnClick>
|
||||
self:OnClick()
|
||||
</OnClick>
|
||||
</Scripts>
|
||||
</Button>
|
||||
|
||||
<Frame name="ItemBrowserListCellNameIconTemplate" virtual="true">
|
||||
<Layers>
|
||||
<Layer level="OVERLAY">
|
||||
<Texture name="$parentBorder" parentKey="Border" file="Interface\Common\Search">
|
||||
<Size x="40" y="40"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" x="10" y="0"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0.755859" right="0.830078" top="0.234375" bottom="0.531250"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
<Layer level="ARTWORK">
|
||||
<Texture name="$parentIcon" parentKey="Icon">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentBorder" x="1" y="-2"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBorder" x="-1" y="1"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<FontString name="$parentText" parentKey="Text" inherits="GameFontNormalLarge" justifyH="LEFT" maxLines="1">
|
||||
<Size x="0" y="0"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parentIcon" relativePoint="RIGHT" x="10" y="8"/>
|
||||
</Anchors>
|
||||
<Color r="0.96875" g="0.8984375" b="0.578125" a="1"/>
|
||||
</FontString>
|
||||
<FontString name="$parentSubText" parentKey="SubText" inherits="GameFontNormal" justifyH="LEFT">
|
||||
<Size x="400" y="0"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentText" relativePoint="BOTTOMLEFT" x="0" y="-5"/>
|
||||
</Anchors>
|
||||
<Color r="0.66796875" g="0.51171875" b="0.3359375" a="1"/>
|
||||
</FontString>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, ItemBrowserListCellNameIconMixin)
|
||||
self:OnLoad()
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
<Frame name="ItemBrowserListCellItemLevelTemplate" virtual="true">
|
||||
<Layers>
|
||||
<Layer level="ARTWORK">
|
||||
<FontString name="$parentText" parentKey="Text" inherits="GameFontNormalLarge" maxLines="1">
|
||||
<Size x="0" y="0"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" x="0" y="0"/>
|
||||
</Anchors>
|
||||
<Color r="1" g="1" b="1"/>
|
||||
</FontString>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, ItemBrowserListCellItemLevelMixin)
|
||||
self:OnLoad()
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
<Frame name="ItemBrowserListCellItemIDTemplate" virtual="true">
|
||||
<Layers>
|
||||
<Layer level="ARTWORK">
|
||||
<FontString name="$parentText" parentKey="Text" inherits="GameFontNormalLarge" maxLines="1">
|
||||
<Size x="0" y="0"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" x="0" y="0"/>
|
||||
</Anchors>
|
||||
<Color r="1" g="1" b="1"/>
|
||||
</FontString>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, ItemBrowserListCellItemIDMixin)
|
||||
self:OnLoad()
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
|
||||
<Frame name="ItemBrowser" inherits="PortraitFrameTemplate" toplevel="true" enableMouse="true" parent="UIParent" hidden="true">
|
||||
<Size x="800" y="496"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" x="0" y="0"/>
|
||||
</Anchors>
|
||||
|
||||
<Frames>
|
||||
<Frame name="$parentInset" inherits="InsetFrameTemplate" parentKey="inset">
|
||||
<Anchors>
|
||||
<Anchor point="TOPRIGHT" x="-4" y="-60"/>
|
||||
<Anchor point="BOTTOMLEFT" x="4" y="5"/>
|
||||
</Anchors>
|
||||
</Frame>
|
||||
|
||||
<EditBox name="$parentSearchBox" parentKey="SearchBox" inherits="PKBT_EditBoxTemplate" letters="64">
|
||||
<Size x="130" y="36"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="60" y="-22"/>
|
||||
<Anchor point="TOPRIGHT" x="-10" y="-22"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="OVERLAY">
|
||||
<Texture name="$parentSearchIcon" parentKey="searchIcon" file="Interface\Common\UI-Searchbox-Icon">
|
||||
<Size x="14" y="14"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" x="5" y="-2"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Frames>
|
||||
<Button name="$parentClearButton" parentKey="clearButton" hidden="true">
|
||||
<Size x="22" y="22"/>
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" x="-5" y="-1"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="ARTWORK">
|
||||
<Texture parentKey="texture" file="Interface\FriendsFrame\ClearBroadcastIcon" alpha="0.5" setAllPoints="true"/>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
<OnEnter>
|
||||
self.texture:SetAlpha(1.0)
|
||||
</OnEnter>
|
||||
<OnLeave>
|
||||
self.texture:SetAlpha(0.5)
|
||||
</OnLeave>
|
||||
<OnMouseDown>
|
||||
if self:IsEnabled() == 1 then
|
||||
self.texture:SetPoint("TOPLEFT", self, "TOPLEFT", 1, -1)
|
||||
end
|
||||
</OnMouseDown>
|
||||
<OnMouseUp>
|
||||
self.texture:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)
|
||||
</OnMouseUp>
|
||||
<OnClick>
|
||||
self:GetParent():OnClearClick(button)
|
||||
</OnClick>
|
||||
</Scripts>
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, ItemBrowserSearchBoxMixin)
|
||||
self:OnLoad()
|
||||
</OnLoad>
|
||||
<OnHide>
|
||||
self:OnHide()
|
||||
</OnHide>
|
||||
<OnTextChanged>
|
||||
self:OnTextChanged(userInput)
|
||||
</OnTextChanged>
|
||||
<OnEnterPressed>
|
||||
self:OnEnterPressed()
|
||||
</OnEnterPressed>
|
||||
<OnEditFocusLost>
|
||||
self:OnEditFocusLost()
|
||||
</OnEditFocusLost>
|
||||
<OnEditFocusGained function="SearchBoxTemplate_OnEditFocusGained"/>
|
||||
</Scripts>
|
||||
</EditBox>
|
||||
|
||||
<StatusBar name="$parentSearchProgressBar" parentKey="SearchProgressBar" minValue="0" maxValue="1" alpha="0">
|
||||
<Size x="0" y="6"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentSearchBox" relativePoint="BOTTOMLEFT" x="7" y="1"/>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentSearchBox" relativePoint="BOTTOMRIGHT" x="-7" y="1"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture parentKey="Background">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT"/>
|
||||
<Anchor point="BOTTOMRIGHT"/>
|
||||
</Anchors>
|
||||
<Color r="0" g="0" b="0" a="0.3"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<BarTexture file="Interface\TargetingFrame\UI-StatusBar"/>
|
||||
<BarColor r="0" g="1" b="0"/>
|
||||
</StatusBar>
|
||||
|
||||
<ScrollFrame name="$parentScroll" parentKey="Scroll" inherits="HybridScrollFrameTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentInset" relativePoint="TOPLEFT" x="10" y="-50"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentInset" relativePoint="BOTTOMRIGHT" x="-36" y="10"/>
|
||||
</Anchors>
|
||||
<Frames>
|
||||
<Slider name="$parentScrollBar" parentKey="ScrollBar" inherits="PKBT_HybridScrollBarTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="5" y="-25"/>
|
||||
<Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT" x="5" y="27"/>
|
||||
</Anchors>
|
||||
</Slider>
|
||||
</Frames>
|
||||
</ScrollFrame>
|
||||
|
||||
<Frame name="$parentHeaderHolder" parentKey="HeaderHolder">
|
||||
<Size x="0" y="30"/>
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parentScroll" relativePoint="TOPLEFT" x="0" y="12"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentScroll" relativePoint="TOPRIGHT" x="0" y="12"/>
|
||||
</Anchors>
|
||||
</Frame>
|
||||
|
||||
<Button name="$parentTab1" inherits="CharacterFrameTabButtonTemplate" text="ADVENTURE_JOURNAL" id="1" parentKey="tab1">
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parent" relativePoint="BOTTOMLEFT" x="19" y="-30"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnClick function="Adventure_TabOnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
<Button name="$parentTab2" inherits="CharacterFrameTabButtonTemplate" text="HEADHUNTING" id="2" parentKey="tab2">
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parentTab1" relativePoint="RIGHT" x="-16" y="0"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnClick function="Adventure_TabOnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
<Button name="$parentTab3" inherits="CharacterFrameTabButtonTemplate" text="HARDCORE_CHALLENGES_TITLE" id="3" parentKey="tab3">
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parentTab2" relativePoint="RIGHT" x="-16" y="0"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnClick function="Adventure_TabOnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
<Button name="$parentTab4" inherits="CharacterFrameTabButtonTemplate" text="ITEM_BROWSER" id="4" parentKey="tab4">
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parentTab3" relativePoint="RIGHT" x="-16" y="0"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnClick function="Adventure_TabOnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, ItemBrowserMixin)
|
||||
self:OnLoad()
|
||||
</OnLoad>
|
||||
<OnShow>
|
||||
self:OnShow()
|
||||
</OnShow>
|
||||
<OnEvent>
|
||||
self:OnEvent(event, ...)
|
||||
</OnEvent>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
</Ui>
|
||||
+491
@@ -0,0 +1,491 @@
|
||||
do
|
||||
local tonumber = tonumber
|
||||
local unpack = unpack
|
||||
local bitband = bit.band
|
||||
local strsub = string.sub
|
||||
|
||||
local LJ_BUFFER = {}
|
||||
|
||||
local NO_CLASS_FILTER = 0
|
||||
local NO_SPEC_FILTER = 0
|
||||
|
||||
local LJ_ITEMSET_REALM_FLAG = {
|
||||
[E_REALM_ID.SOULSEEKER] = 0x1,
|
||||
[E_REALM_ID.SIRUS] = 0x2,
|
||||
[E_REALM_ID.SCOURGE] = 0x4,
|
||||
[E_REALM_ID.ALGALON] = 0x8,
|
||||
[E_REALM_ID.NEVEREST] = 0x10,
|
||||
}
|
||||
|
||||
local function getPlayerFactionID()
|
||||
local factionGroup = UnitFactionGroup("player") or "NEUTRAL"
|
||||
if factionGroup == "Renegade" then
|
||||
return (C_FactionManager.GetFactionInfoOriginal())
|
||||
end
|
||||
return PLAYER_FACTION_GROUP[factionGroup]
|
||||
end
|
||||
|
||||
local function filterByFaction(factionID, playerFactionID)
|
||||
if factionID == PLAYER_FACTION_GROUP.Neutral then
|
||||
return true
|
||||
elseif factionID == playerFactionID then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function filterByClassAndSpecFilters(classID, specID, classFilter, specFilter)
|
||||
if classFilter and specFilter then
|
||||
if specFilter == 3 then
|
||||
specFilter = 4
|
||||
end
|
||||
|
||||
if classFilter == NO_CLASS_FILTER and specFilter == NO_SPEC_FILTER then
|
||||
return true
|
||||
elseif classFilter == classID and specFilter == NO_SPEC_FILTER then
|
||||
return true
|
||||
elseif classFilter == classID and bitband(specFilter, specID) == specFilter then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function sortItemSets(a, b)
|
||||
if a[4] == b[4] then
|
||||
if a[6] ~= b[6] then
|
||||
return a[6]
|
||||
end
|
||||
return (tonumber(strsub(a[3], 3, -1) or 0)) > (tonumber(strsub(b[3], 3, -1) or 0))
|
||||
end
|
||||
return a[4] > b[4]
|
||||
end
|
||||
|
||||
C_LootJournal = {}
|
||||
|
||||
function C_LootJournal.GenerateLootData(classFilter, specFilter)
|
||||
table.wipe(LJ_BUFFER)
|
||||
|
||||
local serverID = C_Service.GetRealmID()
|
||||
local playerFactionID = getPlayerFactionID()
|
||||
local itemSetSourceRealm = EJ_ITEMSET_SOURCE_REALM[serverID]
|
||||
|
||||
for setIndex, itemSetData in pairs(EJ_ITEMSET_DATA) do
|
||||
local name, itemlevel, tierName, sourceID, classID, specID, isPVP, itemList, factionID, realmFlag = unpack(itemSetData, 1, 10)
|
||||
if not factionID then
|
||||
factionID = 0
|
||||
end
|
||||
|
||||
if filterByClassAndSpecFilters(classID, specID, classFilter or 0, specFilter or 0)
|
||||
and filterByFaction(factionID, playerFactionID)
|
||||
then
|
||||
if itemSetSourceRealm and itemSetSourceRealm[setIndex] then
|
||||
sourceID = itemSetSourceRealm[setIndex]
|
||||
end
|
||||
local sourceText = EJ_ITEMSET_SOURCE[sourceID] or ""
|
||||
|
||||
local numItems = type(itemList) == "table" and #itemList or 0
|
||||
local items = {}
|
||||
|
||||
for i = 1, numItems do
|
||||
local itemID = itemList[i]
|
||||
items[i] = {
|
||||
itemID = itemID,
|
||||
icon = GetItemIcon(itemID) or [[Interface\Icons\INV_Misc_QuestionMark]],
|
||||
}
|
||||
end
|
||||
|
||||
LJ_BUFFER[#LJ_BUFFER + 1] = {setIndex, name, tierName or "", itemlevel, sourceText, isPVP == 1, items, numItems}
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(LJ_BUFFER, sortItemSets)
|
||||
|
||||
return LJ_BUFFER
|
||||
end
|
||||
|
||||
function C_LootJournal.GetNumItemSets()
|
||||
return #LJ_BUFFER
|
||||
end
|
||||
|
||||
function C_LootJournal.GetItemSetInfo(index)
|
||||
if index and LJ_BUFFER[index] then
|
||||
return unpack(LJ_BUFFER[index])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local NO_SPEC_FILTER = 0;
|
||||
local NO_CLASS_FILTER = 0;
|
||||
local NO_INV_TYPE_FILTER = 0;
|
||||
|
||||
--===================================================================================================================================
|
||||
LootJournalItemsMixin = { };
|
||||
|
||||
function LootJournalItemsMixin:OnLoad()
|
||||
self.Background:SetAtlas("loottab-background", true)
|
||||
self:SetView(LOOT_JOURNAL_ITEM_SETS);
|
||||
local _, _, classID = UnitClass("player");
|
||||
local specIndex = C_Talent.GetCurrentSpecTabIndex()
|
||||
self:SetClassAndSpecFilters(classID, specIndex);
|
||||
end
|
||||
|
||||
function LootJournalItemsMixin:SetClassAndSpecFilters(classID, specID)
|
||||
self.classFilter = classID;
|
||||
self.specFilter = specID;
|
||||
end
|
||||
|
||||
function LootJournalItemsMixin:GetClassAndSpecFilters()
|
||||
return self.classFilter or NO_CLASS_FILTER, self.specFilter or NO_SPEC_FILTER;
|
||||
end
|
||||
|
||||
function LootJournalItemsMixin:SetView(view)
|
||||
if ( self.view == view ) then
|
||||
return;
|
||||
end
|
||||
|
||||
self.view = view;
|
||||
self.ItemSetsFrame:Show();
|
||||
end
|
||||
|
||||
function LootJournalItemsMixin:GetActiveList()
|
||||
return self.ItemSetsFrame;
|
||||
end
|
||||
|
||||
function LootJournalItemsMixin:Refresh()
|
||||
self:GetActiveList():Refresh();
|
||||
end
|
||||
|
||||
function LootJournalItemButtonTemplate_OnEnter(self)
|
||||
local listFrame = self:GetParent();
|
||||
while ( listFrame and not listFrame.ShowItemTooltip ) do
|
||||
listFrame = listFrame:GetParent();
|
||||
end
|
||||
if ( listFrame ) then
|
||||
listFrame:ShowItemTooltip(self);
|
||||
self:SetScript("OnUpdate", LootJournalItemButton_OnUpdate);
|
||||
self.UpdateTooltip = LootJournalItemButtonTemplate_OnEnter;
|
||||
end
|
||||
end
|
||||
|
||||
function LootJournalItemButtonTemplate_OnLeave(self)
|
||||
self.UpdateTooltip = nil;
|
||||
GameTooltip:Hide();
|
||||
self:SetScript("OnUpdate", nil);
|
||||
ResetCursor();
|
||||
end
|
||||
|
||||
function LootJournalItemButton_OnClick(self, button)
|
||||
if HandleModifiedItemClick(self.itemLink) then
|
||||
return
|
||||
end
|
||||
|
||||
LootJournal_OpenItemByEntry(self.itemID)
|
||||
end
|
||||
|
||||
--===================================================================================================================================
|
||||
LootJournalItemSetsMixin = {}
|
||||
|
||||
local LJ_ITEMSET_X_OFFSET = 10;
|
||||
local LJ_ITEMSET_Y_OFFSET = 10;
|
||||
local LJ_ITEMSET_BUTTON_SPACING = 13;
|
||||
local LJ_ITEMSET_BOTTOM_BUFFER = 4;
|
||||
|
||||
function LootJournalItemSetsMixin:Refresh()
|
||||
self.dirty = true;
|
||||
local offset = self.scrollBar:GetValue();
|
||||
if ( offset == 0 ) then
|
||||
self:UpdateList();
|
||||
else
|
||||
self.scrollBar:SetValue(0);
|
||||
end
|
||||
if ( self.ClassButton ) then
|
||||
self:UpdateClassButtonText();
|
||||
end
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:GetClassAndSpecFilters()
|
||||
return self:GetParent():GetClassAndSpecFilters();
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:UpdateClassButtonText()
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:ShowItemTooltip(button)
|
||||
-- itemLink may not be available
|
||||
if not button.itemLink then
|
||||
GameTooltip:Hide()
|
||||
return
|
||||
end
|
||||
|
||||
GameTooltip:SetOwner(button, "ANCHOR_RIGHT");
|
||||
GameTooltip:SetHyperlink(button.itemLink);
|
||||
|
||||
if LootJournal_CanOpenItemByEntry(button.itemID) then
|
||||
GameTooltip:AddLine(LOOTJOURNAL_ITEM_CLICK_TO_OPEN_LOOT, 0, 0.8, 1)
|
||||
end
|
||||
|
||||
self.tooltipItemID = button.itemID;
|
||||
GameTooltip:Show();
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:CheckItemButtonTooltip(button)
|
||||
if ( GameTooltip:GetOwner() == button and self.tooltipItemID ~= button.itemID ) then
|
||||
self:ShowItemTooltip(button);
|
||||
end
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:GetClassFilter()
|
||||
local classFilter, specFilter = self:GetClassAndSpecFilters();
|
||||
return classFilter;
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:GetSpecFilter()
|
||||
local classFilter, specFilter = self:GetClassAndSpecFilters();
|
||||
return specFilter;
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:SetClassAndSpecFilters(newClassFilter, newSpecFilter)
|
||||
local classFilter, specFilter = self:GetClassAndSpecFilters();
|
||||
if not self.classAndSpecFiltersSet or classFilter ~= newClassFilter or specFilter ~= newSpecFilter then
|
||||
--[[
|
||||
-- if choosing just a class without a spec, pick a spec
|
||||
if newClassFilter ~= NO_CLASS_FILTER and newSpecFilter == NO_SPEC_FILTER then
|
||||
local _, _, classID = UnitClass("player");
|
||||
-- if player's class, choose active spec
|
||||
-- otherwise use 1st spec
|
||||
if classID == newClassFilter then
|
||||
local specIndex = C_Talent.GetCurrentSpecTabIndex()
|
||||
newSpecFilter = specIndex
|
||||
else
|
||||
newSpecFilter = 1
|
||||
end
|
||||
end
|
||||
--]]
|
||||
self:GetParent():SetClassAndSpecFilters(newClassFilter, newSpecFilter);
|
||||
self.scrollBar:SetValue(0);
|
||||
self:Refresh();
|
||||
end
|
||||
|
||||
CloseDropDownMenus(1);
|
||||
self.classAndSpecFiltersSet = true;
|
||||
end
|
||||
|
||||
do
|
||||
function LootJournalItemButton_OnUpdate(self)
|
||||
if GameTooltip:IsOwned(self) then
|
||||
if IsModifiedClick("DRESSUP") then
|
||||
ShowInspectCursor();
|
||||
else
|
||||
ResetCursor();
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function OpenClassFilterDropDown(self, level)
|
||||
if level then
|
||||
self:GetParent():GetActiveList():OpenClassFilterDropDown(level);
|
||||
end
|
||||
end
|
||||
|
||||
function LootJournalItemsClassDropDown_OnLoad(self)
|
||||
UIDropDownMenu_Initialize(self, OpenClassFilterDropDown, "MENU");
|
||||
end
|
||||
|
||||
local CLASS_DROPDOWN = 1;
|
||||
|
||||
function LootJournalItemSetsMixin:OpenClassFilterDropDown(level)
|
||||
local filterClassID = self:GetClassFilter();
|
||||
local filterSpecID = self:GetSpecFilter();
|
||||
local classDisplayName, classTag, classID;
|
||||
|
||||
local function SetClassAndSpecFilters(_, classFilter, specFilter)
|
||||
self:SetClassAndSpecFilters(classFilter, specFilter);
|
||||
end
|
||||
|
||||
local info = UIDropDownMenu_CreateInfo();
|
||||
|
||||
if UIDROPDOWNMENU_MENU_VALUE == CLASS_DROPDOWN then
|
||||
info.text = ALL_CLASSES;
|
||||
info.checked = filterClassID == NO_CLASS_FILTER;
|
||||
info.arg1 = NO_CLASS_FILTER;
|
||||
info.arg2 = NO_SPEC_FILTER;
|
||||
info.func = SetClassAndSpecFilters;
|
||||
UIDropDownMenu_AddButton(info, level);
|
||||
|
||||
local numClasses = GetNumClasses();
|
||||
for i = 1, numClasses do
|
||||
classDisplayName, classTag, classID = GetClassInfo(i);
|
||||
if classID ~= 10 then
|
||||
info.text = classDisplayName;
|
||||
info.checked = filterClassID == classID;
|
||||
info.arg1 = classID;
|
||||
info.arg2 = NO_SPEC_FILTER;
|
||||
info.func = SetClassAndSpecFilters;
|
||||
UIDropDownMenu_AddButton(info, level);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if level == 1 then
|
||||
info.text = CLASS;
|
||||
info.func = nil;
|
||||
info.notCheckable = true;
|
||||
info.hasArrow = true;
|
||||
info.value = CLASS_DROPDOWN;
|
||||
UIDropDownMenu_AddButton(info, level);
|
||||
|
||||
local classDisplayName, classTag, classID;
|
||||
if filterClassID ~= NO_CLASS_FILTER then
|
||||
classID = filterClassID;
|
||||
classDisplayName = GetClassInfo(classID)
|
||||
else
|
||||
classDisplayName, classTag, classID = UnitClass("player");
|
||||
end
|
||||
|
||||
info.text = classDisplayName;
|
||||
info.notCheckable = true;
|
||||
info.arg1 = nil;
|
||||
info.arg2 = nil;
|
||||
info.func = nil;
|
||||
info.hasArrow = false;
|
||||
UIDropDownMenu_AddButton(info, level);
|
||||
|
||||
info.notCheckable = nil;
|
||||
for i = 1, GetNumSpecializationsForClassID(classID) do
|
||||
local _, specName = GetSpecializationInfoForClassID(classID, i)
|
||||
info.leftPadding = 10;
|
||||
info.text = specName;
|
||||
info.checked = filterSpecID == i;
|
||||
info.arg1 = classID;
|
||||
info.arg2 = i;
|
||||
info.func = SetClassAndSpecFilters;
|
||||
UIDropDownMenu_AddButton(info, level);
|
||||
end
|
||||
|
||||
info.text = ALL_SPECS;
|
||||
info.leftPadding = 10;
|
||||
info.checked = (classID == filterClassID and filterSpecID == NO_SPEC_FILTER) or (filterClassID == NO_CLASS_FILTER and filterSpecID == NO_SPEC_FILTER);
|
||||
info.arg1 = classID;
|
||||
info.arg2 = NO_SPEC_FILTER;
|
||||
info.func = SetClassAndSpecFilters;
|
||||
UIDropDownMenu_AddButton(info, level);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:OnLoad()
|
||||
self.scrollBar.trackBG:Hide();
|
||||
self.update = LootJournalItemSetsMixin.UpdateList;
|
||||
HybridScrollFrame_CreateButtons(self, "LootJournalItemSetButtonTemplate", LJ_ITEMSET_X_OFFSET, -LJ_ITEMSET_Y_OFFSET, "TOPLEFT", nil, nil, -LJ_ITEMSET_BUTTON_SPACING);
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:OnShow()
|
||||
if not self.init then
|
||||
self.init = true;
|
||||
self:Refresh();
|
||||
end
|
||||
end
|
||||
|
||||
local function onItemLoaded(itemID)
|
||||
local self = EncounterJournal.LootJournalItems.ItemSetsFrame
|
||||
for i = 1, #self.buttons do
|
||||
local itemButtons = self.buttons[i].ItemButtons;
|
||||
for j = 1, #itemButtons do
|
||||
if ( itemButtons[j].itemID == itemID ) then
|
||||
self:ConfigureItemButton(itemButtons[j]);
|
||||
return;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:ConfigureItemButton(button)
|
||||
local _, itemLink, itemQuality, _, _, _, _, _, _, icon = C_Item.GetItemInfo(button.itemID, false, onItemLoaded, true);
|
||||
button.itemLink = itemLink;
|
||||
itemQuality = itemQuality or Enum.ItemQuality.Epic; -- sets are most likely rare
|
||||
if ( itemQuality == Enum.ItemQuality.Uncommon ) then
|
||||
button.Border:SetAtlas("loottab-set-itemborder-green", true);
|
||||
elseif ( itemQuality == Enum.ItemQuality.Rare ) then
|
||||
button.Border:SetAtlas("loottab-set-itemborder-blue", true);
|
||||
elseif ( itemQuality == Enum.ItemQuality.Epic ) then
|
||||
button.Border:SetAtlas("loottab-set-itemborder-purple", true);
|
||||
end
|
||||
|
||||
button.Icon:SetTexture(icon or "Interface\\ICONS\\temp")
|
||||
|
||||
button:GetParent().SetName:SetTextColor(GetItemQualityColor(itemQuality));
|
||||
self:CheckItemButtonTooltip(button);
|
||||
end
|
||||
|
||||
function LootJournalItemSetsMixin:UpdateList()
|
||||
if ( self.dirty ) then
|
||||
C_LootJournal.GenerateLootData(self:GetClassAndSpecFilters())
|
||||
self.dirty = nil;
|
||||
end
|
||||
|
||||
local buttons = self.buttons;
|
||||
local offset = HybridScrollFrame_GetOffset(self);
|
||||
|
||||
local numSets = C_LootJournal.GetNumItemSets()
|
||||
|
||||
for i = 1, #buttons do
|
||||
local button = buttons[i];
|
||||
local index = offset + i;
|
||||
if ( index <= numSets ) then
|
||||
local setIndex, name, tierName, itemlevel, sourceText, isPVP, items, numItems = C_LootJournal.GetItemSetInfo(index)
|
||||
|
||||
button:Show();
|
||||
button.SetName:SetText(name);
|
||||
button.ItemLevel:SetFormattedText(EJ_SET_ITEM_LEVEL, tierName, itemlevel);
|
||||
button.PVPIcon:SetShown(isPVP);
|
||||
|
||||
button.setIndex = setIndex
|
||||
button.tooltipText = sourceText
|
||||
button:CheckItemButtonTooltip()
|
||||
|
||||
for j = 1, numItems do
|
||||
local itemButton = button.ItemButtons[j];
|
||||
if ( not itemButton ) then
|
||||
itemButton = CreateFrame("BUTTON", string.format("$parentItemButton%i", j), button, "LootJournalItemSetItemButtonTemplate");
|
||||
button[string.format("$parentItemButton%i", j)] = itemButton
|
||||
itemButton:SetPoint("LEFT", button.ItemButtons[j-1], "RIGHT", 5, 0);
|
||||
end
|
||||
itemButton.Icon:SetTexture(items[j].icon);
|
||||
itemButton.itemID = items[j].itemID;
|
||||
itemButton:Show();
|
||||
self:ConfigureItemButton(itemButton);
|
||||
end
|
||||
for j = numItems + 1, #button.ItemButtons do
|
||||
button.ItemButtons[j].itemID = nil;
|
||||
button.ItemButtons[j]:Hide();
|
||||
end
|
||||
else
|
||||
button:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
local totalHeight = numSets * buttons[1]:GetHeight() + (numSets - 1) * LJ_ITEMSET_BUTTON_SPACING + LJ_ITEMSET_Y_OFFSET + LJ_ITEMSET_BOTTOM_BUFFER
|
||||
HybridScrollFrame_Update(self, totalHeight, self:GetHeight());
|
||||
end
|
||||
|
||||
LootJournalItemSetButtonMixin = {}
|
||||
|
||||
function LootJournalItemSetButtonMixin:OnEnter()
|
||||
if self.tooltipText then
|
||||
GameTooltip:SetOwner(self, "ANCHOR_TOP")
|
||||
GameTooltip:SetText(LOOTJOURNAL_SOURCE_TOOLTIP_HEAD, 1, 1, 1)
|
||||
GameTooltip:AddLine(self.tooltipText, nil, nil, nil, 1)
|
||||
self.tooltipSetIndex = self.setIndex
|
||||
GameTooltip:Show()
|
||||
else
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function LootJournalItemSetButtonMixin:CheckItemButtonTooltip()
|
||||
if ( GameTooltip:GetOwner() == self and self.tooltipSetIndex ~= self.setIndex ) then
|
||||
self:OnEnter();
|
||||
end
|
||||
end
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\..\FrameXML\UI.xsd">
|
||||
<Script file="Custom_LootJournalItems.lua"/>
|
||||
|
||||
<Button name="LootJournalItemButtonTemplate" virtual="true">
|
||||
<Scripts>
|
||||
<OnEnter function="LootJournalItemButtonTemplate_OnEnter"/>
|
||||
<OnLeave function="LootJournalItemButtonTemplate_OnLeave"/>
|
||||
<OnClick function="LootJournalItemButton_OnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
|
||||
<Button name="LootJournalItemSetItemButtonTemplate" inherits="LootJournalItemButtonTemplate" virtual="true" hidden="true">
|
||||
<Size x="32" y="32"/>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture name="$parentIcon" parentKey="Icon">
|
||||
<Size x="28" y="28"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
<Layer level="BORDER">
|
||||
<Texture parentKey="Border">
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parentIcon" relativePoint="CENTER" x="20" y="1"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self:SetParentArray("ItemButtons")
|
||||
self.Border:SetAtlas("loottab-set-itemborder-green", true)
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
</Button>
|
||||
|
||||
<Button name="LootJournalItemSetButtonTemplate" virtual="true">
|
||||
<Size x="744" y="41"/>
|
||||
<HitRectInsets left="34" right="390" top="1" bottom="1"/>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture parentKey="Background">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
<Layer level="ARTWORK">
|
||||
<FontString name="$parentSetName" parentKey="SetName" inherits="GameFontNormalMed2" maxLines="1" justifyH="LEFT">
|
||||
<Size x="320" y="0"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="38" y="-6"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
<FontString name="$parentItemLevel" parentKey="ItemLevel" inherits="GameFontNormal" text="Item Level" maxLines="1" justifyH="LEFT">
|
||||
<Size x="320" y="0"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentSetName" relativePoint="BOTTOMLEFT" x="0" y="-2"/>
|
||||
</Anchors>
|
||||
<Color r="0.718" g="0.561" b="0.416"/>
|
||||
</FontString>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Frames>
|
||||
<Frame name="$parentPVPIcon" parentKey="PVPIcon" hidden="true">
|
||||
<Size x="30" y="30"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativePoint="LEFT" x="0" y="2"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture name="$parentIcon" parentKey="Icon" file="Interface\PVPFrame\Icons\prestige-icon-4"/>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
<OnEnter>
|
||||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||||
GameTooltip:AddLine(LOOTJOURNAL_PVPICON_TOOLTIP_HEAD, 1, 1, 1)
|
||||
GameTooltip:AddLine(LOOTJOURNAL_PVPICON_TOOLTIP, nil, nil, nil, 1)
|
||||
GameTooltip:Show()
|
||||
</OnEnter>
|
||||
<OnLeave function="GameTooltip_Hide"/>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
<Button name="$parentItemButton1" parentKey="ItemButton1" inherits="LootJournalItemSetItemButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" x="397" y="0"/>
|
||||
</Anchors>
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, LootJournalItemSetButtonMixin)
|
||||
self.Background:SetAtlas("loottab-set-background", true)
|
||||
</OnLoad>
|
||||
<OnEnter>
|
||||
self:OnEnter()
|
||||
</OnEnter>
|
||||
<OnLeave function="GameTooltip_Hide"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
|
||||
<Frame parent="EncounterJournal" name="$parentLootJournalItems" parentKey="LootJournalItems" hidden="true">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentInset" x="4" y="-51" />
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentInset" x="-4" y="0"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture parentKey="Background">
|
||||
<Anchors>
|
||||
<Anchor point="TOP" x="0" y="4"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Frames>
|
||||
<Frame name="LootJournalItemsClassDropDown" parentKey="ClassDropDown" inherits="UIDropDownMenuTemplate" hidden="true">
|
||||
<Scripts>
|
||||
<OnLoad function="LootJournalItemsClassDropDown_OnLoad"/>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
<ScrollFrame name="$parentItemSetsFrame" parentKey="ItemSetsFrame" inherits="MinimalHybridScrollFrameTemplate" hidden="true">
|
||||
<Size x="762" y="332"/>
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" x="0" y="3"/>
|
||||
</Anchors>
|
||||
<Frames>
|
||||
<Button parentKey="ClassButton" inherits="EJButtonTemplate" text="FILTER">
|
||||
<Size x="114" y="26"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPRIGHT" x="-12" y="35"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnMouseDown>
|
||||
EJButtonMixin.OnMouseDown(self, button);
|
||||
ToggleDropDownMenu(1, nil, self:GetParent():GetParent().ClassDropDown, self, 5, 0);
|
||||
PlaySound("igMainMenuOptionCheckBoxOn");
|
||||
</OnMouseDown>
|
||||
</Scripts>
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, LootJournalItemSetsMixin)
|
||||
self:OnLoad()
|
||||
</OnLoad>
|
||||
<OnShow>
|
||||
self:OnShow()
|
||||
</OnShow>
|
||||
</Scripts>
|
||||
</ScrollFrame>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, LootJournalItemsMixin)
|
||||
self:OnLoad()
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
</Ui>
|
||||
+919
@@ -0,0 +1,919 @@
|
||||
-- Compatibility shims for the Sirus Encounter Journal backport on 3.3.5a.
|
||||
|
||||
if not tIndexOf then
|
||||
function tIndexOf(tbl, value)
|
||||
if not tbl then
|
||||
return nil
|
||||
end
|
||||
for index, entry in ipairs(tbl) do
|
||||
if entry == value then
|
||||
return index
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
if not CopyTable then
|
||||
function CopyTable(tbl)
|
||||
if type(tbl) ~= "table" then
|
||||
return tbl
|
||||
end
|
||||
local copy = {}
|
||||
for key, value in pairs(tbl) do
|
||||
copy[key] = CopyTable(value)
|
||||
end
|
||||
return copy
|
||||
end
|
||||
end
|
||||
|
||||
if not table.wipe then
|
||||
function table.wipe(tbl)
|
||||
for key in pairs(tbl) do
|
||||
tbl[key] = nil
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
end
|
||||
|
||||
if not tCompare then
|
||||
function tCompare(lhsTable, rhsTable, depth)
|
||||
depth = depth or 1
|
||||
for key, value in pairs(lhsTable) do
|
||||
if type(value) == "table" then
|
||||
local rhsValue = rhsTable[key]
|
||||
if type(rhsValue) ~= "table" then
|
||||
return false
|
||||
end
|
||||
if depth > 1 then
|
||||
if not tCompare(value, rhsValue, depth - 1) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
elseif value ~= rhsTable[key] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
for key in pairs(rhsTable) do
|
||||
if lhsTable[key] == nil then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
tsort = tsort or table.sort
|
||||
|
||||
bit = bit or {}
|
||||
if not bit.band then
|
||||
function bit.band(a, b)
|
||||
local result = 0
|
||||
local bitValue = 1
|
||||
a = a or 0
|
||||
b = b or 0
|
||||
while a > 0 or b > 0 do
|
||||
local aBit = a % 2
|
||||
local bBit = b % 2
|
||||
if aBit == 1 and bBit == 1 then
|
||||
result = result + bitValue
|
||||
end
|
||||
a = math.floor(a / 2)
|
||||
b = math.floor(b / 2)
|
||||
bitValue = bitValue * 2
|
||||
end
|
||||
return result
|
||||
end
|
||||
end
|
||||
bitband = bitband or bit.band
|
||||
|
||||
if not string.trim then
|
||||
function string.trim(value)
|
||||
return value and value:match("^%s*(.-)%s*$") or value
|
||||
end
|
||||
end
|
||||
|
||||
utf8 = utf8 or {}
|
||||
utf8.find = utf8.find or string.find
|
||||
utf8.upper = utf8.upper or string.upper
|
||||
|
||||
LE_EXPANSION_CLASSIC = LE_EXPANSION_CLASSIC or 0
|
||||
LE_EXPANSION_BURNING_CRUSADE = LE_EXPANSION_BURNING_CRUSADE or 1
|
||||
LE_EXPANSION_WRATH_OF_THE_LICH_KING = LE_EXPANSION_WRATH_OF_THE_LICH_KING or 2
|
||||
LE_EXPANSION_CATACLYSM = LE_EXPANSION_CATACLYSM or 3
|
||||
LE_EXPANSION_MISTS_OF_PANDARIA = LE_EXPANSION_MISTS_OF_PANDARIA or 4
|
||||
LE_EXPANSION_WARLORDS_OF_DRAENOR = LE_EXPANSION_WARLORDS_OF_DRAENOR or 5
|
||||
LE_EXPANSION_LEGION = LE_EXPANSION_LEGION or 6
|
||||
LE_EXPANSION_BATTLE_FOR_AZEROTH = LE_EXPANSION_BATTLE_FOR_AZEROTH or 7
|
||||
LE_EXPANSION_SHADOWLANDS = LE_EXPANSION_SHADOWLANDS or 8
|
||||
LE_EXPANSION_DRAGONFLIGHT = LE_EXPANSION_DRAGONFLIGHT or 9
|
||||
LE_EXPANSION_WAR_WITHIN = LE_EXPANSION_WAR_WITHIN or 10
|
||||
LE_EXPANSION_MIDNIGHT = LE_EXPANSION_MIDNIGHT or 11
|
||||
LE_EXPANSION_LEVEL_CURRENT = LE_EXPANSION_LEVEL_CURRENT or LE_EXPANSION_WRATH_OF_THE_LICH_KING
|
||||
|
||||
MAX_PLAYER_LEVEL_TABLE = MAX_PLAYER_LEVEL_TABLE or {}
|
||||
MAX_PLAYER_LEVEL_TABLE[LE_EXPANSION_CLASSIC] = MAX_PLAYER_LEVEL_TABLE[LE_EXPANSION_CLASSIC] or 60
|
||||
MAX_PLAYER_LEVEL_TABLE[LE_EXPANSION_BURNING_CRUSADE] = MAX_PLAYER_LEVEL_TABLE[LE_EXPANSION_BURNING_CRUSADE] or 70
|
||||
MAX_PLAYER_LEVEL_TABLE[LE_EXPANSION_WRATH_OF_THE_LICH_KING] = MAX_PLAYER_LEVEL_TABLE[LE_EXPANSION_WRATH_OF_THE_LICH_KING] or 80
|
||||
|
||||
PLAYER_FACTION_GROUP = PLAYER_FACTION_GROUP or {}
|
||||
PLAYER_FACTION_GROUP.Alliance = PLAYER_FACTION_GROUP.Alliance or 1
|
||||
PLAYER_FACTION_GROUP.Horde = PLAYER_FACTION_GROUP.Horde or 2
|
||||
PLAYER_FACTION_GROUP.Neutral = PLAYER_FACTION_GROUP.Neutral or 3
|
||||
PLAYER_FACTION_GROUP.Renegade = PLAYER_FACTION_GROUP.Renegade or 4
|
||||
|
||||
QUESTION_MARK_ICON = QUESTION_MARK_ICON or "Interface\\Icons\\INV_Misc_QuestionMark"
|
||||
|
||||
CLASS_ID_WARRIOR = CLASS_ID_WARRIOR or 1
|
||||
CLASS_ID_PALADIN = CLASS_ID_PALADIN or 2
|
||||
CLASS_ID_HUNTER = CLASS_ID_HUNTER or 3
|
||||
CLASS_ID_ROGUE = CLASS_ID_ROGUE or 4
|
||||
CLASS_ID_PRIEST = CLASS_ID_PRIEST or 5
|
||||
CLASS_ID_DEATHKNIGHT = CLASS_ID_DEATHKNIGHT or 6
|
||||
CLASS_ID_SHAMAN = CLASS_ID_SHAMAN or 7
|
||||
CLASS_ID_MAGE = CLASS_ID_MAGE or 8
|
||||
CLASS_ID_WARLOCK = CLASS_ID_WARLOCK or 9
|
||||
CLASS_ID_DRUID = CLASS_ID_DRUID or 11
|
||||
|
||||
if not SetParentFrameLevel then
|
||||
function SetParentFrameLevel(frame, offset)
|
||||
frame:SetFrameLevel(frame:GetParent():GetFrameLevel() + (offset or 0))
|
||||
end
|
||||
end
|
||||
|
||||
if not IsOnGlueScreen then
|
||||
function IsOnGlueScreen() return false end
|
||||
end
|
||||
|
||||
if not RegisterCustomEvent then
|
||||
function RegisterCustomEvent() end
|
||||
end
|
||||
|
||||
if not UnregisterCustomEvent then
|
||||
function UnregisterCustomEvent() end
|
||||
end
|
||||
|
||||
C_Timer = C_Timer or {}
|
||||
if not C_Timer.NewTimer then
|
||||
local timerFrame
|
||||
local timers = {}
|
||||
|
||||
local function EnsureTimerFrame()
|
||||
if timerFrame or not CreateFrame then
|
||||
return
|
||||
end
|
||||
|
||||
timerFrame = CreateFrame("Frame")
|
||||
timerFrame:SetScript("OnUpdate", function(_, elapsed)
|
||||
for timer in pairs(timers) do
|
||||
timer.remaining = timer.remaining - elapsed
|
||||
if timer.remaining <= 0 then
|
||||
timers[timer] = nil
|
||||
if not timer.cancelled then
|
||||
timer.callback()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function C_Timer.NewTimer(seconds, callback)
|
||||
local timer = {
|
||||
remaining = seconds or 0,
|
||||
callback = callback or function() end,
|
||||
}
|
||||
|
||||
function timer:Cancel()
|
||||
self.cancelled = true
|
||||
timers[self] = nil
|
||||
end
|
||||
|
||||
EnsureTimerFrame()
|
||||
timers[timer] = true
|
||||
return timer
|
||||
end
|
||||
end
|
||||
C_Timer.After = C_Timer.After or function(seconds, callback)
|
||||
return C_Timer.NewTimer(seconds, callback)
|
||||
end
|
||||
|
||||
if not IsInterfaceDevClient then
|
||||
function IsInterfaceDevClient()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if not IsGMAccount then
|
||||
function IsGMAccount()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if not FireCustomClientEvent then
|
||||
function FireCustomClientEvent(event, ...)
|
||||
if EventRegistry and EventRegistry.TriggerEvent then
|
||||
EventRegistry:TriggerEvent(event, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
EventRegistry = EventRegistry or {}
|
||||
EventRegistry.registry = EventRegistry.registry or {}
|
||||
EventRegistry.TriggerEvent = EventRegistry.TriggerEvent or function(self, event, ...)
|
||||
local callbacks = self.registry[event]
|
||||
if callbacks then
|
||||
for _, callback in ipairs(callbacks) do
|
||||
callback(...)
|
||||
end
|
||||
end
|
||||
end
|
||||
EventRegistry.RegisterCallback = EventRegistry.RegisterCallback or function(self, event, callback)
|
||||
self.registry[event] = self.registry[event] or {}
|
||||
table.insert(self.registry[event], callback)
|
||||
end
|
||||
|
||||
C_Service = C_Service or {}
|
||||
C_Service.GetRealmID = function() return 0 end
|
||||
C_Service.GetRealmStage = C_Service.GetRealmStage or function() return 0 end
|
||||
C_Service.GetCustomValue = C_Service.GetCustomValue or function() return 0 end
|
||||
C_Service.IsInGMMode = C_Service.IsInGMMode or IsGMAccount
|
||||
C_Service.IsGMAccount = C_Service.IsGMAccount or IsGMAccount
|
||||
C_Service.IsRenegadeRealm = C_Service.IsRenegadeRealm or function() return false end
|
||||
C_Service.IsHardcoreEnabledOnRealm = C_Service.IsHardcoreEnabledOnRealm or function() return false end
|
||||
|
||||
C_MythicPlus = C_MythicPlus or {}
|
||||
C_MythicPlus.IsMythicPlusActive = C_MythicPlus.IsMythicPlusActive or function() return false end
|
||||
|
||||
C_PvP = C_PvP or {}
|
||||
|
||||
C_LFGList = C_LFGList or {}
|
||||
C_LFGList.IsPremadeGroupFinderEnabled = C_LFGList.IsPremadeGroupFinderEnabled or function() return false end
|
||||
|
||||
if not MicroButtonPulseStop then
|
||||
function MicroButtonPulseStop() end
|
||||
end
|
||||
|
||||
if not EJSuggestFrame_OpenFrame then
|
||||
function EJSuggestFrame_OpenFrame() end
|
||||
end
|
||||
|
||||
if not EJSuggestTab_GetPlayerTierIndex then
|
||||
function EJSuggestTab_GetPlayerTierIndex()
|
||||
if EJ_GetCurrentTier then
|
||||
return EJ_GetCurrentTier()
|
||||
end
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
if not ChatEdit_TryInsertChatLink then
|
||||
function ChatEdit_TryInsertChatLink()
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if not SharedTooltip_SetBackdropStyle then
|
||||
function SharedTooltip_SetBackdropStyle(tooltip)
|
||||
if not tooltip then
|
||||
return
|
||||
end
|
||||
if tooltip.SetBackdropBorderColor and TOOLTIP_DEFAULT_COLOR then
|
||||
tooltip:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
|
||||
end
|
||||
if tooltip.SetBackdropColor and TOOLTIP_DEFAULT_BACKGROUND_COLOR then
|
||||
tooltip:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not HelpPlate_Hide then
|
||||
function HelpPlate_Hide() end
|
||||
end
|
||||
|
||||
if not HelpPlate_Show then
|
||||
function HelpPlate_Show() end
|
||||
end
|
||||
|
||||
-- 3.3.5 has no GetNumClasses/GetClassInfo (added in Cataclysm). Sirus EJ uses
|
||||
-- them to populate the loot class filter dropdown.
|
||||
local MOONWELL_CLASS_INFO = {
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.WARRIOR or "Warrior", "WARRIOR", CLASS_ID_WARRIOR},
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.PALADIN or "Paladin", "PALADIN", CLASS_ID_PALADIN},
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.HUNTER or "Hunter", "HUNTER", CLASS_ID_HUNTER},
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.ROGUE or "Rogue", "ROGUE", CLASS_ID_ROGUE},
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.PRIEST or "Priest", "PRIEST", CLASS_ID_PRIEST},
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.DEATHKNIGHT or "Death Knight", "DEATHKNIGHT", CLASS_ID_DEATHKNIGHT},
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.SHAMAN or "Shaman", "SHAMAN", CLASS_ID_SHAMAN},
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.MAGE or "Mage", "MAGE", CLASS_ID_MAGE},
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.WARLOCK or "Warlock", "WARLOCK", CLASS_ID_WARLOCK},
|
||||
{LOCALIZED_CLASS_NAMES_MALE and LOCALIZED_CLASS_NAMES_MALE.DRUID or "Druid", "DRUID", CLASS_ID_DRUID},
|
||||
}
|
||||
|
||||
if not GetNumClasses then
|
||||
function GetNumClasses()
|
||||
return #MOONWELL_CLASS_INFO
|
||||
end
|
||||
end
|
||||
|
||||
if not GetClassInfo then
|
||||
function GetClassInfo(index)
|
||||
local info = MOONWELL_CLASS_INFO[index]
|
||||
if info then
|
||||
return info[1], info[2], info[3]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CLASS_ID_DEMONHUNTER = CLASS_ID_DEMONHUNTER or 12
|
||||
local function EnsureColorMethods(color)
|
||||
if type(color) ~= "table" then
|
||||
return color
|
||||
end
|
||||
|
||||
color.GetRGB = color.GetRGB or function(self)
|
||||
return self.r or 1, self.g or 1, self.b or 1
|
||||
end
|
||||
color.GetRGBA = color.GetRGBA or function(self)
|
||||
return self.r or 1, self.g or 1, self.b or 1, self.a or 1
|
||||
end
|
||||
color.WrapTextInColorCode = color.WrapTextInColorCode or function(self, text)
|
||||
if self.colorStr then
|
||||
return "|c" .. self.colorStr .. text .. "|r"
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
return color
|
||||
end
|
||||
|
||||
EnsureColorMethods(NORMAL_FONT_COLOR)
|
||||
EnsureColorMethods(HIGHLIGHT_FONT_COLOR)
|
||||
EnsureColorMethods(RED_FONT_COLOR)
|
||||
EnsureColorMethods(GREEN_FONT_COLOR)
|
||||
EnsureColorMethods(DISABLED_FONT_COLOR)
|
||||
LOOTJOURNAL_SOURCE_TOOLTIP_HEAD = LOOTJOURNAL_SOURCE_TOOLTIP_HEAD or "Способ получения:"
|
||||
RETURN_TO_DEFAULT = RETURN_TO_DEFAULT or "Настройки по умолчанию"
|
||||
INSTANCES = INSTANCES or "Подземелья"
|
||||
RAIDS = RAIDS or "Рейды"
|
||||
LOOT_JOURNAL_ITEM_SETS = LOOT_JOURNAL_ITEM_SETS or "Комплекты"
|
||||
|
||||
-- Format string used by EncounterJournal_SetLootButton to label the loot
|
||||
-- source ("Босс: <name>"). Sirus ships it via locale globals; default to a
|
||||
-- compact form on 3.3.5.
|
||||
BOSS_INFO_STRING = BOSS_INFO_STRING or "Босс: %s"
|
||||
|
||||
-- Sirus ships a PKBT model mixin in SharedXML/SharedUIPanelPKBTTemplates;
|
||||
-- we don't carry it. The EJ DressUpModel OnShow does `self:OnShow()` and
|
||||
-- OnEvent does `self:OnEvent(...)`, expecting the mixin to provide them.
|
||||
PKBT_ModelMixin = PKBT_ModelMixin or {}
|
||||
PKBT_ModelMixin.OnShow = PKBT_ModelMixin.OnShow or function() end
|
||||
PKBT_ModelMixin.OnEvent = PKBT_ModelMixin.OnEvent or function() end
|
||||
PKBT_ModelMixin.OnLoad = PKBT_ModelMixin.OnLoad or function() end
|
||||
|
||||
if not SharedXML_Model_OnLoad then
|
||||
function SharedXML_Model_OnLoad() end
|
||||
end
|
||||
if not SharedXML_Model_OnEvent then
|
||||
function SharedXML_Model_OnEvent() end
|
||||
end
|
||||
|
||||
ITEM_CLASS_2 = ITEM_CLASS_2 or 2
|
||||
ITEM_CLASS_4 = ITEM_CLASS_4 or 4
|
||||
|
||||
for _, classID in ipairs({0, 2, 4, 5, 7, 9, 11, 12, 13, 14, 15}) do
|
||||
for subclassID = 0, 20 do
|
||||
local key = string.format("ITEM_SUB_CLASS_%d_%d", classID, subclassID)
|
||||
if _G[key] == nil then
|
||||
_G[key] = subclassID
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
LE_ITEM_FILTER_TYPE_HEAD = LE_ITEM_FILTER_TYPE_HEAD or 1
|
||||
LE_ITEM_FILTER_TYPE_NECK = LE_ITEM_FILTER_TYPE_NECK or 2
|
||||
LE_ITEM_FILTER_TYPE_SHOULDER = LE_ITEM_FILTER_TYPE_SHOULDER or 3
|
||||
LE_ITEM_FILTER_TYPE_CLOAK = LE_ITEM_FILTER_TYPE_CLOAK or 16
|
||||
LE_ITEM_FILTER_TYPE_CHEST = LE_ITEM_FILTER_TYPE_CHEST or 5
|
||||
LE_ITEM_FILTER_TYPE_WRIST = LE_ITEM_FILTER_TYPE_WRIST or 9
|
||||
LE_ITEM_FILTER_TYPE_HAND = LE_ITEM_FILTER_TYPE_HAND or 10
|
||||
LE_ITEM_FILTER_TYPE_WAIST = LE_ITEM_FILTER_TYPE_WAIST or 6
|
||||
LE_ITEM_FILTER_TYPE_LEGS = LE_ITEM_FILTER_TYPE_LEGS or 7
|
||||
LE_ITEM_FILTER_TYPE_FEET = LE_ITEM_FILTER_TYPE_FEET or 8
|
||||
LE_ITEM_FILTER_TYPE_MAIN_HAND = LE_ITEM_FILTER_TYPE_MAIN_HAND or 21
|
||||
LE_ITEM_FILTER_TYPE_OFF_HAND = LE_ITEM_FILTER_TYPE_OFF_HAND or 22
|
||||
LE_ITEM_FILTER_TYPE_2HWEAPON = LE_ITEM_FILTER_TYPE_2HWEAPON or 17
|
||||
LE_ITEM_FILTER_TYPE_HWEAPON = LE_ITEM_FILTER_TYPE_HWEAPON or 13
|
||||
LE_ITEM_FILTER_TYPE_RANGED = LE_ITEM_FILTER_TYPE_RANGED or 15
|
||||
LE_ITEM_FILTER_TYPE_FINGER = LE_ITEM_FILTER_TYPE_FINGER or 11
|
||||
LE_ITEM_FILTER_TYPE_TRINKET = LE_ITEM_FILTER_TYPE_TRINKET or 12
|
||||
|
||||
LE_ITEM_QUALITY_COMMON = LE_ITEM_QUALITY_COMMON or 1
|
||||
|
||||
BAG_ITEM_QUALITY_COLORS = BAG_ITEM_QUALITY_COLORS or {}
|
||||
local itemQualityColors = ITEM_QUALITY_COLORS or {}
|
||||
for quality = 0, 7 do
|
||||
local color = BAG_ITEM_QUALITY_COLORS[quality] or itemQualityColors[quality] or NORMAL_FONT_COLOR
|
||||
BAG_ITEM_QUALITY_COLORS[quality] = EnsureColorMethods(color or {})
|
||||
end
|
||||
|
||||
if not SetItemButtonQuality then
|
||||
function SetItemButtonQuality(button, quality)
|
||||
if not button or not button.IconBorder then
|
||||
return
|
||||
end
|
||||
|
||||
local color = quality and BAG_ITEM_QUALITY_COLORS[quality]
|
||||
if color then
|
||||
button.IconBorder:Show()
|
||||
button.IconBorder:SetVertexColor(color.r or 1, color.g or 1, color.b or 1)
|
||||
else
|
||||
button.IconBorder:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Enum = Enum or {}
|
||||
Enum.ItemQuality = Enum.ItemQuality or {
|
||||
Poor = 0,
|
||||
Common = 1,
|
||||
Uncommon = 2,
|
||||
Rare = 3,
|
||||
Epic = 4,
|
||||
Legendary = 5,
|
||||
Artifact = 6,
|
||||
Heirloom = 7,
|
||||
}
|
||||
Enum.ModelType = Enum.ModelType or {
|
||||
M2 = 0,
|
||||
Unit = 1,
|
||||
Creature = 2,
|
||||
Item = 3,
|
||||
ItemSet = 4,
|
||||
Illusion = 5,
|
||||
ItemTransmog = 6,
|
||||
Customization = 7,
|
||||
}
|
||||
Enum.HardcoreDeathReason = Enum.HardcoreDeathReason or {
|
||||
FAILED_DEATH = 1,
|
||||
RESTORE = 2,
|
||||
}
|
||||
local ITEM_CACHE_FIELD = {
|
||||
NAME_ENGB = 1,
|
||||
NAME_RURU = 2,
|
||||
RARITY = 3,
|
||||
ILEVEL = 4,
|
||||
MINLEVEL = 5,
|
||||
TYPE = 6,
|
||||
SUBTYPE = 7,
|
||||
STACKCOUNT = 8,
|
||||
EQUIPLOC = 9,
|
||||
TEXTURE = 10,
|
||||
VENDORPRICE = 11,
|
||||
VENDORPRIC = 11,
|
||||
}
|
||||
local ITEM_ID_FIELD = 0
|
||||
local ITEM_LINK_FIELD = -1
|
||||
|
||||
Enum.ItemCacheField = Enum.ItemCacheField or {}
|
||||
for key, value in pairs(ITEM_CACHE_FIELD) do
|
||||
Enum.ItemCacheField[key] = value
|
||||
end
|
||||
Enum.ItemCacheField.ITEM_ID = ITEM_ID_FIELD
|
||||
|
||||
SHARED_INVTYPE_BY_ID = SHARED_INVTYPE_BY_ID or {
|
||||
[0] = "",
|
||||
[1] = "INVTYPE_HEAD",
|
||||
[2] = "INVTYPE_NECK",
|
||||
[3] = "INVTYPE_SHOULDER",
|
||||
[4] = "INVTYPE_BODY",
|
||||
[5] = "INVTYPE_CHEST",
|
||||
[6] = "INVTYPE_WAIST",
|
||||
[7] = "INVTYPE_LEGS",
|
||||
[8] = "INVTYPE_FEET",
|
||||
[9] = "INVTYPE_WRIST",
|
||||
[10] = "INVTYPE_HAND",
|
||||
[11] = "INVTYPE_FINGER",
|
||||
[12] = "INVTYPE_TRINKET",
|
||||
[13] = "INVTYPE_WEAPON",
|
||||
[14] = "INVTYPE_SHIELD",
|
||||
[15] = "INVTYPE_RANGED",
|
||||
[16] = "INVTYPE_CLOAK",
|
||||
[17] = "INVTYPE_2HWEAPON",
|
||||
[18] = "INVTYPE_BAG",
|
||||
[19] = "INVTYPE_TABARD",
|
||||
[20] = "INVTYPE_ROBE",
|
||||
[21] = "INVTYPE_WEAPONMAINHAND",
|
||||
[22] = "INVTYPE_WEAPONOFFHAND",
|
||||
[23] = "INVTYPE_HOLDABLE",
|
||||
[24] = "INVTYPE_AMMO",
|
||||
[25] = "INVTYPE_THROWN",
|
||||
[26] = "INVTYPE_RANGEDRIGHT",
|
||||
[27] = "INVTYPE_QUIVER",
|
||||
[28] = "INVTYPE_RELIC",
|
||||
}
|
||||
|
||||
C_FactionManager = C_FactionManager or {}
|
||||
C_FactionManager.GetFactionInfoOriginal = C_FactionManager.GetFactionInfoOriginal or function()
|
||||
local faction = UnitFactionGroup and UnitFactionGroup("player")
|
||||
return PLAYER_FACTION_GROUP[faction] or PLAYER_FACTION_GROUP.Alliance
|
||||
end
|
||||
C_FactionManager.RegisterCallback = C_FactionManager.RegisterCallback or function(callback)
|
||||
if callback then
|
||||
callback()
|
||||
end
|
||||
end
|
||||
|
||||
C_Item = C_Item or {}
|
||||
|
||||
local ExistingCItemGetItemInfo = C_Item.GetItemInfo
|
||||
local ExistingCItemRequestServerCache = C_Item.RequestServerCache
|
||||
local ExistingCItemGetItemIDFromString = C_Item.GetItemIDFromString
|
||||
local ITEM_CACHE_CALLBACKS = {}
|
||||
local ITEM_QUALITY_HEX = {
|
||||
[0] = "ff9d9d9d",
|
||||
[1] = "ffffffff",
|
||||
[2] = "ff1eff00",
|
||||
[3] = "ff0070dd",
|
||||
[4] = "ffa335ee",
|
||||
[5] = "ffff8000",
|
||||
[6] = "ffe6cc80",
|
||||
[7] = "ffe6cc80",
|
||||
}
|
||||
local ITEMS_CACHE_INITIALIZED
|
||||
|
||||
local function GetItemIDFromAny(item)
|
||||
if type(item) == "number" then
|
||||
return item
|
||||
end
|
||||
if type(item) == "string" then
|
||||
local itemsCache = _G.ItemsCache
|
||||
if type(itemsCache) == "table" and type(itemsCache[item]) == "table" then
|
||||
return itemsCache[item][ITEM_ID_FIELD]
|
||||
end
|
||||
return tonumber(item:match("item:(%d+)") or item:match("^(%d+)$"))
|
||||
end
|
||||
end
|
||||
|
||||
local function CreateItemCacheLink(itemName, itemID, itemRarity, itemMinLevel)
|
||||
return string.format("|c%s|Hitem:%d:0:0:0:0:0:0:0:%d|h[%s]|h|r",
|
||||
ITEM_QUALITY_HEX[itemRarity] or "ffffffff",
|
||||
itemID or 0,
|
||||
itemMinLevel or 0,
|
||||
itemName or UNKNOWN or ""
|
||||
)
|
||||
end
|
||||
|
||||
local function EnsureItemsCache()
|
||||
if ITEMS_CACHE_INITIALIZED then
|
||||
return _G.ItemsCache
|
||||
end
|
||||
|
||||
local itemsCache = type(_G.ItemsCache) == "table" and _G.ItemsCache or nil
|
||||
local fileIndex = 1
|
||||
local itemCacheTable = _G["ItemsCache" .. fileIndex]
|
||||
|
||||
while type(itemCacheTable) == "table" do
|
||||
if not itemsCache then
|
||||
itemsCache = itemCacheTable
|
||||
_G.ItemsCache = itemsCache
|
||||
elseif itemCacheTable ~= itemsCache then
|
||||
for itemID, itemData in pairs(itemCacheTable) do
|
||||
itemsCache[itemID] = itemData
|
||||
end
|
||||
table.wipe(itemCacheTable)
|
||||
end
|
||||
|
||||
_G["ItemsCache" .. fileIndex] = nil
|
||||
fileIndex = fileIndex + 1
|
||||
itemCacheTable = _G["ItemsCache" .. fileIndex]
|
||||
end
|
||||
|
||||
if itemsCache then
|
||||
local localeIndex = GetLocale and GetLocale() == "ruRU" and ITEM_CACHE_FIELD.NAME_RURU or ITEM_CACHE_FIELD.NAME_ENGB
|
||||
local namedItems = {}
|
||||
|
||||
for itemID, itemData in pairs(itemsCache) do
|
||||
if type(itemID) == "number" and type(itemData) == "table" then
|
||||
itemData[ITEM_ID_FIELD] = itemID
|
||||
itemData[ITEM_LINK_FIELD] = nil
|
||||
|
||||
local itemName = itemData[localeIndex]
|
||||
if itemName and itemName ~= "" then
|
||||
namedItems[itemName] = itemData
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(itemsCache, {__index = namedItems})
|
||||
end
|
||||
|
||||
ITEMS_CACHE_INITIALIZED = true
|
||||
return itemsCache
|
||||
end
|
||||
|
||||
function C_Item.GetItemInfoCache(item)
|
||||
local itemsCache = EnsureItemsCache()
|
||||
if not itemsCache then
|
||||
return
|
||||
end
|
||||
|
||||
local itemID = GetItemIDFromAny(item)
|
||||
if not itemID then
|
||||
return
|
||||
end
|
||||
|
||||
local cacheData = itemsCache[itemID]
|
||||
if type(cacheData) ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
local localeIndex = GetLocale and GetLocale() == "ruRU" and ITEM_CACHE_FIELD.NAME_RURU or ITEM_CACHE_FIELD.NAME_ENGB
|
||||
local itemName = cacheData[localeIndex] or cacheData[ITEM_CACHE_FIELD.NAME_ENGB]
|
||||
if not itemName or itemName == "" then
|
||||
return
|
||||
end
|
||||
|
||||
local itemRarity = cacheData[ITEM_CACHE_FIELD.RARITY] or LE_ITEM_QUALITY_COMMON
|
||||
local itemMinLevel = cacheData[ITEM_CACHE_FIELD.MINLEVEL] or 0
|
||||
local classID = cacheData[ITEM_CACHE_FIELD.TYPE]
|
||||
local subclassID = cacheData[ITEM_CACHE_FIELD.SUBTYPE]
|
||||
local equipLocID = cacheData[ITEM_CACHE_FIELD.EQUIPLOC] or 0
|
||||
|
||||
if not cacheData[ITEM_LINK_FIELD] then
|
||||
cacheData[ITEM_LINK_FIELD] = CreateItemCacheLink(itemName, itemID, itemRarity, itemMinLevel)
|
||||
end
|
||||
|
||||
return itemName,
|
||||
cacheData[ITEM_LINK_FIELD],
|
||||
itemRarity,
|
||||
cacheData[ITEM_CACHE_FIELD.ILEVEL],
|
||||
itemMinLevel,
|
||||
_G["ITEM_CLASS_" .. tostring(classID)] or classID,
|
||||
_G["ITEM_SUB_CLASS_" .. tostring(classID) .. "_" .. tostring(subclassID)] or subclassID,
|
||||
cacheData[ITEM_CACHE_FIELD.STACKCOUNT],
|
||||
SHARED_INVTYPE_BY_ID[equipLocID],
|
||||
"Interface\\Icons\\" .. tostring(cacheData[ITEM_CACHE_FIELD.TEXTURE] or "INV_Misc_QuestionMark"),
|
||||
cacheData[ITEM_CACHE_FIELD.VENDORPRICE],
|
||||
itemID,
|
||||
classID,
|
||||
subclassID,
|
||||
equipLocID
|
||||
end
|
||||
|
||||
local function GetItemInfoCompat(item)
|
||||
local name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice = GetItemInfo(item)
|
||||
if name then
|
||||
return name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice
|
||||
end
|
||||
|
||||
return C_Item.GetItemInfoCache(item)
|
||||
end
|
||||
|
||||
local function FireItemCacheCallbacks(itemID)
|
||||
local callbacks = ITEM_CACHE_CALLBACKS[itemID]
|
||||
if not callbacks then
|
||||
return
|
||||
end
|
||||
|
||||
local name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice = GetItemInfoCompat(itemID)
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
|
||||
ITEM_CACHE_CALLBACKS[itemID] = nil
|
||||
for _, callback in ipairs(callbacks) do
|
||||
callback(itemID, name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice)
|
||||
end
|
||||
end
|
||||
|
||||
local function QueueItemCacheCallback(item, callback)
|
||||
if not callback then
|
||||
return
|
||||
end
|
||||
|
||||
local itemID = tonumber(item)
|
||||
if not itemID and type(item) == "string" then
|
||||
itemID = tonumber(item:match("item:(%d+)") or item:match("^(%d+)$"))
|
||||
end
|
||||
if not itemID then
|
||||
return
|
||||
end
|
||||
|
||||
ITEM_CACHE_CALLBACKS[itemID] = ITEM_CACHE_CALLBACKS[itemID] or {}
|
||||
table.insert(ITEM_CACHE_CALLBACKS[itemID], callback)
|
||||
end
|
||||
|
||||
local itemCacheFrame
|
||||
local function EnsureItemCacheFrame()
|
||||
if itemCacheFrame or not CreateFrame then
|
||||
return
|
||||
end
|
||||
|
||||
itemCacheFrame = CreateFrame("Frame")
|
||||
itemCacheFrame:RegisterEvent("GET_ITEM_INFO_RECEIVED")
|
||||
itemCacheFrame:SetScript("OnEvent", function(_, _, itemID)
|
||||
if itemID then
|
||||
FireItemCacheCallbacks(itemID)
|
||||
else
|
||||
for queuedItemID in pairs(ITEM_CACHE_CALLBACKS) do
|
||||
FireItemCacheCallbacks(queuedItemID)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
C_Item.GetItemInfo = function(item, skipClientCache, callback, ...)
|
||||
local name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice
|
||||
if ExistingCItemGetItemInfo then
|
||||
name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice = ExistingCItemGetItemInfo(item, skipClientCache, nil, ...)
|
||||
end
|
||||
if not name then
|
||||
name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice = GetItemInfoCompat(item)
|
||||
end
|
||||
|
||||
if callback then
|
||||
if name then
|
||||
callback(GetItemIDFromAny(item) or item, name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice)
|
||||
else
|
||||
QueueItemCacheCallback(item, callback)
|
||||
EnsureItemCacheFrame()
|
||||
end
|
||||
end
|
||||
return name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice
|
||||
end
|
||||
|
||||
C_Item.RequestServerCache = function(item, callback)
|
||||
local name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice = GetItemInfoCompat(item)
|
||||
if callback then
|
||||
if name then
|
||||
callback(GetItemIDFromAny(item) or item, name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice)
|
||||
elseif ExistingCItemRequestServerCache then
|
||||
return ExistingCItemRequestServerCache(item, callback)
|
||||
else
|
||||
QueueItemCacheCallback(item, callback)
|
||||
EnsureItemCacheFrame()
|
||||
end
|
||||
end
|
||||
return name, link, quality, itemLevel, reqLevel, itemType, itemSubType, maxStack, equipSlot, icon, vendorPrice
|
||||
end
|
||||
C_Item.GetItemIDFromString = function(item)
|
||||
local itemID = ExistingCItemGetItemIDFromString and ExistingCItemGetItemIDFromString(item)
|
||||
if itemID then
|
||||
return itemID
|
||||
end
|
||||
|
||||
EnsureItemsCache()
|
||||
return GetItemIDFromAny(item)
|
||||
end
|
||||
|
||||
EnsureItemsCache()
|
||||
|
||||
if not Mixin then
|
||||
function Mixin(object, ...)
|
||||
for i = 1, select("#", ...) do
|
||||
local mixin = select(i, ...)
|
||||
for key, value in pairs(mixin) do
|
||||
object[key] = value
|
||||
end
|
||||
end
|
||||
return object
|
||||
end
|
||||
end
|
||||
|
||||
if not CreateFromMixins then
|
||||
function CreateFromMixins(...)
|
||||
return Mixin({}, ...)
|
||||
end
|
||||
end
|
||||
|
||||
if not CreateAndInitFromMixin then
|
||||
function CreateAndInitFromMixin(mixin, ...)
|
||||
local object = CreateFromMixins(mixin)
|
||||
object:Init(...)
|
||||
return object
|
||||
end
|
||||
end
|
||||
|
||||
if not InlineHyperlinkFrame_SimpleHTMLAsFontString_OnLoad then
|
||||
function InlineHyperlinkFrame_SimpleHTMLAsFontString_OnLoad(self)
|
||||
if PKBT_SimpleHTMLAsFontStringMixin then
|
||||
Mixin(self, PKBT_SimpleHTMLAsFontStringMixin)
|
||||
if self.OnLoadSimpleHTMLAsFontString then
|
||||
self:OnLoadSimpleHTMLAsFontString()
|
||||
end
|
||||
elseif self.GetRegions and not self:GetRegions() then
|
||||
local meta = getmetatable(self)
|
||||
local methods = meta and meta.__index
|
||||
if methods and methods.SetText then
|
||||
methods.SetText(self, "")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function InstallTextureAtlasShim()
|
||||
if not CreateFrame then
|
||||
return
|
||||
end
|
||||
|
||||
local texture = CreateFrame("Frame"):CreateTexture(nil, "ARTWORK")
|
||||
local meta = getmetatable(texture)
|
||||
local methods = meta and meta.__index
|
||||
|
||||
local atlasToTexture = {
|
||||
["adventureguide-pane-large"] = {335, 337, 0.001953, 0.656250, 0.320312, 0.978516, "Interface\\EncounterJournal\\AdventureGuide"},
|
||||
["adventureguide-pane-small"] = {344, 161, 0.001953, 0.673828, 0.001953, 0.316406, "Interface\\EncounterJournal\\AdventureGuide"},
|
||||
["adventureguide-ring"] = {94, 95, 0.775391, 0.958984, 0.001953, 0.187500, "Interface\\EncounterJournal\\AdventureGuide"},
|
||||
["adventureguide-rewardring"] = {48, 48, 0.677734, 0.771484, 0.001953, 0.095703, "Interface\\EncounterJournal\\AdventureGuide"},
|
||||
["adventureguide-redx"] = {35, 34, 0.677734, 0.746094, 0.175781, 0.242188, "Interface\\EncounterJournal\\AdventureGuide"},
|
||||
|
||||
["UI-EJ-Classic"] = {786, 425, 0.000977, 0.768555, 0.417969, 0.833008, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds1"},
|
||||
["UI-EJ-BurningCrusade"] = {786, 425, 0.000977, 0.768555, 0.000977, 0.416016, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds1"},
|
||||
["UI-EJ-WrathoftheLichKing"] = {786, 425, 0.000977, 0.768555, 0.417969, 0.833008, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds2"},
|
||||
["UI-EJ-Cataclysm"] = {786, 425, 0.000977, 0.768555, 0.000977, 0.416016, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds2"},
|
||||
["UI-EJ-MistsofPandaria"] = {786, 425, 0.000977, 0.768555, 0.000977, 0.416016, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds3"},
|
||||
["UI-EJ-WarlordsofDraenor"] = {786, 425, 0.000977, 0.768555, 0.417969, 0.833008, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds3"},
|
||||
["UI-EJ-BattleforAzeroth"] = {786, 425, 0.000977, 0.768555, 0.000977, 0.416016, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds4"},
|
||||
["UI-EJ-Legion"] = {786, 425, 0.000977, 0.768555, 0.417969, 0.833008, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds4"},
|
||||
["UI-EJ-Dragonflight"] = {786, 425, 0.000977, 0.768555, 0.000977, 0.416016, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds5"},
|
||||
["UI-EJ-Shadowlands"] = {786, 425, 0.000977, 0.768555, 0.417969, 0.833008, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds5"},
|
||||
["UI-EJ-TheWarWithin"] = {786, 425, 0.000977, 0.768555, 0.000977, 0.416016, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds6"},
|
||||
["UI-EJ-Midnight"] = {786, 425, 0.000977, 0.768555, 0.417969, 0.833008, "Interface\\EncounterJournal\\DungeonJournalTierBackgrounds6"},
|
||||
}
|
||||
|
||||
if type(methods) == "table" and not methods.SetAtlas then
|
||||
methods.SetAtlas = function(self, atlas, useAtlasSize)
|
||||
local atlasInfo = atlasToTexture[atlas]
|
||||
if atlasInfo then
|
||||
self:SetTexture(atlasInfo[7])
|
||||
self:SetTexCoord(atlasInfo[3], atlasInfo[4], atlasInfo[5], atlasInfo[6])
|
||||
if useAtlasSize then
|
||||
self:SetSize(atlasInfo[1], atlasInfo[2])
|
||||
end
|
||||
elseif SetAtlasTexture then
|
||||
local ok = pcall(SetAtlasTexture, self, atlas)
|
||||
if not ok then
|
||||
self:SetTexture(nil)
|
||||
end
|
||||
else
|
||||
self:SetTexture(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
InstallTextureAtlasShim()
|
||||
|
||||
local function InstallFrameMethodShims()
|
||||
if not CreateFrame then
|
||||
return
|
||||
end
|
||||
|
||||
local frame = CreateFrame("Frame")
|
||||
local meta = getmetatable(frame)
|
||||
local methods = meta and meta.__index
|
||||
if type(methods) ~= "table" or methods.SetParentArray then
|
||||
return
|
||||
end
|
||||
|
||||
methods.SetParentArray = function(self, arrayName)
|
||||
local parent = self:GetParent()
|
||||
if not parent or not arrayName then
|
||||
return
|
||||
end
|
||||
|
||||
parent[arrayName] = parent[arrayName] or {}
|
||||
table.insert(parent[arrayName], self)
|
||||
end
|
||||
end
|
||||
|
||||
InstallFrameMethodShims()
|
||||
|
||||
if not EncounterJournal_SetSearchPreviewSelection then
|
||||
function EncounterJournal_SetSearchPreviewSelection(selectedIndex)
|
||||
if not EncounterJournal or not EncounterJournal.searchBox then
|
||||
return
|
||||
end
|
||||
|
||||
local searchBox = EncounterJournal.searchBox
|
||||
searchBox.selectedIndex = selectedIndex or 1
|
||||
|
||||
if searchBox.searchPreview then
|
||||
for index, button in ipairs(searchBox.searchPreview) do
|
||||
if button.selectedTexture then
|
||||
if index == searchBox.selectedIndex then
|
||||
button.selectedTexture:Show()
|
||||
else
|
||||
button.selectedTexture:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if searchBox.showAllResults and searchBox.showAllResults.selectedTexture then
|
||||
searchBox.showAllResults.selectedTexture:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
-- Optional AIO bridge: lets the server push fresh Encounter Journal data at runtime.
|
||||
-- The static fallback is loaded from Generated_EncounterJournal.lua, so the journal works
|
||||
-- without ever calling ApplyEncounterJournalData.
|
||||
|
||||
local function ApplyEncounterJournalData(data)
|
||||
if type(data) ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
JOURNALINSTANCE = data.JOURNALINSTANCE or data.instances or JOURNALINSTANCE
|
||||
JOURNALENCOUNTER = data.JOURNALENCOUNTER or data.encounters or JOURNALENCOUNTER
|
||||
JOURNALENCOUNTERCREATURE = data.JOURNALENCOUNTERCREATURE or data.creatures or JOURNALENCOUNTERCREATURE
|
||||
JOURNALENCOUNTERITEM = data.JOURNALENCOUNTERITEM or data.items or JOURNALENCOUNTERITEM
|
||||
JOURNALENCOUNTERSECTION = data.JOURNALENCOUNTERSECTION or data.sections or JOURNALENCOUNTERSECTION
|
||||
JOURNALTIER = data.JOURNALTIER or data.tiers or JOURNALTIER
|
||||
JOURNALTIERXINSTANCE = data.JOURNALTIERXINSTANCE or data.tierInstances or JOURNALTIERXINSTANCE
|
||||
JOURNAACTUALRAIDS = data.JOURNAACTUALRAIDS or data.actualRaids or JOURNAACTUALRAIDS
|
||||
|
||||
if C_EncounterJournal and C_EncounterJournal.ReloadData then
|
||||
C_EncounterJournal.ReloadData()
|
||||
end
|
||||
end
|
||||
|
||||
MoonWell_ApplyEncounterJournalData = ApplyEncounterJournalData
|
||||
|
||||
if AIO then
|
||||
local Handler = AIO.AddHandlers("MoonWellEncounterJournal", {})
|
||||
|
||||
function Handler.SetData(_, data)
|
||||
ApplyEncounterJournalData(data)
|
||||
end
|
||||
end
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
-- Hide the Sirus Encounter Journal panels we don't ship: suggested content,
|
||||
-- LootJournal/ItemBrowser, search box, retail-era top tabs. Dungeons + Raids stay.
|
||||
-- The shipped Sirus tab layout assumes all four content tabs are visible; this
|
||||
-- skin repositions the two tabs we keep.
|
||||
|
||||
local function HideFrame(frame)
|
||||
if frame then
|
||||
frame:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local function HideTabKeepEnabled(tab)
|
||||
if not tab then
|
||||
return
|
||||
end
|
||||
tab:Hide()
|
||||
-- Keep the tab enabled so Sirus EJ_OnShow does not fall back to the
|
||||
-- suggest-tier code path (EJSuggestTab_GetPlayerTierIndex etc).
|
||||
end
|
||||
|
||||
local function ConfigureTierTab(tab, text)
|
||||
if not tab then
|
||||
return
|
||||
end
|
||||
|
||||
tab:SetText(text or "")
|
||||
|
||||
if tab.SetNormalFontObject and GameFontNormal then
|
||||
tab:SetNormalFontObject(GameFontNormal)
|
||||
end
|
||||
if tab.SetHighlightFontObject and GameFontHighlight then
|
||||
tab:SetHighlightFontObject(GameFontHighlight)
|
||||
end
|
||||
if tab.SetDisabledFontObject and GameFontNormal then
|
||||
tab:SetDisabledFontObject(GameFontNormal)
|
||||
end
|
||||
|
||||
local fontString = tab:GetFontString()
|
||||
if fontString then
|
||||
fontString:SetText(text or "")
|
||||
fontString:ClearAllPoints()
|
||||
fontString:SetPoint("CENTER", tab, "CENTER", 0, -3)
|
||||
if fontString.SetDrawLayer then
|
||||
fontString:SetDrawLayer("OVERLAY", 7)
|
||||
end
|
||||
end
|
||||
|
||||
tab:SetWidth(math.max((tab:GetTextWidth() or 0) + 28, 92))
|
||||
end
|
||||
|
||||
local function PositionVisibleTierTabs(instanceSelect)
|
||||
local dungeonsTab = instanceSelect and instanceSelect.dungeonsTab
|
||||
local raidsTab = instanceSelect and instanceSelect.raidsTab
|
||||
if not dungeonsTab or not raidsTab then
|
||||
return
|
||||
end
|
||||
|
||||
ConfigureTierTab(dungeonsTab, INSTANCES or "Instances")
|
||||
ConfigureTierTab(raidsTab, RAIDS or "Raids")
|
||||
|
||||
dungeonsTab:ClearAllPoints()
|
||||
dungeonsTab:SetPoint("BOTTOMLEFT", instanceSelect, "TOPLEFT", 150, -45)
|
||||
|
||||
raidsTab:ClearAllPoints()
|
||||
raidsTab:SetPoint("BOTTOMLEFT", dungeonsTab, "BOTTOMRIGHT", 22, 0)
|
||||
end
|
||||
|
||||
local function GetVisibleSelectedTabID(instanceSelect)
|
||||
if not instanceSelect then
|
||||
return
|
||||
end
|
||||
|
||||
local selectedTab = instanceSelect.selectedTab
|
||||
local dungeonsTab = instanceSelect.dungeonsTab
|
||||
local raidsTab = instanceSelect.raidsTab
|
||||
|
||||
if raidsTab and selectedTab == raidsTab.id then
|
||||
return selectedTab
|
||||
end
|
||||
|
||||
if dungeonsTab then
|
||||
dungeonsTab.id = dungeonsTab.id or dungeonsTab:GetID()
|
||||
return dungeonsTab.id
|
||||
end
|
||||
end
|
||||
|
||||
local function SelectVisibleInstanceTab(journal)
|
||||
local instanceSelect = journal and journal.instanceSelect
|
||||
if not instanceSelect then
|
||||
return
|
||||
end
|
||||
|
||||
local selectedTab = GetVisibleSelectedTabID(instanceSelect)
|
||||
if selectedTab then
|
||||
instanceSelect.selectedTab = selectedTab
|
||||
end
|
||||
|
||||
if journal:IsShown()
|
||||
and instanceSelect:IsShown()
|
||||
and (not journal.encounter or not journal.encounter:IsShown())
|
||||
and selectedTab
|
||||
and EJ_ContentTab_Select
|
||||
then
|
||||
EJ_ContentTab_Select(selectedTab)
|
||||
end
|
||||
end
|
||||
|
||||
local function ApplyDungeonAndRaidOnlySkin()
|
||||
local journal = EncounterJournal
|
||||
if not journal then
|
||||
return
|
||||
end
|
||||
|
||||
-- Sirus EJ_OnLoad sets numTabs at the very end; if anything earlier in
|
||||
-- OnLoad bails out, PanelTemplates_UpdateTabs blows up later with a nil
|
||||
-- for-limit when OnShow calls PanelTemplates_SetTab. Guard it.
|
||||
if journal.numTabs == nil then
|
||||
journal.numTabs = 4
|
||||
end
|
||||
|
||||
HideFrame(journal.searchBox)
|
||||
HideFrame(journal.searchResults)
|
||||
HideFrame(journal.suggestFrame)
|
||||
HideFrame(journal.LootJournal)
|
||||
HideFrame(journal.LootJournalItems)
|
||||
HideFrame(journal.TutorialButton)
|
||||
|
||||
for index = 1, 4 do
|
||||
HideFrame(_G["EncounterJournalTab" .. index])
|
||||
end
|
||||
|
||||
local instanceSelect = journal.instanceSelect
|
||||
if instanceSelect then
|
||||
HideTabKeepEnabled(instanceSelect.suggestTab)
|
||||
HideTabKeepEnabled(instanceSelect.LootJournalTab)
|
||||
|
||||
-- Sirus EJ_OnShow forwards instanceSelect.selectedTab into
|
||||
-- EJ_ContentTab_Select; if it's nil the tab loop matches nothing and
|
||||
-- selectedTab.selectedGlow blows up. Default to the dungeons tab.
|
||||
local dungeonsTab = instanceSelect.dungeonsTab
|
||||
if dungeonsTab then
|
||||
dungeonsTab.id = dungeonsTab.id or dungeonsTab:GetID()
|
||||
end
|
||||
|
||||
PositionVisibleTierTabs(instanceSelect)
|
||||
SelectVisibleInstanceTab(journal)
|
||||
end
|
||||
end
|
||||
|
||||
MoonWell_EncounterJournalApplyDungeonMode = ApplyDungeonAndRaidOnlySkin
|
||||
|
||||
if EncounterJournal then
|
||||
ApplyDungeonAndRaidOnlySkin()
|
||||
EncounterJournal:HookScript("OnShow", ApplyDungeonAndRaidOnlySkin)
|
||||
end
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Font name="QuestFont_Super_Huge" font="Fonts\MORPHEUS.ttf" virtual="true">
|
||||
<FontHeight val="24"/>
|
||||
<Color r="1" g=".82" b="0"/>
|
||||
</Font>
|
||||
<Font name="QuestFont_Super_Huge2" font="Fonts\MORPHEUS.ttf" virtual="true">
|
||||
<FontHeight val="26"/>
|
||||
<Shadow>
|
||||
<Offset x="2" y="-2"/>
|
||||
<Color r="0" g="0" b="0"/>
|
||||
</Shadow>
|
||||
</Font>
|
||||
<Font name="GameFontNormalMed1" inherits="GameFontNormal" virtual="true">
|
||||
<FontHeight val="12"/>
|
||||
<Shadow>
|
||||
<Offset x="1" y="-1"/>
|
||||
<Color r="0" g="0" b="0"/>
|
||||
</Shadow>
|
||||
<Color r="1" g=".82" b="0"/>
|
||||
</Font>
|
||||
<Font name="QuestFont22" font="Fonts\MORPHEUS.ttf" virtual="true">
|
||||
<FontHeight val="22"/>
|
||||
<Color r="1" g=".82" b="0"/>
|
||||
</Font>
|
||||
<Font name="QuestFont_Enormous" font="Fonts\MORPHEUS.ttf" virtual="true">
|
||||
<FontHeight val="30"/>
|
||||
<Color r="1" g=".82" b="0"/>
|
||||
</Font>
|
||||
<Font name="DestinyFontHuge" font="Fonts\MORPHEUS.ttf" virtual="true">
|
||||
<FontHeight val="32"/>
|
||||
<Color r="1" g=".82" b="0"/>
|
||||
</Font>
|
||||
</Ui>
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
-- Minimal Frame metatable extensions used by Sirus EJ. Replaces Sirus
|
||||
-- SharedExtendedMethods.lua, which clobbers SetUnit/PlayerModel methods with
|
||||
-- retail-only API (ResetAllSpells, SetSpell, SetUnitRaw, GetDisplayIDs,
|
||||
-- C_CustomizationsCollection.*) and breaks TabardFrame/DressUpFrame on 3.3.5.
|
||||
|
||||
local function getMeta(objType)
|
||||
local frame = CreateFrame(objType)
|
||||
frame:Hide()
|
||||
return getmetatable(frame).__index
|
||||
end
|
||||
|
||||
local function RegisterCustomEventNoop() end
|
||||
local function UnregisterCustomEventNoop() end
|
||||
|
||||
local function SetShown(self, shown)
|
||||
if shown then
|
||||
self:Show()
|
||||
else
|
||||
self:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local function SetParentArray(self, arrayName)
|
||||
local parent = self:GetParent()
|
||||
if not parent or not arrayName then
|
||||
return
|
||||
end
|
||||
parent[arrayName] = parent[arrayName] or {}
|
||||
table.insert(parent[arrayName], self)
|
||||
end
|
||||
|
||||
local function SetEnabled(self, enabled)
|
||||
if enabled then
|
||||
self:Enable()
|
||||
else
|
||||
self:Disable()
|
||||
end
|
||||
end
|
||||
|
||||
-- Sirus EJ calls Frame/Button:IsMouseOverEx() (Cataclysm+ retail-only).
|
||||
-- Map to the 3.3.5 IsMouseOver().
|
||||
local function IsMouseOverEx(self)
|
||||
return self:IsMouseOver()
|
||||
end
|
||||
|
||||
local metas = {
|
||||
getMeta("Frame"),
|
||||
getMeta("Button"),
|
||||
getMeta("CheckButton"),
|
||||
getMeta("EditBox"),
|
||||
getMeta("Slider"),
|
||||
getMeta("StatusBar"),
|
||||
getMeta("ScrollFrame"),
|
||||
getMeta("MessageFrame"),
|
||||
getMeta("ScrollingMessageFrame"),
|
||||
}
|
||||
|
||||
for _, meta in ipairs(metas) do
|
||||
if type(meta) == "table" then
|
||||
if not meta.RegisterCustomEvent then
|
||||
meta.RegisterCustomEvent = RegisterCustomEventNoop
|
||||
end
|
||||
if not meta.UnregisterCustomEvent then
|
||||
meta.UnregisterCustomEvent = UnregisterCustomEventNoop
|
||||
end
|
||||
if not meta.SetShown then
|
||||
meta.SetShown = SetShown
|
||||
end
|
||||
if not meta.SetParentArray then
|
||||
meta.SetParentArray = SetParentArray
|
||||
end
|
||||
if not meta.SetEnabled then
|
||||
meta.SetEnabled = SetEnabled
|
||||
end
|
||||
if not meta.IsMouseOverEx then
|
||||
meta.IsMouseOverEx = IsMouseOverEx
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Sirus EJ calls FontString:IsTruncated() (Cataclysm+) to detect overflow for
|
||||
-- header tooltips. Always return false on 3.3.5 — we just don't show the
|
||||
-- "expand" tooltip.
|
||||
do
|
||||
local frame = CreateFrame("Frame")
|
||||
local fs = frame:CreateFontString()
|
||||
local meta = getmetatable(fs)
|
||||
local methods = meta and meta.__index
|
||||
if type(methods) == "table" and not methods.IsTruncated then
|
||||
methods.IsTruncated = function() return false end
|
||||
end
|
||||
end
|
||||
|
||||
-- Sirus EJ description fields are SimpleHTML frames; the EJ logic does
|
||||
-- `self.description:GetText()` (Cataclysm+ on SimpleHTML). 3.3.5 SimpleHTML
|
||||
-- only has SetText, no GetText. Hook SetText to remember the last text and
|
||||
-- expose GetText that returns it.
|
||||
do
|
||||
local ok, simple = pcall(CreateFrame, "SimpleHTML")
|
||||
if ok and simple then
|
||||
local meta = getmetatable(simple)
|
||||
local methods = meta and meta.__index
|
||||
if type(methods) == "table" then
|
||||
local origSetText = methods.SetText
|
||||
if origSetText and not methods.GetText then
|
||||
methods.SetText = function(self, text, ...)
|
||||
self.__moonwellText = text
|
||||
return origSetText(self, text, ...)
|
||||
end
|
||||
methods.GetText = function(self)
|
||||
return self.__moonwellText
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Sirus EJ calls Texture:SetPortrait(displayID) for boss/creature portraits.
|
||||
-- 3.3.5 has no SetPortraitTextureFromCreatureDisplayID equivalent, so leave
|
||||
-- the texture blank — the static UI-EJ-BOSS-* icon set elsewhere is enough.
|
||||
do
|
||||
local frame = CreateFrame("Frame")
|
||||
local texture = frame:CreateTexture()
|
||||
local meta = getmetatable(texture)
|
||||
local methods = meta and meta.__index
|
||||
if type(methods) == "table" and not methods.SetPortrait then
|
||||
methods.SetPortrait = function(self)
|
||||
self:SetTexture(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
-- Force C_EncounterJournal to copy the freshly loaded JOURNAL* globals into its
|
||||
-- internal locals. Without this the EJ data API returns nil and the instance
|
||||
-- list comes up empty.
|
||||
|
||||
if C_EncounterJournal and C_EncounterJournal.ReloadData then
|
||||
C_EncounterJournal.ReloadData()
|
||||
end
|
||||
|
||||
-- EJ_GetLootFilter returns nil until a class filter is set; Sirus
|
||||
-- EncounterJournal_UpdateFilterString does `if classID > 0 then`, which blows
|
||||
-- up when classID is nil. Coerce to 0.
|
||||
if EJ_GetLootFilter then
|
||||
local _GetLootFilter = EJ_GetLootFilter
|
||||
function EJ_GetLootFilter()
|
||||
return _GetLootFilter() or 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Sirus C_AdventureJournal sometimes fails to fully initialize on 3.3.5
|
||||
-- because PRIVATE.Initialize() inside Utils/C_AdventureJournal.lua hits an
|
||||
-- unsupported API mid-way and aborts before `C_AdventureJournal = {}` is
|
||||
-- reached. Provide a no-op stub so suggestFrame OnShow doesn't blow up.
|
||||
C_AdventureJournal = C_AdventureJournal or {}
|
||||
local function noop() end
|
||||
C_AdventureJournal.UpdateSuggestions = C_AdventureJournal.UpdateSuggestions or noop
|
||||
C_AdventureJournal.GetPrimaryOffset = C_AdventureJournal.GetPrimaryOffset or function() return 0 end
|
||||
C_AdventureJournal.SetPrimaryOffset = C_AdventureJournal.SetPrimaryOffset or noop
|
||||
C_AdventureJournal.GetNumAvailableSuggestions = C_AdventureJournal.GetNumAvailableSuggestions or function() return 0 end
|
||||
C_AdventureJournal.GetSuggestion = C_AdventureJournal.GetSuggestion or function() end
|
||||
C_AdventureJournal.CanBeShown = C_AdventureJournal.CanBeShown or function() return true end
|
||||
C_AdventureJournal.ReloadData = C_AdventureJournal.ReloadData or noop
|
||||
C_AdventureJournal.ActivateEntry = C_AdventureJournal.ActivateEntry or noop
|
||||
C_AdventureJournal.GetSuggestions = C_AdventureJournal.GetSuggestions or function(out)
|
||||
if type(out) == "table" then
|
||||
for k in pairs(out) do out[k] = nil end
|
||||
end
|
||||
return out or {}
|
||||
end
|
||||
C_AdventureJournal.GetReward = C_AdventureJournal.GetReward or function() end
|
||||
C_AdventureJournal.GetPrimaryReward = C_AdventureJournal.GetPrimaryReward or function() end
|
||||
C_AdventureJournal.GetSecondaryReward = C_AdventureJournal.GetSecondaryReward or function() end
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
-- Explicit entry point for 3.3.5 clients, which do not have the retail
|
||||
-- EncounterJournal micro button.
|
||||
|
||||
local function MoonWell_ToggleEncounterJournal()
|
||||
if not EncounterJournal then
|
||||
return
|
||||
end
|
||||
|
||||
if EncounterJournal:IsShown() then
|
||||
HideUIPanel(EncounterJournal)
|
||||
return
|
||||
end
|
||||
|
||||
if MoonWell_EncounterJournalApplyDungeonMode then
|
||||
MoonWell_EncounterJournalApplyDungeonMode()
|
||||
end
|
||||
|
||||
if EncounterJournal_OpenJournal then
|
||||
EncounterJournal_OpenJournal()
|
||||
else
|
||||
ShowUIPanel(EncounterJournal)
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_MOONWELLENCOUNTERJOURNAL1 = "/ej"
|
||||
SLASH_MOONWELLENCOUNTERJOURNAL2 = "/journal"
|
||||
SLASH_MOONWELLENCOUNTERJOURNAL3 = "/encounterjournal"
|
||||
SlashCmdList.MOONWELLENCOUNTERJOURNAL = MoonWell_ToggleEncounterJournal
|
||||
|
||||
MoonWell_ToggleEncounterJournal = MoonWell_ToggleEncounterJournal
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<!--
|
||||
Sirus EncounterJournalScrollBarTemplate inherits MinimalScrollBarTemplate
|
||||
and references self.trackBG inside its inline OnLoad. On 3.3.5 the
|
||||
parentKey="trackBG" attribute on the inherited template does not
|
||||
propagate, leaving self.trackBG nil and crashing OnLoad. Define the
|
||||
template here ourselves with trackBG as a direct child texture, before
|
||||
Sirus Custom_EncounterJournal.xml gets a chance to register its own.
|
||||
-->
|
||||
<Slider name="EncounterJournalScrollBarTemplate" inherits="MinimalScrollBarTemplate" parentKey="ScrollBar" virtual="true">
|
||||
<Anchors>
|
||||
<Anchor point="TOPRIGHT" x="0" y="-17"/>
|
||||
<Anchor point="BOTTOMRIGHT" x="0" y="17"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="ARTWORK">
|
||||
<Texture parentKey="trackBG" setAllPoints="true">
|
||||
<Color r="0.2" g="0.13" b="0.08" a="0.25"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
</Slider>
|
||||
</Ui>
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
-- Sirus EJ XML for lootScroll/searchResults.scrollFrame omits the scrollUp /
|
||||
-- scrollDown buttons that the stock 3.3.5 HybridScrollFrame implementation
|
||||
-- requires (HybridScrollFrame_Update / HybridScrollFrame_UpdateButtonStates
|
||||
-- index them directly). Wire up no-op buttons so the stock helpers don't
|
||||
-- index nil and the rest of the EJ flow works.
|
||||
|
||||
local function AttachFakeScrollButtons(scrollFrame)
|
||||
if not scrollFrame then
|
||||
return
|
||||
end
|
||||
if not scrollFrame.scrollUp then
|
||||
local btn = CreateFrame("Button", nil, scrollFrame)
|
||||
btn:Hide()
|
||||
btn:SetSize(1, 1)
|
||||
btn:SetPoint("TOPLEFT")
|
||||
scrollFrame.scrollUp = btn
|
||||
end
|
||||
if not scrollFrame.scrollDown then
|
||||
local btn = CreateFrame("Button", nil, scrollFrame)
|
||||
btn:Hide()
|
||||
btn:SetSize(1, 1)
|
||||
btn:SetPoint("BOTTOMLEFT")
|
||||
scrollFrame.scrollDown = btn
|
||||
end
|
||||
if scrollFrame.scrollBar and not scrollFrame.scrollBar.thumbTexture then
|
||||
scrollFrame.scrollBar.thumbTexture = scrollFrame.scrollBar:GetThumbTexture()
|
||||
or scrollFrame.scrollBar:CreateTexture(nil, "ARTWORK")
|
||||
end
|
||||
if scrollFrame.scrollBar and not scrollFrame.scrollBar.trackBG then
|
||||
scrollFrame.scrollBar.trackBG = scrollFrame.scrollBar:CreateTexture(nil, "BACKGROUND")
|
||||
end
|
||||
end
|
||||
|
||||
if EncounterJournal then
|
||||
AttachFakeScrollButtons(EncounterJournal.encounter
|
||||
and EncounterJournal.encounter.info
|
||||
and EncounterJournal.encounter.info.lootScroll)
|
||||
AttachFakeScrollButtons(EncounterJournal.searchResults
|
||||
and EncounterJournal.searchResults.scrollFrame)
|
||||
end
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
-- Restrict Sirus EJ data tables to expansions that exist on 3.3.5a (Classic, TBC, WotLK).
|
||||
-- Must run AFTER Generated_EncounterJournal.lua (where the globals are populated) and BEFORE
|
||||
-- Utils/C_EncounterJournal.lua reads them into locals on first ReloadData.
|
||||
|
||||
local ALLOWED_TIER_IDS = {
|
||||
[68] = true, -- Classic
|
||||
[70] = true, -- Burning Crusade
|
||||
[72] = true, -- Wrath of the Lich King
|
||||
}
|
||||
|
||||
local TIER_FIELD_ID = 1
|
||||
|
||||
if type(JOURNALTIER) == "table" then
|
||||
local filtered = {}
|
||||
for _, tierInfo in ipairs(JOURNALTIER) do
|
||||
if ALLOWED_TIER_IDS[tierInfo[TIER_FIELD_ID]] then
|
||||
filtered[#filtered + 1] = tierInfo
|
||||
end
|
||||
end
|
||||
JOURNALTIER = filtered
|
||||
end
|
||||
|
||||
if type(JOURNALTIERXINSTANCE) == "table" then
|
||||
for instanceID, tierList in pairs(JOURNALTIERXINSTANCE) do
|
||||
local kept
|
||||
for _, tierID in ipairs(tierList) do
|
||||
if ALLOWED_TIER_IDS[tierID] then
|
||||
kept = kept or {}
|
||||
kept[#kept + 1] = tierID
|
||||
end
|
||||
end
|
||||
if kept then
|
||||
JOURNALTIERXINSTANCE[instanceID] = kept
|
||||
else
|
||||
JOURNALTIERXINSTANCE[instanceID] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
-- Keep tier tables available for the 3.3.5a dungeon-list shim.
|
||||
-- C_EncounterJournal imports Sirus globals into locals and clears the globals.
|
||||
|
||||
MoonWell_EncounterJournalTiers = CopyTable(JOURNALTIER or {})
|
||||
MoonWell_EncounterJournalTierInstances = CopyTable(JOURNALTIERXINSTANCE or {})
|
||||
|
||||
+24958
File diff suppressed because it is too large
Load Diff
+38
@@ -0,0 +1,38 @@
|
||||
ADVENTURE_JOURNAL = "Путеводитель по приключениям"
|
||||
AJ_ACTION_TEXT_JOIN_BATTLE = "Вступить в бой"
|
||||
AJ_ACTION_TEXT_JOIN_GROUP = "Вступить в группу"
|
||||
AJ_ACTION_TEXT_OPEN_EJ = "Открыть журнал"
|
||||
AJ_ACTION_TEXT_SHOW_QUEST = "Открыть задания"
|
||||
AJ_ACTION_TEXT_START_HUNT = "Открыть охоту"
|
||||
AJ_ACTION_TEXT_START_QUEST = "Начать задание"
|
||||
AJ_LFG_REWARD_DEFAULT_IRANGE_TEXT = "%s: здесь можно получить предметы экипировки %i - %i уровней."
|
||||
AJ_LFG_REWARD_DEFAULT_TEXT = "%s: здесь можно получить предметы экипировки %i-го уровня."
|
||||
AJ_LFG_REWARD_DIFFICULTY_IRANGE_TEXT = "%s (%s): здесь можно получить предметы экипировки %i - %i уровней."
|
||||
AJ_LFG_REWARD_DIFFICULTY_TEXT = "%s (%s): здесь можно получить предметы экипировки %i-го уровня."
|
||||
AJ_PRIMARY_REWARD_TEXT = "Награда:"
|
||||
AJ_REWARD_CLICK_TEXT = "Щелкните для просмотра всех наград."
|
||||
AJ_SAMPLE_REWARD_TEXT = "\n\nПример награды:"
|
||||
AJ_SUGGESTED_CONTENT_TAB = "Рекомендуемый контент"
|
||||
EJ_CLASS_FILTER = "Фильтр по классу: %s"
|
||||
EJ_FILTER_ALL_CLASS = "Все классы"
|
||||
EJ_INSTANCE_REQUIREMENT_ACHIEVEMENTS = "Достижения:"
|
||||
EJ_INSTANCE_REQUIREMENT_DIFFICULTY = "Сложность: %s"
|
||||
EJ_INSTANCE_REQUIREMENT_ITEM_LEVEL = "Средний уровень предметов: %s"
|
||||
EJ_INSTANCE_REQUIREMENT_LABLE = "Требования:"
|
||||
EJ_INSTANCE_REQUIREMENT_LEVEL = "Уровень: %s"
|
||||
EJ_INSTANCE_REQUIREMENT_LEVEL_RANGE = "Уровень: %s-%s"
|
||||
EJ_INSTANCE_REQUIREMENT_NONE = "Вход свободный"
|
||||
EJ_INSTANCE_REQUIREMENT_QUESTS = "Задания:"
|
||||
EJ_INSTANCE_REQUIREMENT_RAID_GROUP = "Для входа требуется быть участником рейдовой группы"
|
||||
EJ_SET_ITEM_LEVEL = "|cffcc4040[%s]|r Уровень предмета: %d"
|
||||
ENCOUNTER_JOURNAL_ABILITY = "Способность"
|
||||
ENCOUNTER_JOURNAL_ENCOUNTER = "Босс"
|
||||
ENCOUNTER_JOURNAL_ENCOUNTER_ADD = "Помощник"
|
||||
ENCOUNTER_JOURNAL_FIND_GROUP = "Найти\nгруппу"
|
||||
ENCOUNTER_JOURNAL_FIND_RAID = "Найти\nрейд"
|
||||
ENCOUNTER_JOURNAL_INSTANCE = "Подземелье"
|
||||
ENCOUNTER_JOURNAL_ITEM = "Предмет"
|
||||
ENCOUNTER_JOURNAL_SEARCH_RESULTS = "Результаты поиска для \"%s\" (%d)"
|
||||
ENCOUNTER_JOURNAL_SHOW_MAP = "Показать\nкарту"
|
||||
ENCOUNTER_JOURNAL_SHOW_SEARCH_RESULTS = "Показать все результаты: %d"
|
||||
LOOT_JOURNAL_ITEM_SETS = "Комплекты"
|
||||
+45002
File diff suppressed because it is too large
Load Diff
+45002
File diff suppressed because it is too large
Load Diff
+119789
File diff suppressed because it is too large
Load Diff
+128
@@ -0,0 +1,128 @@
|
||||
local securecall = securecall
|
||||
local ipairs = ipairs
|
||||
local next = next
|
||||
local type = type
|
||||
local strsplit = string.split
|
||||
|
||||
local ExecuteFrameScript = ExecuteFrameScript
|
||||
local GetFramesRegisteredForEvent = GetFramesRegisteredForEvent
|
||||
local UnitName = UnitName
|
||||
local UnitTokenFromGUID = UnitTokenFromGUID
|
||||
|
||||
local REGISTERED_CUSTOM_EVENTS = {}
|
||||
local REGISTERED_CUSTOM_EVENTS_ALL
|
||||
|
||||
local function SecureNext(elements, key)
|
||||
return securecall(next, elements, key)
|
||||
end
|
||||
|
||||
function FireClientEvent(event, ...)
|
||||
for _, frame in SecureNext, {GetFramesRegisteredForEvent(event)} do
|
||||
securecall(ExecuteFrameScript, frame, "OnEvent", event, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function FireCustomClientEvent(event, ...)
|
||||
if REGISTERED_CUSTOM_EVENTS[event] then
|
||||
for frame in SecureNext, REGISTERED_CUSTOM_EVENTS[event] do
|
||||
securecall(ExecuteFrameScript, frame, "OnEvent", event, ...)
|
||||
end
|
||||
end
|
||||
if REGISTERED_CUSTOM_EVENTS_ALL then
|
||||
for frame in SecureNext, REGISTERED_CUSTOM_EVENTS_ALL do
|
||||
securecall(ExecuteFrameScript, frame, "OnEvent", event, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local eventRegistrar = CreateFrame("Frame")
|
||||
eventRegistrar:SetScript("OnAttributeChanged", function(this, name, value)
|
||||
if name == "1" then
|
||||
if not REGISTERED_CUSTOM_EVENTS[value] then
|
||||
REGISTERED_CUSTOM_EVENTS[value] = {}
|
||||
end
|
||||
REGISTERED_CUSTOM_EVENTS[value][this:GetAttribute("f")] = true
|
||||
elseif name == "0" then
|
||||
if REGISTERED_CUSTOM_EVENTS[value] then
|
||||
REGISTERED_CUSTOM_EVENTS[value][this:GetAttribute("f")] = nil
|
||||
end
|
||||
elseif name == "2" then
|
||||
REGISTERED_CUSTOM_EVENTS_ALL[value] = true
|
||||
elseif name == "3" then
|
||||
REGISTERED_CUSTOM_EVENTS_ALL[value] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
function RegisterCustomEvent(self, event)
|
||||
eventRegistrar:SetAttribute("f", self)
|
||||
eventRegistrar:SetAttribute("1", event)
|
||||
end
|
||||
|
||||
function UnregisterCustomEvent(self, event)
|
||||
eventRegistrar:SetAttribute("f", self)
|
||||
eventRegistrar:SetAttribute("0", event)
|
||||
end
|
||||
|
||||
function RegisterAllCustomEvents(self)
|
||||
if not REGISTERED_CUSTOM_EVENTS_ALL then
|
||||
REGISTERED_CUSTOM_EVENTS_ALL = {}
|
||||
end
|
||||
eventRegistrar:SetAttribute("2", self)
|
||||
end
|
||||
|
||||
function UnregisterAllCustomEvents(self)
|
||||
if not REGISTERED_CUSTOM_EVENTS_ALL then
|
||||
return
|
||||
end
|
||||
eventRegistrar:SetAttribute("3", self)
|
||||
end
|
||||
|
||||
function FireCustomClientUnitGroupEvent(event, unitGUID, ...)
|
||||
if event and REGISTERED_CUSTOM_EVENTS[event] and unitGUID then
|
||||
local units = {UnitTokenFromGUID(unitGUID)}
|
||||
if #units > 0 then
|
||||
for frame in SecureNext, REGISTERED_CUSTOM_EVENTS[event] do
|
||||
for _, unit in ipairs(units) do
|
||||
securecall(ExecuteFrameScript, frame, "OnEvent", event, unit, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
EventHandler = setmetatable(
|
||||
{
|
||||
events = {}, -- Original events
|
||||
listeners = {}, -- New tables for handling events outside og EventHandler
|
||||
RegisterListener = function(self, listener)
|
||||
self.listeners[listener] = true
|
||||
end,
|
||||
Handle = function(self, opcode, message, unk, sender)
|
||||
if sender == UnitName("player") then
|
||||
for listener in SecureNext, self.listeners do
|
||||
if listener[opcode] then
|
||||
securecall(listener[opcode], listener, message)
|
||||
end
|
||||
end
|
||||
|
||||
if self.events[opcode] then
|
||||
securecall(self.events[opcode], self, message)
|
||||
end
|
||||
end
|
||||
end
|
||||
},
|
||||
{
|
||||
__newindex = function(self, key, value)
|
||||
if type(value) == "function" then
|
||||
self.events[key] = value
|
||||
end
|
||||
rawset(self, key, value)
|
||||
end
|
||||
}
|
||||
)
|
||||
|
||||
local EventHandlerFrame = CreateFrame("Frame")
|
||||
EventHandlerFrame:RegisterEvent("CHAT_MSG_ADDON")
|
||||
EventHandlerFrame:SetScript("OnEvent", function(self, event, opcode, message, unk, sender)
|
||||
EventHandler:Handle(opcode, message, unk, sender)
|
||||
end)
|
||||
+427
@@ -0,0 +1,427 @@
|
||||
--[[-----------------------------------------------------------------------------------------------
|
||||
For a hybrid scroll frame with buttons of varying size, set .dynamic on the scroll frame
|
||||
to be a function which will take the offset and return:
|
||||
1. how many buttons the offset is completely past
|
||||
2. how many pixels the offset is into the topmost button
|
||||
So with buttons of size 20, .dynamic(0) should return 0,0 and .dynamic(34) should return 1,14
|
||||
-----------------------------------------------------------------------------------------------]]--
|
||||
|
||||
local round = function (num) return math.floor(num + .5); end
|
||||
|
||||
local function HybridScrollFrame_SetVerticalScrollOffset(self, offset)
|
||||
if self.SetVerticalScroll then
|
||||
self:SetVerticalScroll(offset);
|
||||
end
|
||||
end
|
||||
|
||||
local function HybridScrollFrame_UpdateScrollChildRectSafe(self)
|
||||
if self.UpdateScrollChildRect then
|
||||
self:UpdateScrollChildRect();
|
||||
end
|
||||
end
|
||||
|
||||
local function HybridScrollFrame_GetScrollFrame(self)
|
||||
if not self then
|
||||
return self;
|
||||
end
|
||||
if self.SetVerticalScroll then
|
||||
return self;
|
||||
end
|
||||
|
||||
local name = self.GetName and self:GetName();
|
||||
local scrollFrame = self.Container or (name and _G[name.."Container"]);
|
||||
return scrollFrame or self;
|
||||
end
|
||||
|
||||
local function HybridScrollFrame_GetScrollBar(self)
|
||||
if self.scrollBar then
|
||||
return self.scrollBar;
|
||||
end
|
||||
|
||||
local name = self.GetName and self:GetName();
|
||||
local scrollBar = self.ScrollBar or (name and (_G[name.."ScrollBar"] or _G[name.."ContainerScrollBar"]));
|
||||
if scrollBar then
|
||||
self.scrollBar = scrollBar;
|
||||
end
|
||||
return scrollBar;
|
||||
end
|
||||
|
||||
function HybridScrollFrame_OnLoad (self)
|
||||
self:EnableMouse(true);
|
||||
end
|
||||
|
||||
function HybridScrollFrameScrollUp_OnLoad (self)
|
||||
self:GetParent():GetParent().scrollUp = self;
|
||||
self:Disable();
|
||||
self:RegisterForClicks("LeftButtonUp", "LeftButtonDown");
|
||||
self.direction = 1;
|
||||
end
|
||||
|
||||
function HybridScrollFrameScrollDown_OnLoad (self)
|
||||
self:GetParent():GetParent().scrollDown = self;
|
||||
self:Disable();
|
||||
self:RegisterForClicks("LeftButtonUp", "LeftButtonDown");
|
||||
self.direction = -1;
|
||||
end
|
||||
|
||||
function HybridScrollFrame_OnValueChanged (self, value)
|
||||
local scrollFrame = self;
|
||||
if self.SetMinMaxValues and self.GetParent then
|
||||
scrollFrame = self:GetParent();
|
||||
end
|
||||
scrollFrame = HybridScrollFrame_GetScrollFrame(scrollFrame);
|
||||
HybridScrollFrame_SetOffset(scrollFrame, value);
|
||||
HybridScrollFrame_UpdateButtonStates(scrollFrame, value);
|
||||
end
|
||||
|
||||
function HybridScrollFrame_UpdateButtonStates (self, currValue)
|
||||
local scrollBar = HybridScrollFrame_GetScrollBar(self);
|
||||
if ( not scrollBar ) then
|
||||
return;
|
||||
end
|
||||
|
||||
local scrollBarName = scrollBar.GetName and scrollBar:GetName();
|
||||
local scrollUp = self.scrollUp or scrollBar.ScrollUpButton or (scrollBarName and _G[scrollBarName.."ScrollUpButton"]);
|
||||
local scrollDown = self.scrollDown or scrollBar.ScrollDownButton or (scrollBarName and _G[scrollBarName.."ScrollDownButton"]);
|
||||
|
||||
if ( not currValue ) then
|
||||
currValue = scrollBar:GetValue();
|
||||
end
|
||||
|
||||
if ( scrollUp ) then
|
||||
scrollUp:Enable();
|
||||
end
|
||||
if ( scrollDown ) then
|
||||
scrollDown:Enable();
|
||||
end
|
||||
|
||||
local minVal, maxVal = scrollBar:GetMinMaxValues();
|
||||
if ( currValue >= maxVal ) then
|
||||
if ( scrollBar.thumbTexture ) then
|
||||
scrollBar.thumbTexture:Show();
|
||||
end
|
||||
if ( scrollDown ) then
|
||||
scrollDown:Disable()
|
||||
end
|
||||
end
|
||||
if ( currValue <= minVal ) then
|
||||
if ( scrollBar.thumbTexture ) then
|
||||
scrollBar.thumbTexture:Show();
|
||||
end
|
||||
if ( scrollUp ) then
|
||||
scrollUp:Disable();
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function HybridScrollFrame_OnMouseWheel (self, delta, stepSize)
|
||||
self = HybridScrollFrame_GetScrollFrame(self);
|
||||
local scrollBar = HybridScrollFrame_GetScrollBar(self);
|
||||
if ( not scrollBar or not scrollBar:IsVisible() ) then
|
||||
return;
|
||||
end
|
||||
local isEnabled = not scrollBar.IsEnabled or scrollBar:IsEnabled();
|
||||
if ( not isEnabled or isEnabled == 0 ) then
|
||||
return;
|
||||
end
|
||||
|
||||
local minVal, maxVal = scrollBar:GetMinMaxValues();
|
||||
minVal = minVal or 0;
|
||||
maxVal = maxVal or self.range or 0;
|
||||
stepSize = stepSize or self.stepSize or self.buttonHeight or 1;
|
||||
if ( delta == 1 ) then
|
||||
scrollBar:SetValue(max(minVal, scrollBar:GetValue() - stepSize));
|
||||
else
|
||||
scrollBar:SetValue(min(maxVal, scrollBar:GetValue() + stepSize));
|
||||
end
|
||||
end
|
||||
|
||||
function HybridScrollFrameScrollButton_OnUpdate (self, elapsed)
|
||||
self.timeSinceLast = self.timeSinceLast + elapsed;
|
||||
if ( self.timeSinceLast >= ( self.updateInterval or 0.08 ) ) then
|
||||
if ( not IsMouseButtonDown("LeftButton") ) then
|
||||
self:SetScript("OnUpdate", nil);
|
||||
elseif ( self:IsMouseOver() ) then
|
||||
local parent = self.parent or self:GetParent():GetParent();
|
||||
HybridScrollFrame_OnMouseWheel (parent, self.direction, (self.stepSize or parent.buttonHeight/3));
|
||||
self.timeSinceLast = 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function HybridScrollFrameScrollButton_OnClick (self, button, down)
|
||||
local parent = self.parent or self:GetParent():GetParent();
|
||||
|
||||
if ( down ) then
|
||||
if IsMouseButtonDown then
|
||||
self.timeSinceLast = (self.timeToStart or -0.2);
|
||||
self:SetScript("OnUpdate", HybridScrollFrameScrollButton_OnUpdate);
|
||||
end
|
||||
HybridScrollFrame_OnMouseWheel (parent, self.direction);
|
||||
PlaySound("UChatScrollButton");
|
||||
else
|
||||
self:SetScript("OnUpdate", nil);
|
||||
end
|
||||
end
|
||||
|
||||
function HybridScrollFrame_SetPercentageHeight(self, percentageHeight)
|
||||
local offset = percentageHeight * (self.totalHeight or 0);
|
||||
HybridScrollFrame_SetOffset(self, offset);
|
||||
end
|
||||
|
||||
function HybridScrollFrame_GetVisiblePercentage(self)
|
||||
local totalHeight = (self.totalHeight or 0);
|
||||
if totalHeight == 0 then
|
||||
return 0;
|
||||
end
|
||||
|
||||
return self.scrollChild:GetHeight() / totalHeight;
|
||||
end
|
||||
|
||||
function HybridScrollFrame_GetScrollPercentage(self)
|
||||
local scrollableHeight = (self.totalHeight or 0) - self.scrollChild:GetHeight();
|
||||
if scrollableHeight == 0 then
|
||||
return 0;
|
||||
end
|
||||
|
||||
return (self.offset or 0) / scrollableHeight;
|
||||
end
|
||||
|
||||
function HybridScrollFrame_Update (self, totalHeight, displayedHeight)
|
||||
local range = floor(totalHeight - self:GetHeight() + 0.5);
|
||||
local scrollBar = HybridScrollFrame_GetScrollBar(self);
|
||||
if ( range > 0 and scrollBar ) then
|
||||
local minVal, maxVal = scrollBar:GetMinMaxValues();
|
||||
if ( math.floor(scrollBar:GetValue()) >= math.floor(maxVal) ) then
|
||||
scrollBar:SetMinMaxValues(0, range);
|
||||
if ( math.floor(scrollBar:GetValue()) ~= math.floor(range) ) then
|
||||
scrollBar:SetValue(range);
|
||||
else
|
||||
HybridScrollFrame_SetOffset(self, range); -- If we've scrolled to the bottom, we need to recalculate the offset.
|
||||
end
|
||||
else
|
||||
scrollBar:SetMinMaxValues(0, range)
|
||||
end
|
||||
scrollBar:Enable();
|
||||
HybridScrollFrame_UpdateButtonStates(self);
|
||||
scrollBar:Show();
|
||||
elseif ( scrollBar ) then
|
||||
scrollBar:SetValue(0);
|
||||
if ( scrollBar.doNotHide ) then
|
||||
scrollBar:Disable();
|
||||
if ( self.scrollUp ) then
|
||||
self.scrollUp:Disable();
|
||||
end
|
||||
if ( self.scrollDown ) then
|
||||
self.scrollDown:Disable();
|
||||
end
|
||||
if ( scrollBar.thumbTexture ) then
|
||||
scrollBar.thumbTexture:Hide();
|
||||
end
|
||||
else
|
||||
scrollBar:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
self.range = range;
|
||||
self.totalHeight = totalHeight;
|
||||
self.scrollChild:SetHeight(displayedHeight);
|
||||
HybridScrollFrame_UpdateScrollChildRectSafe(self);
|
||||
end
|
||||
|
||||
function HybridScrollFrame_GetOffset (self)
|
||||
return math.floor(self.offset or 0), (self.offset or 0);
|
||||
end
|
||||
|
||||
function HybridScrollFrameScrollChild_OnLoad (self)
|
||||
self:GetParent().scrollChild = self;
|
||||
end
|
||||
|
||||
function HybridScrollFrame_ExpandButton (self, offset, height)
|
||||
self.largeButtonTop = round(offset);
|
||||
self.largeButtonHeight = round(height)
|
||||
local scrollBar = HybridScrollFrame_GetScrollBar(self);
|
||||
HybridScrollFrame_SetOffset(self, scrollBar and scrollBar:GetValue() or 0);
|
||||
end
|
||||
|
||||
function HybridScrollFrame_CollapseButton (self)
|
||||
self.largeButtonTop = nil;
|
||||
self.largeButtonHeight = nil;
|
||||
end
|
||||
|
||||
function HybridScrollFrame_SetOffset (self, offset)
|
||||
local buttons = self.buttons
|
||||
local buttonHeight = self.buttonHeight;
|
||||
local element, overflow;
|
||||
|
||||
if ( not buttonHeight and buttons and buttons[1] ) then
|
||||
buttonHeight = round(buttons[1]:GetHeight());
|
||||
self.buttonHeight = buttonHeight;
|
||||
end
|
||||
if ( not buttonHeight or buttonHeight == 0 ) then
|
||||
self.offset = 0;
|
||||
HybridScrollFrame_SetVerticalScrollOffset(self, 0);
|
||||
return;
|
||||
end
|
||||
|
||||
local scrollHeight = 0;
|
||||
|
||||
local largeButtonTop = self.largeButtonTop
|
||||
if ( self.dynamic ) then --This is for frames where buttons will have different heights
|
||||
if ( offset < buttonHeight ) then
|
||||
-- a little optimization
|
||||
element = 0;
|
||||
scrollHeight = offset;
|
||||
else
|
||||
element, scrollHeight = self.dynamic(offset);
|
||||
end
|
||||
elseif ( largeButtonTop and offset >= largeButtonTop ) then
|
||||
local largeButtonHeight = self.largeButtonHeight;
|
||||
-- Initial offset...
|
||||
element = largeButtonTop / buttonHeight;
|
||||
|
||||
if ( offset >= (largeButtonTop + largeButtonHeight) ) then
|
||||
element = element + 1;
|
||||
|
||||
local leftovers = (offset - (largeButtonTop + largeButtonHeight) );
|
||||
|
||||
element = element + ( leftovers / buttonHeight );
|
||||
overflow = element - math.floor(element);
|
||||
scrollHeight = overflow * buttonHeight;
|
||||
else
|
||||
scrollHeight = math.abs(offset - largeButtonTop);
|
||||
end
|
||||
else
|
||||
element = offset / buttonHeight;
|
||||
overflow = element - math.floor(element);
|
||||
scrollHeight = overflow * buttonHeight;
|
||||
end
|
||||
|
||||
if ( math.floor(self.offset or 0) ~= math.floor(element) and self.update ) then
|
||||
self.offset = element;
|
||||
self:update();
|
||||
else
|
||||
self.offset = element;
|
||||
end
|
||||
|
||||
HybridScrollFrame_SetVerticalScrollOffset(self, scrollHeight);
|
||||
end
|
||||
|
||||
function HybridScrollFrame_CreateButtons (self, buttonTemplate, initialOffsetX, initialOffsetY, initialPoint, initialRelative, offsetX, offsetY, point, relativePoint)
|
||||
local scrollChild = self.scrollChild;
|
||||
local button, buttonHeight, buttons, numButtons;
|
||||
|
||||
local parentName = self:GetName();
|
||||
local buttonName = parentName and (parentName .. "Button") or nil;
|
||||
|
||||
initialPoint = initialPoint or "TOPLEFT";
|
||||
initialRelative = initialRelative or "TOPLEFT";
|
||||
point = point or "TOPLEFT";
|
||||
relativePoint = relativePoint or "BOTTOMLEFT";
|
||||
offsetX = offsetX or 0;
|
||||
offsetY = offsetY or 0;
|
||||
|
||||
if ( self.buttons ) then
|
||||
buttons = self.buttons;
|
||||
buttonHeight = buttons[1]:GetHeight();
|
||||
else
|
||||
button = CreateFrame("BUTTON", buttonName and (buttonName .. 1) or nil, scrollChild, buttonTemplate);
|
||||
buttonHeight = button:GetHeight();
|
||||
button:SetPoint(initialPoint, scrollChild, initialRelative, initialOffsetX, initialOffsetY);
|
||||
buttons = {}
|
||||
tinsert(buttons, button);
|
||||
end
|
||||
|
||||
self.buttonHeight = round(buttonHeight) - offsetY;
|
||||
|
||||
numButtons = math.ceil(self:GetHeight() / buttonHeight) + 1;
|
||||
|
||||
for i = #buttons + 1, numButtons do
|
||||
button = CreateFrame("BUTTON", buttonName and (buttonName .. i) or nil, scrollChild, buttonTemplate);
|
||||
button:SetPoint(point, buttons[i-1], relativePoint, offsetX, offsetY);
|
||||
tinsert(buttons, button);
|
||||
end
|
||||
|
||||
scrollChild:SetWidth(self:GetWidth())
|
||||
scrollChild:SetHeight(numButtons * buttonHeight);
|
||||
HybridScrollFrame_SetVerticalScrollOffset(self, 0);
|
||||
HybridScrollFrame_UpdateScrollChildRectSafe(self);
|
||||
|
||||
self.buttons = buttons;
|
||||
local scrollBar = HybridScrollFrame_GetScrollBar(self);
|
||||
if scrollBar then
|
||||
scrollBar:SetMinMaxValues(0, numButtons * buttonHeight)
|
||||
scrollBar.buttonHeight = buttonHeight;
|
||||
scrollBar:SetValueStep(.005);
|
||||
scrollBar:SetValue(0);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function HybridScrollFrame_GetButtonIndex(self, button)
|
||||
return tIndexOf(self.buttons, button);
|
||||
end
|
||||
|
||||
function HybridScrollFrame_GetButtons (self)
|
||||
return self.buttons;
|
||||
end
|
||||
|
||||
function HybridScrollFrame_SetDoNotHideScrollBar (self, doNotHide)
|
||||
local scrollBar = HybridScrollFrame_GetScrollBar(self);
|
||||
if not scrollBar or scrollBar.doNotHide == doNotHide then
|
||||
return;
|
||||
end
|
||||
|
||||
scrollBar.doNotHide = doNotHide;
|
||||
HybridScrollFrame_Update(self, self.totalHeight or 0, self.scrollChild:GetHeight());
|
||||
end
|
||||
|
||||
function HybridScrollFrame_ScrollToIndex(self, index, getHeightFunc)
|
||||
local scrollBar = HybridScrollFrame_GetScrollBar(self);
|
||||
if not scrollBar then
|
||||
return;
|
||||
end
|
||||
|
||||
local totalHeight = 0;
|
||||
local scrollFrameHeight = self:GetHeight();
|
||||
for i = 1, index do
|
||||
local entryHeight = getHeightFunc(i);
|
||||
if i == index then
|
||||
local offset = 0;
|
||||
-- we don't need to do anything if the entry is fully displayed with the scroll all the way up
|
||||
if ( totalHeight + entryHeight > scrollFrameHeight ) then
|
||||
if ( entryHeight > scrollFrameHeight ) then
|
||||
-- this entry is larger than the entire scrollframe, put it at the top
|
||||
offset = totalHeight;
|
||||
else
|
||||
-- otherwise place it in the center
|
||||
local diff = scrollFrameHeight - entryHeight;
|
||||
offset = totalHeight - diff / 2;
|
||||
end
|
||||
-- because of valuestep our positioning might change
|
||||
-- we'll do the adjustment ourselves to make sure the entry ends up above the center rather than below
|
||||
local valueStep = scrollBar:GetValueStep();
|
||||
offset = offset + valueStep - mod(offset, valueStep);
|
||||
-- but if we ended up moving the entry so high up that its top is not visible, move it back down
|
||||
if ( offset > totalHeight ) then
|
||||
offset = offset - valueStep;
|
||||
end
|
||||
end
|
||||
scrollBar:SetValue(offset);
|
||||
break;
|
||||
end
|
||||
totalHeight = totalHeight + entryHeight;
|
||||
end
|
||||
end
|
||||
|
||||
function HybridScrollBar_Disable(scrollBar)
|
||||
scrollBar:Disable();
|
||||
local scrollDownButton = scrollBar.ScrollDownButton or _G[scrollBar:GetName().."ScrollDownButton"];
|
||||
if scrollDownButton then
|
||||
scrollDownButton:Disable();
|
||||
end
|
||||
local scrollUpButton = scrollBar.ScrollUpButton or _G[scrollBar:GetName().."ScrollUpButton"];
|
||||
if scrollUpButton then
|
||||
scrollUpButton:Disable();
|
||||
end
|
||||
end
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="HybridScrollFrame.lua"/>
|
||||
|
||||
<Texture name="HybridScrollBarButton" virtual="true">
|
||||
<TexCoords left="0.25" right="0.75" top="0.25" bottom="0.75"/>
|
||||
</Texture>
|
||||
|
||||
<Slider name="HybridScrollBarBackgroundTemplate" parentKey="scrollBar" virtual="true">
|
||||
<Size x="20" y="0"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="0" y="-18"/>
|
||||
<Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT" x="0" y="16"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture name="$parentBG" setAllPoints="true" hidden="true" parentKey="trackBG">
|
||||
<Color r="0" g="0" b="0" a=".85"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
<Layer level="ARTWORK">
|
||||
<Texture name="$parentTop" parentKey="ScrollBarTop" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
|
||||
<Size x="27" y="48"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="-4" y="17"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0" right="0.484375" top="0" bottom=".20"/>
|
||||
</Texture>
|
||||
<Texture name="$parentBottom" parentKey="ScrollBarBottom" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
|
||||
<Size x="27" y="64"/>
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" x="-4" y="-15"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0.515625" right="1.0" top="0.1440625" bottom="0.4140625"/>
|
||||
</Texture>
|
||||
<Texture name="$parentMiddle" parentKey="ScrollBarMiddle" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentTop" relativePoint="BOTTOMLEFT"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBottom" relativePoint="TOPRIGHT"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0" right="0.484375" top="0.1640625" bottom="1"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<ThumbTexture name="$parentThumbTexture" file="Interface\Buttons\UI-ScrollBar-Knob" parentKey="thumbTexture">
|
||||
<Size x="18" y="24"/>
|
||||
<TexCoords left="0.20" right="0.80" top="0.125" bottom="0.875"/>
|
||||
</ThumbTexture>
|
||||
</Slider>
|
||||
|
||||
<Slider name="HybridScrollBarTemplate" inherits="HybridScrollBarBackgroundTemplate" virtual="true">
|
||||
<Frames>
|
||||
<Button name="$parentScrollUpButton" parentKey="ScrollUpButton" inherits="UIPanelScrollUpButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOM" relativePoint="TOP" x="0" y="-2"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnLoad function="HybridScrollFrameScrollUp_OnLoad"/>
|
||||
<OnClick function ="HybridScrollFrameScrollButton_OnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
<Button name="$parentScrollDownButton" parentKey="ScrollDownButton" inherits="UIPanelScrollDownButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOP" relativePoint="BOTTOM" x="0" y="2"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnLoad function="HybridScrollFrameScrollDown_OnLoad"/>
|
||||
<OnClick function="HybridScrollFrameScrollButton_OnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnValueChanged function="HybridScrollFrame_OnValueChanged"/>
|
||||
</Scripts>
|
||||
</Slider>
|
||||
|
||||
<Slider name="HybridScrollBarTrimTemplate" parentKey="scrollBar" virtual="true">
|
||||
<Size x="20" y="0"/>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture name="$parentBG" setAllPoints="true" hidden="true" parentKey="trackBG">
|
||||
<Color r="0" g="0" b="0" a=".85"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
<Layer level="ARTWORK">
|
||||
<Texture name="$parentTop" parentKey="Top" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
|
||||
<Size x="24" y="48"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="-4" y="17"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0" right="0.45" top="0" bottom=".20"/>
|
||||
</Texture>
|
||||
<Texture name="$parentBottom" parentKey="Bottom" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
|
||||
<Size x="24" y="64"/>
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" x="-4" y="-15"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0.515625" right="0.97" top="0.1440625" bottom="0.4140625"/>
|
||||
</Texture>
|
||||
<Texture name="$parentMiddle" parentKey="Middle" file="Interface\PaperDollInfoFrame\UI-Character-ScrollBar">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentTop" relativePoint="BOTTOMLEFT"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBottom" relativePoint="TOPRIGHT"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0" right="0.45" top="0.1640625" bottom="1"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Frames>
|
||||
<Button name="$parentScrollUpButton" parentKey="UpButton" inherits="UIPanelScrollUpButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOM" relativePoint="TOP" x="0" y="-2"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnLoad function="HybridScrollFrameScrollUp_OnLoad"/>
|
||||
<OnClick function="HybridScrollFrameScrollButton_OnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
<Button name="$parentScrollDownButton" parentKey="DownButton" inherits="UIPanelScrollDownButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOP" relativePoint="BOTTOM" x="0" y="2"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnLoad function="HybridScrollFrameScrollDown_OnLoad"/>
|
||||
<OnClick function="HybridScrollFrameScrollButton_OnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnValueChanged function="HybridScrollFrame_OnValueChanged"/>
|
||||
</Scripts>
|
||||
<ThumbTexture name="$parentThumbTexture" inherits="HybridScrollBarButton" file="Interface\Buttons\UI-ScrollBar-Knob" parentKey="thumbTexture">
|
||||
<Size x="18" y="24"/>
|
||||
<TexCoords left="0.20" right="0.80" top="0.125" bottom="0.875"/>
|
||||
</ThumbTexture>
|
||||
</Slider>
|
||||
|
||||
<Slider name="MinimalHybridScrollBarTemplate" parentKey="scrollBar" virtual="true">
|
||||
<Size x="22" y="0"/>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture name="$parentTrack" parentKey="trackBG">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="0" y="17"/>
|
||||
<Anchor point="BOTTOMRIGHT" x="0" y="-17"/>
|
||||
</Anchors>
|
||||
<Color r="0" g="0" b="0" a="1"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Frames>
|
||||
<Button name="$parentScrollUpButton" inherits="UIPanelScrollUpButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOP" x="0" y="15"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnLoad function="HybridScrollFrameScrollUp_OnLoad"/>
|
||||
<OnClick function="HybridScrollFrameScrollButton_OnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
<Button name="$parentScrollDownButton" inherits="UIPanelScrollDownButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOM" x="0" y="-15"/>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnLoad function="HybridScrollFrameScrollDown_OnLoad"/>
|
||||
<OnClick function="HybridScrollFrameScrollButton_OnClick"/>
|
||||
</Scripts>
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnValueChanged function="HybridScrollFrame_OnValueChanged"/>
|
||||
</Scripts>
|
||||
<ThumbTexture name="$parentThumbTexture" inherits="HybridScrollBarButton" file="Interface\Buttons\UI-ScrollBar-Knob" parentKey="thumbTexture">
|
||||
<Size x="18" y="24"/>
|
||||
<TexCoords left="0.20" right="0.80" top="0.125" bottom="0.875"/>
|
||||
</ThumbTexture>
|
||||
</Slider>
|
||||
|
||||
<ScrollFrame name="HybridScrollFrameTemplate" virtual="true">
|
||||
<Scripts>
|
||||
<OnLoad function="HybridScrollFrame_OnLoad"/>
|
||||
<OnMouseWheel function="HybridScrollFrame_OnMouseWheel"/>
|
||||
</Scripts>
|
||||
<ScrollChild>
|
||||
<Frame name="$parentScrollChild" parentKey="ScrollChild">
|
||||
<Scripts>
|
||||
<OnLoad function="HybridScrollFrameScrollChild_OnLoad"/>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
</ScrollChild>
|
||||
</ScrollFrame>
|
||||
|
||||
<ScrollFrame name="BasicHybridScrollFrameTemplate" inherits="HybridScrollFrameTemplate" virtual="true">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT"/>
|
||||
<Anchor point="BOTTOMRIGHT"/>
|
||||
</Anchors>
|
||||
<Frames>
|
||||
<Slider name="$parentScrollBar" parentKey="ScrollBar" inherits="HybridScrollBarTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="0" y="-17"/>
|
||||
<Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT" x="0" y="12"/>
|
||||
</Anchors>
|
||||
</Slider>
|
||||
</Frames>
|
||||
</ScrollFrame>
|
||||
|
||||
<!-- This is a scrollframe with no border and a black texture for a track -->
|
||||
<ScrollFrame name="MinimalHybridScrollFrameTemplate" inherits="HybridScrollFrameTemplate" virtual="true">
|
||||
<Frames>
|
||||
<Slider name="$parentScrollBar" inherits="MinimalHybridScrollBarTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativePoint="TOPRIGHT" x="0" y="-17"/>
|
||||
<Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT" x="0" y="17"/>
|
||||
</Anchors>
|
||||
</Slider>
|
||||
</Frames>
|
||||
</ScrollFrame>
|
||||
</Ui>
|
||||
+355
@@ -0,0 +1,355 @@
|
||||
|
||||
NAVBAR_WIDTHBUFFER = 20;
|
||||
|
||||
|
||||
function NavBar_Initialize(self, template, homeData, homeButton, overflowButton)
|
||||
self.template = template;
|
||||
self.freeButtons = {};
|
||||
self.navList = {};
|
||||
self.widthBuffer = NAVBAR_WIDTHBUFFER;
|
||||
|
||||
local name = self:GetName();
|
||||
|
||||
if not self.dropDown then
|
||||
local dropDownName = name and name.."DropDown" or nil;
|
||||
self.dropDown = CreateFrame("Frame", dropDownName, self, "UIDropDownMenuTemplate");
|
||||
UIDropDownMenu_Initialize(self.dropDown, NavBar_DropDown_Initialize, "MENU");
|
||||
end
|
||||
|
||||
if not homeButton then
|
||||
local homeButtonName = name and name.."HomeButton" or nil;
|
||||
homeButton = CreateFrame("BUTTON", homeButtonName, self, self.template);
|
||||
homeButton:SetWidth(homeButton.text:GetStringWidth()+30);
|
||||
end
|
||||
homeButton:SetText(homeData.name or HOME);
|
||||
|
||||
if not overflowButton then
|
||||
local overflowButtonName = name and name.."OverflowButton" or nil;
|
||||
overflowButton = CreateFrame("BUTTON", overflowButtonName, self, self.template);
|
||||
overflowButton:SetWidth(30);
|
||||
|
||||
-- LOOK AT CLICK
|
||||
end
|
||||
|
||||
|
||||
if not homeButton:GetScript("OnEnter") then
|
||||
homeButton:SetScript("OnEnter", NavBar_ButtonOnEnter);
|
||||
end
|
||||
|
||||
if not homeButton:GetScript("OnLeave") then
|
||||
homeButton:SetScript("OnLeave", NavBar_ButtonOnLeave);
|
||||
end
|
||||
|
||||
if ( self.oldStyle ) then
|
||||
homeButton:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
||||
overflowButton:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
||||
else
|
||||
homeButton:RegisterForClicks("LeftButtonUp");
|
||||
end
|
||||
overflowButton.listFunc = NavBar_ListOverFlowButtons;
|
||||
homeButton:ClearAllPoints();
|
||||
overflowButton:ClearAllPoints();
|
||||
homeButton:SetPoint("LEFT", self, "LEFT", 0, 0);
|
||||
overflowButton:SetPoint("LEFT", self, "LEFT", 0, 0);
|
||||
overflowButton:Hide();
|
||||
|
||||
homeButton.oldClick = homeButton:GetScript("OnClick");
|
||||
homeButton:SetScript("OnClick", NavBar_ButtonOnClick);
|
||||
overflowButton:SetScript("OnMouseDown", NavBar_ToggleMenu);
|
||||
self.homeButton = homeButton;
|
||||
self.overflowButton = overflowButton;
|
||||
|
||||
|
||||
self.navList[#self.navList+1] = homeButton;
|
||||
homeButton.myclick = homeData.OnClick;
|
||||
homeButton.listFunc = homeData.listFunc;
|
||||
homeButton.data = homeData;
|
||||
homeButton:Show();
|
||||
end
|
||||
|
||||
|
||||
|
||||
function NavBar_Reset(self)
|
||||
for index=2,#self.navList do
|
||||
self.navList[index]:Hide();
|
||||
tinsert(self.freeButtons, self.navList[index])
|
||||
self.navList[index] = nil;
|
||||
end
|
||||
NavBar_CheckLength(self);
|
||||
end
|
||||
|
||||
|
||||
function NavBar_AddButton(self, buttonData)
|
||||
local navButton = self.freeButtons[#self.freeButtons];
|
||||
if navButton then
|
||||
self.freeButtons[#self.freeButtons] = nil;
|
||||
end
|
||||
|
||||
if not navButton then
|
||||
local name = self:GetName();
|
||||
local buttonName = name and name.."Button"..(#self.navList+1);
|
||||
navButton = CreateFrame("BUTTON", buttonName, self, self.template);
|
||||
navButton.oldClick = navButton:GetScript("OnClick");
|
||||
navButton:SetScript("OnClick", NavBar_ButtonOnClick);
|
||||
if ( self.oldStyle ) then
|
||||
navButton:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
||||
else
|
||||
navButton:RegisterForClicks("LeftButtonUp");
|
||||
end
|
||||
|
||||
if not navButton:GetScript("OnEnter") then
|
||||
navButton:SetScript("OnEnter", NavBar_ButtonOnEnter);
|
||||
end
|
||||
|
||||
if not navButton:GetScript("OnLeave") then
|
||||
navButton:SetScript("OnLeave", NavBar_ButtonOnLeave);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--Set up the button
|
||||
local navParent = self.navList[#self.navList];
|
||||
self.navList[#self.navList+1] = navButton;
|
||||
navButton.navParent = navParent;
|
||||
|
||||
navButton:SetText(buttonData.name);
|
||||
local buttonExtraWidth;
|
||||
navButton.MenuArrowButton:Hide();
|
||||
buttonExtraWidth = 30;
|
||||
navButton.text:SetWidth(self.textMaxWidth or 0);
|
||||
navButton:SetWidth(navButton.text:GetStringWidth() + buttonExtraWidth);
|
||||
navButton.myclick = buttonData.OnClick;
|
||||
navButton.listFunc = buttonData.listFunc;
|
||||
navButton.id = buttonData.id;
|
||||
navButton.data = buttonData;
|
||||
|
||||
navButton:Show();
|
||||
NavBar_CheckLength(self);
|
||||
|
||||
navButton.MenuArrowButton:SetEnabled(not buttonData.isDisabled)
|
||||
end
|
||||
|
||||
function NavBar_ClearTrailingButtons(list, freeList, button)
|
||||
for index=#list,1,-1 do
|
||||
if not list[index] or button == list[index] then
|
||||
break
|
||||
end
|
||||
|
||||
list[index]:Hide();
|
||||
tinsert(freeList, list[index])
|
||||
list[index] = nil;
|
||||
end
|
||||
NavBar_CheckLength(button:GetParent());
|
||||
end
|
||||
|
||||
function NavBar_OpenTo(self, id)
|
||||
local button;
|
||||
local found = false;
|
||||
for i=1, #self.navList do
|
||||
button = self.navList[i];
|
||||
if (button.id and button.id == id) then
|
||||
found = true;
|
||||
break;
|
||||
end
|
||||
end
|
||||
|
||||
if (found) then
|
||||
NavBar_ClearTrailingButtons(self.navList, self.freeButtons, button)
|
||||
end
|
||||
end
|
||||
|
||||
function NavBar_ButtonOnClick(self, button)
|
||||
local parent = self:GetParent()
|
||||
CloseDropDownMenus();
|
||||
if button == "LeftButton" then
|
||||
NavBar_ClearTrailingButtons(parent.navList, parent.freeButtons, self);
|
||||
|
||||
if self.oldClick then
|
||||
self:oldClick(button);
|
||||
end
|
||||
|
||||
if self.myclick then
|
||||
self:myclick(button);
|
||||
end
|
||||
elseif button == "RightButton" then
|
||||
NavBar_ToggleMenu(self);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function NavBar_ButtonOnEnter(self)
|
||||
if self.text:IsTruncated() then
|
||||
GameTooltip:SetOwner(self, "ANCHOR_BOTTOMRIGHT");
|
||||
GameTooltip:AddLine(self.text:GetText(), NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, true);
|
||||
GameTooltip:Show();
|
||||
end
|
||||
end
|
||||
|
||||
function NavBar_ButtonOnLeave(self)
|
||||
if self.text:IsTruncated() then
|
||||
GameTooltip:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function NavBar_CheckLength(self)
|
||||
local width = 0;
|
||||
local collapsedWidth;
|
||||
local maxWidth = self:GetWidth() - self.widthBuffer;
|
||||
local xoffset;
|
||||
|
||||
local lastShown;
|
||||
local collapsed = false;
|
||||
|
||||
for i=#self.navList,1,-1 do
|
||||
local currentWidth = width;
|
||||
width = width + self.navList[i]:GetWidth();
|
||||
|
||||
if width > maxWidth then
|
||||
self.navList[i]:Hide();
|
||||
collapsed = true;
|
||||
if not collapsedWidth then -- store the width for adding the offset button
|
||||
collapsedWidth = currentWidth;
|
||||
end
|
||||
else
|
||||
self.navList[i]:Show();
|
||||
if lastShown then
|
||||
local lastButton = self.navList[lastShown];
|
||||
xoffset = self.navList[i].xoffset or 0
|
||||
lastButton:SetPoint("LEFT", self.navList[i], "RIGHT", xoffset, 0);
|
||||
self.navList[i]:SetFrameLevel(lastButton:GetFrameLevel()+1);
|
||||
else
|
||||
self.navList[i]:SetFrameLevel(self:GetFrameLevel()+1);
|
||||
end
|
||||
lastShown = i;
|
||||
end
|
||||
|
||||
if i<#self.navList then
|
||||
if self.navList[i].selected then
|
||||
self.navList[i].selected:Hide();
|
||||
end
|
||||
self.navList[i]:Enable();
|
||||
else
|
||||
if self.navList[i].selected then
|
||||
self.navList[i].selected:Show();
|
||||
end
|
||||
|
||||
self.navList[i]:SetButtonState("NORMAL");
|
||||
self.navList[i]:Disable();
|
||||
end
|
||||
end
|
||||
|
||||
if self.navList[1] then
|
||||
local frameLevel = self.navList[1]:GetFrameLevel()
|
||||
if frameLevel >= self.overlay:GetFrameLevel() then
|
||||
self.overlay:SetFrameLevel(frameLevel + 1)
|
||||
end
|
||||
end
|
||||
|
||||
if collapsed then
|
||||
if collapsedWidth + self.overflowButton:GetWidth() > maxWidth then
|
||||
--No room for the overflow button
|
||||
self.navList[lastShown]:Hide();
|
||||
lastShown = lastShown + 1;
|
||||
end
|
||||
|
||||
self.overflowButton:Show();
|
||||
|
||||
--There should only ever be no lastShown if a single button is longer than maxWidth by itself.
|
||||
if ( lastShown ) then
|
||||
local lastButton = self.navList[lastShown];
|
||||
|
||||
--There should only ever be no lastButton when there is lastShown if a single button is less than maxWidth
|
||||
--but it's width plus the width of the overflow button is longer than maxWidth. In this case the single button
|
||||
--is hidden to make room for the overflowButton.
|
||||
if ( lastButton ) then
|
||||
xoffset = self.overflowButton.xoffset or 0
|
||||
lastButton:SetPoint("LEFT", self.overflowButton, "RIGHT", xoffset, 0);
|
||||
self.overflowButton:SetFrameLevel(lastButton:GetFrameLevel()+1);
|
||||
end
|
||||
end
|
||||
else
|
||||
self.overflowButton:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
function NavBar_ListOverFlowButtons(self, index)
|
||||
local navBar = self:GetParent();
|
||||
|
||||
local button = navBar.navList[index];
|
||||
if not button:IsShown() then
|
||||
return button:GetText(), NavBar_OverflowItemOnClick;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function NavBar_ToggleMenu(self, button)
|
||||
if ( self:GetParent().dropDown.buttonOwner ~= self ) then
|
||||
CloseDropDownMenus();
|
||||
end
|
||||
self:GetParent().dropDown.buttonOwner = self;
|
||||
ToggleDropDownMenu(nil, nil, self:GetParent().dropDown, self, 20, 3);
|
||||
end
|
||||
|
||||
|
||||
function NavBar_DropDown_Initialize(self, level)
|
||||
local navButton = self.buttonOwner;
|
||||
if not navButton or not navButton.listFunc then
|
||||
return;
|
||||
end
|
||||
|
||||
local info = UIDropDownMenu_CreateInfo();
|
||||
info.func = NavBar_DropDown_Click;
|
||||
info.owner = navButton;
|
||||
info.notCheckable = true;
|
||||
local index = 1;
|
||||
local text, func = navButton:listFunc(index);
|
||||
while text do
|
||||
info.text = text;
|
||||
|
||||
info.arg1 = index;
|
||||
info.arg2 = func;
|
||||
UIDropDownMenu_AddButton(info, level);
|
||||
|
||||
index = index + 1;
|
||||
text, func = navButton:listFunc(index);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function NavBar_DropDown_Click(self, index, func)
|
||||
local navButton = self.owner;
|
||||
local navBar = navButton:GetParent();
|
||||
|
||||
if func ~= NavBar_OverflowItemOnClick then
|
||||
NavBar_ClearTrailingButtons(navBar.navList, navBar.freeButtons, navButton);
|
||||
end
|
||||
if type(func) == "function" then
|
||||
func(self, index, navBar);
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function NavBar_OverflowItemOnClick(junk, index, navBar)
|
||||
local button = navBar.navList[index];
|
||||
if button then
|
||||
button:Click();
|
||||
end
|
||||
end
|
||||
|
||||
function NavBar_ReconsultationSize( self )
|
||||
self.xoffset = -15
|
||||
local newWidth = min(128, self.text:GetStringWidth()+50)
|
||||
local texCoordoffsetX = (newWidth/128)*0.25
|
||||
|
||||
self:GetNormalTexture():SetTexCoord(0.70312500-texCoordoffsetX, 0.70312500, 0.00781250, 0.24218750)
|
||||
self:GetPushedTexture():SetTexCoord(0.70312500-texCoordoffsetX, 0.70312500, 0.25781250, 0.49218750)
|
||||
self:GetHighlightTexture():SetTexCoord(0.70312500-texCoordoffsetX, 0.71312500, 0.50781250, 0.74218750)
|
||||
|
||||
self:SetWidth(newWidth)
|
||||
end
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="NavigationBar.lua"/>
|
||||
|
||||
<Button name="NavButtonTemplate" motionScriptsWhileDisabled="true" virtual="true">
|
||||
<Size x="80" y="30"/>
|
||||
<Layers>
|
||||
<Layer level="OVERLAY">
|
||||
<Texture file="Interface\HelpFrame\CS_HelpTextures" parentKey="arrowUp">
|
||||
<Size x="21" y="30"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativePoint="RIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0.88867188" right="0.92968750" top="0.29687500" bottom="0.53125000"/>
|
||||
</Texture>
|
||||
<Texture file="Interface\HelpFrame\CS_HelpTextures" parentKey="arrowDown">
|
||||
<Size x="21" y="30"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativePoint="RIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0.63281250" right="0.67382813" top="0.75781250" bottom="0.99218750"/>
|
||||
</Texture>
|
||||
<Texture file="Interface\HelpFrame\CS_HelpTextures" parentKey="selected" hidden="true">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="0" y="0"/>
|
||||
<Anchor point="BOTTOMRIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0.00195313" right="0.25195313" top="0.37500000" bottom="0.64062500"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Frames>
|
||||
<Button parentKey="MenuArrowButton" hidden="true">
|
||||
<Size x="27" y="31"/>
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativePoint="TOPRIGHT" x="-2" y="-15"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="OVERLAY">
|
||||
<Texture parentKey="Art" file="Interface\Buttons\SquareButtonTextures">
|
||||
<Size x="12" y="12"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" x="0" y="-1"/>
|
||||
</Anchors>
|
||||
<TexCoords left="0.45312500" right="0.64062500" bottom="0.01562500" top="0.20312500"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<NormalTexture file="Interface\Buttons\UI-SquareButton-Up" parentKey="NormalTexture" alpha="0">
|
||||
<Size x="32" y="32"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER"/>
|
||||
</Anchors>
|
||||
</NormalTexture>
|
||||
<PushedTexture file="Interface\Buttons\UI-SquareButton-Down" parentKey="PushedTexture" alpha="0">
|
||||
<Size x="32" y="32"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER"/>
|
||||
</Anchors>
|
||||
</PushedTexture>
|
||||
<HighlightTexture file="Interface\Buttons\UI-Common-MouseHilight" alphaMode="ADD">
|
||||
<Size x="32" y="32"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER"/>
|
||||
</Anchors>
|
||||
</HighlightTexture>
|
||||
<Scripts>
|
||||
<OnMouseDown>
|
||||
if self:IsEnabled() == 1 then
|
||||
self.Art:SetPoint("CENTER", -1, -2);
|
||||
end
|
||||
</OnMouseDown>
|
||||
<OnMouseUp>
|
||||
if self:IsEnabled() == 1 then
|
||||
self.Art:SetPoint("CENTER", 0, -1);
|
||||
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
|
||||
NavBar_ToggleMenu(self:GetParent());
|
||||
end
|
||||
</OnMouseUp>
|
||||
<OnEnter>
|
||||
self.NormalTexture:SetAlpha(1);
|
||||
self.PushedTexture:SetAlpha(1);
|
||||
</OnEnter>
|
||||
<OnLeave>
|
||||
self.NormalTexture:SetAlpha(0);
|
||||
self.PushedTexture:SetAlpha(0);
|
||||
</OnLeave>
|
||||
<OnEnable>
|
||||
self.NormalTexture:SetDesaturated(false)
|
||||
self.PushedTexture:SetDesaturated(false)
|
||||
self.Art:SetDesaturated(false)
|
||||
</OnEnable>
|
||||
<OnDisable>
|
||||
self.NormalTexture:SetDesaturated(true)
|
||||
self.PushedTexture:SetDesaturated(true)
|
||||
self.Art:SetDesaturated(true)
|
||||
</OnDisable>
|
||||
</Scripts>
|
||||
</Button>
|
||||
</Frames>
|
||||
<Scripts>
|
||||
<OnMouseDown>
|
||||
if self:IsEnabled() == 1 then
|
||||
self.arrowUp:Hide();
|
||||
self.arrowDown:Show();
|
||||
end
|
||||
</OnMouseDown>
|
||||
<OnMouseUp>
|
||||
self.arrowDown:Hide();
|
||||
self.arrowUp:Show();
|
||||
</OnMouseUp>
|
||||
<OnClick>
|
||||
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
|
||||
</OnClick>
|
||||
<OnEnable>
|
||||
self.arrowDown:Hide();
|
||||
self.arrowUp:Show();
|
||||
</OnEnable>
|
||||
<OnDisable>
|
||||
self.arrowDown:Hide();
|
||||
self.arrowUp:Show();
|
||||
</OnDisable>
|
||||
</Scripts>
|
||||
<NormalTexture file="Interface\HelpFrame\CS_HelpTextures_Tile" parentKey="NormalTexture" horizTile="true">
|
||||
<TexCoords top="0.06250000" bottom="0.12109375"/>
|
||||
</NormalTexture>
|
||||
<PushedTexture file="Interface\HelpFrame\CS_HelpTextures_Tile" parentKey="PushedTexture" horizTile="true">
|
||||
<TexCoords top="0.12500000" bottom="0.18359375"/>
|
||||
</PushedTexture>
|
||||
<HighlightTexture file="Interface\HelpFrame\CS_HelpTextures" parentKey="HighlightTexture" alphaMode="ADD">
|
||||
<TexCoords left="0.00195313" right="0.25195313" top="0.65625000" bottom="0.92187500"/>
|
||||
</HighlightTexture>
|
||||
<ButtonText name="$parentText" inherits="GameFontNormal" justifyH="LEFT" parentKey="text">
|
||||
<Size x="0" y="12"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" x="20" y="0"/>
|
||||
</Anchors>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
|
||||
<Frame name="NavBarTemplate" parentKey="navBar" virtual="true">
|
||||
<Size x="300" y="34"/>
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture file="Interface\HelpFrame\CS_HelpTextures_Tile" horizTile="true">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT" x="0" y="0"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
<TexCoords top="0.18750000" bottom="0.25390625"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Frames>
|
||||
<Frame name="$parentOverlay" parentKey="overlay">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="0" y="0"/>
|
||||
<Anchor point="BOTTOMRIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
<Layers>
|
||||
<Layer level="OVERLAY">
|
||||
<Texture file="Interface\HelpFrame\CS_HelpTextures_Tile" horizTile="true">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="0" y="0"/>
|
||||
<Anchor point="BOTTOMRIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
<TexCoords top="0.25781250" bottom="0.32421875"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self:SetFrameLevel(50);
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
<Button name="$parentOverflowButton" parentKey="overflow">
|
||||
<Size x="44" y="30"/>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self.xoffset = -18
|
||||
</OnLoad>
|
||||
<OnClick>
|
||||
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
|
||||
</OnClick>
|
||||
</Scripts>
|
||||
<NormalTexture file="Interface\HelpFrame\CS_HelpTextures">
|
||||
<TexCoords left="0.54296875" right="0.62890625" top="0.75781250" bottom="0.99218750"/>
|
||||
</NormalTexture>
|
||||
<PushedTexture file="Interface\HelpFrame\CS_HelpTextures">
|
||||
<TexCoords left="0.45312500" right="0.53906250" top="0.75781250" bottom="0.99218750"/>
|
||||
</PushedTexture>
|
||||
<HighlightTexture file="Interface\HelpFrame\CS_HelpTextures" alphaMode="ADD" alpha="0.4">
|
||||
<TexCoords left="0.54296875" right="0.62890625" top="0.75781250" bottom="0.99218750"/>
|
||||
</HighlightTexture>
|
||||
</Button>
|
||||
<Button name="$parentHomeButton" parentKey="home" text="NAVIGATIONBAR_HOME">
|
||||
<Size x="128" y="30"/>
|
||||
<Layers>
|
||||
<Layer level="OVERLAY">
|
||||
<Texture name="$parentLeft" file="Interface\Common\ShadowOverlay-Left">
|
||||
<Size x="30" y="30"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self.xoffset = -15;
|
||||
local newWidth = min(128, self.text:GetStringWidth()+50)
|
||||
local texCoordoffsetX = (newWidth/128)*0.25;
|
||||
|
||||
self:GetNormalTexture():SetTexCoord(0.70312500-texCoordoffsetX, 0.70312500, 0.00781250, 0.24218750);
|
||||
self:GetPushedTexture():SetTexCoord(0.70312500-texCoordoffsetX, 0.70312500, 0.25781250, 0.49218750);
|
||||
self:GetHighlightTexture():SetTexCoord(0.70312500-texCoordoffsetX, 0.71312500, 0.50781250, 0.74218750);
|
||||
|
||||
self:SetWidth(newWidth);
|
||||
</OnLoad>
|
||||
<OnClick>
|
||||
PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
|
||||
</OnClick>
|
||||
</Scripts>
|
||||
<NormalTexture file="Interface\HelpFrame\CS_HelpTextures">
|
||||
</NormalTexture>
|
||||
<PushedTexture file="Interface\HelpFrame\CS_HelpTextures">
|
||||
</PushedTexture>
|
||||
<HighlightTexture file="Interface\HelpFrame\CS_HelpTextures" alphaMode="ADD">
|
||||
</HighlightTexture>
|
||||
<ButtonText name="$parentText" inherits="GameFontNormal" justifyH="LEFT" parentKey="text">
|
||||
<Size x="0" y="12"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" x="10" y="0"/>
|
||||
<Anchor point="RIGHT" x="-30" y="0"/>
|
||||
</Anchors>
|
||||
</ButtonText>
|
||||
</Button>
|
||||
</Frames>
|
||||
</Frame>
|
||||
</Ui>
|
||||
+422
@@ -0,0 +1,422 @@
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local next = next
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
ObjectPoolMixin = {};
|
||||
|
||||
function ObjectPoolMixin:OnLoad(creationFunc, resetterFunc)
|
||||
self.creationFunc = creationFunc;
|
||||
self.resetterFunc = resetterFunc;
|
||||
|
||||
self.activeObjects = {};
|
||||
self.inactiveObjects = {};
|
||||
|
||||
self.numActiveObjects = 0;
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:Acquire()
|
||||
local numInactiveObjects = #self.inactiveObjects;
|
||||
if numInactiveObjects > 0 then
|
||||
local obj = self.inactiveObjects[numInactiveObjects];
|
||||
self.activeObjects[obj] = true;
|
||||
self.numActiveObjects = self.numActiveObjects + 1;
|
||||
self.inactiveObjects[numInactiveObjects] = nil;
|
||||
return obj, false;
|
||||
end
|
||||
|
||||
local newObj = self.creationFunc(self);
|
||||
if self.resetterFunc and not self.disallowResetIfNew then
|
||||
self.resetterFunc(self, newObj);
|
||||
end
|
||||
self.activeObjects[newObj] = true;
|
||||
self.numActiveObjects = self.numActiveObjects + 1;
|
||||
return newObj, true;
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:Release(obj)
|
||||
if self:IsActive(obj) then
|
||||
self.inactiveObjects[#self.inactiveObjects + 1] = obj;
|
||||
self.activeObjects[obj] = nil;
|
||||
self.numActiveObjects = self.numActiveObjects - 1;
|
||||
if self.resetterFunc then
|
||||
self.resetterFunc(self, obj);
|
||||
end
|
||||
|
||||
return true;
|
||||
end
|
||||
|
||||
return false;
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:ReleaseAll()
|
||||
for obj in pairs(self.activeObjects) do
|
||||
self:Release(obj);
|
||||
end
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:SetResetDisallowedIfNew(disallowed)
|
||||
self.disallowResetIfNew = disallowed;
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:EnumerateActive()
|
||||
return pairs(self.activeObjects);
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:GetNextActive(current)
|
||||
return (next(self.activeObjects, current));
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:GetNextInactive(current)
|
||||
return (next(self.inactiveObjects, current));
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:IsActive(object)
|
||||
return (self.activeObjects[object] ~= nil);
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:GetNumActive()
|
||||
return self.numActiveObjects;
|
||||
end
|
||||
|
||||
function ObjectPoolMixin:EnumerateInactive()
|
||||
return ipairs(self.inactiveObjects);
|
||||
end
|
||||
|
||||
function CreateObjectPool(creationFunc, resetterFunc)
|
||||
local objectPool = CreateFromMixins(ObjectPoolMixin);
|
||||
objectPool:OnLoad(creationFunc, resetterFunc);
|
||||
return objectPool;
|
||||
end
|
||||
|
||||
FramePoolMixin = CreateFromMixins(ObjectPoolMixin);
|
||||
|
||||
local pollFrameIndex = 0
|
||||
local function FramePoolFactory(framePool)
|
||||
framePool.createdFrames = framePool.createdFrames + 1
|
||||
pollFrameIndex = pollFrameIndex + 1
|
||||
local parentName, frameName = framePool.parent and framePool.parent:GetName()
|
||||
if parentName then
|
||||
frameName = string.format("%sPoolFrame%s%i_%i", parentName, framePool.frameTemplate or "NoTemplate", framePool.createdFrames, pollFrameIndex)
|
||||
elseif framePool.frameTemplate then
|
||||
frameName = string.format("UnnamedPoolFrame%s%i_%i", framePool.frameTemplate, framePool.createdFrames, pollFrameIndex)
|
||||
else
|
||||
frameName = string.format("UnnamedPoolFrameNoTemplate%i_%i", framePool.createdFrames, pollFrameIndex)
|
||||
end
|
||||
return CreateFrame(framePool.frameType, frameName, framePool.parent, framePool.frameTemplate);
|
||||
end
|
||||
|
||||
local function ForbiddenFramePoolFactory(framePool)
|
||||
return FramePoolFactory(framePool)
|
||||
end
|
||||
|
||||
function FramePoolMixin:OnLoad(frameType, parent, frameTemplate, resetterFunc, forbidden, frameInitFunc)
|
||||
if forbidden then
|
||||
local creationFunc = ForbiddenFramePoolFactory;
|
||||
if frameInitFunc ~= nil then
|
||||
creationFunc = function(framePool)
|
||||
local frame = ForbiddenFramePoolFactory(framePool);
|
||||
frameInitFunc(frame);
|
||||
return frame;
|
||||
end
|
||||
end
|
||||
|
||||
ObjectPoolMixin.OnLoad(self, creationFunc, resetterFunc);
|
||||
else
|
||||
local creationFunc = FramePoolFactory;
|
||||
if frameInitFunc ~= nil then
|
||||
creationFunc = function(framePool)
|
||||
local frame = FramePoolFactory(framePool);
|
||||
frameInitFunc(frame);
|
||||
return frame;
|
||||
end
|
||||
end
|
||||
|
||||
ObjectPoolMixin.OnLoad(self, creationFunc, resetterFunc);
|
||||
end
|
||||
self.createdFrames = 0;
|
||||
self.frameType = frameType;
|
||||
self.parent = parent;
|
||||
self.frameTemplate = frameTemplate;
|
||||
end
|
||||
|
||||
function FramePoolMixin:GetTemplate()
|
||||
return self.frameTemplate;
|
||||
end
|
||||
|
||||
function FramePool_Hide(framePool, frame)
|
||||
frame:Hide();
|
||||
end
|
||||
|
||||
function FramePool_HideAndClearAnchors(framePool, frame)
|
||||
frame:Hide();
|
||||
frame:ClearAllPoints();
|
||||
end
|
||||
|
||||
function CreateFramePool(frameType, parent, frameTemplate, resetterFunc, forbidden, frameInitFunc)
|
||||
local framePool = CreateFromMixins(FramePoolMixin);
|
||||
framePool:OnLoad(frameType, parent, frameTemplate, resetterFunc or FramePool_HideAndClearAnchors, forbidden, frameInitFunc);
|
||||
return framePool;
|
||||
end
|
||||
|
||||
TexturePoolMixin = CreateFromMixins(ObjectPoolMixin);
|
||||
|
||||
local function TexturePoolFactory(texturePool)
|
||||
return texturePool.parent:CreateTexture(nil, texturePool.layer, texturePool.textureTemplate, texturePool.subLayer);
|
||||
end
|
||||
|
||||
function TexturePoolMixin:OnLoad(parent, layer, subLayer, textureTemplate, resetterFunc)
|
||||
ObjectPoolMixin.OnLoad(self, TexturePoolFactory, resetterFunc);
|
||||
self.parent = parent;
|
||||
self.layer = layer;
|
||||
self.subLayer = subLayer;
|
||||
self.textureTemplate = textureTemplate;
|
||||
end
|
||||
|
||||
TexturePool_Hide = FramePool_Hide;
|
||||
TexturePool_HideAndClearAnchors = FramePool_HideAndClearAnchors;
|
||||
|
||||
function CreateTexturePool(parent, layer, subLayer, textureTemplate, resetterFunc)
|
||||
local texturePool = CreateFromMixins(TexturePoolMixin);
|
||||
texturePool:OnLoad(parent, layer, subLayer, textureTemplate, resetterFunc or TexturePool_HideAndClearAnchors);
|
||||
return texturePool;
|
||||
end
|
||||
|
||||
FontStringPoolMixin = CreateFromMixins(ObjectPoolMixin);
|
||||
|
||||
local function FontStringPoolFactory(fontStringPool)
|
||||
return fontStringPool.parent:CreateFontString(nil, fontStringPool.layer, fontStringPool.fontStringTemplate, fontStringPool.subLayer);
|
||||
end
|
||||
|
||||
function FontStringPoolMixin:OnLoad(parent, layer, subLayer, fontStringTemplate, resetterFunc)
|
||||
ObjectPoolMixin.OnLoad(self, FontStringPoolFactory, resetterFunc);
|
||||
self.parent = parent;
|
||||
self.layer = layer;
|
||||
self.subLayer = subLayer;
|
||||
self.fontStringTemplate = fontStringTemplate;
|
||||
end
|
||||
|
||||
FontStringPool_Hide = FramePool_Hide;
|
||||
FontStringPool_HideAndClearAnchors = FramePool_HideAndClearAnchors;
|
||||
|
||||
function CreateFontStringPool(parent, layer, subLayer, fontStringTemplate, resetterFunc)
|
||||
local fontStringPool = CreateFromMixins(FontStringPoolMixin);
|
||||
fontStringPool:OnLoad(parent, layer, subLayer, fontStringTemplate, resetterFunc or FontStringPool_HideAndClearAnchors);
|
||||
return fontStringPool;
|
||||
end
|
||||
|
||||
ActorPoolMixin = CreateFromMixins(ObjectPoolMixin);
|
||||
|
||||
local function ActorPoolFactory(actorPool)
|
||||
return actorPool.parent:CreateActor(nil, actorPool.actorTemplate);
|
||||
end
|
||||
|
||||
function ActorPoolMixin:OnLoad(parent, actorTemplate, resetterFunc)
|
||||
ObjectPoolMixin.OnLoad(self, ActorPoolFactory, resetterFunc);
|
||||
self.parent = parent;
|
||||
self.actorTemplate = actorTemplate;
|
||||
end
|
||||
|
||||
ActorPool_Hide = FramePool_Hide;
|
||||
function ActorPool_HideAndClearModel(actorPool, actor)
|
||||
actor:ClearModel();
|
||||
actor:Hide();
|
||||
end
|
||||
|
||||
function CreateActorPool(parent, actorTemplate, resetterFunc)
|
||||
local actorPool = CreateFromMixins(ActorPoolMixin);
|
||||
actorPool:OnLoad(parent, actorTemplate, resetterFunc or ActorPool_HideAndClearModel);
|
||||
return actorPool;
|
||||
end
|
||||
|
||||
FramePoolCollectionMixin = {};
|
||||
|
||||
function CreateFramePoolCollection()
|
||||
local poolCollection = CreateFromMixins(FramePoolCollectionMixin);
|
||||
poolCollection:OnLoad();
|
||||
return poolCollection;
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:OnLoad()
|
||||
self.pools = {};
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:GetNumActive()
|
||||
local numTotalActive = 0;
|
||||
for _, pool in pairs(self.pools) do
|
||||
numTotalActive = numTotalActive + pool:GetNumActive();
|
||||
end
|
||||
return numTotalActive;
|
||||
end
|
||||
|
||||
-- Returns the pool, and whether or not the pool needed to be created.
|
||||
function FramePoolCollectionMixin:GetOrCreatePool(frameType, parent, template, resetterFunc, forbidden)
|
||||
local pool = self:GetPool(template);
|
||||
if not pool then
|
||||
return self:CreatePool(frameType, parent, template, resetterFunc, forbidden), true;
|
||||
end
|
||||
return pool, false;
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:CreatePool(frameType, parent, template, resetterFunc, forbidden, frameInitFunc)
|
||||
assert(self:GetPool(template) == nil);
|
||||
local pool = CreateFramePool(frameType, parent, template, resetterFunc, forbidden, frameInitFunc);
|
||||
self.pools[template] = pool;
|
||||
return pool;
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:GetPool(template)
|
||||
return self.pools[template];
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:Acquire(template)
|
||||
local pool = self:GetPool(template);
|
||||
assert(pool);
|
||||
return pool:Acquire();
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:Release(object)
|
||||
for _, pool in pairs(self.pools) do
|
||||
if pool:Release(object) then
|
||||
-- Found it! Just return
|
||||
return;
|
||||
end
|
||||
end
|
||||
|
||||
-- Huh, we didn't find that object
|
||||
assert(false);
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:ReleaseAllByTemplate(template)
|
||||
local pool = self:GetPool(template);
|
||||
if pool then
|
||||
pool:ReleaseAll();
|
||||
end
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:ReleaseAll()
|
||||
for key, pool in pairs(self.pools) do
|
||||
pool:ReleaseAll();
|
||||
end
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:EnumerateActiveByTemplate(template)
|
||||
local pool = self:GetPool(template);
|
||||
if pool then
|
||||
return pool:EnumerateActive();
|
||||
end
|
||||
|
||||
return nop;
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:EnumerateActive()
|
||||
local currentPoolKey, currentPool = next(self.pools, nil);
|
||||
local currentObject = nil;
|
||||
return function()
|
||||
if currentPool then
|
||||
currentObject = currentPool:GetNextActive(currentObject);
|
||||
while not currentObject do
|
||||
currentPoolKey, currentPool = next(self.pools, currentPoolKey);
|
||||
if currentPool then
|
||||
currentObject = currentPool:GetNextActive();
|
||||
else
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return currentObject;
|
||||
end, nil;
|
||||
end
|
||||
|
||||
function FramePoolCollectionMixin:EnumerateInactiveByTemplate(template)
|
||||
local pool = self:GetPool(template);
|
||||
if pool then
|
||||
return pool:EnumerateInactive();
|
||||
end
|
||||
|
||||
return nop;
|
||||
end
|
||||
|
||||
FixedSizeFramePoolCollectionMixin = CreateFromMixins(FramePoolCollectionMixin);
|
||||
|
||||
function CreateFixedSizeFramePoolCollection()
|
||||
local poolCollection = CreateFromMixins(FixedSizeFramePoolCollectionMixin);
|
||||
poolCollection:OnLoad();
|
||||
return poolCollection;
|
||||
end
|
||||
|
||||
function FixedSizeFramePoolCollectionMixin:OnLoad()
|
||||
FramePoolCollectionMixin.OnLoad(self);
|
||||
self.sizes = {};
|
||||
end
|
||||
|
||||
function FixedSizeFramePoolCollectionMixin:CreatePool(frameType, parent, template, resetterFunc, forbidden, maxPoolSize, preallocate)
|
||||
local pool = FramePoolCollectionMixin.CreatePool(self, frameType, parent, template, resetterFunc, forbidden);
|
||||
|
||||
if preallocate then
|
||||
for i = 1, maxPoolSize do
|
||||
pool:Acquire();
|
||||
end
|
||||
pool:ReleaseAll();
|
||||
end
|
||||
|
||||
self.sizes[template] = maxPoolSize;
|
||||
|
||||
return pool;
|
||||
end
|
||||
|
||||
function FixedSizeFramePoolCollectionMixin:Acquire(template)
|
||||
local pool = self:GetPool(template);
|
||||
assert(pool);
|
||||
|
||||
if pool:GetNumActive() < self.sizes[template] then
|
||||
return pool:Acquire();
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
|
||||
FontStringPoolCollectionMixin = CreateFromMixins(FramePoolCollectionMixin);
|
||||
|
||||
function CreateFontStringPoolCollection()
|
||||
local poolCollection = CreateFromMixins(FontStringPoolCollectionMixin);
|
||||
poolCollection:OnLoad();
|
||||
return poolCollection;
|
||||
end
|
||||
|
||||
function FontStringPoolCollectionMixin:GetOrCreatePool(parent, layer, subLayer, fontStringTemplate, resetterFunc)
|
||||
local pool = self:GetPool(fontStringTemplate);
|
||||
if not pool then
|
||||
pool = self:CreatePool(parent, layer, subLayer, fontStringTemplate, resetterFunc);
|
||||
end
|
||||
return pool;
|
||||
end
|
||||
|
||||
function FontStringPoolCollectionMixin:CreatePool(parent, layer, subLayer, fontStringTemplate, resetterFunc)
|
||||
assert(self:GetPool(fontStringTemplate) == nil);
|
||||
local pool = CreateFontStringPool(parent, layer, subLayer, fontStringTemplate, resetterFunc);
|
||||
self.pools[fontStringTemplate] = pool;
|
||||
return pool;
|
||||
end
|
||||
|
||||
function FontStringPoolCollectionMixin:CreatePoolIfNeeded(parent, layer, subLayer, fontStringTemplate, resetterFunc)
|
||||
if not self:GetPool(fontStringTemplate) then
|
||||
self:CreatePool(parent, layer, subLayer, fontStringTemplate, resetterFunc);
|
||||
end
|
||||
end
|
||||
|
||||
function FontStringPoolCollectionMixin:Acquire(fontStringTemplate, parent, layer, subLayer, resetterFunc)
|
||||
local pool = self:GetOrCreatePool(parent, layer, subLayer, fontStringTemplate, resetterFunc);
|
||||
local newString = pool:Acquire();
|
||||
|
||||
if parent then
|
||||
newString:SetParent(parent);
|
||||
end
|
||||
|
||||
if layer then
|
||||
newString:SetDrawLayer(layer, subLayer);
|
||||
end
|
||||
|
||||
return newString;
|
||||
end
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
local SetPortraitTexture = SetPortraitTexture
|
||||
local SetBagPortraitTexture = SetBagPortraitTexture
|
||||
|
||||
TitledPanelMixin = {};
|
||||
|
||||
function TitledPanelMixin:GetTitleText()
|
||||
return self.TitleContainer.TitleText;
|
||||
end
|
||||
|
||||
function TitledPanelMixin:SetTitleColor(color)
|
||||
self:GetTitleText():SetTextColor(color:GetRGBA());
|
||||
end
|
||||
|
||||
function TitledPanelMixin:SetTitle(title)
|
||||
self:GetTitleText():SetText(title);
|
||||
end
|
||||
|
||||
function TitledPanelMixin:SetTitleFormatted(fmt, ...)
|
||||
self:GetTitleText():SetFormattedText(fmt, ...);
|
||||
end
|
||||
|
||||
function TitledPanelMixin:SetTitleMaxLinesAndHeight(maxLines, height)
|
||||
self:GetTitleText():SetMaxLines(maxLines);
|
||||
self:GetTitleText():SetHeight(height);
|
||||
end
|
||||
|
||||
function TitledPanelMixin:SetTitleOffsets(leftOffset, rightOffset)
|
||||
self.TitleContainer:SetPoint("TOPLEFT", self, "TOPLEFT", leftOffset or 58, -1);
|
||||
self.TitleContainer:SetPoint("TOPRIGHT", self, "TOPRIGHT", rightOffset or -24, -1);
|
||||
end
|
||||
|
||||
DefaultPanelMixin = CreateFromMixins(TitledPanelMixin);
|
||||
|
||||
PortraitFrameMixin = CreateFromMixins(TitledPanelMixin);
|
||||
|
||||
function PortraitFrameMixin:GetPortrait()
|
||||
return self.portrait;
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:GetTitleText()
|
||||
return self.TitleText;
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetBorder(layoutName)
|
||||
local layout = NineSliceUtil.GetLayout(layoutName);
|
||||
NineSliceUtil.ApplyLayout(self.NineSlice, layout);
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetPortraitToAsset(texture)
|
||||
SetPortraitToTexture(self:GetPortrait(), texture);
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetPortraitToUnit(unit)
|
||||
SetPortraitTexture(self:GetPortrait(), unit);
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetPortraitToBag(bagID)
|
||||
SetBagPortraitTexture(self:GetPortrait(), bagID);
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetPortraitTextureRaw(texture)
|
||||
self:GetPortrait():SetTexture(texture);
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetPortraitAtlasRaw(atlas, ...)
|
||||
self:GetPortrait():SetAtlas(atlas, ...);
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetPortraitToClassIcon(classFilename)
|
||||
self:SetPortraitToAsset("Interface/TargetingFrame/UI-Classes-Circles");
|
||||
local left, right, bottom, top = unpack(CLASS_ICON_TCOORDS[string.upper(classFilename)]);
|
||||
self:SetPortraitTexCoord(left, right, bottom, top);
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetPortraitTexCoord(...)
|
||||
self:GetPortrait():SetTexCoord(...);
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetPortraitShown(shown)
|
||||
self:GetPortrait():SetShown(shown);
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetPortraitTextureSizeAndOffset(size, offsetX, offsetY)
|
||||
local portrait = self:GetPortrait();
|
||||
portrait:SetSize(size, size);
|
||||
portrait:SetPoint("TOPLEFT", self, "TOPLEFT", offsetX, offsetY);
|
||||
end
|
||||
|
||||
do
|
||||
local function SetFrameLevelInternal(frame, level)
|
||||
if frame then
|
||||
-- assertsafe(level < 10000, "Base level needs to be low enough to accomodate the existing layering"); -- TODO: Should become a constant
|
||||
frame:SetFrameLevel(level);
|
||||
end
|
||||
end
|
||||
|
||||
function PortraitFrameMixin:SetFrameLevelsFromBaseLevel(baseLevel)
|
||||
SetFrameLevelInternal(self.NineSlice, baseLevel + 2);
|
||||
SetFrameLevelInternal(self.PortraitContainer, baseLevel + 1);
|
||||
SetFrameLevelInternal(self.TitleContainer, baseLevel + 3);
|
||||
SetFrameLevelInternal(self.CloseButton, baseLevel + 3);
|
||||
end
|
||||
end
|
||||
|
||||
PortraitFrameFlatBaseMixin = {};
|
||||
|
||||
function PortraitFrameFlatBaseMixin:SetBackgroundColor(color)
|
||||
if self.Bg then
|
||||
local bg = self.Bg;
|
||||
color = color or PANEL_BACKGROUND_COLOR;
|
||||
local r, g, b, a = color:GetRGBA();
|
||||
bg.BottomLeft:SetVertexColor(r, g, b, a);
|
||||
bg.BottomRight:SetVertexColor(r, g, b, a);
|
||||
bg.BottomEdge:SetColorTexture(r, g, b, a);
|
||||
bg.TopSection:SetColorTexture(r, g, b, a);
|
||||
end
|
||||
end
|
||||
+660
@@ -0,0 +1,660 @@
|
||||
local function getObjTypeMeta(objType)
|
||||
local obj = CreateFrame(objType)
|
||||
obj:Hide()
|
||||
return getmetatable(obj).__index, obj
|
||||
end
|
||||
|
||||
local FrameMeta, FrameObj = getObjTypeMeta("Frame")
|
||||
local FontStringMeta = getmetatable(FrameObj:CreateFontString()).__index
|
||||
local TextureMeta = getmetatable(FrameObj:CreateTexture()).__index
|
||||
|
||||
local ButtonMeta = getObjTypeMeta("Button")
|
||||
local CheckButtonMeta = getObjTypeMeta("CheckButton")
|
||||
local EditBoxMeta = getObjTypeMeta("EditBox")
|
||||
local SimpleHTMLMeta = getObjTypeMeta("SimpleHTML")
|
||||
local SliderMeta = getObjTypeMeta("Slider")
|
||||
local StatusBarMeta = getObjTypeMeta("StatusBar")
|
||||
local ScrollFrameMeta = getObjTypeMeta("ScrollFrame")
|
||||
local MessageFrameMeta = getObjTypeMeta("MessageFrame")
|
||||
local ScrollingMessageFrameMeta = getObjTypeMeta("ScrollingMessageFrame")
|
||||
local ModelMeta = getObjTypeMeta("Model")
|
||||
--local ColorSelectMeta = createAndGetMeta("ColorSelect")
|
||||
--local MovieFrameMeta = createAndGetMeta("MovieFrame")
|
||||
|
||||
local AnimationGroup = FrameObj:CreateAnimationGroup()
|
||||
local AnimationGroupMeta = getmetatable(AnimationGroup).__index
|
||||
local AnimationAnimationMeta = getmetatable(AnimationGroup:CreateAnimation("Animation")).__index
|
||||
local AnimationAlphaMeta = getmetatable(AnimationGroup:CreateAnimation("Alpha")).__index
|
||||
local AnimationRotationMeta = getmetatable(AnimationGroup:CreateAnimation("Rotation")).__index
|
||||
local AnimationPathMeta = getmetatable(AnimationGroup:CreateAnimation("Path")).__index
|
||||
local AnimationScaleMeta = getmetatable(AnimationGroup:CreateAnimation("Scale")).__index
|
||||
local AnimationTranslationMeta = getmetatable(AnimationGroup:CreateAnimation("Translation")).__index
|
||||
|
||||
local GameTooltipMeta, PlayerModelMeta, DressUpModelMeta, TabardModelMeta, ModelFFXMeta
|
||||
|
||||
if IsOnGlueScreen() then
|
||||
ModelFFXMeta = getObjTypeMeta("ModelFFX")
|
||||
else
|
||||
GameTooltipMeta = getObjTypeMeta("GameTooltip")
|
||||
PlayerModelMeta = getObjTypeMeta("PlayerModel")
|
||||
DressUpModelMeta = getObjTypeMeta("DressUpModel")
|
||||
TabardModelMeta = getObjTypeMeta("TabardModel")
|
||||
|
||||
-- local CooldownMeta = createAndGetMeta("Cooldown")
|
||||
-- local MinimapMeta = createAndGetMeta("Minimap")
|
||||
-- local TaxiRouteFrameMeta = createAndGetMeta("TaxiRouteFrame")
|
||||
-- local QuestPOIFrameMeta = createAndGetMeta("QuestPOIFrame")
|
||||
-- local WorldFrameMeta = createAndGetMeta("WorldFrame")
|
||||
end
|
||||
|
||||
local function nop() end
|
||||
|
||||
local function ScriptRegion_SetShown(self, show)
|
||||
if show then
|
||||
self:Show()
|
||||
else
|
||||
self:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local function ScriptRegion_GetScaledRect(self)
|
||||
local left, bottom, width, height = self:GetRect()
|
||||
if left and bottom and width and height then
|
||||
local scale = self:GetEffectiveScale()
|
||||
return left * scale, bottom * scale, width * scale, height * scale
|
||||
end
|
||||
end
|
||||
|
||||
local function ScriptRegion_IsMouseOverEx(self, ignoreVisibility, checkMouseFocus)
|
||||
if ignoreVisibility or self:IsVisible() then
|
||||
local l, r, t, b = self:GetHitRectInsets()
|
||||
return self:IsMouseOver(-t, b, l, -r) and (not checkMouseFocus or self == GetMouseFocus())
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function ScriptRegionResizing_ClearAndSetPoint(self, ...)
|
||||
self:ClearAllPoints()
|
||||
self:SetPoint(...)
|
||||
end
|
||||
|
||||
local function Region_GetEffectiveScale(self)
|
||||
return self:GetParent():GetEffectiveScale()
|
||||
end
|
||||
|
||||
local function LayoutFrame_SetParentArray(self, arrayName, element, setInSelf)
|
||||
local parent = not setInSelf and self:GetParent() or self
|
||||
|
||||
if not parent[arrayName] then
|
||||
parent[arrayName] = {}
|
||||
end
|
||||
|
||||
table.insert(parent[arrayName], element or self)
|
||||
end
|
||||
|
||||
local RegisterCustomEvent = RegisterCustomEvent
|
||||
local UnregisterCustomEvent = UnregisterCustomEvent
|
||||
|
||||
local function Frame_RegisterCustomEvent(self, event)
|
||||
RegisterCustomEvent(self, event)
|
||||
end
|
||||
|
||||
local function Frame_UnregisterCustomEvent(self, event)
|
||||
UnregisterCustomEvent(self, event)
|
||||
end
|
||||
|
||||
local function FontString_SetDesaturated(self, toggle, color)
|
||||
if toggle then
|
||||
self:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b)
|
||||
else
|
||||
if type(color) == "table" then
|
||||
self:SetTextColor(color.r, color.g, color.b)
|
||||
else
|
||||
self:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local SECONDS_PER_DAY = 86400
|
||||
local function FontString_SetRemainingTime(self, seconds, daysformat)
|
||||
if type(seconds) ~= "number" then
|
||||
self:SetText("")
|
||||
return
|
||||
end
|
||||
|
||||
if daysformat then
|
||||
if seconds >= SECONDS_PER_DAY then
|
||||
self:SetFormattedText(D_DAYS_FULL, math.floor(seconds / SECONDS_PER_DAY))
|
||||
else
|
||||
self:SetText(date("!%X", seconds))
|
||||
end
|
||||
elseif seconds >= SECONDS_PER_DAY then
|
||||
local days = string.format(DAY_ONELETTER_ABBR_SHORT, math.floor(seconds / SECONDS_PER_DAY))
|
||||
self:SetFormattedText("%s %s", days, date("!%X", seconds % SECONDS_PER_DAY))
|
||||
elseif seconds >= 0 then
|
||||
self:SetText(date("!%X", seconds))
|
||||
else
|
||||
self:SetText("")
|
||||
end
|
||||
end
|
||||
|
||||
local function Texture_SetSubTexCoord(self, left, right, top, bottom)
|
||||
local ULx, ULy, LLx, LLy, URx, URy, LRx, LRy = self:GetTexCoord()
|
||||
|
||||
local leftedge = ULx
|
||||
local rightedge = URx
|
||||
local topedge = ULy
|
||||
local bottomedge = LLy
|
||||
|
||||
local width = rightedge - leftedge
|
||||
local height = bottomedge - topedge
|
||||
|
||||
leftedge = ULx + width * left
|
||||
topedge = ULy + height * top
|
||||
rightedge = math.max(rightedge * right, ULx)
|
||||
bottomedge = math.max(bottomedge * bottom, ULy)
|
||||
|
||||
ULx = leftedge
|
||||
ULy = topedge
|
||||
LLx = leftedge
|
||||
LLy = bottomedge
|
||||
URx = rightedge
|
||||
URy = topedge
|
||||
LRx = rightedge
|
||||
LRy = bottomedge
|
||||
|
||||
self:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy)
|
||||
end
|
||||
|
||||
local ATLAS_FIELD_WIDTH = 1
|
||||
local ATLAS_FIELD_HEIGHT = 2
|
||||
local ATLAS_FIELD_LEFT = 3
|
||||
local ATLAS_FIELD_RIGHT = 4
|
||||
local ATLAS_FIELD_TOP = 5
|
||||
local ATLAS_FIELD_BOTTOM = 6
|
||||
local ATLAS_FIELD_TILESHORIZ = 7
|
||||
local ATLAS_FIELD_TILESVERT = 8
|
||||
local ATLAS_FIELD_TEXTUREPATH = 9
|
||||
|
||||
local S_ATLAS_STORAGE = S_ATLAS_STORAGE
|
||||
|
||||
local function Texture_SetAtlas(self, atlasName, useAtlasSize, filterMode)
|
||||
if type(self) ~= "table" then
|
||||
error("Attempt to find 'this' in non-table object (used '.' instead of ':' ?)", 3)
|
||||
elseif type(atlasName) ~= "string" then
|
||||
error(string.format("Usage: %s:SetAtlas(\"atlasName\"[, useAtlasSize])", self:GetName() or tostring(self)), 3)
|
||||
end
|
||||
|
||||
local atlas = S_ATLAS_STORAGE[atlasName]
|
||||
if not atlas then
|
||||
error(string.format("%s:SetAtlas: Atlas %s does not exist", self:GetName() or tostring(self), atlasName), 3)
|
||||
end
|
||||
|
||||
local success = self:SetTexture(atlas[ATLAS_FIELD_TEXTUREPATH] or "", atlas[ATLAS_FIELD_TILESHORIZ], atlas[ATLAS_FIELD_TILESVERT])
|
||||
if success then
|
||||
if useAtlasSize then
|
||||
self:SetWidth(atlas[ATLAS_FIELD_WIDTH])
|
||||
self:SetHeight(atlas[ATLAS_FIELD_HEIGHT])
|
||||
end
|
||||
|
||||
self:SetTexCoord(atlas[ATLAS_FIELD_LEFT], atlas[ATLAS_FIELD_RIGHT], atlas[ATLAS_FIELD_TOP], atlas[ATLAS_FIELD_BOTTOM])
|
||||
|
||||
self:SetHorizTile(atlas[ATLAS_FIELD_TILESHORIZ])
|
||||
self:SetVertTile(atlas[ATLAS_FIELD_TILESVERT])
|
||||
end
|
||||
|
||||
return success
|
||||
end
|
||||
|
||||
local function Texture_SetPortrait(self, displayID)
|
||||
local portrait = strconcat("Interface\\PORTRAITS\\Portrait_model_", tonumber(displayID))
|
||||
local success = self:SetTexture(portrait)
|
||||
return success
|
||||
end
|
||||
|
||||
local function Button_SetEnabled(self, enabled)
|
||||
if enabled then
|
||||
self:Enable()
|
||||
else
|
||||
self:Disable()
|
||||
end
|
||||
end
|
||||
|
||||
local function Button_SetNormalAtlas(self, atlasName, useAtlasSize, filterMode)
|
||||
local texture = self:GetNormalTexture()
|
||||
if not texture then
|
||||
self:SetNormalTexture("")
|
||||
texture = self:GetNormalTexture()
|
||||
end
|
||||
Texture_SetAtlas(texture, atlasName, useAtlasSize, filterMode)
|
||||
end
|
||||
|
||||
local function Button_SetPushedAtlas(self, atlasName, useAtlasSize, filterMode)
|
||||
local texture = self:GetPushedTexture()
|
||||
if not texture then
|
||||
self:SetPushedTexture("")
|
||||
texture = self:GetPushedTexture()
|
||||
end
|
||||
Texture_SetAtlas(texture, atlasName, useAtlasSize, filterMode)
|
||||
end
|
||||
|
||||
local function Button_SetDisabledAtlas(self, atlasName, useAtlasSize, filterMode)
|
||||
local texture = self:GetDisabledTexture()
|
||||
if not texture then
|
||||
self:SetDisabledTexture("")
|
||||
texture = self:GetDisabledTexture()
|
||||
end
|
||||
Texture_SetAtlas(texture, atlasName, useAtlasSize, filterMode)
|
||||
end
|
||||
|
||||
local function Button_SetHighlightAtlas(self, atlasName, useAtlasSize, filterMode)
|
||||
local texture = self:GetHighlightTexture()
|
||||
if not texture then
|
||||
self:SetHighlightTexture("")
|
||||
texture = self:GetHighlightTexture()
|
||||
end
|
||||
Texture_SetAtlas(texture, atlasName, useAtlasSize, filterMode)
|
||||
end
|
||||
|
||||
local function Button_ClearNormalTexture(self)
|
||||
self:SetNormalTexture("")
|
||||
end
|
||||
|
||||
local function Button_ClearPushedTexture(self)
|
||||
self:SetPushedTexture("")
|
||||
end
|
||||
|
||||
local function Button_ClearDisabledTexture(self)
|
||||
self:SetDisabledTexture("")
|
||||
end
|
||||
|
||||
local function Button_ClearHighlightTexture(self)
|
||||
self:SetHighlightTexture("")
|
||||
end
|
||||
|
||||
local function CheckButton_SetCheckedAtlas(self, atlasName, useAtlasSize, filterMode)
|
||||
local texture = self:GetCheckedTexture()
|
||||
if not texture then
|
||||
self:SetCheckedTexture("")
|
||||
texture = self:GetCheckedTexture()
|
||||
end
|
||||
Texture_SetAtlas(texture, atlasName, useAtlasSize, filterMode)
|
||||
end
|
||||
|
||||
local function CheckButton_SetDisabledCheckedAtlas(self, atlasName, useAtlasSize, filterMode)
|
||||
local texture = self:GetDisabledCheckedTexture()
|
||||
if not texture then
|
||||
self:SetDisabledCheckedTexture("")
|
||||
texture = self:GetDisabledCheckedTexture()
|
||||
end
|
||||
Texture_SetAtlas(texture, atlasName, useAtlasSize, filterMode)
|
||||
end
|
||||
|
||||
local function CheckButton_ClearCheckedTexture(self)
|
||||
self:SetCheckedTexture("")
|
||||
end
|
||||
|
||||
local function CheckButton_ClearDisabledCheckedTexture(self)
|
||||
self:SetDisabledCheckedTexture("")
|
||||
end
|
||||
|
||||
local function EditBox_IsEnabled(self)
|
||||
return self.__ext_Disabled ~= true
|
||||
end
|
||||
|
||||
local function EditBox_Enabled(self)
|
||||
if self.__ext_mouseEnabled then
|
||||
self:EnableMouse(true)
|
||||
end
|
||||
if self.__ext_autoFocus then
|
||||
self:SetAutoFocus(true)
|
||||
self:SetFocus()
|
||||
self:HighlightText(0, 0)
|
||||
end
|
||||
self.SetFocus = nil
|
||||
self.__ext_Disabled = nil
|
||||
self.__ext_autoFocus = nil
|
||||
self.__ext_mouseEnabled = nil
|
||||
end
|
||||
|
||||
local function EditBox_Disable(self)
|
||||
if not self.__ext_Disabled then
|
||||
self.__ext_autoFocus = self:IsAutoFocus() == 1
|
||||
self.__ext_mouseEnabled = self:IsMouseEnabled() == 1
|
||||
end
|
||||
self:SetAutoFocus(false)
|
||||
self:ClearFocus()
|
||||
self:EnableMouse(false)
|
||||
self.SetFocus = nop
|
||||
self.__ext_Disabled = true
|
||||
end
|
||||
|
||||
local function PlayerModel_UpdateModelEffects(self)
|
||||
self:ResetAllSpells()
|
||||
|
||||
do -- 3D armor
|
||||
local displayIDs = self:GetDisplayIDs()
|
||||
if displayIDs then
|
||||
for index, displayID in ipairs(displayIDs) do
|
||||
if displayID ~= 0 then
|
||||
local spellID = ITEMS_WITH_3D[displayID]
|
||||
if spellID then
|
||||
self:SetSpell(spellID)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do -- customizations
|
||||
if not self.__hideCustomizations then
|
||||
local guid = self.__unitGUID
|
||||
if guid and guid == UnitGUID("player") then
|
||||
local activeCustomizationItems = C_CustomizationsCollection.GetActiveCustomizationItems(1)
|
||||
if activeCustomizationItems then
|
||||
for index, customizationItemID in ipairs(activeCustomizationItems) do
|
||||
local spellID = C_CustomizationsCollection.GetCustomizationSpellByItem(customizationItemID)
|
||||
if spellID then
|
||||
if spellID == 320799 then
|
||||
local SPELL_EFFECTS_GIFT_OF_MOST_PRECIOUS = {313589, 313590, 313591, 313592, 313593, 313594}
|
||||
spellID = SPELL_EFFECTS_GIFT_OF_MOST_PRECIOUS[math.random(1, #SPELL_EFFECTS_GIFT_OF_MOST_PRECIOUS)]
|
||||
end
|
||||
self:SetSpell(spellID)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function PlayerModel_SetUnit(self, unit, isCustomPosition, positionData)
|
||||
if type(unit) ~= "string" then
|
||||
error("Usage: SetUnit(\"unit\")", 2)
|
||||
end
|
||||
|
||||
local objectType = self:GetObjectType()
|
||||
if objectType == "PlayerModel" then
|
||||
self:SetUnitRaw(unit)
|
||||
return
|
||||
end
|
||||
|
||||
if isCustomPosition then
|
||||
if objectType == "TabardModel" then
|
||||
self:SetPosition(0, 0, 0)
|
||||
else
|
||||
self:SetPosition(1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
self:SetUnitRaw(unit)
|
||||
|
||||
self.__hideCustomizations = nil
|
||||
self.__unitGUID = UnitGUID(unit)
|
||||
|
||||
PlayerModel_UpdateModelEffects(self)
|
||||
|
||||
if isCustomPosition then
|
||||
local unitSex = UnitSex(unit) or 2
|
||||
local _, unitRace = UnitRace(unit)
|
||||
local positionStorage = positionData or (objectType == "TabardModel" and TABARDMODEL_CAMERA_POSITION or DRESSUPMODEL_CAMERA_POSITION)
|
||||
local data = positionStorage[string.format("%s%d", unitRace or "Human", unitSex)]
|
||||
|
||||
if data then
|
||||
local positionX, positionY, positionZ, facing = unpack(data, 1, 4)
|
||||
self.basePositionOverrideX = positionX
|
||||
self.basePositionOverrideY = positionY
|
||||
self.basePositionOverrideZ = positionZ
|
||||
self.basePositionOverrideXasZ = true
|
||||
self:SetPosition(positionX or 0, positionY or 0, positionZ or 0)
|
||||
|
||||
if facing then
|
||||
self:SetFacing(math.rad(facing))
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self.basePositionOverrideX = nil
|
||||
self.basePositionOverrideY = nil
|
||||
self.basePositionOverrideZ = nil
|
||||
self.basePositionOverrideXasZ = nil
|
||||
end
|
||||
|
||||
local function PlayerModel_RefreshUnit(self)
|
||||
self:RefreshUnitRaw()
|
||||
|
||||
local objectType = self:GetObjectType()
|
||||
if objectType == "DressUpModel" or objectType == "TabardModel" then
|
||||
self.__hideCustomizations = nil
|
||||
PlayerModel_UpdateModelEffects(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function DressUpModel_Dress(self)
|
||||
self:DressRaw()
|
||||
self.__hideCustomizations = nil
|
||||
PlayerModel_UpdateModelEffects(self)
|
||||
end
|
||||
|
||||
local function DressUpModel_Undress(self)
|
||||
self:UndressRaw()
|
||||
self.__hideCustomizations = true
|
||||
PlayerModel_UpdateModelEffects(self)
|
||||
end
|
||||
|
||||
local function DressUpModel_TryOn(self, item)
|
||||
if C_CustomizationsCollection.CanPreviewCustomizationInDressUp(item) then
|
||||
local spellID, category, subcategory = C_CustomizationsCollection.GetCustomizationSpellByItem(item)
|
||||
if spellID then
|
||||
PlayerModel_UpdateModelEffects(self)
|
||||
|
||||
for index, activeSpellID in ipairs({self:GetAllSpells()}) do
|
||||
local isCustomizationSpell, activeSpellCategory, activeSpellSubCategory = C_CustomizationsCollection.IsCustomizationSpell(activeSpellID)
|
||||
if isCustomizationSpell and category == activeSpellCategory and subcategory == activeSpellSubCategory then
|
||||
self:ResetSpell(activeSpellID)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if spellID == 320799 then
|
||||
local SPELL_EFFECTS_GIFT_OF_MOST_PRECIOUS = {313589, 313590, 313591, 313592, 313593, 313594}
|
||||
spellID = SPELL_EFFECTS_GIFT_OF_MOST_PRECIOUS[math.random(1, #SPELL_EFFECTS_GIFT_OF_MOST_PRECIOUS)]
|
||||
end
|
||||
|
||||
self:SetSpell(spellID)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
self:TryOnRaw(item)
|
||||
PlayerModel_UpdateModelEffects(self)
|
||||
end
|
||||
|
||||
local function Animation_Restart(self)
|
||||
if self:IsPlaying() then
|
||||
self:Stop()
|
||||
end
|
||||
self:Play()
|
||||
end
|
||||
|
||||
FrameMeta.SetShown = ScriptRegion_SetShown
|
||||
FrameMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
FrameMeta.IsMouseOverEx = ScriptRegion_IsMouseOverEx
|
||||
FrameMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
FrameMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
FrameMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
FrameMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
|
||||
FontStringMeta.SetShown = ScriptRegion_SetShown
|
||||
FontStringMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
FontStringMeta.GetEffectiveScale = Region_GetEffectiveScale
|
||||
FontStringMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
FontStringMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
FontStringMeta.SetDesaturated = FontString_SetDesaturated
|
||||
FontStringMeta.SetRemainingTime = FontString_SetRemainingTime
|
||||
|
||||
TextureMeta.SetShown = ScriptRegion_SetShown
|
||||
TextureMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
TextureMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
TextureMeta.GetEffectiveScale = Region_GetEffectiveScale
|
||||
TextureMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
TextureMeta.SetSubTexCoord = Texture_SetSubTexCoord
|
||||
TextureMeta.SetAtlas = Texture_SetAtlas
|
||||
TextureMeta.SetPortrait = Texture_SetPortrait
|
||||
|
||||
ButtonMeta.SetShown = ScriptRegion_SetShown
|
||||
ButtonMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
ButtonMeta.IsMouseOverEx = ScriptRegion_IsMouseOverEx
|
||||
ButtonMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
ButtonMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
ButtonMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
ButtonMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
ButtonMeta.SetEnabled = Button_SetEnabled
|
||||
ButtonMeta.SetNormalAtlas = Button_SetNormalAtlas
|
||||
ButtonMeta.SetPushedAtlas = Button_SetPushedAtlas
|
||||
ButtonMeta.SetDisabledAtlas = Button_SetDisabledAtlas
|
||||
ButtonMeta.SetHighlightAtlas = Button_SetHighlightAtlas
|
||||
ButtonMeta.ClearClearNormalTexture = Button_ClearNormalTexture
|
||||
ButtonMeta.ClearPushedTexture = Button_ClearPushedTexture
|
||||
ButtonMeta.ClearDisabledTexture = Button_ClearDisabledTexture
|
||||
ButtonMeta.ClearHighlightTexture = Button_ClearHighlightTexture
|
||||
|
||||
CheckButtonMeta.SetShown = ScriptRegion_SetShown
|
||||
CheckButtonMeta.IsMouseOverEx = ScriptRegion_IsMouseOverEx
|
||||
CheckButtonMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
CheckButtonMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
CheckButtonMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
CheckButtonMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
CheckButtonMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
CheckButtonMeta.SetEnabled = Button_SetEnabled
|
||||
CheckButtonMeta.SetNormalAtlas = Button_SetNormalAtlas
|
||||
CheckButtonMeta.SetPushedAtlas = Button_SetPushedAtlas
|
||||
CheckButtonMeta.SetDisabledAtlas = Button_SetDisabledAtlas
|
||||
CheckButtonMeta.SetHighlightAtlas = Button_SetHighlightAtlas
|
||||
CheckButtonMeta.SetCheckedAtlas = CheckButton_SetCheckedAtlas
|
||||
CheckButtonMeta.SetDisabledCheckedAtlas = CheckButton_SetDisabledCheckedAtlas
|
||||
CheckButtonMeta.ClearClearNormalTexture = Button_ClearNormalTexture
|
||||
CheckButtonMeta.ClearPushedTexture = Button_ClearPushedTexture
|
||||
CheckButtonMeta.ClearDisabledTexture = Button_ClearDisabledTexture
|
||||
CheckButtonMeta.ClearHighlightTexture = Button_ClearHighlightTexture
|
||||
CheckButtonMeta.ClearDisabledCheckedTexture = CheckButton_ClearCheckedTexture
|
||||
CheckButtonMeta.ClearDisabledCheckedTexture = CheckButton_ClearDisabledCheckedTexture
|
||||
|
||||
EditBoxMeta.SetShown = ScriptRegion_SetShown
|
||||
EditBoxMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
EditBoxMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
EditBoxMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
EditBoxMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
EditBoxMeta.SetEnabled = Button_SetEnabled
|
||||
EditBoxMeta.IsEnabled = EditBox_IsEnabled
|
||||
EditBoxMeta.Enable = EditBox_Enabled
|
||||
EditBoxMeta.Disable = EditBox_Disable
|
||||
|
||||
SimpleHTMLMeta.SetShown = ScriptRegion_SetShown
|
||||
SimpleHTMLMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
SimpleHTMLMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
SimpleHTMLMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
SimpleHTMLMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
SimpleHTMLMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
|
||||
SliderMeta.SetShown = ScriptRegion_SetShown
|
||||
SliderMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
SliderMeta.IsMouseOverEx = ScriptRegion_IsMouseOverEx
|
||||
SliderMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
SliderMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
SliderMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
SliderMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
SliderMeta.SetEnabled = Button_SetEnabled
|
||||
|
||||
StatusBarMeta.SetShown = ScriptRegion_SetShown
|
||||
StatusBarMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
StatusBarMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
StatusBarMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
StatusBarMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
StatusBarMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
|
||||
ScrollFrameMeta.SetShown = ScriptRegion_SetShown
|
||||
ScrollFrameMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
ScrollFrameMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
ScrollFrameMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
ScrollFrameMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
ScrollFrameMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
|
||||
MessageFrameMeta.SetShown = ScriptRegion_SetShown
|
||||
MessageFrameMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
MessageFrameMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
MessageFrameMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
MessageFrameMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
MessageFrameMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
|
||||
ScrollingMessageFrameMeta.SetShown = ScriptRegion_SetShown
|
||||
ScrollingMessageFrameMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
ScrollingMessageFrameMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
ScrollingMessageFrameMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
ScrollingMessageFrameMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
ScrollingMessageFrameMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
|
||||
ModelMeta.SetShown = ScriptRegion_SetShown
|
||||
ModelMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
ModelMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
ModelMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
ModelMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
|
||||
AnimationGroupMeta.Restart = Animation_Restart
|
||||
AnimationAnimationMeta.Restart = Animation_Restart
|
||||
AnimationAlphaMeta.Restart = Animation_Restart
|
||||
AnimationRotationMeta.Restart = Animation_Restart
|
||||
AnimationPathMeta.Restart = Animation_Restart
|
||||
AnimationScaleMeta.Restart = Animation_Restart
|
||||
AnimationTranslationMeta.Restart = Animation_Restart
|
||||
|
||||
if IsOnGlueScreen() then
|
||||
ModelFFXMeta.SetShown = ScriptRegion_SetShown
|
||||
ModelFFXMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
ModelFFXMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
else
|
||||
GameTooltipMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
GameTooltipMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
GameTooltipMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
|
||||
PlayerModelMeta.SetShown = ScriptRegion_SetShown
|
||||
PlayerModelMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
PlayerModelMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
PlayerModelMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
PlayerModelMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
PlayerModelMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
PlayerModelMeta.SetUnitRaw = PlayerModelMeta.SetUnit
|
||||
PlayerModelMeta.SetUnit = PlayerModel_SetUnit
|
||||
PlayerModelMeta.RefreshUnitRaw = PlayerModelMeta.RefreshUnit
|
||||
PlayerModelMeta.RefreshUnit = PlayerModel_RefreshUnit
|
||||
|
||||
DressUpModelMeta.SetShown = ScriptRegion_SetShown
|
||||
DressUpModelMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
DressUpModelMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
DressUpModelMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
DressUpModelMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
DressUpModelMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
DressUpModelMeta.SetUnitRaw = DressUpModelMeta.SetUnit
|
||||
DressUpModelMeta.SetUnit = PlayerModel_SetUnit
|
||||
DressUpModelMeta.RefreshUnitRaw = DressUpModelMeta.RefreshUnit
|
||||
DressUpModelMeta.RefreshUnit = PlayerModel_RefreshUnit
|
||||
DressUpModelMeta.TryOnRaw = DressUpModelMeta.TryOn
|
||||
DressUpModelMeta.TryOn = DressUpModel_TryOn
|
||||
DressUpModelMeta.DressRaw = DressUpModelMeta.Dress
|
||||
DressUpModelMeta.Dress = DressUpModel_Dress
|
||||
DressUpModelMeta.UndressRaw = DressUpModelMeta.Undress
|
||||
DressUpModelMeta.Undress = DressUpModel_Undress
|
||||
|
||||
TabardModelMeta.SetShown = ScriptRegion_SetShown
|
||||
TabardModelMeta.GetScaledRect = ScriptRegion_GetScaledRect
|
||||
TabardModelMeta.ClearAndSetPoint = ScriptRegionResizing_ClearAndSetPoint
|
||||
TabardModelMeta.SetParentArray = LayoutFrame_SetParentArray
|
||||
TabardModelMeta.RegisterCustomEvent = Frame_RegisterCustomEvent
|
||||
TabardModelMeta.UnregisterCustomEvent = Frame_UnregisterCustomEvent
|
||||
TabardModelMeta.SetUnitRaw = TabardModelMeta.SetUnit
|
||||
TabardModelMeta.SetUnit = PlayerModel_SetUnit
|
||||
TabardModelMeta.RefreshUnitRaw = TabardModelMeta.RefreshUnit
|
||||
TabardModelMeta.RefreshUnit = PlayerModel_RefreshUnit
|
||||
TabardModelMeta.SetSpell = function() end
|
||||
end
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
local function SetupTextFont(fontString, fontObject)
|
||||
if fontString and fontObject then
|
||||
fontString:SetFontObject(fontObject);
|
||||
end
|
||||
end
|
||||
|
||||
function SharedTooltip_OnLoad(self)
|
||||
local style = nil;
|
||||
local isEmbedded = false;
|
||||
SharedTooltip_SetBackdropStyle(self, style, isEmbedded);
|
||||
self:SetClampRectInsets(0, 0, 15, 0);
|
||||
|
||||
SetupTextFont(self.TextLeft1, self.textLeft1Font);
|
||||
SetupTextFont(self.TextRight1, self.textRight1Font);
|
||||
SetupTextFont(self.TextLeft2, self.textLeft2Font);
|
||||
SetupTextFont(self.TextRight2, self.textRight2Font);
|
||||
end
|
||||
|
||||
function SharedTooltip_OnHide(self)
|
||||
self:SetPadding(0, 0, 0, 0);
|
||||
end
|
||||
|
||||
local DEFAULT_TOOLTIP_OFFSET_X = -17;
|
||||
local DEFAULT_TOOLTIP_OFFSET_Y = 70;
|
||||
|
||||
function SharedTooltip_SetDefaultAnchor(tooltip, parent)
|
||||
tooltip:SetOwner(parent or GetAppropriateTopLevelParent(), "ANCHOR_NONE");
|
||||
tooltip:SetPoint("BOTTOMRIGHT", GetAppropriateTopLevelParent(), "BOTTOMRIGHT", DEFAULT_TOOLTIP_OFFSET_X, DEFAULT_TOOLTIP_OFFSET_Y);
|
||||
end
|
||||
|
||||
function SharedTooltip_ClearInsertedFrames(self)
|
||||
if self.insertedFrames then
|
||||
for i = 1, #self.insertedFrames do
|
||||
self.insertedFrames[i]:Hide();
|
||||
end
|
||||
end
|
||||
self.insertedFrames = nil;
|
||||
end
|
||||
|
||||
function SharedTooltip_SetBackdropStyle(self, style, embedded)
|
||||
if embedded or self.IsEmbedded then
|
||||
self:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b, 0)
|
||||
self:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b, 0);
|
||||
else
|
||||
self:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b, 1);
|
||||
self:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b, 1);
|
||||
end
|
||||
|
||||
if self.TopOverlay then
|
||||
if style and style.overlayAtlasTop then
|
||||
self.TopOverlay:SetAtlas(style.overlayAtlasTop, true);
|
||||
self.TopOverlay:SetScale(style.overlayAtlasTopScale or 1.0);
|
||||
self.TopOverlay:SetPoint("CENTER", self, "TOP", style.overlayAtlasTopXOffset or 0, style.overlayAtlasTopYOffset or 0);
|
||||
self.TopOverlay:Show();
|
||||
else
|
||||
self.TopOverlay:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
if self.BottomOverlay then
|
||||
if style and style.overlayAtlasBottom then
|
||||
self.BottomOverlay:SetAtlas(style.overlayAtlasBottom, true);
|
||||
self.BottomOverlay:SetScale(style.overlayAtlasBottomScale or 1.0);
|
||||
self.BottomOverlay:SetPoint("CENTER", self, "BOTTOM", style.overlayAtlasBottomXOffset or 0, style.overlayAtlasBottomYOffset or 0);
|
||||
self.BottomOverlay:Show();
|
||||
else
|
||||
self.BottomOverlay:Hide();
|
||||
end
|
||||
end
|
||||
|
||||
if style and style.padding then
|
||||
self:SetPadding(style.padding.right, style.padding.bottom, style.padding.left, style.padding.top);
|
||||
end
|
||||
end
|
||||
|
||||
function GameTooltip_AddBlankLinesToTooltip(tooltip, numLines)
|
||||
if numLines ~= nil then
|
||||
for i = 1, numLines do
|
||||
tooltip:AddLine(" ");
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function GameTooltip_AddBlankLineToTooltip(tooltip)
|
||||
GameTooltip_AddBlankLinesToTooltip(tooltip, 1);
|
||||
end
|
||||
|
||||
function GameTooltip_SetTitle(tooltip, text, overrideColor, wrap)
|
||||
local titleColor = overrideColor or HIGHLIGHT_FONT_COLOR;
|
||||
local r, g, b, a = titleColor:GetRGBA();
|
||||
if wrap == nil then
|
||||
wrap = 1;
|
||||
end
|
||||
tooltip:SetText(text, r, g, b, a, wrap);
|
||||
end
|
||||
|
||||
function GameTooltip_ShowDisabledTooltip(tooltip, owner, text, tooltipAnchor)
|
||||
tooltip:SetOwner(owner, tooltipAnchor);
|
||||
|
||||
local wrap = 1;
|
||||
GameTooltip_SetTitle(tooltip, text, RED_FONT_COLOR, wrap);
|
||||
|
||||
tooltip:Show();
|
||||
end
|
||||
|
||||
function GameTooltip_AddNormalLine(tooltip, text, wrap, leftOffset)
|
||||
GameTooltip_AddColoredLine(tooltip, text, NORMAL_FONT_COLOR, wrap, leftOffset);
|
||||
end
|
||||
|
||||
function GameTooltip_AddHighlightLine(tooltip, text, wrap, leftOffset)
|
||||
GameTooltip_AddColoredLine(tooltip, text, HIGHLIGHT_FONT_COLOR, wrap, leftOffset);
|
||||
end
|
||||
|
||||
function GameTooltip_AddInstructionLine(tooltip, text, wrap, leftOffset)
|
||||
GameTooltip_AddColoredLine(tooltip, text, GREEN_FONT_COLOR, wrap, leftOffset);
|
||||
end
|
||||
|
||||
function GameTooltip_AddErrorLine(tooltip, text, wrap, leftOffset)
|
||||
GameTooltip_AddColoredLine(tooltip, text, RED_FONT_COLOR, wrap, leftOffset);
|
||||
end
|
||||
|
||||
function GameTooltip_AddDisabledLine(tooltip, text, wrap, leftOffset)
|
||||
GameTooltip_AddColoredLine(tooltip, text, DISABLED_FONT_COLOR, wrap, leftOffset);
|
||||
end
|
||||
|
||||
function GameTooltip_AddColoredLine(tooltip, text, color, wrap, leftOffset)
|
||||
local r, g, b = color:GetRGB();
|
||||
if wrap == nil then
|
||||
wrap = 1;
|
||||
end
|
||||
tooltip:AddLine(text, r, g, b, wrap, leftOffset);
|
||||
end
|
||||
|
||||
function GameTooltip_AddColoredDoubleLine(tooltip, leftText, rightText, leftColor, rightColor, wrap)
|
||||
local leftR, leftG, leftB = leftColor:GetRGB();
|
||||
local rightR, rightG, rightB = rightColor:GetRGB();
|
||||
if wrap == nil then
|
||||
wrap = 1;
|
||||
end
|
||||
tooltip:AddDoubleLine(leftText, rightText, leftR, leftG, leftB, rightR, rightG, rightB, wrap);
|
||||
end
|
||||
|
||||
function GameTooltip_InsertFrame(tooltipFrame, frame, verticalPadding)
|
||||
verticalPadding = verticalPadding or 0;
|
||||
|
||||
local textSpacing = 2;
|
||||
local textHeight = Round(_G[tooltipFrame:GetName().."TextLeft2"]:GetLineHeight());
|
||||
local neededHeight = Round(frame:GetHeight() + verticalPadding);
|
||||
local numLinesNeeded = math.ceil(neededHeight / (textHeight + textSpacing));
|
||||
local currentLine = tooltipFrame:NumLines();
|
||||
GameTooltip_AddBlankLinesToTooltip(tooltipFrame, numLinesNeeded);
|
||||
frame:SetParent(tooltipFrame);
|
||||
frame:ClearAllPoints();
|
||||
frame:SetPoint("TOPLEFT", tooltipFrame:GetName().."TextLeft"..(currentLine + 1), "TOPLEFT", 0, -verticalPadding);
|
||||
if not tooltipFrame.insertedFrames then
|
||||
tooltipFrame.insertedFrames = { };
|
||||
end
|
||||
local frameWidth = frame:GetWidth();
|
||||
if tooltipFrame:GetMinimumWidth() < frameWidth then
|
||||
tooltipFrame:SetMinimumWidth(frameWidth);
|
||||
end
|
||||
frame:Show();
|
||||
tinsert(tooltipFrame.insertedFrames, frame);
|
||||
-- return space taken so inserted frame can resize if needed
|
||||
return (numLinesNeeded * textHeight) + (numLinesNeeded - 1) * textSpacing;
|
||||
end
|
||||
|
||||
DisabledTooltipButtonMixin = {};
|
||||
|
||||
function DisabledTooltipButtonMixin:OnEnter()
|
||||
if not self:IsEnabled() then
|
||||
local disabledTooltip, disabledTooltipAnchor = self:GetDisabledTooltip();
|
||||
if disabledTooltip ~= nil then
|
||||
GameTooltip_ShowDisabledTooltip(GetAppropriateTooltip(), self, disabledTooltip, disabledTooltipAnchor);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function DisabledTooltipButtonMixin:OnLeave()
|
||||
local tooltip = GetAppropriateTooltip();
|
||||
tooltip:Hide();
|
||||
end
|
||||
|
||||
function DisabledTooltipButtonMixin:SetDisabledTooltip(disabledTooltip, disabledTooltipAnchor)
|
||||
self.disabledTooltip = disabledTooltip;
|
||||
self.disabledTooltipAnchor = disabledTooltipAnchor;
|
||||
end
|
||||
|
||||
function DisabledTooltipButtonMixin:GetDisabledTooltip()
|
||||
return self.disabledTooltip, self.disabledTooltipAnchor;
|
||||
end
|
||||
|
||||
function DisabledTooltipButtonMixin:SetDisabledState(disabled, disabledTooltip, disabledTooltipAnchor)
|
||||
self:SetEnabled(not disabled);
|
||||
self:SetDisabledTooltip(disabledTooltip, disabledTooltipAnchor);
|
||||
end
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="SharedTooltipTemplates.lua"/>
|
||||
|
||||
<FontString name="TooltipTextLeftTemplate" inherits="GameTooltipText" justifyH="LEFT" hidden="true" virtual="true"/>
|
||||
<FontString name="TooltipTextRightTemplate" inherits="GameTooltipText" justifyH="RIGHT" hidden="true" virtual="true"/>
|
||||
|
||||
<Texture name="TooltipTextureTemplate" hidden="true" virtual="true">
|
||||
<Size x="12" y="12"/>
|
||||
</Texture>
|
||||
|
||||
<GameTooltip name="SharedTooltipTemplate" clampedToScreen="true" frameStrata="TOOLTIP" hidden="true" virtual="true">
|
||||
<Attributes>
|
||||
<Attribute name="textLeft1Font" value="GameTooltipHeaderText" type="string"/>
|
||||
<Attribute name="textRight1Font" value="GameTooltipHeaderText" type="string"/>
|
||||
<Attribute name="textLeft2Font" value="GameTooltipText" type="string"/>
|
||||
<Attribute name="textRight2Font" value="GameTooltipText" type="string"/>
|
||||
<Attribute name="layoutType" value="TooltipDefaultLayout" type="string"/>
|
||||
</Attributes>
|
||||
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
|
||||
<EdgeSize>
|
||||
<AbsValue val="16"/>
|
||||
</EdgeSize>
|
||||
<TileSize>
|
||||
<AbsValue val="16"/>
|
||||
</TileSize>
|
||||
<BackgroundInsets>
|
||||
<AbsInset left="5" right="5" top="5" bottom="5"/>
|
||||
</BackgroundInsets>
|
||||
</Backdrop>
|
||||
<Layers>
|
||||
<Layer level="OVERLAY">
|
||||
<Texture parentKey="TopOverlay" hidden="true">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativePoint="TOP" />
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<Texture parentKey="BottomOverlay" hidden="true">
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativePoint="BOTTOM" />
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
<Layer level="ARTWORK">
|
||||
<FontString name="$parentTextLeft1" parentKey="TextLeft1" inherits="TooltipTextLeftTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" x="10" y="-10"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
<FontString name="$parentTextRight1" parentKey="TextRight1" inherits="TooltipTextRightTemplate" justifyH="LEFT">
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parentTextLeft1" relativePoint="LEFT" x="40" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
<FontString name="$parentTextLeft2" parentKey="TextLeft2" inherits="TooltipTextLeftTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentTextLeft1" relativePoint="BOTTOMLEFT" x="0" y="-2"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
<FontString name="$parentTextRight2" parentKey="TextRight2" inherits="TooltipTextRightTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parentTextLeft2" relativePoint="LEFT" x="40" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
<Texture name="$parentTexture1" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture2" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture3" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture4" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture5" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture6" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture7" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture8" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture9" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture10" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture11" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture12" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture13" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture14" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture15" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture16" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture17" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture18" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture19" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture20" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture21" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture22" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture23" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture24" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture25" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture26" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture27" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture28" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture29" inherits="TooltipTextureTemplate"/>
|
||||
<Texture name="$parentTexture30" inherits="TooltipTextureTemplate"/>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
<OnLoad function="SharedTooltip_OnLoad"/>
|
||||
<OnHide function="SharedTooltip_OnHide"/>
|
||||
<OnTooltipSetDefaultAnchor function="SharedTooltip_SetDefaultAnchor"/>
|
||||
<OnTooltipCleared function="SharedTooltip_ClearInsertedFrames"/>
|
||||
</Scripts>
|
||||
</GameTooltip>
|
||||
|
||||
<GameTooltip name="SharedNoHeaderTooltipTemplate" inherits="SharedTooltipTemplate" virtual="true">
|
||||
<Attributes>
|
||||
<Attribute name="textLeft1Font" value="GameTooltipText" type="string"/>
|
||||
<Attribute name="textRight1Font" value="GameTooltipText" type="string"/>
|
||||
</Attributes>
|
||||
</GameTooltip>
|
||||
|
||||
<Frame name="TooltipBorderedFrameTemplate" virtual="true">
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<Texture parentKey="BorderTopLeft" name="$parentBorderTopLeft" file="Interface\Tooltips\UI-Tooltip-TL">
|
||||
<Size x="8" y="8"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<Texture parentKey="BorderTopRight" name="$parentBorderTopRight" file="Interface\Tooltips\UI-Tooltip-TR">
|
||||
<Size x="8" y="8"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPRIGHT"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<Texture parentKey="BorderBottomRight" name="$parentBorderBottomRight" file="Interface\Tooltips\UI-Tooltip-BR">
|
||||
<Size x="8" y="8"/>
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMRIGHT"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<Texture parentKey="BorderBottomLeft" name="$parentBorderBottomLeft" file="Interface\Tooltips\UI-Tooltip-BL">
|
||||
<Size x="8" y="8"/>
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<Texture parentKey="BorderTop" file="Interface\Tooltips\UI-Tooltip-T">
|
||||
<Size x="8" y="8"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentBorderTopLeft" relativePoint="TOPRIGHT"/>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentBorderTopRight" relativePoint="TOPLEFT"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<Texture parentKey="BorderRight" file="Interface\Tooltips\UI-Tooltip-R">
|
||||
<Size x="8" y="8"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentBorderTopRight" relativePoint="BOTTOMRIGHT"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBorderBottomRight" relativePoint="TOPRIGHT"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<Texture parentKey="BorderBottom" file="Interface\Tooltips\UI-Tooltip-B">
|
||||
<Size x="8" y="8"/>
|
||||
<Anchors>
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parentBorderBottomLeft" relativePoint="BOTTOMRIGHT"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBorderBottomRight" relativePoint="BOTTOMLEFT"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<Texture parentKey="BorderLeft" file="Interface\Tooltips\UI-Tooltip-L">
|
||||
<Size x="8" y="8"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentBorderTopLeft" relativePoint="BOTTOMLEFT"/>
|
||||
<Anchor point="BOTTOMLEFT" relativeTo="$parentBorderBottomLeft" relativePoint="TOPLEFT"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<Texture parentKey="Background">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentBorderTopLeft" relativePoint="BOTTOMRIGHT"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentBorderBottomRight" relativePoint="TOPLEFT"/>
|
||||
</Anchors>
|
||||
<Color r="0" g="0" b="0" a="0.8"/>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
</Frame>
|
||||
|
||||
<Button name="DisabledTooltipButtonTemplate" motionScriptsWhileDisabled="true" virtual="true">
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
Mixin(self, DisabledTooltipButtonMixin)
|
||||
</OnLoad>
|
||||
<OnEnter>
|
||||
self:OnEnter()
|
||||
</OnEnter>
|
||||
<OnLeave>
|
||||
self:OnLeave()
|
||||
</OnLeave>
|
||||
</Scripts>
|
||||
</Button>
|
||||
</Ui>
|
||||
+4548
File diff suppressed because it is too large
Load Diff
+2128
File diff suppressed because it is too large
Load Diff
+1536
File diff suppressed because it is too large
Load Diff
+2443
File diff suppressed because it is too large
Load Diff
+365
@@ -0,0 +1,365 @@
|
||||
-- SOUND KITS
|
||||
SOUNDKIT = {
|
||||
LOOT_WINDOW_COIN_SOUND = 120,
|
||||
INTERFACE_SOUND_LOST_TARGET_UNIT = 684,
|
||||
GS_TITLE_OPTIONS = 778,
|
||||
GS_TITLE_CREDITS = 790,
|
||||
GS_TITLE_OPTION_OK = 798,
|
||||
GS_TITLE_OPTION_EXIT = 799,
|
||||
GS_LOGIN = 800,
|
||||
GS_LOGIN_NEW_ACCOUNT = 801,
|
||||
GS_LOGIN_CHANGE_REALM_OK = 805,
|
||||
GS_LOGIN_CHANGE_REALM_CANCEL = 807,
|
||||
GS_CHARACTER_SELECTION_ENTER_WORLD = 809,
|
||||
GS_CHARACTER_SELECTION_DEL_CHARACTER = 810,
|
||||
GS_CHARACTER_SELECTION_ACCT_OPTIONS = 811,
|
||||
GS_CHARACTER_SELECTION_EXIT = 812,
|
||||
GS_CHARACTER_SELECTION_CREATE_NEW = 813,
|
||||
GS_CHARACTER_CREATION_CLASS = 814,
|
||||
GS_CHARACTER_CREATION_LOOK = 817,
|
||||
GS_CHARACTER_CREATION_CREATE_CHAR = 818,
|
||||
GS_CHARACTER_CREATION_CANCEL = 819,
|
||||
IG_MINIMAP_OPEN = 821,
|
||||
IG_MINIMAP_CLOSE = 822,
|
||||
IG_MINIMAP_ZOOM_IN = 823,
|
||||
IG_MINIMAP_ZOOM_OUT = 824,
|
||||
IG_CHAT_EMOTE_BUTTON = 825,
|
||||
IG_CHAT_SCROLL_UP = 826,
|
||||
IG_CHAT_SCROLL_DOWN = 827,
|
||||
IG_CHAT_BOTTOM = 828,
|
||||
IG_SPELLBOOK_OPEN = 829,
|
||||
IG_SPELLBOOK_CLOSE = 830,
|
||||
IG_ABILITY_OPEN = 834,
|
||||
IG_ABILITY_CLOSE = 835,
|
||||
IG_ABILITY_PAGE_TURN = 836,
|
||||
IG_ABILITY_ICON_DROP = 838,
|
||||
IG_CHARACTER_INFO_OPEN = 839,
|
||||
IG_CHARACTER_INFO_CLOSE = 840,
|
||||
IG_CHARACTER_INFO_TAB = 841,
|
||||
IG_QUEST_LOG_OPEN = 844,
|
||||
IG_QUEST_LOG_CLOSE = 845,
|
||||
IG_QUEST_LOG_ABANDON_QUEST = 846,
|
||||
IG_MAINMENU_OPEN = 850,
|
||||
IG_MAINMENU_CLOSE = 851,
|
||||
IG_MAINMENU_OPTION = 852,
|
||||
IG_MAINMENU_LOGOUT = 853,
|
||||
IG_MAINMENU_QUIT = 854,
|
||||
IG_MAINMENU_CONTINUE = 855,
|
||||
IG_MAINMENU_OPTION_CHECKBOX_ON = 856,
|
||||
IG_MAINMENU_OPTION_CHECKBOX_OFF = 857,
|
||||
IG_MAINMENU_OPTION_FAER_TAB = 858,
|
||||
IG_INVENTORY_ROTATE_CHARACTER = 861,
|
||||
IG_BACKPACK_OPEN = 862,
|
||||
IG_BACKPACK_CLOSE = 863,
|
||||
IG_BACKPACK_COIN_SELECT = 864,
|
||||
IG_BACKPACK_COIN_OK = 865,
|
||||
IG_BACKPACK_COIN_CANCEL = 866,
|
||||
IG_CHARACTER_NPC_SELECT = 867,
|
||||
IG_CREATURE_NEUTRAL_SELECT = 871,
|
||||
IG_CREATURE_AGGRO_SELECT = 873,
|
||||
IG_QUEST_LIST_OPEN = 875,
|
||||
IG_QUEST_LIST_CLOSE = 876,
|
||||
IG_QUEST_LIST_SELECT = 877,
|
||||
IG_QUEST_LIST_COMPLETE = 878,
|
||||
IG_QUEST_CANCEL = 879,
|
||||
IG_PLAYER_INVITE = 880,
|
||||
MONEY_FRAME_OPEN = 891,
|
||||
MONEY_FRAME_CLOSE = 892,
|
||||
U_CHAT_SCROLL_BUTTON = 1115,
|
||||
PUT_DOWN_SMALL_CHAIN = 1212,
|
||||
LOOT_WINDOW_OPEN_EMPTY = 1264,
|
||||
TELL_MESSAGE = 3081,
|
||||
MAP_PING = 3175,
|
||||
FISHING_REEL_IN = 3407,
|
||||
IG_PVP_UPDATE = 4574,
|
||||
AUCTION_WINDOW_OPEN = 5274,
|
||||
AUCTION_WINDOW_CLOSE = 5275,
|
||||
TUTORIAL_POPUP = 7355,
|
||||
ITEM_REPAIR = 7994,
|
||||
PVP_ENTER_QUEUE = 8458,
|
||||
PVP_THROUGH_QUEUE = 8459,
|
||||
KEY_RING_OPEN = 8938,
|
||||
KEY_RING_CLOSE = 8939,
|
||||
RAID_WARNING = 8959,
|
||||
READY_CHECK = 8960,
|
||||
GLUESCREEN_INTRO = 9902,
|
||||
AMB_GLUESCREEN_HUMAN = 9903,
|
||||
AMB_GLUESCREEN_ORC = 9905,
|
||||
AMB_GLUESCREEN_TAUREN = 9906,
|
||||
AMB_GLUESCREEN_DWARF = 9907,
|
||||
AMB_GLUESCREEN_NIGHTELF = 9908,
|
||||
AMB_GLUESCREEN_UNDEAD = 9909,
|
||||
AMB_GLUESCREEN_BLOODELF = 9910,
|
||||
AMB_GLUESCREEN_DRAENEI = 9911,
|
||||
JEWEL_CRAFTING_FINALIZE = 10590,
|
||||
MENU_CREDITS01 = 10763,
|
||||
MENU_CREDITS02 = 10804,
|
||||
GUILD_VAULT_OPEN = 12188,
|
||||
GUILD_VAULT_CLOSE = 12189,
|
||||
RAID_BOSS_EMOTE_WARNING = 12197,
|
||||
GUILD_BANK_OPEN_BAG = 12206,
|
||||
GS_LICH_KING = 12765,
|
||||
ALARM_CLOCK_WARNING_2 = 12867,
|
||||
ALARM_CLOCK_WARNING_3 = 12889,
|
||||
MENU_CREDITS03 = 13822,
|
||||
ACHIEVEMENT_MENU_OPEN = 13832,
|
||||
ACHIEVEMENT_MENU_CLOSE = 13833,
|
||||
BARBERSHOP_HAIRCUT = 13873,
|
||||
BARBERSHOP_SIT = 14148,
|
||||
GM_CHAT_WARNING = 15273,
|
||||
LFG_REWARDS = 17316,
|
||||
LFG_ROLE_CHECK = 17317,
|
||||
LFG_DENIED = 17341,
|
||||
UI_BNET_TOAST = 18019,
|
||||
ALARM_CLOCK_WARNING_1 = 18871,
|
||||
AMB_GLUESCREEN_WORGEN = 20169,
|
||||
AMB_GLUESCREEN_GOBLIN = 20170,
|
||||
AMB_GLUESCREEN_TROLL = 21136,
|
||||
AMB_GLUESCREEN_GNOME = 21137,
|
||||
UI_POWER_AURA_GENERIC = 23287,
|
||||
UI_REFORGING_REFORGE = 23291,
|
||||
UI_AUTO_QUEST_COMPLETE = 23404,
|
||||
GS_CATACLYSM = 23640,
|
||||
MENU_CREDITS04 = 23812,
|
||||
UI_BATTLEGROUND_COUNTDOWN_TIMER = 25477,
|
||||
UI_BATTLEGROUND_COUNTDOWN_FINISHED = 25478,
|
||||
UI_VOID_STORAGE_UNLOCK = 25711,
|
||||
UI_VOID_STORAGE_DEPOSIT = 25712,
|
||||
UI_VOID_STORAGE_WITHDRAW = 25713,
|
||||
UI_TRANSMOGRIFY_UNDO = 25715,
|
||||
UI_ETHEREAL_WINDOW_OPEN = 25716,
|
||||
UI_ETHEREAL_WINDOW_CLOSE = 25717,
|
||||
UI_TRANSMOGRIFY_REDO = 25738,
|
||||
UI_VOID_STORAGE_BOTH = 25744,
|
||||
AMB_GLUESCREEN_PANDAREN = 25848,
|
||||
MUS_50_HEART_OF_PANDARIA_MAINTITLE = 28509,
|
||||
UI_PET_BATTLES_TRAP_READY = 28814,
|
||||
UI_EPICLOOT_TOAST = 31578,
|
||||
UI_BONUS_LOOT_ROLL_START = 31579,
|
||||
UI_BONUS_LOOT_ROLL_LOOP = 31580,
|
||||
UI_BONUS_LOOT_ROLL_END = 31581,
|
||||
UI_PET_BATTLE_START = 31584,
|
||||
UI_SCENARIO_ENDING = 31754,
|
||||
UI_SCENARIO_STAGE_END = 31757,
|
||||
MENU_CREDITS05 = 32015,
|
||||
UI_PET_BATTLE_CAMERA_MOVE_IN = 32047,
|
||||
UI_PET_BATTLE_CAMERA_MOVE_OUT = 32052,
|
||||
AMB_50_GLUESCREEN_ALLIANCE = 32412,
|
||||
AMB_50_GLUESCREEN_HORDE = 32413,
|
||||
AMB_50_GLUESCREEN_PANDAREN_NEUTRAL = 32414,
|
||||
UI_CHALLENGES_NEW_RECORD = 33338,
|
||||
MENU_CREDITS06 = 34020,
|
||||
UI_LOSS_OF_CONTROL_START = 34468,
|
||||
UI_PET_BATTLES_PVP_THROUGH_QUEUE = 36609,
|
||||
AMB_GLUESCREEN_DEATHKNIGHT = 37056,
|
||||
UI_RAID_BOSS_WHISPER_WARNING = 37666,
|
||||
UI_DIG_SITE_COMPLETION_TOAST = 38326,
|
||||
UI_IG_STORE_PAGE_NAV_BUTTON = 39511,
|
||||
UI_IG_STORE_WINDOW_OPEN_BUTTON = 39512,
|
||||
UI_IG_STORE_WINDOW_CLOSE_BUTTON = 39513,
|
||||
UI_IG_STORE_CANCEL_BUTTON = 39514,
|
||||
UI_IG_STORE_BUY_BUTTON = 39515,
|
||||
UI_IG_STORE_CONFIRM_PURCHASE_BUTTON = 39516,
|
||||
UI_IG_STORE_PURCHASE_DELIVERED_TOAST_01 = 39517,
|
||||
MUS_60_MAIN_TITLE = 40169,
|
||||
UI_GARRISON_MISSION_COMPLETE_ENCOUNTER_FAIL = 43501,
|
||||
UI_GARRISON_MISSION_COMPLETE_MISSION_SUCCESS = 43502,
|
||||
UI_GARRISON_MISSION_COMPLETE_MISSION_FAIL_STINGER = 43503,
|
||||
UI_GARRISON_MISSION_THREAT_COUNTERED = 43505,
|
||||
UI_GARRISON_MISSION_100_PERCENT_CHANCE_REACHED_NOT_USED = 43507,
|
||||
UI_QUEST_ROLLING_FORWARD_01 = 43936,
|
||||
UI_BAG_SORTING_01 = 43937,
|
||||
UI_TOYBOX_TABS = 43938,
|
||||
UI_GARRISON_TOAST_INVASION_ALERT = 44292,
|
||||
UI_GARRISON_TOAST_MISSION_COMPLETE = 44294,
|
||||
UI_GARRISON_TOAST_BUILDING_COMPLETE = 44295,
|
||||
UI_GARRISON_TOAST_FOLLOWER_GAINED = 44296,
|
||||
UI_GARRISON_NAV_TABS = 44297,
|
||||
UI_GARRISON_GARRISON_REPORT_OPEN = 44298,
|
||||
UI_GARRISON_GARRISON_REPORT_CLOSE = 44299,
|
||||
UI_GARRISON_ARCHITECT_TABLE_OPEN = 44300,
|
||||
UI_GARRISON_ARCHITECT_TABLE_CLOSE = 44301,
|
||||
UI_GARRISON_ARCHITECT_TABLE_UPGRADE = 44302,
|
||||
UI_GARRISON_ARCHITECT_TABLE_UPGRADE_CANCEL = 44304,
|
||||
UI_GARRISON_ARCHITECT_TABLE_UPGRADE_START = 44305,
|
||||
UI_GARRISON_ARCHITECT_TABLE_PLOT_SELECT = 44306,
|
||||
UI_GARRISON_ARCHITECT_TABLE_BUILDING_SELECT = 44307,
|
||||
UI_GARRISON_ARCHITECT_TABLE_BUILDING_PLACEMENT = 44308,
|
||||
UI_GARRISON_COMMAND_TABLE_OPEN = 44311,
|
||||
UI_GARRISON_COMMAND_TABLE_CLOSE = 44312,
|
||||
UI_GARRISON_COMMAND_TABLE_MISSION_CLOSE = 44313,
|
||||
UI_GARRISON_COMMAND_TABLE_NAV_NEXT = 44314,
|
||||
UI_GARRISON_COMMAND_TABLE_SELECT_MISSION = 44315,
|
||||
UI_GARRISON_COMMAND_TABLE_SELECT_FOLLOWER = 44316,
|
||||
UI_GARRISON_COMMAND_TABLE_FOLLOWER_ABILITY_OPEN = 44317,
|
||||
UI_GARRISON_COMMAND_TABLE_FOLLOWER_ABILITY_CLOSE = 44318,
|
||||
UI_GARRISON_COMMAND_TABLE_ASSIGN_FOLLOWER = 44319,
|
||||
UI_GARRISON_COMMAND_TABLE_UNASSIGN_FOLLOWER = 44320,
|
||||
UI_GARRISON_COMMAND_TABLE_SLOT_CHAMPION = 72546,
|
||||
UI_GARRISON_COMMAND_TABLE_SLOT_TROOP = 72547,
|
||||
UI_GARRISON_COMMAND_TABLE_REDUCED_SUCCESS_CHANCE = 44321,
|
||||
UI_GARRISON_COMMAND_TABLE_100_SUCCESS = 44322,
|
||||
UI_GARRISON_COMMAND_TABLE_MISSION_START = 44323,
|
||||
UI_GARRISON_COMMAND_TABLE_VIEW_MISSION_REPORT = 44324,
|
||||
UI_GARRISON_COMMAND_TABLE_MISSION_SUCCESS_STINGER = 44330,
|
||||
UI_GARRISON_COMMAND_TABLE_CHEST_UNLOCK = 44331,
|
||||
UI_GARRISON_COMMAND_TABLE_CHEST_UNLOCK_GOLD_SUCCESS = 44332,
|
||||
UI_GARRISON_MONUMENTS_OPEN = 44344,
|
||||
UI_BONUS_EVENT_SYSTEM_VIGNETTES = 45142,
|
||||
UI_GARRISON_COMMAND_TABLE_FOLLOWER_LEVEL_UP = 46893,
|
||||
UI_GARRISON_ARCHITECT_TABLE_BUILDING_PLACEMENT_ERROR = 47355,
|
||||
UI_GARRISON_MONUMENTS_CLOSE = 47373,
|
||||
AMB_GLUESCREEN_WARLORDS_OF_DRAENOR = 47544,
|
||||
MUS_1_0_MAINTITLE_ORIGINAL = 47598,
|
||||
UI_GROUP_FINDER_RECEIVE_APPLICATION = 47615,
|
||||
UI_GARRISON_MISSION_ENCOUNTER_ANIMATION_GENERIC = 47704,
|
||||
UI_GARRISON_START_WORK_ORDER = 47972,
|
||||
UI_GARRISON_SHIPMENTS_WINDOW_OPEN = 48191,
|
||||
UI_GARRISON_SHIPMENTS_WINDOW_CLOSE = 48192,
|
||||
UI_GARRISON_MONUMENTS_NAV = 48942,
|
||||
UI_RAID_BOSS_DEFEATED = 50111,
|
||||
UI_PERSONAL_LOOT_BANNER = 50893,
|
||||
UI_GARRISON_FOLLOWER_LEARN_TRAIT = 51324,
|
||||
UI_GARRISON_SHIPYARD_PLACE_CARRIER = 51385,
|
||||
UI_GARRISON_SHIPYARD_PLACE_GALLEON = 51387,
|
||||
UI_GARRISON_SHIPYARD_PLACE_DREADNOUGHT = 51388,
|
||||
UI_GARRISON_SHIPYARD_PLACE_SUBMARINE = 51389,
|
||||
UI_GARRISON_SHIPYARD_PLACE_LANDING_CRAFT = 51390,
|
||||
UI_GARRISON_SHIPYARD_START_MISSION = 51401,
|
||||
UI_RAID_LOOT_TOAST_LESSER_ITEM_WON = 51402,
|
||||
UI_WARFORGED_ITEM_LOOT_TOAST = 51561,
|
||||
UI_GARRISON_COMMAND_TABLE_INCREASED_SUCCESS_CHANCE = 51570,
|
||||
UI_GARRISON_SHIPYARD_DECOMISSION_SHIP = 51871,
|
||||
UI_70_ARTIFACT_FORGE_TRAIT_FIRST_TRAIT = 54126,
|
||||
UI_70_ARTIFACT_FORGE_RELIC_PLACE = 54128,
|
||||
UI_70_ARTIFACT_FORGE_APPEARANCE_COLOR_SELECT = 54130,
|
||||
UI_70_ARTIFACT_FORGE_APPEARANCE_LOCKED = 54131,
|
||||
UI_70_ARTIFACT_FORGE_APPEARANCE_APPEARANCE_CHANGE = 54132,
|
||||
UI_70_ARTIFACT_FORGE_TOAST_TRAIT_AVAILABLE = 54133,
|
||||
UI_70_ARTIFACT_FORGE_APPEARANCE_APPEARANCE_UNLOCK = 54139,
|
||||
UI_70_ARTIFACT_FORGE_TRAIT_GOLD_TRAIT = 54125,
|
||||
UI_72_ARTIFACT_FORGE_FINAL_TRAIT_UNLOCKED = 83682,
|
||||
UI_70_ARTIFACT_FORGE_TRAIT_FINALRANK = 54127,
|
||||
UI_70_ARTIFACT_FORGE_TRAIT_RANKUP = 54129,
|
||||
AMB_GLUESCREEN_DEMONHUNTER = 56352,
|
||||
MUS_70_MAIN_TITLE = 56353,
|
||||
MENU_CREDITS07 = 56354,
|
||||
UI_TRANSMOG_ITEM_CLICK = 62538,
|
||||
UI_TRANSMOG_PAGE_TURN = 62539,
|
||||
UI_TRANSMOG_GEAR_SLOT_CLICK = 62540,
|
||||
UI_TRANSMOG_REVERTING_GEAR_SLOT = 62541,
|
||||
UI_TRANSMOG_APPLY = 62542,
|
||||
UI_TRANSMOG_CLOSE_WINDOW = 62543,
|
||||
UI_TRANSMOG_OPEN_WINDOW = 62544,
|
||||
UI_LEGENDARY_LOOT_TOAST = 63971,
|
||||
UI_STORE_UNWRAP = 64329,
|
||||
AMB_GLUESCREEN_LEGION = 71535,
|
||||
UI_MISSION_200_PERCENT = 72548,
|
||||
UI_MISSION_MAP_ZOOM = 72549,
|
||||
UI_70_BOOST_THANKSFORPLAYING_SMALLER = 72978,
|
||||
UI_70_BOOST_THANKSFORPLAYING = 72977,
|
||||
UI_WORLDQUEST_START = 73275,
|
||||
UI_WORLDQUEST_MAP_SELECT = 73276,
|
||||
UI_WORLDQUEST_COMPLETE = 73277,
|
||||
UI_ORDERHALL_TALENT_SELECT = 73279,
|
||||
UI_ORDERHALL_TALENT_READY_TOAST = 73280,
|
||||
UI_ORDERHALL_TALENT_READY_CHECK = 73281,
|
||||
UI_ORDERHALL_TALENT_NUKE_FROM_ORBIT = 73282,
|
||||
UI_ORDERHALL_TALENT_WINDOW_OPEN = 73914,
|
||||
UI_ORDERHALL_TALENT_WINDOW_CLOSE = 73915,
|
||||
UI_PROFESSIONS_WINDOW_OPEN = 73917,
|
||||
UI_PROFESSIONS_WINDOW_CLOSE = 73918,
|
||||
UI_PROFESSIONS_NEW_RECIPE_LEARNED_TOAST = 73919,
|
||||
UI_70_CHALLENGE_MODE_SOCKET_PAGE_OPEN = 74421,
|
||||
UI_70_CHALLENGE_MODE_SOCKET_PAGE_CLOSE = 74423,
|
||||
UI_70_CHALLENGE_MODE_SOCKET_PAGE_SOCKET = 74431,
|
||||
UI_70_CHALLENGE_MODE_SOCKET_PAGE_ACTIVATE_BUTTON = 74432,
|
||||
UI_70_CHALLENGE_MODE_KEYSTONE_UPGRADE = 74437,
|
||||
UI_70_CHALLENGE_MODE_NEW_RECORD = 74438,
|
||||
UI_70_CHALLENGE_MODE_SOCKET_PAGE_REMOVE_KEYSTONE = 74525,
|
||||
UI_70_CHALLENGE_MODE_COMPLETE_NO_UPGRADE = 74526,
|
||||
UI_MISSION_SUCCESS_CHEERS = 74702,
|
||||
UI_PVP_HONOR_PRESTIGE_OPEN_WINDOW = 76995,
|
||||
UI_PVP_HONOR_PRESTIGE_WINDOW_CLOSE = 77002,
|
||||
UI_PVP_HONOR_PRESTIGE_RANK_UP = 77003,
|
||||
UI_71_SOCIAL_QUEUEING_TOAST = 79739,
|
||||
UI_72_ARTIFACT_FORGE_ACTIVATE_FINAL_TIER = 83681,
|
||||
UI_72_BUILDINGS_CONTRIBUTE_POWER_MENU_CLICK = 84240,
|
||||
UI_72_BUILDING_CONTRIBUTION_TABLE_OPEN = 84368,
|
||||
UI_72_BUILDINGS_CONTRIBUTION_TABLE_CLOSE = 84369,
|
||||
UI_72_BUILDINGS_CONTRIBUTE_RESOURCES = 84378,
|
||||
UI_72_ARTIFACT_FORGE_FINAL_TRAIT_REFUND_START = 83684,
|
||||
UI_72_ARTIFACT_FORGE_FINAL_TRAIT_REFUND_LOOP = 83685,
|
||||
UI_73_ARTIFACT_RELICS_TRAIT_SELECT_AND_REVEAL = 89685,
|
||||
UI_73_ARTIFACT_RELICS_TRAIT_SELECT_ONLY = 89686,
|
||||
UI_73_ARTIFACT_RELICS_TRAIT_REVEAL_ONLY = 90080,
|
||||
PUT_DOWN_GEMS = 1204,
|
||||
PICK_UP_GEMS = 1221,
|
||||
UI_73_ARTIFACT_OVERLOADED_HIGHEST = 97301,
|
||||
UI_73_ARTIFACT_OVERLOADED_HIGH = 97471,
|
||||
UI_73_ARTIFACT_OVERLOADED_MEDIUM = 97470,
|
||||
UI_73_ARTIFACT_OVERLOADED_LOW = 97469,
|
||||
UI_73_ARTIFACT_OVERLOADED_ORB_HIGHEST = 97559,
|
||||
UI_73_ARTIFACT_OVERLOADED_ORB_HIGH = 97558,
|
||||
UI_73_ARTIFACT_OVERLOADED_ORB_MEDIUM = 97557,
|
||||
UI_73_ARTIFACT_OVERLOADED_ORB_LOW = 97556,
|
||||
UI_73_ARTIFACT_OVERLOADED_ORB_IMPACT_MEDIUM = 97597,
|
||||
UI_73_ARTIFACT_OVERLOADED_ORB_IMPACT_LOW = 97598,
|
||||
AMB_GLUESCREEN_VOIDELF = 97324,
|
||||
AMB_GLUESCREEN_LIGHTFORGEDDRAENEI = 97325,
|
||||
AMB_GLUESCREEN_NIGHTBORNE = 97326,
|
||||
AMB_GLUESCREEN_HIGHMOUNTAINTAUREN = 97327,
|
||||
UI_VOICECHAT_DEAFENOFF = 110990,
|
||||
UI_VOICECHAT_DEAFENON = 110989,
|
||||
UI_VOICECHAT_MUTEOFF = 110988,
|
||||
UI_VOICECHAT_MUTEON = 110987,
|
||||
UI_VOICECHAT_MUTEOTHEROFF = 111080,
|
||||
UI_VOICECHAT_MUTEOTHERON = 111081,
|
||||
UI_VOICECHAT_MEMBERLEAVECHANNEL = 110986,
|
||||
UI_VOICECHAT_MEMBERJOINCHANNEL = 110985,
|
||||
UI_VOICECHAT_STOPTALK = 110984,
|
||||
UI_VOICECHAT_TALKSTART = 110983,
|
||||
UI_VOICECHAT_LEAVECHANNEL = 110982,
|
||||
UI_VOICECHAT_JOINCHANNEL = 110981,
|
||||
AMB_GLUESCREEN_BATTLE_FOR_AZEROTH = 113894,
|
||||
AMB_GLUESCREEN_MAGHARORC = 113556,
|
||||
AMB_GLUESCREEN_DARKIRONDWARF = 113557,
|
||||
MUS_80_MAIN_TITLE = 113559,
|
||||
MENU_CREDITS08 = 113560,
|
||||
UI_AZERITE_EMPOWERED_ITEM_LOOT_TOAST = 118238,
|
||||
|
||||
UI_80_AZERITEARMOR_SELECTBUFF = 114993,
|
||||
UI_80_AZERITEARMOR_BUFFAVAILABLE = 116657,
|
||||
UI_80_AZERITEARMOR_ROTATION_LOOP = 114994,
|
||||
UI_80_AZERITEARMOR_ROTATIONENDS = 114995,
|
||||
UI_80_AZERITEARMOR_ROTATIONENDS_FINALTRAIT = 116233,
|
||||
UI_80_AZERITEARMOR_ROTATIONENDCLICKS = 115314,
|
||||
UI_80_AZERITEARMOR_ROTATIONSTARTCLICKS = 115358,
|
||||
UI_80_AZERITEARMOR_FIRSTTIMEFLOURISH = 118264,
|
||||
|
||||
UI_80_AZERITEARMOR_REFORGE_ETHEREALWINDOW_OPEN = 114990,
|
||||
UI_80_AZERITEARMOR_REFORGE_ETHEREALWINDOW_CLOSE = 114991,
|
||||
UI_80_AZERITEARMOR_REFORGE = 114992,
|
||||
UI_80_ISLANDS_AZERITECOLLECTION_START = 115003,
|
||||
UI_80_ISLANDS_AZERITECOLLECTION_LOOP = 115004,
|
||||
UI_80_ISLANDS_AZERITECOLLECTION_STOP = 115005,
|
||||
UI_80_SCRAPPING_WINDOW_CLOSE = 115487,
|
||||
UI_80_SCRAPPING_WINDOW_OPEN = 115488,
|
||||
UI_WARMODE_ACTIVATE = 118563,
|
||||
UI_WARMODE_DECTIVATE = 118564,
|
||||
|
||||
UI_80_ISLANDS_TABLE_OPEN = 118610,
|
||||
UI_80_ISLANDS_TABLE_CLOSE = 118611,
|
||||
UI_80_ISLANDS_TABLE_SELECT_DIFFICULTY = 118612,
|
||||
UI_80_ISLANDS_TABLE_FIND_GROUP = 118613,
|
||||
UI_80_ISLANDS_TABLE_FIND_GROUP_PVP = 118668,
|
||||
UI_80_ISLANDS_TUTORIAL_CLOSE = 119726,
|
||||
|
||||
UI_GARRISON_MISSION_COMPLETE_ENCOUNTER_CHANCE = 0, -- missing SoundKit entry!
|
||||
|
||||
UI_COUNTDOWN_BAR_STATE_STARTS = 158958,
|
||||
UI_COUNTDOWN_BAR_STATE_FINISHED = 158959,
|
||||
UI_COUNTDOWN_MEDIUM_NUMBER_FINISHED = 158960,
|
||||
UI_COUNTDOWN_TIMER = 191352,
|
||||
UI_COUNTDOWN_FINISHED = 158566,
|
||||
};
|
||||
+499
@@ -0,0 +1,499 @@
|
||||
local ColumnWidthConstraints = {
|
||||
Fill = 1, -- Width will be distributed by available space.
|
||||
Fixed = 2, -- Width is specified when initializing the column.
|
||||
};
|
||||
|
||||
-- Any row or cell is expected to initialize itself in terms of the row data. The dataIndex is provided
|
||||
-- in case the derived mixin needs to make additional CAPI calls involving it's relative index. The row
|
||||
-- data may also be needed for a tooltip, so it will be assigned to the row and cells on update.
|
||||
TableBuilderElementMixin = {};
|
||||
|
||||
--Derive
|
||||
function TableBuilderElementMixin:Init(...)
|
||||
end
|
||||
|
||||
--Derive
|
||||
function TableBuilderElementMixin:Populate(rowData, dataIndex)
|
||||
end
|
||||
|
||||
TableBuilderCellMixin = CreateFromMixins(TableBuilderElementMixin);
|
||||
|
||||
--Derive
|
||||
function TableBuilderCellMixin:OnLineEnter()
|
||||
end
|
||||
|
||||
--Derive
|
||||
function TableBuilderCellMixin:OnLineLeave()
|
||||
end
|
||||
|
||||
|
||||
TableBuilderRowMixin = CreateFromMixins(TableBuilderElementMixin);
|
||||
|
||||
--Derive
|
||||
function TableBuilderRowMixin:OnLineEnter()
|
||||
end
|
||||
|
||||
--Derive
|
||||
function TableBuilderRowMixin:OnLineLeave()
|
||||
end
|
||||
|
||||
|
||||
function TableBuilderRowMixin:OnEnter()
|
||||
self:OnLineEnter();
|
||||
for i, cell in ipairs(self.cells) do
|
||||
cell:OnLineEnter();
|
||||
end
|
||||
end
|
||||
|
||||
function TableBuilderRowMixin:OnLeave()
|
||||
self:OnLineLeave();
|
||||
for i, cell in ipairs(self.cells) do
|
||||
cell:OnLineLeave();
|
||||
end
|
||||
end
|
||||
|
||||
-- Defines an entire column within the table builder, by default a column's sizing constraints are set to fill.
|
||||
TableBuilderColumnMixin = {};
|
||||
function TableBuilderColumnMixin:Init(table)
|
||||
self.cells = {};
|
||||
self.table = table;
|
||||
|
||||
local fillCoefficient = 1.0;
|
||||
local padding = 0;
|
||||
self:SetFillConstraints(fillCoefficient, padding);
|
||||
end
|
||||
|
||||
-- Constructs the header frame with an optional initializer.
|
||||
function TableBuilderColumnMixin:ConstructHeader(templateType, template, ...)
|
||||
local frame = self.table:ConstructHeader(templateType, template);
|
||||
self.headerFrame = frame;
|
||||
if frame.Init then
|
||||
frame:Init(...);
|
||||
end
|
||||
frame:Show();
|
||||
end
|
||||
|
||||
-- Constructs cells corresponding to each row with an optional initializer.
|
||||
function TableBuilderColumnMixin:ConstructCells(templateType, template, ...)
|
||||
local cells = self.table:ConstructCells(templateType, template);
|
||||
self.cells = cells;
|
||||
for k, cell in pairs(cells) do
|
||||
if cell.Init then
|
||||
cell:Init(...);
|
||||
end
|
||||
cell:Show();
|
||||
end
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetCellByRowIndex(rowIndex)
|
||||
return self.cells[rowIndex];
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetFillCoefficient()
|
||||
return self.fillCoefficient;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:SetFillCoefficient(fillCoefficient)
|
||||
self.fillCoefficient = fillCoefficient;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetPadding()
|
||||
return self.padding;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:SetPadding(padding)
|
||||
self.padding = padding;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetCellPadding()
|
||||
return self.leftCellPadding or 0, self.rightCellPadding or 0;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:SetCellPadding(leftCellPadding, rightCellPadding)
|
||||
self.leftCellPadding = leftCellPadding;
|
||||
self.rightCellPadding = rightCellPadding;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetHeaderFrame()
|
||||
return self.headerFrame;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:SetHeaderFrame(headerFrame)
|
||||
self.headerFrame = headerFrame;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetWidthConstraints()
|
||||
return self.widthConstraints;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetFixedWidth()
|
||||
return self.fixedWidth;
|
||||
end
|
||||
|
||||
-- A header frame for the column is expected to be constructed or assigned prior to calling this.
|
||||
-- See ConstructHeader() or SetHeaderFrame().
|
||||
function TableBuilderColumnMixin:ConstrainToHeader(padding)
|
||||
local header = self:GetHeaderFrame();
|
||||
assert(header, "ConstrainToHeader() called with a nil header frame. Use ConstructHeader() or assign one with SetHeaderFrame(), or use SetFixedConstraints to have a headerless column.");
|
||||
self:SetFixedConstraints(header:GetWidth(), padding or 0);
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:SetFixedConstraints(fixedWidth, padding)
|
||||
self.widthConstraints = ColumnWidthConstraints.Fixed;
|
||||
self.fixedWidth = fixedWidth;
|
||||
self:SetFillCoefficient(0);
|
||||
self:SetPadding(padding or 0);
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:SetFillConstraints(fillCoefficient, padding)
|
||||
self.widthConstraints = ColumnWidthConstraints.Fill;
|
||||
self.fixedWidth = 0;
|
||||
self:SetFillCoefficient(fillCoefficient);
|
||||
self:SetPadding(padding or 0);
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:SetCalculatedWidth(calculatedWidth)
|
||||
self.calculatedWidth = calculatedWidth;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetCalculatedWidth()
|
||||
return self.calculatedWidth;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetCellWidth()
|
||||
local leftCellPadding, rightCellPadding = self:GetCellPadding();
|
||||
return (self.calculatedWidth - leftCellPadding) - rightCellPadding;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetFullWidth()
|
||||
return self:GetCalculatedWidth() + self:GetPadding();
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:SetDisplayUnderPreviousHeader(displayUnderPreviousHeader)
|
||||
self.displayUnderPreviousHeader = displayUnderPreviousHeader;
|
||||
end
|
||||
|
||||
function TableBuilderColumnMixin:GetDisplayUnderPreviousHeader()
|
||||
return self.displayUnderPreviousHeader;
|
||||
end
|
||||
|
||||
-- Constructs a table of frames within an existing set of row frames. These row frames could originate from
|
||||
-- a hybrid scroll frame or statically fixed set. To populate the table, assign a data provider (CAPI or lua function)
|
||||
-- that can retrieve an object by index (number).
|
||||
TableBuilderMixin = {};
|
||||
function TableBuilderMixin:Init(rows)
|
||||
self.columns = {};
|
||||
self.leftMargin = 0;
|
||||
self.rightMargin = 0;
|
||||
self.columnHeaderOverlap = 0;
|
||||
self.tableWidth = 0;
|
||||
self.headerPoolCollection = CreateFramePoolCollection();
|
||||
self:SetRows(rows);
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetDataProvider()
|
||||
return self.dataProvider;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:SetDataProvider(dataProvider)
|
||||
self.dataProvider = dataProvider;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetDataProviderData(dataIndex)
|
||||
local dataProvider = self:GetDataProvider();
|
||||
return dataProvider and dataProvider(dataIndex) or nil;
|
||||
end
|
||||
|
||||
-- Controls the margins of the left-most and right-most columns within the table.
|
||||
function TableBuilderMixin:SetTableMargins(leftMargin, rightMargin)
|
||||
rightMargin = rightMargin or leftMargin; -- Use leftMargin as the default for both.
|
||||
self.leftMargin = leftMargin;
|
||||
self.rightMargin = rightMargin;
|
||||
end
|
||||
|
||||
-- Column headers overlap to make a consistent display.
|
||||
function TableBuilderMixin:SetColumnHeaderOverlap(columnHeaderOverlap)
|
||||
self.columnHeaderOverlap = columnHeaderOverlap;
|
||||
end
|
||||
|
||||
-- Can be used to set the table width, particularly if no header frames are involved.
|
||||
function TableBuilderMixin:SetTableWidth(tableWidth)
|
||||
self.tableWidth = tableWidth;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetTableWidth()
|
||||
return self.tableWidth;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetTableMargins()
|
||||
return self.leftMargin, self.rightMargin;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetColumnHeaderOverlap()
|
||||
return self.columnHeaderOverlap;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetColumns()
|
||||
return self.columns;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetHeaderContainer()
|
||||
return self.headerContainer;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:SetHeaderContainer(headerContainer)
|
||||
assert(headerContainer, "SetHeaderContainer() with a nil header container. Use ConstructHeader() or assign one with SetHeaderFrame(), or use SetFixedConstraints to have a headerless column.");
|
||||
self.headerContainer = headerContainer;
|
||||
self:SetTableWidth(headerContainer:GetWidth());
|
||||
end
|
||||
|
||||
function TableBuilderMixin:ReleaseRowPools()
|
||||
local rows = self.rows;
|
||||
if rows then
|
||||
for k, row in pairs(rows) do
|
||||
local poolCollection = row.poolCollection;
|
||||
if poolCollection then
|
||||
poolCollection:ReleaseAll();
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TableBuilderMixin:SetRows(rows)
|
||||
-- Release any previous rows, though I can't imagine a case where the rows
|
||||
-- are being exchanged.
|
||||
self:ReleaseRowPools();
|
||||
|
||||
self.rows = rows;
|
||||
for k, row in pairs(rows) do
|
||||
if not row.poolCollection then
|
||||
row.poolCollection = CreateFramePoolCollection();
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetHeaderPoolCollection()
|
||||
return self.headerPoolCollection;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetRows()
|
||||
return self.rows;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:ConstructHeader(templateType, template)
|
||||
local headerContainer = self:GetHeaderContainer();
|
||||
assert(headerContainer ~= nil, "A header container must be set with TableBuilderMixin:SetHeaderContainer before adding column headers.")
|
||||
local headerPoolCollection = self:GetHeaderPoolCollection();
|
||||
local pool = headerPoolCollection:GetOrCreatePool(templateType, headerContainer, template);
|
||||
return pool:Acquire(template);
|
||||
end
|
||||
|
||||
function TableBuilderMixin:ConstructCells(templateType, template)
|
||||
local cells = {};
|
||||
for k, row in pairs(self:GetRows()) do
|
||||
local pool = row.poolCollection:GetOrCreatePool(templateType, row, template);
|
||||
local cell = pool:Acquire(template);
|
||||
tinsert(cells, cell);
|
||||
end
|
||||
return cells;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:Arrange()
|
||||
local columns = self:GetColumns();
|
||||
if columns and #columns > 0 then
|
||||
self:CalculateColumnSpacing();
|
||||
self:ArrangeHeaders();
|
||||
self:ArrangeCells();
|
||||
end
|
||||
end
|
||||
|
||||
function TableBuilderMixin:Reset()
|
||||
self.columns = {};
|
||||
self:GetHeaderPoolCollection():ReleaseAll();
|
||||
self:ReleaseRowPools();
|
||||
end
|
||||
|
||||
function TableBuilderMixin:Populate(offset, count)
|
||||
local dataProvider = self:GetDataProvider();
|
||||
local columns = self:GetColumns();
|
||||
for rowIndex = 1, count do
|
||||
local dataIndex = rowIndex + offset;
|
||||
local rowData = dataProvider(dataIndex);
|
||||
if not rowData then
|
||||
break;
|
||||
end
|
||||
|
||||
local row = self:GetRowByIndex(rowIndex);
|
||||
if row then
|
||||
-- Data is assigned to the rows and elements so they can
|
||||
-- access it later in tooltips.
|
||||
row.rowData = rowData;
|
||||
if row.Populate then
|
||||
row:Populate(rowData, dataIndex);
|
||||
end
|
||||
|
||||
for columnIndex, p in ipairs(columns) do
|
||||
local cell = self:GetCellByIndex(rowIndex, columnIndex);
|
||||
if cell.Populate then
|
||||
cell.rowData = rowData;
|
||||
cell:Populate(rowData, dataIndex);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetCellByIndex(rowIndex, index)
|
||||
local row = self:GetRowByIndex(rowIndex);
|
||||
return row.cells[index];
|
||||
end
|
||||
|
||||
function TableBuilderMixin:GetRowByIndex(rowIndex)
|
||||
return self.rows[rowIndex];
|
||||
end
|
||||
|
||||
function TableBuilderMixin:AddColumn()
|
||||
local column = CreateAndInitFromMixin(TableBuilderColumnMixin, self);
|
||||
tinsert(self.columns, column);
|
||||
return column;
|
||||
end
|
||||
|
||||
function TableBuilderMixin:CalculateColumnSpacing()
|
||||
-- The arrangement of frames is daisy-chained left to right. The margin on the left side
|
||||
-- is created by adding the margin to it's anchor offset, and the margin on the right side
|
||||
-- is created by subtracting space from the remaining fill space.
|
||||
local columns = self:GetColumns();
|
||||
local paddingTotal = 0;
|
||||
local fillCoefficientTotal = 0;
|
||||
local fixedWidthTotal = 0;
|
||||
for columnIndex, column in ipairs(columns) do
|
||||
if column:GetWidthConstraints() == ColumnWidthConstraints.Fill then
|
||||
fillCoefficientTotal = fillCoefficientTotal + column:GetFillCoefficient();
|
||||
else
|
||||
fixedWidthTotal = fixedWidthTotal + column:GetFixedWidth();
|
||||
end
|
||||
|
||||
paddingTotal = paddingTotal + column:GetPadding();
|
||||
end
|
||||
|
||||
local tableWidth = self:GetTableWidth();
|
||||
local leftMargin, rightMargin = self:GetTableMargins();
|
||||
local fillWidthTotal = tableWidth - paddingTotal - (leftMargin + rightMargin) - fixedWidthTotal;
|
||||
for k, column in pairs(columns) do
|
||||
if fillCoefficientTotal > 0 and column:GetWidthConstraints() == ColumnWidthConstraints.Fill then
|
||||
local fillRatio = column:GetFillCoefficient() / fillCoefficientTotal;
|
||||
local width = fillRatio * fillWidthTotal;
|
||||
column:SetCalculatedWidth(width);
|
||||
else
|
||||
local width = column:GetFixedWidth();
|
||||
column:SetCalculatedWidth(width);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TableBuilderMixin:ArrangeHorizontally(frame, relativeTo, width, pointTop, pointRelativeTop, pointBottom, pointRelativeBottom, xOffset)
|
||||
frame:SetPoint(pointTop, relativeTo, pointRelativeTop, xOffset, 0);
|
||||
frame:SetPoint(pointBottom, relativeTo, pointRelativeBottom, xOffset, 0);
|
||||
frame:SetWidth(width);
|
||||
end
|
||||
|
||||
function TableBuilderMixin:ArrangeHeaders()
|
||||
local headerOverlap = self:GetColumnHeaderOverlap();
|
||||
local leftMargin, rightMargin = self:GetTableMargins();
|
||||
local columns = self:GetColumns();
|
||||
|
||||
-- Any trailing columns without headers should add to the width of the last column with a header.
|
||||
local numColumns = #columns;
|
||||
local lastActiveHeaderIndex = numColumns;
|
||||
local trailingWidth = 0;
|
||||
for i, column in ipairs(columns) do
|
||||
if column:GetHeaderFrame() then
|
||||
trailingWidth = 0;
|
||||
lastActiveHeaderIndex = i;
|
||||
else
|
||||
trailingWidth = trailingWidth + column:GetFullWidth();
|
||||
end
|
||||
end
|
||||
|
||||
local previousHeader = nil;
|
||||
local accumulatedWidth = 0;
|
||||
local columnIndex = 1;
|
||||
|
||||
while columnIndex <= numColumns do
|
||||
local column = columns[columnIndex];
|
||||
accumulatedWidth = accumulatedWidth + column:GetCalculatedWidth();
|
||||
|
||||
local isLastIndex = columnIndex == lastActiveHeaderIndex;
|
||||
local header = column:GetHeaderFrame();
|
||||
if header then
|
||||
if isLastIndex then
|
||||
accumulatedWidth = accumulatedWidth + trailingWidth;
|
||||
else
|
||||
for j = columnIndex + 1, #columns do
|
||||
local nextColumn = columns[j];
|
||||
if nextColumn:GetDisplayUnderPreviousHeader() then
|
||||
columnIndex = columnIndex + 1;
|
||||
accumulatedWidth = accumulatedWidth + nextColumn:GetFullWidth();
|
||||
else
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if previousHeader == nil then
|
||||
self:ArrangeHorizontally(header, header:GetParent(), accumulatedWidth, "TOPLEFT", "TOPLEFT", "BOTTOMLEFT", "BOTTOMLEFT", leftMargin);
|
||||
else
|
||||
self:ArrangeHorizontally(header, previousHeader, accumulatedWidth + headerOverlap, "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT", column:GetPadding() - headerOverlap);
|
||||
end
|
||||
|
||||
accumulatedWidth = 0;
|
||||
previousHeader = header;
|
||||
end
|
||||
|
||||
if isLastIndex then
|
||||
break;
|
||||
end
|
||||
|
||||
columnIndex = columnIndex + 1;
|
||||
end
|
||||
end
|
||||
|
||||
function TableBuilderMixin:ArrangeCells()
|
||||
local columns = self:GetColumns();
|
||||
local leftMargin, rightMargin = self:GetTableMargins();
|
||||
for rowIndex, row in ipairs(self:GetRows()) do
|
||||
local cells = {};
|
||||
local height = row:GetHeight();
|
||||
|
||||
local column = columns[1];
|
||||
local cell = column:GetCellByRowIndex(rowIndex);
|
||||
tinsert(cells, cell);
|
||||
cell:SetHeight(height);
|
||||
local leftCellPadding, rightCellPadding = column:GetCellPadding();
|
||||
|
||||
self:ArrangeHorizontally(cell, row, column:GetCellWidth(), "TOPLEFT", "TOPLEFT", "BOTTOMLEFT", "BOTTOMLEFT", leftMargin + leftCellPadding);
|
||||
|
||||
local previousCell = cell;
|
||||
local previousRightCellPadding = rightCellPadding;
|
||||
for columnIndex = 2, #columns do
|
||||
column = columns[columnIndex];
|
||||
cell = column:GetCellByRowIndex(rowIndex);
|
||||
tinsert(cells, cell);
|
||||
cell:SetHeight(height);
|
||||
leftCellPadding, rightCellPadding = column:GetCellPadding();
|
||||
|
||||
self:ArrangeHorizontally(cell, previousCell, column:GetCellWidth(), "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT", column:GetPadding() + leftCellPadding + previousRightCellPadding);
|
||||
previousCell = cell;
|
||||
previousRightCellPadding = rightCellPadding;
|
||||
end
|
||||
|
||||
row.cells = cells;
|
||||
end
|
||||
end
|
||||
|
||||
-- ... are additional mixins
|
||||
function CreateTableBuilder(rows, ...)
|
||||
local tableBuilder = CreateAndInitFromMixin(TableBuilderMixin, rows);
|
||||
Mixin(tableBuilder, ...);
|
||||
return tableBuilder;
|
||||
end
|
||||
+697
@@ -0,0 +1,697 @@
|
||||
local tRemove = table.remove;
|
||||
local tInsert = table.insert;
|
||||
local tWipe = table.wipe;
|
||||
|
||||
TableUtil = {};
|
||||
|
||||
TableUtil.Constants =
|
||||
{
|
||||
AssociativePriorityTable = true,
|
||||
ArraylikePriorityTable = false,
|
||||
IsIndexTable = true,
|
||||
};
|
||||
|
||||
function ipairs_reverse(table)
|
||||
local function Enumerator(table, index)
|
||||
index = index - 1;
|
||||
local value = table[index];
|
||||
if value ~= nil then
|
||||
return index, value;
|
||||
end
|
||||
end
|
||||
return Enumerator, table, #table + 1;
|
||||
end
|
||||
|
||||
function CreateTableEnumerator(tbl, minIndex, maxIndex)
|
||||
minIndex = minIndex and (minIndex - 1) or 0;
|
||||
maxIndex = maxIndex or math.huge;
|
||||
|
||||
local function Enumerator(tbl, index)
|
||||
index = index + 1;
|
||||
if index <= maxIndex then
|
||||
local value = tbl[index];
|
||||
if value ~= nil then
|
||||
return index, value;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Enumerator, tbl, minIndex;
|
||||
end
|
||||
|
||||
function CreateTableReverseEnumerator(tbl, minIndex, maxIndex)
|
||||
minIndex = minIndex or 1;
|
||||
maxIndex = (maxIndex or #tbl) + 1;
|
||||
|
||||
local function Enumerator(tbl, index)
|
||||
index = index - 1;
|
||||
if index >= minIndex then
|
||||
local value = tbl[index];
|
||||
if value ~= nil then
|
||||
return index, value;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Enumerator, tbl, maxIndex;
|
||||
end
|
||||
|
||||
function tCount(t)
|
||||
if type(t) ~= "table" then
|
||||
return 0
|
||||
end
|
||||
local size = 0
|
||||
for _ in pairs(t) do
|
||||
size = size + 1
|
||||
end
|
||||
return size
|
||||
end
|
||||
|
||||
function tDeleteItem(tbl, item)
|
||||
local size = #tbl;
|
||||
local index = size;
|
||||
while index > 0 do
|
||||
if item == tbl[index] then
|
||||
tRemove(tbl, index);
|
||||
end
|
||||
index = index - 1;
|
||||
end
|
||||
return size - #tbl;
|
||||
end
|
||||
|
||||
function tIndexOf(tbl, item)
|
||||
for i, v in ipairs(tbl) do
|
||||
if item == v then
|
||||
return i;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tContains(tbl, item)
|
||||
local index = 1;
|
||||
while tbl[index] do
|
||||
if ( item == tbl[index] ) then
|
||||
return 1;
|
||||
end
|
||||
index = index + 1;
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
function tContainsValue(tbl, item)
|
||||
for k, v in pairs(tbl) do
|
||||
if item == v then
|
||||
return true;
|
||||
end
|
||||
end
|
||||
return false;
|
||||
end
|
||||
|
||||
function TableUtil.ContainsAllKeys(lhsTable, rhsTable)
|
||||
for key, _ in pairs(lhsTable) do
|
||||
if rhsTable[key] == nil then
|
||||
return false;
|
||||
end
|
||||
end
|
||||
-- Check for any keys that are in rhsTable and not lhsTable.
|
||||
for key, _ in pairs(rhsTable) do
|
||||
if lhsTable[key] == nil then
|
||||
return false;
|
||||
end
|
||||
end
|
||||
return true;
|
||||
end
|
||||
|
||||
function TableUtil.CompareValuesAsKeys(lhsTable, rhsTable, valueToKeyOp)
|
||||
local lhsKeys = CopyTransformedValuesAsKeys(lhsTable, valueToKeyOp);
|
||||
local rhsKeys = CopyTransformedValuesAsKeys(rhsTable, valueToKeyOp);
|
||||
return TableUtil.ContainsAllKeys(lhsKeys, rhsKeys)
|
||||
end
|
||||
|
||||
-- This is a deep compare on the values of the table (based on depth) but not a deep comparison
|
||||
-- of the keys, as this would be an expensive check and won't be necessary in most cases.
|
||||
function tCompare(lhsTable, rhsTable, depth)
|
||||
depth = depth or 1;
|
||||
for key, value in pairs(lhsTable) do
|
||||
if type(value) == "table" then
|
||||
local rhsValue = rhsTable[key];
|
||||
if type(rhsValue) ~= "table" then
|
||||
return false;
|
||||
end
|
||||
if depth > 1 then
|
||||
if not tCompare(value, rhsValue, depth - 1) then
|
||||
return false;
|
||||
end
|
||||
end
|
||||
elseif value ~= rhsTable[key] then
|
||||
return false;
|
||||
end
|
||||
end
|
||||
|
||||
-- Check for any keys that are in rhsTable and not lhsTable.
|
||||
for key, value in pairs(rhsTable) do
|
||||
if lhsTable[key] == nil then
|
||||
return false;
|
||||
end
|
||||
end
|
||||
|
||||
return true;
|
||||
end
|
||||
|
||||
function tInvert(tbl)
|
||||
local inverted = {};
|
||||
for k, v in pairs(tbl) do
|
||||
inverted[v] = k;
|
||||
end
|
||||
return inverted;
|
||||
end
|
||||
|
||||
function TableUtil.TrySet(tbl, key)
|
||||
if not tbl[key] then
|
||||
tbl[key] = true;
|
||||
return true;
|
||||
end
|
||||
return false;
|
||||
end
|
||||
|
||||
function TableUtil.CopyUnique(tbl, isIndexTable)
|
||||
local found = {};
|
||||
local function FilterPredicate(value)
|
||||
return TableUtil.TrySet(found, value);
|
||||
end
|
||||
|
||||
return tFilter(tbl, FilterPredicate, isIndexTable);
|
||||
end
|
||||
|
||||
function TableUtil.CopyUniqueByPredicate(tbl, isIndexTable, unaryPredicate)
|
||||
local found = {};
|
||||
local function FilterPredicate(value)
|
||||
return TableUtil.TrySet(found, unaryPredicate(value));
|
||||
end
|
||||
|
||||
return tFilter(tbl, FilterPredicate, isIndexTable);
|
||||
end
|
||||
|
||||
function tFilter(tbl, pred, isIndexTable)
|
||||
local out = {};
|
||||
|
||||
if (isIndexTable) then
|
||||
local currentIndex = 1;
|
||||
for i, v in ipairs(tbl) do
|
||||
if (pred(v)) then
|
||||
out[currentIndex] = v;
|
||||
currentIndex = currentIndex + 1;
|
||||
end
|
||||
end
|
||||
else
|
||||
for k, v in pairs(tbl) do
|
||||
if (pred(v)) then
|
||||
out[k] = v;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return out;
|
||||
end
|
||||
|
||||
function tAppendAll(table, addedArray)
|
||||
for i, element in ipairs(addedArray) do
|
||||
tinsert(table, element);
|
||||
end
|
||||
end
|
||||
|
||||
function tInsertUnique(tbl, item)
|
||||
if not tContains(tbl, item) then
|
||||
table.insert(tbl, item);
|
||||
return #tbl;
|
||||
end
|
||||
return nil;
|
||||
end
|
||||
|
||||
function tUnorderedRemove(tbl, index)
|
||||
if index ~= #tbl then
|
||||
tbl[index] = tbl[#tbl];
|
||||
end
|
||||
|
||||
tRemove(tbl);
|
||||
end
|
||||
|
||||
function CopyTable(settings, shallow)
|
||||
local copy = {};
|
||||
for k, v in pairs(settings) do
|
||||
if type(v) == "table" and not shallow then
|
||||
copy[k] = CopyTable(v);
|
||||
else
|
||||
copy[k] = v;
|
||||
end
|
||||
end
|
||||
return copy;
|
||||
end
|
||||
|
||||
function MergeTable(destination, source)
|
||||
for k, v in pairs(source) do
|
||||
destination[k] = v;
|
||||
end
|
||||
end
|
||||
|
||||
-- Useful if there are external references to a table but we want to set
|
||||
-- that table's key-value pairs to be exactly the same as another table's key-value pairs.
|
||||
function SetTablePairsToTable(destination, source)
|
||||
tWipe(destination);
|
||||
MergeTable(destination, source);
|
||||
end
|
||||
|
||||
function Accumulate(tbl)
|
||||
local count = 0;
|
||||
for k, v in pairs(tbl) do
|
||||
count = count + v;
|
||||
end
|
||||
return count;
|
||||
end
|
||||
|
||||
function AccumulateOp(tbl, op)
|
||||
local count = 0;
|
||||
for k, v in pairs(tbl) do
|
||||
count = count + op(v);
|
||||
end
|
||||
return count;
|
||||
end
|
||||
|
||||
function TableUtil.Execute(tbl, op)
|
||||
for k, v in pairs(tbl) do
|
||||
op(v);
|
||||
end
|
||||
end
|
||||
|
||||
function TableUtil.ExecuteUntil(tbl, op)
|
||||
for k, v in pairs(tbl) do
|
||||
local operationResult = op(v);
|
||||
if operationResult then
|
||||
return operationResult;
|
||||
end
|
||||
end
|
||||
|
||||
return nil;
|
||||
end
|
||||
|
||||
function TableUtil.Transform(tbl, op)
|
||||
local result = {};
|
||||
for k, v in pairs(tbl) do
|
||||
table.insert(result, op(v));
|
||||
end
|
||||
return result;
|
||||
end
|
||||
|
||||
function ContainsIf(tbl, pred)
|
||||
for k, v in pairs(tbl) do
|
||||
if (pred(v)) then
|
||||
return true;
|
||||
end
|
||||
end
|
||||
|
||||
return false;
|
||||
end
|
||||
|
||||
function FindInTableIf(tbl, pred)
|
||||
for k, v in pairs(tbl) do
|
||||
if (pred(v)) then
|
||||
return k, v;
|
||||
end
|
||||
end
|
||||
|
||||
return nil;
|
||||
end
|
||||
|
||||
function FindValueInTableIf(tbl, pred)
|
||||
local _, value = FindInTableIf(tbl, pred);
|
||||
return value;
|
||||
end
|
||||
|
||||
local function FindSortedIndexImplementation(tbl, searchComparison, startIndex, rangeStart, rangeEnd)
|
||||
local comparisonResult = searchComparison(tbl[startIndex]);
|
||||
if comparisonResult == 0 then
|
||||
return startIndex;
|
||||
end
|
||||
|
||||
if comparisonResult > 0 then
|
||||
if startIndex >= rangeEnd then
|
||||
return startIndex + 1;
|
||||
end
|
||||
|
||||
rangeStart = startIndex + 1;
|
||||
return FindSortedIndexImplementation(tbl, searchComparison, startIndex + math.ceil((rangeEnd - startIndex) / 2), rangeStart, rangeEnd);
|
||||
end
|
||||
|
||||
-- comparisonResult < 0
|
||||
if startIndex <= rangeStart then
|
||||
return startIndex;
|
||||
end
|
||||
|
||||
rangeEnd = startIndex - 1;
|
||||
return FindSortedIndexImplementation(tbl, searchComparison, math.floor(startIndex / 2), rangeStart, rangeEnd);
|
||||
end
|
||||
|
||||
function FindSortedIndex(tbl, searchComparison)
|
||||
local numTable = #tbl;
|
||||
local startingIndex = math.ceil(numTable / 2);
|
||||
if startingIndex == 0 then
|
||||
return 1;
|
||||
end
|
||||
|
||||
return FindSortedIndexImplementation(tbl, searchComparison, startingIndex, 1, numTable);
|
||||
end
|
||||
|
||||
function TableIsEmpty(tbl)
|
||||
return next(tbl) == nil;
|
||||
end
|
||||
|
||||
function TableHasAnyEntries(tbl)
|
||||
return next(tbl) ~= nil;
|
||||
end
|
||||
|
||||
function CopyValuesAsKeys(tbl)
|
||||
local output = {};
|
||||
for k, v in ipairs(tbl) do
|
||||
output[v] = v;
|
||||
end
|
||||
return output;
|
||||
end
|
||||
|
||||
function CopyTransformedValuesAsKeys(tbl, transformOp)
|
||||
local output = {};
|
||||
for _, v in ipairs(tbl) do
|
||||
output[transformOp(v)] = v;
|
||||
end
|
||||
return output;
|
||||
end
|
||||
|
||||
-- Addresses the problem where nil values within a varargs list are not preserved when constructing
|
||||
-- a table, resulting a table with a smaller size than expected. Should be paired with a call to
|
||||
-- SafeUnpack when unpacking the table.
|
||||
function SafePack(...)
|
||||
local tbl = { ... };
|
||||
tbl.n = select("#", ...);
|
||||
return tbl;
|
||||
end
|
||||
|
||||
-- Upacks a table that was constructed using SafePack.
|
||||
function SafeUnpack(tbl, startIndex)
|
||||
return unpack(tbl, startIndex or 1, tbl.n);
|
||||
end
|
||||
|
||||
-- Returns the length of a table, accounting for the possibility of a table constructed using SafePack.
|
||||
function SafeLength(tbl)
|
||||
if not tbl then
|
||||
return 0;
|
||||
end
|
||||
|
||||
local operatorCount = #tbl;
|
||||
local safePackCount = tbl.n;
|
||||
|
||||
if safePackCount and operatorCount ~= safePackCount then
|
||||
return safePackCount;
|
||||
end
|
||||
|
||||
return operatorCount;
|
||||
end
|
||||
|
||||
function GetOrCreateTableEntry(table, key, defaultValue)
|
||||
local currentValue = table[key];
|
||||
local isNewValue = (currentValue == nil);
|
||||
if isNewValue then
|
||||
if defaultValue ~= nil then
|
||||
currentValue = defaultValue;
|
||||
else
|
||||
currentValue = {};
|
||||
end
|
||||
table[key] = currentValue;
|
||||
end
|
||||
|
||||
return currentValue, isNewValue;
|
||||
end
|
||||
|
||||
function GetOrCreateTableEntryByCallback(table, key, callback)
|
||||
local currentValue = table[key];
|
||||
local isNewValue = (currentValue == nil);
|
||||
if isNewValue then
|
||||
currentValue = callback(key);
|
||||
table[key] = currentValue;
|
||||
end
|
||||
|
||||
return currentValue, isNewValue;
|
||||
end
|
||||
|
||||
function GetRandomArrayEntry(array)
|
||||
return array[math.random(1, #array)];
|
||||
end
|
||||
|
||||
function GetRandomTableValue(tbl)
|
||||
local value;
|
||||
local n = 0;
|
||||
for k, v in pairs(tbl) do
|
||||
n = n + 1;
|
||||
local r = math.random();
|
||||
if r <= (1 / n) then
|
||||
value = v;
|
||||
end
|
||||
end
|
||||
return value;
|
||||
end
|
||||
|
||||
function GetKeysArray(tbl)
|
||||
local keysArray = {};
|
||||
for key in pairs(tbl) do
|
||||
tInsert(keysArray, key);
|
||||
end
|
||||
|
||||
return keysArray;
|
||||
end
|
||||
|
||||
function GetValuesArray(tbl)
|
||||
local valuesArray = {};
|
||||
for key, value in pairs(tbl) do
|
||||
tInsert(valuesArray, value);
|
||||
end
|
||||
|
||||
return valuesArray;
|
||||
end
|
||||
|
||||
function GetPairsArray(tbl)
|
||||
local pairsArray = {};
|
||||
for key, value in pairs(tbl) do
|
||||
tInsert(pairsArray, { key = key, value = value, });
|
||||
end
|
||||
|
||||
return pairsArray;
|
||||
end
|
||||
|
||||
function SwapTableEntries(lhsTable, rhsTable, key)
|
||||
local lhsValue = lhsTable[key];
|
||||
lhsTable[key] = rhsTable[key];
|
||||
rhsTable[key] = lhsValue;
|
||||
end
|
||||
|
||||
function GetKeysArraySortedByValue(tbl)
|
||||
local keysArray = GetKeysArray(tbl);
|
||||
|
||||
table.sort(keysArray, function(a, b)
|
||||
return tbl[a] < tbl[b];
|
||||
end);
|
||||
|
||||
return keysArray;
|
||||
end
|
||||
|
||||
function TableUtil.OperateOnKeys(tbl, operation)
|
||||
for key, value in pairs(tbl) do
|
||||
operation(key);
|
||||
end
|
||||
end
|
||||
|
||||
function TableUtil.GetTableValueListFromEnumeration(tableKey, ...)
|
||||
local values = {};
|
||||
for enumerationKey, tbl in ... do
|
||||
table.insert(values, tbl[tableKey]);
|
||||
end
|
||||
|
||||
return values;
|
||||
end
|
||||
|
||||
function TableUtil.GetHighestNumericalValueInTable(table)
|
||||
local highestValue = nil;
|
||||
for key, value in pairs(table) do
|
||||
if type(value) == "number" and (not highestValue or value > highestValue) then
|
||||
highestValue = value;
|
||||
end
|
||||
end
|
||||
return highestValue;
|
||||
end
|
||||
|
||||
--[[
|
||||
This utility creates and returns a table of elements that are sorted by value "priority".
|
||||
|
||||
Arguments:
|
||||
comparator - comparator(A, B) returns whether A has higher priority than B
|
||||
isAssociative - whether the table should be associative (true) or array-like (false). Only values have priorities for associative tables, not keys.
|
||||
|
||||
Return usage:
|
||||
t[k]/t:Get(k) - returns the value stored with key/index k
|
||||
t[k] = v (Associative only) - stores the value v at key k, sorting accordingly
|
||||
t:Insert(v) (Array-like only) - inserts the value v, sorting accordingly
|
||||
t:Remove(k) - removes the element at key/index k
|
||||
t:Iterate(cb) - calls function cb on each key/index value pair in sorted priority order. !!WARNING!! This must be used instead of pairs(t)/ipairs(t)
|
||||
t:GetTop() - returns the highest priority element
|
||||
t:Pop() - returns and removes the highest priority element
|
||||
t:GetBottom() - returns the lowest priority element
|
||||
t:Size() - returns the number of stored elements. !!WARNING!! This must be used instead of #t
|
||||
t:Clear() - removes all elements
|
||||
--]]
|
||||
function TableUtil.CreatePriorityTable(comparator, isAssociative)
|
||||
local sortedArray = {};
|
||||
|
||||
local ShiftPositionMap;
|
||||
local keyToPosMap;
|
||||
if isAssociative then
|
||||
keyToPosMap = {};
|
||||
|
||||
ShiftPositionMap = function(position, shiftUp)
|
||||
local mod = shiftUp and 1 or -1;
|
||||
for k, p in pairs(keyToPosMap) do
|
||||
if p >= position then
|
||||
keyToPosMap[k] = p + mod;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function SortedInsert(k, v)
|
||||
if isAssociative then
|
||||
local prevPos = keyToPosMap[k];
|
||||
if prevPos then
|
||||
tRemove(sortedArray, prevPos);
|
||||
local shiftUp = false;
|
||||
ShiftPositionMap(prevPos, shiftUp);
|
||||
end
|
||||
end
|
||||
|
||||
local top = (#sortedArray > 0) and (#sortedArray + 1) or 1;
|
||||
local bottom = 1;
|
||||
while top ~= bottom do
|
||||
local mid = math.floor((top - bottom) / 2) + bottom;
|
||||
if not comparator(v, sortedArray[mid]) then
|
||||
bottom = mid + 1;
|
||||
else
|
||||
top = mid;
|
||||
end
|
||||
end
|
||||
local idx = bottom;
|
||||
tInsert(sortedArray, idx, v);
|
||||
|
||||
if isAssociative then
|
||||
local shiftUp = true;
|
||||
ShiftPositionMap(idx, shiftUp);
|
||||
keyToPosMap[k] = idx;
|
||||
end
|
||||
end
|
||||
|
||||
local t = {};
|
||||
|
||||
function t:Get(k)
|
||||
local key = isAssociative and keyToPosMap[k] or k;
|
||||
return sortedArray[key];
|
||||
end
|
||||
|
||||
if not isAssociative then
|
||||
function t:Insert(v)
|
||||
SortedInsert(nil, v)
|
||||
end
|
||||
end
|
||||
|
||||
function t:Remove(k)
|
||||
local key = isAssociative and keyToPosMap[k] or k;
|
||||
tRemove(sortedArray, key);
|
||||
if isAssociative then
|
||||
keyToPosMap[k] = nil;
|
||||
local shiftUp = false;
|
||||
ShiftPositionMap(key, shiftUp);
|
||||
end
|
||||
end
|
||||
|
||||
function t:GetTop()
|
||||
return #sortedArray > 0 and sortedArray[1];
|
||||
end
|
||||
|
||||
function t:GetBottom()
|
||||
return #sortedArray > 0 and sortedArray[#sortedArray];
|
||||
end
|
||||
|
||||
function t:Pop()
|
||||
if t:Size() == 0 then
|
||||
return nil;
|
||||
end
|
||||
|
||||
local top = t:GetTop();
|
||||
local removalKey = isAssociative and tInvert(keyToPosMap)[1] or 1;
|
||||
t:Remove(removalKey);
|
||||
return top;
|
||||
end
|
||||
|
||||
function t:Iterate(callback)
|
||||
local posToKeyMap = isAssociative and tInvert(keyToPosMap) or nil;
|
||||
for pos, v in ipairs(sortedArray) do
|
||||
local key = isAssociative and posToKeyMap[pos] or pos;
|
||||
local done = callback(key, v);
|
||||
if done then
|
||||
return;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function t:Size()
|
||||
return #sortedArray;
|
||||
end
|
||||
|
||||
function t:Clear()
|
||||
sortedArray = {};
|
||||
if isAssociative then
|
||||
keyToPosMap = {};
|
||||
end
|
||||
end
|
||||
|
||||
local mt =
|
||||
{
|
||||
__index = function(t, k)
|
||||
return t:Get(k);
|
||||
end,
|
||||
};
|
||||
if isAssociative then
|
||||
mt.__newindex = function(t, k, v)
|
||||
if v ~= nil then
|
||||
SortedInsert(k, v);
|
||||
else
|
||||
t:Remove(k);
|
||||
end
|
||||
end
|
||||
else
|
||||
mt.__newindex = function(t, k, v)
|
||||
error("Attempted to assign a value to an array-like priority queue index. Use Insert()/Remove() instead.")
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(t, mt);
|
||||
|
||||
return t;
|
||||
end
|
||||
|
||||
function DeepMergeTable(destination, source)
|
||||
for k, v in pairs(source) do
|
||||
if type(v) == "table" then
|
||||
if type(destination[k]) == "table" then
|
||||
DeepMergeTable(destination[k], v)
|
||||
else
|
||||
destination[k] = CopyTable(v)
|
||||
end
|
||||
else
|
||||
destination[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
+850
@@ -0,0 +1,850 @@
|
||||
local ADVENTURE_TYPE = {
|
||||
PRIMARY = 1,
|
||||
SECONDARY = 2,
|
||||
}
|
||||
|
||||
local ADVENTURE_CATEGORY = {
|
||||
DEV = 0,
|
||||
NOVICE_TIPS = 1,
|
||||
WINTERGRASP = 2,
|
||||
CATEGORY_BOSSES = 3,
|
||||
SPEC_INFO = 4,
|
||||
QUEST_DAILY_CRYSTALS = 5,
|
||||
BATTLE_PASS_QUEST_DAILY = 6,
|
||||
QUEST_RENEGADE = 7,
|
||||
QUEST_SIRUS = 8,
|
||||
SEASONAL_EVENT = 9,
|
||||
QUEST_WEEKLY_PVE = 10,
|
||||
BRAWL = 11,
|
||||
BATTLE_PASS_QUEST_WEEKLY = 12,
|
||||
RAID_NEWEST_NORMAL = 13,
|
||||
RAID_NEWEST_HEROIC = 14,
|
||||
WEEKEND_EVENT = 15,
|
||||
QUEST_DAILY_ISLAND = 16,
|
||||
ZONE_QUEST = 17,
|
||||
TUTORIAL_COINS = 100,
|
||||
MISC = 128,
|
||||
}
|
||||
|
||||
local ADVENTURE_CATEGORY_PRIORITY = {
|
||||
[ADVENTURE_CATEGORY.DEV] = 0,
|
||||
[ADVENTURE_CATEGORY.NOVICE_TIPS] = 1,
|
||||
[ADVENTURE_CATEGORY.WINTERGRASP] = 1,
|
||||
[ADVENTURE_CATEGORY.CATEGORY_BOSSES] = 1,
|
||||
[ADVENTURE_CATEGORY.SPEC_INFO] = 3,
|
||||
[ADVENTURE_CATEGORY.QUEST_DAILY_CRYSTALS] = 1,
|
||||
[ADVENTURE_CATEGORY.BATTLE_PASS_QUEST_DAILY] = 2,
|
||||
[ADVENTURE_CATEGORY.QUEST_RENEGADE] = 2,
|
||||
[ADVENTURE_CATEGORY.QUEST_SIRUS] = 2,
|
||||
[ADVENTURE_CATEGORY.SEASONAL_EVENT] = 2,
|
||||
[ADVENTURE_CATEGORY.QUEST_WEEKLY_PVE] = 2,
|
||||
[ADVENTURE_CATEGORY.BRAWL] = 2,
|
||||
[ADVENTURE_CATEGORY.BATTLE_PASS_QUEST_WEEKLY] = 5,
|
||||
[ADVENTURE_CATEGORY.RAID_NEWEST_NORMAL] = 2,
|
||||
[ADVENTURE_CATEGORY.RAID_NEWEST_HEROIC] = 2,
|
||||
[ADVENTURE_CATEGORY.WEEKEND_EVENT] = 4,
|
||||
[ADVENTURE_CATEGORY.QUEST_DAILY_ISLAND] = 5,
|
||||
[ADVENTURE_CATEGORY.ZONE_QUEST] = 5,
|
||||
[ADVENTURE_CATEGORY.TUTORIAL_COINS] = 6,
|
||||
[ADVENTURE_CATEGORY.MISC] = 5,
|
||||
}
|
||||
|
||||
local CONDITION_CHECK = {
|
||||
PLAYER_IN_GM_MODE = 0,
|
||||
PLAYER_FACTION = 1,
|
||||
PLAYER_LEVEL = 2,
|
||||
PLAYER_HAS_BUFF = 3,
|
||||
PLAYER_HAS_DEBUFF = 4,
|
||||
PLAYER_HAS_ITEM = 5,
|
||||
PLAYER_SPELL_KNOWN = 6,
|
||||
PET_SPELL_KNOWN = 7,
|
||||
REALM_STAGE = 8,
|
||||
REALM_DUNGEON_ACTUAL = 9,
|
||||
REALM_GAME_EVENT_ACTIVE = 10,
|
||||
PLAYER_QUEST_COMPLETE = 11,
|
||||
PLAYER_ACHIEVEMENT_COMPLETE = 12,
|
||||
PLAYER_BATTLEPASS_DAILY_COUNT = 13,
|
||||
PLAYER_BATTLEPASS_WEEKLY_COUNT = 14,
|
||||
REALM_WINTERGRASP_REGISTRATION_ACTIVE = 15,
|
||||
REALM_BRAWL_ACTIVE = 16,
|
||||
PLAYER_LFG_DUNGEON_JOINABLE = 17,
|
||||
PLAYER_LFG_MINIGAME_JOINABLE = 18,
|
||||
PLAYER_CUSTOM_VALUE = 19,
|
||||
PLAYER_HAS_QUEST_IN_QUESTLOG = 20,
|
||||
PLAYER_TALENT_GROUPS_COUNT = 21,
|
||||
REALM_ID = 22,
|
||||
PLAYER_IN_CHALLENGE_MODE = 23,
|
||||
}
|
||||
|
||||
local CONDITION_OPERATOR = {
|
||||
COMP_TYPE_EQ = 0,
|
||||
COMP_TYPE_HIGH = 1,
|
||||
COMP_TYPE_LOW = 2,
|
||||
COMP_TYPE_HIGH_EQ = 3,
|
||||
COMP_TYPE_LOW_EQ = 4,
|
||||
}
|
||||
|
||||
local ACTION_BUTTON_TYPE = {
|
||||
NONE = 0,
|
||||
QUEST_START = 1,
|
||||
UI_PVP_ARENA_RATING = 2,
|
||||
UI_PVP_HONOR_RANDOM = 3,
|
||||
UI_PVP_HONOR_WINTERGRASP = 4,
|
||||
UI_PVP_HONOR_BRAWL = 5,
|
||||
UI_PVE_LFG_DUNGEON_RANDOM = 6,
|
||||
UI_PVE_LFG_DUNGEON_ID = 7,
|
||||
UI_PVE_LFG_MINIGAME_ID = 8,
|
||||
UI_EJ_DUNGEON_ID = 9,
|
||||
UI_BATTLEPASS_QUESTS = 10,
|
||||
UI_HEAD_HUNTING = 11,
|
||||
}
|
||||
|
||||
local error = error
|
||||
local ipairs = ipairs
|
||||
local pairs = pairs
|
||||
local select = select
|
||||
local tonumber = tonumber
|
||||
local type = type
|
||||
local mathmax, mathmin, mathrandom = math.max, math.min, math.random
|
||||
local strconcat, strformat, strgsub = strconcat, string.format, string.gsub
|
||||
local tinsert, tsort, twipe, tCompare = table.insert, table.sort, table.wipe, tCompare
|
||||
|
||||
local CanQueueForWintergrasp = CanQueueForWintergrasp
|
||||
local GetAchievementInfo = GetAchievementInfo
|
||||
local GetFramerate = GetFramerate
|
||||
local GetItemCount = GetItemCount
|
||||
local GetQuestLinkByID = GetQuestLinkByID
|
||||
local GetSpellInfo = GetSpellInfo
|
||||
local GetTitleForQuestID = GetTitleForQuestID
|
||||
local IsLFGDungeonJoinable = IsLFGDungeonJoinable
|
||||
local IsQuestCompleted = IsQuestCompleted
|
||||
local IsQuestDataCached = IsQuestDataCached
|
||||
local IsSpellKnown = IsSpellKnown
|
||||
local QueryQuestStart = QueryQuestStart
|
||||
local UnitFactionGroup = UnitFactionGroup
|
||||
local UnitLevel = UnitLevel
|
||||
local debugprofilestop = debugprofilestop
|
||||
|
||||
local FireCustomClientEvent = FireCustomClientEvent
|
||||
local GetCurrentBrawlID = C_PvP.GetCurrentBrawlID
|
||||
local IsGameEventActive = IsGameEventActive
|
||||
local IsGMAccount = IsGMAccount
|
||||
local IsInterfaceDevClient = IsInterfaceDevClient
|
||||
--local RequestQuestCacheByID = RequestQuestCacheByID
|
||||
|
||||
local AJ_ACTION_TEXT_JOIN_BATTLE = AJ_ACTION_TEXT_JOIN_BATTLE
|
||||
local AJ_ACTION_TEXT_JOIN_GROUP = AJ_ACTION_TEXT_JOIN_GROUP
|
||||
local AJ_ACTION_TEXT_OPEN_EJ = AJ_ACTION_TEXT_OPEN_EJ
|
||||
local AJ_ACTION_TEXT_SHOW_QUEST = AJ_ACTION_TEXT_SHOW_QUEST
|
||||
local AJ_ACTION_TEXT_START_HUNT = AJ_ACTION_TEXT_START_HUNT
|
||||
local AJ_ACTION_TEXT_START_QUEST = AJ_ACTION_TEXT_START_QUEST
|
||||
local AJ_PRIMARY_REWARD_TEXT = AJ_PRIMARY_REWARD_TEXT
|
||||
local UNKNOWN = UNKNOWN
|
||||
|
||||
local COLOR_PATTERN = strformat("^|cff%s|H", string.rep("[0-9A-Fa-f]", 6))
|
||||
local QUESTION_MARK_ICON = strgsub(QUESTION_MARK_ICON, "%.BLP$", "")
|
||||
|
||||
local NUM_SECONDARY_SUGGESTIONS = 2
|
||||
local MAX_INT = 2^32/2-1
|
||||
|
||||
local PRIVATE = {
|
||||
DIRTY = true,
|
||||
|
||||
FRAMETIME_TARGET = 1 / 55,
|
||||
FRAMETIME_AVAILABLE = 8,
|
||||
FRAMETIME_RESERVE = 4,
|
||||
|
||||
REGISTRY = {},
|
||||
SUGGESTIONS = {},
|
||||
PRIMARY_OFFSET_INDEX = 1,
|
||||
}
|
||||
|
||||
PRIVATE.eventHandler = CreateFrame("Frame")
|
||||
PRIVATE.eventHandler:Hide()
|
||||
PRIVATE.eventHandler:SetScript("OnUpdate", function(self, elapsed)
|
||||
local frametimeStep = PRIVATE.FRAMETIME_TARGET - elapsed
|
||||
|
||||
if frametimeStep ~= 0 then
|
||||
frametimeStep = frametimeStep * 1000
|
||||
PRIVATE.FRAMETIME_AVAILABLE = mathmax(5, PRIVATE.FRAMETIME_AVAILABLE + frametimeStep)
|
||||
end
|
||||
|
||||
if PRIVATE.BUILD_COROUTINE then
|
||||
PRIVATE.BUILD_COROUTINE_TIMESTAMP = debugprofilestop()
|
||||
local status, result, progress = coroutine.resume(PRIVATE.BUILD_COROUTINE)
|
||||
|
||||
if not status then
|
||||
PRIVATE.BUILD_COROUTINE = nil
|
||||
self:Hide()
|
||||
error(result, 2)
|
||||
elseif not result then
|
||||
if PRIVATE.BUILD_COROUTINE_DEBUG then print("AJ_BUILD_COROUTINE", progress) end
|
||||
else
|
||||
PRIVATE.BUILD_COROUTINE = nil
|
||||
self:Hide()
|
||||
end
|
||||
else
|
||||
self:Hide()
|
||||
end
|
||||
end)
|
||||
|
||||
PRIVATE.Initialize = function()
|
||||
if PRIVATE.initialized then
|
||||
return
|
||||
end
|
||||
|
||||
PRIVATE.initialized = true
|
||||
|
||||
_G.ADVENTURE_TYPE = nil
|
||||
_G.ADVENTURE_CATEGORY = nil
|
||||
_G.ADVENTURE_CATEGORY_PRIORITY = nil
|
||||
_G.CONDITION_CHECK = nil
|
||||
_G.ACTION_BUTTON_TYPE = nil
|
||||
|
||||
local ADVENTURE_REGISTRY = _G.ADVENTURE_REGISTRY or {}
|
||||
if not IsInterfaceDevClient() then
|
||||
_G.ADVENTURE_REGISTRY = nil
|
||||
end
|
||||
|
||||
for _, adventureType in pairs(ADVENTURE_TYPE) do
|
||||
PRIVATE.REGISTRY[adventureType] = {}
|
||||
end
|
||||
|
||||
for index, entry in ipairs(ADVENTURE_REGISTRY) do
|
||||
if not entry.rngPriority then
|
||||
entry.rngPriority = mathrandom(1, MAX_INT)
|
||||
end
|
||||
|
||||
if entry.content then
|
||||
entry.content = strgsub(entry.content, "\\n", "\n")
|
||||
end
|
||||
|
||||
tinsert(PRIVATE.REGISTRY[entry.type], entry)
|
||||
end
|
||||
|
||||
for adventureType, registry in pairs(PRIVATE.REGISTRY) do
|
||||
tsort(registry, PRIVATE.SortEntries)
|
||||
end
|
||||
end
|
||||
|
||||
PRIVATE.SortEntries = function(a, b)
|
||||
if ADVENTURE_CATEGORY_PRIORITY[a.category] ~= ADVENTURE_CATEGORY_PRIORITY[b.category] then
|
||||
return ADVENTURE_CATEGORY_PRIORITY[a.category] < ADVENTURE_CATEGORY_PRIORITY[b.category]
|
||||
elseif a.rngPriority ~= b.rngPriority then
|
||||
return a.rngPriority < b.rngPriority
|
||||
elseif a.id ~= b.id then
|
||||
return a.id < b.id
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
PRIVATE.IsMinigameAvailable = function(minigameID)
|
||||
for index = 1, C_MiniGames.GetNumGames() do
|
||||
if C_MiniGames.GetGameIDFromIndex(index) == minigameID then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
PRIVATE.ApplyConditionOperator = function(operator, conditionValue, value)
|
||||
if operator == CONDITION_OPERATOR.COMP_TYPE_EQ then
|
||||
return value == conditionValue
|
||||
elseif operator == CONDITION_OPERATOR.COMP_TYPE_HIGH then
|
||||
return value > conditionValue
|
||||
elseif operator == CONDITION_OPERATOR.COMP_TYPE_LOW then
|
||||
return value < conditionValue
|
||||
elseif operator == CONDITION_OPERATOR.COMP_TYPE_HIGH_EQ then
|
||||
return value >= conditionValue
|
||||
elseif operator == CONDITION_OPERATOR.COMP_TYPE_LOW_EQ then
|
||||
return value <= conditionValue
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
PRIVATE.CheckCondition = function(entry, conditionType, conditionValue, operator, invert)
|
||||
local isComplete = false
|
||||
|
||||
if conditionType == CONDITION_CHECK.PLAYER_QUEST_COMPLETE then
|
||||
isComplete = IsQuestCompleted(conditionValue)
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_HAS_QUEST_IN_QUESTLOG then
|
||||
isComplete = GetQuestLogIndexByID(conditionValue) ~= nil
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_ACHIEVEMENT_COMPLETE then
|
||||
isComplete = select(4, GetAchievementInfo(conditionValue))
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_BATTLEPASS_DAILY_COUNT then
|
||||
isComplete = PRIVATE.ApplyConditionOperator(operator or CONDITION_OPERATOR.COMP_TYPE_HIGH_EQ, conditionValue, C_BattlePass.GetNumQuests(Enum.BattlePass.QuestType.Daily))
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_BATTLEPASS_WEEKLY_COUNT then
|
||||
isComplete = PRIVATE.ApplyConditionOperator(operator or CONDITION_OPERATOR.COMP_TYPE_HIGH_EQ, conditionValue, C_BattlePass.GetNumQuests(Enum.BattlePass.QuestType.Weekly))
|
||||
elseif conditionType == CONDITION_CHECK.REALM_STAGE then
|
||||
isComplete = PRIVATE.ApplyConditionOperator(operator or CONDITION_OPERATOR.COMP_TYPE_HIGH_EQ, conditionValue, C_Service.GetRealmStage())
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_LEVEL then
|
||||
isComplete = PRIVATE.ApplyConditionOperator(operator or CONDITION_OPERATOR.COMP_TYPE_HIGH_EQ, conditionValue, UnitLevel("player"))
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_FACTION then
|
||||
isComplete = PRIVATE.ApplyConditionOperator(operator or CONDITION_OPERATOR.COMP_TYPE_EQ, conditionValue, SERVER_PLAYER_FACTION_GROUP[UnitFactionGroup("player")])
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_CUSTOM_VALUE then
|
||||
isComplete = PRIVATE.ApplyConditionOperator(operator or CONDITION_OPERATOR.COMP_TYPE_HIGH, 0, C_Service.GetCustomValue(conditionValue) or 0)
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_TALENT_GROUPS_COUNT then
|
||||
isComplete = PRIVATE.ApplyConditionOperator(operator or CONDITION_OPERATOR.COMP_TYPE_HIGH, conditionValue, C_Talent.GetNumTalentGroups() or 1)
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_HAS_ITEM then
|
||||
isComplete = GetItemCount(conditionValue) > 0
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_HAS_BUFF then
|
||||
isComplete = C_Unit.FindAuraBySpell("player", conditionValue, "HELPFUL") ~= nil
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_HAS_DEBUFF then
|
||||
isComplete = C_Unit.FindAuraBySpell("player", conditionValue, "HARMFUL") ~= nil
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_SPELL_KNOWN then
|
||||
isComplete = IsSpellKnown(conditionValue, false)
|
||||
elseif conditionType == CONDITION_CHECK.PET_SPELL_KNOWN then
|
||||
isComplete = IsSpellKnown(conditionValue, true)
|
||||
elseif conditionType == CONDITION_CHECK.REALM_ID then
|
||||
isComplete = C_Service.GetRealmID() == conditionValue
|
||||
elseif conditionType == CONDITION_CHECK.REALM_GAME_EVENT_ACTIVE then
|
||||
isComplete = IsGameEventActive(conditionValue)
|
||||
elseif conditionType == CONDITION_CHECK.REALM_BRAWL_ACTIVE then
|
||||
isComplete = GetCurrentBrawlID() == conditionValue
|
||||
elseif conditionType == CONDITION_CHECK.REALM_WINTERGRASP_REGISTRATION_ACTIVE then
|
||||
isComplete = CanQueueForWintergrasp() ~= nil
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_LFG_DUNGEON_JOINABLE then
|
||||
isComplete = conditionValue ~= 0 and IsLFGDungeonJoinable(conditionValue)
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_LFG_MINIGAME_JOINABLE then
|
||||
isComplete = conditionValue ~= 0 and PRIVATE.IsMinigameAvailable(conditionValue)
|
||||
elseif conditionType == CONDITION_CHECK.REALM_DUNGEON_ACTUAL then
|
||||
isComplete = C_EncounterJournal.IsActualInstance(conditionValue, entry.ej_difficultyID)
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_IN_CHALLENGE_MODE then
|
||||
isComplete = (C_Hardcore.GetActiveChallengeID() or 0) == conditionValue
|
||||
elseif conditionType == CONDITION_CHECK.PLAYER_IN_GM_MODE then
|
||||
isComplete = C_Service.IsInGMMode()
|
||||
else -- unhandled condition
|
||||
return false
|
||||
end
|
||||
|
||||
if (not invert and isComplete)
|
||||
or (invert and not isComplete)
|
||||
then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
PRIVATE.CheckConditions = function(entry)
|
||||
for index, condition in ipairs(entry.conditions) do
|
||||
local isComplete = PRIVATE.CheckCondition(entry, condition.type, condition.value, condition.operator, condition.invert)
|
||||
if not isComplete then
|
||||
--[[
|
||||
if condition.altID then
|
||||
if type(condition.altID) == "table" then
|
||||
for idIndex, conditionAltID in ipairs(condition.altID) do
|
||||
isComplete = PRIVATE.CheckCondition(entry, condition.type, conditionAltID, condition.operator, condition.invert)
|
||||
if isComplete then
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
isComplete = PRIVATE.CheckCondition(entry, condition.type, condition.altID, condition.operator, condition.invert)
|
||||
end
|
||||
|
||||
if not isComplete then
|
||||
return false
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
--]]
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
PRIVATE.UpdateSuggestionsCoroutine = function(isLevelUp)
|
||||
local oldIDs = PRIVATE.GetUniqueSuggestionIDs()
|
||||
|
||||
local numEntries = 0
|
||||
local processedEntries = 0
|
||||
for adventureType, registry in ipairs(PRIVATE.REGISTRY) do
|
||||
numEntries = numEntries + #registry
|
||||
end
|
||||
|
||||
do -- Build Suggestions
|
||||
twipe(PRIVATE.SUGGESTIONS)
|
||||
|
||||
local numPrimary = 0
|
||||
local numSecondary = 0
|
||||
|
||||
for adventureType, registry in ipairs(PRIVATE.REGISTRY) do
|
||||
local isPrimary = adventureType == ADVENTURE_TYPE.PRIMARY
|
||||
|
||||
PRIVATE.SUGGESTIONS[adventureType] = {}
|
||||
|
||||
for index, entry in ipairs(registry) do
|
||||
processedEntries = processedEntries + 1
|
||||
|
||||
if PRIVATE.CheckConditions(entry) then
|
||||
if isPrimary then
|
||||
numPrimary = numPrimary + 1
|
||||
tinsert(PRIVATE.SUGGESTIONS[adventureType], entry)
|
||||
else
|
||||
if numSecondary >= NUM_SECONDARY_SUGGESTIONS or numPrimary == 0 then
|
||||
numPrimary = numPrimary + 1
|
||||
tinsert(PRIVATE.SUGGESTIONS[ADVENTURE_TYPE.PRIMARY], entry)
|
||||
else
|
||||
numSecondary = numSecondary + 1
|
||||
tinsert(PRIVATE.SUGGESTIONS[adventureType], entry)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (debugprofilestop() - PRIVATE.BUILD_COROUTINE_TIMESTAMP) > PRIVATE.FRAMETIME_BUDGET then
|
||||
coroutine.yield(false, processedEntries / numEntries)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local newIDs = PRIVATE.GetUniqueSuggestionIDs()
|
||||
local newAdventureNotice = tCompare(oldIDs, newIDs, 2)
|
||||
|
||||
local offsetFound
|
||||
|
||||
do -- try to select previously displayed primary suggestion
|
||||
if PRIVATE.PRIMARY_OFFSET_ID then
|
||||
local suggestion, offsetIndex = PRIVATE.GetSuggestionEntryByID(ADVENTURE_TYPE.PRIMARY, PRIVATE.PRIMARY_OFFSET_ID)
|
||||
if suggestion then
|
||||
PRIVATE.PRIMARY_OFFSET_INDEX = offsetIndex
|
||||
PRIVATE.PRIMARY_OFFSET_ID = suggestion.id
|
||||
offsetFound = true
|
||||
end
|
||||
end
|
||||
|
||||
if not offsetFound then
|
||||
local suggestion = PRIVATE.GetSuggestionEntry(ADVENTURE_TYPE.PRIMARY, 1)
|
||||
if suggestion then
|
||||
PRIVATE.PRIMARY_OFFSET_ID = suggestion.id
|
||||
else
|
||||
PRIVATE.PRIMARY_OFFSET_ID = nil
|
||||
end
|
||||
PRIVATE.PRIMARY_OFFSET_INDEX = 1
|
||||
end
|
||||
end
|
||||
|
||||
FireCustomClientEvent("AJ_REFRESH_DISPLAY", newAdventureNotice)
|
||||
|
||||
return true, 1
|
||||
end
|
||||
|
||||
PRIVATE.UpdateSuggestions = function(isLevelUp)
|
||||
if PRIVATE.BUILD_COROUTINE then
|
||||
return
|
||||
end
|
||||
|
||||
local framerate = GetFramerate()
|
||||
PRIVATE.FRAMETIME_TARGET = framerate > 63 and (1 / 60) or (1 / 55)
|
||||
PRIVATE.FRAMETIME_BUDGET = 1000 / framerate - PRIVATE.FRAMETIME_RESERVE
|
||||
|
||||
PRIVATE.BUILD_COROUTINE = coroutine.create(PRIVATE.UpdateSuggestionsCoroutine)
|
||||
PRIVATE.BUILD_COROUTINE_TIMESTAMP = debugprofilestop()
|
||||
|
||||
local status, result, progress = coroutine.resume(PRIVATE.BUILD_COROUTINE, isLevelUp)
|
||||
if not status then
|
||||
PRIVATE.BUILD_COROUTINE = nil
|
||||
PRIVATE.eventHandler:Hide()
|
||||
error(result, 2)
|
||||
end
|
||||
|
||||
if coroutine.status(PRIVATE.BUILD_COROUTINE) == "dead" then
|
||||
PRIVATE.BUILD_COROUTINE = nil
|
||||
else
|
||||
if PRIVATE.BUILD_COROUTINE_DEBUG then print("AJ_BUILD_COROUTINE", progress) end
|
||||
PRIVATE.eventHandler:Show()
|
||||
end
|
||||
end
|
||||
|
||||
PRIVATE.GetNumPrimarySuggestions = function()
|
||||
if PRIVATE.SUGGESTIONS[ADVENTURE_TYPE.PRIMARY] then
|
||||
return #PRIVATE.SUGGESTIONS[ADVENTURE_TYPE.PRIMARY]
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
PRIVATE.GetNumSecondarySuggestions = function()
|
||||
if PRIVATE.SUGGESTIONS[ADVENTURE_TYPE.SECONDARY] then
|
||||
return #PRIVATE.SUGGESTIONS[ADVENTURE_TYPE.SECONDARY]
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
PRIVATE.GetButtonText = function(suggestion)
|
||||
if suggestion.actionType == ACTION_BUTTON_TYPE.NONE then
|
||||
-- skip
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.QUEST_START then
|
||||
return AJ_ACTION_TEXT_START_QUEST
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVP_ARENA_RATING
|
||||
or suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVP_HONOR_RANDOM
|
||||
or suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVP_HONOR_WINTERGRASP
|
||||
or suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVP_HONOR_BRAWL
|
||||
then
|
||||
return AJ_ACTION_TEXT_JOIN_BATTLE
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVE_LFG_DUNGEON_RANDOM
|
||||
or suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVE_LFG_DUNGEON_ID
|
||||
or suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVE_LFG_MINIGAME_ID
|
||||
then
|
||||
return AJ_ACTION_TEXT_JOIN_GROUP
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_EJ_DUNGEON_ID then
|
||||
return AJ_ACTION_TEXT_OPEN_EJ
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_BATTLEPASS_QUESTS then
|
||||
return AJ_ACTION_TEXT_SHOW_QUEST
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_HEAD_HUNTING then
|
||||
return AJ_ACTION_TEXT_START_HUNT
|
||||
end
|
||||
end
|
||||
|
||||
local ACTION_TARGET_VIEW = {
|
||||
[ACTION_BUTTON_TYPE.UI_PVP_ARENA_RATING] = "pvp-arena-rating",
|
||||
[ACTION_BUTTON_TYPE.UI_PVP_HONOR_RANDOM] = "pvp-honor-random",
|
||||
[ACTION_BUTTON_TYPE.UI_PVP_HONOR_WINTERGRASP] = "pvp-honor-wintergrasp",
|
||||
[ACTION_BUTTON_TYPE.UI_PVP_HONOR_BRAWL] = "pvp-honor-brawl",
|
||||
|
||||
[ACTION_BUTTON_TYPE.UI_PVE_LFG_DUNGEON_RANDOM] = "pve-lfg-dungeon",
|
||||
[ACTION_BUTTON_TYPE.UI_PVE_LFG_DUNGEON_ID] = "pve-lfg-dungeon",
|
||||
[ACTION_BUTTON_TYPE.UI_PVE_LFG_MINIGAME_ID] = "pve-lfg-minigame",
|
||||
}
|
||||
|
||||
PRIVATE.ActivateEntry = function(suggestion)
|
||||
if suggestion.actionType == ACTION_BUTTON_TYPE.NONE then
|
||||
-- skip
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.QUEST_START then
|
||||
local questID = suggestion.actionParam
|
||||
if questID then
|
||||
QueryQuestStart(questID, Enum.QueryQuestStartSource.Suggestion, suggestion.id)
|
||||
-- FireCustomClientEvent("AJ_QUEST_LOG_OPEN", questID or 0, uiMapID or 0)
|
||||
else
|
||||
GMError(string.format("[Suggestion::ActivateEntry] no quest id to start [suggestionID=%d]", suggestion.id))
|
||||
end
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVP_ARENA_RATING
|
||||
or suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVP_HONOR_RANDOM
|
||||
or suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVP_HONOR_WINTERGRASP
|
||||
or suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVP_HONOR_BRAWL
|
||||
then
|
||||
local desiredViewType = ACTION_TARGET_VIEW[suggestion.actionType]
|
||||
FireCustomClientEvent("AJ_ACTION_PVP_LFG", desiredViewType)
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVE_LFG_DUNGEON_RANDOM then
|
||||
for i, lfgDungeonID in ipairs({258, 259, 261}) do
|
||||
if IsLFGDungeonJoinable(lfgDungeonID) then
|
||||
local desiredViewType = ACTION_TARGET_VIEW[suggestion.actionType]
|
||||
FireCustomClientEvent("AJ_ACTION_PVE_LFG", desiredViewType, lfgDungeonID)
|
||||
return
|
||||
end
|
||||
end
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVE_LFG_DUNGEON_ID then
|
||||
local desiredViewType = ACTION_TARGET_VIEW[suggestion.actionType]
|
||||
local lfgDungeonID = suggestion.actionParam or 0
|
||||
if IsLFGDungeonJoinable(lfgDungeonID) then
|
||||
FireCustomClientEvent("AJ_ACTION_PVE_LFG", desiredViewType, lfgDungeonID)
|
||||
end
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_PVE_LFG_MINIGAME_ID then
|
||||
local desiredViewType = ACTION_TARGET_VIEW[suggestion.actionType]
|
||||
local minigameID = suggestion.actionParam or 0
|
||||
FireCustomClientEvent("AJ_ACTION_PVE_LFG", desiredViewType, minigameID)
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_EJ_DUNGEON_ID then
|
||||
local dungeonID = suggestion.actionParam or 0
|
||||
local difficultyID = suggestion.actionParam2 or -1
|
||||
FireCustomClientEvent("AJ_ACTION_EJ_DUNGEON", dungeonID, difficultyID)
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_BATTLEPASS_QUESTS then
|
||||
local showQuestTab = true
|
||||
FireCustomClientEvent("AJ_ACTION_BATTLE_PASS", showQuestTab)
|
||||
elseif suggestion.actionType == ACTION_BUTTON_TYPE.UI_HEAD_HUNTING then
|
||||
FireCustomClientEvent("AJ_ACTION_HEAD_HUNTING")
|
||||
end
|
||||
end
|
||||
|
||||
PRIVATE.GetSuggestionEntry = function(suggestionType, index)
|
||||
if PRIVATE.SUGGESTIONS[suggestionType] then
|
||||
return PRIVATE.SUGGESTIONS[suggestionType][index]
|
||||
end
|
||||
end
|
||||
|
||||
PRIVATE.GetSuggestionEntryByID = function(suggestionType, id)
|
||||
if PRIVATE.SUGGESTIONS[suggestionType] then
|
||||
for index, suggestion in ipairs(PRIVATE.SUGGESTIONS[suggestionType]) do
|
||||
if suggestion.id == id then
|
||||
return suggestion, index
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
PRIVATE.OnItemLoaded = function()
|
||||
FireCustomClientEvent("AJ_REWARD_DATA_RECEIVED")
|
||||
end
|
||||
|
||||
PRIVATE.OnItemLoadedContent = function()
|
||||
FireCustomClientEvent("AJ_REFRESH_DISPLAY", false)
|
||||
end
|
||||
|
||||
PRIVATE.OnQuestLoadedContent = function(questID)
|
||||
FireCustomClientEvent("AJ_REFRESH_DISPLAY", false)
|
||||
end
|
||||
|
||||
PRIVATE.GetQuestLink = function(questID)
|
||||
questID = tonumber(questID)
|
||||
|
||||
if IsQuestDataCached(questID) then
|
||||
local questLink = GetQuestLinkByID(questID)
|
||||
if questLink then
|
||||
questLink = strgsub(questLink, COLOR_PATTERN, "|cff8B0000|H")
|
||||
return questLink
|
||||
end
|
||||
else
|
||||
RequestQuestCacheByID(questID, PRIVATE.OnQuestLoadedContent)
|
||||
end
|
||||
|
||||
local name = GetTitleForQuestID(questID)
|
||||
if not name then
|
||||
name = IsGMAccount() and strformat("%s (quest:%s)", UNKNOWN, questID) or UNKNOWN
|
||||
end
|
||||
return strformat("|cff8B0000|Hquest:%d:-1|h[%s]|h|r", questID, name)
|
||||
end
|
||||
|
||||
PRIVATE.GetItemLink = function(itemID)
|
||||
itemID = tonumber(itemID)
|
||||
local name, link = C_Item.GetItemInfo(itemID, nil, PRIVATE.OnItemLoadedContent, true)
|
||||
if not link then
|
||||
name = IsGMAccount() and strformat("%s (item:%s)", UNKNOWN, itemID) or UNKNOWN
|
||||
return strformat("|cffffffff[%s]|r", name)
|
||||
end
|
||||
return link
|
||||
end
|
||||
|
||||
PRIVATE.GetSpellLink = function(spellID)
|
||||
spellID = tonumber(spellID)
|
||||
local name = GetSpellInfo(spellID)
|
||||
if not name then
|
||||
name = IsGMAccount() and strformat("%s (spell:%s)", UNKNOWN, spellID) or UNKNOWN
|
||||
return strformat("|cffffffff[%s]|r", name)
|
||||
end
|
||||
return strformat("|cff000080|Hspell:%d|h[%s]|h|r", spellID, name)
|
||||
end
|
||||
|
||||
PRIVATE.GetSuggestionInfo = function(suggestionType, index)
|
||||
local suggestion = PRIVATE.GetSuggestionEntry(suggestionType, index)
|
||||
if suggestion then
|
||||
local description = suggestion.content
|
||||
|
||||
if description then
|
||||
description = strgsub(description, "{quest:(%d+)}", PRIVATE.GetQuestLink)
|
||||
description = strgsub(description, "{item:(%d+)}", PRIVATE.GetItemLink)
|
||||
description = strgsub(description, "{spell:(%d+)}", PRIVATE.GetSpellLink)
|
||||
end
|
||||
|
||||
return {
|
||||
title = suggestion.title,
|
||||
description = description,
|
||||
buttonText = PRIVATE.GetButtonText(suggestion),
|
||||
iconPath = suggestion.icon and strconcat([[Interface\Icons\]], suggestion.icon) or QUESTION_MARK_ICON,
|
||||
ej_instanceID = suggestion.ej_instanceID,
|
||||
difficultyID = suggestion.ej_difficultyID or 1,
|
||||
expansionLevel = suggestion.ej_expansionLevel,
|
||||
isRandomDungeon = suggestion.ej_isRandomDungeon,
|
||||
hideDifficulty = suggestion.ej_showDifficulty ~= 1,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
PRIVATE.GetSuggestionByIndex = function(suggestionIndex)
|
||||
if suggestionIndex <= 1 then
|
||||
return PRIVATE.GetSuggestionEntry(ADVENTURE_TYPE.PRIMARY, PRIVATE.PRIMARY_OFFSET_INDEX)
|
||||
else
|
||||
return PRIVATE.GetSuggestionEntry(ADVENTURE_TYPE.SECONDARY, suggestionIndex - 1)
|
||||
end
|
||||
end
|
||||
|
||||
PRIVATE.GetReward = function(suggestion)
|
||||
if not suggestion then
|
||||
return
|
||||
end
|
||||
|
||||
local numRewards = #suggestion.rewards
|
||||
|
||||
if numRewards > 0 then
|
||||
if numRewards == 1 and suggestion.rewardDesc then
|
||||
local itemName, itemLink, itemRarity, iLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, vendorPrice = C_Item.GetItemInfo(suggestion.rewards[1], nil, PRIVATE.OnItemLoaded, true)
|
||||
local rewardDesc = type(suggestion.rewardDesc) == "string" and suggestion.rewardDesc or AJ_PRIMARY_REWARD_TEXT
|
||||
|
||||
return {
|
||||
isRewardTable = false,
|
||||
rewardDesc = rewardDesc,
|
||||
itemLink = itemLink,
|
||||
itemIcon = itemTexture,
|
||||
itemQuantity = 1,
|
||||
}
|
||||
else
|
||||
local rewards = {}
|
||||
|
||||
for index, itemID in ipairs(suggestion.rewards) do
|
||||
local itemName, itemLink, itemRarity, iLevel, itemMinLevel, itemType, itemSubType, itemStackCount, itemEquipLoc, itemTexture, vendorPrice = C_Item.GetItemInfo(suggestion.rewards[index], nil, PRIVATE.OnItemLoaded, true)
|
||||
if itemLink then
|
||||
tinsert(rewards, {
|
||||
itemLink = itemLink,
|
||||
itemIcon = itemTexture,
|
||||
itemQuantity = 1,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if #rewards > 0 then
|
||||
rewards.isRewardList = true
|
||||
return rewards
|
||||
end
|
||||
end
|
||||
elseif false then -- currency item
|
||||
return {
|
||||
isRewardTable = false,
|
||||
rewardDesc = AJ_PRIMARY_REWARD_TEXT,
|
||||
currencyIcon = nil,
|
||||
currencyQuantity = nil,
|
||||
currencyIcon = nil,
|
||||
}
|
||||
else
|
||||
local minItemLevel = suggestion.reward_minItemLevel
|
||||
local maxItemLevel = suggestion.reward_maxItemLevel
|
||||
local itemLevel = suggestion.reward_itemLevel
|
||||
|
||||
if itemLevel or minItemLevel or maxItemLevel then
|
||||
if itemLevel then
|
||||
minItemLevel = nil
|
||||
maxItemLevel = nil
|
||||
elseif not minItemLevel or not maxItemLevel then
|
||||
minItemLevel = nil
|
||||
maxItemLevel = nil
|
||||
itemLevel = minItemLevel or maxItemLevel
|
||||
end
|
||||
|
||||
return {
|
||||
isRewardTable = true,
|
||||
itemLevel = itemLevel,
|
||||
minItemLevel = minItemLevel,
|
||||
maxItemLevel = maxItemLevel,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
PRIVATE.GetUniqueSuggestionIDs = function()
|
||||
local suggestionIDs = {}
|
||||
|
||||
for adventureType, registry in ipairs(PRIVATE.REGISTRY) do
|
||||
suggestionIDs[adventureType] = {}
|
||||
|
||||
for index, entry in ipairs(registry) do
|
||||
suggestionIDs[adventureType][entry.id] = true
|
||||
end
|
||||
end
|
||||
|
||||
return suggestionIDs
|
||||
end
|
||||
|
||||
do
|
||||
if IsInterfaceDevClient() then
|
||||
PRIVATE.BUILD_COROUTINE_DEBUG = true
|
||||
PRIVATE_AJ = PRIVATE
|
||||
end
|
||||
PRIVATE.Initialize()
|
||||
end
|
||||
|
||||
C_AdventureJournal = {}
|
||||
|
||||
function C_AdventureJournal.ReloadData()
|
||||
if IsInterfaceDevClient() then
|
||||
if _G.ADVENTURE_REGISTRY and PRIVATE.initialized then
|
||||
PRIVATE.initialized = nil
|
||||
twipe(PRIVATE.REGISTRY)
|
||||
PRIVATE.Initialize()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function C_AdventureJournal.CanBeShown()
|
||||
return true
|
||||
end
|
||||
|
||||
function C_AdventureJournal.UpdateSuggestions(isLevelUp)
|
||||
PRIVATE.UpdateSuggestions(not not isLevelUp)
|
||||
end
|
||||
|
||||
function C_AdventureJournal.SetPrimaryOffset(offset)
|
||||
if type(offset) ~= "number" then
|
||||
error(strformat("bad argument #1 to 'C_AdventureJournal.SetPrimaryOffset' (number expected, got %s)", offset ~= nil and type(offset) or "no value"), 2)
|
||||
end
|
||||
|
||||
offset = offset + 1
|
||||
|
||||
if offset < 1 or offset > PRIVATE.GetNumPrimarySuggestions() then
|
||||
error(strformat("bad argument #1 to 'C_AdventureJournal.SetPrimaryOffset' (index %s out of range [1 - %s])", offset, PRIVATE.GetNumPrimarySuggestions()), 2)
|
||||
end
|
||||
|
||||
if offset == PRIVATE.PRIMARY_OFFSET_INDEX then
|
||||
return
|
||||
end
|
||||
|
||||
local suggestion = PRIVATE.GetSuggestionEntry(ADVENTURE_TYPE.PRIMARY, offset)
|
||||
if suggestion then
|
||||
PRIVATE.PRIMARY_OFFSET_INDEX = offset
|
||||
PRIVATE.PRIMARY_OFFSET_ID = suggestion.id
|
||||
FireCustomClientEvent("AJ_REFRESH_DISPLAY", false)
|
||||
end
|
||||
end
|
||||
|
||||
function C_AdventureJournal.GetPrimaryOffset()
|
||||
return PRIVATE.PRIMARY_OFFSET_INDEX - 1
|
||||
end
|
||||
|
||||
function C_AdventureJournal.GetNumAvailableSuggestions()
|
||||
return PRIVATE.GetNumPrimarySuggestions()
|
||||
end
|
||||
|
||||
function C_AdventureJournal.GetSuggestions(suggestionTable)
|
||||
if type(suggestionTable) ~= "table" then
|
||||
error(strformat("bad argument #1 to 'C_AdventureJournal.GetSuggestions' (table expected, got %s)", suggestionTable ~= nil and type(suggestionTable) or "no value"), 2)
|
||||
end
|
||||
|
||||
twipe(suggestionTable)
|
||||
|
||||
if PRIVATE.GetNumPrimarySuggestions() > 0 then
|
||||
local suggestion = PRIVATE.GetSuggestionInfo(ADVENTURE_TYPE.PRIMARY, PRIVATE.PRIMARY_OFFSET_INDEX)
|
||||
if suggestion then
|
||||
tinsert(suggestionTable, suggestion)
|
||||
end
|
||||
end
|
||||
|
||||
for index = 1, mathmin(NUM_SECONDARY_SUGGESTIONS, PRIVATE.GetNumSecondarySuggestions()) do
|
||||
local suggestion = PRIVATE.GetSuggestionInfo(ADVENTURE_TYPE.SECONDARY, index)
|
||||
if suggestion then
|
||||
tinsert(suggestionTable, suggestion)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function C_AdventureJournal.GetReward(suggestionIndex)
|
||||
if type(suggestionIndex) ~= "number" then
|
||||
error(strformat("bad argument #1 to 'C_AdventureJournal.GetReward' (number expected, got %s)", suggestionIndex ~= nil and type(suggestionIndex) or "no value"), 2)
|
||||
elseif suggestionIndex < 1 or suggestionIndex > NUM_SECONDARY_SUGGESTIONS + 1 then
|
||||
error(strformat("bad argument #1 to 'C_AdventureJournal.GetReward' (index %s out of range [1 - %s])", suggestionIndex, NUM_SECONDARY_SUGGESTIONS + 1), 2)
|
||||
end
|
||||
|
||||
return PRIVATE.GetReward(PRIVATE.GetSuggestionByIndex(suggestionIndex))
|
||||
end
|
||||
|
||||
function C_AdventureJournal.ActivateEntry(suggestionIndex)
|
||||
if type(suggestionIndex) ~= "number" then
|
||||
error(strformat("bad argument #1 to 'C_AdventureJournal.ActivateEntry' (number expected, got %s)", suggestionIndex ~= nil and type(suggestionIndex) or "no value"), 2)
|
||||
elseif suggestionIndex < 1 or suggestionIndex > NUM_SECONDARY_SUGGESTIONS + 1 then
|
||||
error(strformat("bad argument #1 to 'C_AdventureJournal.ActivateEntry' (index %s out of range [1 - %s])", suggestionIndex, NUM_SECONDARY_SUGGESTIONS + 1), 2)
|
||||
end
|
||||
|
||||
local suggestion = PRIVATE.GetSuggestionByIndex(suggestionIndex)
|
||||
if suggestion then
|
||||
PRIVATE.ActivateEntry(suggestion)
|
||||
end
|
||||
end
|
||||
+2932
File diff suppressed because it is too large
Load Diff
@@ -9,3 +9,34 @@
|
||||
## X-Hidden: 1
|
||||
|
||||
MoonWellClient.lua
|
||||
EncounterJournal\SharedXML\ClientDataGenerated\Generated_ItemsCache1.lua
|
||||
EncounterJournal\SharedXML\ClientDataGenerated\Generated_ItemsCache2.lua
|
||||
EncounterJournal\SharedXML\ClientDataGenerated\Generated_ItemsCache3.lua
|
||||
EncounterJournal\EncounterJournalCompat.lua
|
||||
EncounterJournal\SharedXML\Pools.lua
|
||||
EncounterJournal\SharedXML\TableUtil.lua
|
||||
EncounterJournal\SharedXML\SoundKitConstants.lua
|
||||
EncounterJournal\EncounterJournalData.lua
|
||||
EncounterJournal\Generated_EncounterJournal.lua
|
||||
EncounterJournal\EncounterJournalTierFilter.lua
|
||||
EncounterJournal\EncounterJournalTierSnapshot.lua
|
||||
EncounterJournal\GlobalStrings.lua
|
||||
EncounterJournal\Utils\C_EncounterJournal.lua
|
||||
EncounterJournal\Utils\C_AdventureJournal.lua
|
||||
EncounterJournal\EncounterJournalInit.lua
|
||||
EncounterJournal\EncounterJournalFrameMethods.lua
|
||||
EncounterJournal\EncounterJournalFonts.xml
|
||||
EncounterJournal\SharedXML\SharedTooltipTemplates.xml
|
||||
EncounterJournal\SharedXML\TableBuilder.lua
|
||||
EncounterJournal\SharedXML\EventHandler.lua
|
||||
EncounterJournal\SharedXML\SharedUIPanelTemplates.xml
|
||||
EncounterJournal\SharedXML\SharedUIPanelPKBTTemplates.xml
|
||||
EncounterJournal\SharedXML\HybridScrollFrame.xml
|
||||
EncounterJournal\SharedXML\NavigationBar.xml
|
||||
EncounterJournal\Custom_EncounterJournal\Custom_EncounterJournal.lua
|
||||
EncounterJournal\Custom_EncounterJournal\Custom_EncounterJournal.xml
|
||||
EncounterJournal\Custom_EncounterJournal\Custom_LootJournalItems.xml
|
||||
EncounterJournal\Custom_EncounterJournal\Custom_ItemBrowser.xml
|
||||
EncounterJournal\EncounterJournalScrollFix.lua
|
||||
EncounterJournal\EncounterJournalDungeonMode.lua
|
||||
EncounterJournal\EncounterJournalOpen.lua
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user