forked from DynamoDS/Dynamo
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDefineData.cs
More file actions
248 lines (205 loc) · 8.45 KB
/
Copy pathDefineData.cs
File metadata and controls
248 lines (205 loc) · 8.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using DSCore;
using Dynamo.Graph;
using Dynamo.Graph.Nodes;
using Newtonsoft.Json;
using ProtoCore.AST.AssociativeAST;
using VMDataBridge;
using static DSCore.Data;
namespace CoreNodeModels
{
[NodeName("DefineData")]
[NodeDescription(nameof(Properties.Resources.RememberDescription), typeof(Properties.Resources))]
[NodeCategory("Core.Data")]
[OutPortNames(">")]
[OutPortTypes("var[]..[]")]
[OutPortDescriptions(typeof(Properties.Resources), nameof(Properties.Resources.RememberOuputToolTip))]
[IsDesignScriptCompatible]
[AlsoKnownAs("Data.DefineData")]
public class DefineData : DSDropDownBase
{
private List<DynamoDropDownItem> serializedItems;
private bool isAutoMode;
private bool isList;
private string playerValue = "";
/// <summary>
/// AutoMode property
/// </summary>
[JsonProperty]
public bool IsAutoMode
{
get { return isAutoMode; }
set
{
isAutoMode = value;
OnNodeModified();
RaisePropertyChanged(nameof(IsAutoMode));
}
}
/// <summary>
/// IsList property
/// </summary>
[JsonProperty]
public bool IsList
{
get { return isList; }
set
{
isList = value;
OnNodeModified();
RaisePropertyChanged(nameof(IsList));
}
}
[JsonIgnore]
public override bool IsInputNode
{
get { return true; }
}
[JsonIgnore]
public string PlayerValue
{
get { return playerValue; }
set
{
var valueToSet = value ?? "";
if (valueToSet != value)
{
playerValue = valueToSet;
MarkNodeAsModified();
}
}
}
/// <summary>
/// Construct a new DefineData Dropdown Menu node
/// </summary>
public DefineData() : base(">")
{
InPorts.Add(new PortModel(PortType.Input, this, new PortData("", Properties.Resources.WatchPortDataInputToolTip)));
OutPorts.Add(new PortModel(PortType.Output, this, new PortData("", Properties.Resources.WatchPortDataResultToolTip)));
RegisterAllPorts();
PropertyChanged += OnPropertyChanged;
}
[JsonConstructor]
private DefineData(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(">", inPorts, outPorts)
{
PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
}
protected override void OnBuilt()
{
base.OnBuilt();
DataBridge.Instance.RegisterCallback(GUID.ToString(), DataBridgeCallback);
}
public override void Dispose()
{
PropertyChanged -= OnPropertyChanged;
base.Dispose();
DataBridge.Instance.UnregisterCallback(GUID.ToString());
}
private static readonly string BuiltinDictionaryTypeName = typeof(DesignScript.Builtin.Dictionary).FullName;
private static readonly string BuiltinDictionaryGet = nameof(DesignScript.Builtin.Dictionary.ValueAtKey);
public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
{
if(inputAstNodes == null)
{
throw new ArgumentNullException(Properties.Resources.BooleanSelectorSearchTags);
}
var resultAst = new List<AssociativeNode>();
// function call inputs - reference to the function, and the function arguments coming from the inputs
// the object to be (type) evaluated
// the expected datatype
// if the input is an ArrayList or not
var function = new Func<object, string, bool, bool, string, Dictionary<string, object>>(DSCore.Data.IsSupportedDataNodeType);
var funtionInputs = new List<AssociativeNode> {
inputAstNodes[0],
AstFactory.BuildStringNode((Items[SelectedIndex].Item as Data. DataNodeDynamoType).Type.ToString()),
AstFactory.BuildBooleanNode(IsList),
AstFactory.BuildBooleanNode(IsAutoMode),
AstFactory.BuildStringNode(PlayerValue)
};
var functionCall = AstFactory.BuildFunctionCall(function, funtionInputs);
var functionCallIdentifier = AstFactory.BuildIdentifier(GUID + "_func");
resultAst.Add(AstFactory.BuildAssignment(functionCallIdentifier, functionCall));
//Next add the first key value pair to the output port
var getFirstKey = AstFactory.BuildFunctionCall(BuiltinDictionaryTypeName, BuiltinDictionaryGet,
new List<AssociativeNode> { functionCallIdentifier, 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> { functionCallIdentifier, AstFactory.BuildStringNode("Validation") });
resultAst.Add(AstFactory.BuildAssignment(
AstFactory.BuildIdentifier(GUID + "_db"),
DataBridge.GenerateBridgeDataAst(GUID.ToString(), getSecondKey)));
return resultAst;
}
/// <summary>
/// Not sure at the moment how relevant is the databridge for this node type
/// </summary>
/// <param name="data"></param>
private void DataBridgeCallback(object data)
{
//Todo If the playerValue is not empty string then we can chanage the UI to reflect the value is coming from the player
//Todo if the function call throws we don't get back to DatabridgeCallback. Not sure if we need to handle this case
//Now we reset this value to empty string so that the next time a value is set from upstream nodes we can know that it is not coming from the player
playerValue = "";
if (data == null) return;
(bool IsValid, bool UpdateList, DataNodeDynamoType InputType) resultData = (ValueTuple<bool, bool, DataNodeDynamoType>)data;
if (IsAutoMode && resultData.UpdateList)
{
IsList = !IsList;
}
if (!resultData.IsValid)
{
if (IsAutoMode)
{
// Assign to the correct value, if the object was of supported type
if (resultData.InputType != null)
{
var index = Items.IndexOf(Items.First(i => i.Name.Equals(resultData.InputType.Name)));
SelectedIndex = index;
}
}
else
{
// Throw an exception/warning and go back to the default dropdown value
SelectedIndex = 0;
}
}
}
protected override SelectionState PopulateItemsCore(string currentSelection)
{
Items.Clear();
foreach (var dataType in Data.GetDataNodeDynamoTypeList())
{
var displayName = dataType.Name;
var value = dataType;
Items.Add(new DynamoDropDownItem(displayName, value));
}
SelectedIndex = 0;
return SelectionState.Restore;
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
serializedItems = Items.ToList();
}
protected override bool UpdateValueCore(UpdateValueParams updateValueParams)
{
string name = updateValueParams.PropertyName;
string value = updateValueParams.PropertyValue;
switch (name)
{
case "Value":
PlayerValue = value;
return true; // UpdateValueCore handled.
}
return base.UpdateValueCore(updateValueParams);
}
}
}