示例#1
0
        static AdditionalCommandDescriptor GenerateFragInputs(VFXContext context, VFXContextCompiledData contextData)
        {
            var builder = new ShaderStringBuilder();

            // VFX Material Properties
            var expressionToName = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));

            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            var mainParameters = contextData.gpuMapper.CollectExpression(-1).ToArray();

            foreach (string fragmentParameter in context.fragmentParameters)
            {
                var filteredNamedExpression = mainParameters.FirstOrDefault(o => fragmentParameter == o.name);

                if (filteredNamedExpression.exp != null)
                {
                    var type = VFXExpression.TypeToType(filteredNamedExpression.exp.valueType);

                    if (!kVFXShaderValueTypeMap.TryGetValue(type, out var shaderValueType))
                    {
                        continue;
                    }

                    builder.AppendLine($"{shaderValueType.ToShaderString("float")} {filteredNamedExpression.name};");
                }
            }

            return(new AdditionalCommandDescriptor("FragInputsVFX", builder.ToString()));
        }
示例#2
0
        static FieldDescriptor VFXAttributeToFieldDescriptor(VFXAttribute attribute)
        {
            var type = VFXExpression.TypeToType(attribute.type);

            if (!kVFXShaderValueTypeMap.TryGetValue(type, out var shaderValueType))
            {
                return(null);
            }

            return(new FieldDescriptor("Attributes", attribute.name, "", shaderValueType));
        }
示例#3
0
        // A key difference between Material Shader and VFX Shader generation is how surface properties are provided. Material Shaders
        // simply provide properties via UnityPerMaterial cbuffer. VFX expects these same properties to be computed in the vertex
        // stage (because we must evaluate them with the VFX blocks), and packed with the interpolators for the fragment stage.
        static StructDescriptor AppendVFXInterpolator(StructDescriptor interpolator, VFXContext context, VFXContextCompiledData contextData)
        {
            var fields = interpolator.fields.ToList();

            var expressionToName = context.GetData().GetAttributes().ToDictionary(o => new VFXAttributeExpression(o.attrib) as VFXExpression, o => (new VFXAttributeExpression(o.attrib)).GetCodeString(null));

            expressionToName = expressionToName.Union(contextData.uniformMapper.expressionToCode).ToDictionary(s => s.Key, s => s.Value);

            var mainParameters = contextData.gpuMapper.CollectExpression(-1).ToArray();

            // Warning/TODO: FragmentParameters are created from the ShaderGraphVfxAsset.
            // We may ultimately need to move this handling of VFX Interpolators + SurfaceDescriptionFunction function signature directly into the SG Generator (since it knows about the exposed properties).
            foreach (string fragmentParameter in context.fragmentParameters)
            {
                var filteredNamedExpression = mainParameters.FirstOrDefault(o => fragmentParameter == o.name &&
                                                                            !(expressionToName.ContainsKey(o.exp) && expressionToName[o.exp] == o.name)); // if parameter already in the global scope, there's nothing to do

                if (filteredNamedExpression.exp != null)
                {
                    var type = VFXExpression.TypeToType(filteredNamedExpression.exp.valueType);

                    if (!kVFXShaderValueTypeMap.TryGetValue(type, out var shaderValueType))
                    {
                        continue;
                    }

                    // TODO: NoInterpolation only for non-strips.
                    fields.Add(new FieldDescriptor(HDStructFields.VaryingsMeshToPS.name, filteredNamedExpression.name, "", shaderValueType, subscriptOptions: StructFieldOptions.Static, interpolation: "nointerpolation"));
                }
            }

            // VFX Object Space Interpolators
            fields.Add(HDStructFields.VaryingsMeshToPS.worldToElement0);
            fields.Add(HDStructFields.VaryingsMeshToPS.worldToElement1);
            fields.Add(HDStructFields.VaryingsMeshToPS.worldToElement2);

            fields.Add(HDStructFields.VaryingsMeshToPS.elementToWorld0);
            fields.Add(HDStructFields.VaryingsMeshToPS.elementToWorld1);
            fields.Add(HDStructFields.VaryingsMeshToPS.elementToWorld2);

            interpolator.fields = fields.ToArray();
            return(interpolator);
        }
