2021-03-11 19:02:58 -05:00
|
|
|
import React, { useContext, useState, useEffect } from "react";
|
2021-02-05 21:32:38 -05:00
|
|
|
|
|
|
|
import Vector2 from "../helpers/Vector2";
|
|
|
|
import Size from "../helpers/Size";
|
2021-02-07 05:53:29 -05:00
|
|
|
// eslint-disable-next-line no-unused-vars
|
2021-02-05 21:32:38 -05:00
|
|
|
import { getGridPixelSize, getCellPixelSize, Grid } from "../helpers/grid";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef GridContextValue
|
|
|
|
* @property {Grid} grid Base grid value
|
|
|
|
* @property {Size} gridPixelSize Size of the grid in pixels
|
|
|
|
* @property {Size} gridCellPixelSize Size of each cell in pixels
|
|
|
|
* @property {Size} gridCellNormalizedSize Size of each cell normalized to the grid
|
|
|
|
* @property {Vector2} gridOffset Offset of the grid from the top left in pixels
|
|
|
|
* @property {number} gridStrokeWidth Stroke width of the grid in pixels
|
2021-02-11 03:57:34 -05:00
|
|
|
* @property {Vector2} gridCellPixelOffset Offset of the grid cells to convert the center position of hex cells to the top left
|
2021-02-05 21:32:38 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @type {GridContextValue}
|
|
|
|
*/
|
|
|
|
const defaultValue = {
|
|
|
|
grid: {
|
2021-02-06 03:29:24 -05:00
|
|
|
size: new Vector2(0, 0),
|
|
|
|
inset: { topLeft: new Vector2(0, 0), bottomRight: new Vector2(1, 1) },
|
2021-02-05 21:32:38 -05:00
|
|
|
type: "square",
|
2021-02-10 18:06:06 -05:00
|
|
|
measurement: {
|
|
|
|
scale: "",
|
|
|
|
type: "euclidean",
|
|
|
|
},
|
2021-02-05 21:32:38 -05:00
|
|
|
},
|
|
|
|
gridPixelSize: new Size(0, 0),
|
|
|
|
gridCellPixelSize: new Size(0, 0, 0),
|
|
|
|
gridCellNormalizedSize: new Size(0, 0, 0),
|
2021-02-06 03:29:24 -05:00
|
|
|
gridOffset: new Vector2(0, 0),
|
2021-02-05 21:32:38 -05:00
|
|
|
gridStrokeWidth: 0,
|
2021-02-11 03:57:34 -05:00
|
|
|
gridCellPixelOffset: new Vector2(0, 0),
|
2021-02-05 21:32:38 -05:00
|
|
|
};
|
|
|
|
|
2021-03-11 19:02:58 -05:00
|
|
|
const GridContext = React.createContext(defaultValue.grid);
|
|
|
|
const GridPixelSizeContext = React.createContext(defaultValue.gridPixelSize);
|
|
|
|
const GridCellPixelSizeContext = React.createContext(
|
|
|
|
defaultValue.gridCellPixelSize
|
|
|
|
);
|
|
|
|
const GridCellNormalizedSizeContext = React.createContext(
|
|
|
|
defaultValue.gridCellNormalizedSize
|
|
|
|
);
|
|
|
|
const GridOffsetContext = React.createContext(defaultValue.gridOffset);
|
|
|
|
const GridStrokeWidthContext = React.createContext(
|
|
|
|
defaultValue.gridStrokeWidth
|
|
|
|
);
|
|
|
|
const GridCellPixelOffsetContext = React.createContext(
|
|
|
|
defaultValue.gridCellPixelOffset
|
|
|
|
);
|
2021-02-05 21:32:38 -05:00
|
|
|
|
|
|
|
const defaultStrokeWidth = 1 / 10;
|
|
|
|
|
2021-03-11 19:02:58 -05:00
|
|
|
export function GridProvider({ grid: inputGrid, width, height, children }) {
|
|
|
|
let grid = inputGrid;
|
|
|
|
|
2021-02-05 21:32:38 -05:00
|
|
|
if (!grid?.size.x || !grid?.size.y) {
|
2021-03-11 19:02:58 -05:00
|
|
|
grid = defaultValue.grid;
|
2021-02-05 21:32:38 -05:00
|
|
|
}
|
|
|
|
|
2021-03-11 19:02:58 -05:00
|
|
|
const [gridPixelSize, setGridPixelSize] = useState(
|
|
|
|
defaultValue.gridCellPixelSize
|
2021-02-05 21:32:38 -05:00
|
|
|
);
|
2021-03-11 19:02:58 -05:00
|
|
|
const [gridCellPixelSize, setGridCellPixelSize] = useState(
|
|
|
|
defaultValue.gridCellPixelSize
|
2021-02-05 21:32:38 -05:00
|
|
|
);
|
2021-03-11 19:02:58 -05:00
|
|
|
const [gridCellNormalizedSize, setGridCellNormalizedSize] = useState(
|
|
|
|
defaultValue.gridCellNormalizedSize
|
|
|
|
);
|
|
|
|
const [gridOffset, setGridOffset] = useState(defaultValue.gridOffset);
|
|
|
|
const [gridStrokeWidth, setGridStrokeWidth] = useState(
|
|
|
|
defaultValue.gridStrokeWidth
|
|
|
|
);
|
|
|
|
const [gridCellPixelOffset, setGridCellPixelOffset] = useState(
|
|
|
|
defaultValue.gridCellPixelOffset
|
|
|
|
);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const _gridPixelSize = getGridPixelSize(grid, width, height);
|
|
|
|
const _gridCellPixelSize = getCellPixelSize(
|
|
|
|
grid,
|
|
|
|
_gridPixelSize.width,
|
|
|
|
_gridPixelSize.height
|
|
|
|
);
|
|
|
|
const _gridCellNormalizedSize = new Size(
|
|
|
|
_gridCellPixelSize.width / width,
|
|
|
|
_gridCellPixelSize.height / height
|
|
|
|
);
|
|
|
|
const _gridOffset = Vector2.multiply(grid.inset.topLeft, {
|
|
|
|
x: width,
|
|
|
|
y: height,
|
|
|
|
});
|
|
|
|
const _gridStrokeWidth =
|
|
|
|
(_gridCellPixelSize.width < _gridCellPixelSize.height
|
|
|
|
? _gridCellPixelSize.width
|
|
|
|
: _gridCellPixelSize.height) * defaultStrokeWidth;
|
|
|
|
|
|
|
|
let _gridCellPixelOffset = { x: 0, y: 0 };
|
|
|
|
// Move hex tiles to top left
|
|
|
|
if (grid.type === "hexVertical" || grid.type === "hexHorizontal") {
|
|
|
|
_gridCellPixelOffset = Vector2.multiply(_gridCellPixelSize, 0.5);
|
|
|
|
}
|
|
|
|
|
|
|
|
setGridPixelSize(_gridPixelSize);
|
|
|
|
setGridCellPixelSize(_gridCellPixelSize);
|
|
|
|
setGridCellNormalizedSize(_gridCellNormalizedSize);
|
|
|
|
setGridOffset(_gridOffset);
|
|
|
|
setGridStrokeWidth(_gridStrokeWidth);
|
|
|
|
setGridCellPixelOffset(_gridCellPixelOffset);
|
|
|
|
}, [grid, width, height]);
|
2021-02-11 03:57:34 -05:00
|
|
|
|
2021-03-11 19:02:58 -05:00
|
|
|
return (
|
|
|
|
<GridContext.Provider value={grid}>
|
|
|
|
<GridPixelSizeContext.Provider value={gridPixelSize}>
|
|
|
|
<GridCellPixelSizeContext.Provider value={gridCellPixelSize}>
|
|
|
|
<GridCellNormalizedSizeContext.Provider
|
|
|
|
value={gridCellNormalizedSize}
|
|
|
|
>
|
|
|
|
<GridOffsetContext.Provider value={gridOffset}>
|
|
|
|
<GridStrokeWidthContext.Provider value={gridStrokeWidth}>
|
|
|
|
<GridCellPixelOffsetContext.Provider
|
|
|
|
value={gridCellPixelOffset}
|
|
|
|
>
|
|
|
|
{children}
|
|
|
|
</GridCellPixelOffsetContext.Provider>
|
|
|
|
</GridStrokeWidthContext.Provider>
|
|
|
|
</GridOffsetContext.Provider>
|
|
|
|
</GridCellNormalizedSizeContext.Provider>
|
|
|
|
</GridCellPixelSizeContext.Provider>
|
|
|
|
</GridPixelSizeContext.Provider>
|
|
|
|
</GridContext.Provider>
|
|
|
|
);
|
2021-02-05 21:32:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
export function useGrid() {
|
|
|
|
const context = useContext(GridContext);
|
|
|
|
if (context === undefined) {
|
|
|
|
throw new Error("useGrid must be used within a GridProvider");
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
2021-03-11 19:02:58 -05:00
|
|
|
export function useGridPixelSize() {
|
|
|
|
const context = useContext(GridPixelSizeContext);
|
|
|
|
if (context === undefined) {
|
|
|
|
throw new Error("useGridPixelSize must be used within a GridProvider");
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function useGridCellPixelSize() {
|
|
|
|
const context = useContext(GridCellPixelSizeContext);
|
|
|
|
if (context === undefined) {
|
|
|
|
throw new Error("useGridCellPixelSize must be used within a GridProvider");
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function useGridCellNormalizedSize() {
|
|
|
|
const context = useContext(GridCellNormalizedSizeContext);
|
|
|
|
if (context === undefined) {
|
|
|
|
throw new Error(
|
|
|
|
"useGridCellNormalizedSize must be used within a GridProvider"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function useGridOffset() {
|
|
|
|
const context = useContext(GridOffsetContext);
|
|
|
|
if (context === undefined) {
|
|
|
|
throw new Error("useGridOffset must be used within a GridProvider");
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function useGridStrokeWidth() {
|
|
|
|
const context = useContext(GridStrokeWidthContext);
|
|
|
|
if (context === undefined) {
|
|
|
|
throw new Error("useGridStrokeWidth must be used within a GridProvider");
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function useGridCellPixelOffset() {
|
|
|
|
const context = useContext(GridCellPixelOffsetContext);
|
|
|
|
if (context === undefined) {
|
|
|
|
throw new Error(
|
|
|
|
"useGridCellPixelOffset must be used within a GridProvider"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return context;
|
|
|
|
}
|