Beispiel #1
0
        IEnumerable <VFXParameter> GetSortedInputParameters()
        {
            var resource = m_Subgraph.GetResource();

            if (resource != null)
            {
                var graph = resource.GetOrCreateGraph();
                if (graph != null)
                {
                    var UIInfos         = graph.UIInfos;
                    var categoriesOrder = UIInfos.categories;
                    if (categoriesOrder == null)
                    {
                        categoriesOrder = new List <VFXUI.CategoryInfo>();
                    }
                    return(GetParameters(t => InputPredicate(t)).OrderBy(t => categoriesOrder.FindIndex(u => u.name == t.category)).ThenBy(t => t.order));
                }
                else
                {
                    Debug.LogError("Can't find subgraph graph");
                }
            }
            else
            {
                Debug.LogError("Cant't find subgraph resource");
            }

            return(Enumerable.Empty <VFXParameter>());
        }
Beispiel #2
0
        private void CheckAsset(VisualEffectAsset asset)
        {
            VisualEffectResource resource = asset.GetResource();
            var graph = resource.GetOrCreateGraph();

            Assert.AreEqual(6, graph.GetNbChildren());

            Assert.AreEqual(1, graph[0].GetNbChildren());
            Assert.AreEqual(1, graph[1].GetNbChildren());
            Assert.AreEqual(1, graph[2].GetNbChildren());
            Assert.AreEqual(0, graph[3].GetNbChildren());
            Assert.AreEqual(0, graph[4].GetNbChildren());
            Assert.AreEqual(0, graph[5].GetNbChildren());

            Assert.IsNotNull((graph[0])[0]);
            Assert.IsNotNull((graph[1])[0]);
            Assert.IsNotNull((graph[2])[0]);

            Assert.AreEqual(VFXContextType.Init, ((VFXContext)(graph[0])).contextType);
            Assert.AreEqual(VFXContextType.Update, ((VFXContext)(graph[1])).contextType);
            Assert.AreEqual(VFXContextType.Output, ((VFXContext)(graph[2])).contextType);
            Assert.AreEqual(VFXContextType.Init, ((VFXContext)(graph[3])).contextType);
            Assert.AreEqual(VFXContextType.Output, ((VFXContext)(graph[4])).contextType);

            Assert.IsNotNull(graph[5] as Operator.Add);
        }
        VFXGraph MakeTemporaryGraph()
        {
            m_Asset = VisualEffectResource.CreateNewAsset(tempFilePath);
            VisualEffectResource resource = m_Asset.GetResource(); // force resource creation
            VFXGraph graph = ScriptableObject.CreateInstance<VFXGraph>();
            graph.visualEffectResource = resource;

            var window = EditorWindow.GetWindow<VFXViewWindow>();
            window.Close();
            window = EditorWindow.GetWindow<VFXViewWindow>();
            m_ViewController = VFXViewController.GetController(m_Asset.GetResource(), true);
            m_View = window.graphView;
            m_View.controller = m_ViewController;

            return graph;
        }
Beispiel #4
0
        public void CreateTestAsset(string name)
        {
            var filePath      = string.Format(testAssetName, name);
            var directoryPath = Path.GetDirectoryName(filePath);

            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }


            m_Asset = VisualEffectResource.CreateNewAsset(filePath);
            VFXViewWindow window = EditorWindow.GetWindow <VFXViewWindow>();

            window.Close();
            window                      = EditorWindow.GetWindow <VFXViewWindow>();
            m_ViewController            = VFXViewController.GetController(m_Asset.GetResource(), true);
            window.graphView.controller = m_ViewController;
        }
Beispiel #5
0
    public static void MigrateComponentsCurrentScnene()
    {
        HashSet <GameObject> prefabs    = new HashSet <GameObject>();
        FileVFXComponents    components = FindComponentsInScene(prefabs);

        List <FileVFXComponents> prefabsInfos = new List <FileVFXComponents>();

        foreach (var prefab in prefabs)
        {
            prefabsInfos.Add(FindComponentsInPrefab(prefab));
            Debug.Log("Found prefab : " + AssetDatabase.GetAssetPath(prefab));
        }

        foreach (var path in components.componentPaths.Values.Union(prefabsInfos.SelectMany(t => t.componentPaths.Values)).Distinct())
        {
            VisualEffectAsset asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(path.assetPath);
            if (asset == null)
            {
                AssetDatabase.ImportAsset(path.assetPath);
                asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(path.assetPath);
            }

            if (asset != null)
            {
                var resource = asset.GetResource();
                resource.ValidateAsset();
                try
                {
                    var graph = resource.GetOrCreateGraph();
                    graph.RecompileIfNeeded();
                    EditorUtility.SetDirty(graph);
                }
                catch (System.Exception e)
                {
                    Debug.LogError("Couldn't resave vfx" + path.assetPath + " " + e.Message);
                }
            }
        }


        SetComponentsInScene(components);
        EditorSceneManager.SaveScene(EditorSceneManager.GetSceneByPath(components.path));
    }
            public override void Action(int instanceId, string pathName, string resourceFile)
            {
                try
                {
                    var templateString = System.IO.File.ReadAllText(templatePath + templateAssetName);
                    System.IO.File.WriteAllText(pathName, templateString);
                }
                catch (FileNotFoundException)
                {
                    CreateNewAsset(pathName);
                }

                AssetDatabase.ImportAsset(pathName);
                VisualEffectAsset vfxAsset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(pathName);
                var graph = vfxAsset.GetResource().GetOrCreateGraph();

                graph.SetExpressionGraphDirty();
                graph.RecompileIfNeeded();

                ProjectWindowUtil.FrameObjectInProjectWindow(vfxAsset.GetInstanceID());
            }
        public void CreateTestAsset()
        {
            var directoryPath = Path.GetDirectoryName(testAssetName);

            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }
            if (File.Exists(testAssetName))
            {
                AssetDatabase.DeleteAsset(testAssetName);
            }

            VisualEffectAsset    asset    = VisualEffectResource.CreateNewAsset(testAssetName);
            VisualEffectResource resource = asset.GetResource(); // force resource creation

            m_ViewController = VFXViewController.GetController(resource);
            m_ViewController.useCount++;

            m_StartUndoGroupId = Undo.GetCurrentGroup();
        }
Beispiel #8
0
        public void CheckTypeMenu(SerializedProperty property, VFXPropertyBindingAttribute attribute, VisualEffectAsset asset)
        {
            GenericMenu menu       = new GenericMenu();
            var         parameters = (asset.GetResource().graph as UnityEditor.VFX.VFXGraph).children.OfType <UnityEditor.VFX.VFXParameter>();

            foreach (var param in parameters)
            {
                string typeName = param.type.ToString();
                if (attribute.EditorTypes.Contains(typeName))
                {
                    MenuPropertySetName set = new MenuPropertySetName
                    {
                        property = property,
                        value    = param.exposedName
                    };
                    menu.AddItem(new GUIContent(param.exposedName), false, SetFieldName, set);
                }
            }

            menu.ShowAsContext();
        }
Beispiel #9
0
    static void ResaveFolder(string dirPath)
    {
        foreach (var path in Directory.GetFiles(dirPath))
        {
            if (Path.GetExtension(path) == ".vfx")
            {
                VisualEffectAsset asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(path);
                if (asset == null)
                {
                    AssetDatabase.ImportAsset(path);
                    asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(path);
                }

                if (asset == null)
                {
                    Debug.LogError("Couldn't Import vfx" + path);
                }

                var resource = asset.GetResource();
                if (resource != null)
                {
                    resource.ValidateAsset();
                    try
                    {
                        var graph = resource.GetOrCreateGraph();
                        graph.RecompileIfNeeded();
                        EditorUtility.SetDirty(graph);
                    }
                    catch (System.Exception e)
                    {
                        Debug.LogError("Couldn't resave vfx" + path + " " + e.Message);
                    }
                }
            }
        }
        foreach (var path in Directory.GetDirectories(dirPath))
        {
            ResaveFolder(path);
        }
    }
Beispiel #10
0
        private void InitAsset(VisualEffectAsset asset)
        {
            VisualEffectResource resource = asset.GetResource();
            var graph = resource.GetOrCreateGraph();

            graph.RemoveAllChildren();

            var init0   = ScriptableObject.CreateInstance <VFXBasicInitialize>();
            var update0 = ScriptableObject.CreateInstance <VFXBasicUpdate>();
            var output0 = ScriptableObject.CreateInstance <VFXPointOutput>();

            graph.AddChild(init0);
            graph.AddChild(update0);
            graph.AddChild(output0);

            init0.LinkTo(update0);
            update0.LinkTo(output0);

            var init1   = ScriptableObject.CreateInstance <VFXBasicInitialize>();
            var output1 = ScriptableObject.CreateInstance <VFXPointOutput>();

            init1.LinkTo(output1);

            graph.AddChild(init1);
            graph.AddChild(output1);

            // Add some block
            var block0 = ScriptableObject.CreateInstance <InitBlockTest>();
            var block1 = ScriptableObject.CreateInstance <UpdateBlockTest>();
            var block2 = ScriptableObject.CreateInstance <OutputBlockTest>();

            // Add some operator
            VFXOperator add = ScriptableObject.CreateInstance <Operator.Add>();

            init0.AddChild(block0);
            update0.AddChild(block1);
            output0.AddChild(block2);

            graph.AddChild(add);
        }
        public void Initial_Space_Supposed_To_Be_Same_As_Context()
        {
            //Cover also case 1163442, this behavior only exists in controller
            var directoryPath = Path.GetDirectoryName(testAssetName);

            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }
            if (File.Exists(testAssetName))
            {
                AssetDatabase.DeleteAsset(testAssetName);
            }

            VisualEffectAsset asset = VisualEffectAssetEditorUtility.CreateNewAsset(testAssetName);
            var resource            = asset.GetResource(); // force resource creation
            var viewController      = VFXViewController.GetController(resource);

            viewController.useCount++;
            var startUndoGroupId = Undo.GetCurrentGroup();

            var updateContext = ScriptableObject.CreateInstance <VFXBasicUpdate>();

            updateContext.space = VFXCoordinateSpace.World;
            viewController.AddVFXModel(Vector2.zero, updateContext);
            viewController.ApplyChanges();
            viewController.ForceReload();

            var collision         = ScriptableObject.CreateInstance <CollisionSphere>();
            var contextController = viewController.allChildren.OfType <VFXContextController>().First();

            contextController.AddBlock(0, collision, true);

            Assert.IsTrue(collision.inputSlots.Where(o => o.spaceable).All(o => o.space == VFXCoordinateSpace.World));

            viewController.useCount--;
            Undo.RevertAllDownToGroup(startUndoGroupId);
            AssetDatabase.DeleteAsset(testAssetName);
        }
        private void WriteBasicOperators(VisualEffectAsset asset, bool spawnAbs, bool linkAbs)
        {
            var add = ScriptableObject.CreateInstance<Operator.Add>();
            VisualEffectResource resource = asset.GetResource();
            var graph = resource.GetOrCreateGraph();
            graph.AddChild(add);

            CheckIsolatedOperatorAdd(add);

            if (spawnAbs)
            {
                var abs = ScriptableObject.CreateInstance<Operator.Absolute>();
                abs.position = new Vector2(64.0f, 64.0f);
                graph.AddChild(abs);
                CheckIsolatedOperatorAbs(abs);
                if (linkAbs)
                {
                    abs.inputSlots[0].Link(add.outputSlots[0]);
                    CheckConnectedAbs(abs);
                }
            }
        }
        private void ReadBasicOperators(VisualEffectAsset asset, bool spawnAbs, bool linkAbs)
        {
            VisualEffectResource resource = asset.GetResource();
            var graph = resource.GetOrCreateGraph();
            Assert.AreEqual(spawnAbs ? 2 : 1, graph.GetNbChildren());
            Assert.IsNotNull((Operator.Add)graph[0]);
            var add = (Operator.Add)graph[0];
            CheckIsolatedOperatorAdd(add);

            if (spawnAbs)
            {
                Assert.IsNotNull((Operator.Absolute)graph[1]);
                var abs = (Operator.Absolute)graph[1];
                CheckIsolatedOperatorAbs(abs);
                Assert.AreEqual(abs.position.x, 64.0f);
                Assert.AreEqual(abs.position.y, 64.0f);
                if (linkAbs)
                {
                    CheckConnectedAbs(abs);
                }
            }
        }