示例#4
0
        public IEnumerator Create_Prefab_Several_Override()
        {
            var graph             = VFXTestCommon.MakeTemporaryGraph();
            var parametersIntDesc = VFXLibrary.GetParameters().Where(o => o.model.type == typeof(int)).First();

            Func <VisualEffect, string> dumpPropertySheetInteger = delegate(VisualEffect target)
            {
                var r = "{";

                var editor = Editor.CreateEditor(target);
                editor.serializedObject.Update();

                var propertySheet = editor.serializedObject.FindProperty("m_PropertySheet");
                var fieldName     = VisualEffectSerializationUtility.GetTypeField(VFXExpression.TypeToType(VFXValueType.Int32)) + ".m_Array";
                var vfxField      = propertySheet.FindPropertyRelative(fieldName);

                for (int i = 0; i < vfxField.arraySize; ++i)
                {
                    var itField    = vfxField.GetArrayElementAtIndex(i);
                    var name       = itField.FindPropertyRelative("m_Name").stringValue;
                    var value      = itField.FindPropertyRelative("m_Value").intValue;
                    var overridden = itField.FindPropertyRelative("m_Overridden").boolValue;

                    r += string.Format("({0}, {1}, {2})", name, value, overridden);
                    if (i != vfxField.arraySize - 1)
                    {
                        r += ", ";
                    }
                }

                GameObject.DestroyImmediate(editor);
                r += "}";
                return(r);
            };

            var log = string.Empty;
            var exposedProperties = new[] { "a", "b", "c" };

            for (var i = 0; i < exposedProperties.Length; ++i)
            {
                var parameter = parametersIntDesc.CreateInstance();
                parameter.SetSettingValue("m_ExposedName", exposedProperties[i]);
                parameter.SetSettingValue("m_Exposed", true);
                parameter.value = i + 1;
                graph.AddChild(parameter);
            }

            AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(graph));

            var mainObject = MakeTemporaryGameObject();
            var vfx        = mainObject.AddComponent <VisualEffect>();

            vfx.visualEffectAsset = graph.visualEffectResource.asset;

            GameObject newGameObject, prefabInstanceObject;

            MakeTemporaryPrebab(mainObject, out newGameObject, out prefabInstanceObject);
            GameObject.DestroyImmediate(mainObject);
            yield return(null);

            var currentPrefabInstanceObject = PrefabUtility.InstantiatePrefab(prefabInstanceObject) as GameObject;

            var overridenParametersInScene  = new[] { new { name = "b", value = 666 }, new { name = "a", value = 444 } };
            var overridenParametersInPrefab = new[] { new { name = "c", value = -123 } };

            log += "Initial Sheet\n";
            log += "Prefab : " + dumpPropertySheetInteger(prefabInstanceObject.GetComponent <VisualEffect>()) + "\n";
            log += "Instance  : " + dumpPropertySheetInteger(currentPrefabInstanceObject.GetComponent <VisualEffect>()) + "\n";
            yield return(null);

            foreach (var overridenParameter in overridenParametersInScene)
            {
                currentPrefabInstanceObject.GetComponent <VisualEffect>().SetInt(overridenParameter.name, overridenParameter.value);
            }

            log += "\nIntermediate Sheet\n";
            log += "Prefab : " + dumpPropertySheetInteger(prefabInstanceObject.GetComponent <VisualEffect>()) + "\n";
            log += "Instance  : " + dumpPropertySheetInteger(currentPrefabInstanceObject.GetComponent <VisualEffect>()) + "\n";
            yield return(null);

            foreach (var overridenParameter in overridenParametersInPrefab)
            {
                prefabInstanceObject.GetComponent <VisualEffect>().SetInt(overridenParameter.name, overridenParameter.value);
            }

            yield return(null);

            log += "\nEnd Sheet\n";
            log += "Prefab : " + dumpPropertySheetInteger(prefabInstanceObject.GetComponent <VisualEffect>()) + "\n";
            log += "Instance  : " + dumpPropertySheetInteger(currentPrefabInstanceObject.GetComponent <VisualEffect>()) + "\n";

            var stringFormat   = @"({0} : {1}) ";
            var expectedValues = string.Empty;

            for (var i = 0; i < exposedProperties.Length; ++i)
            {
                var expectedValue    = i;
                var expectedName     = exposedProperties[i];
                var overrideInPrefab = overridenParametersInPrefab.FirstOrDefault(o => o.name == exposedProperties[i]);
                var overrideInScene  = overridenParametersInScene.FirstOrDefault(o => o.name == exposedProperties[i]);

                if (overrideInPrefab != null)
                {
                    expectedValue = overrideInPrefab.value;
                }

                if (overrideInScene != null)
                {
                    expectedValue = overrideInScene.value;
                }

                expectedValues += string.Format(stringFormat, expectedName, expectedValue);
            }

            var actualValues = string.Empty;

            for (var i = 0; i < exposedProperties.Length; ++i)
            {
                var expectedName = exposedProperties[i];
                var actualValue  = currentPrefabInstanceObject.GetComponent <VisualEffect>().GetInt(expectedName);
                actualValues += string.Format(stringFormat, expectedName, actualValue);
            }

            if (k_HasFixed_Several_PrefabOverride)
            {
                Assert.AreEqual(expectedValues, actualValues, log);
            }
            else
            {
                Assert.AreNotEqual(expectedValues, actualValues, log); //Did you fixed it ? Should enable this test : k_HasFixed_Several_PrefabOverride
            }
            yield return(null);
        }
