Skip to content

Commit 9c1310d

Browse files
committed
Optimize the node graph panel while panning
1 parent 35dcf25 commit 9c1310d

2 files changed

Lines changed: 116 additions & 99 deletions

File tree

frontend/src/components/views/Graph.svelte

Lines changed: 71 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,17 @@
2020
2121
const editor = getContext<EditorWrapper>("editor");
2222
const nodeGraph = getContext<NodeGraphStore>("nodeGraph");
23+
const nodeGraphTransform = nodeGraph.transformStore;
24+
const nodeGraphImportsExports = nodeGraph.importsExportsStore;
25+
const visibleNodes = nodeGraph.visibleNodesStore;
26+
const nodeGraphWires = nodeGraph.wiresStore;
2327
const documentState = getContext<DocumentStore>("document");
2428
const subscriptions = getContext<SubscriptionsRouter>("subscriptions");
2529
2630
let graph: HTMLDivElement | undefined;
2731
28-
$: gridSpacing = calculateGridSpacing($nodeGraph.transform.scale);
29-
$: gridDotRadius = 1 + Math.floor($nodeGraph.transform.scale - 0.5 + 0.001) / 2;
32+
$: gridSpacing = calculateGridSpacing($nodeGraphTransform.scale);
33+
$: gridDotRadius = 1 + Math.floor($nodeGraphTransform.scale - 0.5 + 0.001) / 2;
3034
3135
// Close the context menu when the graph view overlay is closed
3236
$: if (!$documentState.graphViewOverlayOpen) closeContextMenu();
@@ -215,23 +219,22 @@
215219
}
216220
</script>
217221

