Add opacity and open to the render data

This commit is contained in:
Adam
2025-09-08 16:39:22 -07:00
parent a917c0c88d
commit e2c45195ef
9 changed files with 551 additions and 556 deletions
@@ -244,9 +244,6 @@ pub enum FrontendMessage {
#[serde(rename = "setColorChoice")] #[serde(rename = "setColorChoice")]
set_color_choice: Option<String>, set_color_choice: Option<String>,
}, },
UpdateGraphFadeArtwork {
percentage: f64,
},
UpdateInputHints { UpdateInputHints {
#[serde(rename = "hintData")] #[serde(rename = "hintData")]
hint_data: HintData, hint_data: HintData,
@@ -274,9 +271,11 @@ pub enum FrontendMessage {
UpdateMouseCursor { UpdateMouseCursor {
cursor: MouseCursorIcon, cursor: MouseCursorIcon,
}, },
UpdateNodeGraphNodes { UpdateNodeGraphRender {
#[serde(rename = "nodesToRender")] #[serde(rename = "nodesToRender")]
nodes_to_render: Vec<FrontendNodeToRender>, nodes_to_render: Vec<FrontendNodeToRender>,
open: bool,
opacity: f64,
#[serde(rename = "inSelectedNetwork")] #[serde(rename = "inSelectedNetwork")]
in_selected_network: bool, in_selected_network: bool,
// Displays a dashed border around the node // Displays a dashed border around the node
@@ -561,9 +561,6 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
self.graph_view_overlay_open = open; self.graph_view_overlay_open = open;
responses.add(FrontendMessage::UpdateGraphViewOverlay { open }); responses.add(FrontendMessage::UpdateGraphViewOverlay { open });
responses.add(FrontendMessage::UpdateGraphFadeArtwork {
percentage: self.graph_fade_artwork_percentage,
});
// Update the tilt menu bar buttons to be disabled when the graph is open // Update the tilt menu bar buttons to be disabled when the graph is open
responses.add(MenuBarMessage::SendLayout); responses.add(MenuBarMessage::SendLayout);
@@ -579,12 +576,13 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
responses.add(NavigationMessage::CanvasTiltSet { angle_radians: 0. }); responses.add(NavigationMessage::CanvasTiltSet { angle_radians: 0. });
responses.add(NodeGraphMessage::SetGridAlignedEdges); responses.add(NodeGraphMessage::SetGridAlignedEdges);
responses.add(NodeGraphMessage::UpdateGraphBarRight); responses.add(NodeGraphMessage::UpdateGraphBarRight);
responses.add(NodeGraphMessage::SendGraph);
responses.add(NodeGraphMessage::UpdateHints); responses.add(NodeGraphMessage::UpdateHints);
} else { } else {
responses.add(ToolMessage::ActivateTool { tool_type: *current_tool }); responses.add(ToolMessage::ActivateTool { tool_type: *current_tool });
responses.add(OverlaysMessage::Draw); // Redraw overlays when graph is closed responses.add(OverlaysMessage::Draw); // Redraw overlays when graph is closed
} }
responses.add(NodeGraphMessage::SendGraph);
} }
DocumentMessage::GraphViewOverlayToggle => { DocumentMessage::GraphViewOverlayToggle => {
responses.add(DocumentMessage::GraphViewOverlay { open: !self.graph_view_overlay_open }); responses.add(DocumentMessage::GraphViewOverlay { open: !self.graph_view_overlay_open });
@@ -1200,7 +1198,7 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
} }
DocumentMessage::SetGraphFadeArtwork { percentage } => { DocumentMessage::SetGraphFadeArtwork { percentage } => {
self.graph_fade_artwork_percentage = percentage; self.graph_fade_artwork_percentage = percentage;
responses.add(FrontendMessage::UpdateGraphFadeArtwork { percentage }); responses.add(NodeGraphMessage::SendGraph);
} }
DocumentMessage::SetNodePinned { node_id, pinned } => { DocumentMessage::SetNodePinned { node_id, pinned } => {
responses.add(DocumentMessage::AddTransaction); responses.add(DocumentMessage::AddTransaction);
@@ -1634,12 +1634,13 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
responses.add(DocumentMessage::DocumentStructureChanged); responses.add(DocumentMessage::DocumentStructureChanged);
responses.add(PropertiesPanelMessage::Refresh); responses.add(PropertiesPanelMessage::Refresh);
responses.add(NodeGraphMessage::UpdateActionButtons); responses.add(NodeGraphMessage::UpdateActionButtons);
if graph_view_overlay_open {
let nodes_to_render = network_interface.collect_nodes(&self.node_graph_errors, breadcrumb_network_path); let nodes_to_render = network_interface.collect_nodes(&self.node_graph_errors, breadcrumb_network_path);
self.frontend_nodes = nodes_to_render.iter().map(|node| node.metadata.node_id).collect(); self.frontend_nodes = nodes_to_render.iter().map(|node| node.metadata.node_id).collect();
let previewed_node = network_interface.previewed_node(breadcrumb_network_path); let previewed_node = network_interface.previewed_node(breadcrumb_network_path);
responses.add(FrontendMessage::UpdateNodeGraphNodes { responses.add(FrontendMessage::UpdateNodeGraphRender {
nodes_to_render, nodes_to_render,
open: graph_view_overlay_open,
opacity: graph_fade_artwork_percentage,
in_selected_network: selection_network_path == breadcrumb_network_path, in_selected_network: selection_network_path == breadcrumb_network_path,
previewed_node, previewed_node,
}); });
@@ -1652,7 +1653,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
responses.add(NodeGraphMessage::SendWires); responses.add(NodeGraphMessage::SendWires);
self.update_node_graph_hints(responses); self.update_node_graph_hints(responses);
} }
}
NodeGraphMessage::SetGridAlignedEdges => { NodeGraphMessage::SetGridAlignedEdges => {
if graph_view_overlay_open { if graph_view_overlay_open {
network_interface.set_grid_aligned_edges(DVec2::new(ipp.viewport_bounds.bottom_right.x - ipp.viewport_bounds.top_left.x, 0.), breadcrumb_network_path); network_interface.set_grid_aligned_edges(DVec2::new(ipp.viewport_bounds.bottom_right.x - ipp.viewport_bounds.top_left.x, 0.), breadcrumb_network_path);
+4 -4
View File
@@ -301,11 +301,11 @@ pub trait FrontendMessageTestUtils {
impl FrontendMessageTestUtils for FrontendMessage { impl FrontendMessageTestUtils for FrontendMessage {
fn check_node_graph_error(&self) { fn check_node_graph_error(&self) {
let FrontendMessage::UpdateNodeGraphNodes { nodes, .. } = self else { return }; let FrontendMessage::UpdateNodeGraphRender { nodes_to_render, .. } = self else { return };
for node in nodes { for node in nodes_to_render {
if let Some(error) = &node.errors { if let Some(error) = &node.metadata.errors {
panic!("error on {}: {}", node.display_name, error); panic!("error on {}: {}", node.metadata.display_name, error);
} }
} }
} }
@@ -565,9 +565,7 @@
{/if} {/if}
</div> </div>
<div class="graph-view" class:open={$document.graphViewOverlayOpen} style:--fade-artwork={`${$document.fadeArtwork}%`} data-graph>
<Graph /> <Graph />
</div>
</LayoutCol> </LayoutCol>
<LayoutCol class="ruler-or-scrollbar right-scrollbar"> <LayoutCol class="ruler-or-scrollbar right-scrollbar">
<ScrollbarInput <ScrollbarInput
@@ -825,30 +823,6 @@
} }
} }
.graph-view {
pointer-events: none;
transition: opacity 0.2s;
opacity: 0;
&.open {
cursor: auto;
pointer-events: auto;
opacity: 1;
}
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--color-2-mildblack);
opacity: var(--fade-artwork);
pointer-events: none;
}
}
.fade-artwork, .fade-artwork,
.graph { .graph {
position: absolute; position: absolute;
+39 -10
View File
@@ -4,7 +4,7 @@
import { fade } from "svelte/transition"; import { fade } from "svelte/transition";
import type { Editor } from "@graphite/editor"; import type { Editor } from "@graphite/editor";
import type { FrontendGraphInput, FrontendGraphOutput } from "@graphite/messages"; import { type FrontendGraphInput, type FrontendGraphOutput } from "@graphite/messages";
import type { NodeGraphState } from "@graphite/state-providers/node-graph"; import type { NodeGraphState } from "@graphite/state-providers/node-graph";
import type { IconName } from "@graphite/utility-functions/icons"; import type { IconName } from "@graphite/utility-functions/icons";
@@ -223,6 +223,7 @@
} }
</script> </script>
<div class="graph-view" class:open={$nodeGraph.open} style:--fade-artwork={`${$nodeGraph.opacity}%`} data-graph>
<div <div
class="graph" class="graph"
bind:this={graph} bind:this={graph}
@@ -277,7 +278,7 @@
<!-- Click target debug visualizations --> <!-- Click target debug visualizations -->
{#if $nodeGraph.clickTargets} {#if $nodeGraph.clickTargets}
<div class="click-targets" style:transform-origin="0 0" style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}> <div class="click-targets" style:transform-origin={`0 0`} style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}>
<svg> <svg>
{#each $nodeGraph.clickTargets.nodeClickTargets as pathString} {#each $nodeGraph.clickTargets.nodeClickTargets as pathString}
<path class="node" d={pathString} /> <path class="node" d={pathString} />
@@ -301,14 +302,14 @@
{/if} {/if}
<!-- Thick vertical layer connection wires --> <!-- Thick vertical layer connection wires -->
<div class="wires" style:transform-origin="0 0" style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}> <div class="wires" style:transform-origin={`0 0`} style:transform={`translate(${$nodeGraph.transform.x}px, ${$nodeGraph.transform.y}px) scale(${$nodeGraph.transform.scale})`}>
<svg> <svg>
{#each $nodeGraph.wires.values() as map} {#each $nodeGraph.wires.values() as map}
{#each map.values() as { pathString, dataType, thick, dashed }} {#each map.values() as { pathString, dataType, thick, dashed }}
{#if thick} {#if thick}
<path <path
d={pathString} d={pathString}
style:--data-line-width="8px" style:--data-line-width={"8px"}
style:--data-color={`var(--color-data-${dataType.toLowerCase()})`} style:--data-color={`var(--color-data-${dataType.toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${dataType.toLowerCase()}-dim)`} style:--data-color-dim={`var(--color-data-${dataType.toLowerCase()}-dim)`}
style:--data-dasharray={`3,${dashed ? 2 : 0}`} style:--data-dasharray={`3,${dashed ? 2 : 0}`}
@@ -320,7 +321,7 @@
</div> </div>
<!-- Import and Export connectors --> <!-- Import and Export connectors -->
<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})`}> <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})`}>
{#if $nodeGraph.updateImportsExports} {#if $nodeGraph.updateImportsExports}
{#each $nodeGraph.updateImportsExports.imports as frontendOutput, index} {#each $nodeGraph.updateImportsExports.imports as frontendOutput, index}
{#if frontendOutput} {#if frontendOutput}
@@ -368,7 +369,7 @@
{#if (hoveringImportIndex === index || editingNameImportIndex === index) && $nodeGraph.updateImportsExports.addImportExport} {#if (hoveringImportIndex === index || editingNameImportIndex === index) && $nodeGraph.updateImportsExports.addImportExport}
<IconButton <IconButton
size={16} size={16}
icon="Remove" icon={"Remove"}
class="remove-button-import" class="remove-button-import"
data-index={index} data-index={index}
data-import-text-edge data-import-text-edge
@@ -425,7 +426,7 @@
{/if} {/if}
<IconButton <IconButton
size={16} size={16}
icon="Remove" icon={"Remove"}
class="remove-button-export" class="remove-button-export"
data-index={index} data-index={index}
data-export-text-edge data-export-text-edge
@@ -473,7 +474,7 @@
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 12) / 24} style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 12) / 24}
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition.y - 12) / 24 + $nodeGraph.updateImportsExports.exports.length} style:--offset-top={($nodeGraph.updateImportsExports.exportPosition.y - 12) / 24 + $nodeGraph.updateImportsExports.exports.length}
> >
<IconButton size={24} icon="Add" action={() => editor.handle.addSecondaryExport()} /> <IconButton size={24} icon={"Add"} action={() => editor.handle.addSecondaryExport()} />
</div> </div>
{/if} {/if}
@@ -536,7 +537,10 @@
style:--data-color-dim={`var(--color-data-${layer.output.dataType.toLowerCase()}-dim)`} style:--data-color-dim={`var(--color-data-${layer.output.dataType.toLowerCase()}-dim)`}
> >
<title>{outputTooltip(layer.output)}</title> <title>{outputTooltip(layer.output)}</title>
<path d="M0,6.953l2.521,-1.694a2.649,2.649,0,0,1,2.959,0l2.52,1.694v5.047h-8z" fill={layer.output.connectedTo.length > 0 ? "var(--data-color)" : "var(--data-color-dim)"} /> <path
d="M0,6.953l2.521,-1.694a2.649,2.649,0,0,1,2.959,0l2.52,1.694v5.047h-8z"
fill={layer.output.connectedTo.length > 0 ? "var(--data-color)" : "var(--data-color-dim)"}
/>
{#if layer.output.connectedTo.length > 0 && layer.primaryOutputConnectedToLayer} {#if layer.output.connectedTo.length > 0 && layer.primaryOutputConnectedToLayer}
<path d="M0,-3.5h8v8l-2.521,-1.681a2.666,2.666,0,0,0,-2.959,0l-2.52,1.681z" fill="var(--data-color-dim)" /> <path d="M0,-3.5h8v8l-2.521,-1.681a2.666,2.666,0,0,0,-2.959,0l-2.52,1.681z" fill="var(--data-color-dim)" />
@@ -615,7 +619,7 @@
{#if !thick} {#if !thick}
<path <path
d={pathString} d={pathString}
style:--data-line-width="2px" style:--data-line-width={"2px"}
style:--data-color={`var(--color-data-${dataType.toLowerCase()})`} style:--data-color={`var(--color-data-${dataType.toLowerCase()})`}
style:--data-color-dim={`var(--color-data-${dataType.toLowerCase()}-dim)`} style:--data-color-dim={`var(--color-data-${dataType.toLowerCase()}-dim)`}
style:--data-dasharray={`3,${dashed ? 2 : 0}`} style:--data-dasharray={`3,${dashed ? 2 : 0}`}
@@ -738,8 +742,32 @@
style:height={`${Math.abs($nodeGraph.box.startY - $nodeGraph.box.endY)}px`} style:height={`${Math.abs($nodeGraph.box.startY - $nodeGraph.box.endY)}px`}
></div> ></div>
{/if} {/if}
</div>
<style lang="scss" global> <style lang="scss" global>
.graph-view {
pointer-events: none;
transition: opacity 0.2s;
opacity: 0;
&.open {
cursor: auto;
pointer-events: auto;
opacity: 1;
}
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--color-2-mildblack);
opacity: var(--fade-artwork);
pointer-events: none;
}
}
.graph { .graph {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
@@ -759,6 +787,7 @@
background-repeat: repeat; background-repeat: repeat;
image-rendering: pixelated; image-rendering: pixelated;
mix-blend-mode: screen; mix-blend-mode: screen;
opacity: var(--fade-artwork);
} }
> img { > img {
+6 -7
View File
@@ -77,9 +77,13 @@ export class UpdateLayerWidths extends JsMessage {
readonly layerWidths!: Map<bigint, number>; readonly layerWidths!: Map<bigint, number>;
} }
export class UpdateNodeGraphNodes extends JsMessage { export class UpdateNodeGraphRender extends JsMessage {
readonly nodesToRender!: FrontendNodeToRender[]; readonly nodesToRender!: FrontendNodeToRender[];
readonly open!: boolean;
readonly opacity!: number;
readonly inSelectedNetwork!: boolean; readonly inSelectedNetwork!: boolean;
readonly previewedNode!: bigint | undefined; readonly previewedNode!: bigint | undefined;
@@ -730,10 +734,6 @@ export class UpdateGraphViewOverlay extends JsMessage {
open!: boolean; open!: boolean;
} }
export class UpdateGraphFadeArtwork extends JsMessage {
readonly percentage!: number;
}
export class UpdateDataPanelState extends JsMessage { export class UpdateDataPanelState extends JsMessage {
readonly open!: boolean; readonly open!: boolean;
} }
@@ -1691,7 +1691,6 @@ export const messageMakers: Record<string, MessageMaker> = {
UpdateDocumentScrollbars, UpdateDocumentScrollbars,
UpdateExportReorderIndex, UpdateExportReorderIndex,
UpdateEyedropperSamplingState, UpdateEyedropperSamplingState,
UpdateGraphFadeArtwork,
UpdateGraphViewOverlay, UpdateGraphViewOverlay,
UpdateImportReorderIndex, UpdateImportReorderIndex,
UpdateImportsExports, UpdateImportsExports,
@@ -1704,7 +1703,7 @@ export const messageMakers: Record<string, MessageMaker> = {
UpdateMenuBarLayout, UpdateMenuBarLayout,
UpdateMouseCursor, UpdateMouseCursor,
UpdateNodeGraphControlBarLayout, UpdateNodeGraphControlBarLayout,
UpdateNodeGraphNodes, UpdateNodeGraphRender,
UpdateNodeGraphTransform, UpdateNodeGraphTransform,
UpdateNodeGraphWires, UpdateNodeGraphWires,
UpdateNodeThumbnail, UpdateNodeThumbnail,
-9
View File
@@ -13,7 +13,6 @@ import {
UpdateWorkingColorsLayout, UpdateWorkingColorsLayout,
UpdateNodeGraphControlBarLayout, UpdateNodeGraphControlBarLayout,
UpdateGraphViewOverlay, UpdateGraphViewOverlay,
UpdateGraphFadeArtwork,
} from "@graphite/messages"; } from "@graphite/messages";
export function createDocumentState(editor: Editor) { export function createDocumentState(editor: Editor) {
@@ -25,19 +24,11 @@ export function createDocumentState(editor: Editor) {
toolShelfLayout: defaultWidgetLayout(), toolShelfLayout: defaultWidgetLayout(),
workingColorsLayout: defaultWidgetLayout(), workingColorsLayout: defaultWidgetLayout(),
nodeGraphControlBarLayout: defaultWidgetLayout(), nodeGraphControlBarLayout: defaultWidgetLayout(),
// Graph view overlay
graphViewOverlayOpen: false, graphViewOverlayOpen: false,
fadeArtwork: 100,
}); });
const { subscribe, update } = state; const { subscribe, update } = state;
// Update layouts // Update layouts
editor.subscriptions.subscribeJsMessage(UpdateGraphFadeArtwork, (updateGraphFadeArtwork) => {
update((state) => {
state.fadeArtwork = updateGraphFadeArtwork.percentage;
return state;
});
});
editor.subscriptions.subscribeJsMessage(UpdateDocumentModeLayout, async (updateDocumentModeLayout) => { editor.subscriptions.subscribeJsMessage(UpdateDocumentModeLayout, async (updateDocumentModeLayout) => {
await tick(); await tick();
+10 -5
View File
@@ -17,7 +17,7 @@ import {
UpdateExportReorderIndex, UpdateExportReorderIndex,
UpdateImportsExports, UpdateImportsExports,
UpdateLayerWidths, UpdateLayerWidths,
UpdateNodeGraphNodes, UpdateNodeGraphRender,
UpdateVisibleNodes, UpdateVisibleNodes,
UpdateNodeGraphWires, UpdateNodeGraphWires,
UpdateNodeGraphTransform, UpdateNodeGraphTransform,
@@ -33,6 +33,9 @@ export function createNodeGraphState(editor: Editor) {
layerWidths: new Map<bigint, number>(), layerWidths: new Map<bigint, number>(),
updateImportsExports: undefined as UpdateImportsExports | undefined, updateImportsExports: undefined as UpdateImportsExports | undefined,
nodesToRender: new Map<bigint, FrontendNodeToRender>(), nodesToRender: new Map<bigint, FrontendNodeToRender>(),
open: false,
opacity: 0.8,
visibleNodes: new Set<bigint>(), visibleNodes: new Set<bigint>(),
/// The index is the exposed input index. The exports have a first key value of u32::MAX. /// The index is the exposed input index. The exports have a first key value of u32::MAX.
wires: new Map<bigint, Map<number, WirePath>>(), wires: new Map<bigint, Map<number, WirePath>>(),
@@ -98,14 +101,16 @@ export function createNodeGraphState(editor: Editor) {
return state; return state;
}); });
}); });
editor.subscriptions.subscribeJsMessage(UpdateNodeGraphNodes, (updateNodeGraphNodes) => { editor.subscriptions.subscribeJsMessage(UpdateNodeGraphRender, (updateNodeGraphRender) => {
update((state) => { update((state) => {
state.nodesToRender.clear(); state.nodesToRender.clear();
updateNodeGraphNodes.nodesToRender.forEach((node) => { updateNodeGraphRender.nodesToRender.forEach((node) => {
state.nodesToRender.set(node.metadata.nodeId, node); state.nodesToRender.set(node.metadata.nodeId, node);
}); });
state.inSelectedNetwork = updateNodeGraphNodes.inSelectedNetwork; state.open = updateNodeGraphRender.open;
state.previewedNode = updateNodeGraphNodes.previewedNode; state.opacity = updateNodeGraphRender.opacity;
state.inSelectedNetwork = updateNodeGraphRender.inSelectedNetwork;
state.previewedNode = updateNodeGraphRender.previewedNode;
return state; return state;
}); });
}); });