local Layout = {mediaPath = {}} local SML, mediaRequired, anchoringQueued local mediaPath = Layout.mediaPath local backdropTbl = {insets = {}} local _G = getfenv(0) ShadowUF.Layout = Layout -- Someone is using another mod that is forcing a media type for all mods using SML function Layout:MediaForced(mediaType) local oldPath = mediaPath[mediaType] self:CheckMedia() if( mediaPath[mediaType] ~= oldPath ) then self:Reload() end end local function loadMedia(type, name, default) if( name == "" ) then return "" end local media = SML:Fetch(type, name, true) if( not media ) then mediaRequired = mediaRequired or {} mediaRequired[type] = name return default end return media end -- Updates the background table local function updateBackdrop() -- Update the backdrop table local backdrop = ShadowUF.db.profile.backdrop backdropTbl.bgFile = mediaPath.background if( mediaPath.border ~= "Interface\\None" ) then backdropTbl.edgeFile = mediaPath.border end backdropTbl.tile = backdrop.tileSize > 0 and true or false backdropTbl.edgeSize = backdrop.edgeSize == 0 and 1 or backdrop.edgeSize backdropTbl.tileSize = backdrop.tileSize backdropTbl.insets.left = backdrop.inset backdropTbl.insets.right = backdrop.inset backdropTbl.insets.top = backdrop.inset backdropTbl.insets.bottom = backdrop.inset end -- Tries to load media, if it fails it will default to whatever I set function Layout:CheckMedia() mediaPath[SML.MediaType.STATUSBAR] = loadMedia(SML.MediaType.STATUSBAR, ShadowUF.db.profile.bars.texture, "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Aluminium") mediaPath[SML.MediaType.FONT] = loadMedia(SML.MediaType.FONT, ShadowUF.db.profile.font.name, "Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf") mediaPath[SML.MediaType.BACKGROUND] = loadMedia(SML.MediaType.BACKGROUND, ShadowUF.db.profile.backdrop.backgroundTexture, "Interface\\ChatFrame\\ChatFrameBackground") mediaPath[SML.MediaType.BORDER] = loadMedia(SML.MediaType.BORDER, ShadowUF.db.profile.backdrop.borderTexture, "") updateBackdrop() end -- We might not have had a media we required at initial load, wait for it to load and then update everything when it does function Layout:MediaRegistered(event, mediaType, key) if( mediaRequired and mediaRequired[mediaType] and mediaRequired[mediaType] == key ) then mediaPath[mediaType] = SML:Fetch(mediaType, key) mediaRequired[mediaType] = nil self:Reload() end end -- Helper functions function Layout:ToggleVisibility(frame, visible) if( frame and visible ) then frame:Show() elseif( frame ) then frame:Hide() end end function Layout:SetBarVisibility(frame, key, status) if( frame.secureLocked ) then return end -- Show the bar if it wasn't already if( status and not frame[key]:IsVisible() ) then ShadowUF.Tags:FastRegister(frame, frame[key]) frame[key].visibilityManaged = true frame[key]:Show() ShadowUF.Layout:PositionWidgets(frame, ShadowUF.db.profile.units[frame.unitType]) -- Hide the bar if it wasn't already elseif( not status and frame[key]:IsVisible() ) then ShadowUF.Tags:FastUnregister(frame, frame[key]) frame[key].visibilityManaged = nil frame[key]:Hide() ShadowUF.Layout:PositionWidgets(frame, ShadowUF.db.profile.units[frame.unitType]) end end -- Frame changed somehow between when we first set it all up and now function Layout:Reload(unit) updateBackdrop() -- Now update them for frame in pairs(ShadowUF.Units.frameList) do if( frame.unit and ( not unit or frame.unitType == unit ) and not frame.isHeaderFrame ) then frame:SetVisibility() self:Load(frame) frame:FullUpdate() end end for header in pairs(ShadowUF.Units.headerFrames) do if( header.unitType and ( not unit or header.unitType == unit ) ) then local config = ShadowUF.db.profile.units[header.unitType] header:SetAttribute("style-height", config.height) header:SetAttribute("style-width", config.width) header:SetAttribute("style-scale", config.scale) end end ShadowUF:FireModuleEvent("OnLayoutReload", unit) end -- Do a full update function Layout:Load(frame) local unitConfig = ShadowUF.db.profile.units[frame.unitType] -- About to set layout ShadowUF:FireModuleEvent("OnPreLayoutApply", frame, unitConfig) -- Figure out if we're secure locking frame.secureLocked = nil for _, module in pairs(ShadowUF.moduleOrder) do if( frame.visibility[module.moduleKey] and ShadowUF.db.profile.units[frame.unitType][module.moduleKey] and ShadowUF.db.profile.units[frame.unitType][module.moduleKey].secure and module:SecureLockable() ) then frame.secureLocked = true break end end -- Load all of the layout things self:SetupFrame(frame, unitConfig) self:SetupBars(frame, unitConfig) self:PositionWidgets(frame, unitConfig) self:SetupText(frame, unitConfig) -- Layouts been fully set ShadowUF:FireModuleEvent("OnLayoutApplied", frame, unitConfig) end -- Register it on file load because authors seem to do a bad job at registering the callbacks SML = LibStub:GetLibrary("LibSharedMedia-3.0") SML:Register(SML.MediaType.FONT, "Myriad Condensed Web", "Interface\\AddOns\\ShadowedUnitFrames\\media\\fonts\\Myriad Condensed Web.ttf") SML:Register(SML.MediaType.BORDER, "Square Clean", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\ABFBorder") SML:Register(SML.MediaType.BACKGROUND, "Chat Frame", "Interface\\ChatFrame\\ChatFrameBackground") SML:Register(SML.MediaType.STATUSBAR, "BantoBar", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\banto") SML:Register(SML.MediaType.STATUSBAR, "Smooth", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smooth") SML:Register(SML.MediaType.STATUSBAR, "Smooth v2","Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Smoothv2") SML:Register(SML.MediaType.STATUSBAR, "Smoother", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\smoother") SML:Register(SML.MediaType.STATUSBAR, "Perl", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\perl") SML:Register(SML.MediaType.STATUSBAR, "Glaze", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\glaze") SML:Register(SML.MediaType.STATUSBAR, "Charcoal", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Charcoal") SML:Register(SML.MediaType.STATUSBAR, "Otravi", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\otravi") SML:Register(SML.MediaType.STATUSBAR, "Striped", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\striped") SML:Register(SML.MediaType.STATUSBAR, "LiteStep", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\LiteStep") SML:Register(SML.MediaType.STATUSBAR, "Aluminium", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Aluminium") SML:Register(SML.MediaType.STATUSBAR, "Minimalist", "Interface\\AddOns\\ShadowedUnitFrames\\media\\textures\\Minimalist") function Layout:LoadSML() SML.RegisterCallback(self, "LibSharedMedia_Registered", "MediaRegistered") SML.RegisterCallback(self, "LibSharedMedia_SetGlobal", "MediaForced") self:CheckMedia() end --[[ Keep in mind this is relative to where you're parenting it, RT will put the object outside of the frame, on the right side, at the top of it while ITR will put it inside the frame, at the top to the right * Positions OUTSIDE the frame RT = Right Top, RC = Right Center, RB = Right Bottom LT = Left Top, LC = Left Center, LB = Left Bottom, BL = Bottom Left, BC = Bottom Center, BR = Bottom Right TR = Top Right, TC = Top Center, TL = Top Left * Positions INSIDE the frame CLI = Inside Center Left, CRI = Inside Center Right TRI = Inside Top Right, TLI = Inside Top Left BRI = Inside Bottom Right, BRI = Inside Bottom left ]] local preDefPoint = {C = "CENTER", CLI = "LEFT", RT = "TOPLEFT", BC = "TOP", CRI = "RIGHT", LT = "TOPRIGHT", TR = "BOTTOMRIGHT", BL = "TOPLEFT", LB = "BOTTOMRIGHT", LC = "RIGHT", RB = "BOTTOMLEFT", RC = "LEFT", TC = "BOTTOM", BR = "TOPRIGHT", TL = "BOTTOMLEFT", BRI = "BOTTOMRIGHT", BLI = "BOTTOMLEFT", TRI = "TOPRIGHT", TLI = "TOPLEFT"} local preDefRelative = {C = "CENTER", CLI = "LEFT", RT = "TOPRIGHT", BC = "BOTTOM", CRI = "RIGHT", LT = "TOPLEFT", TR = "TOPRIGHT", BL = "BOTTOMLEFT", LB = "BOTTOMLEFT", LC = "LEFT", RB = "BOTTOMRIGHT", RC = "RIGHT", TC = "TOP", BR = "BOTTOMRIGHT", TL = "TOPLEFT", BRI = "BOTTOMRIGHT", BLI = "BOTTOMLEFT", TRI = "TOPRIGHT", TLI = "TOPLEFT"} local columnDirection = {RT = "RIGHT", C = "RIGHT", BC = "BOTTOM", LT = "LEFT", TR = "TOP", BL = "BOTTOM", LB = "LEFT", LC = "LEFT", TRI = "TOP", RB = "RIGHT", RC = "RIGHT", TC = "TOP", CLI = "RIGHT", TL = "TOP", BR = "BOTTOM", IBL = "RIGHT", IBR = "RIGHT", CRI = "RIGHT", TLI = "TOP"} local auraDirection = {RT = "BOTTOM", C = "LEFT", BC = "LEFT", LT = "BOTTOM", TR = "LEFT", BL = "RIGHT", LB = "TOP", LC = "LEFT", TRI = "LEFT", RB = "TOP", RC = "LEFT", TC = "LEFT", CLI = "RIGHT", TL = "RIGHT", BR = "LEFT", IBL = "TOP", IBR = "TOP", CRI = "LEFT", TLI = "RIGHT"} -- Figures out how text should be justified based on where it's anchoring function Layout:GetJustify(config) local point = config.anchorPoint and config.anchorPoint ~= "" and preDefPoint[config.anchorPoint] or config.point if( point and point ~= "" ) then if( string.match(point, "LEFT$") ) then return "LEFT" elseif( string.match(point, "RIGHT$") ) then return "RIGHT" end end return "CENTER" end function Layout:GetPoint(key) return preDefPoint[key] or "CENTER" end function Layout:GetRelative(key) return preDefRelative[key] or "CENTER" end function Layout:GetColumnGrowth(key) return columnDirection[key] or "DOWN" end function Layout:GetAuraGrowth(key) return auraDirection[key] or "LEFT" end function Layout:ReverseDirection(key) return key == "LEFT" and "RIGHT" or key == "RIGHT" and "LEFT" or key == "TOP" and "BOTTOM" or key == "BOTTOM" and "TOP" end -- Gets the relative anchoring for Blizzards default raid frames, these differ from the split ones function Layout:GetRelativeAnchor(point) if( point == "TOP" ) then return "BOTTOM", 0, -1 elseif( point == "BOTTOM" ) then return "TOP", 0, 1 elseif( point == "LEFT" ) then return "RIGHT", 1, 0 elseif( point == "RIGHT" ) then return "LEFT", -1, 0 elseif( point == "TOPLEFT" ) then return "BOTTOMRIGHT", 1, -1 elseif( point == "TOPRIGHT" ) then return "BOTTOMLEFT", -1, -1 elseif( point == "BOTTOMLEFT" ) then return "TOPRIGHT", 1, 1 elseif( point == "BOTTOMRIGHT" ) then return "TOPLEFT", -1, 1 else return "CENTER", 0, 0 end end function Layout:GetSplitRelativeAnchor(point, columnPoint) -- Column is growing to the RIGHT if( columnPoint == "LEFT" ) then return "TOPLEFT", "TOPRIGHT", 1, 0 -- Column is growing to the LEFT elseif( columnPoint == "RIGHT" ) then return "TOPRIGHT", "TOPLEFT", -1, 0 -- Column is growing DOWN elseif( columnPoint == "TOP" ) then return "TOP" .. point, "BOTTOM" .. point, 0, -1 -- Column is growing UP elseif( columnPoint == "BOTTOM" ) then return "BOTTOM" .. point, "TOP" .. point, 0, 1 end end function Layout:AnchorFrame(parent, frame, config) if( not config or not config.anchorTo or not config.x or not config.y ) then return end local anchorTo = config.anchorTo local prefix = string.sub(config.anchorTo, 0, 1) if( config.anchorTo == "$parent" ) then anchorTo = parent -- $ is used as an indicator of a sub-frame inside a parent, $healthBar -> parent.healthBar and so on elseif( prefix == "$" ) then anchorTo = parent[string.sub(config.anchorTo, 2)] -- # is used as an indicator of an actual frame created by SUF, it lets us know that the frame might not be created yet -- and if so, to watch for it to be created and fix the anchoring elseif( prefix == "#" ) then anchorTo = string.sub(config.anchorTo, 2) -- The frame we wanted to anchor to doesn't exist yet, so will queue and wait for it to exist if( not _G[anchorTo] ) then frame.queuedParent = parent frame.queuedConfig = config frame.queuedName = anchorTo anchoringQueued = anchoringQueued or {} anchoringQueued[frame] = true -- For the time being, will take over the frame we wanted to anchor to's position. local unit = string.match(anchorTo, "SUFUnit(%w+)") or string.match(anchorTo, "SUFHeader(%w+)") if( unit and ShadowUF.db.profile.positions[unit] ) then self:AnchorFrame(parent, frame, ShadowUF.db.profile.positions[unit]) end return end end if( config.block ) then anchorTo = anchorTo.blocks[frame.blockID] end -- Figure out where it's anchored local point = config.point and config.point ~= "" and config.point or preDefPoint[config.anchorPoint] or "CENTER" local relativePoint = config.relativePoint and config.relativePoint ~= "" and config.relativePoint or preDefRelative[config.anchorPoint] or "CENTER" -- Effective scaling is only used for unit based frames and if they are anchored to UIParent local scale = 1 if( config.anchorTo == "UIParent" and frame.unitType ) then scale = frame:GetScale() * UIParent:GetScale() end frame:ClearAllPoints() frame:SetPoint(point, anchorTo, relativePoint, config.x / scale, config.y / scale) end -- Setup the main frame function Layout:SetupFrame(frame, config) local backdrop = ShadowUF.db.profile.backdrop frame.backdropInfo = backdropTbl frame:ApplyBackdrop() frame:SetBackdropColor(backdrop.backgroundColor.r, backdrop.backgroundColor.g, backdrop.backgroundColor.b, backdrop.backgroundColor.a) frame:SetBackdropBorderColor(backdrop.borderColor.r, backdrop.borderColor.g, backdrop.borderColor.b, backdrop.borderColor.a) -- Prevent these from updating while in combat to prevent tainting if( not InCombatLockdown() ) then frame:SetHeight(config.height) frame:SetWidth(config.width) frame:SetScale(config.scale) -- Let the frame clip closer to the edge, not using inset + clip as that lets you move it too far in local clamp = backdrop.inset + 0.20 frame:SetClampRectInsets(clamp, -clamp, -clamp, clamp) frame:SetClampedToScreen(true) -- This is wrong technically, I need to redo the backdrop stuff so it will accept insets and that will fit hitbox issues -- for the time being, this is a temporary fix to it local hit = backdrop.borderTexture == "None" and backdrop.inset or 0 frame:SetHitRectInsets(hit, hit, hit, hit) if( not frame.ignoreAnchor ) then self:AnchorFrame(frame.parent or UIParent, frame, ShadowUF.db.profile.positions[frame.unitType]) end end -- Check if we had anything parented to us if( anchoringQueued ) then for queued in pairs(anchoringQueued) do if( queued.queuedName == frame:GetName() ) then self:AnchorFrame(queued.queuedParent, queued, queued.queuedConfig) queued.queuedParent = nil queued.queuedConfig = nil queued.queuedName = nil anchoringQueued[queued] = nil end end end end -- Setup bars function Layout:SetupBars(frame, config) for _, module in pairs(ShadowUF.modules) do local key = module.moduleKey local widget = frame[key] if( widget and ( module.moduleHasBar or config[key] and config[key].isBar ) ) then if( frame.visibility[key] and not frame[key].visibilityManaged and module.defaultVisibility == false ) then self:ToggleVisibility(widget, false) else self:ToggleVisibility(widget, frame.visibility[key]) end if( ( widget:IsShown() or ( not frame[key].visibilityManaged and module.defaultVisibility == false ) ) and widget.SetStatusBarTexture ) then widget:SetStatusBarTexture(mediaPath.statusbar) widget:GetStatusBarTexture():SetHorizTile(false) widget:SetOrientation(config[key].vertical and "VERTICAL" or "HORIZONTAL") widget:SetReverseFill(config[key].reverse and true or false) end if( widget.background ) then if( config[key].background or config[key].invert ) then widget.background:SetTexture(mediaPath.statusbar) widget.background:SetHorizTile(false) widget.background:Show() widget.background.overrideColor = ShadowUF.db.profile.bars.backgroundColor or config[key].backgroundColor if( widget.background.overrideColor ) then widget.background:SetVertexColor(widget.background.overrideColor.r, widget.background.overrideColor.g, widget.background.overrideColor.b, ShadowUF.db.profile.bars.backgroundAlpha) end else widget.background:Hide() end end end end end -- Setup text function Layout:SetupFontString(fontString, extraSize) local size = ShadowUF.db.profile.font.size + (extraSize or 0) if( size <= 0 ) then size = 1 end fontString:SetFont(mediaPath.font, size, ShadowUF.db.profile.font.extra) if( ShadowUF.db.profile.font.shadowColor and ShadowUF.db.profile.font.shadowX and ShadowUF.db.profile.font.shadowY ) then fontString:SetShadowColor(ShadowUF.db.profile.font.shadowColor.r, ShadowUF.db.profile.font.shadowColor.g, ShadowUF.db.profile.font.shadowColor.b, ShadowUF.db.profile.font.shadowColor.a) fontString:SetShadowOffset(ShadowUF.db.profile.font.shadowX, ShadowUF.db.profile.font.shadowY) else fontString:SetShadowColor(0, 0, 0, 0) fontString:SetShadowOffset(0, 0) end end local totalWeight = {} function Layout:InitFontString(parent, frame, id, config, blockID) local rowID = blockID and tonumber(id .. "." .. blockID) or id local fontString = frame.fontStrings[rowID] or frame.highFrame:CreateFontString(nil, "ARTWORK") fontString.configID = id if( blockID ) then fontString.blockID = blockID fontString.block = parent.blocks[blockID] end self:SetupFontString(fontString, config.size) fontString:SetTextColor(ShadowUF.db.profile.font.color.r, ShadowUF.db.profile.font.color.g, ShadowUF.db.profile.font.color.b, ShadowUF.db.profile.font.color.a) fontString:SetText(config.text) fontString:SetJustifyH(self:GetJustify(config)) self:AnchorFrame(frame, fontString, config) -- We figure out the anchor point so we can put text in the same area with the same width requirements local anchorPoint = columnDirection[config.anchorPoint] if( string.len(config.anchorPoint) == 3 ) then anchorPoint = anchorPoint .. "I" end fontString.parentBar = parent fontString.availableWidth = parent:GetWidth() - config.x fontString.widthID = config.anchorTo .. anchorPoint .. config.y totalWeight[fontString.widthID] = (totalWeight[fontString.widthID] or 0) + config.width ShadowUF.Tags:Register(frame, fontString, config.text) fontString:UpdateTags() fontString:Show() frame.fontStrings[rowID] = fontString end function Layout:SetupText(frame, config) -- Update tag text frame.fontStrings = frame.fontStrings or {} for _, fontString in pairs(frame.fontStrings) do ShadowUF.Tags:Unregister(fontString) fontString:Hide() end for k in pairs(totalWeight) do totalWeight[k] = nil end -- Update the actual text, and figure out the weighting information now for id, row in pairs(config.text) do local module = string.sub(row.anchorTo, 2) local parent = row.anchorTo == "$parent" and frame or frame[module] if( parent and ( ShadowUF.modules[module].defaultVisibility == false or parent:IsShown() ) and row.enabled and row.text ~= "" ) then if( not row.block ) then self:InitFontString(parent, frame, id, row, nil) else for blockID, block in pairs(parent.blocks) do self:InitFontString(parent, frame, id, row, blockID) end end end end -- Now set all of the width using our weightings for _, fontString in pairs(frame.fontStrings) do local id = fontString.configID if( fontString:IsShown() ) then fontString:SetWidth(fontString.availableWidth * (config.text[id].width / totalWeight[fontString.widthID])) fontString:SetHeight(ShadowUF.db.profile.font.size + 1) frame:RegisterUpdateFunc(fontString, "UpdateTags") else frame:UnregisterAll(fontString) end end end -- Setup the bar barOrder/info local currentConfig local function sortOrder(a, b) return currentConfig[a].order < currentConfig[b].order end local barOrder = {} function Layout:PositionWidgets(frame, config) -- Deal with setting all of the bar heights local totalWidgetWeight, totalBars, hasFullSize = 0, -1 -- Figure out total weighting as well as what bars are full sized for i=#(barOrder), 1, -1 do table.remove(barOrder, i) end for key, module in pairs(ShadowUF.modules) do if( config[key] and not config[key].height ) then config[key].height = 0.50 end if( ( module.moduleHasBar or config[key] and config[key].isBar ) and frame[key] and frame[key]:IsShown() and config[key].height > 0 ) then totalWidgetWeight = totalWidgetWeight + config[key].height totalBars = totalBars + 1 table.insert(barOrder, key) config[key].order = config[key].order or 99 -- Decide whats full sized if( not frame.visibility.portrait or config.portrait.isBar or config[key].order < config.portrait.fullBefore or config[key].order > config.portrait.fullAfter ) then hasFullSize = true frame[key].fullSize = true else frame[key].fullSize = nil end end end -- Sort the barOrder so it's all nice and orderly (:>) currentConfig = config table.sort(barOrder, sortOrder) -- Now deal with setting the heights and figure out how large the portrait should be. local clip = ShadowUF.db.profile.backdrop.inset + ShadowUF.db.profile.backdrop.clip local clipDoubled = clip * 2 local portraitOffset, portraitAlignment, portraitAnchor, portraitWidth if( not config.portrait.isBar ) then self:ToggleVisibility(frame.portrait, frame.visibility.portrait) if( frame.visibility.portrait ) then -- Figure out portrait alignment portraitAlignment = config.portrait.alignment -- Set the portrait width so we can figure out the offset to use on bars, will do height and position later portraitWidth = math.floor(frame:GetWidth() * config.portrait.width) - ShadowUF.db.profile.backdrop.inset frame.portrait:SetWidth(portraitWidth - (portraitAlignment == "RIGHT" and 1 or 0.5)) -- Disable portrait if there isn't enough room if( portraitWidth <= 0 ) then frame.portrait:Hide() end -- As well as how much to offset bars by (if it's using a left alignment) to keep them all fancy looking portraitOffset = clip if( portraitAlignment == "LEFT" ) then portraitOffset = portraitOffset + portraitWidth end end end -- Position and size everything local portraitHeight, xOffset = 0, -clip local availableHeight = frame:GetHeight() - clipDoubled - (math.abs(ShadowUF.db.profile.bars.spacing) * totalBars) for id, key in pairs(barOrder) do local bar = frame[key] -- Position the actual bar based on it's type if( bar.fullSize ) then bar:SetWidth(frame:GetWidth() - clipDoubled) bar:SetHeight(availableHeight * (config[key].height / totalWidgetWeight)) bar:ClearAllPoints() bar:SetPoint("TOPLEFT", frame, "TOPLEFT", clip, xOffset) else bar:SetWidth(frame:GetWidth() - portraitWidth - clipDoubled) bar:SetHeight(availableHeight * (config[key].height / totalWidgetWeight)) bar:ClearAllPoints() bar:SetPoint("TOPLEFT", frame, "TOPLEFT", portraitOffset, xOffset) portraitHeight = portraitHeight + bar:GetHeight() end -- Figure out where the portrait is going to be anchored to if( not portraitAnchor and config[key].order >= config.portrait.fullBefore ) then portraitAnchor = bar end xOffset = xOffset - bar:GetHeight() + ShadowUF.db.profile.bars.spacing end -- Now position the portrait and set the height if( frame.portrait and frame.portrait:IsShown() and portraitAnchor and portraitHeight > 0 ) then if( portraitAlignment == "LEFT" ) then frame.portrait:ClearAllPoints() frame.portrait:SetPoint("TOPLEFT", portraitAnchor, "TOPLEFT", -frame.portrait:GetWidth() - 0.5, 0) elseif( portraitAlignment == "RIGHT" ) then frame.portrait:ClearAllPoints() frame.portrait:SetPoint("TOPRIGHT", portraitAnchor, "TOPRIGHT", frame.portrait:GetWidth() + 1, 0) end if( hasFullSize ) then frame.portrait:SetHeight(portraitHeight) else frame.portrait:SetHeight(frame:GetHeight() - clipDoubled) end end ShadowUF:FireModuleEvent("OnLayoutWidgets", frame, config) end