Skip to content

Commit

Permalink
DYN-8334 Node Cluster Visual Preparation Work (#15865)
Browse files Browse the repository at this point in the history
  • Loading branch information
QilongTang authored Mar 3, 2025
1 parent 91bca1d commit 9bf521e
Show file tree
Hide file tree
Showing 17 changed files with 161 additions and 41 deletions.
11 changes: 11 additions & 0 deletions src/DynamoCore/Graph/Nodes/NodeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,17 @@ public bool IsFrozen
}
}

/// <summary>
/// A flag indicating whether the node is in transient mode.
/// When a node is in transient mode, the node will not participate in execution,
/// Or saved to the graph. It is only used for previewing the AutoComplete result in the canvas.
/// </summary>
internal bool IsTransient
{
get;
set;
}

/// <summary>
/// The default behavior for ModelBase objects is to not serialize the X and Y
/// properties. This overload allows the serialization of the X property
Expand Down
4 changes: 2 additions & 2 deletions src/DynamoCore/Graph/Workspaces/SerializationConverters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -862,9 +862,9 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
.Select(outputNode => outputNode.OutputData).ToList();
serializer.Serialize(writer, outputNodeDatas);

// Nodes
// Nodes except for nodes in Transient state
writer.WritePropertyName("Nodes");
serializer.Serialize(writer, ws.Nodes);
serializer.Serialize(writer, ws.Nodes.Where(x => x.IsTransient != true));

