Add controls tab to the right pane, use S to step

main
Shad Amethyst 2 years ago
parent e2971e85eb
commit 0ed5df3fcc
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -0,0 +1,67 @@
import {onMount, onCleanup} from "solid-js";
import styles from "./RightPane.module.css";
import input_styles from "./input/input.module.css";
import {World} from "../stackline-wasm/stackline_wasm.js";
export default function Controls(props) {
let {settings, setSettings, world, setWorld} = props;
let save_button, reload_button;
function save() {
console.log("save");
window.localStorage.setItem("world", JSON.stringify(world().serialize()));
}
function reload() {
let new_world = window.localStorage.getItem("world");
if (!new_world) return;
new_world = JSON.parse(new_world);
new_world = World.deserialize(new_world);
setWorld(world => {
if (world.ptr) {
world.free();
}
return new_world;
});
}
function key_down(evt) {
if (evt.code === "KeyS" && evt.ctrlKey) {
evt.preventDefault();
save_button.classList.add(input_styles.active);
save();
setTimeout(() => {
save_button.classList.remove(input_styles.active);
}, 200);
}
if (evt.code === "KeyR" && evt.ctrlKey) {
evt.preventDefault();
reload_button.classList.add(input_styles.active);
reload();
setTimeout(() => {
reload_button.classList.remove(input_styles.active);
}, 200);
}
}
onMount(() => {
window.addEventListener("keydown", key_down, {capture: true});
});
onCleanup(() => {
window.removeEventListener("keydown", key_down);
});
return <div>
<button ref={save_button} class={input_styles.button} onClick={save}>Save</button>
<button ref={reload_button} class={input_styles.button} onClick={reload}>Reload</button>
</div>
}

@ -1,13 +1,18 @@
import { import {
createSignal, createSignal,
onMount,
onCleanup,
} from "solid-js"; } from "solid-js";
import {createStore} from "solid-js/store"; import {createStore} from "solid-js/store";
import Tabbed from "./Tabbed.jsx";
import styles from "./Editor.module.css"; import styles from "./Editor.module.css";
import styles_RightPane from "./RightPane.module.css";
import LeftPane from "./LeftPane.jsx"; import LeftPane from "./LeftPane.jsx";
import MiddlePane from "./MiddlePane.jsx"; import MiddlePane from "./MiddlePane.jsx";
import RightPane from "./RightPane.jsx"; import Properties from "./Properties.jsx";
import Controls from "./Controls.jsx";
import {World, Pane} from "../stackline-wasm/stackline_wasm.js"; import {World, Pane} from "../stackline-wasm/stackline_wasm.js";
@ -76,12 +81,12 @@ export default function Editor() {
} }
function keydown(event) { function keydown(event) {
if (event.code === "Space") { if (event.code === "KeyS") {
if (running()) { if (running()) {
pause(); pause();
} else if (event.shiftKey) { } else if (event.shiftKey) {
play(); play();
} else { } else if (!event.ctrlKey) {
step(); step();
} }
} else if (event.code === "KeyG") { } else if (event.code === "KeyG") {
@ -90,18 +95,18 @@ export default function Editor() {
} }
} }
function mount() { onMount(() => {
window.addEventListener("keydown", keydown); window.addEventListener("keydown", keydown);
} });
function cleanup() { onCleanup(() => {
window.removeEventListener("keydown", keydown); window.removeEventListener("keydown", keydown);
if (running()) { if (running()) {
clearInterval(running()); clearInterval(running());
setRunning(null); setRunning(null);
} }
} });
let [left_pane, presets] = LeftPane({settings, setSettings}); let [left_pane, presets] = LeftPane({settings, setSettings});
@ -136,10 +141,18 @@ export default function Editor() {
} }
return ( return (
<div class={styles.Editor} onMount={mount()} onCleanup={cleanup()}> <div class={styles.Editor}>
{left_pane} {left_pane}
<MiddlePane settings={settings} world={world} setSettings={setSettings} click={click} blit={blit} /> <MiddlePane settings={settings} world={world} setSettings={setSettings} click={click} blit={blit} />
<RightPane settings={settings} world={world} setWorld={setWorld} setSettings={setSettings} /> <div class={styles_RightPane.RightPane}>
<Tabbed>
<div title="Controls">
<Controls settings={settings} setSettings={setSettings} world={world} setWorld={setWorld} />
</div>
<div title="Files">Files</div>
</Tabbed>
<Properties settings={settings} world={world} setWorld={setWorld} setSettings={setSettings} />
</div>
</div> </div>
); );
} }

