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