// Connectors
writer.WritePropertyName("Connectors");
Expand Down
6 changes: 3 additions & 3 deletions src/DynamoCore/Scheduler/UpdateGraphAsyncTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ protected override TaskMergeInstruction CanMergeWithCore(AsyncTask otherTask)
private static IEnumerable<NodeModel> ComputeModifiedNodes(WorkspaceModel workspace)
{
var nodesToUpdate = new List<NodeModel>();
//Get those modified nodes that are not frozen
foreach (var node in workspace.Nodes.Where(n => n.IsModified && !n.IsFrozen))
//Get those modified nodes that are not frozen or transient states
foreach (var node in workspace.Nodes.Where(n => n.IsModified && !n.IsFrozen && !n.IsTransient))
{
GetDownstreamNodes(node, nodesToUpdate);
}
Expand All @@ -273,7 +273,7 @@ private static IEnumerable<NodeModel> ComputeModifiedNodes(WorkspaceModel worksp
///
private static void GetDownstreamNodes(NodeModel node, ICollection<NodeModel> gathered)
{
if (gathered.Contains(node) || node.IsFrozen) // Considered this node before, bail.pu
if (gathered.Contains(node) || node.IsFrozen || node.IsTransient) // Considered this node before, bail.pu
return;

gathered.Add(node);
Expand Down
6 changes: 5 additions & 1 deletion src/DynamoCoreWpf/DynamoCoreWpf.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@
<None Remove="UI\Images\help-16px.png" />
<None Remove="UI\Images\info_48px.png" />
<None Remove="UI\Images\menu_white_48px.png" />
<None Remove="UI\Images\NodeStates\package-64px.png" />
<None Remove="UI\Images\PackageManager\empty-state-first-use-light-gray.png" />
<None Remove="UI\Images\search_icon_20px.png" />
<None Remove="UI\Images\TitleBarButtons\close-darktheme-disabled-16px.png" />
Expand Down Expand Up @@ -161,6 +160,9 @@
<None Remove="UI\Images\NodeStates\frozen-64px.png" />
<None Remove="UI\Images\NodeStates\hidden-64px.png" />
<None Remove="UI\Images\NodeStates\info-64px.png" />
<None Remove="UI\Images\NodeStates\package-64px.png" />
<None Remove="UI\Images\NodeStates\transient-64px.png" />
<None Remove="UI\Images\NodeStates\transient-light-64px.png" />
<None Remove="UI\Images\TitleBarButtons\close-darktheme-default-16px.png" />
<None Remove="UI\Images\TitleBarButtons\close-darktheme-hover-16px.png" />
<None Remove="UI\Images\TitleBarButtons\close-lighttheme-default-16px.png" />
Expand Down Expand Up @@ -1041,6 +1043,8 @@
<Resource Include="UI\Images\NodeStates\hidden-64px.png" />
<Resource Include="UI\Images\NodeStates\info-64px.png" />
<Resource Include="UI\Images\NodeStates\package-64px.png" />
<Resource Include="UI\Images\NodeStates\transient-64px.png" />
<Resource Include="UI\Images\NodeStates\transient-light-64px.png" />
<Resource Include="UI\Images\PackageManager\empty-state-first-use-light-gray.png" />
<Resource Include="UI\Images\question-hover-blue-16px.png" />
<Resource Include="UI\Images\search_icon_20px.png" />
Expand Down
2 changes: 2 additions & 0 deletions src/DynamoCoreWpf/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2435,6 +2435,8 @@ Dynamo.ViewModels.NodeViewModel.IsDisplayingLabels.set -> void
Dynamo.ViewModels.NodeViewModel.IsExperimental.get -> bool
Dynamo.ViewModels.NodeViewModel.IsFrozen.get -> bool
Dynamo.ViewModels.NodeViewModel.IsFrozen.set -> void
Dynamo.ViewModels.NodeViewModel.IsTransient.get -> bool
Dynamo.ViewModels.NodeViewModel.IsTransient.set -> void
Dynamo.ViewModels.NodeViewModel.IsFrozenExplicitly.get -> bool
Dynamo.ViewModels.NodeViewModel.IsInput.get -> bool
Dynamo.ViewModels.NodeViewModel.IsInteractionEnabled.get -> bool
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@

<!-- Nodes -->
<SolidColorBrush x:Key="NodeFrozenOverlayColor" Color="{StaticResource DarkBlue200}" />
<SolidColorBrush x:Key="NodeTransientOverlayColor" Color="#D5BCF7" />
<SolidColorBrush x:Key="NodeInfoColor" Color="{StaticResource Blue300}" />
<SolidColorBrush x:Key="NodeWarningColor" Color="{StaticResource YellowOrange500}" />
<SolidColorBrush x:Key="NodeErrorColor" Color="{StaticResource Red500}" />
Expand Down
2 changes: 1 addition & 1 deletion src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ internal bool IsDNAClusterPlacementEnabled
{
get
{
return DynamoModel.FeatureFlags?.CheckFeatureFlag("IsDNAClusterPlacementEnabled", false) ?? true;
return DynamoModel.FeatureFlags?.CheckFeatureFlag("IsDNAClusterPlacementEnabled", false) ?? false;
}
}

Expand Down
42 changes: 36 additions & 6 deletions src/DynamoCoreWpf/ViewModels/Core/NodeViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,8 @@ public bool NodeHoveringState
private static readonly string warningGlyph = "/DynamoCoreWpf;component/UI/Images/NodeStates/alert-64px.png";
private static readonly string errorGlyph = "/DynamoCoreWpf;component/UI/Images/NodeStates/error-64px.png";
private static readonly string infoGlyph = "/DynamoCoreWpf;component/UI/Images/NodeStates/info-64px.png";
private static readonly string previewGlyph = "/DynamoCoreWpf;component/UI/Images/NodeStates/hidden-64px.png";
private static readonly string previewGeometryGlyph = "/DynamoCoreWpf;component/UI/Images/NodeStates/hidden-64px.png";
private static readonly string previewClusterGlyph = "/DynamoCoreWpf;component/UI/Images/NodeStates/transient-light-64px.png";
private static readonly string frozenGlyph = "/DynamoCoreWpf;component/UI/Images/NodeStates/frozen-64px.png";
private static readonly string packageGlyph = "/DynamoCoreWpf;component/UI/Images/NodeStates/package-64px.png";

Expand Down Expand Up @@ -622,6 +623,16 @@ public bool IsFrozen
}
}

/// <summary>
/// Return a value indicating whether this node is in transient state.
/// </summary>
[JsonIgnore]
public bool IsTransient
{
set { NodeModel.IsTransient = value; }
get { return NodeModel.IsTransient; }
}

/// <summary>
/// A flag indicating whether the node is set to freeze by the user.
/// </summary>
Expand Down Expand Up @@ -1302,8 +1313,9 @@ private void BuildErrorBubble()
private static SolidColorBrush infoColor = (SolidColorBrush)(new BrushConverter().ConvertFrom("#6AC0E7"));
private static SolidColorBrush noPreviewColor = (SolidColorBrush)(new BrushConverter().ConvertFrom("#BBBBBB"));
private static SolidColorBrush nodeCustomColor = (SolidColorBrush)(new BrushConverter().ConvertFrom("#B385F2"));
private static SolidColorBrush nodePreviewColor = (SolidColorBrush)(new BrushConverter().ConvertFrom("#BBBBBB"));
private static SolidColorBrush nodePreviewGeometryColor = (SolidColorBrush)(new BrushConverter().ConvertFrom("#BBBBBB"));
private static SolidColorBrush nodeFrozenOverlayColor = (SolidColorBrush)(new BrushConverter().ConvertFrom("#BCD3EE"));
private static SolidColorBrush nodeTransientOverlayColor = (SolidColorBrush)(new BrushConverter().ConvertFrom("#D5BCF7"));
private static SolidColorBrush nodeInfoColor = (SolidColorBrush)(new BrushConverter().ConvertFrom("#6AC0E7"));

/// <summary>
Expand Down Expand Up @@ -1360,10 +1372,10 @@ Pass through all possible states in reverse order

if (!this.IsVisible)
{
result = nodePreviewColor;
result = nodePreviewGeometryColor;
if (result != null)
{
ImgGlyphOneSource = previewGlyph;
ImgGlyphOneSource = previewGeometryGlyph;
}
}

Expand All @@ -1379,7 +1391,7 @@ Pass through all possible states in reverse order
else
{
ImgGlyphOneSource = packageGlyph;
ImgGlyphTwoSource = previewGlyph;
ImgGlyphTwoSource = previewGeometryGlyph;
}
}
}
Expand All @@ -1396,10 +1408,28 @@ Pass through all possible states in reverse order
else
{
ImgGlyphOneSource = frozenGlyph;
ImgGlyphTwoSource = previewGlyph;
ImgGlyphTwoSource = previewGeometryGlyph;
}
}
}

