示例#1
0
        public static bool HasCompatibleValueOutput(this IUnitOption option, Type inputType)
        {
            Ensure.That(nameof(inputType)).IsNotNull(inputType);

            foreach (var valueOutputType in option.valueOutputTypes)
            {
                if (ConversionUtility.CanConvert(valueOutputType, inputType, false))
                {
                    return(true);
                }
            }

            return(false);
        }
示例#2
0
        private void _Run(object assigner, object assignee)
        {
            var oldValue = this.assignee.Get(assignee);
            var newValue = ConversionUtility.Convert(this.assigner.Invoke(assigner), this.assignee.type);

            this.assignee.Set(assignee, newValue);

            if (!Equals(oldValue, newValue))
            {
                if (assigner is IAssigner _assigner)
                {
                    _assigner.ValueChanged();
                }
            }
        }
示例#3
0
        private bool CanPredict(ValueInput input)
        {
            if (!input.hasValidConnection)
            {
                if (!TryGetDefaultValue(input, out var defaultValue))
                {
                    return(false);
                }

                if (typeof(Component).IsAssignableFrom(input.type))
                {
                    defaultValue = defaultValue?.ConvertTo(input.type);
                }

                if (!input.allowsNull && defaultValue == null)
                {
                    return(false);
                }

                return(true);
            }

            var output = input.validConnectedPorts.Single();

            if (!CanPredict(output))
            {
                return(false);
            }

            var connectedValue = GetValue(output);

            if (!ConversionUtility.CanConvert(connectedValue, input.type, false))
            {
                return(false);
            }

            if (typeof(Component).IsAssignableFrom(input.type))
            {
                connectedValue = connectedValue?.ConvertTo(input.type);
            }

            if (!input.allowsNull && connectedValue == null)
            {
                return(false);
            }

            return(true);
        }
        private void EnforceType()
        {
            if (metadata.value?.GetType() == type)
            {
                return;
            }

            metadata.UnlinkChildren();

            if (type == null)
            {
                metadata.value = null;
            }
            else if (ConversionUtility.CanConvert(metadata.value, type, true))
            {
                metadata.value = ConversionUtility.Convert(metadata.value, type);
            }
            else
            {
                metadata.value = type.TryInstantiate();
            }

            metadata.InferOwnerFromParent();
        }
示例#5
0
 public static object GetValue(this IGettable gettable, Type type)
 {
     return(ConversionUtility.Convert(gettable.GetValue(), type));
 }
示例#6
0
        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."));
            }
        }
示例#7
0
 public static object Predict(IUnitValuePort port, GraphReference reference, Type type)
 {
     return(ConversionUtility.Convert(Predict(port, reference), type));
 }
示例#8
0
 public static object FetchValue(ValueInput input, Type type, GraphReference reference)
 {
     return(ConversionUtility.Convert(FetchValue(input, reference), type));
 }
示例#9
0
 public object GetValue(ValueInput input, Type type)
 {
     return(ConversionUtility.Convert(GetValue(input), type));
 }
        public virtual object Operate(object leftOperand, object rightOperand)
        {
            OperatorQuery query;

            var leftType  = leftOperand?.GetType();
            var rightType = rightOperand?.GetType();

            if (leftType != null && rightType != null)
            {
                query = new OperatorQuery(leftType, rightType);
            }
            else if (leftType != null && leftType.IsNullable())
            {
                query = new OperatorQuery(leftType, leftType);
            }
            else if (rightType != null && rightType.IsNullable())
            {
                query = new OperatorQuery(rightType, rightType);
            }
            else if (leftType == null && rightType == null)
            {
                return(BothNullHandling());
            }
            else
            {
                return(SingleNullHandling());
            }

            if (handlers.ContainsKey(query))
            {
                return(handlers[query](leftOperand, rightOperand));
            }

            if (customMethodName != null)
            {
                if (!userDefinedOperators.ContainsKey(query))
                {
                    var leftMethod = query.leftType.GetMethod(customMethodName, BindingFlags.Public | BindingFlags.Static, null, new[] { query.leftType, query.rightType }, null);

                    if (query.leftType != query.rightType)
                    {
                        var rightMethod = query.rightType.GetMethod(customMethodName, BindingFlags.Public | BindingFlags.Static, null, new[] { query.leftType, query.rightType }, null);

                        if (leftMethod != null && rightMethod != null)
                        {
                            throw new AmbiguousOperatorException(symbol, query.leftType, query.rightType);
                        }

                        var method = (leftMethod ?? rightMethod);

                        if (method != null)
                        {
                            userDefinedOperandTypes.Add(query, ResolveUserDefinedOperandTypes(method));
                        }

                        userDefinedOperators.Add(query, method?.Prewarm());
                    }
                    else
                    {
                        if (leftMethod != null)
                        {
                            userDefinedOperandTypes.Add(query, ResolveUserDefinedOperandTypes(leftMethod));
                        }

                        userDefinedOperators.Add(query, leftMethod?.Prewarm());
                    }
                }

                if (userDefinedOperators[query] != null)
                {
                    leftOperand  = ConversionUtility.Convert(leftOperand, userDefinedOperandTypes[query].leftType);
                    rightOperand = ConversionUtility.Convert(rightOperand, userDefinedOperandTypes[query].rightType);

                    return(userDefinedOperators[query].Invoke(null, leftOperand, rightOperand));
                }
            }

            return(CustomHandling(leftOperand, rightOperand));
        }