This commit is contained in:
kolaflash
2025-11-25 19:32:27 +01:00
commit 104f0998e1
36 changed files with 1274 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
import type { Component, JSX } from "solid-js";
import style from "./controls.module.css";
export const RangeSlider: Component<{
name: string;
min: number;
max: number;
step: number;
value: number;
children?: JSX.Element;
onChange?: (value: number) => void;
onInput?: (value: number) => void;
}> = (props) => (
<label class={style.rangeSlider}>
{props.children}
<input
type="range"
name={props.name}
min={props.min}
max={props.max}
step={props.step}
value={props.value}
onChange={(e) => props.onChange?.(e.target.valueAsNumber)}
onInput={(e) => props.onInput?.(e.target.valueAsNumber)}
/>
</label>
);
+70
View File
@@ -0,0 +1,70 @@
.rangeSlider {
width: 100%;
color: var(--c-fg-2);
display: flex;
flex-flow: row nowrap;
justify-content: center;
align-items: center;
gap: var(--sp-2);
font-family: var(--font-sans);
font-weight: bold;
padding: var(--sp-2);
}
.rangeSlider [type="range"] {
cursor: pointer;
appearance: none;
background: transparent;
border-radius: var(--sp-2);
height: var(--sp-3);
flex: auto;
&:focus {
outline: 0;
}
&::-webkit-slider-runnable-track {
width: 100%;
height: var(--sp-2);
border-radius: var(--sp-3);
color: transparent;
background: var(--c-bg-3);
border: none;
}
&::-webkit-slider-thumb {
height: var(--sp-3);
width: var(--sp-3);
border-radius: var(--sp-3);
border: none;
background: var(--c-fg-1);
margin-top: calc(var(--sp-1) * -1);
--webkit-appearance: none;
appearance: none;
}
&:focus::-webkit-slider-thumb {
outline-width: 2px;
outline-style: solid;
outline-color: var(--c-primary);
}
&::-moz-range-track {
width: 100%;
height: var(--sp-2);
border-radius: var(--sp-3);
color: transparent;
background: var(--c-bg-3);
border: none;
}
&::-moz-range-thumb {
height: var(--sp-3);
width: var(--sp-3);
border-radius: var(--sp-3);
border: none;
background: var(--c-fg-1);
}
&:focus::-moz-range-thumb {
outline-width: 2px;
outline-style: solid;
outline-color: var(--c-primary);
}
}
+105
View File
@@ -0,0 +1,105 @@
.devTools {
--font-sans:
ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol", "Noto Color Emoji";
--font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
--font-mono:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
--rgb-blurple: 101, 114, 245;
--c-blurple: rgb(var(--rgb-blurple));
--rgb-fuchsia: 238, 69, 158;
--c-fuchsia: rgb(var(--rgb-fuchsia));
--rgb-green: 35, 165, 89;
--c-green: rgb(var(--rgb-green));
--rgb-yellow: 240, 178, 50;
--c-yellow: rgb(var(--rgb-yellow));
--rgb-orange: 255, 144, 0;
--c-orange: rgb(var(--rgb-orange));
--rgb-red: 218, 55, 60;
--c-red: rgb(var(--rgb-red));
--rgb-cyan: 95, 205, 228;
--c-cyan: rgb(var(--rgb-cyan));
--rgb-pink: 246, 42, 245;
--c-pink: rgb(var(--rgb-pink));
--rgb-gray: 117, 126, 138;
--c-gray: rgb(var(--rgb-gray));
--rgb-white: 255, 255, 255;
--c-white: rgb(var(--rgb-white));
--rgb-black: 30, 31, 34;
--c-black: rgb(var(--rgb-black));
--c-primary: var(--c-blurple);
--c-secondary: var(--c-fuchsia);
--c-alert: var(--c-orange);
--c-error: var(--c-red);
--c-bg-0: rgb(30, 31, 34);
--c-bg-1: rgb(43, 45, 49);
--c-bg-2: rgb(49, 51, 56);
--c-bg-3: rgb(64, 66, 73);
--c-fg-0: rgb(255 255 225);
--c-fg-1: rgb(219 222 225);
--c-fg-2: rgb(181 186 193);
--c-fg-3: rgb(113 116 120);
--sp-1: 4px;
--sp-2: 8px;
--sp-3: 16px;
--sp-4: 24px;
--sp-5: 32px;
--sp-6: 48px;
height: 100%;
min-width: 1px;
max-width: 100%;
position: absolute;
top: 0;
left: 0;
order: -1;
font-size: medium;
font-family: var(--font-sans);
*,
*::after,
*::before {
box-sizing: border-box;
}
*:focus {
outline-width: 2px;
outline-style: solid;
outline-color: var(--c-primary);
}
}
.toolBar {
overflow: hidden;
border-right: 1px solid var(--c-fg-3);
background: var(--c-bg-1);
color: var(--c-fg-1);
width: 100%;
height: 100%;
}
.toolBarResize {
position: absolute;
top: 0;
right: -3px;
width: 5px;
height: 100%;
cursor: ew-resize;
user-select: none;
}
+63
View File
@@ -0,0 +1,63 @@
import { type Component, createSignal, onMount } from "solid-js";
import { render } from "solid-js/web";
import { setScale, viewport } from "#/engine/Viewport.ts";
import { RangeSlider } from "#/tools/controls/RangeSlider.tsx";
import style from "./main.module.css";
function adjustGameContainer(gameContainer: HTMLElement, width: number): void {
gameContainer.style = `position: relative; top: 0; left: ${width}px; width: ${document.body.offsetWidth - width}px;`;
}
const DevTools: Component<{ gameContainer: HTMLElement }> = ({
gameContainer,
}) => {
const [width, setWidth] = createSignal(320);
let isResizing = false;
const startResizing = (): void => {
isResizing = true;
};
const stopResizing = (): void => {
isResizing = false;
};
const handleMouseMove = (event: MouseEvent) => {
if (isResizing) {
setWidth(event.clientX);
self.dispatchEvent(new Event("resize"));
}
};
adjustGameContainer(gameContainer, width());
onMount(() => {
self.addEventListener("resize", () => {
adjustGameContainer(gameContainer, width());
});
self.dispatchEvent(new Event("resize"));
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", stopResizing);
});
return (
<div class={style.devTools} style={{ width: `${width()}px` }}>
<div class={style.toolBar}>
<RangeSlider
name="scale"
min={1}
max={8}
step={1}
value={viewport.initialScale}
onInput={setScale}
/>
</div>
<div class={style.toolBarResize} onMouseDown={startResizing}></div>
</div>
);
};
export function use(container: HTMLElement): void {
render(() => <DevTools gameContainer={container} />, document.body);
}