if (this.IsTransient)
{
result = nodeTransientOverlayColor;
if (result != null)
{
if (ImgGlyphOneSource == null)
{
ImgGlyphOneSource = previewClusterGlyph;
}
else
{
ImgGlyphOneSource = previewClusterGlyph;
ImgGlyphTwoSource = previewGeometryGlyph;
}
}
}

if (NodeModel.State == ElementState.Info || NodeModel.State == ElementState.PersistentInfo)
{
result = nodeInfoColor;
Expand Down
36 changes: 33 additions & 3 deletions src/DynamoCoreWpf/ViewModels/Core/PortViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using Dynamo.Controls;
using Dynamo.Graph.Nodes;
using Dynamo.Models;
using Dynamo.Search.SearchElements;
using Dynamo.UI.Commands;
using Dynamo.Utilities;
Expand Down Expand Up @@ -495,6 +493,8 @@ private void AutoComplete(object parameter)
// Handler to invoke Node autocomplete cluster
private void AutoCompleteCluster(object parameter)
{
// Put a C# timer here to test the cluster placement mock
Stopwatch stopwatch = Stopwatch.StartNew();
var wsViewModel = node.WorkspaceViewModel;
wsViewModel.NodeAutoCompleteSearchViewModel.PortViewModel = this;

Expand All @@ -511,13 +511,43 @@ private void AutoCompleteCluster(object parameter)
{
return;
}

// Create mock nodes, currently Watch nodes (to avoid potential memory leak from Python Editor), and connect them to the input port
var targetNodeSearchEle = wsViewModel.NodeAutoCompleteSearchViewModel.DefaultResults.ToList()[5];
targetNodeSearchEle.CreateAndConnectCommand.Execute(wsViewModel.NodeAutoCompleteSearchViewModel.PortViewModel.PortModel);

var sizeOfMockCluster = 3;
var n = 1;
while (n < sizeOfMockCluster)
{
// Get the last node and connect a new node to it
var node1 = wsViewModel.Nodes.LastOrDefault();
node1.IsTransient = true;
targetNodeSearchEle.CreateAndConnectCommand.Execute(node1.InPorts.FirstOrDefault().PortModel);
n++;
}

wsViewModel.Nodes.LastOrDefault().IsTransient = true;

stopwatch.Stop(); // Stop the stopwatch
wsViewModel.DynamoViewModel.Model.Logger.Log($"Cluster Placement Execution Time: {stopwatch.ElapsedMilliseconds} ms");

// cluster info display in right side panel
if (wsViewModel.DynamoViewModel.IsDNAClusterPlacementEnabled)
{
try
{
MLNodeClusterAutoCompletionResponse results = wsViewModel.NodeAutoCompleteSearchViewModel.GetMLNodeClusterAutocompleteResults();
wsViewModel.OnRequestNodeAutoCompleteViewExtension(results);

// Process the results and display the preview of the cluster with the highest confidence level
// Leverage some API here to convert topology to actual cluster
results.Results.FirstOrDefault().Topology.Nodes.ToList().ForEach(node =>
{
// nothing for now
});

// Display the cluster info in the right side panel
// wsViewModel.OnRequestNodeAutoCompleteViewExtension(results);
}
catch (Exception e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,31 +399,41 @@ internal void ShowNodeAutocompleMLResults()
}
}

foreach (var result in results)
OrganizeConfidenceSection(results);
}
}

