sealed protected override VFXExpression ConvertExpression(VFXExpression expression, VFXSlot sourceSlot)
        {
            if (expression.valueType == VFXValueType.Float2)
            {
                return(expression);
            }

            if (expression.valueType == VFXValueType.Float)
            {
                return(new VFXExpressionCombine(expression, expression));
            }

            if (expression.valueType == VFXValueType.Uint32)
            {
                var floatExpression = new VFXExpressionCastUintToFloat(expression);
                return(new VFXExpressionCombine(floatExpression, floatExpression));
            }

            if (expression.valueType == VFXValueType.Int32)
            {
                var floatExpression = new VFXExpressionCastIntToFloat(expression);
                return(new VFXExpressionCombine(floatExpression, floatExpression));
            }

            if (expression.valueType == VFXValueType.Float3 || expression.valueType == VFXValueType.Float4)
            {
                return(new VFXExpressionCombine(expression.x, expression.y));
            }

            throw new Exception("Unexpected type of expression " + expression);
        }
        static public VFXExpression Sequential3D(VFXExpression origin, VFXExpression axisX, VFXExpression axisY, VFXExpression axisZ, VFXExpression index, VFXExpression countX, VFXExpression countY, VFXExpression countZ)
        {
            index = VFXOperatorUtility.Modulo(index, countX * countY * countZ);
            var z = new VFXExpressionCastUintToFloat(VFXOperatorUtility.Modulo(index, countZ));
            var y = new VFXExpressionCastUintToFloat(VFXOperatorUtility.Modulo(index / countZ, countY));
            var x = new VFXExpressionCastUintToFloat(index / (countY * countZ));

            VFXExpression volumeSize = new VFXExpressionCombine(new VFXExpressionCastUintToFloat(countX), new VFXExpressionCastUintToFloat(countY), new VFXExpressionCastUintToFloat(countZ));

            volumeSize = volumeSize - VFXOperatorUtility.OneExpression[VFXValueType.Float3];
            var scaleAxisZero = Saturate(volumeSize); //Handle special case for one count => lead to be centered on origin (instead of -axis)

            volumeSize = new VFXExpressionMax(volumeSize, VFXOperatorUtility.OneExpression[VFXValueType.Float3]);
            var dt = new VFXExpressionCombine(x, y, z) / volumeSize;

            dt = dt * VFXOperatorUtility.TwoExpression[VFXValueType.Float3] - VFXOperatorUtility.OneExpression[VFXValueType.Float3];

            var r = origin;

            r += dt.xxx * scaleAxisZero.xxx * axisX;
            r += dt.yyy * scaleAxisZero.yyy * axisY;
            r += dt.zzz * scaleAxisZero.zzz * axisZ;

            return(r);
        }
        static public VFXExpression ConvertExpressionToVector3(VFXExpression expression)
        {
            if (expression.valueType == VFXValueType.Float3)
            {
                return(expression);
            }

            if (expression.valueType == VFXValueType.Float)
            {
                return(new VFXExpressionCombine(expression, expression, expression));
            }

            if (expression.valueType == VFXValueType.Uint32)
            {
                var floatExpression = new VFXExpressionCastUintToFloat(expression);
                return(new VFXExpressionCombine(floatExpression, floatExpression, floatExpression));
            }

            if (expression.valueType == VFXValueType.Int32)
            {
                var floatExpression = new VFXExpressionCastIntToFloat(expression);
                return(new VFXExpressionCombine(floatExpression, floatExpression, floatExpression));
            }

            if (expression.valueType == VFXValueType.Float4)
            {
                return(new VFXExpressionCombine(expression.x, expression.y, expression.z));
            }

            throw new Exception("Unexpected type of expression " + expression + "valueType" + expression.valueType);
        }
        static public VFXExpression SequentialLine(VFXExpression start, VFXExpression end, VFXExpression index, VFXExpression count)
        {
            VFXExpression dt = new VFXExpressionCastUintToFloat(VFXOperatorUtility.Modulo(index, count));

            dt = dt / new VFXExpressionCastUintToFloat(count);
            dt = new VFXExpressionCombine(dt, dt, dt);
            return(VFXOperatorUtility.Lerp(start, end, dt));
        }
        static public VFXExpression SequentialLine(VFXExpression start, VFXExpression end, VFXExpression index, VFXExpression count)
        {
            VFXExpression dt   = new VFXExpressionCastUintToFloat(VFXOperatorUtility.Modulo(index, count));
            var           size = new VFXExpressionCastUintToFloat(count) - VFXOperatorUtility.OneExpression[VFXValueType.Float];

            size = new VFXExpressionMax(size, VFXOperatorUtility.OneExpression[VFXValueType.Float]);
            dt   = dt / size;
            dt   = new VFXExpressionCombine(dt, dt, dt);
            return(VFXOperatorUtility.Lerp(start, end, dt));
        }
        protected override IEnumerable <VFXExpression> ApplyPatchInputExpression(IEnumerable <VFXExpression> inputExpression)
        {
            var minIndex    = inputExpression.Select(o => Array.IndexOf(kExpectedTypeOrdering, VFXExpression.TypeToType(o.valueType))).Min();
            var unifiedType = VFXExpression.GetVFXValueTypeFromType(kExpectedTypeOrdering[minIndex]);

            foreach (var expression in inputExpression)
            {
                if (expression.valueType == unifiedType)
                {
                    yield return(expression);

                    continue;
                }

                var currentExpression = expression;
                if (VFXExpression.IsFloatValueType(unifiedType))
                {
                    if (VFXExpression.IsUIntValueType(expression.valueType))
                    {
                        currentExpression = new VFXExpressionCastUintToFloat(currentExpression);
                    }
                    else if (VFXExpression.IsIntValueType(expression.valueType))
                    {
                        currentExpression = new VFXExpressionCastIntToFloat(currentExpression);
                    }
                    currentExpression = VFXOperatorUtility.CastFloat(currentExpression, unifiedType, identityValueFloat);
                }
                else if (VFXExpression.IsIntValueType(unifiedType))
                {
                    if (VFXExpression.IsUIntValueType(currentExpression.valueType))
                    {
                        currentExpression = new VFXExpressionCastUintToInt(currentExpression);
                    }
                    else if (VFXExpression.IsFloatValueType(currentExpression.valueType))
                    {
                        currentExpression = new VFXExpressionCastFloatToInt(VFXOperatorUtility.ExtractComponents(currentExpression).First());
                    }
                }
                else if (VFXExpression.IsUIntValueType(unifiedType))
                {
                    if (VFXExpression.IsIntValueType(currentExpression.valueType))
                    {
                        currentExpression = new VFXExpressionCastIntToUint(currentExpression);
                    }
                    else if (VFXExpression.IsFloatValueType(expression.valueType))
                    {
                        currentExpression = new VFXExpressionCastFloatToUint(VFXOperatorUtility.ExtractComponents(expression).First());
                    }
                }
                yield return(currentExpression);
            }
        }
        static public VFXExpression SequentialCircle(VFXExpression center, VFXExpression radius, VFXExpression normal, VFXExpression up, VFXExpression index, VFXExpression count)
        {
            VFXExpression dt = new VFXExpressionCastUintToFloat(VFXOperatorUtility.Modulo(index, count));

            dt = dt / new VFXExpressionCastUintToFloat(count);

            var cos  = new VFXExpressionCos(dt * VFXOperatorUtility.TauExpression[VFXValueType.Float]) as VFXExpression;
            var sin  = new VFXExpressionSin(dt * VFXOperatorUtility.TauExpression[VFXValueType.Float]) as VFXExpression;
            var left = VFXOperatorUtility.Normalize(VFXOperatorUtility.Cross(normal, up));

            radius = new VFXExpressionCombine(radius, radius, radius);
            sin    = new VFXExpressionCombine(sin, sin, sin);
            cos    = new VFXExpressionCombine(cos, cos, cos);

            return(center + (cos * up + sin * left) * radius);
        }
        sealed protected override VFXExpression ConvertExpression(VFXExpression expression, VFXSlot sourceSlot)
        {
            if (expression.valueType == VFXValueType.Uint32)
            {
                var floatExpression = new VFXExpressionCastUintToFloat(expression);
                return(floatExpression);
            }

            if (expression.valueType == VFXValueType.Int32)
            {
                var floatExpression = new VFXExpressionCastIntToFloat(expression);
                return(floatExpression);
            }

            return(expression);
        }
        static public VFXExpression SequentialCircle(VFXExpression center, VFXExpression radius, VFXExpression normal, VFXExpression up, VFXExpression index, VFXExpression count, SequentialAddressingMode mode)
        {
            VFXExpression countForAddressing = count;

            if (mode == SequentialAddressingMode.Clamp || mode == SequentialAddressingMode.Mirror)
            {
                //Explicitly close the circle loop, if `index` equals to `count`, adds an extra step.
                countForAddressing = count + OneExpression[VFXValueType.Uint32];
            }
            VFXExpression dt = ApplyAddressingMode(index, countForAddressing, mode);

            dt = new VFXExpressionCastUintToFloat(dt);
            dt = dt / new VFXExpressionCastUintToFloat(count);

            var cos  = new VFXExpressionCos(dt * VFXOperatorUtility.TauExpression[VFXValueType.Float]) as VFXExpression;
            var sin  = new VFXExpressionSin(dt * VFXOperatorUtility.TauExpression[VFXValueType.Float]) as VFXExpression;
            var left = VFXOperatorUtility.Normalize(VFXOperatorUtility.Cross(normal, up));

            radius = new VFXExpressionCombine(radius, radius, radius);
            sin    = new VFXExpressionCombine(sin, sin, sin);
            cos    = new VFXExpressionCombine(cos, cos, cos);

            return(center + (cos * up + sin * left) * radius);
        }