-
Notifications
You must be signed in to change notification settings - Fork 636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Core.Data Serialization and Add Remember Node #14111
Changes from 17 commits
ea9afbe
d3479fe
0a12332
5179b47
ef5e9fc
05d5a89
281ac3d
22d624c
cdffedb
128d133
ae9ddbe
3eede66
4ba4038
6fe96a1
8e0ef8c
1f43200
295af29
eafd245
233b4c8
01454db
6557cea
c7e5043
9db3562
c8c3eb9
f092690
d089075
105a2a6
0dabf04
62a489d
9d9e67c
cc807f8
2637309
0be48cd
8db0472
02ff430
88c929d
5cf2790
95c6a48
9aaf819
76174bd
72baac0
2f787ee
0a1abb4
58f3a9f
43d4f3c
cab7d39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
using Dynamo.Graph; | ||
using Dynamo.Graph.Nodes; | ||
using Newtonsoft.Json; | ||
using ProtoCore.AST.AssociativeAST; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.ComponentModel; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using VMDataBridge; | ||
|
||
namespace CoreNodeModels | ||
{ | ||
[NodeName("Remember")] | ||
[NodeDescription(nameof(Properties.Resources.RememberDescription), typeof(Properties.Resources))] | ||
[NodeCategory("Core.Data")] | ||
[InPortNames(">")] | ||
[InPortTypes("object")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This node does not replicate. We can change the label to whatever we would like. In the Node model case the port names are just for display. What do you think is the oppriate label @mjkkirschner There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the appropriate label for a none replicating node is |
||
[InPortDescriptions(typeof(Properties.Resources), nameof(Properties.Resources.RememberInputToolTip))] | ||
[OutPortNames(">")] | ||
[OutPortTypes("object")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be |
||
[OutPortDescriptions(typeof(Properties.Resources), nameof(Properties.Resources.RememberOuputToolTip))] | ||
[IsDesignScriptCompatible] | ||
[DynamoServices.RegisterForTrace] | ||
mjkkirschner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public class Remember : NodeModel | ||
{ | ||
private bool _deactivateNode; | ||
private string _cache = ""; | ||
private string _updatedToolTipText = ""; | ||
saintentropy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
[JsonProperty("Cache")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why do you need this when the property has the same name? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch |
||
public string Cache | ||
{ | ||
get { return _cache; } | ||
set | ||
{ | ||
var valueToSet = value == null ? "" : value; | ||
if (valueToSet != _cache) | ||
{ | ||
_cache = valueToSet; | ||
MarkNodeAsModified(); | ||
} | ||
} | ||
} | ||
|
||
[JsonConstructor] | ||
private Remember(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(inPorts, outPorts) | ||
{ | ||
PropertyChanged += OnPropertyChanged; | ||
} | ||
|
||
public Remember() | ||
{ | ||
RegisterAllPorts(); | ||
PropertyChanged += OnPropertyChanged; | ||
} | ||
|
||
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) | ||
{ | ||
switch (e.PropertyName) | ||
{ | ||
case "State": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nameof? |
||
if (State == ElementState.Warning) | ||
{ | ||
Cache = ""; | ||
} | ||
break; | ||
|
||
case "ToolTipText": | ||
if (State == ElementState.Warning && ToolTipText != _updatedToolTipText) | ||
{ | ||
string[] errorMessages = | ||
ToolTipText.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None); | ||
_updatedToolTipText = errorMessages.Last(); | ||
ToolTipText = _updatedToolTipText; | ||
} | ||
|
||
break; | ||
|
||
default: | ||
// Nothing to handle | ||
break; | ||
} | ||
} | ||
|
||
protected override void OnBuilt() | ||
{ | ||
base.OnBuilt(); | ||
DataBridge.Instance.RegisterCallback(GUID.ToString(), DataBridgeCallback); | ||
} | ||
|
||
public override void Dispose() | ||
{ | ||
base.Dispose(); | ||
DataBridge.Instance.UnregisterCallback(GUID.ToString()); | ||
} | ||
|
||
private static readonly string BuiltinDictionaryTypeName = typeof(DesignScript.Builtin.Dictionary).FullName; | ||
aparajit-pratap marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private static readonly string BuiltinDictionaryGet = nameof(DesignScript.Builtin.Dictionary.ValueAtKey); | ||
|
||
public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes) | ||
{ | ||
// Check that node can run | ||
if (_deactivateNode) | ||
{ | ||
return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) }; | ||
} | ||
|
||
var resultAst = new List<AssociativeNode>(); | ||
|
||
var funtionInputs = new List<AssociativeNode> { inputAstNodes[0], AstFactory.BuildStringNode(Cache) }; | ||
|
||
//First build the function call | ||
var functionCall = AstFactory.BuildFunctionCall( | ||
new Func<object, string, Dictionary<string, object>>(DSCore.Data.Remember), funtionInputs); | ||
|
||
var functionCallIndent = AstFactory.BuildIdentifier(GUID + "_func"); | ||
|
||
resultAst.Add(AstFactory.BuildAssignment(functionCallIndent, functionCall)); | ||
|
||
//Next add the first key value pair to the output port | ||
var getFirstKey = AstFactory.BuildFunctionCall(BuiltinDictionaryTypeName, BuiltinDictionaryGet, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the ASTFactory somewhere has methods for building these calls easily. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not that I am aware of or could find. The main thing we do here is that we need to pass the data from the inputPort and the cached string into and back out of the node every time. The dictionary is used so that we can only present to the ports data on the node and keep the cache data internal. I think we look long and hard at the time we wrote this and didn't have any out of the box options of dictionaries in ASTFactory. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. look for: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahhh. Thanks. I did look at that. Interesting but not exactly what we need. The dictionary is already set up by the function we call |
||
new List<AssociativeNode> { functionCallIndent, AstFactory.BuildStringNode(">") }); | ||
|
||
resultAst.Add(AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), getFirstKey)); | ||
|
||
//Second get the key value pair to pass to the databridge callback | ||
var getSecondKey = AstFactory.BuildFunctionCall(BuiltinDictionaryTypeName, BuiltinDictionaryGet, | ||
new List<AssociativeNode> { functionCallIndent, AstFactory.BuildStringNode("Cache") }); | ||
|
||
resultAst.Add(AstFactory.BuildAssignment( | ||
AstFactory.BuildIdentifier(GUID + "_db"), | ||
DataBridge.GenerateBridgeDataAst(GUID.ToString(), getSecondKey))); | ||
|
||
return resultAst; | ||
} | ||
|
||
private void DataBridgeCallback(object callbackObject) | ||
{ | ||
if (DSCore.Data.CanObjectBeCached(callbackObject)) | ||
{ | ||
Cache = callbackObject as String; | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Node is designed to look like a watch node with ">" port strings