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] && settings.selected[1] == last_selected[1]
) { ) {
if (settings.selected !== null && settings.picked !== null) { if (settings.selected !== null && settings.picked !== null) {
let preset = presets[settings.picked]; blit(presets[settings.picked].serialized, ...settings.selected);
let pane = Pane.deserialize(preset.serialized);
setWorld((world) => {
pane.blit(...settings.selected, world);
return world;
});
pane.free();
} }
} }
last_selected = [...settings.selected]; last_selected = [...settings.selected];
last_click = Date.now(); 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 ( return (
<div class={styles.Editor} onMount={mount()} onCleanup={cleanup()}> <div class={styles.Editor} onMount={mount()} onCleanup={cleanup()}>
{left_pane} {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} /> <RightPane settings={settings} world={world} setWorld={setWorld} setSettings={setSettings} />
</div> </div>
); );

@ -8,7 +8,7 @@ import styles from "./MiddlePane.module.css";
const ZOOM_STRENGTH = -0.005; const ZOOM_STRENGTH = -0.005;
export default function MiddlePane(props) { export default function MiddlePane(props) {
let {settings, setSettings, world} = props; let {settings, setSettings, world, blit} = props;
let mounted = true; let mounted = true;
let [canvas, setCanvas] = createStore({ let [canvas, setCanvas] = createStore({
@ -273,11 +273,12 @@ export default function MiddlePane(props) {
return [x, y]; return [x, y];
}); });
let _canvas; let _canvas, container;
return (<div return (<div
class={styles.MiddlePane} class={styles.MiddlePane}
onMount={set_resize()} onMount={set_resize()}
onCleanup={remove_resize()} onCleanup={remove_resize()}
ref={container}
> >
<canvas <canvas
ref={(el) => { ref={(el) => {
@ -290,8 +291,8 @@ export default function MiddlePane(props) {
onMount={() => {mounted = true}} onMount={() => {mounted = true}}
onCleanup={() => {mounted = false}} onCleanup={() => {mounted = false}}
onMouseDown={(evt) => { onMouseDown={(evt) => {
let mouse_x = evt.clientX - canvas.element.offsetLeft; let mouse_x = evt.clientX - container.offsetLeft;
let mouse_y = evt.clientY - canvas.element.offsetTop; let mouse_y = evt.clientY - container.offsetTop;
setMouse((mouse) => { setMouse((mouse) => {
return { return {
...mouse, ...mouse,
@ -309,17 +310,17 @@ export default function MiddlePane(props) {
if (mouse.down) { if (mouse.down) {
// TODO: numerically stable solution // TODO: numerically stable solution
setView("cx", view.cx + (evt.clientX - canvas.element.offsetLeft) - mouse.x); setView("cx", view.cx + (evt.clientX - container.offsetLeft) - mouse.x);
setView("cy", view.cy + (evt.clientY - canvas.element.offsetTop) - mouse.y); setView("cy", view.cy + (evt.clientY - container.offsetTop) - mouse.y);
} }
setMouse("x", evt.clientX - canvas.element.offsetLeft); setMouse("x", evt.clientX - container.offsetLeft);
setMouse("y", evt.clientY - canvas.element.offsetTop); setMouse("y", evt.clientY - container.offsetTop);
}} }}
onMouseUp={(evt) => { onMouseUp={(evt) => {
setMouse("down", false); setMouse("down", false);
setMouse("x", evt.clientX - canvas.element.offsetLeft); setMouse("x", evt.clientX - container.offsetLeft);
setMouse("y", evt.clientY - canvas.element.offsetTop); setMouse("y", evt.clientY - container.offsetTop);
let dist = Math.sqrt((mouse.x - mouse.click_x) ** 2 + (mouse.y - mouse.click_y) ** 2); let dist = Math.sqrt((mouse.x - mouse.click_x) ** 2 + (mouse.y - mouse.click_y) ** 2);
if (dist < 10) { if (dist < 10) {
@ -344,6 +345,28 @@ export default function MiddlePane(props) {
setView("cx", view.cx * delta); setView("cx", view.cx * delta);
setView("cy", view.cy * 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. Sowwy, your browser does not support canvases.
</canvas> </canvas>

@ -1,9 +1,23 @@
.MiddlePane { .MiddlePane {
flex-grow: 1; flex-grow: 1;
background: #202027; background: #202027;
position: relative;
} }
.canvas { .canvas {
width: 100%; width: 100%;
height: 100vh; 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 text = pane.to_text();
let width = pane.width; let width = pane.width;
let height = pane.height;
pane.free(); pane.free();
return {text, width}; return {text, width, height};
}); });
let id = createUniqueId(); let id = createUniqueId();
@ -30,6 +31,27 @@ export default function TilePreset(props) {
setSettings("picked", null); 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> <pre class={styles.preview} style={{width: 30 * rendered().width + "px"}} id={id}>{rendered().text}</pre>
<div>{props.name}</div> <div>{props.name}</div>

Loading…
Cancel
Save