local Azurah = _G['Azurah'] -- grab addon table from global local Watcher = _G['Azurah_BagWatcher'] -- grab bag watcher control local WatcherScene = ZO_HUDFadeSceneFragment:New(Watcher, 0, 0) local LMP = LibStub('LibMediaProvider-1.0') -- UPVALUES -- local BAG_BACKPACK = BAG_BACKPACK local SmoothTransition = ZO_StatusBar_SmoothTransition local GetNumBagUsedSlots = GetNumBagUsedSlots local GetBagSize = GetBagSize local VISIBLE_TIME_HOLD = 2500 local VISIBLE_TIME_FADE_OUT = 400 local firstLoad = true local bagMax = 0 local bagCurrent, bagNew = 0, 0 local FormatOverlay local db local function ShowWatcher() Watcher:SetAlpha(1) -- make sure watcher is fully visible if (db.lowSpaceLock and (bagMax - bagCurrent) <= db.lowSpaceTrigger) then -- low space triggered, we should stay visible if (Watcher.fader:IsPlaying()) then Watcher.fader:Stop() -- stop fader anim if playing end else -- not in low space or not locking on low space, start (or restart) fader Watcher.fader:PlayFromStart() end end -- ------------------------ -- EVENT HANDLERS -- ------------------------ local function OnBagSizeChanged(code, prevSize, currentSize) if (prevSize == currentSize) then return end -- just make sure they aren't the same bagMax = currentSize -- set new backpack size bagCurrent = GetNumBagUsedSlots(BAG_BACKPACK) Watcher.bar:SetMinMax(0, bagMax) Watcher.bar.gloss:SetMinMax(0, bagMax) ShowWatcher() SmoothTransition(Watcher.bar, bagCurrent, bagMax, false, false, 0.05) Watcher.overlay:SetText(FormatOverlay(bagCurrent, nil, bagMax)) end local function OnBagUpdate(code, bagID) if (bagID ~= BAG_BACKPACK) then return end -- we only care about the backpack bagNew = GetNumBagUsedSlots(BAG_BACKPACK) if (bagNew == bagCurrent) then return end -- available slots didn't actually change bagCurrent = bagNew -- available slots have changed, proceed ShowWatcher() SmoothTransition(Watcher.bar, bagCurrent, bagMax, false, false, 0.05) Watcher.overlay:SetText(FormatOverlay(bagCurrent, nil, bagMax)) end local function SceneOnShown() if (Watcher.fader:IsPlaying()) then Watcher.fader:Stop() -- stop fader anim if playing end if (db.lowSpaceLock and (bagMax - bagCurrent) <= db.lowSpaceTrigger) then -- low space triggered, we should stay visible Watcher:SetAlpha(1) -- make sure we're fully visible else -- shouldnt' be visible right now Watcher:SetAlpha(0) end end -- ------------------------ -- CONSTRUCTION -- ------------------------ local function AddControl(parent, cType, level) local c = WINDOW_MANAGER:CreateControl(nil, parent, cType) c:SetDrawLayer(DL_CONTROLS) c:SetDrawLevel(level) return c, c end local function BuildWatcher() local ctrl -- ICON Watcher.icon, ctrl = AddControl(Watcher, CT_TEXTURE, 3) ctrl:SetDimensions(56, 56) ctrl:SetTexture([[/esoui/art/mainmenu/menuBar_inventory_up.dds]]) ctrl:SetTextureCoords(0.0625, 0.9375, 0.0625, 0.9375) -- BAR Watcher.bar, ctrl = AddControl(Watcher, CT_STATUSBAR, 2) ZO_StatusBar_SetGradientColor(ctrl, ZO_XP_BAR_GRADIENT_COLORS) ctrl:EnableLeadingEdge(true) ctrl:SetHandler('OnValueChanged', function(bar, value) bar.gloss:SetValue(value) end) -- change gloss value as main bar changes -- BAR GLOSS Watcher.bar.gloss, ctrl = AddControl(Watcher.bar, CT_STATUSBAR, 3) ctrl:SetAnchor(TOPLEFT) ctrl:EnableLeadingEdge(true) -- BAR FRAME Watcher.bar.borderL, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 4) Watcher.bar.borderR, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 4) Watcher.bar.borderM, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 4) -- BAR BACKDROP Watcher.bar.backdropEnd, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 1) Watcher.bar.backdrop, ctrl = AddControl(Watcher.bar, CT_TEXTURE, 1) -- OVERLAY Watcher.overlay = Azurah:CreateOverlay(Watcher, CENTER, CENTER, 0, 0, nil, nil, nil, TEXT_ALIGN_LEFT) -- will be reanchored later by configure -- ANIMATION TIMELINE ctrl = ANIMATION_MANAGER:CreateTimeline() ctrl:SetPlaybackType(ANIMATION_PLAYBACK_ONE_SHOT) Watcher.fader = ctrl ctrl = Watcher.fader:InsertAnimation(ANIMATION_ALPHA, Watcher, VISIBLE_TIME_HOLD) ctrl:SetDuration(VISIBLE_TIME_FADE_OUT) ctrl:SetEasingFunction(ZO_LinearEase) ctrl:SetAlphaValues(1, 0) HUD_SCENE:AddFragment(WatcherScene) HUD_UI_SCENE:AddFragment(WatcherScene) LOOT_SCENE:AddFragment(WatcherScene) WatcherScene:SetConditional(function() return Azurah.db.bagWatcher.enabled end) WatcherScene.OnShown = SceneOnShown end -- ------------------------ -- CONFIGURATION -- ------------------------ function Azurah:ConfigureBagWatcherKeyboard() Watcher:SetDimensions(375, 56) if (not Watcher.bar) then return end -- bar isn't built yet (is disabled), abort Watcher.icon:ClearAnchors() Watcher.overlay:SetHidden(false) Watcher.overlay:ClearAnchors() Watcher.bar:ClearAnchors() Watcher.bar.borderL:ClearAnchors() Watcher.bar.borderR:ClearAnchors() Watcher.bar.borderM:ClearAnchors() Watcher.bar.backdropEnd:ClearAnchors() Watcher.bar.backdrop:ClearAnchors() Watcher.bar:SetDimensions(315, 20) Watcher.bar:SetTexture([[/esoui/art/miscellaneous/progressbar_genericfill.dds]]) Watcher.bar:SetTextureCoords(0, 1, 0, 0.625) Watcher.bar:SetLeadingEdge([[/esoui/art/miscellaneous/progressbar_genericfill_leadingedge.dds]], 10, 20) Watcher.bar:SetLeadingEdgeTextureCoords(0, 1, 0, 0.625) Watcher.bar.gloss:SetDimensions(315, 20) Watcher.bar.gloss:SetTexture([[/esoui/art/miscellaneous/progressbar_genericfill_gloss.dds]]) Watcher.bar.gloss:SetTextureCoords(0, 1, 0, 0.625) Watcher.bar.gloss:SetLeadingEdge([[/esoui/art/miscellaneous/progressbar_genericfill_leadingedge_gloss.dds]], 10, 20) Watcher.bar.gloss:SetLeadingEdgeTextureCoords(0, 1, 0, 0.625) Watcher.bar.borderL:SetDimensions(10, 20) Watcher.bar.borderL:SetAnchor(TOPLEFT) Watcher.bar.borderL:SetTexture([[/esoui/art/miscellaneous/progressbar_frame.dds]]) Watcher.bar.borderR:SetDimensions(10, 20) Watcher.bar.borderR:SetAnchor(TOPRIGHT) Watcher.bar.borderR:SetTexture([[/esoui/art/miscellaneous/progressbar_frame.dds]]) Watcher.bar.borderM:SetDimensions(295, 20) Watcher.bar.borderM:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, 10, 0) Watcher.bar.borderM:SetTexture([[/esoui/art/miscellaneous/progressbar_frame.dds]]) Watcher.bar.borderM:SetTextureCoords(0.019500000402331, 0.58980000019073, 0, 0.625) Watcher.bar.backdropEnd:SetDimensions(10, 20) Watcher.bar.backdropEnd:SetTexture([[/esoui/art/miscellaneous/progressbar_frame_bg.dds]]) Watcher.bar.backdrop:SetDimensions(305, 20) Watcher.bar.backdrop:SetTexture([[/esoui/art/miscellaneous/progressbar_frame_bg.dds]]) Watcher.bar.backdrop:SetTextureCoords(0.019500000402331, 0.58980000019073, 0, 0.625) if (db.reverseAlignment) then Watcher.icon:SetAnchor(TOPRIGHT, Watcher, TOPRIGHT, 10, 7) Watcher.overlay:SetAnchor(BOTTOMRIGHT, Watcher.bar, TOPRIGHT, -4, -2) Watcher.bar:SetAnchor(BOTTOMRIGHT, Watcher.icon, BOTTOMLEFT, 7, -8) Watcher.bar:SetBarAlignment(BAR_ALIGNMENT_REVERSE) Watcher.bar.gloss:SetBarAlignment(BAR_ALIGNMENT_REVERSE) Watcher.bar.borderL:SetTextureCoords(0.6133000254631, 0.59380000829697, 0, 0.625) Watcher.bar.borderR:SetTextureCoords(0.019500000402331, 0, 0, 0.625) Watcher.bar.backdropEnd:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, 0, 0) Watcher.bar.backdropEnd:SetTextureCoords(0.6133000254631, 0.59380000829697, 0, 0.625) Watcher.bar.backdrop:SetAnchor(TOPRIGHT, Watcher.bar, TOPRIGHT, 0, 0) else Watcher.icon:SetAnchor(TOPLEFT, Watcher, TOPLEFT, -10, 7) Watcher.overlay:SetAnchor(BOTTOMLEFT, Watcher.bar, TOPLEFT, 4, -2) Watcher.bar:SetAnchor(BOTTOMLEFT, Watcher.icon, BOTTOMRIGHT, -7, -8) Watcher.bar:SetBarAlignment(BAR_ALIGNMENT_NORMAL) Watcher.bar.gloss:SetBarAlignment(BAR_ALIGNMENT_NORMAL) Watcher.bar.borderL:SetTextureCoords(0, 0.019500000402331, 0, 0.625) Watcher.bar.borderR:SetTextureCoords(0.59380000829697, 0.6133000254631, 0, 0.625) Watcher.bar.backdropEnd:SetAnchor(TOPRIGHT, Watcher.bar, TOPRIGHT, 0, 0) Watcher.bar.backdropEnd:SetTextureCoords(0.59380000829697, 0.6133000254631, 0, 0.625) Watcher.bar.backdrop:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, 0, 0) end end function Azurah:ConfigureBagWatcherGamepad() Watcher:SetDimensions(255, 56) if (not Watcher.bar) then return end -- bar isn't built yet (is disabled), abort Watcher.icon:ClearAnchors() Watcher.overlay:SetHidden(true) -- no overlay in gamepad mode -- Watcher.overlay:ClearAnchors() Watcher.bar:ClearAnchors() Watcher.bar.borderL:ClearAnchors() Watcher.bar.borderR:ClearAnchors() Watcher.bar.borderM:ClearAnchors() Watcher.bar.backdropEnd:ClearAnchors() Watcher.bar.backdrop:ClearAnchors() Watcher.bar:SetDimensions(205, 22) Watcher.bar:SetTexture([[/esoui/art/miscellaneous/gamepad/gp_dynamicbar_medium_fill.dds]]) Watcher.bar:SetTextureCoords(0, 1, 0.15625, 0.84375) Watcher.bar:SetLeadingEdge([[/esoui/art/miscellaneous/gamepad/gp_dynamicbar_medium_leadingedge.dds]], 16, 32) Watcher.bar:SetLeadingEdgeTextureCoords(0, 0.5, 0.15625, 0.84375) Watcher.bar.gloss:SetDimensions(205, 22) Watcher.bar.gloss:SetTexture([[/esoui/art/miscellaneous/gamepad/gp_dynamicbar_medium_gloss.dds]]) Watcher.bar.gloss:SetTextureCoords(0, 1, 0.15625, 0.84375) Watcher.bar.gloss:SetLeadingEdge([[/esoui/art/miscellaneous/gamepad/gp_dynamicbar_medium_leadingedge_gloss.dds]], 16, 32) Watcher.bar.gloss:SetLeadingEdgeTextureCoords(0, 0.5, 0.15625, 0.84375) Watcher.bar.borderL:SetDimensions(7, 22) Watcher.bar.borderL:SetTexture([[/esoui/art/miscellaneous/gamepad/gp_dynamicbar_medium_frame.dds]]) Watcher.bar.borderR:SetDimensions(11, 22) Watcher.bar.borderR:SetTexture([[/esoui/art/miscellaneous/gamepad/gp_dynamicbar_medium_frame.dds]]) Watcher.bar.borderM:SetDimensions(191, 22) Watcher.bar.borderM:SetTexture([[/esoui/art/miscellaneous/gamepad/gp_dynamicbar_medium_frame.dds]]) Watcher.bar.borderM:SetTextureCoords(0.6875, 0.4375, 0.15625, 0.84375) Watcher.bar.backdropEnd:SetDimensions(11, 22) Watcher.bar.backdropEnd:SetTexture([[/esoui/art/miscellaneous/gamepad/gp_dynamicbar_medium_bg.dds]]) Watcher.bar.backdrop:SetDimensions(198, 22) Watcher.bar.backdrop:SetTexture([[/esoui/art/miscellaneous/gamepad/gp_dynamicbar_medium_bg.dds]]) Watcher.bar.backdrop:SetTextureCoords(0.6875, 0.4375, 0.15625, 0.84375) if (db.reverseAlignment) then Watcher.icon:SetAnchor(TOPRIGHT, Watcher, TOPRIGHT, 9, 7) -- Watcher.overlay:SetAnchor(BOTTOMRIGHT, Watcher.bar, TOPRIGHT, -4, 1) Watcher.bar:SetAnchor(BOTTOMRIGHT, Watcher.icon, BOTTOMLEFT, 7, -15) Watcher.bar:SetBarAlignment(BAR_ALIGNMENT_REVERSE) Watcher.bar.gloss:SetBarAlignment(BAR_ALIGNMENT_REVERSE) Watcher.bar.borderL:SetAnchor(TOPRIGHT, Watcher.bar, TOPRIGHT, 2, 0) Watcher.bar.borderL:SetTextureCoords(0.71875, 0.9375, 0.15625, 0.84375) Watcher.bar.borderR:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, -2, 0) Watcher.bar.borderR:SetTextureCoords(0.0625, 0.40625, 0.15625, 0.84375) Watcher.bar.borderM:SetAnchor(TOPRIGHT, Watcher.bar, TOPRIGHT, -5, 0) Watcher.bar.backdropEnd:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, -2, 0) Watcher.bar.backdropEnd:SetTextureCoords(0.0625, 0.40625, 0.15625, 0.84375) Watcher.bar.backdrop:SetAnchor(TOPRIGHT, Watcher.bar, TOPRIGHT, 2, 0) else Watcher.icon:SetAnchor(TOPLEFT, Watcher, TOPLEFT, -9, 0) -- Watcher.overlay:SetAnchor(BOTTOMLEFT, Watcher.bar, TOPLEFT, 4, 1) Watcher.bar:SetAnchor(BOTTOMLEFT, Watcher.icon, BOTTOMRIGHT, -7, -15) Watcher.bar:SetBarAlignment(BAR_ALIGNMENT_NORMAL) Watcher.bar.gloss:SetBarAlignment(BAR_ALIGNMENT_NORMAL) Watcher.bar.borderL:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, -2, 0) Watcher.bar.borderL:SetTextureCoords(0.9375, 0.71875, 0.15625, 0.84375) Watcher.bar.borderR:SetAnchor(TOPRIGHT, Watcher.bar, TOPRIGHT, 2, 0) Watcher.bar.borderR:SetTextureCoords(0.40625, 0.0625, 0.15625, 0.84375) Watcher.bar.borderM:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, 5, 0) Watcher.bar.backdropEnd:SetAnchor(TOPRIGHT, Watcher.bar, TOPRIGHT, 2, 0) Watcher.bar.backdropEnd:SetTextureCoords(0.40625, 0.0625, 0.15625, 0.84375) Watcher.bar.backdrop:SetAnchor(TOPLEFT, Watcher.bar, TOPLEFT, -2, 0) end end function Azurah:ConfigureBagWatcher(onLoad) if (not db.enabled) then -- not using bag watcher -- unregister watcher events EVENT_MANAGER:UnregisterForEvent(self.name .. 'BagWatcher', EVENT_INVENTORY_SINGLE_SLOT_UPDATE) EVENT_MANAGER:UnregisterForEvent(self.name .. 'BagWatcher', EVENT_INVENTORY_BAG_CAPACITY_CHANGED) else -- using bag watcher if (not Watcher.bar) then -- need to build the watcher gui BuildWatcher() end -- configure bag watcher appearance Watcher.overlay:SetFont(string.format('%s|%d|%s', LMP:Fetch('font', db.fontFace), db.fontSize, db.fontOutline)) Watcher.overlay:SetColor(db.fontColour.r, db.fontColour.g, db.fontColour.b, db.fontColour.a) if (IsInGamepadPreferredMode()) then self:ConfigureBagWatcherGamepad() else self:ConfigureBagWatcherKeyboard() end bagMax = GetBagSize(BAG_BACKPACK) bagCurrent = GetNumBagUsedSlots(BAG_BACKPACK) FormatOverlay = self.overlayFuncs[db.overlay] Watcher.bar:SetMinMax(0, bagMax) Watcher.bar.gloss:SetMinMax(0, bagMax) EVENT_MANAGER:RegisterForEvent(self.name .. 'BagWatcher', EVENT_INVENTORY_SINGLE_SLOT_UPDATE, OnBagUpdate) EVENT_MANAGER:RegisterForEvent(self.name .. 'BagWatcher', EVENT_INVENTORY_BAG_CAPACITY_CHANGED, OnBagSizeChanged) if (firstLoad) then -- first load, fillup bar to current level nicely firstLoad = false Watcher.bar:SetValue(0) ShowWatcher() SmoothTransition(Watcher.bar, bagCurrent, bagMax, false, false, 0.05) else Watcher.bar:SetValue(bagCurrent) end Watcher.overlay:SetText(FormatOverlay(bagCurrent, nil, bagMax)) end end -- ------------------------ -- INITIALIZATION -- ------------------------ function Azurah:InitializeBagWatcher() db = self.db.bagWatcher -- local db reference end