import { FC, memo } from 'react'; import { Tile } from '../state/types'; import { tileFill } from '../state/selectors'; import { TILE_SIZE } from '../state/constants'; import { tileToScreen } from '../hooks/usePointerToTile'; type Props = { row: number; col: number; tile: Tile; selected: boolean; isDoor: boolean; southH?: number; westH?: number; }; const HEIGHT_LIFT = TILE_SIZE / 8; const diamondPoints = (row: number, col: number, h: number): string => { const [ cx, cyBase ] = tileToScreen(row, col); const cy = cyBase - h * HEIGHT_LIFT; const half = TILE_SIZE / 2; const quarter = TILE_SIZE / 4; return `${ cx },${ cy - quarter } ${ cx + half },${ cy } ${ cx },${ cy + quarter } ${ cx - half },${ cy }`; }; const darkenHex = (hex: string, factor: number): string => { const h = hex.replace('#', ''); if(h.length !== 6) return hex; const r = Math.max(0, Math.floor(parseInt(h.slice(0, 2), 16) * factor)); const g = Math.max(0, Math.floor(parseInt(h.slice(2, 4), 16) * factor)); const b = Math.max(0, Math.floor(parseInt(h.slice(4, 6), 16) * factor)); return `#${ [ r, g, b ].map(v => v.toString(16).padStart(2, '0')).join('') }`; }; const southWallPoints = (cx: number, cy: number, drop: number): string => { const half = TILE_SIZE / 2; const quarter = TILE_SIZE / 4; return `${ cx + half },${ cy } ${ cx + half },${ cy + drop } ${ cx },${ cy + quarter + drop } ${ cx },${ cy + quarter }`; }; const westWallPoints = (cx: number, cy: number, drop: number): string => { const half = TILE_SIZE / 2; const quarter = TILE_SIZE / 4; return `${ cx - half },${ cy } ${ cx },${ cy + quarter } ${ cx },${ cy + quarter + drop } ${ cx - half },${ cy + drop }`; }; const FloorplanTileImpl: FC = ({ row, col, tile, selected, isDoor, southH = 0, westH = 0 }) => { if(tile.blocked) { if(!selected) return null; const points = diamondPoints(row, col, tile.h); return ( ); } const points = diamondPoints(row, col, tile.h); const fill = tileFill(tile); const [ cx, cyBase ] = tileToScreen(row, col); const cy = cyBase - tile.h * HEIGHT_LIFT; const southDrop = Math.max(0, tile.h - southH) * HEIGHT_LIFT; const westDrop = Math.max(0, tile.h - westH) * HEIGHT_LIFT; const southFill = (southDrop > 0) ? darkenHex(fill, 0.70) : null; const westFill = (westDrop > 0) ? darkenHex(fill, 0.55) : null; return ( { southFill && ( ) } { westFill && ( ) } { tile.occupied && ( ) } { selected && ( ) } { isDoor && ( ) } ); }; export const FloorplanTile = memo(FloorplanTileImpl);