diff --git a/TestProjects/ShaderGraph/Assets/CommonAssets/Editor/PropertyTests.cs b/TestProjects/ShaderGraph/Assets/CommonAssets/Editor/PropertyTests.cs new file mode 100644 index 00000000000..a8b40d2851d --- /dev/null +++ b/TestProjects/ShaderGraph/Assets/CommonAssets/Editor/PropertyTests.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using UnityEngine; +using UnityEditor.Graphing; +using UnityEditor.ShaderGraph.Internal; + +namespace UnityEditor.ShaderGraph.UnitTests +{ + [TestFixture] + internal class PropertyTests + { + static string kGraphName = "Assets/CommonAssets/Graphs/Properties.shadergraph"; + GraphData m_Graph; + + PropertyCollector m_Collector; + + Dictionary m_TestNodes = new Dictionary(); + + [OneTimeSetUp] + public void LoadGraph() + { + List lti; + var lsadp = new List(); + ShaderGraphImporter.GetShaderText(kGraphName, out lti, lsadp, out m_Graph); + Assert.NotNull(m_Graph, $"Invalid graph data found for {kGraphName}"); + + m_Graph.ValidateGraph(); + + m_Collector = new PropertyCollector(); + m_Graph.CollectShaderProperties(m_Collector, GenerationMode.ForReals); + } + + [Test] + public void SliderPropertyRangeMinLesserThanMax() + { + foreach(AbstractShaderProperty property in m_Collector.properties) + { + if (property is Vector1ShaderProperty vector1ShaderProperty && vector1ShaderProperty.floatType == FloatType.Slider) + { + Assert.IsTrue(vector1ShaderProperty.rangeValues.x < vector1ShaderProperty.rangeValues.y, + "Slider property cannot have min be greater than max!"); + } + } + } + } +} diff --git a/TestProjects/ShaderGraph/Assets/CommonAssets/Editor/PropertyTests.cs.meta b/TestProjects/ShaderGraph/Assets/CommonAssets/Editor/PropertyTests.cs.meta new file mode 100644 index 00000000000..8da27cce8ff --- /dev/null +++ b/TestProjects/ShaderGraph/Assets/CommonAssets/Editor/PropertyTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dd32827558071524889ec9bc76e7126f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/TestProjects/ShaderGraph/Assets/CommonAssets/Graphs/Properties.shadergraph b/TestProjects/ShaderGraph/Assets/CommonAssets/Graphs/Properties.shadergraph new file mode 100644 index 00000000000..74062e5c375 --- /dev/null +++ b/TestProjects/ShaderGraph/Assets/CommonAssets/Graphs/Properties.shadergraph @@ -0,0 +1,59 @@ +{ + "m_SerializedProperties": [ + { + "typeInfo": { + "fullName": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty" + }, + "JSONnodeData": "{\n \"m_Guid\": {\n \"m_GuidSerialized\": \"d13f1c8f-912c-4202-88dd-1d81f762d260\"\n },\n \"m_Name\": \"FlippedSliderProperty\",\n \"m_DefaultReferenceName\": \"Vector1_829D8397\",\n \"m_OverrideReferenceName\": \"\",\n \"m_GeneratePropertyBlock\": true,\n \"m_Precision\": 0,\n \"m_GPUInstanced\": false,\n \"m_Hidden\": false,\n \"m_Value\": 1.0,\n \"m_FloatType\": 1,\n \"m_RangeValues\": {\n \"x\": 1.0,\n \"y\": -1.0\n }\n}" + } + ], + "m_SerializedKeywords": [], + "m_SerializableNodes": [ + { + "typeInfo": { + "fullName": "UnityEditor.ShaderGraph.PropertyNode" + }, + "JSONnodeData": "{\n \"m_GuidSerialized\": \"419f7fde-45d3-413d-a681-3f80de32bc31\",\n \"m_GroupGuidSerialized\": \"a0c9f82f-8f00-4690-8ef3-bf4079519d15\",\n \"m_Name\": \"Property\",\n \"m_NodeVersion\": 0,\n \"m_DrawState\": {\n \"m_Expanded\": true,\n \"m_Position\": {\n \"serializedVersion\": \"2\",\n \"x\": -551.0000610351563,\n \"y\": 283.0,\n \"width\": 190.00001525878907,\n \"height\": 34.0\n }\n },\n \"m_SerializableSlots\": [\n {\n \"typeInfo\": {\n \"fullName\": \"UnityEditor.ShaderGraph.Vector1MaterialSlot\"\n },\n \"JSONnodeData\": \"{\\n \\\"m_Id\\\": 0,\\n \\\"m_DisplayName\\\": \\\"FlippedSliderProperty\\\",\\n \\\"m_SlotType\\\": 1,\\n \\\"m_Priority\\\": 2147483647,\\n \\\"m_Hidden\\\": false,\\n \\\"m_ShaderOutputName\\\": \\\"Out\\\",\\n \\\"m_StageCapability\\\": 3,\\n \\\"m_Value\\\": 0.0,\\n \\\"m_DefaultValue\\\": 0.0,\\n \\\"m_Labels\\\": [\\n \\\"X\\\"\\n ]\\n}\"\n }\n ],\n \"m_Precision\": 0,\n \"m_PreviewExpanded\": true,\n \"m_CustomColors\": {\n \"m_SerializableColors\": []\n },\n \"m_PropertyGuidSerialized\": \"d13f1c8f-912c-4202-88dd-1d81f762d260\"\n}" + }, + { + "typeInfo": { + "fullName": "UnityEditor.ShaderGraph.PreviewNode" + }, + "JSONnodeData": "{\n \"m_GuidSerialized\": \"47df49fd-91a7-4c8a-8404-c3710b050632\",\n \"m_GroupGuidSerialized\": \"a0c9f82f-8f00-4690-8ef3-bf4079519d15\",\n \"m_Name\": \"Preview\",\n \"m_NodeVersion\": 0,\n \"m_DrawState\": {\n \"m_Expanded\": true,\n \"m_Position\": {\n \"serializedVersion\": \"2\",\n \"x\": -301.00006103515627,\n \"y\": 242.0,\n \"width\": 208.0,\n \"height\": 278.0\n }\n },\n \"m_SerializableSlots\": [\n {\n \"typeInfo\": {\n \"fullName\": \"UnityEditor.ShaderGraph.DynamicVectorMaterialSlot\"\n },\n \"JSONnodeData\": \"{\\n \\\"m_Id\\\": 0,\\n \\\"m_DisplayName\\\": \\\"In\\\",\\n \\\"m_SlotType\\\": 0,\\n \\\"m_Priority\\\": 2147483647,\\n \\\"m_Hidden\\\": false,\\n \\\"m_ShaderOutputName\\\": \\\"In\\\",\\n \\\"m_StageCapability\\\": 3,\\n \\\"m_Value\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0,\\n \\\"w\\\": 0.0\\n },\\n \\\"m_DefaultValue\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0,\\n \\\"w\\\": 0.0\\n }\\n}\"\n },\n {\n \"typeInfo\": {\n \"fullName\": \"UnityEditor.ShaderGraph.DynamicVectorMaterialSlot\"\n },\n \"JSONnodeData\": \"{\\n \\\"m_Id\\\": 1,\\n \\\"m_DisplayName\\\": \\\"Out\\\",\\n \\\"m_SlotType\\\": 1,\\n \\\"m_Priority\\\": 2147483647,\\n \\\"m_Hidden\\\": false,\\n \\\"m_ShaderOutputName\\\": \\\"Out\\\",\\n \\\"m_StageCapability\\\": 3,\\n \\\"m_Value\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0,\\n \\\"w\\\": 0.0\\n },\\n \\\"m_DefaultValue\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0,\\n \\\"w\\\": 0.0\\n }\\n}\"\n }\n ],\n \"m_Precision\": 0,\n \"m_PreviewExpanded\": true,\n \"m_CustomColors\": {\n \"m_SerializableColors\": []\n },\n \"m_Width\": 208.0,\n \"m_Height\": 208.0\n}" + }, + { + "typeInfo": { + "fullName": "UnityEditor.ShaderGraph.UnlitMasterNode" + }, + "JSONnodeData": "{\n \"m_GuidSerialized\": \"faac5ed4-8a55-4c7e-a36f-e4380ae3593a\",\n \"m_GroupGuidSerialized\": \"00000000-0000-0000-0000-000000000000\",\n \"m_Name\": \"Unlit Master\",\n \"m_NodeVersion\": 0,\n \"m_DrawState\": {\n \"m_Expanded\": true,\n \"m_Position\": {\n \"serializedVersion\": \"2\",\n \"x\": 287.0,\n \"y\": 168.99998474121095,\n \"width\": 200.00001525878907,\n \"height\": 197.00001525878907\n }\n },\n \"m_SerializableSlots\": [\n {\n \"typeInfo\": {\n \"fullName\": \"UnityEditor.ShaderGraph.PositionMaterialSlot\"\n },\n \"JSONnodeData\": \"{\\n \\\"m_Id\\\": 9,\\n \\\"m_DisplayName\\\": \\\"Vertex Position\\\",\\n \\\"m_SlotType\\\": 0,\\n \\\"m_Priority\\\": 2147483647,\\n \\\"m_Hidden\\\": false,\\n \\\"m_ShaderOutputName\\\": \\\"Vertex Position\\\",\\n \\\"m_StageCapability\\\": 1,\\n \\\"m_Value\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0\\n },\\n \\\"m_DefaultValue\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0\\n },\\n \\\"m_Labels\\\": [\\n \\\"X\\\",\\n \\\"Y\\\",\\n \\\"Z\\\"\\n ],\\n \\\"m_Space\\\": 0\\n}\"\n },\n {\n \"typeInfo\": {\n \"fullName\": \"UnityEditor.ShaderGraph.NormalMaterialSlot\"\n },\n \"JSONnodeData\": \"{\\n \\\"m_Id\\\": 10,\\n \\\"m_DisplayName\\\": \\\"Vertex Normal\\\",\\n \\\"m_SlotType\\\": 0,\\n \\\"m_Priority\\\": 2147483647,\\n \\\"m_Hidden\\\": false,\\n \\\"m_ShaderOutputName\\\": \\\"Vertex Normal\\\",\\n \\\"m_StageCapability\\\": 1,\\n \\\"m_Value\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0\\n },\\n \\\"m_DefaultValue\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0\\n },\\n \\\"m_Labels\\\": [\\n \\\"X\\\",\\n \\\"Y\\\",\\n \\\"Z\\\"\\n ],\\n \\\"m_Space\\\": 0\\n}\"\n },\n {\n \"typeInfo\": {\n \"fullName\": \"UnityEditor.ShaderGraph.TangentMaterialSlot\"\n },\n \"JSONnodeData\": \"{\\n \\\"m_Id\\\": 11,\\n \\\"m_DisplayName\\\": \\\"Vertex Tangent\\\",\\n \\\"m_SlotType\\\": 0,\\n \\\"m_Priority\\\": 2147483647,\\n \\\"m_Hidden\\\": false,\\n \\\"m_ShaderOutputName\\\": \\\"Vertex Tangent\\\",\\n \\\"m_StageCapability\\\": 1,\\n \\\"m_Value\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0\\n },\\n \\\"m_DefaultValue\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0\\n },\\n \\\"m_Labels\\\": [\\n \\\"X\\\",\\n \\\"Y\\\",\\n \\\"Z\\\"\\n ],\\n \\\"m_Space\\\": 0\\n}\"\n },\n {\n \"typeInfo\": {\n \"fullName\": \"UnityEditor.ShaderGraph.ColorRGBMaterialSlot\"\n },\n \"JSONnodeData\": \"{\\n \\\"m_Id\\\": 0,\\n \\\"m_DisplayName\\\": \\\"Color\\\",\\n \\\"m_SlotType\\\": 0,\\n \\\"m_Priority\\\": 2147483647,\\n \\\"m_Hidden\\\": false,\\n \\\"m_ShaderOutputName\\\": \\\"Color\\\",\\n \\\"m_StageCapability\\\": 2,\\n \\\"m_Value\\\": {\\n \\\"x\\\": 0.7353569269180298,\\n \\\"y\\\": 0.7353569269180298,\\n \\\"z\\\": 0.7353569269180298\\n },\\n \\\"m_DefaultValue\\\": {\\n \\\"x\\\": 0.0,\\n \\\"y\\\": 0.0,\\n \\\"z\\\": 0.0\\n },\\n \\\"m_Labels\\\": [\\n \\\"X\\\",\\n \\\"Y\\\",\\n \\\"Z\\\"\\n ],\\n \\\"m_ColorMode\\\": 0\\n}\"\n },\n {\n \"typeInfo\": {\n \"fullName\": \"UnityEditor.ShaderGraph.Vector1MaterialSlot\"\n },\n \"JSONnodeData\": \"{\\n \\\"m_Id\\\": 7,\\n \\\"m_DisplayName\\\": \\\"Alpha\\\",\\n \\\"m_SlotType\\\": 0,\\n \\\"m_Priority\\\": 2147483647,\\n \\\"m_Hidden\\\": false,\\n \\\"m_ShaderOutputName\\\": \\\"Alpha\\\",\\n \\\"m_StageCapability\\\": 2,\\n \\\"m_Value\\\": 1.0,\\n \\\"m_DefaultValue\\\": 1.0,\\n \\\"m_Labels\\\": [\\n \\\"X\\\"\\n ]\\n}\"\n },\n {\n \"typeInfo\": {\n \"fullName\": \"UnityEditor.ShaderGraph.Vector1MaterialSlot\"\n },\n \"JSONnodeData\": \"{\\n \\\"m_Id\\\": 8,\\n \\\"m_DisplayName\\\": \\\"AlphaClipThreshold\\\",\\n \\\"m_SlotType\\\": 0,\\n \\\"m_Priority\\\": 2147483647,\\n \\\"m_Hidden\\\": false,\\n \\\"m_ShaderOutputName\\\": \\\"AlphaClipThreshold\\\",\\n \\\"m_StageCapability\\\": 2,\\n \\\"m_Value\\\": 0.5,\\n \\\"m_DefaultValue\\\": 0.0,\\n \\\"m_Labels\\\": [\\n \\\"X\\\"\\n ]\\n}\"\n }\n ],\n \"m_Precision\": 0,\n \"m_PreviewExpanded\": true,\n \"m_CustomColors\": {\n \"m_SerializableColors\": []\n },\n \"m_SurfaceType\": 0,\n \"m_AlphaMode\": 0,\n \"m_TwoSided\": false,\n \"m_AddPrecomputedVelocity\": false,\n \"m_DOTSInstancing\": false,\n \"m_ShaderGUIOverride\": \"\",\n \"m_OverrideEnabled\": false\n}" + } + ], + "m_Groups": [ + { + "m_GuidSerialized": "a0c9f82f-8f00-4690-8ef3-bf4079519d15", + "m_Title": "Min < Max", + "m_Position": { + "x": 10.0, + "y": 10.0 + } + } + ], + "m_StickyNotes": [], + "m_SerializableEdges": [ + { + "typeInfo": { + "fullName": "UnityEditor.Graphing.Edge" + }, + "JSONnodeData": "{\n \"m_OutputSlot\": {\n \"m_SlotId\": 0,\n \"m_NodeGUIDSerialized\": \"419f7fde-45d3-413d-a681-3f80de32bc31\"\n },\n \"m_InputSlot\": {\n \"m_SlotId\": 0,\n \"m_NodeGUIDSerialized\": \"47df49fd-91a7-4c8a-8404-c3710b050632\"\n }\n}" + } + ], + "m_PreviewData": { + "serializedMesh": { + "m_SerializedMesh": "{\"mesh\":{\"instanceID\":0}}", + "m_Guid": "" + } + }, + "m_Path": "Shader Graphs", + "m_ConcretePrecision": 0, + "m_ActiveOutputNodeGuidSerialized": "faac5ed4-8a55-4c7e-a36f-e4380ae3593a" +} diff --git a/TestProjects/ShaderGraph/Assets/CommonAssets/Graphs/Properties.shadergraph.meta b/TestProjects/ShaderGraph/Assets/CommonAssets/Graphs/Properties.shadergraph.meta new file mode 100644 index 00000000000..72cd3640713 --- /dev/null +++ b/TestProjects/ShaderGraph/Assets/CommonAssets/Graphs/Properties.shadergraph.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: cd023eec8aa14e840b0b5101bfdb2eb9 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3} diff --git a/com.unity.render-pipelines.core/Editor/Drawing.meta b/com.unity.render-pipelines.core/Editor/Drawing.meta new file mode 100644 index 00000000000..cf7a35a15f0 --- /dev/null +++ b/com.unity.render-pipelines.core/Editor/Drawing.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 079a8e4faab04ff2929b3d925675cc2d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.shadergraph/CHANGELOG.md b/com.unity.shadergraph/CHANGELOG.md index b6cb722260e..63a3d920bd4 100644 --- a/com.unity.shadergraph/CHANGELOG.md +++ b/com.unity.shadergraph/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added +- Added the Internal Inspector which allows the user to view data contained in selected nodes and properties in a new floating graph sub-window. Also added support for custom property drawers to let you visualize any data type you like and expose it to the inspector. - Added samples for Procedural Patterns to the package. - You can now use the right-click context menu to delete Sticky Notes. - You can now save your graph as a new Asset. diff --git a/com.unity.shadergraph/Editor/Data/Attributes/InspectableAttribute.cs b/com.unity.shadergraph/Editor/Data/Attributes/InspectableAttribute.cs new file mode 100644 index 00000000000..f70d75ebce3 --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Attributes/InspectableAttribute.cs @@ -0,0 +1,24 @@ +using System; + +namespace UnityEditor.ShaderGraph.Drawing +{ + [AttributeUsage(AttributeTargets.Property)] + public class InspectableAttribute : Attribute + { + // String value to use in the Property name TextLabel + public string labelName { get; private set; } + + // The default value of this property + public object defaultValue { get; private set; } + + // String value to supply if you wish to use a custom style when drawing this property + public string customStyleName { get; private set; } + + public InspectableAttribute(string labelName, object defaultValue, string customStyleName = "") + { + this.labelName = labelName; + this.defaultValue = defaultValue; + this.customStyleName = customStyleName; + } + } +} diff --git a/com.unity.shadergraph/Editor/Data/Attributes/InspectableAttribute.cs.meta b/com.unity.shadergraph/Editor/Data/Attributes/InspectableAttribute.cs.meta new file mode 100644 index 00000000000..a457de446b8 --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Attributes/InspectableAttribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 135160e3cb114b679f9d5363c349b289 +timeCreated: 1587157677 \ No newline at end of file diff --git a/com.unity.shadergraph/Editor/Data/Attributes/SGPropertyDrawerAttribute.cs b/com.unity.shadergraph/Editor/Data/Attributes/SGPropertyDrawerAttribute.cs new file mode 100644 index 00000000000..3b94e243260 --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Attributes/SGPropertyDrawerAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace UnityEditor.ShaderGraph.Drawing +{ + [AttributeUsage(AttributeTargets.Class)] + public class SGPropertyDrawerAttribute : Attribute + { + public Type propertyType { get; private set; } + + public SGPropertyDrawerAttribute(Type propertyType) + { + this.propertyType = propertyType; + } + } +} diff --git a/com.unity.shadergraph/Editor/Data/Attributes/SGPropertyDrawerAttribute.cs.meta b/com.unity.shadergraph/Editor/Data/Attributes/SGPropertyDrawerAttribute.cs.meta new file mode 100644 index 00000000000..a727e1c21bf --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Attributes/SGPropertyDrawerAttribute.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 291f21a1598748ba8fe53ab69eb10b5e +timeCreated: 1588090538 \ No newline at end of file diff --git a/com.unity.shadergraph/Editor/Data/Interfaces/ICanChangeShaderGUI.cs b/com.unity.shadergraph/Editor/Data/Interfaces/ICanChangeShaderGUI.cs index 0fc0f3ad9f2..1ef62e59ea6 100644 --- a/com.unity.shadergraph/Editor/Data/Interfaces/ICanChangeShaderGUI.cs +++ b/com.unity.shadergraph/Editor/Data/Interfaces/ICanChangeShaderGUI.cs @@ -1,5 +1,3 @@ -using UnityEngine.UIElements; - namespace UnityEditor.Graphing { interface ICanChangeShaderGUI diff --git a/com.unity.shadergraph/Editor/Data/Interfaces/IInspectable.cs b/com.unity.shadergraph/Editor/Data/Interfaces/IInspectable.cs new file mode 100644 index 00000000000..950b179fd1a --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Interfaces/IInspectable.cs @@ -0,0 +1,25 @@ +using System; +using System.Reflection; +using Data.Interfaces; +using Drawing.Inspector; +using UnityEngine.UIElements; + +namespace UnityEditor.ShaderGraph.Drawing +{ + interface IInspectable + { + // Implementors can override this in order to display their desired string when selected and viewed through the inscetor + string inspectorTitle { get; } + + // This function should return the underlying data object that user wishes to expose to the Inspector + object GetObjectToInspect(); + + // This function should return the property information of whatever object has been marked up for metadata gathering by the inspector + // This might be the same as the object returned by GetObjectToInspect(), it might not + PropertyInfo[] GetPropertyInfo(); + + // Used to provide any data needed by the property drawer from the inspectable + // The inspectorUpdateDelegate is used to trigger an inspector update + void SupplyDataToPropertyDrawer(IPropertyDrawer propertyDrawer, Action inspectorUpdateDelegate); + } +} diff --git a/com.unity.shadergraph/Editor/Data/Interfaces/IInspectable.cs.meta b/com.unity.shadergraph/Editor/Data/Interfaces/IInspectable.cs.meta new file mode 100644 index 00000000000..4d35ab2c784 --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Interfaces/IInspectable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 52cd086fd60734d89b34f49bd73e7510 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.shadergraph/Editor/Data/Interfaces/IPropertyDrawer.cs b/com.unity.shadergraph/Editor/Data/Interfaces/IPropertyDrawer.cs new file mode 100644 index 00000000000..401754526f1 --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Interfaces/IPropertyDrawer.cs @@ -0,0 +1,15 @@ +using System; +using System.Reflection; +using UnityEditor.ShaderGraph.Drawing; +using UnityEngine.UIElements; + +namespace Data.Interfaces +{ + // Interface that should be implemented by any property drawer for the inspector view + public interface IPropertyDrawer + { + Action inspectorUpdateDelegate { get; set; } + + VisualElement DrawProperty(PropertyInfo propertyInfo, object actualObject, InspectableAttribute attribute); + } +} diff --git a/com.unity.shadergraph/Editor/Data/Interfaces/IPropertyDrawer.cs.meta b/com.unity.shadergraph/Editor/Data/Interfaces/IPropertyDrawer.cs.meta new file mode 100644 index 00000000000..c488314d87e --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Interfaces/IPropertyDrawer.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e370946d202a43edaabc0940f13932cd +timeCreated: 1588090693 \ No newline at end of file diff --git a/com.unity.shadergraph/Editor/Data/Nodes/AbstractMaterialNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/AbstractMaterialNode.cs index e3e7c982b06..19fadf5ef2f 100644 --- a/com.unity.shadergraph/Editor/Data/Nodes/AbstractMaterialNode.cs +++ b/com.unity.shadergraph/Editor/Data/Nodes/AbstractMaterialNode.cs @@ -6,6 +6,7 @@ using UnityEditor.ShaderGraph.Drawing.Colors; using UnityEditor.ShaderGraph.Internal; using UnityEditor.Graphing.Util; +using UnityEditor.ShaderGraph.Drawing; namespace UnityEditor.ShaderGraph { @@ -104,6 +105,7 @@ public virtual bool canSetPrecision private ConcretePrecision m_ConcretePrecision = ConcretePrecision.Float; + [Inspectable("Precision", ConcretePrecision.Float)] public ConcretePrecision concretePrecision { get => m_ConcretePrecision; diff --git a/com.unity.shadergraph/Editor/Data/Nodes/Input/PropertyNode.cs b/com.unity.shadergraph/Editor/Data/Nodes/Input/PropertyNode.cs index 8712d974b12..e1f830ab345 100644 --- a/com.unity.shadergraph/Editor/Data/Nodes/Input/PropertyNode.cs +++ b/com.unity.shadergraph/Editor/Data/Nodes/Input/PropertyNode.cs @@ -15,17 +15,41 @@ public PropertyNode() name = "Property"; UpdateNodeAfterDeserialization(); } - + [SerializeField] string m_PropertyGuidSerialized; Guid m_PropertyGuid; + public override void UpdateNodeAfterDeserialization() + { + base.UpdateNodeAfterDeserialization(); + + if (owner == null) + return; + + // Get property from graphData + var property = owner.properties.FirstOrDefault(x => x.guid == propertyGuid); + if (property == null) + throw new NullReferenceException(); + + if (property is Vector1ShaderProperty vector1ShaderProperty && vector1ShaderProperty.floatType == FloatType.Slider) + { + // Previously, the Slider vector1 property allowed the min value to be greater than the max + // We no longer want to support that behavior so if such a property is encountered, swap the values + if (vector1ShaderProperty.rangeValues.x > vector1ShaderProperty.rangeValues.y) + { + vector1ShaderProperty.rangeValues = new Vector2(vector1ShaderProperty.rangeValues.y, vector1ShaderProperty.rangeValues.x); + Dirty(ModificationScope.Graph); + } + } + } + public Guid propertyGuid { get { return m_PropertyGuid; } set - { + { if (m_PropertyGuid == value) return; @@ -33,10 +57,10 @@ public Guid propertyGuid var property = owner.properties.FirstOrDefault(x => x.guid == value); if (property == null) return; - + AddOutputSlot(property); Dirty(ModificationScope.Topological); - } + } } public override bool canSetPrecision => false; @@ -48,7 +72,7 @@ public void OnEnable() AddOutputSlot(property); } - + public const int OutputSlotId = 0; void AddOutputSlot(AbstractShaderProperty property) @@ -121,7 +145,7 @@ public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMo var property = owner.properties.FirstOrDefault(x => x.guid == propertyGuid); if (property == null) return; - + switch(property.propertyType) { case PropertyType.Boolean: @@ -159,7 +183,7 @@ public void GenerateNodeCode(ShaderStringBuilder sb, GenerationMode generationMo sb.AppendLine($"Gradient {GetVariableNameForSlot(OutputSlotId)} = {GradientUtil.GetGradientForPreview(property.referenceName)};"); else sb.AppendLine($"Gradient {GetVariableNameForSlot(OutputSlotId)} = {property.referenceName};"); - break; + break; } } @@ -168,7 +192,7 @@ public override string GetVariableNameForSlot(int slotId) var property = owner.properties.FirstOrDefault(x => x.guid == propertyGuid); if (property == null) throw new NullReferenceException(); - + if (!(property is Texture2DShaderProperty) && !(property is Texture2DArrayShaderProperty) && !(property is Texture3DShaderProperty) && @@ -177,7 +201,7 @@ public override string GetVariableNameForSlot(int slotId) return property.referenceName; } - + protected override void CalculateNodeHasError() { if (!propertyGuid.Equals(Guid.Empty) && !owner.properties.Any(x => x.guid == propertyGuid)) @@ -202,13 +226,13 @@ public override void EvaluateConcretePrecision() concretePrecision = precision.ToConcrete(); else concretePrecision = owner.concretePrecision; - } - + } + public override void OnBeforeSerialize() - { + { base.OnBeforeSerialize(); m_PropertyGuidSerialized = m_PropertyGuid.ToString(); - } + } public override void OnAfterDeserialize() { diff --git a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldKeywordView.cs b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldKeywordView.cs deleted file mode 100644 index e2bb29e94c1..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldKeywordView.cs +++ /dev/null @@ -1,294 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using System.Globalization; -using UnityEditor.Graphing; -using UnityEditor.Graphing.Util; -using UnityEngine; -using UnityEditor.UIElements; -using UnityEngine.UIElements; -using Toggle = UnityEngine.UIElements.Toggle; -using UnityEditor.Experimental.GraphView; -using UnityEditorInternal; -using UnityEditor.ShaderGraph.Internal; - -namespace UnityEditor.ShaderGraph.Drawing -{ - class BlackboardFieldKeywordView : BlackboardFieldView - { - private ReorderableList m_ReorderableList; - private IMGUIContainer m_Container; - private int m_SelectedIndex; - private ShaderKeyword m_Keyword; - private static GUIStyle greyLabel; - - public BlackboardFieldKeywordView(BlackboardField blackboardField, GraphData graph, ShaderInput input) - : base (blackboardField, graph, input) - { - greyLabel = new GUIStyle(EditorStyles.label); - greyLabel.normal = new GUIStyleState { textColor = Color.grey }; - greyLabel.focused = new GUIStyleState { textColor = Color.grey }; - greyLabel.hover = new GUIStyleState { textColor = Color.grey }; - } - - public override void BuildCustomFields(ShaderInput input) - { - m_Keyword = input as ShaderKeyword; - if(m_Keyword == null) - return; - - // KeywordDefinition - var keywordDefinitionField = new EnumField((Enum)m_Keyword.keywordDefinition); - keywordDefinitionField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Keyword Type"); - if (m_Keyword.keywordDefinition == (KeywordDefinition)evt.newValue) - return; - m_Keyword.keywordDefinition = (KeywordDefinition)evt.newValue; - Rebuild(); - }); - AddRow("Definition", keywordDefinitionField, !m_Keyword.isBuiltIn); - - // KeywordScope - if(m_Keyword.keywordDefinition != KeywordDefinition.Predefined) - { - var keywordScopeField = new EnumField((Enum)m_Keyword.keywordScope); - keywordScopeField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Keyword Type"); - if (m_Keyword.keywordScope == (KeywordScope)evt.newValue) - return; - m_Keyword.keywordScope = (KeywordScope)evt.newValue; - }); - AddRow("Scope", keywordScopeField, !m_Keyword.isBuiltIn); - } - - switch(m_Keyword.keywordType) - { - case KeywordType.Boolean: - BuildBooleanKeywordField(m_Keyword); - break; - case KeywordType.Enum: - BuildEnumKeywordField(m_Keyword); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - - void BuildBooleanKeywordField(ShaderKeyword keyword) - { - // Default field - var field = new Toggle() { value = keyword.value == 1 }; - field.OnToggleChanged(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change property value"); - keyword.value = evt.newValue ? 1 : 0; - DirtyNodes(ModificationScope.Graph); - }); - AddRow("Default", field); - } - - void BuildEnumKeywordField(ShaderKeyword keyword) - { - // Clamp value between entry list - int value = Mathf.Clamp(keyword.value, 0, keyword.entries.Count - 1); - - // Default field - var field = new PopupField(keyword.entries.Select(x => x.displayName).ToList(), value); - field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Keyword Value"); - keyword.value = field.index; - DirtyNodes(ModificationScope.Graph); - }); - AddRow("Default", field); - - // Entries - m_Container = new IMGUIContainer(() => OnGUIHandler ()) { name = "ListContainer" }; - AddRow("Entries", m_Container, !keyword.isBuiltIn); - } - - public ShaderKeyword keyword => m_Keyword; - - private void OnGUIHandler() - { - if(m_ReorderableList == null) - { - RecreateList(); - AddCallbacks(); - } - - m_ReorderableList.index = m_SelectedIndex; - m_ReorderableList.DoLayoutList(); - } - - internal void RecreateList() - { - // Create reorderable list from entries - m_ReorderableList = new ReorderableList(m_Keyword.entries, typeof(KeywordEntry), true, true, true, true); - } - - private void AddCallbacks() - { - // Draw Header - m_ReorderableList.drawHeaderCallback = (Rect rect) => - { - int indent = 14; - var displayRect = new Rect(rect.x + indent, rect.y, (rect.width - indent) / 2, rect.height); - EditorGUI.LabelField(displayRect, "Entry Name"); - var referenceRect = new Rect((rect.x + indent) + (rect.width - indent) / 2, rect.y, (rect.width - indent) / 2, rect.height); - EditorGUI.LabelField(referenceRect, "Reference Suffix", m_Keyword.isBuiltIn ? EditorStyles.label : greyLabel); - }; - - // Draw Element - m_ReorderableList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => - { - KeywordEntry entry = ((KeywordEntry)m_ReorderableList.list[index]); - EditorGUI.BeginChangeCheck(); - - var displayName = EditorGUI.DelayedTextField( new Rect(rect.x, rect.y, rect.width / 2, EditorGUIUtility.singleLineHeight), entry.displayName, EditorStyles.label); - var referenceName = EditorGUI.TextField( new Rect(rect.x + rect.width / 2, rect.y, rect.width / 2, EditorGUIUtility.singleLineHeight), entry.referenceName, - m_Keyword.isBuiltIn ? EditorStyles.label : greyLabel); - - displayName = GetDuplicateSafeDisplayName(entry.id, displayName); - referenceName = GetDuplicateSafeReferenceName(entry.id, displayName.ToUpper()); - - if (EditorGUI.EndChangeCheck()) - { - m_Keyword.entries[index] = new KeywordEntry(entry.id, displayName, referenceName); - - DirtyNodes(); - Rebuild(); - } - }; - - // Element height - m_ReorderableList.elementHeightCallback = (int indexer) => - { - return m_ReorderableList.elementHeight; - }; - - // Can add - m_ReorderableList.onCanAddCallback = (ReorderableList list) => - { - return list.count < KeywordNode.k_MaxEnumEntries; - }; - - // Can remove - m_ReorderableList.onCanRemoveCallback = (ReorderableList list) => - { - return list.count > KeywordNode.k_MinEnumEntries; - }; - - // Add callback delegates - m_ReorderableList.onSelectCallback += SelectEntry; - m_ReorderableList.onAddCallback += AddEntry; - m_ReorderableList.onRemoveCallback += RemoveEntry; - m_ReorderableList.onReorderCallback += ReorderEntries; - } - - private void SelectEntry(ReorderableList list) - { - m_SelectedIndex = list.index; - } - - private void AddEntry(ReorderableList list) - { - graph.owner.RegisterCompleteObjectUndo("Add Keyword Entry"); - - int index = GetFirstUnusedID(); - if (index <= 0) - return; // Error has already occured, don't attempt to add this entry. - - var displayName = GetDuplicateSafeDisplayName(index, "New"); - var referenceName = GetDuplicateSafeReferenceName(index, "NEW"); - - // Add new entry - m_Keyword.entries.Add(new KeywordEntry(index, displayName, referenceName)); - - // Update Blackboard & Nodes - DirtyNodes(); - Rebuild(); - graph.OnKeywordChanged(); - m_SelectedIndex = list.list.Count - 1; - } - - // Allowed indicies are 1-MAX_ENUM_ENTRIES - private int GetFirstUnusedID() - { - List ususedIDs = new List(); - - foreach (KeywordEntry keywordEntry in m_Keyword.entries) - { - ususedIDs.Add(keywordEntry.id); - } - - for (int x = 1; x <= KeywordNode.k_MaxEnumEntries; x++) - { - if (!ususedIDs.Contains(x)) - return x; - } - - Debug.LogError("GetFirstUnusedID: Attempting to get unused ID when all IDs are used."); - return -1; - } - - private void RemoveEntry(ReorderableList list) - { - graph.owner.RegisterCompleteObjectUndo("Remove Keyword Entry"); - - // Remove entry - m_SelectedIndex = list.index; - var selectedEntry = (KeywordEntry)m_ReorderableList.list[list.index]; - m_Keyword.entries.Remove(selectedEntry); - - // Clamp value within new entry range - int value = Mathf.Clamp(m_Keyword.value, 0, m_Keyword.entries.Count - 1); - m_Keyword.value = value; - - // Update Blackboard & Nodes - DirtyNodes(); - Rebuild(); - graph.OnKeywordChanged(); - m_SelectedIndex = m_SelectedIndex >= list.list.Count - 1 ? list.list.Count - 1 : m_SelectedIndex; - } - - private void ReorderEntries(ReorderableList list) - { - DirtyNodes(); - } - - public string GetDuplicateSafeDisplayName(int id, string name) - { - name = name.Trim(); - name = Regex.Replace(name, @"(?:[^A-Za-z_0-9_\s])", "_"); - var entryList = m_ReorderableList.list as List; - return GraphUtil.SanitizeName(entryList.Where(p => p.id != id).Select(p => p.displayName), "{0} ({1})", name); - } - - public string GetDuplicateSafeReferenceName(int id, string name) - { - name = name.Trim(); - name = Regex.Replace(name, @"(?:[^A-Za-z_0-9])|(?:\s)", "_"); - var entryList = m_ReorderableList.list as List; - return GraphUtil.SanitizeName(entryList.Where(p => p.id != id).Select(p => p.referenceName), "{0}_{1}", name); - } - - public override void DirtyNodes(ModificationScope modificationScope = ModificationScope.Node) - { - foreach (var node in graph.GetNodes()) - { - node.UpdateNode(); - node.Dirty(modificationScope); - } - - // Cant determine if Sub Graphs contain the keyword so just update them - foreach (var node in graph.GetNodes()) - { - node.Dirty(modificationScope); - } - } - } -} diff --git a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldKeywordView.cs.meta b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldKeywordView.cs.meta deleted file mode 100644 index 36dd8326f4f..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldKeywordView.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 760efc4b9b9e58d4bb8ab27436fcf9e5 -timeCreated: 1516704904 \ No newline at end of file diff --git a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldPropertyView.cs b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldPropertyView.cs deleted file mode 100644 index 3ec1dab5322..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldPropertyView.cs +++ /dev/null @@ -1,707 +0,0 @@ -using System; -using System.Linq; -using System.Globalization; -using UnityEditor.Graphing; -using UnityEditor.Graphing.Util; -using UnityEngine; -using UnityEditor.UIElements; -using UnityEngine.UIElements; -using Toggle = UnityEngine.UIElements.Toggle; -using UnityEditor.Experimental.GraphView; -using UnityEditor.ShaderGraph.Internal; - -namespace UnityEditor.ShaderGraph.Drawing -{ - class BlackboardFieldPropertyView : BlackboardFieldView - { - public BlackboardFieldPropertyView(BlackboardField blackboardField, GraphData graph, ShaderInput input) - : base (blackboardField, graph, input) - { - } - - public override void BuildCustomFields(ShaderInput input) - { - AbstractShaderProperty property = input as AbstractShaderProperty; - if(property == null) - return; - - switch(input) - { - case Vector1ShaderProperty vector1Property: - BuildVector1PropertyField(vector1Property); - break; - case Vector2ShaderProperty vector2Property: - BuildVector2PropertyField(vector2Property); - break; - case Vector3ShaderProperty vector3Property: - BuildVector3PropertyField(vector3Property); - break; - case Vector4ShaderProperty vector4Property: - BuildVector4PropertyField(vector4Property); - break; - case ColorShaderProperty colorProperty: - BuildColorPropertyField(colorProperty); - break; - case Texture2DShaderProperty texture2DProperty: - BuildTexture2DPropertyField(texture2DProperty); - break; - case Texture2DArrayShaderProperty texture2DArrayProperty: - BuildTexture2DArrayPropertyField(texture2DArrayProperty); - break; - case Texture3DShaderProperty texture3DProperty: - BuildTexture3DPropertyField(texture3DProperty); - break; - case CubemapShaderProperty cubemapProperty: - BuildCubemapPropertyField(cubemapProperty); - break; - case BooleanShaderProperty booleanProperty: - BuildBooleanPropertyField(booleanProperty); - break; - case Matrix2ShaderProperty matrix2Property: - BuildMatrix2PropertyField(matrix2Property); - break; - case Matrix3ShaderProperty matrix3Property: - BuildMatrix3PropertyField(matrix3Property); - break; - case Matrix4ShaderProperty matrix4Property: - BuildMatrix4PropertyField(matrix4Property); - break; - case SamplerStateShaderProperty samplerStateProperty: - BuildSamplerStatePropertyField(samplerStateProperty); - break; - case GradientShaderProperty gradientProperty: - BuildGradientPropertyField(gradientProperty); - break; - default: - throw new ArgumentOutOfRangeException(); - } - - // Precision - var precisionField = new EnumField((Enum)property.precision); - precisionField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Precision"); - if (property.precision == (Precision)evt.newValue) - return; - - property.precision = (Precision)evt.newValue; - graph.ValidateGraph(); - precisionField.MarkDirtyRepaint(); - DirtyNodes(); - }); - AddRow("Precision", precisionField); - if (property.isGpuInstanceable) - { - Toggle gpuInstancedToogle = new Toggle { value = property.gpuInstanced }; - gpuInstancedToogle.OnToggleChanged(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Hybrid Instanced Toggle"); - property.gpuInstanced = evt.newValue; - DirtyNodes(ModificationScope.Graph); - }); - AddRow("Hybrid Instanced (experimental)", gpuInstancedToogle); - } - - } - - void BuildVector1PropertyField(Vector1ShaderProperty property) - { - switch (property.floatType) - { - case FloatType.Slider: - { - float min = Mathf.Min(property.value, property.rangeValues.x); - float max = Mathf.Max(property.value, property.rangeValues.y); - property.rangeValues = new Vector2(min, max); - - var defaultField = new FloatField { value = property.value }; - var minField = new FloatField { value = property.rangeValues.x }; - var maxField = new FloatField { value = property.rangeValues.y }; - - defaultField.RegisterValueChangedCallback(evt => - { - property.value = (float)evt.newValue; - this.MarkDirtyRepaint(); - }); - defaultField.Q("unity-text-input").RegisterCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - float minValue = Mathf.Min(property.value, property.rangeValues.x); - float maxValue = Mathf.Max(property.value, property.rangeValues.y); - property.rangeValues = new Vector2(minValue, maxValue); - minField.value = minValue; - maxField.value = maxValue; - DirtyNodes(); - }); - minField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Range Property Minimum"); - property.rangeValues = new Vector2((float)evt.newValue, property.rangeValues.y); - DirtyNodes(); - }); - minField.Q("unity-text-input").RegisterCallback(evt => - { - property.value = Mathf.Max(Mathf.Min(property.value, property.rangeValues.y), property.rangeValues.x); - defaultField.value = property.value; - DirtyNodes(); - }); - maxField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Range Property Maximum"); - property.rangeValues = new Vector2(property.rangeValues.x, (float)evt.newValue); - DirtyNodes(); - }); - maxField.Q("unity-text-input").RegisterCallback(evt => - { - property.value = Mathf.Max(Mathf.Min(property.value, property.rangeValues.y), property.rangeValues.x); - defaultField.value = property.value; - DirtyNodes(); - }); - - AddRow("Default", defaultField); - AddRow("Min", minField); - AddRow("Max", maxField); - } - break; - case FloatType.Integer: - { - property.value = (int)property.value; - var defaultField = new IntegerField { value = (int)property.value }; - defaultField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - property.value = (int)evt.newValue; - DirtyNodes(); - }); - AddRow("Default", defaultField); - } - break; - default: - { - var defaultField = new FloatField { value = property.value }; - defaultField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - property.value = (float)evt.newValue; - DirtyNodes(); - }); - AddRow("Default", defaultField); - } - break; - } - - if(!graph.isSubGraph) - { - var modeField = new EnumField(property.floatType); - modeField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Vector1 Mode"); - property.floatType = (FloatType)evt.newValue; - Rebuild(); - }); - AddRow("Mode", modeField); - } - } - - void BuildVector2PropertyField(Vector2ShaderProperty property) - { - var field = new Vector2Field { value = property.value }; - - field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(keyDownCallback); - field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(focusOutCallback); - field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(keyDownCallback); - field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(focusOutCallback); - - // Called after KeyDownEvent - field.RegisterValueChangedCallback(evt => - { - // Only true when setting value via FieldMouseDragger - // Undo recorded once per dragger release - if (undoGroup == -1) - graph.owner.RegisterCompleteObjectUndo("Change property value"); - - property.value = evt.newValue; - DirtyNodes(); - }); - AddRow("Default", field); - } - - void BuildVector3PropertyField(Vector3ShaderProperty property) - { - var field = new Vector3Field { value = property.value }; - - field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(keyDownCallback); - field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(focusOutCallback); - field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(keyDownCallback); - field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(focusOutCallback); - field.Q("unity-z-input").Q("unity-text-input").RegisterCallback(keyDownCallback); - field.Q("unity-z-input").Q("unity-text-input").RegisterCallback(focusOutCallback); - - // Called after KeyDownEvent - field.RegisterValueChangedCallback(evt => - { - // Only true when setting value via FieldMouseDragger - // Undo recorded once per dragger release - if (undoGroup == -1) - graph.owner.RegisterCompleteObjectUndo("Change property value"); - - property.value = evt.newValue; - DirtyNodes(); - }); - AddRow("Default", field); - } - - void BuildVector4PropertyField(Vector4ShaderProperty property) - { - var field = new Vector4Field { value = property.value }; - - field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(keyDownCallback); - field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(focusOutCallback); - field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(keyDownCallback); - field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(focusOutCallback); - field.Q("unity-z-input").Q("unity-text-input").RegisterCallback(keyDownCallback); - field.Q("unity-z-input").Q("unity-text-input").RegisterCallback(focusOutCallback); - field.Q("unity-w-input").Q("unity-text-input").RegisterCallback(keyDownCallback); - field.Q("unity-w-input").Q("unity-text-input").RegisterCallback(focusOutCallback); - - // Called after KeyDownEvent - field.RegisterValueChangedCallback(evt => - { - // Only true when setting value via FieldMouseDragger - // Undo recorded once per dragger release - if (undoGroup == -1) - graph.owner.RegisterCompleteObjectUndo("Change property value"); - - property.value = evt.newValue; - DirtyNodes(); - }); - AddRow("Default", field); - } - - void BuildColorPropertyField(ColorShaderProperty property) - { - var colorField = new ColorField { value = property.value, showEyeDropper = false, hdr = property.colorMode == ColorMode.HDR }; - colorField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change property value"); - property.value = evt.newValue; - DirtyNodes(); - }); - AddRow("Default", colorField); - - if(!graph.isSubGraph) - { - var colorModeField = new EnumField((Enum)property.colorMode); - colorModeField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Color Mode"); - if (property.colorMode == (ColorMode)evt.newValue) - return; - property.colorMode = (ColorMode)evt.newValue; - colorField.hdr = property.colorMode == ColorMode.HDR; - colorField.MarkDirtyRepaint(); - DirtyNodes(); - }); - AddRow("Mode", colorModeField); - } - } - - void BuildTexture2DPropertyField(Texture2DShaderProperty property) - { - var field = new ObjectField { value = property.value.texture, objectType = typeof(Texture) }; - field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change property value"); - property.value.texture = (Texture)evt.newValue; - DirtyNodes(); - }); - AddRow("Default", field); - - var defaultMode = (Enum)Texture2DShaderProperty.DefaultType.Grey; - var textureMode = property.generatePropertyBlock ? (Enum)property.defaultType : defaultMode; - var defaultModeField = new EnumField(textureMode); - defaultModeField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Texture Mode"); - if (property.defaultType == (Texture2DShaderProperty.DefaultType)evt.newValue) - return; - property.defaultType = (Texture2DShaderProperty.DefaultType)evt.newValue; - DirtyNodes(ModificationScope.Graph); - }); - AddRow("Mode", defaultModeField, !graph.isSubGraph && property.generatePropertyBlock); - } - - void BuildTexture2DArrayPropertyField(Texture2DArrayShaderProperty property) - { - var field = new ObjectField { value = property.value.textureArray, objectType = typeof(Texture2DArray) }; - field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change property value"); - property.value.textureArray = (Texture2DArray)evt.newValue; - DirtyNodes(); - }); - AddRow("Default", field); - } - - void BuildTexture3DPropertyField(Texture3DShaderProperty property) - { - var field = new ObjectField { value = property.value.texture, objectType = typeof(Texture3D) }; - field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change property value"); - property.value.texture = (Texture3D)evt.newValue; - DirtyNodes(); - }); - AddRow("Default", field); - } - - void BuildCubemapPropertyField(CubemapShaderProperty property) - { - var field = new ObjectField { value = property.value.cubemap, objectType = typeof(Cubemap) }; - field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change property value"); - property.value.cubemap = (Cubemap)evt.newValue; - DirtyNodes(); - }); - AddRow("Default", field); - } - - void BuildBooleanPropertyField(BooleanShaderProperty property) - { - var field = new Toggle() { value = property.value }; - field.OnToggleChanged(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change property value"); - property.value = evt.newValue; - DirtyNodes(); - }); - AddRow("Default", field); - } - - void BuildMatrix2PropertyField(Matrix2ShaderProperty property) - { - var row0Field = new Vector2Field { value = property.value.GetRow(0) }; - row0Field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - Vector2 row1 = property.value.GetRow(1); - property.value = new Matrix4x4() - { - m00 = evt.newValue.x, - m01 = evt.newValue.y, - m02 = 0, - m03 = 0, - m10 = row1.x, - m11 = row1.y, - m12 = 0, - m13 = 0, - m20 = 0, - m21 = 0, - m22 = 0, - m23 = 0, - m30 = 0, - m31 = 0, - m32 = 0, - m33 = 0, - }; - DirtyNodes(); - }); - AddRow("Default", row0Field); - - var row1Field = new Vector2Field { value = property.value.GetRow(1) }; - row1Field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - Vector2 row0 = property.value.GetRow(0); - property.value = new Matrix4x4() - { - m00 = row0.x, - m01 = row0.y, - m02 = 0, - m03 = 0, - m10 = evt.newValue.x, - m11 = evt.newValue.y, - m12 = 0, - m13 = 0, - m20 = 0, - m21 = 0, - m22 = 0, - m23 = 0, - m30 = 0, - m31 = 0, - m32 = 0, - m33 = 0, - }; - DirtyNodes(); - }); - AddRow("", row1Field); - } - - void BuildMatrix3PropertyField(Matrix3ShaderProperty property) - { - var row0Field = new Vector3Field { value = property.value.GetRow(0) }; - row0Field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - Vector3 row1 = property.value.GetRow(1); - Vector3 row2 = property.value.GetRow(2); - property.value = new Matrix4x4() - { - m00 = evt.newValue.x, - m01 = evt.newValue.y, - m02 = evt.newValue.z, - m03 = 0, - m10 = row1.x, - m11 = row1.y, - m12 = row1.z, - m13 = 0, - m20 = row2.x, - m21 = row2.y, - m22 = row2.z, - m23 = 0, - m30 = 0, - m31 = 0, - m32 = 0, - m33 = 0, - }; - DirtyNodes(); - }); - AddRow("Default", row0Field); - - var row1Field = new Vector3Field { value = property.value.GetRow(1) }; - row1Field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - Vector3 row0 = property.value.GetRow(0); - Vector3 row2 = property.value.GetRow(2); - property.value = new Matrix4x4() - { - m00 = row0.x, - m01 = row0.y, - m02 = row0.z, - m03 = 0, - m10 = evt.newValue.x, - m11 = evt.newValue.y, - m12 = evt.newValue.z, - m13 = 0, - m20 = row2.x, - m21 = row2.y, - m22 = row2.z, - m23 = 0, - m30 = 0, - m31 = 0, - m32 = 0, - m33 = 0, - }; - DirtyNodes(); - }); - - AddRow("", row1Field); - var row2Field = new Vector3Field { value = property.value.GetRow(2) }; - row2Field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - Vector3 row0 = property.value.GetRow(0); - Vector3 row1 = property.value.GetRow(1); - property.value = new Matrix4x4() - { - m00 = row0.x, - m01 = row0.y, - m02 = row0.z, - m03 = 0, - m10 = row1.x, - m11 = row1.y, - m12 = row1.z, - m13 = 0, - m20 = evt.newValue.x, - m21 = evt.newValue.y, - m22 = evt.newValue.z, - m23 = 0, - m30 = 0, - m31 = 0, - m32 = 0, - m33 = 0, - }; - DirtyNodes(); - }); - AddRow("", row2Field); - } - - void BuildMatrix4PropertyField(Matrix4ShaderProperty property) - { - var row0Field = new Vector4Field { value = property.value.GetRow(0) }; - row0Field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - Vector4 row1 = property.value.GetRow(1); - Vector4 row2 = property.value.GetRow(2); - Vector4 row3 = property.value.GetRow(3); - property.value = new Matrix4x4() - { - m00 = evt.newValue.x, - m01 = evt.newValue.y, - m02 = evt.newValue.z, - m03 = evt.newValue.w, - m10 = row1.x, - m11 = row1.y, - m12 = row1.z, - m13 = row1.w, - m20 = row2.x, - m21 = row2.y, - m22 = row2.z, - m23 = row2.w, - m30 = row3.x, - m31 = row3.y, - m32 = row3.z, - m33 = row3.w, - }; - DirtyNodes(); - }); - AddRow("Default", row0Field); - - var row1Field = new Vector4Field { value = property.value.GetRow(1) }; - row1Field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - Vector4 row0 = property.value.GetRow(0); - Vector4 row2 = property.value.GetRow(2); - Vector4 row3 = property.value.GetRow(3); - property.value = new Matrix4x4() - { - m00 = row0.x, - m01 = row0.y, - m02 = row0.z, - m03 = row0.w, - m10 = evt.newValue.x, - m11 = evt.newValue.y, - m12 = evt.newValue.z, - m13 = evt.newValue.w, - m20 = row2.x, - m21 = row2.y, - m22 = row2.z, - m23 = row2.w, - m30 = row3.x, - m31 = row3.y, - m32 = row3.z, - m33 = row3.w, - }; - DirtyNodes(); - }); - AddRow("", row1Field); - - var row2Field = new Vector4Field { value = property.value.GetRow(2) }; - row2Field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - Vector4 row0 = property.value.GetRow(0); - Vector4 row1 = property.value.GetRow(1); - Vector4 row3 = property.value.GetRow(3); - property.value = new Matrix4x4() - { - m00 = row0.x, - m01 = row0.y, - m02 = row0.z, - m03 = row0.w, - m10 = row1.x, - m11 = row1.y, - m12 = row1.z, - m13 = row1.w, - m20 = evt.newValue.x, - m21 = evt.newValue.y, - m22 = evt.newValue.z, - m23 = evt.newValue.w, - m30 = row3.x, - m31 = row3.y, - m32 = row3.z, - m33 = row3.w, - }; - DirtyNodes(); - }); - AddRow("", row2Field); - - var row3Field = new Vector4Field { value = property.value.GetRow(3) }; - row3Field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - Vector4 row0 = property.value.GetRow(0); - Vector4 row1 = property.value.GetRow(1); - Vector4 row2 = property.value.GetRow(2); - property.value = new Matrix4x4() - { - m00 = row0.x, - m01 = row0.y, - m02 = row0.z, - m03 = row0.w, - m10 = row1.x, - m11 = row1.y, - m12 = row1.z, - m13 = row1.w, - m20 = row2.x, - m21 = row2.y, - m22 = row2.z, - m23 = row2.w, - m30 = evt.newValue.x, - m31 = evt.newValue.y, - m32 = evt.newValue.z, - m33 = evt.newValue.w, - }; - DirtyNodes(); - }); - AddRow("", row3Field); - } - - void BuildSamplerStatePropertyField(SamplerStateShaderProperty property) - { - var filterField = new EnumField(property.value.filter); - filterField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - TextureSamplerState state = property.value; - state.filter = (TextureSamplerState.FilterMode)evt.newValue; - property.value = state; - Rebuild(); - DirtyNodes(ModificationScope.Graph); - }); - AddRow("Filter", filterField); - - var wrapField = new EnumField(property.value.wrap); - wrapField.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - TextureSamplerState state = property.value; - state.wrap = (TextureSamplerState.WrapMode)evt.newValue; - property.value = state; - Rebuild(); - DirtyNodes(ModificationScope.Graph); - }); - AddRow("Wrap", wrapField); - } - - void BuildGradientPropertyField(GradientShaderProperty property) - { - var field = new GradientField { value = property.value }; - field.RegisterValueChangedCallback(evt => - { - graph.owner.RegisterCompleteObjectUndo("Change Property Value"); - property.value = evt.newValue; - DirtyNodes(); - }); - AddRow("Default", field); - } - - public override void DirtyNodes(ModificationScope modificationScope = ModificationScope.Node) - { - var colorManager = GetFirstAncestorOfType().colorManager; - var nodes = GetFirstAncestorOfType().graphView.Query().ToList(); - - colorManager.SetNodesDirty(nodes); - colorManager.UpdateNodeViews(nodes); - - foreach (var node in graph.GetNodes()) - { - node.Dirty(modificationScope); - } - } - } -} diff --git a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldPropertyView.cs.meta b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldPropertyView.cs.meta deleted file mode 100644 index 58e2696eed0..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldPropertyView.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d71f7c86172344198783dacd26515c28 -timeCreated: 1516704904 \ No newline at end of file diff --git a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldView.cs b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldView.cs index 696c76aad82..6801c8c9fdb 100644 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldView.cs +++ b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldView.cs @@ -1,126 +1,101 @@ using System; -using System.Collections.Generic; using System.Linq; +using System.Reflection; +using Data.Interfaces; using UnityEngine; using UnityEngine.UIElements; using UnityEditor.Graphing; using UnityEditor.Graphing.Util; using UnityEditor.Experimental.GraphView; +using UnityEditor.ShaderGraph.Drawing.Controls; +using UnityEditor.ShaderGraph.Drawing.Inspector.PropertyDrawers; using UnityEditor.ShaderGraph.Internal; namespace UnityEditor.ShaderGraph.Drawing { - abstract class BlackboardFieldView : VisualElement + class BlackboardFieldView : BlackboardField, IInspectable { - readonly BlackboardField m_BlackboardField; readonly GraphData m_Graph; public GraphData graph => m_Graph; ShaderInput m_Input; - Toggle m_ExposedToogle; - TextField m_ReferenceNameField; - List m_Rows; - public List rows => m_Rows; + [Inspectable("Shader Input", null)] + public ShaderInput shaderInput => m_Input; - int m_UndoGroup = -1; - public int undoGroup => m_UndoGroup; + static Type s_ContextualMenuManipulator = TypeCache.GetTypesDerivedFrom().FirstOrDefault(t => t.FullName == "UnityEngine.UIElements.ContextualMenuManipulator"); - static Type s_ContextualMenuManipulator = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypesOrNothing()).FirstOrDefault(t => t.FullName == "UnityEngine.UIElements.ContextualMenuManipulator"); + // Common IManipulator m_ResetReferenceMenu; - EventCallback m_KeyDownCallback; - public EventCallback keyDownCallback => m_KeyDownCallback; - EventCallback m_FocusOutCallback; - public EventCallback focusOutCallback => m_FocusOutCallback; - - public BlackboardFieldView(BlackboardField blackboardField, GraphData graph, ShaderInput input) + private void DirtyNodes(ModificationScope modificationScope = ModificationScope.Node) { - styleSheets.Add(Resources.Load("Styles/ShaderGraphBlackboard")); - m_BlackboardField = blackboardField; - m_Graph = graph; - m_Input = input; - m_Rows = new List(); - - m_KeyDownCallback = new EventCallback(evt => - { - // Record Undo for input field edit - if (m_UndoGroup == -1) - { - m_UndoGroup = Undo.GetCurrentGroup(); - graph.owner.RegisterCompleteObjectUndo("Change property value"); - } - // Handle scaping input field edit - if (evt.keyCode == KeyCode.Escape && m_UndoGroup > -1) - { - Undo.RevertAllDownToGroup(m_UndoGroup); - m_UndoGroup = -1; - evt.StopPropagation(); - } - // Dont record Undo again until input field is unfocused - m_UndoGroup++; - this.MarkDirtyRepaint(); - }); - - m_FocusOutCallback = new EventCallback(evt => + switch(m_Input) { - // Reset UndoGroup when done editing input field - m_UndoGroup = -1; - }); - - BuildDefaultFields(input); - BuildCustomFields(input); - - AddToClassList("sgblackboardFieldView"); + case AbstractShaderProperty property: + var graphEditorView = GetFirstAncestorOfType(); + if(graphEditorView == null) + return; + var colorManager = graphEditorView.colorManager; + var nodes = graphEditorView.graphView.Query().ToList(); + + colorManager.SetNodesDirty(nodes); + colorManager.UpdateNodeViews(nodes); + + foreach (var node in graph.GetNodes()) + { + node.Dirty(modificationScope); + } + break; + case ShaderKeyword keyword: + foreach (var node in graph.GetNodes()) + { + node.UpdateNode(); + node.Dirty(modificationScope); + } + + // Cant determine if Sub Graphs contain the keyword so just update them + foreach (var node in graph.GetNodes()) + { + node.Dirty(modificationScope); + } + break; + default: + throw new ArgumentOutOfRangeException(); + } } - void BuildDefaultFields(ShaderInput input) + // When the properties are changed, this delegate is used to trigger an update in the view that represents those properties + private Action m_propertyViewUpdateTrigger; + private ShaderInputPropertyDrawer.ChangeReferenceNameCallback m_resetReferenceNameTrigger; + + public string inspectorTitle { - if(!m_Graph.isSubGraph) + get { - m_ExposedToogle = new Toggle(); - m_ExposedToogle.OnToggleChanged(evt => + switch(m_Input) { - m_Graph.owner.RegisterCompleteObjectUndo("Change Exposed Toggle"); - input.generatePropertyBlock = evt.newValue; - m_BlackboardField.icon = input.generatePropertyBlock ? BlackboardProvider.exposedIcon : null; - Rebuild(); - DirtyNodes(ModificationScope.Graph); - }); - m_ExposedToogle.value = input.generatePropertyBlock && input.isExposable; - AddRow("Exposed", m_ExposedToogle, input.isExposable); + case AbstractShaderProperty property: + return $"{m_Input.displayName} (Property)"; + case ShaderKeyword keyword: + return $"{m_Input.displayName} (Keyword)"; + default: + throw new ArgumentOutOfRangeException(); + } } + } - if(!m_Graph.isSubGraph || input is ShaderKeyword) - { - m_ReferenceNameField = new TextField(512, false, false, ' ') { isDelayed = true }; - m_ReferenceNameField.styleSheets.Add(Resources.Load("Styles/PropertyNameReferenceField")); - m_ReferenceNameField.value = input.referenceName; - m_ReferenceNameField.RegisterValueChangedCallback(evt => - { - m_Graph.owner.RegisterCompleteObjectUndo("Change Reference Name"); - if (m_ReferenceNameField.value != m_Input.referenceName) - m_Graph.SanitizeGraphInputReferenceName(input, evt.newValue); - - m_ReferenceNameField.value = input.referenceName; - if (string.IsNullOrEmpty(input.overrideReferenceName)) - m_ReferenceNameField.RemoveFromClassList("modified"); - else - m_ReferenceNameField.AddToClassList("modified"); - - Rebuild(); - DirtyNodes(ModificationScope.Graph); - UpdateReferenceNameResetMenu(); - }); - if (!string.IsNullOrEmpty(input.overrideReferenceName)) - m_ReferenceNameField.AddToClassList("modified"); - - AddRow("Reference", m_ReferenceNameField, input.isRenamable); - } + public BlackboardFieldView(GraphData graph, ShaderInput input, Texture icon, string text, string typeText) : base(icon, text, typeText) + { + styleSheets.Add(Resources.Load("Styles/ShaderGraphBlackboard")); + m_Graph = graph; + m_Input = input; } - public abstract void BuildCustomFields(ShaderInput input); - public abstract void DirtyNodes(ModificationScope modificationScope = ModificationScope.Node); + public object GetObjectToInspect() + { + return shaderInput; + } void UpdateReferenceNameResetMenu() { @@ -141,53 +116,120 @@ void BuildContextualMenu(ContextualMenuPopulateEvent evt) evt.menu.AppendAction("Reset Reference", e => { m_Input.overrideReferenceName = null; - m_ReferenceNameField.value = m_Input.referenceName; - m_ReferenceNameField.RemoveFromClassList("modified"); + m_resetReferenceNameTrigger(shaderInput.referenceName); DirtyNodes(ModificationScope.Graph); }, DropdownMenuAction.AlwaysEnabled); } - public VisualElement AddRow(string labelText, VisualElement control, bool enabled = true) +#region PropertyDrawers + public void SupplyDataToPropertyDrawer(IPropertyDrawer propertyDrawer, Action inspectorUpdateDelegate) { - VisualElement rowView = CreateRow(labelText, control, enabled); - Add(rowView); - m_Rows.Add(rowView); - return rowView; + if(propertyDrawer is ShaderInputPropertyDrawer shaderInputPropertyDrawer) + { + shaderInputPropertyDrawer.GetPropertyData(m_Graph.isSubGraph, + ChangeExposedField, + ChangeReferenceNameField, + () => m_Graph.ValidateGraph(), + () => m_Graph.OnKeywordChanged(), + ChangePropertyValue, + RegisterPropertyChangeUndo, + MarkNodesAsDirty); + + m_propertyViewUpdateTrigger = inspectorUpdateDelegate; + m_resetReferenceNameTrigger = shaderInputPropertyDrawer._resetReferenceNameCallback; + } } - public void Rebuild() + public PropertyInfo[] GetPropertyInfo() { - // Delete all rows - for (int i = 0; i < m_Rows.Count; i++) - { - if (m_Rows[i].parent == this) - Remove(m_Rows[i]); - } + return GetType().GetProperties(); + } - // Rebuild - BuildDefaultFields(m_Input); - BuildCustomFields(m_Input); + void ChangeExposedField(bool newValue) + { + m_Input.generatePropertyBlock = newValue; + icon = m_Input.generatePropertyBlock ? BlackboardProvider.exposedIcon : null; } - VisualElement CreateRow(string labelText, VisualElement control, bool enabled) + void ChangeReferenceNameField(string newValue) { - VisualElement rowView = new VisualElement(); + if (newValue != m_Input.referenceName) + m_Graph.SanitizeGraphInputReferenceName(m_Input, newValue); + + UpdateReferenceNameResetMenu(); + } - rowView.AddToClassList("rowView"); + void RegisterPropertyChangeUndo(string actionName) + { + m_Graph.owner.RegisterCompleteObjectUndo(actionName); + } - if(!string.IsNullOrEmpty(labelText)) + void MarkNodesAsDirty(bool triggerPropertyViewUpdate = false, ModificationScope modificationScope = ModificationScope.Node) + { + DirtyNodes(modificationScope); + if(triggerPropertyViewUpdate) + m_propertyViewUpdateTrigger(); + } + + void ChangePropertyValue(object newValue) + { + var property = m_Input as AbstractShaderProperty; + if(property == null) + return; + + switch(property) { - Label label = new Label(labelText); - label.SetEnabled(enabled); - label.AddToClassList("rowViewLabel"); - rowView.Add(label); + case BooleanShaderProperty booleanProperty: + booleanProperty.value = ((ToggleData)newValue).isOn; + break; + case Vector1ShaderProperty vector1Property: + vector1Property.value = (float) newValue; + break; + case Vector2ShaderProperty vector2Property: + vector2Property.value = (Vector2) newValue; + break; + case Vector3ShaderProperty vector3Property: + vector3Property.value = (Vector3) newValue; + break; + case Vector4ShaderProperty vector4Property: + vector4Property.value = (Vector4) newValue; + break; + case ColorShaderProperty colorProperty: + colorProperty.value = (Color) newValue; + break; + case Texture2DShaderProperty texture2DProperty: + texture2DProperty.value.texture = (Texture) newValue; + break; + case Texture2DArrayShaderProperty texture2DArrayProperty: + texture2DArrayProperty.value.textureArray = (Texture2DArray) newValue; + break; + case Texture3DShaderProperty texture3DProperty: + texture3DProperty.value.texture = (Texture3D) newValue; + break; + case CubemapShaderProperty cubemapProperty: + cubemapProperty.value.cubemap = (Cubemap) newValue; + break; + case Matrix2ShaderProperty matrix2Property: + matrix2Property.value = (Matrix4x4) newValue; + break; + case Matrix3ShaderProperty matrix3Property: + matrix3Property.value = (Matrix4x4) newValue; + break; + case Matrix4ShaderProperty matrix4Property: + matrix4Property.value = (Matrix4x4) newValue; + break; + case SamplerStateShaderProperty samplerStateProperty: + samplerStateProperty.value = (TextureSamplerState) newValue; + break; + case GradientShaderProperty gradientProperty: + gradientProperty.value = (Gradient) newValue; + break; + default: + throw new ArgumentOutOfRangeException(); } - control.AddToClassList("rowViewControl"); - control.SetEnabled(enabled); - - rowView.Add(control); - return rowView; + MarkDirtyRepaint(); } +#endregion } } diff --git a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardProvider.cs b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardProvider.cs index 33774d6b2b6..53fad51dbcc 100644 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardProvider.cs +++ b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardProvider.cs @@ -26,13 +26,6 @@ class BlackboardProvider bool m_EditPathCancelled = false; List m_SelectedNodes = new List(); - Dictionary m_ExpandedInputs = new Dictionary(); - - public Dictionary expandedInputs - { - get { return m_ExpandedInputs; } - } - public string assetName { get { return blackboard.title; } @@ -260,8 +253,10 @@ void EditTextRequested(Blackboard blackboard, VisualElement visualElement, strin } } - public void HandleGraphChanges() + public void HandleGraphChanges(bool wasUndoRedoPerformed) { + var selection = new List(blackboard.selection); + foreach (var inputGuid in m_Graph.removedInputs) { BlackboardRow row; @@ -272,14 +267,24 @@ public void HandleGraphChanges() } } - foreach (var input in m_Graph.addedInputs) + // This tries to maintain the selection the user had before the undo/redo was performed, + // if the user hasn't added or removed any inputs + if (wasUndoRedoPerformed) { - AddInputRow(input, index: m_Graph.GetGraphInputIndex(input)); + oldSelectionPersistenceData.Clear(); + foreach (var item in selection) + { + if (item is BlackboardFieldView blackboardFieldView) + { + var guid = blackboardFieldView.shaderInput.referenceName; + oldSelectionPersistenceData.Add(guid, blackboardFieldView.viewDataKey); + } + } } - foreach (var expandedInput in expandedInputs) + foreach (var input in m_Graph.addedInputs) { - SessionState.SetBool($"Unity.ShaderGraph.Input.{expandedInput.Key}.isExpanded", expandedInput.Value); + AddInputRow(input, index: m_Graph.GetGraphInputIndex(input)); } if (m_Graph.movedInputs.Any()) @@ -293,9 +298,12 @@ public void HandleGraphChanges() foreach (var keyword in m_Graph.keywords) m_KeywordSection.Add(m_InputRows[keyword.guid]); } - m_ExpandedInputs.Clear(); } + // A map from shaderInput reference names to the viewDataKey of the blackboardFieldView that used to represent them + // This data is used to re-select the shaderInputs in the blackboard after an undo/redo is performed + Dictionary oldSelectionPersistenceData { get; set; } = new Dictionary(); + void AddInputRow(ShaderInput input, bool create = false, int index = -1) { if (m_InputRows.ContainsKey(input.guid)) @@ -307,7 +315,7 @@ void AddInputRow(ShaderInput input, bool create = false, int index = -1) input.generatePropertyBlock = input.isExposable; } - BlackboardField field = null; + BlackboardFieldView field = null; BlackboardRow row = null; switch(input) @@ -315,9 +323,9 @@ void AddInputRow(ShaderInput input, bool create = false, int index = -1) case AbstractShaderProperty property: { var icon = (m_Graph.isSubGraph || (property.isExposable && property.generatePropertyBlock)) ? exposedIcon : null; - field = new BlackboardField(icon, property.displayName, property.propertyType.ToString()) { userData = property }; - var propertyView = new BlackboardFieldPropertyView(field, m_Graph, property); - row = new BlackboardRow(field, propertyView) { userData = input }; + field = new BlackboardFieldView(m_Graph, property, icon, property.displayName, property.propertyType.ToString()) { userData = property }; + field.RegisterCallback(UpdateSelectionAfterUndoRedo); + row = new BlackboardRow(field, null); if (index < 0 || index > m_InputRows.Count) index = m_InputRows.Count; @@ -336,9 +344,9 @@ void AddInputRow(ShaderInput input, bool create = false, int index = -1) string typeText = keyword.keywordType.ToString() + " Keyword"; typeText = keyword.isBuiltIn ? "Built-in " + typeText : typeText; - field = new BlackboardField(icon, keyword.displayName, typeText) { userData = keyword }; - var keywordView = new BlackboardFieldKeywordView(field, m_Graph, keyword); - row = new BlackboardRow(field, keywordView); + field = new BlackboardFieldView(m_Graph, keyword, icon, keyword.displayName, typeText) { userData = keyword }; + field.RegisterCallback(UpdateSelectionAfterUndoRedo); + row = new BlackboardRow(field, null); if (index < 0 || index > m_InputRows.Count) index = m_InputRows.Count; @@ -354,16 +362,13 @@ void AddInputRow(ShaderInput input, bool create = false, int index = -1) throw new ArgumentOutOfRangeException(); } - if(field == null || row == null) - return; - - var pill = row.Q(); - pill.RegisterCallback(evt => OnMouseHover(evt, input)); - pill.RegisterCallback(evt => OnMouseHover(evt, input)); - pill.RegisterCallback(OnDragUpdatedEvent); + field.RegisterCallback(evt => OnMouseHover(evt, input)); + field.RegisterCallback(evt => OnMouseHover(evt, input)); + field.RegisterCallback(OnDragUpdatedEvent); + // Removing the expand button from the blackboard, its added by default var expandButton = row.Q