feat: implement variable height for node shader
Some checks failed
🚀 Lint & Test & Deploy / release (pull_request) Failing after 1m3s

This commit is contained in:
release-bot
2026-02-12 18:11:14 +01:00
parent da09f8ba1e
commit 3f440728fc
5 changed files with 91 additions and 42 deletions

View File

@@ -38,7 +38,6 @@ export function getSocketPosition(
const inputs = nodeType.inputs || {}; const inputs = nodeType.inputs || {};
for (const inputKey in inputs) { for (const inputKey in inputs) {
const h = getParameterHeight(nodeType, inputKey) / 10; const h = getParameterHeight(nodeType, inputKey) / 10;
console.log({ inputKey, h });
if (inputKey === index) { if (inputKey === index) {
height += h / 2; height += h / 2;
break; break;
@@ -61,7 +60,6 @@ export function getNodeHeight(node: NodeDefinition) {
return 5; return 5;
} }
let height = 5; let height = 5;
console.log('Get Node Height', node.id);
for (const key in node.inputs) { for (const key in node.inputs) {
const h = getParameterHeight(node, key) / 10; const h = getParameterHeight(node, key) / 10;

View File

@@ -1,56 +1,88 @@
varying vec2 vUv; varying vec2 vUv;
uniform float uWidth; uniform float uWidth;
uniform float uHeight; uniform float uHeight;
uniform float uZoom;
uniform vec3 uColorDark; uniform vec3 uColorDark;
uniform vec3 uColorBright; uniform vec3 uColorBright;
uniform vec3 uStrokeColor; uniform vec3 uStrokeColor;
uniform float uStrokeWidth;
const float uHeaderHeight = 5.0;
uniform float uSectionHeights[16];
uniform int uNumSections;
float msign(in float x) { return (x < 0.0) ? -1.0 : 1.0; } float msign(in float x) { return (x < 0.0) ? -1.0 : 1.0; }
float sdCircle(vec2 p, float r) { return length(p) - r; }
vec4 roundedBoxSDF( in vec2 p, in vec2 b, in float r, in float s) { vec4 roundedBoxSDF( in vec2 p, in vec2 b, in float r, in float s) {
vec2 q = abs(p) - b + r; vec2 q = abs(p) - b + r;
float l = b.x + b.y + 1.570796 * r; float l = b.x + b.y + 1.570796 * r;
float k1 = min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r; float k1 = min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;
float k2 = ((q.x > 0.0) ? atan(q.y, q.x) : 1.570796); float k2 = ((q.x > 0.0) ? atan(q.y, q.x) : 1.570796);
float k3 = 3.0 + 2.0 * msign(min(p.x, -p.y)) - msign(p.x); float k3 = 3.0 + 2.0 * msign(min(p.x, -p.y)) - msign(p.x);
float k4 = msign(p.x * p.y); float k4 = msign(p.x * p.y);
float k5 = r * k2 + max(-q.x, 0.0); float k5 = r * k2 + max(-q.x, 0.0);
float ra = s * round(k1 / s); float ra = s * round(k1 / s);
float l2 = l + 1.570796 * ra; float l2 = l + 1.570796 * ra;
return vec4(k1 - ra, k3 * l2 + k4 * (b.y + ((q.y > 0.0) ? k5 + k2 * ra : q.y)), 4.0 * l2, k1); return vec4(k1 - ra, k3 * l2 + k4 * (b.y + ((q.y > 0.0) ? k5 + k2 * ra : q.y)), 4.0 * l2, k1);
} }
void main(){ void main(){
float strokeWidth = mix(2.0, 0.5, uZoom);
float y = (1.0-vUv.y) * uHeight; float borderRadius = 0.5;
float dentRadius = 0.8;
float y = (1.0 - vUv.y) * uHeight;
float x = vUv.x * uWidth; float x = vUv.x * uWidth;
vec2 size = vec2(uWidth, uHeight); vec2 size = vec2(uWidth, uHeight);
vec2 uv = (vUv - 0.5) * 2.0; vec2 uvCenter = (vUv - 0.5) * 2.0;
float u_border_radius = 0.4; vec4 boxData = roundedBoxSDF(uvCenter * size, size, borderRadius * 2.0, 0.0);
vec4 distance = roundedBoxSDF(uv * size, size, u_border_radius*2.0, 0.0); float sceneSDF = boxData.w;
if (distance.w > 0.0 ) { vec2 headerDentPos = vec2(uWidth, uHeaderHeight * 0.5);
// outside float headerDentDist = sdCircle(vec2(x, y) - headerDentPos, dentRadius);
gl_FragColor = vec4(0.0,0.0,0.0, 0.0); sceneSDF = max(sceneSDF, -headerDentDist*2.0);
}else{
if (distance.w > -uStrokeWidth || mod(y+5.0, 10.0) < uStrokeWidth/2.0) { float currentYBoundary = uHeaderHeight;
// draw the outer stroke float previousYBoundary = uHeaderHeight;
gl_FragColor = vec4(uStrokeColor, 1.0);
}else if (y<5.0){ for (int i = 0; i < 16; i++) {
// draw the header if (i >= uNumSections) break;
gl_FragColor = vec4(uColorBright, 1.0);
}else{ float sectionHeight = uSectionHeights[i];
gl_FragColor = vec4(uColorDark, 1.0); currentYBoundary += sectionHeight;
float centerY = previousYBoundary + (sectionHeight * 0.5);
vec2 circlePos = vec2(0.0, centerY);
float circleDist = sdCircle(vec2(x, y) - circlePos, dentRadius);
sceneSDF = max(sceneSDF, -circleDist*2.0);
previousYBoundary = currentYBoundary;
} }
if (sceneSDF > 0.05) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
return;
}
vec3 finalColor = (y < uHeaderHeight) ? uColorBright : uColorDark;
bool isDivider = false;
float dividerY = uHeaderHeight;
if (abs(y - dividerY) < strokeWidth * 0.25) isDivider = true;
for (int i = 0; i < 16; i++) {
if (i >= uNumSections - 1) break;
dividerY += uSectionHeights[i];
if (abs(y - dividerY) < strokeWidth * 0.25) isDivider = true;
}
if (sceneSDF > -strokeWidth || isDivider) {
gl_FragColor = vec4(uStrokeColor, 1.0);
} else {
gl_FragColor = vec4(finalColor, 1.0);
} }
} }

View File

@@ -5,7 +5,7 @@
import { type Mesh } from 'three'; import { type Mesh } from 'three';
import { getGraphState } from '../graph-state.svelte'; import { getGraphState } from '../graph-state.svelte';
import { colors } from '../graph/colors.svelte'; import { colors } from '../graph/colors.svelte';
import { getNodeHeight } from '../helpers/nodeHelpers'; import { getNodeHeight, getParameterHeight } from '../helpers/nodeHelpers';
import NodeFrag from './Node.frag'; import NodeFrag from './Node.frag';
import NodeVert from './Node.vert'; import NodeVert from './Node.vert';
import NodeHtml from './NodeHTML.svelte'; import NodeHtml from './NodeHTML.svelte';
@@ -15,9 +15,10 @@
type Props = { type Props = {
node: NodeInstance; node: NodeInstance;
inView: boolean; inView: boolean;
z: number;
}; };
let { node = $bindable(), inView, z }: Props = $props(); let { node = $bindable(), inView }: Props = $props();
const nodeType = $derived(node.state.type!);
const isActive = $derived(graphState.activeNodeId === node.id); const isActive = $derived(graphState.activeNodeId === node.id);
const isSelected = $derived(graphState.selectedNodes.has(node.id)); const isSelected = $derived(graphState.selectedNodes.has(node.id));
@@ -30,16 +31,29 @@
: colors.outline) : colors.outline)
); );
const sectionHeights = $derived(
Object
.keys(nodeType.inputs || {})
.map(key => getParameterHeight(nodeType, key) / 10)
.filter(b => !!b)
);
let meshRef: Mesh | undefined = $state(); let meshRef: Mesh | undefined = $state();
const height = getNodeHeight(node.state.type!); const height = getNodeHeight(node.state.type!);
const zoom = $derived(graphState.cameraPosition[2]);
$effect(() => { $effect(() => {
if (meshRef && !node.state?.mesh) { if (meshRef && !node.state?.mesh) {
node.state.mesh = meshRef; node.state.mesh = meshRef;
graphState.updateNodePosition(node); graphState.updateNodePosition(node);
} }
}); });
const zoomValue = $derived(
(Math.log(graphState.cameraPosition[2]) - Math.log(1)) / (Math.log(40) - Math.log(1))
);
// const zoomValue = (graphState.cameraPosition[2] - 1) / 39;
</script> </script>
<T.Mesh <T.Mesh
@@ -48,7 +62,7 @@
position.y={0.8} position.y={0.8}
rotation.x={-Math.PI / 2} rotation.x={-Math.PI / 2}
bind:ref={meshRef} bind:ref={meshRef}
visible={inView && z < 7} visible={inView && zoom < 7}
> >
<T.PlaneGeometry args={[20, height]} radius={1} /> <T.PlaneGeometry args={[20, height]} radius={1} />
<T.ShaderMaterial <T.ShaderMaterial
@@ -58,14 +72,19 @@
uniforms={{ uniforms={{
uColorBright: { value: colors['layer-2'] }, uColorBright: { value: colors['layer-2'] },
uColorDark: { value: colors['layer-1'] }, uColorDark: { value: colors['layer-1'] },
uStrokeColor: { value: colors['layer-2'].clone() }, uStrokeColor: { value: colors.outline.clone() },
uStrokeWidth: { value: 1.0 }, uSectionHeights: { value: [5, 10] },
uNumSections: { value: 2 },
uWidth: { value: 20 }, uWidth: { value: 20 },
uHeight: { value: height } uHeight: { value: 200 },
uZoom: { value: 1.0 }
}} }}
uniforms.uStrokeColor.value={strokeColor.clone()} uniforms.uZoom.value={zoomValue}
uniforms.uStrokeWidth.value={(7 - z) / 3} uniforms.uHeight.value={height}
uniforms.uSectionHeights.value={sectionHeights}
uniforms.uNumSections.value={sectionHeights.length}
uniforms.uStrokeColor.value={strokeColor}
/> />
</T.Mesh> </T.Mesh>
<NodeHtml bind:node {inView} {isActive} {isSelected} {z} /> <NodeHtml bind:node {inView} {isActive} {isSelected} z={zoom} />

View File

@@ -43,7 +43,7 @@
const path = $derived( const path = $derived(
createNodePath({ createNodePath({
depth: 6, depth: 6,
height: 1700 / height, height: 2000 / height,
y: 50.5, y: 50.5,
cornerBottom, cornerBottom,
leftBump, leftBump,
@@ -53,7 +53,7 @@
const pathHover = $derived( const pathHover = $derived(
createNodePath({ createNodePath({
depth: 7, depth: 7,
height: 2000 / height, height: 2200 / height,
y: 50.5, y: 50.5,
cornerBottom, cornerBottom,
leftBump, leftBump,

View File

@@ -3,10 +3,10 @@
prefix: "i"; prefix: "i";
} }
@source inline("{hover:,}{bg-,outline-,text-,}layer-0"); @source inline("{hover:,}{bg-,outline-,text-,}layer-0{/30,/50,}");
@source inline("{hover:,}{bg-,outline-,text-,}layer-1"); @source inline("{hover:,}{bg-,outline-,text-,}layer-1{/30,/50,}");
@source inline("{hover:,}{bg-,outline-,text-,}layer-2"); @source inline("{hover:,}{bg-,outline-,text-,}layer-2{/30,/50,}");
@source inline("{hover:,}{bg-,outline-,text-,}layer-3"); @source inline("{hover:,}{bg-,outline-,text-,}layer-3{/30,/50,}");
@source inline("{hover:,}{bg-,outline-,text-,}active"); @source inline("{hover:,}{bg-,outline-,text-,}active");
@source inline("{hover:,}{bg-,outline-,text-,}selected"); @source inline("{hover:,}{bg-,outline-,text-,}selected");
@source inline("{hover:,}{bg-,outline-,text-,}outline{!,}"); @source inline("{hover:,}{bg-,outline-,text-,}outline{!,}");