@ -72,8 +72,8 @@ export default function RightPane(props) {
} }
} }
return (<div class={styles.RightPane} onCleanup={cleanup}> return (<div class={styles.Properties}>
<Show when={selected() !== null} fallback={<i class={styles.gray}>Nothing selected</i>}> <Show when={selected() !== null} fallback={<i class={styles.gray}>Nothing selected</i>} onCleanup={cleanup}>
<h2 class={styles.h2}>Coordinates:</h2> <h2 class={styles.h2}>Coordinates:</h2>
({settings.selected[0]}, {settings.selected[1]}) ({settings.selected[0]}, {settings.selected[1]})
<h2 class={styles.h2}>State:</h2> <h2 class={styles.h2}>State:</h2>

@ -3,12 +3,15 @@
max-width: 25vw; max-width: 25vw;
background: #18181b; background: #18181b;
color: #d0d0d0; color: #d0d0d0;
padding: 1.5em 1em;
font-family: monospace; font-family: monospace;
font-size: 15px; font-size: 15px;
flex-shrink: 0; flex-shrink: 0;
} }
.Properties {
padding: 1.5em 1em;
}
.gray, .empty { .gray, .empty {
color: #a0a0a0; color: #a0a0a0;
} }

@ -0,0 +1,28 @@
import {createEffect, createSignal} from "solid-js";
import styles from "./Tabbed.module.css";
export default function Tabbed(props) {
let [current_tab, set_current_tab] = createSignal(0);
let children = props.children;
return <div class={styles.Tabbed}>
<ol class={styles.header}>
<For each={children.map(item => item.title)}>
{(item, index) => {
return <li
class={current_tab() == index() ? styles.active : null}
onClick={() => set_current_tab(index())}
>{item}</li>;
}}
</For>
</ol>
<ol class={styles.container}>
<For each={children}>
{(item, index) => {
return <li class={styles.body} class={current_tab() == index() ? styles.active : null}>{item}</li>
}}
</For>
</ol>
</div>
}

@ -0,0 +1,71 @@
.Tabbed {
height: 25vh;
display: flex;
flex-direction: column;
justify-content: stretch;
}
.header {
display: flex;
list-style-type: none;
margin: 0;
padding: 0;
flex-direction: row;
flex-wrap: wrap;
justify-content: stretch;
align-items: flex-start;
width: 100%;
flex-grow: 0;
flex-shrink: 0;
background: #242830;
}
.header > li {
box-sizing: border-box;
height: 2em;
padding: 0.5em;
color: #d0d0d0;
cursor: pointer;
user-select: none;
border-top: 1px solid var(--border-color);
border-left: 1px solid var(--border-color);
border-right: 1px solid var(--border-color);
border-top-left-radius: 2px;
border-top-right-radius: 2px;
--border-color: transparent;
}
.header > li:hover {
color: white;
--border-color: #d0d0d0;
}
.header > li.active {
color: #f0f0f0;
background: #18181b;
--border-color: white;
}
.header > li.active:hover {
color: white;
}
.container {
list-style-type: none;
margin: 0;
padding: 0;
flex-grow: 1;
}
.body:not(.active) {
display: none;
}
.body {
height: 100%;
padding: 1.5em 1em;
overflow-y: auto;
overflow-x: hidden;
box-sizing: border-box;
}

@ -77,6 +77,8 @@
border-radius: 2px; border-radius: 2px;
margin-left: 2px; margin-left: 2px;
margin-right: 2px; margin-right: 2px;
font-family: inherit;
font-size: inherit;
} }
.button[disabled] { .button[disabled] {
@ -91,6 +93,6 @@
border: 1px solid white; border: 1px solid white;
} }
.button:not([disabled]):active { .button:not([disabled]):active, .button:not([dissabled]).active {
background: rgb(64, 68, 96, 1.0); background: rgb(64, 68, 96, 1.0);
} }

Loading…
Cancel
Save