218-
<div
219-
class="graph"
220-
bind:this={graph}
221-
style:--grid-spacing={`${gridSpacing}px`}
222-
style:--grid-offset-x={`${$nodeGraph.transform.x}px`}
223-
style:--grid-offset-y={`${$nodeGraph.transform.y}px`}
224-
style:--grid-dot-radius={`${gridDotRadius}px`}
225-
data-node-graph
226-
>
222+
<div class="graph" bind:this={graph} data-node-graph>
223+
<div
224+
class="grid-background"
225+
style:--grid-spacing={`${gridSpacing}px`}
226+
style:--grid-offset-x={`${$nodeGraphTransform.x}px`}
227+
style:--grid-offset-y={`${$nodeGraphTransform.y}px`}
228+
style:--grid-dot-radius={`${gridDotRadius}px`}
229+
></div>
227230
<!-- Right click menu for adding nodes -->
228231
{#if $nodeGraph.contextMenuInformation}
229232
<FloatingMenu
230233
class="context-menu"
231234
data-context-menu
232235
styles={{
233-
left: `${$nodeGraph.contextMenuInformation.contextMenuCoordinates[0] * $nodeGraph.transform.scale + $nodeGraph.transform.x}px`,
234-
top: `${$nodeGraph.contextMenuInformation.contextMenuCoordinates[1] * $nodeGraph.transform.scale + $nodeGraph.transform.y}px`,
236+
left: `${$nodeGraph.contextMenuInformation.contextMenuCoordinates[0] * $nodeGraphTransform.scale + $nodeGraphTransform.x}px`,
237+
top: `${$nodeGraph.contextMenuInformation.contextMenuCoordinates[1] * $nodeGraphTransform.scale + $nodeGraphTransform.y}px`,
235238
}}
236239
open={true}
237240
type="Popover"
@@ -283,7 +286,7 @@
283286
{/if}
284287

285288
{#if $nodeGraph.error}
286-
<div class="node-error-container" style:transform-origin="0 0" style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}>
289+
<div class="node-error-container" style:transform-origin="0 0" style:transform={`translate(${$nodeGraphTransform.x}px, ${$nodeGraphTransform.y}px) scale(${$nodeGraphTransform.scale})`}>
287290
<span class="node-error faded" style:left={`${$nodeGraph.error.position[0]}px`} style:top={`${$nodeGraph.error.position[1]}px`} transition:fade={FADE_TRANSITION}>
288291
{$nodeGraph.error.error}
289292
</span>
@@ -295,7 +298,7 @@
295298

296299
<!-- Click target debug visualizations -->
297300
{#if $nodeGraph.clickTargets}
298-
<div class="click-targets" style:transform-origin="0 0" style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}>
301+
<div class="click-targets" style:transform-origin="0 0" style:transform={`translate(${$nodeGraphTransform.x}px, ${$nodeGraphTransform.y}px) scale(${$nodeGraphTransform.scale})`}>
299302
<svg>
300303
{#each $nodeGraph.clickTargets.nodeClickTargets as pathString}
301304
<path class="node" d={pathString} />
@@ -318,9 +321,9 @@
318321
{/if}
319322

320323
<!-- Thick vertical layer connection wires -->
321-
<div class="wires" style:transform-origin="0 0" style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}>
324+
<div class="wires" style:transform-origin="0 0" style:transform={`translate(${$nodeGraphTransform.x}px, ${$nodeGraphTransform.y}px) scale(${$nodeGraphTransform.scale})`}>
322325
<svg>
323-
{#each $nodeGraph.wires.values() as map}
326+
{#each $nodeGraphWires.values() as map}
324327
{#each map.values() as { pathString, dataType, thick, dashed }}
325328
{#if thick}
326329
<path
@@ -337,9 +340,9 @@
337340
</div>
338341

339342
<!-- Import and Export connectors -->
340-
<div class="imports-and-exports" style:transform-origin="0 0" style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}>
341-
{#if $nodeGraph.updateImportsExports}
342-
{#each $nodeGraph.updateImportsExports.imports as frontendOutput, index}
343+
<div class="imports-and-exports" style:transform-origin="0 0" style:transform={`translate(${$nodeGraphTransform.x}px, ${$nodeGraphTransform.y}px) scale(${$nodeGraphTransform.scale})`}>
344+
{#if $nodeGraphImportsExports}
345+
{#each $nodeGraphImportsExports.imports as frontendOutput, index}
343346
{#if frontendOutput}
344347
<svg
345348
xmlns="http://www.w3.org/2000/svg"
@@ -351,8 +354,8 @@
351354
data-datatype={frontendOutput.dataType}
352355
style:--data-color={`var(--color-data-${frontendOutput.dataType.toLowerCase()})`}
353356
style:--data-color-dim={`var(--color-data-${frontendOutput.dataType.toLowerCase()}-dim)`}
354-
style:--offset-left={($nodeGraph.updateImportsExports.importPosition[0] - 8) / 24}
355-
style:--offset-top={($nodeGraph.updateImportsExports.importPosition[1] - 8) / 24 + index}
357+
style:--offset-left={($nodeGraphImportsExports.importPosition[0] - 8) / 24}
358+
style:--offset-top={($nodeGraphImportsExports.importPosition[1] - 8) / 24 + index}
356359
>
357360
{#if frontendOutput.connectedTo.length > 0}
358361
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
@@ -365,10 +368,10 @@
365368
on:pointerenter={() => (hoveringImportIndex = index)}
366369
on:pointerleave={() => (hoveringImportIndex = undefined)}
367370
class="edit-import-export import"
368-
class:separator-bottom={index === 0 && $nodeGraph.updateImportsExports.addImportExport}
369-
class:separator-top={index === 1 && $nodeGraph.updateImportsExports.addImportExport}
370-
style:--offset-left={($nodeGraph.updateImportsExports.importPosition[0] - 8) / 24}
371-
style:--offset-top={($nodeGraph.updateImportsExports.importPosition[1] - 8) / 24 + index}
371+
class:separator-bottom={index === 0 && $nodeGraphImportsExports.addImportExport}
372+
class:separator-top={index === 1 && $nodeGraphImportsExports.addImportExport}
373+
style:--offset-left={($nodeGraphImportsExports.importPosition[0] - 8) / 24}
374+
style:--offset-top={($nodeGraphImportsExports.importPosition[1] - 8) / 24 + index}
372375
>
373376
{#if editingNameImportIndex === index}
374377
<input
@@ -385,7 +388,7 @@
385388
{frontendOutput.name}
386389
</p>
387390
{/if}
388-
{#if (hoveringImportIndex === index || editingNameImportIndex === index) && $nodeGraph.updateImportsExports.addImportExport}
391+
{#if (hoveringImportIndex === index || editingNameImportIndex === index) && $nodeGraphImportsExports.addImportExport}
389392
<IconButton
390393
size={16}
391394
icon="Remove"
@@ -402,17 +405,13 @@
402405
{/if}
403406
</div>
404407
{:else}
405-
<div
406-
class="plus"
407-
style:--offset-top={($nodeGraph.updateImportsExports.importPosition[1] - 12) / 24}
408-
style:--offset-left={($nodeGraph.updateImportsExports.importPosition[0] - 12) / 24}
409-
>
408+
<div class="plus" style:--offset-top={($nodeGraphImportsExports.importPosition[1] - 12) / 24} style:--offset-left={($nodeGraphImportsExports.importPosition[0] - 12) / 24}>
410409
<IconButton size={24} icon="Add" action={() => editor.addPrimaryImport()} />
411410
</div>
412411
{/if}
413412
{/each}
414413

415-
{#each $nodeGraph.updateImportsExports.exports as frontendInput, index}
414+
{#each $nodeGraphImportsExports.exports as frontendInput, index}
416415
{#if frontendInput}
417416
<svg
418417
xmlns="http://www.w3.org/2000/svg"
@@ -424,8 +423,8 @@
424423
data-datatype={frontendInput.dataType}
425424
style:--data-color={`var(--color-data-${frontendInput.dataType.toLowerCase()})`}
426425
style:--data-color-dim={`var(--color-data-${frontendInput.dataType.toLowerCase()}-dim)`}
427-
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition[0] - 8) / 24}
428-
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition[1] - 8) / 24 + index}
426+
style:--offset-left={($nodeGraphImportsExports.exportPosition[0] - 8) / 24}
427+
style:--offset-top={($nodeGraphImportsExports.exportPosition[1] - 8) / 24 + index}
429428
>
430429
{#if frontendInput.connectedTo !== "Connected to nothing."}
431430
<path d="M0,6.306A1.474,1.474,0,0,0,2.356,7.724L7.028,5.248c1.3-.687,1.3-1.809,0-2.5L2.356.276A1.474,1.474,0,0,0,0,1.694Z" fill="var(--data-color)" />
@@ -437,12 +436,12 @@
437436
on:pointerenter={() => (hoveringExportIndex = index)}
438437
on:pointerleave={() => (hoveringExportIndex = undefined)}
439438
class="edit-import-export export"
440-
class:separator-bottom={index === 0 && $nodeGraph.updateImportsExports.addImportExport}
441-
class:separator-top={index === 1 && $nodeGraph.updateImportsExports.addImportExport}
442-
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition[0] - 8) / 24}
443-
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition[1] - 8) / 24 + index}
439+
class:separator-bottom={index === 0 && $nodeGraphImportsExports.addImportExport}
440+
class:separator-top={index === 1 && $nodeGraphImportsExports.addImportExport}
441+
style:--offset-left={($nodeGraphImportsExports.exportPosition[0] - 8) / 24}
442+
style:--offset-top={($nodeGraphImportsExports.exportPosition[1] - 8) / 24 + index}
444443
>
445-
{#if (hoveringExportIndex === index || editingNameExportIndex === index) && $nodeGraph.updateImportsExports.addImportExport}
444+
{#if (hoveringExportIndex === index || editingNameExportIndex === index) && $nodeGraphImportsExports.addImportExport}
446445
{#if index > 0}
447446
<div class="reorder-drag-grip" data-tooltip-description="Reorder this export"></div>
448447
{/if}
@@ -473,57 +472,53 @@
473472
{/if}
474473
</div>
475474
{:else}
476-
<div
477-
class="plus"
478-
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition[0] - 12) / 24}
479-
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition[1] - 12) / 24}
480-
>
475+
<div class="plus" style:--offset-left={($nodeGraphImportsExports.exportPosition[0] - 12) / 24} style:--offset-top={($nodeGraphImportsExports.exportPosition[1] - 12) / 24}>
481476
<IconButton size={24} icon="Add" action={() => editor.addPrimaryExport()} />
482477
</div>
483478
{/if}
484479
{/each}
485480

486-
{#if $nodeGraph.updateImportsExports.addImportExport}
481+
{#if $nodeGraphImportsExports.addImportExport}
487482
<div
488483
class="plus"
489-
style:--offset-left={($nodeGraph.updateImportsExports.importPosition[0] - 12) / 24}
490-
style:--offset-top={($nodeGraph.updateImportsExports.importPosition[1] - 12) / 24 + $nodeGraph.updateImportsExports.imports.length}
484+
style:--offset-left={($nodeGraphImportsExports.importPosition[0] - 12) / 24}
485+
style:--offset-top={($nodeGraphImportsExports.importPosition[1] - 12) / 24 + $nodeGraphImportsExports.imports.length}
491486
>
492487
<IconButton size={24} icon="Add" action={() => editor.addSecondaryImport()} />
493488
</div>
494489
<div
495490
class="plus"
496-
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition[0] - 12) / 24}
497-
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition[1] - 12) / 24 + $nodeGraph.updateImportsExports.exports.length}
491+
style:--offset-left={($nodeGraphImportsExports.exportPosition[0] - 12) / 24}
492+
style:--offset-top={($nodeGraphImportsExports.exportPosition[1] - 12) / 24 + $nodeGraphImportsExports.exports.length}
498493
>
499494
<IconButton size={24} icon="Add" action={() => editor.addSecondaryExport()} />
500495
</div>
501496
{/if}
502497

503498
{#if $nodeGraph.reorderImportIndex !== undefined}
504499
{@const position = {
505-
x: Number($nodeGraph.updateImportsExports.importPosition[0]),
506-
y: Number($nodeGraph.updateImportsExports.importPosition[1]) + Number($nodeGraph.reorderImportIndex) * 24,
500+
x: Number($nodeGraphImportsExports.importPosition[0]),
501+
y: Number($nodeGraphImportsExports.importPosition[1]) + Number($nodeGraph.reorderImportIndex) * 24,
507502
}}
508503
<div class="reorder-bar" style:--offset-left={(position.x - 48) / 24} style:--offset-top={(position.y - 12) / 24}></div>
509504
{/if}
510505

511506
{#if $nodeGraph.reorderExportIndex !== undefined}
512507
{@const position = {
513-
x: Number($nodeGraph.updateImportsExports.exportPosition[0]),
514-
y: Number($nodeGraph.updateImportsExports.exportPosition[1]) + Number($nodeGraph.reorderExportIndex) * 24,
508+
x: Number($nodeGraphImportsExports.exportPosition[0]),
509+
y: Number($nodeGraphImportsExports.exportPosition[1]) + Number($nodeGraph.reorderExportIndex) * 24,
515510
}}
516511
<div class="reorder-bar" style:--offset-left={position.x / 24} style:--offset-top={(position.y - 12) / 24}></div>
517512
{/if}
518513
{/if}
519514
</div>
520515

521516
<!-- Layers and nodes -->
522-
<div class="layers-and-nodes" style:transform-origin="0 0" style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}>
517+
<div class="layers-and-nodes" style:transform-origin="0 0" style:transform={`translate(${$nodeGraphTransform.x}px, ${$nodeGraphTransform.y}px) scale(${$nodeGraphTransform.scale})`}>
523518
<!-- Layers -->
524519
{#each Array.from($nodeGraph.nodes)
525-
.filter(([nodeId, node]) => node.isLayer && $nodeGraph.visibleNodes.has(nodeId))
526-
.map(([_, node], nodeIndex) => ({ node, nodeIndex })) as { node, nodeIndex } (nodeIndex)}
520+
.filter(([nodeId, node]) => node.isLayer && $visibleNodes.has(nodeId))
521+
.map(([_, node]) => node) as node (node.id)}
527522
{@const clipPathId = String(Math.random()).substring(2)}
528523
{@const stackDataInput = node.exposedInputs[0]}
529524
{@const layerAreaWidth = $nodeGraph.layerWidths.get(node.id) || 8}
@@ -687,7 +682,7 @@
687682
<!-- Node connection wires -->
688683
<div class="wires">
689684
<svg>
690-
{#each $nodeGraph.wires.values() as map}
685+
{#each $nodeGraphWires.values() as map}
691686
{#each map.values() as { pathString, dataType, thick, dashed }}
692687
{#if !thick}
693688
<path
@@ -714,8 +709,8 @@
714709

715710
<!-- Nodes -->
716711
{#each Array.from($nodeGraph.nodes)
717-
.filter(([nodeId, node]) => !node.isLayer && $nodeGraph.visibleNodes.has(nodeId))
718-
.map(([_, node], nodeIndex) => ({ node, nodeIndex })) as { node, nodeIndex } (nodeIndex)}
712+
.filter(([nodeId, node]) => !node.isLayer && $visibleNodes.has(nodeId))
713+
.map(([_, node]) => node) as node (node.id)}
719714
{@const exposedInputsOutputs = zipWithUndefined(node.exposedInputs, node.exposedOutputs)}
720715
{@const clipPathId = String(Math.random()).substring(2)}
721716
{@const description = node.reference ? $nodeGraph.nodeDescriptions.get(node.reference) : undefined}
@@ -870,18 +865,25 @@
870865
flex-direction: row;
871866
flex-grow: 1;
872867
873-
// We're displaying the dotted grid in a pseudo-element because `image-rendering` is an inherited property and we don't want it to apply to child elements
874-
&::before {
875-
content: "";
868+
.grid-background {
876869
position: absolute;
877870
width: 100%;
878871
height: 100%;
879-
background-size: var(--grid-spacing) var(--grid-spacing);
880-
background-position: calc(var(--grid-offset-x) - var(--grid-dot-radius)) calc(var(--grid-offset-y) - var(--grid-dot-radius));
881-
background-image: radial-gradient(circle at var(--grid-dot-radius) var(--grid-dot-radius), var(--color-3-darkgray) var(--grid-dot-radius), transparent 0);
882-
background-repeat: repeat;
883-
image-rendering: pixelated;
884-
mix-blend-mode: screen;
872+
pointer-events: none;
873+
874+
// We're displaying the dotted grid in a pseudo-element because `image-rendering` is an inherited property and we don't want it to apply to child elements
875+
&::before {
876+
content: "";
877+
position: absolute;
878+
width: 100%;
879+
height: 100%;
880+
background-size: var(--grid-spacing) var(--grid-spacing);
881+
background-position: calc(var(--grid-offset-x) - var(--grid-dot-radius)) calc(var(--grid-offset-y) - var(--grid-dot-radius));
882+
background-image: radial-gradient(circle at var(--grid-dot-radius) var(--grid-dot-radius), var(--color-3-darkgray) var(--grid-dot-radius), transparent 0);
883+
background-repeat: repeat;
884+
image-rendering: pixelated;
885+
mix-blend-mode: screen;
886+
}
885887
}
886888
887889
> img {

0 commit comments

Comments
 (0)