-- ForeverUI: the mounts tab of the character sheet, under the pet tab (3.3.5 showed mounts as a -- page of the pet screen). Left pane: the selected mount in 3D, turned by the arrows or the -- mouse like the pet. Right pane: the mounts as equipment set cards (EquipmentManager.lua -- measures), without the edit and delete buttons, scrolled by camelot's bar. -- GetCompanionInfo("MOUNT", i) returns creatureID, name, spellID, icon, active. local ForeverUI = ForeverUI or {} _G.ForeverUI = ForeverUI -- The equipment set card: 40 high, background 45 high from x = 42 (the art keeps its 5 px -- overhang), icon 36 at x = 4 in its circle, name from x = 55, check 12 px from the right -- edge. Without edit and delete buttons the name keeps only the check's room. local CARD_H = 40 local CARD_BACKGROUND_X, CARD_BACKGROUND_H = 42, 45 local CARD_ICON, CARD_ICON_X = 36, 4 local CARD_TEXT_X, CARD_TEXT_H = 55, 38 local CHECKMARK_X = -12 local TEXT_RIGHT = 30 -- List: 9 from the pane's left edge and 8 from its top, as the set list; 8 from the right edge -- without a bar, 21 with one (5 gap, 8 bar, 8 margin). local LIST_X, LIST_Y = 9, -8 local LIST_RIGHT, LIST_RIGHT_BAR = -8, -21 local LIST_BOTTOM = 8 -- Rotation arrows of the character and pet previews: 35 x 35, side by side, centered on the -- pane's top local ROTATION_SIZE, ROTATION_Y, ROTATION_GAP = 35, -12, 4 -- Right pane height before the window is laid out (GetHeight returns 0 then) local PANE_H = 464 local ATLAS_BACKGROUND = "ui-character-info-outfitcard" local ATLAS_HOVER = "ui-character-info-outfitcard-hover" local ATLAS_SELECTED = "ui-character-info-outfitcard-selected" local ATLAS_CHECKMARK = "ui-character-info-icon-tick" local ATLAS_CIRCLE = "ui-character-info-outfiticon-frame" local preview, panel, list, bar local cards, offset = {}, 0 local selected -- creature id of the chosen mount local layout -- ---------------------------------------------------------------- Data local function count() return (GetNumCompanions and GetNumCompanions("MOUNT")) or 0 end -- Index of the chosen mount. With none chosen yet, or gone, the ridden one, else the first. local function selectedIndex() local total, ridden = count(), nil for index = 1, total do local creatureID, _, _, _, active = GetCompanionInfo("MOUNT", index) if creatureID == selected then return index end if active and not ridden then ridden = index end end local index = ridden or (total > 0 and 1) or nil selected = index and GetCompanionInfo("MOUNT", index) or nil return index end -- ---------------------------------------------------------------- Preview local function updatePreview() if not preview or not preview:IsVisible() then return end local index = selectedIndex() local creatureID = index and GetCompanionInfo("MOUNT", index) if creatureID and preview.creature ~= creatureID then preview.creature = creatureID preview:SetCreature(creatureID) preview:SetRotation(preview.rotation or 0) end end -- side: "Left" or "Right"; x: offset from the pane's top center. Named after the model, as -- Model_OnUpdate looks them up to turn it while held. local function createArrow(pane, side, x) local button = CreateFrame("Button", preview:GetName() .. "Rotate" .. side .. "Button", preview) button:SetWidth(ROTATION_SIZE) button:SetHeight(ROTATION_SIZE) button:SetPoint("TOP", pane, "TOP", x, ROTATION_Y) button:SetFrameLevel(preview:GetFrameLevel() + 2) button:RegisterForClicks("LeftButtonDown", "LeftButtonUp") button:SetNormalTexture("Interface\\Buttons\\UI-Rotation" .. side .. "-Button-Up") button:SetPushedTexture("Interface\\Buttons\\UI-Rotation" .. side .. "-Button-Down") button:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Round") button:GetHighlightTexture():SetBlendMode("ADD") local turn = side == "Left" and Model_RotateLeft or Model_RotateRight button:SetScript("OnClick", function() turn(preview) end) end -- Left pane content; host: the left pane frame. Returns its root (see Panes.Register). local function build(host) if preview then updatePreview() return preview.pane, {} end local pane = CreateFrame("Frame", "ForeverUIMountsPreviewPane", host) pane:SetAllPoints(host) preview = CreateFrame("PlayerModel", "ForeverUIMountsPreview", pane) preview:SetAllPoints(pane) preview.pane = pane Model_OnLoad(preview) local half = ROTATION_SIZE / 2 + ROTATION_GAP / 2 createArrow(pane, "Left", -half) createArrow(pane, "Right", half) preview:SetScript("OnUpdate", Model_OnUpdate) -- A model hidden when its creature was set shows nothing: set it again on show preview:SetScript("OnShow", function(self) self.creature = nil updatePreview() end) ForeverUI.RotateWithMouse(preview) updatePreview() return pane, {} end -- ---------------------------------------------------------------- List local function visibleCards() local height = list:GetHeight() or 0 if height < CARD_H then height = PANE_H + LIST_Y - LIST_BOTTOM end return math.max(1, math.floor(height / CARD_H)) end -- atlas: card art; layer: draw layer. Spans the card from x = 42, as the set card's. local function cardArt(card, atlas, layer) local texture = card:CreateTexture(nil, layer) ForeverUI.SetAtlas(texture, atlas, true) texture:SetHeight(CARD_BACKGROUND_H) texture:SetPoint("TOPLEFT", card, "TOPLEFT", CARD_BACKGROUND_X, 0) texture:SetPoint("TOPRIGHT", card, "TOPRIGHT", 0, 0) return texture end local function createCard(rank) local card = CreateFrame("Button", "ForeverUIMountsCard" .. rank, list) card:SetHeight(CARD_H) -- Selected (ARTWORK) draws above hover (BORDER), as on the set cards card.background = cardArt(card, ATLAS_BACKGROUND, "BACKGROUND") card.hover = cardArt(card, ATLAS_HOVER, "BORDER") card.hover:Hide() card.selected = cardArt(card, ATLAS_SELECTED, "ARTWORK") card.selected:Hide() local icon = card:CreateTexture(nil, "ARTWORK") icon:SetWidth(CARD_ICON) icon:SetHeight(CARD_ICON) icon:SetPoint("LEFT", card, "LEFT", CARD_ICON_X, 0) card.icon = icon local circle = card:CreateTexture(nil, "OVERLAY") ForeverUI.SetAtlas(circle, ATLAS_CIRCLE) circle:SetPoint("CENTER", icon, "CENTER", 0, 0) -- The ridden mount carries the check, as the worn set does local check = card:CreateTexture(nil, "OVERLAY") ForeverUI.SetAtlas(check, ATLAS_CHECKMARK) check:SetPoint("RIGHT", card, "RIGHT", CHECKMARK_X, 0) check:Hide() card.check = check local name = card:CreateFontString(nil, "ARTWORK") name:SetFontObject(GameFontNormalLeft or GameFontNormal) name:SetHeight(CARD_TEXT_H) name:SetJustifyH("LEFT") name:SetPoint("LEFT", card, "LEFT", CARD_TEXT_X, 0) name:SetPoint("RIGHT", card, "RIGHT", -TEXT_RIGHT, 0) card.name = name card:SetScript("OnEnter", function(self) self.hover:Show() end) card:SetScript("OnLeave", function(self) self.hover:Hide() end) -- Left click chooses the mount; right click mounts it, or dismounts from the ridden one, as -- the 3.3.5 companion buttons do (CompanionButton_OnClick) card:RegisterForClicks("LeftButtonUp", "RightButtonUp") card:SetScript("OnClick", function(self, button) if not self.creatureID then return end if button == "RightButton" then if self.active then DismissCompanion("MOUNT") else CallCompanion("MOUNT", self.index) end else selected = self.creatureID layout() end end) -- The whole card drags the mount, name as well as icon, onto an action bar card:RegisterForDrag("LeftButton") card:SetScript("OnDragStart", function(self) if self.creatureID then PickupCompanion("MOUNT", self.index) end end) cards[rank] = card return card end -- Fills the cards from the scroll offset, then the bar and the preview layout = function() if not list then return end local total = count() local visibleCount = visibleCards() offset = math.max(0, math.min(offset, total - visibleCount)) local current = selectedIndex() for rank = 1, visibleCount do local card = cards[rank] or createCard(rank) local index = offset + rank local creatureID, name, _, icon, active if index <= total then creatureID, name, _, icon, active = GetCompanionInfo("MOUNT", index) end if creatureID then card:ClearAllPoints() card:SetPoint("TOPLEFT", list, "TOPLEFT", 0, -(rank - 1) * CARD_H) card:SetPoint("TOPRIGHT", list, "TOPRIGHT", 0, -(rank - 1) * CARD_H) card.creatureID, card.index, card.active = creatureID, index, active card.icon:SetTexture(icon) card.name:SetText(name) if index == current then card.selected:Show() else card.selected:Hide() end if active then card.check:Show() else card.check:Hide() end card:Show() else card.creatureID = nil card:Hide() end end for rank = visibleCount + 1, #cards do cards[rank]:Hide() end bar:Configure(total, visibleCount, offset) updatePreview() end -- Right pane content; host: the right pane frame. Returns its root (see Panes.Register). local function buildRight(host) if panel then layout() return panel, {} end panel = CreateFrame("Frame", "ForeverUIMountsListPane", host) panel:SetAllPoints(host) list = CreateFrame("Frame", "ForeverUIMountsList", panel) list:SetPoint("TOPLEFT", panel, "TOPLEFT", LIST_X, LIST_Y) list:SetPoint("BOTTOMRIGHT", panel, "BOTTOMRIGHT", LIST_RIGHT, LIST_BOTTOM) -- The cards follow the list's width: with the bar shown they give it their room bar = ForeverUI.CreateScrollBar("ForeverUIMountsScrollBar", panel, list) bar.onScroll = function(new) offset = new layout() end bar.onVisibility = function(hasBar) list:SetPoint("BOTTOMRIGHT", panel, "BOTTOMRIGHT", hasBar and LIST_RIGHT_BAR or LIST_RIGHT, LIST_BOTTOM) end list:EnableMouseWheel(true) list:SetScript("OnMouseWheel", function(_, direction) bar:MoveTo(offset - direction) end) panel:SetScript("OnShow", layout) layout() return panel, {} end ForeverUI.MountsTab = { Build = build, BuildRight = buildRight } -- Learned, forgotten, mounted or dismounted local listener = CreateFrame("Frame") for _, event in ipairs({ "COMPANION_LEARNED", "COMPANION_UNLEARNED", "COMPANION_UPDATE" }) do listener:RegisterEvent(event) end listener:SetScript("OnEvent", function() if panel and panel:IsVisible() then layout() end end)