Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/DynamoCore/Engine/EngineController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public class EngineController : LogSourceBase, IAstNodeContainer, IDisposable
/// </summary>
public event AstBuiltEventHandler AstBuilt;

/// <summary>
/// The event notifies client that the VMLibraries have been reset and the VM is now ready to run the new code.
/// </summary>
internal static event Action VMLibrariesReset;

/// <summary>
/// This flag is used to check if any packages are currently being loaded, and to disable any executions that are triggered before the package loading is completed. See DYN-2101 for more info.
/// </summary>
Expand Down Expand Up @@ -504,6 +509,8 @@ private void OnLibraryLoaded()
{
liveRunnerServices.ReloadAllLibraries(libraryServices.ImportedLibraries);

VMLibrariesReset?.Invoke();

// The LiveRunner core is newly instantiated whenever a new library is imported
// due to which a new instance of CodeCompletionServices needs to be created with the new Core
codeCompletionServices = new CodeCompletionServices(LiveRunnerCore);
Expand Down
77 changes: 77 additions & 0 deletions src/DynamoCore/Graph/Nodes/DummyNode.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
using Autodesk.DesignScript.Runtime;
using Dynamo.Core;
using Dynamo.Engine;
using Dynamo.Graph.Nodes.NodeLoaders;
using Dynamo.Graph.Workspaces;
using Dynamo.Logging;
using Dynamo.Utilities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
Expand Down Expand Up @@ -398,5 +404,76 @@ private XmlElement OriginalXmlNodeContent
return originalXmlElement;
}
}

/// <summary>
/// Deserializes and returns the nodeModel that is represented by the original content of this DummyNode.
/// If this node cannot be resolved, returns a new DummyNode
/// </summary>
/// <param name="json"></param>
/// <param name="libraryServices"></param>
/// <param name="factory"></param>
/// <param name="isTestMode"></param>
/// <param name="manager"></param>
internal NodeModel GetNodeModelForDummyNode(string json, LibraryServices libraryServices,
NodeFactory factory, bool isTestMode, CustomNodeManager manager)
{
var settings = new JsonSerializerSettings
{
Error = (sender, args) =>
{
args.ErrorContext.Handled = true;
Console.WriteLine(args.ErrorContext.Error);
},
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto,
Formatting = Newtonsoft.Json.Formatting.Indented,
Culture = CultureInfo.InvariantCulture,
Converters = new List<JsonConverter>{
new NodeReadConverter(manager, libraryServices, factory, isTestMode),
new TypedParameterConverter()
},
ReferenceResolverProvider = () => { return new IdReferenceResolver(); }
};

var result = SerializationExtensions.ReplaceTypeDeclarations(json, true);
var resolvedNodeModel = JsonConvert.DeserializeObject<NodeModel>(result, settings);

// If the resolved node model is not a dummy node, then copy the node view properties from the dummy node to the resolved version of that node.
if (!(resolvedNodeModel is DummyNode))
{
SetNodeViewDataOnResolvedNode(this, resolvedNodeModel);
}
else
{
this.Log(string.Format("This graph has a node with id:{0} and name:{1}, but it could not be resolved",
resolvedNodeModel.GUID, resolvedNodeModel.Name)
, WarningLevel.Moderate);
}

return resolvedNodeModel;
}

/// <summary>
/// This will set the dummy node's node view properties to the resolved node
/// </summary>
/// <param name="dummyNode"></param>
/// <param name="resolvedNode"></param>
private void SetNodeViewDataOnResolvedNode(NodeModel dummyNode, NodeModel resolvedNode)
{
if (dummyNode == null || resolvedNode == null)
{
return;
}

resolvedNode.X = dummyNode.X;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one thought I have about this is - is there a way to ensure we are transferring all view properties of the dummyNode - so we don't forget to update this if new view properties are added? Something like checking the ExtraNodeViewInfo object for all properties or something? This is not required - but something to think about.

resolvedNode.Y = dummyNode.Y;
resolvedNode.IsFrozen = dummyNode.IsFrozen;
resolvedNode.IsSetAsInput = dummyNode.IsSetAsInput;
resolvedNode.IsSetAsOutput = dummyNode.IsSetAsOutput;

// NOTE: The name needs to be set using UpdateValue to cause the view to update
resolvedNode.UpdateValue(new UpdateValueParams("Name", dummyNode.Name));
resolvedNode.UpdateValue(new UpdateValueParams("IsVisible", dummyNode.IsVisible.ToString()));
}
}
}
31 changes: 22 additions & 9 deletions src/DynamoCore/Graph/Workspaces/WorkspaceModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
using Dynamo.Core;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using Dynamo.Core;
using Dynamo.Engine;
using Dynamo.Engine.CodeGeneration;
using Dynamo.Events;
Expand All @@ -19,14 +27,6 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ProtoCore.Namespace;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;