Beispiel #14
0
        protected VisualEffectResource GetCurrentResource()
        {
            var objs = Selection.objects;

            VisualEffectResource selectedResource = null;

            if (objs != null && objs.Length == 1)
            {
                if (objs[0] is VisualEffectAsset)
                {
                    VisualEffectAsset asset = objs[0] as VisualEffectAsset;
                    selectedResource = asset.GetResource();
                }
                else if (objs[0] is VisualEffectResource)
                {
                    selectedResource = objs[0] as VisualEffectResource;
                }
            }
            if (selectedResource == null)
            {
                int instanceID = Selection.activeInstanceID;

                if (instanceID != 0)
                {
                    string path = AssetDatabase.GetAssetPath(instanceID);
                    if (path.EndsWith(".vfx"))
                    {
                        selectedResource = VisualEffectResource.GetResourceAtPath(path);
                    }
                }
            }
            if (selectedResource == null && m_DisplayedResource != null)
            {
                selectedResource = m_DisplayedResource;
            }
            return(selectedResource);
        }
        public void CheckTypeMenu(SerializedProperty property, VFXPropertyBindingAttribute attribute, VisualEffectAsset asset)
        {
            VFXGraph graph = null;

            if (asset != null)
            {
                var resource = asset.GetResource();
                if (resource != null) //If VisualEffectGraph is store in asset bundle, we can't use this following code
                {
                    graph = resource.graph as VFXGraph;
                }
            }

            if (graph == null)
            {
                return;
            }

            var menu       = new GenericMenu();
            var parameters = graph.children.OfType <UnityEditor.VFX.VFXParameter>();

            foreach (var param in parameters)
            {
                string typeName = param.type.ToString();
                if (attribute.EditorTypes.Contains(typeName))
                {
                    MenuPropertySetName set = new MenuPropertySetName
                    {
                        property = property,
                        value    = param.exposedName
                    };
                    menu.AddItem(new GUIContent(param.exposedName), false, SetFieldName, set);
                }
            }

            menu.ShowAsContext();
        }
        public void CopyPasteEdges()
        {
            VisualEffectAsset asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>("Assets/AllTests/Editor/Tests/CopyPasteTest.vfx");

            VFXViewController controller = VFXViewController.GetController(asset.GetResource(), true);

            VFXViewWindow window = EditorWindow.GetWindow <VFXViewWindow>();
            VFXView       view   = window.graphView;

            view.controller = controller;

            view.ClearSelection();


            var originalElements = view.Query().OfType <GraphElement>().ToList().OfType <ISelectable>().ToArray();

            Assert.AreNotEqual(originalElements.Length, 0);

            foreach (var element in originalElements)
            {
                view.AddToSelection(element);
            }

            view.CopySelectionCallback();

            view.controller = m_ViewController;

            view.PasteCallback();

            m_ViewController.ApplyChanges();

            VFXParameterUI[] parameters = view.Query().OfType <VFXParameterUI>().ToList().ToArray();

            Assert.AreEqual(parameters.Length, 2);

            if (parameters[0].title == "Vector3")
            {
                var tmp = parameters[0];
                parameters[0] = parameters[1];
                parameters[1] = tmp;
            }

            VFXOperatorUI[] operators = view.Query().OfType <VFXOperatorUI>().ToList().ToArray();

            Assert.AreEqual(operators.Length, 2);

            VFXContextUI[] contexts = view.Query().OfType <VFXContextUI>().ToList().ToArray();

            Assert.AreEqual(contexts.Length, 2);

            if (contexts[0].controller.model is VFXBasicUpdate)
            {
                var tmp = contexts[0];
                contexts[0] = contexts[1];
                contexts[1] = tmp;
            }


            VFXDataEdge[] dataEdges = view.Query().OfType <VFXDataEdge>().ToList().ToArray();

            Assert.AreEqual(dataEdges.Length, 4);

            Assert.IsNotNull(dataEdges.Where(t =>
                                             t.output.GetFirstAncestorOfType <VFXNodeUI>() == parameters[1] &&
                                             operators.Contains(t.input.GetFirstAncestorOfType <VFXOperatorUI>())
                                             ).FirstOrDefault());

            Assert.IsNotNull(dataEdges.Where(t =>
                                             operators.Contains(t.input.GetFirstAncestorOfType <VFXOperatorUI>()) &&
                                             operators.Contains(t.output.GetFirstAncestorOfType <VFXOperatorUI>()) &&
                                             t.output.GetFirstAncestorOfType <VFXNodeUI>() != t.input.GetFirstAncestorOfType <VFXNodeUI>()
                                             ).FirstOrDefault());

            Assert.IsNotNull(dataEdges.Where(t =>
                                             t.output.GetFirstAncestorOfType <VFXNodeUI>() == parameters[0] &&
                                             t.input.GetFirstAncestorOfType <VFXNodeUI>() == contexts[0]
                                             ).FirstOrDefault());

            Assert.IsNotNull(dataEdges.Where(t =>
                                             operators.Contains(t.output.GetFirstAncestorOfType <VFXNodeUI>()) &&
                                             t.input.GetFirstAncestorOfType <VFXNodeUI>() == contexts[0].GetAllBlocks().First()
                                             ).FirstOrDefault());


            VFXFlowEdge flowEdge = view.Query().OfType <VFXFlowEdge>();

            Assert.IsNotNull(flowEdge);

            Assert.AreEqual(flowEdge.output.GetFirstAncestorOfType <VFXContextUI>(), contexts[1]);
            Assert.AreEqual(flowEdge.input.GetFirstAncestorOfType <VFXContextUI>(), contexts[0]);
        }
    public override void OnInspectorGUI()
    {
        resourceObject.Update();

        bool enable = GUI.enabled; //Everything in external asset is disabled by default

        GUI.enabled = true;

        EditorGUI.BeginChangeCheck();
        EditorGUI.showMixedValue = resourceUpdateModeProperty.hasMultipleDifferentValues;
        VFXUpdateMode newUpdateMode = (VFXUpdateMode)EditorGUILayout.EnumPopup(EditorGUIUtility.TrTextContent("Update Mode"), (VFXUpdateMode)resourceUpdateModeProperty.intValue);

        if (EditorGUI.EndChangeCheck())
        {
            resourceUpdateModeProperty.intValue = (int)newUpdateMode;
            resourceObject.ApplyModifiedProperties();
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUI.showMixedValue = cullingFlagsProperty.hasMultipleDifferentValues;
        EditorGUILayout.PrefixLabel(EditorGUIUtility.TrTextContent("Culling Flags"));
        EditorGUI.BeginChangeCheck();
        int newOption = EditorGUILayout.Popup(Array.IndexOf(k_CullingOptionsValue, (VFXCullingFlags)cullingFlagsProperty.intValue), k_CullingOptionsContents);

        if (EditorGUI.EndChangeCheck())
        {
            cullingFlagsProperty.intValue = (int)k_CullingOptionsValue[newOption];
            resourceObject.ApplyModifiedProperties();
        }
        EditorGUILayout.EndHorizontal();

        if (prewarmDeltaTime != null && prewarmStepCount != null)
        {
            if (!prewarmDeltaTime.hasMultipleDifferentValues && !prewarmStepCount.hasMultipleDifferentValues)
            {
                var currentDeltaTime = prewarmDeltaTime.floatValue;
                var currentStepCount = prewarmStepCount.intValue;
                var currentTotalTime = currentDeltaTime * currentStepCount;
                EditorGUI.BeginChangeCheck();
                currentTotalTime = EditorGUILayout.FloatField(EditorGUIUtility.TrTextContent("PreWarm Total Time"), currentTotalTime);
                if (EditorGUI.EndChangeCheck())
                {
                    if (currentStepCount <= 0)
                    {
                        prewarmStepCount.intValue = currentStepCount = 1;
                    }

                    currentDeltaTime            = currentTotalTime / currentStepCount;
                    prewarmDeltaTime.floatValue = currentDeltaTime;
                    resourceObject.ApplyModifiedProperties();
                }

                EditorGUI.BeginChangeCheck();
                currentStepCount = EditorGUILayout.IntField(EditorGUIUtility.TrTextContent("PreWarm Step Count"), currentStepCount);
                if (EditorGUI.EndChangeCheck())
                {
                    if (currentStepCount <= 0 && currentTotalTime != 0.0f)
                    {
                        prewarmStepCount.intValue = currentStepCount = 1;
                    }

                    currentDeltaTime            = currentTotalTime == 0.0f ? 0.0f : currentTotalTime / currentStepCount;
                    prewarmDeltaTime.floatValue = currentDeltaTime;
                    prewarmStepCount.intValue   = currentStepCount;
                    resourceObject.ApplyModifiedProperties();
                }

                EditorGUI.BeginChangeCheck();
                currentDeltaTime = EditorGUILayout.FloatField(EditorGUIUtility.TrTextContent("PreWarm Delta Time"), currentDeltaTime);
                if (EditorGUI.EndChangeCheck())
                {
                    if (currentDeltaTime < k_MinimalCommonDeltaTime)
                    {
                        prewarmDeltaTime.floatValue = currentDeltaTime = k_MinimalCommonDeltaTime;
                    }

                    if (currentDeltaTime > currentTotalTime)
                    {
                        currentTotalTime = currentDeltaTime;
                    }

                    if (currentTotalTime != 0.0f)
                    {
                        var candidateStepCount_A = Mathf.FloorToInt(currentTotalTime / currentDeltaTime);
                        var candidateStepCount_B = Mathf.RoundToInt(currentTotalTime / currentDeltaTime);

                        var totalTime_A = currentDeltaTime * candidateStepCount_A;
                        var totalTime_B = currentDeltaTime * candidateStepCount_B;

                        if (Mathf.Abs(totalTime_A - currentTotalTime) < Mathf.Abs(totalTime_B - currentTotalTime))
                        {
                            currentStepCount = candidateStepCount_A;
                        }
                        else
                        {
                            currentStepCount = candidateStepCount_B;
                        }

                        prewarmStepCount.intValue = currentStepCount;
                    }
                    prewarmDeltaTime.floatValue = currentDeltaTime;
                    resourceObject.ApplyModifiedProperties();
                }
            }
            else
            {
                //Multi selection case, can't resolve total time easily
                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prewarmStepCount.hasMultipleDifferentValues;
                EditorGUILayout.PropertyField(prewarmStepCount, EditorGUIUtility.TrTextContent("PreWarm Step Count"));
                EditorGUI.showMixedValue = prewarmDeltaTime.hasMultipleDifferentValues;
                EditorGUILayout.PropertyField(prewarmDeltaTime, EditorGUIUtility.TrTextContent("PreWarm Delta Time"));
                if (EditorGUI.EndChangeCheck())
                {
                    if (prewarmDeltaTime.floatValue < k_MinimalCommonDeltaTime)
                    {
                        prewarmDeltaTime.floatValue = k_MinimalCommonDeltaTime;
                    }
                    resourceObject.ApplyModifiedProperties();
                }
            }
        }

        if (initialEventName != null)
        {
            EditorGUI.BeginChangeCheck();
            EditorGUI.showMixedValue = initialEventName.hasMultipleDifferentValues;
            EditorGUILayout.PropertyField(initialEventName);
            if (EditorGUI.EndChangeCheck())
            {
                resourceObject.ApplyModifiedProperties();
            }
        }

        if (!serializedObject.isEditingMultipleObjects)
        {
            VisualEffectAsset    asset    = (VisualEffectAsset)target;
            VisualEffectResource resource = asset.GetResource();

            m_OutputContexts.Clear();
            m_OutputContexts.AddRange(resource.GetOrCreateGraph().children.OfType <IVFXSubRenderer>().OrderBy(t => t.sortPriority));

            m_ReorderableList.DoLayoutList();

            VisualEffectEditor.ShowHeader(EditorGUIUtility.TrTextContent("Shaders"), false, false);

            var shaderSources = resource.shaderSources;

            string        assetPath = AssetDatabase.GetAssetPath(asset);
            UnityObject[] objects   = AssetDatabase.LoadAllAssetsAtPath(assetPath);
            string        directory = Path.GetDirectoryName(assetPath) + "/" + VFXExternalShaderProcessor.k_ShaderDirectory + "/" + asset.name + "/";

            foreach (var shader in objects)
            {
                if (shader is Shader || shader is ComputeShader)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(shader.name, GUILayout.ExpandWidth(true));
                    int index = resource.GetShaderIndex(shader);
                    if (index >= 0 && index < shaderSources.Length)
                    {
                        if (VFXExternalShaderProcessor.allowExternalization)
                        {
                            string externalPath = directory + shaderSources[index].name;
                            if (!shaderSources[index].compute)
                            {
                                externalPath = directory + shaderSources[index].name.Replace('/', '_') + VFXExternalShaderProcessor.k_ShaderExt;
                            }
                            else
                            {
                                externalPath = directory + shaderSources[index].name + VFXExternalShaderProcessor.k_ShaderExt;
                            }

                            if (System.IO.File.Exists(externalPath))
                            {
                                if (GUILayout.Button("Reveal External"))
                                {
                                    EditorUtility.RevealInFinder(externalPath);
                                }
                            }
                            else
                            {
                                if (GUILayout.Button("Externalize", GUILayout.Width(80)))
                                {
                                    Directory.CreateDirectory(directory);

                                    File.WriteAllText(externalPath, "//" + shaderSources[index].name + "," + index.ToString() + "\n//Don't delete the previous line or this one\n" + shaderSources[index].source);
                                }
                            }
                        }

                        if (GUILayout.Button("Show Generated", GUILayout.Width(110)))
                        {
                            resource.ShowGeneratedShaderFile(index);
                        }
                    }
                    if (GUILayout.Button("Select", GUILayout.Width(50)))
                    {
                        Selection.activeObject = shader;
                    }
                    GUILayout.EndHorizontal();
                }
            }
        }
        GUI.enabled = false;
    }
    void OnEnable()
    {
        VisualEffectAsset target = this.target as VisualEffectAsset;

        m_OutputContexts.Clear();
        m_OutputContexts.AddRange(target.GetResource().GetOrCreateGraph().children.OfType <IVFXSubRenderer>().OrderBy(t => t.sortPriority));

        m_ReorderableList = new ReorderableList(m_OutputContexts, typeof(IVFXSubRenderer));
        m_ReorderableList.displayRemove      = false;
        m_ReorderableList.displayAdd         = false;
        m_ReorderableList.onReorderCallback  = OnReorder;
        m_ReorderableList.drawHeaderCallback = DrawHeader;

        m_ReorderableList.drawElementCallback = DrawOutputContextItem;

        if (m_VisualEffectGO == null)
        {
            m_PreviewUtility = new PreviewRenderUtility();
            m_PreviewUtility.camera.fieldOfView           = 60.0f;
            m_PreviewUtility.camera.allowHDR              = true;
            m_PreviewUtility.camera.allowMSAA             = false;
            m_PreviewUtility.camera.farClipPlane          = 10000.0f;
            m_PreviewUtility.ambientColor                 = new Color(.1f, .1f, .1f, 1.0f);
            m_PreviewUtility.lights[0].intensity          = 1.4f;
            m_PreviewUtility.lights[0].transform.rotation = Quaternion.Euler(40f, 40f, 0);
            m_PreviewUtility.lights[1].intensity          = 1.4f;

            m_VisualEffectGO = new GameObject("VisualEffect (Preview)");

            m_VisualEffectGO.hideFlags = HideFlags.DontSave;
            m_VisualEffect             = m_VisualEffectGO.AddComponent <VisualEffect>();
            m_PreviewUtility.AddManagedGO(m_VisualEffectGO);

            m_VisualEffectGO.transform.localPosition = Vector3.zero;
            m_VisualEffectGO.transform.localRotation = Quaternion.identity;
            m_VisualEffectGO.transform.localScale    = Vector3.one;

            m_VisualEffect.visualEffectAsset = target;

            m_CurrentBounds = new Bounds(Vector3.zero, Vector3.one);
            m_FrameCount    = 0;
            m_Distance      = 10;
            m_Angles        = Vector3.forward;

            if (s_CubeWireFrame == null)
            {
                s_CubeWireFrame = new Mesh();

                var vertices = new Vector3[]
                {
                    new Vector3(-0.5f, -0.5f, -0.5f),
                    new Vector3(-0.5f, -0.5f, 0.5f),
                    new Vector3(-0.5f, 0.5f, 0.5f),
                    new Vector3(-0.5f, 0.5f, -0.5f),

                    new Vector3(0.5f, -0.5f, -0.5f),
                    new Vector3(0.5f, -0.5f, 0.5f),
                    new Vector3(0.5f, 0.5f, 0.5f),
                    new Vector3(0.5f, 0.5f, -0.5f)
                };


                var indices = new int[]
                {
                    0, 1,
                    0, 3,
                    0, 4,

                    6, 2,
                    6, 5,
                    6, 7,

                    1, 2,
                    1, 5,

                    3, 7,
                    3, 2,

                    4, 5,
                    4, 7
                };
                s_CubeWireFrame.vertices = vertices;
                s_CubeWireFrame.SetIndices(indices, MeshTopology.Lines, 0);
            }
        }


        resourceObject                 = new SerializedObject(targets.Cast <VisualEffectAsset>().Select(t => t.GetResource()).Where(t => t != null).ToArray());
        resourceUpdateModeProperty     = resourceObject.FindProperty("m_Infos.m_UpdateMode");
        cullingFlagsProperty           = resourceObject.FindProperty("m_Infos.m_CullingFlags");
        motionVectorRenderModeProperty = resourceObject.FindProperty("m_Infos.m_RendererSettings.motionVectorGenerationMode");
        prewarmDeltaTime               = resourceObject.FindProperty("m_Infos.m_PreWarmDeltaTime");
        prewarmStepCount               = resourceObject.FindProperty("m_Infos.m_PreWarmStepCount");
        initialEventName               = resourceObject.FindProperty("m_Infos.m_InitialEventName");
    }
    void OnPreprocessAsset()
    {
        if (!allowExternalization)
        {
            return;
        }
        if (assetPath.EndsWith(VisualEffectResource.Extension))
        {
            string vfxName      = Path.GetFileNameWithoutExtension(assetPath);
            string vfxDirectory = Path.GetDirectoryName(assetPath);

            string shaderDirectory = vfxDirectory + "/" + k_ShaderDirectory + "/" + vfxName;

            if (!Directory.Exists(shaderDirectory))
            {
                return;
            }
            VisualEffectAsset asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(assetPath);
            if (asset == null)
            {
                return;
            }

            bool oneFound = false;
            VisualEffectResource resource = asset.GetResource();
            if (resource == null)
            {
                return;
            }
            VFXShaderSourceDesc[] descs = resource.shaderSources;

            foreach (var shaderPath in Directory.GetFiles(shaderDirectory))
            {
                if (shaderPath.EndsWith(k_ShaderExt))
                {
                    System.IO.StreamReader file = new System.IO.StreamReader(shaderPath);

                    string shaderLine = file.ReadLine();
                    file.Close();
                    if (shaderLine == null || !shaderLine.StartsWith("//"))
                    {
                        continue;
                    }

                    string[] shaderParams = shaderLine.Split(',');

                    string shaderName = shaderParams[0].Substring(2);

                    int index;
                    if (!int.TryParse(shaderParams[1], out index))
                    {
                        continue;
                    }

                    if (index < 0 || index >= descs.Length)
                    {
                        continue;
                    }
                    if (descs[index].name != shaderName)
                    {
                        continue;
                    }

                    string shaderSource = File.ReadAllText(shaderPath);
                    //remove the first two lines that where added when externalized
                    shaderSource = shaderSource.Substring(shaderSource.IndexOf("\n", shaderSource.IndexOf("\n") + 1) + 1);

                    descs[index].source = shaderSource;
                    oneFound            = true;
                }
            }
            if (oneFound)
            {
                resource.shaderSources = descs;
            }
        }
    }
    static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
    {
        foreach (var assetPath in deletedAssets)
        {
            if (VisualEffectAssetModicationProcessor.HasVFXExtension(assetPath))
            {
                VisualEffectResource.DeleteAtPath(assetPath);
            }
        }

        if (!allowExternalization)
        {
            return;
        }
        HashSet <string> vfxToRefresh   = new HashSet <string>();
        HashSet <string> vfxToRecompile = new HashSet <string>(); // Recompile vfx if a shader is deleted to replace

        foreach (string assetPath in importedAssets.Concat(deletedAssets).Concat(movedAssets))
        {
            if (assetPath.EndsWith(k_ShaderExt))
            {
                string shaderDirectory = Path.GetDirectoryName(assetPath);
                string vfxName         = Path.GetFileName(shaderDirectory);
                string vfxPath         = Path.GetDirectoryName(shaderDirectory);

                if (Path.GetFileName(vfxPath) != k_ShaderDirectory)
                {
                    continue;
                }

                vfxPath = Path.GetDirectoryName(vfxPath) + "/" + vfxName + VisualEffectResource.Extension;

                if (deletedAssets.Contains(assetPath))
                {
                    vfxToRecompile.Add(vfxPath);
                }
                else
                {
                    vfxToRefresh.Add(vfxPath);
                }
            }
        }

        foreach (var assetPath in vfxToRecompile)
        {
            VisualEffectAsset asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(assetPath);
            if (asset == null)
            {
                continue;
            }

            // Force Recompilation to restore the previous shaders
            VisualEffectResource resource = asset.GetResource();
            if (resource == null)
            {
                continue;
            }
            resource.GetOrCreateGraph().SetExpressionGraphDirty();
            resource.GetOrCreateGraph().RecompileIfNeeded(false, true);
        }

        foreach (var assetPath in vfxToRefresh)
        {
            VisualEffectAsset asset = AssetDatabase.LoadAssetAtPath <VisualEffectAsset>(assetPath);
            if (asset == null)
            {
                return;
            }
            AssetDatabase.ImportAsset(assetPath);
        }
    }
