diff --git a/src/OmicronFrames.toc b/src/OmicronFrames.toc index 0132cd8..5349866 100644 --- a/src/OmicronFrames.toc +++ b/src/OmicronFrames.toc @@ -12,6 +12,7 @@ types/trigger.lua types/statusbar.lua types/auralist.lua types/indicator.lua +types/unitgroup.lua types/unitframe.lua frames.lua diff --git a/src/frames.lua b/src/frames.lua index f6b93b0..ed03972 100644 --- a/src/frames.lua +++ b/src/frames.lua @@ -16,8 +16,10 @@ -- Omicron Frames. If not, see . local omif = select(2, ...) -local UnitFrame = omif.GetModule("types").UnitFrame -local frames = omif.GetModule("frames") + +local types = omif.GetModule("types") +local UnitFrame = types.UnitFrame +local UnitGroup = types.UnitGroup -- re-parent all blizzard frames and then hide the new parent function HideBlizzardFrames() @@ -39,35 +41,42 @@ function HideBlizzardFrames() end function CreateRaidFrames(left, top, width, height) + local group = UnitGroup:new(left, top, width, height) for i=0,5 do for j=0,4 do local num = i*5 + j + 1 local frame = UnitFrame:new("raid" .. num, width, height) - frame:SetPosition(left + (j-2)*width, top - i*height) + group:AddUnitFrame(frame) end end end function CreatePartyFrames(left, top, width, height) + local group = UnitGroup:new(left, top, width, height) local player = UnitFrame:new("player", width, height, true) - player:SetPosition(-2*width, top) + group:AddUnitFrame(player) for i=1,4 do local frame = UnitFrame:new("party" .. i, width, height, true) - frame:SetPosition((i-2)*width, top) + group:AddUnitFrame(frame) end + group:Sort() end function CreateTargetFrames(left, top, width, height) - local target = UnitFrame:new("target", width, height) - target:SetPosition(left, top) local focus = UnitFrame:new("focus", width, height) - focus:SetPosition(left, top-height) + focus:SetPosition(left, top) + local target = UnitFrame:new("target", width, height) + target:SetPosition(left, top - height) + for i=1,4 do + local boss = UnitFrame:new("boss" .. i, width, height) + boss:SetPosition(left, top-(i+1)*height) + end end function CreateFrames() CreatePartyFrames(0, -290, 110, 45) CreateRaidFrames(0, -290, 110, 45) - CreateTargetFrames(110*3+50, -290, 110, 45) + CreateTargetFrames(110*3+50, -245, 110, 45) HideBlizzardFrames() end omif.SetEventHandler("OMICRON_LOADING", CreateFrames) diff --git a/src/types/unitgroup.lua b/src/types/unitgroup.lua new file mode 100644 index 0000000..1103641 --- /dev/null +++ b/src/types/unitgroup.lua @@ -0,0 +1,134 @@ +-- Copyright 2023 +-- +-- This file is part of Omicron Frames +-- +-- Omicron Frames is free software: you can redistribute it and/or modify it +-- under the terms of the GNU General Public License as published by the Free +-- Software Foundation, either version 3 of the License, or (at your option) +-- any later version. +-- +-- Omicron Frames is distributed in the hope that it will be useful, but +-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +-- more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- Omicron Frames. If not, see . +local omi = select(2, ...) +local types = omi.GetModule("types") +local UnitGroup = types.CreateClass("UnitGroup") +types.UnitGroup = UnitGroup + +local function RoleValue(role) + if role == "TANK" then + return 0 + elseif role == "HEALER" then + return 1 + elseif role == "DAMAGER" then + return 2 + else + return 3 + end +end + +local function UnitFrameDefaultCompare(lhs, rhs) + -- visible < invisible + if lhs.secureFrame:IsShown() ~= rhs.secureFrame:IsShown() then + return lhs.secureFrame:IsShown() + end + + local lunit, runit = lhs.unit, rhs.unit + + -- players < non-players + local player = UnitIsPlayer(lunit) + if UnitIsPlayer(lunit) ~= UnitIsPlayer(runit) then + return player + end + + if player then + -- you < others + if UnitIsUnit(lunit, "player") ~= UnitIsUnit(runit, "player") then + return UnitIsUnit(lunit, "player") + end + + -- tank < healer < damage < ? + local lrole = RoleValue(UnitGroupRolesAssigned(lunit)) + local rrole = RoleValue(UnitGroupRolesAssigned(runit)) + + if lrole ~= rrole then + return lrole < rrole + end + end + + return lunit < runit +end + +function UnitGroup:Init(left, top, width, height) + self.width = width + self.height = height + self.top = top + self.left = left + self.units = {} + self.sortAfterCombat = false + self:RegisterEvents() +end + +function UnitGroup:RegisterEvents() + local frame = CreateFrame("Frame") + self.frame = frame + + frame:SetScript("OnEvent", function(frame, event, ...) + self[event](self, ...) + end) + + frame:RegisterEvent("GROUP_ROSTER_UPDATE") + frame:RegisterEvent("PLAYER_REGEN_ENABLED") + frame:RegisterEvent("PLAYER_ENTERING_WORLD") +end + +function UnitGroup:GROUP_ROSTER_UPDATE() + self:OnRosterUpdate() +end + +function UnitGroup:PLAYER_ENTERING_WORLD() + self:OnRosterUpdate() +end + +function UnitGroup:PLAYER_REGEN_ENABLED() + self:OnLeaveCombat() +end + +function UnitGroup:OnLeaveCombat() + if self.sortAfterCombat then + self:Sort() + self.sortAfterCombat = false + end +end + +function UnitGroup:OnRosterUpdate() + if InCombatLockdown() then + self.sortAfterCombat = true + else + self:Sort() + end +end + +function UnitGroup:AddUnitFrame(unit) + table.insert(self.units, unit) +end + +function UnitGroup:Sort() + table.sort(self.units, UnitFrameDefaultCompare) + local left, top, width, height = self.left, self.top, self.width, self.height + local maxFrameIndex = #self.units + for y=0,5 do + for x=0,4 do + local num = y*5 + x + 1 + if num > maxFrameIndex then + return + end + local frame = self.units[num] + frame:SetPosition(left + (x-2)*width, top - y*height) + end + end +end