From c353ea26300a11bd6bb77e09a2673ec3cd332604 Mon Sep 17 00:00:00 2001 From: xoxorwr Date: Wed, 22 Jul 2026 11:24:30 +0200 Subject: [PATCH 1/3] Allow panes to be pinned --- src/Classes/CalcSectionControl.lua | 410 +++++++++++++++++++++++------ src/Classes/CalcsTab.lua | 12 +- src/Modules/Build.lua | 32 +++ 3 files changed, 364 insertions(+), 90 deletions(-) diff --git a/src/Classes/CalcSectionControl.lua b/src/Classes/CalcSectionControl.lua index 75be52c567e..248ab19ab65 100644 --- a/src/Classes/CalcSectionControl.lua +++ b/src/Classes/CalcSectionControl.lua @@ -49,8 +49,20 @@ local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost" end end end + self.controls.popOut = new("ButtonControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-22, 3, 16, 16}, "^", function() + self:ToggleOverlay() + end) + self.controls.popOut.shown = function() + return self.enabled and not self.isOverlay + end + self.isOverlay = false + self.overlayX = 320 + self.overlayY = 50 + self.dragging = false + self.dragOffX = 0 + self.dragOffY = 0 self.shown = function() - return self.enabled + return self.enabled and not self.isOverlay end end) @@ -160,7 +172,6 @@ end function CalcSectionClass:Draw(viewPort, noTooltip) local x, y = self:GetPos() local width, height = self:GetSize() - local cursorX, cursorY = GetCursorPos() local actor = self.calcsTab.input.showMinion and self.calcsTab.calcsEnv.minion or self.calcsTab.calcsEnv.player -- Draw border and background SetDrawLayer(nil, -10) @@ -168,35 +179,284 @@ function CalcSectionClass:Draw(viewPort, noTooltip) DrawImage(nil, x, y, width, height) SetDrawColor(0.10, 0.10, 0.10) DrawImage(nil, x + 2, y + 2, width - 4, height - 4) - + + self:DrawContent(x, y, width, actor, viewPort, false, noTooltip) +end + +function CalcSectionClass:OnKeyDown(key, doubleClick) + if not self:IsShown() or not self:IsEnabled() then + return + end + local mOverControl = self:GetMouseOverControl() + if mOverControl and mOverControl.OnKeyDown then + return mOverControl:OnKeyDown(key) + end + local mOver, mOverComp = self:IsMouseOver() + if key:match("BUTTON") then + if not mOver then + return + end + if mOverComp then + -- Pin the stat breakdown + self.calcsTab:SetDisplayStat(mOverComp, true) + return self.calcsTab.controls.breakdown + end + end + return +end + +function CalcSectionClass:OnKeyUp(key) + if not self:IsShown() or not self:IsEnabled() then + return + end + local mOverControl = self:GetMouseOverControl() + if mOverControl and mOverControl.OnKeyUp then + return mOverControl:OnKeyUp(key) + end + return +end + +function CalcSectionClass:ToggleOverlay() + self.isOverlay = not self.isOverlay + if self.isOverlay then + local x, y = self:GetPos() + self.overlayX = self.calcsTab.x + x + self.overlayY = self.calcsTab.y + y + t_insert(self.calcsTab.build.overlayPanes, self) + else + local panes = self.calcsTab.build.overlayPanes + for i, pane in ipairs(panes) do + if pane == self then + table.remove(panes, i) + break + end + end + self.dragging = false + end +end + +function CalcSectionClass:RaiseOverlay() + local panes = self.calcsTab.build.overlayPanes + for i, pane in ipairs(panes) do + if pane == self then + table.remove(panes, i) + t_insert(panes, self) + break + end + end +end + +function CalcSectionClass:IsMouseInOverlay(cursorX, cursorY) + if not self.isOverlay or not self.calcsTab.calcsEnv then return false end + local x = self.overlayX + local y = self.overlayY + if cursorX < x or cursorX > x + self.width or cursorY < y then return false end + local h = 28 + for i, subSec in ipairs(self.subSection) do + h = h + 22 + if not subSec.collapsed and self.calcsTab:CheckFlag(self) then + for _, rowData in ipairs(subSec.data) do + if self.calcsTab:CheckFlag(rowData) then + h = h + 18 + end + end + h = h + 2 + end + end + return cursorY < y + h +end + +function CalcSectionClass:HandleOverlayClick(key, cursorX, cursorY) + if key ~= "LEFTBUTTON" then return end + + self:RaiseOverlay() + + local x = self.overlayX + local y = self.overlayY + local overlayWidth = self.width + + -- Check close button + local closeX = x + overlayWidth - 18 + local closeY = y + 2 + if cursorX >= closeX and cursorX <= closeX + 14 and cursorY >= closeY and cursorY <= closeY + 16 then + self:ToggleOverlay() + return + end + + local lineY = y + 26 + local primary = true + for i, subSec in ipairs(self.subSection) do + local secEnabled = self.calcsTab:CheckFlag(self) + + -- Check subsection toggle + if secEnabled then + local toggleX = x + overlayWidth - 18 + local toggleY = lineY + 3 + if cursorX >= toggleX and cursorX <= toggleX + 14 and cursorY >= toggleY and cursorY <= toggleY + 16 then + subSec.collapsed = not subSec.collapsed + self.calcsTab.modFlag = true + return + end + end + + if subSec.collapsed or not secEnabled then + if primary then + break + else + lineY = lineY + 20 + primary = false + end + else + lineY = lineY + 20 + primary = false + for _, rowData in ipairs(subSec.data) do + if self.calcsTab:CheckFlag(rowData) then + for _, colData in ipairs(rowData) do + local cellX = x + (colData.xOffset or 134) + local cellW = colData.width or (overlayWidth - 136) + if cursorX >= cellX and cursorX <= cellX + cellW and cursorY >= lineY + 2 and cursorY <= lineY + 19 then + if colData.format and self.calcsTab:CheckFlag(colData) then + self.calcsTab:SetDisplayStat(colData, true) + end + return + end + end + lineY = lineY + 18 + end + end + lineY = lineY + 2 + end + end + + -- Start dragging + if cursorY >= y and cursorY <= y + 24 then + self.dragging = true + self.dragOffX = cursorX - self.overlayX + self.dragOffY = cursorY - self.overlayY + end +end + +function CalcSectionClass:HandleOverlayRelease(key) + if key == "LEFTBUTTON" then + self.dragging = false + end +end + +function CalcSectionClass:DrawOverlay(viewPort, inputEvents) + local cursorX, cursorY = GetCursorPos() + self.overlayBreakdownCell = nil + + if self.dragging then + self.overlayX = cursorX - self.dragOffX + self.overlayY = cursorY - self.dragOffY + end + + local x = self.overlayX + local y = self.overlayY + local overlayWidth = self.width + local actor = self.calcsTab.calcsEnv and (self.calcsTab.input.showMinion and self.calcsTab.calcsEnv.minion or self.calcsTab.calcsEnv.player) + + -- Calculate content height + local totalHeight = 28 + for i, subSec in ipairs(self.subSection) do + totalHeight = totalHeight + 22 + if actor and not subSec.collapsed and self.calcsTab:CheckFlag(self) then + for _, rowData in ipairs(subSec.data) do + if actor and self.calcsTab:CheckFlag(rowData) then + totalHeight = totalHeight + 18 + end + end + totalHeight = totalHeight + 2 + end + end + + -- Ensure it's above most other controls + SetDrawLayer(12) + + -- Draw background + SetDrawColor(0.08, 0.08, 0.08, 0.95) + DrawImage(nil, x, y, overlayWidth, totalHeight) + + -- Draw border + SetDrawColor(self.colour) + DrawImage(nil, x, y, overlayWidth, 1) + DrawImage(nil, x, y + totalHeight - 1, overlayWidth, 1) + DrawImage(nil, x, y, 1, totalHeight) + DrawImage(nil, x + overlayWidth - 1, y, 1, totalHeight) + + -- Draw header + SetDrawColor(0.18, 0.18, 0.18) + DrawImage(nil, x + 1, y + 1, overlayWidth - 2, 22) + SetDrawColor(1, 1, 1) + local cbx = x + overlayWidth - 16 + local cby = y + 3 + DrawImageQuad(nil, cbx + 3, cby + 5, cbx + 5, cby + 3, cbx + 13, cby + 11, cbx + 11, cby + 13) + DrawImageQuad(nil, cbx + 11, cby + 3, cbx + 13, cby + 5, cbx + 5, cby + 13, cbx + 3, cby + 11) + + -- Separator + SetDrawColor(self.colour) + DrawImage(nil, x + 2, y + 24, overlayWidth - 4, 1) + + -- Draw content + self:DrawContent(x, y + 26, overlayWidth, actor, viewPort, true) + + -- Draw stat breakdown + if self.calcsTab.displayData and (self.overlayBreakdownCell or self.calcsTab.displayPinned) then + local cd = self.calcsTab.displayData + local origX, origY = cd.x, cd.y + cd.x = x + (cd.xOffset or 134) + cd.y = y + 26 + (cd.yOffset or 0) + self.calcsTab.controls.breakdown:Draw(viewPort) + cd.x, cd.y = origX, origY + end + self.overlayBreakdownCell = nil + + SetDrawLayer(0) +end + +function CalcSectionClass:DrawContent(drawX, startLineY, drawWidth, actor, viewPort, isOverlay, noTooltip) + local cursorX, cursorY = GetCursorPos() + local lineY = startLineY local primary = true - local lineY = y + local enabled = isOverlay and (actor and self.calcsTab:CheckFlag(self)) or self.enabled + for _, subSec in ipairs(self.subSection) do - -- Draw line above label + -- Top border SetDrawColor(self.colour) - DrawImage(nil, x + 2, lineY, width - 4, 2) - SetDrawColor(0.10, 0.10, 0.10) - -- Draw label - if not self.enabled then - DrawString(x + 3, lineY + 3, "LEFT", 16, "VAR BOLD", "^8"..subSec.label) + DrawImage(nil, drawX + 2, lineY, drawWidth - 4, 2) + + -- Label + if not enabled then + local lx = isOverlay and drawX + 4 or drawX + 3 + DrawString(lx, lineY + 3, "LEFT", 16, "VAR BOLD", "^8"..(subSec.label or "")) else + local lx = isOverlay and drawX + 4 or drawX + 3 local textColor = "^7" - if self.calcsTab:SearchMatch(subSec.label) then + if not isOverlay and self.calcsTab:SearchMatch(subSec.label) then textColor = colorCodes.HIGHLIGHT end - DrawString(x + 3, lineY + 3, "LEFT", 16, "VAR BOLD", textColor..subSec.label..":") + DrawString(lx, lineY + 3, "LEFT", 16, "VAR BOLD", textColor..(subSec.label or "")..":") if subSec.data.extra then - local x = x + 3 + DrawStringWidth(16, "VAR BOLD", subSec.label) + 10 - DrawString(x, lineY + 3, "LEFT", 16, "VAR", "^7"..formatCalcStr(subSec.data.extra, actor)) + local ex = lx + DrawStringWidth(16, "VAR BOLD", subSec.label) + (isOverlay and 12 or 10) + DrawString(ex, lineY + 3, "LEFT", 16, "VAR", "^7"..formatCalcStr(subSec.data.extra, actor)) end end - -- Draw line below label + + -- Bottom border SetDrawColor(self.colour) - DrawImage(nil, x + 2, lineY + 20, width - 4, 2) - -- Draw controls - SetDrawLayer(nil, 0) - self:DrawControls(viewPort, noTooltip and self.calcsTab.selControl) - if subSec.collapsed or not self.enabled then + DrawImage(nil, drawX + 2, lineY + 20, drawWidth - 4, 2) + + -- Toggle + if isOverlay then + if enabled then + DrawString(drawX + drawWidth - 16, lineY + 3, "LEFT", 14, "VAR", "^7"..(subSec.collapsed and "+" or "-")) + end + else + SetDrawLayer(nil, 0) + self:DrawControls(viewPort, noTooltip and self.calcsTab.selControl) + end + + if subSec.collapsed or not enabled then if primary then return else @@ -206,86 +466,66 @@ function CalcSectionClass:Draw(viewPort, noTooltip) else lineY = lineY + 20 primary = false - local rows = 0; + local rows = 0 for _, rowData in ipairs(subSec.data) do - if rowData.enabled then + if (isOverlay and actor and self.calcsTab:CheckFlag(rowData)) or (not isOverlay and rowData.enabled) then rows = rows + 1 - local textColor = "^7" - if rowData.color then - textColor = rowData.color - end - if rowData.label then - SetDrawColor(rowData.bgCol or "^0") - DrawImage(nil, x + 2, lineY + 2, 130, 18) - if self.calcsTab:SearchMatch(rowData.label) then - textColor = colorCodes.HIGHLIGHT + if not isOverlay then + local textColor = rowData.color or "^7" + if rowData.label then + SetDrawColor(rowData.bgCol or "^0") + DrawImage(nil, drawX + 2, lineY + 2, 130, 18) + if self.calcsTab:SearchMatch(rowData.label) then + textColor = colorCodes.HIGHLIGHT + end + DrawString(drawX + 132, lineY + 2, "RIGHT_X", 16, "VAR", textColor..rowData.label.."^7:") end - DrawString(x + 132, lineY + 2, "RIGHT_X", 16, "VAR", textColor..rowData.label.."^7:") + elseif rowData.label then + DrawString(drawX + 132, lineY + 2, "RIGHT_X", 16, "VAR", "^7"..rowData.label.."^7:") end for colour, colData in ipairs(rowData) do - -- Draw column separator at the left end of the cell + local cellX = isOverlay and (drawX + (colData.xOffset or 134)) or colData.x + local cellW = isOverlay and (colData.width or (drawWidth - 136)) or colData.width + local cellY = isOverlay and lineY + 2 or colData.y + local cellH = colData.height or 18 + SetDrawColor(self.colour) - DrawImage(nil, colData.x, lineY + 2, 2, colData.height) - if colData.format and self.calcsTab:CheckFlag(colData) then - if cursorY >= viewPort.y and cursorY < viewPort.y + viewPort.height and cursorX >= colData.x and cursorY >= colData.y and cursorX < colData.x + colData.width and cursorY < colData.y + colData.height then - self.calcsTab:SetDisplayStat(colData) - end - if self.calcsTab.displayData == colData then - -- This is the display stat, draw a green border around this cell - SetDrawColor(0.25, 1, 0.25) - DrawImage(nil, colData.x + 2, colData.y, colData.width - 2, colData.height) - SetDrawColor(rowData.bgCol or "^0") - DrawImage(nil, colData.x + 3, colData.y + 1, colData.width - 4, colData.height - 2) - else - SetDrawColor(rowData.bgCol or "^0") - DrawImage(nil, colData.x + 2, colData.y, colData.width - 2, colData.height) + DrawImage(nil, cellX, lineY + 2, 2, cellH) + + if colData.format and (isOverlay or self.calcsTab:CheckFlag(colData)) then + if isOverlay and actor and self.calcsTab:CheckFlag(colData) or not isOverlay then + if isOverlay then + if cursorY >= lineY + 2 and cursorY < lineY + 20 and cursorX >= cellX and cursorX < cellX + cellW then + self.calcsTab:SetDisplayStat(colData) + self.overlayBreakdownCell = true + end + elseif cursorY >= viewPort.y and cursorY < viewPort.y + viewPort.height and cursorX >= cellX and cursorY >= cellY and cursorX < cellX + cellW and cursorY < cellY + cellH then + self.calcsTab:SetDisplayStat(colData) + end + + if not isOverlay and self.calcsTab.displayData == colData then + SetDrawColor(0.25, 1, 0.25) + DrawImage(nil, cellX + 2, cellY, cellW - 2, cellH) + SetDrawColor(rowData.bgCol or "^0") + DrawImage(nil, cellX + 3, cellY + 1, cellW - 4, cellH - 2) + else + SetDrawColor(rowData.bgCol or "^0") + DrawImage(nil, cellX + 2, lineY + 2, cellW - 2, 18) + end + + local textSize = rowData.textSize or 14 + SetViewport(cellX + 3, isOverlay and lineY + 2 or cellY, cellW - 4, 18) + DrawString(1, 9 - textSize / 2, "LEFT", textSize, "VAR", "^7"..formatCalcStr(colData.format, actor, colData)) + SetViewport() end - local textSize = rowData.textSize or 14 - SetViewport(colData.x + 3, colData.y, colData.width - 4, colData.height) - DrawString(1, 9 - textSize/2, "LEFT", textSize, "VAR", "^7"..formatCalcStr(colData.format, actor, colData)) - SetViewport() end end lineY = lineY + 18 end end - -- If there's at least one enabled row in this subsection, offset by the border for the subsection label if rows > 0 then lineY = lineY + 2 end end end -end - -function CalcSectionClass:OnKeyDown(key, doubleClick) - if not self:IsShown() or not self:IsEnabled() then - return - end - local mOverControl = self:GetMouseOverControl() - if mOverControl and mOverControl.OnKeyDown then - return mOverControl:OnKeyDown(key) - end - local mOver, mOverComp = self:IsMouseOver() - if key:match("BUTTON") then - if not mOver then - return - end - if mOverComp then - -- Pin the stat breakdown - self.calcsTab:SetDisplayStat(mOverComp, true) - return self.calcsTab.controls.breakdown - end - end - return -end - -function CalcSectionClass:OnKeyUp(key) - if not self:IsShown() or not self:IsEnabled() then - return - end - local mOverControl = self:GetMouseOverControl() - if mOverControl and mOverControl.OnKeyUp then - return mOverControl:OnKeyUp(key) - end - return end \ No newline at end of file diff --git a/src/Classes/CalcsTab.lua b/src/Classes/CalcsTab.lua index 53b379002e3..c4bf937ab85 100644 --- a/src/Classes/CalcsTab.lua +++ b/src/Classes/CalcsTab.lua @@ -231,7 +231,7 @@ function CalcsTabClass:Draw(viewPort, inputEvents) local maxY = 0 for _, section in ipairs(self.sectionList) do section:UpdateSize() - if section.enabled then + if section.enabled and not section.isOverlay then local col if section.group == 1 then -- Group 1: Offense or 3 wide sections @@ -280,7 +280,7 @@ function CalcsTabClass:Draw(viewPort, inputEvents) colY[c] = m_max(colY[1], colY[2], colY[3]) end for _, section in ipairs(self.sectionList) do - if section.enabled and (main.portraitMode and section.group == 2 or section.group == 3) then + if section.enabled and not section.isOverlay and (main.portraitMode and section.group == 2 or section.group == 3) then local col = 3 if colY[col] + section.height + 4 >= m_max(viewPort.y + viewPort.height, maxY) then -- No room in the 4th column, find the highest available location in columns 1-4 @@ -302,9 +302,11 @@ function CalcsTabClass:Draw(viewPort, inputEvents) self.controls.scrollBar.height = viewPort.height self.controls.scrollBar:SetContentDimension(maxY - (baseY - 26), viewPort.height) for _, section in ipairs(self.sectionList) do - -- Give sections their actual Y position and let them update - section.y = section.y - self.controls.scrollBar.offset - section:UpdatePos() + if not section.isOverlay then + -- Give sections their actual Y position and let them update + section.y = section.y - self.controls.scrollBar.offset + section:UpdatePos() + end end self.controls.search.y = 4 - self.controls.scrollBar.offset diff --git a/src/Modules/Build.lua b/src/Modules/Build.lua index aa428db4905..0f8e0b423f0 100644 --- a/src/Modules/Build.lua +++ b/src/Modules/Build.lua @@ -604,6 +604,8 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin self.skillsTab = new("SkillsTab", self) self.calcsTab = new("CalcsTab", self) self.compareTab = new("CompareTab", self) + -- Used for pined calcs panes + self.overlayPanes = { } -- Load sections from the build file self.savers = { @@ -1173,6 +1175,29 @@ function buildMode:OnFrame(inputEvents) end end end + + -- Consume mouse events for overlay panes before normal input processing + local cursorX, cursorY = GetCursorPos() + for i = #inputEvents, 1, -1 do + local event = inputEvents[i] + if not event then break end + if event.type == "KeyDown" and event.key:match("BUTTON") then + for _, pane in ipairs(self.overlayPanes) do + if pane.isOverlay and pane:IsMouseInOverlay(cursorX, cursorY) then + pane:HandleOverlayClick(event.key, cursorX, cursorY) + inputEvents[i] = nil + break + end + end + elseif event.type == "KeyUp" and event.key:match("BUTTON") then + for _, pane in ipairs(self.overlayPanes) do + if pane.isOverlay then + pane:HandleOverlayRelease(event.key) + end + end + end + end + self:ProcessControlsInput(inputEvents, main.viewPort) self.controls.classDrop:SelByValue(self.spec.curClassId, "classId") @@ -1235,6 +1260,13 @@ function buildMode:OnFrame(inputEvents) self.compareTab:Draw(tabViewPort, inputEvents) end + -- Draw overlay panes on top of all tab content (last = topmost) + for _, pane in ipairs(self.overlayPanes) do + if pane.isOverlay then + pane:DrawOverlay(main.viewPort, inputEvents) + end + end + self.unsaved = self.modFlag or self.notesTab.modFlag or self.partyTab.modFlag or self.configTab.modFlag or self.treeTab.modFlag or self.treeTab.searchFlag or self.spec.modFlag or self.skillsTab.modFlag or self.itemsTab.modFlag or self.calcsTab.modFlag SetDrawLayer(5) From ab080e22995f80c6e4caecd0cb9b9b1daf77d205 Mon Sep 17 00:00:00 2001 From: xoxorwr Date: Thu, 23 Jul 2026 09:25:55 +0200 Subject: [PATCH 2/3] Make stat breakdown toggleable --- src/Classes/CalcsTab.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Classes/CalcsTab.lua b/src/Classes/CalcsTab.lua index c4bf937ab85..f838ad25f80 100644 --- a/src/Classes/CalcsTab.lua +++ b/src/Classes/CalcsTab.lua @@ -369,6 +369,10 @@ function CalcsTabClass:SetDisplayStat(displayData, pin) if not displayData or (not pin and self.displayPinned) then return end + if pin and self.displayPinned and self.displayData == displayData then + self:ClearDisplayStat() + return + end self.displayData = displayData self.displayPinned = pin self.controls.breakdown:SetBreakdownData(displayData, pin) From f893b805b958854d4871ba5cf010e72d1931ea84 Mon Sep 17 00:00:00 2001 From: LocalIdentity Date: Fri, 24 Jul 2026 10:24:11 +1000 Subject: [PATCH 3/3] Fix calc pane overlay positioning and interactions Fix calc pane overlays opening off-screen, incorrect input ordering for overlapping panes, and duplicated stat breakdowns. Prevent panes with interactive controls from being pinned, keep overlays within the viewport, refresh their layout when calculations change, and support scrolling pinned breakdowns outside the Calcs tab. --- src/Classes/CalcSectionControl.lua | 53 +++++++++++++++++------------- src/Classes/CalcsTab.lua | 8 +++++ src/Modules/Build.lua | 19 ++++++++++- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/Classes/CalcSectionControl.lua b/src/Classes/CalcSectionControl.lua index 248ab19ab65..69f24ad16e0 100644 --- a/src/Classes/CalcSectionControl.lua +++ b/src/Classes/CalcSectionControl.lua @@ -4,6 +4,8 @@ -- Section control used in the Calcs tab -- local t_insert = table.insert +local m_max = math.max +local m_min = math.min local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost", function(self, calcsTab, width, id, group, colour, subSection, updateFunc) self.Control(calcsTab, {0, 0, width, 0}) @@ -23,7 +25,9 @@ local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost" for _, data in ipairs(subSec.data) do for _, colData in ipairs(data) do + colData.calcSection = self if colData.control then + self.hasControls = true -- Add control to the section's control list and set show/hide function self.controls[colData.controlName] = colData.control colData.control.shown = function() @@ -53,7 +57,7 @@ local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost" self:ToggleOverlay() end) self.controls.popOut.shown = function() - return self.enabled and not self.isOverlay + return self.enabled and not self.isOverlay and not self.hasControls end self.isOverlay = false self.overlayX = 320 @@ -220,8 +224,8 @@ function CalcSectionClass:ToggleOverlay() self.isOverlay = not self.isOverlay if self.isOverlay then local x, y = self:GetPos() - self.overlayX = self.calcsTab.x + x - self.overlayY = self.calcsTab.y + y + self.overlayX = x + self.overlayY = y t_insert(self.calcsTab.build.overlayPanes, self) else local panes = self.calcsTab.build.overlayPanes @@ -251,19 +255,26 @@ function CalcSectionClass:IsMouseInOverlay(cursorX, cursorY) local x = self.overlayX local y = self.overlayY if cursorX < x or cursorX > x + self.width or cursorY < y then return false end - local h = 28 + return cursorY < y + self:GetOverlayHeight() +end + +function CalcSectionClass:GetOverlayHeight() + local height = 28 + local enabled = self.calcsTab.calcsEnv and self.calcsTab:CheckFlag(self) for i, subSec in ipairs(self.subSection) do - h = h + 22 - if not subSec.collapsed and self.calcsTab:CheckFlag(self) then + height = height + 22 + if not subSec.collapsed and enabled then for _, rowData in ipairs(subSec.data) do if self.calcsTab:CheckFlag(rowData) then - h = h + 18 + height = height + 18 end end - h = h + 2 + height = height + 2 + elseif i == 1 then + break end end - return cursorY < y + h + return height end function CalcSectionClass:HandleOverlayClick(key, cursorX, cursorY) @@ -294,6 +305,7 @@ function CalcSectionClass:HandleOverlayClick(key, cursorX, cursorY) local toggleY = lineY + 3 if cursorX >= toggleX and cursorX <= toggleX + 14 and cursorY >= toggleY and cursorY <= toggleY + 16 then subSec.collapsed = not subSec.collapsed + self.overlayRevision = nil self.calcsTab.modFlag = true return end @@ -346,29 +358,26 @@ function CalcSectionClass:DrawOverlay(viewPort, inputEvents) local cursorX, cursorY = GetCursorPos() self.overlayBreakdownCell = nil + if self.overlayRevision ~= self.calcsTab.build.outputRevision then + self:UpdateSize() + self.overlayRevision = self.calcsTab.build.outputRevision + end + if self.dragging then self.overlayX = cursorX - self.dragOffX self.overlayY = cursorY - self.dragOffY end + self.overlayX = m_max(viewPort.x, m_min(self.overlayX, viewPort.x + viewPort.width - self.width)) + self.overlayY = m_max(viewPort.y, m_min(self.overlayY, viewPort.y + viewPort.height - 24)) + local x = self.overlayX local y = self.overlayY local overlayWidth = self.width local actor = self.calcsTab.calcsEnv and (self.calcsTab.input.showMinion and self.calcsTab.calcsEnv.minion or self.calcsTab.calcsEnv.player) -- Calculate content height - local totalHeight = 28 - for i, subSec in ipairs(self.subSection) do - totalHeight = totalHeight + 22 - if actor and not subSec.collapsed and self.calcsTab:CheckFlag(self) then - for _, rowData in ipairs(subSec.data) do - if actor and self.calcsTab:CheckFlag(rowData) then - totalHeight = totalHeight + 18 - end - end - totalHeight = totalHeight + 2 - end - end + local totalHeight = self:GetOverlayHeight() -- Ensure it's above most other controls SetDrawLayer(12) @@ -401,7 +410,7 @@ function CalcSectionClass:DrawOverlay(viewPort, inputEvents) self:DrawContent(x, y + 26, overlayWidth, actor, viewPort, true) -- Draw stat breakdown - if self.calcsTab.displayData and (self.overlayBreakdownCell or self.calcsTab.displayPinned) then + if self.calcsTab.displayData and (self.overlayBreakdownCell or (self.calcsTab.displayPinned and self.calcsTab.displayData.calcSection == self)) then local cd = self.calcsTab.displayData local origX, origY = cd.x, cd.y cd.x = x + (cd.xOffset or 134) diff --git a/src/Classes/CalcsTab.lua b/src/Classes/CalcsTab.lua index f838ad25f80..f621c7de751 100644 --- a/src/Classes/CalcsTab.lua +++ b/src/Classes/CalcsTab.lua @@ -341,7 +341,15 @@ function CalcsTabClass:Draw(viewPort, inputEvents) self.displayData = nil end + local breakdown = self.controls.breakdown + local overlayBreakdown = breakdown.sourceData and breakdown.sourceData.calcSection and breakdown.sourceData.calcSection.isOverlay + if overlayBreakdown then + breakdown.shown = false + end self:DrawControls(viewPort, self.selControl) + if overlayBreakdown then + breakdown.shown = true + end if self.displayData then if self.displayPinned and not self.selControl then diff --git a/src/Modules/Build.lua b/src/Modules/Build.lua index 0f8e0b423f0..7e1b24a5901 100644 --- a/src/Modules/Build.lua +++ b/src/Modules/Build.lua @@ -1178,23 +1178,40 @@ function buildMode:OnFrame(inputEvents) -- Consume mouse events for overlay panes before normal input processing local cursorX, cursorY = GetCursorPos() + local breakdown = self.calcsTab.controls.breakdown + local overlayBreakdown = self.calcsTab.displayPinned and self.calcsTab.displayData + and self.calcsTab.displayData.calcSection and self.calcsTab.displayData.calcSection.isOverlay for i = #inputEvents, 1, -1 do local event = inputEvents[i] if not event then break end if event.type == "KeyDown" and event.key:match("BUTTON") then - for _, pane in ipairs(self.overlayPanes) do + for paneIndex = #self.overlayPanes, 1, -1 do + local pane = self.overlayPanes[paneIndex] if pane.isOverlay and pane:IsMouseInOverlay(cursorX, cursorY) then pane:HandleOverlayClick(event.key, cursorX, cursorY) inputEvents[i] = nil break end end + if inputEvents[i] and overlayBreakdown and breakdown:IsMouseOver() then + self.overlayBreakdownControl = breakdown:OnKeyDown(event.key, event.doubleClick) + inputEvents[i] = nil + end elseif event.type == "KeyUp" and event.key:match("BUTTON") then for _, pane in ipairs(self.overlayPanes) do if pane.isOverlay then pane:HandleOverlayRelease(event.key) end end + if self.overlayBreakdownControl then + self.overlayBreakdownControl:OnKeyUp(event.key) + self.overlayBreakdownControl = nil + inputEvents[i] = nil + end + elseif event.type == "KeyUp" and overlayBreakdown and breakdown:IsMouseOver() + and (breakdown.controls.scrollBar:IsScrollDownKey(event.key) or breakdown.controls.scrollBar:IsScrollUpKey(event.key)) then + breakdown:OnKeyUp(event.key) + inputEvents[i] = nil end end