public IEnumerable <string> GetDynamicVariableNames(VariableKind kind, GraphReference reference) { return(units.OfType <IUnifiedVariableUnit>() .Where(v => v.kind == kind && Flow.CanPredict(v.name, reference)) .Select(v => Flow.Predict <string>(v.name, reference)) .Where(name => !StringUtility.IsNullOrWhiteSpace(name)) .Distinct() .OrderBy(name => name)); }
public override void DrawForeground() { base.DrawForeground(); if (BoltFlow.Configuration.showConnectionValues) { var showLastValue = EditorApplication.isPlaying && ConnectionDebugData.assignedLastValue; var showPredictedvalue = BoltFlow.Configuration.predictConnectionValues && !EditorApplication.isPlaying && Flow.CanPredict(connection.source, reference); if (showLastValue || showPredictedvalue) { var previousIconSize = EditorGUIUtility.GetIconSize(); EditorGUIUtility.SetIconSize(new Vector2(IconSize.Small, IconSize.Small)); object value; if (showLastValue) { value = ConnectionDebugData.lastValue; } else // if (showPredictedvalue) { value = Flow.Predict(connection.source, reference); } var label = new GUIContent(value.ToShortString(), Icons.Type(value?.GetType())?[IconSize.Small]); var labelSize = Styles.prediction.CalcSize(label); var labelPosition = new Rect(position.position - labelSize / 2, labelSize); BeginDim(); GUI.Label(labelPosition, label, Styles.prediction); EndDim(); EditorGUIUtility.SetIconSize(previousIconSize); } } }
private IEnumerable <Warning> ValueInputWarnings(ValueInput valueInput) { // We can disable null reference check if no self is available // and the port requires an owner, for example in macros. var trustFutureOwner = valueInput.nullMeansSelf && reference.self == null; var checkForNullReference = BoltFlow.Configuration.predictPotentialNullReferences && !valueInput.allowsNull && !trustFutureOwner; var checkForMissingComponent = BoltFlow.Configuration.predictPotentialMissingComponents && typeof(Component).IsAssignableFrom(valueInput.type); // Note that we cannot directly check the input's predicted value, because it // will return false for safeguard specifically because it might be missing requirements. // Therefore, we first check the connected value, then the default value. // If the port is connected to a predictable output, use the connected value to perform checks. if (valueInput.hasValidConnection) { var valueOutput = valueInput.validConnectedPorts.Single(); if (Flow.CanPredict(valueOutput, reference)) { if (checkForNullReference) { if (Flow.Predict(valueOutput, reference) == null) { yield return(Warning.Severe($"{PortLabel(valueInput)} cannot be null.")); } } if (checkForMissingComponent) { var connectedPredictedValue = Flow.Predict(valueOutput, reference); // This check is necessary, because the predicted value could be // incompatible as connections with non-guaranteed conversions are allowed. if (ConversionUtility.CanConvert(connectedPredictedValue, typeof(GameObject), true)) { var gameObject = ConversionUtility.Convert <GameObject>(connectedPredictedValue); if (gameObject != null) { var component = (Component)ConversionUtility.Convert(gameObject, valueInput.type); if (component == null) { yield return(Warning.Caution($"{PortLabel(valueInput)} is missing a {valueInput.type.DisplayName()} component.")); } } } } } } // If the port isn't connected but has a default value, use the default value to perform checks. else if (valueInput.hasDefaultValue) { if (checkForNullReference) { if (Flow.Predict(valueInput, reference) == null) { yield return(Warning.Severe($"{PortLabel(valueInput)} cannot be null.")); } } if (checkForMissingComponent) { var unconnectedPredictedValue = Flow.Predict(valueInput, reference); if (ConversionUtility.CanConvert(unconnectedPredictedValue, typeof(GameObject), true)) { var gameObject = ConversionUtility.Convert <GameObject>(unconnectedPredictedValue); if (gameObject != null) { var component = (Component)ConversionUtility.Convert(gameObject, valueInput.type); if (component == null) { yield return(Warning.Caution($"{PortLabel(valueInput)} is missing a {valueInput.type.DisplayName()} component.")); } } } } } // The value isn't connected and has no default value, // therefore it is certain to be missing at runtime. else { yield return(Warning.Severe($"{PortLabel(valueInput)} is missing.")); } }