namespace Dynamo.Graph.Workspaces
Expand Down Expand Up @@ -188,6 +188,19 @@ internal int CurrentPasteOffset
/// </summary>
private bool workspaceLoaded;

/// <summary>
/// This event is raised after the workspace tries to resolve existing dummyNodes - for example after a new package or library is loaded.
/// </summary>
public static event Action DummyNodesReloaded;

/// <summary>
/// This method invokes the DummyNodesReloaded event on the workspace model.
/// </summary>
public void OnDummyNodesReloaded()
{
DummyNodesReloaded?.Invoke();
}

/// <summary>
/// sets the name property of the model based on filename,backup state and model type.
/// </summary>
Expand Down
83 changes: 79 additions & 4 deletions src/DynamoCore/Models/DynamoModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -36,6 +37,8 @@
using DynamoServices;
using DynamoUnits;
using Greg;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ProtoCore;
using ProtoCore.Runtime;
using Compiler = ProtoAssociative.Compiler;
Expand All @@ -44,10 +47,6 @@
using FunctionGroup = Dynamo.Engine.FunctionGroup;
using Utils = Dynamo.Graph.Nodes.Utilities;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Globalization;

namespace Dynamo.Models
{
/// <summary>
Expand Down Expand Up @@ -732,6 +731,8 @@ protected DynamoModel(IStartConfiguration config)

ResetEngineInternal();

EngineController.VMLibrariesReset += ReloadDummyNodes;

AddHomeWorkspace();

AuthenticationManager = new AuthenticationManager(config.AuthProvider);
Expand Down Expand Up @@ -1037,6 +1038,8 @@ public void Dispose()
LibraryServices.Dispose();
LibraryServices.LibraryManagementCore.Cleanup();

EngineController.VMLibrariesReset -= ReloadDummyNodes;

UpdateManager.Log -= UpdateManager_Log;
Logger.Dispose();

Expand Down Expand Up @@ -1715,6 +1718,78 @@ private bool OpenJsonFile(
return true;
}

// Attempts to reload all the dummy nodes in the current workspace and replaces them with resolved version.
private void ReloadDummyNodes()
{
JObject dummyNodeJSON = null;
Boolean resolvedDummyNode = false;

WorkspaceModel currentWorkspace = this.CurrentWorkspace;

if (currentWorkspace == null || string.IsNullOrEmpty(currentWorkspace.FileName))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if this is a customNode workspace? Have you tested that? I think we need a test for that case.

{
return;
}

// Get the dummy nodes in the current workspace.
var dummyNodes = currentWorkspace.Nodes.OfType<DummyNode>();

foreach (DummyNode dn in dummyNodes)
{
dummyNodeJSON = dn.OriginalNodeContent as JObject;

if (dummyNodeJSON != null)
{
// Deserializing the dummy node and verifying if it is resolved by the downloaded or imported package
NodeModel resolvedNode = dn.GetNodeModelForDummyNode(
dummyNodeJSON.ToString(),
LibraryServices,
NodeFactory,
IsTestMode,
CustomNodeManager);

// If the resolved node is also a dummy node, then skip it else replace the dummy node with the resolved version of the node.
if (!(resolvedNode is DummyNode))
{
// Disable graph runs temporarily while the dummy node is replaced with the resolved version of that node.
EngineController.DisableRun = true;
currentWorkspace.RemoveAndDisposeNode(dn);
currentWorkspace.AddAndRegisterNode(resolvedNode, false);

// Adding back the connectors for the resolved node.
List<ConnectorModel> connectors = dn.AllConnectors.ToList();
foreach (var connectorModel in connectors)
{
var startNode = connectorModel.Start.Owner;
var endNode = connectorModel.End.Owner;

if (startNode is DummyNode && startNode.GUID == resolvedNode.GUID)
{
startNode = resolvedNode;
}
if (endNode is DummyNode && endNode.GUID == resolvedNode.GUID)
{
endNode = resolvedNode;
}

connectorModel.Delete();
ConnectorModel.Make(startNode, endNode, connectorModel.Start.Index, connectorModel.End.Index, connectorModel.GUID);
}
EngineController.DisableRun = false ;
resolvedDummyNode = true;
}
}
}

if (resolvedDummyNode)
{
currentWorkspace.HasUnsavedChanges = false;
// Once all the dummy nodes are reloaded, the DummyNodesReloaded event is invoked and
// the Dependency table is regenerated in the WorkspaceDependencyView extension.
currentWorkspace.OnDummyNodesReloaded();
}
}

private bool OpenXmlFile(WorkspaceInfo workspaceInfo, XmlDocument xmlDoc, out WorkspaceModel workspace)
{
CustomNodeManager.AddUninitializedCustomNodesInPath(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Dynamo.WorkspaceDependency
/// <summary>
/// Interaction logic for WorkspaceDependencyView.xaml
/// </summary>
public partial class WorkspaceDependencyView : UserControl
public partial class WorkspaceDependencyView : UserControl, IDisposable
{

private WorkspaceModel currentWorkspace;
Expand Down Expand Up @@ -116,6 +116,14 @@ internal void DependencyRegen(WorkspaceModel ws)
PackageDependencyTable.ItemsSource = packageDependencies.Select(d => new PackageDependencyRow(d as PackageDependencyInfo));
}

/// <summary>
/// Calls the DependencyRegen function when the DummyNodesReloaded event is triggered from the dynamo model.
/// </summary>
internal void TriggerDependencyRegen()
{
DependencyRegen(currentWorkspace);
}

/// <summary>
/// Constructor
/// </summary>
Expand All @@ -124,6 +132,7 @@ public WorkspaceDependencyView(WorkspaceDependencyViewExtension viewExtension,Vi
{
InitializeComponent();
currentWorkspace = p.CurrentWorkspaceModel as WorkspaceModel;
WorkspaceModel.DummyNodesReloaded += TriggerDependencyRegen;
p.CurrentWorkspaceChanged += OnWorkspaceChanged;
p.CurrentWorkspaceCleared += OnWorkspaceCleared;
currentWorkspace.PropertyChanged += OnWorkspacePropertyChanged;
Expand Down Expand Up @@ -187,6 +196,16 @@ internal void UpdateWorkspaceToUseInstalledPackage(PackageDependencyInfo info)
}
}
}

/// <summary>
/// Dispose function for WorkspaceDependencyView
/// </summary>
public void Dispose()
{
loadedParams.CurrentWorkspaceChanged -= OnWorkspaceChanged;
loadedParams.CurrentWorkspaceCleared -= OnWorkspaceCleared;
WorkspaceModel.DummyNodesReloaded -= TriggerDependencyRegen;
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ namespace Dynamo.WorkspaceDependency
public class WorkspaceDependencyViewExtension : IViewExtension, ILogSource
{
private MenuItem packageDependencyMenuItem;
private ViewLoadedParams LoadedParams;

internal WorkspaceDependencyView DependencyView
{
Expand Down Expand Up @@ -65,8 +64,7 @@ public void Ready(ReadyParams readyParams)

public void Shutdown()
{
LoadedParams.CurrentWorkspaceChanged -= DependencyView.OnWorkspaceChanged;
LoadedParams.CurrentWorkspaceCleared -= DependencyView.OnWorkspaceCleared;
DependencyView.Dispose();
this.Dispose();
}

Expand Down
Loading