From d0fba917a2c34534458b48cd39588f9f81f3d480 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Sat, 12 Jun 2021 20:53:40 +1000 Subject: [PATCH] Add custom intersection for token vehicles using their outline --- src/components/map/MapToken.js | 57 ++++-------------- src/helpers/token.js | 106 +++++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 44 deletions(-) diff --git a/src/components/map/MapToken.js b/src/components/map/MapToken.js index f94b315..13aa769 100644 --- a/src/components/map/MapToken.js +++ b/src/components/map/MapToken.js @@ -2,7 +2,6 @@ import React, { useState, useRef } from "react"; import { Image as KonvaImage, Group } from "react-konva"; import { useSpring, animated } from "react-spring/konva"; import useImage from "use-image"; -import Konva from "konva"; import usePrevious from "../../hooks/usePrevious"; import useGridSnapping from "../../hooks/useGridSnapping"; @@ -20,6 +19,8 @@ import TokenStatus from "../token/TokenStatus"; import TokenLabel from "../token/TokenLabel"; import TokenOutline from "../token/TokenOutline"; +import { Intersection, getScaledOutline } from "../../helpers/token"; + import { tokenSources } from "../../tokens"; function MapToken({ @@ -49,11 +50,14 @@ function MapToken({ function handleDragStart(event) { const tokenGroup = event.target; - const tokenImage = imageRef.current; if (tokenState.category === "vehicle") { - // Enable hit detection for .intersects() function - Konva.hitOnDragEnabled = true; + const tokenIntersection = new Intersection( + getScaledOutline(tokenState, tokenWidth, tokenHeight), + { x: tokenX - tokenWidth / 2, y: tokenY - tokenHeight / 2 }, + { x: tokenX, y: tokenY }, + tokenState.rotation + ); // Find all other tokens on the map const layer = tokenGroup.getLayer(); @@ -62,12 +66,7 @@ function MapToken({ if (other === tokenGroup) { continue; } - const otherRect = other.getClientRect(); - const otherCenter = { - x: otherRect.x + otherRect.width / 2, - y: otherRect.y + otherRect.height / 2, - }; - if (tokenImage.intersects(otherCenter)) { + if (tokenIntersection.intersects(other.position())) { // Save and restore token position after moving layer const position = other.absolutePosition(); other.moveTo(tokenGroup); @@ -92,8 +91,6 @@ function MapToken({ const mountChanges = {}; if (tokenState.category === "vehicle") { - Konva.hitOnDragEnabled = false; - const parent = tokenGroup.getParent(); const mountedTokens = tokenGroup.find(".character"); for (let mountedToken of mountedTokens) { @@ -177,8 +174,6 @@ function MapToken({ const tokenWidth = minCellSize * tokenState.size; const tokenHeight = (minCellSize / tokenAspectRatio) * tokenState.size; - const imageRef = useRef(); - // Animate to new token positions if edited by others const tokenX = tokenState.x * mapWidth; const tokenY = tokenState.y * mapHeight; @@ -206,34 +201,6 @@ function MapToken({ tokenName = tokenName + "-locked"; } - function getScaledOutline() { - let outline = tokenState.outline; - if (outline.type === "rect") { - return { - ...outline, - x: (outline.x / tokenState.width) * tokenWidth, - y: (outline.y / tokenState.height) * tokenHeight, - width: (outline.width / tokenState.width) * tokenWidth, - height: (outline.height / tokenState.height) * tokenHeight, - }; - } else if (outline.type === "circle") { - return { - ...outline, - x: (outline.x / tokenState.width) * tokenWidth, - y: (outline.y / tokenState.height) * tokenHeight, - radius: (outline.radius / tokenState.width) * tokenWidth, - }; - } else { - let points = [...outline.points]; // Copy array so we can edit it imutably - for (let i = 0; i < points.length; i += 2) { - // Scale outline to the token - points[i] = (points[i] / tokenState.width) * tokenWidth; - points[i + 1] = (points[i + 1] / tokenState.height) * tokenHeight; - } - return { ...outline, points }; - } - } - return ( -