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())); }
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)); }
// 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); }
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); }
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); } }