feat: improve zoom performance by adding a tiny rand offset to nodes
This commit is contained in:
@ -1,129 +1,138 @@
|
||||
<script lang="ts">
|
||||
import type { Node } from '@nodes/types';
|
||||
import { getContext, onMount } from 'svelte';
|
||||
import NodeHeader from './NodeHeader.svelte';
|
||||
import NodeParameter from './NodeParameter.svelte';
|
||||
import { activeNodeId, selectedNodes } from '../graph/stores.js';
|
||||
import { T } from '@threlte/core';
|
||||
import { Color, type Mesh } from 'three';
|
||||
import NodeFrag from './Node.frag';
|
||||
import NodeVert from './Node.vert';
|
||||
import type { Node } from "@nodes/types";
|
||||
import { getContext, onMount } from "svelte";
|
||||
import NodeHeader from "./NodeHeader.svelte";
|
||||
import NodeParameter from "./NodeParameter.svelte";
|
||||
import { activeNodeId, selectedNodes } from "../graph/stores.js";
|
||||
import { T } from "@threlte/core";
|
||||
import { Color, type Mesh } from "three";
|
||||
import NodeFrag from "./Node.frag";
|
||||
import NodeVert from "./Node.vert";
|
||||
|
||||
export let node: Node;
|
||||
export let inView = true;
|
||||
export let z = 2;
|
||||
export let node: Node;
|
||||
export let inView = true;
|
||||
export let z = 2;
|
||||
|
||||
$: isActive = $activeNodeId === node.id;
|
||||
$: isSelected = !!$selectedNodes?.has(node.id);
|
||||
$: isActive = $activeNodeId === node.id;
|
||||
$: isSelected = !!$selectedNodes?.has(node.id);
|
||||
|
||||
const updateNodePosition = getContext<(n: Node) => void>('updateNodePosition');
|
||||
const updateNodePosition =
|
||||
getContext<(n: Node) => void>("updateNodePosition");
|
||||
|
||||
const getNodeHeight = getContext<(n: string) => number>('getNodeHeight');
|
||||
const getNodeHeight = getContext<(n: string) => number>("getNodeHeight");
|
||||
|
||||
const type = node?.tmp?.type;
|
||||
const type = node?.tmp?.type;
|
||||
|
||||
const parameters = Object.entries(type?.inputs || {})
|
||||
.filter((p) => p[1].type !== 'seed')
|
||||
.filter((p) => !('setting' in p[1]));
|
||||
const zOffset = (node.tmp?.random || 0) * 0.5;
|
||||
const zLimit = 2 - zOffset;
|
||||
$: visible = inView && z > zLimit;
|
||||
|
||||
let ref: HTMLDivElement;
|
||||
let meshRef: Mesh;
|
||||
const parameters = Object.entries(type?.inputs || {})
|
||||
.filter((p) => p[1].type !== "seed")
|
||||
.filter((p) => !("setting" in p[1]));
|
||||
|
||||
const height = getNodeHeight(node.type);
|
||||
let ref: HTMLDivElement;
|
||||
let meshRef: Mesh;
|
||||
|
||||
$: if (node && ref && meshRef) {
|
||||
node.tmp = node.tmp || {};
|
||||
node.tmp.ref = ref;
|
||||
node.tmp.mesh = meshRef;
|
||||
updateNodePosition(node);
|
||||
}
|
||||
const height = getNodeHeight(node.type);
|
||||
|
||||
onMount(() => {
|
||||
node.tmp = node.tmp || {};
|
||||
node.tmp.ref = ref;
|
||||
node.tmp.mesh = meshRef;
|
||||
updateNodePosition(node);
|
||||
});
|
||||
$: if (node && ref && meshRef) {
|
||||
node.tmp = node.tmp || {};
|
||||
node.tmp.ref = ref;
|
||||
node.tmp.mesh = meshRef;
|
||||
updateNodePosition(node);
|
||||
}
|
||||
|
||||
const colorDark = new Color();
|
||||
colorDark.setStyle('#151515');
|
||||
//colorDark.();
|
||||
onMount(() => {
|
||||
node.tmp = node.tmp || {};
|
||||
node.tmp.ref = ref;
|
||||
node.tmp.mesh = meshRef;
|
||||
updateNodePosition(node);
|
||||
});
|
||||
|
||||
const colorBright = new Color('#202020');
|
||||
//colorBright.convertLinearToSRGB();
|
||||
const colorDark = new Color();
|
||||
colorDark.setStyle("#151515");
|
||||
//colorDark.();
|
||||
|
||||
const colorBright = new Color("#202020");
|
||||
//colorBright.convertLinearToSRGB();
|
||||
</script>
|
||||
|
||||
<T.Mesh
|
||||
position.x={node.position[0] + 10}
|
||||
position.z={node.position[1] + height / 2}
|
||||
position.y={0.8}
|
||||
rotation.x={-Math.PI / 2}
|
||||
bind:ref={meshRef}
|
||||
visible={z < 7}
|
||||
position.x={node.position[0] + 10}
|
||||
position.z={node.position[1] + height / 2}
|
||||
position.y={0.8}
|
||||
rotation.x={-Math.PI / 2}
|
||||
bind:ref={meshRef}
|
||||
visible={inView && z < 7}
|
||||
>
|
||||
<T.PlaneGeometry args={[20, height]} radius={1} />
|
||||
<T.ShaderMaterial
|
||||
vertexShader={NodeVert}
|
||||
fragmentShader={NodeFrag}
|
||||
transparent
|
||||
uniforms={{
|
||||
uColorBright: { value: colorBright },
|
||||
uColorDark: { value: colorDark },
|
||||
uSelectedColor: { value: new Color('#9d5f28') },
|
||||
uActiveColor: { value: new Color('white') },
|
||||
uSelected: { value: false },
|
||||
uActive: { value: false },
|
||||
uStrokeWidth: { value: 1.0 },
|
||||
uWidth: { value: 20 },
|
||||
uHeight: { value: height }
|
||||
}}
|
||||
uniforms.uSelected.value={isSelected}
|
||||
uniforms.uActive.value={isActive}
|
||||
uniforms.uStrokeWidth.value={(7 - z) / 3}
|
||||
/>
|
||||
<T.PlaneGeometry args={[20, height]} radius={1} />
|
||||
<T.ShaderMaterial
|
||||
vertexShader={NodeVert}
|
||||
fragmentShader={NodeFrag}
|
||||
transparent
|
||||
uniforms={{
|
||||
uColorBright: { value: colorBright },
|
||||
uColorDark: { value: colorDark },
|
||||
uSelectedColor: { value: new Color("#9d5f28") },
|
||||
uActiveColor: { value: new Color("white") },
|
||||
uSelected: { value: false },
|
||||
uActive: { value: false },
|
||||
uStrokeWidth: { value: 1.0 },
|
||||
uWidth: { value: 20 },
|
||||
uHeight: { value: height },
|
||||
}}
|
||||
uniforms.uSelected.value={isSelected}
|
||||
uniforms.uActive.value={isActive}
|
||||
uniforms.uStrokeWidth.value={(7 - z) / 3}
|
||||
/>
|
||||
</T.Mesh>
|
||||
|
||||
<div
|
||||
class="node"
|
||||
class:active={isActive}
|
||||
class:selected={isSelected}
|
||||
class:out-of-view={!inView}
|
||||
data-node-id={node.id}
|
||||
bind:this={ref}
|
||||
class="node"
|
||||
class:active={isActive}
|
||||
style:--cz={z + zOffset}
|
||||
style:display={inView && z > zLimit ? "block" : "none"}
|
||||
class:selected={isSelected}
|
||||
class:out-of-view={!inView}
|
||||
data-node-id={node.id}
|
||||
bind:this={ref}
|
||||
>
|
||||
<NodeHeader {node} />
|
||||
<NodeHeader {node} />
|
||||
|
||||
{#each parameters as [key, value], i}
|
||||
<NodeParameter bind:node id={key} input={value} isLast={i == parameters.length - 1} />
|
||||
{/each}
|
||||
{#each parameters as [key, value], i}
|
||||
<NodeParameter
|
||||
bind:node
|
||||
id={key}
|
||||
input={value}
|
||||
isLast={i == parameters.length - 1}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.node {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
user-select: none !important;
|
||||
cursor: pointer;
|
||||
width: 200px;
|
||||
color: var(--text-color);
|
||||
transform: translate3d(var(--nx), var(--ny), 0);
|
||||
z-index: 1;
|
||||
font-weight: 300;
|
||||
--stroke: var(--background-color-lighter);
|
||||
--stroke-width: 2px;
|
||||
}
|
||||
.node {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
user-select: none !important;
|
||||
cursor: pointer;
|
||||
width: 200px;
|
||||
color: var(--text-color);
|
||||
transform: translate3d(var(--nx), var(--ny), 0);
|
||||
z-index: 1;
|
||||
opacity: calc((var(--cz) - 2.5) / 3.5);
|
||||
font-weight: 300;
|
||||
--stroke: var(--background-color-lighter);
|
||||
--stroke-width: 2px;
|
||||
}
|
||||
|
||||
.node.active {
|
||||
--stroke: white;
|
||||
--stroke-width: 1px;
|
||||
}
|
||||
.node.active {
|
||||
--stroke: white;
|
||||
--stroke-width: 1px;
|
||||
}
|
||||
|
||||
.node.selected {
|
||||
--stroke: #9d5f28;
|
||||
--stroke-width: 1px;
|
||||
}
|
||||
|
||||
.node.out-of-view {
|
||||
display: none;
|
||||
}
|
||||
.node.selected {
|
||||
--stroke: #9d5f28;
|
||||
--stroke-width: 1px;
|
||||
}
|
||||
</style>
|
||||
|
@ -156,10 +156,6 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:global(.zoom-small) .content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
svg {
|
||||
position: absolute;
|
||||
box-sizing: border-box;
|
||||
|
Reference in New Issue
Block a user