Update grid inset editing to maintain aspect ratio

This commit is contained in:
Mitchell McCaffrey 2020-10-09 11:23:34 +11:00
parent cce339224b
commit 60a163f351

View File

@ -20,10 +20,18 @@ function MapGridEditor({ map, onGridChange }) {
const bottomRightHandleRef = useRef(); const bottomRightHandleRef = useRef();
const bottomLeftHandleRef = 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) { function handleScaleCircleDragMove(event) {
onGridChange(getHandleInset(event.target)); const handle = event.target;
onGridChange(getHandleInset(handle));
handlePreviousPositionRef.current = getHandleNormalizedPosition(handle);
} }
function handleScaleCircleDragEnd(event) { function handleScaleCircleDragEnd(event) {
@ -66,35 +74,66 @@ function MapGridEditor({ map, onGridChange }) {
}; };
function getHandleInset(handle) { function getHandleInset(handle) {
const topLeftHandle = topLeftHandleRef.current; const gridX = map.grid.size.x;
const topRightHandle = topRightHandleRef.current; const gridY = map.grid.size.y;
const bottomRightHandle = bottomRightHandleRef.current;
const bottomLeftHandle = bottomLeftHandleRef.current;
const topLeft = Vector2.divide( const name = handle.name();
{ x: topLeftHandle.x(), y: topLeftHandle.y() },
mapSize // Find distance and direction of dragging
); const previousPosition = handlePreviousPositionRef.current;
const topRight = Vector2.divide( const position = getHandleNormalizedPosition(handle);
{ x: topRightHandle.x(), y: topRightHandle.y() }, const distance = Vector2.distance(previousPosition, position, "euclidean");
mapSize const direction = Vector2.normalize(
); Vector2.subtract(position, previousPosition)
const bottomRight = Vector2.divide(
{ x: bottomRightHandle.x(), y: bottomRightHandle.y() },
mapSize
);
const bottomLeft = Vector2.divide(
{ x: bottomLeftHandle.x(), y: bottomLeftHandle.y() },
mapSize
); );
if (handle === topLeftHandle || handle === bottomRightHandle) { const inset = map.grid.inset;
return { topLeft, bottomRight };
} else { 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 { return {
topLeft: { x: bottomLeft.x, y: topRight.y }, topLeft: newPosition,
bottomRight: { x: topRight.x, y: bottomLeft.y }, 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(); const handlePositions = getHandlePositions();
return ( return (
@ -129,24 +172,28 @@ function MapGridEditor({ map, onGridChange }) {
ref={topLeftHandleRef} ref={topLeftHandleRef}
x={handlePositions.topLeft.x} x={handlePositions.topLeft.x}
y={handlePositions.topLeft.y} y={handlePositions.topLeft.y}
name="topLeft"
{...editCircleProps} {...editCircleProps}
/> />
<Circle <Circle
ref={topRightHandleRef} ref={topRightHandleRef}
x={handlePositions.topRight.x} x={handlePositions.topRight.x}
y={handlePositions.topRight.y} y={handlePositions.topRight.y}
name="topRight"
{...editCircleProps} {...editCircleProps}
/> />
<Circle <Circle
ref={bottomRightHandleRef} ref={bottomRightHandleRef}
x={handlePositions.bottomRight.x} x={handlePositions.bottomRight.x}
y={handlePositions.bottomRight.y} y={handlePositions.bottomRight.y}
name="bottomRight"
{...editCircleProps} {...editCircleProps}
/> />
<Circle <Circle
ref={bottomLeftHandleRef} ref={bottomLeftHandleRef}
x={handlePositions.bottomLeft.x} x={handlePositions.bottomLeft.x}
y={handlePositions.bottomLeft.y} y={handlePositions.bottomLeft.y}
name="bottomLeft"
{...editCircleProps} {...editCircleProps}
/> />
</Group> </Group>