diff --git a/src/Classes/PassiveTree.lua b/src/Classes/PassiveTree.lua index 9b08e54b7e..378cc76646 100644 --- a/src/Classes/PassiveTree.lua +++ b/src/Classes/PassiveTree.lua @@ -339,9 +339,30 @@ function PassiveTreeClass:PassiveTree(treeVersion) if not connectors then goto endConnection end - t_insert(self.connectors, connectors[1]) - if connectors[2] then - t_insert(self.connectors, connectors[2]) + -- precalculate some information for tree views: + for i = 1, #connectors do + -- culling + local connector = connectors[i] + local minX, minY = math.huge, math.huge + local maxX, maxY = -math.huge, -math.huge + for _, vert in pairs(connector.vert) do + for j = 1, 7, 2 do + local x, y = vert[j], vert[j + 1] + if x < minX then minX = x end + if x > maxX then maxX = x end + if y < minY then minY = y end + if y > maxY then maxY = y end + end + end + connector.minX, connector.minY = minX, minY + connector.maxX, connector.maxY = maxX, maxY + + -- asset key names + connector.assetNames = {} + for state, _ in pairs(connector.vert) do + connector.assetNames[state] = string.format("%s%s%s", connector.connectionArt, connector.type, state) + end + t_insert(self.connectors, connector) end :: endConnection :: end diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index 86ffcd4659..2255b51c82 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -53,6 +53,7 @@ function PassiveTreeViewClass:PassiveTreeView() self.searchStrResults = {} self.showStatDifferences = true self.hoverNode = nil + self.connectorQueue = {} return self end @@ -165,8 +166,12 @@ function PassiveTreeViewClass:GetCompareNodeColor(node, compareNode, spec, build return nodeDefaultColor end +---@param build Build +---@param viewPort any +---@param inputEvents any function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) local spec = build.spec + ---@type PassiveTree local tree = spec.tree local cursorX, cursorY = GetCursorPos() @@ -174,7 +179,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) -- Process input events local treeClick - for id, event in ipairs(inputEvents) do + for _, event in ipairs(inputEvents) do if event.type == "KeyDown" then if event.key == "LEFTBUTTON" then if mOver then @@ -675,10 +680,6 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) end end - local connectorColor = { 1, 1, 1 } - local function setConnectorColor(r, g, b) - connectorColor[1], connectorColor[2], connectorColor[3] = r, g, b - end local function nodeIsHoverPathEndpoint(node) if node == hoverNode or hoverPath[node] then return true @@ -711,9 +712,19 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) end return state end + for _, connectorList in pairs(self.connectorQueue) do + connectorList.n = 0 + end + -- 0.75 gray + local inactiveGray = "^xBFBFBF" + local brightRed = colorCodes.HIGHLIGHT + local brightGreen = "^x00FF00" + local alloc1Red = colorCodes.NEGATIVE + local alloc2Green = colorCodes.POSITIVE + local white = "^xFFFFFF" local function renderConnector(connector) local node1, node2 = spec.nodes[connector.nodeId1], spec.nodes[connector.nodeId2] - setConnectorColor(1, 1, 1) + connector.colour = white local state = getState(node1, node2) local baseState = state if self.compareSpec then @@ -722,29 +733,26 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) baseState = getState(cNode1,cNode2) end end - if baseState == "Active" and state ~= "Active" then state = "Active" - setConnectorColor(0, 1, 0) + connector.colour = brightGreen end if baseState ~= "Active" and state == "Active" then - setConnectorColor(1, 0, 0) + connector.colour = brightRed end - if baseState == "Intermediate" and spec.allocMode > 0 and not connector.ascendancyName then if spec.allocMode == 1 then - setConnectorColor(unpack(hexToRGB(colorCodes["NEGATIVE"]:sub(3)))) + connector.colour = alloc1Red elseif spec.allocMode == 2 then - setConnectorColor(unpack(hexToRGB(colorCodes["POSITIVE"]:sub(3)))) + connector.colour = alloc2Green end end - if baseState == "Active" and state == "Active" and not connector.ascendancyName then - local allocMode = (node1 and node1.allocMode and node1.allocMode ~= 0 and node1.allocMode) or (node2 and node2.allocMode and node2.allocMode ~= 0 and node2.allocMode) or 0 + local allocMode = (node1 and node1.allocMode and node1.allocMode ~= 0 and node1.allocMode) or (node2 and node2.allocMode and node2.allocMode ~= 0 and node2.allocMode) or 0 if allocMode == 1 then - setConnectorColor(unpack(hexToRGB(colorCodes["NEGATIVE"]:sub(3)))) + connector.colour = alloc1Red elseif allocMode == 2 then - setConnectorColor(unpack(hexToRGB(colorCodes["POSITIVE"]:sub(3)))) + connector.colour = alloc2Green end end @@ -754,35 +762,47 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) connector.c[3], connector.c[4] = treeToScreen(vert[3], vert[4]) connector.c[5], connector.c[6] = treeToScreen(vert[5], vert[6]) connector.c[7], connector.c[8] = treeToScreen(vert[7], vert[8]) - if hoverNode and hoverNode.id == 5571 and hoverDep and (hoverDep[node1] or hoverDep[node2]) and not hoverNode.alloc and not connector.ascendancyName then --Used to display Unseen Path nodes green when unallocated and hovered over - setConnectorColor(0, 1, 0) + connector.colour = brightGreen elseif hoverDep and (hoverDep[node1] or hoverDep[node2]) and hoverNode.id == 5571 and not hoverNode.isAlloc and not connector.ascendancyName then --Used to display Unseen Path nodes red when allocated and hovered over node - setConnectorColor(1, 0, 0) + connector.colour = brightRed elseif hoverDep and hoverDep[node1] and hoverDep[node2] then -- Both nodes depend on the node currently being hovered over, so color the line red - setConnectorColor(1, 0, 0) + connector.colour = brightRed elseif connector.ascendancyName and connector.ascendancyName ~= spec.curAscendClassBaseName then - -- Fade out lines in ascendancy classes other than the current one - setConnectorColor(0.75, 0.75, 0.75) + -- Fade out lines in ascendancy classes other than the current one (0.75 gray) + connector.colour = inactiveGray end - SetDrawColor(unpack(connectorColor)) - handle = tree:GetAssetByName(connector.connectionArt .. connector.type..state).handle - DrawImageQuad(handle, unpack(connector.c)) + local handleName = connector.assetNames[state] + connector.state = state + local connectorHandleQueue = self.connectorQueue[handleName] + if not connectorHandleQueue then + connectorHandleQueue = { n = 0 } + self.connectorQueue[handleName] = connectorHandleQueue + end + connectorHandleQueue.n += 1 + connectorHandleQueue[connectorHandleQueue.n] = connector end -- Draw the connecting lines between nodes SetDrawLayer(nil, 20) - for _, connector in pairs(tree.connectors) do - local node1 = spec.nodes[connector.nodeId1] - local node2 = spec.nodes[connector.nodeId2] - if not node1.unlockConstraint and not node2.unlockConstraint then - renderConnector(connector) - elseif self:checkUnlockConstraints(build, node1) and self:checkUnlockConstraints(build, node2) then - renderConnector(connector) + local vpMaxX, vpMaxY = screenToTree(viewPort.x + viewPort.width, viewPort.y + viewPort.height) + local vpMinX, vpMinY = screenToTree(viewPort.x, viewPort.y) + for i = 1, #tree.connectors do + local connector = tree.connectors[i] + -- avoid rendering connectors that are out of view + if vpMinX <= connector.maxX and connector.minX <= vpMaxX + and vpMinY <= connector.maxY and connector.minY <= vpMaxY then + local node1 = spec.nodes[connector.nodeId1] + local node2 = spec.nodes[connector.nodeId2] + if not node1.unlockConstraint and not node2.unlockConstraint then + renderConnector(connector) + elseif self:checkUnlockConstraints(build, node1) and self:checkUnlockConstraints(build, node2) then + renderConnector(connector) + end end end @@ -791,6 +811,20 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) renderConnector(connector) end end + for assetName, connectors in pairs(self.connectorQueue) do + local handle = tree:GetAssetByName(assetName).handle + local currentColour + for i = 1, connectors.n do + local connector = connectors[i] + local c = connector.c + local colour = connector.colour or white + if currentColour ~= colour then + SetDrawColor(colour) + currentColour = colour + end + DrawImageQuad(handle, c[1], c[2], c[3], c[4], c[5], c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15], c[16]) + end + end -- Draw connectors for compare-only subgraphs (cluster jewels only in compare build) if self.compareSpec then for subGraphId, subGraph in pairs(self.compareSpec.subGraphs) do @@ -897,6 +931,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) end -- Draw the nodes + local halfGray = "^x808080" for nodeId, node in pairs(spec.nodes) do -- Determine the base and overlay images for this node based on type and state local compareNode = self.compareSpec and self.compareSpec.nodes[nodeId] or nil @@ -1076,7 +1111,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) else if not self.showHeatMap and not launch.devModeAlt and not node.alloc then - self:LessLuminance() + SetDrawColor(halfGray) end self:DrawAsset(base, scrX, scrY, scale) @@ -1088,7 +1123,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) if overlay then if allocModeColor then - SetDrawColor(unpack(hexToRGB(colorCodes[allocMode == 1 and "NEGATIVE" or "POSITIVE"]:sub(3)))) + SetDrawColor(allocMode == 1 and alloc1Red or alloc2Green) end -- Draw overlay if node.type ~= "ClassStart" and node.type ~= "AscendClassStart" then @@ -1139,7 +1174,7 @@ function PassiveTreeViewClass:Draw(build, viewPort, inputEvents) end if not self.showHeatMap and not launch.devModeAlt and not node.alloc and (node.type == "AscendClassStart" or node.type == "ClassStart") then - self:LessLuminance() + SetDrawColor(halfGray) end self:DrawAsset(overlayImage, scrX, scrY, scale) if not self.showHeatMap and not launch.devModeAlt and not node.alloc and (node.type == "AscendClassStart" or node.type == "ClassStart") then @@ -1357,7 +1392,11 @@ function PassiveTreeViewClass:DrawAsset(data, x, y, scale, isHalf) DrawImage(data.handle, x - width, y - height * 2, width * 2, height * 2) DrawImage(data.handle, x - width, y, width * 2, height * 2, 0, 1, 1, 0) else - DrawImage(data.handle, x - width, y - height, width * 2, height * 2, unpack(data)) + if data[2] then + DrawImage(data.handle, x - width, y - height, width * 2, height * 2, data[1], data[2], data[3], data[4]) + else + DrawImage(data.handle, x - width, y - height, width * 2, height * 2, data[1]) + end end end @@ -2110,27 +2149,6 @@ function PassiveTreeViewClass:DrawAllocMode(allocMode, viewPort) SetDrawLayer(nil, 10) end -function PassiveTreeViewClass:LessLuminance() - local luminanceFactor = 0.5 - local r,g,b,a = 1, 1, 1, 1 - local desaturationFactor = 0.5; - local alphaFactor = 1; - local luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b; - - -- Blend with original color - local newR = (1.0 - desaturationFactor) * r + desaturationFactor * luminance; - local newG = (1.0 - desaturationFactor) * g + desaturationFactor * luminance; - local newB = (1.0 - desaturationFactor) * b + desaturationFactor * luminance; - - -- Apply luminance adjustment - newR = newR * luminanceFactor; - newG = newG * luminanceFactor; - newB = newB * luminanceFactor; - - local newA = a * alphaFactor; - SetDrawColor(newR, newG, newB, newA) -end - -- Checks if a node has unlockConstraint and if that node is allocated function PassiveTreeViewClass:checkUnlockConstraints(build, node) if unseenPathHover and node.unlockConstraint and node.unlockConstraint.nodes[1] == 5571 then