local _, addon = ... local API = addon.API; local UIFrameFade = API.UIFrameFade; local ACTION_BUTTON_SIZE = 46; local ACTION_BUTTON_GAP = 4; local UnitCastingInfo = UnitCastingInfo; local UnitChannelInfo = UnitChannelInfo; local InCombatLockdown = InCombatLockdown; local GetCursorPosition = GetCursorPosition; local math = math; local UIParent = UIParent; local CreateFrame = CreateFrame; local tinsert = table.insert; local QuickSlot = CreateFrame("Frame", nil, UIParent); addon.QuickSlot = QuickSlot; QuickSlot:Hide(); QuickSlot:SetSize(8, 8); QuickSlot:SetAlpha(0); QuickSlot:SetFrameStrata("MEDIUM"); QuickSlot.Buttons = {}; QuickSlot.numActiveButtons = 0; QuickSlot.SpellXButton = {}; local ContextMenu; local function ContextMenu_EditMode_OnClick(self, button) QuickSlot:EnableEditMode(true); return true end local ContextMenuData = { { text = _G["HUD_EDIT_MODE_MENU"] or "Edit Mode", onClickFunc = ContextMenu_EditMode_OnClick}, }; local Positioner = CreateFrame("Frame", nil, UIParent); Positioner.alpha = 0; Positioner:Hide(); Positioner:SetFrameStrata("BACKGROUND"); Positioner.buttonSize = 46; --Constant Positioner.buttonGap = 8; --Constant Positioner.fromRadian = 0; --User customizable function Positioner:GetButtonGap() --the gap between to round buttons return 8 end function Positioner:GetRadius() return math.floor( (0.5 * UIParent:GetHeight()*16/9 /3) + (self.buttonSize*0.5) + 0.5 ); end function Positioner:GetButtonCenterGap() local radius = self:GetRadius(); local gapArc = self.buttonGap + self.buttonSize; local radianGap = gapArc/radius; return radianGap end function Positioner:GetFromRadian() return self.fromRadian end function Positioner:SetFromRadian(radian) local snappedRadian = math.rad(45); if radian > snappedRadian then radian = snappedRadian; else snappedRadian = math.rad(-60) + self:GetButtonRadianByIndex(-1); if radian < snappedRadian then radian = snappedRadian; end end for i = 0, 1 do snappedRadian = self:GetButtonRadianByIndex(i); if radian < snappedRadian + 0.043 and radian > snappedRadian - 0.043 then radian = snappedRadian; end end self.fromRadian = radian; if PlumberDB then PlumberDB.quickslotFromRadian = radian; end end function Positioner:GetEditButtonRadian() local radius = self:GetRadius(); return self.fromRadian + (self.buttonSize)/radius; end function Positioner:GetButtonRadianByIndex(index) local radius = self:GetRadius(); local gapArc = self.buttonGap + self.buttonSize; local radianGap = gapArc/radius; return (1 - index)*radianGap; end function Positioner:GetRadianPerButton() local radius = self:GetRadius(); local radianPerButton = self.buttonSize/radius; return radianPerButton end function Positioner:GetCastBar() return _G["PlayerCastingBarFrame"] end function Positioner:OnUpdate_FadeIn(elapsed) self.alpha = self.alpha + elapsed*5; if self.alpha >= 1 then self.alpha = 1; self:SetScript("OnUpdate", nil); end self:SetAlpha(self.alpha); end function Positioner:FadeInGuideLine() self:SetScript("OnUpdate", self.OnUpdate_FadeIn); self.t = nil; self:Show(); end function Positioner:OnUpdate_FadeOut(elapsed) if self.t < 0.5 then self.t = self.t + elapsed; return end self.alpha = self.alpha - elapsed*2; if self.alpha <= 0 then self.alpha = 0; self.t = nil; self:Hide(); self:SetScript("OnUpdate", nil); end self:SetAlpha(self.alpha); end function Positioner:FadeOutGuideLine() if not self.t then if self.alpha >= 0.8 then self.t = 0; else self.t = 1; --no delay end end self:SetScript("OnUpdate", self.OnUpdate_FadeOut); end function Positioner:ShowGuideLineCircle(state) self.showingGuideLine = state; if state then if not self.GuideLineCircle then self.GuideLineCircle = addon.CreateArc(self); self.GuideLineCircle:SetThickness(2); self.GuideLineCircle:SetPoint("CENTER", UIParent, "CENTER", 0, 0); local buttonRadian = self:GetRadianPerButton(); local toRdian = math.rad(-45.5) + buttonRadian*0.5; local fromRadian = math.rad(30.5) - buttonRadian*0.5; self.GuideLineCircle:SetToRadian(toRdian); self.GuideLineCircle:SetFromRadian(fromRadian); self.GuideLineCircle:SetAlpha(0.5); --[[ local snappedRadian = math.rad(45); if radian > snappedRadian then radian = snappedRadian; else snappedRadian = math.rad(-60) + self:GetButtonRadianByIndex(-1); if radian < snappedRadian then radian = snappedRadian; end end --]] end local radius = self:GetRadius(); self.GuideLineCircle:SetRadius(radius); --self:Show(); self:FadeInGuideLine(); else --self:Hide(); self:FadeOutGuideLine(); end end function Positioner:SetCircleMaskPosition(x, y) if self.CircleMask2 then self.CircleMask2:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x, y); end end function Positioner:HideGuideLine() self.showingGuideLine = false; self:Hide(); self:SetScript("OnUpdate", nil); end local function RealActionButton_OnLeave(self) if not InCombatLockdown() then self:SetScript("OnLeave", nil); self:Release(); end if self.owner then self.owner:UnlockHighlight(); self.owner:SetStateNormal(); self.owner.hasActionButton = nil; self.owner = nil; QuickSlot:SetHeaderText(); QuickSlot:StartShowingDefaultHeaderCountdown(true); end end local function RealActionButton_PostClick(self, button) local owner = self.owner; if owner then if button == "LeftButton" and owner:HasCharges() then owner:ShowPostClickEffect(); return end if button == "RightButton" then if not ContextMenu then ContextMenu = addon.GetSharedContextMenu(); end local menu = ContextMenu; if menu:IsShown() then menu:CloseMenu(); return end menu:SetOwner(owner); menu:ClearAllPoints(); menu:SetPoint("LEFT", owner, "RIGHT", 12, 0); menu:SetContent(ContextMenuData); menu:Show(); end end end local function RealActionButton_OnMouseDown(self, button) if self.owner then if self.owner:HasCharges() then self.owner:SetStatePushed(); end end end local function RealActionButton_OnMouseUp(self) if self.owner then self.owner:SetStateNormal(); end end local function ItemButton_OnEnter(self) QuickSlot:SetHeaderText(API.GetColorizedItemName(self.id)); QuickSlot:StartShowingDefaultHeaderCountdown(false); local privateKey = "QuickSlot"; local RealActionButton = addon.AcquireSecureActionButton(privateKey); if RealActionButton then local w, h = self:GetSize(); RealActionButton:SetFrameStrata("DIALOG"); RealActionButton:SetFixedFrameStrata(true); RealActionButton:SetScript("OnEnter", nil); RealActionButton:SetScript("OnLeave", RealActionButton_OnLeave); RealActionButton:SetScript("PostClick", RealActionButton_PostClick); RealActionButton:SetScript("OnMouseDown", RealActionButton_OnMouseDown); RealActionButton:SetScript("OnMouseUp", RealActionButton_OnMouseUp); RealActionButton:ClearAllPoints(); RealActionButton:SetParent(self); RealActionButton:SetSize(w, h); RealActionButton:SetPoint("CENTER", self, "CENTER", 0, 0); RealActionButton:Show(); RealActionButton.owner = self; local macroText = string.format("/use item:%s", self.id); RealActionButton:SetAttribute("type1", "macro"); --Any Mouseclick RealActionButton:SetMacroText(macroText); RealActionButton:RegisterForClicks("LeftButtonDown", "LeftButtonUp", "RightButtonUp"); self:LockHighlight(); self.hasActionButton = true; end end local function ItemButton_OnLeave(self) if not (self:IsVisible() and self:IsMouseOver()) then QuickSlot:SetHeaderText(); QuickSlot:StartShowingDefaultHeaderCountdown(true); end end function QuickSlot:Init() if PlumberDB and PlumberDB.quickslotFromRadian then Positioner:SetFromRadian(PlumberDB.quickslotFromRadian); end self.side = 1; local Header = self:CreateFontString(nil, "OVERLAY", "GameTooltipText"); self.Header = Header; Header:SetJustifyH("CENTER"); Header:SetJustifyV("MIDDLE"); Header:SetPoint("BOTTOM", self, "TOP", 0, 8); Header:SetSpacing(2); local font, height = GameTooltipText:GetFont(); Header:SetFont(font, height, ""); --OUTLINE Header:SetShadowColor(0, 0, 0); Header:SetShadowOffset(1, -1); local HeaderShadow = self:CreateTexture(nil, "ARTWORK"); HeaderShadow:SetPoint("TOPLEFT", Header, "TOPLEFT", -8, 6); HeaderShadow:SetPoint("BOTTOMRIGHT", Header, "BOTTOMRIGHT", 8, -8); HeaderShadow:SetTexture("Interface/AddOns/Plumber/Art/Button/GenericTextDropShadow"); HeaderShadow:Hide(); HeaderShadow:SetAlpha(0); function QuickSlot:SetHeaderText(text, transparentText) if self:IsInEditMode() then return end; if text then Header:SetSize(0, 0); Header:SetText(text); if transparentText then local toAlpha = 0.6; UIFrameFade(Header, 0.5, toAlpha); UIFrameFade(HeaderShadow, 0.25, 0); else API.UIFrameFadeIn(Header, 0.25); UIFrameFade(HeaderShadow, 0.25, 1); end local textWidth = Header:GetWrappedWidth() - 2; if textWidth > QuickSlot.headerMaxWidth then Header:SetSize(QuickSlot.headerMaxWidth, 64); local numLines = Header:GetNumLines(); Header:SetHeight(numLines*18); textWidth = Header:GetWrappedWidth(); Header:SetWidth(textWidth + 2); end else UIFrameFade(Header, 0.5, 0); UIFrameFade(HeaderShadow, 0.25, 0); end end self.SpellCastOverlay = addon.CreateActionButtonSpellCastOverlay(self); self.SpellCastOverlay:Hide(); self.Init = nil; end local function ContainerFrame_OnUpdate(self, elapsed) self.t = self.t + elapsed; if self.t > 1 then self:SetScript("OnUpdate", nil); self:SetHeaderText(self.defaultHeaderText, true); end end function QuickSlot:SetDefaultHeaderText(text) self.defaultHeaderText = text; end function QuickSlot:StartShowingDefaultHeaderCountdown(state) if state and not self:IsInEditMode() then self.t = 0; self:SetScript("OnUpdate", ContainerFrame_OnUpdate); else self:SetScript("OnUpdate", nil); end end function QuickSlot:SetButtonData(itemData, spellData, systemName, isCasting) if itemData == self.itemData then return end self.itemData = itemData; self.spellData = spellData; self.systemName = systemName; self.layoutDirty = true; self.numActiveButtons = #itemData; self.spellcastType = (isCasting and 1) or 2; local buttonSize = ACTION_BUTTON_SIZE; local gap = ACTION_BUTTON_GAP; local positionIndex = 0; local trackIndex = 0; for i, itemID in ipairs(itemData) do positionIndex = positionIndex + 1; if itemID == 0 then --Used as a spacer elseif itemID == -1 then --reset radian, reduce radius positionIndex = 0; trackIndex = trackIndex + 1; else local button = self.Buttons[i]; if not button then button = addon.CreatePeudoActionButton(self); tinsert(self.Buttons, button); button:SetPoint("LEFT", self, "LEFT", (i - 1) * (buttonSize + gap), 0); end local spellID = spellData and spellData[i] or nil; if spellID then self.SpellXButton[spellID] = button; end button:SetItem(itemID); button.spellID = spellID; button.positionIndex = positionIndex; button.trackIndex = trackIndex; button:SetScript("OnEnter", ItemButton_OnEnter); button:SetScript("OnLeave", ItemButton_OnLeave); button:Show(); end end for i = self.numActiveButtons + 1, #self.Buttons do self.Buttons[i]:Hide(); end end function QuickSlot:SetButtonOrder(side) if side ~= self.side then self.side = side; else return end if not self.itemData then return end local items = self.itemData; local spells = self.spellData; if side > 0 then --right side of the screen else --left side items = API.ReverseList(items); spells = API.ReverseList(spells); end for i, button in ipairs(self.Buttons) do button:SetItem(items[i]); button.spellID = spells[i]; self.SpellXButton[ spells[i] ] = button; end end function QuickSlot:SetFrameLayout(layoutIndex) local buttonSize = Positioner.buttonSize; local buttonGap = Positioner.buttonGap; if layoutIndex == 1 then --Normal, below the center --CastingBar's position is changed conditionally local anchorTo = Positioner:GetCastBar(); local y = anchorTo:GetTop(); local scale = anchorTo:GetScale(); self:ClearAllPoints(); self:SetPoint("BOTTOM", UIParent, "BOTTOM", 0, 250); --(y + 30)*scale --Default CastingBar moves up 29y when start casting for i, button in ipairs(self.Buttons) do button:ClearAllPoints(); button:SetPoint("LEFT", self, "LEFT", (i - 1) * (buttonSize + buttonGap), 0); end self.Header:ClearAllPoints(); self.Header:SetPoint("BOTTOM", self, "TOP", 0, 8); self.headerMaxWidth = 0; else --Circular, on the right side local radius = math.floor( (0.5 * UIParent:GetHeight()*16/9 /3) + (buttonSize*0.5) + 0.5); local track0Radius = radius; local gapArc = buttonGap + buttonSize; local fromRadian = Positioner:GetFromRadian(); local radianGap = gapArc/radius; local radian; local x, y; local cx, cy = UIParent:GetCenter(); local cos = math.cos; local sin = math.sin; local trackIndex = 0; for i, button in ipairs(self.Buttons) do button:ClearAllPoints(); if trackIndex ~= button.trackIndex then trackIndex = button.trackIndex; radius = track0Radius - trackIndex * gapArc; radianGap = gapArc/radius; end radian = fromRadian + (1 - button.positionIndex or i)*radianGap; x = cx + radius * cos(radian); y = cy + radius * sin(radian); button:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x, y); if i == 2 then Positioner:SetCircleMaskPosition(x, y); end end local headerRadiusOffset = 112; --Positive value moves towards center local headerMaxWidth = 2*(headerRadiusOffset - buttonSize*0.5) - 8; radian = fromRadian - (self.numActiveButtons - 1)*radianGap*0.5; x = cx + (radius - headerRadiusOffset) * cos(radian); y = cy + (radius - headerRadiusOffset) * sin(radian); self.headerMaxWidth = headerMaxWidth; self.Header:ClearAllPoints(); self.Header:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x, y); if self.RepositionButton then --Adjust Radian: radian = Positioner:GetEditButtonRadian(); self.RepositionButton:ClearAllPoints(); self.RepositionButton:SetPoint("CENTER", UIParent, "BOTTOMLEFT", cx + radius * cos(radian), cy + radius * sin(radian)); --self.RepositionButton:SetRotation(radian); --Adjust Radius: --[[ radian = fromRadian; radius = radius + buttonSize; self.RepositionButton:ClearAllPoints(); self.RepositionButton:SetPoint("CENTER", UIParent, "BOTTOMLEFT", cx + radius * cos(radian), cy + radius * sin(radian)); self.RepositionButton:SetRotation(radian); --]] end end end function QuickSlot:SetInteractable(state, dueToCombat) if state then UIFrameFade(self, 0.5, 1); else if dueToCombat then if self:IsShown() and not self:IsInEditMode() then local toAlpha = 0.25; UIFrameFade(self, 0.2, toAlpha); end else end end for i, button in ipairs(self.Buttons) do button:SetEnabled(state); button:EnableMouse(state); button:UnlockHighlight(); end end function QuickSlot:UpdateItemCount() for i, button in ipairs(self.Buttons) do button:UpdateCount(); end end function QuickSlot:OnSpellCastChanged(spellID, isStartCasting) local targetButton = self.SpellXButton[spellID]; if self.lastSpellTargetButton then self.lastSpellTargetButton.Count:Show(); end self.lastSpellTargetButton = targetButton; if targetButton then if isStartCasting then self.isPlayerMoving = false; self.isChanneling = true; for i, button in ipairs(self.Buttons) do if button.spellID == spellID then local _, _, _, startTime, endTime = UnitChannelInfo("player"); if not _ then _, _, _, startTime, endTime = UnitCastingInfo("player"); end self.SpellCastOverlay:ClearAllPoints(); self.SpellCastOverlay:SetPoint("CENTER", button, "CENTER", 0, 0); self.SpellCastOverlay:FadeIn(); self.SpellCastOverlay:SetDuration( (endTime - startTime) / 1000); self.SpellCastOverlay:SetFrameStrata("HIGH"); button.Count:Hide(); end end else self.isChanneling = false; self.lastSpellTargetButton = nil; self.SpellCastOverlay:FadeOut(); end end end function QuickSlot:OnShow() end function QuickSlot:OnHide() self:EnableEditMode(false); end QuickSlot:SetScript("OnHide", QuickSlot.OnHide); local function GetCursorRadianToPoint(cx, cy, uiRatio) local x, y = GetCursorPosition(); x = x *uiRatio; y = y * uiRatio; return math.atan2(y - cy, x - cx); end local function RepositionButton_OnUpdate(self, elapsed) self.t = self.t + elapsed; if self.t >= 0.016 then self.t = 0; local radian = GetCursorRadianToPoint(self.cx, self.cy, self.uiRatio); if radian ~= self.radian then self.radian = radian; Positioner:SetFromRadian(self.frameRadian + radian - self.selfRadian); QuickSlot:SetFrameLayout(2); --[[ if radian > -1.57 and radian < 1.57 then QuickSlot:SetButtonOrder(1); else QuickSlot:SetButtonOrder(-1); end --]] end end end local function RepositionButton_OnMouseDown(self, button) if button == "RightButton" then Positioner:SetFromRadian(0); QuickSlot:SetFrameLayout(2); return end self.t = 0; self.cx, self.cy = UIParent:GetCenter(); self.uiRatio = 1/ UIParent:GetEffectiveScale(); self.radian = GetCursorRadianToPoint(self.cx, self.cy, self.uiRatio); self.selfRadian = Positioner:GetEditButtonRadian(); self.frameRadian = Positioner:GetFromRadian(); self:SetScript("OnUpdate", RepositionButton_OnUpdate); QuickSlot:SetInteractable(false); self:LockHighlight(); Positioner:ShowGuideLineCircle(true); end local function RepositionButton_OnMouseUp(self) self.t = nil; self.cx, self.cy = nil, nil; self:SetScript("OnUpdate", nil); self:UnlockHighlight(); Positioner:ShowGuideLineCircle(false); end local function RepositionButton_OnClick(self) local delta = -1; --clock-wise local oldRadian = Positioner:GetFromRadian(); local dRadian = Positioner:GetButtonCenterGap(); local newRadian = oldRadian + delta*dRadian; Positioner:SetFromRadian(newRadian); QuickSlot:SetFrameLayout(2); end local function RepositionButton_SetRotation(self, radian) self.Icon:SetRotation(radian); self.Highlight:SetRotation(radian); end function QuickSlot:IsInEditMode() return self.isEditing == true end local function SetControlNodeAnimation(obj) local ag = obj:CreateAnimationGroup(); obj.AnimIn = ag; local s1 = ag:CreateAnimation("Scale"); s1:SetOrder(1); s1:SetDuration(0); s1:SetScale(0.25, 0.25); local s2 = ag:CreateAnimation("Scale"); s2:SetOrder(2); s2:SetDuration(0.3); s2:SetScale(6, 6); s2:SetSmoothing("IN_OUT"); local s3 = ag:CreateAnimation("Scale"); s3:SetOrder(3); s3:SetDuration(0.4); s3:SetScale(0.67, 0.67); s3:SetSmoothing("OUT"); end function QuickSlot:EnableEditMode(state) if state then if not self.RepositionButton then local b = CreateFrame("Button", nil, self); b:SetSize(16, 16); self.RepositionButton = b; b:SetFrameStrata("DIALOG"); b:SetFixedFrameStrata(true); local tex = "Interface/AddOns/Plumber/Art/Button/RepositionButton-Circle"; b.Icon = b:CreateTexture(nil, "ARTWORK"); b.Icon:SetSize(16, 16); b.Icon:SetPoint("CENTER", b, "CENTER", 0, 0); b.Icon:SetTexture(tex, nil, nil, "TRILINEAR"); b.Highlight = b:CreateTexture(nil, "HIGHLIGHT"); b.Highlight:SetSize(32, 32); b.Highlight:SetPoint("CENTER", b, "CENTER", 0, 0); b.Highlight:SetTexture(tex.."-Highlight", nil, nil, "TRILINEAR"); b.SetRotation = RepositionButton_SetRotation; --b:SetScript("OnClick", RepositionButton_OnClick); b:SetScript("OnMouseDown", RepositionButton_OnMouseDown); b:SetScript("OnMouseUp", RepositionButton_OnMouseUp); SetControlNodeAnimation(b); end if not self.EditModeConfirmButton then local b = CreateFrame("Button", nil, self); b:SetSize(30, 30); self.EditModeConfirmButton = b; b:SetFrameStrata("DIALOG"); b:SetFixedFrameStrata(true); local tex = "Interface/AddOns/Plumber/Art/Button/EditMode-Confirm"; b.Icon = b:CreateTexture(nil, "ARTWORK"); b.Icon:SetSize(32, 32); b.Icon:SetPoint("CENTER", b, "CENTER", 0, 0); b.Icon:SetTexture(tex); API.DisableSharpening(b.Icon); b.Highlight = b:CreateTexture(nil, "HIGHLIGHT"); b.Highlight:SetSize(32, 32); b.Highlight:SetPoint("CENTER", b, "CENTER", 0, 0); b.Highlight:SetTexture(tex.."-Highlight"); API.DisableSharpening(b.Highlight); b:SetPoint("CENTER", self.Header, "CENTER", 0, 0); b:SetScript("OnClick", function() self:EnableEditMode(false); end); end if not self.isEditing then self.RepositionButton:Show(); self.EditModeConfirmButton:Show(); self.RepositionButton.AnimIn:Play(); UIFrameFade(self.EditModeConfirmButton, 0.25, 1, 0); self:SetInteractable(false); self:SetHeaderText(); --HUD_EDIT_MODE_MENU self:StartShowingDefaultHeaderCountdown(false); for i, button in ipairs(self.Buttons) do button.Count:Hide(); end self.isEditing = true; self:SetFrameLayout(2); end else if self.isEditing then self.isEditing = nil; self.RepositionButton:Hide(); self.RepositionButton:SetScript("OnUpdate", nil); self.EditModeConfirmButton:Hide(); Positioner:HideGuideLine(); for i, button in ipairs(self.Buttons) do if button ~= self.lastSpellTargetButton then button.Count:Show(); end end if not InCombatLockdown() then self:SetInteractable(true); end if self.closeUIAfterEditing then self.closeUIAfterEditing = nil; self:CloseUI(); end else return end end end function QuickSlot:ShowUI() if self.Init then self:Init(); end if self.layoutDirty then self.layoutDirty = nil; self:SetFrameLayout(2); end self:RegisterEvent("BAG_UPDATE"); self:RegisterEvent("PLAYER_REGEN_DISABLED"); self:RegisterEvent("PLAYER_REGEN_ENABLED"); self:RegisterEvent("UI_SCALE_CHANGED"); if self.spellcastType == 1 then self:RegisterUnitEvent("UNIT_SPELLCAST_START", "player"); self:RegisterUnitEvent("UNIT_SPELLCAST_STOP", "player"); else self:RegisterUnitEvent("UNIT_SPELLCAST_CHANNEL_START", "player"); self:RegisterUnitEvent("UNIT_SPELLCAST_CHANNEL_STOP", "player"); self:RegisterUnitEvent("UNIT_SPELLCAST_CHANNEL_UPDATE", "player"); end self:UpdateItemCount(); for _, button in ipairs(self.Buttons) do button.Count:Show(); end self.closeUIAfterEditing = nil; self.isChanneling = nil; self.lastSpellTargetButton = nil; self:Show(); if InCombatLockdown() then self:SetInteractable(false, true); else self:SetInteractable(true); end return true end function QuickSlot:CloseUI() if self:IsShown() then self:EnableEditMode(false); UIFrameFade(self, 0.5, 0); self:UnregisterEvent("BAG_UPDATE"); self:UnregisterEvent("PLAYER_REGEN_DISABLED"); self:UnregisterEvent("PLAYER_REGEN_ENABLED"); self:UnregisterEvent("UI_SCALE_CHANGED"); self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_START"); self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_STOP"); self:UnregisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE"); self:UnregisterEvent("UNIT_SPELLCAST_START"); self:UnregisterEvent("UNIT_SPELLCAST_STOP"); self:SetInteractable(false); self.isChanneling = nil; self.defaultHeaderText = nil; self.SpellCastOverlay:Hide(); end end function QuickSlot:RequestCloseUI(systemName) if self:IsInEditMode() then self.closeUIAfterEditing = true; else if (not systemName) or (systemName and systemName == self.systemName) then self:CloseUI(); end end end function QuickSlot:OnEvent(event, ...) if event == "BAG_UPDATE" then self:UpdateItemCount(); elseif event == "PLAYER_REGEN_DISABLED" then self:SetInteractable(false, true); elseif event == "PLAYER_REGEN_ENABLED" then if not self.isEditing then self:SetInteractable(true); end elseif event == "UI_SCALE_CHANGED" then self:SetFrameLayout(2); elseif event == "UNIT_SPELLCAST_CHANNEL_START" or event == "UNIT_SPELLCAST_START" then local _, _, spellID = ... QuickSlot:OnSpellCastChanged(spellID, true); elseif event == "UNIT_SPELLCAST_CHANNEL_UPDATE" then elseif event == "UNIT_SPELLCAST_CHANNEL_STOP" or event == "UNIT_SPELLCAST_STOP" then local _, _, spellID = ... self:OnSpellCastChanged(spellID, false); end end QuickSlot:SetScript("OnEvent", QuickSlot.OnEvent);