feat: add benchmark settings panel
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 1m59s
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 1m59s
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
export type { NodeInput } from "./inputs";
|
||||
export type { NodeRegistry, RuntimeExecutor, RuntimeCache } from "./components";
|
||||
export type { Node, NodeDefinition, Socket, NodeId, Edge, Graph } from "./types";
|
||||
export { NodeSchema, GraphSchema } from "./types";
|
||||
export { NodeDefinitionSchema } from "./types";
|
||||
|
||||
|
@ -3,10 +3,18 @@ import { NodeInputSchema } from "./inputs";
|
||||
|
||||
export type NodeId = `${string}/${string}/${string}`;
|
||||
|
||||
export const NodeSchema = z.object({
|
||||
id: z.number(),
|
||||
type: z.string(),
|
||||
props: z.record(z.union([z.number(), z.array(z.number())])).optional(),
|
||||
meta: z.object({
|
||||
title: z.string().optional(),
|
||||
lastModified: z.string().optional(),
|
||||
}).optional(),
|
||||
position: z.tuple([z.number(), z.number()])
|
||||
});
|
||||
|
||||
export type Node = {
|
||||
id: number;
|
||||
type: NodeId;
|
||||
props?: Record<string, number | number[]>,
|
||||
tmp?: {
|
||||
depth?: number;
|
||||
mesh?: any;
|
||||
@ -22,13 +30,8 @@ export type Node = {
|
||||
ref?: HTMLElement;
|
||||
visible?: boolean;
|
||||
isMoving?: boolean;
|
||||
},
|
||||
meta?: {
|
||||
title?: string;
|
||||
lastModified?: string;
|
||||
},
|
||||
position: [x: number, y: number]
|
||||
}
|
||||
}
|
||||
} & z.infer<typeof NodeSchema>;
|
||||
|
||||
export const NodeDefinitionSchema = z.object({
|
||||
id: z.string(),
|
||||
@ -50,16 +53,17 @@ export type Socket = {
|
||||
position: [number, number];
|
||||
};
|
||||
|
||||
|
||||
export type Edge = [Node, number, Node, string];
|
||||
|
||||
export type Graph = {
|
||||
id: number;
|
||||
meta?: {
|
||||
title?: string;
|
||||
lastModified?: string;
|
||||
},
|
||||
settings?: Record<string, any>,
|
||||
nodes: Node[];
|
||||
edges: [number, number, number, string][];
|
||||
}
|
||||
export const GraphSchema = z.object({
|
||||
id: z.number().optional(),
|
||||
meta: z.object({
|
||||
title: z.string().optional(),
|
||||
lastModified: z.string().optional(),
|
||||
}).optional(),
|
||||
settings: z.record(z.any()).optional(),
|
||||
nodes: z.array(NodeSchema),
|
||||
edges: z.array(z.tuple([z.number(), z.number(), z.number(), z.string()])),
|
||||
});
|
||||
|
||||
export type Graph = z.infer<typeof GraphSchema> & { nodes: Node[] };
|
||||
|
@ -1,25 +1,25 @@
|
||||
<script lang="ts">
|
||||
import Checkbox from "./elements/Checkbox.svelte";
|
||||
import Float from "./elements/Float.svelte";
|
||||
import Integer from "./elements/Integer.svelte";
|
||||
import Select from "./elements/Select.svelte";
|
||||
import Checkbox from './elements/Checkbox.svelte';
|
||||
import Float from './elements/Float.svelte';
|
||||
import Integer from './elements/Integer.svelte';
|
||||
import Select from './elements/Select.svelte';
|
||||
|
||||
import type { NodeInput } from "@nodes/types";
|
||||
import Vec3 from "./elements/Vec3.svelte";
|
||||
import type { NodeInput } from '@nodes/types';
|
||||
import Vec3 from './elements/Vec3.svelte';
|
||||
|
||||
export let input: NodeInput;
|
||||
export let value: any;
|
||||
export let id: string;
|
||||
export let input: NodeInput;
|
||||
export let value: any;
|
||||
export let id: string;
|
||||
</script>
|
||||
|
||||
{#if input.type === "float"}
|
||||
<Float {id} bind:value min={input?.min} max={input?.max} />
|
||||
{:else if input.type === "integer"}
|
||||
<Integer {id} bind:value min={input?.min} max={input?.max} />
|
||||
{:else if input.type === "boolean"}
|
||||
<Checkbox {id} bind:value />
|
||||
{:else if input.type === "select"}
|
||||
<Select {id} bind:value options={input.options} />
|
||||
{:else if input.type === "vec3"}
|
||||
<Vec3 {id} bind:value />
|
||||
{#if input.type === 'float'}
|
||||
<Float {id} bind:value min={input?.min} max={input?.max} />
|
||||
{:else if input.type === 'integer'}
|
||||
<Integer {id} bind:value min={input?.min} max={input?.max} />
|
||||
{:else if input.type === 'boolean'}
|
||||
<Checkbox {id} bind:value />
|
||||
{:else if input.type === 'select'}
|
||||
<Select {id} bind:value options={input?.options || []} />
|
||||
{:else if input.type === 'vec3'}
|
||||
<Vec3 {id} bind:value />
|
||||
{/if}
|
||||
|
@ -1,96 +1,96 @@
|
||||
<script lang="ts">
|
||||
export let value: boolean;
|
||||
export let value: boolean;
|
||||
|
||||
$: if (typeof value === "string") {
|
||||
value = value === "true";
|
||||
} else if (typeof value === "number") {
|
||||
value = value === 1;
|
||||
}
|
||||
$: if (typeof value === 'string') {
|
||||
value = value === 'true';
|
||||
} else if (typeof value === 'number') {
|
||||
value = value === 1;
|
||||
}
|
||||
|
||||
export let id = "";
|
||||
export let id = '';
|
||||
</script>
|
||||
|
||||
<input {id} type="checkbox" bind:checked={value} />
|
||||
<label for={id}>
|
||||
<svg viewBox="0 0 19 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M2 7L7 12L17 2"
|
||||
stroke="currentColor"
|
||||
stroke-width="3"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
<svg viewBox="0 0 19 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M2 7L7 12L17 2"
|
||||
stroke="currentColor"
|
||||
stroke-width="3"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</label>
|
||||
|
||||
<style>
|
||||
input[type="checkbox"] {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
#inputPreview {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
}
|
||||
input + label {
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
input + label::before {
|
||||
content: " ";
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
margin-right: 3px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
background-color: var(--layer-2);
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
input:checked + label::after {
|
||||
content: " ";
|
||||
background-repeat: no-repeat;
|
||||
background-size: 12px 12px;
|
||||
background-position: center center;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-left: 0px;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
text-align: center;
|
||||
background-color: transparent;
|
||||
color: red;
|
||||
font-size: 10px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
}
|
||||
input[type='checkbox'] {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
#inputPreview {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
justify-content: center;
|
||||
}
|
||||
input + label {
|
||||
position: relative;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
input + label::before {
|
||||
content: ' ';
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
margin-right: 3px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
background-color: var(--layer-2);
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
input:checked + label::after {
|
||||
content: ' ';
|
||||
background-repeat: no-repeat;
|
||||
background-size: 12px 12px;
|
||||
background-position: center center;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-left: 0px;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
text-align: center;
|
||||
background-color: transparent;
|
||||
color: red;
|
||||
font-size: 10px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
}
|
||||
|
||||
input + label > svg {
|
||||
position: absolute;
|
||||
display: none;
|
||||
width: 12px;
|
||||
height: 10px;
|
||||
left: 5px;
|
||||
color: var(--text-color);
|
||||
top: 5.9px;
|
||||
}
|
||||
input + label > svg {
|
||||
position: absolute;
|
||||
display: none;
|
||||
width: 12px;
|
||||
height: 10px;
|
||||
left: 5px;
|
||||
color: var(--text-color);
|
||||
top: 5.9px;
|
||||
}
|
||||
|
||||
input:checked + label > svg {
|
||||
display: block;
|
||||
}
|
||||
input:checked + label > svg {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,11 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let value = 0.5;
|
||||
export let step = 0.01;
|
||||
export let min = 0;
|
||||
export let max = 1;
|
||||
export let id = '';
|
||||
let {
|
||||
onchange,
|
||||
value = $bindable(),
|
||||
id,
|
||||
step = 0.01,
|
||||
min = 0,
|
||||
max = 1
|
||||
}: {
|
||||
onchange?: (num: number) => void;
|
||||
value?: number;
|
||||
id?: string;
|
||||
step?: number;
|
||||
min?: number;
|
||||
max?: number;
|
||||
} = $props();
|
||||
|
||||
if (min > max) {
|
||||
[min, max] = [max, min];
|
||||
@ -18,31 +26,32 @@
|
||||
return +parseFloat(input + '').toPrecision(2);
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let inputEl: HTMLInputElement;
|
||||
|
||||
$: if ((value || 0).toString().length > 5) {
|
||||
value = strip(value || 0);
|
||||
}
|
||||
$: value !== undefined && handleChange();
|
||||
$effect(() => {
|
||||
if ((value || 0).toString().length > 5) {
|
||||
value = strip(value || 0);
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (value !== undefined) handleChange();
|
||||
});
|
||||
|
||||
let oldValue: number;
|
||||
function handleChange() {
|
||||
if (value === oldValue) return;
|
||||
oldValue = value;
|
||||
dispatch('change', parseFloat(value + ''));
|
||||
onchange?.(value);
|
||||
}
|
||||
|
||||
$: width = Number.isFinite(value)
|
||||
? Math.max((value?.toString().length ?? 1) * 8, 50) + 'px'
|
||||
: '20px';
|
||||
let width = $derived(
|
||||
Number.isFinite(value) ? Math.max((value?.toString().length ?? 1) * 8, 50) + 'px' : '20px'
|
||||
);
|
||||
|
||||
let isMouseDown = false;
|
||||
/* let downX = 0; */
|
||||
/* let downY = 0; */
|
||||
let isMouseDown = $state(false);
|
||||
let downV = 0;
|
||||
let vx = 0;
|
||||
/* let vy = 0; */
|
||||
let rect: DOMRect;
|
||||
|
||||
function handleMouseDown(ev: MouseEvent) {
|
||||
@ -53,8 +62,6 @@
|
||||
isMouseDown = true;
|
||||
|
||||
downV = value;
|
||||
/* downX = ev.clientX; */
|
||||
/* downY = ev.clientY; */
|
||||
rect = inputEl.getBoundingClientRect();
|
||||
|
||||
window.removeEventListener('mousemove', handleMouseMove);
|
||||
@ -78,16 +85,6 @@
|
||||
min = value;
|
||||
}
|
||||
|
||||
// setTimeout(() => {
|
||||
// if (value >= 0) {
|
||||
// max = getBoundingValue(value);
|
||||
// min = 0;
|
||||
// } else {
|
||||
// min = getBoundingValue(value);
|
||||
// max = 0;
|
||||
// }
|
||||
// }, 500);
|
||||
|
||||
document.body.style.cursor = 'unset';
|
||||
window.removeEventListener('mouseup', handleMouseUp);
|
||||
window.removeEventListener('mousemove', handleMouseMove);
|
||||
@ -122,9 +119,9 @@
|
||||
{step}
|
||||
{max}
|
||||
{min}
|
||||
on:keydown={handleKeyDown}
|
||||
on:mousedown={handleMouseDown}
|
||||
on:mouseup={handleMouseUp}
|
||||
onkeydown={handleKeyDown}
|
||||
onmousedown={handleMouseDown}
|
||||
onmouseup={handleMouseUp}
|
||||
type="number"
|
||||
style={`width:${width};`}
|
||||
/>
|
||||
|
@ -1,169 +1,172 @@
|
||||
<svelte:options accessors />
|
||||
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
const dispatch = createEventDispatcher();
|
||||
let {
|
||||
min = 0,
|
||||
max = 10,
|
||||
step = 1,
|
||||
value = $bindable(),
|
||||
id,
|
||||
onchange
|
||||
}: {
|
||||
min?: number;
|
||||
max?: number;
|
||||
step?: number;
|
||||
value?: number;
|
||||
id?: string;
|
||||
onchange?: (num: number) => void;
|
||||
} = $props();
|
||||
|
||||
// Styling
|
||||
export let min: number | undefined = undefined;
|
||||
export let max: number | undefined = undefined;
|
||||
export let step = 1;
|
||||
export let value = 0;
|
||||
export let id = "";
|
||||
if (!value) {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
if (!value) {
|
||||
value = 0;
|
||||
}
|
||||
let inputEl: HTMLInputElement;
|
||||
let wrapper: HTMLDivElement;
|
||||
$effect(() => {
|
||||
if (value !== undefined) {
|
||||
update();
|
||||
}
|
||||
});
|
||||
|
||||
let inputEl: HTMLInputElement;
|
||||
let wrapper: HTMLDivElement;
|
||||
$: value !== undefined && update();
|
||||
let prev = -1;
|
||||
function update() {
|
||||
if (prev === value) return;
|
||||
prev = value;
|
||||
onchange?.(value);
|
||||
}
|
||||
|
||||
let prev = -1;
|
||||
function update() {
|
||||
if (prev === value) return;
|
||||
prev = value;
|
||||
dispatch("change", parseFloat(value + ""));
|
||||
}
|
||||
let width = $derived(
|
||||
Number.isFinite(value) ? Math.max((value?.toString().length ?? 1) * 8, 30) + 'px' : '20px'
|
||||
);
|
||||
|
||||
$: width = Number.isFinite(value)
|
||||
? Math.max((value?.toString().length ?? 1) * 8, 30) + "px"
|
||||
: "20px";
|
||||
function handleChange(change: number) {
|
||||
value = Math.max(min ?? -Infinity, Math.min(+value + change, max ?? Infinity));
|
||||
}
|
||||
|
||||
function handleChange(change: number) {
|
||||
value = Math.max(
|
||||
min ?? -Infinity,
|
||||
Math.min(+value + change, max ?? Infinity),
|
||||
);
|
||||
}
|
||||
let downX = 0;
|
||||
let downV = 0;
|
||||
let rect: DOMRect;
|
||||
|
||||
let downX = 0;
|
||||
let downV = 0;
|
||||
let rect: DOMRect;
|
||||
function handleMouseDown(ev: MouseEvent) {
|
||||
ev.preventDefault();
|
||||
|
||||
function handleMouseDown(ev: MouseEvent) {
|
||||
ev.preventDefault();
|
||||
downV = value;
|
||||
downX = ev.clientX;
|
||||
rect = wrapper.getBoundingClientRect();
|
||||
|
||||
downV = value;
|
||||
downX = ev.clientX;
|
||||
rect = wrapper.getBoundingClientRect();
|
||||
window.removeEventListener('mousemove', handleMouseMove);
|
||||
window.addEventListener('mousemove', handleMouseMove);
|
||||
window.addEventListener('mouseup', handleMouseUp);
|
||||
document.body.style.cursor = 'ew-resize';
|
||||
}
|
||||
|
||||
window.removeEventListener("mousemove", handleMouseMove);
|
||||
window.addEventListener("mousemove", handleMouseMove);
|
||||
window.addEventListener("mouseup", handleMouseUp);
|
||||
document.body.style.cursor = "ew-resize";
|
||||
}
|
||||
function handleMouseUp() {
|
||||
if (downV === value) {
|
||||
inputEl.focus();
|
||||
} else {
|
||||
inputEl.blur();
|
||||
}
|
||||
|
||||
function handleMouseUp() {
|
||||
if (downV === value) {
|
||||
inputEl.focus();
|
||||
} else {
|
||||
inputEl.blur();
|
||||
}
|
||||
document.body.style.cursor = 'unset';
|
||||
window.removeEventListener('mouseup', handleMouseUp);
|
||||
window.removeEventListener('mousemove', handleMouseMove);
|
||||
}
|
||||
|
||||
document.body.style.cursor = "unset";
|
||||
window.removeEventListener("mouseup", handleMouseUp);
|
||||
window.removeEventListener("mousemove", handleMouseMove);
|
||||
}
|
||||
|
||||
function handleMouseMove(ev: MouseEvent) {
|
||||
if (!ev.ctrlKey && typeof min === "number" && typeof max === "number") {
|
||||
const vx = (ev.clientX - rect.left) / rect.width;
|
||||
value = Math.max(Math.min(Math.round(min + (max - min) * vx), max), min);
|
||||
} else {
|
||||
const vx = ev.clientX - downX;
|
||||
value = downV + Math.round(vx / 10);
|
||||
}
|
||||
}
|
||||
function handleMouseMove(ev: MouseEvent) {
|
||||
if (!ev.ctrlKey && typeof min === 'number' && typeof max === 'number') {
|
||||
const vx = (ev.clientX - rect.left) / rect.width;
|
||||
value = Math.max(Math.min(Math.round(min + (max - min) * vx), max), min);
|
||||
} else {
|
||||
const vx = ev.clientX - downX;
|
||||
value = downV + Math.round(vx / 10);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="component-wrapper"
|
||||
bind:this={wrapper}
|
||||
role="slider"
|
||||
tabindex="0"
|
||||
aria-valuenow={value}
|
||||
on:mousedown={handleMouseDown}
|
||||
on:mouseup={handleMouseUp}
|
||||
class="component-wrapper"
|
||||
bind:this={wrapper}
|
||||
role="slider"
|
||||
tabindex="0"
|
||||
aria-valuenow={value}
|
||||
onmousedown={handleMouseDown}
|
||||
onmouseup={handleMouseUp}
|
||||
>
|
||||
{#if typeof min !== "undefined" && typeof max !== "undefined"}
|
||||
<span
|
||||
class="overlay"
|
||||
style={`width: ${Math.min((value - min) / (max - min), 1) * 100}%`}
|
||||
/>
|
||||
{/if}
|
||||
<button on:click={() => handleChange(-step)}>-</button>
|
||||
<input
|
||||
bind:value
|
||||
bind:this={inputEl}
|
||||
{id}
|
||||
{step}
|
||||
{max}
|
||||
{min}
|
||||
type="number"
|
||||
style={`width:${width};`}
|
||||
/>
|
||||
{#if typeof min !== 'undefined' && typeof max !== 'undefined'}
|
||||
<span class="overlay" style={`width: ${Math.min((value - min) / (max - min), 1) * 100}%`}
|
||||
></span>
|
||||
{/if}
|
||||
<button onclick={() => handleChange(-step)}>-</button>
|
||||
<input
|
||||
bind:value
|
||||
bind:this={inputEl}
|
||||
{id}
|
||||
{step}
|
||||
{max}
|
||||
{min}
|
||||
type="number"
|
||||
style={`width:${width};`}
|
||||
/>
|
||||
|
||||
<button on:click={() => handleChange(+step)}>+</button>
|
||||
<button onclick={() => handleChange(+step)}>+</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.component-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
background-color: var(--layer-2, #4b4b4b);
|
||||
border-radius: 2px;
|
||||
user-select: none;
|
||||
transition: box-shadow 0.3s ease;
|
||||
outline: solid 1px var(--outline);
|
||||
overflow: hidden;
|
||||
border-radius: var(--border-radius, 2px);
|
||||
}
|
||||
.component-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
background-color: var(--layer-2, #4b4b4b);
|
||||
border-radius: 2px;
|
||||
user-select: none;
|
||||
transition: box-shadow 0.3s ease;
|
||||
outline: solid 1px var(--outline);
|
||||
overflow: hidden;
|
||||
border-radius: var(--border-radius, 2px);
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
-webkit-appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
font-family: var(--font-family);
|
||||
padding-top: 8px;
|
||||
flex: 1;
|
||||
width: 72%;
|
||||
}
|
||||
input[type='number'] {
|
||||
-webkit-appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
font-family: var(--font-family);
|
||||
padding-top: 8px;
|
||||
flex: 1;
|
||||
width: 72%;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
input[type='number']::-webkit-inner-spin-button,
|
||||
input[type='number']::-webkit-outer-spin-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
height: 100%;
|
||||
background-color: var(--layer-3);
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
height: 100%;
|
||||
background-color: var(--layer-3);
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
line-height: 0px;
|
||||
margin: 0;
|
||||
color: var(--text-color);
|
||||
margin-inline: 6px;
|
||||
}
|
||||
button {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
line-height: 0px;
|
||||
margin: 0;
|
||||
color: var(--text-color);
|
||||
margin-inline: 6px;
|
||||
}
|
||||
|
||||
div input[type="number"] {
|
||||
color: var(--text-color);
|
||||
background-color: transparent;
|
||||
padding: var(--padding, 6px);
|
||||
padding-inline: 0px;
|
||||
text-align: center;
|
||||
border: none;
|
||||
border-style: none;
|
||||
}
|
||||
div input[type='number'] {
|
||||
color: var(--text-color);
|
||||
background-color: transparent;
|
||||
padding: var(--padding, 6px);
|
||||
padding-inline: 0px;
|
||||
text-align: center;
|
||||
border: none;
|
||||
border-style: none;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,23 +1,25 @@
|
||||
<script lang="ts">
|
||||
export let options: string[] = [];
|
||||
export let value: number = 0;
|
||||
export let id = "";
|
||||
let {
|
||||
id,
|
||||
value = $bindable(),
|
||||
options
|
||||
}: { id: string; value: number; options: string[] } = $props();
|
||||
</script>
|
||||
|
||||
<select {id} bind:value>
|
||||
{#each options as label, i}
|
||||
<option value={i}>{label}</option>
|
||||
{/each}
|
||||
{#each options as label, i}
|
||||
<option value={i}>{label}</option>
|
||||
{/each}
|
||||
</select>
|
||||
|
||||
<style>
|
||||
select {
|
||||
background: var(--layer-2);
|
||||
color: var(--text-color);
|
||||
font-family: var(--font-family);
|
||||
outline: solid 1px var(--outline);
|
||||
padding: 0.8em 1em;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
}
|
||||
select {
|
||||
background: var(--layer-2);
|
||||
color: var(--text-color);
|
||||
font-family: var(--font-family);
|
||||
outline: solid 1px var(--outline);
|
||||
padding: 0.8em 1em;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,31 +1,29 @@
|
||||
<script lang="ts">
|
||||
import Float from "./Float.svelte";
|
||||
import Float from './Float.svelte';
|
||||
|
||||
export let value = [0, 0, 0];
|
||||
export let id = "";
|
||||
let { value = $bindable(), id }: { value: number[]; id: string } = $props();
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Float id={`${id}-x`} bind:value={value[0]} />
|
||||
<Float id={`${id}-y`} bind:value={value[1]} />
|
||||
<Float id={`${id}-z`} bind:value={value[2]} />
|
||||
<Float id={`${id}-x`} bind:value={value[0]} />
|
||||
<Float id={`${id}-y`} bind:value={value[1]} />
|
||||
<Float id={`${id}-z`} bind:value={value[2]} />
|
||||
</div>
|
||||
|
||||
<style>
|
||||
div > :global(.component-wrapper:nth-child(1)) {
|
||||
border-radius: 4px 4px 0px 0px !important;
|
||||
border-bottom: none !important;
|
||||
}
|
||||
div > :global(.component-wrapper:nth-child(2)) {
|
||||
border-radius: 0px !important;
|
||||
outline: none;
|
||||
border: solid thin var(--outline);
|
||||
border-top: solid thin color-mix(in srgb, var(--outline) 50%, transparent);
|
||||
border-bottom: solid thin
|
||||
color-mix(in srgb, var(--outline) 50%, transparent);
|
||||
}
|
||||
div > :global(.component-wrapper:nth-child(3)) {
|
||||
border-top: none !important;
|
||||
border-radius: 0px 0px 4px 4px !important;
|
||||
}
|
||||
div > :global(.component-wrapper:nth-child(1)) {
|
||||
border-radius: 4px 4px 0px 0px !important;
|
||||
border-bottom: none !important;
|
||||
}
|
||||
div > :global(.component-wrapper:nth-child(2)) {
|
||||
border-radius: 0px !important;
|
||||
outline: none;
|
||||
border: solid thin var(--outline);
|
||||
border-top: solid thin color-mix(in srgb, var(--outline) 50%, transparent);
|
||||
border-bottom: solid thin color-mix(in srgb, var(--outline) 50%, transparent);
|
||||
}
|
||||
div > :global(.component-wrapper:nth-child(3)) {
|
||||
border-top: none !important;
|
||||
border-radius: 0px 0px 4px 4px !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,7 +1,34 @@
|
||||
<script lang="ts">
|
||||
import "$lib/app.css";
|
||||
import Slider from "$lib/elements/Float.svelte";
|
||||
import '$lib/app.css';
|
||||
import Float from '$lib/elements/Float.svelte';
|
||||
import Integer from '$lib/elements/Integer.svelte';
|
||||
import Vec3 from '$lib/elements/Vec3.svelte';
|
||||
|
||||
let intValue = $state(0);
|
||||
let floatValue = $state(0.2);
|
||||
let vecValue = $state([0.2, 0.3, 0.4]);
|
||||
</script>
|
||||
|
||||
<Slider id="asd" />
|
||||
<main>
|
||||
<section>
|
||||
<h3>Integer {intValue}</h3>
|
||||
<Integer bind:value={intValue} />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>Float {floatValue}</h3>
|
||||
<Float bind:value={floatValue} />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h3>Vec3 {JSON.stringify(vecValue)}</h3>
|
||||
<Vec3 bind:value={vecValue} />
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
@ -102,3 +102,47 @@ function decode_recursive(dense: number[] | Int32Array, index = 0) {
|
||||
export function decodeNestedArray(dense: number[] | Int32Array) {
|
||||
return decode_recursive(dense, 0)[0];
|
||||
}
|
||||
|
||||
|
||||
export function splitNestedArray(input: Int32Array) {
|
||||
let index = 0;
|
||||
const length = input.length;
|
||||
let res: Int32Array[] = [];
|
||||
|
||||
let nextBracketIndex = 0;
|
||||
let argStartIndex = 0;
|
||||
let depth = -1;
|
||||
|
||||
while (index < length) {
|
||||
const value = input[index];
|
||||
|
||||
if (index === nextBracketIndex) {
|
||||
nextBracketIndex = index + input[index + 1] + 1;
|
||||
if (value === 0) {
|
||||
depth++;
|
||||
} else {
|
||||
depth--;
|
||||
}
|
||||
|
||||
if (depth === 1 && value === 0) {
|
||||
// if opening bracket
|
||||
argStartIndex = index + 2;
|
||||
}
|
||||
|
||||
if (depth === 0 && value === 1) {
|
||||
// if closing bracket
|
||||
res.push(input.slice(argStartIndex, index));
|
||||
argStartIndex = index + 2;
|
||||
}
|
||||
|
||||
index = nextBracketIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
// we should not be here
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -11,12 +11,52 @@ pub struct PathDataMut<'a> {
|
||||
pub points: &'a mut [f32],
|
||||
}
|
||||
|
||||
impl PathDataMut<'_> {
|
||||
pub fn get_length(&self) -> f32 {
|
||||
let mut l = 0.0;
|
||||
for i in 0..(self.length - 1) {
|
||||
let a = vec3(
|
||||
self.points[i * 4],
|
||||
self.points[i * 4 + 1],
|
||||
self.points[i * 4 + 2],
|
||||
);
|
||||
let b = vec3(
|
||||
self.points[(i + 1) * 4],
|
||||
self.points[(i + 1) * 4 + 1],
|
||||
self.points[(i + 1) * 4 + 2],
|
||||
);
|
||||
l += (b - a).length();
|
||||
}
|
||||
l
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PathData<'a> {
|
||||
pub depth: i32,
|
||||
pub length: usize,
|
||||
pub points: &'a [f32],
|
||||
}
|
||||
|
||||
impl PathData<'_> {
|
||||
pub fn get_length(&self) -> f32 {
|
||||
let mut l = 0.0;
|
||||
for i in 0..(self.length - 1) {
|
||||
let a = vec3(
|
||||
self.points[i * 4],
|
||||
self.points[i * 4 + 1],
|
||||
self.points[i * 4 + 2],
|
||||
);
|
||||
let b = vec3(
|
||||
self.points[(i + 1) * 4],
|
||||
self.points[(i + 1) * 4 + 1],
|
||||
self.points[(i + 1) * 4 + 2],
|
||||
);
|
||||
l += (b - a).length();
|
||||
}
|
||||
l
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_multiple_paths(amount: usize, point_amount: usize, depth: i32) -> Vec<i32> {
|
||||
let output_size = amount * (point_amount * 4 + PATH_HEADER_SIZE + 4) + 4;
|
||||
|
||||
|
@ -162,7 +162,12 @@ pub fn evaluate_vec3(input_args: &[i32]) -> Vec<f32> {
|
||||
}
|
||||
|
||||
pub fn evaluate_float(arg: &[i32]) -> f32 {
|
||||
decode_float(evaluate_int(arg))
|
||||
let res = decode_float(evaluate_int(arg));
|
||||
if res.is_nan() {
|
||||
0.0
|
||||
} else {
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
pub fn evaluate_int(input_args: &[i32]) -> i32 {
|
||||
|
Reference in New Issue
Block a user