Originally Posted by Jonisaurus
For my OOP practice I made a class (prototype) that can display font strings of units and their different values.
Like level, name, HP, power of the specified units.
|
I understand you're just practicing, but what you're practicting is way more complicated than it needs to be, and has some issues regardless of efficiency. 220 is not a valid font size; anything larger than 36* will be treated as if it were 36. You don't need to hide and re-show a frame before and after registering events. You should be using RegisterUnitEvent instead of RegisterEvent for unit-specific events. You're limiting your "font strings" to a few pre-defined event handlers, but allowing any arbitrary events to be registered; either allow a custom handler, or just hardcode the right event(s) for the pre-defined handler (eg. if you're handling health, register UNIT_HEALTH and UNIT_MAXHEALTH). There's absolutely no reason to wrap every frame API in an additional function that stores the alpha/position/whatever on keys on the frame, as you can just call frame:GetWhatever() if you really need to know those values later. You should just create a frame and return it so you can use its own API methods directly.
* The maximum font size is specific to the font file you're using, and is closer to 32 for most fonts, but can be much lower for some. It is never higher than 36.
Here's how I would write the same thing, in a more straightforward and more easily extensible way:
Code:
local NewUnitFontString
do
-- Define events and handlers for specific "display types":
local displayEvents = {
health = {
UNIT_HEALTH = true,
UNIT_MAXHEALTH = true,
},
name = {
PLAYER_TARGET_CHANGED = false,
UNIT_NAME_UPDATE = true,
},
}
local displayHandlers = {
health = function(self, event, unit)
local hp = UnitHealth(unit or self.unit)
self:SetText(hp and hp > 0 and hp or nil)
end,
name = function(self, event, unit)
local name = GetUnitName(unit or self.unit, true)
self:SetText(name)
end,
}
-- Define functions to let the frame be moved:
local function OnMouseDown(self)
if IsAltKeyDown() then
self.isMoving = true
self:StartMoving()
end
end
local function OnMouseUp(self)
if self.isMoving then
self:StopMoving()
self.isMoving = nil
end
end
function NewUnitFontString(unit, displayType)
-- Only proceed if this displayType is defined:
local events, handler = displayEvents[displayType], displayHandlers[displayType]
if not events or not handler then
return print("NewUnitFontString:", displayType, "is not a valid display type!")
end
-- Make the frame:
local f = CreateFrame("Frame", nil, UIParent, "SecureHandlerStateTemplate")
f:SetFrameStrata("BACKGROUND")
f:SetPoint("CENTER")
f:SetWidth(228)
f:SetHeight(64)
-- Add the font string:
local text = f:CreateFontString(nil, "OVERLAY")
text:SetFont("Fonts\\FRIZQT__.TTF", 22, "THICKOUTLINE")
text:SetAllPoints(true)
-- Let the frame be dragged around:
f:EnableMouse(true)
f:SetMovable(true)
f:RegisterForDrag("LeftButton")
f:SetScript("OnMouseDown", OnMouseDown)
f:SetScript("OnMouseUp", OnMouseUp)
f:SetScript("OnHide", OnMouseUp) -- otherwise it can get stuck to the cursor if it's being dragged when it gets hidden
-- Register the events and assign the handler:
f.unit = unit
f:SetScript("OnEvent", handler)
for event, unitSpecific in pairs(events) do
if unitSpecific then
f:RegisterUnitEvent(event, unit)
else
f:RegisterEvent(event)
end
end
-- Hide the frame when the unit doesn't exist:
RegisterStateDriver(f, "visibility", "[@"..unit..",exists]show;hide")
f:SetShown(UnitExists(unit))
-- Return the frame:
return f
end
end
Then you can just ask for and get a normal frame in a normal way, and access and manipulate its properties directly through the normal frame API:
Code:
local targetName = NewUnitFontString("target", "name")
print(targetName:GetWidth())
targetName:SetAlpha(0.5)
(I also made the frames movable when Alt is pressed, and automatically hide themselves when their unit doesn't exist.)