public UdonParameterField(UdonGraph udonGraph, UdonNodeData nodeData)
        {
            this.udonGraph = udonGraph;
            this.nodeData  = nodeData;

            // Get Definition or exit early
            UdonNodeDefinition definition = UdonEditorManager.Instance.GetNodeDefinition(nodeData.fullName);

            if (definition == null)
            {
                UnityEngine.Debug.LogWarning($"Couldn't create Parameter Field for {nodeData.fullName}");
                return;
            }

            this.text     = (string)nodeData.nodeValues[(int)UdonParameterProperty.ValueIndices.name].Deserialize();
            this.typeText = UdonGraphExtensions.PrettyString(definition.name).FriendlyNameify();

            this.AddManipulator(new ContextualMenuManipulator(BuildContextualMenu));

            this.Q("icon").AddToClassList("parameter-" + definition.type);
            this.Q("icon").visible = true;

            var textField = (TextField)this.Q("textField");

            textField.isDelayed = true;
        }
示例#2
0
        private void SetupPort()
        {
            this.AddManipulator(m_EdgeConnector);

            tooltip = UdonGraphExtensions.FriendlyTypeName(portType);

            if (portType == null || direction == Direction.Output)
            {
                return;
            }

            var value = TryGetValueObject(out object result);
            var field = UdonFieldFactory.CreateField(
                portType,
                result,
                newValue => SetNewValue(newValue)
                );

            if (field != null)
            {
                SetupField(field);
            }

            if (_udonNodeData.fullName.StartsWith("Const"))
            {
                RemoveConnector();
            }

            UpdateLabel(connected);
        }
