mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +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 currently_is_node = !network_interface.is_layer(&node_id, selection_network_path);
|
||||
ContextMenuData::ToggleLayer { node_id, currently_is_node }
|
||||
let currently_is_node = !network_interface.is_layer(&node_id, breadcrumb_network_path);
|
||||
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 {
|
||||
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> {
|
||||
let error = network_interface
|
||||
let graph_error = network_interface
|
||||
.resolved_types
|
||||
.node_graph_errors
|
||||
.iter()
|
||||
.filter(|error| error.node_path.starts_with(breadcrumb_network_path) && error.node_path.len() > breadcrumb_network_path.len())
|
||||
.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)?;
|
||||
// Convert to graph space
|
||||
position *= 24;
|
||||
if network_interface.is_layer(&error_node, breadcrumb_network_path) {
|
||||
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 })
|
||||
}
|
||||
|
||||
|
||||
@@ -153,16 +153,18 @@ pub struct BoxSelection {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, specta::Type)]
|
||||
#[serde(tag = "type", content = "data")]
|
||||
pub enum ContextMenuData {
|
||||
ToggleLayer {
|
||||
#[serde(rename = "nodeId")]
|
||||
node_id: NodeId,
|
||||
ModifyNode {
|
||||
#[serde(rename = "canBeLayer")]
|
||||
can_be_layer: bool,
|
||||
#[serde(rename = "currentlyIsNode")]
|
||||
currently_is_node: bool,
|
||||
#[serde(rename = "nodeId")]
|
||||
node_id: NodeId,
|
||||
},
|
||||
CreateNode {
|
||||
#[serde(rename = "compatibleType")]
|
||||
#[serde(default)]
|
||||
compatible_type: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -27,9 +27,6 @@
|
||||
|
||||
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);
|
||||
$: gridDotRadius = 1 + Math.floor($nodeGraph.transform.scale - 0.5 + 0.001) / 2;
|
||||
|
||||
@@ -115,15 +112,6 @@
|
||||
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) {
|
||||
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(" ")}`;
|
||||
}
|
||||
|
||||
function dataTypeTooltip(value: FrontendGraphInput | FrontendGraphOutput): string {
|
||||
return `Data Type: ${value.resolvedType}`;
|
||||
}
|
||||
// function dataTypeTooltip(value: FrontendGraphInput | FrontendGraphOutput): string {
|
||||
// return `Data Type: ${value.resolvedType}`;
|
||||
// }
|
||||
|
||||
// function validTypesText(value: FrontendGraphInput): string {
|
||||
// const validTypes = value.validTypes.length > 0 ? value.validTypes.map((x) => `• ${x}`).join("\n") : "None";
|
||||
// return `Valid Types:\n${validTypes}`;
|
||||
// }
|
||||
|
||||
function outputConnectedToText(output: FrontendGraphOutput): string {
|
||||
if (output.connectedTo.length === 0) return "Connected to nothing";
|
||||
// function outputConnectedToText(output: FrontendGraphOutput): string {
|
||||
// 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 {
|
||||
return `Connected to:\n${input.connectedTo}`;
|
||||
}
|
||||
// function inputConnectedToText(input: FrontendGraphInput): string {
|
||||
// return `Connected to:\n${input.connectedTo}`;
|
||||
// }
|
||||
|
||||
function zipWithUndefined(arr1: FrontendGraphInput[], arr2: FrontendGraphOutput[]) {
|
||||
const maxLength = Math.max(arr1.length, arr2.length);
|
||||
@@ -224,29 +212,26 @@
|
||||
top: `${$nodeGraph.contextMenuInformation.contextMenuCoordinates.y * $nodeGraph.transform.scale + $nodeGraph.transform.y}px`,
|
||||
}}
|
||||
>
|
||||
{#if typeof $nodeGraph.contextMenuInformation.contextMenuData === "string" && $nodeGraph.contextMenuInformation.contextMenuData === "CreateNode"}
|
||||
<NodeCatalog on:selectNodeType={(e) => createNode(e.detail)} />
|
||||
{:else if $nodeGraph.contextMenuInformation.contextMenuData && "compatibleType" in $nodeGraph.contextMenuInformation.contextMenuData}
|
||||
<NodeCatalog initialSearchTerm={$nodeGraph.contextMenuInformation.contextMenuData.compatibleType || ""} on:selectNodeType={(e) => createNode(e.detail)} />
|
||||
{:else}
|
||||
{@const contextMenuData = $nodeGraph.contextMenuInformation.contextMenuData}
|
||||
{#if $nodeGraph.contextMenuInformation.contextMenuData.type == "CreateNode"}
|
||||
<NodeCatalog initialSearchTerm={$nodeGraph.contextMenuInformation.contextMenuData.data.compatibleType || ""} on:selectNodeType={(e) => createNode(e.detail)} />
|
||||
{:else if $nodeGraph.contextMenuInformation.contextMenuData.type == "ModifyNode"}
|
||||
<LayoutRow class="toggle-layer-or-node">
|
||||
<TextLabel>Display as</TextLabel>
|
||||
<RadioInput
|
||||
selectedIndex={contextMenuData.currentlyIsNode ? 0 : 1}
|
||||
selectedIndex={$nodeGraph.contextMenuInformation.contextMenuData.data.currentlyIsNode ? 0 : 1}
|
||||
entries={[
|
||||
{
|
||||
value: "node",
|
||||
label: "Node",
|
||||
action: () => toggleLayerDisplay(false, contextMenuData.nodeId),
|
||||
action: () => editor.handle.setToNodeOrLayer($nodeGraph.contextMenuInformation.contextMenuData.data.nodeId, false),
|
||||
},
|
||||
{
|
||||
value: "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>
|
||||
<Separator type="Section" direction="Vertical" />
|
||||
@@ -264,7 +249,6 @@
|
||||
style={`left: ${$nodeGraph.error.position.x}px;
|
||||
top: ${$nodeGraph.error.position.y}px;`}
|
||||
transition:fade={FADE_TRANSITION}
|
||||
title=""
|
||||
data-node-error>{$nodeGraph.error.error}</span
|
||||
>
|
||||
<span
|
||||
@@ -272,7 +256,6 @@
|
||||
style={`left: ${$nodeGraph.error.position.x}px;
|
||||
top: ${$nodeGraph.error.position.y}px;`}
|
||||
transition:fade={FADE_TRANSITION}
|
||||
title=""
|
||||
data-node-error>{$nodeGraph.error.error}</span
|
||||
>
|
||||
</div>
|
||||
@@ -338,7 +321,6 @@
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.importPosition.x - 8) / 24}
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.importPosition.y - 8) / 24 + index}
|
||||
>
|
||||
<title>{`${dataTypeTooltip(frontendOutput)}\n\n${outputConnectedToText(frontendOutput)}`}</title>
|
||||
{#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)" />
|
||||
{:else}
|
||||
@@ -382,7 +364,7 @@
|
||||
}}
|
||||
/>
|
||||
{#if index > 0}
|
||||
<div class="reorder-drag-grip" title="Reorder this export" />
|
||||
<div class="reorder-drag-grip" />
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
@@ -410,7 +392,6 @@
|
||||
style:--offset-left={($nodeGraph.updateImportsExports.exportPosition.x - 8) / 24}
|
||||
style:--offset-top={($nodeGraph.updateImportsExports.exportPosition.y - 8) / 24 + index}
|
||||
>
|
||||
<title>{`${dataTypeTooltip(frontendInput)}\n\n${inputConnectedToText(frontendInput)}`}</title>
|
||||
{#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)" />
|
||||
{:else}
|
||||
@@ -428,7 +409,7 @@
|
||||
>
|
||||
{#if (hoveringExportIndex === index || editingNameExportIndex === index) && $nodeGraph.updateImportsExports.addImportExport}
|
||||
{#if index > 0}
|
||||
<div class="reorder-drag-grip" title="Reorder this export" />
|
||||
<div class="reorder-drag-grip" />
|
||||
{/if}
|
||||
<IconButton
|
||||
size={16}
|
||||
|
||||
@@ -33,20 +33,7 @@ export class UpdateClickTargets extends JsMessage {
|
||||
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 {
|
||||
@ContextTupleToVec2
|
||||
readonly contextMenuInformation!: ContextMenuInformation | undefined;
|
||||
}
|
||||
|
||||
@@ -183,7 +170,7 @@ export type FrontendClickTargets = {
|
||||
|
||||
export type ContextMenuInformation = {
|
||||
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";
|
||||
|
||||
Reference in New Issue
Block a user