mirror of
https://codeberg.org/Duvelcorp/MetaHunt.git
synced 2026-10-20 22:50:49 +00:00
Unify all option panels through MTH_Layout engine
Add reusable MTH_Layout box/column layout engine (api/options-layout.lua) and route every option panel through it (shell, general, zButtons per-button config, zBar, chronometer, auto buy, profiles, credits, etc.) for consistent, auto-sizing layout. Restore realm gate. README note.
This commit is contained in:
+2
-4
@@ -9,9 +9,9 @@ Resurrecting on Octowow.
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- **Pet Auto-Teach — Growl**: When you tame a new beast, MetaHunt now offers to teach it Growl at the best rank for the pet's level. Click **Yes** and it opens the Beast Training window, teaches the ability and closes the window for you — no manual trip to the pet trainer needed. Toggle it in **Options → General → Pet Auto-Teach** ("Activate Auto-Teach of Growl (Max rank)", on by default) or with `/mth growl on|off`.
|
- **Pet Auto-Teach — Growl**: When you tame a new beast, MetaHunt now offers to teach it Growl at the best rank for the pet's level. Click **Yes** and it opens the Beast Training window, teaches the ability and closes the window automatically.
|
||||||
|
|
||||||
- **Animations**: MetaHunt now plays optional animations that make the interface feel alive. A firework-and-banner celebration bursts on screen when your pet learns a new ability or a new rank, and a red shaking banner warns you when a pet runs away for good. Your pet button flashes when its happiness changes, it gains a loyalty level, or you feed it; the ammo button flashes when Smart Ammo swaps your bullets or auto-equips after a weapon swap; and the MM Widget pulses on a Lock & Load proc. The Great Book slides up and fades in when you open it, gently fades its list when you switch tabs or run a search, fades beast models into view, and fades out when closed; stable slots flash when a pet is deposited, withdrawn or swapped. The options window slides in when opened, fades its tabs as you switch them, and fades out when closed. The minimap button pulses when clicked, minimap markers ping as beasts come into range, collapsible zButton bars fade their buttons in as they expand, the zBar fades in when enabled, and world-map markers fade in when you locate a beast, vendor or master. Everything is optional and off-switchable: a new **Animations** tab (Options → Animations) lets you toggle each effect on its own — or disable them all at once. Powered by the PizzaSauce animation library.
|
- **Animations**: MetaHunt now plays optional animations that make the interface feel alive. Powered by the PizzaSauce library of [Pizzahawaii](https://codeberg.org/Pizzahawaii/) !
|
||||||
|
|
||||||
- **zTrack — Find Fish**: Added new spell Find Fish to the zTrack list of trackings.
|
- **zTrack — Find Fish**: Added new spell Find Fish to the zTrack list of trackings.
|
||||||
|
|
||||||
@@ -19,8 +19,6 @@ Resurrecting on Octowow.
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **zButton bars — expand animation**: Collapsible zButton flyout bars and the zBar now fade in together when they open, instead of stacking their buttons one after another, so expanding them feels smoother.
|
|
||||||
|
|
||||||
- **Complete revamp of SavedVariables**: All your settings now live in one tidy place instead of being scattered around. A migration happens the first time you log in, and you shouldn't lose any settings.
|
- **Complete revamp of SavedVariables**: All your settings now live in one tidy place instead of being scattered around. A migration happens the first time you log in, and you shouldn't lose any settings.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+47
-78
@@ -80,102 +80,71 @@ function MTH_SetupAnimationsOptions()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_ClearContainer(container)
|
local panel = MTH_Layout.Panel(container)
|
||||||
|
panel:Title(MTH_ANIM_L("ANIM_TITLE", "Animations"))
|
||||||
|
panel:Note(MTH_ANIM_L("ANIM_CREDIT",
|
||||||
|
"Animations are powered by PizzaSauce, a WoW 1.12 animation library kindly made and shared by Pizzahawaii. Thank you!"),
|
||||||
|
{ color = MTH_Layout.Theme.colText, lines = 2 })
|
||||||
|
panel:Link("MetaHuntOptionsAnimLink", MTH_ANIM_LINK, function() MTH_ANIM_InsertLink(MTH_ANIM_LINK) end)
|
||||||
|
|
||||||
MTH_ANIM_CTRL = {}
|
MTH_ANIM_CTRL = {}
|
||||||
|
|
||||||
local title = container:CreateFontString("MetaHuntOptionsAnimationsTitle", "ARTWORK", "GameFontNormal")
|
-- Global master toggle (full width, above the columns).
|
||||||
title:SetPoint("TOPLEFT", container, "TOPLEFT", 10, -10)
|
panel:TopCheckbox("MetaHuntOptionsAnimMaster",
|
||||||
title:SetText(MTH_ANIM_L("ANIM_TITLE", "Animations"))
|
MTH_ANIM_L("ANIM_ENABLE_ALL", "Enable animations"), {
|
||||||
title:SetTextColor(1.00, 0.82, 0.00)
|
checked = MTH_FX_AnimationsEnabled,
|
||||||
|
onClick = function()
|
||||||
local credit = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
local cb = getglobal("MetaHuntOptionsAnimMaster")
|
||||||
credit:SetPoint("TOPLEFT", title, "BOTTOMLEFT", 0, -8)
|
MTH_FX_SetAnimationsEnabled(cb:GetChecked())
|
||||||
credit:SetWidth(460)
|
|
||||||
credit:SetJustifyH("LEFT")
|
|
||||||
credit:SetText(MTH_ANIM_L("ANIM_CREDIT",
|
|
||||||
"Animations are powered by PizzaSauce, a WoW 1.12 animation library kindly made and shared by Pizzahawaii. Thank you!"))
|
|
||||||
credit:SetTextColor(0.93, 0.93, 0.93)
|
|
||||||
|
|
||||||
local link = CreateFrame("Button", nil, container)
|
|
||||||
link:SetPoint("TOPLEFT", credit, "BOTTOMLEFT", 0, -4)
|
|
||||||
link:SetHeight(16)
|
|
||||||
link:SetWidth(460)
|
|
||||||
local linkText = link:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
|
|
||||||
linkText:SetPoint("LEFT", link, "LEFT", 0, 0)
|
|
||||||
linkText:SetJustifyH("LEFT")
|
|
||||||
linkText:SetText(MTH_ANIM_LINK)
|
|
||||||
linkText:SetTextColor(0.40, 0.75, 1.00)
|
|
||||||
link:SetScript("OnClick", function() MTH_ANIM_InsertLink(MTH_ANIM_LINK) end)
|
|
||||||
link:SetScript("OnEnter", function() linkText:SetTextColor(0.60, 0.90, 1.00) end)
|
|
||||||
link:SetScript("OnLeave", function() linkText:SetTextColor(0.40, 0.75, 1.00) end)
|
|
||||||
|
|
||||||
-- Global master toggle.
|
|
||||||
local master = MTH_CreateCheckbox(container, "MetaHuntOptionsAnimMaster",
|
|
||||||
MTH_ANIM_L("ANIM_ENABLE_ALL", "Enable animations"), -70)
|
|
||||||
if master then
|
|
||||||
master:SetChecked(MTH_FX_AnimationsEnabled())
|
|
||||||
master:SetScript("OnClick", function()
|
|
||||||
MTH_FX_SetAnimationsEnabled(master:GetChecked())
|
|
||||||
MTH_ANIM_UpdateChildStates()
|
MTH_ANIM_UpdateChildStates()
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
-- Per-animation checkboxes, grouped by section, laid out in two columns.
|
-- Per-animation checkboxes: each section is a self-sizing box, dropped into
|
||||||
-- Each whole section is placed into whichever column is currently shorter
|
-- whichever column currently has the most room so the two stay balanced.
|
||||||
-- (largest remaining Y), so the two columns stay balanced as defs grow.
|
|
||||||
local rowStep = 26
|
|
||||||
local sectionGap = 12
|
|
||||||
local columns = {
|
|
||||||
{ headerX = 15, cbX = 28, y = -104 },
|
|
||||||
{ headerX = 300, cbX = 313, y = -104 },
|
|
||||||
}
|
|
||||||
local s = 1
|
local s = 1
|
||||||
while MTH_FX_ANIM_SECTIONS and s <= table.getn(MTH_FX_ANIM_SECTIONS) do
|
while MTH_FX_ANIM_SECTIONS and s <= table.getn(MTH_FX_ANIM_SECTIONS) do
|
||||||
local sec = MTH_FX_ANIM_SECTIONS[s]
|
local sec = MTH_FX_ANIM_SECTIONS[s]
|
||||||
|
|
||||||
-- Pick the shorter column (the one whose cursor is nearest the top).
|
-- Collect this section's defs in order.
|
||||||
local col = columns[1]
|
local secDefs = {}
|
||||||
if columns[2].y > columns[1].y then
|
|
||||||
col = columns[2]
|
|
||||||
end
|
|
||||||
|
|
||||||
local header = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
|
||||||
header:SetPoint("TOPLEFT", container, "TOPLEFT", col.headerX, col.y)
|
|
||||||
header:SetText(MTH_ANIM_L(sec.titleKey, sec.title))
|
|
||||||
header:SetTextColor(1.00, 0.82, 0.00)
|
|
||||||
col.y = col.y - 22
|
|
||||||
|
|
||||||
local d = 1
|
local d = 1
|
||||||
while MTH_FX_ANIM_DEFS and d <= table.getn(MTH_FX_ANIM_DEFS) do
|
while MTH_FX_ANIM_DEFS and d <= table.getn(MTH_FX_ANIM_DEFS) do
|
||||||
local def = MTH_FX_ANIM_DEFS[d]
|
local def = MTH_FX_ANIM_DEFS[d]
|
||||||
if def.section == sec.id then
|
if def.section == sec.id then
|
||||||
local cbName = "MetaHuntOptionsAnim_" .. string.gsub(def.key, "%.", "_")
|
table.insert(secDefs, def)
|
||||||
local cb = MTH_CreateCheckbox(container, cbName, MTH_ANIM_L(def.labelKey, def.label), col.y, col.cbX)
|
|
||||||
if cb then
|
|
||||||
cb.mthKey = def.key
|
|
||||||
cb:SetChecked(MTH_FX_GetFlag(def.key))
|
|
||||||
cb:SetScript("OnClick", function()
|
|
||||||
MTH_FX_SetFlag(cb.mthKey, cb:GetChecked())
|
|
||||||
end)
|
|
||||||
if def.tooltip and def.tooltip ~= "" then
|
|
||||||
cb.mthTooltip = MTH_ANIM_L(def.tooltipKey, def.tooltip)
|
|
||||||
cb:SetScript("OnEnter", function()
|
|
||||||
GameTooltip:SetOwner(cb, "ANCHOR_RIGHT")
|
|
||||||
GameTooltip:SetText(cb.mthTooltip, 1, 1, 1, 1, true)
|
|
||||||
GameTooltip:Show()
|
|
||||||
end)
|
|
||||||
cb:SetScript("OnLeave", function() GameTooltip:Hide() end)
|
|
||||||
end
|
|
||||||
table.insert(MTH_ANIM_CTRL, cb)
|
|
||||||
col.y = col.y - rowStep
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
d = d + 1
|
d = d + 1
|
||||||
end
|
end
|
||||||
col.y = col.y - sectionGap
|
local count = table.getn(secDefs)
|
||||||
|
|
||||||
|
if count > 0 then
|
||||||
|
local box = panel:Box(panel:ShorterSide(),
|
||||||
|
"MetaHuntOptionsAnimBox_" .. tostring(sec.id),
|
||||||
|
MTH_ANIM_L(sec.titleKey, sec.title))
|
||||||
|
|
||||||
|
local di = 1
|
||||||
|
while di <= count do
|
||||||
|
local def = secDefs[di]
|
||||||
|
local cbName = "MetaHuntOptionsAnim_" .. string.gsub(def.key, "%.", "_")
|
||||||
|
local cb = box:Checkbox(cbName, MTH_ANIM_L(def.labelKey, def.label), {
|
||||||
|
checked = function() return MTH_FX_GetFlag(def.key) end,
|
||||||
|
tooltip = (def.tooltip and def.tooltip ~= "") and MTH_ANIM_L(def.tooltipKey, def.tooltip) or nil,
|
||||||
|
})
|
||||||
|
if cb then
|
||||||
|
cb.mthKey = def.key
|
||||||
|
cb:SetScript("OnClick", function()
|
||||||
|
MTH_FX_SetFlag(cb.mthKey, cb:GetChecked())
|
||||||
|
end)
|
||||||
|
table.insert(MTH_ANIM_CTRL, cb)
|
||||||
|
end
|
||||||
|
di = di + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
s = s + 1
|
s = s + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
panel:Finish()
|
||||||
MTH_ANIM_UpdateChildStates()
|
MTH_ANIM_UpdateChildStates()
|
||||||
MTH_ANIM_DBG.setupResult = "ok"
|
MTH_ANIM_DBG.setupResult = "ok"
|
||||||
end
|
end
|
||||||
|
|||||||
+70
-95
@@ -589,7 +589,9 @@ local function MTH_AB_RefreshOptionsUI()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
|
local function MTH_AB_CreateRow(box, subtype, index)
|
||||||
|
local f, y = box:Row(38)
|
||||||
|
local padX = box:PadX()
|
||||||
local row = {
|
local row = {
|
||||||
subtype = subtype,
|
subtype = subtype,
|
||||||
index = index,
|
index = index,
|
||||||
@@ -597,14 +599,15 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
|
|||||||
}
|
}
|
||||||
local nameBase = "MetaHuntOptionsAutoBuy_" .. subtype .. "_" .. tostring(index)
|
local nameBase = "MetaHuntOptionsAutoBuy_" .. subtype .. "_" .. tostring(index)
|
||||||
|
|
||||||
row.check = MTH_CreateCheckbox(container, nameBase .. "Check", "", yOffset, xBase + MTH_AB_LAYOUT.ROW_CHECK_X)
|
row.check = MTH_CreateCheckbox(f, nameBase .. "Check", "", y, padX)
|
||||||
row.label = container:CreateFontString(nameBase .. "Label", "ARTWORK", "GameFontNormalSmall")
|
row.label = getglobal(nameBase .. "Label") or f:CreateFontString(nameBase .. "Label", "ARTWORK", "GameFontNormalSmall")
|
||||||
row.label:SetPoint("TOPLEFT", container, "TOPLEFT", xBase + MTH_AB_LAYOUT.ROW_CHECK_LABEL_X, yOffset - 5)
|
row.label:ClearAllPoints()
|
||||||
|
row.label:SetPoint("TOPLEFT", f, "TOPLEFT", padX + 27, y - 5)
|
||||||
row.label:SetText("On?")
|
row.label:SetText("On?")
|
||||||
|
|
||||||
row.dropdown = CreateFrame("Frame", nameBase .. "Drop", container, "UIDropDownMenuTemplate")
|
row.dropdown = getglobal(nameBase .. "Drop") or CreateFrame("Frame", nameBase .. "Drop", f, "UIDropDownMenuTemplate")
|
||||||
row.dropdown:ClearAllPoints()
|
row.dropdown:ClearAllPoints()
|
||||||
row.dropdown:SetPoint("TOPLEFT", container, "TOPLEFT", xBase + MTH_AB_LAYOUT.ROW_DROPDOWN_X, yOffset + 3)
|
row.dropdown:SetPoint("TOPLEFT", f, "TOPLEFT", padX + 33, y + 3)
|
||||||
if UIDropDownMenu_SetWidth then
|
if UIDropDownMenu_SetWidth then
|
||||||
UIDropDownMenu_SetWidth(MTH_AB_LAYOUT.ROW_DROPDOWN_WIDTH, row.dropdown)
|
UIDropDownMenu_SetWidth(MTH_AB_LAYOUT.ROW_DROPDOWN_WIDTH, row.dropdown)
|
||||||
end
|
end
|
||||||
@@ -640,7 +643,8 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
row.qty = CreateFrame("EditBox", nameBase .. "Qty", container, "InputBoxTemplate")
|
row.qty = getglobal(nameBase .. "Qty") or CreateFrame("EditBox", nameBase .. "Qty", f, "InputBoxTemplate")
|
||||||
|
row.qty:ClearAllPoints()
|
||||||
local dropButton = getglobal(nameBase .. "DropButton")
|
local dropButton = getglobal(nameBase .. "DropButton")
|
||||||
if dropButton then
|
if dropButton then
|
||||||
row.qty:SetPoint("LEFT", dropButton, "RIGHT", MTH_AB_LAYOUT.ROW_QTY_GAP, -1)
|
row.qty:SetPoint("LEFT", dropButton, "RIGHT", MTH_AB_LAYOUT.ROW_QTY_GAP, -1)
|
||||||
@@ -652,7 +656,8 @@ local function MTH_AB_CreateRow(container, subtype, index, xBase, yOffset)
|
|||||||
row.qty:SetNumeric(true)
|
row.qty:SetNumeric(true)
|
||||||
row.qty:SetAutoFocus(false)
|
row.qty:SetAutoFocus(false)
|
||||||
|
|
||||||
row.suffix = container:CreateFontString(nameBase .. "Suffix", "ARTWORK", "GameFontNormalSmall")
|
row.suffix = getglobal(nameBase .. "Suffix") or f:CreateFontString(nameBase .. "Suffix", "ARTWORK", "GameFontNormalSmall")
|
||||||
|
row.suffix:ClearAllPoints()
|
||||||
row.suffix:SetPoint("LEFT", row.qty, "RIGHT", MTH_AB_LAYOUT.ROW_SUFFIX_GAP, 0)
|
row.suffix:SetPoint("LEFT", row.qty, "RIGHT", MTH_AB_LAYOUT.ROW_SUFFIX_GAP, 0)
|
||||||
row.suffix:SetText("Stacks")
|
row.suffix:SetText("Stacks")
|
||||||
|
|
||||||
@@ -687,32 +692,18 @@ local function MTH_AB_BuildUI(container)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_ClearContainer(container)
|
local panel = MTH_Layout.Panel(container)
|
||||||
MTH_AB_STATE.container = container
|
MTH_AB_STATE.container = container
|
||||||
MTH_AB_STATE.built = true
|
MTH_AB_STATE.built = true
|
||||||
|
|
||||||
local controls = MTH_AB_STATE.controls
|
local controls = MTH_AB_STATE.controls
|
||||||
|
|
||||||
controls.title = container:CreateFontString("MetaHuntOptionsAutoBuyTitle", "ARTWORK", "GameFontHighlight")
|
panel:Title("Auto Buy")
|
||||||
if controls.title then
|
panel:Note("Configure automatic buying rules that trigger when you open a vendor. Quantity is how many STACKS of the item you want in your bags after purchase.",
|
||||||
if controls.title.SetPoint then controls.title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10) end
|
{ lines = 2, color = MTH_Layout.Theme.colText })
|
||||||
if controls.title.SetText then controls.title:SetText("Auto Buy") end
|
|
||||||
end
|
|
||||||
|
|
||||||
controls.body = container:CreateFontString("MetaHuntOptionsAutoBuyBody", "ARTWORK", "GameFontNormalSmall")
|
controls.moduleEnabled = panel:TopCheckbox("MetaHuntOptionsAutoBuyModuleEnabled", "Enable Auto Buy module", {
|
||||||
if controls.body then
|
onClick = function()
|
||||||
if controls.body.SetPoint then controls.body:SetPoint("TOPLEFT", container, "TOPLEFT", 176, -30) end
|
|
||||||
if controls.body.SetWidth then controls.body:SetWidth(400) end
|
|
||||||
if controls.body.SetJustifyH then controls.body:SetJustifyH("LEFT") end
|
|
||||||
if controls.body.SetTextColor then controls.body:SetTextColor(1, 1, 1) end
|
|
||||||
if controls.body.SetText then
|
|
||||||
controls.body:SetText("Configure automatic buying rules that triggers when you open a vendor.\nThe quantity refers to how many STACKS of the item you want to have in your bags after your purchase")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
controls.moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyModuleEnabled", "Enable Auto Buy module", -30)
|
|
||||||
if controls.moduleEnabled then
|
|
||||||
controls.moduleEnabled:SetScript("OnClick", function()
|
|
||||||
if not this or MTH_AB_STATE.syncing then return end
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
local ok, err = MTH:SetModuleEnabled("autobuy", MTH_AB_IsChecked(this))
|
local ok, err = MTH:SetModuleEnabled("autobuy", MTH_AB_IsChecked(this))
|
||||||
@@ -721,70 +712,44 @@ local function MTH_AB_BuildUI(container)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
controls.projectilesEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles", -74)
|
controls.projectilesEnabled = panel:TopCheckbox("MetaHuntOptionsAutoBuyProjectilesEnabled", "Enable for Projectiles (arrows & bullets)", {
|
||||||
if controls.projectilesEnabled then
|
onClick = function()
|
||||||
controls.projectilesEnabled:SetScript("OnClick", function()
|
|
||||||
if not this or MTH_AB_STATE.syncing then return end
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
store.projectiles.enabled = MTH_AB_IsChecked(this)
|
store.projectiles.enabled = MTH_AB_IsChecked(this)
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
controls.sectionArrowTitle = container:CreateFontString("MetaHuntOptionsAutoBuyArrowsTitle", "ARTWORK", "GameFontHighlight")
|
|
||||||
if controls.sectionArrowTitle then
|
|
||||||
if controls.sectionArrowTitle.SetPoint then
|
|
||||||
controls.sectionArrowTitle:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X, MTH_AB_LAYOUT.SECTION_TITLE_Y)
|
|
||||||
end
|
|
||||||
if controls.sectionArrowTitle.SetText then controls.sectionArrowTitle:SetText("Arrows") end
|
|
||||||
end
|
|
||||||
|
|
||||||
controls.sectionBulletTitle = container:CreateFontString("MetaHuntOptionsAutoBuyBulletsTitle", "ARTWORK", "GameFontHighlight")
|
|
||||||
if controls.sectionBulletTitle then
|
|
||||||
if controls.sectionBulletTitle.SetPoint then
|
|
||||||
controls.sectionBulletTitle:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.RIGHT_SECTION_X, MTH_AB_LAYOUT.SECTION_TITLE_Y)
|
|
||||||
end
|
|
||||||
if controls.sectionBulletTitle.SetText then controls.sectionBulletTitle:SetText("Bullets") end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
-- ===== LEFT: Arrows / RIGHT: Bullets (3 rules each) =====
|
||||||
|
local arrowBox = panel:Box("left", "MetaHuntOptionsAutoBuyArrowsBox", "Arrows")
|
||||||
for i = 1, 3 do
|
for i = 1, 3 do
|
||||||
local rowY = MTH_AB_LAYOUT.SECTION_ROWS_Y0 - ((i - 1) * MTH_AB_LAYOUT.ROW_STEP)
|
controls.rows.arrow[i] = MTH_AB_CreateRow(arrowBox, "arrow", i)
|
||||||
controls.rows.arrow[i] = MTH_AB_CreateRow(container, "arrow", i, MTH_AB_LAYOUT.LEFT_SECTION_X, rowY)
|
|
||||||
controls.rows.bullet[i] = MTH_AB_CreateRow(container, "bullet", i, MTH_AB_LAYOUT.RIGHT_SECTION_X, rowY)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
controls.petFoodTitle = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodTitle", "ARTWORK", "GameFontHighlight")
|
local bulletBox = panel:Box("right", "MetaHuntOptionsAutoBuyBulletsBox", "Bullets")
|
||||||
if controls.petFoodTitle then
|
for i = 1, 3 do
|
||||||
controls.petFoodTitle:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X, -300)
|
controls.rows.bullet[i] = MTH_AB_CreateRow(bulletBox, "bullet", i)
|
||||||
controls.petFoodTitle:SetText("Pet Food")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
controls.petFoodEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", -322, MTH_AB_LAYOUT.LEFT_SECTION_X)
|
-- ===== Pet Food =====
|
||||||
if controls.petFoodEnabled then
|
local petBox = panel:Box(panel:ShorterSide(), "MetaHuntOptionsAutoBuyPetFoodBox", "Pet Food")
|
||||||
controls.petFoodEnabled:SetScript("OnClick", function()
|
|
||||||
|
controls.petFoodEnabled = petBox:Checkbox("MetaHuntOptionsAutoBuyPetFoodEnabled", "Enable for Pet Food", {
|
||||||
|
onClick = function()
|
||||||
if not this or MTH_AB_STATE.syncing then return end
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
store.petFood.enabled = MTH_AB_IsChecked(this)
|
store.petFood.enabled = MTH_AB_IsChecked(this)
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
controls.petFoodQtyLabel = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodQtyLabel", "ARTWORK", "GameFontNormalSmall")
|
controls.petFoodQty = petBox:EditRow("MetaHuntOptionsAutoBuyPetFoodQtyLabel", "Quantity:",
|
||||||
if controls.petFoodQtyLabel then
|
"MetaHuntOptionsAutoBuyPetFoodQty", 40, { numeric = true, height = 20 })
|
||||||
controls.petFoodQtyLabel:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X + 28, -350)
|
|
||||||
controls.petFoodQtyLabel:SetText("Quantity :")
|
|
||||||
end
|
|
||||||
|
|
||||||
controls.petFoodQty = CreateFrame("EditBox", "MetaHuntOptionsAutoBuyPetFoodQty", container, "InputBoxTemplate")
|
|
||||||
if controls.petFoodQty then
|
if controls.petFoodQty then
|
||||||
controls.petFoodQty:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X + 95, -347)
|
|
||||||
controls.petFoodQty:SetWidth(40)
|
|
||||||
controls.petFoodQty:SetHeight(20)
|
|
||||||
controls.petFoodQty:SetNumeric(true)
|
|
||||||
controls.petFoodQty:SetAutoFocus(false)
|
|
||||||
controls.petFoodQty:SetScript("OnEnterPressed", function()
|
controls.petFoodQty:SetScript("OnEnterPressed", function()
|
||||||
if not this then return end
|
if not this then return end
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
@@ -798,43 +763,52 @@ local function MTH_AB_BuildUI(container)
|
|||||||
MTH_AB_SetPetFoodStacks(store, this:GetText())
|
MTH_AB_SetPetFoodStacks(store, this:GetText())
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end)
|
||||||
|
local suffix = getglobal("MetaHuntOptionsAutoBuyPetFoodQtySuffix")
|
||||||
|
if not suffix then
|
||||||
|
suffix = petBox:Frame():CreateFontString("MetaHuntOptionsAutoBuyPetFoodQtySuffix", "ARTWORK", "GameFontNormalSmall")
|
||||||
|
end
|
||||||
|
suffix:ClearAllPoints()
|
||||||
|
suffix:SetPoint("LEFT", controls.petFoodQty, "RIGHT", 8, 0)
|
||||||
|
suffix:SetText("stacks")
|
||||||
|
controls.petFoodQtySuffix = suffix
|
||||||
end
|
end
|
||||||
|
|
||||||
controls.petFoodQtySuffix = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodQtySuffix", "ARTWORK", "GameFontNormalSmall")
|
controls.petFoodScopeCurrent = petBox:Checkbox("MetaHuntOptionsAutoBuyPetFoodScopeCurrent", "Buy only for my current pet", {
|
||||||
if controls.petFoodQtySuffix then
|
onClick = function()
|
||||||
controls.petFoodQtySuffix:SetPoint("LEFT", controls.petFoodQty, "RIGHT", 8, 0)
|
|
||||||
controls.petFoodQtySuffix:SetText("stacks")
|
|
||||||
end
|
|
||||||
|
|
||||||
controls.petFoodScopeCurrent = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeCurrent", "Buy only for my current pet", -376, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
|
|
||||||
if controls.petFoodScopeCurrent then
|
|
||||||
controls.petFoodScopeCurrent:SetScript("OnClick", function()
|
|
||||||
if not this or MTH_AB_STATE.syncing then return end
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
store.petFood.scope = "current"
|
store.petFood.scope = "current"
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
controls.petFoodScopeAll = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoBuyPetFoodScopeAll", "Buy for all my pets", -402, MTH_AB_LAYOUT.LEFT_SECTION_X + 28)
|
controls.petFoodScopeAll = petBox:Checkbox("MetaHuntOptionsAutoBuyPetFoodScopeAll", "Buy for all my pets", {
|
||||||
if controls.petFoodScopeAll then
|
onClick = function()
|
||||||
controls.petFoodScopeAll:SetScript("OnClick", function()
|
|
||||||
if not this or MTH_AB_STATE.syncing then return end
|
if not this or MTH_AB_STATE.syncing then return end
|
||||||
local store = MTH_AB_EnsureConfig()
|
local store = MTH_AB_EnsureConfig()
|
||||||
store.petFood.scope = "all"
|
store.petFood.scope = "all"
|
||||||
MTH_AB_RefreshOptionsUI()
|
MTH_AB_RefreshOptionsUI()
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
controls.petFoodPetLines = {}
|
controls.petFoodPetLines = {}
|
||||||
for i = 1, 5 do
|
for i = 1, 5 do
|
||||||
local rowY = -434 - ((i - 1) * 22)
|
local f, y = petBox:Row(22)
|
||||||
local icon = container:CreateTexture("MetaHuntOptionsAutoBuyPetFoodPetIcon" .. tostring(i), "ARTWORK")
|
local padX = petBox:PadX()
|
||||||
|
local icon = getglobal("MetaHuntOptionsAutoBuyPetFoodPetIcon" .. tostring(i))
|
||||||
|
if not icon then
|
||||||
|
icon = f:CreateTexture("MetaHuntOptionsAutoBuyPetFoodPetIcon" .. tostring(i), "ARTWORK")
|
||||||
|
end
|
||||||
icon:SetWidth(16)
|
icon:SetWidth(16)
|
||||||
icon:SetHeight(16)
|
icon:SetHeight(16)
|
||||||
icon:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_AB_LAYOUT.LEFT_SECTION_X + 28, rowY)
|
icon:ClearAllPoints()
|
||||||
|
icon:SetPoint("TOPLEFT", f, "TOPLEFT", padX + 4, y)
|
||||||
icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
|
icon:SetTexture("Interface\\Icons\\INV_Misc_QuestionMark")
|
||||||
local text = container:CreateFontString("MetaHuntOptionsAutoBuyPetFoodPetText" .. tostring(i), "ARTWORK", "GameFontNormalSmall")
|
local text = getglobal("MetaHuntOptionsAutoBuyPetFoodPetText" .. tostring(i))
|
||||||
|
if not text then
|
||||||
|
text = f:CreateFontString("MetaHuntOptionsAutoBuyPetFoodPetText" .. tostring(i), "ARTWORK", "GameFontNormalSmall")
|
||||||
|
end
|
||||||
|
text:ClearAllPoints()
|
||||||
text:SetPoint("LEFT", icon, "RIGHT", 6, 0)
|
text:SetPoint("LEFT", icon, "RIGHT", 6, 0)
|
||||||
text:SetJustifyH("LEFT")
|
text:SetJustifyH("LEFT")
|
||||||
text:SetTextColor(1, 1, 1)
|
text:SetTextColor(1, 1, 1)
|
||||||
@@ -842,6 +816,7 @@ local function MTH_AB_BuildUI(container)
|
|||||||
controls.petFoodPetLines[i] = { icon = icon, text = text }
|
controls.petFoodPetLines[i] = { icon = icon, text = text }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
panel:Finish()
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_SetupAutoBuyOptions()
|
function MTH_SetupAutoBuyOptions()
|
||||||
|
|||||||
+68
-152
@@ -48,19 +48,10 @@ function MTH_SetupAutoQuestOptions()
|
|||||||
local container = MTH_GetFrame("MetaHuntOptionsAutoQuest")
|
local container = MTH_GetFrame("MetaHuntOptionsAutoQuest")
|
||||||
if not container then return end
|
if not container then return end
|
||||||
|
|
||||||
MTH_ClearContainer(container)
|
local store = MTH_AQ_EnsureStore()
|
||||||
|
if store.scorpokTooltip == nil then
|
||||||
local title = container:CreateFontString("MetaHuntOptionsAutoQuestTitle", "ARTWORK", "GameFontHighlight")
|
store.scorpokTooltip = false
|
||||||
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
|
end
|
||||||
title:SetText("Auto Quest")
|
|
||||||
|
|
||||||
local body = container:CreateFontString("MetaHuntOptionsAutoQuestBody", "ARTWORK", "GameFontNormalSmall")
|
|
||||||
body:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -30)
|
|
||||||
body:SetWidth(560)
|
|
||||||
body:SetJustifyH("LEFT")
|
|
||||||
body:SetJustifyV("TOP")
|
|
||||||
body:SetTextColor(0.45, 0.75, 1)
|
|
||||||
body:SetText("Automation for specific quest interactions.")
|
|
||||||
|
|
||||||
local moduleEnabled = true
|
local moduleEnabled = true
|
||||||
if MTH and MTH.GetModule then
|
if MTH and MTH.GetModule then
|
||||||
@@ -73,10 +64,14 @@ function MTH_SetupAutoQuestOptions()
|
|||||||
elseif MTH and MTH.IsModuleEnabled then
|
elseif MTH and MTH.IsModuleEnabled then
|
||||||
moduleEnabled = MTH:IsModuleEnabled("autoquest", false) and true or false
|
moduleEnabled = MTH:IsModuleEnabled("autoquest", false) and true or false
|
||||||
end
|
end
|
||||||
local moduleToggle = MTH_CreateCheckbox(container, "MetaHuntOptionsAutoQuestModuleToggle", "Enable Auto Quest module", -70, 20)
|
|
||||||
if moduleToggle then
|
local panel = MTH_Layout.Panel(container)
|
||||||
moduleToggle:SetChecked(moduleEnabled and true or false)
|
panel:Title("Auto Quest")
|
||||||
moduleToggle:SetScript("OnClick", function()
|
panel:Note("Automation for specific quest interactions.")
|
||||||
|
|
||||||
|
panel:TopCheckbox("MetaHuntOptionsAutoQuestModuleToggle", "Enable Auto Quest module", {
|
||||||
|
checked = moduleEnabled,
|
||||||
|
onClick = function()
|
||||||
if not this then return end
|
if not this then return end
|
||||||
local enabled = MTH_AQ_IsChecked(this)
|
local enabled = MTH_AQ_IsChecked(this)
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
@@ -88,145 +83,66 @@ function MTH_SetupAutoQuestOptions()
|
|||||||
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest") or nil
|
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest") or nil
|
||||||
local actual = (type(module) == "table" and module.enabled ~= nil) and (module.enabled and true or false) or enabled
|
local actual = (type(module) == "table" and module.enabled ~= nil) and (module.enabled and true or false) or enabled
|
||||||
this:SetChecked(actual and true or false)
|
this:SetChecked(actual and true or false)
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
local store = MTH_AQ_EnsureStore()
|
-- Salt of the Scorpok (left column)
|
||||||
if store.scorpokTooltip == nil then
|
local scorpok = panel:Box("left", "MetaHuntAutoQuestScorpokBox", "Salt of the Scorpok")
|
||||||
store.scorpokTooltip = false
|
scorpok:Checkbox("MetaHuntOptionsAutoQuestScorpokToggle",
|
||||||
end
|
"Enable SHIFT-rightclick for Bloodmage Drazial", {
|
||||||
|
checked = store.scorpokDrazial and true or false,
|
||||||
local sectionWidth = (container:GetWidth() or 600) - 40
|
onClick = function()
|
||||||
if sectionWidth < 360 then
|
local enabled = MTH_AQ_IsChecked(this)
|
||||||
sectionWidth = 360
|
store.scorpokDrazial = enabled and true or false
|
||||||
end
|
if MTH and MTH.GetModuleCharSavedVariables then
|
||||||
|
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
||||||
local function ensureSection(name, sectionTitle, yOffset, height)
|
if type(moduleStore) == "table" then
|
||||||
local section = getglobal(name)
|
moduleStore.scorpokDrazial = store.scorpokDrazial and true or false
|
||||||
if not section then
|
|
||||||
section = CreateFrame("Frame", name, container, "OptionFrameBoxTemplate")
|
|
||||||
end
|
|
||||||
if not section then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
section:SetParent(container)
|
|
||||||
section:ClearAllPoints()
|
|
||||||
section:SetPoint("TOPLEFT", container, "TOPLEFT", 20, yOffset)
|
|
||||||
section:SetWidth(sectionWidth)
|
|
||||||
section:SetHeight(height)
|
|
||||||
section:Show()
|
|
||||||
|
|
||||||
local titleFrame = getglobal(name .. "Title")
|
|
||||||
if titleFrame then
|
|
||||||
titleFrame:SetText(sectionTitle)
|
|
||||||
end
|
|
||||||
return section
|
|
||||||
end
|
|
||||||
|
|
||||||
local function ensureCheckbox(section, name, label, yOffset, checked)
|
|
||||||
local check = getglobal(name)
|
|
||||||
if not check then
|
|
||||||
check = CreateFrame("CheckButton", name, section, "OptionsCheckButtonTemplate")
|
|
||||||
end
|
|
||||||
if not check then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
check:SetParent(section)
|
|
||||||
check:ClearAllPoints()
|
|
||||||
check:SetPoint("TOPLEFT", section, "TOPLEFT", 12, yOffset)
|
|
||||||
check:SetChecked(checked and true or false)
|
|
||||||
check:Show()
|
|
||||||
|
|
||||||
local text = getglobal(name .. "Text")
|
|
||||||
if text then
|
|
||||||
text:SetText(label)
|
|
||||||
end
|
|
||||||
return check
|
|
||||||
end
|
|
||||||
|
|
||||||
local scorpokSection = ensureSection("MetaHuntAutoQuestScorpokBox", "Salt of the Scorpok", -130, 112)
|
|
||||||
if scorpokSection then
|
|
||||||
local scorpokToggle = ensureCheckbox(
|
|
||||||
scorpokSection,
|
|
||||||
"MetaHuntOptionsAutoQuestScorpokToggle",
|
|
||||||
"Enable SHIFT-rightclick for Bloodmage Drazial",
|
|
||||||
-10,
|
|
||||||
store.scorpokDrazial and true or false
|
|
||||||
)
|
|
||||||
if scorpokToggle then
|
|
||||||
scorpokToggle:SetScript("OnClick", function()
|
|
||||||
local enabled = MTH_AQ_IsChecked(this)
|
|
||||||
store.scorpokDrazial = enabled and true or false
|
|
||||||
if MTH and MTH.GetModuleCharSavedVariables then
|
|
||||||
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
|
||||||
if type(moduleStore) == "table" then
|
|
||||||
moduleStore.scorpokDrazial = store.scorpokDrazial and true or false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
|
end
|
||||||
if module and module.SetScorpokDrazialEnabled then
|
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
|
||||||
module:SetScorpokDrazialEnabled(enabled)
|
if module and module.SetScorpokDrazialEnabled then
|
||||||
|
module:SetScorpokDrazialEnabled(enabled)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
scorpok:Checkbox("MetaHuntOptionsAutoQuestScorpokTooltipToggle",
|
||||||
|
"Enhance Tooltip on Drazial and related beasts (requires Tooltips module enabled)", {
|
||||||
|
checked = store.scorpokTooltip and true or false,
|
||||||
|
onClick = function()
|
||||||
|
local enabled = MTH_AQ_IsChecked(this)
|
||||||
|
store.scorpokTooltip = enabled and true or false
|
||||||
|
if MTH and MTH.GetModuleCharSavedVariables then
|
||||||
|
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
||||||
|
if type(moduleStore) == "table" then
|
||||||
|
moduleStore.scorpokTooltip = store.scorpokTooltip and true or false
|
||||||
end
|
end
|
||||||
end)
|
end
|
||||||
end
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
local tooltipToggle = ensureCheckbox(
|
-- Arrows Are For Sissies (right column)
|
||||||
scorpokSection,
|
local sissies = panel:Box("right", "MetaHuntAutoQuestSissiesBox", "Arrows Are For Sissies")
|
||||||
"MetaHuntOptionsAutoQuestScorpokTooltipToggle",
|
sissies:Note("MetaHuntOptionsAutoQuestSissiesNote",
|
||||||
"Enhance Tooltip on Drazial and related beasts (requires Tooltips module enabled)",
|
"Note that you should not activate this if you are using LazyPig", { lines = 2 })
|
||||||
-42,
|
sissies:Checkbox("MetaHuntOptionsAutoQuestSissiesToggle",
|
||||||
store.scorpokTooltip and true or false
|
"Enable SHIFT-rightclick for Artilleryman Sheldonore", {
|
||||||
)
|
checked = store.arrowsForSissies and true or false,
|
||||||
if tooltipToggle then
|
onClick = function()
|
||||||
tooltipToggle:SetScript("OnClick", function()
|
local enabled = MTH_AQ_IsChecked(this)
|
||||||
local enabled = MTH_AQ_IsChecked(this)
|
store.arrowsForSissies = enabled and true or false
|
||||||
store.scorpokTooltip = enabled and true or false
|
if MTH and MTH.GetModuleCharSavedVariables then
|
||||||
if MTH and MTH.GetModuleCharSavedVariables then
|
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
||||||
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
if type(moduleStore) == "table" then
|
||||||
if type(moduleStore) == "table" then
|
moduleStore.arrowsForSissies = store.arrowsForSissies and true or false
|
||||||
moduleStore.scorpokTooltip = store.scorpokTooltip and true or false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
end
|
||||||
end
|
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
|
||||||
end
|
if module and module.SetArrowsForSissiesEnabled then
|
||||||
|
module:SetArrowsForSissiesEnabled(enabled)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
local sissiesSection = ensureSection("MetaHuntAutoQuestSissiesBox", "Arrows Are For Sissies", -255, 108)
|
panel:Finish()
|
||||||
if sissiesSection then
|
|
||||||
local sissiesNote = getglobal("MetaHuntOptionsAutoQuestSissiesNote")
|
|
||||||
if not sissiesNote then
|
|
||||||
sissiesNote = sissiesSection:CreateFontString("MetaHuntOptionsAutoQuestSissiesNote", "ARTWORK", "GameFontNormalSmall")
|
|
||||||
end
|
|
||||||
sissiesNote:ClearAllPoints()
|
|
||||||
sissiesNote:SetPoint("TOPLEFT", sissiesSection, "TOPLEFT", 14, -10)
|
|
||||||
sissiesNote:SetWidth(sectionWidth - 28)
|
|
||||||
sissiesNote:SetJustifyH("LEFT")
|
|
||||||
sissiesNote:SetTextColor(0.45, 0.75, 1)
|
|
||||||
sissiesNote:SetText("Note that you should not activate this if you are using LazyPig")
|
|
||||||
sissiesNote:Show()
|
|
||||||
|
|
||||||
local sissiesToggle = ensureCheckbox(
|
|
||||||
sissiesSection,
|
|
||||||
"MetaHuntOptionsAutoQuestSissiesToggle",
|
|
||||||
"Enable SHIFT-rightclick for Artilleryman Sheldonore",
|
|
||||||
-40,
|
|
||||||
store.arrowsForSissies and true or false
|
|
||||||
)
|
|
||||||
if sissiesToggle then
|
|
||||||
sissiesToggle:SetScript("OnClick", function()
|
|
||||||
local enabled = MTH_AQ_IsChecked(this)
|
|
||||||
store.arrowsForSissies = enabled and true or false
|
|
||||||
if MTH and MTH.GetModuleCharSavedVariables then
|
|
||||||
local moduleStore = MTH:GetModuleCharSavedVariables("autoquest")
|
|
||||||
if type(moduleStore) == "table" then
|
|
||||||
moduleStore.arrowsForSissies = store.arrowsForSissies and true or false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local module = MTH and MTH.GetModule and MTH:GetModule("autoquest")
|
|
||||||
if module and module.SetArrowsForSissiesEnabled then
|
|
||||||
module:SetArrowsForSissiesEnabled(enabled)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
+137
-176
@@ -358,25 +358,14 @@ local function MTH_CHRON_NormalizeSection(tabKey)
|
|||||||
return "general"
|
return "general"
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bucket, opts)
|
local function MTH_CHRON_RenderTimerBox(box, profile, items, bucket, prefix)
|
||||||
opts = opts or {}
|
prefix = tostring(prefix or "Main")
|
||||||
local timerX = opts.x or 20
|
|
||||||
local timerY = opts.y or -84
|
|
||||||
local prefix = tostring(opts.prefix or "Main")
|
|
||||||
|
|
||||||
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerTimersHeader" .. prefix, title, timerX, timerY)
|
|
||||||
timerY = timerY - 24
|
|
||||||
|
|
||||||
if table.getn(items) == 0 then
|
if table.getn(items) == 0 then
|
||||||
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerSectionEmpty" .. prefix, "(none)", timerX + 8, timerY)
|
box:Text("MetaHuntOptionsChronometerSectionEmpty" .. prefix, "(none)")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, table.getn(items) do
|
for i = 1, table.getn(items) do
|
||||||
if timerY < -560 then
|
|
||||||
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerOverflow" .. prefix, "...more", timerX + 8, timerY)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
local row = items[i]
|
local row = items[i]
|
||||||
local timerName = row
|
local timerName = row
|
||||||
local label = row
|
local label = row
|
||||||
@@ -387,11 +376,9 @@ local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bu
|
|||||||
timerName = tostring(timerName or "")
|
timerName = tostring(timerName or "")
|
||||||
label = tostring(label or timerName)
|
label = tostring(label or timerName)
|
||||||
local controlName = "MetaHuntOptionsChronometerTimer" .. prefix .. tostring(bucket) .. tostring(i)
|
local controlName = "MetaHuntOptionsChronometerTimer" .. prefix .. tostring(bucket) .. tostring(i)
|
||||||
local check = MTH_CreateCheckbox(container, controlName, label, timerY, timerX)
|
box:Checkbox(controlName, label, {
|
||||||
if check then
|
checked = profile.disabledSpells[bucket][timerName] == nil,
|
||||||
check:SetChecked(profile.disabledSpells[bucket][timerName] == nil and true or false)
|
onClick = function()
|
||||||
check:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
local currentlyDisabled = profile.disabledSpells[bucket][timerName] ~= nil
|
local currentlyDisabled = profile.disabledSpells[bucket][timerName] ~= nil
|
||||||
if currentlyDisabled then
|
if currentlyDisabled then
|
||||||
profile.disabledSpells[bucket][timerName] = nil
|
profile.disabledSpells[bucket][timerName] = nil
|
||||||
@@ -402,9 +389,8 @@ local function MTH_CHRON_RenderTimerSection(container, profile, title, items, bu
|
|||||||
end
|
end
|
||||||
|
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
timerY = timerY - 20
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -461,210 +447,185 @@ function MTH_SetupChronometerOptions(tabKey)
|
|||||||
local container = MTH_GetFrame("MetaHuntOptionsChronometer")
|
local container = MTH_GetFrame("MetaHuntOptionsChronometer")
|
||||||
if not container then return end
|
if not container then return end
|
||||||
|
|
||||||
MTH_ClearContainer(container)
|
|
||||||
MTH_CHRON_STATE.controls = {}
|
MTH_CHRON_STATE.controls = {}
|
||||||
|
|
||||||
local profile = MTH_CHRON_GetProfile()
|
local profile = MTH_CHRON_GetProfile()
|
||||||
local _, class = UnitClass("player")
|
local _, class = UnitClass("player")
|
||||||
class = class or "HUNTER"
|
class = class or "HUNTER"
|
||||||
|
|
||||||
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerTitle", "Chronometer", 20, -10)
|
local panel = MTH_Layout.Panel(container)
|
||||||
|
panel:Title("Chronometer")
|
||||||
|
|
||||||
local moduleCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerEnabled", "Enable Chronometer module", -54)
|
local moduleEnabled = false
|
||||||
if moduleCheck then
|
do
|
||||||
local module = MTH and MTH:GetModule("chronometer")
|
local module = MTH and MTH:GetModule("chronometer")
|
||||||
moduleCheck:SetChecked(module and module.enabled and true or false)
|
moduleEnabled = module and module.enabled and true or false
|
||||||
moduleCheck:SetScript("OnClick", function()
|
end
|
||||||
if not this then return end
|
panel:TopCheckbox("MetaHuntOptionsChronometerEnabled", "Enable Chronometer module", {
|
||||||
local enabled = MTH_CHRON_IsChecked(this)
|
checked = moduleEnabled,
|
||||||
|
onClick = function()
|
||||||
|
local enabled = this:GetChecked() == 1
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
MTH:SetModuleEnabled("chronometer", enabled)
|
MTH:SetModuleEnabled("chronometer", enabled)
|
||||||
end
|
end
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
if section == "general" then
|
if section == "general" then
|
||||||
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerGeneralHeader", "General", 20, -84)
|
local genBox = panel:Box("left", "MetaHuntOptionsChronometerGeneralBox", "General")
|
||||||
|
genBox:Slider("MetaHuntOptionsChronometerGhost", {
|
||||||
local ghostSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerGhost", "Ghost Duration", 0, 30, 1, -112)
|
label = "Ghost Duration", min = 0, max = 30, step = 1,
|
||||||
if ghostSlider then
|
value = tonumber(profile.ghost) or 0,
|
||||||
ghostSlider:SetValue(tonumber(profile.ghost) or 0)
|
onChange = function(value)
|
||||||
ghostSlider.onChange = function(value)
|
|
||||||
profile.ghost = tonumber(value) or 0
|
profile.ghost = tonumber(value) or 0
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end
|
end,
|
||||||
end
|
})
|
||||||
|
genBox:Checkbox("MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", {
|
||||||
local killCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnKill", "Fade on kill", -154)
|
checked = profile.fadeonkill and true or false,
|
||||||
if killCheck then
|
onClick = function() profile.fadeonkill = this:GetChecked() == 1 end,
|
||||||
killCheck:SetChecked(profile.fadeonkill and true or false)
|
})
|
||||||
killCheck:SetScript("OnClick", function()
|
genBox:Checkbox("MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", {
|
||||||
if not this then return end
|
checked = profile.fadeonfade and true or false,
|
||||||
profile.fadeonkill = MTH_CHRON_IsChecked(this)
|
onClick = function() profile.fadeonfade = this:GetChecked() == 1 end,
|
||||||
end)
|
})
|
||||||
end
|
genBox:Checkbox("MetaHuntOptionsChronometerSelfBars", "Show self bars", {
|
||||||
|
checked = profile.selfbars and true or false,
|
||||||
local fadeCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerFadeOnFade", "Fade on aura fade", -179)
|
onClick = function() profile.selfbars = this:GetChecked() == 1 end,
|
||||||
if fadeCheck then
|
})
|
||||||
fadeCheck:SetChecked(profile.fadeonfade and true or false)
|
genBox:Checkbox("MetaHuntOptionsChronometerOnlySelf", "Only self target", {
|
||||||
fadeCheck:SetScript("OnClick", function()
|
checked = profile.onlyself and true or false,
|
||||||
if not this then return end
|
onClick = function() profile.onlyself = this:GetChecked() == 1 end,
|
||||||
profile.fadeonfade = MTH_CHRON_IsChecked(this)
|
})
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local selfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerSelfBars", "Show self bars", -204)
|
|
||||||
if selfCheck then
|
|
||||||
selfCheck:SetChecked(profile.selfbars and true or false)
|
|
||||||
selfCheck:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
profile.selfbars = MTH_CHRON_IsChecked(this)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
local onlySelfCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerOnlySelf", "Only self target", -229)
|
|
||||||
if onlySelfCheck then
|
|
||||||
onlySelfCheck:SetChecked(profile.onlyself and true or false)
|
|
||||||
onlySelfCheck:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
profile.onlyself = MTH_CHRON_IsChecked(this)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
elseif section == "bar" then
|
elseif section == "bar" then
|
||||||
MTH_CHRON_MakeTitle(container, "MetaHuntOptionsChronometerBarHeader", "Bars", 20, -84)
|
local ctrlBox = panel:Box("left", "MetaHuntOptionsChronometerControlsBox", "Controls")
|
||||||
|
ctrlBox:Buttons({
|
||||||
local runTestButton = MTH_CreateActionButton(container, "MetaHuntOptionsChronometerRunTest", "Run Test", 20, -112, 130, 22, function()
|
{ name = "MetaHuntOptionsChronometerRunTest", label = "Run Test", width = 120,
|
||||||
local engine = MTH_ChronometerHunter
|
onClick = function()
|
||||||
if engine and engine.RunTest then
|
local engine = MTH_ChronometerHunter
|
||||||
engine:RunTest()
|
if engine and engine.RunTest then engine:RunTest() end
|
||||||
end
|
end },
|
||||||
end)
|
{ name = "MetaHuntOptionsChronometerAnchor", label = "Toggle Anchor", width = 120,
|
||||||
local anchorButton = MTH_CreateActionButton(container, "MetaHuntOptionsChronometerAnchor", "Toggle Anchor", 165, -112, 130, 22, function()
|
onClick = function()
|
||||||
local engine = MTH_ChronometerHunter
|
local engine = MTH_ChronometerHunter
|
||||||
if engine and engine.ToggleAnchor then
|
if engine and engine.ToggleAnchor then engine:ToggleAnchor() end
|
||||||
engine:ToggleAnchor()
|
end },
|
||||||
end
|
})
|
||||||
end)
|
|
||||||
if runTestButton then runTestButton:Show() end
|
|
||||||
if anchorButton then anchorButton:Show() end
|
|
||||||
|
|
||||||
local anchorX = tonumber(profile.barposition and profile.barposition.x) or 0
|
local anchorX = tonumber(profile.barposition and profile.barposition.x) or 0
|
||||||
local anchorY = tonumber(profile.barposition and profile.barposition.y) or 0
|
local anchorY = tonumber(profile.barposition and profile.barposition.y) or 0
|
||||||
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerAnchorPos", "Anchor: X " .. tostring(anchorX) .. " Y " .. tostring(anchorY), 20, -142)
|
ctrlBox:Note("MetaHuntOptionsChronometerAnchorPos",
|
||||||
|
"Anchor: X " .. tostring(anchorX) .. " Y " .. tostring(anchorY))
|
||||||
|
|
||||||
local widthSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarWidth", "Bar Width", 80, 320, 1, -180)
|
local dimBox = panel:Box("left", "MetaHuntOptionsChronometerDimBox", "Dimensions")
|
||||||
if widthSlider then
|
dimBox:Slider("MetaHuntOptionsChronometerBarWidth", {
|
||||||
widthSlider:SetValue(tonumber(profile.barwidth) or 220)
|
label = "Bar Width", min = 80, max = 320, step = 1,
|
||||||
widthSlider.onChange = function(value)
|
value = tonumber(profile.barwidth) or 220,
|
||||||
|
onChange = function(value)
|
||||||
profile.barwidth = tonumber(value) or 220
|
profile.barwidth = tonumber(value) or 220
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end
|
end,
|
||||||
end
|
})
|
||||||
|
dimBox:Slider("MetaHuntOptionsChronometerBarScale", {
|
||||||
local scaleSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarScale", "Bar Scale", 0.5, 1.5, 0.1, -222)
|
label = "Bar Scale", min = 0.5, max = 1.5, step = 0.1,
|
||||||
if scaleSlider then
|
value = tonumber(profile.barscale) or 1,
|
||||||
scaleSlider:SetValue(tonumber(profile.barscale) or 1)
|
format = function(v) return string.format("%.1f", v) end,
|
||||||
scaleSlider.onChange = function(value)
|
onChange = function(value)
|
||||||
profile.barscale = tonumber(value) or 1
|
profile.barscale = tonumber(value) or 1
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end
|
end,
|
||||||
end
|
})
|
||||||
|
dimBox:Slider("MetaHuntOptionsChronometerBarHeight", {
|
||||||
local heightSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarHeight", "Bar Height", 8, 30, 1, -264)
|
label = "Bar Height", min = 8, max = 30, step = 1,
|
||||||
if heightSlider then
|
value = tonumber(profile.barheight) or 16,
|
||||||
heightSlider:SetValue(tonumber(profile.barheight) or 16)
|
onChange = function(value)
|
||||||
heightSlider.onChange = function(value)
|
|
||||||
profile.barheight = tonumber(value) or 16
|
profile.barheight = tonumber(value) or 16
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end
|
end,
|
||||||
end
|
})
|
||||||
|
dimBox:Slider("MetaHuntOptionsChronometerBarSpacing", {
|
||||||
local spacingSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerBarSpacing", "Bar Spacing", 0, 15, 1, -306)
|
label = "Bar Spacing", min = 0, max = 15, step = 1,
|
||||||
if spacingSlider then
|
value = tonumber(profile.spacing) or 0,
|
||||||
spacingSlider:SetValue(tonumber(profile.spacing) or 0)
|
onChange = function(value)
|
||||||
spacingSlider.onChange = function(value)
|
|
||||||
profile.spacing = tonumber(value) or 0
|
profile.spacing = tonumber(value) or 0
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end
|
end,
|
||||||
end
|
})
|
||||||
|
dimBox:Slider("MetaHuntOptionsChronometerTextSize", {
|
||||||
local textSizeSlider = MTH_CreateSlider(container, "MetaHuntOptionsChronometerTextSize", "Text Size", 8, 20, 1, -348)
|
label = "Text Size", min = 8, max = 20, step = 1,
|
||||||
if textSizeSlider then
|
value = tonumber(profile.textsize) or 10,
|
||||||
textSizeSlider:SetValue(tonumber(profile.textsize) or 10)
|
onChange = function(value)
|
||||||
textSizeSlider.onChange = function(value)
|
|
||||||
profile.textsize = tonumber(value) or 10
|
profile.textsize = tonumber(value) or 10
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerTextPatternLabel", "Bar Text ($s spell, $t target)", 20, -390)
|
local textBox = panel:Box("right", "MetaHuntOptionsChronometerTextBox", "Text & Growth")
|
||||||
MTH_CHRON_MakeInput(container, "MetaHuntOptionsChronometerTextPattern", 20, -408, 220, 20, profile.text or "$t", function(newText)
|
textBox:Note("MetaHuntOptionsChronometerTextPatternHint",
|
||||||
if not newText or newText == "" then
|
"Bar text tokens: $s = spell, $t = target", { lines = 2 })
|
||||||
newText = "$t"
|
local patternEdit = textBox:EditRow("MetaHuntOptionsChronometerTextPatternLabel", "Bar Text",
|
||||||
end
|
"MetaHuntOptionsChronometerTextPattern", 150, { height = 20 })
|
||||||
profile.text = tostring(newText)
|
if patternEdit then
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
patternEdit:SetText(tostring(profile.text or "$t"))
|
||||||
end)
|
patternEdit:SetScript("OnEnterPressed", function()
|
||||||
|
local newText = this:GetText() or ""
|
||||||
local growCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerGrowUp", "Grow bars upward", -438)
|
if newText == "" then newText = "$t" end
|
||||||
if growCheck then
|
profile.text = tostring(newText)
|
||||||
growCheck:SetChecked(profile.growup and true or false)
|
|
||||||
growCheck:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
profile.growup = MTH_CHRON_IsChecked(this)
|
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
|
this:ClearFocus()
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
textBox:Checkbox("MetaHuntOptionsChronometerGrowUp", "Grow bars upward", {
|
||||||
local reverseCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerReverse", "Reverse bars", -463)
|
checked = profile.growup and true or false,
|
||||||
if reverseCheck then
|
onClick = function()
|
||||||
reverseCheck:SetChecked(profile.reverse and true or false)
|
profile.growup = this:GetChecked() == 1
|
||||||
reverseCheck:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
profile.reverse = MTH_CHRON_IsChecked(this)
|
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
textBox:Checkbox("MetaHuntOptionsChronometerReverse", "Reverse bars", {
|
||||||
|
checked = profile.reverse and true or false,
|
||||||
|
onClick = function()
|
||||||
|
profile.reverse = this:GetChecked() == 1
|
||||||
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
MTH_CHRON_MakeSmall(container, "MetaHuntOptionsChronometerIconPosLabel", "Icon Position", 20, -494)
|
local iconBox = panel:Box("right", "MetaHuntOptionsChronometerIconBox", "Icon Position")
|
||||||
local iconLeft = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerIconLeft", "Left", -514)
|
local iconLeft, iconRight
|
||||||
local iconRight = MTH_CreateCheckbox(container, "MetaHuntOptionsChronometerIconRight", "Right", -538)
|
iconLeft = iconBox:Checkbox("MetaHuntOptionsChronometerIconLeft", "Left", {
|
||||||
if iconLeft and iconRight then
|
checked = profile.iconposition ~= "RIGHT",
|
||||||
iconLeft:SetChecked(profile.iconposition ~= "RIGHT")
|
onClick = function()
|
||||||
iconRight:SetChecked(profile.iconposition == "RIGHT")
|
|
||||||
iconLeft:SetScript("OnClick", function()
|
|
||||||
profile.iconposition = "LEFT"
|
profile.iconposition = "LEFT"
|
||||||
iconLeft:SetChecked(true)
|
iconLeft:SetChecked(true)
|
||||||
iconRight:SetChecked(nil)
|
iconRight:SetChecked(nil)
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end)
|
end,
|
||||||
iconRight:SetScript("OnClick", function()
|
})
|
||||||
|
iconRight = iconBox:Checkbox("MetaHuntOptionsChronometerIconRight", "Right", {
|
||||||
|
checked = profile.iconposition == "RIGHT",
|
||||||
|
onClick = function()
|
||||||
profile.iconposition = "RIGHT"
|
profile.iconposition = "RIGHT"
|
||||||
iconRight:SetChecked(true)
|
iconRight:SetChecked(true)
|
||||||
iconLeft:SetChecked(nil)
|
iconLeft:SetChecked(nil)
|
||||||
MTH_CHRON_ApplyLiveProfile(profile)
|
MTH_CHRON_ApplyLiveProfile(profile)
|
||||||
end)
|
end,
|
||||||
end
|
})
|
||||||
|
|
||||||
else
|
else
|
||||||
local classSpells, classEvents, racial = MTH_CHRON_BuildTimerLists()
|
local classSpells, classEvents, racial = MTH_CHRON_BuildTimerLists()
|
||||||
if section == "classspells" then
|
if section == "classspells" then
|
||||||
MTH_CHRON_RenderTimerSection(container, profile, "Hunter Spells", classSpells, class, {
|
local spellsBox = panel:Box("left", "MetaHuntOptionsChronometerSpellsBox", "Hunter Spells")
|
||||||
x = 20,
|
MTH_CHRON_RenderTimerBox(spellsBox, profile, classSpells, class, "ClassSpells")
|
||||||
y = -84,
|
local trinketBox = panel:Box("right", "MetaHuntOptionsChronometerTrinketsBox", "Hunter Trinkets")
|
||||||
prefix = "ClassSpells",
|
MTH_CHRON_RenderTimerBox(trinketBox, profile, MTH_CHRON_BuildHunterTrinketItems(classEvents), class, "ClassTrinkets")
|
||||||
})
|
|
||||||
MTH_CHRON_RenderTimerSection(container, profile, "Hunter Trinkets", MTH_CHRON_BuildHunterTrinketItems(classEvents), class, {
|
|
||||||
x = 300,
|
|
||||||
y = -84,
|
|
||||||
prefix = "ClassTrinkets",
|
|
||||||
})
|
|
||||||
elseif section == "classevents" then
|
elseif section == "classevents" then
|
||||||
MTH_CHRON_RenderTimerSection(container, profile, "Hunter Events", classEvents, class, { prefix = "ClassEvents" })
|
local eventsBox = panel:Box("left", "MetaHuntOptionsChronometerEventsBox", "Hunter Events")
|
||||||
|
MTH_CHRON_RenderTimerBox(eventsBox, profile, classEvents, class, "ClassEvents")
|
||||||
elseif section == "racial" then
|
elseif section == "racial" then
|
||||||
MTH_CHRON_RenderTimerSection(container, profile, "Racial", racial, "RACIAL", { prefix = "Racial" })
|
local racialBox = panel:Box("left", "MetaHuntOptionsChronometerRacialBox", "Racial")
|
||||||
|
MTH_CHRON_RenderTimerBox(racialBox, profile, racial, "RACIAL", "Racial")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
panel:Finish()
|
||||||
end
|
end
|
||||||
|
|
||||||
if _G then
|
if _G then
|
||||||
|
|||||||
@@ -96,12 +96,8 @@ function MTH_SetupCreditsOptions()
|
|||||||
local container = MTH_GetFrame("MetaHuntOptionsCredits")
|
local container = MTH_GetFrame("MetaHuntOptionsCredits")
|
||||||
if not container then return end
|
if not container then return end
|
||||||
|
|
||||||
MTH_ClearContainer(container)
|
local panel = MTH_Layout.Panel(container)
|
||||||
|
local title = panel:Title(MTH_CR_L("CREDITS_TITLE", "Credits"))
|
||||||
local title = container:CreateFontString("MetaHuntOptionsCreditsTitle", "ARTWORK", "GameFontNormal")
|
|
||||||
title:SetPoint("TOPLEFT", container, "TOPLEFT", 10, -10)
|
|
||||||
title:SetText(MTH_CR_L("CREDITS_TITLE", "Credits"))
|
|
||||||
title:SetTextColor(1.00, 0.82, 0.00)
|
|
||||||
|
|
||||||
local scrollFrame = MTH_GetFrame("MetaHuntOptionsCreditsScroll")
|
local scrollFrame = MTH_GetFrame("MetaHuntOptionsCreditsScroll")
|
||||||
if not scrollFrame then
|
if not scrollFrame then
|
||||||
@@ -124,12 +120,12 @@ function MTH_SetupCreditsOptions()
|
|||||||
cursor = MTH_CreditsCreateText(content, cursor,
|
cursor = MTH_CreditsCreateText(content, cursor,
|
||||||
MTH_CR_L("CREDITS_ABOUT_CODE_INTRO",
|
MTH_CR_L("CREDITS_ABOUT_CODE_INTRO",
|
||||||
"This addon is, in others, a compilation of old vanilla addons that I loved and played with during years. But most of them had become very buggy with TwoW as new contain was added to the server. \n I fixed, reworked, enhanced, and melted them within a modern modular framework that I created.\n"
|
"This addon is, in others, a compilation of old vanilla addons that I loved and played with during years. But most of them had become very buggy with TwoW as new contain was added to the server. \n I fixed, reworked, enhanced, and melted them within a modern modular framework that I created.\n"
|
||||||
.. "I want to make it crystal clear about what work is mine, and what is not and respectfully credit the original authors for the great stuff I've taken from them:"),
|
.. "I want to make it clear about what work is mine, and what is not and respectfully credit the original authors for the great stuff I've taken from them:"),
|
||||||
"GameFontNormalSmall", -10)
|
"GameFontNormalSmall", -10)
|
||||||
|
|
||||||
cursor = MTH_CreditsCreateText(content, cursor,
|
cursor = MTH_CreditsCreateText(content, cursor,
|
||||||
MTH_CR_L("CREDITS_ABOUT_ZHUNTER",
|
MTH_CR_L("CREDITS_ABOUT_ZHUNTER",
|
||||||
"- zBars, Antidaze and Autostrip were core functionalities of Vanilla zHunterMod addon. And I kept the \"z\" naming of bars/buttons to always remember it. On top of this I have created myself zBars, zAmmo, zCompanions, zMount, zToys, zCraft.\nAlso the SmartAmmo feature idea is coming from Zhuntermod: there was a file in it with that functionality, but was like a work-in-progress, totally unfunctional and even \"dangerous\" in its current state, and was not active in the addon. Since it was a fucking great idea, I recoded it mostly from scratch and made it work reliably and safely."),
|
"- zBars, Antidaze and Autostrip were core functionalities of Vanilla zHunterMod addon. And I kept the \"z\" naming of bars/buttons to always remember it. I improve it and added zBar, zAmmo, zCompanions, zMount, zToys, zCraft.\nAlso the SmartAmmo feature idea is coming from Zhuntermod: there was a file in it with that functionality, but was like a work-in-progress, totally unfunctional and even \"dangerous\" in its current state, and was not active in the addon. Since it was a fucking great idea, I recoded it mostly from scratch and made it work reliably and safely."),
|
||||||
"GameFontNormalSmall", -10)
|
"GameFontNormalSmall", -10)
|
||||||
|
|
||||||
cursor = MTH_CreditsCreateText(content, cursor,
|
cursor = MTH_CreditsCreateText(content, cursor,
|
||||||
@@ -189,7 +185,7 @@ function MTH_SetupCreditsOptions()
|
|||||||
"GameFontNormalSmall", -10)
|
"GameFontNormalSmall", -10)
|
||||||
|
|
||||||
cursor = MTH_CreditsCreateText(content, cursor,
|
cursor = MTH_CreditsCreateText(content, cursor,
|
||||||
MTH_CR_L("CREDITS_CLOSING", "With that being said, go back hunting fellas! Preferably on Octowow."),
|
MTH_CR_L("CREDITS_CLOSING", ""),
|
||||||
"GameFontNormalSmall", -10, 1.00, 0.82, 0.00)
|
"GameFontNormalSmall", -10, 1.00, 0.82, 0.00)
|
||||||
|
|
||||||
cursor = MTH_CreditsCreateText(content, cursor,
|
cursor = MTH_CreditsCreateText(content, cursor,
|
||||||
|
|||||||
+138
-250
@@ -15,16 +15,7 @@ local function MTH_EA_OPT_GetCfg()
|
|||||||
return MTH_SavedVariables.modules["expammo"] or {}
|
return MTH_SavedVariables.modules["expammo"] or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
local MTH_EA_OPT_built = false
|
|
||||||
local MTH_EA_OPT_STATE = { bindStatus = nil, bindButton = nil, captureFrame = nil }
|
local MTH_EA_OPT_STATE = { bindStatus = nil, bindButton = nil, captureFrame = nil }
|
||||||
|
|
||||||
-- ── Layout constants ──────────────────────────────────────────
|
|
||||||
-- Two equal columns separated by a gutter. Values are offsets from the
|
|
||||||
-- container TOPLEFT corner (positive X right, negative Y down).
|
|
||||||
local OPT_L = 20 -- left column X
|
|
||||||
local OPT_R = 300 -- right column X
|
|
||||||
local OPT_CW = 255 -- column width (used for text wrapping and sliders)
|
|
||||||
|
|
||||||
local function MTH_EA_OPT_GetBindText()
|
local function MTH_EA_OPT_GetBindText()
|
||||||
if not GetBindingKey then return "Unbound" end
|
if not GetBindingKey then return "Unbound" end
|
||||||
local k1, k2 = GetBindingKey("EXPAMMO ACTION")
|
local k1, k2 = GetBindingKey("EXPAMMO ACTION")
|
||||||
@@ -119,271 +110,168 @@ local function MTH_EA_OPT_StartCapture()
|
|||||||
if bb then bb:SetText("Press key...") end
|
if bb then bb:SetText("Press key...") end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Helper: checkbox anchored to a given X column
|
|
||||||
local function MTH_EA_OPT_CB(container, name, label, yOff, xOff, isChecked, onClick)
|
|
||||||
local cb = MTH_CreateCheckbox(container, name, label, yOff, xOff or OPT_L)
|
|
||||||
if cb then
|
|
||||||
cb:SetChecked(isChecked and 1 or 0)
|
|
||||||
cb:SetScript("OnClick", function()
|
|
||||||
local v = this:GetChecked()
|
|
||||||
onClick(v == 1 or v == true)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
return cb
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Helper: section header label
|
|
||||||
local function MTH_EA_OPT_Header(container, text, yOff, xOff)
|
|
||||||
local fs = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
|
||||||
fs:SetPoint("TOPLEFT", container, "TOPLEFT", xOff or OPT_L, yOff)
|
|
||||||
fs:SetText("|cffff9900" .. text .. "|r")
|
|
||||||
return fs
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Helper: small descriptive text
|
|
||||||
local function MTH_EA_OPT_Tip(container, text, yOff, xOff, r, g, b)
|
|
||||||
local fs = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
|
||||||
fs:SetPoint("TOPLEFT", container, "TOPLEFT", xOff or OPT_L, yOff)
|
|
||||||
fs:SetWidth(OPT_CW)
|
|
||||||
fs:SetJustifyH("LEFT")
|
|
||||||
fs:SetTextColor(r or 0.6, g or 0.6, b or 0.6)
|
|
||||||
fs:SetText(text)
|
|
||||||
return fs
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Enable or disable a list of widgets (supports Frames/Buttons and FontStrings)
|
|
||||||
local function MTH_EA_OPT_SetGroupEnabled(widgets, enabled)
|
|
||||||
for _, w in ipairs(widgets) do
|
|
||||||
if w then
|
|
||||||
if w.Enable and w.Disable then
|
|
||||||
-- Frame / Button / CheckButton
|
|
||||||
if enabled then w:Enable() else w:Disable() end
|
|
||||||
end
|
|
||||||
-- Dim all (including FontStrings and frames) via alpha
|
|
||||||
if w.SetAlpha then
|
|
||||||
w:SetAlpha(enabled and 1.0 or 0.35)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function MTH_EA_OPT_BuildUI(container)
|
local function MTH_EA_OPT_BuildUI(container)
|
||||||
if MTH_EA_OPT_built then return end
|
|
||||||
MTH_EA_OPT_built = true
|
|
||||||
|
|
||||||
local cfg = MTH_EA_OPT_GetCfg()
|
local cfg = MTH_EA_OPT_GetCfg()
|
||||||
local showHint = cfg.showHint ~= false
|
local showHint = cfg.showHint ~= false
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
local panel = MTH_Layout.Panel(container)
|
||||||
-- Title
|
panel:Title("MM Widget — Experimental Ammunition Tracker")
|
||||||
---------------------------------------------------------------------------
|
|
||||||
local title = container:CreateFontString(nil, "ARTWORK", "GameFontHighlightLarge")
|
|
||||||
title:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L, -16)
|
|
||||||
title:SetText("MM Widget — Experimental Ammunition Tracker")
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
-- Right-column gating: dim the box frames and disable their interactive
|
||||||
-- LEFT COLUMN
|
-- controls when the "Show action hint cell" checkbox is off.
|
||||||
---------------------------------------------------------------------------
|
local rightBoxes = {}
|
||||||
|
local rightControls = {}
|
||||||
-- ── Module ──────────────────────────────────────────────
|
local function setRightEnabled(enabled)
|
||||||
MTH_EA_OPT_Header(container, "Module", -46)
|
local i
|
||||||
|
for i = 1, table.getn(rightBoxes) do
|
||||||
|
local f = rightBoxes[i]
|
||||||
|
if f and f.SetAlpha then f:SetAlpha(enabled and 1.0 or 0.35) end
|
||||||
|
end
|
||||||
|
for i = 1, table.getn(rightControls) do
|
||||||
|
local c = rightControls[i]
|
||||||
|
if c and c.Enable and c.Disable then
|
||||||
|
if enabled then c:Enable() else c:Disable() end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ===== LEFT: Module =====
|
||||||
|
local moduleBox = panel:Box("left", "MTH_ExpAmmoModuleBox", "Module")
|
||||||
local moduleEnabled = true
|
local moduleEnabled = true
|
||||||
if MTH and MTH.IsModuleEnabled then
|
if MTH and MTH.IsModuleEnabled then
|
||||||
moduleEnabled = MTH:IsModuleEnabled("expammo", true) and true or false
|
moduleEnabled = MTH:IsModuleEnabled("expammo", true) and true or false
|
||||||
end
|
end
|
||||||
MTH_EA_OPT_CB(container, "MTH_ExpAmmoModuleCB",
|
moduleBox:Checkbox("MTH_ExpAmmoModuleCB", "Enable MM Widget module", {
|
||||||
"Enable MM Widget module",
|
checked = moduleEnabled,
|
||||||
-66, OPT_L, moduleEnabled,
|
onClick = function()
|
||||||
function(v)
|
local v = this:GetChecked() == 1
|
||||||
if MTH and MTH.SetModuleEnabled then MTH:SetModuleEnabled("expammo", v) end
|
if MTH and MTH.SetModuleEnabled then MTH:SetModuleEnabled("expammo", v) end
|
||||||
if MTH_ExpAmmo then MTH_ExpAmmo.SetEnabled(v) end
|
if MTH_ExpAmmo then MTH_ExpAmmo.SetEnabled(v) end
|
||||||
end)
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
-- ── Tracker Visibility ───────────────────────────────────
|
-- ===== LEFT: Tracker Visibility =====
|
||||||
MTH_EA_OPT_Header(container, "Tracker Visibility", -100)
|
local visBox = panel:Box("left", "MTH_ExpAmmoVisBox", "Tracker Visibility")
|
||||||
|
visBox:Checkbox("MTH_ExpAmmoShowLnLCB", "Show Lock and Load cell (top)", {
|
||||||
MTH_EA_OPT_CB(container, "MTH_ExpAmmoShowLnLCB",
|
checked = cfg.showLnL ~= false,
|
||||||
"Show Lock and Load cell (top)",
|
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetShowLnL(this:GetChecked() == 1) end end,
|
||||||
-120, OPT_L, cfg.showLnL ~= false,
|
})
|
||||||
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetShowLnL(v) end end)
|
visBox:Checkbox("MTH_ExpAmmoShowHintCB", "Show action hint cell (bottom)", {
|
||||||
|
checked = showHint,
|
||||||
-- "Show action hint cell" also gates the right column
|
onClick = function()
|
||||||
local rightGroup = {} -- filled below; toggled when this CB changes
|
local v = this:GetChecked() == 1
|
||||||
local showHintCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoShowHintCB",
|
|
||||||
"Show action hint cell (bottom)",
|
|
||||||
-144, OPT_L, showHint,
|
|
||||||
function(v)
|
|
||||||
if MTH_ExpAmmo then MTH_ExpAmmo.SetShowHint(v) end
|
if MTH_ExpAmmo then MTH_ExpAmmo.SetShowHint(v) end
|
||||||
MTH_EA_OPT_SetGroupEnabled(rightGroup, v)
|
setRightEnabled(v)
|
||||||
end)
|
end,
|
||||||
|
})
|
||||||
|
visBox:Checkbox("MTH_ExpAmmoHideOOCCB", "Hide widget when out of combat", {
|
||||||
|
checked = cfg.hideOOC == true,
|
||||||
|
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetHideOOC(this:GetChecked() == 1) end end,
|
||||||
|
})
|
||||||
|
|
||||||
MTH_EA_OPT_CB(container, "MTH_ExpAmmoHideOOCCB",
|
-- ===== LEFT: Appearance =====
|
||||||
"Hide widget when out of combat",
|
local appBox = panel:Box("left", "MTH_ExpAmmoAppBox", "Appearance")
|
||||||
-168, OPT_L, cfg.hideOOC == true,
|
appBox:Slider("MTH_ExpAmmoCellSizeSlider", {
|
||||||
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetHideOOC(v) end end)
|
label = "Cell Size (px)", min = 20, max = 80, step = 4,
|
||||||
|
value = math.max(20, math.min(80, cfg.cellSize or 40)),
|
||||||
|
onChange = function(val) if MTH_ExpAmmo then MTH_ExpAmmo.SetCellSize(val) end end,
|
||||||
|
})
|
||||||
|
appBox:Slider("MTH_ExpAmmoCellGapSlider", {
|
||||||
|
label = "Cell Spacing (px)", min = 0, max = 20, step = 1,
|
||||||
|
value = math.max(0, math.min(20, cfg.cellGap or 2)),
|
||||||
|
onChange = function(val) if MTH_ExpAmmo then MTH_ExpAmmo.SetCellGap(val) end end,
|
||||||
|
})
|
||||||
|
appBox:Checkbox("MTH_ExpAmmoBigCDCB", "Large cooldown numbers (centered in cell)", {
|
||||||
|
checked = cfg.bigCD == true,
|
||||||
|
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetBigCD(this:GetChecked() == 1) end end,
|
||||||
|
})
|
||||||
|
|
||||||
-- ── Appearance ───────────────────────────────────────────
|
-- ===== LEFT: Position =====
|
||||||
MTH_EA_OPT_Header(container, "Appearance", -202)
|
local posBox = panel:Box("left", "MTH_ExpAmmoPosBox", "Position")
|
||||||
|
posBox:Button("MTH_ExpAmmoToggleAnchor", "Toggle Anchor", {
|
||||||
local sizeSlider = MTH_CreateSlider(container, "MTH_ExpAmmoCellSizeSlider",
|
width = 130,
|
||||||
"Cell Size (px)", 20, 80, 4, -222)
|
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.ToggleAnchor() end end,
|
||||||
if sizeSlider then
|
})
|
||||||
sizeSlider:ClearAllPoints()
|
posBox:Note("MTH_ExpAmmoPosNote",
|
||||||
sizeSlider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L + 5, -222)
|
|
||||||
sizeSlider:SetWidth(OPT_CW - 10)
|
|
||||||
sizeSlider:SetValue(math.max(20, math.min(80, cfg.cellSize or 40)))
|
|
||||||
sizeSlider.onChange = function(val)
|
|
||||||
if MTH_ExpAmmo then MTH_ExpAmmo.SetCellSize(val) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local gapSlider = MTH_CreateSlider(container, "MTH_ExpAmmoCellGapSlider",
|
|
||||||
"Cell Spacing (px)", 0, 20, 1, -286)
|
|
||||||
if gapSlider then
|
|
||||||
gapSlider:ClearAllPoints()
|
|
||||||
gapSlider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_L + 5, -286)
|
|
||||||
gapSlider:SetWidth(OPT_CW - 10)
|
|
||||||
gapSlider:SetValue(math.max(0, math.min(20, cfg.cellGap or 2)))
|
|
||||||
gapSlider.onChange = function(val)
|
|
||||||
if MTH_ExpAmmo then MTH_ExpAmmo.SetCellGap(val) end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
MTH_EA_OPT_CB(container, "MTH_ExpAmmoBigCDCB",
|
|
||||||
"Large cooldown numbers (centered in cell)",
|
|
||||||
-350, OPT_L, cfg.bigCD == true,
|
|
||||||
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetBigCD(v) end end)
|
|
||||||
|
|
||||||
-- ── Position ─────────────────────────────────────────────
|
|
||||||
MTH_EA_OPT_Header(container, "Position", -390)
|
|
||||||
|
|
||||||
local anchorButton = MTH_CreateActionButton(container, "MTH_ExpAmmoToggleAnchor",
|
|
||||||
"Toggle Anchor", OPT_L, -410, 130, 22, function()
|
|
||||||
if MTH_ExpAmmo then MTH_ExpAmmo.ToggleAnchor() end
|
|
||||||
end)
|
|
||||||
if anchorButton then anchorButton:Show() end
|
|
||||||
|
|
||||||
MTH_EA_OPT_Tip(container,
|
|
||||||
"Shows 4 drag handles around the widget (top / bottom / left / right). Drag any one to reposition it.",
|
"Shows 4 drag handles around the widget (top / bottom / left / right). Drag any one to reposition it.",
|
||||||
-436, OPT_L)
|
{ color = MTH_Layout.Theme.colText, lines = 3 })
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
-- ===== RIGHT: Smart Action Cell (helper + keybind + casting) =====
|
||||||
-- RIGHT COLUMN — Action Hint Cell (keybind + casting)
|
-- One feature = one box. The intro notes explain the bottom cell, and the
|
||||||
-- All widgets here are greyed out when the bottom cell is hidden.
|
-- Keybind / Casting controls that drive it live underneath as sub-sections.
|
||||||
---------------------------------------------------------------------------
|
local cellBox = panel:Box("right", "MTH_ExpAmmoCellBox", "Smart Action Cell")
|
||||||
|
table.insert(rightBoxes, cellBox:Frame())
|
||||||
-- Vertical divider line
|
cellBox:Text("MTH_ExpAmmoHintSub",
|
||||||
local divider = container:CreateTexture(nil, "BACKGROUND")
|
"Options below apply to the bottom cell only. Disable \"Show action hint cell\" to hide the cell and these controls.",
|
||||||
divider:SetTexture(0.3, 0.3, 0.3, 0.6)
|
{ color = { 1, 1, 1 }, lines = 3 })
|
||||||
divider:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R - 10, -46)
|
cellBox:Note("MTH_ExpAmmoHintNam",
|
||||||
divider:SetPoint("BOTTOMLEFT", container, "TOPLEFT", OPT_R - 10, -530)
|
|
||||||
divider:SetWidth(1)
|
|
||||||
|
|
||||||
-- Column title
|
|
||||||
local rTitle = container:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
|
|
||||||
rTitle:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -46)
|
|
||||||
rTitle:SetText("|cffff9900" .. "Action Hint Cell" .. "|r")
|
|
||||||
table.insert(rightGroup, rTitle)
|
|
||||||
|
|
||||||
|
|
||||||
local rSubtitle = MTH_EA_OPT_Tip(container,
|
|
||||||
"Options below apply to the bottom cell only.\n Disable \"Show action hint cell\" to hide the cell and these controls.",
|
|
||||||
-64, OPT_R, 1.00, 1.00, 1.00)
|
|
||||||
if rSubtitle then rSubtitle:SetWidth(290) end
|
|
||||||
table.insert(rightGroup, rSubtitle)
|
|
||||||
|
|
||||||
local rNamPowerTip = MTH_EA_OPT_Tip(container,
|
|
||||||
"Notes:\n - You need NAMPOWER for this to work reliably.\n - Aimed/Steady/Multi/Arcane Shots SHOULD BE on your action bars.",
|
"Notes:\n - You need NAMPOWER for this to work reliably.\n - Aimed/Steady/Multi/Arcane Shots SHOULD BE on your action bars.",
|
||||||
-100, OPT_R, 0.35, 0.65, 1.00)
|
{ lines = 3 })
|
||||||
if rNamPowerTip then rNamPowerTip:SetWidth(290) end
|
|
||||||
table.insert(rightGroup, rNamPowerTip)
|
|
||||||
|
|
||||||
-- ── Keybind ──────────────────────────────────────────────
|
-- Keybind sub-section
|
||||||
table.insert(rightGroup, MTH_EA_OPT_Header(container, "Keybind", -182, OPT_R))
|
cellBox:Gap(4)
|
||||||
|
cellBox:Text("MTH_ExpAmmoKeyHead", "Keybind",
|
||||||
|
{ font = MTH_Layout.Theme.fontBoxTitle, color = MTH_Layout.Theme.colPanelTitle })
|
||||||
|
cellBox:Note("MTH_ExpAmmoBindTip",
|
||||||
|
"One key to rule them all.\n Aimed Shot when ready, Steady Shot while Aimed is on cooldown, consume-spell (Multi / Serpent / Arcane) when proc is up.",
|
||||||
|
{ lines = 4 })
|
||||||
|
MTH_EA_OPT_STATE.bindStatus = cellBox:Text("MTH_ExpAmmoBindStatus",
|
||||||
|
"Key: " .. MTH_EA_OPT_GetBindText())
|
||||||
|
local keyButtons = cellBox:Buttons({
|
||||||
|
{ name = "MTH_ExpAmmoBindButton", label = "Set Key", width = 90,
|
||||||
|
onClick = function()
|
||||||
|
if MTH_EA_OPT_STATE.captureFrame and MTH_EA_OPT_STATE.captureFrame:IsShown() then
|
||||||
|
MTH_EA_OPT_StopCapture()
|
||||||
|
else
|
||||||
|
MTH_EA_OPT_StartCapture()
|
||||||
|
end
|
||||||
|
end },
|
||||||
|
{ name = "MTH_ExpAmmoBindClear", label = "Clear", width = 70,
|
||||||
|
onClick = function() MTH_EA_OPT_SaveBinding(nil) end },
|
||||||
|
})
|
||||||
|
MTH_EA_OPT_STATE.bindButton = keyButtons[1]
|
||||||
|
table.insert(rightControls, keyButtons[1])
|
||||||
|
table.insert(rightControls, keyButtons[2])
|
||||||
|
|
||||||
local bindTip = MTH_EA_OPT_Tip(container,
|
-- Casting sub-section
|
||||||
"One key to rule them all.\n Aimed Shot when ready, Steady Shot while Aimed is on cooldown,\n consume-spell (Multi / Serpent / Arcane) when proc is up.",
|
cellBox:Gap(4)
|
||||||
-200, OPT_R, 0.65, 0.65, 0.65)
|
cellBox:Text("MTH_ExpAmmoCastHead", "Casting",
|
||||||
if bindTip then bindTip:SetWidth(290) end
|
{ font = MTH_Layout.Theme.fontBoxTitle, color = MTH_Layout.Theme.colPanelTitle })
|
||||||
table.insert(rightGroup, bindTip)
|
local quiverCB = cellBox:Checkbox("MTH_ExpAmmoQuiverNoClipCB", "Use Quiver no-clip casting", {
|
||||||
|
checked = cfg.useQuiverNoClip == true,
|
||||||
|
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetUseQuiverNoClip(this:GetChecked() == 1) end end,
|
||||||
|
})
|
||||||
|
table.insert(rightControls, quiverCB)
|
||||||
|
cellBox:Note("MTH_ExpAmmoQuiverTip",
|
||||||
|
"Requires the Quiver addon. Routes Aimed/Steady/Multi cast through Quiver.CastNoClip to avoid clipping your auto-shot swing timer.",
|
||||||
|
{ lines = 3 })
|
||||||
|
|
||||||
local bindStatus = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
-- ===== RIGHT: Rotation =====
|
||||||
bindStatus:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -248)
|
local rotBox = panel:Box("right", "MTH_ExpAmmoRotBox", "Rotation")
|
||||||
bindStatus:SetText("Key: " .. MTH_EA_OPT_GetBindText())
|
table.insert(rightBoxes, rotBox:Frame())
|
||||||
MTH_EA_OPT_STATE.bindStatus = bindStatus
|
rotBox:Note("MTH_ExpAmmoRotTip",
|
||||||
table.insert(rightGroup, bindStatus)
|
"Uncheck a shot to permanently skip it during its proc window. The keybind will cast Steady/Aimed instead.",
|
||||||
|
{ lines = 2 })
|
||||||
|
local multiCB = rotBox:Checkbox("MTH_ExpAmmoBlockMultiCB", "Multi-Shot (Explosive)", {
|
||||||
|
checked = cfg.blockExplosive ~= true,
|
||||||
|
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockExplosive(not (this:GetChecked() == 1)) end end,
|
||||||
|
})
|
||||||
|
table.insert(rightControls, multiCB)
|
||||||
|
local serpentCB = rotBox:Checkbox("MTH_ExpAmmoBlockSerpentCB", "Serpent Sting (Poisonous)", {
|
||||||
|
checked = cfg.blockPoisonous ~= true,
|
||||||
|
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockPoisonous(not (this:GetChecked() == 1)) end end,
|
||||||
|
})
|
||||||
|
table.insert(rightControls, serpentCB)
|
||||||
|
local arcaneCB = rotBox:Checkbox("MTH_ExpAmmoBlockArcaneCB", "Arcane Shot (Enchanted)", {
|
||||||
|
checked = cfg.blockEnchanted ~= true,
|
||||||
|
onClick = function() if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockEnchanted(not (this:GetChecked() == 1)) end end,
|
||||||
|
})
|
||||||
|
table.insert(rightControls, arcaneCB)
|
||||||
|
|
||||||
local bindButton = CreateFrame("Button", "MTH_ExpAmmoBindButton", container, "UIPanelButtonTemplate")
|
panel:Finish()
|
||||||
bindButton:SetPoint("TOPLEFT", container, "TOPLEFT", OPT_R, -264)
|
|
||||||
bindButton:SetWidth(90)
|
|
||||||
bindButton:SetHeight(22)
|
|
||||||
bindButton:SetText("Set Key")
|
|
||||||
bindButton:EnableKeyboard(false)
|
|
||||||
bindButton:SetScript("OnClick", function()
|
|
||||||
if MTH_EA_OPT_STATE.captureFrame and MTH_EA_OPT_STATE.captureFrame:IsShown() then
|
|
||||||
MTH_EA_OPT_StopCapture()
|
|
||||||
else
|
|
||||||
MTH_EA_OPT_StartCapture()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
MTH_EA_OPT_STATE.bindButton = bindButton
|
|
||||||
table.insert(rightGroup, bindButton)
|
|
||||||
|
|
||||||
local clearButton = CreateFrame("Button", "MTH_ExpAmmoBindClear", container, "UIPanelButtonTemplate")
|
-- Apply initial gating state.
|
||||||
clearButton:SetPoint("LEFT", bindButton, "RIGHT", 6, 0)
|
setRightEnabled(showHint)
|
||||||
clearButton:SetWidth(70)
|
|
||||||
clearButton:SetHeight(22)
|
|
||||||
clearButton:SetText("Clear")
|
|
||||||
clearButton:SetScript("OnClick", function()
|
|
||||||
MTH_EA_OPT_SaveBinding(nil)
|
|
||||||
end)
|
|
||||||
table.insert(rightGroup, clearButton)
|
|
||||||
|
|
||||||
-- ── Casting ──────────────────────────────────────────────
|
|
||||||
table.insert(rightGroup, MTH_EA_OPT_Header(container, "Casting", -304, OPT_R))
|
|
||||||
|
|
||||||
local quiverCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoQuiverNoClipCB",
|
|
||||||
"Use Quiver no-clip casting",
|
|
||||||
-324, OPT_R, cfg.useQuiverNoClip == true,
|
|
||||||
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetUseQuiverNoClip(v) end end)
|
|
||||||
table.insert(rightGroup, quiverCB)
|
|
||||||
|
|
||||||
local quiverTip = MTH_EA_OPT_Tip(container,
|
|
||||||
"|cff4d9cffRequires the Quiver addon.|r \n Routes Aimed/Steady/Multi cast through Quiver.CastNoClip \n to avoid clipping your auto-shot swing timer",
|
|
||||||
-350, OPT_R, 1, 1, 1)
|
|
||||||
if quiverTip then quiverTip:SetWidth(290) end
|
|
||||||
table.insert(rightGroup, quiverTip)
|
|
||||||
|
|
||||||
-- ── Rotation ─────────────────────────────────────────────
|
|
||||||
table.insert(rightGroup, MTH_EA_OPT_Header(container, "Rotation", -400, OPT_R))
|
|
||||||
|
|
||||||
local rotTip = MTH_EA_OPT_Tip(container,
|
|
||||||
"Uncheck a shot to permanently skip it during its proc window.\n The keybind will cast Steady/Aimed instead.",
|
|
||||||
-418, OPT_R, 0.65, 0.65, 0.65)
|
|
||||||
if rotTip then rotTip:SetWidth(290) end
|
|
||||||
table.insert(rightGroup, rotTip)
|
|
||||||
|
|
||||||
local multiCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoBlockMultiCB",
|
|
||||||
"Multi-Shot (Explosive)",
|
|
||||||
-452, OPT_R, cfg.blockExplosive ~= true,
|
|
||||||
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockExplosive(not v) end end)
|
|
||||||
table.insert(rightGroup, multiCB)
|
|
||||||
|
|
||||||
local serpentCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoBlockSerpentCB",
|
|
||||||
"Serpent Sting (Poisonous)",
|
|
||||||
-476, OPT_R, cfg.blockPoisonous ~= true,
|
|
||||||
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockPoisonous(not v) end end)
|
|
||||||
table.insert(rightGroup, serpentCB)
|
|
||||||
|
|
||||||
local arcaneCB = MTH_EA_OPT_CB(container, "MTH_ExpAmmoBlockArcaneCB",
|
|
||||||
"Arcane Shot (Enchanted)",
|
|
||||||
-500, OPT_R, cfg.blockEnchanted ~= true,
|
|
||||||
function(v) if MTH_ExpAmmo then MTH_ExpAmmo.SetBlockEnchanted(not v) end end)
|
|
||||||
table.insert(rightGroup, arcaneCB)
|
|
||||||
|
|
||||||
-- Apply initial enabled state
|
|
||||||
MTH_EA_OPT_SetGroupEnabled(rightGroup, showHint)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_SetupExpAmmoOptions()
|
function MTH_SetupExpAmmoOptions()
|
||||||
|
|||||||
+107
-125
@@ -242,31 +242,25 @@ function MTH_RefreshFeedOMaticOptions()
|
|||||||
if MTH_FOM_STATE.ctrl.SaveCookNone then MTH_FOM_STATE.ctrl.SaveCookNone:SetChecked(FOM_Config.SaveForCookingLevel and FOM_Config.SaveForCookingLevel >= 4 and 1 or nil) end
|
if MTH_FOM_STATE.ctrl.SaveCookNone then MTH_FOM_STATE.ctrl.SaveCookNone:SetChecked(FOM_Config.SaveForCookingLevel and FOM_Config.SaveForCookingLevel >= 4 and 1 or nil) end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Small label helper: prefer Feed-O-Matic's own button text, else localized.
|
||||||
|
local function MTH_FOM_Label(key, lkey, fallback)
|
||||||
|
return (FOM_OptionsButtonText and FOM_OptionsButtonText[key]) or MTH_FOM_L(lkey, fallback)
|
||||||
|
end
|
||||||
|
|
||||||
function MTH_SetupFeedOMaticOptions()
|
function MTH_SetupFeedOMaticOptions()
|
||||||
if not MTH_FOM_READY then return end
|
if not MTH_FOM_READY then return end
|
||||||
local container = MTH_GetFrame("MetaHuntOptionsFeedOMatic")
|
local container = MTH_GetFrame("MetaHuntOptionsFeedOMatic")
|
||||||
if not container then return end
|
if not container then return end
|
||||||
local rightColumnX = 300
|
|
||||||
local yAdjust = -64
|
|
||||||
|
|
||||||
MTH_ClearContainer(container)
|
|
||||||
MTH_FOM_STATE.ctrl = {}
|
MTH_FOM_STATE.ctrl = {}
|
||||||
|
|
||||||
local title = container:CreateFontString("MetaHuntOptionsFeedOMaticTitle", "ARTWORK", "GameFontHighlight")
|
local panel = MTH_Layout.Panel(container)
|
||||||
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
|
panel:Title(MTH_FOM_L("FOM_TITLE", "Feed-O-Matic"))
|
||||||
title:SetText(MTH_FOM_L("FOM_TITLE", "Feed-O-Matic"))
|
panel:Note(MTH_FOM_L("FOM_STATUS_NOTICE", "Feed-O-Matic, created by the great Fizzwidget, is not yet entirely ready for Twow because I am missing \na reliable list of all foods, mostly impossible to fetch from the DB.\n It still works much better in this version, but all stuff related to Food buff and Cooking isnt fully functional."), { lines = 4 })
|
||||||
|
|
||||||
local statusNotice = container:CreateFontString("MetaHuntOptionsFeedOMaticStatusNotice", "ARTWORK", "GameFontNormalSmall")
|
MTH_FOM_STATE.enableCheck = panel:TopCheckbox("MetaHuntOptionsFeedOMaticEnabled",
|
||||||
statusNotice:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -34)
|
MTH_FOM_L("FOM_ENABLE_MODULE", "Enable FeedOMatic module"), {
|
||||||
statusNotice:SetWidth(600)
|
onClick = function()
|
||||||
statusNotice:SetJustifyH("LEFT")
|
|
||||||
statusNotice:SetJustifyV("TOP")
|
|
||||||
statusNotice:SetTextColor(0.35, 0.65, 1)
|
|
||||||
statusNotice:SetText(MTH_FOM_L("FOM_STATUS_NOTICE", "Feed-O-Matic, created by the great Fizzwidget, is not yet entirely ready for Twow because I am missing \na reliable list of all foods, mostly impossible to fetch from the DB.\n It still works much better in this version, but all stuff related to Food buff and Cooking isnt fully functional."))
|
|
||||||
|
|
||||||
local moduleCheck = MTH_CreateCheckbox(container, "MetaHuntOptionsFeedOMaticEnabled", MTH_FOM_L("FOM_ENABLE_MODULE", "Enable FeedOMatic module"), -32 + yAdjust)
|
|
||||||
if moduleCheck then
|
|
||||||
moduleCheck:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
if not this then return end
|
||||||
local enabled = this:GetChecked() == 1
|
local enabled = this:GetChecked() == 1
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
@@ -276,125 +270,113 @@ function MTH_SetupFeedOMaticOptions()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
MTH_RefreshFeedOMaticOptions()
|
MTH_RefreshFeedOMaticOptions()
|
||||||
end)
|
end,
|
||||||
MTH_FOM_STATE.enableCheck = moduleCheck
|
})
|
||||||
end
|
|
||||||
|
|
||||||
local leftHeader = container:CreateFontString("MetaHuntOptionsFeedOMaticGeneralHeader", "ARTWORK", "GameFontHighlight")
|
-- ===== General (left column) =====
|
||||||
leftHeader:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -62 + yAdjust)
|
local general = panel:Box("left", "MetaHuntOptionsFOMGeneralBox", MTH_FOM_L("FOM_HEADER_GENERAL", "General"))
|
||||||
leftHeader:SetText(MTH_FOM_L("FOM_HEADER_GENERAL", "General"))
|
|
||||||
|
|
||||||
local bindStatus = container:CreateFontString("MetaHuntOptionsFOMBindStatus", "ARTWORK", "GameFontNormalSmall")
|
MTH_FOM_STATE.bindStatus = general:Text("MetaHuntOptionsFOMBindStatus",
|
||||||
bindStatus:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -80 + yAdjust)
|
string.format(MTH_FOM_L("FOM_BIND_STATUS_VALUE", "Feed key: %s"), MTH_FOM_GetBindingDisplayText()))
|
||||||
bindStatus:SetText(string.format(MTH_FOM_L("FOM_BIND_STATUS_VALUE", "Feed key: %s"), MTH_FOM_GetBindingDisplayText()))
|
|
||||||
MTH_FOM_STATE.bindStatus = bindStatus
|
|
||||||
|
|
||||||
local bindButton = CreateFrame("Button", "MetaHuntOptionsFOMBindButton", container, "UIPanelButtonTemplate")
|
local bindButtons = general:Buttons({
|
||||||
bindButton:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -100 + yAdjust)
|
{ name = "MetaHuntOptionsFOMBindButton", label = MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key"), width = 90,
|
||||||
bindButton:SetWidth(90)
|
onClick = function()
|
||||||
bindButton:SetHeight(22)
|
if MTH_FOM_STATE.captureFrame and MTH_FOM_STATE.captureFrame:IsShown() then
|
||||||
bindButton:SetText(MTH_FOM_L("FOM_BIND_SET_KEY", "Set Key"))
|
MTH_FOM_StopBindingCapture()
|
||||||
bindButton:SetScript("OnClick", function()
|
else
|
||||||
if MTH_FOM_STATE.captureFrame and MTH_FOM_STATE.captureFrame:IsShown() then
|
MTH_FOM_StartBindingCapture()
|
||||||
MTH_FOM_StopBindingCapture()
|
end
|
||||||
else
|
end },
|
||||||
MTH_FOM_StartBindingCapture()
|
{ name = "MetaHuntOptionsFOMBindClearButton", label = MTH_FOM_L("FOM_BIND_CLEAR", "Clear"), width = 70,
|
||||||
end
|
onClick = function() MTH_FOM_SaveBinding(nil) end },
|
||||||
end)
|
})
|
||||||
MTH_FOM_STATE.bindButton = bindButton
|
MTH_FOM_STATE.bindButton = bindButtons[1]
|
||||||
|
MTH_FOM_STATE.bindClearButton = bindButtons[2]
|
||||||
|
|
||||||
local bindClearButton = CreateFrame("Button", "MetaHuntOptionsFOMBindClearButton", container, "UIPanelButtonTemplate")
|
general:Note("MetaHuntOptionsFOMBindHint",
|
||||||
bindClearButton:SetPoint("LEFT", bindButton, "RIGHT", 8, 0)
|
MTH_FOM_L("FOM_BIND_HINT", "You should assign a key bind for feed-o-matic,\nin order to feed your pet automatically.\nThe key \"P\" is an excellent candidate !"), { lines = 3 })
|
||||||
bindClearButton:SetWidth(70)
|
|
||||||
bindClearButton:SetHeight(22)
|
|
||||||
bindClearButton:SetText(MTH_FOM_L("FOM_BIND_CLEAR", "Clear"))
|
|
||||||
bindClearButton:SetScript("OnClick", function()
|
|
||||||
MTH_FOM_SaveBinding(nil)
|
|
||||||
end)
|
|
||||||
MTH_FOM_STATE.bindClearButton = bindClearButton
|
|
||||||
|
|
||||||
local bindHint = container:CreateFontString("MetaHuntOptionsFOMBindHint", "ARTWORK", "GameFontNormalSmall")
|
MTH_FOM_STATE.ctrl.AvoidQuestFood = general:Checkbox("MetaHuntOptionsFOMAvoidQuest",
|
||||||
bindHint:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -128 + yAdjust)
|
MTH_FOM_Label("AvoidQuestFood", "FOM_LABEL_AVOID_QUEST_FOODS", "Avoid quest foods"),
|
||||||
bindHint:SetWidth(360)
|
{ onClick = function() if not this then return end FOM_Config.AvoidQuestFood = this:GetChecked() == 1 end })
|
||||||
bindHint:SetJustifyH("LEFT")
|
MTH_FOM_STATE.ctrl.AvoidBonusFood = general:Checkbox("MetaHuntOptionsFOMAvoidBonus",
|
||||||
bindHint:SetJustifyV("TOP")
|
MTH_FOM_Label("AvoidBonusFood", "FOM_LABEL_AVOID_BONUS_FOODS", "Avoid bonus foods"),
|
||||||
bindHint:SetTextColor(0.35, 0.65, 1)
|
{ onClick = function() if not this then return end FOM_Config.AvoidBonusFood = this:GetChecked() == 1 end })
|
||||||
bindHint:SetText(MTH_FOM_L("FOM_BIND_HINT", "You should assign a key bind for feed-o-matic,\nin order to feed your pet automatically.\nThe key \"P\" is an excellent candidate !"))
|
MTH_FOM_STATE.ctrl.PreferHigherQuality = general:Checkbox("MetaHuntOptionsFOMPreferQuality",
|
||||||
|
MTH_FOM_Label("PreferHigherQuality", "FOM_LABEL_PREFER_HIGHER_QUALITY_FOOD", "Prefer higher quality food"),
|
||||||
|
{ onClick = function() if not this then return end FOM_Config.PreferHigherQuality = this:GetChecked() == 1 end })
|
||||||
|
MTH_FOM_STATE.ctrl.Fallback = general:Checkbox("MetaHuntOptionsFOMFallback",
|
||||||
|
MTH_FOM_Label("Fallback", "FOM_LABEL_FALLBACK_TO_AVOIDED_FOODS", "Fallback to avoided foods"),
|
||||||
|
{ onClick = function() if not this then return end FOM_Config.Fallback = this:GetChecked() == 1 end })
|
||||||
|
|
||||||
MTH_FOM_STATE.ctrl.AvoidQuestFood = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAvoidQuest", FOM_OptionsButtonText and FOM_OptionsButtonText["AvoidQuestFood"] or MTH_FOM_L("FOM_LABEL_AVOID_QUEST_FOODS", "Avoid quest foods"), -170 + yAdjust)
|
MTH_FOM_STATE.keepOpenEdit = general:EditRow("MetaHuntOptionsFOMKeepOpenLabel",
|
||||||
MTH_FOM_STATE.ctrl.AvoidBonusFood = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAvoidBonus", FOM_OptionsButtonText and FOM_OptionsButtonText["AvoidBonusFood"] or MTH_FOM_L("FOM_LABEL_AVOID_BONUS_FOODS", "Avoid bonus foods"), -195 + yAdjust)
|
MTH_FOM_L("FOM_KEEP_OPEN_BAG_SLOTS", "Keep open bag slots:"),
|
||||||
MTH_FOM_STATE.ctrl.PreferHigherQuality = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMPreferQuality", FOM_OptionsButtonText and FOM_OptionsButtonText["PreferHigherQuality"] or MTH_FOM_L("FOM_LABEL_PREFER_HIGHER_QUALITY_FOOD", "Prefer higher quality food"), -220 + yAdjust)
|
"MetaHuntOptionsFOMKeepOpen", 40, {
|
||||||
MTH_FOM_STATE.ctrl.Fallback = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMFallback", FOM_OptionsButtonText and FOM_OptionsButtonText["Fallback"] or MTH_FOM_L("FOM_LABEL_FALLBACK_TO_AVOIDED_FOODS", "Fallback to avoided foods"), -245 + yAdjust)
|
numeric = true,
|
||||||
|
onChange = function()
|
||||||
|
if not this then return end
|
||||||
|
FOM_Config.KeepOpenSlots = tonumber(this:GetText()) or 0
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
if MTH_FOM_STATE.ctrl.AvoidQuestFood then MTH_FOM_STATE.ctrl.AvoidQuestFood:SetScript("OnClick", function() if not this then return end FOM_Config.AvoidQuestFood = this:GetChecked() == 1 end) end
|
-- ===== Notify when feeding (left column) =====
|
||||||
if MTH_FOM_STATE.ctrl.AvoidBonusFood then MTH_FOM_STATE.ctrl.AvoidBonusFood:SetScript("OnClick", function() if not this then return end FOM_Config.AvoidBonusFood = this:GetChecked() == 1 end) end
|
local notify = panel:Box("left", "MetaHuntOptionsFOMNotifyBox", MTH_FOM_L("FOM_HEADER_NOTIFY_WHEN_FEEDING", "Notify when feeding"))
|
||||||
if MTH_FOM_STATE.ctrl.PreferHigherQuality then MTH_FOM_STATE.ctrl.PreferHigherQuality:SetScript("OnClick", function() if not this then return end FOM_Config.PreferHigherQuality = this:GetChecked() == 1 end) end
|
MTH_FOM_STATE.ctrl.AlertEmote = notify:Checkbox("MetaHuntOptionsFOMAlertEmote",
|
||||||
if MTH_FOM_STATE.ctrl.Fallback then MTH_FOM_STATE.ctrl.Fallback:SetScript("OnClick", function() if not this then return end FOM_Config.Fallback = this:GetChecked() == 1 end) end
|
MTH_FOM_Label("AlertEmote", "FOM_LABEL_NOTIFY_VIA_EMOTE", "Via emote"),
|
||||||
|
{ onClick = function() MTH_FOM_SetAlert("emote"); MTH_RefreshFeedOMaticOptions() end })
|
||||||
|
MTH_FOM_STATE.ctrl.AlertChat = notify:Checkbox("MetaHuntOptionsFOMAlertChat",
|
||||||
|
MTH_FOM_Label("AlertChat", "FOM_LABEL_NOTIFY_IN_CHAT", "In chat"),
|
||||||
|
{ onClick = function() MTH_FOM_SetAlert("chat"); MTH_RefreshFeedOMaticOptions() end })
|
||||||
|
MTH_FOM_STATE.ctrl.AlertNone = notify:Checkbox("MetaHuntOptionsFOMAlertNone",
|
||||||
|
MTH_FOM_Label("AlertNone", "FOM_LABEL_NOTIFY_NONE", "Don't notify"),
|
||||||
|
{ onClick = function() MTH_FOM_SetAlert("none"); MTH_RefreshFeedOMaticOptions() end })
|
||||||
|
|
||||||
local keepOpenLabel = container:CreateFontString("MetaHuntOptionsFOMKeepOpenLabel", "ARTWORK", "GameFontNormalSmall")
|
-- ===== Avoid foods used in cooking (right column) =====
|
||||||
keepOpenLabel:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -302 + yAdjust)
|
local avoid = panel:Box("right", "MetaHuntOptionsFOMAvoidBox", MTH_FOM_L("FOM_HEADER_AVOID_FOODS_USED_IN_COOKING", "Avoid foods used in cooking"))
|
||||||
keepOpenLabel:SetText(MTH_FOM_L("FOM_KEEP_OPEN_BAG_SLOTS", "Keep open bag slots:"))
|
MTH_FOM_STATE.ctrl.SaveCookOrange = avoid:Checkbox("MetaHuntOptionsFOMSaveCookOrange",
|
||||||
|
MTH_FOM_Label("SaveForCook_Orange", "FOM_LABEL_ONLY_DIFFICULT_RECIPES", "Only difficult recipes"),
|
||||||
|
{ onClick = function() MTH_FOM_SetCookingLevel(3); MTH_RefreshFeedOMaticOptions() end })
|
||||||
|
MTH_FOM_STATE.ctrl.SaveCookYellow = avoid:Checkbox("MetaHuntOptionsFOMSaveCookYellow",
|
||||||
|
MTH_FOM_Label("SaveForCook_Yellow", "FOM_LABEL_MEDIUM_OR_BETTER", "Medium or better"),
|
||||||
|
{ onClick = function() MTH_FOM_SetCookingLevel(2); MTH_RefreshFeedOMaticOptions() end })
|
||||||
|
MTH_FOM_STATE.ctrl.SaveCookGreen = avoid:Checkbox("MetaHuntOptionsFOMSaveCookGreen",
|
||||||
|
MTH_FOM_Label("SaveForCook_Green", "FOM_LABEL_EASY_OR_BETTER", "Easy or better"),
|
||||||
|
{ onClick = function() MTH_FOM_SetCookingLevel(1); MTH_RefreshFeedOMaticOptions() end })
|
||||||
|
MTH_FOM_STATE.ctrl.SaveCookAll = avoid:Checkbox("MetaHuntOptionsFOMSaveCookAll",
|
||||||
|
MTH_FOM_Label("SaveForCook_All", "FOM_LABEL_ALL_FOODS", "All foods"),
|
||||||
|
{ onClick = function() MTH_FOM_SetCookingLevel(0); MTH_RefreshFeedOMaticOptions() end })
|
||||||
|
MTH_FOM_STATE.ctrl.SaveCookNone = avoid:Checkbox("MetaHuntOptionsFOMSaveCookNone",
|
||||||
|
MTH_FOM_Label("SaveForCook_None", "FOM_LABEL_DO_NOT_SAVE_COOKING_FOODS", "Do not save cooking foods"),
|
||||||
|
{ onClick = function() MTH_FOM_SetCookingLevel(4); MTH_RefreshFeedOMaticOptions() end })
|
||||||
|
|
||||||
local keepOpen = CreateFrame("EditBox", "MetaHuntOptionsFOMKeepOpen", container, "InputBoxTemplate")
|
-- ===== Warn when pet needs feeding (right column) =====
|
||||||
keepOpen:SetPoint("LEFT", keepOpenLabel, "RIGHT", 8, 0)
|
local warn = panel:Box("right", "MetaHuntOptionsFOMWarnBox", MTH_FOM_L("FOM_HEADER_WARN_WHEN_PET_NEEDS_FEEDING", "Warn when pet needs feeding"))
|
||||||
keepOpen:SetWidth(40)
|
MTH_FOM_STATE.ctrl.LevelContent = warn:Checkbox("MetaHuntOptionsFOMLevelContent",
|
||||||
keepOpen:SetHeight(20)
|
MTH_FOM_Label("LevelContent", "FOM_LABEL_WARN_WHEN_CONTENT", "When content"),
|
||||||
keepOpen:SetNumeric(true)
|
{ onClick = function() MTH_FOM_SetLevel("content"); MTH_RefreshFeedOMaticOptions() end })
|
||||||
keepOpen:SetAutoFocus(false)
|
MTH_FOM_STATE.ctrl.LevelUnhappy = warn:Checkbox("MetaHuntOptionsFOMLevelUnhappy",
|
||||||
keepOpen:SetScript("OnTextChanged", function()
|
MTH_FOM_Label("LevelUnhappy", "FOM_LABEL_WARN_WHEN_UNHAPPY", "When unhappy"),
|
||||||
if not this then return end
|
{ onClick = function() MTH_FOM_SetLevel("unhappy"); MTH_RefreshFeedOMaticOptions() end })
|
||||||
local value = tonumber(this:GetText()) or 0
|
MTH_FOM_STATE.ctrl.LevelOff = warn:Checkbox("MetaHuntOptionsFOMLevelOff",
|
||||||
FOM_Config.KeepOpenSlots = value
|
MTH_FOM_Label("LevelOff", "FOM_LABEL_DONT_WARN", "Don't warn"),
|
||||||
end)
|
{ onClick = function() MTH_FOM_SetLevel("off"); MTH_RefreshFeedOMaticOptions() end })
|
||||||
keepOpen:SetScript("OnEnterPressed", function() if this then this:ClearFocus() end end)
|
|
||||||
keepOpen:SetScript("OnEscapePressed", function() if this then this:ClearFocus() end end)
|
|
||||||
MTH_FOM_STATE.keepOpenEdit = keepOpen
|
|
||||||
|
|
||||||
local notifyHeader = container:CreateFontString("MetaHuntOptionsFOMNotifyHeader", "ARTWORK", "GameFontHighlight")
|
warn:Gap(6)
|
||||||
notifyHeader:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -336 + yAdjust)
|
|
||||||
notifyHeader:SetText(MTH_FOM_L("FOM_HEADER_NOTIFY_WHEN_FEEDING", "Notify when feeding"))
|
|
||||||
|
|
||||||
MTH_FOM_STATE.ctrl.AlertEmote = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAlertEmote", FOM_OptionsButtonText and FOM_OptionsButtonText["AlertEmote"] or MTH_FOM_L("FOM_LABEL_NOTIFY_VIA_EMOTE", "Via emote"), -360 + yAdjust)
|
MTH_FOM_STATE.ctrl.AudioWarning = warn:Checkbox("MetaHuntOptionsFOMAudioWarning",
|
||||||
MTH_FOM_STATE.ctrl.AlertChat = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAlertChat", FOM_OptionsButtonText and FOM_OptionsButtonText["AlertChat"] or MTH_FOM_L("FOM_LABEL_NOTIFY_IN_CHAT", "In chat"), -385 + yAdjust)
|
MTH_FOM_Label("AudioWarning", "FOM_LABEL_PLAY_SOUND", "Play sound"),
|
||||||
MTH_FOM_STATE.ctrl.AlertNone = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAlertNone", FOM_OptionsButtonText and FOM_OptionsButtonText["AlertNone"] or MTH_FOM_L("FOM_LABEL_NOTIFY_NONE", "Don't notify"), -410 + yAdjust)
|
{ onClick = function() if not this then return end if this:GetChecked() == 1 then if FOM_Config.AudioWarning ~= "bell" then FOM_Config.AudioWarning = true end else FOM_Config.AudioWarning = nil end MTH_RefreshFeedOMaticOptions() end })
|
||||||
if MTH_FOM_STATE.ctrl.AlertEmote then MTH_FOM_STATE.ctrl.AlertEmote:SetScript("OnClick", function() MTH_FOM_SetAlert("emote"); MTH_RefreshFeedOMaticOptions() end) end
|
MTH_FOM_STATE.ctrl.AudioWarningBell = warn:Checkbox("MetaHuntOptionsFOMAudioWarningBell",
|
||||||
if MTH_FOM_STATE.ctrl.AlertChat then MTH_FOM_STATE.ctrl.AlertChat:SetScript("OnClick", function() MTH_FOM_SetAlert("chat"); MTH_RefreshFeedOMaticOptions() end) end
|
MTH_FOM_Label("AudioWarningBell", "FOM_LABEL_USE_BELL_SOUND", "Use bell sound"),
|
||||||
if MTH_FOM_STATE.ctrl.AlertNone then MTH_FOM_STATE.ctrl.AlertNone:SetScript("OnClick", function() MTH_FOM_SetAlert("none"); MTH_RefreshFeedOMaticOptions() end) end
|
{ onClick = function() if not this then return end if this:GetChecked() == 1 then FOM_Config.AudioWarning = "bell" else FOM_Config.AudioWarning = true end MTH_RefreshFeedOMaticOptions() end })
|
||||||
|
MTH_FOM_STATE.ctrl.TextWarning = warn:Checkbox("MetaHuntOptionsFOMTextWarning",
|
||||||
local warnHeader = container:CreateFontString("MetaHuntOptionsFOMWarnHeader", "ARTWORK", "GameFontHighlight")
|
MTH_FOM_Label("TextWarning", "FOM_LABEL_SHOW_TEXT", "Show text"),
|
||||||
warnHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightColumnX, -276 + yAdjust)
|
{ onClick = function() if not this then return end FOM_Config.TextWarning = this:GetChecked() == 1 end })
|
||||||
warnHeader:SetText(MTH_FOM_L("FOM_HEADER_WARN_WHEN_PET_NEEDS_FEEDING", "Warn when pet needs feeding"))
|
MTH_FOM_STATE.ctrl.IconWarning = warn:Checkbox("MetaHuntOptionsFOMIconWarning",
|
||||||
|
MTH_FOM_Label("IconWarning", "FOM_LABEL_FLASH_ICON", "Flash icon"),
|
||||||
MTH_FOM_STATE.ctrl.LevelContent = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMLevelContent", FOM_OptionsButtonText and FOM_OptionsButtonText["LevelContent"] or MTH_FOM_L("FOM_LABEL_WARN_WHEN_CONTENT", "When content"), -300 + yAdjust, rightColumnX)
|
{ onClick = function() if not this then return end FOM_Config.IconWarning = this:GetChecked() == 1 end })
|
||||||
MTH_FOM_STATE.ctrl.LevelUnhappy = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMLevelUnhappy", FOM_OptionsButtonText and FOM_OptionsButtonText["LevelUnhappy"] or MTH_FOM_L("FOM_LABEL_WARN_WHEN_UNHAPPY", "When unhappy"), -325 + yAdjust, rightColumnX)
|
|
||||||
MTH_FOM_STATE.ctrl.LevelOff = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMLevelOff", FOM_OptionsButtonText and FOM_OptionsButtonText["LevelOff"] or MTH_FOM_L("FOM_LABEL_DONT_WARN", "Don't warn"), -350 + yAdjust, rightColumnX)
|
|
||||||
if MTH_FOM_STATE.ctrl.LevelContent then MTH_FOM_STATE.ctrl.LevelContent:SetScript("OnClick", function() MTH_FOM_SetLevel("content"); MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
if MTH_FOM_STATE.ctrl.LevelUnhappy then MTH_FOM_STATE.ctrl.LevelUnhappy:SetScript("OnClick", function() MTH_FOM_SetLevel("unhappy"); MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
if MTH_FOM_STATE.ctrl.LevelOff then MTH_FOM_STATE.ctrl.LevelOff:SetScript("OnClick", function() MTH_FOM_SetLevel("off"); MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
|
|
||||||
MTH_FOM_STATE.ctrl.AudioWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAudioWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["AudioWarning"] or MTH_FOM_L("FOM_LABEL_PLAY_SOUND", "Play sound"), -378 + yAdjust, rightColumnX)
|
|
||||||
MTH_FOM_STATE.ctrl.AudioWarningBell = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMAudioWarningBell", FOM_OptionsButtonText and FOM_OptionsButtonText["AudioWarningBell"] or MTH_FOM_L("FOM_LABEL_USE_BELL_SOUND", "Use bell sound"), -403 + yAdjust, rightColumnX)
|
|
||||||
MTH_FOM_STATE.ctrl.TextWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMTextWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["TextWarning"] or MTH_FOM_L("FOM_LABEL_SHOW_TEXT", "Show text"), -428 + yAdjust, rightColumnX)
|
|
||||||
MTH_FOM_STATE.ctrl.IconWarning = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMIconWarning", FOM_OptionsButtonText and FOM_OptionsButtonText["IconWarning"] or MTH_FOM_L("FOM_LABEL_FLASH_ICON", "Flash icon"), -453 + yAdjust, rightColumnX)
|
|
||||||
if MTH_FOM_STATE.ctrl.AudioWarning then MTH_FOM_STATE.ctrl.AudioWarning:SetScript("OnClick", function() if not this then return end if this:GetChecked() == 1 then if FOM_Config.AudioWarning ~= "bell" then FOM_Config.AudioWarning = true end else FOM_Config.AudioWarning = nil end MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
if MTH_FOM_STATE.ctrl.AudioWarningBell then MTH_FOM_STATE.ctrl.AudioWarningBell:SetScript("OnClick", function() if not this then return end if this:GetChecked() == 1 then FOM_Config.AudioWarning = "bell" else FOM_Config.AudioWarning = true end MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
if MTH_FOM_STATE.ctrl.TextWarning then MTH_FOM_STATE.ctrl.TextWarning:SetScript("OnClick", function() if not this then return end FOM_Config.TextWarning = this:GetChecked() == 1 end) end
|
|
||||||
if MTH_FOM_STATE.ctrl.IconWarning then MTH_FOM_STATE.ctrl.IconWarning:SetScript("OnClick", function() if not this then return end FOM_Config.IconWarning = this:GetChecked() == 1 end) end
|
|
||||||
|
|
||||||
local cookHeader = container:CreateFontString("MetaHuntOptionsFOMCookingHeader", "ARTWORK", "GameFontHighlight")
|
|
||||||
cookHeader:SetPoint("TOPLEFT", container, "TOPLEFT", rightColumnX, -62 + yAdjust)
|
|
||||||
cookHeader:SetText(MTH_FOM_L("FOM_HEADER_AVOID_FOODS_USED_IN_COOKING", "Avoid foods used in cooking"))
|
|
||||||
|
|
||||||
MTH_FOM_STATE.ctrl.SaveCookOrange = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookOrange", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_Orange"] or MTH_FOM_L("FOM_LABEL_ONLY_DIFFICULT_RECIPES", "Only difficult recipes"), -86 + yAdjust, rightColumnX)
|
|
||||||
MTH_FOM_STATE.ctrl.SaveCookYellow = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookYellow", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_Yellow"] or MTH_FOM_L("FOM_LABEL_MEDIUM_OR_BETTER", "Medium or better"), -111 + yAdjust, rightColumnX)
|
|
||||||
MTH_FOM_STATE.ctrl.SaveCookGreen = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookGreen", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_Green"] or MTH_FOM_L("FOM_LABEL_EASY_OR_BETTER", "Easy or better"), -136 + yAdjust, rightColumnX)
|
|
||||||
MTH_FOM_STATE.ctrl.SaveCookAll = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookAll", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_All"] or MTH_FOM_L("FOM_LABEL_ALL_FOODS", "All foods"), -161 + yAdjust, rightColumnX)
|
|
||||||
MTH_FOM_STATE.ctrl.SaveCookNone = MTH_CreateCheckbox(container, "MetaHuntOptionsFOMSaveCookNone", FOM_OptionsButtonText and FOM_OptionsButtonText["SaveForCook_None"] or MTH_FOM_L("FOM_LABEL_DO_NOT_SAVE_COOKING_FOODS", "Do not save cooking foods"), -186 + yAdjust, rightColumnX)
|
|
||||||
if MTH_FOM_STATE.ctrl.SaveCookOrange then MTH_FOM_STATE.ctrl.SaveCookOrange:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(3); MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
if MTH_FOM_STATE.ctrl.SaveCookYellow then MTH_FOM_STATE.ctrl.SaveCookYellow:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(2); MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
if MTH_FOM_STATE.ctrl.SaveCookGreen then MTH_FOM_STATE.ctrl.SaveCookGreen:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(1); MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
if MTH_FOM_STATE.ctrl.SaveCookAll then MTH_FOM_STATE.ctrl.SaveCookAll:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(0); MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
if MTH_FOM_STATE.ctrl.SaveCookNone then MTH_FOM_STATE.ctrl.SaveCookNone:SetScript("OnClick", function() MTH_FOM_SetCookingLevel(4); MTH_RefreshFeedOMaticOptions() end) end
|
|
||||||
|
|
||||||
|
panel:Finish()
|
||||||
MTH_RefreshFeedOMaticOptions()
|
MTH_RefreshFeedOMaticOptions()
|
||||||
end
|
end
|
||||||
|
|||||||
+103
-195
@@ -197,31 +197,25 @@ local function MTH_ICU_OpenColorPicker(colorKey)
|
|||||||
ColorPickerFrame:Show()
|
ColorPickerFrame:Show()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function MTH_ICU_CreateOptionRow(container, rowName, label, key, y, labelX, dropdownX)
|
local function MTH_ICU_BuildUI(container)
|
||||||
labelX = labelX or MTH_ICU_LAYOUT.LEFT_X
|
MTH_ICU_OPT_STATE.controls = {}
|
||||||
dropdownX = dropdownX or MTH_ICU_LAYOUT.LEFT_DROPDOWN_X
|
MTH_ICU_OPT_STATE.container = container
|
||||||
|
MTH_ICU_OPT_STATE.built = true
|
||||||
|
|
||||||
local labelFs = container:CreateFontString(rowName .. "Label", "ARTWORK", "GameFontNormalSmall")
|
local controls = MTH_ICU_OPT_STATE.controls
|
||||||
labelFs:SetPoint("TOPLEFT", container, "TOPLEFT", labelX, y)
|
|
||||||
labelFs:SetText(label)
|
|
||||||
|
|
||||||
local dropdown = CreateFrame("Frame", rowName .. "Drop", container, "UIDropDownMenuTemplate")
|
local panel = MTH_Layout.Panel(container)
|
||||||
dropdown:ClearAllPoints()
|
panel:Title("MTH ICU")
|
||||||
dropdown:SetPoint("TOPLEFT", container, "TOPLEFT", dropdownX, y + 12)
|
panel:Note("ICU is a minimap targeting utility module for your Trackings. It provides enhanced target information and click actions for players and NPCs on the minimap.",
|
||||||
if UIDropDownMenu_SetWidth then
|
{ lines = 2 })
|
||||||
UIDropDownMenu_SetWidth(MTH_ICU_LAYOUT.DROPDOWN_WIDTH, dropdown)
|
|
||||||
end
|
|
||||||
if UIDropDownMenu_JustifyText then
|
|
||||||
UIDropDownMenu_JustifyText("LEFT", dropdown)
|
|
||||||
end
|
|
||||||
|
|
||||||
if UIDropDownMenu_Initialize then
|
-- Standard UIDropDownMenu initialize factory for a stored option key.
|
||||||
UIDropDownMenu_Initialize(dropdown, function()
|
local function makeInit(key)
|
||||||
|
return function()
|
||||||
local values = MTH_ICU_GetOptionValues(key)
|
local values = MTH_ICU_GetOptionValues(key)
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
local current = tostring(store[key] or "")
|
local current = tostring(store[key] or "")
|
||||||
local infoFactory = UIDropDownMenu_CreateInfo
|
local infoFactory = UIDropDownMenu_CreateInfo
|
||||||
|
|
||||||
for i = 1, table.getn(values) do
|
for i = 1, table.getn(values) do
|
||||||
local optionValue = tostring(values[i])
|
local optionValue = tostring(values[i])
|
||||||
local info = type(infoFactory) == "function" and infoFactory() or {}
|
local info = type(infoFactory) == "function" and infoFactory() or {}
|
||||||
@@ -229,76 +223,23 @@ local function MTH_ICU_CreateOptionRow(container, rowName, label, key, y, labelX
|
|||||||
info.checked = optionValue == current and 1 or nil
|
info.checked = optionValue == current and 1 or nil
|
||||||
info.func = function()
|
info.func = function()
|
||||||
MTH_ICU_SetValue(key, optionValue)
|
MTH_ICU_SetValue(key, optionValue)
|
||||||
MTH_RefreshICUOptions()
|
-- ANCHOR toggles whether the Toggle Anchor / Expand Up
|
||||||
|
-- controls exist, so rebuild instead of a plain refresh.
|
||||||
|
if key == "ANCHOR" then
|
||||||
|
MTH_SetupICUOptions()
|
||||||
|
else
|
||||||
|
MTH_RefreshICUOptions()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if UIDropDownMenu_AddButton then UIDropDownMenu_AddButton(info) end
|
if UIDropDownMenu_AddButton then UIDropDownMenu_AddButton(info) end
|
||||||
end
|
end
|
||||||
end)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
MTH_ICU_OPT_STATE.controls[key] = {
|
-- ===== LEFT: Module =====
|
||||||
label = labelFs,
|
local moduleBox = panel:Box("left", "MTH_ICUModuleBox", "Module")
|
||||||
dropdown = dropdown,
|
controls.moduleEnabled = moduleBox:Checkbox("MetaHuntOptionsICUModuleEnabled", "Enable ICU module", {
|
||||||
}
|
onClick = function()
|
||||||
end
|
|
||||||
|
|
||||||
local function MTH_ICU_CreateColorRow(container, rowName, label, colorKey, y, labelX, buttonX)
|
|
||||||
labelX = labelX or MTH_ICU_LAYOUT.RIGHT_X
|
|
||||||
buttonX = buttonX or MTH_ICU_LAYOUT.COLOR_BUTTON_X
|
|
||||||
|
|
||||||
local labelFs = container:CreateFontString(rowName .. "Label", "ARTWORK", "GameFontNormalSmall")
|
|
||||||
labelFs:SetPoint("TOPLEFT", container, "TOPLEFT", labelX, y)
|
|
||||||
labelFs:SetText(label)
|
|
||||||
|
|
||||||
local button = CreateFrame("Button", rowName .. "Button", container, "UIPanelButtonTemplate")
|
|
||||||
button:SetPoint("TOPLEFT", container, "TOPLEFT", buttonX, y + 8)
|
|
||||||
button:SetWidth(MTH_ICU_LAYOUT.COLOR_BUTTON_WIDTH)
|
|
||||||
button:SetHeight(22)
|
|
||||||
button:SetText("Pick")
|
|
||||||
button:SetScript("OnClick", function()
|
|
||||||
MTH_ICU_OpenColorPicker(colorKey)
|
|
||||||
end)
|
|
||||||
|
|
||||||
local swatch = button:CreateTexture(rowName .. "Swatch", "ARTWORK")
|
|
||||||
swatch:SetTexture("Interface\\Buttons\\WHITE8X8")
|
|
||||||
swatch:SetPoint("LEFT", button, "LEFT", 6, 0)
|
|
||||||
swatch:SetWidth(14)
|
|
||||||
swatch:SetHeight(14)
|
|
||||||
|
|
||||||
MTH_ICU_OPT_STATE.controls[colorKey] = {
|
|
||||||
label = labelFs,
|
|
||||||
button = button,
|
|
||||||
swatch = swatch,
|
|
||||||
isColor = true,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function MTH_ICU_BuildUI(container)
|
|
||||||
if MTH_ICU_OPT_STATE.built and MTH_ICU_OPT_STATE.container == container then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
MTH_ClearContainer(container)
|
|
||||||
MTH_ICU_OPT_STATE.controls = {}
|
|
||||||
MTH_ICU_OPT_STATE.container = container
|
|
||||||
MTH_ICU_OPT_STATE.built = true
|
|
||||||
|
|
||||||
local title = container:CreateFontString("MetaHuntOptionsICUTitle", "ARTWORK", "GameFontHighlight")
|
|
||||||
title:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -10)
|
|
||||||
title:SetText("MTH ICU")
|
|
||||||
|
|
||||||
local note = container:CreateFontString("MetaHuntOptionsICUNote", "ARTWORK", "GameFontNormalSmall")
|
|
||||||
note:SetPoint("TOPLEFT", container, "TOPLEFT", 20, -32)
|
|
||||||
note:SetWidth(560)
|
|
||||||
note:SetJustifyH("LEFT")
|
|
||||||
note:SetJustifyV("TOP")
|
|
||||||
note:SetTextColor(0.35, 0.65, 1)
|
|
||||||
note:SetText("ICU is a minimap targeting utility module for your Trackings.\nIt provides enhanced target information and click actions for players and NPCs on the minimap.")
|
|
||||||
|
|
||||||
local moduleEnabled = MTH_CreateCheckbox(container, "MetaHuntOptionsICUModuleEnabled", "Enable ICU module", -72, MTH_ICU_LAYOUT.LEFT_X)
|
|
||||||
if moduleEnabled then
|
|
||||||
moduleEnabled:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
if MTH and MTH.SetModuleEnabled then
|
if MTH and MTH.SetModuleEnabled then
|
||||||
local ok, err = MTH:SetModuleEnabled("icu", this:GetChecked() == 1)
|
local ok, err = MTH:SetModuleEnabled("icu", this:GetChecked() == 1)
|
||||||
if not ok and MTH and MTH.Print then
|
if not ok and MTH and MTH.Print then
|
||||||
@@ -306,130 +247,97 @@ local function MTH_ICU_BuildUI(container)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
MTH_RefreshICUOptions()
|
MTH_RefreshICUOptions()
|
||||||
end)
|
end,
|
||||||
MTH_ICU_OPT_STATE.controls.moduleEnabled = moduleEnabled
|
})
|
||||||
end
|
controls.mouseOver = moduleBox:Checkbox("MetaHuntOptionsICUMouseOver", "Enable CTRL mouseover scan", {
|
||||||
|
onClick = function()
|
||||||
local mouseOver = MTH_CreateCheckbox(container, "MetaHuntOptionsICUMouseOver", "Enable CTRL mouseover scan", -98, MTH_ICU_LAYOUT.LEFT_X)
|
|
||||||
if mouseOver then
|
|
||||||
mouseOver:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
store.mouseOver = this:GetChecked() == 1 and true or false
|
store.mouseOver = this:GetChecked() == 1 and true or false
|
||||||
end)
|
end,
|
||||||
MTH_ICU_OPT_STATE.controls.mouseOver = mouseOver
|
})
|
||||||
|
|
||||||
|
-- ===== LEFT: General Settings =====
|
||||||
|
local genBox = panel:Box("left", "MTH_ICUGeneralBox", "General Settings")
|
||||||
|
controls.ALERT = { dropdown = genBox:Dropdown("MetaHuntOptionsICUAlertDrop",
|
||||||
|
{ label = "ALERT PvP", width = 130, initialize = makeInit("ALERT") }) }
|
||||||
|
controls.ANNOUNCE = { dropdown = genBox:Dropdown("MetaHuntOptionsICUAnnounceDrop",
|
||||||
|
{ label = "ANNOUNCE on click", width = 130, initialize = makeInit("ANNOUNCE") }) }
|
||||||
|
controls.HEALTH_TEXT_MODE = { dropdown = genBox:Dropdown("MetaHuntOptionsICUHealthModeDrop",
|
||||||
|
{ label = "Health text", width = 130, initialize = makeInit("HEALTH_TEXT_MODE") }) }
|
||||||
|
controls.POPUP_HIDE_DELAY = { dropdown = genBox:Dropdown("MetaHuntOptionsICUHideDelayDrop",
|
||||||
|
{ label = "List hide delay", width = 130, initialize = makeInit("POPUP_HIDE_DELAY") }) }
|
||||||
|
controls.ANCHOR = { dropdown = genBox:Dropdown("MetaHuntOptionsICUAnchorDrop",
|
||||||
|
{ label = "ANCHOR", width = 130, initialize = makeInit("ANCHOR") }) }
|
||||||
|
-- The manual-anchor controls only apply to a CUSTOM anchor. Build them
|
||||||
|
-- only in that case so the box never reserves empty space for them.
|
||||||
|
if tostring(MTH_ICU_GetStore().ANCHOR or "") == "CUSTOM" then
|
||||||
|
controls.customAnchorButton = genBox:Button("MetaHuntOptionsICUToggleAnchorButton", "Toggle Anchor", {
|
||||||
|
width = 116,
|
||||||
|
onClick = function() if type(ICU_ToggleAnchor) == "function" then ICU_ToggleAnchor() end end,
|
||||||
|
})
|
||||||
|
controls.expandUp = genBox:Checkbox("MetaHuntOptionsICUExpandUp", "Expand Up", {
|
||||||
|
onClick = function()
|
||||||
|
local store = MTH_ICU_GetStore()
|
||||||
|
store.EXPAND_UP = this:GetChecked() == 1 and true or false
|
||||||
|
if type(ICU_SetPoints) == "function" then ICU_SetPoints() end
|
||||||
|
end,
|
||||||
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
local sectionHeader = container:CreateFontString("MetaHuntOptionsICUSectionHeader", "ARTWORK", "GameFontHighlight")
|
-- ===== RIGHT: Background Colors =====
|
||||||
sectionHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.LEFT_X, -146)
|
local bgBox = panel:Box("right", "MTH_ICUBgBox", "Background Colors")
|
||||||
sectionHeader:SetText("General Settings")
|
controls.PLAYER_COLOR_MODE = { dropdown = bgBox:Dropdown("MetaHuntOptionsICUPlayerColorModeDrop",
|
||||||
|
{ label = "Player colors", width = 130, initialize = makeInit("PLAYER_COLOR_MODE") }) }
|
||||||
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAlert", "ALERT PVP", "ALERT", -172, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
|
controls.reactionOnlyPvp = bgBox:Checkbox("MetaHuntOptionsICUReactionOnlyPvp", "Reaction only when PvP-flagged", {
|
||||||
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAnnounce", "ANNOUNCE on click", "ANNOUNCE", -198, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
|
onClick = function()
|
||||||
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUHealthMode", "Health text", "HEALTH_TEXT_MODE", -224, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
|
|
||||||
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUHideDelay", "List hide delay", "POPUP_HIDE_DELAY", -250, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
|
|
||||||
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUAnchor", "ANCHOR", "ANCHOR", -276, MTH_ICU_LAYOUT.LEFT_X, MTH_ICU_LAYOUT.LEFT_DROPDOWN_X)
|
|
||||||
|
|
||||||
local toggleAnchorButton = CreateFrame("Button", "MetaHuntOptionsICUToggleAnchorButton", container, "UIPanelButtonTemplate")
|
|
||||||
toggleAnchorButton:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.LEFT_X, -302)
|
|
||||||
toggleAnchorButton:SetWidth(116)
|
|
||||||
toggleAnchorButton:SetHeight(22)
|
|
||||||
toggleAnchorButton:SetText("Toggle Anchor")
|
|
||||||
toggleAnchorButton:SetScript("OnClick", function()
|
|
||||||
if type(ICU_ToggleAnchor) == "function" then
|
|
||||||
ICU_ToggleAnchor()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
MTH_ICU_OPT_STATE.controls.customAnchorButton = toggleAnchorButton
|
|
||||||
|
|
||||||
local expandUp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUExpandUp", "Expand Up", -301, MTH_ICU_LAYOUT.LEFT_X + 132)
|
|
||||||
if expandUp then
|
|
||||||
expandUp:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
|
||||||
store.EXPAND_UP = this:GetChecked() == 1 and true or false
|
|
||||||
if type(ICU_SetPoints) == "function" then
|
|
||||||
ICU_SetPoints()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
MTH_ICU_OPT_STATE.controls.expandUp = expandUp
|
|
||||||
end
|
|
||||||
|
|
||||||
local showGuild = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowGuild", "Show player guild names", -344, MTH_ICU_LAYOUT.LEFT_X)
|
|
||||||
if showGuild then
|
|
||||||
showGuild:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
|
||||||
store.SHOW_GUILD_NAME = this:GetChecked() == 1 and true or false
|
|
||||||
end)
|
|
||||||
MTH_ICU_OPT_STATE.controls.showGuildName = showGuild
|
|
||||||
end
|
|
||||||
|
|
||||||
local showClass = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowClass", "Show player class", -368, MTH_ICU_LAYOUT.LEFT_X)
|
|
||||||
if showClass then
|
|
||||||
showClass:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
|
||||||
store.SHOW_PLAYER_CLASS = this:GetChecked() == 1 and true or false
|
|
||||||
end)
|
|
||||||
MTH_ICU_OPT_STATE.controls.showPlayerClass = showClass
|
|
||||||
end
|
|
||||||
|
|
||||||
local showRace = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowRace", "Show player race", -392, MTH_ICU_LAYOUT.LEFT_X)
|
|
||||||
if showRace then
|
|
||||||
showRace:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
|
||||||
store.SHOW_PLAYER_RACE = this:GetChecked() == 1 and true or false
|
|
||||||
end)
|
|
||||||
MTH_ICU_OPT_STATE.controls.showPlayerRace = showRace
|
|
||||||
end
|
|
||||||
|
|
||||||
local showTitles = MTH_CreateCheckbox(container, "MetaHuntOptionsICUShowTitles", "Show custom titles in alerts", -416, MTH_ICU_LAYOUT.LEFT_X)
|
|
||||||
if showTitles then
|
|
||||||
showTitles:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
|
||||||
store.SHOW_CUSTOM_TITLES = this:GetChecked() == 1 and true or false
|
|
||||||
end)
|
|
||||||
MTH_ICU_OPT_STATE.controls.showCustomTitles = showTitles
|
|
||||||
end
|
|
||||||
|
|
||||||
local rightHeader = container:CreateFontString("MetaHuntOptionsICURightHeader", "ARTWORK", "GameFontHighlight")
|
|
||||||
rightHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -146)
|
|
||||||
rightHeader:SetText("Background Colors")
|
|
||||||
|
|
||||||
MTH_ICU_CreateOptionRow(container, "MetaHuntOptionsICUPlayerColorMode", "Player colors", "PLAYER_COLOR_MODE", -172, MTH_ICU_LAYOUT.RIGHT_X, MTH_ICU_LAYOUT.RIGHT_DROPDOWN_X)
|
|
||||||
|
|
||||||
local reactionOnlyPvp = MTH_CreateCheckbox(container, "MetaHuntOptionsICUReactionOnlyPvp", "Reaction only when PvP-flagged", -200, MTH_ICU_LAYOUT.RIGHT_X)
|
|
||||||
if reactionOnlyPvp then
|
|
||||||
reactionOnlyPvp:SetScript("OnClick", function()
|
|
||||||
if not this then return end
|
|
||||||
local store = MTH_ICU_GetStore()
|
local store = MTH_ICU_GetStore()
|
||||||
store.REACTION_ONLY_PVP_PLAYERS = this:GetChecked() == 1 and true or false
|
store.REACTION_ONLY_PVP_PLAYERS = this:GetChecked() == 1 and true or false
|
||||||
end)
|
end,
|
||||||
MTH_ICU_OPT_STATE.controls.reactionOnlyPvp = reactionOnlyPvp
|
})
|
||||||
end
|
|
||||||
|
|
||||||
local colorHeader = container:CreateFontString("MetaHuntOptionsICUColorsHeader", "ARTWORK", "GameFontHighlight")
|
-- ===== RIGHT: Color Pickers =====
|
||||||
colorHeader:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -224)
|
local colorBox = panel:Box("right", "MTH_ICUColorBox", "Color Pickers")
|
||||||
|
colorBox:Note("MetaHuntOptionsICUColorsScope",
|
||||||
local colorScope = container:CreateFontString("MetaHuntOptionsICUColorsScope", "ARTWORK", "GameFontNormalSmall")
|
"Player pickers: REACTION / FACTION / CUSTOM\nNPC pickers: always", { lines = 2 })
|
||||||
colorScope:SetPoint("TOPLEFT", container, "TOPLEFT", MTH_ICU_LAYOUT.RIGHT_X, -242)
|
|
||||||
colorScope:SetWidth(250)
|
|
||||||
colorScope:SetJustifyH("LEFT")
|
|
||||||
colorScope:SetJustifyV("TOP")
|
|
||||||
colorScope:SetTextColor(0.35, 0.65, 1)
|
|
||||||
colorScope:SetText("Player pickers: REACTION / FACTION / CUSTOM\nNPC pickers: always")
|
|
||||||
|
|
||||||
local colorY = -284
|
|
||||||
for i = 1, table.getn(MTH_ICU_COLOR_ROWS) do
|
for i = 1, table.getn(MTH_ICU_COLOR_ROWS) do
|
||||||
local row = MTH_ICU_COLOR_ROWS[i]
|
local row = MTH_ICU_COLOR_ROWS[i]
|
||||||
MTH_ICU_CreateColorRow(container, "MetaHuntOptionsICUColor" .. tostring(i), row.label, row.key, colorY, MTH_ICU_LAYOUT.RIGHT_X, MTH_ICU_LAYOUT.COLOR_BUTTON_X)
|
local btn, swatch = colorBox:ColorRow("MetaHuntOptionsICUColor" .. tostring(i), {
|
||||||
colorY = colorY - MTH_ICU_LAYOUT.COLOR_ROW_STEP
|
label = row.label,
|
||||||
|
buttonText = "Pick",
|
||||||
|
buttonWidth = 78,
|
||||||
|
onClick = function() MTH_ICU_OpenColorPicker(row.key) end,
|
||||||
|
})
|
||||||
|
controls[row.key] = { button = btn, swatch = swatch, isColor = true }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- ===== Player Info (placed on whichever column has the most room) =====
|
||||||
|
local infoBox = panel:Box(panel:ShorterSide(), "MTH_ICUInfoBox", "Player Info")
|
||||||
|
controls.showGuildName = infoBox:Checkbox("MetaHuntOptionsICUShowGuild", "Show player guild names", {
|
||||||
|
onClick = function()
|
||||||
|
local store = MTH_ICU_GetStore()
|
||||||
|
store.SHOW_GUILD_NAME = this:GetChecked() == 1 and true or false
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
controls.showPlayerClass = infoBox:Checkbox("MetaHuntOptionsICUShowClass", "Show player class", {
|
||||||
|
onClick = function()
|
||||||
|
local store = MTH_ICU_GetStore()
|
||||||
|
store.SHOW_PLAYER_CLASS = this:GetChecked() == 1 and true or false
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
controls.showPlayerRace = infoBox:Checkbox("MetaHuntOptionsICUShowRace", "Show player race", {
|
||||||
|
onClick = function()
|
||||||
|
local store = MTH_ICU_GetStore()
|
||||||
|
store.SHOW_PLAYER_RACE = this:GetChecked() == 1 and true or false
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
controls.showCustomTitles = infoBox:Checkbox("MetaHuntOptionsICUShowTitles", "Show custom titles in alerts", {
|
||||||
|
onClick = function()
|
||||||
|
local store = MTH_ICU_GetStore()
|
||||||
|
store.SHOW_CUSTOM_TITLES = this:GetChecked() == 1 and true or false
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
panel:Finish()
|
||||||
end
|
end
|
||||||
|
|
||||||
function MTH_RefreshICUOptions()
|
function MTH_RefreshICUOptions()
|
||||||
|
|||||||
@@ -0,0 +1,608 @@
|
|||||||
|
-- =====================================================================
|
||||||
|
-- MetaHunt Option Panel Layout Engine
|
||||||
|
-- ---------------------------------------------------------------------
|
||||||
|
-- One reusable builder that every option panel uses. It removes ALL
|
||||||
|
-- hand-typed pixel offsets and box heights from the panels: you declare
|
||||||
|
-- rows, the engine stacks them and auto-sizes each box.
|
||||||
|
--
|
||||||
|
-- Think of it as CSS + flexbox for WoW 1.12:
|
||||||
|
-- * MTH_Layout.Theme -> the "CSS variables" (spacing / fonts / colors).
|
||||||
|
-- Change a value here to restyle every panel.
|
||||||
|
-- * panel / box methods -> the "flexbox": append rows, boxes grow to fit.
|
||||||
|
--
|
||||||
|
-- Design rules baked in (so the classic bugs are impossible):
|
||||||
|
-- * Each box TITLE lives INSIDE its box -> titles can never collide.
|
||||||
|
-- * Box HEIGHT is computed from its content -> never cramped/too short.
|
||||||
|
-- * Box CONTENT is parented to the box frame -> correct z-order.
|
||||||
|
-- * Everything is reuse-by-name (getglobal) -> no duplicates on /rl.
|
||||||
|
--
|
||||||
|
-- Typical usage:
|
||||||
|
-- local panel = MTH_Layout.Panel(container)
|
||||||
|
-- panel:Title("Feed-O-Matic")
|
||||||
|
-- panel:Note("blue helper paragraph", { lines = 3 })
|
||||||
|
-- panel:TopCheckbox("MyEnable", "Enable module", { onClick = fn, checked = fn })
|
||||||
|
-- local box = panel:Box("left", "MyBoxName", "General")
|
||||||
|
-- box:Text("MyStatus", "Feed key: P")
|
||||||
|
-- box:Buttons({ { name="A", label="Set Key", width=90, onClick=fn },
|
||||||
|
-- { name="B", label="Clear", width=70, onClick=fn } })
|
||||||
|
-- box:Note("MyHint", "blue helper text", { lines = 3 })
|
||||||
|
-- local cb = box:Checkbox("MyOpt", "Some option", { onClick = fn, checked = true })
|
||||||
|
-- box:EditRow("MyLbl", "Keep open bag slots:", "MyEdit", 40, { numeric = true, onChange = fn })
|
||||||
|
-- panel:Finish()
|
||||||
|
-- =====================================================================
|
||||||
|
|
||||||
|
MTH_Layout = MTH_Layout or {}
|
||||||
|
local L = MTH_Layout
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------
|
||||||
|
-- THEME ("CSS variables": tweak these to restyle the whole UI)
|
||||||
|
-- ---------------------------------------------------------------------
|
||||||
|
L.Theme = {
|
||||||
|
-- Spacing (pixels)
|
||||||
|
panelPad = 12, -- outer gutter from the panel edges
|
||||||
|
colGap = 12, -- horizontal gap between the two columns
|
||||||
|
boxGap = 16, -- vertical gap between stacked boxes
|
||||||
|
colTopGap = 8, -- gap between the header block and the first boxes
|
||||||
|
|
||||||
|
boxPadX = 10, -- content inset from a box's left edge
|
||||||
|
boxPadTop = 28, -- first row offset from a box's top (clears inside title)
|
||||||
|
boxPadBottom = 12, -- padding beneath the last row inside a box
|
||||||
|
cbInset = 8, -- checkbox inset from a box's left edge
|
||||||
|
|
||||||
|
rowCheckbox = 24, -- vertical step consumed by a checkbox / edit row
|
||||||
|
rowButton = 30, -- vertical step consumed by a button row
|
||||||
|
rowSlider = 46, -- vertical step consumed by a slider (label+track+value)
|
||||||
|
rowDropdown = 50, -- vertical step consumed by a dropdown (label+menu)
|
||||||
|
textLine = 14, -- height of one wrapped text line
|
||||||
|
textGap = 6, -- extra gap after a text/note block
|
||||||
|
|
||||||
|
titleInsetX = 10, -- box title inset X (inside the box)
|
||||||
|
titleInsetY = -12, -- box title inset Y (inside the box)
|
||||||
|
|
||||||
|
headTop = -12, -- Y where the panel header starts
|
||||||
|
headTitleStep = 24, -- vertical step after the panel title
|
||||||
|
headNoteGap = 10, -- extra gap after a header note
|
||||||
|
headRowGap = 8, -- extra gap after a header checkbox
|
||||||
|
headLinkStep = 18, -- vertical step after a header link
|
||||||
|
|
||||||
|
-- Fonts
|
||||||
|
fontPanelTitle = "GameFontNormal", -- panel heading
|
||||||
|
fontBoxTitle = "GameFontNormal", -- box title (recolored)
|
||||||
|
fontLabel = "GameFontNormalSmall", -- checkbox / edit labels
|
||||||
|
fontText = "GameFontNormalSmall", -- plain text
|
||||||
|
fontNote = "GameFontNormalSmall", -- helper paragraphs
|
||||||
|
fontLink = "GameFontHighlightSmall",
|
||||||
|
|
||||||
|
-- Colors { r, g, b }
|
||||||
|
colPanelTitle = { 1.00, 0.82, 0.00 }, -- gold
|
||||||
|
colBoxTitle = { 1.00, 1.00, 1.00 }, -- white
|
||||||
|
colNote = { 0.35, 0.65, 1.00 }, -- blue helper text
|
||||||
|
colText = { 0.93, 0.93, 0.93 }, -- normal text
|
||||||
|
colLink = { 0.40, 0.75, 1.00 }, -- link idle
|
||||||
|
colLinkHover = { 0.60, 0.90, 1.00 }, -- link hover
|
||||||
|
|
||||||
|
-- Templates
|
||||||
|
boxTemplate = "OptionFrameBoxTemplate",
|
||||||
|
checkTemplate = "UICheckButtonTemplate",
|
||||||
|
buttonTemplate = "UIPanelButtonTemplate",
|
||||||
|
editTemplate = "InputBoxTemplate",
|
||||||
|
}
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------
|
||||||
|
-- Small shared helpers
|
||||||
|
-- ---------------------------------------------------------------------
|
||||||
|
local function applyColor(region, c)
|
||||||
|
if region and c then region:SetTextColor(c[1], c[2], c[3]) end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ensureFontString(parent, name, font)
|
||||||
|
local fs = getglobal(name)
|
||||||
|
if not fs then
|
||||||
|
fs = parent:CreateFontString(name, "ARTWORK", font)
|
||||||
|
end
|
||||||
|
fs:Show()
|
||||||
|
return fs
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ensureFrame(kind, name, parent, template)
|
||||||
|
local f = getglobal(name)
|
||||||
|
if not f then
|
||||||
|
f = CreateFrame(kind, name, parent, template)
|
||||||
|
end
|
||||||
|
f:SetParent(parent)
|
||||||
|
return f
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Attach (or refresh) a checkbox's label, tooltip, checked state and click.
|
||||||
|
-- labelWidth (optional) enables word-wrap; the wrapped text height is returned
|
||||||
|
-- so the caller can grow the row to fit multi-line labels.
|
||||||
|
local function configureCheckbox(cb, label, opts, T, labelWidth)
|
||||||
|
local txt = getglobal(cb:GetName() .. "Text")
|
||||||
|
if not txt then
|
||||||
|
txt = cb:CreateFontString(cb:GetName() .. "Text", "ARTWORK", T.fontLabel)
|
||||||
|
end
|
||||||
|
-- Anchor the label to the checkbox's top-right and let it grow downward so
|
||||||
|
-- wrapped lines never collide with the row above. Centre a single line
|
||||||
|
-- vertically against the checkbox.
|
||||||
|
local cbH = (cb.GetHeight and cb:GetHeight()) or 24
|
||||||
|
local topOff = -((cbH - T.textLine) / 2)
|
||||||
|
if topOff > 0 then topOff = 0 end
|
||||||
|
txt:ClearAllPoints()
|
||||||
|
txt:SetPoint("TOPLEFT", cb, "TOPRIGHT", 4, topOff)
|
||||||
|
if labelWidth and labelWidth > 0 then
|
||||||
|
txt:SetWidth(labelWidth)
|
||||||
|
else
|
||||||
|
txt:SetWidth(0)
|
||||||
|
end
|
||||||
|
txt:SetJustifyH("LEFT")
|
||||||
|
txt:SetJustifyV("TOP")
|
||||||
|
txt:SetText(label or "")
|
||||||
|
txt:Show()
|
||||||
|
|
||||||
|
if opts.checked ~= nil then
|
||||||
|
if type(opts.checked) == "function" then
|
||||||
|
cb:SetChecked(opts.checked())
|
||||||
|
else
|
||||||
|
cb:SetChecked(opts.checked)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if opts.onClick then
|
||||||
|
cb:SetScript("OnClick", opts.onClick)
|
||||||
|
end
|
||||||
|
|
||||||
|
if opts.tooltip and opts.tooltip ~= "" then
|
||||||
|
cb.mthTooltip = opts.tooltip
|
||||||
|
cb:SetScript("OnEnter", function()
|
||||||
|
GameTooltip:SetOwner(cb, "ANCHOR_RIGHT")
|
||||||
|
GameTooltip:SetText(cb.mthTooltip, 1, 1, 1, 1, true)
|
||||||
|
GameTooltip:Show()
|
||||||
|
end)
|
||||||
|
cb:SetScript("OnLeave", function() GameTooltip:Hide() end)
|
||||||
|
end
|
||||||
|
|
||||||
|
local h = 0
|
||||||
|
if txt.GetStringHeight then h = txt:GetStringHeight() end
|
||||||
|
if (not h or h <= 0) and txt.GetHeight then h = txt:GetHeight() end
|
||||||
|
return h or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------
|
||||||
|
-- Box object (returned by panel:Box). Appends rows top-to-bottom and
|
||||||
|
-- keeps the box height in sync with its content.
|
||||||
|
-- ---------------------------------------------------------------------
|
||||||
|
local function makeBox(container, box, boxWidth, state, T)
|
||||||
|
local self = {}
|
||||||
|
|
||||||
|
local function apply()
|
||||||
|
state.height = -state.cursor + T.boxPadBottom
|
||||||
|
box:SetHeight(state.height)
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:Checkbox(name, label, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local cb = ensureFrame("CheckButton", name, box, T.checkTemplate)
|
||||||
|
cb:ClearAllPoints()
|
||||||
|
cb:SetPoint("TOPLEFT", box, "TOPLEFT", T.cbInset, state.cursor)
|
||||||
|
cb:Show()
|
||||||
|
-- Wrap width = box content width minus the checkbox frame, the 4px label
|
||||||
|
-- gap, and a 2px right cushion so wrapped text never touches the border.
|
||||||
|
local cbW = (cb.GetWidth and cb:GetWidth()) or 26
|
||||||
|
local labelWidth = boxWidth - T.boxPadX - (T.cbInset + cbW + 4) - 2
|
||||||
|
local txtH = configureCheckbox(cb, label, opts, T, labelWidth)
|
||||||
|
-- A single line keeps the compact row height; a wrapped label grows the
|
||||||
|
-- row to clear its top-centre offset plus a gap before the next row.
|
||||||
|
local rowH = T.rowCheckbox
|
||||||
|
local needed = txtH + 8
|
||||||
|
if txtH > (T.textLine + 4) then needed = txtH + 14 end
|
||||||
|
if needed > rowH then rowH = needed end
|
||||||
|
state.cursor = state.cursor - rowH
|
||||||
|
apply()
|
||||||
|
return cb
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:Text(name, text, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local fs = ensureFontString(box, name, opts.font or T.fontText)
|
||||||
|
fs:ClearAllPoints()
|
||||||
|
fs:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
|
||||||
|
fs:SetWidth(opts.width or (boxWidth - T.boxPadX * 2))
|
||||||
|
fs:SetJustifyH("LEFT")
|
||||||
|
fs:SetJustifyV("TOP")
|
||||||
|
fs:SetText(text or "")
|
||||||
|
applyColor(fs, opts.color or T.colText)
|
||||||
|
-- Reserve vertical space: honour an explicit line count, otherwise
|
||||||
|
-- measure the wrapped height so callers don't have to guess.
|
||||||
|
local reserve
|
||||||
|
if opts.lines then
|
||||||
|
reserve = opts.lines * T.textLine
|
||||||
|
else
|
||||||
|
local h = (fs.GetStringHeight and fs:GetStringHeight()) or 0
|
||||||
|
if (not h or h <= 0) and fs.GetHeight then h = fs:GetHeight() end
|
||||||
|
if not h or h <= 0 then h = T.textLine end
|
||||||
|
reserve = h
|
||||||
|
end
|
||||||
|
state.cursor = state.cursor - reserve - T.textGap
|
||||||
|
apply()
|
||||||
|
return fs
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Blue helper paragraph (same as MM Widget style), usable inside a box.
|
||||||
|
function self:Note(name, text, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
opts.color = opts.color or T.colNote
|
||||||
|
opts.font = opts.font or T.fontNote
|
||||||
|
return self:Text(name, text, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- One row of buttons placed left-to-right.
|
||||||
|
-- list = { { name, label, width, height, onClick, gap, template }, ... }
|
||||||
|
function self:Buttons(list)
|
||||||
|
local out = {}
|
||||||
|
local x = T.boxPadX
|
||||||
|
local i = 1
|
||||||
|
while list and i <= table.getn(list) do
|
||||||
|
local spec = list[i]
|
||||||
|
local b = ensureFrame("Button", spec.name, box, spec.template or T.buttonTemplate)
|
||||||
|
b:ClearAllPoints()
|
||||||
|
b:SetPoint("TOPLEFT", box, "TOPLEFT", x, state.cursor)
|
||||||
|
b:SetWidth(spec.width or 90)
|
||||||
|
b:SetHeight(spec.height or 22)
|
||||||
|
b:SetText(spec.label or "")
|
||||||
|
b:Show()
|
||||||
|
if spec.onClick then b:SetScript("OnClick", spec.onClick) end
|
||||||
|
table.insert(out, b)
|
||||||
|
x = x + (spec.width or 90) + (spec.gap or 8)
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
state.cursor = state.cursor - T.rowButton
|
||||||
|
apply()
|
||||||
|
return out
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Label + edit box on one row (e.g. "Keep open bag slots: [__]").
|
||||||
|
function self:EditRow(labelName, labelText, editName, editWidth, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local lbl = ensureFontString(box, labelName, T.fontLabel)
|
||||||
|
lbl:ClearAllPoints()
|
||||||
|
lbl:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
|
||||||
|
lbl:SetText(labelText or "")
|
||||||
|
applyColor(lbl, T.colText)
|
||||||
|
|
||||||
|
local edit = ensureFrame("EditBox", editName, box, T.editTemplate)
|
||||||
|
edit:ClearAllPoints()
|
||||||
|
edit:SetPoint("LEFT", lbl, "RIGHT", 8, 0)
|
||||||
|
edit:SetWidth(editWidth or 40)
|
||||||
|
edit:SetHeight(opts.height or 20)
|
||||||
|
if opts.numeric then edit:SetNumeric(true) end
|
||||||
|
edit:SetAutoFocus(false)
|
||||||
|
edit:Show()
|
||||||
|
if opts.onChange then edit:SetScript("OnTextChanged", opts.onChange) end
|
||||||
|
edit:SetScript("OnEnterPressed", function() if this then this:ClearFocus() end end)
|
||||||
|
edit:SetScript("OnEscapePressed", function() if this then this:ClearFocus() end end)
|
||||||
|
|
||||||
|
state.cursor = state.cursor - T.rowCheckbox
|
||||||
|
apply()
|
||||||
|
return edit, lbl
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Slider with a left label and a right-aligned live value readout.
|
||||||
|
-- opts = { label, min, max, step, value, width, onChange, format }
|
||||||
|
-- format(value) -> string (defaults to a rounded integer).
|
||||||
|
function self:Slider(name, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local lbl = ensureFontString(box, name .. "Caption", T.fontLabel)
|
||||||
|
lbl:ClearAllPoints()
|
||||||
|
lbl:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
|
||||||
|
lbl:SetText(opts.label or "")
|
||||||
|
applyColor(lbl, T.colText)
|
||||||
|
|
||||||
|
local valueFs = ensureFontString(box, name .. "Value", T.fontLabel)
|
||||||
|
valueFs:ClearAllPoints()
|
||||||
|
valueFs:SetPoint("TOPRIGHT", box, "TOPRIGHT", -T.boxPadX, state.cursor)
|
||||||
|
valueFs:SetJustifyH("RIGHT")
|
||||||
|
applyColor(valueFs, T.colPanelTitle)
|
||||||
|
|
||||||
|
local slider = ensureFrame("Slider", name, box, "OptionsSliderTemplate")
|
||||||
|
slider:ClearAllPoints()
|
||||||
|
slider:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX + 4, state.cursor - 18)
|
||||||
|
slider:SetWidth(opts.width or (boxWidth - T.boxPadX * 2 - 8))
|
||||||
|
slider:SetMinMaxValues(opts.min or 0, opts.max or 1)
|
||||||
|
slider:SetValueStep(opts.step or 1)
|
||||||
|
slider:Show()
|
||||||
|
|
||||||
|
-- OptionsSliderTemplate ships Low/High/Text children; silence them.
|
||||||
|
local lowFs = getglobal(name .. "Low"); if lowFs then lowFs:SetText(""); lowFs:Hide() end
|
||||||
|
local highFs = getglobal(name .. "High"); if highFs then highFs:SetText(""); highFs:Hide() end
|
||||||
|
local midFs = getglobal(name .. "Text"); if midFs then midFs:SetText("") end
|
||||||
|
|
||||||
|
slider.mthValueFs = valueFs
|
||||||
|
slider.mthFormat = opts.format
|
||||||
|
slider.mthOnChange = opts.onChange
|
||||||
|
slider:SetScript("OnValueChanged", function()
|
||||||
|
local v = tonumber(arg1)
|
||||||
|
if not v and this and this.GetValue then v = this:GetValue() end
|
||||||
|
if not v then v = 0 end
|
||||||
|
if this.mthValueFs then
|
||||||
|
if this.mthFormat then
|
||||||
|
this.mthValueFs:SetText(this.mthFormat(v))
|
||||||
|
else
|
||||||
|
this.mthValueFs:SetText(tostring(math.floor(v + 0.5)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if this.mthOnChange then this.mthOnChange(v) end
|
||||||
|
end)
|
||||||
|
slider:SetValue(opts.value or opts.min or 0)
|
||||||
|
|
||||||
|
state.cursor = state.cursor - T.rowSlider
|
||||||
|
apply()
|
||||||
|
return slider
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Dropdown menu with a left label. The caller supplies the standard
|
||||||
|
-- UIDropDownMenu initialize function and (optionally) the current text.
|
||||||
|
-- opts = { label, width, initialize, text }
|
||||||
|
function self:Dropdown(name, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local lbl = ensureFontString(box, name .. "Caption", T.fontLabel)
|
||||||
|
lbl:ClearAllPoints()
|
||||||
|
lbl:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
|
||||||
|
lbl:SetText(opts.label or "")
|
||||||
|
applyColor(lbl, T.colText)
|
||||||
|
|
||||||
|
local dd = ensureFrame("Frame", name, box, "UIDropDownMenuTemplate")
|
||||||
|
dd:ClearAllPoints()
|
||||||
|
-- UIDropDownMenu textures carry ~15px of built-in left inset.
|
||||||
|
dd:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX - 15, state.cursor - 16)
|
||||||
|
dd:Show()
|
||||||
|
if UIDropDownMenu_SetWidth then
|
||||||
|
UIDropDownMenu_SetWidth(opts.width or (boxWidth - T.boxPadX * 2 - 20), dd)
|
||||||
|
end
|
||||||
|
if UIDropDownMenu_JustifyText then UIDropDownMenu_JustifyText("LEFT", dd) end
|
||||||
|
if opts.initialize and UIDropDownMenu_Initialize then
|
||||||
|
UIDropDownMenu_Initialize(dd, opts.initialize)
|
||||||
|
end
|
||||||
|
if opts.text and UIDropDownMenu_SetText then
|
||||||
|
UIDropDownMenu_SetText(opts.text, dd)
|
||||||
|
end
|
||||||
|
|
||||||
|
state.cursor = state.cursor - T.rowDropdown
|
||||||
|
apply()
|
||||||
|
return dd
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Single button occupying one button row (thin wrapper over :Buttons).
|
||||||
|
function self:Button(name, label, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local out = self:Buttons({ {
|
||||||
|
name = name, label = label,
|
||||||
|
width = opts.width, height = opts.height,
|
||||||
|
onClick = opts.onClick, template = opts.template,
|
||||||
|
} })
|
||||||
|
return out[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Label on the left, a colour swatch + "Pick" button on the right.
|
||||||
|
-- opts = { label, color = {r,g,b}, buttonText, buttonWidth, onClick }
|
||||||
|
function self:ColorRow(name, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local lbl = ensureFontString(box, name .. "Caption", T.fontLabel)
|
||||||
|
lbl:ClearAllPoints()
|
||||||
|
lbl:SetPoint("TOPLEFT", box, "TOPLEFT", T.boxPadX, state.cursor)
|
||||||
|
lbl:SetText(opts.label or "")
|
||||||
|
applyColor(lbl, T.colText)
|
||||||
|
|
||||||
|
local btn = ensureFrame("Button", name .. "Button", box, T.buttonTemplate)
|
||||||
|
btn:ClearAllPoints()
|
||||||
|
btn:SetPoint("TOPRIGHT", box, "TOPRIGHT", -T.boxPadX, state.cursor + 2)
|
||||||
|
btn:SetWidth(opts.buttonWidth or 60)
|
||||||
|
btn:SetHeight(20)
|
||||||
|
btn:SetText(opts.buttonText or "Pick")
|
||||||
|
btn:Show()
|
||||||
|
if opts.onClick then btn:SetScript("OnClick", opts.onClick) end
|
||||||
|
|
||||||
|
local swatch = getglobal(name .. "Swatch")
|
||||||
|
if not swatch then
|
||||||
|
swatch = btn:CreateTexture(name .. "Swatch", "OVERLAY")
|
||||||
|
swatch:SetTexture("Interface\\Buttons\\WHITE8X8")
|
||||||
|
swatch:SetWidth(12)
|
||||||
|
swatch:SetHeight(12)
|
||||||
|
swatch:SetPoint("LEFT", btn, "LEFT", 5, 0)
|
||||||
|
end
|
||||||
|
if opts.color then
|
||||||
|
swatch:SetVertexColor(opts.color[1], opts.color[2], opts.color[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
state.cursor = state.cursor - T.rowCheckbox
|
||||||
|
apply()
|
||||||
|
return btn, swatch
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Manual vertical spacer.
|
||||||
|
function self:Gap(px)
|
||||||
|
state.cursor = state.cursor - (px or 12)
|
||||||
|
apply()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Reserve a custom row of the given pixel height. Returns the box frame and
|
||||||
|
-- the TOPLEFT y-offset (within the box) where custom widgets can anchor.
|
||||||
|
-- Use for composite rows the primitives don't cover (e.g. checkbox +
|
||||||
|
-- dropdown + edit box on one line). x anchoring is left to the caller.
|
||||||
|
function self:Row(height)
|
||||||
|
local y = state.cursor
|
||||||
|
state.cursor = state.cursor - (height or T.rowCheckbox)
|
||||||
|
apply()
|
||||||
|
return box, y
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Left content inset (px) for callers positioning custom row widgets.
|
||||||
|
function self:PadX() return T.boxPadX end
|
||||||
|
|
||||||
|
function self:Frame() return box end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------
|
||||||
|
-- Panel object (returned by MTH_Layout.Panel).
|
||||||
|
-- ---------------------------------------------------------------------
|
||||||
|
function L.Panel(container)
|
||||||
|
if not container then return nil end
|
||||||
|
local T = L.Theme
|
||||||
|
MTH_ClearContainer(container)
|
||||||
|
|
||||||
|
local cname = (container.GetName and container:GetName()) or "MTHPanel"
|
||||||
|
local width = (container.GetWidth and container:GetWidth()) or 0
|
||||||
|
if not width or width < 460 then width = 580 end
|
||||||
|
|
||||||
|
local colWidth = math.floor((width - T.panelPad * 2 - T.colGap) / 2)
|
||||||
|
if colWidth < 220 then colWidth = 220 end
|
||||||
|
local leftX = T.panelPad
|
||||||
|
local rightX = T.panelPad + colWidth + T.colGap
|
||||||
|
local fullWidth = width - T.panelPad * 2
|
||||||
|
|
||||||
|
local headY = T.headTop
|
||||||
|
local started = false
|
||||||
|
local col = {
|
||||||
|
left = { x = leftX, y = 0, open = nil },
|
||||||
|
right = { x = rightX, y = 0, open = nil },
|
||||||
|
}
|
||||||
|
local noteId = 0
|
||||||
|
|
||||||
|
local panel = {}
|
||||||
|
|
||||||
|
local function startColumns()
|
||||||
|
if started then return end
|
||||||
|
started = true
|
||||||
|
local top = headY - T.colTopGap
|
||||||
|
col.left.y = top
|
||||||
|
col.right.y = top
|
||||||
|
end
|
||||||
|
|
||||||
|
local function closeSide(side)
|
||||||
|
local c = col[side]
|
||||||
|
if c and c.open then
|
||||||
|
c.y = c.y - c.open.height - T.boxGap
|
||||||
|
c.open = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---- Header elements (full width, above the columns) ----
|
||||||
|
function panel:Title(text)
|
||||||
|
local fs = ensureFontString(container, cname .. "_Title", T.fontPanelTitle)
|
||||||
|
fs:ClearAllPoints()
|
||||||
|
fs:SetPoint("TOPLEFT", container, "TOPLEFT", T.panelPad, headY)
|
||||||
|
fs:SetText(text or "")
|
||||||
|
applyColor(fs, T.colPanelTitle)
|
||||||
|
headY = headY - T.headTitleStep
|
||||||
|
return fs
|
||||||
|
end
|
||||||
|
|
||||||
|
function panel:Note(text, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
noteId = noteId + 1
|
||||||
|
local fs = ensureFontString(container, cname .. "_Note" .. noteId, T.fontNote)
|
||||||
|
fs:ClearAllPoints()
|
||||||
|
fs:SetPoint("TOPLEFT", container, "TOPLEFT", T.panelPad, headY)
|
||||||
|
fs:SetWidth(opts.width or fullWidth)
|
||||||
|
fs:SetJustifyH("LEFT")
|
||||||
|
fs:SetJustifyV("TOP")
|
||||||
|
fs:SetText(text or "")
|
||||||
|
applyColor(fs, opts.color or T.colNote)
|
||||||
|
local lines = opts.lines or 1
|
||||||
|
headY = headY - (lines * T.textLine) - T.headNoteGap
|
||||||
|
return fs
|
||||||
|
end
|
||||||
|
|
||||||
|
function panel:Link(name, text, onClick)
|
||||||
|
local btn = ensureFrame("Button", name, container, nil)
|
||||||
|
btn:ClearAllPoints()
|
||||||
|
btn:SetPoint("TOPLEFT", container, "TOPLEFT", T.panelPad, headY)
|
||||||
|
btn:SetHeight(16)
|
||||||
|
btn:SetWidth(fullWidth)
|
||||||
|
local fs = getglobal(name .. "Text")
|
||||||
|
if not fs then
|
||||||
|
fs = btn:CreateFontString(name .. "Text", "ARTWORK", T.fontLink)
|
||||||
|
fs:SetPoint("LEFT", btn, "LEFT", 0, 0)
|
||||||
|
fs:SetJustifyH("LEFT")
|
||||||
|
end
|
||||||
|
fs:SetText(text or "")
|
||||||
|
applyColor(fs, T.colLink)
|
||||||
|
btn:Show()
|
||||||
|
btn:SetScript("OnEnter", function() applyColor(fs, T.colLinkHover) end)
|
||||||
|
btn:SetScript("OnLeave", function() applyColor(fs, T.colLink) end)
|
||||||
|
if onClick then btn:SetScript("OnClick", onClick) end
|
||||||
|
headY = headY - T.headLinkStep
|
||||||
|
return btn
|
||||||
|
end
|
||||||
|
|
||||||
|
function panel:TopCheckbox(name, label, opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local cb = ensureFrame("CheckButton", name, container, T.checkTemplate)
|
||||||
|
cb:ClearAllPoints()
|
||||||
|
cb:SetPoint("TOPLEFT", container, "TOPLEFT", T.panelPad, headY)
|
||||||
|
cb:Show()
|
||||||
|
local txtH = configureCheckbox(cb, label, opts, T, fullWidth - 26)
|
||||||
|
local rowH = T.rowCheckbox
|
||||||
|
if (txtH + 8) > rowH then rowH = txtH + 8 end
|
||||||
|
headY = headY - rowH - T.headRowGap
|
||||||
|
return cb
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ---- Boxes (columns) ----
|
||||||
|
function panel:Box(side, name, title)
|
||||||
|
startColumns()
|
||||||
|
side = (side == "right") and "right" or "left"
|
||||||
|
closeSide(side)
|
||||||
|
local c = col[side]
|
||||||
|
|
||||||
|
local box = ensureFrame("Frame", name, container, T.boxTemplate)
|
||||||
|
box:ClearAllPoints()
|
||||||
|
box:SetPoint("TOPLEFT", container, "TOPLEFT", c.x, c.y)
|
||||||
|
box:SetWidth(colWidth)
|
||||||
|
box:Show()
|
||||||
|
|
||||||
|
local titleFS = getglobal(name .. "Title")
|
||||||
|
if titleFS then
|
||||||
|
titleFS:SetText(title or "")
|
||||||
|
applyColor(titleFS, T.colBoxTitle)
|
||||||
|
titleFS:ClearAllPoints()
|
||||||
|
titleFS:SetPoint("TOPLEFT", box, "TOPLEFT", T.titleInsetX, T.titleInsetY)
|
||||||
|
end
|
||||||
|
|
||||||
|
local state = {
|
||||||
|
cursor = -T.boxPadTop,
|
||||||
|
height = T.boxPadTop + T.boxPadBottom,
|
||||||
|
}
|
||||||
|
box:SetHeight(state.height)
|
||||||
|
c.open = state
|
||||||
|
|
||||||
|
return makeBox(container, box, colWidth, state, T)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns "left" or "right": whichever column currently has more room
|
||||||
|
-- left (i.e. its content bottom is higher). Lets callers auto-balance
|
||||||
|
-- a variable number of boxes without hand-picking columns.
|
||||||
|
function panel:ShorterSide()
|
||||||
|
startColumns()
|
||||||
|
local function bottom(side)
|
||||||
|
local c = col[side]
|
||||||
|
local y = c.y
|
||||||
|
if c.open then y = y - c.open.height - T.boxGap end
|
||||||
|
return y
|
||||||
|
end
|
||||||
|
if bottom("right") > bottom("left") then return "right" end
|
||||||
|
return "left"
|
||||||
|
end
|
||||||
|
|
||||||
|
function panel:Finish()
|
||||||
|
closeSide("left")
|
||||||
|
closeSide("right")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Expose geometry for callers that need it (rare).
|
||||||
|
panel.colWidth = colWidth
|
||||||
|
panel.fullWidth = fullWidth
|
||||||
|
|
||||||
|
return panel
|
||||||
|
end
|
||||||
@@ -300,11 +300,10 @@ function MTH_SetupProfilesOptions()
|
|||||||
if not container then return end
|
if not container then return end
|
||||||
|
|
||||||
if not gSetupDone then
|
if not gSetupDone then
|
||||||
-- Title
|
local panel = MTH_Layout.Panel(container)
|
||||||
local title = container:CreateFontString(nil, "ARTWORK", "GameFontNormal")
|
|
||||||
title:SetPoint("TOPLEFT", container, "TOPLEFT", 6, -6)
|
-- Title (engine header, consistent gold styling)
|
||||||
title:SetText("Profiles")
|
local title = panel:Title("Profiles")
|
||||||
title:SetTextColor(1.00, 0.82, 0.00)
|
|
||||||
|
|
||||||
-- Active profile indicator
|
-- Active profile indicator
|
||||||
gActiveLabel = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
gActiveLabel = container:CreateFontString(nil, "ARTWORK", "GameFontNormalSmall")
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ local MTH_OPTIONS_SETUP = {} -- Track which frames have been set up
|
|||||||
MTH_OPTIONS_CONST = MTH_OPTIONS_CONST or {}
|
MTH_OPTIONS_CONST = MTH_OPTIONS_CONST or {}
|
||||||
MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH = MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH or 120
|
MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH = MTH_OPTIONS_CONST.NAV_DEFAULT_WIDTH or 120
|
||||||
MTH_OPTIONS_CONST.WINDOW_PADDING = MTH_OPTIONS_CONST.WINDOW_PADDING or 12
|
MTH_OPTIONS_CONST.WINDOW_PADDING = MTH_OPTIONS_CONST.WINDOW_PADDING or 12
|
||||||
MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET = MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET or -58
|
MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET = MTH_OPTIONS_CONST.CONTENT_TOP_OFFSET or -30
|
||||||
MTH_OPTIONS_CONST.CONTENT_HEIGHT = MTH_OPTIONS_CONST.CONTENT_HEIGHT or 566
|
MTH_OPTIONS_CONST.CONTENT_HEIGHT = MTH_OPTIONS_CONST.CONTENT_HEIGHT or 600
|
||||||
MTH_OPTIONS_CONST.CLOSE_BTN_SIZE = MTH_OPTIONS_CONST.CLOSE_BTN_SIZE or 22
|
MTH_OPTIONS_CONST.CLOSE_BTN_SIZE = MTH_OPTIONS_CONST.CLOSE_BTN_SIZE or 22
|
||||||
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X or -8
|
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_X or -8
|
||||||
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y or -8
|
MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y = MTH_OPTIONS_CONST.CLOSE_BTN_OFFSET_Y or -8
|
||||||
|
|||||||
+476
-750
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -46,12 +46,12 @@
|
|||||||
<Frames>
|
<Frames>
|
||||||
<Frame name="$parentNav" enableMouse="true">
|
<Frame name="$parentNav" enableMouse="true">
|
||||||
<Size>
|
<Size>
|
||||||
<AbsDimension x="120" y="566"/>
|
<AbsDimension x="120" y="600"/>
|
||||||
</Size>
|
</Size>
|
||||||
<Anchors>
|
<Anchors>
|
||||||
<Anchor point="TOPLEFT">
|
<Anchor point="TOPLEFT">
|
||||||
<Offset>
|
<Offset>
|
||||||
<AbsDimension x="12" y="-58"/>
|
<AbsDimension x="12" y="-30"/>
|
||||||
</Offset>
|
</Offset>
|
||||||
</Anchor>
|
</Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
|
|||||||
@@ -1,23 +1,5 @@
|
|||||||
-- MetaHunt: auto-train Growl to a freshly tamed pet.
|
-- MetaHunt: auto-train Growl to a freshly tamed pet.
|
||||||
--
|
--
|
||||||
-- Growl is a "trainer" pet ability (Growl / Great Stamina / Natural Armor /
|
|
||||||
-- Great Resistance) that the hunter learns from a Pet Trainer NPC and then
|
|
||||||
-- teaches to the active pet through the always-available BEAST TRAINING window
|
|
||||||
-- (a spellbook-like hunter spell, no NPC required). Growl specifically costs
|
|
||||||
-- 0 training points, so it can always be taught to a brand-new pet.
|
|
||||||
--
|
|
||||||
-- The Beast Training window is driven by the vanilla Craft API:
|
|
||||||
-- GetNumCrafts() -> number of rows
|
|
||||||
-- GetCraftInfo(i) -> name, rankSubText, type, ...
|
|
||||||
-- DoCraft(i) -> trains that row (the "Select + Train" action)
|
|
||||||
-- CloseCraft() -> closes the window
|
|
||||||
--
|
|
||||||
-- The correct Growl rank is a function of the pet's level:
|
|
||||||
-- rank = floor(level / 10) + 1 (ranks 1..7, at pet levels 1/10/.../60)
|
|
||||||
--
|
|
||||||
-- Flow on a confirmed fresh tame (when enabled): compute the target rank, open
|
|
||||||
-- the Beast Training window, find the Growl row at that rank once the craft list
|
|
||||||
-- populates, DoCraft() it silently, then close the window if we opened it.
|
|
||||||
|
|
||||||
local MTH_GROWL_MAX_RANK = 7
|
local MTH_GROWL_MAX_RANK = 7
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<Include file="..\api\options-tree.lua"/>
|
<Include file="..\api\options-tree.lua"/>
|
||||||
<Include file="..\api\options.xml"/>
|
<Include file="..\api\options.xml"/>
|
||||||
<Include file="..\api\options.lua"/>
|
<Include file="..\api\options.lua"/>
|
||||||
|
<Include file="..\api\options-layout.lua"/>
|
||||||
<Include file="..\api\options-chronometer.lua"/>
|
<Include file="..\api\options-chronometer.lua"/>
|
||||||
<Include file="..\api\options-credits.lua"/>
|
<Include file="..\api\options-credits.lua"/>
|
||||||
<Include file="..\api\options-animations.lua"/>
|
<Include file="..\api\options-animations.lua"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user