diff --git a/app/react-components/devtools.jsx b/app/react-components/devtools.jsx index 4e3a1eb..4b31f7f 100644 --- a/app/react-components/devtools.jsx +++ b/app/react-components/devtools.jsx @@ -7,12 +7,8 @@ import Tiles from './devtools/tiles.jsx'; export default function Devtools({ applyFilters, - brush, - layer, + eventsChannel, setApplyFilters, - setBrush, - setLayer, - setStamp, }) { return (
@@ -44,11 +40,7 @@ export default function Devtools({ diff --git a/app/react-components/devtools/tiles.jsx b/app/react-components/devtools/tiles.jsx index 920368e..a81dbc1 100644 --- a/app/react-components/devtools/tiles.jsx +++ b/app/react-components/devtools/tiles.jsx @@ -1,23 +1,58 @@ -import {useRef, useState} from 'react'; +import {useEffect, useRef, useState} from 'react'; +import {useClient} from '@/context/client.js'; import {useEcs} from '@/context/ecs.js'; import useRect from '@/util/react-hooks/use-rect.js'; import styles from './tiles.module.css'; -export default function Tiles({ - brush, - layer, - setBrush, - setLayer, - setStamp, -}) { +export default function Tiles({eventsChannel}) { + const client = useClient(); const wrapperRef = useRef(); const imageRef = useRef(); const imageRect = useRect(imageRef); const [selection, setSelection] = useState({x: 0, y: 0, w: 1, h: 1}); const [moveStart, setMoveStart] = useState(); + const [layer, setLayer] = useState(0); + const [brush, setBrush] = useState(0); + const [stamp, setStamp] = useState([]); const [ecs] = useEcs(); + useEffect(() => { + if (!ecs) { + return false; + } + const master = ecs.get(1); + if (!master) { + return false; + } + const {TileLayers} = master; + const {area, tileSize} = TileLayers.layer(0); + function onClick({x, y}) { + const at = { + x: Math.floor(x / tileSize.x), + y: Math.floor(y / tileSize.y), + }; + if (at.x < 0 || at.y < 0 || at.x >= area.x || at.y >= area.y) { + return; + } + const payload = { + brush, + layer, + stamp: { + at, + data: stamp, + }, + } + client.send({ + type: 'AdminAction', + payload: {type: 'paint', value: payload}, + }); + } + eventsChannel.addListener('click', onClick); + return () => { + eventsChannel.removeListener('click', onClick); + }; + }); if (!ecs) { return false; } diff --git a/app/react-components/ui.jsx b/app/react-components/ui.jsx index 695abfa..d7b3c19 100644 --- a/app/react-components/ui.jsx +++ b/app/react-components/ui.jsx @@ -19,6 +19,32 @@ function emptySlots() { return Array(10).fill(undefined); } +const devEventsChannel = { + $$listeners: {}, + addListener(type, listener) { + if (!this.$$listeners[type]) { + this.$$listeners[type] = new Set(); + } + this.$$listeners[type].add(listener); + }, + invoke(type, payload) { + const listeners = this.$$listeners[type]; + if (!listeners) { + return; + } + for (const listener of listeners) { + listener(payload); + } + }, + removeListener(type, listener) { + const listeners = this.$$listeners[type]; + if (!listeners) { + return; + } + listeners.delete(listener); + }, +}; + export default function Ui({disconnected}) { // Key input. const client = useClient(); @@ -35,9 +61,6 @@ export default function Ui({disconnected}) { const [scale, setScale] = useState(2); const [Components, setComponents] = useState(); const [Systems, setSystems] = useState(); - const [layer, setLayer] = useState(0); - const [brush, setBrush] = useState(0); - const [stamp, setStamp] = useState([]); const [applyFilters, setApplyFilters] = useState(true); useEffect(() => { async function setEcsStuff() { @@ -278,36 +301,22 @@ export default function Ui({disconnected}) { return; } const {Camera} = ecs.get(mainEntity); - const {TileLayers} = master; - const {area, tileSize} = TileLayers.layer(0); const size = width / RESOLUTION.x; - const cr = { + const client = { x: (event.clientX - left) / size, y: (event.clientY - top) / size, }; - const cm = { + const camera = { x: ((Camera.x * scale) - (RESOLUTION.x / 2)), y: ((Camera.y * scale) - (RESOLUTION.y / 2)), } - const at = { - x: Math.floor((cr.x + cm.x) / (tileSize.x * scale)), - y: Math.floor((cr.y + cm.y) / (tileSize.y * scale)), - }; - if (at.x < 0 || at.y < 0 || at.x >= area.x || at.y >= area.y) { - return; - } - const payload = { - brush, - layer, - stamp: { - at, - data: stamp, + devEventsChannel.invoke( + 'click', + { + x: (client.x + camera.x) / scale, + y: (client.y + camera.y) / scale, }, - } - client.send({ - type: 'AdminAction', - payload: {type: 'paint', value: payload}, - }); + ); } else { client.send({ @@ -380,13 +389,8 @@ export default function Ui({disconnected}) {