Newer
Older
import { useCallback, useContext, useEffect, useRef, useState } from "react";
import { Canvas } from "../lib/canvas";
import { useAppContext } from "../contexts/AppContext";
import { PanZoomWrapper } from "@sc07-canvas/lib/src/renderer";
import { RendererContext } from "@sc07-canvas/lib/src/renderer/RendererContext";
import { ViewportMoveEvent } from "@sc07-canvas/lib/src/renderer/PanZoom";
import throttle from "lodash.throttle";
import { IPosition } from "@sc07-canvas/lib/src/net";
import { Template } from "./Templating/Template";
import { IRouterData, Router } from "../lib/router";
import { KeybindManager } from "../lib/keybinds";

Grant
committed
import { HeatmapOverlay } from "./Overlay/HeatmapOverlay";
const { config } = useAppContext();
// to prevent safari from blurring things, use the zoom css property

Grant
committed
<HeatmapOverlay />
{config && <Template />}
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
const Cursor = () => {
const { cursor } = useAppContext();
const [color, setColor] = useState<string>();
useEffect(() => {
console.log("color", color);
}, [color]);
useEffect(() => {
if (typeof cursor.color === "number") {
const color = Canvas.instance?.Pallete.getColor(cursor.color);
setColor(color?.hex);
} else {
setColor(undefined);
}
}, [setColor, cursor.color]);
if (!color) return <></>;
return (
<div
className="noselect"
style={{
position: "absolute",
top: cursor.y,
left: cursor.x,
backgroundColor: "#" + color,
width: "1px",
height: "1px",
opacity: 0.5,
}}
></div>
);
};
const canvasRef = useRef<HTMLCanvasElement | null>();
const canvas = useRef<Canvas>();
const { config, setCanvasPosition, setCursor, setPixelWhois } =
useAppContext();
const handlePixelWhois = useCallback(
({ clientX, clientY }: { clientX: number; clientY: number }) => {
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
if (!canvas.current) {
console.warn(
"[CanvasWrapper#handlePixelWhois] canvas instance does not exist"
);
return;
}
const [x, y] = canvas.current.screenToPos(clientX, clientY);
if (x < 0 || y < 0) return; // discard if out of bounds
// canvas size can dynamically change, so we need to check the current config
// we're depending on canvas.instance's config so we don't have to use a react dependency
if (canvas.current.hasConfig()) {
const {
canvas: {
size: [width, height],
},
} = canvas.current.getConfig();
if (x >= width || y >= height) return; // out of bounds
} else {
// although this should never happen, log it
console.warn(
"[CanvasWrapper#handlePixelWhois] canvas config is not available yet"
);
}
// .......
// .......
// .......
// ...x...
// .......
// .......
// .......
const surrounding = canvas.current.getSurroundingPixels(x, y, 3);
setPixelWhois({ x, y, surrounding });
},
[canvas.current]
);
useEffect(() => {
if (!canvasRef.current) return;
canvas.current = new Canvas(canvasRef.current!, PanZoom);
canvas.current.on("canvasReady", () => {
console.log("[CanvasWrapper] received canvasReady");
// refresh because canvas might've resized
const initialRouter = Router.get();
handleNavigate(initialRouter);
});
KeybindManager.on("PIXEL_WHOIS", handlePixelWhois);
KeybindManager.off("PIXEL_WHOIS", handlePixelWhois);
useEffect(() => {
Router.PanZoom = PanZoom;
}, [PanZoom]);
if (!canvas.current) {
console.warn("canvas isntance doesn't exist");
return;
}
const handleCursorPos = throttle((pos: IPosition) => {
if (!canvas.current?.hasConfig() || !config) {
console.warn("handleCursorPos has no config");
return;
}
if (
pos.x < 0 ||
pos.y < 0 ||
pos.x > config.canvas.size[0] ||
pos.y > config.canvas.size[1]
) {
setCursor((v) => ({
...v,
x: undefined,
y: undefined,
}));
} else {
// fixes not passing the current value
setCursor((v) => ({
...v,
x: pos.x,
y: pos.y,
}));
}
}, 1);
canvas.current.on("cursorPos", handleCursorPos);
return () => {
canvas.current!.off("cursorPos", handleCursorPos);
};
useEffect(() => {
if (!canvas.current) {
console.warn("canvasinner config received but no canvas instance");
return;
}
if (!config) {
console.warn("canvasinner config received falsey");
return;
}
console.log("[CanvasInner] config updated, informing canvas instance");
canvas.current.loadConfig(config);
// refresh because canvas might've resized
const initialRouter = Router.get();
console.log(
"[CanvasWrapper] Config updated, triggering navigate",
initialRouter
);
handleNavigate(initialRouter);
}, [config]);
const handleNavigate = useCallback(
(data: IRouterData) => {
const position = canvas.current!.canvasToPanZoomTransform(
data.canvas.x,
data.canvas.y
);
PanZoom.setPosition(
{
x: position.transformX,
y: position.transformY,
zoom: data.canvas.zoom || 0, // TODO: fit canvas to viewport instead of defaulting
},
{ suppressEmit: true }
);
},
[PanZoom]
);
useEffect(() => {
// if (!config?.canvas || !canvasRef.current) return;
// const canvas = canvasRef.current!;
// const canvasInstance = new Canvas(canvas, PanZoom);
const initAt = Date.now();
// initial load
const initialRouter = Router.get();
console.log(
"[CanvasWrapper] Initial router data, handling navigate",
initialRouter
);
handleNavigate(initialRouter);
const handleViewportMove = (state: ViewportMoveEvent) => {
if (Date.now() - initAt < 60 * 1000) {
console.debug(
"[CanvasWrapper] handleViewportMove called soon after init",
Date.now() - initAt
);
}
if (canvas.current) {
const pos = canvas.current?.panZoomTransformToCanvas();
setCanvasPosition({
x: pos.canvasX,
y: pos.canvasY,
zoom: state.scale >> 0,
});
} else {
console.warn(
"[CanvasWrapper] handleViewportMove has no canvas instance"
);
}
PanZoom.addListener("viewportMove", handleViewportMove);
PanZoom.removeListener("viewportMove", handleViewportMove);
return (
<canvas
id="board"
width="1000"
height="1000"
className="pixelate"