/// <summary>
/// Compare to low confidence threadhold defined by user can origanize the results into high and low confidence sections.
/// </summary>
/// <param name="results"></param>
internal void OrganizeConfidenceSection(List<NodeSearchElementViewModel> results)
{
foreach (var result in results)
{
if (result.AutoCompletionNodeMachineLearningInfo.ConfidenceScore >= dynamoViewModel.PreferenceSettings.MLRecommendationConfidenceLevel)
{
if (result.AutoCompletionNodeMachineLearningInfo.ConfidenceScore >= dynamoViewModel.PreferenceSettings.MLRecommendationConfidenceLevel)
{
FilteredHighConfidenceResults = FilteredHighConfidenceResults.Append(result);
}
else {
FilteredLowConfidenceResults = FilteredLowConfidenceResults.Append(result);
}
FilteredHighConfidenceResults = FilteredHighConfidenceResults.Append(result);
}

// Show low confidence section if there are some results under threshold and feature enabled
DisplayLowConfidence = FilteredLowConfidenceResults.Any() && dynamoViewModel.PreferenceSettings.HideNodesBelowSpecificConfidenceLevel;

if (!FilteredHighConfidenceResults.Any())
else
{
DisplayAutocompleteMLStaticPage = true;
AutocompleteMLTitle = Resources.AutocompleteLowConfidenceTitle;
AutocompleteMLMessage = Resources.AutocompleteLowConfidenceMessage;
return;
FilteredLowConfidenceResults = FilteredLowConfidenceResults.Append(result);
}
}

// Show low confidence section if there are some results under threshold and feature enabled
DisplayLowConfidence = FilteredLowConfidenceResults.Any() && dynamoViewModel.PreferenceSettings.HideNodesBelowSpecificConfidenceLevel;

// By default, show only the results which are above the threshold
FilteredResults = dynamoViewModel.PreferenceSettings.HideNodesBelowSpecificConfidenceLevel? FilteredHighConfidenceResults : results ;
if (!FilteredHighConfidenceResults.Any())
{
DisplayAutocompleteMLStaticPage = true;
AutocompleteMLTitle = Resources.AutocompleteLowConfidenceTitle;
AutocompleteMLMessage = Resources.AutocompleteLowConfidenceMessage;
return;
}

// By default, show only the results which are above the threshold
FilteredResults = dynamoViewModel.PreferenceSettings.HideNodesBelowSpecificConfidenceLevel ? FilteredHighConfidenceResults : results;
}

