public void CreateNode(UdonNodeDefinition udonNodeDefinition, Vector2?position = null) { //Awful hack to fix regression in unity graph property type conversion { var prop = typeof(TypeConverter).GetField( "useCompatibleTypeConversion", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static ); prop.SetValue(this, true); } UdonNode node = CreateInstance <UdonNode>(); node.name = udonNodeDefinition.fullName; node.title = PrettyString(udonNodeDefinition.name).FriendlyNameify(); node.position = position == null ? new Rect(Vector2.zero, Vector2.zero) : new Rect(position.Value, Vector2.zero); if (node.name.StartsWith("Event_") && node.name != "Event_Custom") { if (nodes.Any(n => n.name == node.name)) { Debug.LogWarning($"Can't create more than one {node.name} node, try managing your flow with a Block node instead!"); return; } } if (node.title == "Const_VRCUdonCommonInterfacesIUdonEventReceiver") { node.title = "UdonBehaviour"; } UdonNodeData nodeData = data.AddNode(udonNodeDefinition.fullName); if (udonNodeDefinition.flow) { if (!udonNodeDefinition.fullName.StartsWith("Event_")) { node.AddInputSlot(""); } node.AddOutputSlot(""); if (_specialFlows.Contains(udonNodeDefinition.fullName)) { node.AddOutputSlot(""); } } foreach (Type input in udonNodeDefinition.inputs) { node.AddInputSlot(FriendlyTypeName(input), SlotTypeConverter(input, udonNodeDefinition.fullName)); } foreach (Type output in udonNodeDefinition.outputs) { node.AddOutputSlot(FriendlyTypeName(output), SlotTypeConverter(output, udonNodeDefinition.fullName)); } if (udonNodeDefinition.defaultValues != null) { nodeData.nodeValues = new SerializableObjectContainer[udonNodeDefinition.defaultValues.Length]; nodeData.nodeUIDs = new string[udonNodeDefinition.defaultValues.Length]; for (int i = 0; i < udonNodeDefinition.defaultValues.Length; i++) { object defaultValue = udonNodeDefinition.defaultValues[i]; if (defaultValue != null) { nodeData.nodeValues[i] = SerializableObjectContainer.Serialize(defaultValue); } } } node.uid = nodeData.uid; ReSerializeData(); AddNode(node); }
public UdonNode CreateNode(UdonNodeData nodeData) { //Awful hack to fix regression in unity graph property type conversion { var prop = typeof(TypeConverter).GetField( "useCompatibleTypeConversion", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static ); prop.SetValue(this, true); } UdonNodeDefinition udonNodeDefinition = null; try { udonNodeDefinition = UdonEditorManager.Instance.GetNodeDefinition(nodeData.fullName); } catch { Debug.LogError($"Skipping missing node: {nodeData.fullName}"); return(null); } UdonNode node = CreateInstance <UdonNode>(); node.name = udonNodeDefinition.fullName; node.title = PrettyString(udonNodeDefinition.name).FriendlyNameify(); if (node.name.StartsWith("Event_") && node.name != "Event_Custom") { if (nodes.Any(n => n.name == node.name)) { Debug.LogWarning($"Can't create more than one {node.name} node, try managing your flow with a Block node instead!"); return(null); } } if (node.title == "Const_VRCUdonCommonInterfacesIUdonEventReceiver") { node.title = "UdonBehaviour"; } node.uid = nodeData.uid; node.position = new Rect(nodeData.position, Vector2.zero); if (udonNodeDefinition.flow) { if (!udonNodeDefinition.fullName.StartsWith("Event_")) { node.AddInputSlot(""); } node.AddOutputSlot(""); if (_specialFlows.Contains(udonNodeDefinition.fullName)) { node.AddOutputSlot(""); } if (udonNodeDefinition.fullName == "Block") { int connectedFlows = nodeData.flowUIDs.Count(f => !string.IsNullOrEmpty(f)); if (connectedFlows > 1) { for (int i = 0; i < connectedFlows - 1; i++) { node.AddOutputSlot(""); } } } } if (udonNodeDefinition.fullName == "SubGraph") { if (nodeData.nodeValues.Length > 0 && nodeData.nodeValues[0] != null) { IUdonGraphDataProvider graphDataProvider = (IUdonGraphDataProvider)nodeData.nodeValues[0].Deserialize(); if (graphDataProvider != null) { UdonGraphData subGraphData = graphDataProvider.GetGraphData(); bool doExit = false; foreach (UdonNodeData eventNode in subGraphData.EventNodes) { if (eventNode.fullName != "Event_Custom") { continue; } string customEventName = "customEvent"; if (eventNode.nodeValues.Length > 0 && eventNode.nodeValues[0] != null) { string eventName = (string)eventNode.nodeValues[0].Deserialize(); if (!string.IsNullOrEmpty(eventName)) { customEventName = eventName; } } node.AddInputSlot(customEventName); doExit = true; break; //TODO: support more than one custom event in a subgraph } if (doExit) { node.AddOutputSlot("Exit"); } } } } // Data Validation // bool modifiedData = false; for (int i = 0; i < nodeData.nodeValues.Length; i++) { if (udonNodeDefinition.inputs.Length <= i) { continue; } Type expectedType = udonNodeDefinition.inputs[i]; if (nodeData.nodeValues[i] == null) { continue; } object value = nodeData.nodeValues[i].Deserialize(); if (value == null) { continue; } if (!expectedType.IsInstanceOfType(value)) { nodeData.nodeValues[i] = SerializableObjectContainer.Serialize(null, expectedType); modifiedData = true; } } if (modifiedData) { ReSerializeData(); } //////////////////// foreach (Type input in udonNodeDefinition.inputs) { node.AddInputSlot(FriendlyTypeName(input), SlotTypeConverter(input, udonNodeDefinition.fullName)); } foreach (Type output in udonNodeDefinition.outputs) { node.AddOutputSlot(FriendlyTypeName(output), SlotTypeConverter(output, udonNodeDefinition.fullName)); } AddNode(node); return(node); }