Drag and drop support

main
Shad Amethyst 2 years ago
parent 06040f2c89
commit 4f38aa71c5
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -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 (
<div class={styles.Editor} onMount={mount()} onCleanup={cleanup()}>
{left_pane}
<MiddlePane settings={settings} world={world} setSettings={setSettings} click={click} />
<MiddlePane settings={settings} world={world} setSettings={setSettings} click={click} blit={blit} />
<RightPane settings={settings} world={world} setWorld={setWorld} setSettings={setSettings} />
</div>
);

@ -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 (<div
class={styles.MiddlePane}
onMount={set_resize()}
onCleanup={remove_resize()}
ref={container}
>
<canvas
ref={(el) => {
@ -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.
</canvas>

@ -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;
}

@ -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);
}}
>
<pre class={styles.preview} style={{width: 30 * rendered().width + "px"}} id={id}>{rendered().text}</pre>
<div>{props.name}</div>

Loading…
Cancel
Save