diff --git a/src/components/map/MapGridEditor.js b/src/components/map/MapGridEditor.js
index fdb69ab..02f7615 100644
--- a/src/components/map/MapGridEditor.js
+++ b/src/components/map/MapGridEditor.js
@@ -20,10 +20,18 @@ function MapGridEditor({ map, onGridChange }) {
const bottomRightHandleRef = useRef();
const bottomLeftHandleRef = useRef();
- function handleScaleCircleDragStart() {}
+ const handlePreviousPositionRef = useRef();
+
+ function handleScaleCircleDragStart(event) {
+ const handle = event.target;
+ const position = getHandleNormalizedPosition(handle);
+ handlePreviousPositionRef.current = position;
+ }
function handleScaleCircleDragMove(event) {
- onGridChange(getHandleInset(event.target));
+ const handle = event.target;
+ onGridChange(getHandleInset(handle));
+ handlePreviousPositionRef.current = getHandleNormalizedPosition(handle);
}
function handleScaleCircleDragEnd(event) {
@@ -66,35 +74,66 @@ function MapGridEditor({ map, onGridChange }) {
};
function getHandleInset(handle) {
- const topLeftHandle = topLeftHandleRef.current;
- const topRightHandle = topRightHandleRef.current;
- const bottomRightHandle = bottomRightHandleRef.current;
- const bottomLeftHandle = bottomLeftHandleRef.current;
+ const gridX = map.grid.size.x;
+ const gridY = map.grid.size.y;
- const topLeft = Vector2.divide(
- { x: topLeftHandle.x(), y: topLeftHandle.y() },
- mapSize
- );
- const topRight = Vector2.divide(
- { x: topRightHandle.x(), y: topRightHandle.y() },
- mapSize
- );
- const bottomRight = Vector2.divide(
- { x: bottomRightHandle.x(), y: bottomRightHandle.y() },
- mapSize
- );
- const bottomLeft = Vector2.divide(
- { x: bottomLeftHandle.x(), y: bottomLeftHandle.y() },
- mapSize
+ const name = handle.name();
+
+ // Find distance and direction of dragging
+ const previousPosition = handlePreviousPositionRef.current;
+ const position = getHandleNormalizedPosition(handle);
+ const distance = Vector2.distance(previousPosition, position, "euclidean");
+ const direction = Vector2.normalize(
+ Vector2.subtract(position, previousPosition)
);
- if (handle === topLeftHandle || handle === bottomRightHandle) {
- return { topLeft, bottomRight };
- } else {
+ const inset = map.grid.inset;
+
+ if (direction.x === 0 && direction.y === 0) {
+ return inset;
+ }
+
+ // Scale the grid direction by the distance dragged and the
+ // dot product between the drag direction and the grid direction
+ // This drags the handle while keeping the aspect ratio
+ if (name === "topLeft") {
+ const gridDirection = Vector2.normalize({ x: gridX, y: gridY });
+ const dot = Vector2.dot(direction, gridDirection);
+ const offset = Vector2.multiply(gridDirection, distance * dot);
+ const newPosition = Vector2.add(previousPosition, offset);
return {
- topLeft: { x: bottomLeft.x, y: topRight.y },
- bottomRight: { x: topRight.x, y: bottomLeft.y },
+ topLeft: newPosition,
+ bottomRight: inset.bottomRight,
};
+ } else if (name === "topRight") {
+ const gridDirection = Vector2.normalize({ x: -gridX, y: gridY });
+ const dot = Vector2.dot(direction, gridDirection);
+ const offset = Vector2.multiply(gridDirection, distance * dot);
+ const newPosition = Vector2.add(previousPosition, offset);
+ return {
+ topLeft: { x: inset.topLeft.x, y: newPosition.y },
+ bottomRight: { x: newPosition.x, y: inset.bottomRight.y },
+ };
+ } else if (name === "bottomRight") {
+ const gridDirection = Vector2.normalize({ x: -gridX, y: -gridY });
+ const dot = Vector2.dot(direction, gridDirection);
+ const offset = Vector2.multiply(gridDirection, distance * dot);
+ const newPosition = Vector2.add(previousPosition, offset);
+ return {
+ topLeft: inset.topLeft,
+ bottomRight: newPosition,
+ };
+ } else if (name === "bottomLeft") {
+ const gridDirection = Vector2.normalize({ x: gridX, y: -gridY });
+ const dot = Vector2.dot(direction, gridDirection);
+ const offset = Vector2.multiply(gridDirection, distance * dot);
+ const newPosition = Vector2.add(previousPosition, offset);
+ return {
+ topLeft: { x: newPosition.x, y: inset.topLeft.y },
+ bottomRight: { x: inset.bottomRight.x, y: newPosition.y },
+ };
+ } else {
+ return inset;
}
}
@@ -115,6 +154,10 @@ function MapGridEditor({ map, onGridChange }) {
};
}
+ function getHandleNormalizedPosition(handle) {
+ return Vector2.divide({ x: handle.x(), y: handle.y() }, mapSize);
+ }
+
const handlePositions = getHandlePositions();
return (
@@ -129,24 +172,28 @@ function MapGridEditor({ map, onGridChange }) {
ref={topLeftHandleRef}
x={handlePositions.topLeft.x}
y={handlePositions.topLeft.y}
+ name="topLeft"
{...editCircleProps}
/>