diff --git a/ui/src/app/page.tsx b/ui/src/app/page.tsx
index 78da4b0..d4fc22c 100644
--- a/ui/src/app/page.tsx
+++ b/ui/src/app/page.tsx
@@ -4,7 +4,7 @@ import React from 'react';
// Home page for siren
export default function Page() {
return (
-
+
);
diff --git a/ui/src/components/Header/header.css b/ui/src/components/Header/header.css
index 4ba9397..dabaca1 100644
--- a/ui/src/components/Header/header.css
+++ b/ui/src/components/Header/header.css
@@ -4,6 +4,7 @@
color: black;
border-bottom: 1px solid #e6e6e6;
max-height: 70px;
+ user-select: none;
}
.navbar .left {
diff --git a/ui/src/components/TileGrid/TileControls.tsx b/ui/src/components/TileGrid/TileControls.tsx
new file mode 100644
index 0000000..516b572
--- /dev/null
+++ b/ui/src/components/TileGrid/TileControls.tsx
@@ -0,0 +1,168 @@
+import { ActionIcon, Box, ColorPicker, Menu } from '@mantine/core';
+import { FaSquare, FaCircle, FaHandPaper, FaRegCircle } from 'react-icons/fa';
+import { FaMagnifyingGlass, FaPencil } from 'react-icons/fa6';
+
+export enum Tool {
+ HAND,
+ ZOOM,
+ EDIT,
+ TOKEN
+}
+
+export enum EditTool {
+ SQUARE,
+ CIRCLE
+}
+
+export const defaultColors = [
+ '#000000',
+ '#1D2B53',
+ '#7E2553',
+ '#008751',
+ '#AB5236',
+ '#5F574F',
+ '#C2C3C7',
+ '#FFF1E8',
+ '#FF004D'
+];
+
+interface TileControlsProps {
+ tool: Tool;
+ setTool: (tool: Tool) => void;
+ editTool: EditTool;
+ setEditTool: (editTool: EditTool) => void;
+ colors: string[];
+ setColors: (colors: string[]) => void;
+ selectedColor: number;
+ setSelectedColor: (selectedColor: number) => void;
+}
+
+export default function TileControls({
+ tool,
+ setTool,
+ editTool,
+ setEditTool,
+ colors,
+ setColors,
+ selectedColor,
+ setSelectedColor
+}: TileControlsProps) {
+ window.addEventListener(
+ 'keydown',
+ (e) => {
+ if (e.key === ' ') {
+ setTool(Tool.HAND);
+ } else if (e.key === 'z') {
+ setTool(Tool.ZOOM);
+ } else if (e.key === 'e') {
+ setTool(Tool.EDIT);
+ } else if (e.key === 't') {
+ setTool(Tool.TOKEN);
+ } else if (e.key === '1') {
+ setSelectedColor(0);
+ } else if (e.key === '2') {
+ setSelectedColor(1);
+ } else if (e.key === '3') {
+ setSelectedColor(2);
+ } else if (e.key === '4') {
+ setSelectedColor(3);
+ } else if (e.key === '5') {
+ setSelectedColor(4);
+ } else if (e.key === '6') {
+ setSelectedColor(5);
+ } else if (e.key === '7') {
+ setSelectedColor(6);
+ } else if (e.key === '8') {
+ setSelectedColor(7);
+ } else if (e.key === '9') {
+ setSelectedColor(8);
+ }
+ },
+ { passive: false }
+ );
+
+ function checkIfColorIsDark(color: string) {
+ // If the color is dark, return white, otherwise return black
+ const r = parseInt(color.slice(1, 3), 16);
+ const g = parseInt(color.slice(3, 5), 16);
+ const b = parseInt(color.slice(5, 7), 16);
+ const brightness = (r * 299 + g * 587 + b * 114) / 1000;
+ return brightness < 128 ? '#ffffff' : '#000000';
+ }
+
+ return (
+
+ {tool === Tool.EDIT && (
+
+ setEditTool(EditTool.SQUARE)}
+ >
+
+
+ setEditTool(EditTool.CIRCLE)}
+ >
+
+
+
+ )}
+
+ setTool(Tool.HAND)}>
+
+
+ setTool(Tool.ZOOM)}>
+
+
+ setTool(Tool.EDIT)}>
+
+
+ setTool(Tool.TOKEN)}>
+
+
+
+
+ {colors.map((color, index) => (
+
+ ))}
+
+
+ );
+}
diff --git a/ui/src/components/TileGrid/index.tsx b/ui/src/components/TileGrid/index.tsx
index c186348..5823da1 100644
--- a/ui/src/components/TileGrid/index.tsx
+++ b/ui/src/components/TileGrid/index.tsx
@@ -1,25 +1,45 @@
'use client';
-import { Graphics, Stage } from '@pixi/react';
+import { Container, Graphics, Stage } from '@pixi/react';
import { Graphics as PixiGraphics } from '@pixi/graphics';
-import { MouseEvent, WheelEvent, useCallback, useState } from 'react';
-
-// export default function TileGrid({ width, height }: TileGridProps) {
-export default function TIleGrid() {
- const [mouseDown, setMouseDown] = useState(false);
- const [lastPosition, setLastPosition] = useState({ x: 0, y: 0 });
- const [position, setPosition] = useState({ x: 0, y: 0 });
+import { MouseEvent, WheelEvent, useCallback, useEffect, useState } from 'react';
+import TileControls, { EditTool, Tool, defaultColors } from './TileControls';
+export default function TileGrid() {
// Offset height of navbar from window height
- const height = window.innerHeight - 75;
+ const height = window ? window.innerHeight - 75 : 0;
// Offset width of layout padding from window width
- const width = window.innerWidth;
+ const width = window ? window.innerWidth : 0;
+
+ const [scale, setScale] = useState(1);
+ const [zoom, setZoom] = useState(1);
+ const [size, setSize] = useState({ width: width * 2, height: height * 2 });
+ const [boundaries, setBoundaries] = useState({ top: 0, bottom: 0, left: 0, right: 0 });
+ const [mouseDown, setMouseDown] = useState(false);
+ const [lastPosition, setLastPosition] = useState({ x: -width / 2, y: -height / 2 });
+ const [position, setPosition] = useState({ x: -width / 2, y: -height / 2 });
+ const [tool, setTool] = useState
(Tool.HAND);
+ const [editTool, setEditTool] = useState(EditTool.SQUARE);
+ const [colors, setColors] = useState(defaultColors);
+ const [selectedColor, setSelectedColor] = useState(0);
+
+ useEffect(() => {
+ if (window) {
+ window.addEventListener(
+ 'wheel',
+ (event) => {
+ event.preventDefault();
+ },
+ { passive: false }
+ );
+ }
+ }, []);
const draw = useCallback((g: PixiGraphics) => {
g.clear();
// Draw dot in the corner of each tile
- for (let x = 0; x < width; x += 32) {
- for (let y = 0; y < height; y += 32) {
+ for (let x = 0; x < size.width; x += 32 * scale) {
+ for (let y = 0; y < size.height; y += 32 * scale) {
g.beginFill(0xffffff, 0.5);
g.drawCircle(x, y, 1);
g.endFill();
@@ -27,37 +47,60 @@ export default function TIleGrid() {
}
}, []);
- function pan(e: MouseEvent) {
+ function clickEvent(e: MouseEvent) {
+ if (tool === Tool.HAND) {
+ setMouseDown(true);
+ setLastPosition({ x: e.clientX, y: e.clientY });
+ }
+ }
+
+ function moveEvent(e: MouseEvent) {
if (mouseDown) {
const dx = position.x + e.clientX - lastPosition.x;
const dy = position.y + e.clientY - lastPosition.y;
+ // TODO: Boundaries
setPosition({ x: dx, y: dy });
setLastPosition({ x: e.clientX, y: e.clientY });
}
}
- function zoom(e: WheelEvent) {
- console.log('zoom', e);
+ function zoomEvent(e: WheelEvent) {
+ const delta = e.deltaY;
+ if (delta > 0) {
+ setZoom(zoom / 1.1);
+ } else {
+ setZoom(zoom * 1.1);
+ }
+ setScale(scale * zoom);
}
return (
- {
- setMouseDown(true);
- setLastPosition({ x: e.clientX, y: e.clientY });
- }}
- onMouseUp={() => setMouseDown(false)}
- onMouseMove={(e) => pan(e)}
- onWheel={(e) => zoom(e)}
- onClick={(e) => console.log(e)}
- >
-
-
+ <>
+ clickEvent(e)}
+ onMouseUp={() => setMouseDown(false)}
+ onMouseMove={(e) => moveEvent(e)}
+ onWheel={(e) => zoomEvent(e)}
+ >
+
+
+
+
+ >
);
}