示例#5
0
        public IEnumerator Create_Prefab_Modify_And_Expect_No_Override()
        {
            var graph = VFXTestCommon.MakeTemporaryGraph();
            var parametersVector3Desc = VFXLibrary.GetParameters().Where(o => o.model.type == typeof(Vector3)).First();

            var exposedName = "ghjkl";
            var parameter   = parametersVector3Desc.CreateInstance();

            parameter.SetSettingValue("m_ExposedName", exposedName);
            parameter.SetSettingValue("m_Exposed", true);
            parameter.value = new Vector3(0, 0, 0);
            graph.AddChild(parameter);

            AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(graph));

            var mainObject = MakeTemporaryGameObject();

            var vfx = mainObject.AddComponent <VisualEffect>();

            vfx.visualEffectAsset = graph.visualEffectResource.asset;
            Assert.IsTrue(vfx.HasVector3(exposedName));
            vfx.SetVector3(exposedName, new Vector3(1, 2, 3));

            GameObject newGameObject, prefabInstanceObject;

            MakeTemporaryPrebab(mainObject, out newGameObject, out prefabInstanceObject);
            GameObject.DestroyImmediate(mainObject);

            var currentPrefabInstanceObject = PrefabUtility.InstantiatePrefab(prefabInstanceObject) as GameObject;

            yield return(null);

            var vfxInPrefab      = prefabInstanceObject.GetComponent <VisualEffect>();
            var expectedNewValue = new Vector3(4, 5, 6);

            if (k_HasFixed_DisabledState)
            {
                Assert.IsTrue(vfxInPrefab.HasVector3(exposedName));
                vfxInPrefab.SetVector3(exposedName, expectedNewValue);
            }
            else
            {
                /* modifying prefab using serialized property */
                var editor = Editor.CreateEditor(vfxInPrefab);
                editor.serializedObject.Update();

                var propertySheet = editor.serializedObject.FindProperty("m_PropertySheet");
                var fieldName     = VisualEffectSerializationUtility.GetTypeField(VFXExpression.TypeToType(VFXValueType.Float3)) + ".m_Array";
                var vfxField      = propertySheet.FindPropertyRelative(fieldName);

                Assert.AreEqual(1, vfxField.arraySize);

                var property = vfxField.GetArrayElementAtIndex(0);
                property = property.FindPropertyRelative("m_Value");

                property.vector3Value = expectedNewValue;

                editor.serializedObject.ApplyModifiedPropertiesWithoutUndo();
                GameObject.DestroyImmediate(editor);
                EditorUtility.SetDirty(prefabInstanceObject);
            }
            //AssetDatabase.SaveAssets(); //Helps debug but not necessary

            PrefabUtility.SavePrefabAsset(prefabInstanceObject);
            yield return(null);

            var currentVFXInstanciedFromPrefab = currentPrefabInstanceObject.GetComponent <VisualEffect>();

            Assert.IsTrue(currentVFXInstanciedFromPrefab.HasVector3(exposedName));
            var refExposedValue = currentVFXInstanciedFromPrefab.GetVector3(exposedName);

            var newInstanciedFromPrefab    = PrefabUtility.InstantiatePrefab(prefabInstanceObject) as GameObject;
            var newVFXInstanciedFromPrefab = newInstanciedFromPrefab.GetComponent <VisualEffect>();

            Assert.IsTrue(newVFXInstanciedFromPrefab.HasVector3(exposedName));
            var newExposedValue = newVFXInstanciedFromPrefab.GetVector3(exposedName);

            var overrides = PrefabUtility.GetObjectOverrides(currentPrefabInstanceObject);

            Assert.AreEqual(newExposedValue.x, expectedNewValue.x); Assert.AreEqual(newExposedValue.y, expectedNewValue.y); Assert.AreEqual(newExposedValue.z, expectedNewValue.z); //< Expected to work
            if (k_HasFixed_PrefabOverride)
            {
                //Known issue : Failing due to fogbugz 1117103
                Assert.AreEqual(refExposedValue.x, expectedNewValue.x); Assert.AreEqual(refExposedValue.y, expectedNewValue.y); Assert.AreEqual(refExposedValue.z, expectedNewValue.z);
                Assert.IsEmpty(overrides);
            }
        }
        public IEnumerator CreateComponentWithAllBasicTypeExposed([ValueSource("linkModes")] bool linkMode, [ValueSource("bindingModes")] bool bindingModes)
        {
            var commonBaseName = "abcd_";

            Func <Type, object> GetValue_A_Type = delegate(Type type)
            {
                if (typeof(float) == type)
                {
                    return(2.0f);
                }
                else if (typeof(Vector2) == type)
                {
                    return(new Vector2(3.0f, 4.0f));
                }
                else if (typeof(Vector3) == type)
                {
                    return(new Vector3(8.0f, 9.0f, 10.0f));
                }
                else if (typeof(Vector4) == type)
                {
                    return(new Vector4(11.0f, 12.0f, 13.0f, 14.0f));
                }
                else if (typeof(Color) == type)
                {
                    return(new Color(0.1f, 0.2f, 0.3f, 0.4f));
                }
                else if (typeof(int) == type)
                {
                    return(15);
                }
                else if (typeof(uint) == type)
                {
                    return(16u);
                }
                else if (typeof(AnimationCurve) == type)
                {
                    return(new AnimationCurve(new Keyframe(0, 13), new Keyframe(1, 14)));
                }
                else if (typeof(Gradient) == type)
                {
                    return new Gradient()
                           {
                               colorKeys = new GradientColorKey[] { new GradientColorKey(Color.white, 0.2f) }
                           }
                }
                ;
                else if (typeof(Mesh) == type)
                {
                    return(m_cubeEmpty.GetComponent <MeshFilter>().sharedMesh);
                }
                else if (typeof(Texture2D) == type)
                {
                    return(m_texture2D_A);
                }
                else if (typeof(Texture2DArray) == type)
                {
                    return(m_texture2DArray_A);
                }
                else if (typeof(Texture3D) == type)
                {
                    return(m_texture3D_A);
                }
                else if (typeof(Cubemap) == type)
                {
                    return(m_textureCube_A);
                }
                else if (typeof(CubemapArray) == type)
                {
                    return(m_textureCubeArray_A);
                }
                else if (typeof(bool) == type)
                {
                    return(true);
                }
                else if (typeof(Matrix4x4) == type)
                {
                    return(Matrix4x4.identity);
                }
                Assert.Fail();
                return(null);
            };

            Func <Type, object> GetValue_B_Type = delegate(Type type)
            {
                if (typeof(float) == type)
                {
                    return(50.0f);
                }
                else if (typeof(Vector2) == type)
                {
                    return(new Vector2(53.0f, 54.0f));
                }
                else if (typeof(Vector3) == type)
                {
                    return(new Vector3(58.0f, 59.0f, 510.0f));
                }
                else if (typeof(Vector4) == type || typeof(Color) == type)// ValueB_Type is used to set a component value, so return a Vector4 with color values
                {
                    return(new Vector4(511.0f, 512.0f, 513.0f, 514.0f));
                }
                else if (typeof(int) == type)
                {
                    return(515);
                }
                else if (typeof(uint) == type)
                {
                    return(516u);
                }
                else if (typeof(AnimationCurve) == type)
                {
                    return(new AnimationCurve(new Keyframe(0, 47), new Keyframe(0.5f, 23), new Keyframe(1.0f, 17)));
                }
                else if (typeof(Gradient) == type)
                {
                    return new Gradient()
                           {
                               colorKeys = new GradientColorKey[] { new GradientColorKey(Color.white, 0.2f), new GradientColorKey(Color.black, 0.6f) }
                           }
                }
                ;
                else if (typeof(Mesh) == type)
                {
                    return(m_sphereEmpty.GetComponent <MeshFilter>().sharedMesh);
                }
                else if (typeof(Texture2D) == type)
                {
                    return(m_texture2D_B);
                }
                else if (typeof(Texture2DArray) == type)
                {
                    return(m_texture2DArray_B);
                }
                else if (typeof(Texture3D) == type)
                {
                    return(m_texture3D_B);
                }
                else if (typeof(Cubemap) == type)
                {
                    return(m_textureCube_B);
                }
                else if (typeof(CubemapArray) == type)
                {
                    return(m_textureCubeArray_B);
                }
                else if (typeof(bool) == type)
                {
                    return(true);
                }
                else if (typeof(Matrix4x4) == type)
                {
                    return(Matrix4x4.identity);
                }
                Assert.Fail();
                return(null);
            };

            Func <VFXValueType, VisualEffect, string, bool> fnHas_UsingBindings = delegate(VFXValueType type, VisualEffect vfx, string name)
            {
                switch (type)
                {
                case VFXValueType.Float: return(vfx.HasFloat(name));

                case VFXValueType.Float2: return(vfx.HasVector2(name));

                case VFXValueType.Float3: return(vfx.HasVector3(name));

                case VFXValueType.Float4: return(vfx.HasVector4(name));

                case VFXValueType.Int32: return(vfx.HasInt(name));

                case VFXValueType.Uint32: return(vfx.HasUInt(name));

                case VFXValueType.Curve: return(vfx.HasAnimationCurve(name));

                case VFXValueType.ColorGradient: return(vfx.HasGradient(name));

                case VFXValueType.Mesh: return(vfx.HasMesh(name));

                case VFXValueType.Texture2D: return(vfx.HasTexture(name) && vfx.GetTextureDimension(name) == TextureDimension.Tex2D);

                case VFXValueType.Texture2DArray: return(vfx.HasTexture(name) && vfx.GetTextureDimension(name) == TextureDimension.Tex2DArray);

                case VFXValueType.Texture3D: return(vfx.HasTexture(name) && vfx.GetTextureDimension(name) == TextureDimension.Tex3D);

                case VFXValueType.TextureCube: return(vfx.HasTexture(name) && vfx.GetTextureDimension(name) == TextureDimension.Cube);

                case VFXValueType.TextureCubeArray: return(vfx.HasTexture(name) && vfx.GetTextureDimension(name) == TextureDimension.CubeArray);

                case VFXValueType.Boolean: return(vfx.HasBool(name));

                case VFXValueType.Matrix4x4: return(vfx.HasMatrix4x4(name));
                }
                Assert.Fail();
                return(false);
            };

            Func <VFXValueType, VisualEffect, string, object> fnGet_UsingBindings = delegate(VFXValueType type, VisualEffect vfx, string name)
            {
                switch (type)
                {
                case VFXValueType.Float: return(vfx.GetFloat(name));

                case VFXValueType.Float2: return(vfx.GetVector2(name));

                case VFXValueType.Float3: return(vfx.GetVector3(name));

                case VFXValueType.Float4: return(vfx.GetVector4(name));

                case VFXValueType.Int32: return(vfx.GetInt(name));

                case VFXValueType.Uint32: return(vfx.GetUInt(name));

                case VFXValueType.Curve: return(vfx.GetAnimationCurve(name));

                case VFXValueType.ColorGradient: return(vfx.GetGradient(name));

                case VFXValueType.Mesh: return(vfx.GetMesh(name));

                case VFXValueType.Texture2D:
                case VFXValueType.Texture2DArray:
                case VFXValueType.Texture3D:
                case VFXValueType.TextureCube:
                case VFXValueType.TextureCubeArray: return(vfx.GetTexture(name));

                case VFXValueType.Boolean: return(vfx.GetBool(name));

                case VFXValueType.Matrix4x4: return(vfx.GetMatrix4x4(name));
                }
                Assert.Fail();
                return(null);
            };

            Action <VFXValueType, VisualEffect, string, object> fnSet_UsingBindings = delegate(VFXValueType type, VisualEffect vfx, string name, object value)
            {
                switch (type)
                {
                case VFXValueType.Float: vfx.SetFloat(name, (float)value); break;

                case VFXValueType.Float2: vfx.SetVector2(name, (Vector2)value); break;

                case VFXValueType.Float3: vfx.SetVector3(name, (Vector3)value); break;

                case VFXValueType.Float4: vfx.SetVector4(name, (Vector4)value); break;

                case VFXValueType.Int32: vfx.SetInt(name, (int)value); break;

                case VFXValueType.Uint32: vfx.SetUInt(name, (uint)value); break;

                case VFXValueType.Curve: vfx.SetAnimationCurve(name, (AnimationCurve)value); break;

                case VFXValueType.ColorGradient: vfx.SetGradient(name, (Gradient)value); break;

                case VFXValueType.Mesh: vfx.SetMesh(name, (Mesh)value); break;

                case VFXValueType.Texture2D:
                case VFXValueType.Texture2DArray:
                case VFXValueType.Texture3D:
                case VFXValueType.TextureCube:
                case VFXValueType.TextureCubeArray: vfx.SetTexture(name, (Texture)value); break;

                case VFXValueType.Boolean: vfx.SetBool(name, (bool)value); break;

                case VFXValueType.Matrix4x4: vfx.SetMatrix4x4(name, (Matrix4x4)value); break;
                }
            };


            Func <VFXValueType, VisualEffect, string, bool> fnHas_UsingSerializedProperty = delegate(VFXValueType type, VisualEffect vfx, string name)
            {
                var editor = Editor.CreateEditor(vfx);
                try
                {
                    var propertySheet = editor.serializedObject.FindProperty("m_PropertySheet");
                    var fieldName     = VisualEffectSerializationUtility.GetTypeField(VFXExpression.TypeToType(type)) + ".m_Array";
                    var vfxField      = propertySheet.FindPropertyRelative(fieldName);
                    if (vfxField != null)
                    {
                        for (int i = 0; i < vfxField.arraySize; ++i)
                        {
                            var property     = vfxField.GetArrayElementAtIndex(i);
                            var nameProperty = property.FindPropertyRelative("m_Name").stringValue;
                            if (nameProperty == name)
                            {
                                return(true);
                            }
                        }
                    }
                }
                finally
                {
                    GameObject.DestroyImmediate(editor);
                }
                return(false);
            };

            Func <SerializedProperty, Matrix4x4> fnMatrixFromSerializedProperty = delegate(SerializedProperty property)
            {
                var mat = new Matrix4x4();

                mat.m00 = property.FindPropertyRelative("e00").floatValue;
                mat.m01 = property.FindPropertyRelative("e01").floatValue;
                mat.m02 = property.FindPropertyRelative("e02").floatValue;
                mat.m03 = property.FindPropertyRelative("e03").floatValue;

                mat.m10 = property.FindPropertyRelative("e10").floatValue;
                mat.m11 = property.FindPropertyRelative("e11").floatValue;
                mat.m12 = property.FindPropertyRelative("e12").floatValue;
                mat.m13 = property.FindPropertyRelative("e13").floatValue;

                mat.m20 = property.FindPropertyRelative("e20").floatValue;
                mat.m21 = property.FindPropertyRelative("e21").floatValue;
                mat.m22 = property.FindPropertyRelative("e22").floatValue;
                mat.m23 = property.FindPropertyRelative("e23").floatValue;

                mat.m30 = property.FindPropertyRelative("e30").floatValue;
                mat.m31 = property.FindPropertyRelative("e31").floatValue;
                mat.m32 = property.FindPropertyRelative("e32").floatValue;
                mat.m33 = property.FindPropertyRelative("e33").floatValue;

                return(mat);
            };

            Action <SerializedProperty, Matrix4x4> fnMatrixToSerializedProperty = delegate(SerializedProperty property, Matrix4x4 mat)
            {
                property.FindPropertyRelative("e00").floatValue = mat.m00;
                property.FindPropertyRelative("e01").floatValue = mat.m01;
                property.FindPropertyRelative("e02").floatValue = mat.m02;
                property.FindPropertyRelative("e03").floatValue = mat.m03;

                property.FindPropertyRelative("e10").floatValue = mat.m10;
                property.FindPropertyRelative("e11").floatValue = mat.m11;
                property.FindPropertyRelative("e12").floatValue = mat.m12;
                property.FindPropertyRelative("e13").floatValue = mat.m13;

                property.FindPropertyRelative("e20").floatValue = mat.m20;
                property.FindPropertyRelative("e21").floatValue = mat.m21;
                property.FindPropertyRelative("e22").floatValue = mat.m22;
                property.FindPropertyRelative("e23").floatValue = mat.m23;

                property.FindPropertyRelative("e30").floatValue = mat.m30;
                property.FindPropertyRelative("e31").floatValue = mat.m31;
                property.FindPropertyRelative("e32").floatValue = mat.m32;
                property.FindPropertyRelative("e33").floatValue = mat.m33;
            };

            Func <VFXValueType, VisualEffect, string, object> fnGet_UsingSerializedProperty = delegate(VFXValueType type, VisualEffect vfx, string name)
            {
                var editor = Editor.CreateEditor(vfx);
                try
                {
                    var propertySheet = editor.serializedObject.FindProperty("m_PropertySheet");
                    editor.serializedObject.Update();

                    var fieldName = VisualEffectSerializationUtility.GetTypeField(VFXExpression.TypeToType(type)) + ".m_Array";
                    var vfxField  = propertySheet.FindPropertyRelative(fieldName);
                    if (vfxField != null)
                    {
                        for (int i = 0; i < vfxField.arraySize; ++i)
                        {
                            var property     = vfxField.GetArrayElementAtIndex(i);
                            var nameProperty = property.FindPropertyRelative("m_Name").stringValue;
                            if (nameProperty == name)
                            {
                                property = property.FindPropertyRelative("m_Value");

                                switch (type)
                                {
                                case VFXValueType.Float: return(property.floatValue);

                                case VFXValueType.Float2: return(property.vector2Value);

                                case VFXValueType.Float3: return(property.vector3Value);

                                case VFXValueType.Float4: return(property.vector4Value);

                                case VFXValueType.Int32: return(property.intValue);

                                case VFXValueType.Uint32: return(property.intValue);        // there isn't uintValue

                                case VFXValueType.Curve: return(property.animationCurveValue);

                                case VFXValueType.ColorGradient: return(property.gradientValue);

                                case VFXValueType.Mesh: return(property.objectReferenceValue);

                                case VFXValueType.Texture2D:
                                case VFXValueType.Texture2DArray:
                                case VFXValueType.Texture3D:
                                case VFXValueType.TextureCube:
                                case VFXValueType.TextureCubeArray: return(property.objectReferenceValue);

                                case VFXValueType.Boolean: return(property.boolValue);

                                case VFXValueType.Matrix4x4: return(fnMatrixFromSerializedProperty(property));
                                }
                                Assert.Fail();
                            }
                        }
                    }
                }
                finally
                {
                    GameObject.DestroyImmediate(editor);
                }

                return(null);
            };

            Action <VFXValueType, VisualEffect, string, object> fnSet_UsingSerializedProperty = delegate(VFXValueType type, VisualEffect vfx, string name, object value)
            {
                var editor = Editor.CreateEditor(vfx);
                try
                {
                    editor.serializedObject.Update();

                    var propertySheet = editor.serializedObject.FindProperty("m_PropertySheet");
                    var fieldName     = VisualEffectSerializationUtility.GetTypeField(VFXExpression.TypeToType(type)) + ".m_Array";
                    var vfxField      = propertySheet.FindPropertyRelative(fieldName);
                    if (vfxField != null)
                    {
                        for (int i = 0; i < vfxField.arraySize; ++i)
                        {
                            var property     = vfxField.GetArrayElementAtIndex(i);
                            var propertyName = property.FindPropertyRelative("m_Name").stringValue;
                            if (propertyName == name)
                            {
                                var propertyValue     = property.FindPropertyRelative("m_Value");
                                var propertyOverriden = property.FindPropertyRelative("m_Overridden");

                                switch (type)
                                {
                                case VFXValueType.Float: propertyValue.floatValue = (float)value; break;

                                case VFXValueType.Float2: propertyValue.vector2Value = (Vector2)value; break;

                                case VFXValueType.Float3: propertyValue.vector3Value = (Vector3)value; break;

                                case VFXValueType.Float4: propertyValue.vector4Value = (Vector4)value; break;

                                case VFXValueType.Int32: propertyValue.intValue = (int)value; break;

                                case VFXValueType.Uint32: propertyValue.intValue = (int)((uint)value); break;         // there isn't uintValue

                                case VFXValueType.Curve: propertyValue.animationCurveValue = (AnimationCurve)value; break;

                                case VFXValueType.ColorGradient: propertyValue.gradientValue = (Gradient)value; break;

                                case VFXValueType.Mesh: propertyValue.objectReferenceValue = (UnityEngine.Object)value; break;

                                case VFXValueType.Texture2D:
                                case VFXValueType.Texture2DArray:
                                case VFXValueType.Texture3D:
                                case VFXValueType.TextureCube:
                                case VFXValueType.TextureCubeArray: propertyValue.objectReferenceValue = (UnityEngine.Object)value;   break;

                                case VFXValueType.Boolean: propertyValue.boolValue = (bool)value; break;

                                case VFXValueType.Matrix4x4: fnMatrixToSerializedProperty(propertyValue, (Matrix4x4)value); break;
                                }
                                propertyOverriden.boolValue = true;
                            }
                        }
                    }
                    editor.serializedObject.ApplyModifiedProperties();
                }
                finally
                {
                    GameObject.DestroyImmediate(editor);
                }
            };

            Func <VFXValueType, VisualEffect, string, bool>     fnHas = bindingModes ? fnHas_UsingBindings : fnHas_UsingSerializedProperty;
            Func <VFXValueType, VisualEffect, string, object>   fnGet = bindingModes ? fnGet_UsingBindings : fnGet_UsingSerializedProperty;
            Action <VFXValueType, VisualEffect, string, object> fnSet = bindingModes ? fnSet_UsingBindings : fnSet_UsingSerializedProperty;

            EditorApplication.ExecuteMenuItem("Window/General/Game");
            var graph = MakeTemporaryGraph();

            var contextInitialize = ScriptableObject.CreateInstance <VFXBasicInitialize>();
            var allType           = ScriptableObject.CreateInstance <AllType>();

            contextInitialize.AddChild(allType);
            graph.AddChild(contextInitialize);

            // Needs a spawner and output for the system to be valid
            {
                var spawner = ScriptableObject.CreateInstance <VFXBasicSpawner>();
                spawner.LinkTo(contextInitialize);
                graph.AddChild(spawner);

                var output = ScriptableObject.CreateInstance <VFXPointOutput>();
                output.LinkFrom(contextInitialize);
                graph.AddChild(output);
            }

            var types = Enum.GetValues(typeof(VFXValueType)).Cast <VFXValueType>()
                        .Where(e => e != VFXValueType.Spline &&
                               e != VFXValueType.None).ToArray();

            foreach (var parameter in VFXLibrary.GetParameters())
            {
                var newInstance = parameter.CreateInstance();

                VFXValueType type = types.FirstOrDefault(e => VFXExpression.GetVFXValueTypeFromType(newInstance.type) == e);
                if (type != VFXValueType.None)
                {
                    newInstance.SetSettingValue("m_exposedName", commonBaseName + newInstance.type.UserFriendlyName());
                    newInstance.SetSettingValue("m_exposed", true);
                    var value = GetValue_A_Type(newInstance.type);
                    Assert.IsNotNull(value);
                    newInstance.value = value;
                    graph.AddChild(newInstance);
                }
            }

            if (linkMode)
            {
                foreach (var type in types)
                {
                    VFXSlot slot = null;
                    for (int i = 0; i < allType.GetNbInputSlots(); ++i)
                    {
                        var currentSlot = allType.GetInputSlot(i);
                        var expression  = currentSlot.GetExpression();
                        if (expression != null && expression.valueType == type)
                        {
                            slot = currentSlot;
                            break;
                        }
                    }
                    Assert.IsNotNull(slot, type.ToString());

                    var parameter = graph.children.OfType <VFXParameter>().FirstOrDefault(o =>
                    {
                        if (o.GetNbOutputSlots() > 0)
                        {
                            var expression = o.outputSlots[0].GetExpression();
                            if (expression != null && expression.valueType == type)
                            {
                                return(true);
                            }
                        }
                        return(false);
                    });
                    Assert.IsNotNull(parameter, "parameter with type : " + type.ToString());
                    slot.Link(parameter.GetOutputSlot(0));
                }
            }

            graph.RecompileIfNeeded();

            while (m_mainObject.GetComponent <VisualEffect>() != null)
            {
                UnityEngine.Object.DestroyImmediate(m_mainObject.GetComponent <VisualEffect>());
            }
            var vfxComponent = m_mainObject.AddComponent <VisualEffect>();

            vfxComponent.visualEffectAsset = graph.visualEffectResource.asset;

            yield return(null);

            Func <AnimationCurve, AnimationCurve, bool> fnCompareCurve = delegate(AnimationCurve left, AnimationCurve right)
            {
                return(left.keys.Length == right.keys.Length);
            };

            Func <Gradient, Gradient, bool> fnCompareGradient = delegate(Gradient left, Gradient right)
            {
                return(left.colorKeys.Length == right.colorKeys.Length);
            };

            //Check default Value_A & change to Value_B (At this stage, it's useless to access with SerializedProperty)
            foreach (var parameter in VFXLibrary.GetParameters())
            {
                VFXValueType type = types.FirstOrDefault(e => VFXExpression.GetVFXValueTypeFromType(parameter.model.type) == e);
                if (type == VFXValueType.None)
                {
                    continue;
                }
                var currentName = commonBaseName + parameter.model.type.UserFriendlyName();
                var baseValue   = GetValue_A_Type(parameter.model.type);
                var newValue    = GetValue_B_Type(parameter.model.type);

                Assert.IsTrue(fnHas_UsingBindings(type, vfxComponent, currentName));
                var currentValue = fnGet_UsingBindings(type, vfxComponent, currentName);
                if (type == VFXValueType.ColorGradient)
                {
                    Assert.IsTrue(fnCompareGradient((Gradient)baseValue, (Gradient)currentValue));
                }
                else if (type == VFXValueType.Curve)
                {
                    Assert.IsTrue(fnCompareCurve((AnimationCurve)baseValue, (AnimationCurve)currentValue));
                }
                else if (parameter.model.type == typeof(Color))
                {
                    Color col = (Color)baseValue;
                    Assert.AreEqual(new Vector4(col.r, col.g, col.b, col.a), currentValue);
                }
                else
                {
                    Assert.AreEqual(baseValue, currentValue);
                }
                fnSet_UsingBindings(type, vfxComponent, currentName, newValue);

                yield return(null);
            }

            //Compare new setted values
            foreach (var parameter in VFXLibrary.GetParameters())
            {
                VFXValueType type = types.FirstOrDefault(e => VFXExpression.GetVFXValueTypeFromType(parameter.model.type) == e);
                if (type == VFXValueType.None)
                {
                    continue;
                }
                var currentName = commonBaseName + parameter.model.type.UserFriendlyName();
                var baseValue   = GetValue_B_Type(parameter.model.type);
                Assert.IsTrue(fnHas(type, vfxComponent, currentName));

                var currentValue = fnGet(type, vfxComponent, currentName);
                if (type == VFXValueType.ColorGradient)
                {
                    Assert.IsTrue(fnCompareGradient((Gradient)baseValue, (Gradient)currentValue));
                }
                else if (type == VFXValueType.Curve)
                {
                    Assert.IsTrue(fnCompareCurve((AnimationCurve)baseValue, (AnimationCurve)currentValue));
                }
                else
                {
                    Assert.AreEqual(baseValue, currentValue);
                }
                yield return(null);
            }

            //Test ResetOverride function
            foreach (var parameter in VFXLibrary.GetParameters())
            {
                VFXValueType type = types.FirstOrDefault(e => VFXExpression.GetVFXValueTypeFromType(parameter.model.type) == e);
                if (type == VFXValueType.None)
                {
                    continue;
                }
                var currentName = commonBaseName + parameter.model.type.UserFriendlyName();
                vfxComponent.ResetOverride(currentName);

                {
                    //If we use bindings, internal value is restored but it doesn't change serialized property (strange at first but intended behavior)
                    var baseValue = bindingModes ? GetValue_A_Type(parameter.model.type) : GetValue_B_Type(parameter.model.type);

                    var currentValue = fnGet(type, vfxComponent, currentName);
                    if (type == VFXValueType.ColorGradient)
                    {
                        Assert.IsTrue(fnCompareGradient((Gradient)baseValue, (Gradient)currentValue));
                    }
                    else if (type == VFXValueType.Curve)
                    {
                        Assert.IsTrue(fnCompareCurve((AnimationCurve)baseValue, (AnimationCurve)currentValue));
                    }
                    else if (bindingModes && parameter.model.type == typeof(Color))
                    {
                        Color col = (Color)baseValue;
                        Assert.AreEqual(new Vector4(col.r, col.g, col.b, col.a), currentValue);
                    }
                    else
                    {
                        Assert.AreEqual(baseValue, currentValue);
                    }
                }

                if (!bindingModes)
                {
                    var internalValue      = fnGet_UsingBindings(type, vfxComponent, currentName);
                    var originalAssetValue = GetValue_A_Type(parameter.model.type);

                    if (type == VFXValueType.ColorGradient)
                    {
                        Assert.IsTrue(fnCompareGradient((Gradient)originalAssetValue, (Gradient)internalValue));
                    }
                    else if (type == VFXValueType.Curve)
                    {
                        Assert.IsTrue(fnCompareCurve((AnimationCurve)originalAssetValue, (AnimationCurve)internalValue));
                    }
                    else if (parameter.model.type == typeof(Color))
                    {
                        Color col = (Color)originalAssetValue;
                        Assert.AreEqual(new Vector4(col.r, col.g, col.b, col.a), internalValue);
                    }
                    else
                    {
                        Assert.AreEqual(originalAssetValue, internalValue);
                    }
                }
                yield return(null);
            }
        }