Beispiel #21
0
    public override void OnInspectorGUI()
    {
        resourceObject.Update();

        GUI.enabled = AssetDatabase.IsOpenForEdit(this.target, StatusQueryOptions.UseCachedIfPossible);

        VFXUpdateMode initialUpdateMode          = (VFXUpdateMode)0;
        bool?         initialFixedDeltaTime      = null;
        bool?         initialProcessEveryFrame   = null;
        bool?         initialIgnoreGameTimeScale = null;

        if (resourceUpdateModeProperty.hasMultipleDifferentValues)
        {
            var resourceUpdateModeProperties = resourceUpdateModeProperty.serializedObject.targetObjects
                                               .Select(o => new SerializedObject(o)
                                                       .FindProperty(resourceUpdateModeProperty.propertyPath))
                                               .ToArray();  //N.B.: This will create garbage
            var allDeltaTime = resourceUpdateModeProperties.Select(o => ((VFXUpdateMode)o.intValue & VFXUpdateMode.DeltaTime) == VFXUpdateMode.DeltaTime)
                               .Distinct();
            var allProcessEveryFrame = resourceUpdateModeProperties.Select(o => ((VFXUpdateMode)o.intValue & VFXUpdateMode.ExactFixedTimeStep) == VFXUpdateMode.ExactFixedTimeStep)
                                       .Distinct();
            var allIgnoreScale = resourceUpdateModeProperties.Select(o => ((VFXUpdateMode)o.intValue & VFXUpdateMode.IgnoreTimeScale) == VFXUpdateMode.IgnoreTimeScale)
                                 .Distinct();
            if (allDeltaTime.Count() == 1)
            {
                initialFixedDeltaTime = !allDeltaTime.First();
            }
            if (allProcessEveryFrame.Count() == 1)
            {
                initialProcessEveryFrame = allProcessEveryFrame.First();
            }
            if (allIgnoreScale.Count() == 1)
            {
                initialIgnoreGameTimeScale = allIgnoreScale.First();
            }
        }
        else
        {
            initialUpdateMode          = (VFXUpdateMode)resourceUpdateModeProperty.intValue;
            initialFixedDeltaTime      = !((initialUpdateMode & VFXUpdateMode.DeltaTime) == VFXUpdateMode.DeltaTime);
            initialProcessEveryFrame   = (initialUpdateMode & VFXUpdateMode.ExactFixedTimeStep) == VFXUpdateMode.ExactFixedTimeStep;
            initialIgnoreGameTimeScale = (initialUpdateMode & VFXUpdateMode.IgnoreTimeScale) == VFXUpdateMode.IgnoreTimeScale;
        }

        EditorGUI.showMixedValue = !initialFixedDeltaTime.HasValue;
        var deltaTimeContent         = EditorGUIUtility.TrTextContent("Fixed Delta Time", "If enabled, use visual effect manager fixed delta time mode, otherwise, use the default Time.deltaTime.");
        var processEveryFrameContent = EditorGUIUtility.TrTextContent("Exact Fixed Time", "Only relevant when using Fixed Delta Time. When enabled, several updates can be processed per frame (e.g.: if a frame is 10ms and the fixed frame rate is set to 5 ms, the effect will update twice with a 5ms deltaTime instead of once with a 10ms deltaTime). This method is expensive and should only be used for high-end scenarios.");
        var ignoreTimeScaleContent   = EditorGUIUtility.TrTextContent("Ignore Time Scale", "When enabled, the computed visual effect delta time ignores the game Time Scale value (Play Rate is still applied).");

        EditorGUI.BeginChangeCheck();

        VisualEffectEditor.ShowHeader(EditorGUIUtility.TrTextContent("Update mode"), false, false);
        bool newFixedDeltaTime     = EditorGUILayout.Toggle(deltaTimeContent, initialFixedDeltaTime ?? false);
        bool newExactFixedTimeStep = false;

        EditorGUI.showMixedValue = !initialProcessEveryFrame.HasValue;
        EditorGUI.BeginDisabledGroup((!initialFixedDeltaTime.HasValue || !initialFixedDeltaTime.Value) && !resourceUpdateModeProperty.hasMultipleDifferentValues);
        newExactFixedTimeStep = EditorGUILayout.Toggle(processEveryFrameContent, initialProcessEveryFrame ?? false);
        EditorGUI.EndDisabledGroup();
        EditorGUI.showMixedValue = !initialIgnoreGameTimeScale.HasValue;
        bool newIgnoreTimeScale = EditorGUILayout.Toggle(ignoreTimeScaleContent, initialIgnoreGameTimeScale ?? false);

        if (EditorGUI.EndChangeCheck())
        {
            if (!resourceUpdateModeProperty.hasMultipleDifferentValues)
            {
                var newUpdateMode = (VFXUpdateMode)0;
                if (!newFixedDeltaTime)
                {
                    newUpdateMode = newUpdateMode | VFXUpdateMode.DeltaTime;
                }
                if (newExactFixedTimeStep)
                {
                    newUpdateMode = newUpdateMode | VFXUpdateMode.ExactFixedTimeStep;
                }
                if (newIgnoreTimeScale)
                {
                    newUpdateMode = newUpdateMode | VFXUpdateMode.IgnoreTimeScale;
                }

                resourceUpdateModeProperty.intValue = (int)newUpdateMode;
                resourceObject.ApplyModifiedProperties();
            }
            else
            {
                var resourceUpdateModeProperties = resourceUpdateModeProperty.serializedObject.targetObjects.Select(o => new SerializedObject(o).FindProperty(resourceUpdateModeProperty.propertyPath));
                foreach (var property in resourceUpdateModeProperties)
                {
                    var updateMode = (VFXUpdateMode)property.intValue;

                    if (initialFixedDeltaTime.HasValue)
                    {
                        if (!newFixedDeltaTime)
                        {
                            updateMode = updateMode | VFXUpdateMode.DeltaTime;
                        }
                        else
                        {
                            updateMode = updateMode & ~VFXUpdateMode.DeltaTime;
                        }
                    }
                    else
                    {
                        if (newFixedDeltaTime)
                        {
                            updateMode = updateMode & ~VFXUpdateMode.DeltaTime;
                        }
                    }

                    if (newExactFixedTimeStep)
                    {
                        updateMode = updateMode | VFXUpdateMode.ExactFixedTimeStep;
                    }
                    else if (initialProcessEveryFrame.HasValue)
                    {
                        updateMode = updateMode & ~VFXUpdateMode.ExactFixedTimeStep;
                    }

                    if (newIgnoreTimeScale)
                    {
                        updateMode = updateMode | VFXUpdateMode.IgnoreTimeScale;
                    }
                    else if (initialIgnoreGameTimeScale.HasValue)
                    {
                        updateMode = updateMode & ~VFXUpdateMode.IgnoreTimeScale;
                    }

                    property.intValue = (int)updateMode;
                    property.serializedObject.ApplyModifiedProperties();
                }
            }
        }
        VisualEffectAsset    asset    = (VisualEffectAsset)target;
        VisualEffectResource resource = asset.GetResource();

        //The following should be working, and works for newly created systems, but fails for old systems,
        //due probably to incorrectly pasting the VFXData when creating them.
        // bool hasAutomaticBoundsSystems = resource.GetOrCreateGraph().children
        //     .OfType<VFXDataParticle>().Any(d => d.boundsMode == BoundsSettingMode.Automatic);

        bool hasAutomaticBoundsSystems = resource.GetOrCreateGraph().children
                                         .OfType <VFXBasicInitialize>().Any(d => (d.GetData() as VFXDataParticle).boundsMode == BoundsSettingMode.Automatic);

        using (new EditorGUI.DisabledScope(hasAutomaticBoundsSystems))
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUI.showMixedValue = cullingFlagsProperty.hasMultipleDifferentValues;
            string forceSimulateTooltip = hasAutomaticBoundsSystems
                ? " When using systems with Bounds Mode set to Automatic, this has to be set to Always recompute bounds and simulate."
                : "";
            EditorGUILayout.PrefixLabel(EditorGUIUtility.TrTextContent("Culling Flags", "Specifies how the system recomputes its bounds and simulates when off-screen." + forceSimulateTooltip));
            EditorGUI.BeginChangeCheck();

            int newOption =
                EditorGUILayout.Popup(
                    Array.IndexOf(k_CullingOptionsValue, (VFXCullingFlags)cullingFlagsProperty.intValue),
                    k_CullingOptionsContents);
            if (EditorGUI.EndChangeCheck())
            {
                cullingFlagsProperty.intValue = (int)k_CullingOptionsValue[newOption];
                resourceObject.ApplyModifiedProperties();
            }
        }

        EditorGUILayout.EndHorizontal();

        VisualEffectEditor.ShowHeader(EditorGUIUtility.TrTextContent("Initial state"), false, false);
        if (prewarmDeltaTime != null && prewarmStepCount != null)
        {
            DisplayPrewarmInspectorGUI(resourceObject, prewarmDeltaTime, prewarmStepCount);
        }

        if (initialEventName != null)
        {
            EditorGUI.BeginChangeCheck();
            EditorGUI.showMixedValue = initialEventName.hasMultipleDifferentValues;
            EditorGUILayout.PropertyField(initialEventName, new GUIContent("Initial Event Name", "Sets the name of the event which triggers once the system is activated. Default: ‘OnPlay’."));
            if (EditorGUI.EndChangeCheck())
            {
                resourceObject.ApplyModifiedProperties();
            }
        }

        if (!serializedObject.isEditingMultipleObjects)
        {
            asset    = (VisualEffectAsset)target;
            resource = asset.GetResource();

            m_OutputContexts.Clear();
            m_OutputContexts.AddRange(resource.GetOrCreateGraph().children.OfType <IVFXSubRenderer>().OrderBy(t => t.vfxSystemSortPriority));

            m_ReorderableList.DoLayoutList();

            VisualEffectEditor.ShowHeader(EditorGUIUtility.TrTextContent("Shaders"), false, false);

            string        assetPath = AssetDatabase.GetAssetPath(asset);
            UnityObject[] objects   = AssetDatabase.LoadAllAssetsAtPath(assetPath);
            string        directory = Path.GetDirectoryName(assetPath) + "/" + VFXExternalShaderProcessor.k_ShaderDirectory + "/" + asset.name + "/";

            foreach (var obj in objects)
            {
                if (obj is Material || obj is ComputeShader)
                {
                    GUILayout.BeginHorizontal();
                    Rect r = GUILayoutUtility.GetRect(0, 18, GUILayout.ExpandWidth(true));

                    int buttonsWidth = VFXExternalShaderProcessor.allowExternalization ? 240 : 160;

                    int index = resource.GetShaderIndex(obj);

                    var shader = obj;
                    if (obj is Material) // Retrieve the shader from the material
                    {
                        shader = ((Material)(obj)).shader;
                    }
                    if (shader == null)
                    {
                        continue;
                    }

                    Rect labelR = r;
                    labelR.width -= buttonsWidth;
                    GUI.Label(labelR, shader.name.Replace('\n', ' '));

                    if (index >= 0)
                    {
                        if (VFXExternalShaderProcessor.allowExternalization && index < resource.GetShaderSourceCount())
                        {
                            string shaderSourceName = resource.GetShaderSourceName(index);
                            string externalPath     = directory + shaderSourceName;

                            externalPath = directory + shaderSourceName.Replace('/', '_') + VFXExternalShaderProcessor.k_ShaderExt;

                            Rect buttonRect = r;
                            buttonRect.xMin  = labelR.xMax;
                            buttonRect.width = 80;
                            labelR.width    += 80;
                            if (System.IO.File.Exists(externalPath))
                            {
                                if (GUI.Button(buttonRect, "Reveal External"))
                                {
                                    EditorUtility.RevealInFinder(externalPath);
                                }
                            }
                            else
                            {
                                if (GUI.Button(buttonRect, "Externalize"))
                                {
                                    Directory.CreateDirectory(directory);

                                    File.WriteAllText(externalPath, "//" + shaderSourceName + "," + index.ToString() + "\n//Don't delete the previous line or this one\n" + resource.GetShaderSource(index));
                                }
                            }
                        }

                        Rect buttonR = r;
                        buttonR.xMin  = labelR.xMax;
                        buttonR.width = 110;
                        labelR.width += 110;
                        if (GUI.Button(buttonR, "Show Generated"))
                        {
                            resource.ShowGeneratedShaderFile(index);
                        }
                    }

                    Rect selectButtonR = r;
                    selectButtonR.xMin  = labelR.xMax;
                    selectButtonR.width = 50;
                    if (GUI.Button(selectButtonR, "Select"))
                    {
                        Selection.activeObject = shader;
                    }
                    GUILayout.EndHorizontal();
                }
            }
        }
        GUI.enabled = false;
    }
        protected virtual void DrawParameters()
        {
#if !WORKAROUND_TIMELINE
            if (s_FakeObjectCache == null)
            {
                s_FakeObjectCache           = ScriptableObject.CreateInstance <FakeObject>();
                s_FakeObjectSerializedCache = new SerializedObject(s_FakeObjectCache);
            }
#endif
            var component = (VisualEffect)target;
            if (m_graph == null || m_asset != component.visualEffectAsset)
            {
                m_asset = component.visualEffectAsset;
                if (m_asset != null)
                {
                    m_graph = m_asset.GetResource().GetOrCreateGraph();
                }
            }

            GUI.enabled = true;

            if (m_graph != null)
            {
                if (m_graph.m_ParameterInfo == null)
                {
                    m_graph.BuildParameterInfo();
                }

                if (m_graph.m_ParameterInfo != null)
                {
                    ShowHeader(Contents.headerParameters, false, false, false, false);
                    var stack        = new List <int>();
                    int currentCount = m_graph.m_ParameterInfo.Length;
                    if (currentCount == 0)
                    {
                        GUILayout.Label("No Parameter exposed in the asset");
                    }

                    bool ignoreUntilNextCat = false;

                    foreach (var param in m_graph.m_ParameterInfo)
                    {
                        --currentCount;

                        var parameter = param;
                        if (parameter.descendantCount > 0)
                        {
                            stack.Add(currentCount);
                            currentCount = parameter.descendantCount;
                        }

                        if (currentCount == 0 && stack.Count > 0)
                        {
                            do
                            {
                                currentCount = stack.Last();
                                stack.RemoveAt(stack.Count - 1);
                            }while (currentCount == 0);
                        }

                        if (string.IsNullOrEmpty(parameter.sheetType))
                        {
                            if (!string.IsNullOrEmpty(parameter.name))
                            {
                                if (string.IsNullOrEmpty(parameter.realType)) // This is a category
                                {
                                    bool wasIgnored = ignoreUntilNextCat;
                                    ignoreUntilNextCat = false;
                                    var nameContent = GetGUIContent(parameter.name);

                                    bool prevState    = EditorPrefs.GetBool("VFX-category-" + parameter.name, true);
                                    bool currentState = ShowHeader(nameContent, !wasIgnored, false, true, prevState);
                                    if (currentState != prevState)
                                    {
                                        EditorPrefs.SetBool("VFX-category-" + parameter.name, currentState);
                                    }

                                    if (!currentState)
                                    {
                                        ignoreUntilNextCat = true;
                                    }
                                    else
                                    {
                                        GUILayout.Space(Styles.headerBottomMargin);
                                    }
                                }
                                else if (!ignoreUntilNextCat)
                                {
                                    EmptyLineControl(parameter.name, parameter.tooltip, stack.Count);
                                }
                            }
                        }
                        else if (!ignoreUntilNextCat)
                        {
                            //< Try find source property
                            var sourceVfxField = m_VFXPropertySheet.FindPropertyRelative(parameter.sheetType + ".m_Array");
                            SerializedProperty sourceProperty = null;
                            for (int i = 0; i < sourceVfxField.arraySize; ++i)
                            {
                                sourceProperty = sourceVfxField.GetArrayElementAtIndex(i);
                                var nameProperty = sourceProperty.FindPropertyRelative("m_Name").stringValue;
                                if (nameProperty == parameter.path)
                                {
                                    break;
                                }
                                sourceProperty = null;
                            }

                            //< Prepare potential indirection
                            bool wasNewProperty           = false;
                            bool wasNotOverriddenProperty = false;

                            SerializedProperty actualDisplayedPropertyValue      = null;
                            SerializedProperty actualDisplayedPropertyOverridden = null;
                            if (sourceProperty == null)
                            {
                                s_FakeObjectSerializedCache.Update();
                                var fakeField = s_FakeObjectSerializedCache.FindProperty("m_PropertySheet." + parameter.sheetType + ".m_Array");
                                fakeField.InsertArrayElementAtIndex(fakeField.arraySize);
                                var newFakeEntry = fakeField.GetArrayElementAtIndex(fakeField.arraySize - 1);
                                newFakeEntry.FindPropertyRelative("m_Name").stringValue     = param.path;
                                newFakeEntry.FindPropertyRelative("m_Overridden").boolValue = false;

                                actualDisplayedPropertyOverridden = newFakeEntry.FindPropertyRelative("m_Overridden");
                                actualDisplayedPropertyValue      = newFakeEntry.FindPropertyRelative("m_Value");
                                SetObjectValue(actualDisplayedPropertyValue, parameter.defaultValue.Get());

                                wasNewProperty = true;
                            }
                            else
                            {
                                actualDisplayedPropertyOverridden = sourceProperty.FindPropertyRelative("m_Overridden");
                                actualDisplayedPropertyValue      = sourceProperty.FindPropertyRelative("m_Value");
                                if (!actualDisplayedPropertyOverridden.boolValue)
                                {
                                    s_FakeObjectSerializedCache.Update();

                                    actualDisplayedPropertyOverridden = s_FakeObjectSerializedCache.FindProperty(actualDisplayedPropertyOverridden.propertyPath);
                                    actualDisplayedPropertyValue      = s_FakeObjectSerializedCache.FindProperty(actualDisplayedPropertyValue.propertyPath);
                                    SetObjectValue(actualDisplayedPropertyValue, parameter.defaultValue.Get());

                                    wasNotOverriddenProperty = true;
                                }
                            }

                            //< Actual display
                            GUIContent nameContent = GetGUIContent(parameter.name, parameter.tooltip);
                            EditorGUI.BeginChangeCheck();
                            DisplayProperty(ref parameter, nameContent, actualDisplayedPropertyOverridden, actualDisplayedPropertyValue, AnimationMode.IsPropertyAnimated(target, actualDisplayedPropertyValue.propertyPath));
                            if (EditorGUI.EndChangeCheck())
                            {
                                if (wasNewProperty)
                                {
                                    //We start editing a new exposed value which wasn't stored in this Visual Effect Component
                                    sourceVfxField.InsertArrayElementAtIndex(sourceVfxField.arraySize);
                                    var newEntry = sourceVfxField.GetArrayElementAtIndex(sourceVfxField.arraySize - 1);

                                    newEntry.FindPropertyRelative("m_Overridden").boolValue = actualDisplayedPropertyOverridden.boolValue;
                                    SetObjectValue(newEntry.FindPropertyRelative("m_Value"), GetObjectValue(actualDisplayedPropertyValue));
                                    newEntry.FindPropertyRelative("m_Name").stringValue = param.path;
                                }
                                else if (wasNotOverriddenProperty)
                                {
                                    if (actualDisplayedPropertyOverridden.boolValue)
                                    {
                                        //The check box has simply been toggle, we should not restore value from asset but simply change overridden state
                                        sourceProperty.FindPropertyRelative("m_Overridden").boolValue = true;
                                    }
                                    else
                                    {
                                        //The value has been directly changed, change overridden state and recopy new value
                                        SetObjectValue(sourceProperty.FindPropertyRelative("m_Value"), GetObjectValue(actualDisplayedPropertyValue));
                                        sourceProperty.FindPropertyRelative("m_Overridden").boolValue = true;
                                    }
                                }
                                else //wasNewProperty == wasNotOverriddenProperty == false => there isn't any additionnal behavior needed, we are already using real serialized property
                                {
                                }
                                serializedObject.ApplyModifiedProperties();
                            }
                        }
                        EditorGUI.indentLevel = stack.Count;
                    }
                }
            }
            GUILayout.Space(1); // Space for the line if the last category is closed.
        }
        protected virtual void DrawParameters()
        {
#if !WORKAROUND_TIMELINE
            if (s_FakeObjectCache == null)
            {
                s_FakeObjectCache           = ScriptableObject.CreateInstance <FakeObject>();
                s_FakeObjectSerializedCache = new SerializedObject(s_FakeObjectCache);
            }
#endif
            var component = (VisualEffect)target;
            if (m_graph == null || m_asset != component.visualEffectAsset)
            {
                m_asset = component.visualEffectAsset;
                if (m_asset != null)
                {
                    m_graph = m_asset.GetResource().GetOrCreateGraph();
                }
            }

            GUI.enabled = true;

            if (m_graph != null)
            {
                if (m_graph.m_ParameterInfo == null)
                {
                    m_graph.BuildParameterInfo();
                }

                if (m_graph.m_ParameterInfo != null)
                {
                    ShowHeader(Contents.headerParameters, false, false, false, false);
                    List <int> stack        = new List <int>();
                    int        currentCount = m_graph.m_ParameterInfo.Length;
                    if (currentCount == 0)
                    {
                        GUILayout.Label("No Parameter exposed in the asset");
                    }

                    bool ignoreUntilNextCat = false;

                    foreach (var param in m_graph.m_ParameterInfo)
                    {
                        --currentCount;

                        var parameter = param;

                        if (parameter.descendantCount > 0)
                        {
                            stack.Add(currentCount);
                            currentCount = parameter.descendantCount;
                        }

                        if (currentCount == 0 && stack.Count > 0)
                        {
                            do
                            {
                                currentCount = stack.Last();
                                stack.RemoveAt(stack.Count - 1);
                            }while (currentCount == 0);
                        }

                        if (string.IsNullOrEmpty(parameter.sheetType))
                        {
                            if (!string.IsNullOrEmpty(parameter.name))
                            {
                                if (string.IsNullOrEmpty(parameter.realType)) // This is a category
                                {
                                    bool wasIgnored = ignoreUntilNextCat;
                                    ignoreUntilNextCat = false;
                                    var nameContent = GetGUIContent(parameter.name);

                                    bool prevState    = EditorPrefs.GetBool("VFX-category-" + parameter.name, true);
                                    bool currentState = ShowHeader(nameContent, !wasIgnored, false, true, prevState);
                                    if (currentState != prevState)
                                    {
                                        EditorPrefs.SetBool("VFX-category-" + parameter.name, currentState);
                                    }

                                    if (!currentState)
                                    {
                                        ignoreUntilNextCat = true;
                                    }
                                    else
                                    {
                                        GUILayout.Space(Styles.headerBottomMargin);
                                    }
                                }
                                else if (!ignoreUntilNextCat)
                                {
                                    EmptyLineControl(parameter.name, parameter.tooltip, stack.Count);
                                }
                            }
                        }
                        else if (!ignoreUntilNextCat)
                        {
                            var vfxField = m_VFXPropertySheet.FindPropertyRelative(parameter.sheetType + ".m_Array");
                            SerializedProperty property = null;
                            if (vfxField != null)
                            {
                                for (int i = 0; i < vfxField.arraySize; ++i)
                                {
                                    property = vfxField.GetArrayElementAtIndex(i);
                                    var nameProperty = property.FindPropertyRelative("m_Name").stringValue;
                                    if (nameProperty == parameter.path)
                                    {
                                        break;
                                    }

                                    property = null;
                                }
                            }

                            if (property != null)
                            {
                                SerializedProperty overrideProperty = property.FindPropertyRelative("m_Overridden");
                                property = property.FindPropertyRelative("m_Value");
                                string firstpropName = property.name;

                                Color previousColor = GUI.color;
                                var   animated      = AnimationMode.IsPropertyAnimated(target, property.propertyPath);
                                if (animated)
                                {
                                    GUI.color = AnimationMode.animatedPropertyColor;
                                }

                                DisplayProperty(ref parameter, overrideProperty, property);

                                if (animated)
                                {
                                    GUI.color = previousColor;
                                }
                            }
                        }

                        EditorGUI.indentLevel = stack.Count;
                    }
                }
            }
            GUILayout.Space(1); // Space for the line if the last category is closed.
        }
