chore: setup linting
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
<script lang="ts">
|
||||
import type { NodeInstance, NodeInput } from "@nodarium/types";
|
||||
import NestedSettings from "$lib/settings/NestedSettings.svelte";
|
||||
import type { GraphManager } from "$lib/graph-interface/graph-manager.svelte";
|
||||
import type { GraphManager } from '$lib/graph-interface/graph-manager.svelte';
|
||||
import NestedSettings from '$lib/settings/NestedSettings.svelte';
|
||||
import type { NodeId, NodeInput, NodeInstance } from '@nodarium/types';
|
||||
|
||||
type InternalNodeInput = NodeInput & {
|
||||
__node_type?: NodeId;
|
||||
__node_input: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
manager: GraphManager;
|
||||
@@ -11,40 +16,44 @@
|
||||
const { manager, node = $bindable() }: Props = $props();
|
||||
|
||||
function filterInputs(inputs?: Record<string, NodeInput>) {
|
||||
const _inputs = $state.snapshot(inputs);
|
||||
const _inputs = $state.snapshot(
|
||||
inputs as Record<string, InternalNodeInput>
|
||||
);
|
||||
return Object.fromEntries(
|
||||
Object.entries(structuredClone(_inputs ?? {}))
|
||||
.filter(([_key, value]) => {
|
||||
.filter(([, value]) => {
|
||||
return value.hidden === true;
|
||||
})
|
||||
.map(([key, value]) => {
|
||||
//@ts-ignore
|
||||
value.__node_type = node.state?.type.id;
|
||||
//@ts-ignore
|
||||
value.__node_type = node.state.type?.id;
|
||||
value.__node_input = key;
|
||||
return [key, value];
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
const nodeDefinition = filterInputs(node.state?.type?.inputs);
|
||||
const nodeDefinition = filterInputs(node.state.type?.inputs);
|
||||
|
||||
type Store = Record<string, number | number[]>;
|
||||
let store = $state<Store>(createStore(node?.props, nodeDefinition));
|
||||
function createStore(
|
||||
props: NodeInstance["props"],
|
||||
inputs: Record<string, NodeInput>,
|
||||
props: NodeInstance['props'],
|
||||
inputs: Record<string, NodeInput>
|
||||
): Store {
|
||||
const store: Store = {};
|
||||
Object.keys(inputs).forEach((key) => {
|
||||
if (props) {
|
||||
//@ts-ignore
|
||||
store[key] = props[key] || inputs[key].value;
|
||||
const value = props[key] || inputs[key].value;
|
||||
if (Array.isArray(value) || typeof value === 'number') {
|
||||
store[key] = value;
|
||||
} else {
|
||||
console.error('Wrong error');
|
||||
}
|
||||
}
|
||||
});
|
||||
return store;
|
||||
}
|
||||
|
||||
let lastPropsHash = "";
|
||||
let lastPropsHash = '';
|
||||
function updateNode() {
|
||||
if (!node || !store) return;
|
||||
let needsUpdate = false;
|
||||
@@ -53,7 +62,10 @@
|
||||
const key = _key as keyof typeof store;
|
||||
if (node && store) {
|
||||
needsUpdate = true;
|
||||
node.props[key] = store[key];
|
||||
const value = store[key];
|
||||
if (value !== undefined) {
|
||||
node.props[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { NodeInstance } from "@nodarium/types";
|
||||
import type { GraphManager } from "$lib/graph-interface/graph-manager.svelte";
|
||||
import ActiveNodeSelected from "./ActiveNodeSelected.svelte";
|
||||
import type { GraphManager } from '$lib/graph-interface/graph-manager.svelte';
|
||||
import type { NodeInstance } from '@nodarium/types';
|
||||
import ActiveNodeSelected from './ActiveNodeSelected.svelte';
|
||||
|
||||
type Props = {
|
||||
manager: GraphManager;
|
||||
|
||||
@@ -1,148 +1,148 @@
|
||||
<script lang="ts" module>
|
||||
let result:
|
||||
| { stdev: number; avg: number; duration: number; samples: number[] }
|
||||
| undefined = $state();
|
||||
let result:
|
||||
| { stdev: number; avg: number; duration: number; samples: number[] }
|
||||
| undefined = $state();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { humanizeDuration } from '$lib/helpers';
|
||||
import { localState } from '$lib/helpers/localState.svelte';
|
||||
import Monitor from '$lib/performance/Monitor.svelte';
|
||||
import { Number } from '@nodarium/ui';
|
||||
import { writable } from 'svelte/store';
|
||||
import { humanizeDuration } from '$lib/helpers';
|
||||
import { localState } from '$lib/helpers/localState.svelte';
|
||||
import Monitor from '$lib/performance/Monitor.svelte';
|
||||
import { Float } from '@nodarium/ui';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
function calculateStandardDeviation(array: number[]) {
|
||||
const n = array.length;
|
||||
const mean = array.reduce((a, b) => a + b) / n;
|
||||
return Math.sqrt(
|
||||
array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n
|
||||
);
|
||||
}
|
||||
type Props = {
|
||||
run: () => Promise<any>;
|
||||
};
|
||||
function calculateStandardDeviation(array: number[]) {
|
||||
const n = array.length;
|
||||
const mean = array.reduce((a, b) => a + b) / n;
|
||||
return Math.sqrt(
|
||||
array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n
|
||||
);
|
||||
}
|
||||
type Props = {
|
||||
run: () => Promise<unknown>;
|
||||
};
|
||||
|
||||
const { run }: Props = $props();
|
||||
const { run }: Props = $props();
|
||||
|
||||
let isRunning = $state(false);
|
||||
let amount = localState<number>('nodes.benchmark.samples', 500);
|
||||
let samples = $state(0);
|
||||
let warmUp = writable(0);
|
||||
let warmUpAmount = 10;
|
||||
let status = '';
|
||||
let isRunning = $state(false);
|
||||
let amount = localState<number>('nodes.benchmark.samples', 500);
|
||||
let samples = $state(0);
|
||||
let warmUp = writable(0);
|
||||
let warmUpAmount = 10;
|
||||
let status = '';
|
||||
|
||||
const copyContent = async (text?: string | number) => {
|
||||
if (!text) return;
|
||||
if (typeof text !== 'string') {
|
||||
text = (Math.floor(text * 100) / 100).toString();
|
||||
}
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy: ', err);
|
||||
}
|
||||
};
|
||||
const copyContent = async (text?: string | number) => {
|
||||
if (!text) return;
|
||||
if (typeof text !== 'string') {
|
||||
text = (Math.floor(text * 100) / 100).toString();
|
||||
}
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy: ', err);
|
||||
}
|
||||
};
|
||||
|
||||
async function benchmark() {
|
||||
if (isRunning) return;
|
||||
isRunning = true;
|
||||
result = undefined;
|
||||
samples = 0;
|
||||
$warmUp = 0;
|
||||
async function benchmark() {
|
||||
if (isRunning) return;
|
||||
isRunning = true;
|
||||
result = undefined;
|
||||
samples = 0;
|
||||
$warmUp = 0;
|
||||
|
||||
await new Promise((r) => setTimeout(r, 50));
|
||||
await new Promise((r) => setTimeout(r, 50));
|
||||
|
||||
// warm up
|
||||
for (let i = 0; i < warmUpAmount; i++) {
|
||||
await run();
|
||||
$warmUp = i + 1;
|
||||
}
|
||||
// warm up
|
||||
for (let i = 0; i < warmUpAmount; i++) {
|
||||
await run();
|
||||
$warmUp = i + 1;
|
||||
}
|
||||
|
||||
let a = performance.now();
|
||||
let results = [];
|
||||
let a = performance.now();
|
||||
let results = [];
|
||||
|
||||
// perform run
|
||||
for (let i = 0; i < amount.value; i++) {
|
||||
const a = performance.now();
|
||||
await run();
|
||||
samples = i;
|
||||
const b = performance.now();
|
||||
await new Promise((r) => setTimeout(r, 20));
|
||||
results.push(b - a);
|
||||
}
|
||||
result = {
|
||||
stdev: calculateStandardDeviation(results),
|
||||
samples: results,
|
||||
duration: performance.now() - a,
|
||||
avg: results.reduce((a, b) => a + b) / results.length
|
||||
};
|
||||
}
|
||||
// perform run
|
||||
for (let i = 0; i < amount.value; i++) {
|
||||
const a = performance.now();
|
||||
await run();
|
||||
samples = i;
|
||||
const b = performance.now();
|
||||
await new Promise((r) => setTimeout(r, 20));
|
||||
results.push(b - a);
|
||||
}
|
||||
result = {
|
||||
stdev: calculateStandardDeviation(results),
|
||||
samples: results,
|
||||
duration: performance.now() - a,
|
||||
avg: results.reduce((a, b) => a + b) / results.length
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
{status}
|
||||
|
||||
<div class="wrapper" class:running={isRunning}>
|
||||
{#if result}
|
||||
<h3>Finished ({humanizeDuration(result.duration)})</h3>
|
||||
<div class="monitor-wrapper">
|
||||
<Monitor points={result.samples} />
|
||||
</div>
|
||||
<label for="bench-avg">Average </label>
|
||||
<button
|
||||
id="bench-avg"
|
||||
onkeydown={(ev) => ev.key === 'Enter' && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.avg)}
|
||||
>
|
||||
{Math.floor(result.avg * 100) / 100}
|
||||
</button>
|
||||
<i
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onkeydown={(ev) => ev.key === 'Enter' && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.avg)}
|
||||
>(click to copy)</i>
|
||||
<label for="bench-stdev">Standard Deviation σ</label>
|
||||
<button id="bench-stdev" onclick={() => copyContent(result?.stdev)}>
|
||||
{Math.floor(result.stdev * 100) / 100}
|
||||
</button>
|
||||
<i
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onkeydown={(ev) => ev.key === 'Enter' && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.stdev + '')}
|
||||
>(click to copy)</i>
|
||||
<div>
|
||||
<button onclick={() => (isRunning = false)}>reset</button>
|
||||
</div>
|
||||
{:else if isRunning}
|
||||
<p>WarmUp ({$warmUp}/{warmUpAmount})</p>
|
||||
<progress value={$warmUp} max={warmUpAmount}>
|
||||
{Math.floor(($warmUp / warmUpAmount) * 100)}%
|
||||
</progress>
|
||||
<p>Progress ({samples}/{amount.value})</p>
|
||||
<progress value={samples} max={amount.value}>
|
||||
{Math.floor((samples / amount.value) * 100)}%
|
||||
</progress>
|
||||
{:else}
|
||||
<label for="bench-samples">Samples</label>
|
||||
<Number id="bench-sample" bind:value={amount.value} max={1000} />
|
||||
<button onclick={benchmark} disabled={isRunning}>start</button>
|
||||
{/if}
|
||||
{#if result}
|
||||
<h3>Finished ({humanizeDuration(result.duration)})</h3>
|
||||
<div class="monitor-wrapper">
|
||||
<Monitor points={result.samples} />
|
||||
</div>
|
||||
<label for="bench-avg">Average </label>
|
||||
<button
|
||||
id="bench-avg"
|
||||
onkeydown={(ev) => ev.key === 'Enter' && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.avg)}
|
||||
>
|
||||
{Math.floor(result.avg * 100) / 100}
|
||||
</button>
|
||||
<i
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onkeydown={(ev) => ev.key === 'Enter' && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.avg)}
|
||||
>(click to copy)</i>
|
||||
<label for="bench-stdev">Standard Deviation σ</label>
|
||||
<button id="bench-stdev" onclick={() => copyContent(result?.stdev)}>
|
||||
{Math.floor(result.stdev * 100) / 100}
|
||||
</button>
|
||||
<i
|
||||
role="button"
|
||||
tabindex="0"
|
||||
onkeydown={(ev) => ev.key === 'Enter' && copyContent(result?.avg)}
|
||||
onclick={() => copyContent(result?.stdev + '')}
|
||||
>(click to copy)</i>
|
||||
<div>
|
||||
<button onclick={() => (isRunning = false)}>reset</button>
|
||||
</div>
|
||||
{:else if isRunning}
|
||||
<p>WarmUp ({$warmUp}/{warmUpAmount})</p>
|
||||
<progress value={$warmUp} max={warmUpAmount}>
|
||||
{Math.floor(($warmUp / warmUpAmount) * 100)}%
|
||||
</progress>
|
||||
<p>Progress ({samples}/{amount.value})</p>
|
||||
<progress value={samples} max={amount.value}>
|
||||
{Math.floor((samples / amount.value) * 100)}%
|
||||
</progress>
|
||||
{:else}
|
||||
<label for="bench-samples">Samples</label>
|
||||
<Float id="bench-sample" bind:value={amount.value} max={1000} />
|
||||
<button onclick={benchmark} disabled={isRunning}>start</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1em;
|
||||
}
|
||||
.monitor-wrapper {
|
||||
border: solid thin var(--outline);
|
||||
border-bottom: none;
|
||||
}
|
||||
i {
|
||||
opacity: 0.5;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.wrapper {
|
||||
padding: 1em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1em;
|
||||
}
|
||||
.monitor-wrapper {
|
||||
border: solid thin var(--outline);
|
||||
border-bottom: none;
|
||||
}
|
||||
i {
|
||||
opacity: 0.5;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
<script lang="ts">
|
||||
import type { Group } from "three";
|
||||
import type { OBJExporter } from "three/addons/exporters/OBJExporter.js";
|
||||
import type { GLTFExporter } from "three/addons/exporters/GLTFExporter.js";
|
||||
import FileSaver from "file-saver";
|
||||
import FileSaver from 'file-saver';
|
||||
import type { Group } from 'three';
|
||||
import type { GLTFExporter } from 'three/addons/exporters/GLTFExporter.js';
|
||||
import type { OBJExporter } from 'three/addons/exporters/OBJExporter.js';
|
||||
|
||||
// Download
|
||||
const download = (
|
||||
data: ArrayBuffer | string,
|
||||
name: string,
|
||||
mimetype: string,
|
||||
extension: string,
|
||||
extension: string
|
||||
) => {
|
||||
const blob = new Blob([data], { type: mimetype + ";charset=utf-8" });
|
||||
FileSaver.saveAs(blob, name + "." + extension);
|
||||
const blob = new Blob([data], { type: mimetype + ';charset=utf-8' });
|
||||
FileSaver.saveAs(blob, name + '.' + extension);
|
||||
};
|
||||
|
||||
const { scene } = $props<{ scene: Group }>();
|
||||
|
||||
let gltfExporter: GLTFExporter;
|
||||
async function exportGltf() {
|
||||
const exporter =
|
||||
gltfExporter ||
|
||||
(await import("three/addons/exporters/GLTFExporter.js").then((m) => {
|
||||
const exporter = gltfExporter
|
||||
|| (await import('three/addons/exporters/GLTFExporter.js').then((m) => {
|
||||
gltfExporter = new m.GLTFExporter();
|
||||
return gltfExporter;
|
||||
}));
|
||||
@@ -30,30 +29,29 @@
|
||||
scene,
|
||||
(gltf) => {
|
||||
// download .gltf file
|
||||
download(gltf as ArrayBuffer, "plant", "text/plain", "gltf");
|
||||
download(gltf as ArrayBuffer, 'plant', 'text/plain', 'gltf');
|
||||
},
|
||||
(err) => {
|
||||
console.log(err);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
let objExporter: OBJExporter;
|
||||
|
||||
async function exportObj() {
|
||||
const exporter =
|
||||
objExporter ||
|
||||
(await import("three/addons/exporters/OBJExporter.js").then((m) => {
|
||||
const exporter = objExporter
|
||||
|| (await import('three/addons/exporters/OBJExporter.js').then((m) => {
|
||||
objExporter = new m.OBJExporter();
|
||||
return objExporter;
|
||||
}));
|
||||
const result = exporter.parse(scene);
|
||||
// download .obj file
|
||||
download(result, "plant", "text/plain", "obj");
|
||||
download(result, 'plant', 'text/plain', 'obj');
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="p-4">
|
||||
<button onclick={exportObj}> export obj </button>
|
||||
<button onclick={exportGltf}> export gltf </button>
|
||||
<button onclick={exportObj}>export obj</button>
|
||||
<button onclick={exportGltf}>export gltf</button>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { Graph } from "$lib/types";
|
||||
import type { Graph } from '$lib/types';
|
||||
|
||||
const { graph }: { graph?: Graph } = $props();
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
return JSON.stringify(
|
||||
{
|
||||
...g,
|
||||
nodes: g.nodes.map((n: any) => ({ ...n, tmp: undefined })),
|
||||
nodes: g.nodes.map((n: object) => ({ ...n, tmp: undefined }))
|
||||
},
|
||||
null,
|
||||
2,
|
||||
2
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<pre>
|
||||
{graph ? convert(graph) : 'No graph loaded'}
|
||||
{graph ? convert(graph) : "No graph loaded"}
|
||||
</pre>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { createKeyMap } from "$lib/helpers/createKeyMap";
|
||||
import { ShortCut } from "@nodarium/ui";
|
||||
import { get } from "svelte/store";
|
||||
import type { createKeyMap, ShortCut } from '$lib/helpers/createKeyMap';
|
||||
import { ShortCut as ShortCutEl } from '@nodarium/ui';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
type Props = {
|
||||
keymaps: {
|
||||
@@ -11,22 +11,26 @@
|
||||
};
|
||||
|
||||
let { keymaps }: Props = $props();
|
||||
|
||||
function getKeyKey(key: ShortCut) {
|
||||
return (key?.alt ? 'alt-' : '') + (key?.ctrl ? 'ctrl-' : '') + key.key;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="p-4">
|
||||
<table class="wrapper">
|
||||
<tbody>
|
||||
{#each keymaps as keymap}
|
||||
{#each keymaps as keymap (keymap.title)}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h3>{keymap.title}</h3>
|
||||
</td>
|
||||
</tr>
|
||||
{#each get(keymap.keymap?.keys) as key}
|
||||
{#each get(keymap.keymap?.keys) as key (getKeyKey(key))}
|
||||
<tr>
|
||||
{#if key.description}
|
||||
<td class="command-wrapper">
|
||||
<ShortCut
|
||||
<ShortCutEl
|
||||
alt={key.alt}
|
||||
ctrl={key.ctrl}
|
||||
shift={key.shift}
|
||||
|
||||
Reference in New Issue
Block a user