From 4f38aa71c53fec264ce3bb0d57bd0ab3730ed5e8 Mon Sep 17 00:00:00 2001 From: Adrien Burgun Date: Sat, 20 Aug 2022 18:10:53 +0200 Subject: [PATCH] :sparkles: Drag and drop support --- editor-solidjs/src/Editor.jsx | 28 ++++++++------- editor-solidjs/src/MiddlePane.jsx | 43 ++++++++++++++++++------ editor-solidjs/src/MiddlePane.module.css | 14 ++++++++ editor-solidjs/src/TilePreset.jsx | 24 ++++++++++++- 4 files changed, 86 insertions(+), 23 deletions(-) diff --git a/editor-solidjs/src/Editor.jsx b/editor-solidjs/src/Editor.jsx index f625493..772f037 100644 --- a/editor-solidjs/src/Editor.jsx +++ b/editor-solidjs/src/Editor.jsx @@ -114,27 +114,31 @@ export default function Editor() { && settings.selected[1] == last_selected[1] ) { if (settings.selected !== null && settings.picked !== null) { - let preset = presets[settings.picked]; - - let pane = Pane.deserialize(preset.serialized); - - setWorld((world) => { - pane.blit(...settings.selected, world); - - return world; - }); - - pane.free(); + blit(presets[settings.picked].serialized, ...settings.selected); } } last_selected = [...settings.selected]; last_click = Date.now(); } + function blit(serialized, x, y) { + let pane = Pane.deserialize(serialized); + + setWorld((world) => { + try { + pane.blit(x, y, world); + } finally { + return world; + } + }); + + pane.free(); + } + return (
{left_pane} - +
); diff --git a/editor-solidjs/src/MiddlePane.jsx b/editor-solidjs/src/MiddlePane.jsx index 2438531..8ee5bd0 100644 --- a/editor-solidjs/src/MiddlePane.jsx +++ b/editor-solidjs/src/MiddlePane.jsx @@ -8,7 +8,7 @@ import styles from "./MiddlePane.module.css"; const ZOOM_STRENGTH = -0.005; export default function MiddlePane(props) { - let {settings, setSettings, world} = props; + let {settings, setSettings, world, blit} = props; let mounted = true; let [canvas, setCanvas] = createStore({ @@ -273,11 +273,12 @@ export default function MiddlePane(props) { return [x, y]; }); - let _canvas; + let _canvas, container; return (
{ @@ -290,8 +291,8 @@ export default function MiddlePane(props) { onMount={() => {mounted = true}} onCleanup={() => {mounted = false}} onMouseDown={(evt) => { - let mouse_x = evt.clientX - canvas.element.offsetLeft; - let mouse_y = evt.clientY - canvas.element.offsetTop; + let mouse_x = evt.clientX - container.offsetLeft; + let mouse_y = evt.clientY - container.offsetTop; setMouse((mouse) => { return { ...mouse, @@ -309,17 +310,17 @@ export default function MiddlePane(props) { if (mouse.down) { // TODO: numerically stable solution - setView("cx", view.cx + (evt.clientX - canvas.element.offsetLeft) - mouse.x); - setView("cy", view.cy + (evt.clientY - canvas.element.offsetTop) - mouse.y); + setView("cx", view.cx + (evt.clientX - container.offsetLeft) - mouse.x); + setView("cy", view.cy + (evt.clientY - container.offsetTop) - mouse.y); } - setMouse("x", evt.clientX - canvas.element.offsetLeft); - setMouse("y", evt.clientY - canvas.element.offsetTop); + setMouse("x", evt.clientX - container.offsetLeft); + setMouse("y", evt.clientY - container.offsetTop); }} onMouseUp={(evt) => { setMouse("down", false); - setMouse("x", evt.clientX - canvas.element.offsetLeft); - setMouse("y", evt.clientY - canvas.element.offsetTop); + setMouse("x", evt.clientX - container.offsetLeft); + setMouse("y", evt.clientY - container.offsetTop); let dist = Math.sqrt((mouse.x - mouse.click_x) ** 2 + (mouse.y - mouse.click_y) ** 2); if (dist < 10) { @@ -344,6 +345,28 @@ export default function MiddlePane(props) { setView("cx", view.cx * delta); setView("cy", view.cy * delta); }} + onDrop={(evt) => { + evt.preventDefault(); + + container.classList.remove(styles.dragging); + let data = JSON.parse(evt.dataTransfer.getData("application/json")); + + blit(data, ...getHovered()); + + setSettings("selected", getHovered()); + }} + onDragOver={(evt) => { + evt.preventDefault(); + + container.classList.add(styles.dragging); + setMouse("hovering", true); + setMouse("x", evt.clientX - container.offsetLeft); + setMouse("y", evt.clientY - container.offsetTop); + }} + onDragLeave={(evt) => { + setMouse("hovering", false); + container.classList.remove(styles.dragging); + }} > Sowwy, your browser does not support canvases. diff --git a/editor-solidjs/src/MiddlePane.module.css b/editor-solidjs/src/MiddlePane.module.css index ccc7081..feeae49 100644 --- a/editor-solidjs/src/MiddlePane.module.css +++ b/editor-solidjs/src/MiddlePane.module.css @@ -1,9 +1,23 @@ .MiddlePane { flex-grow: 1; background: #202027; + position: relative; } .canvas { width: 100%; height: 100vh; } + +.MiddlePane.dragging::after { + content: ""; + position: absolute; + display: block; + top: 0; + left: 0; + right: 0; + bottom: 0; + box-shadow: 0px 0px 0px 1px inset rgba(255, 255, 255, 0.5); + pointer-events: none; + user-select: none; +} diff --git a/editor-solidjs/src/TilePreset.jsx b/editor-solidjs/src/TilePreset.jsx index dd5044e..d78e42c 100644 --- a/editor-solidjs/src/TilePreset.jsx +++ b/editor-solidjs/src/TilePreset.jsx @@ -12,10 +12,11 @@ export default function TilePreset(props) { let text = pane.to_text(); let width = pane.width; + let height = pane.height; pane.free(); - return {text, width}; + return {text, width, height}; }); let id = createUniqueId(); @@ -30,6 +31,27 @@ export default function TilePreset(props) { setSettings("picked", null); } }} + draggable="true" + onDragStart={(evt) => { + evt.dataTransfer.setData("application/json", JSON.stringify(props.pane())); + evt.dataTransfer.dropEffect = "copy"; + + const TILE_SIZE = 50; + let canvas = document.createElement("canvas"); + canvas.width = TILE_SIZE * rendered().width; + canvas.height = TILE_SIZE * rendered().height; + + let ctx = canvas.getContext("2d"); + ctx.font = `${TILE_SIZE}px Stackline Classic`; + + ctx.textAlign = "left"; + ctx.textBaseline = "top"; + + ctx.fillStyle = "white"; + ctx.fillText(rendered().text, 0, 0); + + evt.dataTransfer.setDragImage(canvas, canvas.width / 2, canvas.height / 2); + }} >
{rendered().text}
{props.name}