public override void WillCreateLink(ref VFXSlot myInput, ref VFXSlot otherOutput)
        {
            if (!myInput.IsMasterSlot())
            {
                return;
            }
            //Since every input will change at the same time the metric to change is :
            // if we have no input links yet

            var  myInputCopy = myInput;
            bool hasLink     = inputPorts.Any(t => t.model != myInputCopy && t.model.HasLink());
            int  index       = model.GetSlotIndex(myInput);

            if (model.staticSlotIndex.Contains(index))
            {
                return;
            }

            // The new link is impossible if we don't change (case of a vector3 trying to be linked to a vector4)
            bool linkImpossibleNow = !myInput.CanLink(otherOutput) || !otherOutput.CanLink(myInput);

            var bestAffinity = model.GetBestAffinityType(otherOutput.property.type);

            if ((!hasLink || linkImpossibleNow) && bestAffinity != null)
            {
                model.SetOperandType(bestAffinity);
                myInput = model.GetInputSlot(index);
            }
        }
        public override void WillCreateLink(ref VFXSlot myInput, ref VFXSlot otherOutput)
        {
            if (!myInput.IsMasterSlot())
            {
                return;
            }
            int inputIndex = model.GetSlotIndex(myInput);
            IVFXOperatorNumericUnifiedConstrained constraintInterface = model as IVFXOperatorNumericUnifiedConstrained;

            if (!constraintInterface.slotIndicesThatMustHaveSameType.Contains(inputIndex))
            {
                base.WillCreateLink(ref myInput, ref otherOutput);
                return;
            }

            bool scalar = constraintInterface.slotIndicesThatCanBeScalar.Contains(inputIndex);

            if (scalar)
            {
                var bestAffinityType = model.GetBestAffinityType(otherOutput.property.type);

                VFXSlot otherSlotWithConstraint = model.inputSlots.Where((t, i) => constraintInterface.slotIndicesThatMustHaveSameType.Contains(i)).FirstOrDefault();

                if (otherSlotWithConstraint == null || otherSlotWithConstraint.property.type == bestAffinityType)
                {
                    model.SetOperandType(inputIndex, bestAffinityType);
                    myInput = model.GetInputSlot(inputIndex);
                }
                else if (!myInput.CanLink(otherOutput) || !otherOutput.CanLink(myInput))  // if the link is invalid if we don't change the type, change the type to the matching scalar
                {
                    var bestScalarAffinityType = model.GetBestAffinityType(GetMatchingScalar(otherOutput.property.type));
                    if (bestScalarAffinityType != null)
                    {
                        model.SetOperandType(inputIndex, bestScalarAffinityType);
                        myInput = model.GetInputSlot(inputIndex);
                    }
                }
                return; // never change the type of other constraint if the linked slot is scalar
            }

            VFXSlot input = myInput;

            bool hasLinks = model.inputSlots.Where((t, i) => t != input && t.HasLink(true) && constraintInterface.slotIndicesThatMustHaveSameType.Contains(i) && !constraintInterface.slotIndicesThatCanBeScalar.Contains(i)).Count() > 0;

            bool linkPossible = myInput.CanLink(otherOutput) && otherOutput.CanLink(myInput);

            if (!hasLinks || !linkPossible)  //Change the type if other type having the same constraint have no link or if the link will fail if we don't
            {
                var bestAffinityType = model.GetBestAffinityType(otherOutput.property.type);
                if (bestAffinityType != null)
                {
                    foreach (int slotIndex in constraintInterface.slotIndicesThatMustHaveSameType)
                    {
                        if (!constraintInterface.slotIndicesThatCanBeScalar.Contains(slotIndex) || GetMatchingScalar(bestAffinityType) != model.GetInputSlot(slotIndex).property.type)
                        {
                            model.SetOperandType(slotIndex, bestAffinityType);
                        }
                    }

                    myInput = model.GetInputSlot(inputIndex);
                }
            }
        }
        bool ProviderFilter(VFXNodeProvider.Descriptor d)
        {
            var mySlot = controller.model;

            IEnumerable <Type> validTypes = null;

            if (mySlot == null)
            {
                var op = controller.sourceNode.model as VFXOperatorNumericCascadedUnified;
                if (op != null)
                {
                    validTypes = op.validTypes;
                }
            }
            var parameterDescriptor     = d.modelDescriptor as VFXParameterController;
            IVFXSlotContainer container = null;

            if (parameterDescriptor != null)
            {
                container = parameterDescriptor.model;
            }
            else
            {
                VFXModelDescriptor desc = d.modelDescriptor as VFXModelDescriptor;
                if (desc == null)
                {
                    return(false);
                }

                container = desc.model as IVFXSlotContainer;
                if (container == null)
                {
                    return(false);
                }
            }

            var getSlots = direction == Direction.Input ? (System.Func <int, VFXSlot>)container.GetOutputSlot : (System.Func <int, VFXSlot>)container.GetInputSlot;

            int count = direction == Direction.Input ? container.GetNbOutputSlots() : container.GetNbInputSlots();

            bool oneFound = false;

            for (int i = 0; i < count; ++i)
            {
                VFXSlot slot = getSlots(i);

                if (mySlot != null)
                {
                    if (slot.CanLink(mySlot))
                    {
                        oneFound = true;
                        break;
                    }
                }
                else if (validTypes != null)
                {
                    if (validTypes.Contains(slot.property.type))
                    {
                        oneFound = true;
                        break;
                    }
                }
            }

            return(oneFound);
        }