diff --git a/Config.lua b/Config.lua index a148697..0bfed11 100644 --- a/Config.lua +++ b/Config.lua @@ -7,6 +7,9 @@ F.Config = { questTrackingEnabled = true, showTicks = true, tickOpacity = 0.35, + anchorPoint = "TOP", + offsetX = 0, + offsetY = 100, -- Master visibility toggle (can be flipped with /nxp toggle) enabled = true, diff --git a/Options.lua b/Options.lua index 087f9df..881a483 100644 --- a/Options.lua +++ b/Options.lua @@ -156,6 +156,65 @@ local function CreateSlider(parent, key, label, y, minValue, maxValue, step) return y - 52 end +local function CreateSliderWithInput(parent, key, label, y, minValue, maxValue, step, inputWidth) + local name = "NXP_Options_" .. key .. "Slider" + local slider = CreateFrame("Slider", name, parent, "OptionsSliderTemplate") + slider:SetPoint("TOPLEFT", parent, "TOPLEFT", 16, y) + slider:SetMinMaxValues(minValue, maxValue) + slider:SetValueStep(step) + slider:SetObeyStepOnDrag(true) + + local labelText = _G[name .. "Text"] + local lowText = _G[name .. "Low"] + local highText = _G[name .. "High"] + if labelText then labelText:SetText(label) end + if lowText then lowText:SetText(tostring(minValue)) end + if highText then highText:SetText(tostring(maxValue)) end + + local edit = CreateFrame("EditBox", nil, parent, "InputBoxTemplate") + edit:SetAutoFocus(false) + edit:SetSize(inputWidth or 60, 20) + edit:SetPoint("LEFT", slider, "RIGHT", 12, 0) + edit:SetNumeric(true) + + slider:SetScript("OnValueChanged", function(self, value) + if self._updating then return end + local rounded = math.floor(value + 0.5) + if step and step < 1 then + rounded = value + end + self._updating = true + self:SetValue(rounded) + self._updating = false + edit:SetNumber(rounded) + SetNumericOption(key, rounded) + end) + + local function commitEdit() + local value = tonumber(edit:GetText()) + if not value then return end + if value < minValue then value = minValue end + if value > maxValue then value = maxValue end + slider._updating = true + slider:SetValue(value) + slider._updating = false + edit:SetNumber(value) + SetNumericOption(key, value) + end + + edit:SetScript("OnEnterPressed", function(self) + commitEdit() + self:ClearFocus() + end) + + edit:SetScript("OnEditFocusLost", function() + commitEdit() + end) + + controls[key] = { type = "offset", slider = slider, edit = edit } + return y - 52 +end + local function BuildMediaList(kind, defaultLabel, defaultValue) local list = {} local order = {} @@ -306,6 +365,14 @@ function F.Options.Refresh() local r, g, b, a = GetColorOption(key, control.fallback) local tex = control.widget:GetNormalTexture() if tex then tex:SetColorTexture(r, g, b, a) end + elseif control.type == "offset" then + local value = F.DB[key] + if value == nil then value = defaults[key] end + if value == nil then value = 0 end + control.slider._updating = true + control.slider:SetValue(tonumber(value) or 0) + control.slider._updating = false + control.edit:SetNumber(tonumber(value) or 0) elseif control.type == "dropdown" then local defaults = F.Config or {} local value = F.DB[key] @@ -377,6 +444,21 @@ function F.Options.Create() y = y - 6 y = CreateSlider(content, "tickOpacity", "Tick opacity", y, 10, 100, 1) + y = y - 10 + y = CreateHeader(content, "Position", y) + y = y - 6 + local anchorList = { + TOP = "Top", + BOTTOM = "Bottom", + LEFT = "Left", + RIGHT = "Right", + CENTER = "Center", + } + local anchorOrder = { "TOP", "BOTTOM", "LEFT", "RIGHT", "CENTER" } + y = CreateDropdown(content, "anchorPoint", "Anchor position", y, anchorList, anchorOrder) + y = CreateSliderWithInput(content, "offsetX", "X offset", y, -1000, 1000, 1, 60) + y = CreateSliderWithInput(content, "offsetY", "Y offset", y, -1000, 1000, 1, 60) + y = y - 10 y = CreateHeader(content, "Bar Size", y) y = y - 6 diff --git a/UI.lua b/UI.lua index b766e84..182c25b 100644 --- a/UI.lua +++ b/UI.lua @@ -32,81 +32,11 @@ end function F.UI.Create() local f = CreateFrame("Frame", "NXP_Frame", UIParent) f:SetSize(CFG.width, CFG.height) - f:SetPoint("BOTTOM", UIParent, "BOTTOM", 0, 260) -- Default Position + f:SetPoint("TOP", UIParent, "TOP", 0, 100) -- Default Position f:SetFrameStrata("LOW") - -- Enable dragging (only while Shift is held) - f:SetMovable(true) + f:SetMovable(false) f:EnableMouse(false) - f:RegisterForDrag("LeftButton") - - local function stopAndMaybeSnap(self) - if self.__nxb_moving then - self:StopMovingOrSizing() - self.__nxb_moving = nil - - local fx, fy = self:GetCenter() - if fx and fy then - local cx, cy = UIParent:GetCenter() - if cx and cy then - local dx, dy = fx - cx, fy - cy - local distSq = dx * dx + dy * dy - local snapRadius = 40 - if distSq <= (snapRadius * snapRadius) then - self:ClearAllPoints() - self:SetPoint("CENTER", UIParent, "CENTER", 0, 0) - end - end - end - - self:SetScript("OnUpdate", nil) - end - end - - f:SetScript("OnDragStart", function(self) - if IsShiftKeyDown() then - self:StartMoving() - self.__nxb_moving = true - - self:SetScript("OnUpdate", function(self, elapsed) - if not IsShiftKeyDown() or not IsMouseButtonDown("LeftButton") then - stopAndMaybeSnap(self) - end - end) - end - end) - - f:SetScript("OnDragStop", stopAndMaybeSnap) - - f:SetScript("OnMouseDown", function(self, button) - if button == "LeftButton" and IsShiftKeyDown() then - self:StartMoving() - self.__nxb_moving = true - - self:SetScript("OnUpdate", function(self, elapsed) - if not IsShiftKeyDown() or not IsMouseButtonDown("LeftButton") then - stopAndMaybeSnap(self) - end - end) - end - end) - - f:SetScript("OnMouseUp", function(self, button) - if button == "LeftButton" then - stopAndMaybeSnap(self) - end - end) - - f:RegisterEvent("MODIFIER_STATE_CHANGED") - f:SetScript("OnEvent", function(self, event, key, state) - if event == "MODIFIER_STATE_CHANGED" then - -- Enable/disable clicks based on Shift state - self:EnableMouse(IsShiftKeyDown()) - if not IsShiftKeyDown() and self.__nxb_moving then - stopAndMaybeSnap(self) - end - end - end) F.Frame = f @@ -238,6 +168,17 @@ function F.UI.Update() F.Frame:SetSize(width or db.barWidth, db.barHeight) end + if db then + local anchor = db.anchorPoint or "TOP" + local x = tonumber(db.offsetX) or 0 + local y = tonumber(db.offsetY) or 0 + if anchor == "TOP" then + y = -y + end + F.Frame:ClearAllPoints() + F.Frame:SetPoint(anchor, UIParent, anchor, x, y) + end + if F.TickContainer then if db and db.showTicks then local width = F.Frame:GetWidth()