ca2b78e217
/fui keeps edit mode, reset and list. The thirty diagnostic and tuning functions behind the other subcommands (bar, bags, character, tabs, close, model, minimap, mouse, map, questlog, chat, chatlines, tabard...) go with them, with Panes.Report, the bags read-back and the 205 texts they alone used. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
496 lines
17 KiB
Lua
496 lines
17 KiB
Lua
-- Main action bar: the client's secure action buttons, kept and reskinned (camelot
|
|
-- ActionButtonTemplate, MainActionBar), with the bar border, page arrows and end caps (gryphons,
|
|
-- wyverns for the Horde).
|
|
-- Recreating the buttons would mean rewriting spells, macros and drag and drop, and risk taint.
|
|
-- Nothing is resized or moved in combat, where the client forbids it.
|
|
|
|
-- camelot ActionButtonTemplate: 45 x 45; shared/ActionBar.lua minButtonPadding = 2
|
|
local BUTTON_SIZE = 45
|
|
local BUTTON_PADDING = 2
|
|
local BUTTON_PITCH = BUTTON_SIZE + BUTTON_PADDING
|
|
local FRAME_WIDTH, FRAME_HEIGHT = 46, 45 -- size of the four state textures
|
|
local BUTTON_COUNT = 12
|
|
local END_CAP_WIDTH, END_CAP_HEIGHT = 154, 95
|
|
local END_CAP_DROP = -2 -- measured on screen: the art bottom drops 2 px below the bar
|
|
local L = ForeverUI.L
|
|
|
|
local ATLAS = {
|
|
normal = "ui-hud-actionbar-iconframe",
|
|
pushed = "ui-hud-actionbar-iconframe-down",
|
|
highlight = "ui-hud-actionbar-iconframe-mouseover",
|
|
border = "ui-hud-actionbar-iconframe-border",
|
|
slot = "ui-hud-actionbar-iconframe-slot",
|
|
background = "ui-hud-actionbar-iconframe-background",
|
|
flash = "ui-hud-actionbar-iconframe-flash",
|
|
}
|
|
|
|
local BARS = {
|
|
"ActionButton", "MultiBarBottomLeftButton", "MultiBarBottomRightButton",
|
|
"MultiBarRightButton", "MultiBarLeftButton", "BonusActionButton",
|
|
}
|
|
|
|
-- The frame is not the button's NormalTexture: ActionButton_Update sets UI-Quickslot2 on
|
|
-- every refresh and ActionButton_ShowGrid recolors it, erasing any skin. So the client's
|
|
-- texture is silenced and we draw our own frame. add: use the ADD blend mode.
|
|
local function setStateTexture(texture, atlas, add)
|
|
if not texture then
|
|
return
|
|
end
|
|
|
|
ForeverUI.SetAtlas(texture, atlas, true)
|
|
texture:SetWidth(FRAME_WIDTH)
|
|
texture:SetHeight(FRAME_HEIGHT)
|
|
texture:ClearAllPoints()
|
|
texture:SetPoint("TOPLEFT", 0, 0)
|
|
texture:SetBlendMode(add and "ADD" or "BLEND")
|
|
end
|
|
|
|
-- Hide again what the client just rewrote.
|
|
local function silenceNormalTexture(button)
|
|
local normal = button:GetNormalTexture()
|
|
if normal then
|
|
normal:SetAlpha(0)
|
|
normal:SetVertexColor(1, 1, 1, 0)
|
|
end
|
|
end
|
|
|
|
-- 3.3.5 trap: ActionButton_Update and ActionButton_HideGrid hide the WHOLE empty button while
|
|
-- its "showgrid" ATTRIBUTE is 0, and it only rises during a drag, so empty slots vanish, in
|
|
-- combat too (a stance change updates every button). Keeping the attribute at 1 makes the
|
|
-- client keep empty buttons shown. A secure frame changes only out of combat;
|
|
-- PLAYER_REGEN_ENABLED brings back anything hidden meanwhile.
|
|
local function keepGrid(button)
|
|
if not button or InCombatLockdown() or button:GetAttribute("statehidden") then
|
|
return
|
|
end
|
|
|
|
if (button:GetAttribute("showgrid") or 0) < 1 then
|
|
button:SetAttribute("showgrid", 1)
|
|
end
|
|
if not button:IsShown() then
|
|
button:Show()
|
|
end
|
|
end
|
|
|
|
local function skinButton(button)
|
|
if not button or button.foreverSkinned then
|
|
return
|
|
end
|
|
|
|
local name = button:GetName()
|
|
if not name then
|
|
return
|
|
end
|
|
|
|
local icon = _G[name .. "Icon"]
|
|
local border = _G[name .. "Border"]
|
|
local hotkey = _G[name .. "HotKey"]
|
|
local count = _G[name .. "Count"]
|
|
local macro = _G[name .. "Name"]
|
|
local cooldown = _G[name .. "Cooldown"]
|
|
local flash = _G[name .. "Flash"]
|
|
local floatingBG = _G[name .. "FloatingBG"]
|
|
|
|
button:SetWidth(BUTTON_SIZE)
|
|
button:SetHeight(BUTTON_SIZE)
|
|
|
|
-- Empty slot, under the icon.
|
|
local background = button:CreateTexture(nil, "BACKGROUND")
|
|
ForeverUI.SetAtlas(background, ATLAS.background, true)
|
|
background:SetAllPoints(button)
|
|
|
|
local slot = button:CreateTexture(nil, "BACKGROUND")
|
|
ForeverUI.SetAtlas(slot, ATLAS.slot, true)
|
|
slot:SetAllPoints(button)
|
|
|
|
button.foreverBackground = background
|
|
button.foreverSlot = slot
|
|
|
|
if icon then
|
|
-- The icon fills the button, as in camelot; 3.3.5 has no MaskTexture, so the frame's
|
|
-- solid corners cover the icon's corners.
|
|
icon:ClearAllPoints()
|
|
icon:SetAllPoints(button)
|
|
icon:SetTexCoord(0, 1, 0, 1)
|
|
icon:SetDrawLayer("BORDER")
|
|
end
|
|
|
|
-- Our frame, above the icon and out of the client's reach.
|
|
local frame = button:CreateTexture(nil, "ARTWORK")
|
|
setStateTexture(frame, ATLAS.normal)
|
|
button.foreverFrame = frame
|
|
|
|
silenceNormalTexture(button)
|
|
setStateTexture(button:GetPushedTexture(), ATLAS.pushed)
|
|
setStateTexture(button:GetHighlightTexture(), ATLAS.highlight)
|
|
setStateTexture(button:GetCheckedTexture(), ATLAS.highlight, true)
|
|
|
|
if flash then
|
|
ForeverUI.SetAtlas(flash, ATLAS.flash)
|
|
flash:ClearAllPoints()
|
|
flash:SetPoint("TOPLEFT", 0, 0)
|
|
end
|
|
|
|
if border then
|
|
-- The client's equipped border is green and square; camelot uses its own, hidden by default.
|
|
ForeverUI.SetAtlas(border, ATLAS.border)
|
|
border:ClearAllPoints()
|
|
border:SetPoint("TOPLEFT", 0, 0)
|
|
end
|
|
|
|
if floatingBG then
|
|
floatingBG:SetAlpha(0)
|
|
end
|
|
|
|
-- SetFontObject RESETS the justification, so set it AFTER. The number fonts have no
|
|
-- justifyH (client FontStyles.xml), so they are centered by default.
|
|
if hotkey then
|
|
hotkey:SetWidth(32)
|
|
hotkey:SetHeight(10)
|
|
hotkey:ClearAllPoints()
|
|
hotkey:SetPoint("TOPRIGHT", -5, -5)
|
|
hotkey:SetFontObject(NumberFontNormalSmallGray)
|
|
hotkey:SetJustifyH("RIGHT")
|
|
end
|
|
|
|
if count then
|
|
count:ClearAllPoints()
|
|
count:SetPoint("BOTTOMRIGHT", -5, 5)
|
|
count:SetFontObject(NumberFontNormal)
|
|
count:SetJustifyH("RIGHT")
|
|
end
|
|
|
|
if macro then
|
|
macro:SetWidth(36)
|
|
macro:SetHeight(10)
|
|
macro:ClearAllPoints()
|
|
macro:SetPoint("BOTTOM", 0, 2)
|
|
macro:SetFontObject(GameFontHighlightSmallOutline)
|
|
end
|
|
|
|
if cooldown and icon then
|
|
cooldown:ClearAllPoints()
|
|
cooldown:SetPoint("TOPLEFT", icon, "TOPLEFT", 3, -3)
|
|
cooldown:SetPoint("BOTTOMRIGHT", icon, "BOTTOMRIGHT", -3, 3)
|
|
end
|
|
|
|
keepGrid(button)
|
|
button.foreverSkinned = true
|
|
end
|
|
|
|
-- ---------- Bar
|
|
local holder = CreateFrame("Frame", "ForeverUIActionBarHolder", UIParent)
|
|
holder:SetWidth(BUTTON_COUNT * BUTTON_SIZE + (BUTTON_COUNT - 1) * BUTTON_PADDING)
|
|
holder:SetHeight(BUTTON_SIZE)
|
|
|
|
-- Bar border: camelot's UI-HUD-ActionBar-Frame, one octagonal image, from TOPLEFT (-6, 6)
|
|
-- to BOTTOMRIGHT (4, -5). Nine-sliced so the corner bevels keep their size.
|
|
local border = CreateFrame("Frame", nil, holder)
|
|
border:SetPoint("TOPLEFT", -6, 6)
|
|
border:SetPoint("BOTTOMRIGHT", 4, -5)
|
|
border:SetFrameLevel(holder:GetFrameLevel())
|
|
ForeverUI.SetBarFrameArt(border)
|
|
|
|
-- Page block (mainline/MainActionBar.xml ActionBarPageNumber): BOTTOMRIGHT on the bar's
|
|
-- BOTTOMLEFT at (-4, 9); number 17 x 10 centered at -1, two 17 x 14 arrows at +10 and -10;
|
|
-- sized by its children: 17 x 34.
|
|
local page = CreateFrame("Frame", "ForeverUIActionBarPage", holder)
|
|
page:SetWidth(17)
|
|
page:SetHeight(34)
|
|
page:SetPoint("BOTTOMRIGHT", holder, "BOTTOMLEFT", -4, 9)
|
|
page:SetFrameLevel(holder:GetFrameLevel() + 11)
|
|
|
|
-- Dividers between buttons: RIGHT on the button's LEFT, offset 5.
|
|
local dividers = {}
|
|
|
|
-- End caps (gryphons): two 154 x 95 frames filled by their texture, movable on their own
|
|
-- (Customize UI); BottomBar.lua gives their default positions.
|
|
local END_CAP_INSET = 30 -- each cap overlaps its bar by 30 px
|
|
local function createEndCap(name, atlas)
|
|
local cap = CreateFrame("Frame", name, UIParent)
|
|
cap:SetWidth(END_CAP_WIDTH)
|
|
cap:SetHeight(END_CAP_HEIGHT)
|
|
-- Behind every element of the playing screen (levels 1 and up of the same strata): a cap
|
|
-- never covers anything.
|
|
cap:SetFrameStrata(holder:GetFrameStrata())
|
|
cap:SetFrameLevel(0)
|
|
|
|
local texture = cap:CreateTexture(nil, "OVERLAY")
|
|
texture:SetAllPoints(cap)
|
|
if not ForeverUI.SetAtlas(texture, atlas, true) then
|
|
cap:Hide()
|
|
end
|
|
cap.texture = texture
|
|
return cap
|
|
end
|
|
|
|
-- mainline/EditModePresetLayouts.lua: the left cap sits on the bar's LEFT edge, the right
|
|
-- cap on the bag bar's RIGHT edge, each 30 px inward (BottomBar.lua re-anchors it to the
|
|
-- bags). Camelot drops the cap 20 px below the bar, off screen for a bar 2 px above the
|
|
-- screen bottom, so the art bottom is aligned on the bar bottom, then 2 px lower.
|
|
local leftCap = createEndCap("ForeverUIActionBarLeftCap", "ui-hud-actionbar-gryphon-left")
|
|
local rightCap = createEndCap("ForeverUIActionBarRightCap", "ui-hud-actionbar-gryphon-right")
|
|
|
|
-- Faction art: camelot always draws the gryphons (camelot/MainMenuBarEndCaps.xml); on the user's
|
|
-- request (2026-10-18) the Horde gets the wyverns of the same sheet (ui-hud-actionbar-wyvern-*,
|
|
-- same 240 x 140 size). The faction is read again on PLAYER_ENTERING_WORLD.
|
|
local function applyFactionCaps()
|
|
local kind = (UnitFactionGroup and UnitFactionGroup("player") == "Horde") and "wyvern" or "gryphon"
|
|
if leftCap.kind == kind then
|
|
return
|
|
end
|
|
leftCap.kind = kind
|
|
ForeverUI.SetAtlas(leftCap.texture, "ui-hud-actionbar-" .. kind .. "-left", true)
|
|
ForeverUI.SetAtlas(rightCap.texture, "ui-hud-actionbar-" .. kind .. "-right", true)
|
|
end
|
|
applyFactionCaps()
|
|
|
|
-- The bonus bar takes the same place. On a stance change 3.3.5 shows BonusActionBarFrame
|
|
-- over the main bar at its own position, so its buttons are anchored like the main ones and
|
|
-- follow the holder. Nothing is reparented: buttons follow the client bar's visibility.
|
|
-- 3.3.5 slides this bar in, but secure buttons cannot move every frame in combat, where
|
|
-- stances change: they are anchored ONCE to a track (our frame), and the track slides, out
|
|
-- of combat only (see below).
|
|
local PLACED_BARS = { "ActionButton", "BonusActionButton" }
|
|
|
|
-- The track covers the holder and shifts vertically while sliding. The duration comes from
|
|
-- the client when it declares it.
|
|
local track = CreateFrame("Frame", "ForeverUIBonusSlide", holder)
|
|
local SLIDE_DURATION = BONUSACTIONBAR_SLIDETIME or 0.2
|
|
local SLIDE_DISTANCE = BUTTON_SIZE
|
|
|
|
local function placeTrack(progress)
|
|
local offset = -SLIDE_DISTANCE * (1 - progress)
|
|
track:ClearAllPoints()
|
|
track:SetPoint("TOPLEFT", holder, "TOPLEFT", 0, offset)
|
|
track:SetPoint("BOTTOMRIGHT", holder, "BOTTOMRIGHT", 0, offset)
|
|
end
|
|
placeTrack(1)
|
|
|
|
-- The slide goes both ways. When hiding, the client sets mode = "hide" and keeps the bar
|
|
-- shown until the move ends, so the mode is read rather than the visibility alone. Without
|
|
-- that field the hide is instant: hidden buttons cannot be animated.
|
|
-- The bonus buttons are anchored to the track, which makes it protected (as the crafting page,
|
|
-- ProfessionsBook.lua): it never moves in combat. It waits at rest while the bar is hidden and
|
|
-- goes back to rest when combat starts, so a bar shown in combat appears in place, unslid.
|
|
track.progress = 1
|
|
track.target = 1
|
|
track:SetScript("OnUpdate", function(self, elapse)
|
|
local bar = BonusActionBarFrame
|
|
local visible = bar and bar:IsShown()
|
|
|
|
if InCombatLockdown() then
|
|
self.visible = visible
|
|
return
|
|
end
|
|
|
|
if visible and not self.visible then
|
|
self.progress, self.target = 0, 1 -- shown: slides up
|
|
elseif visible then
|
|
-- the client is hiding it, or shows it again before the end of its own slide
|
|
self.target = (bar.mode == "hide") and 0 or 1
|
|
else
|
|
if self.progress ~= 1 then
|
|
placeTrack(1) -- hidden: back at rest
|
|
end
|
|
self.progress, self.target = 1, 1
|
|
end
|
|
self.visible = visible
|
|
|
|
if self.progress ~= self.target then
|
|
local step = (elapse or 0) / SLIDE_DURATION
|
|
if self.target > self.progress then
|
|
self.progress = math.min(self.target, self.progress + step)
|
|
else
|
|
self.progress = math.max(self.target, self.progress - step)
|
|
end
|
|
placeTrack(self.progress)
|
|
end
|
|
end)
|
|
-- PLAYER_REGEN_DISABLED fires before the lockdown: last moment to put the track at rest
|
|
track:RegisterEvent("PLAYER_REGEN_DISABLED")
|
|
track:SetScript("OnEvent", function(self)
|
|
self.progress, self.target = 1, 1
|
|
placeTrack(1)
|
|
end)
|
|
ForeverUI.ActionBarSlide = track
|
|
|
|
local function layoutButtons()
|
|
if InCombatLockdown() then
|
|
return
|
|
end
|
|
|
|
for _, prefix in ipairs(PLACED_BARS) do
|
|
local anchor = (prefix == "BonusActionButton") and track or holder
|
|
for index = 1, BUTTON_COUNT do
|
|
local button = _G[prefix .. index]
|
|
if button then
|
|
button:ClearAllPoints()
|
|
button:SetPoint("LEFT", anchor, "LEFT", (index - 1) * BUTTON_PITCH, 0)
|
|
|
|
-- Dividers belong to the holder: one set, placed on the main bar.
|
|
if prefix == "ActionButton" and index > 1 and not dividers[index] then
|
|
local divider = ForeverUI.CreateDivider(holder, holder:GetFrameLevel() + 1)
|
|
divider:SetPoint("TOP", button, "TOP", 0, 0)
|
|
divider:SetPoint("BOTTOM", button, "BOTTOM", 0, 0)
|
|
divider:SetPoint("RIGHT", button, "LEFT", 5, 0)
|
|
dividers[index] = divider
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Hide the client's bar art. 3.3.5 MainMenuBar.xml has FOUR sets of pieces, and missing one
|
|
-- leaves the old dwarf bar behind ours: MainMenuBarTexture0..3 (bar body),
|
|
-- MainMenuXPBarTexture0..3 (XP bar frame), MainMenuMaxLevelBar0..3 (shown at 80), the
|
|
-- MainMenuBarLeftEndCap / RightEndCap end caps, and MainMenuBarExpText.
|
|
local OLD_ART = {
|
|
"MainMenuBarTexture%d", "MainMenuXPBarTexture%d", "MainMenuMaxLevelBar%d",
|
|
}
|
|
|
|
-- Bonus bar art: all the frame's own texture regions are hidden (buttons are child frames,
|
|
-- not regions). The frame also stops taking the mouse: BonusActionBarFrame is 505 x 43, HIGH
|
|
-- strata, toplevel, enableMouse; invisible, it would still swallow clicks on the micro-menu
|
|
-- below it. Its buttons keep their own mouse, being child frames.
|
|
local function clearBonusArt()
|
|
local bar = BonusActionBarFrame
|
|
if not bar or not bar.GetRegions then
|
|
return
|
|
end
|
|
|
|
if bar.EnableMouse then
|
|
bar:EnableMouse(false)
|
|
end
|
|
|
|
local regions = { bar:GetRegions() }
|
|
for _, region in ipairs(regions) do
|
|
if region and region.GetObjectType and region:GetObjectType() == "Texture" then
|
|
region:SetAlpha(0)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function hideOldBarArt()
|
|
clearBonusArt()
|
|
|
|
for _, model in ipairs(OLD_ART) do
|
|
for index = 0, 3 do
|
|
local texture = _G[string.format(model, index)]
|
|
if texture then
|
|
texture:SetAlpha(0)
|
|
end
|
|
end
|
|
end
|
|
|
|
for _, name in ipairs({ "MainMenuBarLeftEndCap", "MainMenuBarRightEndCap", "MainMenuBarExpText" }) do
|
|
local region = _G[name]
|
|
if region then
|
|
region:SetAlpha(0)
|
|
end
|
|
end
|
|
|
|
if MainMenuBarPageNumber then
|
|
MainMenuBarPageNumber:SetAlpha(1)
|
|
MainMenuBarPageNumber:SetWidth(17)
|
|
MainMenuBarPageNumber:SetHeight(10)
|
|
MainMenuBarPageNumber:SetJustifyH("CENTER")
|
|
MainMenuBarPageNumber:ClearAllPoints()
|
|
MainMenuBarPageNumber:SetPoint("CENTER", page, "CENTER", -1, 0)
|
|
end
|
|
|
|
-- Page arrows: camelot has its own in the bar atlas.
|
|
local arrows = {
|
|
{ button = ActionBarUpButton, prefix = "ui-hud-actionbar-pageuparrow", y = 10 },
|
|
{ button = ActionBarDownButton, prefix = "ui-hud-actionbar-pagedownarrow", y = -10 },
|
|
}
|
|
for _, entry in ipairs(arrows) do
|
|
local button = entry.button
|
|
if button and not button.foreverSkinned then
|
|
ForeverUI.SetAtlas(button:GetNormalTexture(), entry.prefix .. "-up")
|
|
ForeverUI.SetAtlas(button:GetPushedTexture(), entry.prefix .. "-down")
|
|
ForeverUI.SetAtlas(button:GetHighlightTexture(), entry.prefix .. "-mouseover")
|
|
if button.GetDisabledTexture and button:GetDisabledTexture() then
|
|
ForeverUI.SetAtlas(button:GetDisabledTexture(), entry.prefix .. "-disabled")
|
|
end
|
|
button:SetWidth(17)
|
|
button:SetHeight(14)
|
|
-- 3.3.5 insets the 32 x 32 arrows by 6 and 7 px: kept on 17 x 14, they leave no
|
|
-- clickable area. Camelot's arrows have none.
|
|
button:SetHitRectInsets(0, 0, 0, 0)
|
|
button:ClearAllPoints()
|
|
button:SetPoint("CENTER", page, "CENTER", 0, entry.y)
|
|
button.foreverSkinned = true
|
|
end
|
|
end
|
|
end
|
|
|
|
local function skinAll()
|
|
for _, prefix in ipairs(BARS) do
|
|
for index = 1, BUTTON_COUNT do
|
|
local button = _G[prefix .. index]
|
|
skinButton(button)
|
|
keepGrid(button)
|
|
end
|
|
end
|
|
hideOldBarArt()
|
|
end
|
|
|
|
-- The client rewrites the normal texture on every button update: silence it again after.
|
|
if hooksecurefunc then
|
|
hooksecurefunc("ActionButton_Update", function(self)
|
|
-- a window tab on the bar shows the tab's icon (TabMacros.lua)
|
|
if ForeverUI.TabMacros then
|
|
ForeverUI.TabMacros.ShowIcon(self)
|
|
end
|
|
if self and self.foreverSkinned then
|
|
silenceNormalTexture(self)
|
|
keepGrid(self)
|
|
end
|
|
end)
|
|
|
|
hooksecurefunc("ActionButton_ShowGrid", function(self)
|
|
if self and self.foreverSkinned then
|
|
silenceNormalTexture(self)
|
|
end
|
|
end)
|
|
|
|
-- Here the client hides empty buttons.
|
|
hooksecurefunc("ActionButton_HideGrid", function(self)
|
|
if self and self.foreverSkinned then
|
|
silenceNormalTexture(self)
|
|
keepGrid(self)
|
|
end
|
|
end)
|
|
end
|
|
|
|
local watcher = CreateFrame("Frame")
|
|
watcher:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
watcher:RegisterEvent("PLAYER_REGEN_ENABLED")
|
|
watcher:RegisterEvent("ACTIONBAR_PAGE_CHANGED")
|
|
watcher:RegisterEvent("UPDATE_BONUS_ACTIONBAR")
|
|
watcher:SetScript("OnEvent", function(_self, event)
|
|
if event == "PLAYER_ENTERING_WORLD" then
|
|
applyFactionCaps()
|
|
end
|
|
skinAll()
|
|
layoutButtons()
|
|
end)
|
|
|
|
skinAll()
|
|
layoutButtons()
|
|
|
|
ForeverUI.ActionBarHolder = holder
|
|
ForeverUI.ActionBarBorder = border
|
|
ForeverUI.ActionBarEndCaps = { left = leftCap, right = rightCap, inset = END_CAP_INSET, drop = END_CAP_DROP,
|
|
faction = applyFactionCaps }
|
|
-- camelot/EditModePresetLayoutConstants.lua: BOTTOMRIGHT on the micro-menu's BOTTOMLEFT at
|
|
-- (-4.5, -4); the micro-menu at BOTTOM (116.5, 6), 275 wide, puts the bar's right edge at
|
|
-- -25.5 from the screen center, 2 from the bottom. BottomBar.lua redoes this with the real
|
|
-- micro-menu width.
|
|
ForeverUI.Layout.Register(holder, "actionbar", L.ACTIONBAR_EDIT_LABEL, "BOTTOMRIGHT", "BOTTOM", -25.5, 2)
|
|
ForeverUI.Layout.Register(leftCap, "leftgryphon", L.ACTIONBAR_EDIT_LABEL_LEFT_GRYPHON, "BOTTOMRIGHT", "BOTTOM",
|
|
-25.5 - holder:GetWidth() + END_CAP_INSET, 2 + END_CAP_DROP)
|
|
ForeverUI.Layout.Register(rightCap, "rightgryphon", L.ACTIONBAR_EDIT_LABEL_RIGHT_GRYPHON, "BOTTOMLEFT", "BOTTOM",
|
|
0, 2 + END_CAP_DROP)
|