mirror of
https://github.com/Lacustat/Freewood-OctoWoW-Core.git
synced 2026-11-01 09:36:55 +00:00
0.1.175: Einstellungen mit Unter-Reitern, Tooltip-Einstellungen im Core
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016onJCSHLwhs9udhC9ZLzk9
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
e7d2d14bb4
commit
99e6820776
@@ -0,0 +1,204 @@
|
||||
-- Freewood-Core: Tooltip-Einstellungen (Standard fuer alle Module)
|
||||
-- Das Freewood-Design und der Tooltip an der Maus gehoeren dem Core. Module melden ihre Zusatzinfos mit
|
||||
-- FW.Tooltips.RegisterOption(key, labelKey, { default = true, order = 10, available = function() return true end }) an;
|
||||
-- sie erscheinen dann unter Einstellungen -> Tooltips. Lesen: FW.Tooltips.Get(key), Schreiben: FW.Tooltips.Set(key, wert).
|
||||
-- Aenderungen melden sich ueber FW:Fire("QUEST_TIP_CHANGED", key) (Name bleibt aus Kompatibilitaet zu den Modulen).
|
||||
|
||||
local FW = _G.Freewood
|
||||
if not FW then return end
|
||||
|
||||
local T = {}
|
||||
FW.Tooltips = T
|
||||
|
||||
local BG = { 0.059, 0.075, 0.122, 0.97 }
|
||||
local GOLD = { 0.616, 0.471, 0.149, 1 }
|
||||
local WHITE = "Interface\\Buttons\\WHITE8X8"
|
||||
local TIPS = { "GameTooltip", "ItemRefTooltip", "ShoppingTooltip1", "ShoppingTooltip2", "FreewoodCmpTip1", "FreewoodCmpTip2" }
|
||||
|
||||
local defaults = { tipSkin = false, tipCursor = false }
|
||||
local options = {} -- Zusatzoptionen der Module
|
||||
|
||||
local function Store()
|
||||
local s = FW.settings
|
||||
if not s then return nil end
|
||||
if type(s.tooltips) ~= "table" then s.tooltips = {} end
|
||||
return s.tooltips
|
||||
end
|
||||
|
||||
function T.Raw(key)
|
||||
local st = Store()
|
||||
return st and st[key]
|
||||
end
|
||||
|
||||
function T.Get(key)
|
||||
local st = Store()
|
||||
local v = st and st[key]
|
||||
if v == nil then return defaults[key] end
|
||||
return v
|
||||
end
|
||||
|
||||
function T.Set(key, value)
|
||||
local st = Store()
|
||||
if not st then return end
|
||||
st[key] = value
|
||||
FW:Fire("QUEST_TIP_CHANGED", key)
|
||||
end
|
||||
|
||||
-- Alte Werte uebernehmen (Modul ruft es einmal mit seinen gespeicherten Werten auf); nur wenn im Core noch nichts steht
|
||||
function T.Migrate(old)
|
||||
local st = Store()
|
||||
if not st or type(old) ~= "table" then return end
|
||||
for k, v in pairs(old) do
|
||||
if type(k) == "string" and k:sub(1, 3) == "tip" and st[k] == nil and type(v) == "boolean" then
|
||||
st[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function T.RegisterOption(key, labelKey, def)
|
||||
def = def or {}
|
||||
if defaults[key] == nil then defaults[key] = def.default ~= false end
|
||||
for _, o in ipairs(options) do
|
||||
if o.key == key then return end
|
||||
end
|
||||
options[#options + 1] = { key = key, label = labelKey, order = def.order or 100, available = def.available }
|
||||
table.sort(options, function(a, b)
|
||||
if a.order ~= b.order then return a.order < b.order end
|
||||
return a.key < b.key
|
||||
end)
|
||||
if T.RefreshSettings then T.RefreshSettings() end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Design
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local function SkinOn(tt)
|
||||
if not tt.SetBackdrop then return end
|
||||
tt:SetBackdrop({ bgFile = WHITE, edgeFile = WHITE, tile = false, edgeSize = 1,
|
||||
insets = { left = 1, right = 1, top = 1, bottom = 1 } })
|
||||
tt:SetBackdropColor(BG[1], BG[2], BG[3], BG[4])
|
||||
tt:SetBackdropBorderColor(GOLD[1], GOLD[2], GOLD[3], GOLD[4])
|
||||
tt.fwSkinned = true
|
||||
end
|
||||
|
||||
local function SkinOff(tt)
|
||||
if not tt.fwSkinned or not tt.SetBackdrop then return end
|
||||
tt:SetBackdrop({ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", tile = true, tileSize = 16, edgeSize = 16,
|
||||
insets = { left = 5, right = 5, top = 5, bottom = 5 } })
|
||||
tt:SetBackdropColor(0.09, 0.09, 0.19, 1)
|
||||
tt:SetBackdropBorderColor(1, 1, 1, 1)
|
||||
tt.fwSkinned = nil
|
||||
end
|
||||
|
||||
local hooked = {}
|
||||
local function Apply(tt)
|
||||
if T.Get("tipSkin") == true then SkinOn(tt) else SkinOff(tt) end
|
||||
end
|
||||
|
||||
function T.Hook(tt)
|
||||
if not tt or hooked[tt] or not tt.HookScript then return end
|
||||
hooked[tt] = true
|
||||
tt:HookScript("OnShow", function(self) pcall(Apply, self) end)
|
||||
pcall(tt.HookScript, tt, "OnTooltipSetItem", function(self) pcall(Apply, self) end)
|
||||
pcall(tt.HookScript, tt, "OnTooltipSetUnit", function(self) pcall(Apply, self) end)
|
||||
pcall(Apply, tt)
|
||||
end
|
||||
|
||||
local function HookAll()
|
||||
for _, name in ipairs(TIPS) do T.Hook(_G[name]) end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Tooltip an der Maus (nur Welt: Gegner, Objekte; Inventar bleibt am Item)
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local follow = _G.CreateFrame("Frame")
|
||||
follow:SetScript("OnUpdate", function()
|
||||
if T.Get("tipCursor") ~= true then return end
|
||||
local tt = _G.GameTooltip
|
||||
if not tt or not tt:IsShown() then return end
|
||||
local owner = tt.GetOwner and tt:GetOwner()
|
||||
if owner ~= _G.UIParent then return end
|
||||
local x, y = _G.GetCursorPosition()
|
||||
local s = _G.UIParent:GetEffectiveScale()
|
||||
local ts = tt:GetEffectiveScale()
|
||||
if not x or not s or s == 0 or not ts or ts == 0 then return end
|
||||
x, y = x / s, y / s
|
||||
local w, h = (tt:GetWidth() or 0) * ts / s, (tt:GetHeight() or 0) * ts / s
|
||||
local sw, sh = _G.UIParent:GetWidth(), _G.UIParent:GetHeight()
|
||||
local px = x + 16
|
||||
if px + w > sw then px = x - 16 - w end
|
||||
local py = y + 16
|
||||
if py + h > sh then py = y - 16 - h end
|
||||
if px < 0 then px = 0 end
|
||||
if py < 0 then py = 0 end
|
||||
tt:ClearAllPoints()
|
||||
tt:SetPoint("BOTTOMLEFT", _G.UIParent, "BOTTOMLEFT", px * s / ts, py * s / ts)
|
||||
end)
|
||||
|
||||
local function Reapply()
|
||||
HookAll()
|
||||
for _, name in ipairs(TIPS) do
|
||||
local tt = _G[name]
|
||||
if tt then pcall(Apply, tt) end
|
||||
end
|
||||
end
|
||||
|
||||
FW:On("QUEST_TIP_CHANGED", function(key)
|
||||
if key == "tipSkin" then Reapply() end
|
||||
end, T)
|
||||
|
||||
local init = _G.CreateFrame("Frame")
|
||||
init:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
init:SetScript("OnEvent", function() Reapply() end)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- Einstellungen (Unter-Reiter "Tooltips")
|
||||
------------------------------------------------------------------------
|
||||
|
||||
local UI = FW.UI
|
||||
if UI and UI.RegisterSettingsSection then
|
||||
UI:RegisterSettingsSection("tooltips", {
|
||||
order = 10,
|
||||
category = "tooltips",
|
||||
height = 300,
|
||||
build = function(parent)
|
||||
local L = FW.L
|
||||
local f, stack = UI.CreateSection(parent, L.TIPSET_HEADER)
|
||||
local note = UI.CreateLabel(f, L.TIPSET_NOTE, { size = 11, color = "textDim", justifyV = "TOP" })
|
||||
stack:Add(note, { fit = true, gap = 8 })
|
||||
local boxes, made = {}, {}
|
||||
local function Box(key, label)
|
||||
local cb = UI.CreateCheckbox(f, label, function() return T.Get(key) == true end,
|
||||
function(on) T.Set(key, on and true or false) end)
|
||||
stack:Add(cb, { fit = true, gap = 6 })
|
||||
boxes[#boxes + 1] = cb
|
||||
return cb
|
||||
end
|
||||
Box("tipSkin", L.TIPSET_SKIN)
|
||||
Box("tipCursor", L.TIPSET_CURSOR)
|
||||
function f.Refresh()
|
||||
for _, o in ipairs(options) do
|
||||
if not made[o.key] and (not o.available or o.available()) then
|
||||
made[o.key] = true
|
||||
Box(o.key, FW.L[o.label] or o.label)
|
||||
end
|
||||
end
|
||||
for _, cb in ipairs(boxes) do cb:Refresh() end
|
||||
stack:Layout()
|
||||
end
|
||||
T.settingsFrame = f
|
||||
f.Refresh()
|
||||
return f
|
||||
end,
|
||||
refresh = function(frame)
|
||||
frame.Refresh()
|
||||
end,
|
||||
})
|
||||
function T.RefreshSettings()
|
||||
local f = T.settingsFrame
|
||||
if f and f.Refresh then f.Refresh() end
|
||||
end
|
||||
end
|
||||
@@ -3,7 +3,7 @@
|
||||
## Notes: Base addon of the Freewood family: data storage, UI kit, export/import and the main window.
|
||||
## Notes-deDE: Basis-Addon der Freewood-Familie: Datenspeicher, UI-Bausteine, Export/Import und Hauptfenster.
|
||||
## Author: Lacustat
|
||||
## Version: 0.1.174
|
||||
## Version: 0.1.175
|
||||
## SavedVariables: FreewoodDB
|
||||
## SavedVariablesPerCharacter: FreewoodCharDB
|
||||
|
||||
@@ -16,5 +16,6 @@ UI\Kit.lua
|
||||
UI\MainFrame.lua
|
||||
UI\MainWindow.lua
|
||||
UI\Tabs.lua
|
||||
Core\Tooltips.lua
|
||||
UI\Minimap.lua
|
||||
Core\Slash.lua
|
||||
|
||||
+18
@@ -82,6 +82,15 @@ FW:AddLocale("enUS", {
|
||||
SETTINGS_LANGUAGE = "Language",
|
||||
SETTINGS_LANGUAGE_NOTE = "A language change takes effect after /reload.",
|
||||
SETTINGS_RESET_POS = "Reset window position and size",
|
||||
SETTINGS_CAT_GENERAL = "General",
|
||||
SETTINGS_CAT_DATABASE = "Database",
|
||||
SETTINGS_CAT_TOOLTIPS = "Tooltips",
|
||||
SETTINGS_CAT_QUEST = "Quests and hints",
|
||||
SETTINGS_CAT_MODULES = "Modules",
|
||||
TIPSET_HEADER = "Tooltips",
|
||||
TIPSET_NOTE = "Look and extra information in item and creature tooltips. Each part can be switched off.",
|
||||
TIPSET_SKIN = "Freewood look for tooltips (dark blue, gold border)",
|
||||
TIPSET_CURSOR = "Show creature and object tooltips at the mouse",
|
||||
WINDOW_RESIZE = "Resize",
|
||||
WINDOW_RESIZE_TIP = "Drag to change the window size. The size is remembered.",
|
||||
WINDOW_SCALE = "Window scale",
|
||||
@@ -155,6 +164,15 @@ FW:AddLocale("deDE", {
|
||||
SETTINGS_LANGUAGE = "Sprache",
|
||||
SETTINGS_LANGUAGE_NOTE = "Eine Sprachänderung wirkt nach /reload.",
|
||||
SETTINGS_RESET_POS = "Position und Größe zurücksetzen",
|
||||
SETTINGS_CAT_GENERAL = "Allgemein",
|
||||
SETTINGS_CAT_DATABASE = "Datenbank",
|
||||
SETTINGS_CAT_TOOLTIPS = "Tooltips",
|
||||
SETTINGS_CAT_QUEST = "Quests und Hinweise",
|
||||
SETTINGS_CAT_MODULES = "Module",
|
||||
TIPSET_HEADER = "Tooltips",
|
||||
TIPSET_NOTE = "Aussehen und Zusatzinfos in Item- und Gegner-Tooltips. Jeder Teil lässt sich einzeln ausschalten.",
|
||||
TIPSET_SKIN = "Freewood-Design für Tooltips (dunkelblau, Goldrand)",
|
||||
TIPSET_CURSOR = "Gegner- und Objekt-Tooltips an der Maus anzeigen",
|
||||
WINDOW_RESIZE = "Größe ändern",
|
||||
WINDOW_RESIZE_TIP = "Ziehen, um die Fenstergröße zu ändern. Die Größe wird gespeichert.",
|
||||
WINDOW_SCALE = "Fenstergröße",
|
||||
|
||||
+120
-25
@@ -245,12 +245,58 @@ end
|
||||
|
||||
-- Module koennen eigene Abschnitte in den Einstellungen anmelden:
|
||||
-- UI:RegisterSettingsSection(id, { order = 100, height = 260, build = function(parent) return frame end, refresh = function(frame) end })
|
||||
-- Die Abschnitte stehen in zwei Spalten rechts neben den allgemeinen Einstellungen. Die Hoehe eines Abschnitts
|
||||
-- def.category (optional) ordnet den Abschnitt einem Unter-Reiter zu: "general" (Standard, mit den allgemeinen Einstellungen
|
||||
-- links), "database", "tooltips", "quest" oder "modules". Reiter ohne Abschnitte werden nicht gezeigt.
|
||||
-- Die Abschnitte stehen in Spalten (allgemein: zwei Spalten rechts neben den allgemeinen Einstellungen). Die Hoehe eines Abschnitts
|
||||
-- ist der Wert frame.flowH, wenn er ihn meldet (UI.CreateSection tut das), sonst def.height. Die ganze Seite
|
||||
-- scrollt, wenn sie hoeher ist als das Fenster; die Breiten richten sich nach der Fensterbreite.
|
||||
local settingsSections = {}
|
||||
local settingsFrame, settingsBody, settingsScroll, settingsLeft
|
||||
local vline1, vline2
|
||||
local vlines = {}
|
||||
local catBar, catButtons = nil, {}
|
||||
local currentCat
|
||||
local CATS = { "general", "database", "tooltips", "quest", "modules" }
|
||||
local CAT_LABEL = {
|
||||
general = "SETTINGS_CAT_GENERAL", database = "SETTINGS_CAT_DATABASE", tooltips = "SETTINGS_CAT_TOOLTIPS",
|
||||
quest = "SETTINGS_CAT_QUEST", modules = "SETTINGS_CAT_MODULES",
|
||||
}
|
||||
local function CatOf(def)
|
||||
return CAT_LABEL[def.category] and def.category or "general"
|
||||
end
|
||||
local function CountCats()
|
||||
local counts = {}
|
||||
for _, def in ipairs(settingsSections) do
|
||||
local c = CatOf(def)
|
||||
counts[c] = (counts[c] or 0) + 1
|
||||
end
|
||||
return counts
|
||||
end
|
||||
-- gewaehlter Unter-Reiter (gemerkt); ohne Abschnitte faellt er auf "general" zurueck
|
||||
local function CurrentCat()
|
||||
if not currentCat then
|
||||
local c = FW.settings and FW.settings.settingsCat
|
||||
currentCat = CAT_LABEL[c] and c or "general"
|
||||
end
|
||||
if currentCat ~= "general" and not CountCats()[currentCat] then
|
||||
currentCat = "general"
|
||||
end
|
||||
return currentCat
|
||||
end
|
||||
local function UpdateCatBar()
|
||||
if not catBar then return end
|
||||
local cat, counts, x = CurrentCat(), CountCats(), 0
|
||||
for _, b in ipairs(catButtons) do
|
||||
if b.cat == "general" or counts[b.cat] then
|
||||
b:Show()
|
||||
b:ClearAllPoints()
|
||||
b:SetPoint("TOPLEFT", catBar, "TOPLEFT", x, 0)
|
||||
x = x + b:GetWidth() + 6
|
||||
b:SetStyle(b.cat == cat and "primary" or "default")
|
||||
else
|
||||
b:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Abschnitt mit Ueberschrift, Trennlinie und einem Stapel darunter: local f, stack = UI.CreateSection(parent, "Titel")
|
||||
function UI.CreateSection(parent, titleText)
|
||||
@@ -292,35 +338,66 @@ local function LayoutSections()
|
||||
if W < 200 then
|
||||
W = 1000
|
||||
end
|
||||
local cat = CurrentCat()
|
||||
local general = cat == "general"
|
||||
local leftW = LeftWidth(W)
|
||||
local x1 = leftW + LEFT_GAP
|
||||
local colW = math.max(200, math.floor((W - x1 - SECTION_GAP) / 2))
|
||||
local x2 = x1 + colW + SECTION_GAP
|
||||
local x0 = general and (leftW + LEFT_GAP) or 0
|
||||
local ncol = general and 2 or FW.Util.Clamp(math.floor((W + SECTION_GAP) / (420 + SECTION_GAP)), 1, 3)
|
||||
local colW = math.max(200, math.floor((W - x0 - (ncol - 1) * SECTION_GAP) / ncol))
|
||||
local xs, ypos = {}, {}
|
||||
for i = 1, ncol do
|
||||
xs[i] = x0 + (i - 1) * (colW + SECTION_GAP)
|
||||
ypos[i] = 0
|
||||
end
|
||||
settingsLeft:SetShown(general)
|
||||
settingsLeft:SetWidth(leftW)
|
||||
local ypos = { 0, 0 }
|
||||
for i, def in ipairs(settingsSections) do
|
||||
def.col = (ypos[1] >= ypos[2]) and 1 or 2 -- jeweils in die kuerzere Spalte
|
||||
local h = (def.frame and def.frame.flowH) or def.height or 260
|
||||
def.y = ypos[def.col]
|
||||
ypos[def.col] = ypos[def.col] - h - 10
|
||||
for _, def in ipairs(settingsSections) do
|
||||
local frame = def.frame
|
||||
if frame then
|
||||
frame:ClearAllPoints()
|
||||
frame:SetPoint("TOPLEFT", settingsBody, "TOPLEFT", def.col == 2 and x2 or x1, def.y)
|
||||
frame:SetWidth(colW)
|
||||
frame:SetHeight(h)
|
||||
if CatOf(def) ~= cat then
|
||||
if frame then frame:Hide() end
|
||||
else
|
||||
local best = 1 -- jeweils in die kuerzeste Spalte
|
||||
for i = 2, ncol do
|
||||
if ypos[i] > ypos[best] then best = i end
|
||||
end
|
||||
local h = (frame and frame.flowH) or def.height or 260
|
||||
def.col, def.y = best, ypos[best]
|
||||
ypos[best] = ypos[best] - h - 10
|
||||
if frame then
|
||||
frame:Show()
|
||||
frame:ClearAllPoints()
|
||||
frame:SetPoint("TOPLEFT", settingsBody, "TOPLEFT", xs[best], def.y)
|
||||
frame:SetWidth(colW)
|
||||
frame:SetHeight(h)
|
||||
end
|
||||
end
|
||||
end
|
||||
local contentH = math.max(-ypos[1], -ypos[2], settingsLeft.flowH or 0) + 20
|
||||
local contentH = general and (settingsLeft.flowH or 0) or 0
|
||||
for i = 1, ncol do
|
||||
contentH = math.max(contentH, -ypos[i])
|
||||
end
|
||||
contentH = contentH + 20
|
||||
settingsBody.contentH = contentH
|
||||
settingsBody:SetHeight(contentH)
|
||||
settingsScroll:SetContentHeight(contentH)
|
||||
vline1:ClearAllPoints()
|
||||
vline1:SetPoint("TOPLEFT", settingsBody, "TOPLEFT", x1 - 20, 0)
|
||||
vline1:SetPoint("BOTTOMLEFT", settingsBody, "TOPLEFT", x1 - 20, -contentH)
|
||||
vline2:ClearAllPoints()
|
||||
vline2:SetPoint("TOPLEFT", settingsBody, "TOPLEFT", x2 - SECTION_GAP / 2, 0)
|
||||
vline2:SetPoint("BOTTOMLEFT", settingsBody, "TOPLEFT", x2 - SECTION_GAP / 2, -contentH)
|
||||
local pos = {}
|
||||
if general then
|
||||
pos[1] = x0 - 20
|
||||
pos[2] = xs[2] - SECTION_GAP / 2
|
||||
else
|
||||
for i = 2, ncol do pos[#pos + 1] = xs[i] - SECTION_GAP / 2 end
|
||||
end
|
||||
for i, line in ipairs(vlines) do
|
||||
if pos[i] then
|
||||
line:Show()
|
||||
line:ClearAllPoints()
|
||||
line:SetPoint("TOPLEFT", settingsBody, "TOPLEFT", pos[i], 0)
|
||||
line:SetPoint("BOTTOMLEFT", settingsBody, "TOPLEFT", pos[i], -contentH)
|
||||
else
|
||||
line:Hide()
|
||||
end
|
||||
end
|
||||
UpdateCatBar()
|
||||
layingOut = false
|
||||
if pendingLayout and layoutDepth < 4 then
|
||||
pendingLayout = false
|
||||
@@ -331,6 +408,12 @@ local function LayoutSections()
|
||||
pendingLayout = false
|
||||
end
|
||||
|
||||
local function SelectCategory(cat)
|
||||
currentCat = cat
|
||||
if FW.settings then FW.settings.settingsCat = cat end
|
||||
LayoutSections()
|
||||
end
|
||||
|
||||
local function BuildSection(def)
|
||||
if def.frame or not settingsBody then
|
||||
return
|
||||
@@ -367,9 +450,21 @@ local function BuildSettings(content)
|
||||
divider:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -30)
|
||||
divider:SetPoint("TOPRIGHT", f, "TOPRIGHT", 0, -30)
|
||||
|
||||
-- Unter-Reiter (Kategorien)
|
||||
catBar = CreateFrame("Frame", nil, f)
|
||||
catBar:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -42)
|
||||
catBar:SetPoint("TOPRIGHT", f, "TOPRIGHT", 0, -42)
|
||||
catBar:SetHeight(28)
|
||||
catButtons = {}
|
||||
for _, cat in ipairs(CATS) do
|
||||
local b = UI.CreateButton(catBar, L[CAT_LABEL[cat]], 160, 26, function() SelectCategory(cat) end)
|
||||
b.cat = cat
|
||||
catButtons[#catButtons + 1] = b
|
||||
end
|
||||
|
||||
-- Alles darunter scrollt, wenn das Fenster zu niedrig ist
|
||||
local scroll = UI.CreateScrollFrame(f)
|
||||
scroll:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -42)
|
||||
scroll:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -78)
|
||||
scroll:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0)
|
||||
local body = scroll.child
|
||||
settingsScroll, settingsBody, settingsFrame = scroll, body, f
|
||||
@@ -496,7 +591,7 @@ local function BuildSettings(content)
|
||||
line:SetColorTexture(UI.Color("gold", 0.35))
|
||||
return line
|
||||
end
|
||||
vline1, vline2 = VLine(), VLine()
|
||||
vlines = { VLine(), VLine(), VLine() }
|
||||
|
||||
body:SetScript("OnSizeChanged", function(self)
|
||||
local w = self:GetWidth()
|
||||
|
||||
Reference in New Issue
Block a user