diff --git a/src/DynamoCore/Graph/Nodes/NodeModel.cs b/src/DynamoCore/Graph/Nodes/NodeModel.cs
index 5791cf91648..b5ac79bd5d4 100644
--- a/src/DynamoCore/Graph/Nodes/NodeModel.cs
+++ b/src/DynamoCore/Graph/Nodes/NodeModel.cs
@@ -995,6 +995,17 @@ public bool IsFrozen
}
}
+ ///
+ /// 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.
+ ///
+ internal bool IsTransient
+ {
+ get;
+ set;
+ }
+
///
/// The default behavior for ModelBase objects is to not serialize the X and Y
/// properties. This overload allows the serialization of the X property
diff --git a/src/DynamoCore/Graph/Workspaces/SerializationConverters.cs b/src/DynamoCore/Graph/Workspaces/SerializationConverters.cs
index 10c0b985bbd..029e242172d 100644
--- a/src/DynamoCore/Graph/Workspaces/SerializationConverters.cs
+++ b/src/DynamoCore/Graph/Workspaces/SerializationConverters.cs
@@ -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");
diff --git a/src/DynamoCore/Scheduler/UpdateGraphAsyncTask.cs b/src/DynamoCore/Scheduler/UpdateGraphAsyncTask.cs
index 692be1b52e7..2a0a915eafb 100644
--- a/src/DynamoCore/Scheduler/UpdateGraphAsyncTask.cs
+++ b/src/DynamoCore/Scheduler/UpdateGraphAsyncTask.cs
@@ -255,8 +255,8 @@ protected override TaskMergeInstruction CanMergeWithCore(AsyncTask otherTask)
private static IEnumerable ComputeModifiedNodes(WorkspaceModel workspace)
{
var nodesToUpdate = new List();
- //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);
}
@@ -273,7 +273,7 @@ private static IEnumerable ComputeModifiedNodes(WorkspaceModel worksp
///
private static void GetDownstreamNodes(NodeModel node, ICollection 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);
diff --git a/src/DynamoCoreWpf/DynamoCoreWpf.csproj b/src/DynamoCoreWpf/DynamoCoreWpf.csproj
index 25a013533bf..5195fb32057 100644
--- a/src/DynamoCoreWpf/DynamoCoreWpf.csproj
+++ b/src/DynamoCoreWpf/DynamoCoreWpf.csproj
@@ -110,7 +110,6 @@
-
@@ -161,6 +160,9 @@
+
+
+
@@ -1041,6 +1043,8 @@
+
+
diff --git a/src/DynamoCoreWpf/PublicAPI.Unshipped.txt b/src/DynamoCoreWpf/PublicAPI.Unshipped.txt
index 7fb2515f640..07a98a3f159 100644
--- a/src/DynamoCoreWpf/PublicAPI.Unshipped.txt
+++ b/src/DynamoCoreWpf/PublicAPI.Unshipped.txt
@@ -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
diff --git a/src/DynamoCoreWpf/UI/Images/NodeStates/transient-64px.png b/src/DynamoCoreWpf/UI/Images/NodeStates/transient-64px.png
new file mode 100644
index 00000000000..3e367f6f488
Binary files /dev/null and b/src/DynamoCoreWpf/UI/Images/NodeStates/transient-64px.png differ
diff --git a/src/DynamoCoreWpf/UI/Images/NodeStates/transient-light-64px.png b/src/DynamoCoreWpf/UI/Images/NodeStates/transient-light-64px.png
new file mode 100644
index 00000000000..3d1535b0d7d
Binary files /dev/null and b/src/DynamoCoreWpf/UI/Images/NodeStates/transient-light-64px.png differ
diff --git a/src/DynamoCoreWpf/UI/Themes/Modern/DynamoColorsAndBrushes.xaml b/src/DynamoCoreWpf/UI/Themes/Modern/DynamoColorsAndBrushes.xaml
index 6e2d8d8472b..6bc264edbb3 100644
--- a/src/DynamoCoreWpf/UI/Themes/Modern/DynamoColorsAndBrushes.xaml
+++ b/src/DynamoCoreWpf/UI/Themes/Modern/DynamoColorsAndBrushes.xaml
@@ -81,6 +81,7 @@
+
diff --git a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
index 3194dace4b5..9d00eab9fe8 100644
--- a/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Core/DynamoViewModel.cs
@@ -225,7 +225,7 @@ internal bool IsDNAClusterPlacementEnabled
{
get
{
- return DynamoModel.FeatureFlags?.CheckFeatureFlag("IsDNAClusterPlacementEnabled", false) ?? true;
+ return DynamoModel.FeatureFlags?.CheckFeatureFlag("IsDNAClusterPlacementEnabled", false) ?? false;
}
}
diff --git a/src/DynamoCoreWpf/ViewModels/Core/NodeViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/NodeViewModel.cs
index f2b0ba851a2..9684ec0260f 100644
--- a/src/DynamoCoreWpf/ViewModels/Core/NodeViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Core/NodeViewModel.cs
@@ -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";
@@ -622,6 +623,16 @@ public bool IsFrozen
}
}
+ ///
+ /// Return a value indicating whether this node is in transient state.
+ ///
+ [JsonIgnore]
+ public bool IsTransient
+ {
+ set { NodeModel.IsTransient = value; }
+ get { return NodeModel.IsTransient; }
+ }
+
///
/// A flag indicating whether the node is set to freeze by the user.
///
@@ -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"));
///
@@ -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;
}
}
@@ -1379,7 +1391,7 @@ Pass through all possible states in reverse order
else
{
ImgGlyphOneSource = packageGlyph;
- ImgGlyphTwoSource = previewGlyph;
+ ImgGlyphTwoSource = previewGeometryGlyph;
}
}
}
@@ -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;
diff --git a/src/DynamoCoreWpf/ViewModels/Core/PortViewModel.cs b/src/DynamoCoreWpf/ViewModels/Core/PortViewModel.cs
index 56fa37f037b..a1797ea8d28 100644
--- a/src/DynamoCoreWpf/ViewModels/Core/PortViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Core/PortViewModel.cs
@@ -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;
@@ -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;
@@ -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)
{
diff --git a/src/DynamoCoreWpf/ViewModels/Search/NodeAutoCompleteSearchViewModel.cs b/src/DynamoCoreWpf/ViewModels/Search/NodeAutoCompleteSearchViewModel.cs
index 592b11c0a58..7899f809817 100644
--- a/src/DynamoCoreWpf/ViewModels/Search/NodeAutoCompleteSearchViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Search/NodeAutoCompleteSearchViewModel.cs
@@ -399,31 +399,41 @@ internal void ShowNodeAutocompleMLResults()
}
}
- foreach (var result in results)
+ OrganizeConfidenceSection(results);
+ }
+ }
+
+ ///
+ /// Compare to low confidence threadhold defined by user can origanize the results into high and low confidence sections.
+ ///
+ ///
+ internal void OrganizeConfidenceSection(List 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)
@@ -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(','))
{
diff --git a/src/DynamoCoreWpf/ViewModels/Search/NodeSearchElementViewModel.cs b/src/DynamoCoreWpf/ViewModels/Search/NodeSearchElementViewModel.cs
index a66808a2070..a5cd8f3805c 100644
--- a/src/DynamoCoreWpf/ViewModels/Search/NodeSearchElementViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/Search/NodeSearchElementViewModel.cs
@@ -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;
}
diff --git a/src/DynamoCoreWpf/Views/Core/NodeView.xaml b/src/DynamoCoreWpf/Views/Core/NodeView.xaml
index 416fd872779..3fea78b8584 100644
--- a/src/DynamoCoreWpf/Views/Core/NodeView.xaml
+++ b/src/DynamoCoreWpf/Views/Core/NodeView.xaml
@@ -476,6 +476,17 @@
Source="/DynamoCoreWpf;component/UI/Images/NodeStates/frozen-64px.png"
Stretch="UniformToFill" />
+
+
+
+
+
+