Merge pull request #184 from argonui/faster-connectors
Optimize location connection drawing during drag operations
This commit is contained in:
commit
31006694b8
@ -184,6 +184,14 @@ function onObjectSearchEnd(object, playerColor)
|
||||
end
|
||||
end
|
||||
|
||||
-- Pass object enter container events to the PlayArea to clear vector lines from dragged cards.
|
||||
-- This requires the try method as cards won't exist any more after they enter a deck, so the lines
|
||||
-- can't be cleared.
|
||||
function tryObjectEnterContainer(container, object)
|
||||
playAreaAPI.tryObjectEnterContainer(container, object)
|
||||
return true
|
||||
end
|
||||
|
||||
function drawEncountercard(params)
|
||||
local position = params[1]
|
||||
local rotation = params[2]
|
||||
|
@ -8,9 +8,12 @@ local DEBUG = false
|
||||
-- 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
|
||||
@ -90,7 +93,7 @@ end
|
||||
function onCollisionEnter(collisionInfo)
|
||||
local obj = collisionInfo.collision_object
|
||||
local objType = obj.name
|
||||
|
||||
|
||||
-- only continue for cards
|
||||
if not collisionEnabled or (objType ~= "Card" and objType ~= "CardCustom") then return end
|
||||
|
||||
@ -99,7 +102,12 @@ function onCollisionEnter(collisionInfo)
|
||||
if shouldSpawnTokens(card) then
|
||||
tokenManager.spawnForCard(card)
|
||||
end
|
||||
draggingGuids[card.getGUID()] = nil
|
||||
-- If this card was being dragged, clear the dragging connections. A multi-drag/drop may send
|
||||
-- the dropped card immediately into a deck, so this has to be done here
|
||||
if draggingGuids[card.getGUID()] ~= nil then
|
||||
card.setVectorLines(nil)
|
||||
draggingGuids[card.getGUID()] = nil
|
||||
end
|
||||
maybeTrackLocation(card)
|
||||
end
|
||||
|
||||
@ -150,6 +158,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
|
||||
@ -158,7 +171,7 @@ function onUpdate()
|
||||
rebuildConnectionList()
|
||||
end
|
||||
if needsConnectionDraw then
|
||||
drawConnections()
|
||||
drawDraggingConnections()
|
||||
end
|
||||
end
|
||||
|
||||
@ -173,7 +186,7 @@ function maybeTrackLocation(card)
|
||||
if metadata.type == "Location" then
|
||||
locations[card.getGUID()] = metadata
|
||||
rebuildConnectionList()
|
||||
drawConnections()
|
||||
drawBaseConnections()
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -189,14 +202,26 @@ function maybeUntrackLocation(card)
|
||||
if locations[card.getGUID()] ~= nil and not card.locked then
|
||||
locations[card.getGUID()] = nil
|
||||
rebuildConnectionList()
|
||||
drawConnections()
|
||||
drawBaseConnections()
|
||||
end
|
||||
end
|
||||
|
||||
-- Global event handler, delegated from Global. Clears any connection lines from dragged cards
|
||||
-- before they are destroyed by entering a deck. Removal of the card from the dragging list will
|
||||
-- be handled during the next onUpdate() call.
|
||||
function tryObjectEnterContainer(params)
|
||||
for draggedGuid, _ in pairs(draggingGuids) do
|
||||
local draggedObj = getObjectFromGUID(draggedGuid)
|
||||
if draggedObj ~= nil then
|
||||
draggedObj.setVectorLines(nil)
|
||||
end
|
||||
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 = { }
|
||||
@ -255,10 +280,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
|
||||
@ -282,8 +312,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
|
||||
@ -294,14 +325,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
|
||||
@ -310,22 +343,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
|
||||
|
||||
@ -333,10 +405,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
|
||||
@ -354,28 +428,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
|
||||
|
||||
|
@ -47,6 +47,13 @@ do
|
||||
PlayAreaApi.setLimitSnapsByType = function(matchCardTypes)
|
||||
getObjectFromGUID(PLAY_AREA_GUID).call("setLimitSnapsByType", matchCardTypes)
|
||||
end
|
||||
|
||||
|
||||
-- Receiver for the Global tryObjectEnterContainer event. Used to clear vector lines from dragged
|
||||
-- cards before they're destroyed by entering the container
|
||||
PlayAreaApi.tryObjectEnterContainer = function(container, object)
|
||||
getObjectFromGUID(PLAY_AREA_GUID).call("tryObjectEnterContainer",
|
||||
{ container = container, object = object })
|
||||
end
|
||||
|
||||
return PlayAreaApi
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user