Beispiel #24
0
    public override void OnInspectorGUI()
    {
        resourceObject.Update();

        GUI.enabled = AssetDatabase.IsOpenForEdit(this.target, StatusQueryOptions.UseCachedIfPossible);

        EditorGUI.BeginChangeCheck();
        EditorGUI.showMixedValue = resourceUpdateModeProperty.hasMultipleDifferentValues;
        VFXUpdateMode newUpdateMode = (VFXUpdateMode)EditorGUILayout.EnumPopup(EditorGUIUtility.TrTextContent("Update Mode", "Specifies whether particles are updated using a fixed timestep (Fixed Delta Time), or in a frame-rate independent manner (Delta Time)."), (VFXUpdateMode)resourceUpdateModeProperty.intValue);

        if (EditorGUI.EndChangeCheck())
        {
            resourceUpdateModeProperty.intValue = (int)newUpdateMode;
            resourceObject.ApplyModifiedProperties();
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUI.showMixedValue = cullingFlagsProperty.hasMultipleDifferentValues;
        EditorGUILayout.PrefixLabel(EditorGUIUtility.TrTextContent("Culling Flags", "Specifies how the system recomputes its bounds and simulates when off-screen."));
        EditorGUI.BeginChangeCheck();
        int newOption = EditorGUILayout.Popup(Array.IndexOf(k_CullingOptionsValue, (VFXCullingFlags)cullingFlagsProperty.intValue), k_CullingOptionsContents);

        if (EditorGUI.EndChangeCheck())
        {
            cullingFlagsProperty.intValue = (int)k_CullingOptionsValue[newOption];
            resourceObject.ApplyModifiedProperties();
        }
        EditorGUILayout.EndHorizontal();

        if (prewarmDeltaTime != null && prewarmStepCount != null)
        {
            if (!prewarmDeltaTime.hasMultipleDifferentValues && !prewarmStepCount.hasMultipleDifferentValues)
            {
                var currentDeltaTime = prewarmDeltaTime.floatValue;
                var currentStepCount = prewarmStepCount.intValue;
                var currentTotalTime = currentDeltaTime * currentStepCount;
                EditorGUI.BeginChangeCheck();
                currentTotalTime = EditorGUILayout.FloatField(EditorGUIUtility.TrTextContent("PreWarm Total Time", "Sets the time in seconds to advance the current effect to when it is initially played. "), currentTotalTime);
                if (EditorGUI.EndChangeCheck())
                {
                    if (currentStepCount <= 0)
                    {
                        prewarmStepCount.intValue = currentStepCount = 1;
                    }

                    currentDeltaTime            = currentTotalTime / currentStepCount;
                    prewarmDeltaTime.floatValue = currentDeltaTime;
                    resourceObject.ApplyModifiedProperties();
                }

                EditorGUI.BeginChangeCheck();
                currentStepCount = EditorGUILayout.IntField(EditorGUIUtility.TrTextContent("PreWarm Step Count", "Sets the number of simulation steps the prewarm should be broken down to. "), currentStepCount);
                if (EditorGUI.EndChangeCheck())
                {
                    if (currentStepCount <= 0 && currentTotalTime != 0.0f)
                    {
                        prewarmStepCount.intValue = currentStepCount = 1;
                    }

                    currentDeltaTime            = currentTotalTime == 0.0f ? 0.0f : currentTotalTime / currentStepCount;
                    prewarmDeltaTime.floatValue = currentDeltaTime;
                    prewarmStepCount.intValue   = currentStepCount;
                    resourceObject.ApplyModifiedProperties();
                }

                EditorGUI.BeginChangeCheck();
                currentDeltaTime = EditorGUILayout.FloatField(EditorGUIUtility.TrTextContent("PreWarm Delta Time", "Sets the time in seconds for each step to achieve the desired total prewarm time."), currentDeltaTime);
                if (EditorGUI.EndChangeCheck())
                {
                    if (currentDeltaTime < k_MinimalCommonDeltaTime)
                    {
                        prewarmDeltaTime.floatValue = currentDeltaTime = k_MinimalCommonDeltaTime;
                    }

                    if (currentDeltaTime > currentTotalTime)
                    {
                        currentTotalTime = currentDeltaTime;
                    }

                    if (currentTotalTime != 0.0f)
                    {
                        var candidateStepCount_A = Mathf.FloorToInt(currentTotalTime / currentDeltaTime);
                        var candidateStepCount_B = Mathf.RoundToInt(currentTotalTime / currentDeltaTime);

                        var totalTime_A = currentDeltaTime * candidateStepCount_A;
                        var totalTime_B = currentDeltaTime * candidateStepCount_B;

                        if (Mathf.Abs(totalTime_A - currentTotalTime) < Mathf.Abs(totalTime_B - currentTotalTime))
                        {
                            currentStepCount = candidateStepCount_A;
                        }
                        else
                        {
                            currentStepCount = candidateStepCount_B;
                        }

                        prewarmStepCount.intValue = currentStepCount;
                    }
                    prewarmDeltaTime.floatValue = currentDeltaTime;
                    resourceObject.ApplyModifiedProperties();
                }
            }
            else
            {
                //Multi selection case, can't resolve total time easily
                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prewarmStepCount.hasMultipleDifferentValues;
                EditorGUILayout.PropertyField(prewarmStepCount, EditorGUIUtility.TrTextContent("PreWarm Step Count", "Sets the number of simulation steps the prewarm should be broken down to."));
                EditorGUI.showMixedValue = prewarmDeltaTime.hasMultipleDifferentValues;
                EditorGUILayout.PropertyField(prewarmDeltaTime, EditorGUIUtility.TrTextContent("PreWarm Delta Time", "Sets the time in seconds for each step to achieve the desired total prewarm time."));
                if (EditorGUI.EndChangeCheck())
                {
                    if (prewarmDeltaTime.floatValue < k_MinimalCommonDeltaTime)
                    {
                        prewarmDeltaTime.floatValue = k_MinimalCommonDeltaTime;
                    }
                    resourceObject.ApplyModifiedProperties();
                }
            }
        }

        if (initialEventName != null)
        {
            EditorGUI.BeginChangeCheck();
            EditorGUI.showMixedValue = initialEventName.hasMultipleDifferentValues;
            EditorGUILayout.PropertyField(initialEventName, new GUIContent("Initial Event Name", "Sets the name of the event which triggers once the system is activated. Default: ‘OnPlay’."));
            if (EditorGUI.EndChangeCheck())
            {
                resourceObject.ApplyModifiedProperties();
            }
        }

        if (!serializedObject.isEditingMultipleObjects)
        {
            VisualEffectAsset    asset    = (VisualEffectAsset)target;
            VisualEffectResource resource = asset.GetResource();

            m_OutputContexts.Clear();
            m_OutputContexts.AddRange(resource.GetOrCreateGraph().children.OfType <IVFXSubRenderer>().OrderBy(t => t.sortPriority));

            m_ReorderableList.DoLayoutList();

            VisualEffectEditor.ShowHeader(EditorGUIUtility.TrTextContent("Shaders"), false, false);

            string        assetPath = AssetDatabase.GetAssetPath(asset);
            UnityObject[] objects   = AssetDatabase.LoadAllAssetsAtPath(assetPath);
            string        directory = Path.GetDirectoryName(assetPath) + "/" + VFXExternalShaderProcessor.k_ShaderDirectory + "/" + asset.name + "/";

            foreach (var shader in objects)
            {
                if (shader is Shader || shader is ComputeShader)
                {
                    GUILayout.BeginHorizontal();
                    Rect r = GUILayoutUtility.GetRect(0, 18, GUILayout.ExpandWidth(true));

                    int buttonsWidth = VFXExternalShaderProcessor.allowExternalization? 240:160;


                    Rect labelR = r;
                    labelR.width -= buttonsWidth;
                    GUI.Label(labelR, shader.name);
                    int index = resource.GetShaderIndex(shader);
                    if (index >= 0)
                    {
                        if (VFXExternalShaderProcessor.allowExternalization && index < resource.GetShaderSourceCount())
                        {
                            string shaderSourceName = resource.GetShaderSourceName(index);
                            string externalPath     = directory + shaderSourceName;

                            externalPath = directory + shaderSourceName.Replace('/', '_') + VFXExternalShaderProcessor.k_ShaderExt;

                            Rect buttonRect = r;
                            buttonRect.xMin  = labelR.xMax;
                            buttonRect.width = 80;
                            labelR.width    += 80;
                            if (System.IO.File.Exists(externalPath))
                            {
                                if (GUI.Button(buttonRect, "Reveal External"))
                                {
                                    EditorUtility.RevealInFinder(externalPath);
                                }
                            }
                            else
                            {
                                if (GUI.Button(buttonRect, "Externalize"))
                                {
                                    Directory.CreateDirectory(directory);

                                    File.WriteAllText(externalPath, "//" + shaderSourceName + "," + index.ToString() + "\n//Don't delete the previous line or this one\n" + resource.GetShaderSource(index));
                                }
                            }
                        }

                        Rect buttonR = r;
                        buttonR.xMin  = labelR.xMax;
                        buttonR.width = 110;
                        labelR.width += 110;
                        if (GUI.Button(buttonR, "Show Generated"))
                        {
                            resource.ShowGeneratedShaderFile(index);
                        }
                    }

                    Rect selectButtonR = r;
                    selectButtonR.xMin  = labelR.xMax;
                    selectButtonR.width = 50;
                    if (GUI.Button(selectButtonR, "Select"))
                    {
                        Selection.activeObject = shader;
                    }
                    GUILayout.EndHorizontal();
                }
            }
        }
        GUI.enabled = false;
    }
        public void RecreateCopy()
        {
            DetachFromOriginal();

            if (m_Subgraph == null)
            {
                m_SubChildren = null;
                return;
            }

            var resource = m_Subgraph.GetResource();

            if (resource == null)
            {
                m_SubChildren = null;
                return;
            }

            var graph = resource.GetOrCreateGraph();
            HashSet <ScriptableObject> dependencies = new HashSet <ScriptableObject>();

            graph.CollectDependencies(dependencies);

            var duplicated = VFXMemorySerializer.DuplicateObjects(dependencies.ToArray());

            m_SubChildren = duplicated.OfType <VFXModel>().Where(t => t is VFXContext || t is VFXOperator || t is VFXParameter).ToArray();

            foreach (var child in duplicated.Zip(dependencies, (a, b) => new { copy = a, original = b }))
            {
                child.copy.hideFlags = HideFlags.HideAndDontSave;
                if (child.copy is VFXSlot)
                {
                    var original = child.original as VFXSlot;
                    var copy     = child.copy as VFXSlot;
                    if (original.direction == VFXSlot.Direction.kInput || original.owner is VFXParameter)
                    {
                        m_OriginalToCopy[original]     = copy;
                        original.onInvalidateDelegate += OnOriginalSlotModified;
                    }
                }
            }

            List <string> newInputFlowNames = new List <string>();

            foreach (var basicEvent in m_SubChildren.OfType <VFXBasicEvent>())
            {
                if (!newInputFlowNames.Contains(basicEvent.eventName))
                {
                    newInputFlowNames.Add(basicEvent.eventName);
                }
            }

            bool hasStart = false;
            bool hasStop  = false;

            foreach (var initialize in m_SubChildren.OfType <VFXBasicSpawner>())
            {
                if (!hasStart && initialize.inputFlowSlot[0].link.Count() == 0)
                {
                    hasStart = true;
                }
                if (!hasStop && initialize.inputFlowSlot[1].link.Count() == 0)
                {
                    hasStop = true;
                }
            }

            int directEventCount = newInputFlowNames.Count;

            foreach (var subContext in m_SubChildren.OfType <VFXSubgraphContext>())
            {
                for (int i = 0; i < subContext.inputFlowCount; ++i)
                {
                    string name = subContext.GetInputFlowName(i);
                    switch (name)
                    {
                    case VisualEffectAsset.PlayEventName:
                        hasStart = true;
                        break;

                    case VisualEffectAsset.StopEventName:
                        hasStop = true;
                        break;

                    default:
                        m_InputFlowNames.Add(name);
                        break;
                    }
                }
            }
            newInputFlowNames.Sort(0, directEventCount, Comparer <string> .Default);
            newInputFlowNames.Sort(directEventCount, newInputFlowNames.Count - directEventCount, Comparer <string> .Default);
            if (hasStop)
            {
                newInputFlowNames.Insert(0, VisualEffectAsset.StopEventName);
            }
            if (hasStart)
            {
                newInputFlowNames.Insert(0, VisualEffectAsset.PlayEventName);
            }

            if (!newInputFlowNames.SequenceEqual(m_InputFlowNames) || inputFlowSlot.Length != inputFlowCount)
            {
                var oldLinks = new Dictionary <string, List <VFXContextLink> >();

                for (int i = 0; i < inputFlowSlot.Count() && i < m_InputFlowNames.Count; ++i)
                {
                    oldLinks[GetInputFlowName(i)] = inputFlowSlot[i].link.ToList();
                }
                m_InputFlowNames = newInputFlowNames;
                RefreshInputFlowSlots();

                for (int i = 0; i < inputFlowSlot.Count(); ++i)
                {
                    List <VFXContextLink> ctxSlot;
                    if (oldLinks.TryGetValue(GetInputFlowName(i), out ctxSlot))
                    {
                        foreach (var link in ctxSlot)
                        {
                            LinkFrom(link.context, link.slotIndex, i);
                        }
                    }
                }
            }

            SyncSlots(VFXSlot.Direction.kInput, true);
        }
Beispiel #26
0
    public override void OnInspectorGUI()
    {
        resourceObject.Update();

        GUI.enabled = AssetDatabase.IsOpenForEdit(this.target, StatusQueryOptions.UseCachedIfPossible);

        VFXUpdateMode initialUpdateMode          = (VFXUpdateMode)0;
        bool?         initialFixedDeltaTime      = null;
        bool?         initialProcessEveryFrame   = null;
        bool?         initialIgnoreGameTimeScale = null;

        if (resourceUpdateModeProperty.hasMultipleDifferentValues)
        {
            var resourceUpdateModeProperties = resourceUpdateModeProperty.serializedObject.targetObjects
                                               .Select(o => new SerializedObject(o)
                                                       .FindProperty(resourceUpdateModeProperty.propertyPath))
                                               .ToArray();  //N.B.: This will create garbage
            var allDeltaTime = resourceUpdateModeProperties.Select(o => ((VFXUpdateMode)o.intValue & VFXUpdateMode.DeltaTime) == VFXUpdateMode.DeltaTime)
                               .Distinct();
            var allProcessEveryFrame = resourceUpdateModeProperties.Select(o => ((VFXUpdateMode)o.intValue & VFXUpdateMode.ExactFixedTimeStep) == VFXUpdateMode.ExactFixedTimeStep)
                                       .Distinct();
            var allIgnoreScale = resourceUpdateModeProperties.Select(o => ((VFXUpdateMode)o.intValue & VFXUpdateMode.IgnoreTimeScale) == VFXUpdateMode.IgnoreTimeScale)
                                 .Distinct();
            if (allDeltaTime.Count() == 1)
            {
                initialFixedDeltaTime = !allDeltaTime.First();
            }
            if (allProcessEveryFrame.Count() == 1)
            {
                initialProcessEveryFrame = allProcessEveryFrame.First();
            }
            if (allIgnoreScale.Count() == 1)
            {
                initialIgnoreGameTimeScale = allIgnoreScale.First();
            }
        }
        else
        {
            initialUpdateMode          = (VFXUpdateMode)resourceUpdateModeProperty.intValue;
            initialFixedDeltaTime      = !((initialUpdateMode & VFXUpdateMode.DeltaTime) == VFXUpdateMode.DeltaTime);
            initialProcessEveryFrame   = (initialUpdateMode & VFXUpdateMode.ExactFixedTimeStep) == VFXUpdateMode.ExactFixedTimeStep;
            initialIgnoreGameTimeScale = (initialUpdateMode & VFXUpdateMode.IgnoreTimeScale) == VFXUpdateMode.IgnoreTimeScale;
        }

        EditorGUI.showMixedValue = !initialFixedDeltaTime.HasValue;
        var deltaTimeContent         = EditorGUIUtility.TrTextContent("Fixed Delta Time", "If enabled, use visual effect manager fixed delta time mode, otherwise, use the default Time.deltaTime.");
        var processEveryFrameContent = EditorGUIUtility.TrTextContent("Exact Fixed Time", "Only relevant when using Fixed Delta Time. When enabled, several updates can be processed per frame (e.g.: if a frame is 10ms and the fixed frame rate is set to 5 ms, the effect will update twice with a 5ms deltaTime instead of once with a 10ms deltaTime). This method is expensive and should only be used for high-end scenarios.");
        var ignoreTimeScaleContent   = EditorGUIUtility.TrTextContent("Ignore Time Scale", "When enabled, the computed visual effect delta time ignores the game Time Scale value (Play Rate is still applied).");

        EditorGUI.BeginChangeCheck();

        VisualEffectEditor.ShowHeader(EditorGUIUtility.TrTextContent("Update mode"), false, false);
        bool newFixedDeltaTime     = EditorGUILayout.Toggle(deltaTimeContent, initialFixedDeltaTime ?? false);
        bool newExactFixedTimeStep = false;

        EditorGUI.showMixedValue = !initialProcessEveryFrame.HasValue;
        EditorGUI.BeginDisabledGroup((!initialFixedDeltaTime.HasValue || !initialFixedDeltaTime.Value) && !resourceUpdateModeProperty.hasMultipleDifferentValues);

#if CASE_1289829_HAS_BEEN_FIXED
        newExactFixedTimeStep = EditorGUILayout.Toggle(processEveryFrameContent, initialProcessEveryFrame ?? false);
#endif

        EditorGUI.EndDisabledGroup();
        EditorGUI.showMixedValue = !initialIgnoreGameTimeScale.HasValue;
        bool newIgnoreTimeScale = EditorGUILayout.Toggle(ignoreTimeScaleContent, initialIgnoreGameTimeScale ?? false);

        if (EditorGUI.EndChangeCheck())
        {
            if (!resourceUpdateModeProperty.hasMultipleDifferentValues)
            {
                var newUpdateMode = (VFXUpdateMode)0;
                if (!newFixedDeltaTime)
                {
                    newUpdateMode = newUpdateMode | VFXUpdateMode.DeltaTime;
                }
                if (newExactFixedTimeStep)
                {
                    newUpdateMode = newUpdateMode | VFXUpdateMode.ExactFixedTimeStep;
                }
                if (newIgnoreTimeScale)
                {
                    newUpdateMode = newUpdateMode | VFXUpdateMode.IgnoreTimeScale;
                }

                resourceUpdateModeProperty.intValue = (int)newUpdateMode;
                resourceObject.ApplyModifiedProperties();
            }
            else
            {
                var resourceUpdateModeProperties = resourceUpdateModeProperty.serializedObject.targetObjects.Select(o => new SerializedObject(o).FindProperty(resourceUpdateModeProperty.propertyPath));
                foreach (var property in resourceUpdateModeProperties)
                {
                    var updateMode = (VFXUpdateMode)property.intValue;

                    if (initialFixedDeltaTime.HasValue)
                    {
                        if (!newFixedDeltaTime)
                        {
                            updateMode = updateMode | VFXUpdateMode.DeltaTime;
                        }
                        else
                        {
                            updateMode = updateMode & ~VFXUpdateMode.DeltaTime;
                        }
                    }
                    else
                    {
                        if (newFixedDeltaTime)
                        {
                            updateMode = updateMode & ~VFXUpdateMode.DeltaTime;
                        }
                    }

                    if (newExactFixedTimeStep)
                    {
                        updateMode = updateMode | VFXUpdateMode.ExactFixedTimeStep;
                    }
                    else if (initialProcessEveryFrame.HasValue)
                    {
                        updateMode = updateMode & ~VFXUpdateMode.ExactFixedTimeStep;
                    }

                    if (newIgnoreTimeScale)
                    {
                        updateMode = updateMode | VFXUpdateMode.IgnoreTimeScale;
                    }
                    else if (initialIgnoreGameTimeScale.HasValue)
                    {
                        updateMode = updateMode & ~VFXUpdateMode.IgnoreTimeScale;
                    }

                    property.intValue = (int)updateMode;
                    property.serializedObject.ApplyModifiedProperties();
                }
            }
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUI.showMixedValue = cullingFlagsProperty.hasMultipleDifferentValues;
        EditorGUILayout.PrefixLabel(EditorGUIUtility.TrTextContent("Culling Flags", "Specifies how the system recomputes its bounds and simulates when off-screen."));
        EditorGUI.BeginChangeCheck();
        int newOption = EditorGUILayout.Popup(Array.IndexOf(k_CullingOptionsValue, (VFXCullingFlags)cullingFlagsProperty.intValue), k_CullingOptionsContents);
        if (EditorGUI.EndChangeCheck())
        {
            cullingFlagsProperty.intValue = (int)k_CullingOptionsValue[newOption];
            resourceObject.ApplyModifiedProperties();
        }
        EditorGUILayout.EndHorizontal();

        VisualEffectEditor.ShowHeader(EditorGUIUtility.TrTextContent("Initial state"), false, false);
        if (prewarmDeltaTime != null && prewarmStepCount != null)
        {
            if (!prewarmDeltaTime.hasMultipleDifferentValues && !prewarmStepCount.hasMultipleDifferentValues)
            {
                var currentDeltaTime = prewarmDeltaTime.floatValue;
                var currentStepCount = prewarmStepCount.intValue;
                var currentTotalTime = currentDeltaTime * currentStepCount;
                EditorGUI.BeginChangeCheck();
                currentTotalTime = EditorGUILayout.FloatField(EditorGUIUtility.TrTextContent("PreWarm Total Time", "Sets the time in seconds to advance the current effect to when it is initially played. "), currentTotalTime);
                if (EditorGUI.EndChangeCheck())
                {
                    if (currentStepCount <= 0)
                    {
                        prewarmStepCount.intValue = currentStepCount = 1;
                    }

                    currentDeltaTime            = currentTotalTime / currentStepCount;
                    prewarmDeltaTime.floatValue = currentDeltaTime;
                    resourceObject.ApplyModifiedProperties();
                }

                EditorGUI.BeginChangeCheck();
                currentStepCount = EditorGUILayout.IntField(EditorGUIUtility.TrTextContent("PreWarm Step Count", "Sets the number of simulation steps the prewarm should be broken down to. "), currentStepCount);
                if (EditorGUI.EndChangeCheck())
                {
                    if (currentStepCount <= 0 && currentTotalTime != 0.0f)
                    {
                        prewarmStepCount.intValue = currentStepCount = 1;
                    }

                    currentDeltaTime            = currentTotalTime == 0.0f ? 0.0f : currentTotalTime / currentStepCount;
                    prewarmDeltaTime.floatValue = currentDeltaTime;
                    prewarmStepCount.intValue   = currentStepCount;
                    resourceObject.ApplyModifiedProperties();
                }

                EditorGUI.BeginChangeCheck();
                currentDeltaTime = EditorGUILayout.FloatField(EditorGUIUtility.TrTextContent("PreWarm Delta Time", "Sets the time in seconds for each step to achieve the desired total prewarm time."), currentDeltaTime);
                if (EditorGUI.EndChangeCheck())
                {
                    if (currentDeltaTime < k_MinimalCommonDeltaTime)
                    {
                        prewarmDeltaTime.floatValue = currentDeltaTime = k_MinimalCommonDeltaTime;
                    }

                    if (currentDeltaTime > currentTotalTime)
                    {
                        currentTotalTime = currentDeltaTime;
                    }

                    if (currentTotalTime != 0.0f)
                    {
                        var candidateStepCount_A = Mathf.FloorToInt(currentTotalTime / currentDeltaTime);
                        var candidateStepCount_B = Mathf.RoundToInt(currentTotalTime / currentDeltaTime);

                        var totalTime_A = currentDeltaTime * candidateStepCount_A;
                        var totalTime_B = currentDeltaTime * candidateStepCount_B;

                        if (Mathf.Abs(totalTime_A - currentTotalTime) < Mathf.Abs(totalTime_B - currentTotalTime))
                        {
                            currentStepCount = candidateStepCount_A;
                        }
                        else
                        {
                            currentStepCount = candidateStepCount_B;
                        }

                        prewarmStepCount.intValue = currentStepCount;
                    }
                    prewarmDeltaTime.floatValue = currentDeltaTime;
                    resourceObject.ApplyModifiedProperties();
                }
            }
            else
            {
                //Multi selection case, can't resolve total time easily
                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prewarmStepCount.hasMultipleDifferentValues;
                EditorGUILayout.PropertyField(prewarmStepCount, EditorGUIUtility.TrTextContent("PreWarm Step Count", "Sets the number of simulation steps the prewarm should be broken down to."));
                EditorGUI.showMixedValue = prewarmDeltaTime.hasMultipleDifferentValues;
                EditorGUILayout.PropertyField(prewarmDeltaTime, EditorGUIUtility.TrTextContent("PreWarm Delta Time", "Sets the time in seconds for each step to achieve the desired total prewarm time."));
                if (EditorGUI.EndChangeCheck())
                {
                    if (prewarmDeltaTime.floatValue < k_MinimalCommonDeltaTime)
                    {
                        prewarmDeltaTime.floatValue = k_MinimalCommonDeltaTime;
                    }
                    resourceObject.ApplyModifiedProperties();
                }
            }
        }

        if (initialEventName != null)
        {
            EditorGUI.BeginChangeCheck();
            EditorGUI.showMixedValue = initialEventName.hasMultipleDifferentValues;
            EditorGUILayout.PropertyField(initialEventName, new GUIContent("Initial Event Name", "Sets the name of the event which triggers once the system is activated. Default: ‘OnPlay’."));
            if (EditorGUI.EndChangeCheck())
            {
                resourceObject.ApplyModifiedProperties();
            }
        }

        if (!serializedObject.isEditingMultipleObjects)
        {
            VisualEffectAsset    asset    = (VisualEffectAsset)target;
            VisualEffectResource resource = asset.GetResource();

            m_OutputContexts.Clear();
            m_OutputContexts.AddRange(resource.GetOrCreateGraph().children.OfType <IVFXSubRenderer>().OrderBy(t => t.sortPriority));

            m_ReorderableList.DoLayoutList();

            VisualEffectEditor.ShowHeader(EditorGUIUtility.TrTextContent("Shaders"), false, false);

            string        assetPath = AssetDatabase.GetAssetPath(asset);
            UnityObject[] objects   = AssetDatabase.LoadAllAssetsAtPath(assetPath);
            string        directory = Path.GetDirectoryName(assetPath) + "/" + VFXExternalShaderProcessor.k_ShaderDirectory + "/" + asset.name + "/";

            foreach (var obj in objects)
            {
                if (obj is Material || obj is ComputeShader)
                {
                    GUILayout.BeginHorizontal();
                    Rect r = GUILayoutUtility.GetRect(0, 18, GUILayout.ExpandWidth(true));

                    int buttonsWidth = VFXExternalShaderProcessor.allowExternalization ? 240 : 160;

                    int index = resource.GetShaderIndex(obj);

                    var shader = obj;
                    if (obj is Material) // Retrieve the shader from the material
                    {
                        shader = ((Material)(obj)).shader;
                    }
                    if (shader == null)
                    {
                        continue;
                    }

                    Rect labelR = r;
                    labelR.width -= buttonsWidth;
                    GUI.Label(labelR, shader.name);

                    if (index >= 0)
                    {
                        if (VFXExternalShaderProcessor.allowExternalization && index < resource.GetShaderSourceCount())
                        {
                            string shaderSourceName = resource.GetShaderSourceName(index);
                            string externalPath     = directory + shaderSourceName;

                            externalPath = directory + shaderSourceName.Replace('/', '_') + VFXExternalShaderProcessor.k_ShaderExt;

                            Rect buttonRect = r;
                            buttonRect.xMin  = labelR.xMax;
                            buttonRect.width = 80;
                            labelR.width    += 80;
                            if (System.IO.File.Exists(externalPath))
                            {
                                if (GUI.Button(buttonRect, "Reveal External"))
                                {
                                    EditorUtility.RevealInFinder(externalPath);
                                }
                            }
                            else
                            {
                                if (GUI.Button(buttonRect, "Externalize"))
                                {
                                    Directory.CreateDirectory(directory);

                                    File.WriteAllText(externalPath, "//" + shaderSourceName + "," + index.ToString() + "\n//Don't delete the previous line or this one\n" + resource.GetShaderSource(index));
                                }
                            }
                        }

                        Rect buttonR = r;
                        buttonR.xMin  = labelR.xMax;
                        buttonR.width = 110;
                        labelR.width += 110;
                        if (GUI.Button(buttonR, "Show Generated"))
                        {
                            resource.ShowGeneratedShaderFile(index);
                        }
                    }

                    Rect selectButtonR = r;
                    selectButtonR.xMin  = labelR.xMax;
                    selectButtonR.width = 50;
                    if (GUI.Button(selectButtonR, "Select"))
                    {
                        Selection.activeObject = shader;
                    }
                    GUILayout.EndHorizontal();
                }
            }
        }
        GUI.enabled = false;
    }
Beispiel #27
0
    public override void OnInspectorGUI()
    {
        resourceObject.Update();


        bool enable = GUI.enabled; //Everything in external asset is disabled by default

        GUI.enabled = true;

        EditorGUI.BeginChangeCheck();
        EditorGUI.showMixedValue = resourceUpdateModeProperty.hasMultipleDifferentValues;
        VFXUpdateMode newUpdateMode = (VFXUpdateMode)EditorGUILayout.EnumPopup(EditorGUIUtility.TrTextContent("Update Mode"), (VFXUpdateMode)resourceUpdateModeProperty.intValue);

        if (EditorGUI.EndChangeCheck())
        {
            resourceUpdateModeProperty.intValue = (int)newUpdateMode;
            resourceObject.ApplyModifiedProperties();
        }

        EditorGUILayout.BeginHorizontal();
        EditorGUI.showMixedValue = cullingFlagsProperty.hasMultipleDifferentValues;
        EditorGUILayout.PrefixLabel(EditorGUIUtility.TrTextContent("Culling Flags"));
        EditorGUI.BeginChangeCheck();
        int newOption = EditorGUILayout.Popup(Array.IndexOf(k_CullingOptionsValue, (VFXCullingFlags)cullingFlagsProperty.intValue), k_CullingOptionsContents);

        if (EditorGUI.EndChangeCheck())
        {
            cullingFlagsProperty.intValue = (int)k_CullingOptionsValue[newOption];
            resourceObject.ApplyModifiedProperties();
        }
        EditorGUILayout.EndHorizontal();

        bool needRecompile = false;

        EditorGUI.BeginChangeCheck();


        EditorGUI.showMixedValue = motionVectorRenderModeProperty.hasMultipleDifferentValues;
        EditorGUI.BeginChangeCheck();
        bool motionVector = EditorGUILayout.Toggle(EditorGUIUtility.TrTextContent("Use Motion Vectors"), motionVectorRenderModeProperty.intValue == (int)MotionVectorGenerationMode.Object);

        if (EditorGUI.EndChangeCheck())
        {
            motionVectorRenderModeProperty.intValue = motionVector ? (int)MotionVectorGenerationMode.Object : (int)MotionVectorGenerationMode.Camera;
            resourceObject.ApplyModifiedProperties();
            needRecompile = true;
        }

        if (needRecompile)
        {
            foreach (VisualEffectResource resource in resourceObject.targetObjects)
            {
                VFXGraph graph = resource.GetOrCreateGraph() as VFXGraph;
                if (graph != null)
                {
                    graph.SetExpressionGraphDirty();
                    graph.RecompileIfNeeded();
                }
            }
        }

        if (!serializedObject.isEditingMultipleObjects)
        {
            VisualEffectEditor.ShowHeader(EditorGUIUtility.TrTextContent("Shaders"), true, true, false, false);
            VisualEffectAsset    asset    = (VisualEffectAsset)target;
            VisualEffectResource resource = asset.GetResource();

            var shaderSources = resource.shaderSources;


            string        assetPath = AssetDatabase.GetAssetPath(asset);
            UnityObject[] objects   = AssetDatabase.LoadAllAssetsAtPath(assetPath);
            string        directory = Path.GetDirectoryName(assetPath) + "/" + VFXExternalShaderProcessor.k_ShaderDirectory + "/" + asset.name + "/";

            foreach (var shader in objects)
            {
                if (shader is Shader || shader is ComputeShader)
                {
                    GUILayout.BeginHorizontal();
                    GUILayout.Label(shader.name, GUILayout.ExpandWidth(true));
                    int index = resource.GetShaderIndex(shader);
                    if (index >= 0 && index < shaderSources.Length)
                    {
                        if (VFXExternalShaderProcessor.allowExternalization)
                        {
                            string externalPath = directory + shaderSources[index].name;
                            if (!shaderSources[index].compute)
                            {
                                externalPath = directory + shaderSources[index].name.Replace('/', '_') + VFXExternalShaderProcessor.k_ShaderExt;
                            }
                            else
                            {
                                externalPath = directory + shaderSources[index].name + VFXExternalShaderProcessor.k_ShaderExt;
                            }

                            if (System.IO.File.Exists(externalPath))
                            {
                                if (GUILayout.Button("Reveal External"))
                                {
                                    EditorUtility.RevealInFinder(externalPath);
                                }
                            }
                            else
                            {
                                if (GUILayout.Button("Externalize", GUILayout.Width(80)))
                                {
                                    Directory.CreateDirectory(directory);

                                    File.WriteAllText(externalPath, "//" + shaderSources[index].name + "," + index.ToString() + "\n//Don't delete the previous line or this one\n" + shaderSources[index].source);
                                }
                            }
                        }

                        if (GUILayout.Button("Show Generated", GUILayout.Width(110)))
                        {
                            resource.ShowGeneratedShaderFile(index);
                        }
                    }
                    if (GUILayout.Button("Select", GUILayout.Width(50)))
                    {
                        Selection.activeObject = shader;
                    }
                    GUILayout.EndHorizontal();
                }
            }
        }
        GUI.enabled = false;
    }