You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

277 lines
11 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor.Graphing.Util;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Drawing;
using UnityEditor.ShaderGraph.Internal;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditorInternal;
using UnityEditor.ShaderGraph.Serialization;
namespace UnityEditor.ShaderGraph.Drawing.Inspector.PropertyDrawers
{
[SGPropertyDrawer(typeof(GraphData))]
public class GraphDataPropertyDrawer : IPropertyDrawer
{
public delegate void ChangeGraphDefaultPrecisionCallback(GraphPrecision newDefaultGraphPrecision);
public delegate void PostTargetSettingsChangedCallback();
PostTargetSettingsChangedCallback m_postChangeTargetSettingsCallback;
ChangeGraphDefaultPrecisionCallback m_changeGraphDefaultPrecisionCallback;
Dictionary<Target, bool> m_TargetFoldouts = new Dictionary<Target, bool>();
Dictionary<AbstractShaderGraphDataExtension, bool> m_SubDataFoldouts = new Dictionary<AbstractShaderGraphDataExtension, bool>();
public void GetPropertyData(
PostTargetSettingsChangedCallback postChangeValueCallback,
ChangeGraphDefaultPrecisionCallback changeGraphDefaultPrecisionCallback)
{
m_postChangeTargetSettingsCallback = postChangeValueCallback;
m_changeGraphDefaultPrecisionCallback = changeGraphDefaultPrecisionCallback;
}
VisualElement GetSettings(GraphData graphData, Action onChange)
{
var element = new VisualElement() { name = "graphSettings" };
if (graphData.isSubGraph)
return element;
void RegisterActionToUndo(string actionName)
{
graphData.owner.RegisterCompleteObjectUndo(actionName);
}
// Add Label
var targetSettingsLabel = new Label("Target Settings");
targetSettingsLabel.style.unityFontStyleAndWeight = FontStyle.Bold;
element.Add(new PropertyRow(targetSettingsLabel));
var targetList = new ReorderableListView<JsonData<Target>>(
graphData.m_ActiveTargets,
"Active Targets",
false, // disallow reordering (active list is sorted)
target => target.value.displayName);
var validTargets = graphData.GetValidTargets();
targetList.GetAddMenuOptions = () => validTargets.Select(o => o.displayName).ToList();
targetList.OnAddMenuItemCallback +=
(list, addMenuOptionIndex, addMenuOption) =>
{
RegisterActionToUndo("Add Target");
var target = validTargets.ElementAt(addMenuOptionIndex);
graphData.SetTargetActive(target);
m_postChangeTargetSettingsCallback();
};
targetList.RemoveItemCallback +=
(list, itemIndex) =>
{
RegisterActionToUndo("Remove Target");
graphData.SetTargetInactive(list[itemIndex].value);
m_postChangeTargetSettingsCallback();
};
element.Add(targetList);
// Iterate active TargetImplementations
foreach (var target in graphData.activeTargets)
{
// Ensure enabled state is being tracked and get value
bool foldoutActive;
if (!m_TargetFoldouts.TryGetValue(target, out foldoutActive))
{
foldoutActive = true;
m_TargetFoldouts.Add(target, foldoutActive);
}
// Create foldout
var foldout = new Foldout() { text = target.displayName, value = foldoutActive, name = "foldout" };
element.Add(foldout);
foldout.AddToClassList("MainFoldout");
foldout.RegisterValueChangedCallback(evt =>
{
// Update foldout value and rebuild
m_TargetFoldouts[target] = evt.newValue;
foldout.value = evt.newValue;
onChange();
});
if (foldout.value)
{
// Get settings for Target
var context = new TargetPropertyGUIContext(graphData.ValidateGraph);
// Indent the content of the foldout
context.globalIndentLevel++;
target.GetPropertiesGUI(ref context, onChange, RegisterActionToUndo);
context.globalIndentLevel--;
element.Add(context);
}
}
// Data Extensions
var validExtensions = AbstractShaderGraphDataExtension.ValidExtensions();
if (validExtensions.Count() > 0 || graphData.SubDatas.Count() > 0)
{
var dataExtensionSettings = new Label("\nData Extension Settings");
dataExtensionSettings.style.unityFontStyleAndWeight = FontStyle.Bold;
element.Add(new PropertyRow(dataExtensionSettings));
var extensionList = new ReorderableListView<JsonData<AbstractShaderGraphDataExtension>>(
graphData.m_SubDatas,
"Active Data Extensions",
false,
data => data.value.displayName);
extensionList.GetAddMenuOptions = () => validExtensions.Select(o => o.displayName).ToList();
extensionList.OnAddMenuItemCallback +=
(list, addMenuOptionIndex, addMenuOption) =>
{
RegisterActionToUndo("Add Data Extension");
graphData.m_SubDatas.Add(validExtensions[addMenuOptionIndex]);
onChange();
};
extensionList.RemoveItemCallback +=
(list, itemIndex) =>
{
RegisterActionToUndo("Remove Data Extension");
graphData.m_SubDatas.RemoveAt(itemIndex);
onChange();
};
element.Add(extensionList);
foreach (var subData in graphData.SubDatas)
{
if (subData != null) // I think we need to do this in case it didn't serialize correctly.
{
bool foldoutActive;
if (!m_SubDataFoldouts.TryGetValue(subData, out foldoutActive))
{
foldoutActive = true;
m_SubDataFoldouts.Add(subData, foldoutActive);
}
var foldout = new Foldout() { text = subData.displayName, value = foldoutActive, name = "foldout" };
element.Add(foldout);
foldout.AddToClassList("MainFoldout");
foldout.RegisterValueChangedCallback(evt =>
{
// Update foldout value and rebuild
m_SubDataFoldouts[subData] = evt.newValue;
foldout.value = evt.newValue;
onChange();
});
if (foldout.value)
{
var subDataElement = new VisualElement();
subData.OnPropertiesGUI(subDataElement, onChange, RegisterActionToUndo, graphData);
element.Add(subDataElement);
}
}
}
}
#if VFX_GRAPH_10_0_0_OR_NEWER
// Inform the user that VFXTarget is deprecated, if they are using one.
if (graphData.m_ActiveTargets.Any(t => t.value is VFXTarget)) //Use Old VFXTarget
{
var vfxWarning = new HelpBoxRow(MessageType.Info);
var vfxWarningLabel = new Label("The Visual Effect target is deprecated.\n" +
"Use the SRP target(s) instead, and enable 'Support VFX Graph' in the Graph Inspector.\n" +
"Then, you can remove the Visual Effect Target.");
vfxWarningLabel.style.color = new StyleColor(Color.white);
vfxWarningLabel.style.whiteSpace = WhiteSpace.Normal;
vfxWarning.Add(vfxWarningLabel);
element.Add(vfxWarning);
}
#endif
return element;
}
// used to display UI to select GraphPrecision in the GraphData inspector
enum UI_GraphPrecision
{
Single = GraphPrecision.Single,
Half = GraphPrecision.Half,
};
enum UI_SubGraphPrecision
{
Single = GraphPrecision.Single,
Half = GraphPrecision.Half,
Switchable = GraphPrecision.Graph,
};
internal VisualElement CreateGUI(GraphData graphData)
{
var propertySheet = new VisualElement() { name = "graphSettings" };
if (graphData == null)
{
Debug.Log("Attempting to draw something that isn't of type GraphData with a GraphDataPropertyDrawer");
return propertySheet;
}
if (!graphData.isSubGraph)
{
// precision selector for shader graphs
var enumPropertyDrawer = new EnumPropertyDrawer();
propertySheet.Add(enumPropertyDrawer.CreateGUI(
newValue => { m_changeGraphDefaultPrecisionCallback((GraphPrecision)newValue); },
(UI_GraphPrecision)graphData.graphDefaultPrecision,
"Precision",
UI_GraphPrecision.Single,
out var propertyVisualElement));
}
if (graphData.isSubGraph)
{
{
var enum2PropertyDrawer = new EnumPropertyDrawer();
propertySheet.Add(enum2PropertyDrawer.CreateGUI(
newValue => { m_changeGraphDefaultPrecisionCallback((GraphPrecision)newValue); },
(UI_SubGraphPrecision)graphData.graphDefaultPrecision,
"Precision",
UI_SubGraphPrecision.Switchable,
out var propertyVisualElement2));
}
var enumPropertyDrawer = new EnumPropertyDrawer();
propertySheet.Add(enumPropertyDrawer.CreateGUI(
newValue =>
{
graphData.owner.RegisterCompleteObjectUndo("Change Preview Mode");
graphData.previewMode = (PreviewMode)newValue;
},
graphData.previewMode,
"Preview",
PreviewMode.Inherit,
out var propertyVisualElement));
}
propertySheet.Add(GetSettings(graphData, () => this.m_postChangeTargetSettingsCallback()));
return propertySheet;
}
public Action inspectorUpdateDelegate { get; set; }
public VisualElement DrawProperty(PropertyInfo propertyInfo, object actualObject, InspectableAttribute attribute)
{
return this.CreateGUI((GraphData)actualObject);
}
void IPropertyDrawer.DisposePropertyDrawer() { }
}
}