示例#3
0
        // Made its own method for now as we have issues auto-converting between string and char in a TextField
        // TODO: refactor SetupField so we can do just the field.value part separately to combine with this
        private VisualElement SetupCharField()
        {
            TextField field = new TextField();

            field.AddToClassList("portField");
            if (TryGetValueObject(out object result))
            {
                field.value = UdonGraphExtensions.UnescapeLikeALiteral((char)result);
            }

            field.isDelayed = true;

            // Special handling for escaping char value
            field.OnValueChanged((e) =>
            {
                if (e.newValue[0] == '\\' && e.newValue.Length > 1)
                {
                    SetNewValue(UdonGraphExtensions.EscapeLikeALiteral(e.newValue.Substring(0, 2)));
                }
                else
                {
                    SetNewValue(e.newValue[0]);
                }
            });
            _inputField = field;

            // Add label, shown when input is connected. Not shown by default
            var friendlyName = UdonGraphExtensions.FriendlyTypeName(typeof(char)).FriendlyNameify();
            var label        = new EngineUI.Label(friendlyName);

            _inputFieldTypeLabel = label;

            return(_inputField);
        }
        private void SetupField(VisualElement field)
        {
            // Custom Event fields need their event names sanitized after input and their connectors removed
            if (_udonNodeData.fullName.CompareTo("Event_Custom") == 0)
            {
                var tfield = (TextField)field;
#if UNITY_2019_3_OR_NEWER
                tfield.RegisterValueChangedCallback(
#else
                tfield.OnValueChanged(
#endif
                    (e) =>
                {
                    string newValue = e.newValue.SanitizeVariableName();
                    tfield.value    = newValue;
                    SetNewValue(newValue);
                });
                RemoveConnector();
            }

            // Add label, shown when input is connected. Not shown by default
            var friendlyName     = UdonGraphExtensions.FriendlyTypeName(portType).FriendlyNameify();
            var label            = new Label(friendlyName);
            _inputFieldTypeLabel = label;
            field.AddToClassList("portField");

            _inputField = field;
            Add(_inputField);
        }
示例#5
0
        private void SetupField(VisualElement field)
        {
            // Delay color fields so they don't break UI
            if (portType.IsAssignableFrom(typeof(EditorUI.ColorField)))
            {
                _waitToReserialize = true;
            }

            // Custom Event fields need their event names sanitized after input and their connectors removed
            if (_udonNodeData.fullName.CompareTo("Event_Custom") == 0)
            {
                var tfield = (TextField)field;
                tfield.OnValueChanged((e) =>
                {
                    string newValue = e.newValue.SanitizeVariableName();
                    tfield.value    = newValue;
                    SetNewValue(newValue);
                });
                RemoveConnector();
            }

            // Add label, shown when input is connected. Not shown by default
            var friendlyName = UdonGraphExtensions.FriendlyTypeName(portType).FriendlyNameify();
            var label        = new EngineUI.Label(friendlyName);

            _inputFieldTypeLabel = label;
            field.AddToClassList("portField");

            _inputField = field;
            Add(_inputField);
        }
示例#6
0
        public UdonParameterField(UdonGraph udonGraph, UdonNodeData nodeData)
        {
            this.udonGraph = udonGraph;
            this.nodeData  = nodeData;

            // Get Definition or exit early
            UdonNodeDefinition definition = UdonEditorManager.Instance.GetNodeDefinition(nodeData.fullName);

            if (definition == null)
            {
                UnityEngine.Debug.LogWarning($"Couldn't create Parameter Field for {nodeData.fullName}");
                return;
            }

            this.text     = (string)nodeData.nodeValues[(int)UdonParameterProperty.ValueIndices.name].Deserialize();
            this.typeText = UdonGraphExtensions.PrettyString(definition.name).FriendlyNameify();

            this.AddManipulator(new ContextualMenuManipulator(BuildContextualMenu));

            this.Q("icon").AddToClassList("parameter-" + definition.type);
            this.Q("icon").visible = true;

            var textField = (TextField)this.Q("textField");

            textField.isDelayed = true;
            textField.OnValueChanged((e) => {
                UnityEditor.Undo.RecordObject(udonGraph.graphProgramAsset, "Rename Variable");
                // Sanitize value for variable name
                string newVariableName = e.newValue.SanitizeVariableName();
                text = newVariableName;
                nodeData.nodeValues[(int)UdonParameterProperty.ValueIndices.name] = SerializableObjectContainer.Serialize(newVariableName);
            });
        }
        // Works for any TextValueField types, needs to know fieldType and object type
        private VisualElement SetupField <TField, TType>(TField field) where TField : VisualElement, INotifyValueChanged <TType>
        {
            field.AddToClassList("portField");
            if (TryGetValueObject(out object result))
            {
                try
                {
                    field.value = (TType)(result as object);
                }
                catch (Exception e)
                {
                    // Quietly catch this and continue
                }
            }

            // Delay text inputs
            if (typeof(TField).IsAssignableFrom(typeof(TextField)))
            {
                (field as TextField).isDelayed = true;
            }

            // Don't update color fields right away, breaks the UI
            if (typeof(TField).IsAssignableFrom(typeof(EditorUI.ColorField)))
            {
                _waitToReserialize = true;
            }

            // Custom Event fields need their event names sanitized after input and their connectors removed
            if (_udonNodeData.fullName.CompareTo("Event_Custom") == 0)
            {
                var tfield = field as TextField;
                tfield.OnValueChanged((e) =>
                {
                    string newValue = e.newValue.SanitizeVariableName();
                    tfield.value    = newValue;
                    SetNewValue(newValue);
                });
                RemoveConnector();
            }
            else
            {
                field.OnValueChanged((e) => SetNewValue(e.newValue));
            }
            _inputField = field;

            // Add label, shown when input is connected. Not shown by default
            var friendlyName = UdonGraphExtensions.FriendlyTypeName(typeof(TType)).FriendlyNameify();
            var label        = new EngineUI.Label(friendlyName);

            _inputFieldTypeLabel = label;

            return(_inputField);
        }
        private void SetupPort()
        {
            _isSendChangePort = portName == "sendChange";
            if (_isSendChangePort)
            {
                m_EdgeConnector = null;
            }
            else
            {
                this.AddManipulator(m_EdgeConnector);
            }

            tooltip = UdonGraphExtensions.FriendlyTypeName(portType);

            FullName = _udonNodeData.fullName;

            if (portType == null || direction == Direction.Output)
            {
                return;
            }

            if (TryGetValueObject(out object result, portType))
            {
                var field = UdonFieldFactory.CreateField(
                    portType,
                    result,
                    newValue => SetNewValue(newValue)
                    );

                if (field != null)
                {
                    SetupField(field);
                }
            }

            if (_udonNodeData.fullName.StartsWithCached("Const"))
            {
                RemoveConnectorAndLabel();
            }
            else if (_udonNodeData.fullName.StartsWithCached("Set_Variable") && _nodeValueIndex == 2)
            {
                _isSendChangePort = true;
                RemoveConnector();
                AddToClassList("send-change");
            }

            AddToClassList(portName);

            UpdateLabel(connected);
        }
示例#9
0
        internal void AddEntries(List <SearchTreeEntry> cache, IEnumerable <UdonNodeDefinition> definitions, int level, bool stripToLastDot = false)
        {
            Texture2D icon = EditorGUIUtility.FindTexture("cs Script Icon");
            Dictionary <string, UdonNodeDefinition> baseNodeDefinition = new Dictionary <string, UdonNodeDefinition>();

            foreach (UdonNodeDefinition nodeDefinition in definitions.OrderBy(s => UdonGraphExtensions.PrettyFullName(s)))
            {
                string   baseIdentifier      = nodeDefinition.fullName;
                string[] splitBaseIdentifier = baseIdentifier.Split(new[] { "__" }, StringSplitOptions.None);
                if (splitBaseIdentifier.Length >= 2)
                {
                    baseIdentifier = $"{splitBaseIdentifier[0]}__{splitBaseIdentifier[1]}";
                }
                if (baseNodeDefinition.ContainsKey(baseIdentifier))
                {
                    continue;
                }
                baseNodeDefinition.Add(baseIdentifier, nodeDefinition);
            }

            // add all subTypes
            foreach (KeyValuePair <string, UdonNodeDefinition> nodeDefinitionsEntry in baseNodeDefinition)
            {
                string nodeName = UdonGraphExtensions.PrettyBaseName(nodeDefinitionsEntry.Key);
                nodeName = nodeName.UppercaseFirst();
                nodeName = nodeName.Replace("_", " ");
                if (stripToLastDot)
                {
                    int lastDotIndex = nodeName.LastIndexOf('.');
                    nodeName = nodeName.Substring(lastDotIndex + 1);
                }

                // don't add Variable or Comment nodes
                if (nodeName.StartsWithCached("Variable") || nodeName.StartsWithCached("Get Var") || nodeName.StartsWithCached("Set Var") || nodeName.StartsWithCached("Comment"))
                {
                    continue;
                }
                if (nodeName.StartsWithCached("Object"))
                {
                    nodeName = $"{nodeDefinitionsEntry.Value.type.Namespace}.{nodeName}";
                }
                cache.Add(new SearchTreeEntry(new GUIContent(nodeName, icon))
                {
                    level = level, userData = nodeDefinitionsEntry.Value
                });
            }
        }
        private void SetupPort()
        {
            this.AddManipulator(m_EdgeConnector);
            if (portType == null || direction == Direction.Output)
            {
                return;
            }
            tooltip = UdonGraphExtensions.FriendlyTypeName(portType);
            var field = GetTheRightField(portType);

            if (field != null)
            {
                Add(field);
            }

            if (_udonNodeData.fullName.StartsWith("Const"))
            {
                RemoveConnector();
            }

            UpdateLabel(connected);
        }
示例#11
0
        override public List <SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
        {
            if (_fullRegistry != null)
            {
                return(_fullRegistry);
            }

            _fullRegistry = new List <SearchTreeEntry>();

            _fullRegistry.Add(new SearchTreeGroupEntry(new GUIContent("Variable Type Search"), 0));

            var definitions = UdonEditorManager.Instance.GetNodeDefinitions("Variable_").ToList().OrderBy(n => n.name);

            foreach (var definition in definitions)
            {
                _fullRegistry.Add(new SearchTreeEntry(new GUIContent(UdonGraphExtensions.FriendlyTypeName(definition.type).FriendlyNameify()))
                {
                    level    = 1,
                    userData = definition.fullName,
                });
            }

            return(_fullRegistry);
        }
        internal void AddEntries(List <SearchTreeEntry> cache, IEnumerable <UdonNodeDefinition> definitions, int level,
                                 bool stripToLastDot = false)
        {
            Texture2D icon = AssetPreview.GetMiniTypeThumbnail(typeof(GameObject));
            Texture2D iconGetComponents = EditorGUIUtility.FindTexture("d_ViewToolZoom");
            Texture2D iconOther         = new Texture2D(1, 1);

            iconOther.SetPixel(0, 0, new Color(0, 0, 0, 0));
            iconOther.Apply();
            Dictionary <string, UdonNodeDefinition> baseNodeDefinition = new Dictionary <string, UdonNodeDefinition>();

            foreach (UdonNodeDefinition nodeDefinition in definitions.OrderBy(
                         s => UdonGraphExtensions.PrettyFullName(s)))
            {
                string   baseIdentifier      = nodeDefinition.fullName;
                string[] splitBaseIdentifier = baseIdentifier.Split(new[] { "__" }, StringSplitOptions.None);
                if (splitBaseIdentifier.Length >= 2)
                {
                    baseIdentifier = $"{splitBaseIdentifier[0]}__{splitBaseIdentifier[1]}";
                }

                if (baseNodeDefinition.ContainsKey(baseIdentifier))
                {
                    continue;
                }

                baseNodeDefinition.Add(baseIdentifier, nodeDefinition);
            }

            var nodesOfGetComponentType = new List <SearchTreeEntry>();
            var nodesOfOtherType        = new List <SearchTreeEntry>();

            // add all subTypes
            foreach (KeyValuePair <string, UdonNodeDefinition> nodeDefinitionsEntry in baseNodeDefinition)
            {
                string nodeName = UdonGraphExtensions.PrettyBaseName(nodeDefinitionsEntry.Key);
                nodeName = nodeName.UppercaseFirst();
                nodeName = nodeName.Replace("_", " ");
                if (stripToLastDot)
                {
                    int lastDotIndex = nodeName.LastIndexOf('.');
                    nodeName = nodeName.Substring(lastDotIndex + 1);
                }

                // Skip some nodes that should be added in other ways (variables and comments)
                if (nodeName.StartsWithCached("Variable") || nodesToSkip.Contains(nodeDefinitionsEntry.Key))
                {
                    continue;
                }

                if (nodeName.StartsWithCached("Object"))
                {
                    nodeName = $"{nodeDefinitionsEntry.Value.type.Namespace}.{nodeName}";
                }

                if (nodeNamesGetComponentType.Contains(nodeName))
                {
                    nodesOfGetComponentType.Add(new SearchTreeEntry(new GUIContent(nodeName, iconGetComponents))
                    {
                        level = level + 1, userData = nodeDefinitionsEntry.Value
                    });
                    continue;
                }

                // Only put 'Equals' in the 'Other' category if this definition is not an Enum
                if (nodeNamesOtherType.Contains(nodeName) || nodeName == "Equals" && !nodeDefinitionsEntry.Value.type.IsEnum)
                {
                    nodesOfOtherType.Add(new SearchTreeEntry(new GUIContent(nodeName, iconOther))
                    {
                        level = level + 1, userData = nodeDefinitionsEntry.Value
                    });
                    continue;
                }

                cache.Add(new SearchTreeEntry(new GUIContent(nodeName, icon))
                {
                    level = level, userData = nodeDefinitionsEntry.Value
                });
            }

            // add getComponents level
            if (nodesOfGetComponentType.Count > 0)
            {
                cache.Add(new SearchTreeGroupEntry(new GUIContent("GetComponents"), level));
                foreach (var entry in nodesOfGetComponentType)
                {
                    cache.Add(entry);
                }
            }

            // add other level
            if (nodesOfOtherType.Count > 0)
            {
                cache.Add(new SearchTreeGroupEntry(new GUIContent("Other"), level));
                foreach (var entry in nodesOfOtherType)
                {
                    cache.Add(entry);
                }
            }
        }
        // 0 = Value, 1 = name, 2 = public, 3 = synced, 4 = syncType
        public UdonParameterProperty(UdonGraph graphView, UdonNodeDefinition definition, UdonNodeData nodeData)
        {
            this.graph      = graphView;
            this.definition = definition;
            this.nodeData   = nodeData;

            // Make sure the incoming nodeData has the right number of nodeValues (super old graphs didn't have sync info)
            if (this.nodeData.nodeValues.Length != 5)
            {
                this.nodeData.nodeValues = GetDefaultNodeValues();
                for (int i = 0; i < nodeData.nodeValues.Length; i++)
                {
                    this.nodeData.nodeValues[i] = nodeData.nodeValues[i];
                }
            }

            // Public Toggle
            isPublic = new EngineUI.Toggle
            {
                text  = "public",
                value = (bool)GetValue(ValueIndices.isPublic)
            };
            isPublic.OnValueChanged(e =>
            {
                SetNewValue(e.newValue, ValueIndices.isPublic);
            });
            Add(isPublic);

            // Is Synced Field
            isSynced = new EngineUI.Toggle
            {
                text  = "synced",
                value = (bool)GetValue(ValueIndices.isSynced),
            };

            isSynced.OnValueChanged(e =>
            {
                SetNewValue(e.newValue, ValueIndices.isSynced);
                syncField.visible = e.newValue;
            });
            Add(isSynced);

            // Sync Field, add to isSynced
            List <string> choices = new List <string>()
            {
                "none", "linear", "smooth"
            };

            syncField = new EditorUI.PopupField <string>(choices, 0)
            {
                visible = isSynced.value
            };
            syncField.OnValueChanged(e =>
            {
                SetNewValue(e.newValue, ValueIndices.syncType);
            });
            isSynced.Add(syncField);

            // Container to show/edit Default Value
            var friendlyName = UdonGraphExtensions.FriendlyTypeName(definition.type).FriendlyNameify();

            defaultValueContainer = new VisualElement
            {
                new Label("default value")
                {
                    name = "default-value-label"
                }
            };
            var field = GetTheRightField(definition.type);

            if (field != null)
            {
                // TODO: need to handle cases where we can't generate the field above
                defaultValueContainer.Add(field);
                Add(defaultValueContainer);
            }
        }
示例#14
0
        // 0 = Value, 1 = name, 2 = public, 3 = synced, 4 = syncType
        public UdonParameterProperty(UdonGraph graphView, UdonNodeDefinition definition, UdonNodeData nodeData)
        {
            this.graph      = graphView;
            this.definition = definition;
            this.nodeData   = nodeData;

            // Make sure the incoming nodeData has the right number of nodeValues (super old graphs didn't have sync info)
            if (this.nodeData.nodeValues.Length != 5)
            {
                this.nodeData.nodeValues = GetDefaultNodeValues();
                for (int i = 0; i < nodeData.nodeValues.Length; i++)
                {
                    this.nodeData.nodeValues[i] = nodeData.nodeValues[i];
                }
            }

            // Public Toggle
            isPublic = new Toggle
            {
                text  = "public",
                value = (bool)GetValue(ValueIndices.isPublic)
            };
#if UNITY_2019_3_OR_NEWER
            isPublic.RegisterValueChangedCallback(
#else
            isPublic.OnValueChanged(
#endif
                e => { SetNewValue(e.newValue, ValueIndices.isPublic); });
            Add(isPublic);

            // Is Synced Field
            isSynced = new Toggle
            {
                text  = "synced",
                value = (bool)GetValue(ValueIndices.isSynced),
            };

#if UNITY_2019_3_OR_NEWER
            isSynced.RegisterValueChangedCallback(
#else
            isSynced.OnValueChanged(
#endif
                e =>
            {
                SetNewValue(e.newValue, ValueIndices.isSynced);
                syncField.visible = e.newValue;
            });
            Add(isSynced);

            // Sync Field, add to isSynced
            List <string> choices = new List <string>()
            {
                "none", "linear", "smooth"
            };
            syncField = new EditorUI.PopupField <string>(choices, 0)
            {
                visible = isSynced.value
            };
#if UNITY_2019_3_OR_NEWER
            syncField.RegisterValueChangedCallback(
#else
            syncField.OnValueChanged(
#endif
                e => { SetNewValue(e.newValue, ValueIndices.syncType); });
            isSynced.Add(syncField);

            // Container to show/edit Default Value
            var friendlyName      = UdonGraphExtensions.FriendlyTypeName(definition.type).FriendlyNameify();
            defaultValueContainer = new VisualElement();
            defaultValueContainer.Add(
                new Label("default value")
            {
                name = "default-value-label"
            });

            // Generate Default Value Field
            var value   = TryGetValueObject(out object result);
            _inputField = UdonFieldFactory.CreateField(
                definition.type,
                result,
                newValue => SetNewValue(newValue, ValueIndices.value)
                );
            if (_inputField != null)
            {
                defaultValueContainer.Add(_inputField);
                Add(defaultValueContainer);
            }
        }
        // 0 = Value, 1 = name, 2 = public, 3 = synced, 4 = syncType
        public UdonParameterProperty(UdonGraph graphView, UdonNodeDefinition definition, UdonNodeData nodeData)
        {
            this.graph      = graphView;
            this.definition = definition;
            this.nodeData   = nodeData;

            string friendlyName = UdonGraphExtensions.FriendlyTypeName(definition.type).FriendlyNameify();

            // Public Toggle
            isPublic = new Toggle
            {
                text  = "public",
                value = (bool)GetValue(ValueIndices.isPublic)
            };
#if UNITY_2019_3_OR_NEWER
            isPublic.RegisterValueChangedCallback(
#else
            isPublic.OnValueChanged(
#endif
                e => { SetNewValue(e.newValue, ValueIndices.isPublic); });
            Add(isPublic);

            if (UdonNetworkTypes.CanSync(definition.type))
            {
                // Is Synced Field
                isSynced = new Toggle
                {
                    text  = "synced",
                    value = (bool)GetValue(ValueIndices.isSynced),
                    name  = "syncToggle",
                };

#if UNITY_2019_3_OR_NEWER
                isSynced.RegisterValueChangedCallback(
#else
                isSynced.OnValueChanged(
#endif
                    e =>
                {
                    SetNewValue(e.newValue, ValueIndices.isSynced);
                    syncField.visible = e.newValue;
                });

                // Sync Field, add to isSynced
                List <string> choices = new List <string>()
                {
                    "none"
                };

                if (UdonNetworkTypes.CanSyncLinear(definition.type))
                {
                    choices.Add("linear");
                }

                if (UdonNetworkTypes.CanSyncSmooth(definition.type))
                {
                    choices.Add("smooth");
                }

                syncField = new EditorUI.PopupField <string>(choices, 0)
                {
                    visible = isSynced.value,
                };
                syncField.Insert(0, new Label("smooth:"));

#if UNITY_2019_3_OR_NEWER
                syncField.RegisterValueChangedCallback(
#else
                syncField.OnValueChanged(
#endif
                    e =>
                {
                    SetNewValue(e.newValue, ValueIndices.syncType);
                });

                // Only show sync smoothing dropdown if there are choices to be made
                if (choices.Count > 1)
                {
                    isSynced.Add(syncField);
                }

                Add(isSynced);
            }
            else
            {
                // Cannot Sync
                SetNewValue(false, ValueIndices.isSynced);
                Add(new Label($"{friendlyName} cannot be synced."));
            }

            // Container to show/edit Default Value
            defaultValueContainer = new VisualElement();
            defaultValueContainer.Add(
                new Label("default value")
            {
                name = "default-value-label"
            });

            // Generate Default Value Field
            var value   = TryGetValueObject(out object result);
            _inputField = UdonFieldFactory.CreateField(
                definition.type,
                result,
                newValue => SetNewValue(newValue, ValueIndices.value)
                );
            if (_inputField != null)
            {
                defaultValueContainer.Add(_inputField);
                Add(defaultValueContainer);
            }
        }