From c4864c581807da1a50d7f70a866fbfdf5d717d7c Mon Sep 17 00:00:00 2001 From: Relationship <139162359+Relationship-OctoWoW@users.noreply.github.com> Date: Fri, 10 Jul 2026 13:36:10 +0100 Subject: [PATCH] Add files via upload --- CMap.lua | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++ COptions.lua | 4 +- 2 files changed, 156 insertions(+), 2 deletions(-) diff --git a/CMap.lua b/CMap.lua index 5d51699..ea7e922 100644 --- a/CMap.lua +++ b/CMap.lua @@ -134,6 +134,9 @@ local function MigrateSavedVariables() if not SexyMap2DB.userPresets then SexyMap2DB.userPresets = {} end + if not SexyMap2DB.buttonPositions then + SexyMap2DB.buttonPositions = {} + end -- Mark the current version so migration doesn't re-run needlessly -- (but the checks above still protect against manually-edited bad data) @@ -182,6 +185,7 @@ function CMap_OnEvent() CUpdateMinimapVisibility() CApplyMapScale() CLoadArtwork() + CApplyButtonPositions() SlashCmdList["CMAP"] = CMap_SlashCmdHandler SLASH_CMAP1 = "/cm" SLASH_CMAP2 = "/sm" @@ -337,6 +341,152 @@ local function RestoreButtonPoints(frame) hiddenBtnOrigPoints[frame] = nil end +-- ============================================ +-- Persistent minimap button positions +-- ============================================ +-- Minimap buttons are children of the (scaled) MinimapCluster / Minimap. +-- When the user drags one, we save its position in UIParent screen space +-- (i.e. multiplied by its effective scale, divided by UIParent effective +-- scale) so that changing the map scale later does NOT visually move the +-- button. On login we restore that same on-screen center regardless of +-- the current map scale. + +-- Frames we have already made draggable / hooked (avoid double-hooking). +local dragEnabledButtons = {} + +-- Save a frame's on-screen center to SavedVariables, keyed by frame name. +local function CSaveButtonScreenPos(frame) + if not frame or not frame.GetName or not frame.GetCenter then return end + local name = frame:GetName() + if not name or name == "" then return end + local x, y = frame:GetCenter() + if not x or not y then return end + local fScale = frame:GetEffectiveScale() or 1 + local uScale = UIParent:GetEffectiveScale() or 1 + if uScale == 0 then uScale = 1 end + -- Convert into UIParent-space (screen) coordinates. + local ux = x * fScale / uScale + local uy = y * fScale / uScale + if not SexyMap2DB.buttonPositions then + SexyMap2DB.buttonPositions = {} + end + SexyMap2DB.buttonPositions[name] = { x = ux, y = uy } +end + +-- Restore a frame to its saved on-screen center, compensating for the +-- current parent scale so it lands in the same screen pixel. +local function CRestoreButtonScreenPos(frame) + if not frame or not frame.GetName or not frame.ClearAllPoints then return end + local name = frame:GetName() + if not name or name == "" then return end + if not SexyMap2DB.buttonPositions then return end + local saved = SexyMap2DB.buttonPositions[name] + if not saved or not saved.x or not saved.y then return end + local fScale = frame:GetEffectiveScale() or 1 + if fScale == 0 then fScale = 1 end + local uScale = UIParent:GetEffectiveScale() or 1 + -- Convert UIParent-space coords back into the frame's own coord space. + local fx = saved.x * uScale / fScale + local fy = saved.y * uScale / fScale + frame:ClearAllPoints() + frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", fx, fy) +end + +-- OnDragStart / OnDragStop handlers used by hooked buttons. +local function CButton_OnDragStart() + if this and this.StartMoving then + this:StartMoving() + end +end + +local function CButton_OnDragStop() + if this then + if this.StopMovingOrSizing then this:StopMovingOrSizing() end + CSaveButtonScreenPos(this) + end +end + +-- Make a single frame movable + save on drag stop. Safe to call repeatedly. +local function CEnableDragForButton(frame) + if not frame or dragEnabledButtons[frame] then return end + -- Guard: must be a real Frame-derived object (not a Texture/FontString). + if type(frame) ~= "table" or not frame.GetObjectType then return end + local ok, objType = pcall(frame.GetObjectType, frame) + if not ok or not objType then return end + if objType ~= "Frame" and objType ~= "Button" and objType ~= "CheckButton" then return end + if not frame.GetScript or not frame.SetScript then return end + local name = frame:GetName() + if not name or name == "" then return end + if frame.SetMovable then frame:SetMovable(true) end + if frame.RegisterForDrag then frame:RegisterForDrag("LeftButton") end + local origStart = frame:GetScript("OnDragStart") + local origStop = frame:GetScript("OnDragStop") + frame:SetScript("OnDragStart", function() + if origStart then origStart() end + CButton_OnDragStart() + end) + frame:SetScript("OnDragStop", function() + CButton_OnDragStop() + if origStop then origStop() end + end) + dragEnabledButtons[frame] = true +end + +-- Iterate all current minimap side buttons: make them draggable and +-- restore any saved position. Called on login (after CApplyMapScale) and +-- again whenever the map scale changes. +function CApplyButtonPositions() + if not Minimap then return end + + local excludeNames = { + ["MinimapZoomIn"] = true, + ["MinimapZoomOut"] = true, + ["MinimapToggleButton"] = true, + ["CMinimapBackdrop"] = true, + ["MinimapPing"] = true, + ["MiniMapPing"] = true, + } + + -- Named side buttons + local namedFrames = { + "MiniMapTracking", "MiniMapTrackingButton", "MiniMapTrackingFrame", + "MiniMapMailFrame", "MiniMapMailBorder", + "MiniMapBattlefieldFrame", "MiniMapMeetingStoneFrame", + "MiniMapWorldMapButton", "MinimapVoiceChatFrame", "MiniMapLFGFrame", + "GameTimeFrame", + } + for _, n in ipairs(namedFrames) do + local f = _G[n] + if f then + CEnableDragForButton(f) + if SexyMap2DB.buttonPositions and SexyMap2DB.buttonPositions[n] then + CRestoreButtonScreenPos(f) + end + end + end + + -- Any addon buttons parented to Minimap + local children = { Minimap:GetChildren() } + for _, frame in ipairs(children) do + local objType = frame:GetObjectType() + if objType == "Button" or objType == "CheckButton" then + local name = frame:GetName() or "" + if name ~= "" and not excludeNames[name] + and not string.find(name, "POI") + and not string.find(name, "[Qq]uest") + and not string.find(name, "^MinimapPin") + and not string.find(name, "^MiniMapPOI") + and not string.find(name, "[Pp]in%d") + then + CEnableDragForButton(frame) + if SexyMap2DB.buttonPositions and SexyMap2DB.buttonPositions[name] then + CRestoreButtonScreenPos(frame) + end + end + end + end +end + function CUpdateMinimapButtonsVisibility() if SexyMap2DB.showMinimapButtons then -- Show only the buttons we previously hid (preserves original visibility) @@ -461,6 +611,10 @@ function CApplyMapScale() -- Update border textures to match new minimap size CUpdateBackdrop() + + -- Re-place any user-positioned minimap buttons so they stay in the + -- same on-screen spot regardless of the new scale. + if CApplyButtonPositions then CApplyButtonPositions() end end function CUpdateZoneText() diff --git a/COptions.lua b/COptions.lua index 2584862..a5b3a58 100644 --- a/COptions.lua +++ b/COptions.lua @@ -381,8 +381,8 @@ function CMapScaleSlider_Update() if val < 0.3 then val = 0.3 end if val > 1.0 then val = 1.0 end CMapScaleSlider:SetValue(val) - CMapScaleSliderLowText:SetText("0.30") - CMapScaleSliderHighText:SetText("1.00") + CMapScaleSliderLow:SetText("0.30") + CMapScaleSliderHigh:SetText("1.00") CMapScaleSliderValueText:SetText(string.format("%.2f", val)) end