private MLNodeAutoCompletionResponse GetMLNodeAutocompleteResults(string requestJSON)
Expand Down Expand Up @@ -528,7 +538,7 @@ internal void ShowLowConfidenceResults()
}

// Full name and assembly name
private NodeModelTypeId GetInfoFromTypeId(string typeId)
internal NodeModelTypeId GetInfoFromTypeId(string typeId)
{
if (typeId.Contains(','))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ private void AutoLayoutNodes(object sender, EventArgs e)
originalNodeId = nodeView.ViewModel.NodeModel.OutputNodes.Values.SelectMany(s => s.Select(t => t.Item2)).Distinct().FirstOrDefault().GUID;
newInput = true;
}
else if (nodeView.ViewModel.NodeModel.InputNodes.Count() > 0)
else if (nodeView.ViewModel.NodeModel.InputNodes.Count > 0)
{
originalNodeId = nodeView.ViewModel.NodeModel.InputNodes.Values.Select(s => s.Item2).Distinct().FirstOrDefault().GUID;
}
Expand Down
30 changes: 30 additions & 0 deletions src/DynamoCoreWpf/Views/Core/NodeView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,17 @@
Source="/DynamoCoreWpf;component/UI/Images/NodeStates/frozen-64px.png"
Stretch="UniformToFill" />
</Grid>
<!-- Node transient state indication, light sparkle -->
<Grid x:Name="ClusterTransientGlyph"
Visibility="{Binding Path=IsTransient, Converter={StaticResource BooleanToVisibilityCollapsedConverter}, Mode=OneWay}">
<Image x:Name="TransientImage"
Width="16px"
Height="16px"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Source="/DynamoCoreWpf;component/UI/Images/NodeStates/transient-64px.png"
Stretch="UniformToFill" />
</Grid>
<Grid x:Name="HiddenEyeGlyph"
Visibility="{Binding Path=IsVisible, Converter={StaticResource InverseBoolToVisibilityCollapsedConverter}, Mode=OneWay}">
<Image x:Name="HiddenEyeImage"
Expand Down Expand Up @@ -531,6 +542,8 @@
</Style>
</Grid.Style>
</Grid>

<!-- Button to open node context menu from lower right corner -->
<Button x:Name="OptionsButton"
Click="DisplayNodeContextMenu">
<Button.ToolTip>
Expand Down Expand Up @@ -614,6 +627,23 @@
Style="{Binding Path=DataContext.StopNodeViewOpacityAnimations, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:WorkspaceView}}, Converter={StaticResource SZoomFadeOutPreview}}"
Visibility="{Binding Path=IsFrozen, Converter={StaticResource BooleanToVisibilityCollapsedConverter}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />

<!-- Displays when the node cluster is Preivew state and Zoom is above 0.4 -->
<Border Name="nodeTransientColorOverlayZoomIn"
Grid.Row="1"
Grid.RowSpan="4"
Grid.ColumnSpan="3"
Margin="-8"
Background="{StaticResource NodeTransientOverlayColor}"
Canvas.ZIndex="6"
CornerRadius="8,8,0,0"
IsHitTestVisible="False"
Opacity="{Binding Path=DataContext.Zoom,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type controls:WorkspaceView}},
Converter={StaticResource ZoomToOpacityConverter}}"
Style="{Binding Path=DataContext.StopNodeViewOpacityAnimations, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:WorkspaceView}}, Converter={StaticResource SZoomFadeOutPreview}}"
Visibility="{Binding Path=IsTransient, Converter={StaticResource BooleanToVisibilityCollapsedConverter}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />

<!-- Displays when the node is Frozen/Warning/Error state and Zoom is below 0.4 -->
<Border Name="nodeColorOverlayZoomOut"
Grid.Row="1"
Expand Down
Loading

0 comments on commit 9bf521e

Please sign in to comment.