From 9b394e6f7a3381cf51f817ec7c1a3b6e561ccd83 Mon Sep 17 00:00:00 2001 From: Matt Dean Date: Thu, 7 Nov 2019 15:37:58 +0100 Subject: [PATCH 01/29] Initial implementation --- .../Editor/Data/Interfaces/IInspectable.cs | 8 + .../Data/Interfaces/IInspectable.cs.meta | 11 + .../Editor/Drawing/Inspector/InspectorView.cs | 284 ++++++++++++++++++ .../Drawing/Inspector/InspectorView.cs.meta | 11 + .../Editor/Drawing/Views/GraphEditorView.cs | 5 + .../Editor/Drawing/Views/MaterialGraphView.cs | 19 ++ .../Editor/Drawing/Views/MaterialNodeView.cs | 143 ++------- .../Editor/Resources/Styles/InspectorView.uss | 74 +++++ .../Resources/Styles/InspectorView.uss.meta | 10 + .../Editor/Resources/Styles/PropertyRow.uss | 2 +- 10 files changed, 455 insertions(+), 112 deletions(-) create mode 100644 com.unity.shadergraph/Editor/Data/Interfaces/IInspectable.cs create mode 100644 com.unity.shadergraph/Editor/Data/Interfaces/IInspectable.cs.meta create mode 100644 com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs create mode 100644 com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs.meta create mode 100644 com.unity.shadergraph/Editor/Resources/Styles/InspectorView.uss create mode 100644 com.unity.shadergraph/Editor/Resources/Styles/InspectorView.uss.meta 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..116b7efcb5b --- /dev/null +++ b/com.unity.shadergraph/Editor/Data/Interfaces/IInspectable.cs @@ -0,0 +1,8 @@ +namespace UnityEditor.ShaderGraph.Drawing +{ + interface IInspectable + { + string displayName { get; } + PropertySheet GetInspectorContent(); + } +} 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/Drawing/Inspector/InspectorView.cs b/com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs new file mode 100644 index 00000000000..6e5866fcb6d --- /dev/null +++ b/com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs @@ -0,0 +1,284 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UIElements; +using UnityEditor.Graphing; +using UnityEditor.Graphing.Util; +using UnityEditor.Experimental.GraphView; + +namespace UnityEditor.ShaderGraph.Drawing +{ + class InspectorView : VisualElement + { + // References + GraphData m_GraphData; + GraphView m_GraphView; + + // GenericView + const string kTitle = "Inspector"; + const string kElementName = "inspectorView"; + const string kStyleName = "InspectorView"; + const string kLayoutKey = "ShaderGraph.Inspector"; + WindowDockingLayout m_Layout; + WindowDockingLayout m_DefaultLayout = new WindowDockingLayout + { + dockingTop = true, + dockingLeft = true, + verticalOffset = 16, + horizontalOffset = 16, + size = new Vector2(200, 400), + }; + + // Context + Label m_ContextTitle; + VisualElement m_PropertyContainer; + + // Preview + PreviewManager m_PreviewManager; + PreviewRenderData m_PreviewRenderData; + Image m_PreviewImage; + Vector2 m_PreviewScrollPosition; + Mesh m_PreviousMesh; + static Type s_ObjectSelector = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypesOrNothing()).FirstOrDefault(t => t.FullName == "UnityEditor.ObjectSelector"); + + // Passing both the manager and the data here is really bad + // Inspector preview should be directly reactive to the preview manager + public InspectorView(GraphData graphData, GraphView graphView, PreviewManager previewManager) + { + m_GraphData = graphData; + m_GraphView = graphView; + + m_PreviewManager = previewManager; + m_PreviewRenderData = previewManager.masterRenderData; + if (m_PreviewRenderData != null) + m_PreviewRenderData.onPreviewChanged += OnPreviewChanged; + + BuildView(); + DeserializeLayout(); + } + +#region GenericView + // All code in this region is generic to any floating tool window + // This should be extracted for document based tool modes + + void BuildView() + { + name = kElementName; + styleSheets.Add(Resources.Load($"Styles/{kStyleName}")); + m_GraphView.Add(this); + + BuildTitleContainer(); + BuildContentContainer(); + BuildManipulators(); + } + + void BuildTitleContainer() + { + var titleContainer = new VisualElement() { name = "titleContainer" }; + { + var titleLabel = new Label(kTitle) { name = "titleLabel" }; + m_ContextTitle = new Label(" ") { name = "titleValue" }; + + titleContainer.Add(titleLabel); + titleContainer.Add(m_ContextTitle); + } + Add(titleContainer); + } + + void BuildContentContainer() + { + var contentContainer = new VisualElement() { name = "contentContainer" }; + BuildContent(contentContainer); + Add(contentContainer); + } + + void BuildManipulators() + { + var resizeBorderFrame = new ResizeBorderFrame(this) { name = "resizeBorderFrame" }; + resizeBorderFrame.OnResizeFinished += SerializeLayout; + Add(resizeBorderFrame); + + var windowDraggable = new WindowDraggable(null, m_GraphView); + windowDraggable.OnDragFinished += SerializeLayout; + this.AddManipulator(windowDraggable); + } + + void SerializeLayout() + { + m_Layout.CalculateDockingCornerAndOffset(layout, m_GraphView.layout); + m_Layout.ClampToParentWindow(); + + var serializedLayout = JsonUtility.ToJson(m_Layout); + EditorUserSettings.SetConfigValue(kLayoutKey, serializedLayout); + } + + void DeserializeLayout() + { + var serializedLayout = EditorUserSettings.GetConfigValue(kLayoutKey); + if (!string.IsNullOrEmpty(serializedLayout)) + m_Layout = JsonUtility.FromJson(serializedLayout); + else + m_Layout = m_DefaultLayout; + + m_Layout.ApplyPosition(this); + m_Layout.ApplySize(this); + } +#endregion + +#region Content + void BuildContent(VisualElement container) + { + BuildPreview(container); + } + + public void UpdateSelection(List selection) + { + var propertyItemCount = m_PropertyContainer.childCount; + for(int i = 0; i < propertyItemCount; i++) + m_PropertyContainer.RemoveAt(0); + + if(selection.Count == 0) + { + m_ContextTitle.text = " "; + return; + } + + if(selection.Count > 1) + { + m_ContextTitle.text = $"{selection.Count} Objects."; + var sheet = new PropertySheet(); + sheet.Add(new PropertyRow(new Label("Multi-editing not supported."))); + m_PropertyContainer.Add(sheet); + return; + } + + IInspectable inspectable = selection.Select(x => x as IInspectable).FirstOrDefault(); + if(inspectable != null) + { + m_ContextTitle.text = inspectable.displayName; + m_PropertyContainer.Add(inspectable.GetInspectorContent()); + } + m_PropertyContainer.MarkDirtyRepaint(); + } +#endregion + +#region Preview + void BuildPreview(VisualElement container) + { + m_PropertyContainer = new VisualElement { name = "propertyContainer" }; + container.Add(m_PropertyContainer); + + var previewTitleContainer = new VisualElement() { name = "previewTitleContainer" }; + { + var titleLabel = new Label("Preview") { name = "previewTitleLabel" }; + previewTitleContainer.Add(titleLabel); + } + container.Add(previewTitleContainer); + + var previewContainer = new VisualElement { name = "previewContainer" }; + { + CreatePreviewImage(Texture2D.blackTexture); + previewContainer.Add(m_PreviewImage); + previewContainer.style.height = 200; + } + container.Add(previewContainer); + + var draggable = new Draggable(s => + { + previewContainer.style.height = new StyleLength(previewContainer.style.height.value.value - s.y); + }, true); + previewTitleContainer.AddManipulator(draggable); + } + + void CreatePreviewImage(Texture texture) + { + if (m_PreviewRenderData?.texture != null) + texture = m_PreviewRenderData.texture; + + m_PreviewImage = new Image { name = "previewImage", image = texture }; + + // Manipulators + var contextMenu = (IManipulator)Activator.CreateInstance(typeof(ContextualMenuManipulator), (Action)BuildPreviewContextMenu); + m_PreviewImage.AddManipulator(contextMenu); + m_PreviewImage.AddManipulator(new Scrollable(OnPreviewScroll)); + m_PreviewImage.AddManipulator(new Draggable(OnPreviewDrag, true)); + } + + void ChangePreviewMesh(Mesh mesh) + { + m_GraphData.outputNode.Dirty(ModificationScope.Node); + + if (m_GraphData.previewData.serializedMesh.mesh != mesh) + { + m_GraphData.previewData.rotation = Quaternion.identity; + m_PreviewScrollPosition = Vector2.zero; + m_GraphData.previewData.serializedMesh.mesh = mesh; + } + } + + void BuildPreviewContextMenu(ContextualMenuPopulateEvent evt) + { + foreach (var primitiveTypeName in Enum.GetNames(typeof(PrimitiveType))) + { + evt.menu.AppendAction(primitiveTypeName, e => + { + Mesh mesh = Resources.GetBuiltinResource(typeof(Mesh), string.Format("{0}.fbx", primitiveTypeName)) as Mesh; + ChangePreviewMesh(mesh); + }, DropdownMenuAction.AlwaysEnabled); + } + + evt.menu.AppendAction("Custom Mesh", e => + { + MethodInfo ShowMethod = s_ObjectSelector.GetMethod("Show", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, Type.DefaultBinder, new[] {typeof(UnityEngine.Object), typeof(Type), typeof(SerializedProperty), typeof(bool), typeof(List), typeof(Action), typeof(Action)}, new ParameterModifier[7]); + m_PreviousMesh = m_GraphData.previewData.serializedMesh.mesh; + ShowMethod.Invoke(GetMeshSelectionWindow(), new object[] { null, typeof(Mesh), null, false, null, (Action)OnPreviewMeshChanged, (Action)OnPreviewMeshChanged }); + }); + } + + EditorWindow GetMeshSelectionWindow() + { + PropertyInfo P = s_ObjectSelector.GetProperty("get", BindingFlags.Public | BindingFlags.Static); + return P.GetValue(null, null) as EditorWindow; + } + + void OnPreviewMeshChanged(UnityEngine.Object obj) + { + var mesh = obj as Mesh; + if (mesh == null) + mesh = m_PreviousMesh; + ChangePreviewMesh(mesh); + } + + void OnPreviewChanged() + { + m_PreviewImage.image = m_PreviewRenderData?.texture ?? Texture2D.blackTexture; + if (m_PreviewRenderData != null && m_PreviewRenderData.shaderData.isCompiling) + m_PreviewImage.tintColor = new Color(1.0f, 1.0f, 1.0f, 0.3f); + else + m_PreviewImage.tintColor = Color.white; + m_PreviewImage.MarkDirtyRepaint(); + } + + void OnPreviewScroll(float scrollValue) + { + var rescaleMultiplier = 0.03f; + var rescaleAmount = -scrollValue * rescaleMultiplier; + m_GraphData.previewData.scale = Mathf.Clamp(m_GraphData.previewData.scale + rescaleAmount, 0.2f, 5f); + m_GraphData.outputNode.Dirty(ModificationScope.Node); + } + + void OnPreviewDrag(Vector2 mouseDelta) + { + var previewSize = m_PreviewImage.contentRect.size; + + m_PreviewScrollPosition -= mouseDelta * (Event.current.shift ? 3f : 1f) / Mathf.Min(previewSize.x, previewSize.y) * 140f; + m_PreviewScrollPosition.y = Mathf.Clamp(m_PreviewScrollPosition.y, -90f, 90f); + Quaternion previewRotation = Quaternion.Euler(m_PreviewScrollPosition.y, 0, 0) * Quaternion.Euler(0, m_PreviewScrollPosition.x, 0); + m_GraphData.previewData.rotation = previewRotation; + m_GraphData.outputNode.Dirty(ModificationScope.Node); + } +#endregion + } +} diff --git a/com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs.meta b/com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs.meta new file mode 100644 index 00000000000..fadb56a8929 --- /dev/null +++ b/com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6759820ca0a974f36b1a63ec6f6e1a57 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs b/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs index 391db15a52d..f513eb58135 100644 --- a/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs +++ b/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs @@ -98,6 +98,8 @@ public ColorManager colorManager get => m_ColorManager; } + InspectorView m_InspectorView; + public GraphEditorView(EditorWindow editorWindow, GraphData graph, MessageManager messageManager) { m_GraphViewGroupTitleChanged = OnGroupTitleChanged; @@ -242,6 +244,9 @@ public GraphEditorView(EditorWindow editorWindow, GraphData graph, MessageManage CreateMasterPreview(); + m_InspectorView = new InspectorView(graph, graphView, previewManager); + m_GraphView.OnSelectionChange += m_InspectorView.UpdateSelection; + m_GraphView.graphViewChanged = GraphViewChanged; RegisterCallback(ApplySerializewindowLayouts); diff --git a/com.unity.shadergraph/Editor/Drawing/Views/MaterialGraphView.cs b/com.unity.shadergraph/Editor/Drawing/Views/MaterialGraphView.cs index aaa283b2899..6272d083309 100644 --- a/com.unity.shadergraph/Editor/Drawing/Views/MaterialGraphView.cs +++ b/com.unity.shadergraph/Editor/Drawing/Views/MaterialGraphView.cs @@ -209,6 +209,25 @@ public override void BuildContextualMenu(ContextualMenuPopulateEvent evt) } } + public delegate void SelectionChanged(List selection); + public SelectionChanged OnSelectionChange; + + public override void AddToSelection(ISelectable selectable) + { + base.AddToSelection(selectable); + + if(OnSelectionChange != null) + OnSelectionChange(selection); + } + + public override void ClearSelection() + { + base.ClearSelection(); + + if(OnSelectionChange != null) + OnSelectionChange(selection); + } + void RemoveNodesInsideGroup(DropdownMenuAction action, GroupData data) { graph.owner.RegisterCompleteObjectUndo("Delete Group and Contents"); diff --git a/com.unity.shadergraph/Editor/Drawing/Views/MaterialNodeView.cs b/com.unity.shadergraph/Editor/Drawing/Views/MaterialNodeView.cs index 569c0cc1eab..dac07b28dd9 100644 --- a/com.unity.shadergraph/Editor/Drawing/Views/MaterialNodeView.cs +++ b/com.unity.shadergraph/Editor/Drawing/Views/MaterialNodeView.cs @@ -18,7 +18,7 @@ namespace UnityEditor.ShaderGraph.Drawing { - sealed class MaterialNodeView : Node, IShaderNodeView + sealed class MaterialNodeView : Node, IShaderNodeView, IInspectable { PreviewRenderData m_PreviewRenderData; Image m_PreviewImage; @@ -32,14 +32,11 @@ sealed class MaterialNodeView : Node, IShaderNodeView VisualElement m_ControlsDivider; IEdgeConnectorListener m_ConnectorListener; VisualElement m_PortInputContainer; - VisualElement m_SettingsContainer; - bool m_ShowSettings = false; - VisualElement m_SettingsButton; - VisualElement m_Settings; - VisualElement m_NodeSettingsView; GraphView m_GraphView; + public string displayName => $"{node.name} Node"; + public void Initialize(AbstractMaterialNode inNode, PreviewManager previewManager, IEdgeConnectorListener connectorListener, GraphView graphView) { styleSheets.Add(Resources.Load("Styles/MaterialNodeView")); @@ -170,36 +167,6 @@ public void Initialize(AbstractMaterialNode inNode, PreviewManager previewManage } } - m_NodeSettingsView = new NodeSettingsView(); - m_NodeSettingsView.visible = false; - Add(m_NodeSettingsView); - - m_SettingsButton = new VisualElement {name = "settings-button"}; - m_SettingsButton.Add(new VisualElement { name = "icon" }); - - m_Settings = new VisualElement(); - AddDefaultSettings(); - - // Add Node type specific settings - var nodeTypeSettings = node as IHasSettings; - if (nodeTypeSettings != null) - m_Settings.Add(nodeTypeSettings.CreateSettingsElement()); - - // Add manipulators - m_SettingsButton.AddManipulator(new Clickable(() => - { - UpdateSettingsExpandedState(); - })); - - if(m_Settings.childCount > 0) - { - m_ButtonContainer = new VisualElement { name = "button-container" }; - m_ButtonContainer.style.flexDirection = FlexDirection.Row; - m_ButtonContainer.Add(m_SettingsButton); - m_ButtonContainer.Add(m_CollapseButton); - m_TitleContainer.Add(m_ButtonContainer); - } - // Register OnMouseHover callbacks for node highlighting RegisterCallback(OnMouseHover); RegisterCallback(OnMouseHover); @@ -254,17 +221,6 @@ public Color GetColor() return m_TitleContainer.resolvedStyle.borderBottomColor; } - void OnGeometryChanged(GeometryChangedEvent evt) - { - // style.positionTop and style.positionLeft are in relation to the parent, - // so we translate the layout of the settings button to be in the coordinate - // space of the settings view's parent. - - var settingsButtonLayout = m_SettingsButton.ChangeCoordinatesTo(m_NodeSettingsView.parent, m_SettingsButton.layout); - m_NodeSettingsView.style.top = settingsButtonLayout.yMax - 18f; - m_NodeSettingsView.style.left = settingsButtonLayout.xMin - 16f; - } - void OnSubGraphDoubleClick(MouseDownEvent evt) { if (evt.clickCount == 2 && evt.button == 0) @@ -365,80 +321,44 @@ string ConvertToShader(GenerationMode mode) return node.owner.GetShader(node, mode, node.name).shader; } - void AddDefaultSettings() + public PropertySheet GetInspectorContent() { - PropertySheet ps = new PropertySheet(); - bool hasDefaultSettings = false; - - if(node.canSetPrecision) + var sheet = new PropertySheet(); { - hasDefaultSettings = true; - ps.Add(new PropertyRow(new Label("Precision")), (row) => + if(node.canSetPrecision) { - row.Add(new EnumField(node.precision), (field) => + sheet.Add(new PropertyRow(new Label("Precision")), (row) => { - field.RegisterValueChangedCallback(evt => + row.Add(new EnumField(node.precision), (field) => { - if (evt.newValue.Equals(node.precision)) - return; - - var editorView = GetFirstAncestorOfType(); - var nodeList = m_GraphView.Query().ToList(); - - editorView.colorManager.SetNodesDirty(nodeList); - node.owner.owner.RegisterCompleteObjectUndo("Change precision"); - node.precision = (Precision)evt.newValue; - node.owner.ValidateGraph(); - editorView.colorManager.UpdateNodeViews(nodeList); - node.Dirty(ModificationScope.Graph); + field.RegisterValueChangedCallback(evt => + { + if (evt.newValue.Equals(node.precision)) + return; + + var editorView = GetFirstAncestorOfType(); + var nodeList = m_GraphView.Query().ToList(); + + editorView.colorManager.SetNodesDirty(nodeList); + node.owner.owner.RegisterCompleteObjectUndo("Change precision"); + node.precision = (Precision)evt.newValue; + node.owner.ValidateGraph(); + editorView.colorManager.UpdateNodeViews(nodeList); + node.Dirty(ModificationScope.Graph); + }); }); }); - }); - } - - if(hasDefaultSettings) - m_Settings.Add(ps); - } - - void RecreateSettings() - { - m_Settings.RemoveFromHierarchy(); - m_Settings = new PropertySheet(); - - // Add default settings - AddDefaultSettings(); - - // Add Node type specific settings - var nodeTypeSettings = node as IHasSettings; - if (nodeTypeSettings != null) - m_Settings.Add(nodeTypeSettings.CreateSettingsElement()); - - m_NodeSettingsView.Add(m_Settings); - } + } - void UpdateSettingsExpandedState() - { - m_ShowSettings = !m_ShowSettings; - if (m_ShowSettings) - { - m_NodeSettingsView.Add(m_Settings); - m_NodeSettingsView.visible = true; - SetSelfSelected(); - m_SettingsButton.AddToClassList("clicked"); - RegisterCallback(OnGeometryChanged); - OnGeometryChanged(null); - } - else - { - m_Settings.RemoveFromHierarchy(); - SetSelfSelected(); - m_NodeSettingsView.visible = false; - m_SettingsButton.RemoveFromClassList("clicked"); - UnregisterCallback(OnGeometryChanged); + // Add Node type specific settings + if(node is IHasSettings settings) + { + sheet.Add(settings.CreateSettingsElement()); + } } + return sheet; } - private void SetSelfSelected() { m_GraphView.ClearSelection(); @@ -527,7 +447,8 @@ public void OnModified(ModificationScope scope) // Update slots to match node modification if (scope == ModificationScope.Topological) { - RecreateSettings(); + // TODO: Fix this + // RecreateSettings(); var slots = node.GetSlots().ToList(); diff --git a/com.unity.shadergraph/Editor/Resources/Styles/InspectorView.uss b/com.unity.shadergraph/Editor/Resources/Styles/InspectorView.uss new file mode 100644 index 00000000000..518078ed452 --- /dev/null +++ b/com.unity.shadergraph/Editor/Resources/Styles/InspectorView.uss @@ -0,0 +1,74 @@ +InspectorView +{ + flex-direction: column; + position: absolute; + background-color: rgb(42, 42, 42); + justify-content: flex-start; + border-radius: 6px; + border-width: 1px; + border-color: rgb(25,25,25); +} + +InspectorView > #titleContainer +{ + flex-direction: column; + background-color: rgb(60, 60, 60); + justify-content: space-between; + border-top-left-radius: 6px; + border-top-right-radius: 6px; + border-bottom-width: 1px; + border-color: rgb(32,32,32); +} + +InspectorView > #titleContainer > #titleLabel +{ + font-size: 15px; + padding: 6px; + color: rgb(200, 200, 200); +} + +InspectorView > #titleContainer > #titleValue +{ + font-size: 11px; + padding-left: 6px; + padding-top: 1px; + padding-bottom: 6px; + color: rgb(100, 100, 100); +} + +InspectorView > #contentContainer +{ + flex-direction: column; + flex-grow: 1; +} + +InspectorView > #contentContainer > #propertyContainer +{ + flex-grow: 1; +} + +InspectorView > #contentContainer > #previewTitleContainer +{ + background-color: rgb(60, 60, 60); + flex-shrink: 0; + border-bottom-top: 1px; + border-bottom-width: 1px; + border-color: rgb(32,32,32); +} + +InspectorView > #contentContainer > #previewTitleContainer > #previewTitleLabel +{ + font-size: 11px; + padding: 6px; + color: rgb(200, 200, 200); +} + +InspectorView > #contentContainer > #previewContainer +{ + +} + +InspectorView > #contentContainer > #previewContainer > #previewImage +{ + flex-grow: 1; +} diff --git a/com.unity.shadergraph/Editor/Resources/Styles/InspectorView.uss.meta b/com.unity.shadergraph/Editor/Resources/Styles/InspectorView.uss.meta new file mode 100644 index 00000000000..d82f1761a41 --- /dev/null +++ b/com.unity.shadergraph/Editor/Resources/Styles/InspectorView.uss.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 485099284bca84dcfbf9af86eb599f6f +ScriptedImporter: + fileIDToRecycleName: + 11400000: stylesheet + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} diff --git a/com.unity.shadergraph/Editor/Resources/Styles/PropertyRow.uss b/com.unity.shadergraph/Editor/Resources/Styles/PropertyRow.uss index 0ad09b26d5b..3a81066c4d7 100644 --- a/com.unity.shadergraph/Editor/Resources/Styles/PropertyRow.uss +++ b/com.unity.shadergraph/Editor/Resources/Styles/PropertyRow.uss @@ -17,7 +17,7 @@ PropertyRow > #container{ } PropertyRow > #container > #label { - width: 200px; + width: 120px; height: 24px; justify-content: center; } From b1bc7a6ad7ccf775ee60936217a37790d0541cc1 Mon Sep 17 00:00:00 2001 From: Matt Dean Date: Thu, 7 Nov 2019 16:19:38 +0100 Subject: [PATCH 02/29] Remove Master Preview --- .../ShaderGraph/StackLitMasterNode.cs | 1 - .../Unlit/ShaderGraph/HDUnlitMasterNode.cs | 1 - .../Editor/Drawing/Inspector/InspectorView.cs | 22 +- .../Drawing/Inspector/MasterPreviewView.cs | 247 ------------------ .../Inspector/MasterPreviewView.cs.meta | 11 - .../Editor/Drawing/Views/GraphEditorView.cs | 52 +--- .../Resources/Styles/MasterPreviewView.uss | 82 ------ .../Styles/MasterPreviewView.uss.meta | 10 - 8 files changed, 24 insertions(+), 402 deletions(-) delete mode 100644 com.unity.shadergraph/Editor/Drawing/Inspector/MasterPreviewView.cs delete mode 100644 com.unity.shadergraph/Editor/Drawing/Inspector/MasterPreviewView.cs.meta delete mode 100644 com.unity.shadergraph/Editor/Resources/Styles/MasterPreviewView.uss delete mode 100644 com.unity.shadergraph/Editor/Resources/Styles/MasterPreviewView.uss.meta diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/StackLit/ShaderGraph/StackLitMasterNode.cs b/com.unity.render-pipelines.high-definition/Editor/Material/StackLit/ShaderGraph/StackLitMasterNode.cs index 3d1d03d9ab8..00808049d72 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/StackLit/ShaderGraph/StackLitMasterNode.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/StackLit/ShaderGraph/StackLitMasterNode.cs @@ -8,7 +8,6 @@ using UnityEngine; using UnityEngine.UIElements; using UnityEngine.Rendering.HighDefinition; -using UnityEditor.ShaderGraph.Drawing.Inspector; using UnityEditor.ShaderGraph.Internal; using UnityEngine.Rendering; diff --git a/com.unity.render-pipelines.high-definition/Editor/Material/Unlit/ShaderGraph/HDUnlitMasterNode.cs b/com.unity.render-pipelines.high-definition/Editor/Material/Unlit/ShaderGraph/HDUnlitMasterNode.cs index 5531ccc9757..83f6904378d 100644 --- a/com.unity.render-pipelines.high-definition/Editor/Material/Unlit/ShaderGraph/HDUnlitMasterNode.cs +++ b/com.unity.render-pipelines.high-definition/Editor/Material/Unlit/ShaderGraph/HDUnlitMasterNode.cs @@ -9,7 +9,6 @@ using UnityEngine; using UnityEngine.UIElements; using UnityEngine.Rendering.HighDefinition; -using UnityEditor.ShaderGraph.Drawing.Inspector; using UnityEditor.ShaderGraph.Internal; using UnityEngine.Rendering; diff --git a/com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs b/com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs index 6e5866fcb6d..faa1665dced 100644 --- a/com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs +++ b/com.unity.shadergraph/Editor/Drawing/Inspector/InspectorView.cs @@ -40,7 +40,8 @@ class InspectorView : VisualElement PreviewRenderData m_PreviewRenderData; Image m_PreviewImage; Vector2 m_PreviewScrollPosition; - Mesh m_PreviousMesh; + Vector2 m_ExpandedPreviewSize = new Vector2(256f, 256f); + Mesh m_PreviousPreviewMesh; static Type s_ObjectSelector = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypesOrNothing()).FirstOrDefault(t => t.FullName == "UnityEditor.ObjectSelector"); // Passing both the manager and the data here is really bad @@ -204,6 +205,7 @@ void CreatePreviewImage(Texture texture) m_PreviewImage.AddManipulator(contextMenu); m_PreviewImage.AddManipulator(new Scrollable(OnPreviewScroll)); m_PreviewImage.AddManipulator(new Draggable(OnPreviewDrag, true)); + m_PreviewImage.RegisterCallback(OnPreviewGeometryChanged); } void ChangePreviewMesh(Mesh mesh) @@ -232,7 +234,7 @@ void BuildPreviewContextMenu(ContextualMenuPopulateEvent evt) evt.menu.AppendAction("Custom Mesh", e => { MethodInfo ShowMethod = s_ObjectSelector.GetMethod("Show", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, Type.DefaultBinder, new[] {typeof(UnityEngine.Object), typeof(Type), typeof(SerializedProperty), typeof(bool), typeof(List), typeof(Action), typeof(Action)}, new ParameterModifier[7]); - m_PreviousMesh = m_GraphData.previewData.serializedMesh.mesh; + m_PreviousPreviewMesh = m_GraphData.previewData.serializedMesh.mesh; ShowMethod.Invoke(GetMeshSelectionWindow(), new object[] { null, typeof(Mesh), null, false, null, (Action)OnPreviewMeshChanged, (Action)OnPreviewMeshChanged }); }); } @@ -247,7 +249,7 @@ void OnPreviewMeshChanged(UnityEngine.Object obj) { var mesh = obj as Mesh; if (mesh == null) - mesh = m_PreviousMesh; + mesh = m_PreviousPreviewMesh; ChangePreviewMesh(mesh); } @@ -279,6 +281,20 @@ void OnPreviewDrag(Vector2 mouseDelta) m_GraphData.previewData.rotation = previewRotation; m_GraphData.outputNode.Dirty(ModificationScope.Node); } + + void OnPreviewGeometryChanged(GeometryChangedEvent evt) + { + var currentWidth = m_PreviewRenderData?.texture != null ? m_PreviewRenderData.texture.width : -1; + var currentHeight = m_PreviewRenderData?.texture != null ? m_PreviewRenderData.texture.height : -1; + + var targetWidth = Mathf.Max(1f, m_PreviewImage.contentRect.width); + var targetHeight = Mathf.Max(1f, m_PreviewImage.contentRect.height); + + if (Mathf.Approximately(currentWidth, targetHeight) && Mathf.Approximately(currentHeight, targetWidth)) + return; + + m_PreviewManager.ResizeMasterPreview(new Vector2(targetWidth, targetHeight)); + } #endregion } } diff --git a/com.unity.shadergraph/Editor/Drawing/Inspector/MasterPreviewView.cs b/com.unity.shadergraph/Editor/Drawing/Inspector/MasterPreviewView.cs deleted file mode 100644 index 89f5d7d1cc7..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/Inspector/MasterPreviewView.cs +++ /dev/null @@ -1,247 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using UnityEngine; -using UnityEditor.Graphing; -using UnityEditor.Graphing.Util; -using Object = UnityEngine.Object; - -using UnityEditor.UIElements; -using UnityEngine.UIElements; -using UnityEngine.UIElements.StyleSheets; - -namespace UnityEditor.ShaderGraph.Drawing.Inspector -{ - class MasterPreviewView : VisualElement - { - PreviewManager m_PreviewManager; - GraphData m_Graph; - - PreviewRenderData m_PreviewRenderHandle; - Image m_PreviewTextureView; - - public Image previewTextureView - { - get { return m_PreviewTextureView; } - } - - Vector2 m_PreviewScrollPosition; - ObjectField m_PreviewMeshPicker; - - IMasterNode m_MasterNode; - Mesh m_PreviousMesh; - - bool m_Expanded = true; - - public bool expanded - { - get { return m_Expanded; } - } - - bool m_RecalculateLayout; - - Vector2 m_ExpandedPreviewSize; - - VisualElement m_CollapsePreviewContainer; - ResizeBorderFrame m_PreviewResizeBorderFrame; - - public ResizeBorderFrame previewResizeBorderFrame - { - get { return m_PreviewResizeBorderFrame; } - } - - VisualElement m_Preview; - Label m_Title; - - public VisualElement preview - { - get { return m_Preview; } - } - - List m_DoNotShowPrimitives = new List(new string[] {PrimitiveType.Plane.ToString()}); - - static Type s_ContextualMenuManipulator = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypesOrNothing()).FirstOrDefault(t => t.FullName == "UnityEngine.UIElements.ContextualMenuManipulator"); - static Type s_ObjectSelector = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypesOrNothing()).FirstOrDefault(t => t.FullName == "UnityEditor.ObjectSelector"); - - public string assetName - { - get { return m_Title.text; } - set { m_Title.text = value; } - } - - public MasterPreviewView(PreviewManager previewManager, GraphData graph) - { - style.overflow = Overflow.Hidden; - m_PreviewManager = previewManager; - m_Graph = graph; - - styleSheets.Add(Resources.Load("Styles/MasterPreviewView")); - - m_PreviewRenderHandle = previewManager.masterRenderData; - if (m_PreviewRenderHandle != null) - { - m_PreviewRenderHandle.onPreviewChanged += OnPreviewChanged; - } - - var topContainer = new VisualElement() { name = "top" }; - { - m_Title = new Label() { name = "title" }; - m_Title.text = "Main Preview"; - // Add preview collapse button on top of preview - m_CollapsePreviewContainer = new VisualElement { name = "collapse-container" }; - m_CollapsePreviewContainer.AddToClassList("collapse-container"); - - topContainer.Add(m_Title); - topContainer.Add(m_CollapsePreviewContainer); - } - Add(topContainer); - - m_Preview = new VisualElement {name = "middle"}; - { - m_PreviewTextureView = CreatePreview(Texture2D.blackTexture); - m_PreviewScrollPosition = new Vector2(0f, 0f); - preview.Add(m_PreviewTextureView); - preview.AddManipulator(new Scrollable(OnScroll)); - } - Add(preview); - - m_PreviewResizeBorderFrame = new ResizeBorderFrame(previewTextureView, this) { name = "resizeBorderFrame" }; - m_PreviewResizeBorderFrame.maintainAspectRatio = true; - Add(m_PreviewResizeBorderFrame); - - m_ExpandedPreviewSize = new Vector2(256f, 256f); - m_RecalculateLayout = false; - previewTextureView.RegisterCallback(OnGeometryChanged); - } - - Image CreatePreview(Texture texture) - { - if (m_PreviewRenderHandle?.texture != null) - { - texture = m_PreviewRenderHandle.texture; - } - - var image = new Image { name = "preview", image = texture }; - image.AddManipulator(new Draggable(OnMouseDragPreviewMesh, true)); - image.AddManipulator((IManipulator)Activator.CreateInstance(s_ContextualMenuManipulator, (Action)BuildContextualMenu)); - return image; - } - - void BuildContextualMenu(ContextualMenuPopulateEvent evt) - { - foreach (var primitiveTypeName in Enum.GetNames(typeof(PrimitiveType))) - { - if (m_DoNotShowPrimitives.Contains(primitiveTypeName)) - continue; - evt.menu.AppendAction(primitiveTypeName, e => ChangePrimitiveMesh(primitiveTypeName), DropdownMenuAction.AlwaysEnabled); - } - - evt.menu.AppendAction("Custom Mesh", e => ChangeMeshCustom(), DropdownMenuAction.AlwaysEnabled); - } - - void DirtyMasterNode(ModificationScope scope) - { - m_Graph?.outputNode?.Dirty(scope); - } - - void OnPreviewChanged() - { - m_PreviewTextureView.image = m_PreviewRenderHandle?.texture ?? Texture2D.blackTexture; - if (m_PreviewRenderHandle != null && m_PreviewRenderHandle.shaderData.isCompiling) - m_PreviewTextureView.tintColor = new Color(1.0f, 1.0f, 1.0f, 0.3f); - else - m_PreviewTextureView.tintColor = Color.white; - m_PreviewTextureView.MarkDirtyRepaint(); - } - - void ChangePrimitiveMesh(string primitiveName) - { - Mesh changedPrimitiveMesh = Resources.GetBuiltinResource(typeof(Mesh), string.Format("{0}.fbx", primitiveName)) as Mesh; - - ChangeMesh(changedPrimitiveMesh); - } - - void ChangeMesh(Mesh mesh) - { - Mesh changedMesh = mesh; - - DirtyMasterNode(ModificationScope.Node); - - if (m_Graph.previewData.serializedMesh.mesh != changedMesh) - { - m_Graph.previewData.rotation = Quaternion.identity; - m_PreviewScrollPosition = Vector2.zero; - } - - m_Graph.previewData.serializedMesh.mesh = changedMesh; - } - - private static EditorWindow Get() - { - PropertyInfo P = s_ObjectSelector.GetProperty("get", BindingFlags.Public | BindingFlags.Static); - return P.GetValue(null, null) as EditorWindow; - } - - void OnMeshChanged(Object obj) - { - var mesh = obj as Mesh; - if (mesh == null) - mesh = m_PreviousMesh; - ChangeMesh(mesh); - } - - void ChangeMeshCustom() - { - MethodInfo ShowMethod = s_ObjectSelector.GetMethod("Show", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly, Type.DefaultBinder, new[] {typeof(Object), typeof(Type), typeof(SerializedProperty), typeof(bool), typeof(List), typeof(Action), typeof(Action)}, new ParameterModifier[7]); - m_PreviousMesh = m_Graph.previewData.serializedMesh.mesh; - ShowMethod.Invoke(Get(), new object[] { null, typeof(Mesh), null, false, null, (Action)OnMeshChanged, (Action)OnMeshChanged }); - } - - void OnGeometryChanged(GeometryChangedEvent evt) - { - if (m_RecalculateLayout) - { - WindowDockingLayout dockingLayout = new WindowDockingLayout(); - dockingLayout.CalculateDockingCornerAndOffset(layout, parent.layout); - dockingLayout.ClampToParentWindow(); - dockingLayout.ApplyPosition(this); - m_RecalculateLayout = false; - } - - if (!expanded) - return; - - var currentWidth = m_PreviewRenderHandle?.texture != null ? m_PreviewRenderHandle.texture.width : -1; - var currentHeight = m_PreviewRenderHandle?.texture != null ? m_PreviewRenderHandle.texture.height : -1; - - var targetWidth = Mathf.Max(1f, m_PreviewTextureView.contentRect.width); - var targetHeight = Mathf.Max(1f, m_PreviewTextureView.contentRect.height); - - if (Mathf.Approximately(currentWidth, targetHeight) && Mathf.Approximately(currentHeight, targetWidth)) - return; - - m_PreviewManager.ResizeMasterPreview(new Vector2(targetWidth, targetHeight)); - } - - void OnScroll(float scrollValue) - { - float rescaleAmount = -scrollValue * .03f; - m_Graph.previewData.scale = Mathf.Clamp(m_Graph.previewData.scale + rescaleAmount, 0.2f, 5f); - - DirtyMasterNode(ModificationScope.Node); - } - - void OnMouseDragPreviewMesh(Vector2 deltaMouse) - { - Vector2 previewSize = m_PreviewTextureView.contentRect.size; - - m_PreviewScrollPosition -= deltaMouse * (Event.current.shift ? 3f : 1f) / Mathf.Min(previewSize.x, previewSize.y) * 140f; - m_PreviewScrollPosition.y = Mathf.Clamp(m_PreviewScrollPosition.y, -90f, 90f); - Quaternion previewRotation = Quaternion.Euler(m_PreviewScrollPosition.y, 0, 0) * Quaternion.Euler(0, m_PreviewScrollPosition.x, 0); - m_Graph.previewData.rotation = previewRotation; - - DirtyMasterNode(ModificationScope.Node); - } - } -} diff --git a/com.unity.shadergraph/Editor/Drawing/Inspector/MasterPreviewView.cs.meta b/com.unity.shadergraph/Editor/Drawing/Inspector/MasterPreviewView.cs.meta deleted file mode 100644 index 93b146a16a8..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/Inspector/MasterPreviewView.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 546947d46a85b284a971a3f056495735 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs b/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs index f513eb58135..93ff0471e63 100644 --- a/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs +++ b/com.unity.shadergraph/Editor/Drawing/Views/GraphEditorView.cs @@ -4,7 +4,6 @@ using UnityEngine; using UnityEditor.Graphing; using UnityEditor.Graphing.Util; -using UnityEditor.ShaderGraph.Drawing.Inspector; using Object = UnityEngine.Object; using UnityEditor.Experimental.GraphView; @@ -29,14 +28,14 @@ class FloatingWindowsLayout class UserViewSettings { public bool isBlackboardVisible = true; - public bool isPreviewVisible = true; + public bool isInspectorVisible = true; public string colorProvider = NoColors.Title; } class GraphEditorView : VisualElement, IDisposable { MaterialGraphView m_GraphView; - MasterPreviewView m_MasterPreviewView; + InspectorView m_InspectorView; GraphData m_Graph; PreviewManager m_PreviewManager; @@ -98,8 +97,6 @@ public ColorManager colorManager get => m_ColorManager; } - InspectorView m_InspectorView; - public GraphEditorView(EditorWindow editorWindow, GraphData graph, MessageManager messageManager) { m_GraphViewGroupTitleChanged = OnGroupTitleChanged; @@ -110,7 +107,6 @@ public GraphEditorView(EditorWindow editorWindow, GraphData graph, MessageManage m_MessageManager = messageManager; styleSheets.Add(Resources.Load("Styles/GraphEditorView")); previewManager = new PreviewManager(graph, messageManager); - previewManager.onPrimaryMasterChanged = OnPrimaryMasterChanged; var serializedSettings = EditorUserSettings.GetConfigValue(k_UserViewSettings); m_UserViewSettings = JsonUtility.FromJson(serializedSettings) ?? new UserViewSettings(); @@ -207,7 +203,7 @@ public GraphEditorView(EditorWindow editorWindow, GraphData graph, MessageManage GUILayout.Space(6); - m_UserViewSettings.isPreviewVisible = GUILayout.Toggle(m_UserViewSettings.isPreviewVisible, "Main Preview", EditorStyles.toolbarButton); + m_UserViewSettings.isInspectorVisible = GUILayout.Toggle(m_UserViewSettings.isInspectorVisible, "Inspector", EditorStyles.toolbarButton); if (EditorGUI.EndChangeCheck()) { if(newColorIdx != m_ColorManager.activeIndex) @@ -216,7 +212,7 @@ public GraphEditorView(EditorWindow editorWindow, GraphData graph, MessageManage m_UserViewSettings.colorProvider = m_ColorManager.activeProviderName; } - m_MasterPreviewView.visible = m_UserViewSettings.isPreviewVisible; + m_InspectorView.visible = m_UserViewSettings.isInspectorVisible; m_BlackboardProvider.blackboard.visible = m_UserViewSettings.isBlackboardVisible; var serializedViewSettings = JsonUtility.ToJson(m_UserViewSettings); EditorUserSettings.SetConfigValue(k_UserViewSettings, serializedViewSettings); @@ -242,9 +238,8 @@ public GraphEditorView(EditorWindow editorWindow, GraphData graph, MessageManage m_BlackboardProvider.blackboard.visible = m_UserViewSettings.isBlackboardVisible; - CreateMasterPreview(); - m_InspectorView = new InspectorView(graph, graphView, previewManager); + m_InspectorView.visible = m_UserViewSettings.isInspectorVisible; m_GraphView.OnSelectionChange += m_InspectorView.UpdateSelection; m_GraphView.graphViewChanged = GraphViewChanged; @@ -303,19 +298,6 @@ void UnregisterGraphViewCallbacks() m_GraphView.elementsRemovedFromGroup = null; } - void CreateMasterPreview() - { - m_MasterPreviewView = new MasterPreviewView(previewManager, m_Graph) {name = "masterPreview"}; - - var masterPreviewViewDraggable = new WindowDraggable(null, this); - m_MasterPreviewView.AddManipulator(masterPreviewViewDraggable); - m_GraphView.Add(m_MasterPreviewView); - - masterPreviewViewDraggable.OnDragFinished += UpdateSerializedWindowLayout; - m_MasterPreviewView.previewResizeBorderFrame.OnResizeFinished += UpdateSerializedWindowLayout; - m_MasterPreviewView.visible = m_UserViewSettings.isPreviewVisible; - } - void OnKeyDown(KeyDownEvent evt) { if (evt.keyCode == KeyCode.F1) @@ -955,13 +937,6 @@ void UpdateEdgeColors(HashSet nodeViews) } } - void OnPrimaryMasterChanged() - { - m_MasterPreviewView?.RemoveFromHierarchy(); - CreateMasterPreview(); - ApplyMasterPreviewLayout(); - } - void HandleEditorViewChanged(GeometryChangedEvent evt) { m_BlackboardProvider.blackboard.SetPosition(m_FloatingWindowsLayout.blackboardLayout.GetLayout(m_GraphView.layout)); @@ -976,8 +951,6 @@ void ApplySerializewindowLayouts(GeometryChangedEvent evt) { UnregisterCallback(ApplySerializewindowLayouts); - ApplyMasterPreviewLayout(); - // Restore blackboard layout, and make sure that it remains in the view. Rect blackboardRect = m_FloatingWindowsLayout.blackboardLayout.GetLayout(this.layout); @@ -1001,26 +974,11 @@ void ApplySerializewindowLayouts(GeometryChangedEvent evt) RegisterCallback(HandleEditorViewChanged); } - void ApplyMasterPreviewLayout() - { - m_FloatingWindowsLayout.previewLayout.ApplyPosition(m_MasterPreviewView); - m_MasterPreviewView.previewTextureView.style.width = m_FloatingWindowsLayout.masterPreviewSize.x; - m_MasterPreviewView.previewTextureView.style.height = m_FloatingWindowsLayout.masterPreviewSize.y; - } - void UpdateSerializedWindowLayout() { - m_FloatingWindowsLayout.previewLayout.CalculateDockingCornerAndOffset(m_MasterPreviewView.layout, m_GraphView.layout); - m_FloatingWindowsLayout.previewLayout.ClampToParentWindow(); - m_FloatingWindowsLayout.blackboardLayout.CalculateDockingCornerAndOffset(m_BlackboardProvider.blackboard.layout, m_GraphView.layout); m_FloatingWindowsLayout.blackboardLayout.ClampToParentWindow(); - if (m_MasterPreviewView.expanded) - { - m_FloatingWindowsLayout.masterPreviewSize = m_MasterPreviewView.previewTextureView.layout.size; - } - string serializedWindowLayout = JsonUtility.ToJson(m_FloatingWindowsLayout); EditorUserSettings.SetConfigValue(k_FloatingWindowsLayoutKey, serializedWindowLayout); } diff --git a/com.unity.shadergraph/Editor/Resources/Styles/MasterPreviewView.uss b/com.unity.shadergraph/Editor/Resources/Styles/MasterPreviewView.uss deleted file mode 100644 index 8c77054cdc3..00000000000 --- a/com.unity.shadergraph/Editor/Resources/Styles/MasterPreviewView.uss +++ /dev/null @@ -1,82 +0,0 @@ -MasterPreviewView { - flex-direction: column; - position: absolute; - right: 10px; - bottom: 10px; - background-color: rgb(79, 79, 79); - justify-content: flex-start; - border-radius: 6px; - border-top-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-right-width: 1px; - border-color: rgb(25,25,25); -} - -MasterPreviewView > #top { - flex-direction: row; - justify-content: space-between; - background-color: rgb(64, 64, 64); - padding-top: 8px; - padding-bottom: 8px; - padding-left: 8px; - padding-right: 8px; - border-top-left-radius: 6px; - border-top-right-radius: 6px; -} - -MasterPreviewView > #top > #title { - font-size: 12px; - color: rgb(180, 180, 180); - padding-top: 1px; - padding-bottom: 2px; - padding-left: 2px; - padding-right: 2px; -} - -MasterPreviewView > #top > #collapse-container { - align-self : center; - width : 12px; -} - -MasterPreviewView > #top > #collapse-container > #icon{ - align-self: center; - background-image : resource("GraphView/Nodes/NodeChevronDown"); - width: 12px; - height: 12px; - margin-right: 10px; - margin-left: 10px; -} - -MasterPreviewView > #top > #collapse-container > #icon.collapsed { - align-self: center; - background-image : resource("GraphView/Nodes/NodeChevronLeft"); - width: 12px; - height: 12px; -} - -MasterPreviewView > #top > #collapse-container > #icon.expanded { - align-self: center; - background-image : resource("GraphView/Nodes/NodeChevronDown"); - width: 12px; - height: 12px; -} - -MasterPreviewView > #middle { - flex-grow: 1; - flex-direction: row; -} - -MasterPreviewView > #middle > #preview { - flex-grow: 1; - width: 200px; - height: 200px; -} - -MasterPreviewView.collapsed{ - background-color: rgb(206, 53, 185); -} - -MasterPreviewView.expanded{ - background-color: rgb(206, 53, 185); -} diff --git a/com.unity.shadergraph/Editor/Resources/Styles/MasterPreviewView.uss.meta b/com.unity.shadergraph/Editor/Resources/Styles/MasterPreviewView.uss.meta deleted file mode 100644 index ee03048e08b..00000000000 --- a/com.unity.shadergraph/Editor/Resources/Styles/MasterPreviewView.uss.meta +++ /dev/null @@ -1,10 +0,0 @@ -fileFormatVersion: 2 -guid: a141d7b330b4c764ab25b2ba4ac38b2f -ScriptedImporter: - fileIDToRecycleName: - 11400000: stylesheet - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: - script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0} From a1da9447c6fdb8cefc273f7dd9bed70301af0762 Mon Sep 17 00:00:00 2001 From: Matt Dean Date: Fri, 8 Nov 2019 14:31:08 +0100 Subject: [PATCH 03/29] Migrate blackboard field views --- .../Blackboard/BlackboardFieldKeywordView.cs | 258 ---- .../BlackboardFieldKeywordView.cs.meta | 3 - .../Blackboard/BlackboardFieldPropertyView.cs | 699 ----------- .../BlackboardFieldPropertyView.cs.meta | 3 - .../Drawing/Blackboard/BlackboardFieldView.cs | 1102 +++++++++++++++-- .../Drawing/Blackboard/BlackboardProvider.cs | 16 +- .../Editor/Drawing/Inspector/InspectorView.cs | 7 +- .../Editor/Resources/Styles/Blackboard.uss | 310 ----- .../Resources/Styles/Blackboard.uss.meta | 10 - .../Styles/ShaderGraphBlackboard.uss | 15 - .../Editor/Resources/UXML/GraphView.meta | 8 - .../Resources/UXML/GraphView/Blackboard.uxml | 12 - .../UXML/GraphView/Blackboard.uxml.meta | 11 - .../UXML/GraphView/BlackboardField.uxml | 12 - .../UXML/GraphView/BlackboardField.uxml.meta | 11 - .../UXML/GraphView/BlackboardRow.uxml | 13 - .../UXML/GraphView/BlackboardRow.uxml.meta | 11 - .../UXML/GraphView/BlackboardSection.uxml | 7 - .../GraphView/BlackboardSection.uxml.meta | 11 - 19 files changed, 1026 insertions(+), 1493 deletions(-) delete mode 100644 com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldKeywordView.cs delete mode 100644 com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldKeywordView.cs.meta delete mode 100644 com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldPropertyView.cs delete mode 100644 com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldPropertyView.cs.meta delete mode 100644 com.unity.shadergraph/Editor/Resources/Styles/Blackboard.uss delete mode 100644 com.unity.shadergraph/Editor/Resources/Styles/Blackboard.uss.meta delete mode 100644 com.unity.shadergraph/Editor/Resources/UXML/GraphView.meta delete mode 100644 com.unity.shadergraph/Editor/Resources/UXML/GraphView/Blackboard.uxml delete mode 100644 com.unity.shadergraph/Editor/Resources/UXML/GraphView/Blackboard.uxml.meta delete mode 100644 com.unity.shadergraph/Editor/Resources/UXML/GraphView/BlackboardField.uxml delete mode 100644 com.unity.shadergraph/Editor/Resources/UXML/GraphView/BlackboardField.uxml.meta delete mode 100644 com.unity.shadergraph/Editor/Resources/UXML/GraphView/BlackboardRow.uxml delete mode 100644 com.unity.shadergraph/Editor/Resources/UXML/GraphView/BlackboardRow.uxml.meta delete mode 100644 com.unity.shadergraph/Editor/Resources/UXML/GraphView/BlackboardSection.uxml delete mode 100644 com.unity.shadergraph/Editor/Resources/UXML/GraphView/BlackboardSection.uxml.meta 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 1965ed15824..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldKeywordView.cs +++ /dev/null @@ -1,258 +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; - - public BlackboardFieldKeywordView(BlackboardField blackboardField, GraphData graph, ShaderInput input) - : base (blackboardField, graph, input) - { - } - - 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.isEditable); - - // 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.isEditable); - } - - 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.isEditable); - } - - 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, "Display 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"); - }; - - // 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.DelayedTextField( new Rect(rect.x + rect.width / 2, rect.y, rect.width / 2, EditorGUIUtility.singleLineHeight), entry.referenceName, EditorStyles.label); - - displayName = GetDuplicateSafeDisplayName(entry.id, displayName); - referenceName = GetDuplicateSafeReferenceName(entry.id, referenceName.ToUpper()); - - if(EditorGUI.EndChangeCheck()) - { - m_Keyword.entries[index] = new KeywordEntry(index + 1, 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 < 8; - }; - - // Can remove - m_ReorderableList.onCanRemoveCallback = (ReorderableList list) => - { - return list.count > 2; - }; - - // 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"); - - var index = list.list.Count + 1; - var displayName = GetDuplicateSafeDisplayName(index, "New"); - var referenceName = GetDuplicateSafeReferenceName(index, "NEW"); - - // Add new entry - m_Keyword.entries.Add(new KeywordEntry(index, displayName, referenceName)); - - // Update GUI - Rebuild(); - graph.OnKeywordChanged(); - m_SelectedIndex = list.list.Count - 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; - - Rebuild(); - graph.OnKeywordChanged(); - } - - private void ReorderEntries(ReorderableList list) - { - DirtyNodes(); - } - - public string GetDuplicateSafeDisplayName(int id, string name) - { - name = name.Trim(); - 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 4338f94dce6..00000000000 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldPropertyView.cs +++ /dev/null @@ -1,699 +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) - { - 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 abb1e4f4211..31dc8ae9197 100644 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldView.cs +++ b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardFieldView.cs @@ -1,54 +1,69 @@ using System; -using System.Collections.Generic; using System.Linq; +using System.Collections.Generic; +using System.Text.RegularExpressions; using UnityEngine; using UnityEngine.UIElements; +using UnityEditor.UIElements; using UnityEditor.Graphing; using UnityEditor.Graphing.Util; using UnityEditor.Experimental.GraphView; using UnityEditor.ShaderGraph.Internal; +using UnityEditorInternal; 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; - + GraphData m_GraphData; ShaderInput m_Input; - Toggle m_ExposedToogle; - TextField m_ReferenceNameField; - List m_Rows; - public List rows => m_Rows; - - int m_UndoGroup = -1; - public int undoGroup => m_UndoGroup; - - static Type s_ContextualMenuManipulator = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypesOrNothing()).FirstOrDefault(t => t.FullName == "UnityEngine.UIElements.ContextualMenuManipulator"); + // Common + TextField m_ReferenceNameField; IManipulator m_ResetReferenceMenu; - EventCallback m_KeyDownCallback; - public EventCallback keyDownCallback => m_KeyDownCallback; EventCallback m_FocusOutCallback; - public EventCallback focusOutCallback => m_FocusOutCallback; + int m_UndoGroup = -1; + + // Keyword + private ReorderableList m_ReorderableList; + private IMGUIContainer m_Container; + private int m_SelectedIndex; - public BlackboardFieldView(BlackboardField blackboardField, GraphData graph, ShaderInput input) + public string displayName { - styleSheets.Add(Resources.Load("Styles/ShaderGraphBlackboard")); - m_BlackboardField = blackboardField; - m_Graph = graph; + get + { + switch(m_Input) + { + case AbstractShaderProperty property: + return $"{m_Input.displayName} (Property)"; + case ShaderKeyword keyword: + return $"{m_Input.displayName} (Keyword)"; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + + public BlackboardFieldView(GraphData m_GraphDataData, ShaderInput input, Texture icon, string text, string typeText) + : base (icon, text, typeText) + { + m_GraphData = m_GraphDataData; m_Input = input; - m_Rows = new List(); + CreateCallbacks(); + } + + void CreateCallbacks() + { 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"); + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); } // Handle scaping input field edit if (evt.keyCode == KeyCode.Escape && m_UndoGroup > -1) @@ -67,128 +82,1041 @@ public BlackboardFieldView(BlackboardField blackboardField, GraphData graph, Sha // Reset UndoGroup when done editing input field m_UndoGroup = -1; }); + } + + public PropertySheet GetInspectorContent() + { + var propertySheet = new PropertySheet(); + { + BuildExposedField(propertySheet); + BuildReferenceNameField(propertySheet); + BuildPropertyFields(propertySheet); + BuildKeywordFields(propertySheet); + } + return propertySheet; + } + + void AddRow(PropertySheet propertySheet, string labelText, VisualElement control, bool enabled = true) + { + control.SetEnabled(enabled); + propertySheet.Add(new PropertyRow(new Label(labelText)), (row) => + { + row.Add(control); + }); + } + + void UpdateReferenceNameResetMenu() + { + if (string.IsNullOrEmpty(m_Input.overrideReferenceName)) + { + this.RemoveManipulator(m_ResetReferenceMenu); + m_ResetReferenceMenu = null; + } + else + { + m_ResetReferenceMenu = (IManipulator)Activator.CreateInstance(typeof(ContextualMenuManipulator), (Action)BuildContextualMenu); + this.AddManipulator(m_ResetReferenceMenu); + } + } - BuildDefaultFields(input); - BuildCustomFields(input); + void BuildContextualMenu(ContextualMenuPopulateEvent evt) + { + evt.menu.AppendAction("Reset Reference", e => + { + m_Input.overrideReferenceName = null; + m_ReferenceNameField.value = m_Input.referenceName; + m_ReferenceNameField.RemoveFromClassList("modified"); + DirtyNodes(ModificationScope.Graph); + }, DropdownMenuAction.AlwaysEnabled); + } + + void DirtyNodes(ModificationScope modificationScope = ModificationScope.Node) + { + switch(m_Input) + { + case AbstractShaderProperty property: + foreach (var node in m_GraphData.GetNodes()) + node.Dirty(modificationScope); + break; + case ShaderKeyword keyword: + { + foreach (var node in m_GraphData.GetNodes()) + { + node.UpdateNode(); + node.Dirty(modificationScope); + } - AddToClassList("sgblackboardFieldView"); + // Cant determine if Sub Graphs contain the keyword so just update them + foreach (var node in m_GraphData.GetNodes()) + { + node.Dirty(modificationScope); + } + break; + } + default: + throw new ArgumentOutOfRangeException(); + } } - void BuildDefaultFields(ShaderInput input) +#region Default Fields + void BuildExposedField(PropertySheet propertySheet) { - if(!m_Graph.isSubGraph) + if(!m_GraphData.isSubGraph) { - m_ExposedToogle = new Toggle(); - m_ExposedToogle.OnToggleChanged(evt => + var exposedToogle = new Toggle(); + exposedToogle.OnToggleChanged(evt => { - m_Graph.owner.RegisterCompleteObjectUndo("Change Exposed Toggle"); - input.generatePropertyBlock = evt.newValue; - m_BlackboardField.icon = input.generatePropertyBlock ? BlackboardProvider.exposedIcon : null; - Rebuild(); + m_GraphData.owner.RegisterCompleteObjectUndo("Change Exposed Toggle"); + m_Input.generatePropertyBlock = evt.newValue; + icon = m_Input.generatePropertyBlock ? BlackboardProvider.exposedIcon : null; + // Rebuild(); DirtyNodes(ModificationScope.Graph); }); - m_ExposedToogle.value = input.generatePropertyBlock; - AddRow("Exposed", m_ExposedToogle, input.isExposable); - + exposedToogle.value = m_Input.generatePropertyBlock; + AddRow(propertySheet, "Exposed", exposedToogle, m_Input.isExposable); } + } - if(!m_Graph.isSubGraph || input is ShaderKeyword) + void BuildReferenceNameField(PropertySheet propertySheet) + { + if(!m_GraphData.isSubGraph || m_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.value = m_Input.referenceName; m_ReferenceNameField.RegisterValueChangedCallback(evt => { - m_Graph.owner.RegisterCompleteObjectUndo("Change Reference Name"); + m_GraphData.owner.RegisterCompleteObjectUndo("Change Reference Name"); if (m_ReferenceNameField.value != m_Input.referenceName) - m_Graph.SanitizeGraphInputReferenceName(input, evt.newValue); + m_GraphData.SanitizeGraphInputReferenceName(m_Input, evt.newValue); - m_ReferenceNameField.value = input.referenceName; - if (string.IsNullOrEmpty(input.overrideReferenceName)) + m_ReferenceNameField.value = m_Input.referenceName; + if (string.IsNullOrEmpty(m_Input.overrideReferenceName)) m_ReferenceNameField.RemoveFromClassList("modified"); else m_ReferenceNameField.AddToClassList("modified"); - Rebuild(); + // Rebuild(); DirtyNodes(ModificationScope.Graph); UpdateReferenceNameResetMenu(); }); - if (!string.IsNullOrEmpty(input.overrideReferenceName)) + if (!string.IsNullOrEmpty(m_Input.overrideReferenceName)) m_ReferenceNameField.AddToClassList("modified"); - AddRow("Reference", m_ReferenceNameField, input.isRenamable); + AddRow(propertySheet, "Reference", m_ReferenceNameField, m_Input.isRenamable); } } +#endregion - public abstract void BuildCustomFields(ShaderInput input); - public abstract void DirtyNodes(ModificationScope modificationScope = ModificationScope.Node); +#region Property Fields + void BuildPropertyFields(PropertySheet propertySheet) + { + var property = m_Input as AbstractShaderProperty; + if(property == null) + return; - void UpdateReferenceNameResetMenu() + switch(property) + { + case Vector1ShaderProperty vector1Property: + BuildVector1PropertyField(propertySheet, vector1Property); + break; + case Vector2ShaderProperty vector2Property: + BuildVector2PropertyField(propertySheet, vector2Property); + break; + case Vector3ShaderProperty vector3Property: + BuildVector3PropertyField(propertySheet, vector3Property); + break; + case Vector4ShaderProperty vector4Property: + BuildVector4PropertyField(propertySheet, vector4Property); + break; + case ColorShaderProperty colorProperty: + BuildColorPropertyField(propertySheet, colorProperty); + break; + case Texture2DShaderProperty texture2DProperty: + BuildTexture2DPropertyField(propertySheet, texture2DProperty); + break; + case Texture2DArrayShaderProperty texture2DArrayProperty: + BuildTexture2DArrayPropertyField(propertySheet, texture2DArrayProperty); + break; + case Texture3DShaderProperty texture3DProperty: + BuildTexture3DPropertyField(propertySheet, texture3DProperty); + break; + case CubemapShaderProperty cubemapProperty: + BuildCubemapPropertyField(propertySheet, cubemapProperty); + break; + case BooleanShaderProperty booleanProperty: + BuildBooleanPropertyField(propertySheet, booleanProperty); + break; + case Matrix2ShaderProperty matrix2Property: + BuildMatrix2PropertyField(propertySheet, matrix2Property); + break; + case Matrix3ShaderProperty matrix3Property: + BuildMatrix3PropertyField(propertySheet, matrix3Property); + break; + case Matrix4ShaderProperty matrix4Property: + BuildMatrix4PropertyField(propertySheet, matrix4Property); + break; + case SamplerStateShaderProperty samplerStateProperty: + BuildSamplerStatePropertyField(propertySheet, samplerStateProperty); + break; + case GradientShaderProperty gradientProperty: + BuildGradientPropertyField(propertySheet, gradientProperty); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + BuildPrecisionField(propertySheet, property); + BuildGpuInstancingField(propertySheet, property); + } + + void BuildPrecisionField(PropertySheet propertySheet, AbstractShaderProperty property) { - if (string.IsNullOrEmpty(m_Input.overrideReferenceName)) + var precisionField = new EnumField((Enum)property.precision); + precisionField.RegisterValueChangedCallback(evt => { - this.RemoveManipulator(m_ResetReferenceMenu); - m_ResetReferenceMenu = null; + m_GraphData.owner.RegisterCompleteObjectUndo("Change Precision"); + if (property.precision == (Precision)evt.newValue) + return; + + property.precision = (Precision)evt.newValue; + m_GraphData.ValidateGraph(); + precisionField.MarkDirtyRepaint(); + DirtyNodes(); + }); + + AddRow(propertySheet, "Precision", precisionField); + } + + void BuildGpuInstancingField(PropertySheet propertySheet, AbstractShaderProperty property) + { + Toggle gpuInstancedToogle = new Toggle { value = property.gpuInstanced }; + gpuInstancedToogle.OnToggleChanged(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Hybrid Instanced Toggle"); + property.gpuInstanced = evt.newValue; + DirtyNodes(ModificationScope.Graph); + }); + + AddRow(propertySheet, "Hybrid Instanced (experimental)", gpuInstancedToogle, property.isGpuInstanceable); + } + + void BuildVector1PropertyField(PropertySheet propertySheet, 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 => + { + m_GraphData.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 => + { + m_GraphData.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 => + { + m_GraphData.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(propertySheet, "Default", defaultField); + AddRow(propertySheet, "Min", minField); + AddRow(propertySheet, "Max", maxField); + } + break; + case FloatType.Integer: + { + property.value = (int)property.value; + var defaultField = new IntegerField { value = (int)property.value }; + defaultField.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Property Value"); + property.value = (int)evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", defaultField); + } + break; + default: + { + var defaultField = new FloatField { value = property.value }; + defaultField.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Property Value"); + property.value = (float)evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", defaultField); + } + break; } - else + + if(!m_GraphData.isSubGraph) { - m_ResetReferenceMenu = (IManipulator)Activator.CreateInstance(s_ContextualMenuManipulator, (Action)BuildContextualMenu); - this.AddManipulator(m_ResetReferenceMenu); + var modeField = new EnumField(property.floatType); + modeField.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Vector1 Mode"); + property.floatType = (FloatType)evt.newValue; + // Rebuild(); + }); + AddRow(propertySheet, "Mode", modeField); } } + + void BuildVector2PropertyField(PropertySheet propertySheet, Vector2ShaderProperty property) + { + var field = new Vector2Field { value = property.value }; - void BuildContextualMenu(ContextualMenuPopulateEvent evt) + field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(m_KeyDownCallback); + field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(m_FocusOutCallback); + field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(m_KeyDownCallback); + field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(m_FocusOutCallback); + + // Called after KeyDownEvent + field.RegisterValueChangedCallback(evt => + { + // Only true when setting value via FieldMouseDragger + // Undo recorded once per dragger release + if (m_UndoGroup == -1) + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + + property.value = evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", field); + } + + void BuildVector3PropertyField(PropertySheet propertySheet, Vector3ShaderProperty property) { - evt.menu.AppendAction("Reset Reference", e => + var field = new Vector3Field { value = property.value }; + + field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(m_KeyDownCallback); + field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(m_FocusOutCallback); + field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(m_KeyDownCallback); + field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(m_FocusOutCallback); + field.Q("unity-z-input").Q("unity-text-input").RegisterCallback(m_KeyDownCallback); + field.Q("unity-z-input").Q("unity-text-input").RegisterCallback(m_FocusOutCallback); + + // Called after KeyDownEvent + field.RegisterValueChangedCallback(evt => { - m_Input.overrideReferenceName = null; - m_ReferenceNameField.value = m_Input.referenceName; - m_ReferenceNameField.RemoveFromClassList("modified"); + // Only true when setting value via FieldMouseDragger + // Undo recorded once per dragger release + if (m_UndoGroup == -1) + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + + property.value = evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", field); + } + + void BuildVector4PropertyField(PropertySheet propertySheet, Vector4ShaderProperty property) + { + var field = new Vector4Field { value = property.value }; + + field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(m_KeyDownCallback); + field.Q("unity-x-input").Q("unity-text-input").RegisterCallback(m_FocusOutCallback); + field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(m_KeyDownCallback); + field.Q("unity-y-input").Q("unity-text-input").RegisterCallback(m_FocusOutCallback); + field.Q("unity-z-input").Q("unity-text-input").RegisterCallback(m_KeyDownCallback); + field.Q("unity-z-input").Q("unity-text-input").RegisterCallback(m_FocusOutCallback); + field.Q("unity-w-input").Q("unity-text-input").RegisterCallback(m_KeyDownCallback); + field.Q("unity-w-input").Q("unity-text-input").RegisterCallback(m_FocusOutCallback); + + // Called after KeyDownEvent + field.RegisterValueChangedCallback(evt => + { + // Only true when setting value via FieldMouseDragger + // Undo recorded once per dragger release + if (m_UndoGroup == -1) + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + + property.value = evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", field); + } + + void BuildColorPropertyField(PropertySheet propertySheet, ColorShaderProperty property) + { + var colorField = new ColorField { value = property.value, showEyeDropper = false, hdr = property.colorMode == ColorMode.HDR }; + colorField.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + property.value = evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", colorField); + + if(!m_GraphData.isSubGraph) + { + var colorModeField = new EnumField((Enum)property.colorMode); + colorModeField.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "Mode", colorModeField); + } + } + + void BuildTexture2DPropertyField(PropertySheet propertySheet, Texture2DShaderProperty property) + { + var field = new ObjectField { value = property.value.texture, objectType = typeof(Texture) }; + field.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + property.value.texture = (Texture)evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", field); + + if(!m_GraphData.isSubGraph) + { + var defaultMode = (Enum)Texture2DShaderProperty.DefaultType.Grey; + var textureMode = property.generatePropertyBlock ? (Enum)property.defaultType : defaultMode; + var defaultModeField = new EnumField(textureMode); + defaultModeField.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Texture Mode"); + if (property.defaultType == (Texture2DShaderProperty.DefaultType)evt.newValue) + return; + property.defaultType = (Texture2DShaderProperty.DefaultType)evt.newValue; + DirtyNodes(ModificationScope.Graph); + }); + AddRow(propertySheet, "Mode", defaultModeField, property.generatePropertyBlock); + } + } + + void BuildTexture2DArrayPropertyField(PropertySheet propertySheet, Texture2DArrayShaderProperty property) + { + var field = new ObjectField { value = property.value.textureArray, objectType = typeof(Texture2DArray) }; + field.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + property.value.textureArray = (Texture2DArray)evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", field); + } + + void BuildTexture3DPropertyField(PropertySheet propertySheet, Texture3DShaderProperty property) + { + var field = new ObjectField { value = property.value.texture, objectType = typeof(Texture3D) }; + field.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + property.value.texture = (Texture3D)evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", field); + } + + void BuildCubemapPropertyField(PropertySheet propertySheet, CubemapShaderProperty property) + { + var field = new ObjectField { value = property.value.cubemap, objectType = typeof(Cubemap) }; + field.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + property.value.cubemap = (Cubemap)evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", field); + } + + void BuildBooleanPropertyField(PropertySheet propertySheet, BooleanShaderProperty property) + { + var field = new Toggle() { value = property.value }; + field.OnToggleChanged(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + property.value = evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", field); + } + + void BuildMatrix2PropertyField(PropertySheet propertySheet, Matrix2ShaderProperty property) + { + var row0Field = new Vector2Field { value = property.value.GetRow(0) }; + row0Field.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "Default", row0Field); + + var row1Field = new Vector2Field { value = property.value.GetRow(1) }; + row1Field.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "", row1Field); + } + + void BuildMatrix3PropertyField(PropertySheet propertySheet, Matrix3ShaderProperty property) + { + var row0Field = new Vector3Field { value = property.value.GetRow(0) }; + row0Field.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "Default", row0Field); + + var row1Field = new Vector3Field { value = property.value.GetRow(1) }; + row1Field.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "", row1Field); + + var row2Field = new Vector3Field { value = property.value.GetRow(2) }; + row2Field.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "", row2Field); + } + + void BuildMatrix4PropertyField(PropertySheet propertySheet, Matrix4ShaderProperty property) + { + var row0Field = new Vector4Field { value = property.value.GetRow(0) }; + row0Field.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "Default", row0Field); + + var row1Field = new Vector4Field { value = property.value.GetRow(1) }; + row1Field.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "", row1Field); + + var row2Field = new Vector4Field { value = property.value.GetRow(2) }; + row2Field.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "", row2Field); + + var row3Field = new Vector4Field { value = property.value.GetRow(3) }; + row3Field.RegisterValueChangedCallback(evt => + { + m_GraphData.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(propertySheet, "", row3Field); + } + + void BuildSamplerStatePropertyField(PropertySheet propertySheet, SamplerStateShaderProperty property) + { + var filterField = new EnumField(property.value.filter); + filterField.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Property Value"); + TextureSamplerState state = property.value; + state.filter = (TextureSamplerState.FilterMode)evt.newValue; + property.value = state; + // Rebuild(); DirtyNodes(ModificationScope.Graph); - }, DropdownMenuAction.AlwaysEnabled); + }); + AddRow(propertySheet, "Filter", filterField); + + var wrapField = new EnumField(property.value.wrap); + wrapField.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Property Value"); + TextureSamplerState state = property.value; + state.wrap = (TextureSamplerState.WrapMode)evt.newValue; + property.value = state; + // Rebuild(); + DirtyNodes(ModificationScope.Graph); + }); + AddRow(propertySheet, "Wrap", wrapField); } - public VisualElement AddRow(string labelText, VisualElement control, bool enabled = true) + void BuildGradientPropertyField(PropertySheet propertySheet, GradientShaderProperty property) { - VisualElement rowView = CreateRow(labelText, control, enabled); - Add(rowView); - m_Rows.Add(rowView); - return rowView; + var field = new GradientField { value = property.value }; + field.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Property Value"); + property.value = evt.newValue; + DirtyNodes(); + }); + AddRow(propertySheet, "Default", field); } +#endregion - public void Rebuild() +#region Keyword Fields + void BuildKeywordFields(PropertySheet propertySheet) { - // Delete all rows - for (int i = 0; i < m_Rows.Count; i++) + var keyword = m_Input as ShaderKeyword; + if(keyword == null) + return; + + // KeywordDefinition + var keywordDefinitionField = new EnumField((Enum)keyword.keywordDefinition); + keywordDefinitionField.RegisterValueChangedCallback(evt => { - if (m_Rows[i].parent == this) - Remove(m_Rows[i]); + m_GraphData.owner.RegisterCompleteObjectUndo("Change Keyword Type"); + if (keyword.keywordDefinition == (KeywordDefinition)evt.newValue) + return; + keyword.keywordDefinition = (KeywordDefinition)evt.newValue; + // Rebuild(); + }); + AddRow(propertySheet, "Definition", keywordDefinitionField, keyword.isEditable); + + // KeywordScope + if(keyword.keywordDefinition != KeywordDefinition.Predefined) + { + var keywordScopeField = new EnumField((Enum)keyword.keywordScope); + keywordScopeField.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Keyword Type"); + if (keyword.keywordScope == (KeywordScope)evt.newValue) + return; + keyword.keywordScope = (KeywordScope)evt.newValue; + }); + AddRow(propertySheet, "Scope", keywordScopeField, keyword.isEditable); } - // Rebuild - BuildDefaultFields(m_Input); - BuildCustomFields(m_Input); + switch(keyword.keywordType) + { + case KeywordType.Boolean: + BuildBooleanKeywordField(propertySheet, keyword); + break; + case KeywordType.Enum: + BuildEnumKeywordField(propertySheet, keyword); + break; + default: + throw new ArgumentOutOfRangeException(); + } } - VisualElement CreateRow(string labelText, VisualElement control, bool enabled) + void BuildBooleanKeywordField(PropertySheet propertySheet, ShaderKeyword keyword) { - VisualElement rowView = new VisualElement(); + // Default field + var field = new Toggle() { value = keyword.value == 1 }; + field.OnToggleChanged(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change property value"); + keyword.value = evt.newValue ? 1 : 0; + DirtyNodes(ModificationScope.Graph); + }); + AddRow(propertySheet, "Default", field); + } + + void BuildEnumKeywordField(PropertySheet propertySheet, ShaderKeyword keyword) + { + // Clamp value between entry list + int value = Mathf.Clamp(keyword.value, 0, keyword.entries.Count - 1); - rowView.AddToClassList("rowView"); + // Default field + var field = new PopupField(keyword.entries.Select(x => x.displayName).ToList(), value); + field.RegisterValueChangedCallback(evt => + { + m_GraphData.owner.RegisterCompleteObjectUndo("Change Keyword Value"); + keyword.value = field.index; + DirtyNodes(ModificationScope.Graph); + }); + AddRow(propertySheet, "Default", field); - if(!string.IsNullOrEmpty(labelText)) + // Entries + var m_Container = new IMGUIContainer(() => OnGUIHandler ()) { name = "ListContainer" }; + AddRow(propertySheet, "Entries", m_Container, keyword.isEditable); + } + + private void OnGUIHandler() + { + if(m_ReorderableList == null) { - Label label = new Label(labelText); - label.SetEnabled(enabled); - label.AddToClassList("rowViewLabel"); - rowView.Add(label); + RecreateList(); + AddCallbacks(); } + + m_ReorderableList.index = m_SelectedIndex; + m_ReorderableList.DoLayoutList(); + } + + internal void RecreateList() + { + if(!(m_Input is ShaderKeyword keyword)) + return; - control.AddToClassList("rowViewControl"); - control.SetEnabled(enabled); + // Create reorderable list from entries + m_ReorderableList = new ReorderableList(keyword.entries, typeof(KeywordEntry), true, true, true, true); + } + + private void AddCallbacks() + { + if(!(m_Input is ShaderKeyword keyword)) + return; + + // 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, "Display 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"); + }; + + // 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.DelayedTextField( new Rect(rect.x + rect.width / 2, rect.y, rect.width / 2, EditorGUIUtility.singleLineHeight), entry.referenceName, EditorStyles.label); - rowView.Add(control); - return rowView; + displayName = GetDuplicateSafeDisplayName(entry.id, displayName); + referenceName = GetDuplicateSafeReferenceName(entry.id, referenceName.ToUpper()); + + if(EditorGUI.EndChangeCheck()) + { + keyword.entries[index] = new KeywordEntry(index + 1, 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 < 8; + }; + + // Can remove + m_ReorderableList.onCanRemoveCallback = (ReorderableList list) => + { + return list.count > 2; + }; + + // 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) + { + if(!(m_Input is ShaderKeyword keyword)) + return; + + m_GraphData.owner.RegisterCompleteObjectUndo("Add Keyword Entry"); + + var index = list.list.Count + 1; + var displayName = GetDuplicateSafeDisplayName(index, "New"); + var referenceName = GetDuplicateSafeReferenceName(index, "NEW"); + + // Add new entry + keyword.entries.Add(new KeywordEntry(index, displayName, referenceName)); + + // Update GUI + // Rebuild(); + m_GraphData.OnKeywordChanged(); + m_SelectedIndex = list.list.Count - 1; + } + + private void RemoveEntry(ReorderableList list) + { + if(!(m_Input is ShaderKeyword keyword)) + return; + + m_GraphData.owner.RegisterCompleteObjectUndo("Remove Keyword Entry"); + + // Remove entry + m_SelectedIndex = list.index; + var selectedEntry = (KeywordEntry)m_ReorderableList.list[list.index]; + keyword.entries.Remove(selectedEntry); + + // Clamp value within new entry range + int value = Mathf.Clamp(keyword.value, 0, keyword.entries.Count - 1); + keyword.value = value; + + // Rebuild(); + m_GraphData.OnKeywordChanged(); + } + + private void ReorderEntries(ReorderableList list) + { + DirtyNodes(); + } + + public string GetDuplicateSafeDisplayName(int id, string name) + { + name = name.Trim(); + 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); } +#endregion } } diff --git a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardProvider.cs b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardProvider.cs index 66974682fc3..f7a5a29e07e 100644 --- a/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardProvider.cs +++ b/com.unity.shadergraph/Editor/Drawing/Blackboard/BlackboardProvider.cs @@ -244,7 +244,7 @@ void AddBuiltinKeyword(GenericMenu gm, ShaderKeyword keyword) void EditTextRequested(Blackboard blackboard, VisualElement visualElement, string newText) { - var field = (BlackboardField)visualElement; + var field = (BlackboardFieldView)visualElement; var input = (ShaderInput)field.userData; if (!string.IsNullOrEmpty(newText) && newText != input.displayName) { @@ -301,7 +301,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) @@ -309,9 +309,8 @@ 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, input, icon, property.displayName, property.propertyType.ToString()) { userData = property }; + row = new BlackboardRow(field, null) { userData = input }; if (index < 0) index = m_InputRows.Count; if (index == m_InputRows.Count) @@ -324,9 +323,8 @@ void AddInputRow(ShaderInput input, bool create = false, int index = -1) { var icon = (m_Graph.isSubGraph || (keyword.isExposable && keyword.generatePropertyBlock)) ? exposedIcon : null; var typeText = keyword.isEditable ? keyword.keywordType.ToString() : "Built-in Keyword"; - 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, input, icon, keyword.displayName, typeText) { userData = keyword }; + row = new BlackboardRow(field, null); if (index < 0) index = m_InputRows.Count; if (index == m_InputRows.Count) @@ -348,7 +346,7 @@ void AddInputRow(ShaderInput input, bool create = false, int index = -1) pill.RegisterCallback(OnDragUpdatedEvent); var expandButton = row.Q