Optimize location connection drawing during drag operations
Previously the entire location map was being rebuilt and redrawn in onUpdate() during a drag operation, including the connectors which weren't changing. This was causing notable lag on some systems. This splits the draw operations into two separate pieces - locations on the board which are unchanging, and locations which are being dragged. This allows only connections which are actually moving to be recalculated. Since TTS only allows a single list of vector lines per object the dragged lines are now set on the cards themselves rather than the PlayArea. This may possibly improve performance in itself, by keeping each list of vectors smaller. Supporting this required some changes in how pre-built connections are handled.
This commit is contained in:
parent
3211ae848d
commit
a65cf33059
@ -3,14 +3,17 @@
|
||||
---------------------------------------------------------
|
||||
|
||||
-- set true to enable debug logging
|
||||
local DEBUG = false
|
||||
local DEBUG = true
|
||||
|
||||
-- Location connection directional options
|
||||
local BIDIRECTIONAL = 0
|
||||
local ONE_WAY = 1
|
||||
local INCOMING_ONE_WAY = 2
|
||||
|
||||
-- Connector draw parameters
|
||||
local CONNECTION_THICKNESS = 0.015
|
||||
local DRAGGING_CONNECTION_THICKNESS = 0.15
|
||||
local DRAGGING_CONNECTION_COLOR = { 0.8, 0.8, 0.8, 1 }
|
||||
local CONNECTION_COLOR = { 0.4, 0.4, 0.4, 1 }
|
||||
local DIRECTIONAL_ARROW_DISTANCE = 3.5
|
||||
local ARROW_ARM_LENGTH = 0.9
|
||||
@ -151,6 +154,11 @@ function onUpdate()
|
||||
if obj == nil or not isInPlayArea(obj) then
|
||||
draggingGuids[guid] = nil
|
||||
needsConnectionRebuild = true
|
||||
-- If object still exists then it's been dragged outside the area and needs to clear the
|
||||
-- lines attached to it
|
||||
if obj ~= nil then
|
||||
obj.setVectorLines(nil)
|
||||
end
|
||||
end
|
||||
-- Even if the last location left the play area, need one last draw to clear the lines
|
||||
needsConnectionDraw = true
|
||||
@ -159,7 +167,7 @@ function onUpdate()
|
||||
rebuildConnectionList()
|
||||
end
|
||||
if needsConnectionDraw then
|
||||
drawConnections()
|
||||
drawDraggingConnections()
|
||||
end
|
||||
end
|
||||
|
||||
@ -174,7 +182,7 @@ function maybeTrackLocation(card)
|
||||
if metadata.type == "Location" then
|
||||
locations[card.getGUID()] = metadata
|
||||
rebuildConnectionList()
|
||||
drawConnections()
|
||||
drawBaseConnections()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -190,14 +198,14 @@ function maybeUntrackLocation(card)
|
||||
if locations[card.getGUID()] ~= nil and not card.locked then
|
||||
locations[card.getGUID()] = nil
|
||||
rebuildConnectionList()
|
||||
drawConnections()
|
||||
drawBaseConnections()
|
||||
end
|
||||
end
|
||||
|
||||
-- Builds a list of GUID to GUID connection information based on the currently tracked locations.
|
||||
-- This will update the connection information and store it in the locationConnections data member,
|
||||
-- but does not draw those connections. This should often be followed by a call to
|
||||
-- drawConnections()
|
||||
-- drawBaseConnections()
|
||||
function rebuildConnectionList()
|
||||
if not showLocationLinks() then
|
||||
locationConnections = { }
|
||||
@ -256,10 +264,15 @@ function buildConnection(cardId, iconCardList)
|
||||
for _, connectedGuid in ipairs(iconCardList[icon]) do
|
||||
-- If the reciprocal exists, convert it to BiDi, otherwise add as a one-way
|
||||
if locationConnections[connectedGuid] ~= nil
|
||||
and locationConnections[connectedGuid][card.getGUID()] ~= nil then
|
||||
and locationConnections[connectedGuid][card.getGUID()] == ONE_WAY then
|
||||
locationConnections[connectedGuid][card.getGUID()] = BIDIRECTIONAL
|
||||
locationConnections[card.getGUID()][connectedGuid] = nil
|
||||
else
|
||||
if locationConnections[connectedGuid] == nil then
|
||||
locationConnections[connectedGuid] = { }
|
||||
end
|
||||
locationConnections[card.getGUID()][connectedGuid] = ONE_WAY
|
||||
locationConnections[connectedGuid][card.getGUID()] = INCOMING_ONE_WAY
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -283,8 +296,9 @@ function getLocationData(card)
|
||||
end
|
||||
end
|
||||
|
||||
-- Draws the lines for connections currently in locationConnections.
|
||||
function drawConnections()
|
||||
-- Draws the lines for connections currently in locationConnections but not in draggingGuids.
|
||||
-- Constructed vectors will be set to the playmat
|
||||
function drawBaseConnections()
|
||||
if not showLocationLinks() then
|
||||
locationConnections = { }
|
||||
return
|
||||
@ -295,14 +309,16 @@ function drawConnections()
|
||||
-- Objects should reliably exist at this point, but since this can be called during onUpdate the
|
||||
-- object checks are conservative just to make sure.
|
||||
local origin = getObjectFromGUID(originGuid)
|
||||
if origin != nil then
|
||||
if draggingGuids[originGuid] == nil and origin != nil then
|
||||
for targetGuid, direction in pairs(targetGuids) do
|
||||
local target = getObjectFromGUID(targetGuid)
|
||||
if target != nil then
|
||||
if draggingGuids[targetGuid] == nil and target != nil then
|
||||
-- Since we process the full list, we're guaranteed to hit any ONE_WAY connections later
|
||||
-- so we can ignore INCOMING_ONE_WAY
|
||||
if direction == BIDIRECTIONAL then
|
||||
addBidirectionalVector(origin, target, cardConnectionLines)
|
||||
addBidirectionalVector(origin, target, self, cardConnectionLines)
|
||||
elseif direction == ONE_WAY then
|
||||
addOneWayVector(origin, target, cardConnectionLines)
|
||||
addOneWayVector(origin, target, self, cardConnectionLines)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -311,22 +327,61 @@ function drawConnections()
|
||||
self.setVectorLines(cardConnectionLines)
|
||||
end
|
||||
|
||||
-- Draws the lines for cards which are currently being dragged.
|
||||
function drawDraggingConnections()
|
||||
if not showLocationLinks() then
|
||||
return
|
||||
end
|
||||
local cardConnectionLines = { }
|
||||
local ownedVectors = { }
|
||||
|
||||
for originGuid, _ in pairs(draggingGuids) do
|
||||
targetGuids = locationConnections[originGuid]
|
||||
-- Objects should reliably exist at this point, but since this can be called during onUpdate the
|
||||
-- object checks are conservative just to make sure.
|
||||
local origin = getObjectFromGUID(originGuid)
|
||||
if draggingGuids[originGuid] and origin != nil then
|
||||
ownedVectors[originGuid] = { }
|
||||
for targetGuid, direction in pairs(targetGuids) do
|
||||
local target = getObjectFromGUID(targetGuid)
|
||||
if target != nil then
|
||||
if direction == BIDIRECTIONAL then
|
||||
addBidirectionalVector(origin, target, origin, ownedVectors[originGuid])
|
||||
elseif direction == ONE_WAY then
|
||||
addOneWayVector(origin, target, origin, ownedVectors[originGuid])
|
||||
elseif direction == INCOMING_ONE_WAY and not draggingGuids[targetGuid] then
|
||||
addOneWayVector(target, origin, origin, ownedVectors[originGuid])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for ownerGuid, vectors in pairs(ownedVectors) do
|
||||
local card = getObjectFromGUID(ownerGuid)
|
||||
card.setVectorLines(vectors)
|
||||
end
|
||||
end
|
||||
|
||||
-- Draws a bidirectional location connection between the two cards, adding the lines to do so to the
|
||||
-- given lines list.
|
||||
---@param card1 Object One of the card objects to connect
|
||||
---@param card2 Object The other card object to connect
|
||||
---@param vectorOwner Object The object which these lines will be set to. Used for relative
|
||||
--- positioning and scaling, as well as highlighting connections during a drag operation
|
||||
---@param lines Table List of vector line elements. Mutable, will be updated to add this connector
|
||||
function addBidirectionalVector(card1, card2, lines)
|
||||
function addBidirectionalVector(card1, card2, vectorOwner, lines)
|
||||
local cardPos1 = card1.getPosition()
|
||||
local cardPos2 = card2.getPosition()
|
||||
cardPos1.y = CONNECTION_LINE_Y
|
||||
cardPos2.y = CONNECTION_LINE_Y
|
||||
local pos1 = self.positionToLocal(cardPos1)
|
||||
local pos2 = self.positionToLocal(cardPos2)
|
||||
|
||||
local pos1 = vectorOwner.positionToLocal(cardPos1)
|
||||
local pos2 = vectorOwner.positionToLocal(cardPos2)
|
||||
|
||||
table.insert(lines, {
|
||||
points = { pos1, pos2 },
|
||||
color = CONNECTION_COLOR,
|
||||
thickness = CONNECTION_THICKNESS,
|
||||
color = vectorOwner == self and CONNECTION_COLOR or DRAGGING_CONNECTION_COLOR,
|
||||
thickness = vectorOwner == self and CONNECTION_THICKNESS or DRAGGING_CONNECTION_THICKNESS,
|
||||
})
|
||||
end
|
||||
|
||||
@ -334,10 +389,12 @@ end
|
||||
-- given lines list. Arrows will point towards the target card.
|
||||
---@param origin Object Origin card in the connection
|
||||
---@param target Object Target card object to connect
|
||||
---@param vectorOwner Object The object which these lines will be set to. Used for relative
|
||||
--- positioning and scaling, as well as highlighting connections during a drag operation
|
||||
---@param lines Table List of vector line elements. Mutable, will be updated to add this connector
|
||||
function addOneWayVector(origin, target, lines)
|
||||
function addOneWayVector(origin, target, vectorOwner, lines)
|
||||
-- Start with the BiDi then add the arrow lines to it
|
||||
addBidirectionalVector(origin, target, lines)
|
||||
addBidirectionalVector(origin, target, vectorOwner, lines)
|
||||
local originPos = origin.getPosition()
|
||||
local targetPos = target.getPosition()
|
||||
originPos.y = CONNECTION_LINE_Y
|
||||
@ -355,28 +412,30 @@ function addOneWayVector(origin, target, lines)
|
||||
local closeToTarget = Vector(targetPos):moveTowards(originPos, distanceFromCard - ARROW_ARM_LENGTH / 2)
|
||||
|
||||
if (originPos:distance(closeToOrigin) > originPos:distance(closeToTarget)) then
|
||||
addArrowLines(midpoint, originPos, lines)
|
||||
addArrowLines(midpoint, originPos, vectorOwner, lines)
|
||||
else
|
||||
addArrowLines(closeToOrigin, originPos, lines)
|
||||
addArrowLines(closeToTarget, originPos, lines)
|
||||
addArrowLines(closeToOrigin, originPos, vectorOwner, lines)
|
||||
addArrowLines(closeToTarget, originPos, vectorOwner, lines)
|
||||
end
|
||||
end
|
||||
|
||||
-- Draws an arrowhead at the given position.
|
||||
---@param arrowheadPosition Table Centerpoint of the arrowhead to draw (NOT the tip of the arrow)
|
||||
---@param originPos Table Origin point of the connection, used to position the arrow arms
|
||||
---@param vectorOwner Object The object which these lines will be set to. Used for relative
|
||||
--- positioning and scaling, as well as highlighting connections during a drag operation
|
||||
---@param lines Table List of vector line elements. Mutable, will be updated to add this arrow
|
||||
function addArrowLines(arrowheadPos, originPos, lines)
|
||||
function addArrowLines(arrowheadPos, originPos, vectorOwner, lines)
|
||||
local arrowArm1 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y", -1 * ARROW_ANGLE):add(arrowheadPos)
|
||||
local arrowArm2 = Vector(arrowheadPos):moveTowards(originPos, ARROW_ARM_LENGTH):sub(arrowheadPos):rotateOver("y", ARROW_ANGLE):add(arrowheadPos)
|
||||
|
||||
local head = self.positionToLocal(arrowheadPos)
|
||||
local arm1 = self.positionToLocal(arrowArm1)
|
||||
local arm2 = self.positionToLocal(arrowArm2)
|
||||
local head = vectorOwner.positionToLocal(arrowheadPos)
|
||||
local arm1 = vectorOwner.positionToLocal(arrowArm1)
|
||||
local arm2 = vectorOwner.positionToLocal(arrowArm2)
|
||||
table.insert(lines, {
|
||||
points = { arm1, head, arm2},
|
||||
color = CONNECTION_COLOR,
|
||||
thickness = CONNECTION_THICKNESS
|
||||
color = vectorOwner == self and CONNECTION_COLOR or DRAGGING_CONNECTION_COLOR,
|
||||
thickness = vectorOwner == self and CONNECTION_THICKNESS or DRAGGING_CONNECTION_THICKNESS,
|
||||
})
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user