Add UnitGroup class to put frames in a grid layout with sorting

This commit is contained in:
2023-03-18 20:35:41 +01:00
parent f14ffbe0bd
commit 9c796159b3
3 changed files with 153 additions and 9 deletions

134
src/types/unitgroup.lua Normal file
View File

@@ -0,0 +1,134 @@
-- Copyright 2023 <omicron.me@protonmail.com>
--
-- 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 <https://www.gnu.org/licenses/>.
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