mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-07 04:48:11 +08:00
Improve context menu data
This commit is contained in:
@@ -776,8 +776,13 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
|
|||||||
}
|
}
|
||||||
|
|
||||||
let context_menu_data = if let Some(node_id) = clicked_id {
|
let context_menu_data = if let Some(node_id) = clicked_id {
|
||||||
let currently_is_node = !network_interface.is_layer(&node_id, selection_network_path);
|
let currently_is_node = !network_interface.is_layer(&node_id, breadcrumb_network_path);
|
||||||
ContextMenuData::ToggleLayer { node_id, currently_is_node }
|
let can_be_layer = network_interface.is_eligible_to_be_layer(&node_id, breadcrumb_network_path);
|
||||||
|
ContextMenuData::ModifyNode {
|
||||||
|
can_be_layer,
|
||||||
|
currently_is_node,
|
||||||
|
node_id,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ContextMenuData::CreateNode { compatible_type: None }
|
ContextMenuData::CreateNode { compatible_type: None }
|
||||||
};
|
};
|
||||||
@@ -2594,24 +2599,24 @@ impl NodeGraphMessageHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn node_graph_error(&self, network_interface: &mut NodeNetworkInterface, breadcrumb_network_path: &[NodeId]) -> Option<NodeGraphError> {
|
fn node_graph_error(&self, network_interface: &mut NodeNetworkInterface, breadcrumb_network_path: &[NodeId]) -> Option<NodeGraphError> {
|
||||||
let error = network_interface
|
let graph_error = network_interface
|
||||||
.resolved_types
|
.resolved_types
|
||||||
.node_graph_errors
|
.node_graph_errors
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|error| error.node_path.starts_with(breadcrumb_network_path) && error.node_path.len() > breadcrumb_network_path.len())
|
.filter(|error| error.node_path.starts_with(breadcrumb_network_path) && error.node_path.len() > breadcrumb_network_path.len())
|
||||||
.next()?;
|
.next()?;
|
||||||
let error_node = error.node_path[breadcrumb_network_path.len()];
|
let error = if graph_error.node_path.len() == breadcrumb_network_path.len() + 1 {
|
||||||
|
format!("{:?}", graph_error.error)
|
||||||
|
} else {
|
||||||
|
"Node graph type error within this node".to_string()
|
||||||
|
};
|
||||||
|
let error_node = graph_error.node_path[breadcrumb_network_path.len()];
|
||||||
let mut position = network_interface.position(&error_node, breadcrumb_network_path)?;
|
let mut position = network_interface.position(&error_node, breadcrumb_network_path)?;
|
||||||
// Convert to graph space
|
// Convert to graph space
|
||||||
position *= 24;
|
position *= 24;
|
||||||
if network_interface.is_layer(&error_node, breadcrumb_network_path) {
|
if network_interface.is_layer(&error_node, breadcrumb_network_path) {
|
||||||
position += IVec2::new(12, -12)
|
position += IVec2::new(12, -12)
|
||||||
}
|
}
|
||||||
let error = if error.node_path.len() == breadcrumb_network_path.len() + 1 {
|
|
||||||
format!("{:?}", error.error)
|
|
||||||
} else {
|
|
||||||
"Node graph type error within this node".to_string()
|
|
||||||
};
|
|
||||||
Some(NodeGraphError { position: position.into(), error })
|
Some(NodeGraphError { position: position.into(), error })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,16 +153,18 @@ pub struct BoxSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||||
|
#[serde(tag = "type", content = "data")]
|
||||||
pub enum ContextMenuData {
|
pub enum ContextMenuData {
|
||||||
ToggleLayer {
|
ModifyNode {
|
||||||
#[serde(rename = "nodeId")]
|
#[serde(rename = "canBeLayer")]
|
||||||
node_id: NodeId,
|
can_be_layer: bool,
|
||||||
#[serde(rename = "currentlyIsNode")]
|
#[serde(rename = "currentlyIsNode")]
|
||||||
currently_is_node: bool,
|
currently_is_node: bool,
|
||||||
|
#[serde(rename = "nodeId")]
|
||||||
|
node_id: NodeId,
|
||||||
},
|
},
|
||||||
CreateNode {
|
CreateNode {
|
||||||
#[serde(rename = "compatibleType")]
|
#[serde(rename = "compatibleType")]
|
||||||
#[serde(default)]
|
|
||||||
compatible_type: Option<String>,
|
compatible_type: Option<String>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,6 @@
|
|||||||
|
|
||||||
let graph: HTMLDivElement | undefined;
|
let graph: HTMLDivElement | undefined;
|
||||||
|
|
||||||
// Key value is node id + input/output index
|
|
||||||
// Imports/Export are stored at a key value of 0
|
|
||||||
|
|
||||||
$: gridSpacing = calculateGridSpacing($nodeGraph.transform.scale);
|
$: gridSpacing = calculateGridSpacing($nodeGraph.transform.scale);
|
||||||
$: gridDotRadius = 1 + Math.floor($nodeGraph.transform.scale - 0.5 + 0.001) / 2;
|
$: gridDotRadius = 1 + Math.floor($nodeGraph.transform.scale - 0.5 + 0.001) / 2;
|
||||||
|
|
||||||
@@ -115,15 +112,6 @@
|
|||||||
return iconMap[icon] || "NodeNodes";
|
return iconMap[icon] || "NodeNodes";
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleLayerDisplay(displayAsLayer: boolean, toggleId: bigint) {
|
|
||||||
let node = $nodeGraph.nodes.get(toggleId);
|
|
||||||
if (node) editor.handle.setToNodeOrLayer(node.id, displayAsLayer);
|
|
||||||
}
|
|
||||||
|
|
||||||
function canBeToggledBetweenNodeAndLayer(toggleDisplayAsLayerNodeId: bigint) {
|
|
||||||
return $nodeGraph.nodes.get(toggleDisplayAsLayerNodeId)?.canBeLayer || false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createNode(nodeType: string) {
|
function createNode(nodeType: string) {
|
||||||
if ($nodeGraph.contextMenuInformation === undefined) return;
|
if ($nodeGraph.contextMenuInformation === undefined) return;
|
||||||
|
|
||||||
@@ -176,24 +164,24 @@
|
|||||||
return `M-2,-2 L${nodeWidth + 2},-2 L${nodeWidth + 2},${nodeHeight + 2} L-2,${nodeHeight + 2}z ${rectangles.join(" ")}`;
|
return `M-2,-2 L${nodeWidth + 2},-2 L${nodeWidth + 2},${nodeHeight + 2} L-2,${nodeHeight + 2}z ${rectangles.join(" ")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dataTypeTooltip(value: FrontendGraphInput | FrontendGraphOutput): string {
|
// function dataTypeTooltip(value: FrontendGraphInput | FrontendGraphOutput): string {
|
||||||
return `Data Type: ${value.resolvedType}`;
|
// return `Data Type: ${value.resolvedType}`;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// function validTypesText(value: FrontendGraphInput): string {
|
// function validTypesText(value: FrontendGraphInput): string {
|
||||||
// const validTypes = value.validTypes.length > 0 ? value.validTypes.map((x) => `• ${x}`).join("\n") : "None";
|
// const validTypes = value.validTypes.length > 0 ? value.validTypes.map((x) => `• ${x}`).join("\n") : "None";
|
||||||
// return `Valid Types:\n${validTypes}`;
|
// return `Valid Types:\n${validTypes}`;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
function outputConnectedToText(output: FrontendGraphOutput): string {
|
// function outputConnectedToText(output: FrontendGraphOutput): string {
|
||||||
if (output.connectedTo.length === 0) return "Connected to nothing";
|
// if (output.connectedTo.length === 0) return "Connected to nothing";
|
||||||
|
|
||||||
return `Connected to:\n${output.connectedTo.join("\n")}`;
|
// return `Connected to:\n${output.connectedTo.join("\n")}`;
|
||||||
}
|
// }
|
||||||
|
|
||||||
function inputConnectedToText(input: FrontendGraphInput): string {
|
// function inputConnectedToText(input: FrontendGraphInput): string {
|
||||||
return `Connected to:\n${input.connectedTo}`;
|
// return `Connected to:\n${input.connectedTo}`;
|
||||||
}
|
// }
|
||||||
|
|
||||||
function zipWithUndefined(arr1: FrontendGraphInput[], arr2: FrontendGraphOutput[]) {
|
function zipWithUndefined(arr1: FrontendGraphInput[], arr2: FrontendGraphOutput[]) {
|
||||||
const maxLength = Math.max(arr1.length, arr2.length);
|
const maxLength = Math.max(arr1.length, arr2.length);
|
||||||
@@ -224,29 +212,26 @@
|
|||||||
top: `${$nodeGraph.contextMenuInformation.contextMenuCoordinates.y * $nodeGraph.transform.scale + $nodeGraph.transform.y}px`,
|
top: `${$nodeGraph.contextMenuInformation.contextMenuCoordinates.y * $nodeGraph.transform.scale + $nodeGraph.transform.y}px`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{#if typeof $nodeGraph.contextMenuInformation.contextMenuData === "string" && $nodeGraph.contextMenuInformation.contextMenuData === "CreateNode"}
|
{#if $nodeGraph.contextMenuInformation.contextMenuData.type == "CreateNode"}
|
||||||
<NodeCatalog on:selectNodeType={(e) => createNode(e.detail)} />
|
<NodeCatalog initialSearchTerm={$nodeGraph.contextMenuInformation.contextMenuData.data.compatibleType || ""} on:selectNodeType={(e) => createNode(e.detail)} />
|
||||||
{:else if $nodeGraph.contextMenuInformation.contextMenuData && "compatibleType" in $nodeGraph.contextMenuInformation.contextMenuData}
|
{:else if $nodeGraph.contextMenuInformation.contextMenuData.type == "ModifyNode"}
|
||||||
<NodeCatalog initialSearchTerm={$nodeGraph.contextMenuInformation.contextMenuData.compatibleType || ""} on:selectNodeType={(e) => createNode(e.detail)} />
|
|
||||||
{:else}
|
|
||||||
{@const contextMenuData = $nodeGraph.contextMenuInformation.contextMenuData}
|
|
||||||
<LayoutRow class="toggle-layer-or-node">
|
<LayoutRow class="toggle-layer-or-node">
|
||||||
<TextLabel>Display as</TextLabel>
|
<TextLabel>Display as</TextLabel>
|
||||||
<RadioInput
|
<RadioInput
|
||||||
selectedIndex={contextMenuData.currentlyIsNode ? 0 : 1}
|
selectedIndex={$nodeGraph.contextMenuInformation.contextMenuData.data.currentlyIsNode ? 0 : 1}
|
||||||
entries={[
|
entries={[
|
||||||
{
|
{
|
||||||
value: "node",
|
value: "node",
|
||||||
label: "Node",
|
label: "Node",
|
||||||
action: () => toggleLayerDisplay(false, contextMenuData.nodeId),
|
action: () => editor.handle.setToNodeOrLayer($nodeGraph.contextMenuInformation.contextMenuData.data.nodeId, false),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "layer",
|
value: "layer",
|
||||||
label: "Layer",
|
label: "Layer",
|
||||||
action: () => toggleLayerDisplay(true, contextMenuData.nodeId),
|
action: () => editor.handle.setToNodeOrLayer($nodeGraph.contextMenuInformation.contextMenuData.data.nodeId, true),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
disabled={!canBeToggledBetweenNodeAndLayer(contextMenuData.nodeId)}
|
disabled={!$nodeGraph.contextMenuInformation.contextMenuData.data.canBeLayer}
|
||||||
/>
|
/>
|
||||||
</LayoutRow>
|
</LayoutRow>
|
||||||
<Separator type="Section" direction="Vertical" />
|
<Separator type="Section" direction="Vertical" />
|
||||||
@@ -264,7 +249,6 @@
|
|||||||
style={`left: ${$nodeGraph.error.position.x}px;
|
style={`left: ${$nodeGraph.error.position.x}px;
|
||||||
top: ${$nodeGraph.error.position.y}px;`}
|
top: ${$nodeGraph.error.position.y}px;`}
|
||||||
transition:fade={FADE_TRANSITION}
|
transition:fade={FADE_TRANSITION}
|
||||||
title=""
|
|
||||||
data-node-error>{$nodeGraph.error.error}</span
|
data-node-error>{$nodeGraph.error.error}</span
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
@@ -272,7 +256,6 @@
|
|||||||
style={`left: ${$nodeGraph.error.position.x}px;
|
style={`left: ${$nodeGraph.error.position.x}px;
|
||||||
top: ${$nodeGraph.error.position.y}px;`}
|
top: ${$nodeGraph.error.position.y}px;`}
|
||||||
transition:fade={FADE_TRANSITION}
|
transition:fade={FADE_TRANSITION}
|
||||||
title=""
|
|
||||||
data-node-error>{$nodeGraph.error.error}</span
|
data-node-error>{$nodeGraph.error.error}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -338,7 +321,6 @@
|
|||||||
style:--offset-left={($nodeGraph.updateImportsExports.importPosition.x - 8) / 24}
|
style:--offset-left={($nodeGraph.updateImportsExports.importPosition.x - 8) / 24}
|
||||||
style:--offset-top={($nodeGraph.updateImportsExports.importPosition.y - 8) / 24 + index}
|
style:--offset-top={($nodeGraph.updateImportsExports.importPosition.y - 8) / 24 + index}
|
||||||
>
|
>
|
||||||
<title>{`${dataTypeTooltip(frontendOutput)}\n\n${outputConnectedToText(frontendOutput)}`}</title>
|
|
||||||
{#if frontendOutput.connectedTo.length > 0}
|
{#if frontendOutput.connectedTo.length > 0}
|
||||||
<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)" />
|
<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)" />
|
||||||
{:else}
|
{:else}
|
||||||
@@ -382,7 +364,7 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{#if index > 0}
|
{#if index > 0}
|
||||||
<div class="reorder-drag-grip" title="Reorder this export" />
|
<div class="reorder-drag-grip" />
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -410,7 +392,6 @@
|
|||||||
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 8) / 24}
|
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 8) / 24}
|
||||||
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition.y - 8) / 24 + index}
|
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition.y - 8) / 24 + index}
|
||||||
>
|
>
|
||||||
<title>{`${dataTypeTooltip(frontendInput)}\n\n${inputConnectedToText(frontendInput)}`}</title>
|
|
||||||
{#if frontendInput.connectedTo !== "nothing"}
|
{#if frontendInput.connectedTo !== "nothing"}
|
||||||
<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)" />
|
<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)" />
|
||||||
{:else}
|
{:else}
|
||||||
@@ -428,7 +409,7 @@
|
|||||||
>
|
>
|
||||||
{#if (hoveringExportIndex === index || editingNameExportIndex === index) && $nodeGraph.updateImportsExports.addImportExport}
|
{#if (hoveringExportIndex === index || editingNameExportIndex === index) && $nodeGraph.updateImportsExports.addImportExport}
|
||||||
{#if index > 0}
|
{#if index > 0}
|
||||||
<div class="reorder-drag-grip" title="Reorder this export" />
|
<div class="reorder-drag-grip" />
|
||||||
{/if}
|
{/if}
|
||||||
<IconButton
|
<IconButton
|
||||||
size={16}
|
size={16}
|
||||||
|
|||||||
@@ -33,20 +33,7 @@ export class UpdateClickTargets extends JsMessage {
|
|||||||
readonly clickTargets!: FrontendClickTargets | undefined;
|
readonly clickTargets!: FrontendClickTargets | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ContextTupleToVec2 = Transform((data) => {
|
|
||||||
if (data.obj.contextMenuInformation === undefined) return undefined;
|
|
||||||
const contextMenuCoordinates = data.obj.contextMenuInformation.contextMenuCoordinates;
|
|
||||||
let contextMenuData = data.obj.contextMenuInformation.contextMenuData;
|
|
||||||
if (contextMenuData.ToggleLayer !== undefined) {
|
|
||||||
contextMenuData = { nodeId: contextMenuData.ToggleLayer.nodeId, currentlyIsNode: contextMenuData.ToggleLayer.currentlyIsNode };
|
|
||||||
} else if (contextMenuData.CreateNode !== undefined) {
|
|
||||||
contextMenuData = { type: "CreateNode", compatibleType: contextMenuData.CreateNode.compatibleType };
|
|
||||||
}
|
|
||||||
return { contextMenuCoordinates, contextMenuData };
|
|
||||||
});
|
|
||||||
|
|
||||||
export class UpdateContextMenuInformation extends JsMessage {
|
export class UpdateContextMenuInformation extends JsMessage {
|
||||||
@ContextTupleToVec2
|
|
||||||
readonly contextMenuInformation!: ContextMenuInformation | undefined;
|
readonly contextMenuInformation!: ContextMenuInformation | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +170,7 @@ export type FrontendClickTargets = {
|
|||||||
|
|
||||||
export type ContextMenuInformation = {
|
export type ContextMenuInformation = {
|
||||||
contextMenuCoordinates: XY;
|
contextMenuCoordinates: XY;
|
||||||
contextMenuData: "CreateNode" | { type: "CreateNode"; compatibleType: string } | { nodeId: bigint; currentlyIsNode: boolean };
|
contextMenuData: { type: "CreateNode"; data: { compatibleType: string | undefined } } | { type: "ModifyNode"; data: { canBeLayer: boolean; currentlyIsNode: boolean; nodeId: bigint } };
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FrontendGraphDataType = "General" | "Number" | "Artboard" | "Graphic" | "Raster" | "Vector" | "Color" | "Invalid";
|
export type FrontendGraphDataType = "General" | "Number" | "Artboard" | "Graphic" | "Raster" | "Vector" | "Color" | "Invalid";
|
||||||
|
|||||||
Reference in New Issue
Block a user