diff --git a/src/components/map/Map.js b/src/components/map/Map.js index 4b31a7b..7cbf956 100644 --- a/src/components/map/Map.js +++ b/src/components/map/Map.js @@ -330,9 +330,7 @@ function Map({ /> ); - const mapGrid = map && map.showGrid && ( - - ); + const mapGrid = map && map.showGrid && ; const mapMeasure = ( + + + + diff --git a/src/components/map/MapGrid.js b/src/components/map/MapGrid.js index f809f61..54bd306 100644 --- a/src/components/map/MapGrid.js +++ b/src/components/map/MapGrid.js @@ -10,7 +10,7 @@ import { mapSources as defaultMapSources } from "../../maps"; import { getStrokeWidth } from "../../helpers/drawing"; import { getImageLightness } from "../../helpers/image"; -function MapGrid({ map, gridSize }) { +function MapGrid({ map, strokeWidth }) { let mapSourceMap = map; // Use lowest resolution for grid lightness if (map && map.type === "file" && map.resolutions) { @@ -24,6 +24,10 @@ function MapGrid({ map, gridSize }) { const gridX = map && map.grid.size.x; const gridY = map && map.grid.size.y; + const gridSizeNormalized = { + x: gridX ? 1 / gridX : 0, + y: gridY ? 1 / gridY : 0, + }; const { mapWidth, mapHeight } = useContext(MapInteractionContext); @@ -35,6 +39,7 @@ function MapGrid({ map, gridSize }) { // When the map changes find the average lightness of its pixels useEffect(() => { if (mapLoadingStatus === "loaded") { + console.log("getting lightness"); setIsImageLight(getImageLightness(mapImage)); } }, [mapImage, mapLoadingStatus]); @@ -46,7 +51,12 @@ function MapGrid({ map, gridSize }) { key={`grid_x_${x}`} points={[x * lineSpacingX, 0, x * lineSpacingX, mapHeight]} stroke={isImageLight ? "black" : "white"} - strokeWidth={getStrokeWidth(0.1, gridSize, mapWidth, mapHeight)} + strokeWidth={getStrokeWidth( + strokeWidth, + gridSizeNormalized, + mapWidth, + mapHeight + )} opacity={0.5} /> ); @@ -57,7 +67,12 @@ function MapGrid({ map, gridSize }) { key={`grid_y_${y}`} points={[0, y * lineSpacingY, mapWidth, y * lineSpacingY]} stroke={isImageLight ? "black" : "white"} - strokeWidth={getStrokeWidth(0.1, gridSize, mapWidth, mapHeight)} + strokeWidth={getStrokeWidth( + strokeWidth, + gridSizeNormalized, + mapWidth, + mapHeight + )} opacity={0.5} /> ); @@ -66,4 +81,8 @@ function MapGrid({ map, gridSize }) { return {lines}; } +MapGrid.defaultProps = { + strokeWidth: 0.1, +}; + export default MapGrid; diff --git a/src/components/map/MapGridEditor.js b/src/components/map/MapGridEditor.js new file mode 100644 index 0000000..fdeb0b1 --- /dev/null +++ b/src/components/map/MapGridEditor.js @@ -0,0 +1,156 @@ +import React, { useContext, useRef } from "react"; +import { Group, Circle, Rect } from "react-konva"; + +import MapInteractionContext from "../../contexts/MapInteractionContext"; + +import * as Vector2 from "../../helpers/vector2"; + +function MapGridEditor({ map, onGridChange }) { + const { + mapWidth, + mapHeight, + stageScale, + setPreventMapInteraction, + } = useContext(MapInteractionContext); + + const mapSize = { x: mapWidth, y: mapHeight }; + + const topLeftHandleRef = useRef(); + const topRightHandleRef = useRef(); + const bottomRightHandleRef = useRef(); + const bottomLeftHandleRef = useRef(); + + function handleScaleCircleDragStart() {} + + function handleScaleCircleDragMove(event) { + onGridChange(getHandleInset(event.target)); + } + + function handleScaleCircleDragEnd(event) { + onGridChange(getHandleInset(event.target)); + setPreventMapInteraction(false); + } + + function handleInteractivePointerDown() { + setPreventMapInteraction(true); + } + + function handleInteractivePointerUp() { + setPreventMapInteraction(false); + } + + const editCircleRadius = Math.max( + (Math.min(mapWidth, mapHeight) / 30) * Math.max(1 / stageScale, 1), + 1 + ); + + const editCircleProps = { + radius: editCircleRadius, + fill: "rgba(0, 0, 0, 0.5)", + stroke: "white", + strokeWidth: editCircleRadius / 5, + draggable: true, + onDragStart: handleScaleCircleDragStart, + onDragMove: handleScaleCircleDragMove, + onDragEnd: handleScaleCircleDragEnd, + onMouseDown: handleInteractivePointerDown, + onMouseUp: handleInteractivePointerUp, + onTouchStart: handleInteractivePointerDown, + onTouchEnd: handleInteractivePointerUp, + }; + + const editRectProps = { + fill: "transparent", + stroke: "white", + strokeWidth: editCircleRadius / 5, + }; + + function getHandleInset(handle) { + const topLeftHandle = topLeftHandleRef.current; + const topRightHandle = topRightHandleRef.current; + const bottomRightHandle = bottomRightHandleRef.current; + const bottomLeftHandle = bottomLeftHandleRef.current; + + 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 + ); + + if (handle === topLeftHandle || handle === bottomRightHandle) { + return { topLeft, bottomRight }; + } else { + return { + topLeft: { x: bottomLeft.x, y: topRight.y }, + bottomRight: { x: topRight.x, y: bottomLeft.y }, + }; + } + } + + function getHandlePositions() { + const topLeft = Vector2.multiply(map.grid.inset.topLeft, mapSize); + const bottomRight = Vector2.multiply(map.grid.inset.bottomRight, mapSize); + + const size = Vector2.subtract(bottomRight, topLeft); + const offset = Vector2.multiply(topLeft, -1); + + return { + topLeft, + topRight: { x: bottomRight.x, y: topLeft.y }, + bottomRight, + bottomLeft: { x: topLeft.x, y: bottomRight.y }, + size, + offset, + }; + } + + const handlePositions = getHandlePositions(); + + return ( + + + + + + + + ); +} + +export default MapGridEditor; diff --git a/src/database.js b/src/database.js index 9af1e57..f512eed 100644 --- a/src/database.js +++ b/src/database.js @@ -217,8 +217,7 @@ function loadVersions(db) { map.group = ""; map.grid = { size: { x: map.gridX, y: map.gridY }, - scale: { x: 1, y: 1 }, - offset: { x: 0, y: 0 }, + inset: { topLeft: { x: 0, y: 0 }, bottomRight: { x: 1, y: 1 } }, type: "square", }; delete map.gridX; diff --git a/src/maps/index.js b/src/maps/index.js index d008524..0aaa7ea 100644 --- a/src/maps/index.js +++ b/src/maps/index.js @@ -23,8 +23,7 @@ export const maps = Object.keys(mapSources).map((key) => ({ name: Case.capital(key), grid: { size: { x: 22, y: 22 }, - scale: { x: 1, y: 1 }, - offset: { x: 0, y: 0 }, + inset: { topLeft: { x: 0, y: 0 }, bottomRight: { x: 1, y: 1 } }, type: "square", }, width: 1024, diff --git a/src/modals/EditMapModal.js b/src/modals/EditMapModal.js index 6a11475..855b630 100644 --- a/src/modals/EditMapModal.js +++ b/src/modals/EditMapModal.js @@ -87,7 +87,10 @@ function EditMapModal({ isOpen, onDone, map, mapState }) { - +